diff -Nru kodi-audiodecoder-gme-2.0.3/appveyor.yml kodi-audiodecoder-gme-19.0.3/appveyor.yml
--- kodi-audiodecoder-gme-2.0.3/appveyor.yml 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/appveyor.yml 2013-05-31 22:59:22.000000000 +0000
@@ -16,14 +16,14 @@
CONFIG: Release
- GENERATOR: "Visual Studio 15 Win64"
CONFIG: Release
- WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0"
+ WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0"
- GENERATOR: "Visual Studio 15 ARM"
CONFIG: Release
- WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0"
+ WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0"
build_script:
- cd ..
- - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git
+ - git clone --branch Matrix --depth=1 https://github.com/xbmc/xbmc.git
- cd %app_id%
- mkdir build
- cd build
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/addon.xml.in kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/addon.xml.in
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/addon.xml.in 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/addon.xml.in 2013-05-31 22:59:22.000000000 +0000
@@ -1,7 +1,7 @@
@ADDON_DEPENDS@
@@ -13,24 +13,31 @@
tracks="true"
library_@PLATFORM@="@LIBRARY_FILENAME@"/>
- Game Music Emu Audio Decoder
- Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a "retro" feel to the sound.
-
-Suppoted Formats:
-- AY: ZX Spectrum/Amstrad CPC
-- GBS: Nintendo Game Boy
-- GYM: Sega Genesis/Mega Drive
-- HES: NEC TurboGrafx-16/PC Engine
-- KSS: MSX Home Computer/other Z80 systems (no FM sound)
-- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
-- SAP: Atari systems using POKEY sound chip
-- SPC: Super Nintendo/Super Famicom
-- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
@PLATFORM@
- GPL-2.0
+ GPL-2.0-or-later
icon.png
+ Game Music Emu lydafkoder
+ Game Music Emu Audio Decoder
+ Game Music Emu Audio Decoder
+ Decodificador de Audio Game Music Emu
+ Decodificador de audio Game Music Emu
+ Game Music Emu -äänidekooderi
+ Game Musik Emu Audio Decoder
+ Game Music Emu 오디오 디코더
+ Аудиодекодер Game Music Emu
+ 游戏音乐 Emu 音频解码器
+ Game Music Emu (GME)-format bruges til at efterligne lydudgangen fra forskellige videospilkonsoller, der var populære i 1980'erne og 1990'erne. Det giver en "retro" fornemmelse af lyden.[CR][CR][B]Bemærk:[/B][CR]Ikke alle filformater giver længde, og i dette tilfælde er den indstillet til 2,5 minutter.[CR][ CR][B]Understøttede formater:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX hjemmecomputer/andre Z80-systemer (ingen FM-lyd)[CR]- NSF/NSFE: Nintendo NES/Famicom (med VRC 6, Namco 106 og FME-7 lyd)[CR]- SAP: Atari-systemer, der bruger POKEY-lydchip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro
+ Das GME-Format (Game Music Emu) wird verwendet, um die Audioausgabe verschiedener Videospielkonsolen zu emulieren, die in den 1980er und 1990er Jahren beliebt waren. Es gibt dem Sound ein "Retro" -Gefühl.[CR][CR][B]Hinweis:[/B][CR]Nicht alle Dateiformate geben Länge und wird in diesem Fall auf 2,5 Minuten gesetzt.[CR][CR][B]Unterstützte Formate:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
+ Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a "retro" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
+ El formato Game Music Emu (GME) se usa para emular la salida de audio de varias videoconsolas populares en las decadas de 1980 y 1990. El da un aire "retro" al sonido.[CR][CR][B]Nota:[/B][CR]No todos los formatos tienen en cuenta la duracion y en esos casos se establece a 2.5 minutos.[CR][CR][B]Formatos soportados:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/otros sistemas Z80 (sin sonido FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (con sonido VRC 6, Namco 106 y FME-7)[CR]- SAP: Sistemas Atari que usen el chip de sonido POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
+ El formato Game Music Emu (GME) se usa para emular la salida de audio de varias consolas de videojuegos populares en las décadas de 1980 y 1990. Da un aire "retro" al sonido.[CR][CR][B]Nota:[/B][CR]No todos los formatos establecen la duración, y en esos casos se establece a 2.5 minutos.[CR][CR][B]Formatos soportados:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/otros sistemas Z80 (sin sonido FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (con sonido VRC 6, Namco 106 y FME-7)[CR]- SAP: Sistemas Atari con chip de sonido POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro
+ Game Music Emu (GME) -muotoa käytetään emuloitaessa monien 1980- ja 1990-luvun pelikonsoleiden äänilähtöä . Se antaa äänelle "retromaisen" vivahteen.[CR][CR][B]Huomioi:[/B][CR]Kaikki tiedostotyypit eivät ilmoita kestoa ja tällöin se asetetaan 2.5 minuuttiin.[CR][CR][B]Tuetut muodot:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/muu Z80 järjestelmä (ei FM-ääntä)[CR]- NSF/NSFE: Nintendo NES/Famicom (varustettuna VRC 6, Namco 106 ja FME-7 -äänellä)[CR]- SAP: Atari-järjestelmät POKEY-äänipiirillä[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive ja BBC Micro
+ Format Game Music Emu (GME) digunakan untuk meniru output audio dari berbagai konsol video game yang populer di tahun 1980-an dan 1990-an. Ini memberikan nuansa "retro" pada suara.[CR][CR][B]Catatan:[/B][CR]Tidak semua format file memberikan panjang dan dalam hal ini diatur ke 2,5 menit.[CR][][CR] CR][B]Format yang Didukung:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/sistem Z80 lainnya (tanpa suara FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (dengan suara VRC 6, Namco 106, dan FME-7) [CR]- SAP: Sistem Atari menggunakan chip suara POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
+ GME(Game Music Emu) 형식은 1980년대와 1990년대에 유행했던 다양한 비디오 게임 콘솔의 오디오 출력을 에뮬레이트하는 데 사용됩니다. 사운드에 "복고풍" 느낌을 줍니다.[CR][CR][B]참고:[/B][CR]일부 파일 형식은 길이를 제공하지 않으며 이 경우에는 2.5분으로 설정됩니다.[CR][ CR][B]지원되는 형식:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC 엔진[CR]- KSS: MSX 가정용 컴퓨터/기타 Z80 시스템(FM 사운드 없음)[CR]- NSF/NSFE: Nintendo NES/Famicom(VRC 6, Namco 106 및 FME-7 사운드 포함) [CR]- SAP: POKEY 사운드 칩을 사용하는 Atari 시스템[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
+ Формат Game Music Emu (GME) используется для эмуляции аудиовыхода различных игровых приставок, популярных в 1980-х и 1990-х годах. Он придает звуку ощущение "ретро".[CR][CR][B]Примечание:[/B][CR]Не все форматы файлов указывают длину, в данном случае она установлена на 2,5 минуты. [CR][CR][B]Поддерживаемые форматы:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/другие Z80 системы (без FM звука)[CR]- NSF/NSFE: Nintendo NES/Famicom (со звуком VRC 6, Namco 106 и FME-7)[CR]- SAP: Системы Atari, использующие звуковой чип POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro
+ 游戏音乐 Emu(GME)格式用于模拟20世纪80年代和90年代流行的各种视频游戏机的音频输出。它给声音一种“复古”的感觉。[CR][CR][B]注:[/B][CR]并非所有文件格式都给出时长,在这种情况下,它被设置为2.5分钟。[CR][CR][B]支持的格式:[/B][CR]- AY:ZX Spectrum/Amstrad CPC[CR]- GBS:任天堂 Game Boy[CR]- GYM:世嘉 Genesis/Mega Drive[CR]- HES:NEC TurboGrafx-16/PC Engine[CR]- KSS:MSX 家用电脑/其他Z80系统(无FM声音)[CR]- NSF/NSFE:任天堂 NES/Famicom(带有VRC 6、Namco 106 和 FME-7 声音)[CR]- SAP:雅达利系统使用 POKEY sound 芯片[CR]- SPC:超级任天堂/Super Famicom[CR]- VGM/VGZ:世嘉 Master System/Mark III、世嘉Genesis/Mega Drive、BBC Micro
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.af_za/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.af_za/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.af_za/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.af_za/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: af_za\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.am_et/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.am_et/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.am_et/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.am_et/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: am_et\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ar_sa/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ar_sa/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ar_sa/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ar_sa/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ar_sa\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ast_es/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ast_es/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ast_es/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ast_es/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ast_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.az_az/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.az_az/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.az_az/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.az_az/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: az_az\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.be_by/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.be_by/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.be_by/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.be_by/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: be_by\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.bg_bg/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.bg_bg/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.bg_bg/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.bg_bg/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: bg_bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.bs_ba/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.bs_ba/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.bs_ba/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.bs_ba/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: bs_ba\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ca_es/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ca_es/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ca_es/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ca_es/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ca_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.cs_cz/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.cs_cz/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.cs_cz/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.cs_cz/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: cs_cz\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.cy_gb/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.cy_gb/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.cy_gb/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.cy_gb/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: cy_gb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=(n==0) ? 0 : (n==1) ? 1 : (n==2) ? 2 : (n==3) ? 3 :(n==6) ? 4 : 5;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.da_dk/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.da_dk/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.da_dk/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.da_dk/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2021-10-21 12:30+0000\n"
+"Last-Translator: Christian Gade \n"
+"Language-Team: Danish \n"
+"Language: da_dk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.8\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Game Music Emu lydafkoder"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "Game Music Emu (GME)-format bruges til at efterligne lydudgangen fra forskellige videospilkonsoller, der var populære i 1980'erne og 1990'erne. Det giver en \"retro\" fornemmelse af lyden.[CR][CR][B]Bemærk:[/B][CR]Ikke alle filformater giver længde, og i dette tilfælde er den indstillet til 2,5 minutter.[CR][ CR][B]Understøttede formater:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX hjemmecomputer/andre Z80-systemer (ingen FM-lyd)[CR]- NSF/NSFE: Nintendo NES/Famicom (med VRC 6, Namco 106 og FME-7 lyd)[CR]- SAP: Atari-systemer, der bruger POKEY-lydchip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.de_de/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.de_de/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.de_de/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.de_de/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Kodi Translation Team\n"
+"Language-Team: (https://kodi.weblate.cloud/languages/de_de/)\n"
+"Language: de_DE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Game Music Emu Audio Decoder"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "Das GME-Format (Game Music Emu) wird verwendet, um die Audioausgabe verschiedener Videospielkonsolen zu emulieren, die in den 1980er und 1990er Jahren beliebt waren. Es gibt dem Sound ein \"Retro\" -Gefühl.[CR][CR][B]Hinweis:[/B][CR]Nicht alle Dateiformate geben Länge und wird in diesem Fall auf 2,5 Minuten gesetzt.[CR][CR][B]Unterstützte Formate:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.el_gr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.el_gr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.el_gr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.el_gr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: el_gr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_au/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_au/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_au/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_au/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_au\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_gb/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_gb/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_gb/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_gb/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Kodi Translation Team\n"
+"Language-Team: (https://kodi.weblate.cloud/languages/en_gb/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en_GB\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_nz/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_nz/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_nz/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_nz/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_nz\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_us/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_us/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.en_us/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.en_us/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: en_us\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.eo/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.eo/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.eo/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.eo/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_ar/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_ar/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_ar/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_ar/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: es_ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_es/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_es/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_es/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_es/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2022-01-22 22:13+0000\n"
+"Last-Translator: Alfonso Cachero \n"
+"Language-Team: Spanish (Spain) \n"
+"Language: es_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.10.1\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Decodificador de Audio Game Music Emu"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "El formato Game Music Emu (GME) se usa para emular la salida de audio de varias videoconsolas populares en las decadas de 1980 y 1990. El da un aire \"retro\" al sonido.[CR][CR][B]Nota:[/B][CR]No todos los formatos tienen en cuenta la duracion y en esos casos se establece a 2.5 minutos.[CR][CR][B]Formatos soportados:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/otros sistemas Z80 (sin sonido FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (con sonido VRC 6, Namco 106 y FME-7)[CR]- SAP: Sistemas Atari que usen el chip de sonido POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_mx/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_mx/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.es_mx/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.es_mx/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2022-01-22 22:13+0000\n"
+"Last-Translator: Edson Armando \n"
+"Language-Team: Spanish (Mexico) \n"
+"Language: es_mx\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.10.1\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Decodificador de audio Game Music Emu"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "El formato Game Music Emu (GME) se usa para emular la salida de audio de varias consolas de videojuegos populares en las décadas de 1980 y 1990. Da un aire \"retro\" al sonido.[CR][CR][B]Nota:[/B][CR]No todos los formatos establecen la duración, y en esos casos se establece a 2.5 minutos.[CR][CR][B]Formatos soportados:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/otros sistemas Z80 (sin sonido FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (con sonido VRC 6, Namco 106 y FME-7)[CR]- SAP: Sistemas Atari con chip de sonido POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.et_ee/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.et_ee/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.et_ee/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.et_ee/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: et_ee\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.eu_es/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.eu_es/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.eu_es/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.eu_es/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: eu_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fa_af/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fa_af/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fa_af/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fa_af/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fa_af\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fi_fi/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fi_fi/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fi_fi/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fi_fi/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2022-03-19 06:44+0000\n"
+"Last-Translator: Oskari Lavinto \n"
+"Language-Team: Finnish \n"
+"Language: fi_fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.11.2\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Game Music Emu -äänidekooderi"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "Game Music Emu (GME) -muotoa käytetään emuloitaessa monien 1980- ja 1990-luvun pelikonsoleiden äänilähtöä . Se antaa äänelle \"retromaisen\" vivahteen.[CR][CR][B]Huomioi:[/B][CR]Kaikki tiedostotyypit eivät ilmoita kestoa ja tällöin se asetetaan 2.5 minuuttiin.[CR][CR][B]Tuetut muodot:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/muu Z80 järjestelmä (ei FM-ääntä)[CR]- NSF/NSFE: Nintendo NES/Famicom (varustettuna VRC 6, Namco 106 ja FME-7 -äänellä)[CR]- SAP: Atari-järjestelmät POKEY-äänipiirillä[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive ja BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fo_fo/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fo_fo/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fo_fo/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fo_fo/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fo_fo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fr_ca/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fr_ca/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fr_ca/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fr_ca/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fr_ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fr_fr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fr_fr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.fr_fr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.fr_fr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: fr_fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.gl_es/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.gl_es/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.gl_es/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.gl_es/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: gl_es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.he_il/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.he_il/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.he_il/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.he_il/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: he_il\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && n % 10 == 0) ? 2 : 3));\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hi_in/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hi_in/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hi_in/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hi_in/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: hi_in\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hr_hr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hr_hr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hr_hr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hr_hr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: hr_hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hu_hu/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hu_hu/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hu_hu/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hu_hu/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: hu_hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hy_am/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hy_am/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.hy_am/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.hy_am/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: hy_am\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.id_id/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.id_id/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.id_id/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.id_id/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2021-11-18 08:13+0000\n"
+"Last-Translator: Nao3Line Prez \n"
+"Language-Team: Indonesian \n"
+"Language: id_id\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 4.9\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Game Musik Emu Audio Decoder"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "Format Game Music Emu (GME) digunakan untuk meniru output audio dari berbagai konsol video game yang populer di tahun 1980-an dan 1990-an. Ini memberikan nuansa \"retro\" pada suara.[CR][CR][B]Catatan:[/B][CR]Tidak semua format file memberikan panjang dan dalam hal ini diatur ke 2,5 menit.[CR][][CR] CR][B]Format yang Didukung:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/sistem Z80 lainnya (tanpa suara FM)[CR]- NSF/NSFE: Nintendo NES/Famicom (dengan suara VRC 6, Namco 106, dan FME-7) [CR]- SAP: Sistem Atari menggunakan chip suara POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.is_is/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.is_is/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.is_is/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.is_is/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: is_is\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n % 10 != 1 || n % 100 == 11;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.it_it/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.it_it/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.it_it/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.it_it/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: it_it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ja_jp/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ja_jp/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ja_jp/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ja_jp/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ja_jp\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.kn_in/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.kn_in/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.kn_in/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.kn_in/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: kn_in\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ko_kr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ko_kr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ko_kr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ko_kr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2021-10-03 11:47+0000\n"
+"Last-Translator: Minho Park \n"
+"Language-Team: Korean \n"
+"Language: ko_kr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 4.8\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Game Music Emu 오디오 디코더"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "GME(Game Music Emu) 형식은 1980년대와 1990년대에 유행했던 다양한 비디오 게임 콘솔의 오디오 출력을 에뮬레이트하는 데 사용됩니다. 사운드에 \"복고풍\" 느낌을 줍니다.[CR][CR][B]참고:[/B][CR]일부 파일 형식은 길이를 제공하지 않으며 이 경우에는 2.5분으로 설정됩니다.[CR][ CR][B]지원되는 형식:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC 엔진[CR]- KSS: MSX 가정용 컴퓨터/기타 Z80 시스템(FM 사운드 없음)[CR]- NSF/NSFE: Nintendo NES/Famicom(VRC 6, Namco 106 및 FME-7 사운드 포함) [CR]- SAP: POKEY 사운드 칩을 사용하는 Atari 시스템[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.lt_lt/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.lt_lt/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.lt_lt/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.lt_lt/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: lt_lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? 1 : 2);\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.lv_lv/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.lv_lv/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.lv_lv/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.lv_lv/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: lv_lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n % 10 == 0 || n % 100 >= 11 && n % 100 <= 19) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2);\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mi/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mi/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mi/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mi/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: mi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mk_mk/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mk_mk/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mk_mk/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mk_mk/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: mk_mk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n==1 || n%10==1 ? 0 : 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ml_in/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ml_in/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ml_in/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ml_in/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ml_in\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mn_mn/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mn_mn/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mn_mn/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mn_mn/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: mn_mn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ms_my/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ms_my/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ms_my/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ms_my/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ms_my\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mt_mt/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mt_mt/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.mt_mt/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.mt_mt/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: mt_mt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.my_mm/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.my_mm/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.my_mm/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.my_mm/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: my_mm\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.nb_no/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.nb_no/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.nb_no/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.nb_no/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: nb_no\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.nl_nl/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.nl_nl/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.nl_nl/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.nl_nl/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: nl_nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.oc_fr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.oc_fr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.oc_fr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.oc_fr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: oc_fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.os_os/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.os_os/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.os_os/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.os_os/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: os_os\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pl_pl/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pl_pl/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pl_pl/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pl_pl/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pl_pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pt_br/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pt_br/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pt_br/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pt_br/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pt_br\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pt_pt/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pt_pt/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.pt_pt/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.pt_pt/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pt_pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ro_ro/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ro_ro/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ro_ro/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ro_ro/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ro_ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ru_ru/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ru_ru/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ru_ru/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ru_ru/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2021-10-03 11:47+0000\n"
+"Last-Translator: vdkbsd \n"
+"Language-Team: Russian \n"
+"Language: ru_ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 4.8\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "Аудиодекодер Game Music Emu"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "Формат Game Music Emu (GME) используется для эмуляции аудиовыхода различных игровых приставок, популярных в 1980-х и 1990-х годах. Он придает звуку ощущение \"ретро\".[CR][CR][B]Примечание:[/B][CR]Не все форматы файлов указывают длину, в данном случае она установлена на 2,5 минуты. [CR][CR][B]Поддерживаемые форматы:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/другие Z80 системы (без FM звука)[CR]- NSF/NSFE: Nintendo NES/Famicom (со звуком VRC 6, Namco 106 и FME-7)[CR]- SAP: Системы Atari, использующие звуковой чип POKEY[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.si_lk/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.si_lk/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.si_lk/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.si_lk/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: si_lk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sk_sk/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sk_sk/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sk_sk/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sk_sk/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sk_sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sl_si/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sl_si/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sl_si/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sl_si/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sl_si\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sq_al/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sq_al/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sq_al/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sq_al/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sq_al\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sr_rs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs@latin/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs@latin/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs@latin/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sr_rs@latin/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sr_Latn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sv_se/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sv_se/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.sv_se/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.sv_se/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: sv_se\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.szl/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.szl/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.szl/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.szl/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: szl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ta_in/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ta_in/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.ta_in/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.ta_in/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ta_in\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.te_in/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.te_in/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.te_in/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.te_in/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: te_in\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.tg_tj/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.tg_tj/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.tg_tj/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.tg_tj/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: tg_tj\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.th_th/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.th_th/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.th_th/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.th_th/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: th_th\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.tr_tr/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.tr_tr/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.tr_tr/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.tr_tr/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: tr_tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.uk_ua/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.uk_ua/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.uk_ua/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.uk_ua/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: uk_ua\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.uz_uz/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.uz_uz/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.uz_uz/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.uz_uz/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: uz_uz\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.vi_vn/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.vi_vn/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.vi_vn/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.vi_vn/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: vi_vn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.zh_cn/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.zh_cn/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.zh_cn/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.zh_cn/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,26 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: translations@kodi.tv\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2021-10-03 11:47+0000\n"
+"Last-Translator: taxigps \n"
+"Language-Team: Chinese (China) \n"
+"Language: zh_cn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.8\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr "游戏音乐 Emu 音频解码器"
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr "游戏音乐 Emu(GME)格式用于模拟20世纪80年代和90年代流行的各种视频游戏机的音频输出。它给声音一种“复古”的感觉。[CR][CR][B]注:[/B][CR]并非所有文件格式都给出时长,在这种情况下,它被设置为2.5分钟。[CR][CR][B]支持的格式:[/B][CR]- AY:ZX Spectrum/Amstrad CPC[CR]- GBS:任天堂 Game Boy[CR]- GYM:世嘉 Genesis/Mega Drive[CR]- HES:NEC TurboGrafx-16/PC Engine[CR]- KSS:MSX 家用电脑/其他Z80系统(无FM声音)[CR]- NSF/NSFE:任天堂 NES/Famicom(带有VRC 6、Namco 106 和 FME-7 声音)[CR]- SAP:雅达利系统使用 POKEY sound 芯片[CR]- SPC:超级任天堂/Super Famicom[CR]- VGM/VGZ:世嘉 Master System/Mark III、世嘉Genesis/Mega Drive、BBC Micro"
diff -Nru kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.zh_tw/strings.po kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.zh_tw/strings.po
--- kodi-audiodecoder-gme-2.0.3/audiodecoder.gme/resources/language/resource.language.zh_tw/strings.po 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/audiodecoder.gme/resources/language/resource.language.zh_tw/strings.po 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,25 @@
+# Kodi Media Center language file
+# Addon Name: GME Audio Decoder
+# Addon id: audiodecoder.gme
+# Addon Provider: Team Kodi
+msgid ""
+msgstr ""
+"Project-Id-Version: KODI Main\n"
+"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n"
+"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: zh_tw\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+msgctxt "Addon Summary"
+msgid "Game Music Emu Audio Decoder"
+msgstr ""
+
+msgctxt "Addon Description"
+msgid "Game Music Emu (GME) format is used to emulate the audio output of various video game consoles popular in the 1980s and 1990s. It gives a \"retro\" feel to the sound.[CR][CR][B]Note:[/B][CR]Not all file formats give length and in this case it is set to 2.5 minutes.[CR][CR][B]Supported Formats:[/B][CR]- AY: ZX Spectrum/Amstrad CPC[CR]- GBS: Nintendo Game Boy[CR]- GYM: Sega Genesis/Mega Drive[CR]- HES: NEC TurboGrafx-16/PC Engine[CR]- KSS: MSX Home Computer/other Z80 systems (no FM sound)[CR]- NSF/NSFE: Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)[CR]- SAP: Atari systems using POKEY sound chip[CR]- SPC: Super Nintendo/Super Famicom[CR]- VGM/VGZ: Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro"
+msgstr ""
diff -Nru kodi-audiodecoder-gme-2.0.3/azure-pipelines.yml kodi-audiodecoder-gme-19.0.3/azure-pipelines.yml
--- kodi-audiodecoder-gme-2.0.3/azure-pipelines.yml 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/azure-pipelines.yml 2013-05-31 22:59:22.000000000 +0000
@@ -4,7 +4,7 @@
trigger:
branches:
include:
- - Leia
+ - Matrix
- releases/*
paths:
include:
@@ -16,25 +16,25 @@
- job: Windows
pool:
- vmImage: 'VS2017-Win2016'
+ vmImage: 'windows-2022'
strategy:
matrix:
Win32:
- GENERATOR: "Visual Studio 15 2017"
+ GENERATOR: "Visual Studio 17 2022"
ARCHITECTURE: Win32
CONFIGURATION: Release
Win64:
- GENERATOR: "Visual Studio 15 2017"
+ GENERATOR: "Visual Studio 17 2022"
ARCHITECTURE: x64
CONFIGURATION: Release
Win64-UWP:
- GENERATOR: "Visual Studio 15 2017"
+ GENERATOR: "Visual Studio 17 2022"
ARCHITECTURE: x64
CONFIGURATION: Release
WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0"
ARM64-UWP:
- GENERATOR: "Visual Studio 15 2017"
+ GENERATOR: "Visual Studio 17 2022"
ARCHITECTURE: ARM64
CONFIGURATION: Release
WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0"
@@ -46,7 +46,7 @@
- script: |
cd ..
- git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git kodi
+ git clone --branch Matrix --depth=1 https://github.com/xbmc/xbmc.git kodi
cd $(Build.SourcesDirectory)
mkdir build
cd build
diff -Nru kodi-audiodecoder-gme-2.0.3/.clang-format kodi-audiodecoder-gme-19.0.3/.clang-format
--- kodi-audiodecoder-gme-2.0.3/.clang-format 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/.clang-format 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,88 @@
+---
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: DontAlign
+AlignOperands: true
+AlignTrailingComments: false
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: InlineOnly
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Allman
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 100
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeBlocks: Regroup
+IncludeCategories:
+ - Regex: '^<[a-z0-9_]+>$'
+ Priority: 3
+ - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>$'
+ Priority: 3
+ - Regex: '^<'
+ Priority: 3
+ - Regex: '^["<](kodi|p8-platform)\/.*\.h[">]$'
+ Priority: 2
+ - Regex: '.*'
+ Priority: 1
+IncludeIsMainRegex: '$'
+IndentCaseLabels: true
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60000
+PointerAlignment: Left
+ReflowComments: false
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Cpp11
+TabWidth: 8
+UseTab: Never
+...
diff -Nru kodi-audiodecoder-gme-2.0.3/CMakeLists.txt kodi-audiodecoder-gme-19.0.3/CMakeLists.txt
--- kodi-audiodecoder-gme-2.0.3/CMakeLists.txt 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/CMakeLists.txt 2013-05-31 22:59:22.000000000 +0000
@@ -13,6 +13,7 @@
add_subdirectory(lib/Game_Music_Emu)
set(GME_SOURCES src/GMECodec.cpp)
+set(GME_HEADERS src/GMECodec.h)
set(DEPLIBS gme fileex)
diff -Nru kodi-audiodecoder-gme-2.0.3/debian/changelog kodi-audiodecoder-gme-19.0.3/debian/changelog
--- kodi-audiodecoder-gme-2.0.3/debian/changelog 2013-05-31 22:59:22.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/debian/changelog 2013-05-31 22:59:22.000000000 +0000
@@ -1,4 +1,4 @@
-kodi-audiodecoder-gme (2.0.3-1~focal) focal; urgency=low
+kodi-audiodecoder-gme (6:19.0.3-1~focal) focal; urgency=low
[ kodi ]
* autogenerated dummy changelog
diff -Nru kodi-audiodecoder-gme-2.0.3/debian/control kodi-audiodecoder-gme-19.0.3/debian/control
--- kodi-audiodecoder-gme-2.0.3/debian/control 2013-05-31 22:59:22.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/debian/control 2013-05-31 22:59:22.000000000 +0000
@@ -4,7 +4,7 @@
Build-Depends: debhelper (>= 9.0.0), cmake, kodi-addon-dev
Standards-Version: 4.1.2
Section: libs
-Homepage: http://kodi.tv
+Homepage: https://kodi.tv
Package: kodi-audiodecoder-gme
Section: libs
diff -Nru kodi-audiodecoder-gme-2.0.3/debian/copyright kodi-audiodecoder-gme-19.0.3/debian/copyright
--- kodi-audiodecoder-gme-2.0.3/debian/copyright 2013-05-31 22:59:22.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/debian/copyright 2013-05-31 22:59:22.000000000 +0000
@@ -3,7 +3,7 @@
Source: https://github.com/xbmc/audiodecoder.gme
Files: *
-Copyright: 2005-2020 Team Kodi
+Copyright: 2005-2022 Team Kodi
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -Nru kodi-audiodecoder-gme-2.0.3/debian/rules kodi-audiodecoder-gme-19.0.3/debian/rules
--- kodi-audiodecoder-gme-2.0.3/debian/rules 2013-05-31 22:59:22.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/debian/rules 2013-05-31 22:59:22.000000000 +0000
@@ -10,13 +10,10 @@
#export DH_VERBOSE=1
%:
- dh $@
+ dh $@
override_dh_auto_configure:
- dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1
-
-override_dh_strip:
- dh_strip --dbg-package=kodi-audiodecoder-gme-dbg
+ dh_auto_configure -- -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1
override_dh_installdocs:
dh_installdocs --link-doc=kodi-audiodecoder-gme
diff -Nru kodi-audiodecoder-gme-2.0.3/debian/source/format kodi-audiodecoder-gme-19.0.3/debian/source/format
--- kodi-audiodecoder-gme-2.0.3/debian/source/format 2013-05-31 22:59:22.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/debian/source/format 2013-05-31 22:59:22.000000000 +0000
@@ -1 +1 @@
-3.0 (quilt)
+3.0 (native)
diff -Nru kodi-audiodecoder-gme-2.0.3/.github/workflows/build.yml kodi-audiodecoder-gme-19.0.3/.github/workflows/build.yml
--- kodi-audiodecoder-gme-2.0.3/.github/workflows/build.yml 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/.github/workflows/build.yml 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,61 @@
+name: Build and run tests
+on: [push, pull_request]
+env:
+ app_id: audiodecoder.gme
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: "Debian package test"
+ os: ubuntu-20.04
+ CC: gcc
+ CXX: g++
+ DEBIAN_BUILD: true
+ #- os: ubuntu-20.04
+ #CC: gcc
+ #CXX: g++
+ #- os: ubuntu-20.04
+ #CC: clang
+ #CXX: clang++
+ #- os: macos-11
+ steps:
+ - name: Install needed ubuntu depends
+ env:
+ DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+ run: |
+ if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/ppa; fi
+ if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get update; fi
+ if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get install fakeroot; fi
+ - name: Checkout Kodi repo
+ uses: actions/checkout@v2
+ with:
+ repository: xbmc/xbmc
+ ref: Matrix
+ path: xbmc
+ - name: Checkout audiodecoder.gme repo
+ uses: actions/checkout@v2
+ with:
+ path: ${{ env.app_id }}
+ - name: Configure
+ env:
+ CC: ${{ matrix.CC }}
+ CXX: ${{ matrix.CXX }}
+ DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+ run: |
+ if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id} && mkdir -p build && cd build; fi
+ if [[ $DEBIAN_BUILD != true ]]; then cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=${{ github.workspace }} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/xbmc/addons -DPACKAGE_ZIP=1 ${{ github.workspace }}/xbmc/cmake/addons; fi
+ if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/Matrix/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi
+ if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get build-dep ${{ github.workspace }}/${app_id}; fi
+ - name: Build
+ env:
+ CC: ${{ matrix.CC }}
+ CXX: ${{ matrix.CXX }}
+ DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }}
+ run: |
+ if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id}/build; fi
+ if [[ $DEBIAN_BUILD != true ]]; then make; fi
+ if [[ $DEBIAN_BUILD == true ]]; then ./debian-addon-package-test.sh ${{ github.workspace }}/${app_id}; fi
diff -Nru kodi-audiodecoder-gme-2.0.3/.github/workflows/sync-addon-metadata-translations.yml kodi-audiodecoder-gme-19.0.3/.github/workflows/sync-addon-metadata-translations.yml
--- kodi-audiodecoder-gme-2.0.3/.github/workflows/sync-addon-metadata-translations.yml 1970-01-01 00:00:00.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/.github/workflows/sync-addon-metadata-translations.yml 2013-05-31 22:59:22.000000000 +0000
@@ -0,0 +1,46 @@
+name: Sync addon metadata translations
+
+on:
+ push:
+ branches: [ Matrix, Nexus ]
+ paths:
+ - '**addon.xml'
+ - '**resource.language.**strings.po'
+
+jobs:
+ default:
+ if: github.repository == 'xbmc/audiodecoder.gme'
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ with:
+ path: project
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: '3.9'
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install git+https://github.com/xbmc/sync_addon_metadata_translations.git
+
+ - name: Run sync-addon-metadata-translations
+ run: |
+ sync-addon-metadata-translations
+ working-directory: ./project
+
+ - name: Create PR for sync-addon-metadata-translations changes
+ uses: peter-evans/create-pull-request@v3.10.0
+ with:
+ commit-message: Sync of addon metadata translations
+ title: Sync of addon metadata translations
+ body: Sync of addon metadata translations triggered by ${{ github.sha }}
+ branch: amt-sync
+ delete-branch: true
+ path: ./project
+ reviewers: gade01
diff -Nru kodi-audiodecoder-gme-2.0.3/Jenkinsfile kodi-audiodecoder-gme-19.0.3/Jenkinsfile
--- kodi-audiodecoder-gme-2.0.3/Jenkinsfile 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/Jenkinsfile 2013-05-31 22:59:22.000000000 +0000
@@ -1 +1 @@
-buildPlugin(version: "Leia")
+buildPlugin(version: "Matrix")
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/File_Extractor/win32/File_Extractor/.gitignore kodi-audiodecoder-gme-19.0.3/lib/File_Extractor/win32/File_Extractor/.gitignore
--- kodi-audiodecoder-gme-2.0.3/lib/File_Extractor/win32/File_Extractor/.gitignore 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/File_Extractor/win32/File_Extractor/.gitignore 1970-01-01 00:00:00.000000000 +0000
@@ -1,3 +0,0 @@
-*.user
-Debug
-Release
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Ay_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Ay_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Ay_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Ay_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,357 +1,357 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Ay_Emu.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// TODO: probably don't need detailed errors as to why file is corrupt
-
-int const spectrum_clock = 3546900; // 128K Spectrum
-int const spectrum_period = 70908;
-
-//int const spectrum_clock = 3500000; // 48K Spectrum
-//int const spectrum_period = 69888;
-
-int const cpc_clock = 2000000;
-
-Ay_Emu::Ay_Emu()
-{
- core.set_cpc_callback( enable_cpc_, this );
- set_type( gme_ay_type );
- set_silence_lookahead( 6 );
-}
-
-Ay_Emu::~Ay_Emu() { }
-
-// Track info
-
-// Given pointer to 2-byte offset of data, returns pointer to data, or NULL if
-// offset is 0 or there is less than min_size bytes of data available.
-static byte const* get_data( Ay_Emu::file_t const& file, byte const ptr [], int min_size )
-{
- int offset = (BOOST::int16_t) get_be16( ptr );
- int pos = ptr - (byte const*) file.header;
- int size = file.end - (byte const*) file.header;
- assert( (unsigned) pos <= (unsigned) size - 2 );
- int limit = size - min_size;
- if ( limit < 0 || !offset || (unsigned) (pos + offset) > (unsigned) limit )
- return NULL;
- return ptr + offset;
-}
-
-static blargg_err_t parse_header( byte const in [], int size, Ay_Emu::file_t* out )
-{
- typedef Ay_Emu::header_t header_t;
- if ( size < header_t::size )
- return blargg_err_file_type;
-
- out->header = (header_t const*) in;
- out->end = in + size;
- header_t const& h = *(header_t const*) in;
- if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
- return blargg_err_file_type;
-
- out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
- if ( !out->tracks )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "missing track data" );
-
- return blargg_ok;
-}
-
-static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
-{
- Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
- byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
- if ( track_info )
- out->length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
-
- Gme_File::copy_field_( out->author, (char const*) get_data( file, file.header->author, 1 ) );
- Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
-}
-
-static void hash_ay_file( Ay_Emu::file_t const& file, Gme_Info_::Hash_Function& out )
-{
- out.hash_( &file.header->vers, sizeof(file.header->vers) );
- out.hash_( &file.header->player, sizeof(file.header->player) );
- out.hash_( &file.header->unused[0], sizeof(file.header->unused) );
- out.hash_( &file.header->max_track, sizeof(file.header->max_track) );
- out.hash_( &file.header->first_track, sizeof(file.header->first_track) );
-
- for ( unsigned i = 0; i <= file.header->max_track; i++ )
- {
- byte const* track_info = get_data( file, file.tracks + i * 4 + 2, 14 );
- if ( track_info )
- {
- out.hash_( track_info + 8, 2 );
- byte const* points = get_data( file, track_info + 10, 6 );
- if ( points ) out.hash_( points, 6 );
-
- byte const* blocks = get_data( file, track_info + 12, 8 );
- if ( blocks )
- {
- int addr = get_be16( blocks );
-
- while ( addr )
- {
- out.hash_( blocks, 4 );
-
- int len = get_be16( blocks + 2 );
-
- byte const* block = get_data( file, blocks + 4, len );
- if ( block ) out.hash_( block, len );
-
- blocks += 6;
- addr = get_be16( blocks );
- }
- }
- }
- }
-}
-
-blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
-{
- copy_ay_fields( file, out, track );
- return blargg_ok;
-}
-
-struct Ay_File : Gme_Info_
-{
- Ay_Emu::file_t file;
-
- Ay_File() { set_type( gme_ay_type ); }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- RETURN_ERR( parse_header( begin, size, &file ) );
- set_track_count( file.header->max_track + 1 );
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- copy_ay_fields( file, out, track );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_ay_file( file, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_ay_emu ()
-{
- return BLARGG_NEW Ay_Emu;
-}
-
-static Music_Emu* new_ay_file()
-{
- return BLARGG_NEW Ay_File;
-}
-
-gme_type_t_ const gme_ay_type [1] = {{
- "ZX Spectrum",
- 0,
- &new_ay_emu,
- &new_ay_file,
- "AY",
- 1
-}};
-
-// Setup
-
-blargg_err_t Ay_Emu::load_mem_( byte const in [], int size )
-{
- assert( offsetof (header_t,track_info [2]) == header_t::size );
-
- RETURN_ERR( parse_header( in, size, &file ) );
- set_track_count( file.header->max_track + 1 );
-
- if ( file.header->vers > 2 )
- set_warning( "Unknown file version" );
-
- int const osc_count = Ay_Apu::osc_count + 1; // +1 for beeper
-
- set_voice_count( osc_count );
- core.apu().volume( gain() );
-
- static const char* const names [osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Beeper"
- };
- set_voice_names( names );
-
- static int const types [osc_count] = {
- wave_type+0, wave_type+1, wave_type+2, mixed_type+1
- };
- set_voice_types( types );
-
- return setup_buffer( spectrum_clock );
-}
-
-void Ay_Emu::update_eq( blip_eq_t const& eq )
-{
- core.apu().treble_eq( eq );
-}
-
-void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
-{
- if ( i >= Ay_Apu::osc_count )
- core.set_beeper_output( center );
- else
- core.apu().set_output( i, center );
-}
-
-void Ay_Emu::set_tempo_( double t )
-{
- int p = spectrum_period;
- if ( clock_rate() != spectrum_clock )
- p = clock_rate() / 50;
-
- core.set_play_period( blip_time_t (p / t) );
-}
-
-blargg_err_t Ay_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- byte* const mem = core.mem();
-
- memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
- memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
- memset( mem + core.ram_addr, 0x00, core.mem_size - core.ram_addr );
-
- // locate data blocks
- byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
- if ( !data )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
-
- byte const* const more_data = get_data( file, data + 10, 6 );
- if ( !more_data )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
-
- byte const* blocks = get_data( file, data + 12, 8 );
- if ( !blocks )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
-
- // initial addresses
- unsigned addr = get_be16( blocks );
- if ( !addr )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
-
- unsigned init = get_be16( more_data + 2 );
- if ( !init )
- init = addr;
-
- // copy blocks into memory
- do
- {
- blocks += 2;
- unsigned len = get_be16( blocks ); blocks += 2;
- if ( addr + len > core.mem_size )
- {
- set_warning( "Bad data block size" );
- len = core.mem_size - addr;
- }
- check( len );
- byte const* in = get_data( file, blocks, 0 ); blocks += 2;
- if ( len > (unsigned) (file.end - in) )
- {
- set_warning( "File data missing" );
- len = file.end - in;
- }
- //dprintf( "addr: $%04X, len: $%04X\n", addr, len );
- if ( addr < core.ram_addr && addr >= 0x400 ) // several tracks use low data
- dprintf( "Block addr in ROM\n" );
- memcpy( mem + addr, in, len );
-
- if ( file.end - blocks < 8 )
- {
- set_warning( "File data missing" );
- break;
- }
- }
- while ( (addr = get_be16( blocks )) != 0 );
-
- // copy and configure driver
- static byte const passive [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x5E, // LOOP: IM 2
- 0xFB, // EI
- 0x76, // HALT
- 0x18, 0xFA // JR LOOP
- };
- static byte const active [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x56, // LOOP: IM 1
- 0xFB, // EI
- 0x76, // HALT
- 0xCD, 0, 0, // CALL play
- 0x18, 0xF7 // JR LOOP
- };
- memcpy( mem, passive, sizeof passive );
- int const play_addr = get_be16( more_data + 4 );
- if ( play_addr )
- {
- memcpy( mem, active, sizeof active );
- mem [ 9] = play_addr;
- mem [10] = play_addr >> 8;
- }
- mem [2] = init;
- mem [3] = init >> 8;
-
- mem [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
-
- // start at spectrum speed
- change_clock_rate( spectrum_clock );
- set_tempo( tempo() );
-
- Ay_Core::registers_t r = { };
- r.sp = get_be16( more_data );
- r.b.a = r.b.b = r.b.d = r.b.h = data [8];
- r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
- r.alt.w = r.w;
- r.ix = r.iy = r.w.hl;
-
- core.start_track( r, play_addr );
-
- return blargg_ok;
-}
-
-blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
-{
- core.end_frame( &duration );
- return blargg_ok;
-}
-
-inline void Ay_Emu::enable_cpc()
-{
- change_clock_rate( cpc_clock );
- set_tempo( tempo() );
-}
-
-void Ay_Emu::enable_cpc_( void* data )
-{
- STATIC_CAST(Ay_Emu*,data)->enable_cpc();
-}
-
-blargg_err_t Ay_Emu::hash_( Hash_Function& out ) const
-{
- hash_ay_file( file, out );
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Ay_Emu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// TODO: probably don't need detailed errors as to why file is corrupt
+
+int const spectrum_clock = 3546900; // 128K Spectrum
+int const spectrum_period = 70908;
+
+//int const spectrum_clock = 3500000; // 48K Spectrum
+//int const spectrum_period = 69888;
+
+int const cpc_clock = 2000000;
+
+Ay_Emu::Ay_Emu()
+{
+ core.set_cpc_callback( enable_cpc_, this );
+ set_type( gme_ay_type );
+ set_silence_lookahead( 6 );
+}
+
+Ay_Emu::~Ay_Emu() { }
+
+// Track info
+
+// Given pointer to 2-byte offset of data, returns pointer to data, or NULL if
+// offset is 0 or there is less than min_size bytes of data available.
+static byte const* get_data( Ay_Emu::file_t const& file, byte const ptr [], int min_size )
+{
+ int offset = (BOOST::int16_t) get_be16( ptr );
+ int pos = ptr - (byte const*) file.header;
+ int size = file.end - (byte const*) file.header;
+ assert( (unsigned) pos <= (unsigned) size - 2 );
+ int limit = size - min_size;
+ if ( limit < 0 || !offset || (unsigned) (pos + offset) > (unsigned) limit )
+ return NULL;
+ return ptr + offset;
+}
+
+static blargg_err_t parse_header( byte const in [], int size, Ay_Emu::file_t* out )
+{
+ typedef Ay_Emu::header_t header_t;
+ if ( size < header_t::size )
+ return blargg_err_file_type;
+
+ out->header = (header_t const*) in;
+ out->end = in + size;
+ header_t const& h = *(header_t const*) in;
+ if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
+ return blargg_err_file_type;
+
+ out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
+ if ( !out->tracks )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "missing track data" );
+
+ return blargg_ok;
+}
+
+static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
+{
+ Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
+ byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
+ if ( track_info )
+ out->length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
+
+ Gme_File::copy_field_( out->author, (char const*) get_data( file, file.header->author, 1 ) );
+ Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
+}
+
+static void hash_ay_file( Ay_Emu::file_t const& file, Gme_Info_::Hash_Function& out )
+{
+ out.hash_( &file.header->vers, sizeof(file.header->vers) );
+ out.hash_( &file.header->player, sizeof(file.header->player) );
+ out.hash_( &file.header->unused[0], sizeof(file.header->unused) );
+ out.hash_( &file.header->max_track, sizeof(file.header->max_track) );
+ out.hash_( &file.header->first_track, sizeof(file.header->first_track) );
+
+ for ( unsigned i = 0; i <= file.header->max_track; i++ )
+ {
+ byte const* track_info = get_data( file, file.tracks + i * 4 + 2, 14 );
+ if ( track_info )
+ {
+ out.hash_( track_info + 8, 2 );
+ byte const* points = get_data( file, track_info + 10, 6 );
+ if ( points ) out.hash_( points, 6 );
+
+ byte const* blocks = get_data( file, track_info + 12, 8 );
+ if ( blocks )
+ {
+ int addr = get_be16( blocks );
+
+ while ( addr )
+ {
+ out.hash_( blocks, 4 );
+
+ int len = get_be16( blocks + 2 );
+
+ byte const* block = get_data( file, blocks + 4, len );
+ if ( block ) out.hash_( block, len );
+
+ blocks += 6;
+ addr = get_be16( blocks );
+ }
+ }
+ }
+ }
+}
+
+blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
+{
+ copy_ay_fields( file, out, track );
+ return blargg_ok;
+}
+
+struct Ay_File : Gme_Info_
+{
+ Ay_Emu::file_t file;
+
+ Ay_File() { set_type( gme_ay_type ); }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ RETURN_ERR( parse_header( begin, size, &file ) );
+ set_track_count( file.header->max_track + 1 );
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int track ) const
+ {
+ copy_ay_fields( file, out, track );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_ay_file( file, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_ay_emu ()
+{
+ return BLARGG_NEW Ay_Emu;
+}
+
+static Music_Emu* new_ay_file()
+{
+ return BLARGG_NEW Ay_File;
+}
+
+gme_type_t_ const gme_ay_type [1] = {{
+ "ZX Spectrum",
+ 0,
+ &new_ay_emu,
+ &new_ay_file,
+ "AY",
+ 1
+}};
+
+// Setup
+
+blargg_err_t Ay_Emu::load_mem_( byte const in [], int size )
+{
+ assert( offsetof (header_t,track_info [2]) == header_t::size );
+
+ RETURN_ERR( parse_header( in, size, &file ) );
+ set_track_count( file.header->max_track + 1 );
+
+ if ( file.header->vers > 2 )
+ set_warning( "Unknown file version" );
+
+ int const osc_count = Ay_Apu::osc_count + 1; // +1 for beeper
+
+ set_voice_count( osc_count );
+ core.apu().volume( gain() );
+
+ static const char* const names [osc_count] = {
+ "Wave 1", "Wave 2", "Wave 3", "Beeper"
+ };
+ set_voice_names( names );
+
+ static int const types [osc_count] = {
+ wave_type+0, wave_type+1, wave_type+2, mixed_type+1
+ };
+ set_voice_types( types );
+
+ return setup_buffer( spectrum_clock );
+}
+
+void Ay_Emu::update_eq( blip_eq_t const& eq )
+{
+ core.apu().treble_eq( eq );
+}
+
+void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
+{
+ if ( i >= Ay_Apu::osc_count )
+ core.set_beeper_output( center );
+ else
+ core.apu().set_output( i, center );
+}
+
+void Ay_Emu::set_tempo_( double t )
+{
+ int p = spectrum_period;
+ if ( clock_rate() != spectrum_clock )
+ p = clock_rate() / 50;
+
+ core.set_play_period( blip_time_t (p / t) );
+}
+
+blargg_err_t Ay_Emu::start_track_( int track )
+{
+ RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+ byte* const mem = core.mem();
+
+ memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
+ memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
+ memset( mem + core.ram_addr, 0x00, core.mem_size - core.ram_addr );
+
+ // locate data blocks
+ byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
+ if ( !data )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
+
+ byte const* const more_data = get_data( file, data + 10, 6 );
+ if ( !more_data )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
+
+ byte const* blocks = get_data( file, data + 12, 8 );
+ if ( !blocks )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
+
+ // initial addresses
+ unsigned addr = get_be16( blocks );
+ if ( !addr )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "file data missing" );
+
+ unsigned init = get_be16( more_data + 2 );
+ if ( !init )
+ init = addr;
+
+ // copy blocks into memory
+ do
+ {
+ blocks += 2;
+ unsigned len = get_be16( blocks ); blocks += 2;
+ if ( addr + len > core.mem_size )
+ {
+ set_warning( "Bad data block size" );
+ len = core.mem_size - addr;
+ }
+ check( len );
+ byte const* in = get_data( file, blocks, 0 ); blocks += 2;
+ if ( len > (unsigned) (file.end - in) )
+ {
+ set_warning( "File data missing" );
+ len = file.end - in;
+ }
+ //dprintf( "addr: $%04X, len: $%04X\n", addr, len );
+ if ( addr < core.ram_addr && addr >= 0x400 ) // several tracks use low data
+ dprintf( "Block addr in ROM\n" );
+ memcpy( mem + addr, in, len );
+
+ if ( file.end - blocks < 8 )
+ {
+ set_warning( "File data missing" );
+ break;
+ }
+ }
+ while ( (addr = get_be16( blocks )) != 0 );
+
+ // copy and configure driver
+ static byte const passive [] = {
+ 0xF3, // DI
+ 0xCD, 0, 0, // CALL init
+ 0xED, 0x5E, // LOOP: IM 2
+ 0xFB, // EI
+ 0x76, // HALT
+ 0x18, 0xFA // JR LOOP
+ };
+ static byte const active [] = {
+ 0xF3, // DI
+ 0xCD, 0, 0, // CALL init
+ 0xED, 0x56, // LOOP: IM 1
+ 0xFB, // EI
+ 0x76, // HALT
+ 0xCD, 0, 0, // CALL play
+ 0x18, 0xF7 // JR LOOP
+ };
+ memcpy( mem, passive, sizeof passive );
+ int const play_addr = get_be16( more_data + 4 );
+ if ( play_addr )
+ {
+ memcpy( mem, active, sizeof active );
+ mem [ 9] = play_addr;
+ mem [10] = play_addr >> 8;
+ }
+ mem [2] = init;
+ mem [3] = init >> 8;
+
+ mem [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
+
+ // start at spectrum speed
+ change_clock_rate( spectrum_clock );
+ set_tempo( tempo() );
+
+ Ay_Core::registers_t r = { };
+ r.sp = get_be16( more_data );
+ r.b.a = r.b.b = r.b.d = r.b.h = data [8];
+ r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
+ r.alt.w = r.w;
+ r.ix = r.iy = r.w.hl;
+
+ core.start_track( r, play_addr );
+
+ return blargg_ok;
+}
+
+blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
+{
+ core.end_frame( &duration );
+ return blargg_ok;
+}
+
+inline void Ay_Emu::enable_cpc()
+{
+ change_clock_rate( cpc_clock );
+ set_tempo( tempo() );
+}
+
+void Ay_Emu::enable_cpc_( void* data )
+{
+ STATIC_CAST(Ay_Emu*,data)->enable_cpc();
+}
+
+blargg_err_t Ay_Emu::hash_( Hash_Function& out ) const
+{
+ hash_ay_file( file, out );
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_common.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_common.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_common.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_common.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,58 +1,58 @@
-// $package. http://www.slack.net/~ant/
-
-#include "blargg_common.h"
-
-/* Copyright (C) 2008-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-BLARGG_NAMESPACE_BEGIN
-
-// defined here to avoid need for blargg_errors.cpp in simple programs
-blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
-
-void blargg_vector_::init()
-{
- begin_ = NULL;
- size_ = 0;
-}
-
-void blargg_vector_::clear()
-{
- void* p = begin_;
- begin_ = NULL;
- size_ = 0;
- free( p );
-}
-
-blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
-{
- if ( n != size_ )
- {
- if ( n == 0 )
- {
- // Simpler to handle explicitly. Realloc will handle a size of 0,
- // but then we have to avoid raising an error for a NULL return.
- clear();
- }
- else
- {
- void* p = realloc( begin_, n * elem_size );
- CHECK_ALLOC( p );
- begin_ = p;
- size_ = n;
- }
- }
- return blargg_ok;
-}
-
-BLARGG_NAMESPACE_END
+// $package. http://www.slack.net/~ant/
+
+#include "blargg_common.h"
+
+/* Copyright (C) 2008-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+BLARGG_NAMESPACE_BEGIN
+
+// defined here to avoid need for blargg_errors.cpp in simple programs
+blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
+
+void blargg_vector_::init()
+{
+ begin_ = NULL;
+ size_ = 0;
+}
+
+void blargg_vector_::clear()
+{
+ void* p = begin_;
+ begin_ = NULL;
+ size_ = 0;
+ free( p );
+}
+
+blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
+{
+ if ( n != size_ )
+ {
+ if ( n == 0 )
+ {
+ // Simpler to handle explicitly. Realloc will handle a size of 0,
+ // but then we have to avoid raising an error for a NULL return.
+ clear();
+ }
+ else
+ {
+ void* p = realloc( begin_, n * elem_size );
+ CHECK_ALLOC( p );
+ begin_ = p;
+ size_ = n;
+ }
+ }
+ return blargg_ok;
+}
+
+BLARGG_NAMESPACE_END
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_common.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_common.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_common.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_common.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,224 +1,224 @@
-// Sets up common environment for Shay Green's libraries.
-// To change configuration options, modify blargg_config.h, not this file.
-
-// $package
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-#include
-#include
-#include
-
-typedef const char* blargg_err_t; // 0 on success, otherwise error string
-
-// Success; no error
-blargg_err_t const blargg_ok = 0;
-
-// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
-#if __GNUC__ >= 3 || _MSC_VER >= 1100
- #define BLARGG_RESTRICT __restrict
-#else
- #define BLARGG_RESTRICT
-#endif
-
-#if __cplusplus >= 199711
- #define BLARGG_MUTABLE mutable
-#else
- #define BLARGG_MUTABLE
-#endif
-
-/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
-I don't just use 'abcd' because that's implementation-dependent. */
-#define BLARGG_4CHAR( a, b, c, d ) \
- ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
-
-/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
-Can be used at file, function, or class scope. */
-#ifdef _MSC_VER
- // MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
- #define BLARGG_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
-#else
- // Others fail when declaring same function multiple times in class,
- // so differentiate them by line
- #define BLARGG_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
-#endif
-
-/* Pure virtual functions cause a vtable entry to a "called pure virtual"
-error handler, requiring linkage to the C++ runtime library. This macro is
-used in place of the "= 0", and simply expands to its argument. During
-development, it expands to "= 0", allowing detection of missing overrides. */
-#define BLARGG_PURE( def ) def
-
-/* My code depends on ASCII anywhere a character or string constant is
-compared with data read from a file, and anywhere file data is read and
-treated as a string. */
-#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
- #error "ASCII character set required"
-#endif
-
-/* My code depends on int being at least 32 bits. Almost everything these days
-uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
-to test with. The issue can't be gotten around by using a suitable blargg_int
-everywhere either, because int is often converted to implicitly when doing
-arithmetic on smaller types. */
-#if UINT_MAX < 0xFFFFFFFF
- #error "int must be at least 32 bits"
-#endif
-
-// In case compiler doesn't support these properly. Used rarely.
-#define STATIC_CAST(T,expr) static_cast (expr)
-#define CONST_CAST( T,expr) const_cast (expr)
-
-// User configuration can override the above macros if necessary
-#include "blargg_config.h"
-
-#ifdef BLARGG_NAMESPACE
- #define BLARGG_NAMESPACE_BEGIN namespace BLARGG_NAMESPACE {
- #define BLARGG_NAMESPACE_END }
-
- BLARGG_NAMESPACE_BEGIN
- BLARGG_NAMESPACE_END
- using namespace BLARGG_NAMESPACE;
-#else
- #define BLARGG_NAMESPACE_BEGIN
- #define BLARGG_NAMESPACE_END
-#endif
-
-BLARGG_NAMESPACE_BEGIN
-
-/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
-future version. In GCC, we can let the compiler warn. In other compilers,
-we strip it out unless BLARGG_LEGACY is true. */
-#if BLARGG_LEGACY
- // Allow old client code to work without warnings
- #define BLARGG_DEPRECATED_TEXT( text ) text
- #define BLARGG_DEPRECATED( text ) text
-#elif __GNUC__ >= 4
- // In GCC, we can mark declarations and let the compiler warn
- #define BLARGG_DEPRECATED_TEXT( text ) text
- #define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
-#else
- // By default, deprecated items are removed, to avoid use in new code
- #define BLARGG_DEPRECATED_TEXT( text )
- #define BLARGG_DEPRECATED( text )
-#endif
-
-/* BOOST::int8_t, BOOST::int32_t, etc.
-I used BOOST since I originally was going to allow use of the boost library
-for prividing the definitions. If I'm defining them, they must be scoped or
-else they could conflict with the standard ones at global scope. Even if
-HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
-global scope already. */
-#if defined (HAVE_STDINT_H) || \
- UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
- #include
- #define BOOST
-#else
- struct BOOST
- {
- typedef signed char int8_t;
- typedef unsigned char uint8_t;
- typedef short int16_t;
- typedef unsigned short uint16_t;
- typedef int int32_t;
- typedef unsigned int uint32_t;
- typedef __int64 int64_t;
- typedef unsigned __int64 uint64_t;
- };
-#endif
-
-/* My code is not written with exceptions in mind, so either uses new (nothrow)
-OR overrides operator new in my classes. The former is best since clients
-creating objects will get standard exceptions on failure, but that causes it
-to require the standard C++ library. So, when the client is using the C
-interface, I override operator new to use malloc. */
-
-// BLARGG_DISABLE_NOTHROW is put inside classes
-#ifndef BLARGG_DISABLE_NOTHROW
- // throw spec mandatory in ISO C++ if NULL can be returned
- #if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
- #define BLARGG_THROWS_NOTHING throw ()
- #else
- #define BLARGG_THROWS_NOTHING
- #endif
-
- #define BLARGG_DISABLE_NOTHROW \
- void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
- void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
-
- #define BLARGG_NEW new
-#else
- // BLARGG_NEW is used in place of new in library code
- #include
- #define BLARGG_NEW new (std::nothrow)
-#endif
-
- class blargg_vector_ {
- protected:
- void* begin_;
- size_t size_;
- void init();
- blargg_err_t resize_( size_t n, size_t elem_size );
- public:
- size_t size() const { return size_; }
- void clear();
- };
-
-// Very lightweight vector for POD types (no constructor/destructor)
-template
-class blargg_vector : public blargg_vector_ {
- union T_must_be_pod { T t; }; // fails if T is not POD
-public:
- blargg_vector() { init(); }
- ~blargg_vector() { clear(); }
-
- blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
-
- T* begin() { return static_cast (begin_); }
- const T* begin() const { return static_cast (begin_); }
-
- T* end() { return static_cast (begin_) + size_; }
- const T* end() const { return static_cast (begin_) + size_; }
-
- T& operator [] ( size_t n )
- {
- assert( n < size_ );
- return static_cast (begin_) [n];
- }
-
- const T& operator [] ( size_t n ) const
- {
- assert( n < size_ );
- return static_cast (begin_) [n];
- }
-};
-
-// Callback function with user data.
-// blargg_callback set_callback; // for user, this acts like...
-// void set_callback( T func, void* user_data = NULL ); // ...this
-// To call function, do set_callback.f( .. set_callback.data ... );
-template
-struct blargg_callback
-{
- T f;
- void* data;
- blargg_callback() { f = NULL; }
- void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
-};
-
-#ifndef _WIN32
- // Not supported on any other platforms
- #undef BLARGG_UTF8_PATHS
-#endif
-
-BLARGG_DEPRECATED( typedef signed int blargg_long; )
-BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
-#if BLARGG_LEGACY
- #define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
-#endif
-
-BLARGG_NAMESPACE_END
-
-#endif
+// Sets up common environment for Shay Green's libraries.
+// To change configuration options, modify blargg_config.h, not this file.
+
+// $package
+#ifndef BLARGG_COMMON_H
+#define BLARGG_COMMON_H
+
+#include
+#include
+#include
+
+typedef const char* blargg_err_t; // 0 on success, otherwise error string
+
+// Success; no error
+blargg_err_t const blargg_ok = 0;
+
+// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
+#if __GNUC__ >= 3 || _MSC_VER >= 1100
+ #define BLARGG_RESTRICT __restrict
+#else
+ #define BLARGG_RESTRICT
+#endif
+
+#if __cplusplus >= 199711
+ #define BLARGG_MUTABLE mutable
+#else
+ #define BLARGG_MUTABLE
+#endif
+
+/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
+I don't just use 'abcd' because that's implementation-dependent. */
+#define BLARGG_4CHAR( a, b, c, d ) \
+ ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
+
+/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
+Can be used at file, function, or class scope. */
+#ifdef _MSC_VER
+ // MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
+ #define BLARGG_STATIC_ASSERT( expr ) \
+ void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
+#else
+ // Others fail when declaring same function multiple times in class,
+ // so differentiate them by line
+ #define BLARGG_STATIC_ASSERT( expr ) \
+ void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
+#endif
+
+/* Pure virtual functions cause a vtable entry to a "called pure virtual"
+error handler, requiring linkage to the C++ runtime library. This macro is
+used in place of the "= 0", and simply expands to its argument. During
+development, it expands to "= 0", allowing detection of missing overrides. */
+#define BLARGG_PURE( def ) def
+
+/* My code depends on ASCII anywhere a character or string constant is
+compared with data read from a file, and anywhere file data is read and
+treated as a string. */
+#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
+ #error "ASCII character set required"
+#endif
+
+/* My code depends on int being at least 32 bits. Almost everything these days
+uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
+to test with. The issue can't be gotten around by using a suitable blargg_int
+everywhere either, because int is often converted to implicitly when doing
+arithmetic on smaller types. */
+#if UINT_MAX < 0xFFFFFFFF
+ #error "int must be at least 32 bits"
+#endif
+
+// In case compiler doesn't support these properly. Used rarely.
+#define STATIC_CAST(T,expr) static_cast (expr)
+#define CONST_CAST( T,expr) const_cast (expr)
+
+// User configuration can override the above macros if necessary
+#include "blargg_config.h"
+
+#ifdef BLARGG_NAMESPACE
+ #define BLARGG_NAMESPACE_BEGIN namespace BLARGG_NAMESPACE {
+ #define BLARGG_NAMESPACE_END }
+
+ BLARGG_NAMESPACE_BEGIN
+ BLARGG_NAMESPACE_END
+ using namespace BLARGG_NAMESPACE;
+#else
+ #define BLARGG_NAMESPACE_BEGIN
+ #define BLARGG_NAMESPACE_END
+#endif
+
+BLARGG_NAMESPACE_BEGIN
+
+/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
+future version. In GCC, we can let the compiler warn. In other compilers,
+we strip it out unless BLARGG_LEGACY is true. */
+#if BLARGG_LEGACY
+ // Allow old client code to work without warnings
+ #define BLARGG_DEPRECATED_TEXT( text ) text
+ #define BLARGG_DEPRECATED( text ) text
+#elif __GNUC__ >= 4
+ // In GCC, we can mark declarations and let the compiler warn
+ #define BLARGG_DEPRECATED_TEXT( text ) text
+ #define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
+#else
+ // By default, deprecated items are removed, to avoid use in new code
+ #define BLARGG_DEPRECATED_TEXT( text )
+ #define BLARGG_DEPRECATED( text )
+#endif
+
+/* BOOST::int8_t, BOOST::int32_t, etc.
+I used BOOST since I originally was going to allow use of the boost library
+for prividing the definitions. If I'm defining them, they must be scoped or
+else they could conflict with the standard ones at global scope. Even if
+HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
+global scope already. */
+#if defined (HAVE_STDINT_H) || \
+ UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
+ #include
+ #define BOOST
+#else
+ struct BOOST
+ {
+ typedef signed char int8_t;
+ typedef unsigned char uint8_t;
+ typedef short int16_t;
+ typedef unsigned short uint16_t;
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+ };
+#endif
+
+/* My code is not written with exceptions in mind, so either uses new (nothrow)
+OR overrides operator new in my classes. The former is best since clients
+creating objects will get standard exceptions on failure, but that causes it
+to require the standard C++ library. So, when the client is using the C
+interface, I override operator new to use malloc. */
+
+// BLARGG_DISABLE_NOTHROW is put inside classes
+#ifndef BLARGG_DISABLE_NOTHROW
+ // throw spec mandatory in ISO C++ if NULL can be returned
+ #if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
+ #define BLARGG_THROWS_NOTHING throw ()
+ #else
+ #define BLARGG_THROWS_NOTHING
+ #endif
+
+ #define BLARGG_DISABLE_NOTHROW \
+ void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
+ void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
+
+ #define BLARGG_NEW new
+#else
+ // BLARGG_NEW is used in place of new in library code
+ #include
+ #define BLARGG_NEW new (std::nothrow)
+#endif
+
+ class blargg_vector_ {
+ protected:
+ void* begin_;
+ size_t size_;
+ void init();
+ blargg_err_t resize_( size_t n, size_t elem_size );
+ public:
+ size_t size() const { return size_; }
+ void clear();
+ };
+
+// Very lightweight vector for POD types (no constructor/destructor)
+template
+class blargg_vector : public blargg_vector_ {
+ union T_must_be_pod { T t; }; // fails if T is not POD
+public:
+ blargg_vector() { init(); }
+ ~blargg_vector() { clear(); }
+
+ blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
+
+ T* begin() { return static_cast (begin_); }
+ const T* begin() const { return static_cast (begin_); }
+
+ T* end() { return static_cast (begin_) + size_; }
+ const T* end() const { return static_cast (begin_) + size_; }
+
+ T& operator [] ( size_t n )
+ {
+ assert( n < size_ );
+ return static_cast (begin_) [n];
+ }
+
+ const T& operator [] ( size_t n ) const
+ {
+ assert( n < size_ );
+ return static_cast (begin_) [n];
+ }
+};
+
+// Callback function with user data.
+// blargg_callback set_callback; // for user, this acts like...
+// void set_callback( T func, void* user_data = NULL ); // ...this
+// To call function, do set_callback.f( .. set_callback.data ... );
+template
+struct blargg_callback
+{
+ T f;
+ void* data;
+ blargg_callback() { f = NULL; }
+ void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
+};
+
+#ifndef _WIN32
+ // Not supported on any other platforms
+ #undef BLARGG_UTF8_PATHS
+#endif
+
+BLARGG_DEPRECATED( typedef signed int blargg_long; )
+BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
+#if BLARGG_LEGACY
+ #define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
+#endif
+
+BLARGG_NAMESPACE_END
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_config.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_config.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_config.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_config.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,56 +1,56 @@
-// Library configuration. Modify this file as necessary.
-
-// $package
-#ifndef BLARGG_CONFIG_H
-#define BLARGG_CONFIG_H
-
-// Uncomment a #define line below to have effect described.
-
-// Allow static linking with this library and one of my other libraries
-// in the same program.
-//#define BLARGG_NAMESPACE blargg_gme
-
-// Use zlib for transparent decompression of gzipped files.
-//#define HAVE_ZLIB_H
-
-// Support only listed music types. Remove a line to disable that type.
-/* #define GME_TYPE_LIST \
- gme_ay_type,\
- gme_gbs_type,\
- gme_gym_type,\
- gme_hes_type,\
- gme_kss_type,\
- gme_nsf_type,\
- gme_nsfe_type,\
- gme_sap_type,\
- gme_sfm_type,\
- gme_sgc_type,\
- gme_spc_type,\
- gme_vgm_type,\
- gme_vgz_type
-*/
-
-// Enable platform-specific optimizations.
-//#define BLARGG_NONPORTABLE 1
-
-// Use faster sample rate convertor for SPC music.
-//#define GME_SPC_FAST_RESAMPLER 1
-
-// Use faster sample rate convertor for VGM and GYM music.
-//#define GME_VGM_FAST_RESAMPLER 1
-
-// Use faster, significantly lower quality sound synthesis for classic emulators.
-//#define BLIP_BUFFER_FAST 1
-
-// Reduce memory usage of gme.h by disabling gme_set_effects_config().
-//#define GME_DISABLE_EFFECTS 1
-
-// Force library to use assume big-endian processor.
-//#define BLARGG_BIG_ENDIAN 1
-
-// Use standard config.h if present
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#endif
+// Library configuration. Modify this file as necessary.
+
+// $package
+#ifndef BLARGG_CONFIG_H
+#define BLARGG_CONFIG_H
+
+// Uncomment a #define line below to have effect described.
+
+// Allow static linking with this library and one of my other libraries
+// in the same program.
+//#define BLARGG_NAMESPACE blargg_gme
+
+// Use zlib for transparent decompression of gzipped files.
+//#define HAVE_ZLIB_H
+
+// Support only listed music types. Remove a line to disable that type.
+/* #define GME_TYPE_LIST \
+ gme_ay_type,\
+ gme_gbs_type,\
+ gme_gym_type,\
+ gme_hes_type,\
+ gme_kss_type,\
+ gme_nsf_type,\
+ gme_nsfe_type,\
+ gme_sap_type,\
+ gme_sfm_type,\
+ gme_sgc_type,\
+ gme_spc_type,\
+ gme_vgm_type,\
+ gme_vgz_type
+*/
+
+// Enable platform-specific optimizations.
+//#define BLARGG_NONPORTABLE 1
+
+// Use faster sample rate convertor for SPC music.
+//#define GME_SPC_FAST_RESAMPLER 1
+
+// Use faster sample rate convertor for VGM and GYM music.
+//#define GME_VGM_FAST_RESAMPLER 1
+
+// Use faster, significantly lower quality sound synthesis for classic emulators.
+//#define BLIP_BUFFER_FAST 1
+
+// Reduce memory usage of gme.h by disabling gme_set_effects_config().
+//#define GME_DISABLE_EFFECTS 1
+
+// Force library to use assume big-endian processor.
+//#define BLARGG_BIG_ENDIAN 1
+
+// Use standard config.h if present
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_endian.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_endian.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_endian.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_endian.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,203 +1,203 @@
-// CPU Byte Order Utilities
-
-// $package
-#ifndef BLARGG_ENDIAN_H
-#define BLARGG_ENDIAN_H
-
-#include "blargg_common.h"
-
-// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
-#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
- #define BLARGG_CPU_X86 1
- #define BLARGG_CPU_CISC 1
-#endif
-
-#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
- defined (__POWERPC__) || defined (__powerc)
- #define BLARGG_CPU_POWERPC 1
- #define BLARGG_CPU_RISC 1
-#endif
-
-// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
-// one may be #defined to 1. Only needed if something actually depends on byte order.
-#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
-#ifdef __GLIBC__
- // GCC handles this for us
- #include
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- #define BLARGG_LITTLE_ENDIAN 1
- #elif __BYTE_ORDER == __BIG_ENDIAN
- #define BLARGG_BIG_ENDIAN 1
- #endif
-#else
-
-#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
- (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-
-#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
- defined (__sparc__) || BLARGG_CPU_POWERPC || \
- (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
- #define BLARGG_BIG_ENDIAN 1
-#elif !defined (__mips__)
- // No endian specified; assume little-endian, since it's most common
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-#endif
-#endif
-
-#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
- #undef BLARGG_LITTLE_ENDIAN
- #undef BLARGG_BIG_ENDIAN
-#endif
-
-BLARGG_NAMESPACE_BEGIN
-
-inline void blargg_verify_byte_order()
-{
- #ifndef NDEBUG
- #if BLARGG_BIG_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i == 0 );
- #elif BLARGG_LITTLE_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i != 0 );
- #endif
- #endif
-}
-
-inline unsigned get_le16( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [1] << 8 |
- (unsigned) ((unsigned char const*) p) [0];
-}
-
-inline unsigned get_be16( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [0] << 8 |
- (unsigned) ((unsigned char const*) p) [1];
-}
-
-inline unsigned get_le24( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [2] << 16 |
- (unsigned) ((unsigned char const*) p) [1] << 8 |
- (unsigned) ((unsigned char const*) p) [0];
-}
-
-inline unsigned get_be24( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [0] << 16 |
- (unsigned) ((unsigned char const*) p) [1] << 8 |
- (unsigned) ((unsigned char const*) p) [2];
-}
-
-inline unsigned get_le32( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [3] << 24 |
- (unsigned) ((unsigned char const*) p) [2] << 16 |
- (unsigned) ((unsigned char const*) p) [1] << 8 |
- (unsigned) ((unsigned char const*) p) [0];
-}
-
-inline unsigned get_be32( void const* p )
-{
- return (unsigned) ((unsigned char const*) p) [0] << 24 |
- (unsigned) ((unsigned char const*) p) [1] << 16 |
- (unsigned) ((unsigned char const*) p) [2] << 8 |
- (unsigned) ((unsigned char const*) p) [3];
-}
-
-inline void set_le16( void* p, unsigned n )
-{
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [0] = (unsigned char) n;
-}
-
-inline void set_be16( void* p, unsigned n )
-{
- ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [1] = (unsigned char) n;
-}
-
-inline void set_le32( void* p, unsigned n )
-{
- ((unsigned char*) p) [0] = (unsigned char) n;
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
-}
-
-inline void set_be32( void* p, unsigned n )
-{
- ((unsigned char*) p) [3] = (unsigned char) n;
- ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
-}
-
-#if BLARGG_NONPORTABLE
- // Optimized implementation if byte order is known
- #if BLARGG_LITTLE_ENDIAN
- #define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
- #define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
- #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
- #elif BLARGG_BIG_ENDIAN
- #define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
- #define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
- #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
-
- #if BLARGG_CPU_POWERPC
- // PowerPC has special byte-reversed instructions
- #if defined (__MWERKS__)
- #define GET_LE16( addr ) (__lhbrx( addr, 0 ))
- #define GET_LE32( addr ) (__lwbrx( addr, 0 ))
- #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
- #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
- #elif defined (__GNUC__)
- #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
- #define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
- #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
- #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
- #endif
- #endif
- #endif
-#endif
-
-#ifndef GET_LE16
- #define GET_LE16( addr ) get_le16( addr )
- #define SET_LE16( addr, data ) set_le16( addr, data )
-#endif
-
-#ifndef GET_LE32
- #define GET_LE32( addr ) get_le32( addr )
- #define SET_LE32( addr, data ) set_le32( addr, data )
-#endif
-
-#ifndef GET_BE16
- #define GET_BE16( addr ) get_be16( addr )
- #define SET_BE16( addr, data ) set_be16( addr, data )
-#endif
-
-#ifndef GET_BE32
- #define GET_BE32( addr ) get_be32( addr )
- #define SET_BE32( addr, data ) set_be32( addr, data )
-#endif
-
-// auto-selecting versions
-
-inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
-inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
-inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
-inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
-inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
-inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
-inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
-inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
-
-BLARGG_NAMESPACE_END
-
-#endif
+// CPU Byte Order Utilities
+
+// $package
+#ifndef BLARGG_ENDIAN_H
+#define BLARGG_ENDIAN_H
+
+#include "blargg_common.h"
+
+// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
+#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
+ #define BLARGG_CPU_X86 1
+ #define BLARGG_CPU_CISC 1
+#endif
+
+#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
+ defined (__POWERPC__) || defined (__powerc)
+ #define BLARGG_CPU_POWERPC 1
+ #define BLARGG_CPU_RISC 1
+#endif
+
+// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
+// one may be #defined to 1. Only needed if something actually depends on byte order.
+#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
+#ifdef __GLIBC__
+ // GCC handles this for us
+ #include
+ #if __BYTE_ORDER == __LITTLE_ENDIAN
+ #define BLARGG_LITTLE_ENDIAN 1
+ #elif __BYTE_ORDER == __BIG_ENDIAN
+ #define BLARGG_BIG_ENDIAN 1
+ #endif
+#else
+
+#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
+ (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
+ #define BLARGG_LITTLE_ENDIAN 1
+#endif
+
+#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
+ defined (__sparc__) || BLARGG_CPU_POWERPC || \
+ (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
+ #define BLARGG_BIG_ENDIAN 1
+#elif !defined (__mips__)
+ // No endian specified; assume little-endian, since it's most common
+ #define BLARGG_LITTLE_ENDIAN 1
+#endif
+#endif
+#endif
+
+#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
+ #undef BLARGG_LITTLE_ENDIAN
+ #undef BLARGG_BIG_ENDIAN
+#endif
+
+BLARGG_NAMESPACE_BEGIN
+
+inline void blargg_verify_byte_order()
+{
+ #ifndef NDEBUG
+ #if BLARGG_BIG_ENDIAN
+ volatile int i = 1;
+ assert( *(volatile char*) &i == 0 );
+ #elif BLARGG_LITTLE_ENDIAN
+ volatile int i = 1;
+ assert( *(volatile char*) &i != 0 );
+ #endif
+ #endif
+}
+
+inline unsigned get_le16( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [1] << 8 |
+ (unsigned) ((unsigned char const*) p) [0];
+}
+
+inline unsigned get_be16( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [0] << 8 |
+ (unsigned) ((unsigned char const*) p) [1];
+}
+
+inline unsigned get_le24( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [2] << 16 |
+ (unsigned) ((unsigned char const*) p) [1] << 8 |
+ (unsigned) ((unsigned char const*) p) [0];
+}
+
+inline unsigned get_be24( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [0] << 16 |
+ (unsigned) ((unsigned char const*) p) [1] << 8 |
+ (unsigned) ((unsigned char const*) p) [2];
+}
+
+inline unsigned get_le32( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [3] << 24 |
+ (unsigned) ((unsigned char const*) p) [2] << 16 |
+ (unsigned) ((unsigned char const*) p) [1] << 8 |
+ (unsigned) ((unsigned char const*) p) [0];
+}
+
+inline unsigned get_be32( void const* p )
+{
+ return (unsigned) ((unsigned char const*) p) [0] << 24 |
+ (unsigned) ((unsigned char const*) p) [1] << 16 |
+ (unsigned) ((unsigned char const*) p) [2] << 8 |
+ (unsigned) ((unsigned char const*) p) [3];
+}
+
+inline void set_le16( void* p, unsigned n )
+{
+ ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
+ ((unsigned char*) p) [0] = (unsigned char) n;
+}
+
+inline void set_be16( void* p, unsigned n )
+{
+ ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
+ ((unsigned char*) p) [1] = (unsigned char) n;
+}
+
+inline void set_le32( void* p, unsigned n )
+{
+ ((unsigned char*) p) [0] = (unsigned char) n;
+ ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
+ ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
+ ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
+}
+
+inline void set_be32( void* p, unsigned n )
+{
+ ((unsigned char*) p) [3] = (unsigned char) n;
+ ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
+ ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
+ ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
+}
+
+#if BLARGG_NONPORTABLE
+ // Optimized implementation if byte order is known
+ #if BLARGG_LITTLE_ENDIAN
+ #define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
+ #define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
+ #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
+ #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
+ #elif BLARGG_BIG_ENDIAN
+ #define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
+ #define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
+ #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
+ #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
+
+ #if BLARGG_CPU_POWERPC
+ // PowerPC has special byte-reversed instructions
+ #if defined (__MWERKS__)
+ #define GET_LE16( addr ) (__lhbrx( addr, 0 ))
+ #define GET_LE32( addr ) (__lwbrx( addr, 0 ))
+ #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
+ #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
+ #elif defined (__GNUC__)
+ #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
+ #define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
+ #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
+ #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
+ #endif
+ #endif
+ #endif
+#endif
+
+#ifndef GET_LE16
+ #define GET_LE16( addr ) get_le16( addr )
+ #define SET_LE16( addr, data ) set_le16( addr, data )
+#endif
+
+#ifndef GET_LE32
+ #define GET_LE32( addr ) get_le32( addr )
+ #define SET_LE32( addr, data ) set_le32( addr, data )
+#endif
+
+#ifndef GET_BE16
+ #define GET_BE16( addr ) get_be16( addr )
+ #define SET_BE16( addr, data ) set_be16( addr, data )
+#endif
+
+#ifndef GET_BE32
+ #define GET_BE32( addr ) get_be32( addr )
+ #define SET_BE32( addr, data ) set_be32( addr, data )
+#endif
+
+// auto-selecting versions
+
+inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
+inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
+inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
+inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
+inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
+inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
+inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
+inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
+
+BLARGG_NAMESPACE_END
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_errors.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_errors.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_errors.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_errors.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,117 +1,117 @@
-// $package. http://www.slack.net/~ant/
-
-#include "blargg_errors.h"
-
-/* Copyright (C) 2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-BLARGG_NAMESPACE_BEGIN
-
-blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
-// blargg_err_memory is defined in blargg_common.cpp
-blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
-blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
-blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
-
-blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
-blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
-blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
-blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
-blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
-blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
-
-blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
-blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
-blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
-
-const char* blargg_err_str( blargg_err_t err )
-{
- if ( !err )
- return "";
-
- if ( *err == BLARGG_ERR_TYPE("")[0] )
- return err + 1;
-
- return err;
-}
-
-bool blargg_is_err_type( blargg_err_t err, const char type [] )
-{
- if ( err )
- {
- // True if first strlen(type) characters of err match type
- char const* p = err;
- while ( *type && *type == *p )
- {
- type++;
- p++;
- }
-
- if ( !*type )
- return true;
- }
-
- return false;
-}
-
-const char* blargg_err_details( blargg_err_t err )
-{
- const char* p = err;
- if ( !p )
- {
- p = "";
- }
- else if ( *p == BLARGG_ERR_TYPE("")[0] )
- {
- while ( *p && *p != ';' )
- p++;
-
- // Skip ; and space after it
- if ( *p )
- {
- p++;
-
- check( *p == ' ' );
- if ( *p )
- p++;
- }
- }
- return p;
-}
-
-int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
-{
- if ( !err )
- return 0;
-
- while ( codes->str && !blargg_is_err_type( err, codes->str ) )
- codes++;
-
- return codes->code;
-}
-
-blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
-{
- if ( !code )
- return blargg_ok;
-
- while ( codes->str && codes->code != code )
- codes++;
-
- if ( !codes->str )
- return blargg_err_generic;
-
- return codes->str;
-}
-
-BLARGG_NAMESPACE_END
+// $package. http://www.slack.net/~ant/
+
+#include "blargg_errors.h"
+
+/* Copyright (C) 2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+BLARGG_NAMESPACE_BEGIN
+
+blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
+// blargg_err_memory is defined in blargg_common.cpp
+blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
+blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
+blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
+
+blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
+blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
+blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
+blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
+blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
+blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
+
+blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
+blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
+blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
+
+const char* blargg_err_str( blargg_err_t err )
+{
+ if ( !err )
+ return "";
+
+ if ( *err == BLARGG_ERR_TYPE("")[0] )
+ return err + 1;
+
+ return err;
+}
+
+bool blargg_is_err_type( blargg_err_t err, const char type [] )
+{
+ if ( err )
+ {
+ // True if first strlen(type) characters of err match type
+ char const* p = err;
+ while ( *type && *type == *p )
+ {
+ type++;
+ p++;
+ }
+
+ if ( !*type )
+ return true;
+ }
+
+ return false;
+}
+
+const char* blargg_err_details( blargg_err_t err )
+{
+ const char* p = err;
+ if ( !p )
+ {
+ p = "";
+ }
+ else if ( *p == BLARGG_ERR_TYPE("")[0] )
+ {
+ while ( *p && *p != ';' )
+ p++;
+
+ // Skip ; and space after it
+ if ( *p )
+ {
+ p++;
+
+ check( *p == ' ' );
+ if ( *p )
+ p++;
+ }
+ }
+ return p;
+}
+
+int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
+{
+ if ( !err )
+ return 0;
+
+ while ( codes->str && !blargg_is_err_type( err, codes->str ) )
+ codes++;
+
+ return codes->code;
+}
+
+blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
+{
+ if ( !code )
+ return blargg_ok;
+
+ while ( codes->str && codes->code != code )
+ codes++;
+
+ if ( !codes->str )
+ return blargg_err_generic;
+
+ return codes->str;
+}
+
+BLARGG_NAMESPACE_END
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_errors.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_errors.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_errors.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_errors.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,84 +1,84 @@
-// Error strings and conversion functions
-
-// $package
-#ifndef BLARGG_ERRORS_H
-#define BLARGG_ERRORS_H
-
-#ifndef BLARGG_COMMON_H
- #include "blargg_common.h"
-#endif
-
-BLARGG_NAMESPACE_BEGIN
-
-typedef const char blargg_err_def_t [];
-
-// Basic errors
-extern blargg_err_def_t blargg_err_generic;
-extern blargg_err_def_t blargg_err_memory;
-extern blargg_err_def_t blargg_err_caller;
-extern blargg_err_def_t blargg_err_internal;
-extern blargg_err_def_t blargg_err_limitation;
-
-// File low-level
-extern blargg_err_def_t blargg_err_file_missing; // not found
-extern blargg_err_def_t blargg_err_file_read;
-extern blargg_err_def_t blargg_err_file_write;
-extern blargg_err_def_t blargg_err_file_io;
-extern blargg_err_def_t blargg_err_file_full;
-extern blargg_err_def_t blargg_err_file_eof;
-
-// File high-level
-extern blargg_err_def_t blargg_err_file_type; // wrong file type
-extern blargg_err_def_t blargg_err_file_feature;
-extern blargg_err_def_t blargg_err_file_corrupt;
-
-// C string describing error, or "" if err == NULL
-const char* blargg_err_str( blargg_err_t err );
-
-// True iff error is of given type, or false if err == NULL
-bool blargg_is_err_type( blargg_err_t, const char type [] );
-
-// Details of error without describing main cause, or "" if err == NULL
-const char* blargg_err_details( blargg_err_t err );
-
-// Converts error string to integer code using mapping table. Calls blargg_is_err_type()
-// for each str and returns code on first match. Returns 0 if err == NULL.
-struct blargg_err_to_code_t {
- const char* str;
- int code;
-};
-int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
-
-// Converts error code back to string. If code == 0, returns NULL. If not in table,
-// returns blargg_err_generic.
-blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
-
-// Generates error string literal with details of cause
-#define BLARGG_ERR( type, str ) (type "; " str)
-
-// Extra space to make it clear when blargg_err_str() isn't called to get
-// printable version of error. At some point, I might prefix error strings
-// with a code, to speed conversion to a code.
-#define BLARGG_ERR_TYPE( str ) " " str
-
-// Error types to pass to BLARGG_ERR macro
-#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
-#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
-#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
-#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
-#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
-
-#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
-#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
-#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
-#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
-#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
-#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
-
-#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
-#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
-#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
-
-BLARGG_NAMESPACE_END
-
-#endif
+// Error strings and conversion functions
+
+// $package
+#ifndef BLARGG_ERRORS_H
+#define BLARGG_ERRORS_H
+
+#ifndef BLARGG_COMMON_H
+ #include "blargg_common.h"
+#endif
+
+BLARGG_NAMESPACE_BEGIN
+
+typedef const char blargg_err_def_t [];
+
+// Basic errors
+extern blargg_err_def_t blargg_err_generic;
+extern blargg_err_def_t blargg_err_memory;
+extern blargg_err_def_t blargg_err_caller;
+extern blargg_err_def_t blargg_err_internal;
+extern blargg_err_def_t blargg_err_limitation;
+
+// File low-level
+extern blargg_err_def_t blargg_err_file_missing; // not found
+extern blargg_err_def_t blargg_err_file_read;
+extern blargg_err_def_t blargg_err_file_write;
+extern blargg_err_def_t blargg_err_file_io;
+extern blargg_err_def_t blargg_err_file_full;
+extern blargg_err_def_t blargg_err_file_eof;
+
+// File high-level
+extern blargg_err_def_t blargg_err_file_type; // wrong file type
+extern blargg_err_def_t blargg_err_file_feature;
+extern blargg_err_def_t blargg_err_file_corrupt;
+
+// C string describing error, or "" if err == NULL
+const char* blargg_err_str( blargg_err_t err );
+
+// True iff error is of given type, or false if err == NULL
+bool blargg_is_err_type( blargg_err_t, const char type [] );
+
+// Details of error without describing main cause, or "" if err == NULL
+const char* blargg_err_details( blargg_err_t err );
+
+// Converts error string to integer code using mapping table. Calls blargg_is_err_type()
+// for each str and returns code on first match. Returns 0 if err == NULL.
+struct blargg_err_to_code_t {
+ const char* str;
+ int code;
+};
+int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
+
+// Converts error code back to string. If code == 0, returns NULL. If not in table,
+// returns blargg_err_generic.
+blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
+
+// Generates error string literal with details of cause
+#define BLARGG_ERR( type, str ) (type "; " str)
+
+// Extra space to make it clear when blargg_err_str() isn't called to get
+// printable version of error. At some point, I might prefix error strings
+// with a code, to speed conversion to a code.
+#define BLARGG_ERR_TYPE( str ) " " str
+
+// Error types to pass to BLARGG_ERR macro
+#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
+#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
+#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
+#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
+#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
+
+#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
+#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
+#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
+#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
+#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
+#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
+
+#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
+#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
+#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
+
+BLARGG_NAMESPACE_END
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_source.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_source.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/blargg_source.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/blargg_source.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,175 +1,175 @@
-/* Included at the beginning of library source files, AFTER all other #include
-lines. Sets up helpful macros and services used in my source code. Since this
-is only "active" in my source code, I don't have to worry about polluting the
-global namespace with unprefixed names. */
-
-// $package
-#ifndef BLARGG_SOURCE_H
-#define BLARGG_SOURCE_H
-
-#ifndef BLARGG_COMMON_H // optimization only
- #include "blargg_common.h"
-#endif
-#include "blargg_errors.h"
-#include "gme_custom_dprintf.h"
-
-#include /* memcpy(), memset(), memmove() */
-#include /* offsetof() */
-
-/* The following four macros are for debugging only. Some or all might be
-defined to do nothing, depending on the circumstances. Described is what
-happens when a particular macro is defined to do something. When defined to
-do nothing, the macros do NOT evaluate their argument(s). */
-
-/* If expr is false, prints file and line number, then aborts program. Meant
-for checking internal state and consistency. A failed assertion indicates a bug
-in MY code.
-
-void assert( bool expr ); */
-#include
-
-/* If expr is false, prints file and line number, then aborts program. Meant
-for checking caller-supplied parameters and operations that are outside the
-control of the module. A failed requirement probably indicates a bug in YOUR
-code.
-
-void require( bool expr ); */
-#undef require
-#define require( expr ) assert( expr )
-
-/* Like printf() except output goes to debugging console/file.
-
-void dprintf( const char format [], ... ); */
-
-#ifdef CUSTOM_DPRINTF_FUNCTION
-
-static inline void dprintf( const char * fmt, ... )
-{
- if (gme_custom_dprintf)
- {
- va_list vl;
- va_start(vl, fmt);
- gme_custom_dprintf(fmt, vl);
- va_end(vl);
- }
-}
-
-#else
-
-#ifdef NDEBUG
-static inline void blargg_dprintf_( const char [], ... ) { }
-#undef dprintf
-#define dprintf (1) ? (void) 0 : blargg_dprintf_
-#else
-#include
-#include
-#undef dprintf
-#define dprintf (1) ? (void) 0 : blargg_dprintf_
-#ifndef _WIN32
-#include
-static inline void blargg_dprintf_( const char * fmt, ... )
-{
- char error[512];
- va_list vl;
- va_start(vl, fmt);
- vsnprintf( error, 511, fmt, vl );
- va_end(vl);
- fputs( error, stderr );
-}
-#else
-#include
-static inline void blargg_dprintf_( const char * fmt, ... )
-{
- char error[512];
- va_list vl;
- va_start(vl, fmt);
- vsnprintf_s( error, 511, 511, fmt, vl );
- va_end(vl);
- OutputDebugStringA( error );
-}
-#endif
-#endif
-
-#endif
-
-/* If expr is false, prints file and line number to debug console/log, then
-continues execution normally. Meant for flagging potential problems or things
-that should be looked into, but that aren't serious problems.
-
-void check( bool expr ); */
-#undef check
-#define check( expr ) ((void) 0)
-
-/* If expr yields non-NULL error string, returns it from current function,
-otherwise continues normally. */
-#undef RETURN_ERR
-#define RETURN_ERR( expr ) \
- do {\
- blargg_err_t blargg_return_err_ = (expr);\
- if ( blargg_return_err_ )\
- return blargg_return_err_;\
- } while ( 0 )
-
-/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
-#undef CHECK_ALLOC
-#define CHECK_ALLOC( ptr ) \
- do {\
- if ( !(ptr) )\
- return blargg_err_memory;\
- } while ( 0 )
-
-/* The usual min/max functions for built-in types.
-
-template T min( T x, T y ) { return x < y ? x : y; }
-template T max( T x, T y ) { return x > y ? x : y; } */
-#define BLARGG_DEF_MIN_MAX( type ) \
- static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
- static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
-
-BLARGG_DEF_MIN_MAX( int )
-BLARGG_DEF_MIN_MAX( unsigned )
-BLARGG_DEF_MIN_MAX( long )
-BLARGG_DEF_MIN_MAX( unsigned long )
-BLARGG_DEF_MIN_MAX( unsigned long long )
-BLARGG_DEF_MIN_MAX( float )
-BLARGG_DEF_MIN_MAX( double )
-
-#undef min
-#define min blargg_min
-
-#undef max
-#define max blargg_max
-
-// typedef unsigned char byte;
-typedef unsigned char blargg_byte;
-#undef byte
-#define byte blargg_byte
-
-#ifndef BLARGG_EXPORT
- #if defined (_WIN32) && BLARGG_BUILD_DLL
- #define BLARGG_EXPORT __declspec(dllexport)
- #elif defined (__GNUC__)
- // can always set visibility, even when not building DLL
- #define BLARGG_EXPORT __attribute__ ((visibility ("default")))
- #else
- #define BLARGG_EXPORT
- #endif
-#endif
-
-#if BLARGG_LEGACY
- #define BLARGG_CHECK_ALLOC CHECK_ALLOC
- #define BLARGG_RETURN_ERR RETURN_ERR
-#endif
-
-// Called after failed operation when overall operation may still complete OK.
-// Only used by unit testing framework.
-#undef ACK_FAILURE
-#define ACK_FAILURE() ((void)0)
-
-/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc.
-and check */
-#ifdef BLARGG_SOURCE_BEGIN
- #include BLARGG_SOURCE_BEGIN
-#endif
-
-#endif
+/* Included at the beginning of library source files, AFTER all other #include
+lines. Sets up helpful macros and services used in my source code. Since this
+is only "active" in my source code, I don't have to worry about polluting the
+global namespace with unprefixed names. */
+
+// $package
+#ifndef BLARGG_SOURCE_H
+#define BLARGG_SOURCE_H
+
+#ifndef BLARGG_COMMON_H // optimization only
+ #include "blargg_common.h"
+#endif
+#include "blargg_errors.h"
+#include "gme_custom_dprintf.h"
+
+#include /* memcpy(), memset(), memmove() */
+#include /* offsetof() */
+
+/* The following four macros are for debugging only. Some or all might be
+defined to do nothing, depending on the circumstances. Described is what
+happens when a particular macro is defined to do something. When defined to
+do nothing, the macros do NOT evaluate their argument(s). */
+
+/* If expr is false, prints file and line number, then aborts program. Meant
+for checking internal state and consistency. A failed assertion indicates a bug
+in MY code.
+
+void assert( bool expr ); */
+#include
+
+/* If expr is false, prints file and line number, then aborts program. Meant
+for checking caller-supplied parameters and operations that are outside the
+control of the module. A failed requirement probably indicates a bug in YOUR
+code.
+
+void require( bool expr ); */
+#undef require
+#define require( expr ) assert( expr )
+
+/* Like printf() except output goes to debugging console/file.
+
+void dprintf( const char format [], ... ); */
+
+#ifdef CUSTOM_DPRINTF_FUNCTION
+
+static inline void dprintf( const char * fmt, ... )
+{
+ if (gme_custom_dprintf)
+ {
+ va_list vl;
+ va_start(vl, fmt);
+ gme_custom_dprintf(fmt, vl);
+ va_end(vl);
+ }
+}
+
+#else
+
+#ifdef NDEBUG
+static inline void blargg_dprintf_( const char [], ... ) { }
+#undef dprintf
+#define dprintf (1) ? (void) 0 : blargg_dprintf_
+#else
+#include
+#include
+#undef dprintf
+#define dprintf (1) ? (void) 0 : blargg_dprintf_
+#ifndef _WIN32
+#include
+static inline void blargg_dprintf_( const char * fmt, ... )
+{
+ char error[512];
+ va_list vl;
+ va_start(vl, fmt);
+ vsnprintf( error, 511, fmt, vl );
+ va_end(vl);
+ fputs( error, stderr );
+}
+#else
+#include
+static inline void blargg_dprintf_( const char * fmt, ... )
+{
+ char error[512];
+ va_list vl;
+ va_start(vl, fmt);
+ vsnprintf_s( error, 511, 511, fmt, vl );
+ va_end(vl);
+ OutputDebugStringA( error );
+}
+#endif
+#endif
+
+#endif
+
+/* If expr is false, prints file and line number to debug console/log, then
+continues execution normally. Meant for flagging potential problems or things
+that should be looked into, but that aren't serious problems.
+
+void check( bool expr ); */
+#undef check
+#define check( expr ) ((void) 0)
+
+/* If expr yields non-NULL error string, returns it from current function,
+otherwise continues normally. */
+#undef RETURN_ERR
+#define RETURN_ERR( expr ) \
+ do {\
+ blargg_err_t blargg_return_err_ = (expr);\
+ if ( blargg_return_err_ )\
+ return blargg_return_err_;\
+ } while ( 0 )
+
+/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
+#undef CHECK_ALLOC
+#define CHECK_ALLOC( ptr ) \
+ do {\
+ if ( !(ptr) )\
+ return blargg_err_memory;\
+ } while ( 0 )
+
+/* The usual min/max functions for built-in types.
+
+template T min( T x, T y ) { return x < y ? x : y; }
+template T max( T x, T y ) { return x > y ? x : y; } */
+#define BLARGG_DEF_MIN_MAX( type ) \
+ static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
+ static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
+
+BLARGG_DEF_MIN_MAX( int )
+BLARGG_DEF_MIN_MAX( unsigned )
+BLARGG_DEF_MIN_MAX( long )
+BLARGG_DEF_MIN_MAX( unsigned long )
+BLARGG_DEF_MIN_MAX( unsigned long long )
+BLARGG_DEF_MIN_MAX( float )
+BLARGG_DEF_MIN_MAX( double )
+
+#undef min
+#define min blargg_min
+
+#undef max
+#define max blargg_max
+
+// typedef unsigned char byte;
+typedef unsigned char blargg_byte;
+#undef byte
+#define byte blargg_byte
+
+#ifndef BLARGG_EXPORT
+ #if defined (_WIN32) && BLARGG_BUILD_DLL
+ #define BLARGG_EXPORT __declspec(dllexport)
+ #elif defined (__GNUC__)
+ // can always set visibility, even when not building DLL
+ #define BLARGG_EXPORT __attribute__ ((visibility ("default")))
+ #else
+ #define BLARGG_EXPORT
+ #endif
+#endif
+
+#if BLARGG_LEGACY
+ #define BLARGG_CHECK_ALLOC CHECK_ALLOC
+ #define BLARGG_RETURN_ERR RETURN_ERR
+#endif
+
+// Called after failed operation when overall operation may still complete OK.
+// Only used by unit testing framework.
+#undef ACK_FAILURE
+#define ACK_FAILURE() ((void)0)
+
+/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc.
+and check */
+#ifdef BLARGG_SOURCE_BEGIN
+ #include BLARGG_SOURCE_BEGIN
+#endif
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,509 +1,509 @@
-// Blip_Buffer $vers. http://www.slack.net/~ant/
-
-#include "Blip_Buffer.h"
-
-#include
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-//// Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
- factor_ = UINT_MAX/2 + 1;
- buffer_ = NULL;
- buffer_center_ = NULL;
- buffer_size_ = 0;
- sample_rate_ = 0;
- bass_shift_ = 0;
- clock_rate_ = 0;
- bass_freq_ = 16;
- length_ = 0;
-
- // assumptions code makes about implementation-defined features
- #ifndef NDEBUG
- // right shift of negative value preserves sign
- int i = -0x7FFFFFFE;
- assert( (i >> 1) == -0x3FFFFFFF );
-
- // casting truncates and sign-extends
- i = 0x18000;
- assert( (BOOST::int16_t) i == -0x8000 );
- #endif
-
- clear();
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
- free( buffer_ );
-}
-
-void Blip_Buffer::clear()
-{
- bool const entire_buffer = true;
-
- offset_ = 0;
- reader_accum_ = 0;
- modified_ = false;
-
- if ( buffer_ )
- {
- int count = (entire_buffer ? buffer_size_ : samples_avail());
- memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (delta_t) );
- }
-}
-
-blargg_err_t Blip_Buffer::set_sample_rate( int new_rate, int msec )
-{
- // Limit to maximum size that resampled time can represent
- int max_size = (((blip_resampled_time_t) -1) >> BLIP_BUFFER_ACCURACY) -
- blip_buffer_extra_ - 64; // TODO: -64 isn't needed
- int new_size = (new_rate * (msec + 1) + 999) / 1000;
- if ( new_size > max_size )
- new_size = max_size;
-
- // Resize buffer
- if ( buffer_size_ != new_size )
- {
- //dprintf( "%d \n", (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- CHECK_ALLOC( p );
- buffer_ = (delta_t*) p;
- buffer_center_ = buffer_ + BLIP_MAX_QUALITY/2;
- buffer_size_ = new_size;
- }
-
- // Update sample_rate and things that depend on it
- sample_rate_ = new_rate;
- length_ = new_size * 1000 / new_rate - 1;
- if ( clock_rate_ )
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
-
- clear();
-
- return blargg_ok;
-}
-
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( int rate ) const
-{
- double ratio = (double) sample_rate_ / rate;
- int factor = (int) floor( ratio * (1 << BLIP_BUFFER_ACCURACY) + 0.5 );
- assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
- return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- int shift = 31;
- if ( freq > 0 && sample_rate_ )
- {
- shift = 13;
- int f = (freq << 16) / sample_rate_;
- while ( (f >>= 1) != 0 && --shift ) { }
- }
- bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
- offset_ += t * factor_;
- assert( samples_avail() <= (int) buffer_size_ ); // fails if time is past end of buffer
-}
-
-int Blip_Buffer::count_samples( blip_time_t t ) const
-{
- blip_resampled_time_t last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
- blip_resampled_time_t first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
- return (int) (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( int count ) const
-{
- if ( count > buffer_size_ )
- count = buffer_size_;
- blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
- return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( int count )
-{
- if ( count )
- {
- remove_silence( count );
-
- // copy remaining samples to beginning and clear old samples
- int remain = samples_avail() + blip_buffer_extra_;
- memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
- memset( buffer_ + remain, 0, count * sizeof *buffer_ );
- }
-}
-
-int Blip_Buffer::read_samples( blip_sample_t out_ [], int max_samples, bool stereo )
-{
- int count = samples_avail();
- if ( count > max_samples )
- count = max_samples;
-
- if ( count )
- {
- int const bass = highpass_shift();
- delta_t const* reader = read_pos() + count;
- int reader_sum = integrator();
-
- blip_sample_t* BLARGG_RESTRICT out = out_ + count;
- if ( stereo )
- out += count;
- int offset = -count;
-
- if ( !stereo )
- {
- do
- {
- int s = reader_sum >> delta_bits;
-
- reader_sum -= reader_sum >> bass;
- reader_sum += reader [offset];
-
- BLIP_CLAMP( s, s );
- out [offset] = (blip_sample_t) s;
- }
- while ( ++offset );
- }
- else
- {
- do
- {
- int s = reader_sum >> delta_bits;
-
- reader_sum -= reader_sum >> bass;
- reader_sum += reader [offset];
-
- BLIP_CLAMP( s, s );
- out [offset * 2] = (blip_sample_t) s;
- }
- while ( ++offset );
- }
-
- set_integrator( reader_sum );
-
- remove_samples( count );
- }
- return count;
-}
-
-void Blip_Buffer::mix_samples( blip_sample_t const in [], int count )
-{
- delta_t* out = buffer_center_ + (offset_ >> BLIP_BUFFER_ACCURACY);
-
- int const sample_shift = blip_sample_bits - 16;
- int prev = 0;
- while ( --count >= 0 )
- {
- int s = *in++ << sample_shift;
- *out += s - prev;
- prev = s;
- ++out;
- }
- *out -= prev;
-}
-
-void Blip_Buffer::save_state( blip_buffer_state_t* out )
-{
- assert( samples_avail() == 0 );
- out->offset_ = offset_;
- out->reader_accum_ = reader_accum_;
- memcpy( out->buf, &buffer_ [offset_ >> BLIP_BUFFER_ACCURACY], sizeof out->buf );
-}
-
-void Blip_Buffer::load_state( blip_buffer_state_t const& in )
-{
- clear();
-
- offset_ = in.offset_;
- reader_accum_ = in.reader_accum_;
- memcpy( buffer_, in.buf, sizeof in.buf );
-}
-
-
-//// Blip_Synth_
-
-Blip_Synth_Fast_::Blip_Synth_Fast_()
-{
- buf = NULL;
- last_amp = 0;
- delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
- delta_factor = int (new_unit * (1 << blip_sample_bits) + 0.5);
-}
-
-#if BLIP_BUFFER_FAST
-
-void blip_eq_t::generate( float* out, int count ) const { }
-
-#else
-
-Blip_Synth_::Blip_Synth_( short p [], int w ) :
- phases( p ),
- width( w )
-{
- volume_unit_ = 0.0;
- kernel_unit = 0;
- buf = NULL;
- last_amp = 0;
- delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-// Generates right half of sinc kernel (including center point) with cutoff at
-// sample rate / 2 / oversample. Frequency response at cutoff frequency is
-// treble dB (-6=0.5,-12=0.25). Mid controls frequency that rolloff begins at,
-// cut * sample rate / 2.
-static void gen_sinc( float out [], int out_size, double oversample,
- double treble, double mid )
-{
- if ( mid > 0.9999 ) mid = 0.9999;
- if ( treble < -300.0 ) treble = -300.0;
- if ( treble > 5.0 ) treble = 5.0;
-
- double const maxh = 4096.0;
- double rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - mid) );
- double const pow_a_n = pow( rolloff, maxh - maxh * mid );
- double const to_angle = PI / maxh / oversample;
- for ( int i = 1; i < out_size; i++ )
- {
- double angle = i * to_angle;
- double c = rolloff * cos( angle * maxh - angle ) -
- cos( angle * maxh );
- double cos_nc_angle = cos( angle * maxh * mid );
- double cos_nc1_angle = cos( angle * maxh * mid - angle );
- double cos_angle = cos( angle );
-
- c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
- double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
- double b = 2.0 - cos_angle - cos_angle;
- double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
-
- out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
- }
-
- // Approximate center by looking at two points to right. Much simpler
- // and more reliable than trying to calculate it properly.
- out [0] = out [1] + 0.5 * (out [1] - out [2]);
-}
-
-// Gain is 1-2800 for beta of 0-10, instead of 1.0 as it should be, but
-// this is corrected by normalization in treble_eq().
-static void kaiser_window( float io [], int count, float beta )
-{
- int const accuracy = 10;
-
- float const beta2 = beta * beta;
- float const step = (float) 0.5 / count;
- float pos = (float) 0.5;
- for ( float* const end = io + count; io < end; ++io )
- {
- float x = (pos - pos*pos) * beta2;
- float u = x;
- float k = 1;
- float n = 2;
-
- // Keep refining until adjustment becomes small
- do
- {
- u *= x / (n * n);
- n += 1;
- k += u;
- }
- while ( k <= u * (1 << accuracy) );
-
- pos += step;
- *io *= k;
- }
-}
-
-void blip_eq_t::generate( float out [], int count ) const
-{
- // lower cutoff freq for narrow kernels with their wider transition band
- // (8 points->1.49, 16 points->1.15)
- double cutoff_adj = blip_res * 2.25 / count + 0.85;
- if ( cutoff_adj < 1.02 )
- cutoff_adj = 1.02;
- double half_rate = sample_rate * 0.5;
- if ( cutoff_freq )
- cutoff_adj = half_rate / cutoff_freq;
- double cutoff = rolloff_freq * cutoff_adj / half_rate;
-
- gen_sinc( out, count, oversample * cutoff_adj, treble, cutoff );
-
- kaiser_window( out, count, kaiser );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
- // Generate right half of kernel
- int const half_size = blip_eq_t::calc_count( width );
- float fimpulse [blip_res / 2 * (BLIP_MAX_QUALITY - 1) + 1];
- eq.generate( fimpulse, half_size );
-
- int i;
-
- // Find rescale factor. Summing from small to large (right to left)
- // reduces error.
- double total = 0.0;
- for ( i = half_size; --i > 0; )
- total += fimpulse [i];
- total = total * 2.0 + fimpulse [0];
-
- //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
- //double const base_unit = 37888.0; // allows treble to +5 dB
- double const base_unit = 32768.0; // necessary for blip_unscaled to work
- double rescale = base_unit / total;
- kernel_unit = (int) base_unit;
-
- // Integrate, first difference, rescale, convert to int
- double sum = 0;
- double next = 0;
- int const size = impulses_size();
- for ( i = 0; i < size; i++ )
- {
- int j = (half_size - 1) - i;
-
- if ( i >= blip_res )
- sum += fimpulse [j + blip_res];
-
- // goes slightly past center, so it needs a little mirroring
- next += fimpulse [j < 0 ? -j : j];
-
- // calculate unintereleved index
- int x = (~i & (blip_res - 1)) * (width >> 1) + (i >> BLIP_PHASE_BITS);
- assert( (unsigned) x < (unsigned) size );
-
- // flooring separately virtually eliminates error
- phases [x] = (short) (int)
- (floor( sum * rescale + 0.5 ) - floor( next * rescale + 0.5 ));
- //phases [x] = (short) (int)
- // floor( sum * rescale - next * rescale + 0.5 );
- }
-
- adjust_impulse();
-
- // volume might require rescaling
- double vol = volume_unit_;
- if ( vol )
- {
- volume_unit_ = 0.0;
- volume_unit( vol );
- }
-}
-
-void Blip_Synth_::adjust_impulse()
-{
- int const size = impulses_size();
- int const half_width = width / 2;
-
- // Sum each phase as would be done when synthesizing, and correct
- // any that don't add up to exactly kernel_half.
- for ( int phase = blip_res / 2; --phase >= 0; )
- {
- int const fwd = phase * half_width;
- int const rev = size - half_width - fwd;
-
- int error = kernel_unit;
- for ( int i = half_width; --i >= 0; )
- {
- error += phases [fwd + i];
- error += phases [rev + i];
- }
- phases [fwd + half_width - 1] -= (short) error;
-
- // Error shouldn't occur now with improved calculation
- //if ( error ) printf( "error: %ld\n", error );
- }
-
- #if 0
- for ( int i = 0; i < blip_res; i++, printf( "\n" ) )
- for ( int j = 0; j < width / 2; j++ )
- printf( "%5d,", (int) -phases [j + width/2 * i] );
- #endif
-}
-
-void Blip_Synth_::rescale_kernel( int shift )
-{
- // Keep values positive to avoid round-towards-zero of sign-preserving
- // right shift for negative values.
- int const keep_positive = 0x8000 + (1 << (shift - 1));
-
- int const half_width = width / 2;
- for ( int phase = blip_res; --phase >= 0; )
- {
- int const fwd = phase * half_width;
-
- // Integrate, rescale, then differentiate again.
- // If differences are rescaled directly, more error results.
- int sum = keep_positive;
- for ( int i = 0; i < half_width; i++ )
- {
- int prev = sum;
- sum += phases [fwd + i];
- phases [fwd + i] = (sum >> shift) - (prev >> shift);
- }
- }
-
- adjust_impulse();
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
- if ( volume_unit_ != new_unit )
- {
- // use default eq if it hasn't been set yet
- if ( !kernel_unit )
- treble_eq( -8.0 );
-
- // Factor that kernel must be multiplied by
- volume_unit_ = new_unit;
- double factor = new_unit * (1 << blip_sample_bits) / kernel_unit;
-
- if ( factor > 0.0 )
- {
- // If factor is low, reduce amplitude of kernel itself
- int shift = 0;
- while ( factor < 2.0 )
- {
- shift++;
- factor *= 2.0;
- }
-
- if ( shift )
- {
- kernel_unit >>= shift;
- assert( kernel_unit > 0 ); // fails if volume unit is too low
-
- rescale_kernel( shift );
- }
- }
-
- delta_factor = -(int) floor( factor + 0.5 );
- //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
- }
-}
-#endif
+// Blip_Buffer $vers. http://www.slack.net/~ant/
+
+#include "Blip_Buffer.h"
+
+#include
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+//// Blip_Buffer
+
+Blip_Buffer::Blip_Buffer()
+{
+ factor_ = UINT_MAX/2 + 1;
+ buffer_ = NULL;
+ buffer_center_ = NULL;
+ buffer_size_ = 0;
+ sample_rate_ = 0;
+ bass_shift_ = 0;
+ clock_rate_ = 0;
+ bass_freq_ = 16;
+ length_ = 0;
+
+ // assumptions code makes about implementation-defined features
+ #ifndef NDEBUG
+ // right shift of negative value preserves sign
+ int i = -0x7FFFFFFE;
+ assert( (i >> 1) == -0x3FFFFFFF );
+
+ // casting truncates and sign-extends
+ i = 0x18000;
+ assert( (BOOST::int16_t) i == -0x8000 );
+ #endif
+
+ clear();
+}
+
+Blip_Buffer::~Blip_Buffer()
+{
+ free( buffer_ );
+}
+
+void Blip_Buffer::clear()
+{
+ bool const entire_buffer = true;
+
+ offset_ = 0;
+ reader_accum_ = 0;
+ modified_ = false;
+
+ if ( buffer_ )
+ {
+ int count = (entire_buffer ? buffer_size_ : samples_avail());
+ memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (delta_t) );
+ }
+}
+
+blargg_err_t Blip_Buffer::set_sample_rate( int new_rate, int msec )
+{
+ // Limit to maximum size that resampled time can represent
+ int max_size = (((blip_resampled_time_t) -1) >> BLIP_BUFFER_ACCURACY) -
+ blip_buffer_extra_ - 64; // TODO: -64 isn't needed
+ int new_size = (new_rate * (msec + 1) + 999) / 1000;
+ if ( new_size > max_size )
+ new_size = max_size;
+
+ // Resize buffer
+ if ( buffer_size_ != new_size )
+ {
+ //dprintf( "%d \n", (new_size + blip_buffer_extra_) * sizeof *buffer_ );
+ void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
+ CHECK_ALLOC( p );
+ buffer_ = (delta_t*) p;
+ buffer_center_ = buffer_ + BLIP_MAX_QUALITY/2;
+ buffer_size_ = new_size;
+ }
+
+ // Update sample_rate and things that depend on it
+ sample_rate_ = new_rate;
+ length_ = new_size * 1000 / new_rate - 1;
+ if ( clock_rate_ )
+ clock_rate( clock_rate_ );
+ bass_freq( bass_freq_ );
+
+ clear();
+
+ return blargg_ok;
+}
+
+blip_resampled_time_t Blip_Buffer::clock_rate_factor( int rate ) const
+{
+ double ratio = (double) sample_rate_ / rate;
+ int factor = (int) floor( ratio * (1 << BLIP_BUFFER_ACCURACY) + 0.5 );
+ assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
+ return (blip_resampled_time_t) factor;
+}
+
+void Blip_Buffer::bass_freq( int freq )
+{
+ bass_freq_ = freq;
+ int shift = 31;
+ if ( freq > 0 && sample_rate_ )
+ {
+ shift = 13;
+ int f = (freq << 16) / sample_rate_;
+ while ( (f >>= 1) != 0 && --shift ) { }
+ }
+ bass_shift_ = shift;
+}
+
+void Blip_Buffer::end_frame( blip_time_t t )
+{
+ offset_ += t * factor_;
+ assert( samples_avail() <= (int) buffer_size_ ); // fails if time is past end of buffer
+}
+
+int Blip_Buffer::count_samples( blip_time_t t ) const
+{
+ blip_resampled_time_t last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
+ blip_resampled_time_t first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
+ return (int) (last_sample - first_sample);
+}
+
+blip_time_t Blip_Buffer::count_clocks( int count ) const
+{
+ if ( count > buffer_size_ )
+ count = buffer_size_;
+ blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+ return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
+}
+
+void Blip_Buffer::remove_samples( int count )
+{
+ if ( count )
+ {
+ remove_silence( count );
+
+ // copy remaining samples to beginning and clear old samples
+ int remain = samples_avail() + blip_buffer_extra_;
+ memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
+ memset( buffer_ + remain, 0, count * sizeof *buffer_ );
+ }
+}
+
+int Blip_Buffer::read_samples( blip_sample_t out_ [], int max_samples, bool stereo )
+{
+ int count = samples_avail();
+ if ( count > max_samples )
+ count = max_samples;
+
+ if ( count )
+ {
+ int const bass = highpass_shift();
+ delta_t const* reader = read_pos() + count;
+ int reader_sum = integrator();
+
+ blip_sample_t* BLARGG_RESTRICT out = out_ + count;
+ if ( stereo )
+ out += count;
+ int offset = -count;
+
+ if ( !stereo )
+ {
+ do
+ {
+ int s = reader_sum >> delta_bits;
+
+ reader_sum -= reader_sum >> bass;
+ reader_sum += reader [offset];
+
+ BLIP_CLAMP( s, s );
+ out [offset] = (blip_sample_t) s;
+ }
+ while ( ++offset );
+ }
+ else
+ {
+ do
+ {
+ int s = reader_sum >> delta_bits;
+
+ reader_sum -= reader_sum >> bass;
+ reader_sum += reader [offset];
+
+ BLIP_CLAMP( s, s );
+ out [offset * 2] = (blip_sample_t) s;
+ }
+ while ( ++offset );
+ }
+
+ set_integrator( reader_sum );
+
+ remove_samples( count );
+ }
+ return count;
+}
+
+void Blip_Buffer::mix_samples( blip_sample_t const in [], int count )
+{
+ delta_t* out = buffer_center_ + (offset_ >> BLIP_BUFFER_ACCURACY);
+
+ int const sample_shift = blip_sample_bits - 16;
+ int prev = 0;
+ while ( --count >= 0 )
+ {
+ int s = *in++ << sample_shift;
+ *out += s - prev;
+ prev = s;
+ ++out;
+ }
+ *out -= prev;
+}
+
+void Blip_Buffer::save_state( blip_buffer_state_t* out )
+{
+ assert( samples_avail() == 0 );
+ out->offset_ = offset_;
+ out->reader_accum_ = reader_accum_;
+ memcpy( out->buf, &buffer_ [offset_ >> BLIP_BUFFER_ACCURACY], sizeof out->buf );
+}
+
+void Blip_Buffer::load_state( blip_buffer_state_t const& in )
+{
+ clear();
+
+ offset_ = in.offset_;
+ reader_accum_ = in.reader_accum_;
+ memcpy( buffer_, in.buf, sizeof in.buf );
+}
+
+
+//// Blip_Synth_
+
+Blip_Synth_Fast_::Blip_Synth_Fast_()
+{
+ buf = NULL;
+ last_amp = 0;
+ delta_factor = 0;
+}
+
+void Blip_Synth_Fast_::volume_unit( double new_unit )
+{
+ delta_factor = int (new_unit * (1 << blip_sample_bits) + 0.5);
+}
+
+#if BLIP_BUFFER_FAST
+
+void blip_eq_t::generate( float* out, int count ) const { }
+
+#else
+
+Blip_Synth_::Blip_Synth_( short p [], int w ) :
+ phases( p ),
+ width( w )
+{
+ volume_unit_ = 0.0;
+ kernel_unit = 0;
+ buf = NULL;
+ last_amp = 0;
+ delta_factor = 0;
+}
+
+#undef PI
+#define PI 3.1415926535897932384626433832795029
+
+// Generates right half of sinc kernel (including center point) with cutoff at
+// sample rate / 2 / oversample. Frequency response at cutoff frequency is
+// treble dB (-6=0.5,-12=0.25). Mid controls frequency that rolloff begins at,
+// cut * sample rate / 2.
+static void gen_sinc( float out [], int out_size, double oversample,
+ double treble, double mid )
+{
+ if ( mid > 0.9999 ) mid = 0.9999;
+ if ( treble < -300.0 ) treble = -300.0;
+ if ( treble > 5.0 ) treble = 5.0;
+
+ double const maxh = 4096.0;
+ double rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - mid) );
+ double const pow_a_n = pow( rolloff, maxh - maxh * mid );
+ double const to_angle = PI / maxh / oversample;
+ for ( int i = 1; i < out_size; i++ )
+ {
+ double angle = i * to_angle;
+ double c = rolloff * cos( angle * maxh - angle ) -
+ cos( angle * maxh );
+ double cos_nc_angle = cos( angle * maxh * mid );
+ double cos_nc1_angle = cos( angle * maxh * mid - angle );
+ double cos_angle = cos( angle );
+
+ c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
+ double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
+ double b = 2.0 - cos_angle - cos_angle;
+ double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
+
+ out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
+ }
+
+ // Approximate center by looking at two points to right. Much simpler
+ // and more reliable than trying to calculate it properly.
+ out [0] = out [1] + 0.5 * (out [1] - out [2]);
+}
+
+// Gain is 1-2800 for beta of 0-10, instead of 1.0 as it should be, but
+// this is corrected by normalization in treble_eq().
+static void kaiser_window( float io [], int count, float beta )
+{
+ int const accuracy = 10;
+
+ float const beta2 = beta * beta;
+ float const step = (float) 0.5 / count;
+ float pos = (float) 0.5;
+ for ( float* const end = io + count; io < end; ++io )
+ {
+ float x = (pos - pos*pos) * beta2;
+ float u = x;
+ float k = 1;
+ float n = 2;
+
+ // Keep refining until adjustment becomes small
+ do
+ {
+ u *= x / (n * n);
+ n += 1;
+ k += u;
+ }
+ while ( k <= u * (1 << accuracy) );
+
+ pos += step;
+ *io *= k;
+ }
+}
+
+void blip_eq_t::generate( float out [], int count ) const
+{
+ // lower cutoff freq for narrow kernels with their wider transition band
+ // (8 points->1.49, 16 points->1.15)
+ double cutoff_adj = blip_res * 2.25 / count + 0.85;
+ if ( cutoff_adj < 1.02 )
+ cutoff_adj = 1.02;
+ double half_rate = sample_rate * 0.5;
+ if ( cutoff_freq )
+ cutoff_adj = half_rate / cutoff_freq;
+ double cutoff = rolloff_freq * cutoff_adj / half_rate;
+
+ gen_sinc( out, count, oversample * cutoff_adj, treble, cutoff );
+
+ kaiser_window( out, count, kaiser );
+}
+
+void Blip_Synth_::treble_eq( blip_eq_t const& eq )
+{
+ // Generate right half of kernel
+ int const half_size = blip_eq_t::calc_count( width );
+ float fimpulse [blip_res / 2 * (BLIP_MAX_QUALITY - 1) + 1];
+ eq.generate( fimpulse, half_size );
+
+ int i;
+
+ // Find rescale factor. Summing from small to large (right to left)
+ // reduces error.
+ double total = 0.0;
+ for ( i = half_size; --i > 0; )
+ total += fimpulse [i];
+ total = total * 2.0 + fimpulse [0];
+
+ //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
+ //double const base_unit = 37888.0; // allows treble to +5 dB
+ double const base_unit = 32768.0; // necessary for blip_unscaled to work
+ double rescale = base_unit / total;
+ kernel_unit = (int) base_unit;
+
+ // Integrate, first difference, rescale, convert to int
+ double sum = 0;
+ double next = 0;
+ int const size = impulses_size();
+ for ( i = 0; i < size; i++ )
+ {
+ int j = (half_size - 1) - i;
+
+ if ( i >= blip_res )
+ sum += fimpulse [j + blip_res];
+
+ // goes slightly past center, so it needs a little mirroring
+ next += fimpulse [j < 0 ? -j : j];
+
+ // calculate unintereleved index
+ int x = (~i & (blip_res - 1)) * (width >> 1) + (i >> BLIP_PHASE_BITS);
+ assert( (unsigned) x < (unsigned) size );
+
+ // flooring separately virtually eliminates error
+ phases [x] = (short) (int)
+ (floor( sum * rescale + 0.5 ) - floor( next * rescale + 0.5 ));
+ //phases [x] = (short) (int)
+ // floor( sum * rescale - next * rescale + 0.5 );
+ }
+
+ adjust_impulse();
+
+ // volume might require rescaling
+ double vol = volume_unit_;
+ if ( vol )
+ {
+ volume_unit_ = 0.0;
+ volume_unit( vol );
+ }
+}
+
+void Blip_Synth_::adjust_impulse()
+{
+ int const size = impulses_size();
+ int const half_width = width / 2;
+
+ // Sum each phase as would be done when synthesizing, and correct
+ // any that don't add up to exactly kernel_half.
+ for ( int phase = blip_res / 2; --phase >= 0; )
+ {
+ int const fwd = phase * half_width;
+ int const rev = size - half_width - fwd;
+
+ int error = kernel_unit;
+ for ( int i = half_width; --i >= 0; )
+ {
+ error += phases [fwd + i];
+ error += phases [rev + i];
+ }
+ phases [fwd + half_width - 1] -= (short) error;
+
+ // Error shouldn't occur now with improved calculation
+ //if ( error ) printf( "error: %ld\n", error );
+ }
+
+ #if 0
+ for ( int i = 0; i < blip_res; i++, printf( "\n" ) )
+ for ( int j = 0; j < width / 2; j++ )
+ printf( "%5d,", (int) -phases [j + width/2 * i] );
+ #endif
+}
+
+void Blip_Synth_::rescale_kernel( int shift )
+{
+ // Keep values positive to avoid round-towards-zero of sign-preserving
+ // right shift for negative values.
+ int const keep_positive = 0x8000 + (1 << (shift - 1));
+
+ int const half_width = width / 2;
+ for ( int phase = blip_res; --phase >= 0; )
+ {
+ int const fwd = phase * half_width;
+
+ // Integrate, rescale, then differentiate again.
+ // If differences are rescaled directly, more error results.
+ int sum = keep_positive;
+ for ( int i = 0; i < half_width; i++ )
+ {
+ int prev = sum;
+ sum += phases [fwd + i];
+ phases [fwd + i] = (sum >> shift) - (prev >> shift);
+ }
+ }
+
+ adjust_impulse();
+}
+
+void Blip_Synth_::volume_unit( double new_unit )
+{
+ if ( volume_unit_ != new_unit )
+ {
+ // use default eq if it hasn't been set yet
+ if ( !kernel_unit )
+ treble_eq( -8.0 );
+
+ // Factor that kernel must be multiplied by
+ volume_unit_ = new_unit;
+ double factor = new_unit * (1 << blip_sample_bits) / kernel_unit;
+
+ if ( factor > 0.0 )
+ {
+ // If factor is low, reduce amplitude of kernel itself
+ int shift = 0;
+ while ( factor < 2.0 )
+ {
+ shift++;
+ factor *= 2.0;
+ }
+
+ if ( shift )
+ {
+ kernel_unit >>= shift;
+ assert( kernel_unit > 0 ); // fails if volume unit is too low
+
+ rescale_kernel( shift );
+ }
+ }
+
+ delta_factor = -(int) floor( factor + 0.5 );
+ //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
+ }
+}
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,198 +1,198 @@
-// Band-limited sound synthesis buffer
-
-// Blip_Buffer $vers
-#ifndef BLIP_BUFFER_H
-#define BLIP_BUFFER_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer_impl.h"
-
-typedef int blip_time_t; // Source clocks in current time frame
-typedef BOOST::int16_t blip_sample_t; // 16-bit signed output sample
-int const blip_default_length = 1000 / 4; // Default Blip_Buffer length (1/4 second)
-
-
-//// Sample buffer for band-limited synthesis
-
-class Blip_Buffer : public Blip_Buffer_ {
-public:
-
- // Sets output sample rate and resizes and clears sample buffer
- blargg_err_t set_sample_rate( int samples_per_sec, int msec_length = blip_default_length );
-
- // Sets number of source time units per second
- void clock_rate( int clocks_per_sec );
-
- // Clears buffer and removes all samples
- void clear();
-
- // Use Blip_Synth to add waveform to buffer
-
- // Resamples to time t, then subtracts t from current time. Appends result of resampling
- // to buffer for reading.
- void end_frame( blip_time_t t );
-
- // Number of samples available for reading with read_samples()
- int samples_avail() const;
-
- // Reads at most n samples to out [0 to n-1] and returns number actually read. If stereo
- // is true, writes to out [0], out [2], out [4] etc. instead.
- int read_samples( blip_sample_t out [], int n, bool stereo = false );
-
-// More features
-
- // Sets flag that tells some Multi_Buffer types that sound was added to buffer,
- // so they know that it needs to be mixed in. Only needs to be called once
- // per time frame that sound was added. Not needed if not using Multi_Buffer.
- void set_modified() { modified_ = true; }
-
- // Sets high-pass filter frequency, from 0 to 20000 Hz, where higher values reduce bass more
- void bass_freq( int frequency );
-
- int length() const; // Length of buffer in milliseconds
- int sample_rate() const; // Current output sample rate
- int clock_rate() const; // Number of source time units per second
- int output_latency() const; // Number of samples delay from offset() to read_samples()
-
-// Low-level features
-
- // Removes the first n samples
- void remove_samples( int n );
-
- // Returns number of clocks needed until n samples will be available.
- // If buffer cannot even hold n samples, returns number of clocks
- // until buffer becomes full.
- blip_time_t count_clocks( int n ) const;
-
- // Number of samples that should be mixed before calling end_frame( t )
- int count_samples( blip_time_t t ) const;
-
- // Mixes n samples into buffer
- void mix_samples( const blip_sample_t in [], int n );
-
-// Resampled time (sorry, poor documentation right now)
-
- // Resampled time is fixed-point, in terms of output samples.
-
- // Converts clock count to resampled time
- blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
-
- // Converts clock time since beginning of current time frame to resampled time
- blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
-
- // Returns factor that converts clock rate to resampled time
- blip_resampled_time_t clock_rate_factor( int clock_rate ) const;
-
-// State save/load
-
- // Saves state, including high-pass filter and tails of last deltas.
- // All samples must have been read from buffer before calling this
- // (that is, samples_avail() must return 0).
- void save_state( blip_buffer_state_t* out );
-
- // Loads state. State must have been saved from Blip_Buffer with same
- // settings during same run of program; states can NOT be stored on disk.
- // Clears buffer before loading state.
- void load_state( const blip_buffer_state_t& in );
-
-private:
- // noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-
-// Implementation
-public:
- BLARGG_DISABLE_NOTHROW
- Blip_Buffer();
- ~Blip_Buffer();
- void remove_silence( int n );
-};
-
-
-//// Adds amplitude changes to Blip_Buffer
-
-template class Blip_Synth;
-
-typedef Blip_Synth<8, 1> Blip_Synth_Fast; // faster, but less equalizer control
-typedef Blip_Synth<12,1> Blip_Synth_Norm; // good for most things
-typedef Blip_Synth<16,1> Blip_Synth_Good; // sharper filter cutoff
-
-template
-class Blip_Synth {
-public:
-
- // Sets volume of amplitude delta unit
- void volume( double v ) { impl.volume_unit( 1.0 / range * v ); }
-
- // Configures low-pass filter
- void treble_eq( const blip_eq_t& eq ) { impl.treble_eq( eq ); }
-
- // Gets/sets default Blip_Buffer
- Blip_Buffer* output() const { return impl.buf; }
- void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
-
- // Extends waveform to time t at current amplitude, then changes its amplitude to a
- // Using this requires a separate Blip_Synth for each waveform.
- void update( blip_time_t t, int a );
-
-// Low-level interface
-
- // If no Blip_Buffer* is specified, uses one set by output() above
-
- // Adds amplitude transition at time t. Delta can be positive or negative.
- // The actual change in amplitude is delta * volume.
- void offset( blip_time_t t, int delta, Blip_Buffer* ) const;
- void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
-
- // Same as offset(), except code is inlined for higher performance
- void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { offset_resampled( buf->to_fixed( t ), delta, buf ); }
- void offset_inline( blip_time_t t, int delta ) const { offset_resampled( impl.buf->to_fixed( t ), delta, impl.buf ); }
-
- // Works directly in terms of fractional output samples. Use resampled time functions in Blip_Buffer
- // to convert clock counts to resampled time.
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
-
-// Implementation
-public:
- BLARGG_DISABLE_NOTHROW
-
-private:
-#if BLIP_BUFFER_FAST
- Blip_Synth_Fast_ impl;
- typedef char coeff_t;
-#else
- Blip_Synth_ impl;
- typedef short coeff_t;
- // Left halves of first difference of step response for each possible phase
- coeff_t phases [quality / 2 * blip_res];
-public:
- Blip_Synth() : impl( phases, quality ) { }
-#endif
-};
-
-
-//// Low-pass equalization parameters
-
-class blip_eq_t {
- double treble, kaiser;
- int rolloff_freq, sample_rate, cutoff_freq;
-public:
- // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
- // treble, small positive values (0 to 5.0) increase treble.
- blip_eq_t( double treble_db = 0 );
-
- // See blip_buffer.txt
- blip_eq_t( double treble, int rolloff_freq, int sample_rate, int cutoff_freq = 0,
- double kaiser = 5.2 );
-
- // Generate center point and right half of impulse response
- virtual void generate( float out [], int count ) const;
- virtual ~blip_eq_t() { }
-
- enum { oversample = blip_res };
- static int calc_count( int quality ) { return (quality - 1) * (oversample / 2) + 1; }
-};
-
-#include "Blip_Buffer_impl2.h"
-
-#endif
+// Band-limited sound synthesis buffer
+
+// Blip_Buffer $vers
+#ifndef BLIP_BUFFER_H
+#define BLIP_BUFFER_H
+
+#include "blargg_common.h"
+#include "Blip_Buffer_impl.h"
+
+typedef int blip_time_t; // Source clocks in current time frame
+typedef BOOST::int16_t blip_sample_t; // 16-bit signed output sample
+int const blip_default_length = 1000 / 4; // Default Blip_Buffer length (1/4 second)
+
+
+//// Sample buffer for band-limited synthesis
+
+class Blip_Buffer : public Blip_Buffer_ {
+public:
+
+ // Sets output sample rate and resizes and clears sample buffer
+ blargg_err_t set_sample_rate( int samples_per_sec, int msec_length = blip_default_length );
+
+ // Sets number of source time units per second
+ void clock_rate( int clocks_per_sec );
+
+ // Clears buffer and removes all samples
+ void clear();
+
+ // Use Blip_Synth to add waveform to buffer
+
+ // Resamples to time t, then subtracts t from current time. Appends result of resampling
+ // to buffer for reading.
+ void end_frame( blip_time_t t );
+
+ // Number of samples available for reading with read_samples()
+ int samples_avail() const;
+
+ // Reads at most n samples to out [0 to n-1] and returns number actually read. If stereo
+ // is true, writes to out [0], out [2], out [4] etc. instead.
+ int read_samples( blip_sample_t out [], int n, bool stereo = false );
+
+// More features
+
+ // Sets flag that tells some Multi_Buffer types that sound was added to buffer,
+ // so they know that it needs to be mixed in. Only needs to be called once
+ // per time frame that sound was added. Not needed if not using Multi_Buffer.
+ void set_modified() { modified_ = true; }
+
+ // Sets high-pass filter frequency, from 0 to 20000 Hz, where higher values reduce bass more
+ void bass_freq( int frequency );
+
+ int length() const; // Length of buffer in milliseconds
+ int sample_rate() const; // Current output sample rate
+ int clock_rate() const; // Number of source time units per second
+ int output_latency() const; // Number of samples delay from offset() to read_samples()
+
+// Low-level features
+
+ // Removes the first n samples
+ void remove_samples( int n );
+
+ // Returns number of clocks needed until n samples will be available.
+ // If buffer cannot even hold n samples, returns number of clocks
+ // until buffer becomes full.
+ blip_time_t count_clocks( int n ) const;
+
+ // Number of samples that should be mixed before calling end_frame( t )
+ int count_samples( blip_time_t t ) const;
+
+ // Mixes n samples into buffer
+ void mix_samples( const blip_sample_t in [], int n );
+
+// Resampled time (sorry, poor documentation right now)
+
+ // Resampled time is fixed-point, in terms of output samples.
+
+ // Converts clock count to resampled time
+ blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
+
+ // Converts clock time since beginning of current time frame to resampled time
+ blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
+
+ // Returns factor that converts clock rate to resampled time
+ blip_resampled_time_t clock_rate_factor( int clock_rate ) const;
+
+// State save/load
+
+ // Saves state, including high-pass filter and tails of last deltas.
+ // All samples must have been read from buffer before calling this
+ // (that is, samples_avail() must return 0).
+ void save_state( blip_buffer_state_t* out );
+
+ // Loads state. State must have been saved from Blip_Buffer with same
+ // settings during same run of program; states can NOT be stored on disk.
+ // Clears buffer before loading state.
+ void load_state( const blip_buffer_state_t& in );
+
+private:
+ // noncopyable
+ Blip_Buffer( const Blip_Buffer& );
+ Blip_Buffer& operator = ( const Blip_Buffer& );
+
+// Implementation
+public:
+ BLARGG_DISABLE_NOTHROW
+ Blip_Buffer();
+ ~Blip_Buffer();
+ void remove_silence( int n );
+};
+
+
+//// Adds amplitude changes to Blip_Buffer
+
+template class Blip_Synth;
+
+typedef Blip_Synth<8, 1> Blip_Synth_Fast; // faster, but less equalizer control
+typedef Blip_Synth<12,1> Blip_Synth_Norm; // good for most things
+typedef Blip_Synth<16,1> Blip_Synth_Good; // sharper filter cutoff
+
+template
+class Blip_Synth {
+public:
+
+ // Sets volume of amplitude delta unit
+ void volume( double v ) { impl.volume_unit( 1.0 / range * v ); }
+
+ // Configures low-pass filter
+ void treble_eq( const blip_eq_t& eq ) { impl.treble_eq( eq ); }
+
+ // Gets/sets default Blip_Buffer
+ Blip_Buffer* output() const { return impl.buf; }
+ void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
+
+ // Extends waveform to time t at current amplitude, then changes its amplitude to a
+ // Using this requires a separate Blip_Synth for each waveform.
+ void update( blip_time_t t, int a );
+
+// Low-level interface
+
+ // If no Blip_Buffer* is specified, uses one set by output() above
+
+ // Adds amplitude transition at time t. Delta can be positive or negative.
+ // The actual change in amplitude is delta * volume.
+ void offset( blip_time_t t, int delta, Blip_Buffer* ) const;
+ void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
+
+ // Same as offset(), except code is inlined for higher performance
+ void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { offset_resampled( buf->to_fixed( t ), delta, buf ); }
+ void offset_inline( blip_time_t t, int delta ) const { offset_resampled( impl.buf->to_fixed( t ), delta, impl.buf ); }
+
+ // Works directly in terms of fractional output samples. Use resampled time functions in Blip_Buffer
+ // to convert clock counts to resampled time.
+ void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
+
+// Implementation
+public:
+ BLARGG_DISABLE_NOTHROW
+
+private:
+#if BLIP_BUFFER_FAST
+ Blip_Synth_Fast_ impl;
+ typedef char coeff_t;
+#else
+ Blip_Synth_ impl;
+ typedef short coeff_t;
+ // Left halves of first difference of step response for each possible phase
+ coeff_t phases [quality / 2 * blip_res];
+public:
+ Blip_Synth() : impl( phases, quality ) { }
+#endif
+};
+
+
+//// Low-pass equalization parameters
+
+class blip_eq_t {
+ double treble, kaiser;
+ int rolloff_freq, sample_rate, cutoff_freq;
+public:
+ // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
+ // treble, small positive values (0 to 5.0) increase treble.
+ blip_eq_t( double treble_db = 0 );
+
+ // See blip_buffer.txt
+ blip_eq_t( double treble, int rolloff_freq, int sample_rate, int cutoff_freq = 0,
+ double kaiser = 5.2 );
+
+ // Generate center point and right half of impulse response
+ virtual void generate( float out [], int count ) const;
+ virtual ~blip_eq_t() { }
+
+ enum { oversample = blip_res };
+ static int calc_count( int quality ) { return (quality - 1) * (oversample / 2) + 1; }
+};
+
+#include "Blip_Buffer_impl2.h"
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl2.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl2.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl2.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl2.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,282 +1,282 @@
-// Internal stuff here to keep public header uncluttered
-
-// Blip_Buffer $vers
-#ifndef BLIP_BUFFER_IMPL2_H
-#define BLIP_BUFFER_IMPL2_H
-
-//// Compatibility
-
-BLARGG_DEPRECATED( int const blip_low_quality = 8; )
-BLARGG_DEPRECATED( int const blip_med_quality = 8; )
-BLARGG_DEPRECATED( int const blip_good_quality = 12; )
-BLARGG_DEPRECATED( int const blip_high_quality = 16; )
-
-BLARGG_DEPRECATED( int const blip_sample_max = 32767; )
-
-// Number of bits in raw sample that covers normal output range. Less than 32 bits to give
-// extra amplitude range. That is,
-// +1 << (blip_sample_bits-1) = +1.0
-// -1 << (blip_sample_bits-1) = -1.0
-int const blip_sample_bits = 30;
-
-//// BLIP_READER_
-
-//// Optimized reading from Blip_Buffer, for use in custom sample buffer or mixer
-
-// Begins reading from buffer. Name should be unique to the current {} block.
-#define BLIP_READER_BEGIN( name, blip_buffer ) \
- const Blip_Buffer::delta_t* BLARGG_RESTRICT name##_reader_buf = (blip_buffer).read_pos();\
- int name##_reader_accum = (blip_buffer).integrator()
-
-// Gets value to pass to BLIP_READER_NEXT()
-#define BLIP_READER_BASS( blip_buffer ) (blip_buffer).highpass_shift()
-
-// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
-// code at the cost of having no bass_freq() functionality
-int const blip_reader_default_bass = 9;
-
-// Current sample as 16-bit signed value
-#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
-
-// Current raw sample in full internal resolution
-#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
-
-// Advances to next sample
-#define BLIP_READER_NEXT( name, bass ) \
- (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
-
-// Ends reading samples from buffer. The number of samples read must now be removed
-// using Blip_Buffer::remove_samples().
-#define BLIP_READER_END( name, blip_buffer ) \
- (void) ((blip_buffer).set_integrator( name##_reader_accum ))
-
-#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset)
-
-int const blip_reader_idx_factor = sizeof (Blip_Buffer::delta_t);
-
-#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\
- name##_reader_accum -= name##_reader_accum >> (bass);\
- name##_reader_accum += name##_reader_buf [(idx)];\
-}
-
-#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\
- name##_reader_accum -= name##_reader_accum >> (bass);\
- name##_reader_accum +=\
- *(Blip_Buffer::delta_t const*) ((char const*) name##_reader_buf + (idx));\
-}
-
-//// BLIP_CLAMP
-
-#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
- #define BLIP_X86 1
- #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in
-#else
- #define BLIP_CLAMP_( in ) (blip_sample_t) in != in
-#endif
-
-// Clamp sample to blip_sample_t range
-#define BLIP_CLAMP( sample, out )\
- { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 31) ^ 0x7FFF; }
-
-
-//// Blip_Synth
-
-// (in >> sh & mask) * mul
-#define BLIP_SH_AND_MUL( in, sh, mask, mul ) \
-((int) (in) / ((1U << (sh)) / (mul)) & (unsigned) ((mask) * (mul)))
-
-// (T*) ptr + (off >> sh)
-#define BLIP_PTR_OFF_SH( T, ptr, off, sh ) \
- ((T*) (BLIP_SH_AND_MUL( off, sh, -1, sizeof (T) ) + (char*) (ptr)))
-
-template
-inline void Blip_Synth::offset_resampled( blip_resampled_time_t time,
- int delta, Blip_Buffer* blip_buf ) const
-{
-#if BLIP_BUFFER_FAST
- int const half_width = 1;
-#else
- int const half_width = quality / 2;
-#endif
-
- Blip_Buffer::delta_t* BLARGG_RESTRICT buf = blip_buf->delta_at( time );
-
- delta *= impl.delta_factor;
-
- int const phase_shift = BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS;
- int const phase = (half_width & (half_width - 1)) ?
- (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) ) * half_width :
- (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) * half_width );
-
-#if BLIP_BUFFER_FAST
- int left = buf [0] + delta;
-
- // Kind of crappy, but doing shift after multiply results in overflow.
- // Alternate way of delaying multiply by delta_factor results in worse
- // sub-sample resolution.
- int right = (delta >> BLIP_PHASE_BITS) * phase;
- #if BLIP_BUFFER_NOINTERP
- // TODO: remove? (just a hack to see how it sounds)
- right = 0;
- #endif
- left -= right;
- right += buf [1];
-
- buf [0] = left;
- buf [1] = right;
-#else
-
- int const fwd = -quality / 2;
- int const rev = fwd + quality - 2;
-
- coeff_t const* BLARGG_RESTRICT imp = (coeff_t const*) ((char const*) phases + phase);
- int const phase2 = phase + phase - (blip_res - 1) * half_width * sizeof (coeff_t);
-
- #define BLIP_MID_IMP imp = (coeff_t const*) ((char const*) imp - phase2);
-
- #if BLIP_MAX_QUALITY > 16
- // General version for any quality
- if ( quality != 8 && quality != 12 && quality != 16 )
- {
- buf += fwd;
-
- // left half
- for ( int n = half_width / 2; --n >= 0; )
- {
- buf [0] += imp [0] * delta;
- buf [1] += imp [1] * delta;
- imp += 2;
- buf += 2;
- }
-
- // mirrored right half
- BLIP_MID_IMP
- for ( int n = half_width / 2; --n >= 0; )
- {
- buf [0] += imp [-1] * delta;
- buf [1] += *(imp -= 2) * delta;
- buf += 2;
- }
-
- return;
- }
- #endif
-
- // Unrolled versions for qualities 8, 12, and 16
-
- #if BLIP_X86
- // This gives better code for x86
- #define BLIP_ADD( out, in ) \
- buf [out] += imp [in] * delta
-
- #define BLIP_FWD( i ) {\
- BLIP_ADD( fwd + i, i );\
- BLIP_ADD( fwd + 1 + i, i + 1 );\
- }
-
- #define BLIP_REV( r ) {\
- BLIP_ADD( rev - r, r + 1 );\
- BLIP_ADD( rev + 1 - r, r );\
- }
-
- BLIP_FWD( 0 )
- BLIP_FWD( 2 )
- if ( quality > 8 ) BLIP_FWD( 4 )
- if ( quality > 12 ) BLIP_FWD( 6 )
- BLIP_MID_IMP
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
- BLIP_REV( 0 )
-
- #else
- // Help RISC processors and simplistic compilers by reading ahead of writes
- #define BLIP_FWD( i ) {\
- int t0 = i0 * delta + buf [fwd + i];\
- int t1 = imp [i + 1] * delta + buf [fwd + 1 + i];\
- i0 = imp [i + 2];\
- buf [fwd + i] = t0;\
- buf [fwd + 1 + i] = t1;\
- }
-
- #define BLIP_REV( r ) {\
- int t0 = i0 * delta + buf [rev - r];\
- int t1 = imp [r] * delta + buf [rev + 1 - r];\
- i0 = imp [r - 1];\
- buf [rev - r] = t0;\
- buf [rev + 1 - r] = t1;\
- }
-
- int i0 = *imp;
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- int const mid = half_width - 1;
- int t0 = i0 * delta + buf [fwd + mid - 1];
- int t1 = imp [mid] * delta + buf [fwd + mid ];
- BLIP_MID_IMP
- i0 = imp [mid];
- buf [fwd + mid - 1] = t0;
- buf [fwd + mid ] = t1;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- int t0 = i0 * delta + buf [rev ];
- int t1 = *imp * delta + buf [rev + 1];
- buf [rev ] = t0;
- buf [rev + 1] = t1;
- #endif
-
-#endif
-}
-
-template
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
-{
- offset_resampled( buf->to_fixed( t ), delta, buf );
-}
-
-template
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth::update( blip_time_t t, int amp )
-{
- int delta = amp - impl.last_amp;
- impl.last_amp = amp;
- offset_resampled( impl.buf->to_fixed( t ), delta, impl.buf );
-}
-
-
-//// blip_eq_t
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), kaiser( 5.2 ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
-inline blip_eq_t::blip_eq_t( double t, int rf, int sr, int cf, double k ) :
- treble( t ), kaiser( k ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
-
-
-//// Blip_Buffer
-
-inline int Blip_Buffer::length() const { return length_; }
-inline int Blip_Buffer::samples_avail() const { return (int) (offset_ >> BLIP_BUFFER_ACCURACY); }
-inline int Blip_Buffer::sample_rate() const { return sample_rate_; }
-inline int Blip_Buffer::output_latency() const { return BLIP_MAX_QUALITY / 2; }
-inline int Blip_Buffer::clock_rate() const { return clock_rate_; }
-inline void Blip_Buffer::clock_rate( int cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
-
-inline void Blip_Buffer::remove_silence( int count )
-{
- // fails if you try to remove more samples than available
- assert( count <= samples_avail() );
- offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-#endif
+// Internal stuff here to keep public header uncluttered
+
+// Blip_Buffer $vers
+#ifndef BLIP_BUFFER_IMPL2_H
+#define BLIP_BUFFER_IMPL2_H
+
+//// Compatibility
+
+BLARGG_DEPRECATED( int const blip_low_quality = 8; )
+BLARGG_DEPRECATED( int const blip_med_quality = 8; )
+BLARGG_DEPRECATED( int const blip_good_quality = 12; )
+BLARGG_DEPRECATED( int const blip_high_quality = 16; )
+
+BLARGG_DEPRECATED( int const blip_sample_max = 32767; )
+
+// Number of bits in raw sample that covers normal output range. Less than 32 bits to give
+// extra amplitude range. That is,
+// +1 << (blip_sample_bits-1) = +1.0
+// -1 << (blip_sample_bits-1) = -1.0
+int const blip_sample_bits = 30;
+
+//// BLIP_READER_
+
+//// Optimized reading from Blip_Buffer, for use in custom sample buffer or mixer
+
+// Begins reading from buffer. Name should be unique to the current {} block.
+#define BLIP_READER_BEGIN( name, blip_buffer ) \
+ const Blip_Buffer::delta_t* BLARGG_RESTRICT name##_reader_buf = (blip_buffer).read_pos();\
+ int name##_reader_accum = (blip_buffer).integrator()
+
+// Gets value to pass to BLIP_READER_NEXT()
+#define BLIP_READER_BASS( blip_buffer ) (blip_buffer).highpass_shift()
+
+// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
+// code at the cost of having no bass_freq() functionality
+int const blip_reader_default_bass = 9;
+
+// Current sample as 16-bit signed value
+#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
+
+// Current raw sample in full internal resolution
+#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
+
+// Advances to next sample
+#define BLIP_READER_NEXT( name, bass ) \
+ (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
+
+// Ends reading samples from buffer. The number of samples read must now be removed
+// using Blip_Buffer::remove_samples().
+#define BLIP_READER_END( name, blip_buffer ) \
+ (void) ((blip_buffer).set_integrator( name##_reader_accum ))
+
+#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset)
+
+int const blip_reader_idx_factor = sizeof (Blip_Buffer::delta_t);
+
+#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\
+ name##_reader_accum -= name##_reader_accum >> (bass);\
+ name##_reader_accum += name##_reader_buf [(idx)];\
+}
+
+#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\
+ name##_reader_accum -= name##_reader_accum >> (bass);\
+ name##_reader_accum +=\
+ *(Blip_Buffer::delta_t const*) ((char const*) name##_reader_buf + (idx));\
+}
+
+//// BLIP_CLAMP
+
+#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
+ defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
+ #define BLIP_X86 1
+ #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in
+#else
+ #define BLIP_CLAMP_( in ) (blip_sample_t) in != in
+#endif
+
+// Clamp sample to blip_sample_t range
+#define BLIP_CLAMP( sample, out )\
+ { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 31) ^ 0x7FFF; }
+
+
+//// Blip_Synth
+
+// (in >> sh & mask) * mul
+#define BLIP_SH_AND_MUL( in, sh, mask, mul ) \
+((int) (in) / ((1U << (sh)) / (mul)) & (unsigned) ((mask) * (mul)))
+
+// (T*) ptr + (off >> sh)
+#define BLIP_PTR_OFF_SH( T, ptr, off, sh ) \
+ ((T*) (BLIP_SH_AND_MUL( off, sh, -1, sizeof (T) ) + (char*) (ptr)))
+
+template
+inline void Blip_Synth::offset_resampled( blip_resampled_time_t time,
+ int delta, Blip_Buffer* blip_buf ) const
+{
+#if BLIP_BUFFER_FAST
+ int const half_width = 1;
+#else
+ int const half_width = quality / 2;
+#endif
+
+ Blip_Buffer::delta_t* BLARGG_RESTRICT buf = blip_buf->delta_at( time );
+
+ delta *= impl.delta_factor;
+
+ int const phase_shift = BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS;
+ int const phase = (half_width & (half_width - 1)) ?
+ (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) ) * half_width :
+ (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) * half_width );
+
+#if BLIP_BUFFER_FAST
+ int left = buf [0] + delta;
+
+ // Kind of crappy, but doing shift after multiply results in overflow.
+ // Alternate way of delaying multiply by delta_factor results in worse
+ // sub-sample resolution.
+ int right = (delta >> BLIP_PHASE_BITS) * phase;
+ #if BLIP_BUFFER_NOINTERP
+ // TODO: remove? (just a hack to see how it sounds)
+ right = 0;
+ #endif
+ left -= right;
+ right += buf [1];
+
+ buf [0] = left;
+ buf [1] = right;
+#else
+
+ int const fwd = -quality / 2;
+ int const rev = fwd + quality - 2;
+
+ coeff_t const* BLARGG_RESTRICT imp = (coeff_t const*) ((char const*) phases + phase);
+ int const phase2 = phase + phase - (blip_res - 1) * half_width * sizeof (coeff_t);
+
+ #define BLIP_MID_IMP imp = (coeff_t const*) ((char const*) imp - phase2);
+
+ #if BLIP_MAX_QUALITY > 16
+ // General version for any quality
+ if ( quality != 8 && quality != 12 && quality != 16 )
+ {
+ buf += fwd;
+
+ // left half
+ for ( int n = half_width / 2; --n >= 0; )
+ {
+ buf [0] += imp [0] * delta;
+ buf [1] += imp [1] * delta;
+ imp += 2;
+ buf += 2;
+ }
+
+ // mirrored right half
+ BLIP_MID_IMP
+ for ( int n = half_width / 2; --n >= 0; )
+ {
+ buf [0] += imp [-1] * delta;
+ buf [1] += *(imp -= 2) * delta;
+ buf += 2;
+ }
+
+ return;
+ }
+ #endif
+
+ // Unrolled versions for qualities 8, 12, and 16
+
+ #if BLIP_X86
+ // This gives better code for x86
+ #define BLIP_ADD( out, in ) \
+ buf [out] += imp [in] * delta
+
+ #define BLIP_FWD( i ) {\
+ BLIP_ADD( fwd + i, i );\
+ BLIP_ADD( fwd + 1 + i, i + 1 );\
+ }
+
+ #define BLIP_REV( r ) {\
+ BLIP_ADD( rev - r, r + 1 );\
+ BLIP_ADD( rev + 1 - r, r );\
+ }
+
+ BLIP_FWD( 0 )
+ BLIP_FWD( 2 )
+ if ( quality > 8 ) BLIP_FWD( 4 )
+ if ( quality > 12 ) BLIP_FWD( 6 )
+ BLIP_MID_IMP
+ if ( quality > 12 ) BLIP_REV( 6 )
+ if ( quality > 8 ) BLIP_REV( 4 )
+ BLIP_REV( 2 )
+ BLIP_REV( 0 )
+
+ #else
+ // Help RISC processors and simplistic compilers by reading ahead of writes
+ #define BLIP_FWD( i ) {\
+ int t0 = i0 * delta + buf [fwd + i];\
+ int t1 = imp [i + 1] * delta + buf [fwd + 1 + i];\
+ i0 = imp [i + 2];\
+ buf [fwd + i] = t0;\
+ buf [fwd + 1 + i] = t1;\
+ }
+
+ #define BLIP_REV( r ) {\
+ int t0 = i0 * delta + buf [rev - r];\
+ int t1 = imp [r] * delta + buf [rev + 1 - r];\
+ i0 = imp [r - 1];\
+ buf [rev - r] = t0;\
+ buf [rev + 1 - r] = t1;\
+ }
+
+ int i0 = *imp;
+ BLIP_FWD( 0 )
+ if ( quality > 8 ) BLIP_FWD( 2 )
+ if ( quality > 12 ) BLIP_FWD( 4 )
+ {
+ int const mid = half_width - 1;
+ int t0 = i0 * delta + buf [fwd + mid - 1];
+ int t1 = imp [mid] * delta + buf [fwd + mid ];
+ BLIP_MID_IMP
+ i0 = imp [mid];
+ buf [fwd + mid - 1] = t0;
+ buf [fwd + mid ] = t1;
+ }
+ if ( quality > 12 ) BLIP_REV( 6 )
+ if ( quality > 8 ) BLIP_REV( 4 )
+ BLIP_REV( 2 )
+
+ int t0 = i0 * delta + buf [rev ];
+ int t1 = *imp * delta + buf [rev + 1];
+ buf [rev ] = t0;
+ buf [rev + 1] = t1;
+ #endif
+
+#endif
+}
+
+template
+#if BLIP_BUFFER_FAST
+ inline
+#endif
+void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
+{
+ offset_resampled( buf->to_fixed( t ), delta, buf );
+}
+
+template
+#if BLIP_BUFFER_FAST
+ inline
+#endif
+void Blip_Synth::update( blip_time_t t, int amp )
+{
+ int delta = amp - impl.last_amp;
+ impl.last_amp = amp;
+ offset_resampled( impl.buf->to_fixed( t ), delta, impl.buf );
+}
+
+
+//// blip_eq_t
+
+inline blip_eq_t::blip_eq_t( double t ) :
+ treble( t ), kaiser( 5.2 ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
+inline blip_eq_t::blip_eq_t( double t, int rf, int sr, int cf, double k ) :
+ treble( t ), kaiser( k ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
+
+
+//// Blip_Buffer
+
+inline int Blip_Buffer::length() const { return length_; }
+inline int Blip_Buffer::samples_avail() const { return (int) (offset_ >> BLIP_BUFFER_ACCURACY); }
+inline int Blip_Buffer::sample_rate() const { return sample_rate_; }
+inline int Blip_Buffer::output_latency() const { return BLIP_MAX_QUALITY / 2; }
+inline int Blip_Buffer::clock_rate() const { return clock_rate_; }
+inline void Blip_Buffer::clock_rate( int cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
+
+inline void Blip_Buffer::remove_silence( int count )
+{
+ // fails if you try to remove more samples than available
+ assert( count <= samples_avail() );
+ offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Blip_Buffer_impl.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,135 +1,135 @@
-// Internal stuff here to keep public header uncluttered
-
-// Blip_Buffer $vers
-#ifndef BLIP_BUFFER_IMPL_H
-#define BLIP_BUFFER_IMPL_H
-
-typedef unsigned blip_resampled_time_t;
-
-#ifndef BLIP_MAX_QUALITY
- #define BLIP_MAX_QUALITY 32
-#endif
-
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
-
-#ifndef BLIP_PHASE_BITS
- #define BLIP_PHASE_BITS 6
-#endif
-
-class blip_eq_t;
-class Blip_Buffer;
-
-#if BLIP_BUFFER_FAST
- // linear interpolation needs 8 bits
- #undef BLIP_PHASE_BITS
- #define BLIP_PHASE_BITS 8
-
- #undef BLIP_MAX_QUALITY
- #define BLIP_MAX_QUALITY 2
-#endif
-
-int const blip_res = 1 << BLIP_PHASE_BITS;
-int const blip_buffer_extra_ = BLIP_MAX_QUALITY + 2;
-
-class Blip_Buffer_ {
-public:
-// Writer
-
- typedef int clocks_t;
-
- // Properties of fixed-point sample position
- typedef unsigned fixed_t; // unsigned for more range, optimized shifts
- enum { fixed_bits = BLIP_BUFFER_ACCURACY }; // bits in fraction
- enum { fixed_unit = 1 << fixed_bits }; // 1.0 samples
-
- // Converts clock count to fixed-point sample position
- fixed_t to_fixed( clocks_t t ) const { return t * factor_ + offset_; }
-
- // Deltas in buffer are fixed-point with this many fraction bits.
- // Less than 16 for extra range.
- enum { delta_bits = 14 };
-
- // Pointer to first committed delta sample
- typedef int delta_t;
-
- // Pointer to delta corresponding to fixed-point sample position
- delta_t* delta_at( fixed_t );
-
-// Reader
-
- delta_t* read_pos() { return buffer_; }
-
- void clear_modified() { modified_ = false; }
- int highpass_shift() const { return bass_shift_; }
- int integrator() const { return reader_accum_; }
- void set_integrator( int n ) { reader_accum_ = n; }
-
-public: //friend class Tracked_Blip_Buffer; private:
- bool modified() const { return modified_; }
- void remove_silence( int count );
-
-private:
- unsigned factor_;
- fixed_t offset_;
- delta_t* buffer_center_;
- int buffer_size_;
- int reader_accum_;
- int bass_shift_;
- delta_t* buffer_;
- int sample_rate_;
- int clock_rate_;
- int bass_freq_;
- int length_;
- bool modified_;
-
- friend class Blip_Buffer;
-};
-
-class Blip_Synth_Fast_ {
-public:
- int delta_factor;
- int last_amp;
- Blip_Buffer* buf;
-
- void volume_unit( double );
- void treble_eq( blip_eq_t const& ) { }
- Blip_Synth_Fast_();
-};
-
-class Blip_Synth_ {
-public:
- int delta_factor;
- int last_amp;
- Blip_Buffer* buf;
-
- void volume_unit( double );
- void treble_eq( blip_eq_t const& );
- Blip_Synth_( short phases [], int width );
-private:
- double volume_unit_;
- short* const phases;
- int const width;
- int kernel_unit;
-
- void adjust_impulse();
- void rescale_kernel( int shift );
- int impulses_size() const { return blip_res / 2 * width; }
-};
-
-class blip_buffer_state_t
-{
- blip_resampled_time_t offset_;
- int reader_accum_;
- int buf [blip_buffer_extra_];
- friend class Blip_Buffer;
-};
-
-inline Blip_Buffer_::delta_t* Blip_Buffer_::delta_at( fixed_t f )
-{
- assert( (f >> fixed_bits) < (unsigned) buffer_size_ );
- return buffer_center_ + (f >> fixed_bits);
-}
-
-#endif
+// Internal stuff here to keep public header uncluttered
+
+// Blip_Buffer $vers
+#ifndef BLIP_BUFFER_IMPL_H
+#define BLIP_BUFFER_IMPL_H
+
+typedef unsigned blip_resampled_time_t;
+
+#ifndef BLIP_MAX_QUALITY
+ #define BLIP_MAX_QUALITY 32
+#endif
+
+#ifndef BLIP_BUFFER_ACCURACY
+ #define BLIP_BUFFER_ACCURACY 16
+#endif
+
+#ifndef BLIP_PHASE_BITS
+ #define BLIP_PHASE_BITS 6
+#endif
+
+class blip_eq_t;
+class Blip_Buffer;
+
+#if BLIP_BUFFER_FAST
+ // linear interpolation needs 8 bits
+ #undef BLIP_PHASE_BITS
+ #define BLIP_PHASE_BITS 8
+
+ #undef BLIP_MAX_QUALITY
+ #define BLIP_MAX_QUALITY 2
+#endif
+
+int const blip_res = 1 << BLIP_PHASE_BITS;
+int const blip_buffer_extra_ = BLIP_MAX_QUALITY + 2;
+
+class Blip_Buffer_ {
+public:
+// Writer
+
+ typedef int clocks_t;
+
+ // Properties of fixed-point sample position
+ typedef unsigned fixed_t; // unsigned for more range, optimized shifts
+ enum { fixed_bits = BLIP_BUFFER_ACCURACY }; // bits in fraction
+ enum { fixed_unit = 1 << fixed_bits }; // 1.0 samples
+
+ // Converts clock count to fixed-point sample position
+ fixed_t to_fixed( clocks_t t ) const { return t * factor_ + offset_; }
+
+ // Deltas in buffer are fixed-point with this many fraction bits.
+ // Less than 16 for extra range.
+ enum { delta_bits = 14 };
+
+ // Pointer to first committed delta sample
+ typedef int delta_t;
+
+ // Pointer to delta corresponding to fixed-point sample position
+ delta_t* delta_at( fixed_t );
+
+// Reader
+
+ delta_t* read_pos() { return buffer_; }
+
+ void clear_modified() { modified_ = false; }
+ int highpass_shift() const { return bass_shift_; }
+ int integrator() const { return reader_accum_; }
+ void set_integrator( int n ) { reader_accum_ = n; }
+
+public: //friend class Tracked_Blip_Buffer; private:
+ bool modified() const { return modified_; }
+ void remove_silence( int count );
+
+private:
+ unsigned factor_;
+ fixed_t offset_;
+ delta_t* buffer_center_;
+ int buffer_size_;
+ int reader_accum_;
+ int bass_shift_;
+ delta_t* buffer_;
+ int sample_rate_;
+ int clock_rate_;
+ int bass_freq_;
+ int length_;
+ bool modified_;
+
+ friend class Blip_Buffer;
+};
+
+class Blip_Synth_Fast_ {
+public:
+ int delta_factor;
+ int last_amp;
+ Blip_Buffer* buf;
+
+ void volume_unit( double );
+ void treble_eq( blip_eq_t const& ) { }
+ Blip_Synth_Fast_();
+};
+
+class Blip_Synth_ {
+public:
+ int delta_factor;
+ int last_amp;
+ Blip_Buffer* buf;
+
+ void volume_unit( double );
+ void treble_eq( blip_eq_t const& );
+ Blip_Synth_( short phases [], int width );
+private:
+ double volume_unit_;
+ short* const phases;
+ int const width;
+ int kernel_unit;
+
+ void adjust_impulse();
+ void rescale_kernel( int shift );
+ int impulses_size() const { return blip_res / 2 * width; }
+};
+
+class blip_buffer_state_t
+{
+ blip_resampled_time_t offset_;
+ int reader_accum_;
+ int buf [blip_buffer_extra_];
+ friend class Blip_Buffer;
+};
+
+inline Blip_Buffer_::delta_t* Blip_Buffer_::delta_at( fixed_t f )
+{
+ assert( (f >> fixed_bits) < (unsigned) buffer_size_ );
+ return buffer_center_ + (f >> fixed_bits);
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Bml_Parser.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Bml_Parser.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Bml_Parser.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Bml_Parser.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,357 +1,357 @@
-#include
-#include
-#include
-
-#include "Bml_Parser.h"
-
-const char * strchr_limited( const char * in, const char * end, char c )
-{
- while ( in < end && *in != c ) ++in;
- if ( in < end ) return in;
- else return 0;
-}
-
-Bml_Node Bml_Node::emptyNode;
-
-Bml_Node::Bml_Node()
-{
- name = 0;
- value = 0;
-}
-
-Bml_Node::Bml_Node(char const* name, size_t max_length)
-{
- size_t length = 0;
- char const* ptr = name;
- while (*ptr && length < max_length) ++ptr, ++length;
- this->name = new char[ length + 1 ];
- memcpy( this->name, name, length );
- this->name[ length ] = '\0';
- value = 0;
-}
-
-Bml_Node::Bml_Node(const Bml_Node &in)
-{
- size_t length;
- name = 0;
- if (in.name)
- {
- length = strlen(in.name);
- name = new char[length + 1];
- memcpy(name, in.name, length + 1);
- }
- value = 0;
- if (in.value)
- {
- length = strlen(in.value);
- value = new char[length + 1];
- memcpy(value, in.value, length + 1);
- }
- children = in.children;
-}
-
-Bml_Node::~Bml_Node()
-{
- delete [] name;
- delete [] value;
-}
-
-void Bml_Node::clear()
-{
- delete [] name;
- delete [] value;
-
- name = 0;
- value = 0;
- children.resize( 0 );
-}
-
-void Bml_Node::setLine(const char *line, size_t max_length)
-{
- delete [] name;
- delete [] value;
-
- name = 0;
- value = 0;
-
- size_t length = 0;
- const char * end = line;
- while (*end && length < max_length) ++end;
-
- const char * line_end = strchr_limited(line, end, '\n');
- if ( !line_end ) line_end = end;
-
- const char * first_letter = line;
- while ( first_letter < line_end && *first_letter <= 0x20 ) first_letter++;
-
- const char * colon = strchr_limited(first_letter, line_end, ':');
- const char * last_letter = line_end - 1;
-
- if (colon)
- {
- const char * first_value_letter = colon + 1;
- while (first_value_letter < line_end && *first_value_letter <= 0x20) first_value_letter++;
- last_letter = line_end - 1;
- while (last_letter > first_value_letter && *last_letter <= 0x20) last_letter--;
-
- value = new char[last_letter - first_value_letter + 2];
- memcpy(value, first_value_letter, last_letter - first_value_letter + 1);
- value[last_letter - first_value_letter + 1] = '\0';
-
- last_letter = colon - 1;
- }
-
- while (last_letter > first_letter && *last_letter <= 0x20) last_letter--;
-
- name = new char[last_letter - first_letter + 2];
- memcpy(name, first_letter, last_letter - first_letter + 1);
- name[last_letter - first_letter + 1] = '\0';
-}
-
-Bml_Node& Bml_Node::addChild(const Bml_Node &child)
-{
- children.push_back(child);
- return *(children.end() - 1);
-}
-
-const char * Bml_Node::getName() const
-{
- return name;
-}
-
-const char * Bml_Node::getValue() const
-{
- return value;
-}
-
-void Bml_Node::setValue(char const* value)
-{
- delete [] this->value;
- size_t length = strlen( value ) + 1;
- this->value = new char[ length ];
- memcpy( this->value, value, length );
-}
-
-size_t Bml_Node::getChildCount() const
-{
- return children.size();
-}
-
-Bml_Node const& Bml_Node::getChild(size_t index) const
-{
- return children[index];
-}
-
-Bml_Node & Bml_Node::walkToNode(const char *path, bool use_indexes)
-{
- Bml_Node * next_node = nullptr;
- Bml_Node * node = this;
- while ( *path )
- {
- bool item_found = false;
- size_t array_index = 0;
- const char * array_index_start = strchr( path, '[' );
- const char * next_separator = strchr( path, ':' );
- if ( !next_separator ) next_separator = path + strlen(path);
- if ( use_indexes && array_index_start && array_index_start < next_separator )
- {
- char * temp;
- array_index = strtoul( array_index_start + 1, &temp, 10 );
- }
- else
- {
- array_index_start = next_separator;
- }
- if ( use_indexes )
- {
- for ( std::vector::iterator it = node->children.begin(); it != node->children.end(); ++it )
- {
- if ( array_index_start - path == strlen(it->name) &&
- strncmp( it->name, path, array_index_start - path ) == 0 )
- {
- next_node = &(*it);
- item_found = true;
- if ( array_index == 0 ) break;
- --array_index;
- }
- if (array_index)
- item_found = false;
- }
- }
- else
- {
- for ( std::vector::iterator it = node->children.end(); it != node->children.begin(); )
- {
- --it;
- if ( next_separator - path == strlen(it->name) &&
- strncmp( it->name, path, next_separator - path ) == 0 )
- {
- next_node = &(*it);
- item_found = true;
- break;
- }
- }
- }
- if ( !item_found )
- {
- Bml_Node child( path, next_separator - path );
- node = &(node->addChild( child ));
- }
- else
- node = next_node;
- if ( *next_separator )
- {
- path = next_separator + 1;
- }
- else break;
- }
- return *node;
-}
-
-Bml_Node const& Bml_Node::walkToNode(const char *path) const
-{
- Bml_Node const* next_node = nullptr;
- Bml_Node const* node = this;
- while ( *path )
- {
- bool item_found = false;
- size_t array_index = ~0;
- const char * array_index_start = strchr( path, '[' );
- const char * next_separator = strchr( path, ':' );
- if ( !next_separator ) next_separator = path + strlen(path);
- if ( array_index_start && array_index_start < next_separator )
- {
- char * temp;
- array_index = strtoul( array_index_start + 1, &temp, 10 );
- }
- else
- {
- array_index_start = next_separator;
- }
- for ( std::vector::const_iterator it = node->children.begin(), ite = node->children.end(); it != ite; ++it )
- {
- if ( array_index_start - path == strlen(it->name) &&
- strncmp( it->name, path, array_index_start - path ) == 0 )
- {
- next_node = &(*it);
- item_found = true;
- if ( array_index == 0 ) break;
- --array_index;
- }
- }
- if ( !item_found ) return emptyNode;
- node = next_node;
- if ( *next_separator )
- {
- path = next_separator + 1;
- }
- else break;
- }
- return *node;
-}
-
-void Bml_Parser::parseDocument( const char * source, size_t max_length )
-{
- std::vector indents;
- std::string last_name;
- std::string current_path;
-
- document.clear();
-
- size_t last_indent = ~0;
-
- Bml_Node node;
-
- size_t length = 0;
- const char * end = source;
- while ( *end && length < max_length ) ++end, ++length;
-
- while ( source < end )
- {
- const char * line_end = strchr_limited( source, end, '\n' );
- if ( !line_end ) line_end = end;
-
- if ( node.getName() ) last_name = node.getName();
-
- node.setLine( source, line_end - source );
-
- size_t indent = 0;
- while ( source < line_end && *source <= 0x20 )
- {
- source++;
- indent++;
- }
-
- if ( last_indent == ~0 ) last_indent = indent;
-
- if ( indent > last_indent )
- {
- indents.push_back( last_indent );
- last_indent = indent;
- if ( current_path.length() ) current_path += ":";
- current_path += last_name;
- }
- else if ( indent < last_indent )
- {
- while ( last_indent > indent && indents.size() )
- {
- last_indent = *(indents.end() - 1);
- indents.pop_back();
- size_t colon = current_path.find_last_of( ':' );
- if ( colon != std::string::npos ) current_path.resize( colon );
- else current_path.resize( 0 );
- }
- last_indent = indent;
- }
-
- document.walkToNode( current_path.c_str() ).addChild( node );
-
- source = line_end;
- while ( *source && *source == '\n' ) source++;
- }
-}
-
-const char * Bml_Parser::enumValue(std::string const& path) const
-{
- return document.walkToNode(path.c_str()).getValue();
-}
-
-void Bml_Parser::setValue(std::string const& path, const char *value)
-{
- document.walkToNode(path.c_str(), true).setValue(value);
-}
-
-void Bml_Parser::setValue(std::string const& path, long value)
-{
- std::ostringstream str;
- str << value;
- setValue( path, str.str().c_str() );
-}
-
-void Bml_Parser::serialize(std::string & out) const
-{
- std::ostringstream strOut;
- serialize(strOut, &document, 0);
- out = strOut.str();
-}
-
-void Bml_Parser::serialize(std::ostringstream & out, Bml_Node const* node, unsigned int indent) const
-{
- for (unsigned i = 1; i < indent; ++i) out << " ";
-
- if ( indent )
- {
- out << node->getName();
- if (node->getValue() && strlen(node->getValue())) out << ":" << node->getValue();
- out << std::endl;
- }
-
- for (unsigned i = 0, j = node->getChildCount(); i < j; ++i)
- {
- Bml_Node const& child = node->getChild(i);
- if ( (!child.getValue() || !strlen(child.getValue())) && !child.getChildCount() )
- continue;
- serialize( out, &child, indent + 1 );
- if ( indent == 0 ) out << std::endl;
- }
-}
+#include
+#include
+#include
+
+#include "Bml_Parser.h"
+
+const char * strchr_limited( const char * in, const char * end, char c )
+{
+ while ( in < end && *in != c ) ++in;
+ if ( in < end ) return in;
+ else return 0;
+}
+
+Bml_Node Bml_Node::emptyNode;
+
+Bml_Node::Bml_Node()
+{
+ name = 0;
+ value = 0;
+}
+
+Bml_Node::Bml_Node(char const* name, size_t max_length)
+{
+ size_t length = 0;
+ char const* ptr = name;
+ while (*ptr && length < max_length) ++ptr, ++length;
+ this->name = new char[ length + 1 ];
+ memcpy( this->name, name, length );
+ this->name[ length ] = '\0';
+ value = 0;
+}
+
+Bml_Node::Bml_Node(const Bml_Node &in)
+{
+ size_t length;
+ name = 0;
+ if (in.name)
+ {
+ length = strlen(in.name);
+ name = new char[length + 1];
+ memcpy(name, in.name, length + 1);
+ }
+ value = 0;
+ if (in.value)
+ {
+ length = strlen(in.value);
+ value = new char[length + 1];
+ memcpy(value, in.value, length + 1);
+ }
+ children = in.children;
+}
+
+Bml_Node::~Bml_Node()
+{
+ delete [] name;
+ delete [] value;
+}
+
+void Bml_Node::clear()
+{
+ delete [] name;
+ delete [] value;
+
+ name = 0;
+ value = 0;
+ children.resize( 0 );
+}
+
+void Bml_Node::setLine(const char *line, size_t max_length)
+{
+ delete [] name;
+ delete [] value;
+
+ name = 0;
+ value = 0;
+
+ size_t length = 0;
+ const char * end = line;
+ while (*end && length < max_length) ++end;
+
+ const char * line_end = strchr_limited(line, end, '\n');
+ if ( !line_end ) line_end = end;
+
+ const char * first_letter = line;
+ while ( first_letter < line_end && *first_letter <= 0x20 ) first_letter++;
+
+ const char * colon = strchr_limited(first_letter, line_end, ':');
+ const char * last_letter = line_end - 1;
+
+ if (colon)
+ {
+ const char * first_value_letter = colon + 1;
+ while (first_value_letter < line_end && *first_value_letter <= 0x20) first_value_letter++;
+ last_letter = line_end - 1;
+ while (last_letter > first_value_letter && *last_letter <= 0x20) last_letter--;
+
+ value = new char[last_letter - first_value_letter + 2];
+ memcpy(value, first_value_letter, last_letter - first_value_letter + 1);
+ value[last_letter - first_value_letter + 1] = '\0';
+
+ last_letter = colon - 1;
+ }
+
+ while (last_letter > first_letter && *last_letter <= 0x20) last_letter--;
+
+ name = new char[last_letter - first_letter + 2];
+ memcpy(name, first_letter, last_letter - first_letter + 1);
+ name[last_letter - first_letter + 1] = '\0';
+}
+
+Bml_Node& Bml_Node::addChild(const Bml_Node &child)
+{
+ children.push_back(child);
+ return *(children.end() - 1);
+}
+
+const char * Bml_Node::getName() const
+{
+ return name;
+}
+
+const char * Bml_Node::getValue() const
+{
+ return value;
+}
+
+void Bml_Node::setValue(char const* value)
+{
+ delete [] this->value;
+ size_t length = strlen( value ) + 1;
+ this->value = new char[ length ];
+ memcpy( this->value, value, length );
+}
+
+size_t Bml_Node::getChildCount() const
+{
+ return children.size();
+}
+
+Bml_Node const& Bml_Node::getChild(size_t index) const
+{
+ return children[index];
+}
+
+Bml_Node & Bml_Node::walkToNode(const char *path, bool use_indexes)
+{
+ Bml_Node * next_node = nullptr;
+ Bml_Node * node = this;
+ while ( *path )
+ {
+ bool item_found = false;
+ size_t array_index = 0;
+ const char * array_index_start = strchr( path, '[' );
+ const char * next_separator = strchr( path, ':' );
+ if ( !next_separator ) next_separator = path + strlen(path);
+ if ( use_indexes && array_index_start && array_index_start < next_separator )
+ {
+ char * temp;
+ array_index = strtoul( array_index_start + 1, &temp, 10 );
+ }
+ else
+ {
+ array_index_start = next_separator;
+ }
+ if ( use_indexes )
+ {
+ for ( std::vector::iterator it = node->children.begin(); it != node->children.end(); ++it )
+ {
+ if ( array_index_start - path == strlen(it->name) &&
+ strncmp( it->name, path, array_index_start - path ) == 0 )
+ {
+ next_node = &(*it);
+ item_found = true;
+ if ( array_index == 0 ) break;
+ --array_index;
+ }
+ if (array_index)
+ item_found = false;
+ }
+ }
+ else
+ {
+ for ( std::vector::iterator it = node->children.end(); it != node->children.begin(); )
+ {
+ --it;
+ if ( next_separator - path == strlen(it->name) &&
+ strncmp( it->name, path, next_separator - path ) == 0 )
+ {
+ next_node = &(*it);
+ item_found = true;
+ break;
+ }
+ }
+ }
+ if ( !item_found )
+ {
+ Bml_Node child( path, next_separator - path );
+ node = &(node->addChild( child ));
+ }
+ else
+ node = next_node;
+ if ( *next_separator )
+ {
+ path = next_separator + 1;
+ }
+ else break;
+ }
+ return *node;
+}
+
+Bml_Node const& Bml_Node::walkToNode(const char *path) const
+{
+ Bml_Node const* next_node = nullptr;
+ Bml_Node const* node = this;
+ while ( *path )
+ {
+ bool item_found = false;
+ size_t array_index = ~0;
+ const char * array_index_start = strchr( path, '[' );
+ const char * next_separator = strchr( path, ':' );
+ if ( !next_separator ) next_separator = path + strlen(path);
+ if ( array_index_start && array_index_start < next_separator )
+ {
+ char * temp;
+ array_index = strtoul( array_index_start + 1, &temp, 10 );
+ }
+ else
+ {
+ array_index_start = next_separator;
+ }
+ for ( std::vector::const_iterator it = node->children.begin(), ite = node->children.end(); it != ite; ++it )
+ {
+ if ( array_index_start - path == strlen(it->name) &&
+ strncmp( it->name, path, array_index_start - path ) == 0 )
+ {
+ next_node = &(*it);
+ item_found = true;
+ if ( array_index == 0 ) break;
+ --array_index;
+ }
+ }
+ if ( !item_found ) return emptyNode;
+ node = next_node;
+ if ( *next_separator )
+ {
+ path = next_separator + 1;
+ }
+ else break;
+ }
+ return *node;
+}
+
+void Bml_Parser::parseDocument( const char * source, size_t max_length )
+{
+ std::vector indents;
+ std::string last_name;
+ std::string current_path;
+
+ document.clear();
+
+ size_t last_indent = ~0;
+
+ Bml_Node node;
+
+ size_t length = 0;
+ const char * end = source;
+ while ( *end && length < max_length ) ++end, ++length;
+
+ while ( source < end )
+ {
+ const char * line_end = strchr_limited( source, end, '\n' );
+ if ( !line_end ) line_end = end;
+
+ if ( node.getName() ) last_name = node.getName();
+
+ node.setLine( source, line_end - source );
+
+ size_t indent = 0;
+ while ( source < line_end && *source <= 0x20 )
+ {
+ source++;
+ indent++;
+ }
+
+ if ( last_indent == ~0 ) last_indent = indent;
+
+ if ( indent > last_indent )
+ {
+ indents.push_back( last_indent );
+ last_indent = indent;
+ if ( current_path.length() ) current_path += ":";
+ current_path += last_name;
+ }
+ else if ( indent < last_indent )
+ {
+ while ( last_indent > indent && indents.size() )
+ {
+ last_indent = *(indents.end() - 1);
+ indents.pop_back();
+ size_t colon = current_path.find_last_of( ':' );
+ if ( colon != std::string::npos ) current_path.resize( colon );
+ else current_path.resize( 0 );
+ }
+ last_indent = indent;
+ }
+
+ document.walkToNode( current_path.c_str() ).addChild( node );
+
+ source = line_end;
+ while ( *source && *source == '\n' ) source++;
+ }
+}
+
+const char * Bml_Parser::enumValue(std::string const& path) const
+{
+ return document.walkToNode(path.c_str()).getValue();
+}
+
+void Bml_Parser::setValue(std::string const& path, const char *value)
+{
+ document.walkToNode(path.c_str(), true).setValue(value);
+}
+
+void Bml_Parser::setValue(std::string const& path, long value)
+{
+ std::ostringstream str;
+ str << value;
+ setValue( path, str.str().c_str() );
+}
+
+void Bml_Parser::serialize(std::string & out) const
+{
+ std::ostringstream strOut;
+ serialize(strOut, &document, 0);
+ out = strOut.str();
+}
+
+void Bml_Parser::serialize(std::ostringstream & out, Bml_Node const* node, unsigned int indent) const
+{
+ for (unsigned i = 1; i < indent; ++i) out << " ";
+
+ if ( indent )
+ {
+ out << node->getName();
+ if (node->getValue() && strlen(node->getValue())) out << ":" << node->getValue();
+ out << std::endl;
+ }
+
+ for (unsigned i = 0, j = node->getChildCount(); i < j; ++i)
+ {
+ Bml_Node const& child = node->getChild(i);
+ if ( (!child.getValue() || !strlen(child.getValue())) && !child.getChildCount() )
+ continue;
+ serialize( out, &child, indent + 1 );
+ if ( indent == 0 ) out << std::endl;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Bml_Parser.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Bml_Parser.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Bml_Parser.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Bml_Parser.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,61 +1,61 @@
-#ifndef BML_PARSER_H
-#define BML_PARSER_H
-
-#include
-#include
-#include
-
-class Bml_Node
-{
- char * name;
- char * value;
-
- std::vector children;
-
- static Bml_Node emptyNode;
-
-public:
- Bml_Node();
- Bml_Node(char const* name, size_t max_length = ~0UL);
- Bml_Node(Bml_Node const& in);
-
- ~Bml_Node();
-
- void clear();
-
- void setLine(const char * line, size_t max_length = ~0UL);
- Bml_Node& addChild(Bml_Node const& child);
-
- const char * getName() const;
- const char * getValue() const;
-
- void setValue(char const* value);
-
- size_t getChildCount() const;
- Bml_Node const& getChild(size_t index) const;
-
- Bml_Node & walkToNode( const char * path, bool use_indexes = false );
- Bml_Node const& walkToNode( const char * path ) const;
-};
-
-class Bml_Parser
-{
- Bml_Node document;
-
-public:
- Bml_Parser() { }
-
- void parseDocument(const char * document, size_t max_length = ~0UL);
-
- const char * enumValue(std::string const& path) const;
-
- void setValue(std::string const& path, long value);
- void setValue(std::string const& path, const char * value);
-
- void serialize(std::string & out) const;
-
-private:
- void serialize(std::ostringstream & out, Bml_Node const* node, unsigned int indent) const;
-};
-
-#endif // BML_PARSER_H
+#ifndef BML_PARSER_H
+#define BML_PARSER_H
+
+#include
+#include
+#include
+
+class Bml_Node
+{
+ char * name;
+ char * value;
+
+ std::vector children;
+
+ static Bml_Node emptyNode;
+
+public:
+ Bml_Node();
+ Bml_Node(char const* name, size_t max_length = ~0UL);
+ Bml_Node(Bml_Node const& in);
+
+ ~Bml_Node();
+
+ void clear();
+
+ void setLine(const char * line, size_t max_length = ~0UL);
+ Bml_Node& addChild(Bml_Node const& child);
+
+ const char * getName() const;
+ const char * getValue() const;
+
+ void setValue(char const* value);
+
+ size_t getChildCount() const;
+ Bml_Node const& getChild(size_t index) const;
+
+ Bml_Node & walkToNode( const char * path, bool use_indexes = false );
+ Bml_Node const& walkToNode( const char * path ) const;
+};
+
+class Bml_Parser
+{
+ Bml_Node document;
+
+public:
+ Bml_Parser() { }
+
+ void parseDocument(const char * document, size_t max_length = ~0UL);
+
+ const char * enumValue(std::string const& path) const;
+
+ void setValue(std::string const& path, long value);
+ void setValue(std::string const& path, const char * value);
+
+ void serialize(std::string & out) const;
+
+private:
+ void serialize(std::ostringstream & out, Bml_Node const* node, unsigned int indent) const;
+};
+
+#endif // BML_PARSER_H
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/c140.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/c140.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/c140.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/c140.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,621 +1,621 @@
-/*
-C140.c
-
-Simulator based on AMUSE sources.
-The C140 sound chip is used by Namco System 2 and System 21
-The 219 ASIC (which incorporates a modified C140) is used by Namco NA-1 and NA-2
-This chip controls 24 channels (C140) or 16 (219) of PCM.
-16 bytes are associated with each channel.
-Channels can be 8 bit signed PCM, or 12 bit signed PCM.
-
-Timer behavior is not yet handled.
-
-Unmapped registers:
- 0x1f8:timer interval? (Nx0.1 ms)
- 0x1fa:irq ack? timer restart?
- 0x1fe:timer switch?(0:off 1:on)
-
---------------
-
- ASIC "219" notes
-
- On the 219 ASIC used on NA-1 and NA-2, the high registers have the following
- meaning instead:
- 0x1f7: bank for voices 0-3
- 0x1f1: bank for voices 4-7
- 0x1f3: bank for voices 8-11
- 0x1f5: bank for voices 12-15
-
- Some games (bkrtmaq, xday2) write to 0x1fd for voices 12-15 instead. Probably the bank registers
- mirror at 1f8, in which case 1ff is also 0-3, 1f9 is also 4-7, 1fb is also 8-11, and 1fd is also 12-15.
-
- Each bank is 0x20000 (128k), and the voice addresses on the 219 are all multiplied by 2.
- Additionally, the 219's base pitch is the same as the C352's (42667). But these changes
- are IMO not sufficient to make this a separate file - all the other registers are
- fully compatible.
-
- Finally, the 219 only has 16 voices.
-*/
-/*
- 2000.06.26 CAB fixed compressed pcm playback
- 2002.07.20 R.Belmont added support for multiple banking types
- 2006.01.08 R.Belmont added support for NA-1/2 "219" derivative
-*/
-
-
-//#include "emu.h"
-#include
-#include
-#include "c140.h"
-
-#undef NULL
-#define NULL ((void *)0)
-
-#define MAX_VOICE 24
-
-struct voice_registers
-{
- UINT8 volume_right;
- UINT8 volume_left;
- UINT8 frequency_msb;
- UINT8 frequency_lsb;
- UINT8 bank;
- UINT8 mode;
- UINT8 start_msb;
- UINT8 start_lsb;
- UINT8 end_msb;
- UINT8 end_lsb;
- UINT8 loop_msb;
- UINT8 loop_lsb;
- UINT8 reserved[4];
-};
-
-typedef struct
-{
- long ptoffset;
- long pos;
- long key;
- //--work
- long lastdt;
- long prevdt;
- long dltdt;
- //--reg
- long rvol;
- long lvol;
- long frequency;
- long bank;
- long mode;
-
- long sample_start;
- long sample_end;
- long sample_loop;
- UINT8 Muted;
-} VOICE;
-
-typedef struct _c140_state c140_state;
-struct _c140_state
-{
- int sample_rate;
- //sound_stream *stream;
- int banking_type;
- /* internal buffers */
- INT16 *mixer_buffer_left;
- INT16 *mixer_buffer_right;
-
- int baserate;
- UINT32 pRomSize;
- void *pRom;
- UINT8 REG[0x200];
-
- INT16 pcmtbl[8]; //2000.06.26 CAB
-
- VOICE voi[MAX_VOICE];
-};
-
-/*INLINE c140_state *get_safe_token(device_t *device)
-{
- assert(device != NULL);
- assert(device->type() == C140);
- return (c140_state *)downcast(device)->token();
-}*/
-
-
-static void init_voice( VOICE *v )
-{
- v->key=0;
- v->ptoffset=0;
- v->rvol=0;
- v->lvol=0;
- v->frequency=0;
- v->bank=0;
- v->mode=0;
- v->sample_start=0;
- v->sample_end=0;
- v->sample_loop=0;
-}
-//READ8_DEVICE_HANDLER( c140_r )
-UINT8 c140_r(void *chip, offs_t offset)
-{
- //c140_state *info = get_safe_token(device);
- c140_state *info = (c140_state *) chip;
- offset&=0x1ff;
- return info->REG[offset];
-}
-
-/*
- find_sample: compute the actual address of a sample given it's
- address and banking registers, as well as the board type.
-
- I suspect in "real life" this works like the Sega MultiPCM where the banking
- is done by a small PAL or GAL external to the sound chip, which can be switched
- per-game or at least per-PCB revision as addressing range needs grow.
- */
-static long find_sample(c140_state *info, long adrs, long bank, int voice)
-{
- long newadr = 0;
-
- static const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };
-
- adrs=(bank<<16)+adrs;
-
- switch (info->banking_type)
- {
- case C140_TYPE_SYSTEM2:
- // System 2 banking
- newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff);
- break;
-
- case C140_TYPE_SYSTEM21_A:
- // System 21 type A (simple) banking.
- // similar to System 2's.
- newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);
- break;
-
- case C140_TYPE_SYSTEM21_B:
- // System 21 type B (chip select) banking
-
- // get base address of sample inside the bank
- newadr = ((adrs&0x100000)>>2) + (adrs&0x3ffff);
-
- // now add the starting bank offsets based on the 2
- // chip select bits.
- // 0x40000 picks individual 512k ROMs
- if (adrs & 0x40000)
- {
- newadr += 0x80000;
- }
-
- // and 0x200000 which group of chips...
- if (adrs & 0x200000)
- {
- newadr += 0x100000;
- }
- break;
-
- case C140_TYPE_ASIC219:
- // ASIC219's banking is fairly simple
- newadr = ((info->REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs;
- break;
- }
-
- return (newadr);
-}
-//WRITE8_DEVICE_HANDLER( c140_w )
-void c140_w(void *chip, offs_t offset, UINT8 data)
-{
- //c140_state *info = get_safe_token(device);
- c140_state *info = (c140_state *) chip;
- //info->stream->update();
-
- offset&=0x1ff;
-
- // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)
- if ((offset >= 0x1f8) && (info->banking_type == C140_TYPE_ASIC219))
- {
- offset -= 8;
- }
-
- info->REG[offset]=data;
- if( offset<0x180 )
- {
- VOICE *v = &info->voi[offset>>4];
-
- if( (offset&0xf)==0x5 )
- {
- if( data&0x80 )
- {
- const struct voice_registers *vreg = (struct voice_registers *) &info->REG[offset&0x1f0];
- v->key=1;
- v->ptoffset=0;
- v->pos=0;
- v->lastdt=0;
- v->prevdt=0;
- v->dltdt=0;
- v->bank = vreg->bank;
- v->mode = data;
-
- // on the 219 asic, addresses are in words
- if (info->banking_type == C140_TYPE_ASIC219)
- {
- v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2;
- v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2;
- v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2;
-
- #if 0
- logerror("219: play v %d mode %02x start %x loop %x end %x\n",
- offset>>4, v->mode,
- find_sample(info, v->sample_start, v->bank, offset>>4),
- find_sample(info, v->sample_loop, v->bank, offset>>4),
- find_sample(info, v->sample_end, v->bank, offset>>4));
- #endif
- }
- else
- {
- v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb;
- v->sample_start = vreg->start_msb*256 + vreg->start_lsb;
- v->sample_end = vreg->end_msb*256 + vreg->end_lsb;
- }
- }
- else
- {
- v->key=0;
- }
- }
- }
-}
-
-//void c140_set_base(device_t *device, void *base)
-void c140_set_base(void *chip, void *base)
-{
- //c140_state *info = get_safe_token(device);
- c140_state *info = (c140_state *) chip;
- info->pRom = base;
-}
-
-/*INLINE int limit(INT32 in)
-{
- if(in>0x7fff) return 0x7fff;
- else if(in<-0x8000) return -0x8000;
- return in;
-}*/
-
-//static STREAM_UPDATE( update_stereo )
-void c140_update(void *chip, stream_sample_t **outputs, int samples)
-{
- //c140_state *info = (c140_state *)param;
- c140_state *info = (c140_state *) chip;
- int i,j;
-
- INT32 rvol,lvol;
- INT32 dt;
- INT32 sdt;
- INT32 st,ed,sz;
-
- INT8 *pSampleData;
- INT32 frequency,delta,offset,pos;
- INT32 cnt, voicecnt;
- INT32 lastdt,prevdt,dltdt;
- float pbase=(float)info->baserate*2.0f / (float)info->sample_rate;
-
- INT16 *lmix, *rmix;
-
- if(samples>info->sample_rate) samples=info->sample_rate;
-
- /* zap the contents of the mixer buffer */
- memset(info->mixer_buffer_left, 0, samples * sizeof(INT16));
- memset(info->mixer_buffer_right, 0, samples * sizeof(INT16));
- if (info->pRom == NULL)
- return;
-
- /* get the number of voices to update */
- voicecnt = (info->banking_type == C140_TYPE_ASIC219) ? 16 : 24;
-
- //--- audio update
- for( i=0;ivoi[i];
- const struct voice_registers *vreg = (struct voice_registers *)&info->REG[i*16];
-
- if( v->key && ! v->Muted)
- {
- frequency= vreg->frequency_msb*256 + vreg->frequency_lsb;
-
- /* Abort voice if no frequency value set */
- if(frequency==0) continue;
-
- /* Delta = frequency * ((8MHz/374)*2 / sample rate) */
- delta=(long)((float)frequency * pbase);
-
- /* Calculate left/right channel volumes */
- lvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch
- rvol=(vreg->volume_right*32)/MAX_VOICE;
-
- /* Set mixer outputs base pointers */
- lmix = info->mixer_buffer_left;
- rmix = info->mixer_buffer_right;
-
- /* Retrieve sample start/end and calculate size */
- st=v->sample_start;
- ed=v->sample_end;
- sz=ed-st;
-
- /* Retrieve base pointer to the sample data */
- //pSampleData=(signed char*)((FPTR)info->pRom + find_sample(info, st, v->bank, i));
- pSampleData = (INT8*)info->pRom + find_sample(info, st, v->bank, i);
-
- /* Fetch back previous data pointers */
- offset=v->ptoffset;
- pos=v->pos;
- lastdt=v->lastdt;
- prevdt=v->prevdt;
- dltdt=v->dltdt;
-
- /* Switch on data type - compressed PCM is only for C140 */
- if ((v->mode&8) && (info->banking_type != C140_TYPE_ASIC219))
- {
- //compressed PCM (maybe correct...)
- /* Loop for enough to fill sample buffer as requested */
- for(j=0;j>16)&0x7fff;
- offset &= 0xffff;
- pos+=cnt;
- //for(;cnt>0;cnt--)
- {
- /* Check for the end of the sample */
- if(pos >= sz)
- {
- /* Check if its a looping sample, either stop or loop */
- if(v->mode&0x10)
- {
- pos = (v->sample_loop - st);
- }
- else
- {
- v->key=0;
- break;
- }
- }
-
- /* Read the chosen sample byte */
- dt=pSampleData[pos];
-
- /* decompress to 13bit range */ //2000.06.26 CAB
- sdt=dt>>3; //signed
- if(sdt<0) sdt = (sdt<<(dt&7)) - info->pcmtbl[dt&7];
- else sdt = (sdt<<(dt&7)) + info->pcmtbl[dt&7];
-
- prevdt=lastdt;
- lastdt=sdt;
- dltdt=(lastdt - prevdt);
- }
-
- /* Caclulate the sample value */
- dt=((dltdt*offset)>>16)+prevdt;
-
- /* Write the data to the sample buffers */
- *lmix++ +=(dt*lvol)>>(5+5);
- *rmix++ +=(dt*rvol)>>(5+5);
- }
- }
- else
- {
- /* linear 8bit signed PCM */
- for(j=0;j>16)&0x7fff;
- offset &= 0xffff;
- pos += cnt;
- /* Check for the end of the sample */
- if(pos >= sz)
- {
- /* Check if its a looping sample, either stop or loop */
- if( v->mode&0x10 )
- {
- pos = (v->sample_loop - st);
- }
- else
- {
- v->key=0;
- break;
- }
- }
-
- if( cnt )
- {
- prevdt=lastdt;
-
- if (info->banking_type == C140_TYPE_ASIC219)
- {
- //lastdt = pSampleData[BYTE_XOR_BE(pos)];
- lastdt = pSampleData[pos ^ 0x01];
-
- // Sign + magnitude format
- if ((v->mode & 0x01) && (lastdt & 0x80))
- lastdt = -(lastdt & 0x7f);
-
- // Sign flip
- if (v->mode & 0x40)
- lastdt = -lastdt;
- }
- else
- {
- lastdt=pSampleData[pos];
- }
-
- dltdt = (lastdt - prevdt);
- }
-
- /* Caclulate the sample value */
- dt=((dltdt*offset)>>16)+prevdt;
-
- /* Write the data to the sample buffers */
- *lmix++ +=(dt*lvol)>>5;
- *rmix++ +=(dt*rvol)>>5;
- }
- }
-
- /* Save positional data for next callback */
- v->ptoffset=offset;
- v->pos=pos;
- v->lastdt=lastdt;
- v->prevdt=prevdt;
- v->dltdt=dltdt;
- }
- }
-
- /* render to MAME's stream buffer */
- lmix = info->mixer_buffer_left;
- rmix = info->mixer_buffer_right;
- {
- stream_sample_t *dest1 = outputs[0];
- stream_sample_t *dest2 = outputs[1];
- for (i = 0; i < samples; i++)
- {
- //*dest1++ = limit(8*(*lmix++));
- //*dest2++ = limit(8*(*rmix++));
- *dest1++ = 8 * (*lmix ++);
- *dest2++ = 8 * (*rmix ++);
- }
- }
-}
-
-//static DEVICE_START( c140 )
-void * device_start_c140(int sample_rate, int clock, int banking_type)
-{
- //const c140_interface *intf = (const c140_interface *)device->static_config();
- //c140_state *info = get_safe_token(device);
- c140_state *info;
- int i;
-
- info = (c140_state *) malloc(sizeof(c140_state));
- if (!info) return info;
-
- //info->sample_rate=info->baserate=device->clock();
- info->sample_rate = sample_rate;
- info->baserate = clock;
-
- //info->banking_type = intf->banking_type;
- info->banking_type = banking_type;
-
- //info->stream = device->machine().sound().stream_alloc(*device,0,2,info->sample_rate,info,update_stereo);
-
- //info->pRom=*device->region();
- info->pRomSize = 0x00;
- info->pRom = NULL;
-
- /* make decompress pcm table */ //2000.06.26 CAB
- {
- INT32 segbase=0;
- for(i=0;i<8;i++)
- {
- info->pcmtbl[i]=segbase; //segment base value
- segbase += 16<REG,0,sizeof(info->REG));
- {
- int i;
- for(i=0;ivoi[i] );
- }*/
-
- /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
- //info->mixer_buffer_left = auto_alloc_array(device->machine(), INT16, 2 * info->sample_rate);
- info->mixer_buffer_left = (INT16*)malloc(sizeof(INT16) * 2 * info->sample_rate);
- info->mixer_buffer_right = info->mixer_buffer_left + info->sample_rate;
-
- for (i = 0; i < MAX_VOICE; i ++)
- info->voi[i].Muted = 0x00;
-
- return info;
-}
-
-void device_stop_c140(void *chip)
-{
- c140_state *info = (c140_state *) chip;
-
- free(info->pRom); info->pRom = NULL;
- free(info->mixer_buffer_left);
- free(info);
-}
-
-void device_reset_c140(void *chip)
-{
- c140_state *info = (c140_state *) chip;
- int i;
-
- memset(info->REG, 0, sizeof(info->REG));
-
- for(i = 0; i < MAX_VOICE; i ++)
- init_voice( &info->voi[i] );
-
- return;
-}
-
-void c140_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
- const UINT8* ROMData)
-{
- c140_state *info = (c140_state *) chip;
-
- if (info->pRomSize != ROMSize)
- {
- info->pRom = (UINT8*)realloc(info->pRom, ROMSize);
- info->pRomSize = ROMSize;
- memset(info->pRom, 0xFF, ROMSize);
- }
- if (DataStart > ROMSize)
- return;
- if (DataStart + DataLength > ROMSize)
- DataLength = ROMSize - DataStart;
-
- memcpy((INT8*)info->pRom + DataStart, ROMData, DataLength);
-
- return;
-}
-
-
-void c140_set_mute_mask(void *chip, UINT32 MuteMask)
-{
- c140_state *info = (c140_state *) chip;
- UINT8 CurChn;
-
- for (CurChn = 0; CurChn < MAX_VOICE; CurChn ++)
- info->voi[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
-
- return;
-}
-
-
-
-
-/**************************************************************************
- * Generic get_info
- **************************************************************************/
-
-/*DEVICE_GET_INFO( c140 )
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers --- //
- case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(c140_state); break;
-
- // --- the following bits of info are returned as pointers to data or functions --- //
- case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( c140 ); break;
- case DEVINFO_FCT_STOP: // nothing // break;
- case DEVINFO_FCT_RESET: // nothing // break;
-
- // --- the following bits of info are returned as NULL-terminated strings --- //
- case DEVINFO_STR_NAME: strcpy(info->s, "C140"); break;
- case DEVINFO_STR_FAMILY: strcpy(info->s, "Namco PCM"); break;
- case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
- case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
- case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
- }
-}
-
-
-DEFINE_LEGACY_SOUND_DEVICE(C140, c140);*/
+/*
+C140.c
+
+Simulator based on AMUSE sources.
+The C140 sound chip is used by Namco System 2 and System 21
+The 219 ASIC (which incorporates a modified C140) is used by Namco NA-1 and NA-2
+This chip controls 24 channels (C140) or 16 (219) of PCM.
+16 bytes are associated with each channel.
+Channels can be 8 bit signed PCM, or 12 bit signed PCM.
+
+Timer behavior is not yet handled.
+
+Unmapped registers:
+ 0x1f8:timer interval? (Nx0.1 ms)
+ 0x1fa:irq ack? timer restart?
+ 0x1fe:timer switch?(0:off 1:on)
+
+--------------
+
+ ASIC "219" notes
+
+ On the 219 ASIC used on NA-1 and NA-2, the high registers have the following
+ meaning instead:
+ 0x1f7: bank for voices 0-3
+ 0x1f1: bank for voices 4-7
+ 0x1f3: bank for voices 8-11
+ 0x1f5: bank for voices 12-15
+
+ Some games (bkrtmaq, xday2) write to 0x1fd for voices 12-15 instead. Probably the bank registers
+ mirror at 1f8, in which case 1ff is also 0-3, 1f9 is also 4-7, 1fb is also 8-11, and 1fd is also 12-15.
+
+ Each bank is 0x20000 (128k), and the voice addresses on the 219 are all multiplied by 2.
+ Additionally, the 219's base pitch is the same as the C352's (42667). But these changes
+ are IMO not sufficient to make this a separate file - all the other registers are
+ fully compatible.
+
+ Finally, the 219 only has 16 voices.
+*/
+/*
+ 2000.06.26 CAB fixed compressed pcm playback
+ 2002.07.20 R.Belmont added support for multiple banking types
+ 2006.01.08 R.Belmont added support for NA-1/2 "219" derivative
+*/
+
+
+//#include "emu.h"
+#include
+#include
+#include "c140.h"
+
+#undef NULL
+#define NULL ((void *)0)
+
+#define MAX_VOICE 24
+
+struct voice_registers
+{
+ UINT8 volume_right;
+ UINT8 volume_left;
+ UINT8 frequency_msb;
+ UINT8 frequency_lsb;
+ UINT8 bank;
+ UINT8 mode;
+ UINT8 start_msb;
+ UINT8 start_lsb;
+ UINT8 end_msb;
+ UINT8 end_lsb;
+ UINT8 loop_msb;
+ UINT8 loop_lsb;
+ UINT8 reserved[4];
+};
+
+typedef struct
+{
+ long ptoffset;
+ long pos;
+ long key;
+ //--work
+ long lastdt;
+ long prevdt;
+ long dltdt;
+ //--reg
+ long rvol;
+ long lvol;
+ long frequency;
+ long bank;
+ long mode;
+
+ long sample_start;
+ long sample_end;
+ long sample_loop;
+ UINT8 Muted;
+} VOICE;
+
+typedef struct _c140_state c140_state;
+struct _c140_state
+{
+ int sample_rate;
+ //sound_stream *stream;
+ int banking_type;
+ /* internal buffers */
+ INT16 *mixer_buffer_left;
+ INT16 *mixer_buffer_right;
+
+ int baserate;
+ UINT32 pRomSize;
+ void *pRom;
+ UINT8 REG[0x200];
+
+ INT16 pcmtbl[8]; //2000.06.26 CAB
+
+ VOICE voi[MAX_VOICE];
+};
+
+/*INLINE c140_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == C140);
+ return (c140_state *)downcast(device)->token();
+}*/
+
+
+static void init_voice( VOICE *v )
+{
+ v->key=0;
+ v->ptoffset=0;
+ v->rvol=0;
+ v->lvol=0;
+ v->frequency=0;
+ v->bank=0;
+ v->mode=0;
+ v->sample_start=0;
+ v->sample_end=0;
+ v->sample_loop=0;
+}
+//READ8_DEVICE_HANDLER( c140_r )
+UINT8 c140_r(void *chip, offs_t offset)
+{
+ //c140_state *info = get_safe_token(device);
+ c140_state *info = (c140_state *) chip;
+ offset&=0x1ff;
+ return info->REG[offset];
+}
+
+/*
+ find_sample: compute the actual address of a sample given it's
+ address and banking registers, as well as the board type.
+
+ I suspect in "real life" this works like the Sega MultiPCM where the banking
+ is done by a small PAL or GAL external to the sound chip, which can be switched
+ per-game or at least per-PCB revision as addressing range needs grow.
+ */
+static long find_sample(c140_state *info, long adrs, long bank, int voice)
+{
+ long newadr = 0;
+
+ static const INT16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };
+
+ adrs=(bank<<16)+adrs;
+
+ switch (info->banking_type)
+ {
+ case C140_TYPE_SYSTEM2:
+ // System 2 banking
+ newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff);
+ break;
+
+ case C140_TYPE_SYSTEM21_A:
+ // System 21 type A (simple) banking.
+ // similar to System 2's.
+ newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);
+ break;
+
+ case C140_TYPE_SYSTEM21_B:
+ // System 21 type B (chip select) banking
+
+ // get base address of sample inside the bank
+ newadr = ((adrs&0x100000)>>2) + (adrs&0x3ffff);
+
+ // now add the starting bank offsets based on the 2
+ // chip select bits.
+ // 0x40000 picks individual 512k ROMs
+ if (adrs & 0x40000)
+ {
+ newadr += 0x80000;
+ }
+
+ // and 0x200000 which group of chips...
+ if (adrs & 0x200000)
+ {
+ newadr += 0x100000;
+ }
+ break;
+
+ case C140_TYPE_ASIC219:
+ // ASIC219's banking is fairly simple
+ newadr = ((info->REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs;
+ break;
+ }
+
+ return (newadr);
+}
+//WRITE8_DEVICE_HANDLER( c140_w )
+void c140_w(void *chip, offs_t offset, UINT8 data)
+{
+ //c140_state *info = get_safe_token(device);
+ c140_state *info = (c140_state *) chip;
+ //info->stream->update();
+
+ offset&=0x1ff;
+
+ // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)
+ if ((offset >= 0x1f8) && (info->banking_type == C140_TYPE_ASIC219))
+ {
+ offset -= 8;
+ }
+
+ info->REG[offset]=data;
+ if( offset<0x180 )
+ {
+ VOICE *v = &info->voi[offset>>4];
+
+ if( (offset&0xf)==0x5 )
+ {
+ if( data&0x80 )
+ {
+ const struct voice_registers *vreg = (struct voice_registers *) &info->REG[offset&0x1f0];
+ v->key=1;
+ v->ptoffset=0;
+ v->pos=0;
+ v->lastdt=0;
+ v->prevdt=0;
+ v->dltdt=0;
+ v->bank = vreg->bank;
+ v->mode = data;
+
+ // on the 219 asic, addresses are in words
+ if (info->banking_type == C140_TYPE_ASIC219)
+ {
+ v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2;
+ v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2;
+ v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2;
+
+ #if 0
+ logerror("219: play v %d mode %02x start %x loop %x end %x\n",
+ offset>>4, v->mode,
+ find_sample(info, v->sample_start, v->bank, offset>>4),
+ find_sample(info, v->sample_loop, v->bank, offset>>4),
+ find_sample(info, v->sample_end, v->bank, offset>>4));
+ #endif
+ }
+ else
+ {
+ v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb;
+ v->sample_start = vreg->start_msb*256 + vreg->start_lsb;
+ v->sample_end = vreg->end_msb*256 + vreg->end_lsb;
+ }
+ }
+ else
+ {
+ v->key=0;
+ }
+ }
+ }
+}
+
+//void c140_set_base(device_t *device, void *base)
+void c140_set_base(void *chip, void *base)
+{
+ //c140_state *info = get_safe_token(device);
+ c140_state *info = (c140_state *) chip;
+ info->pRom = base;
+}
+
+/*INLINE int limit(INT32 in)
+{
+ if(in>0x7fff) return 0x7fff;
+ else if(in<-0x8000) return -0x8000;
+ return in;
+}*/
+
+//static STREAM_UPDATE( update_stereo )
+void c140_update(void *chip, stream_sample_t **outputs, int samples)
+{
+ //c140_state *info = (c140_state *)param;
+ c140_state *info = (c140_state *) chip;
+ int i,j;
+
+ INT32 rvol,lvol;
+ INT32 dt;
+ INT32 sdt;
+ INT32 st,ed,sz;
+
+ INT8 *pSampleData;
+ INT32 frequency,delta,offset,pos;
+ INT32 cnt, voicecnt;
+ INT32 lastdt,prevdt,dltdt;
+ float pbase=(float)info->baserate*2.0f / (float)info->sample_rate;
+
+ INT16 *lmix, *rmix;
+
+ if(samples>info->sample_rate) samples=info->sample_rate;
+
+ /* zap the contents of the mixer buffer */
+ memset(info->mixer_buffer_left, 0, samples * sizeof(INT16));
+ memset(info->mixer_buffer_right, 0, samples * sizeof(INT16));
+ if (info->pRom == NULL)
+ return;
+
+ /* get the number of voices to update */
+ voicecnt = (info->banking_type == C140_TYPE_ASIC219) ? 16 : 24;
+
+ //--- audio update
+ for( i=0;ivoi[i];
+ const struct voice_registers *vreg = (struct voice_registers *)&info->REG[i*16];
+
+ if( v->key && ! v->Muted)
+ {
+ frequency= vreg->frequency_msb*256 + vreg->frequency_lsb;
+
+ /* Abort voice if no frequency value set */
+ if(frequency==0) continue;
+
+ /* Delta = frequency * ((8MHz/374)*2 / sample rate) */
+ delta=(long)((float)frequency * pbase);
+
+ /* Calculate left/right channel volumes */
+ lvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch
+ rvol=(vreg->volume_right*32)/MAX_VOICE;
+
+ /* Set mixer outputs base pointers */
+ lmix = info->mixer_buffer_left;
+ rmix = info->mixer_buffer_right;
+
+ /* Retrieve sample start/end and calculate size */
+ st=v->sample_start;
+ ed=v->sample_end;
+ sz=ed-st;
+
+ /* Retrieve base pointer to the sample data */
+ //pSampleData=(signed char*)((FPTR)info->pRom + find_sample(info, st, v->bank, i));
+ pSampleData = (INT8*)info->pRom + find_sample(info, st, v->bank, i);
+
+ /* Fetch back previous data pointers */
+ offset=v->ptoffset;
+ pos=v->pos;
+ lastdt=v->lastdt;
+ prevdt=v->prevdt;
+ dltdt=v->dltdt;
+
+ /* Switch on data type - compressed PCM is only for C140 */
+ if ((v->mode&8) && (info->banking_type != C140_TYPE_ASIC219))
+ {
+ //compressed PCM (maybe correct...)
+ /* Loop for enough to fill sample buffer as requested */
+ for(j=0;j>16)&0x7fff;
+ offset &= 0xffff;
+ pos+=cnt;
+ //for(;cnt>0;cnt--)
+ {
+ /* Check for the end of the sample */
+ if(pos >= sz)
+ {
+ /* Check if its a looping sample, either stop or loop */
+ if(v->mode&0x10)
+ {
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key=0;
+ break;
+ }
+ }
+
+ /* Read the chosen sample byte */
+ dt=pSampleData[pos];
+
+ /* decompress to 13bit range */ //2000.06.26 CAB
+ sdt=dt>>3; //signed
+ if(sdt<0) sdt = (sdt<<(dt&7)) - info->pcmtbl[dt&7];
+ else sdt = (sdt<<(dt&7)) + info->pcmtbl[dt&7];
+
+ prevdt=lastdt;
+ lastdt=sdt;
+ dltdt=(lastdt - prevdt);
+ }
+
+ /* Caclulate the sample value */
+ dt=((dltdt*offset)>>16)+prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ +=(dt*lvol)>>(5+5);
+ *rmix++ +=(dt*rvol)>>(5+5);
+ }
+ }
+ else
+ {
+ /* linear 8bit signed PCM */
+ for(j=0;j>16)&0x7fff;
+ offset &= 0xffff;
+ pos += cnt;
+ /* Check for the end of the sample */
+ if(pos >= sz)
+ {
+ /* Check if its a looping sample, either stop or loop */
+ if( v->mode&0x10 )
+ {
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key=0;
+ break;
+ }
+ }
+
+ if( cnt )
+ {
+ prevdt=lastdt;
+
+ if (info->banking_type == C140_TYPE_ASIC219)
+ {
+ //lastdt = pSampleData[BYTE_XOR_BE(pos)];
+ lastdt = pSampleData[pos ^ 0x01];
+
+ // Sign + magnitude format
+ if ((v->mode & 0x01) && (lastdt & 0x80))
+ lastdt = -(lastdt & 0x7f);
+
+ // Sign flip
+ if (v->mode & 0x40)
+ lastdt = -lastdt;
+ }
+ else
+ {
+ lastdt=pSampleData[pos];
+ }
+
+ dltdt = (lastdt - prevdt);
+ }
+
+ /* Caclulate the sample value */
+ dt=((dltdt*offset)>>16)+prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ +=(dt*lvol)>>5;
+ *rmix++ +=(dt*rvol)>>5;
+ }
+ }
+
+ /* Save positional data for next callback */
+ v->ptoffset=offset;
+ v->pos=pos;
+ v->lastdt=lastdt;
+ v->prevdt=prevdt;
+ v->dltdt=dltdt;
+ }
+ }
+
+ /* render to MAME's stream buffer */
+ lmix = info->mixer_buffer_left;
+ rmix = info->mixer_buffer_right;
+ {
+ stream_sample_t *dest1 = outputs[0];
+ stream_sample_t *dest2 = outputs[1];
+ for (i = 0; i < samples; i++)
+ {
+ //*dest1++ = limit(8*(*lmix++));
+ //*dest2++ = limit(8*(*rmix++));
+ *dest1++ = 8 * (*lmix ++);
+ *dest2++ = 8 * (*rmix ++);
+ }
+ }
+}
+
+//static DEVICE_START( c140 )
+void * device_start_c140(int sample_rate, int clock, int banking_type)
+{
+ //const c140_interface *intf = (const c140_interface *)device->static_config();
+ //c140_state *info = get_safe_token(device);
+ c140_state *info;
+ int i;
+
+ info = (c140_state *) malloc(sizeof(c140_state));
+ if (!info) return info;
+
+ //info->sample_rate=info->baserate=device->clock();
+ info->sample_rate = sample_rate;
+ info->baserate = clock;
+
+ //info->banking_type = intf->banking_type;
+ info->banking_type = banking_type;
+
+ //info->stream = device->machine().sound().stream_alloc(*device,0,2,info->sample_rate,info,update_stereo);
+
+ //info->pRom=*device->region();
+ info->pRomSize = 0x00;
+ info->pRom = NULL;
+
+ /* make decompress pcm table */ //2000.06.26 CAB
+ {
+ INT32 segbase=0;
+ for(i=0;i<8;i++)
+ {
+ info->pcmtbl[i]=segbase; //segment base value
+ segbase += 16<REG,0,sizeof(info->REG));
+ {
+ int i;
+ for(i=0;ivoi[i] );
+ }*/
+
+ /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
+ //info->mixer_buffer_left = auto_alloc_array(device->machine(), INT16, 2 * info->sample_rate);
+ info->mixer_buffer_left = (INT16*)malloc(sizeof(INT16) * 2 * info->sample_rate);
+ info->mixer_buffer_right = info->mixer_buffer_left + info->sample_rate;
+
+ for (i = 0; i < MAX_VOICE; i ++)
+ info->voi[i].Muted = 0x00;
+
+ return info;
+}
+
+void device_stop_c140(void *chip)
+{
+ c140_state *info = (c140_state *) chip;
+
+ free(info->pRom); info->pRom = NULL;
+ free(info->mixer_buffer_left);
+ free(info);
+}
+
+void device_reset_c140(void *chip)
+{
+ c140_state *info = (c140_state *) chip;
+ int i;
+
+ memset(info->REG, 0, sizeof(info->REG));
+
+ for(i = 0; i < MAX_VOICE; i ++)
+ init_voice( &info->voi[i] );
+
+ return;
+}
+
+void c140_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
+ const UINT8* ROMData)
+{
+ c140_state *info = (c140_state *) chip;
+
+ if (info->pRomSize != ROMSize)
+ {
+ info->pRom = (UINT8*)realloc(info->pRom, ROMSize);
+ info->pRomSize = ROMSize;
+ memset(info->pRom, 0xFF, ROMSize);
+ }
+ if (DataStart > ROMSize)
+ return;
+ if (DataStart + DataLength > ROMSize)
+ DataLength = ROMSize - DataStart;
+
+ memcpy((INT8*)info->pRom + DataStart, ROMData, DataLength);
+
+ return;
+}
+
+
+void c140_set_mute_mask(void *chip, UINT32 MuteMask)
+{
+ c140_state *info = (c140_state *) chip;
+ UINT8 CurChn;
+
+ for (CurChn = 0; CurChn < MAX_VOICE; CurChn ++)
+ info->voi[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
+
+ return;
+}
+
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+/*DEVICE_GET_INFO( c140 )
+{
+ switch (state)
+ {
+ // --- the following bits of info are returned as 64-bit signed integers --- //
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(c140_state); break;
+
+ // --- the following bits of info are returned as pointers to data or functions --- //
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( c140 ); break;
+ case DEVINFO_FCT_STOP: // nothing // break;
+ case DEVINFO_FCT_RESET: // nothing // break;
+
+ // --- the following bits of info are returned as NULL-terminated strings --- //
+ case DEVINFO_STR_NAME: strcpy(info->s, "C140"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Namco PCM"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+ }
+}
+
+
+DEFINE_LEGACY_SOUND_DEVICE(C140, c140);*/
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/C140_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/C140_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/C140_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/C140_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,77 +1,77 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "C140_Emu.h"
-#include "c140.h"
-
-C140_Emu::C140_Emu() { chip = 0; }
-
-C140_Emu::~C140_Emu()
-{
- if ( chip ) device_stop_c140( chip );
-}
-
-int C140_Emu::set_rate( int type, double sample_rate, double clock_rate )
-{
- if ( chip )
- {
- device_stop_c140( chip );
- chip = 0;
- }
-
- chip = device_start_c140( sample_rate, clock_rate, type );
- if ( !chip )
- return 1;
-
- reset();
- return 0;
-}
-
-void C140_Emu::reset()
-{
- device_reset_c140( chip );
- c140_set_mute_mask( chip, 0 );
-}
-
-void C140_Emu::write( int addr, int data )
-{
- c140_w( chip, addr, data );
-}
-
-void C140_Emu::write_rom( int size, int start, int length, void * data )
-{
- c140_write_rom( chip, size, start, length, (const UINT8 *) data );
-}
-
-void C140_Emu::mute_voices( int mask )
-{
- c140_set_mute_mask( chip, mask );
-}
-
-void C140_Emu::run( int pair_count, sample_t* out )
-{
- stream_sample_t bufL[ 1024 ];
- stream_sample_t bufR[ 1024 ];
- stream_sample_t * buffers[2] = { bufL, bufR };
-
- while (pair_count > 0)
- {
- int todo = pair_count;
- if (todo > 1024) todo = 1024;
- c140_update( chip, buffers, todo );
-
- for (int i = 0; i < todo; i++)
- {
- int output_l = bufL [i];
- int output_r = bufR [i];
- output_l += out [0];
- output_r += out [1];
- if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
- if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
- out [0] = output_l;
- out [1] = output_r;
- out += 2;
- }
-
- pair_count -= todo;
- }
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "C140_Emu.h"
+#include "c140.h"
+
+C140_Emu::C140_Emu() { chip = 0; }
+
+C140_Emu::~C140_Emu()
+{
+ if ( chip ) device_stop_c140( chip );
+}
+
+int C140_Emu::set_rate( int type, double sample_rate, double clock_rate )
+{
+ if ( chip )
+ {
+ device_stop_c140( chip );
+ chip = 0;
+ }
+
+ chip = device_start_c140( sample_rate, clock_rate, type );
+ if ( !chip )
+ return 1;
+
+ reset();
+ return 0;
+}
+
+void C140_Emu::reset()
+{
+ device_reset_c140( chip );
+ c140_set_mute_mask( chip, 0 );
+}
+
+void C140_Emu::write( int addr, int data )
+{
+ c140_w( chip, addr, data );
+}
+
+void C140_Emu::write_rom( int size, int start, int length, void * data )
+{
+ c140_write_rom( chip, size, start, length, (const UINT8 *) data );
+}
+
+void C140_Emu::mute_voices( int mask )
+{
+ c140_set_mute_mask( chip, mask );
+}
+
+void C140_Emu::run( int pair_count, sample_t* out )
+{
+ stream_sample_t bufL[ 1024 ];
+ stream_sample_t bufR[ 1024 ];
+ stream_sample_t * buffers[2] = { bufL, bufR };
+
+ while (pair_count > 0)
+ {
+ int todo = pair_count;
+ if (todo > 1024) todo = 1024;
+ c140_update( chip, buffers, todo );
+
+ for (int i = 0; i < todo; i++)
+ {
+ int output_l = bufL [i];
+ int output_r = bufR [i];
+ output_l += out [0];
+ output_r += out [1];
+ if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
+ if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
+ out [0] = output_l;
+ out [1] = output_r;
+ out += 2;
+ }
+
+ pair_count -= todo;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/C140_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/C140_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/C140_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/C140_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,36 +1,36 @@
-// C140 sound chip emulator interface
-
-// Game_Music_Emu $vers
-#ifndef C140_EMU_H
-#define C140_EMU_H
-
-class C140_Emu {
- void* chip;
-public:
- C140_Emu();
- ~C140_Emu();
-
- // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( int type, double sample_rate, double clock_rate );
-
- // Resets to power-up state
- void reset();
-
- // Mutes voice n if bit n (1 << n) of mask is set
- enum { channel_count = 24 };
- void mute_voices( int mask );
-
- // Writes data to addr
- void write( int addr, int data );
-
- // Scales ROM size, then writes length bytes from data at start offset
- void write_rom( int size, int start, int length, void * data );
-
- // Runs and writes pair_count*2 samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
+// C140 sound chip emulator interface
+
+// Game_Music_Emu $vers
+#ifndef C140_EMU_H
+#define C140_EMU_H
+
+class C140_Emu {
+ void* chip;
+public:
+ C140_Emu();
+ ~C140_Emu();
+
+ // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+ // if error.
+ int set_rate( int type, double sample_rate, double clock_rate );
+
+ // Resets to power-up state
+ void reset();
+
+ // Mutes voice n if bit n (1 << n) of mask is set
+ enum { channel_count = 24 };
+ void mute_voices( int mask );
+
+ // Writes data to addr
+ void write( int addr, int data );
+
+ // Scales ROM size, then writes length bytes from data at start offset
+ void write_rom( int size, int start, int length, void * data );
+
+ // Runs and writes pair_count*2 samples to output
+ typedef short sample_t;
+ enum { out_chan_count = 2 }; // stereo
+ void run( int pair_count, sample_t* out );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/c140.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/c140.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/c140.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/c140.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,58 +1,58 @@
-/* C140.h */
-
-#pragma once
-
-#ifndef __OSDCOMM_H__
-#define __OSDCOMM_H__
-typedef unsigned char UINT8; /* unsigned 8bit */
-typedef unsigned short UINT16; /* unsigned 16bit */
-typedef unsigned int UINT32; /* unsigned 32bit */
-typedef signed char INT8; /* signed 8bit */
-typedef signed short INT16; /* signed 16bit */
-typedef signed int INT32; /* signed 32bit */
-
-typedef INT32 stream_sample_t;
-typedef UINT32 offs_t;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void c140_update(void * chip, stream_sample_t **outputs, int samples);
-void * device_start_c140(int sample_rate, int clock, int banking_type);
-void device_stop_c140(void * chip);
-void device_reset_c140(void * chip);
-
-//READ8_DEVICE_HANDLER( c140_r );
-//WRITE8_DEVICE_HANDLER( c140_w );
-UINT8 c140_r(void * chip, offs_t offset);
-void c140_w(void * chip, offs_t offset, UINT8 data);
-
-//void c140_set_base(device_t *device, void *base);
-void c140_set_base(void *chip, void *base);
-
-enum
-{
- C140_TYPE_SYSTEM2,
- C140_TYPE_SYSTEM21_A,
- C140_TYPE_SYSTEM21_B,
- C140_TYPE_ASIC219
-};
-
-/*typedef struct _c140_interface c140_interface;
-struct _c140_interface {
- int banking_type;
-};*/
-
-
-void c140_write_rom(void * chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
- const UINT8* ROMData);
-
-void c140_set_mute_mask(void * chip, UINT32 MuteMask);
-
-#ifdef __cplusplus
-}
-#endif
-
-//DECLARE_LEGACY_SOUND_DEVICE(C140, c140);
+/* C140.h */
+
+#pragma once
+
+#ifndef __OSDCOMM_H__
+#define __OSDCOMM_H__
+typedef unsigned char UINT8; /* unsigned 8bit */
+typedef unsigned short UINT16; /* unsigned 16bit */
+typedef unsigned int UINT32; /* unsigned 32bit */
+typedef signed char INT8; /* signed 8bit */
+typedef signed short INT16; /* signed 16bit */
+typedef signed int INT32; /* signed 32bit */
+
+typedef INT32 stream_sample_t;
+typedef UINT32 offs_t;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void c140_update(void * chip, stream_sample_t **outputs, int samples);
+void * device_start_c140(int sample_rate, int clock, int banking_type);
+void device_stop_c140(void * chip);
+void device_reset_c140(void * chip);
+
+//READ8_DEVICE_HANDLER( c140_r );
+//WRITE8_DEVICE_HANDLER( c140_w );
+UINT8 c140_r(void * chip, offs_t offset);
+void c140_w(void * chip, offs_t offset, UINT8 data);
+
+//void c140_set_base(device_t *device, void *base);
+void c140_set_base(void *chip, void *base);
+
+enum
+{
+ C140_TYPE_SYSTEM2,
+ C140_TYPE_SYSTEM21_A,
+ C140_TYPE_SYSTEM21_B,
+ C140_TYPE_ASIC219
+};
+
+/*typedef struct _c140_interface c140_interface;
+struct _c140_interface {
+ int banking_type;
+};*/
+
+
+void c140_write_rom(void * chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
+ const UINT8* ROMData);
+
+void c140_set_mute_mask(void * chip, UINT32 MuteMask);
+
+#ifdef __cplusplus
+}
+#endif
+
+//DECLARE_LEGACY_SOUND_DEVICE(C140, c140);
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/dac_control.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/dac_control.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/dac_control.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/dac_control.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,367 +1,367 @@
- /************************
- * DAC Stream Control *
- ***********************/
-// (Custom Driver to handle PCM Streams of YM2612 DAC and PWM.)
-//
-// Written on 3 February 2011 by Valley Bell
-// Last Update: 25 April 2011
-//
-// Only for usage in non-commercial, VGM file related software.
-
-/* How it basically works:
-
-1. send command X with data Y at frequency F to chip C
-2. do that until you receive a STOP command, or until you sent N commands
-
-*/
-
-#include "dac_control.h"
-
-#include
-
-#define INLINE static __inline
-
-void chip_reg_write(void * context, UINT32 Sample, UINT8 ChipType, UINT8 ChipID, UINT8 Port, UINT8 Offset, UINT8 Data);
-
-typedef struct _dac_control
-{
- UINT32 SampleRate;
-
- // Commands sent to dest-chip
- UINT8 DstChipType;
- UINT8 DstChipID;
- UINT16 DstCommand;
- UINT8 CmdSize;
-
- UINT32 Frequency; // Frequency (Hz) at which the commands are sent
- UINT32 DataLen; // to protect from reading beyond End Of Data
- const UINT8* Data;
- UINT32 DataStart; // Position where to start
- UINT8 StepSize; // usually 1, set to 2 for L/R interleaved data
- UINT8 StepBase; // usually 0, set to 0/1 for L/R interleaved data
- UINT32 CmdsToSend;
-
- // Running Bits: 0 (01) - is playing
- // 2 (04) - loop sample (simple loop from start to end)
- // 4 (10) - already sent this command
- // 7 (80) - disabled
- UINT8 Running;
- UINT32 Step;
- UINT32 Pos;
- UINT32 RemainCmds;
- UINT8 DataStep; // always StepSize * CmdSize
-
- void * context; // context data sent to chip_reg_write
-} dac_control;
-
-#ifndef NULL
-#define NULL (void*)0
-#endif
-
-static void daccontrol_SendCommand(dac_control *chip, UINT32 Sample)
-{
- UINT8 Port;
- UINT8 Command;
- UINT8 Data;
- const UINT8* ChipData;
-
- if (chip->Running & 0x10) // command already sent
- return;
- if (chip->DataStart + chip->Pos >= chip->DataLen)
- return;
-
- ChipData = chip->Data + (chip->DataStart + chip->Pos);
- switch(chip->DstChipType)
- {
- // Support for the important chips
- case 0x02: // YM2612
- Port = (chip->DstCommand & 0xFF00) >> 8;
- Command = (chip->DstCommand & 0x00FF) >> 0;
- Data = ChipData[0x00];
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
- break;
- case 0x11: // PWM
- Port = (chip->DstCommand & 0x000F) >> 0;
- Command = ChipData[0x01] & 0x0F;
- Data = ChipData[0x00];
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
- break;
- // (Generic) Support for other chips (just for completeness)
- case 0x00: // SN76496
- Command = (chip->DstCommand & 0x00F0) >> 0;
- Data = ChipData[0x00] & 0x0F;
- if (Command & 0x10)
- {
- // Volume Change (4-Bit value)
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);
- }
- else
- {
- // Frequency Write (10-Bit value)
- Port = ((ChipData[0x01] & 0x03) << 4) | ((ChipData[0x00] & 0xF0) >> 4);
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Port);
- }
- break;
- case 0x01: // YM2413
- case 0x03: // YM2151
- case 0x09: // YM3812
- case 0x0A: // YM3526
- case 0x0B: // Y8950
- case 0x0F: // YMZ280B
- case 0x12: // AY8910
- Command = (chip->DstCommand & 0x00FF) >> 0;
- Data = ChipData[0x00];
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, Command, Data);
- break;
- case 0x06: // YM2203
- case 0x07: // YM2608
- case 0x08: // YM2610/B
- case 0x0C: // YMF262
- case 0x0D: // YMF278B
- case 0x0E: // YMF271
- Port = (chip->DstCommand & 0xFF00) >> 8;
- Command = (chip->DstCommand & 0x00FF) >> 0;
- Data = ChipData[0x00];
- chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
- break;
- }
- chip->Running |= 0x10;
-
- return;
-}
-
-INLINE UINT32 muldiv64round(UINT32 Multiplicand, UINT32 Multiplier, UINT32 Divisor)
-{
- // Yes, I'm correctly rounding the values.
- return (UINT32)(((UINT64)Multiplicand * Multiplier + Multiplier / 2) / Divisor);
-}
-
-void daccontrol_update(void *_chip, UINT32 base_clock, UINT32 samples)
-{
- dac_control *chip = (dac_control *) _chip;
- UINT32 NewPos;
- UINT32 Sample;
-
- if (chip->Running & 0x80) // disabled
- return;
- if (! (chip->Running & 0x01)) // stopped
- return;
-
- /*if (samples > 0x20)
- {
- // very effective Speed Hack for fast seeking
- NewPos = chip->Step + (samples - 0x10);
- NewPos = muldiv64round(NewPos * chip->DataStep, chip->Frequency, chip->SampleRate);
- while(chip->RemainCmds && chip->Pos < NewPos)
- {
- chip->Pos += chip->DataStep;
- chip->RemainCmds --;
- }
- }*/
-
- Sample = 0;
- chip->Step += samples;
- // Formula: Step * Freq / SampleRate
- NewPos = muldiv64round(chip->Step * chip->DataStep, chip->Frequency, chip->SampleRate);
-
- while(chip->RemainCmds && chip->Pos < NewPos)
- {
- daccontrol_SendCommand(chip, base_clock + muldiv64round(Sample, chip->SampleRate, chip->Frequency));
- Sample++;
- chip->Pos += chip->DataStep;
- chip->Running &= ~0x10;
- chip->RemainCmds --;
- }
-
- if (! chip->RemainCmds && (chip->Running & 0x04))
- {
- // loop back to start
- chip->RemainCmds = chip->CmdsToSend;
- chip->Step = 0x00;
- chip->Pos = 0x00;
- }
-
- if (! chip->RemainCmds)
- chip->Running &= ~0x01; // stop
-
- return;
-}
-
-void * device_start_daccontrol(UINT32 samplerate, void * context)
-{
- dac_control *chip;
-
- chip = (dac_control *) calloc(1, sizeof(dac_control));
-
- chip->SampleRate = samplerate;
- chip->context = context;
-
- chip->DstChipType = 0xFF;
- chip->DstChipID = 0x00;
- chip->DstCommand = 0x0000;
-
- chip->Running = 0xFF; // disable all actions (except setup_chip)
-
- return chip;
-}
-
-void device_stop_daccontrol(void *_chip)
-{
- dac_control *chip = (dac_control *) _chip;
-
- free( chip );
-}
-
-void device_reset_daccontrol(void *_chip)
-{
- dac_control *chip = (dac_control *) _chip;
-
- chip->DstChipType = 0x00;
- chip->DstChipID = 0x00;
- chip->DstCommand = 0x00;
- chip->CmdSize = 0x00;
-
- chip->Frequency = 0;
- chip->DataLen = 0x00;
- chip->Data = NULL;
- chip->DataStart = 0x00;
- chip->StepSize = 0x00;
- chip->StepBase = 0x00;
-
- chip->Running = 0x00;
- chip->Step = 0x00;
- chip->Pos = 0x00;
- chip->RemainCmds = 0x00;
- chip->DataStep = 0x00;
-
- return;
-}
-
-void daccontrol_setup_chip(void *_chip, UINT8 ChType, UINT8 ChNum, UINT16 Command)
-{
- dac_control *chip = (dac_control *) _chip;
-
- chip->DstChipType = ChType; // TypeID (e.g. 0x02 for YM2612)
- chip->DstChipID = ChNum; // chip number (to send commands to 1st or 2nd chip)
- chip->DstCommand = Command; // Port and Command (would be 0x02A for YM2612)
-
- switch(chip->DstChipType)
- {
- case 0x00: // SN76496
- if (chip->DstCommand & 0x0010)
- chip->CmdSize = 0x01; // Volume Write
- else
- chip->CmdSize = 0x02; // Frequency Write
- break;
- case 0x02: // YM2612
- chip->CmdSize = 0x01;
- break;
- case 0x11: // PWM
- chip->CmdSize = 0x02;
- break;
- default:
- chip->CmdSize = 0x01;
- break;
- }
- chip->DataStep = chip->CmdSize * chip->StepSize;
-
- return;
-}
-
-void daccontrol_set_data(void *_chip, const UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase)
-{
- dac_control *chip = (dac_control *) _chip;
-
- if (chip->Running & 0x80)
- return;
-
- if (DataLen && Data != NULL)
- {
- chip->DataLen = DataLen;
- chip->Data = Data;
- }
- else
- {
- chip->DataLen = 0x00;
- chip->Data = NULL;
- }
- chip->StepSize = StepSize ? StepSize : 1;
- chip->StepBase = StepBase;
- chip->DataStep = chip->CmdSize * chip->StepSize;
-
- return;
-}
-
-void daccontrol_set_frequency(void *_chip, UINT32 Frequency)
-{
- dac_control *chip = (dac_control *) _chip;
-
- if (chip->Running & 0x80)
- return;
-
- chip->Frequency = Frequency;
-
- return;
-}
-
-void daccontrol_start(void *_chip, UINT32 DataPos, UINT8 LenMode, UINT32 Length)
-{
- dac_control *chip = (dac_control *) _chip;
- UINT16 CmdStepBase;
-
- if (chip->Running & 0x80)
- return;
-
- CmdStepBase = chip->CmdSize * chip->StepBase;
- if (DataPos != 0xFFFFFFFF) // skip setting DataStart, if Pos == -1
- {
- chip->DataStart = DataPos + CmdStepBase;
- if (chip->DataStart > chip->DataLen) // catch bad value and force silence
- chip->DataStart = chip->DataLen;
- }
-
- switch(LenMode & 0x0F)
- {
- case DCTRL_LMODE_IGNORE: // Length is already set - ignore
- break;
- case DCTRL_LMODE_CMDS: // Length = number of commands
- chip->CmdsToSend = Length;
- break;
- case DCTRL_LMODE_MSEC: // Length = time in msec
- chip->CmdsToSend = 1000 * Length / chip->Frequency;
- break;
- case DCTRL_LMODE_TOEND: // play unti stop-command is received (or data-end is reached)
- chip->CmdsToSend = (chip->DataLen - (chip->DataStart - CmdStepBase)) / chip->DataStep;
- break;
- case DCTRL_LMODE_BYTES: // raw byte count
- chip->CmdsToSend = Length / chip->DataStep;
- break;
- default:
- chip->CmdsToSend = 0x00;
- break;
- }
- chip->RemainCmds = chip->CmdsToSend;
- chip->Step = 0x00;
- chip->Pos = 0x00;
-
- chip->Running &= ~0x04;
- chip->Running |= (LenMode & 0x80) ? 0x04 : 0x00; // set loop mode
-
- chip->Running |= 0x01; // start
- chip->Running &= ~0x10; // command isn't yet sent
-
- return;
-}
-
-void daccontrol_stop(void *_chip)
-{
- dac_control *chip = (dac_control *) _chip;
-
- if (chip->Running & 0x80)
- return;
-
- chip->Running &= ~0x01; // stop
-
- return;
-}
+ /************************
+ * DAC Stream Control *
+ ***********************/
+// (Custom Driver to handle PCM Streams of YM2612 DAC and PWM.)
+//
+// Written on 3 February 2011 by Valley Bell
+// Last Update: 25 April 2011
+//
+// Only for usage in non-commercial, VGM file related software.
+
+/* How it basically works:
+
+1. send command X with data Y at frequency F to chip C
+2. do that until you receive a STOP command, or until you sent N commands
+
+*/
+
+#include "dac_control.h"
+
+#include
+
+#define INLINE static __inline
+
+void chip_reg_write(void * context, UINT32 Sample, UINT8 ChipType, UINT8 ChipID, UINT8 Port, UINT8 Offset, UINT8 Data);
+
+typedef struct _dac_control
+{
+ UINT32 SampleRate;
+
+ // Commands sent to dest-chip
+ UINT8 DstChipType;
+ UINT8 DstChipID;
+ UINT16 DstCommand;
+ UINT8 CmdSize;
+
+ UINT32 Frequency; // Frequency (Hz) at which the commands are sent
+ UINT32 DataLen; // to protect from reading beyond End Of Data
+ const UINT8* Data;
+ UINT32 DataStart; // Position where to start
+ UINT8 StepSize; // usually 1, set to 2 for L/R interleaved data
+ UINT8 StepBase; // usually 0, set to 0/1 for L/R interleaved data
+ UINT32 CmdsToSend;
+
+ // Running Bits: 0 (01) - is playing
+ // 2 (04) - loop sample (simple loop from start to end)
+ // 4 (10) - already sent this command
+ // 7 (80) - disabled
+ UINT8 Running;
+ UINT32 Step;
+ UINT32 Pos;
+ UINT32 RemainCmds;
+ UINT8 DataStep; // always StepSize * CmdSize
+
+ void * context; // context data sent to chip_reg_write
+} dac_control;
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+static void daccontrol_SendCommand(dac_control *chip, UINT32 Sample)
+{
+ UINT8 Port;
+ UINT8 Command;
+ UINT8 Data;
+ const UINT8* ChipData;
+
+ if (chip->Running & 0x10) // command already sent
+ return;
+ if (chip->DataStart + chip->Pos >= chip->DataLen)
+ return;
+
+ ChipData = chip->Data + (chip->DataStart + chip->Pos);
+ switch(chip->DstChipType)
+ {
+ // Support for the important chips
+ case 0x02: // YM2612
+ Port = (chip->DstCommand & 0xFF00) >> 8;
+ Command = (chip->DstCommand & 0x00FF) >> 0;
+ Data = ChipData[0x00];
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
+ break;
+ case 0x11: // PWM
+ Port = (chip->DstCommand & 0x000F) >> 0;
+ Command = ChipData[0x01] & 0x0F;
+ Data = ChipData[0x00];
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
+ break;
+ // (Generic) Support for other chips (just for completeness)
+ case 0x00: // SN76496
+ Command = (chip->DstCommand & 0x00F0) >> 0;
+ Data = ChipData[0x00] & 0x0F;
+ if (Command & 0x10)
+ {
+ // Volume Change (4-Bit value)
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);
+ }
+ else
+ {
+ // Frequency Write (10-Bit value)
+ Port = ((ChipData[0x01] & 0x03) << 4) | ((ChipData[0x00] & 0xF0) >> 4);
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Command | Data);
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, 0x00, Port);
+ }
+ break;
+ case 0x01: // YM2413
+ case 0x03: // YM2151
+ case 0x09: // YM3812
+ case 0x0A: // YM3526
+ case 0x0B: // Y8950
+ case 0x0F: // YMZ280B
+ case 0x12: // AY8910
+ Command = (chip->DstCommand & 0x00FF) >> 0;
+ Data = ChipData[0x00];
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, 0x00, Command, Data);
+ break;
+ case 0x06: // YM2203
+ case 0x07: // YM2608
+ case 0x08: // YM2610/B
+ case 0x0C: // YMF262
+ case 0x0D: // YMF278B
+ case 0x0E: // YMF271
+ Port = (chip->DstCommand & 0xFF00) >> 8;
+ Command = (chip->DstCommand & 0x00FF) >> 0;
+ Data = ChipData[0x00];
+ chip_reg_write(chip->context, Sample, chip->DstChipType, chip->DstChipID, Port, Command, Data);
+ break;
+ }
+ chip->Running |= 0x10;
+
+ return;
+}
+
+INLINE UINT32 muldiv64round(UINT32 Multiplicand, UINT32 Multiplier, UINT32 Divisor)
+{
+ // Yes, I'm correctly rounding the values.
+ return (UINT32)(((UINT64)Multiplicand * Multiplier + Multiplier / 2) / Divisor);
+}
+
+void daccontrol_update(void *_chip, UINT32 base_clock, UINT32 samples)
+{
+ dac_control *chip = (dac_control *) _chip;
+ UINT32 NewPos;
+ UINT32 Sample;
+
+ if (chip->Running & 0x80) // disabled
+ return;
+ if (! (chip->Running & 0x01)) // stopped
+ return;
+
+ /*if (samples > 0x20)
+ {
+ // very effective Speed Hack for fast seeking
+ NewPos = chip->Step + (samples - 0x10);
+ NewPos = muldiv64round(NewPos * chip->DataStep, chip->Frequency, chip->SampleRate);
+ while(chip->RemainCmds && chip->Pos < NewPos)
+ {
+ chip->Pos += chip->DataStep;
+ chip->RemainCmds --;
+ }
+ }*/
+
+ Sample = 0;
+ chip->Step += samples;
+ // Formula: Step * Freq / SampleRate
+ NewPos = muldiv64round(chip->Step * chip->DataStep, chip->Frequency, chip->SampleRate);
+
+ while(chip->RemainCmds && chip->Pos < NewPos)
+ {
+ daccontrol_SendCommand(chip, base_clock + muldiv64round(Sample, chip->SampleRate, chip->Frequency));
+ Sample++;
+ chip->Pos += chip->DataStep;
+ chip->Running &= ~0x10;
+ chip->RemainCmds --;
+ }
+
+ if (! chip->RemainCmds && (chip->Running & 0x04))
+ {
+ // loop back to start
+ chip->RemainCmds = chip->CmdsToSend;
+ chip->Step = 0x00;
+ chip->Pos = 0x00;
+ }
+
+ if (! chip->RemainCmds)
+ chip->Running &= ~0x01; // stop
+
+ return;
+}
+
+void * device_start_daccontrol(UINT32 samplerate, void * context)
+{
+ dac_control *chip;
+
+ chip = (dac_control *) calloc(1, sizeof(dac_control));
+
+ chip->SampleRate = samplerate;
+ chip->context = context;
+
+ chip->DstChipType = 0xFF;
+ chip->DstChipID = 0x00;
+ chip->DstCommand = 0x0000;
+
+ chip->Running = 0xFF; // disable all actions (except setup_chip)
+
+ return chip;
+}
+
+void device_stop_daccontrol(void *_chip)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ free( chip );
+}
+
+void device_reset_daccontrol(void *_chip)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ chip->DstChipType = 0x00;
+ chip->DstChipID = 0x00;
+ chip->DstCommand = 0x00;
+ chip->CmdSize = 0x00;
+
+ chip->Frequency = 0;
+ chip->DataLen = 0x00;
+ chip->Data = NULL;
+ chip->DataStart = 0x00;
+ chip->StepSize = 0x00;
+ chip->StepBase = 0x00;
+
+ chip->Running = 0x00;
+ chip->Step = 0x00;
+ chip->Pos = 0x00;
+ chip->RemainCmds = 0x00;
+ chip->DataStep = 0x00;
+
+ return;
+}
+
+void daccontrol_setup_chip(void *_chip, UINT8 ChType, UINT8 ChNum, UINT16 Command)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ chip->DstChipType = ChType; // TypeID (e.g. 0x02 for YM2612)
+ chip->DstChipID = ChNum; // chip number (to send commands to 1st or 2nd chip)
+ chip->DstCommand = Command; // Port and Command (would be 0x02A for YM2612)
+
+ switch(chip->DstChipType)
+ {
+ case 0x00: // SN76496
+ if (chip->DstCommand & 0x0010)
+ chip->CmdSize = 0x01; // Volume Write
+ else
+ chip->CmdSize = 0x02; // Frequency Write
+ break;
+ case 0x02: // YM2612
+ chip->CmdSize = 0x01;
+ break;
+ case 0x11: // PWM
+ chip->CmdSize = 0x02;
+ break;
+ default:
+ chip->CmdSize = 0x01;
+ break;
+ }
+ chip->DataStep = chip->CmdSize * chip->StepSize;
+
+ return;
+}
+
+void daccontrol_set_data(void *_chip, const UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ if (chip->Running & 0x80)
+ return;
+
+ if (DataLen && Data != NULL)
+ {
+ chip->DataLen = DataLen;
+ chip->Data = Data;
+ }
+ else
+ {
+ chip->DataLen = 0x00;
+ chip->Data = NULL;
+ }
+ chip->StepSize = StepSize ? StepSize : 1;
+ chip->StepBase = StepBase;
+ chip->DataStep = chip->CmdSize * chip->StepSize;
+
+ return;
+}
+
+void daccontrol_set_frequency(void *_chip, UINT32 Frequency)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ if (chip->Running & 0x80)
+ return;
+
+ chip->Frequency = Frequency;
+
+ return;
+}
+
+void daccontrol_start(void *_chip, UINT32 DataPos, UINT8 LenMode, UINT32 Length)
+{
+ dac_control *chip = (dac_control *) _chip;
+ UINT16 CmdStepBase;
+
+ if (chip->Running & 0x80)
+ return;
+
+ CmdStepBase = chip->CmdSize * chip->StepBase;
+ if (DataPos != 0xFFFFFFFF) // skip setting DataStart, if Pos == -1
+ {
+ chip->DataStart = DataPos + CmdStepBase;
+ if (chip->DataStart > chip->DataLen) // catch bad value and force silence
+ chip->DataStart = chip->DataLen;
+ }
+
+ switch(LenMode & 0x0F)
+ {
+ case DCTRL_LMODE_IGNORE: // Length is already set - ignore
+ break;
+ case DCTRL_LMODE_CMDS: // Length = number of commands
+ chip->CmdsToSend = Length;
+ break;
+ case DCTRL_LMODE_MSEC: // Length = time in msec
+ chip->CmdsToSend = 1000 * Length / chip->Frequency;
+ break;
+ case DCTRL_LMODE_TOEND: // play unti stop-command is received (or data-end is reached)
+ chip->CmdsToSend = (chip->DataLen - (chip->DataStart - CmdStepBase)) / chip->DataStep;
+ break;
+ case DCTRL_LMODE_BYTES: // raw byte count
+ chip->CmdsToSend = Length / chip->DataStep;
+ break;
+ default:
+ chip->CmdsToSend = 0x00;
+ break;
+ }
+ chip->RemainCmds = chip->CmdsToSend;
+ chip->Step = 0x00;
+ chip->Pos = 0x00;
+
+ chip->Running &= ~0x04;
+ chip->Running |= (LenMode & 0x80) ? 0x04 : 0x00; // set loop mode
+
+ chip->Running |= 0x01; // start
+ chip->Running &= ~0x10; // command isn't yet sent
+
+ return;
+}
+
+void daccontrol_stop(void *_chip)
+{
+ dac_control *chip = (dac_control *) _chip;
+
+ if (chip->Running & 0x80)
+ return;
+
+ chip->Running &= ~0x01; // stop
+
+ return;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/dac_control.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/dac_control.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/dac_control.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/dac_control.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,44 +1,44 @@
-#ifndef _DAC_CONTROL_H_
-#define _DAC_CONTROL_H_
-
-#ifndef __OSDCOMM_H__
-#define __OSDCOMM_H__
-typedef unsigned char UINT8; /* unsigned 8bit */
-typedef unsigned short UINT16; /* unsigned 16bit */
-typedef unsigned int UINT32; /* unsigned 32bit */
-typedef unsigned long long UINT64; /* unsigned 64bit */
-typedef signed char INT8; /* signed 8bit */
-typedef signed short INT16; /* signed 16bit */
-typedef signed int INT32; /* signed 32bit */
-typedef signed long long INT64; /* signed 64bit */
-
-typedef INT32 stream_sample_t;
-typedef UINT32 offs_t;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void * device_start_daccontrol(UINT32 samplerate, void *context);
-void device_stop_daccontrol(void * chip);
-
-void daccontrol_update(void * chip, UINT32 base_clock, UINT32 samples);
-void device_reset_daccontrol(void * chip);
-void daccontrol_setup_chip(void * chip, UINT8 ChType, UINT8 ChNum, UINT16 Command);
-void daccontrol_set_data(void *chip, const UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase);
-void daccontrol_set_frequency(void *chip, UINT32 Frequency);
-void daccontrol_start(void *chip, UINT32 DataPos, UINT8 LenMode, UINT32 Length);
-void daccontrol_stop(void *chip);
-
-#define DCTRL_LMODE_IGNORE 0x00
-#define DCTRL_LMODE_CMDS 0x01
-#define DCTRL_LMODE_MSEC 0x02
-#define DCTRL_LMODE_TOEND 0x03
-#define DCTRL_LMODE_BYTES 0x0F
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#ifndef _DAC_CONTROL_H_
+#define _DAC_CONTROL_H_
+
+#ifndef __OSDCOMM_H__
+#define __OSDCOMM_H__
+typedef unsigned char UINT8; /* unsigned 8bit */
+typedef unsigned short UINT16; /* unsigned 16bit */
+typedef unsigned int UINT32; /* unsigned 32bit */
+typedef unsigned long long UINT64; /* unsigned 64bit */
+typedef signed char INT8; /* signed 8bit */
+typedef signed short INT16; /* signed 16bit */
+typedef signed int INT32; /* signed 32bit */
+typedef signed long long INT64; /* signed 64bit */
+
+typedef INT32 stream_sample_t;
+typedef UINT32 offs_t;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void * device_start_daccontrol(UINT32 samplerate, void *context);
+void device_stop_daccontrol(void * chip);
+
+void daccontrol_update(void * chip, UINT32 base_clock, UINT32 samples);
+void device_reset_daccontrol(void * chip);
+void daccontrol_setup_chip(void * chip, UINT8 ChType, UINT8 ChNum, UINT16 Command);
+void daccontrol_set_data(void *chip, const UINT8* Data, UINT32 DataLen, UINT8 StepSize, UINT8 StepBase);
+void daccontrol_set_frequency(void *chip, UINT32 Frequency);
+void daccontrol_start(void *chip, UINT32 DataPos, UINT8 LenMode, UINT32 Length);
+void daccontrol_stop(void *chip);
+
+#define DCTRL_LMODE_IGNORE 0x00
+#define DCTRL_LMODE_CMDS 0x01
+#define DCTRL_LMODE_MSEC 0x02
+#define DCTRL_LMODE_TOEND 0x03
+#define DCTRL_LMODE_BYTES 0x0F
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Dual_Resampler.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Dual_Resampler.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Dual_Resampler.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Dual_Resampler.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,315 +1,315 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Dual_Resampler.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// TODO: fix this. hack since resampler holds back some output.
-int const resampler_extra = 34;
-
-int const stereo = 2;
-
-Dual_Resampler::Dual_Resampler() { }
-
-Dual_Resampler::~Dual_Resampler() { }
-
-blargg_err_t Dual_Resampler::reset( int pairs )
-{
- // expand allocations a bit
- RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
- resize( pairs );
- resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
- RETURN_ERR( resampler.resize_buffer( resampler_size ) );
- resampler.clear();
- return blargg_ok;
-}
-
-void Dual_Resampler::resize( int pairs )
-{
- int new_sample_buf_size = pairs * 2;
- //new_sample_buf_size = new_sample_buf_size / 4 * 4; // TODO: needed only for 3:2 downsampler
- if ( sample_buf_size != new_sample_buf_size )
- {
- if ( (unsigned) new_sample_buf_size > sample_buf.size() )
- {
- check( false );
- return;
- }
- sample_buf_size = new_sample_buf_size;
- oversamples_per_frame = int (pairs * resampler.rate()) * 2 + 2;
- clear();
- }
-}
-
-void Dual_Resampler::clear()
-{
- buf_pos = buffered = 0;
- resampler.clear();
-}
-
-
-int Dual_Resampler::play_frame_( Stereo_Buffer& stereo_buf, dsample_t out [], Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
-{
- int pair_count = sample_buf_size >> 1;
- blip_time_t blip_time = stereo_buf.center()->count_clocks( pair_count );
- int sample_count = oversamples_per_frame - resampler.written() + resampler_extra;
-
- int new_count = set_callback.f( set_callback.data, blip_time, sample_count, resampler.buffer() );
- assert( new_count < resampler_size );
-
- stereo_buf.end_frame( blip_time );
- assert( stereo_buf.samples_avail() == pair_count * 2 );
- if ( secondary_buf_set && secondary_buf_set_count )
- {
- for ( int i = 0; i < secondary_buf_set_count; i++ )
- {
- Stereo_Buffer * second_buf = secondary_buf_set[i];
- blip_time_t blip_time_2 = second_buf->center()->count_clocks( pair_count );
- second_buf->end_frame( blip_time_2 );
- assert( second_buf->samples_avail() == pair_count * 2 );
- }
- }
-
- resampler.write( new_count );
-
- int count = resampler.read( sample_buf.begin(), sample_buf_size );
-
- mix_samples( stereo_buf, out, count, secondary_buf_set, secondary_buf_set_count );
-
- pair_count = count >> 1;
- stereo_buf.left()->remove_samples( pair_count );
- stereo_buf.right()->remove_samples( pair_count );
- stereo_buf.center()->remove_samples( pair_count );
-
- if ( secondary_buf_set && secondary_buf_set_count )
- {
- for ( int i = 0; i < secondary_buf_set_count; i++ )
- {
- Stereo_Buffer * second_buf = secondary_buf_set[i];
- second_buf->left()->remove_samples( pair_count );
- second_buf->right()->remove_samples( pair_count );
- second_buf->center()->remove_samples( pair_count );
- }
- }
-
- return count;
-}
-
-void Dual_Resampler::dual_play( int count, dsample_t out [], Stereo_Buffer& stereo_buf, Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
-{
- // empty extra buffer
- int remain = buffered - buf_pos;
- if ( remain )
- {
- if ( remain > count )
- remain = count;
- count -= remain;
- memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
- out += remain;
- buf_pos += remain;
- }
-
- // entire frames
- while ( count >= sample_buf_size )
- {
- buf_pos = buffered = play_frame_( stereo_buf, out, secondary_buf_set, secondary_buf_set_count );
- out += buffered;
- count -= buffered;
- }
-
- while (count > 0)
- {
- buffered = play_frame_( stereo_buf, sample_buf.begin(), secondary_buf_set, secondary_buf_set_count );
- if ( buffered >= count )
- {
- buf_pos = count;
- memcpy( out, sample_buf.begin(), count * sizeof *out );
- out += count;
- count = 0;
- }
- else
- {
- memcpy( out, sample_buf.begin(), buffered * sizeof *out );
- out += buffered;
- count -= buffered;
- }
- }
-}
-
-void Dual_Resampler::mix_samples( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count, Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
-{
- // lol hax
- if ( ((Tracked_Blip_Buffer*)stereo_buf.left())->non_silent() | ((Tracked_Blip_Buffer*)stereo_buf.right())->non_silent() )
- mix_stereo( stereo_buf, out_, count );
- else
- mix_mono( stereo_buf, out_, count );
-
- if ( secondary_buf_set && secondary_buf_set_count )
- {
- for ( int i = 0; i < secondary_buf_set_count; i++ )
- {
- Stereo_Buffer * second_buf = secondary_buf_set[i];
- if ( ((Tracked_Blip_Buffer*)second_buf->left())->non_silent() | ((Tracked_Blip_Buffer*)second_buf->right())->non_silent() )
- mix_extra_stereo( *second_buf, out_, count );
- else
- mix_extra_mono( *second_buf, out_, count );
- }
- }
-}
-
-void Dual_Resampler::mix_mono( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
-{
- int const bass = BLIP_READER_BASS( *stereo_buf.center() );
- BLIP_READER_BEGIN( sn, *stereo_buf.center() );
-
- count >>= 1;
- BLIP_READER_ADJ_( sn, count );
-
- typedef dsample_t stereo_dsample_t [2];
- stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
- stereo_dsample_t const* BLARGG_RESTRICT in =
- (stereo_dsample_t const*) sample_buf.begin() + count;
- int offset = -count;
- int const gain = gain_;
- do
- {
- int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16);
- BLIP_READER_NEXT_IDX_( sn, bass, offset );
-
- int l = (in [offset] [0] * gain >> gain_bits) + s;
- int r = (in [offset] [1] * gain >> gain_bits) + s;
-
- BLIP_CLAMP( l, l );
- out [offset] [0] = (blip_sample_t) l;
-
- BLIP_CLAMP( r, r );
- out [offset] [1] = (blip_sample_t) r;
- }
- while ( ++offset );
-
- BLIP_READER_END( sn, *stereo_buf.center() );
-}
-
-void Dual_Resampler::mix_stereo( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
-{
- int const bass = BLIP_READER_BASS( *stereo_buf.center() );
- BLIP_READER_BEGIN( snc, *stereo_buf.center() );
- BLIP_READER_BEGIN( snl, *stereo_buf.left() );
- BLIP_READER_BEGIN( snr, *stereo_buf.right() );
-
- count >>= 1;
- BLIP_READER_ADJ_( snc, count );
- BLIP_READER_ADJ_( snl, count );
- BLIP_READER_ADJ_( snr, count );
-
- typedef dsample_t stereo_dsample_t [2];
- stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
- stereo_dsample_t const* BLARGG_RESTRICT in =
- (stereo_dsample_t const*) sample_buf.begin() + count;
- int offset = -count;
- int const gain = gain_;
- do
- {
- int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16);
- int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16);
- int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16);
- BLIP_READER_NEXT_IDX_( snc, bass, offset );
- BLIP_READER_NEXT_IDX_( snl, bass, offset );
- BLIP_READER_NEXT_IDX_( snr, bass, offset );
-
- int l = (in [offset] [0] * gain >> gain_bits) + sl + sc;
- int r = (in [offset] [1] * gain >> gain_bits) + sr + sc;
-
- BLIP_CLAMP( l, l );
- out [offset] [0] = (blip_sample_t) l;
-
- BLIP_CLAMP( r, r );
- out [offset] [1] = (blip_sample_t) r;
- }
- while ( ++offset );
-
- BLIP_READER_END( snc, *stereo_buf.center() );
- BLIP_READER_END( snl, *stereo_buf.left() );
- BLIP_READER_END( snr, *stereo_buf.right() );
-}
-
-void Dual_Resampler::mix_extra_mono( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
-{
- int const bass = BLIP_READER_BASS( *stereo_buf.center() );
- BLIP_READER_BEGIN( sn, *stereo_buf.center() );
-
- count >>= 1;
- BLIP_READER_ADJ_( sn, count );
-
- typedef dsample_t stereo_dsample_t [2];
- stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
- int offset = -count;
- do
- {
- int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16);
- BLIP_READER_NEXT_IDX_( sn, bass, offset );
-
- int l = out [offset] [0] + s;
- int r = out [offset] [1] + s;
-
- BLIP_CLAMP( l, l );
- out [offset] [0] = (blip_sample_t) l;
-
- BLIP_CLAMP( r, r );
- out [offset] [1] = (blip_sample_t) r;
- }
- while ( ++offset );
-
- BLIP_READER_END( sn, *stereo_buf.center() );
-}
-
-void Dual_Resampler::mix_extra_stereo( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
-{
- int const bass = BLIP_READER_BASS( *stereo_buf.center() );
- BLIP_READER_BEGIN( snc, *stereo_buf.center() );
- BLIP_READER_BEGIN( snl, *stereo_buf.left() );
- BLIP_READER_BEGIN( snr, *stereo_buf.right() );
-
- count >>= 1;
- BLIP_READER_ADJ_( snc, count );
- BLIP_READER_ADJ_( snl, count );
- BLIP_READER_ADJ_( snr, count );
-
- typedef dsample_t stereo_dsample_t [2];
- stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
- int offset = -count;
- do
- {
- int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16);
- int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16);
- int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16);
- BLIP_READER_NEXT_IDX_( snc, bass, offset );
- BLIP_READER_NEXT_IDX_( snl, bass, offset );
- BLIP_READER_NEXT_IDX_( snr, bass, offset );
-
- int l = out [offset] [0] + sl + sc;
- int r = out [offset] [1] + sr + sc;
-
- BLIP_CLAMP( l, l );
- out [offset] [0] = (blip_sample_t) l;
-
- BLIP_CLAMP( r, r );
- out [offset] [1] = (blip_sample_t) r;
- }
- while ( ++offset );
-
- BLIP_READER_END( snc, *stereo_buf.center() );
- BLIP_READER_END( snl, *stereo_buf.left() );
- BLIP_READER_END( snr, *stereo_buf.right() );
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Dual_Resampler.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// TODO: fix this. hack since resampler holds back some output.
+int const resampler_extra = 34;
+
+int const stereo = 2;
+
+Dual_Resampler::Dual_Resampler() { }
+
+Dual_Resampler::~Dual_Resampler() { }
+
+blargg_err_t Dual_Resampler::reset( int pairs )
+{
+ // expand allocations a bit
+ RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
+ resize( pairs );
+ resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
+ RETURN_ERR( resampler.resize_buffer( resampler_size ) );
+ resampler.clear();
+ return blargg_ok;
+}
+
+void Dual_Resampler::resize( int pairs )
+{
+ int new_sample_buf_size = pairs * 2;
+ //new_sample_buf_size = new_sample_buf_size / 4 * 4; // TODO: needed only for 3:2 downsampler
+ if ( sample_buf_size != new_sample_buf_size )
+ {
+ if ( (unsigned) new_sample_buf_size > sample_buf.size() )
+ {
+ check( false );
+ return;
+ }
+ sample_buf_size = new_sample_buf_size;
+ oversamples_per_frame = int (pairs * resampler.rate()) * 2 + 2;
+ clear();
+ }
+}
+
+void Dual_Resampler::clear()
+{
+ buf_pos = buffered = 0;
+ resampler.clear();
+}
+
+
+int Dual_Resampler::play_frame_( Stereo_Buffer& stereo_buf, dsample_t out [], Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
+{
+ int pair_count = sample_buf_size >> 1;
+ blip_time_t blip_time = stereo_buf.center()->count_clocks( pair_count );
+ int sample_count = oversamples_per_frame - resampler.written() + resampler_extra;
+
+ int new_count = set_callback.f( set_callback.data, blip_time, sample_count, resampler.buffer() );
+ assert( new_count < resampler_size );
+
+ stereo_buf.end_frame( blip_time );
+ assert( stereo_buf.samples_avail() == pair_count * 2 );
+ if ( secondary_buf_set && secondary_buf_set_count )
+ {
+ for ( int i = 0; i < secondary_buf_set_count; i++ )
+ {
+ Stereo_Buffer * second_buf = secondary_buf_set[i];
+ blip_time_t blip_time_2 = second_buf->center()->count_clocks( pair_count );
+ second_buf->end_frame( blip_time_2 );
+ assert( second_buf->samples_avail() == pair_count * 2 );
+ }
+ }
+
+ resampler.write( new_count );
+
+ int count = resampler.read( sample_buf.begin(), sample_buf_size );
+
+ mix_samples( stereo_buf, out, count, secondary_buf_set, secondary_buf_set_count );
+
+ pair_count = count >> 1;
+ stereo_buf.left()->remove_samples( pair_count );
+ stereo_buf.right()->remove_samples( pair_count );
+ stereo_buf.center()->remove_samples( pair_count );
+
+ if ( secondary_buf_set && secondary_buf_set_count )
+ {
+ for ( int i = 0; i < secondary_buf_set_count; i++ )
+ {
+ Stereo_Buffer * second_buf = secondary_buf_set[i];
+ second_buf->left()->remove_samples( pair_count );
+ second_buf->right()->remove_samples( pair_count );
+ second_buf->center()->remove_samples( pair_count );
+ }
+ }
+
+ return count;
+}
+
+void Dual_Resampler::dual_play( int count, dsample_t out [], Stereo_Buffer& stereo_buf, Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
+{
+ // empty extra buffer
+ int remain = buffered - buf_pos;
+ if ( remain )
+ {
+ if ( remain > count )
+ remain = count;
+ count -= remain;
+ memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
+ out += remain;
+ buf_pos += remain;
+ }
+
+ // entire frames
+ while ( count >= sample_buf_size )
+ {
+ buf_pos = buffered = play_frame_( stereo_buf, out, secondary_buf_set, secondary_buf_set_count );
+ out += buffered;
+ count -= buffered;
+ }
+
+ while (count > 0)
+ {
+ buffered = play_frame_( stereo_buf, sample_buf.begin(), secondary_buf_set, secondary_buf_set_count );
+ if ( buffered >= count )
+ {
+ buf_pos = count;
+ memcpy( out, sample_buf.begin(), count * sizeof *out );
+ out += count;
+ count = 0;
+ }
+ else
+ {
+ memcpy( out, sample_buf.begin(), buffered * sizeof *out );
+ out += buffered;
+ count -= buffered;
+ }
+ }
+}
+
+void Dual_Resampler::mix_samples( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count, Stereo_Buffer** secondary_buf_set, int secondary_buf_set_count )
+{
+ // lol hax
+ if ( ((Tracked_Blip_Buffer*)stereo_buf.left())->non_silent() | ((Tracked_Blip_Buffer*)stereo_buf.right())->non_silent() )
+ mix_stereo( stereo_buf, out_, count );
+ else
+ mix_mono( stereo_buf, out_, count );
+
+ if ( secondary_buf_set && secondary_buf_set_count )
+ {
+ for ( int i = 0; i < secondary_buf_set_count; i++ )
+ {
+ Stereo_Buffer * second_buf = secondary_buf_set[i];
+ if ( ((Tracked_Blip_Buffer*)second_buf->left())->non_silent() | ((Tracked_Blip_Buffer*)second_buf->right())->non_silent() )
+ mix_extra_stereo( *second_buf, out_, count );
+ else
+ mix_extra_mono( *second_buf, out_, count );
+ }
+ }
+}
+
+void Dual_Resampler::mix_mono( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
+{
+ int const bass = BLIP_READER_BASS( *stereo_buf.center() );
+ BLIP_READER_BEGIN( sn, *stereo_buf.center() );
+
+ count >>= 1;
+ BLIP_READER_ADJ_( sn, count );
+
+ typedef dsample_t stereo_dsample_t [2];
+ stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
+ stereo_dsample_t const* BLARGG_RESTRICT in =
+ (stereo_dsample_t const*) sample_buf.begin() + count;
+ int offset = -count;
+ int const gain = gain_;
+ do
+ {
+ int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16);
+ BLIP_READER_NEXT_IDX_( sn, bass, offset );
+
+ int l = (in [offset] [0] * gain >> gain_bits) + s;
+ int r = (in [offset] [1] * gain >> gain_bits) + s;
+
+ BLIP_CLAMP( l, l );
+ out [offset] [0] = (blip_sample_t) l;
+
+ BLIP_CLAMP( r, r );
+ out [offset] [1] = (blip_sample_t) r;
+ }
+ while ( ++offset );
+
+ BLIP_READER_END( sn, *stereo_buf.center() );
+}
+
+void Dual_Resampler::mix_stereo( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
+{
+ int const bass = BLIP_READER_BASS( *stereo_buf.center() );
+ BLIP_READER_BEGIN( snc, *stereo_buf.center() );
+ BLIP_READER_BEGIN( snl, *stereo_buf.left() );
+ BLIP_READER_BEGIN( snr, *stereo_buf.right() );
+
+ count >>= 1;
+ BLIP_READER_ADJ_( snc, count );
+ BLIP_READER_ADJ_( snl, count );
+ BLIP_READER_ADJ_( snr, count );
+
+ typedef dsample_t stereo_dsample_t [2];
+ stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
+ stereo_dsample_t const* BLARGG_RESTRICT in =
+ (stereo_dsample_t const*) sample_buf.begin() + count;
+ int offset = -count;
+ int const gain = gain_;
+ do
+ {
+ int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16);
+ int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16);
+ int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16);
+ BLIP_READER_NEXT_IDX_( snc, bass, offset );
+ BLIP_READER_NEXT_IDX_( snl, bass, offset );
+ BLIP_READER_NEXT_IDX_( snr, bass, offset );
+
+ int l = (in [offset] [0] * gain >> gain_bits) + sl + sc;
+ int r = (in [offset] [1] * gain >> gain_bits) + sr + sc;
+
+ BLIP_CLAMP( l, l );
+ out [offset] [0] = (blip_sample_t) l;
+
+ BLIP_CLAMP( r, r );
+ out [offset] [1] = (blip_sample_t) r;
+ }
+ while ( ++offset );
+
+ BLIP_READER_END( snc, *stereo_buf.center() );
+ BLIP_READER_END( snl, *stereo_buf.left() );
+ BLIP_READER_END( snr, *stereo_buf.right() );
+}
+
+void Dual_Resampler::mix_extra_mono( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
+{
+ int const bass = BLIP_READER_BASS( *stereo_buf.center() );
+ BLIP_READER_BEGIN( sn, *stereo_buf.center() );
+
+ count >>= 1;
+ BLIP_READER_ADJ_( sn, count );
+
+ typedef dsample_t stereo_dsample_t [2];
+ stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
+ int offset = -count;
+ do
+ {
+ int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16);
+ BLIP_READER_NEXT_IDX_( sn, bass, offset );
+
+ int l = out [offset] [0] + s;
+ int r = out [offset] [1] + s;
+
+ BLIP_CLAMP( l, l );
+ out [offset] [0] = (blip_sample_t) l;
+
+ BLIP_CLAMP( r, r );
+ out [offset] [1] = (blip_sample_t) r;
+ }
+ while ( ++offset );
+
+ BLIP_READER_END( sn, *stereo_buf.center() );
+}
+
+void Dual_Resampler::mix_extra_stereo( Stereo_Buffer& stereo_buf, dsample_t out_ [], int count )
+{
+ int const bass = BLIP_READER_BASS( *stereo_buf.center() );
+ BLIP_READER_BEGIN( snc, *stereo_buf.center() );
+ BLIP_READER_BEGIN( snl, *stereo_buf.left() );
+ BLIP_READER_BEGIN( snr, *stereo_buf.right() );
+
+ count >>= 1;
+ BLIP_READER_ADJ_( snc, count );
+ BLIP_READER_ADJ_( snl, count );
+ BLIP_READER_ADJ_( snr, count );
+
+ typedef dsample_t stereo_dsample_t [2];
+ stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
+ int offset = -count;
+ do
+ {
+ int sc = BLIP_READER_READ_RAW( snc ) >> (blip_sample_bits - 16);
+ int sl = BLIP_READER_READ_RAW( snl ) >> (blip_sample_bits - 16);
+ int sr = BLIP_READER_READ_RAW( snr ) >> (blip_sample_bits - 16);
+ BLIP_READER_NEXT_IDX_( snc, bass, offset );
+ BLIP_READER_NEXT_IDX_( snl, bass, offset );
+ BLIP_READER_NEXT_IDX_( snr, bass, offset );
+
+ int l = out [offset] [0] + sl + sc;
+ int r = out [offset] [1] + sr + sc;
+
+ BLIP_CLAMP( l, l );
+ out [offset] [0] = (blip_sample_t) l;
+
+ BLIP_CLAMP( r, r );
+ out [offset] [1] = (blip_sample_t) r;
+ }
+ while ( ++offset );
+
+ BLIP_READER_END( snc, *stereo_buf.center() );
+ BLIP_READER_END( snl, *stereo_buf.left() );
+ BLIP_READER_END( snr, *stereo_buf.right() );
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Effects_Buffer.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Effects_Buffer.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Effects_Buffer.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Effects_Buffer.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,23 +1,23 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Effects_Buffer.h"
-
-/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Effects_Buffer.h"
+
+/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+ #include BLARGG_ENABLE_OPTIMIZER
+#endif
int const fixed_shift = 12;
#define TO_FIXED( f ) fixed_t ((f) * ((fixed_t) 1 << fixed_shift))
@@ -25,616 +25,616 @@
int const max_read = 2560; // determines minimum delay
-Effects_Buffer::Effects_Buffer( int max_bufs, int echo_size_ ) : Multi_Buffer( stereo )
-{
- echo_size = max( max_read * (int) stereo, echo_size_ & ~1 );
- clock_rate_ = 0;
- bass_freq_ = 90;
- bufs = NULL;
- bufs_size = 0;
- bufs_max = max( max_bufs, (int) extra_chans );
- no_echo = true;
- no_effects = true;
-
- // defaults
- config_.enabled = false;
- config_.delay [0] = 120;
- config_.delay [1] = 122;
- config_.feedback = 0.2f;
- config_.treble = 0.4f;
-
- static float const sep = 0.8f;
- config_.side_chans [0].pan = -sep;
- config_.side_chans [1].pan = +sep;
- config_.side_chans [0].vol = 1.0f;
- config_.side_chans [1].vol = 1.0f;
-
- memset( &s, 0, sizeof s );
- clear();
-}
-
-Effects_Buffer::~Effects_Buffer()
-{
- delete_bufs();
-}
-
-// avoid using new []
-blargg_err_t Effects_Buffer::new_bufs( int size )
-{
- bufs = (buf_t*) malloc( size * sizeof *bufs );
- CHECK_ALLOC( bufs );
- for ( int i = 0; i < size; i++ )
- new (bufs + i) buf_t;
- bufs_size = size;
- return blargg_ok;
-}
-
-void Effects_Buffer::delete_bufs()
-{
- if ( bufs )
- {
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].~buf_t();
- free( bufs );
- bufs = NULL;
- }
- bufs_size = 0;
-}
-
-blargg_err_t Effects_Buffer::set_sample_rate( int rate, int msec )
-{
- // extra to allow farther past-the-end pointers
- mixer.samples_read = 0;
- RETURN_ERR( echo.resize( echo_size + stereo ) );
- return Multi_Buffer::set_sample_rate( rate, msec );
-}
-
-void Effects_Buffer::clock_rate( int rate )
-{
- clock_rate_ = rate;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clock_rate( clock_rate_ );
-}
-
-void Effects_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].bass_freq( bass_freq_ );
-}
-
-blargg_err_t Effects_Buffer::set_channel_count( int count, int const types [] )
-{
- RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) );
-
- delete_bufs();
-
- mixer.samples_read = 0;
-
- RETURN_ERR( chans.resize( count + extra_chans ) );
-
- RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) );
-
- for ( int i = bufs_size; --i >= 0; )
- RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) );
-
- for ( int i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.cfg.vol = 1.0f;
- ch.cfg.pan = 0.0f;
- ch.cfg.surround = false;
- ch.cfg.echo = false;
- }
- // side channels with echo
- chans [2].cfg.echo = true;
- chans [3].cfg.echo = true;
-
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
- apply_config();
- clear();
-
- return blargg_ok;
-}
-
-void Effects_Buffer::clear_echo()
-{
- if ( echo.size() )
- memset( echo.begin(), 0, echo.size() * sizeof echo [0] );
-}
-
-void Effects_Buffer::clear()
-{
- echo_pos = 0;
- s.low_pass [0] = 0;
- s.low_pass [1] = 0;
- mixer.samples_read = 0;
-
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clear();
- clear_echo();
-}
-
-Effects_Buffer::channel_t Effects_Buffer::channel( int i )
-{
- i += extra_chans;
- require( extra_chans <= i && i < (int) chans.size() );
- return chans [i].channel;
-}
-
-
-// Configuration
-
-// 3 wave positions with/without surround, 2 multi (one with same config as wave)
-int const simple_bufs = 3 * 2 + 2 - 1;
-
-Simple_Effects_Buffer::Simple_Effects_Buffer() :
- Effects_Buffer( extra_chans + simple_bufs, 18 * 1024 )
-{
- config_.echo = 0.20f;
- config_.stereo = 0.20f;
- config_.surround = true;
- config_.enabled = false;
-}
-
-void Simple_Effects_Buffer::apply_config()
-{
- Effects_Buffer::config_t& c = Effects_Buffer::config();
-
- c.enabled = config_.enabled;
- if ( c.enabled )
- {
- c.delay [0] = 120;
- c.delay [1] = 122;
- c.feedback = config_.echo * 0.7f;
- c.treble = 0.6f - 0.3f * config_.echo;
-
- float sep = config_.stereo + 0.80f;
- if ( sep > 1.0f )
- sep = 1.0f;
-
- c.side_chans [0].pan = -sep;
- c.side_chans [1].pan = +sep;
-
- for ( int i = channel_count(); --i >= 0; )
- {
- chan_config_t& ch = Effects_Buffer::chan_config( i );
-
- ch.pan = 0.0f;
- ch.surround = config_.surround;
- ch.echo = false;
-
- int const type = (channel_types() ? channel_types() [i] : 0);
- if ( !(type & noise_type) )
- {
- int index = (type & type_index_mask) % 6 - 3;
- if ( index < 0 )
- {
- index += 3;
- ch.surround = false;
- ch.echo = true;
- }
- if ( index >= 1 )
- {
- ch.pan = config_.stereo;
- if ( index == 1 )
- ch.pan = -ch.pan;
- }
- }
- else if ( type & 1 )
- {
- ch.surround = false;
- }
- }
- }
-
- Effects_Buffer::apply_config();
-}
-
-int Effects_Buffer::min_delay() const
-{
- require( sample_rate() );
- return max_read * 1000 / sample_rate();
-}
-
-int Effects_Buffer::max_delay() const
-{
- require( sample_rate() );
- return (echo_size / stereo - max_read) * 1000 / sample_rate();
-}
-
-void Effects_Buffer::apply_config()
-{
- int i;
-
- if ( !bufs_size )
- return;
-
- s.treble = TO_FIXED( config_.treble );
-
- bool echo_dirty = false;
-
- fixed_t old_feedback = s.feedback;
- s.feedback = TO_FIXED( config_.feedback );
- if ( !old_feedback && s.feedback )
- echo_dirty = true;
-
- // delays
- for ( i = stereo; --i >= 0; )
- {
- int delay = config_.delay [i] * sample_rate() / 1000 * stereo;
- delay = max( delay, (int) (max_read * stereo) );
- delay = min( delay, (int) (echo_size - max_read * stereo) );
- if ( s.delay [i] != delay )
- {
- s.delay [i] = delay;
- echo_dirty = true;
- }
- }
-
- // side channels
- for ( i = 2; --i >= 0; )
- {
- chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f;
- chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan;
- }
-
- // convert volumes
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan );
- ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan );
- if ( ch.cfg.surround )
- ch.vol [0] = -ch.vol [0];
- }
-
- assign_buffers();
-
- // set side channels
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.channel.left = chans [ch.cfg.echo*2 ].channel.center;
- ch.channel.right = chans [ch.cfg.echo*2+1].channel.center;
- }
-
- bool old_echo = !no_echo && !no_effects;
-
- // determine whether effects and echo are needed at all
- no_effects = true;
- no_echo = true;
- for ( i = chans.size(); --i >= extra_chans; )
- {
- chan_t& ch = chans [i];
- if ( ch.cfg.echo && s.feedback )
- no_echo = false;
-
- if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) )
- no_effects = false;
- }
- if ( !no_echo )
- no_effects = false;
-
- if ( chans [0].vol [0] != TO_FIXED( 1 ) ||
- chans [0].vol [1] != TO_FIXED( 0 ) ||
- chans [1].vol [0] != TO_FIXED( 0 ) ||
- chans [1].vol [1] != TO_FIXED( 1 ) )
- no_effects = false;
-
- if ( !config_.enabled )
- no_effects = true;
-
- if ( no_effects )
- {
- for ( i = chans.size(); --i >= 0; )
- {
- chan_t& ch = chans [i];
- ch.channel.center = &bufs [2];
- ch.channel.left = &bufs [0];
- ch.channel.right = &bufs [1];
- }
- }
-
- mixer.bufs [0] = &bufs [0];
- mixer.bufs [1] = &bufs [1];
- mixer.bufs [2] = &bufs [2];
-
- if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) )
- clear_echo();
-
- channels_changed();
-}
-
-void Effects_Buffer::assign_buffers()
-{
- // assign channels to buffers
- int buf_count = 0;
- for ( int i = 0; i < (int) chans.size(); i++ )
- {
- // put second two side channels at end to give priority to main channels
- // in case closest matching is necessary
- int x = i;
- if ( i > 1 )
- x += 2;
- if ( x >= (int) chans.size() )
- x -= (chans.size() - 2);
- chan_t& ch = chans [x];
-
- int b = 0;
- for ( ; b < buf_count; b++ )
- {
- if ( ch.vol [0] == bufs [b].vol [0] &&
- ch.vol [1] == bufs [b].vol [1] &&
- (ch.cfg.echo == bufs [b].echo || !s.feedback) )
- break;
- }
-
- if ( b >= buf_count )
- {
- if ( buf_count < bufs_max )
- {
- bufs [b].vol [0] = ch.vol [0];
- bufs [b].vol [1] = ch.vol [1];
- bufs [b].echo = ch.cfg.echo;
- buf_count++;
- }
- else
- {
- // TODO: this is a mess, needs refinement
- dprintf( "Effects_Buffer ran out of buffers; using closest match\n" );
- b = 0;
- fixed_t best_dist = TO_FIXED( 8 );
- for ( int h = buf_count; --h >= 0; )
- {
- #define CALC_LEVELS( vols, sum, diff, surround ) \
- fixed_t sum, diff;\
- bool surround = false;\
- {\
- fixed_t vol_0 = vols [0];\
- if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\
- fixed_t vol_1 = vols [1];\
- if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\
- sum = vol_0 + vol_1;\
- diff = vol_0 - vol_1;\
- }
- CALC_LEVELS( ch.vol, ch_sum, ch_diff, ch_surround );
- CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround );
-
- fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff );
-
- if ( ch_surround != buf_surround )
- dist += TO_FIXED( 1 ) / 2;
-
- if ( s.feedback && ch.cfg.echo != bufs [h].echo )
- dist += TO_FIXED( 1 ) / 2;
-
- if ( best_dist > dist )
- {
- best_dist = dist;
- b = h;
- }
- }
- }
- }
-
- //dprintf( "ch %d->buf %d\n", x, b );
- ch.channel.center = &bufs [b];
- }
-}
-
-
-// Mixing
-
-void Effects_Buffer::end_frame( blip_time_t time )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].end_frame( time );
-}
-
-int Effects_Buffer::read_samples( blip_sample_t out [], int out_size )
-{
- out_size = min( out_size, samples_avail() );
-
- int pair_count = int (out_size >> 1);
- require( pair_count * stereo == out_size ); // must read an even number of samples
- if ( pair_count )
- {
- if ( no_effects )
- {
- mixer.read_pairs( out, pair_count );
- }
- else
- {
- int pairs_remain = pair_count;
- do
- {
- // mix at most max_read pairs at a time
- int count = max_read;
- if ( count > pairs_remain )
- count = pairs_remain;
-
- if ( no_echo )
- {
- // optimization: clear echo here to keep mix_effects() a leaf function
- echo_pos = 0;
- memset( echo.begin(), 0, count * stereo * sizeof echo [0] );
- }
- mix_effects( out, count );
-
- int new_echo_pos = echo_pos + count * stereo;
- if ( new_echo_pos >= echo_size )
- new_echo_pos -= echo_size;
- echo_pos = new_echo_pos;
- assert( echo_pos < echo_size );
-
- out += count * stereo;
- mixer.samples_read += count;
- pairs_remain -= count;
- }
- while ( pairs_remain );
- }
-
- if ( samples_avail() <= 0 || immediate_removal() )
- {
- for ( int i = bufs_size; --i >= 0; )
- {
- buf_t& b = bufs [i];
- // TODO: might miss non-silence settling since it checks END of last read
- if ( b.non_silent() )
- b.remove_samples( mixer.samples_read );
- else
- b.remove_silence( mixer.samples_read );
- }
- mixer.samples_read = 0;
- }
- }
- return out_size;
-}
-
-void Effects_Buffer::mix_effects( blip_sample_t out_ [], int pair_count )
-{
- typedef fixed_t stereo_fixed_t [stereo];
-
- // add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
- int echo_phase = 1;
- do
- {
- // mix any modified buffers
- {
- buf_t* buf = bufs;
- int bufs_remain = bufs_size;
- do
- {
- if ( buf->non_silent() && buf->echo == echo_phase )
- {
- stereo_fixed_t* BLARGG_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
- int const bass = BLIP_READER_BASS( *buf );
- BLIP_READER_BEGIN( in, *buf );
- BLIP_READER_ADJ_( in, mixer.samples_read );
- fixed_t const vol_0 = buf->vol [0];
- fixed_t const vol_1 = buf->vol [1];
-
- int count = (unsigned) (echo_size - echo_pos) / stereo;
- int remain = pair_count;
- if ( count > remain )
- count = remain;
- do
- {
- remain -= count;
- BLIP_READER_ADJ_( in, count );
-
- out += count;
- int offset = -count;
- do
- {
- fixed_t s = BLIP_READER_READ( in );
- BLIP_READER_NEXT_IDX_( in, bass, offset );
-
- out [offset] [0] += s * vol_0;
- out [offset] [1] += s * vol_1;
- }
- while ( ++offset );
-
- out = (stereo_fixed_t*) echo.begin();
- count = remain;
- }
- while ( remain );
-
- BLIP_READER_END( in, *buf );
- }
- buf++;
- }
- while ( --bufs_remain );
- }
-
- // add echo
- if ( echo_phase && !no_echo )
- {
- fixed_t const feedback = s.feedback;
- fixed_t const treble = s.treble;
-
- int i = 1;
- do
- {
- fixed_t low_pass = s.low_pass [i];
-
- fixed_t* echo_end = &echo [echo_size + i];
- fixed_t const* BLARGG_RESTRICT in_pos = &echo [echo_pos + i];
- int out_offset = echo_pos + i + s.delay [i];
- if ( out_offset >= echo_size )
- out_offset -= echo_size;
- assert( out_offset < echo_size );
- fixed_t* BLARGG_RESTRICT out_pos = &echo [out_offset];
-
- // break into up to three chunks to avoid having to handle wrap-around
- // in middle of core loop
- int remain = pair_count;
- do
- {
- fixed_t const* pos = in_pos;
- if ( pos < out_pos )
- pos = out_pos;
- int count = (unsigned) ((char*) echo_end - (char const*) pos) /
- (unsigned) (stereo * sizeof (fixed_t));
- if ( count > remain )
- count = remain;
- remain -= count;
-
- in_pos += count * stereo;
- out_pos += count * stereo;
- int offset = -count;
- do
- {
- low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble;
- out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback;
- }
- while ( ++offset );
-
- if ( in_pos >= echo_end ) in_pos -= echo_size;
- if ( out_pos >= echo_end ) out_pos -= echo_size;
- }
- while ( remain );
-
- s.low_pass [i] = low_pass;
- }
- while ( --i >= 0 );
- }
- }
- while ( --echo_phase >= 0 );
-
- // clamp to 16 bits
- {
- stereo_fixed_t const* BLARGG_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos];
- typedef blip_sample_t stereo_blip_sample_t [stereo];
- stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_;
- int count = (unsigned) (echo_size - echo_pos) / (unsigned) stereo;
- int remain = pair_count;
- if ( count > remain )
- count = remain;
- do
- {
- remain -= count;
- in += count;
- out += count;
- int offset = -count;
- do
- {
- fixed_t in_0 = FROM_FIXED( in [offset] [0] );
- fixed_t in_1 = FROM_FIXED( in [offset] [1] );
-
- BLIP_CLAMP( in_0, in_0 );
- out [offset] [0] = (blip_sample_t) in_0;
-
- BLIP_CLAMP( in_1, in_1 );
- out [offset] [1] = (blip_sample_t) in_1;
- }
- while ( ++offset );
-
- in = (stereo_fixed_t*) echo.begin();
- count = remain;
- }
- while ( remain );
- }
-}
+Effects_Buffer::Effects_Buffer( int max_bufs, int echo_size_ ) : Multi_Buffer( stereo )
+{
+ echo_size = max( max_read * (int) stereo, echo_size_ & ~1 );
+ clock_rate_ = 0;
+ bass_freq_ = 90;
+ bufs = NULL;
+ bufs_size = 0;
+ bufs_max = max( max_bufs, (int) extra_chans );
+ no_echo = true;
+ no_effects = true;
+
+ // defaults
+ config_.enabled = false;
+ config_.delay [0] = 120;
+ config_.delay [1] = 122;
+ config_.feedback = 0.2f;
+ config_.treble = 0.4f;
+
+ static float const sep = 0.8f;
+ config_.side_chans [0].pan = -sep;
+ config_.side_chans [1].pan = +sep;
+ config_.side_chans [0].vol = 1.0f;
+ config_.side_chans [1].vol = 1.0f;
+
+ memset( &s, 0, sizeof s );
+ clear();
+}
+
+Effects_Buffer::~Effects_Buffer()
+{
+ delete_bufs();
+}
+
+// avoid using new []
+blargg_err_t Effects_Buffer::new_bufs( int size )
+{
+ bufs = (buf_t*) malloc( size * sizeof *bufs );
+ CHECK_ALLOC( bufs );
+ for ( int i = 0; i < size; i++ )
+ new (bufs + i) buf_t;
+ bufs_size = size;
+ return blargg_ok;
+}
+
+void Effects_Buffer::delete_bufs()
+{
+ if ( bufs )
+ {
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].~buf_t();
+ free( bufs );
+ bufs = NULL;
+ }
+ bufs_size = 0;
+}
+
+blargg_err_t Effects_Buffer::set_sample_rate( int rate, int msec )
+{
+ // extra to allow farther past-the-end pointers
+ mixer.samples_read = 0;
+ RETURN_ERR( echo.resize( echo_size + stereo ) );
+ return Multi_Buffer::set_sample_rate( rate, msec );
+}
+
+void Effects_Buffer::clock_rate( int rate )
+{
+ clock_rate_ = rate;
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].clock_rate( clock_rate_ );
+}
+
+void Effects_Buffer::bass_freq( int freq )
+{
+ bass_freq_ = freq;
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].bass_freq( bass_freq_ );
+}
+
+blargg_err_t Effects_Buffer::set_channel_count( int count, int const types [] )
+{
+ RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) );
+
+ delete_bufs();
+
+ mixer.samples_read = 0;
+
+ RETURN_ERR( chans.resize( count + extra_chans ) );
+
+ RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) );
+
+ for ( int i = bufs_size; --i >= 0; )
+ RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) );
+
+ for ( int i = chans.size(); --i >= 0; )
+ {
+ chan_t& ch = chans [i];
+ ch.cfg.vol = 1.0f;
+ ch.cfg.pan = 0.0f;
+ ch.cfg.surround = false;
+ ch.cfg.echo = false;
+ }
+ // side channels with echo
+ chans [2].cfg.echo = true;
+ chans [3].cfg.echo = true;
+
+ clock_rate( clock_rate_ );
+ bass_freq( bass_freq_ );
+ apply_config();
+ clear();
+
+ return blargg_ok;
+}
+
+void Effects_Buffer::clear_echo()
+{
+ if ( echo.size() )
+ memset( echo.begin(), 0, echo.size() * sizeof echo [0] );
+}
+
+void Effects_Buffer::clear()
+{
+ echo_pos = 0;
+ s.low_pass [0] = 0;
+ s.low_pass [1] = 0;
+ mixer.samples_read = 0;
+
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].clear();
+ clear_echo();
+}
+
+Effects_Buffer::channel_t Effects_Buffer::channel( int i )
+{
+ i += extra_chans;
+ require( extra_chans <= i && i < (int) chans.size() );
+ return chans [i].channel;
+}
+
+
+// Configuration
+
+// 3 wave positions with/without surround, 2 multi (one with same config as wave)
+int const simple_bufs = 3 * 2 + 2 - 1;
+
+Simple_Effects_Buffer::Simple_Effects_Buffer() :
+ Effects_Buffer( extra_chans + simple_bufs, 18 * 1024 )
+{
+ config_.echo = 0.20f;
+ config_.stereo = 0.20f;
+ config_.surround = true;
+ config_.enabled = false;
+}
+
+void Simple_Effects_Buffer::apply_config()
+{
+ Effects_Buffer::config_t& c = Effects_Buffer::config();
+
+ c.enabled = config_.enabled;
+ if ( c.enabled )
+ {
+ c.delay [0] = 120;
+ c.delay [1] = 122;
+ c.feedback = config_.echo * 0.7f;
+ c.treble = 0.6f - 0.3f * config_.echo;
+
+ float sep = config_.stereo + 0.80f;
+ if ( sep > 1.0f )
+ sep = 1.0f;
+
+ c.side_chans [0].pan = -sep;
+ c.side_chans [1].pan = +sep;
+
+ for ( int i = channel_count(); --i >= 0; )
+ {
+ chan_config_t& ch = Effects_Buffer::chan_config( i );
+
+ ch.pan = 0.0f;
+ ch.surround = config_.surround;
+ ch.echo = false;
+
+ int const type = (channel_types() ? channel_types() [i] : 0);
+ if ( !(type & noise_type) )
+ {
+ int index = (type & type_index_mask) % 6 - 3;
+ if ( index < 0 )
+ {
+ index += 3;
+ ch.surround = false;
+ ch.echo = true;
+ }
+ if ( index >= 1 )
+ {
+ ch.pan = config_.stereo;
+ if ( index == 1 )
+ ch.pan = -ch.pan;
+ }
+ }
+ else if ( type & 1 )
+ {
+ ch.surround = false;
+ }
+ }
+ }
+
+ Effects_Buffer::apply_config();
+}
+
+int Effects_Buffer::min_delay() const
+{
+ require( sample_rate() );
+ return max_read * 1000 / sample_rate();
+}
+
+int Effects_Buffer::max_delay() const
+{
+ require( sample_rate() );
+ return (echo_size / stereo - max_read) * 1000 / sample_rate();
+}
+
+void Effects_Buffer::apply_config()
+{
+ int i;
+
+ if ( !bufs_size )
+ return;
+
+ s.treble = TO_FIXED( config_.treble );
+
+ bool echo_dirty = false;
+
+ fixed_t old_feedback = s.feedback;
+ s.feedback = TO_FIXED( config_.feedback );
+ if ( !old_feedback && s.feedback )
+ echo_dirty = true;
+
+ // delays
+ for ( i = stereo; --i >= 0; )
+ {
+ int delay = config_.delay [i] * sample_rate() / 1000 * stereo;
+ delay = max( delay, (int) (max_read * stereo) );
+ delay = min( delay, (int) (echo_size - max_read * stereo) );
+ if ( s.delay [i] != delay )
+ {
+ s.delay [i] = delay;
+ echo_dirty = true;
+ }
+ }
+
+ // side channels
+ for ( i = 2; --i >= 0; )
+ {
+ chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f;
+ chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan;
+ }
+
+ // convert volumes
+ for ( i = chans.size(); --i >= 0; )
+ {
+ chan_t& ch = chans [i];
+ ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan );
+ ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan );
+ if ( ch.cfg.surround )
+ ch.vol [0] = -ch.vol [0];
+ }
+
+ assign_buffers();
+
+ // set side channels
+ for ( i = chans.size(); --i >= 0; )
+ {
+ chan_t& ch = chans [i];
+ ch.channel.left = chans [ch.cfg.echo*2 ].channel.center;
+ ch.channel.right = chans [ch.cfg.echo*2+1].channel.center;
+ }
+
+ bool old_echo = !no_echo && !no_effects;
+
+ // determine whether effects and echo are needed at all
+ no_effects = true;
+ no_echo = true;
+ for ( i = chans.size(); --i >= extra_chans; )
+ {
+ chan_t& ch = chans [i];
+ if ( ch.cfg.echo && s.feedback )
+ no_echo = false;
+
+ if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) )
+ no_effects = false;
+ }
+ if ( !no_echo )
+ no_effects = false;
+
+ if ( chans [0].vol [0] != TO_FIXED( 1 ) ||
+ chans [0].vol [1] != TO_FIXED( 0 ) ||
+ chans [1].vol [0] != TO_FIXED( 0 ) ||
+ chans [1].vol [1] != TO_FIXED( 1 ) )
+ no_effects = false;
+
+ if ( !config_.enabled )
+ no_effects = true;
+
+ if ( no_effects )
+ {
+ for ( i = chans.size(); --i >= 0; )
+ {
+ chan_t& ch = chans [i];
+ ch.channel.center = &bufs [2];
+ ch.channel.left = &bufs [0];
+ ch.channel.right = &bufs [1];
+ }
+ }
+
+ mixer.bufs [0] = &bufs [0];
+ mixer.bufs [1] = &bufs [1];
+ mixer.bufs [2] = &bufs [2];
+
+ if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) )
+ clear_echo();
+
+ channels_changed();
+}
+
+void Effects_Buffer::assign_buffers()
+{
+ // assign channels to buffers
+ int buf_count = 0;
+ for ( int i = 0; i < (int) chans.size(); i++ )
+ {
+ // put second two side channels at end to give priority to main channels
+ // in case closest matching is necessary
+ int x = i;
+ if ( i > 1 )
+ x += 2;
+ if ( x >= (int) chans.size() )
+ x -= (chans.size() - 2);
+ chan_t& ch = chans [x];
+
+ int b = 0;
+ for ( ; b < buf_count; b++ )
+ {
+ if ( ch.vol [0] == bufs [b].vol [0] &&
+ ch.vol [1] == bufs [b].vol [1] &&
+ (ch.cfg.echo == bufs [b].echo || !s.feedback) )
+ break;
+ }
+
+ if ( b >= buf_count )
+ {
+ if ( buf_count < bufs_max )
+ {
+ bufs [b].vol [0] = ch.vol [0];
+ bufs [b].vol [1] = ch.vol [1];
+ bufs [b].echo = ch.cfg.echo;
+ buf_count++;
+ }
+ else
+ {
+ // TODO: this is a mess, needs refinement
+ dprintf( "Effects_Buffer ran out of buffers; using closest match\n" );
+ b = 0;
+ fixed_t best_dist = TO_FIXED( 8 );
+ for ( int h = buf_count; --h >= 0; )
+ {
+ #define CALC_LEVELS( vols, sum, diff, surround ) \
+ fixed_t sum, diff;\
+ bool surround = false;\
+ {\
+ fixed_t vol_0 = vols [0];\
+ if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\
+ fixed_t vol_1 = vols [1];\
+ if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\
+ sum = vol_0 + vol_1;\
+ diff = vol_0 - vol_1;\
+ }
+ CALC_LEVELS( ch.vol, ch_sum, ch_diff, ch_surround );
+ CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround );
+
+ fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff );
+
+ if ( ch_surround != buf_surround )
+ dist += TO_FIXED( 1 ) / 2;
+
+ if ( s.feedback && ch.cfg.echo != bufs [h].echo )
+ dist += TO_FIXED( 1 ) / 2;
+
+ if ( best_dist > dist )
+ {
+ best_dist = dist;
+ b = h;
+ }
+ }
+ }
+ }
+
+ //dprintf( "ch %d->buf %d\n", x, b );
+ ch.channel.center = &bufs [b];
+ }
+}
+
+
+// Mixing
+
+void Effects_Buffer::end_frame( blip_time_t time )
+{
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].end_frame( time );
+}
+
+int Effects_Buffer::read_samples( blip_sample_t out [], int out_size )
+{
+ out_size = min( out_size, samples_avail() );
+
+ int pair_count = int (out_size >> 1);
+ require( pair_count * stereo == out_size ); // must read an even number of samples
+ if ( pair_count )
+ {
+ if ( no_effects )
+ {
+ mixer.read_pairs( out, pair_count );
+ }
+ else
+ {
+ int pairs_remain = pair_count;
+ do
+ {
+ // mix at most max_read pairs at a time
+ int count = max_read;
+ if ( count > pairs_remain )
+ count = pairs_remain;
+
+ if ( no_echo )
+ {
+ // optimization: clear echo here to keep mix_effects() a leaf function
+ echo_pos = 0;
+ memset( echo.begin(), 0, count * stereo * sizeof echo [0] );
+ }
+ mix_effects( out, count );
+
+ int new_echo_pos = echo_pos + count * stereo;
+ if ( new_echo_pos >= echo_size )
+ new_echo_pos -= echo_size;
+ echo_pos = new_echo_pos;
+ assert( echo_pos < echo_size );
+
+ out += count * stereo;
+ mixer.samples_read += count;
+ pairs_remain -= count;
+ }
+ while ( pairs_remain );
+ }
+
+ if ( samples_avail() <= 0 || immediate_removal() )
+ {
+ for ( int i = bufs_size; --i >= 0; )
+ {
+ buf_t& b = bufs [i];
+ // TODO: might miss non-silence settling since it checks END of last read
+ if ( b.non_silent() )
+ b.remove_samples( mixer.samples_read );
+ else
+ b.remove_silence( mixer.samples_read );
+ }
+ mixer.samples_read = 0;
+ }
+ }
+ return out_size;
+}
+
+void Effects_Buffer::mix_effects( blip_sample_t out_ [], int pair_count )
+{
+ typedef fixed_t stereo_fixed_t [stereo];
+
+ // add channels with echo, do echo, add channels without echo, then convert to 16-bit and output
+ int echo_phase = 1;
+ do
+ {
+ // mix any modified buffers
+ {
+ buf_t* buf = bufs;
+ int bufs_remain = bufs_size;
+ do
+ {
+ if ( buf->non_silent() && buf->echo == echo_phase )
+ {
+ stereo_fixed_t* BLARGG_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos];
+ int const bass = BLIP_READER_BASS( *buf );
+ BLIP_READER_BEGIN( in, *buf );
+ BLIP_READER_ADJ_( in, mixer.samples_read );
+ fixed_t const vol_0 = buf->vol [0];
+ fixed_t const vol_1 = buf->vol [1];
+
+ int count = (unsigned) (echo_size - echo_pos) / stereo;
+ int remain = pair_count;
+ if ( count > remain )
+ count = remain;
+ do
+ {
+ remain -= count;
+ BLIP_READER_ADJ_( in, count );
+
+ out += count;
+ int offset = -count;
+ do
+ {
+ fixed_t s = BLIP_READER_READ( in );
+ BLIP_READER_NEXT_IDX_( in, bass, offset );
+
+ out [offset] [0] += s * vol_0;
+ out [offset] [1] += s * vol_1;
+ }
+ while ( ++offset );
+
+ out = (stereo_fixed_t*) echo.begin();
+ count = remain;
+ }
+ while ( remain );
+
+ BLIP_READER_END( in, *buf );
+ }
+ buf++;
+ }
+ while ( --bufs_remain );
+ }
+
+ // add echo
+ if ( echo_phase && !no_echo )
+ {
+ fixed_t const feedback = s.feedback;
+ fixed_t const treble = s.treble;
+
+ int i = 1;
+ do
+ {
+ fixed_t low_pass = s.low_pass [i];
+
+ fixed_t* echo_end = &echo [echo_size + i];
+ fixed_t const* BLARGG_RESTRICT in_pos = &echo [echo_pos + i];
+ int out_offset = echo_pos + i + s.delay [i];
+ if ( out_offset >= echo_size )
+ out_offset -= echo_size;
+ assert( out_offset < echo_size );
+ fixed_t* BLARGG_RESTRICT out_pos = &echo [out_offset];
+
+ // break into up to three chunks to avoid having to handle wrap-around
+ // in middle of core loop
+ int remain = pair_count;
+ do
+ {
+ fixed_t const* pos = in_pos;
+ if ( pos < out_pos )
+ pos = out_pos;
+ int count = (unsigned) ((char*) echo_end - (char const*) pos) /
+ (unsigned) (stereo * sizeof (fixed_t));
+ if ( count > remain )
+ count = remain;
+ remain -= count;
+
+ in_pos += count * stereo;
+ out_pos += count * stereo;
+ int offset = -count;
+ do
+ {
+ low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble;
+ out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback;
+ }
+ while ( ++offset );
+
+ if ( in_pos >= echo_end ) in_pos -= echo_size;
+ if ( out_pos >= echo_end ) out_pos -= echo_size;
+ }
+ while ( remain );
+
+ s.low_pass [i] = low_pass;
+ }
+ while ( --i >= 0 );
+ }
+ }
+ while ( --echo_phase >= 0 );
+
+ // clamp to 16 bits
+ {
+ stereo_fixed_t const* BLARGG_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos];
+ typedef blip_sample_t stereo_blip_sample_t [stereo];
+ stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_;
+ int count = (unsigned) (echo_size - echo_pos) / (unsigned) stereo;
+ int remain = pair_count;
+ if ( count > remain )
+ count = remain;
+ do
+ {
+ remain -= count;
+ in += count;
+ out += count;
+ int offset = -count;
+ do
+ {
+ fixed_t in_0 = FROM_FIXED( in [offset] [0] );
+ fixed_t in_1 = FROM_FIXED( in [offset] [1] );
+
+ BLIP_CLAMP( in_0, in_0 );
+ out [offset] [0] = (blip_sample_t) in_0;
+
+ BLIP_CLAMP( in_1, in_1 );
+ out [offset] [1] = (blip_sample_t) in_1;
+ }
+ while ( ++offset );
+
+ in = (stereo_fixed_t*) echo.begin();
+ count = remain;
+ }
+ while ( remain );
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/emuconfig.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/emuconfig.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/emuconfig.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/emuconfig.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,78 +1,78 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// Configuration for emulation libraries
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef __EMUCONFIG_H__
-#define __EMUCONFIG_H__
-
-/////////////////////////////////////////////////////////////////////////////
-
-#include
-#include
-#include
-#include
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// WIN32 native project definitions
-//
-/////////////////////////////////////////////////////////////////////////////
-#if defined(WIN32) && !defined(__GNUC__)
-
-#define EMU_CALL __fastcall
-#define EMU_CALL_ __cdecl
-#define EMU_INLINE __inline
-
-#define uint8 unsigned char
-#define uint16 unsigned short
-#define uint32 unsigned int
-#define uint64 unsigned __int64
-#define sint8 signed char
-#define sint16 signed short
-#define sint32 signed int
-#define sint64 signed __int64
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// LINUX / other platform definitions
-//
-/////////////////////////////////////////////////////////////////////////////
-#else
-
-//#if defined(__GNUC__) && defined(__i386__)
-//#define EMU_CALL __attribute__((__regparm__(2)))
-//#else
-#define EMU_CALL
-//#endif
-
-#define EMU_CALL_
-#define EMU_INLINE __inline
-
-#ifdef HAVE_STDINT_H
-#include
-#define uint8 uint8_t
-#define uint16 uint16_t
-#define uint32 uint32_t
-#define uint64 uint64_t
-#define sint8 int8_t
-#define sint16 int16_t
-#define sint32 int32_t
-#define sint64 int64_t
-#else
-#define uint8 unsigned char
-#define uint16 unsigned short
-#define uint32 unsigned int
-#define uint64 unsigned long long
-#define sint8 signed char
-#define sint16 signed short
-#define sint32 signed int
-#define sint64 signed long long
-#endif
-
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
-#endif
+/////////////////////////////////////////////////////////////////////////////
+//
+// Configuration for emulation libraries
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __EMUCONFIG_H__
+#define __EMUCONFIG_H__
+
+/////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+#include
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// WIN32 native project definitions
+//
+/////////////////////////////////////////////////////////////////////////////
+#if defined(WIN32) && !defined(__GNUC__)
+
+#define EMU_CALL __fastcall
+#define EMU_CALL_ __cdecl
+#define EMU_INLINE __inline
+
+#define uint8 unsigned char
+#define uint16 unsigned short
+#define uint32 unsigned int
+#define uint64 unsigned __int64
+#define sint8 signed char
+#define sint16 signed short
+#define sint32 signed int
+#define sint64 signed __int64
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// LINUX / other platform definitions
+//
+/////////////////////////////////////////////////////////////////////////////
+#else
+
+//#if defined(__GNUC__) && defined(__i386__)
+//#define EMU_CALL __attribute__((__regparm__(2)))
+//#else
+#define EMU_CALL
+//#endif
+
+#define EMU_CALL_
+#define EMU_INLINE __inline
+
+#ifdef HAVE_STDINT_H
+#include
+#define uint8 uint8_t
+#define uint16 uint16_t
+#define uint32 uint32_t
+#define uint64 uint64_t
+#define sint8 int8_t
+#define sint16 int16_t
+#define sint32 int32_t
+#define sint64 int64_t
+#else
+#define uint8 unsigned char
+#define uint16 unsigned short
+#define uint32 unsigned int
+#define uint64 unsigned long long
+#define sint8 signed char
+#define sint16 signed short
+#define sint32 signed int
+#define sint64 signed long long
+#endif
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/fmopl.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/fmopl.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/fmopl.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/fmopl.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,2621 +1,2621 @@
-/*
-**
-** File: fmopl.c - software implementation of FM sound generator
-** types OPL and OPL2
-**
-** Copyright Jarek Burczynski (bujar at mame dot net)
-** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development
-**
-** Version 0.72
-**
-
-Revision History:
-
-04-08-2003 Jarek Burczynski:
- - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip
- handles memory read/write or during the adpcm synthesis when the chip
- requests another byte of ADPCM data.
-
-24-07-2003 Jarek Burczynski:
- - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after
- some (unknown) delay). Right now it's always set.
-
-14-06-2003 Jarek Burczynski:
- - implemented all of the status register flags in Y8950 emulation
- - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since
- they can be either RAM or ROM
-
-08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip)
- - corrected ym3526_read() to always set bit 2 and bit 1
- to HIGH state - identical to ym3812_read (verified on real YM3526)
-
-04-28-2002 Jarek Burczynski:
- - binary exact Envelope Generator (verified on real YM3812);
- compared to YM2151: the EG clock is equal to internal_clock,
- rates are 2 times slower and volume resolution is one bit less
- - modified interface functions (they no longer return pointer -
- that's internal to the emulator now):
- - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init()
- - corrected 'off by one' error in feedback calculations (when feedback is off)
- - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)
- - speeded up noise generator calculations (Nicola Salmoria)
-
-03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)
- Complete rewrite (all verified on real YM3812):
- - corrected sin_tab and tl_tab data
- - corrected operator output calculations
- - corrected waveform_select_enable register;
- simply: ignore all writes to waveform_select register when
- waveform_select_enable == 0 and do not change the waveform previously selected.
- - corrected KSR handling
- - corrected Envelope Generator: attack shape, Sustain mode and
- Percussive/Non-percussive modes handling
- - Envelope Generator rates are two times slower now
- - LFO amplitude (tremolo) and phase modulation (vibrato)
- - rhythm sounds phase generation
- - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)
- - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)
- - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)
-
-12-28-2001 Acho A. Tang
- - reflected Delta-T EOS status on Y8950 status port.
- - fixed subscription range of attack/decay tables
-
-
- To do:
- add delay before key off in CSM mode (see CSMKeyControll)
- verify volume of the FM part on the Y8950
-*/
-
-#include
-#include
-#define _USE_MATH_DEFINES
-#include
-#include "fmopl.h"
-#include "ymdeltat.h"
-
-#ifndef INLINE
-#define INLINE __inline
-#endif
-#ifndef NULL
- #define NULL ((void *)0)
-#endif
-#ifndef logerror
-#define logerror (void)
-#endif
-
-#ifndef M_PI
- #define M_PI 3.14159265358979323846
-#endif
-
-/* output final shift */
-#if (OPL_SAMPLE_BITS==16)
- #define FINAL_SH (0)
- #define MAXOUT (+32767)
- #define MINOUT (-32768)
-#else
- #define FINAL_SH (8)
- #define MAXOUT (+127)
- #define MINOUT (-128)
-#endif
-
-
-#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
-#define EG_SH 16 /* 16.16 fixed point (EG timing) */
-#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
-#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
-
-#define FREQ_MASK ((1<=0)
- {
- if (value < 0x0200)
- return (value & ~0);
- if (value < 0x0400)
- return (value & ~1);
- if (value < 0x0800)
- return (value & ~3);
- if (value < 0x1000)
- return (value & ~7);
- if (value < 0x2000)
- return (value & ~15);
- if (value < 0x4000)
- return (value & ~31);
- return (value & ~63);
- }
- /*else value < 0*/
- if (value > -0x0200)
- return (~abs(value) & ~0);
- if (value > -0x0400)
- return (~abs(value) & ~1);
- if (value > -0x0800)
- return (~abs(value) & ~3);
- if (value > -0x1000)
- return (~abs(value) & ~7);
- if (value > -0x2000)
- return (~abs(value) & ~15);
- if (value > -0x4000)
- return (~abs(value) & ~31);
- return (~abs(value) & ~63);
-}
-
-
-static FILE *sample[1];
- #if 1 /*save to MONO file */
- #define SAVE_ALL_CHANNELS \
- { signed int pom = acc_calc(lt); \
- fputc((unsigned short)pom&0xff,sample[0]); \
- fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
- }
- #else /*save to STEREO file */
- #define SAVE_ALL_CHANNELS \
- { signed int pom = lt; \
- fputc((unsigned short)pom&0xff,sample[0]); \
- fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
- pom = rt; \
- fputc((unsigned short)pom&0xff,sample[0]); \
- fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
- }
- #endif
-#endif
-
-#define LOG_CYM_FILE 0
-//static FILE * cymfile = NULL;
-
-
-
-#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
-#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
-#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
-#define OPL_TYPE_IO 0x08 /* I/O port */
-
-/* ---------- Generic interface section ---------- */
-#define OPL_TYPE_YM3526 (0)
-#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
-#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
-
-
-
-typedef struct{
- UINT32 ar; /* attack rate: AR<<2 */
- UINT32 dr; /* decay rate: DR<<2 */
- UINT32 rr; /* release rate:RR<<2 */
- UINT8 KSR; /* key scale rate */
- UINT8 ksl; /* keyscale level */
- UINT8 ksr; /* key scale rate: kcode>>KSR */
- UINT8 mul; /* multiple: mul_tab[ML] */
-
- /* Phase Generator */
- UINT32 Cnt; /* frequency counter */
- UINT32 Incr; /* frequency counter step */
- UINT8 FB; /* feedback shift value */
- INT32 *connect1; /* slot1 output pointer */
- INT32 op1_out[2]; /* slot1 output for feedback */
- UINT8 CON; /* connection (algorithm) type */
-
- /* Envelope Generator */
- UINT8 eg_type; /* percussive/non-percussive mode */
- UINT8 state; /* phase type */
- UINT32 TL; /* total level: TL << 2 */
- INT32 TLL; /* adjusted now TL */
- INT32 volume; /* envelope counter */
- UINT32 sl; /* sustain level: sl_tab[SL] */
- UINT8 eg_sh_ar; /* (attack state) */
- UINT8 eg_sel_ar; /* (attack state) */
- UINT8 eg_sh_dr; /* (decay state) */
- UINT8 eg_sel_dr; /* (decay state) */
- UINT8 eg_sh_rr; /* (release state) */
- UINT8 eg_sel_rr; /* (release state) */
- UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */
-
- /* LFO */
- UINT32 AMmask; /* LFO Amplitude Modulation enable mask */
- UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/
-
- /* waveform select */
- UINT16 wavetable;
-} OPL_SLOT;
-
-typedef struct{
- OPL_SLOT SLOT[2];
- /* phase generator state */
- UINT32 block_fnum; /* block+fnum */
- UINT32 fc; /* Freq. Increment base */
- UINT32 ksl_base; /* KeyScaleLevel Base step */
- UINT8 kcode; /* key code (for key scaling) */
-} OPL_CH;
-
-/* OPL state */
-typedef struct fm_opl_f {
- /* FM channel slots */
- OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
-
- UINT32 eg_cnt; /* global envelope generator counter */
- UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
- UINT32 eg_timer_add; /* step of eg_timer */
- UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
-
- UINT8 rhythm; /* Rhythm mode */
-
- UINT32 fn_tab[1024]; /* fnumber->increment counter */
-
- /* LFO */
- UINT8 lfo_am_depth;
- UINT8 lfo_pm_depth_range;
- UINT32 lfo_am_cnt;
- UINT32 lfo_am_inc;
- UINT32 lfo_pm_cnt;
- UINT32 lfo_pm_inc;
-
- UINT32 noise_rng; /* 23 bit noise shift register */
- UINT32 noise_p; /* current noise 'phase' */
- UINT32 noise_f; /* current noise period */
-
- UINT8 wavesel; /* waveform select enable flag */
-
- UINT32 T[2]; /* timer counters */
- UINT8 st[2]; /* timer enable */
-
-#if BUILD_Y8950
- /* Delta-T ADPCM unit (Y8950) */
-
- YM_DELTAT *deltat;
-
- /* Keyboard and I/O ports interface */
- UINT8 portDirection;
- UINT8 portLatch;
- OPL_PORTHANDLER_R porthandler_r;
- OPL_PORTHANDLER_W porthandler_w;
- void * port_param;
- OPL_PORTHANDLER_R keyboardhandler_r;
- OPL_PORTHANDLER_W keyboardhandler_w;
- void * keyboard_param;
-#endif
-
- /* external event callback handlers */
- //OPL_TIMERHANDLER timer_handler; /* TIMER handler */
- void *TimerParam; /* TIMER parameter */
- OPL_IRQHANDLER IRQHandler; /* IRQ handler */
- void *IRQParam; /* IRQ parameter */
- OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
- void *UpdateParam; /* stream update parameter */
-
- UINT8 type; /* chip type */
- UINT8 address; /* address register */
- UINT8 status; /* status flag */
- UINT8 statusmask; /* status mask */
- UINT8 mode; /* Reg.08 : CSM,notesel,etc. */
-
- UINT32 clock; /* master clock (Hz) */
- UINT32 rate; /* sampling rate (Hz) */
- double freqbase; /* frequency base */
- //attotime TimerBase; /* Timer base time (==sampling time)*/
-
- OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
-
- signed int phase_modulation; /* phase modulation input (SLOT 2) */
- signed int output[1];
-
-#if BUILD_Y8950
- INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
-#endif
-
- UINT32 LFO_AM;
- INT32 LFO_PM;
-} FM_OPL;
-
-
-
-/* mapping of register number (offset) to slot number used by the emulator */
-static const int slot_array[32]=
-{
- 0, 2, 4, 1, 3, 5,-1,-1,
- 6, 8,10, 7, 9,11,-1,-1,
- 12,14,16,13,15,17,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1
-};
-
-/* key scale level */
-/* table is 3dB/octave , DV converts this into 6dB/octave */
-/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
-#define DV (0.1875/2.0)
-static const UINT32 ksl_tab[8*16]=
-{
- /* OCT 0 */
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- /* OCT 1 */
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 0.750/DV), UINT32( 1.125/DV), UINT32( 1.500/DV),
- UINT32( 1.875/DV), UINT32( 2.250/DV), UINT32( 2.625/DV), UINT32( 3.000/DV),
- /* OCT 2 */
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
- UINT32( 0.000/DV), UINT32( 1.125/DV), UINT32( 1.875/DV), UINT32( 2.625/DV),
- UINT32( 3.000/DV), UINT32( 3.750/DV), UINT32( 4.125/DV), UINT32( 4.500/DV),
- UINT32( 4.875/DV), UINT32( 5.250/DV), UINT32( 5.625/DV), UINT32( 6.000/DV),
- /* OCT 3 */
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 1.875/DV),
- UINT32( 3.000/DV), UINT32( 4.125/DV), UINT32( 4.875/DV), UINT32( 5.625/DV),
- UINT32( 6.000/DV), UINT32( 6.750/DV), UINT32( 7.125/DV), UINT32( 7.500/DV),
- UINT32( 7.875/DV), UINT32( 8.250/DV), UINT32( 8.625/DV), UINT32( 9.000/DV),
- /* OCT 4 */
- UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 3.000/DV), UINT32( 4.875/DV),
- UINT32( 6.000/DV), UINT32( 7.125/DV), UINT32( 7.875/DV), UINT32( 8.625/DV),
- UINT32( 9.000/DV), UINT32( 9.750/DV), UINT32(10.125/DV), UINT32(10.500/DV),
- UINT32(10.875/DV), UINT32(11.250/DV), UINT32(11.625/DV), UINT32(12.000/DV),
- /* OCT 5 */
- UINT32( 0.000/DV), UINT32( 3.000/DV), UINT32( 6.000/DV), UINT32( 7.875/DV),
- UINT32( 9.000/DV), UINT32(10.125/DV), UINT32(10.875/DV), UINT32(11.625/DV),
- UINT32(12.000/DV), UINT32(12.750/DV), UINT32(13.125/DV), UINT32(13.500/DV),
- UINT32(13.875/DV), UINT32(14.250/DV), UINT32(14.625/DV), UINT32(15.000/DV),
- /* OCT 6 */
- UINT32( 0.000/DV), UINT32( 6.000/DV), UINT32( 9.000/DV), UINT32(10.875/DV),
- UINT32(12.000/DV), UINT32(13.125/DV), UINT32(13.875/DV), UINT32(14.625/DV),
- UINT32(15.000/DV), UINT32(15.750/DV), UINT32(16.125/DV), UINT32(16.500/DV),
- UINT32(16.875/DV), UINT32(17.250/DV), UINT32(17.625/DV), UINT32(18.000/DV),
- /* OCT 7 */
- UINT32( 0.000/DV), UINT32( 9.000/DV), UINT32(12.000/DV), UINT32(13.875/DV),
- UINT32(15.000/DV), UINT32(16.125/DV), UINT32(16.875/DV), UINT32(17.625/DV),
- UINT32(18.000/DV), UINT32(18.750/DV), UINT32(19.125/DV), UINT32(19.500/DV),
- UINT32(19.875/DV), UINT32(20.250/DV), UINT32(20.625/DV), UINT32(21.000/DV)
-};
-#undef DV
-
-/* sustain level table (3dB per step) */
-/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
-#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
-static const UINT32 sl_tab[16]={
- SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
- SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
-};
-#undef SC
-
-
-#define RATE_STEPS (8)
-static const unsigned char eg_inc[15*RATE_STEPS]={
-
-/*cycle:0 1 2 3 4 5 6 7*/
-
-/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
-/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
-/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
-/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
-
-/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
-/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
-/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
-/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
-
-/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
-/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
-/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
-/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
-
-/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
-/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
-/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
-};
-
-
-#define O(a) (a*RATE_STEPS)
-
-/*note that there is no O(13) in this table - it's directly in the code */
-static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
-/* 16 infinite time rates */
-O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
-O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
-
-/* rates 00-12 */
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-O( 0),O( 1),O( 2),O( 3),
-
-/* rate 13 */
-O( 4),O( 5),O( 6),O( 7),
-
-/* rate 14 */
-O( 8),O( 9),O(10),O(11),
-
-/* rate 15 */
-O(12),O(12),O(12),O(12),
-
-/* 16 dummy rates (same as 15 3) */
-O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
-O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
-
-};
-#undef O
-
-/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
-/*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */
-/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */
-
-#define O(a) (a*1)
-static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
-/* 16 infinite time rates */
-O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
-O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
-
-/* rates 00-12 */
-O(12),O(12),O(12),O(12),
-O(11),O(11),O(11),O(11),
-O(10),O(10),O(10),O(10),
-O( 9),O( 9),O( 9),O( 9),
-O( 8),O( 8),O( 8),O( 8),
-O( 7),O( 7),O( 7),O( 7),
-O( 6),O( 6),O( 6),O( 6),
-O( 5),O( 5),O( 5),O( 5),
-O( 4),O( 4),O( 4),O( 4),
-O( 3),O( 3),O( 3),O( 3),
-O( 2),O( 2),O( 2),O( 2),
-O( 1),O( 1),O( 1),O( 1),
-O( 0),O( 0),O( 0),O( 0),
-
-/* rate 13 */
-O( 0),O( 0),O( 0),O( 0),
-
-/* rate 14 */
-O( 0),O( 0),O( 0),O( 0),
-
-/* rate 15 */
-O( 0),O( 0),O( 0),O( 0),
-
-/* 16 dummy rates (same as 15 3) */
-O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
-O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
-
-};
-#undef O
-
-
-/* multiple table */
-#define ML 2
-static const UINT8 mul_tab[16]= {
-/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
- UINT8( 0.50*ML),UINT8( 1.00*ML),UINT8( 2.00*ML),UINT8( 3.00*ML),UINT8( 4.00*ML),UINT8( 5.00*ML),UINT8( 6.00*ML),UINT8( 7.00*ML),
- UINT8( 8.00*ML),UINT8( 9.00*ML),UINT8(10.00*ML),UINT8(10.00*ML),UINT8(12.00*ML),UINT8(12.00*ML),UINT8(15.00*ML),UINT8(15.00*ML)
-};
-#undef ML
-
-/* TL_TAB_LEN is calculated as:
-* 12 - sinus amplitude bits (Y axis)
-* 2 - sinus sign bit (Y axis)
-* TL_RES_LEN - sinus resolution (X axis)
-*/
-#define TL_TAB_LEN (12*2*TL_RES_LEN)
-static signed int tl_tab[TL_TAB_LEN];
-
-#define ENV_QUIET (TL_TAB_LEN>>4)
-
-/* sin waveform table in 'decibel' scale */
-/* four waveforms on OPL2 type chips */
-static unsigned int sin_tab[SIN_LEN * 4];
-
-
-/* LFO Amplitude Modulation table (verified on real YM3812)
- 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
-
- Length: 210 elements.
-
- Each of the elements has to be repeated
- exactly 64 times (on 64 consecutive samples).
- The whole table takes: 64 * 210 = 13440 samples.
-
- When AM = 1 data is used directly
- When AM = 0 data is divided by 4 before being used (loosing precision is important)
-*/
-
-#define LFO_AM_TAB_ELEMENTS 210
-
-static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
-0,0,0,0,0,0,0,
-1,1,1,1,
-2,2,2,2,
-3,3,3,3,
-4,4,4,4,
-5,5,5,5,
-6,6,6,6,
-7,7,7,7,
-8,8,8,8,
-9,9,9,9,
-10,10,10,10,
-11,11,11,11,
-12,12,12,12,
-13,13,13,13,
-14,14,14,14,
-15,15,15,15,
-16,16,16,16,
-17,17,17,17,
-18,18,18,18,
-19,19,19,19,
-20,20,20,20,
-21,21,21,21,
-22,22,22,22,
-23,23,23,23,
-24,24,24,24,
-25,25,25,25,
-26,26,26,
-25,25,25,25,
-24,24,24,24,
-23,23,23,23,
-22,22,22,22,
-21,21,21,21,
-20,20,20,20,
-19,19,19,19,
-18,18,18,18,
-17,17,17,17,
-16,16,16,16,
-15,15,15,15,
-14,14,14,14,
-13,13,13,13,
-12,12,12,12,
-11,11,11,11,
-10,10,10,10,
-9,9,9,9,
-8,8,8,8,
-7,7,7,7,
-6,6,6,6,
-5,5,5,5,
-4,4,4,4,
-3,3,3,3,
-2,2,2,2,
-1,1,1,1
-};
-
-/* LFO Phase Modulation table (verified on real YM3812) */
-static const INT8 lfo_pm_table[8*8*2] = {
-
-/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
-0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
-0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */
-0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
-1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */
-1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/
-2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */
-1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/
-3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */
-2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/
-4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */
-2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/
-5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */
-3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/
-6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/
-
-/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */
-3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/
-7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/
-};
-
-
-/* lock level of common table */
-//static int num_lock = 0;
-
-
-//static void *cur_chip = NULL; /* current chip pointer */
-
-INLINE int limit( int val, int max, int min ) {
- if ( val > max )
- val = max;
- else if ( val < min )
- val = min;
-
- return val;
-}
-
-
-/* status set and IRQ handling */
-INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
-{
- /* set status flag */
- OPL->status |= flag;
- if(!(OPL->status & 0x80))
- {
- if(OPL->status & OPL->statusmask)
- { /* IRQ on */
- OPL->status |= 0x80;
- /* callback user interrupt handler (IRQ is OFF to ON) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
- }
- }
-}
-
-/* status reset and IRQ handling */
-INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
-{
- /* reset status flag */
- OPL->status &=~flag;
- if((OPL->status & 0x80))
- {
- if (!(OPL->status & OPL->statusmask) )
- {
- OPL->status &= 0x7f;
- /* callback user interrupt handler (IRQ is ON to OFF) */
- if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
- }
- }
-}
-
-/* IRQ mask set */
-INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
-{
- OPL->statusmask = flag;
- /* IRQ handling check */
- OPL_STATUS_SET(OPL,0);
- OPL_STATUS_RESET(OPL,0);
-}
-
-
-/* advance LFO to next sample */
-INLINE void advance_lfo(FM_OPL *OPL)
-{
- UINT8 tmp;
-
- /* LFO */
- OPL->lfo_am_cnt += OPL->lfo_am_inc;
- if (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ];
-
- if (OPL->lfo_am_depth)
- OPL->LFO_AM = tmp;
- else
- OPL->LFO_AM = tmp>>2;
-
- OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
- OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
-}
-
-/* advance to next sample */
-INLINE void advance(FM_OPL *OPL)
-{
- OPL_CH *CH;
- OPL_SLOT *op;
- int i;
-
- OPL->eg_timer += OPL->eg_timer_add;
-
- while (OPL->eg_timer >= OPL->eg_timer_overflow)
- {
- OPL->eg_timer -= OPL->eg_timer_overflow;
-
- OPL->eg_cnt++;
-
- for (i=0; i<9*2; i++)
- {
- CH = &OPL->P_CH[i/2];
- op = &CH->SLOT[i&1];
-
- /* Envelope Generator */
- switch(op->state)
- {
- case EG_ATT: /* attack phase */
- if ( !(OPL->eg_cnt & ((1<eg_sh_ar)-1) ) )
- {
- op->volume += (~op->volume *
- (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])
- ) >>3;
-
- if (op->volume <= MIN_ATT_INDEX)
- {
- op->volume = MIN_ATT_INDEX;
- op->state = EG_DEC;
- }
-
- }
- break;
-
- case EG_DEC: /* decay phase */
- if ( !(OPL->eg_cnt & ((1<eg_sh_dr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
-
- if ( op->volume >= op->sl )
- op->state = EG_SUS;
-
- }
- break;
-
- case EG_SUS: /* sustain phase */
-
- /* this is important behaviour:
- one can change percusive/non-percussive modes on the fly and
- the chip will remain in sustain phase - verified on real YM3812 */
-
- if(op->eg_type) /* non-percussive mode */
- {
- /* do nothing */
- }
- else /* percussive mode */
- {
- /* during sustain phase chip adds Release Rate (in percussive mode) */
- if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-
- if ( op->volume >= MAX_ATT_INDEX )
- op->volume = MAX_ATT_INDEX;
- }
- /* else do nothing in sustain phase */
- }
- break;
-
- case EG_REL: /* release phase */
- if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) )
- {
- op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
-
- if ( op->volume >= MAX_ATT_INDEX )
- {
- op->volume = MAX_ATT_INDEX;
- op->state = EG_OFF;
- }
-
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- for (i=0; i<9*2; i++)
- {
- CH = &OPL->P_CH[i/2];
- op = &CH->SLOT[i&1];
-
- /* Phase Generator */
- if(op->vib)
- {
- UINT8 block;
- unsigned int block_fnum = CH->block_fnum;
-
- unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
-
- signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];
-
- if (lfo_fn_table_index_offset) /* LFO phase modulation active */
- {
- block_fnum += lfo_fn_table_index_offset;
- block = (block_fnum&0x1c00) >> 10;
- op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
- }
- else /* LFO phase modulation = zero */
- {
- op->Cnt += op->Incr;
- }
- }
- else /* LFO phase modulation disabled for this operator */
- {
- op->Cnt += op->Incr;
- }
- }
-
- /* The Noise Generator of the YM3812 is 23-bit shift register.
- * Period is equal to 2^23-2 samples.
- * Register works at sampling frequency of the chip, so output
- * can change on every sample.
- *
- * Output of the register and input to the bit 22 is:
- * bit0 XOR bit14 XOR bit15 XOR bit22
- *
- * Simply use bit 22 as the noise output.
- */
-
- OPL->noise_p += OPL->noise_f;
- i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */
- OPL->noise_p &= FREQ_MASK;
- while (i)
- {
- /*
- UINT32 j;
- j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
- OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
- */
-
- /*
- Instead of doing all the logic operations above, we
- use a trick here (and use bit 0 as the noise output).
- The difference is only that the noise bit changes one
- step ahead. This doesn't matter since we don't know
- what is real state of the noise_rng after the reset.
- */
-
- if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;
- OPL->noise_rng >>= 1;
-
- i--;
- }
-}
-
-
-INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
-{
- UINT32 p;
-
- p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
-
- if (p >= TL_TAB_LEN)
- return 0;
- return tl_tab[p];
-}
-
-INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
-{
- UINT32 p;
-
- p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ];
-
- if (p >= TL_TAB_LEN)
- return 0;
- return tl_tab[p];
-}
-
-
-#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))
-
-/* calculate output */
-INLINE void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )
-{
- OPL_SLOT *SLOT;
- unsigned int env;
- signed int out;
-
- OPL->phase_modulation = 0;
-
- /* SLOT 1 */
- SLOT = &CH->SLOT[SLOT1];
- env = volume_calc(SLOT);
- out = SLOT->op1_out[0] + SLOT->op1_out[1];
- SLOT->op1_out[0] = SLOT->op1_out[1];
- *SLOT->connect1 += SLOT->op1_out[0];
- SLOT->op1_out[1] = 0;
- if( env < ENV_QUIET )
- {
- if (!SLOT->FB)
- out = 0;
- SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable );
- }
-
- /* SLOT 2 */
- SLOT++;
- env = volume_calc(SLOT);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);
-}
-
-/*
- operators used in the rhythm sounds generation process:
-
- Envelope Generator:
-
-channel operator register number Bass High Snare Tom Top
-/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
- 6 / 0 12 50 70 90 f0 +
- 6 / 1 15 53 73 93 f3 +
- 7 / 0 13 51 71 91 f1 +
- 7 / 1 16 54 74 94 f4 +
- 8 / 0 14 52 72 92 f2 +
- 8 / 1 17 55 75 95 f5 +
-
- Phase Generator:
-
-channel operator register number Bass High Snare Tom Top
-/ slot number MULTIPLE Drum Hat Drum Tom Cymbal
- 6 / 0 12 30 +
- 6 / 1 15 33 +
- 7 / 0 13 31 + + +
- 7 / 1 16 34 ----- n o t u s e d -----
- 8 / 0 14 32 +
- 8 / 1 17 35 + +
-
-channel operator register number Bass High Snare Tom Top
-number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
- 6 12,15 B6 A6 +
-
- 7 13,16 B7 A7 + + +
-
- 8 14,17 B8 A8 + + +
-
-*/
-
-/* calculate rhythm */
-
-INLINE void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )
-{
- OPL_SLOT *SLOT;
- signed int out;
- unsigned int env;
-
-
- /* Bass Drum (verified on real YM3812):
- - depends on the channel 6 'connect' register:
- when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
- when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
- - output sample always is multiplied by 2
- */
-
- OPL->phase_modulation = 0;
- /* SLOT 1 */
- SLOT = &CH[6].SLOT[SLOT1];
- env = volume_calc(SLOT);
-
- out = SLOT->op1_out[0] + SLOT->op1_out[1];
- SLOT->op1_out[0] = SLOT->op1_out[1];
-
- if (!SLOT->CON)
- OPL->phase_modulation = SLOT->op1_out[0];
- /* else ignore output of operator 1 */
-
- SLOT->op1_out[1] = 0;
- if( env < ENV_QUIET )
- {
- if (!SLOT->FB)
- out = 0;
- SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable );
- }
-
- /* SLOT 2 */
- SLOT++;
- env = volume_calc(SLOT);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;
-
-
- /* Phase generation is based on: */
- /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
- /* SD (16) channel 7->slot 1 */
- /* TOM (14) channel 8->slot 1 */
- /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
-
- /* Envelope generation based on: */
- /* HH channel 7->slot1 */
- /* SD channel 7->slot2 */
- /* TOM channel 8->slot1 */
- /* TOP channel 8->slot2 */
-
-
- /* The following formulas can be well optimized.
- I leave them in direct form for now (in case I've missed something).
- */
-
- /* High Hat (verified on real YM3812) */
- env = volume_calc(OPL->SLOT7_1);
- if( env < ENV_QUIET )
- {
-
- /* high hat phase generation:
- phase = d0 or 234 (based on frequency only)
- phase = 34 or 2d0 (based on noise)
- */
-
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit7 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
- unsigned char bit3 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
- unsigned char bit2 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-
- unsigned char res1 = (bit2 ^ bit7) | bit3;
-
- /* when res1 = 0 phase = 0x000 | 0xd0; */
- /* when res1 = 1 phase = 0x200 | (0xd0>>2); */
- UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
-
- /* enable gate based on frequency of operator 2 in channel 8 */
- unsigned char bit5e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
- unsigned char bit3e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-
- unsigned char res2 = (bit3e ^ bit5e);
-
- /* when res2 = 0 pass the phase from calculation above (res1); */
- /* when res2 = 1 phase = 0x200 | (0xd0>>2); */
- if (res2)
- phase = (0x200|(0xd0>>2));
-
-
- /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
- /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
- if (phase&0x200)
- {
- if (noise)
- phase = 0x200|0xd0;
- }
- else
- /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
- /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
- {
- if (noise)
- phase = 0xd0>>2;
- }
-
- OPL->output[0] += op_calc(phase<SLOT7_1->wavetable) * 2;
- }
-
- /* Snare Drum (verified on real YM3812) */
- env = volume_calc(OPL->SLOT7_2);
- if( env < ENV_QUIET )
- {
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit8 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
-
- /* when bit8 = 0 phase = 0x100; */
- /* when bit8 = 1 phase = 0x200; */
- UINT32 phase = bit8 ? 0x200 : 0x100;
-
- /* Noise bit XOR'es phase by 0x100 */
- /* when noisebit = 0 pass the phase from calculation above */
- /* when noisebit = 1 phase ^= 0x100; */
- /* in other words: phase ^= (noisebit<<8); */
- if (noise)
- phase ^= 0x100;
-
- OPL->output[0] += op_calc(phase<SLOT7_2->wavetable) * 2;
- }
-
- /* Tom Tom (verified on real YM3812) */
- env = volume_calc(OPL->SLOT8_1);
- if( env < ENV_QUIET )
- OPL->output[0] += op_calc(OPL->SLOT8_1->Cnt, env, 0, OPL->SLOT8_1->wavetable) * 2;
-
- /* Top Cymbal (verified on real YM3812) */
- env = volume_calc(OPL->SLOT8_2);
- if( env < ENV_QUIET )
- {
- /* base frequency derived from operator 1 in channel 7 */
- unsigned char bit7 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
- unsigned char bit3 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
- unsigned char bit2 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
-
- unsigned char res1 = (bit2 ^ bit7) | bit3;
-
- /* when res1 = 0 phase = 0x000 | 0x100; */
- /* when res1 = 1 phase = 0x200 | 0x100; */
- UINT32 phase = res1 ? 0x300 : 0x100;
-
- /* enable gate based on frequency of operator 2 in channel 8 */
- unsigned char bit5e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
- unsigned char bit3e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
-
- unsigned char res2 = (bit3e ^ bit5e);
- /* when res2 = 0 pass the phase from calculation above (res1); */
- /* when res2 = 1 phase = 0x200 | 0x100; */
- if (res2)
- phase = 0x300;
-
- OPL->output[0] += op_calc(phase<SLOT8_2->wavetable) * 2;
- }
-
-}
-
-
-/* generic table initialize */
-static int init_tables(void)
-{
- signed int i,x;
- signed int n;
- double o,m;
-
-
- for (x=0; x>= 4; /* 12 bits here */
- if (n&1) /* round to nearest */
- n = (n>>1)+1;
- else
- n = n>>1;
- /* 11 bits here (rounded) */
- n <<= 1; /* 12 bits here (as in real chip) */
- tl_tab[ x*2 + 0 ] = n;
- tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
-
- for (i=1; i<12; i++)
- {
- tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i;
- tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
- }
- #if 0
- logerror("tl %04i", x*2);
- for (i=0; i<12; i++)
- logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );
- logerror("\n");
- #endif
- }
- /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
-
-
- for (i=0; i0.0)
- o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */
- else
- o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */
-
- o = o / (ENV_STEP/4);
-
- n = (int)(2.0*o);
- if (n&1) /* round to nearest */
- n = (n>>1)+1;
- else
- n = n>>1;
-
- sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
-
- /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
- }
-
- for (i=0; i>1) ];
-
- /* waveform 3: _ _ _ _ */
- /* / |_/ |_/ |_/ |_*/
- /* abs(output only first quarter of the sinus waveform) */
-
- if (i & (1<<(SIN_BITS-2)) )
- sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;
- else
- sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];
-
- /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );
- logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );
- logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/
- }
- /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/
-
-
-#ifdef SAVE_SAMPLE
- sample[0]=fopen("sampsum.pcm","wb");
-#endif
-
- return 1;
-}
-
-static void OPLCloseTable( void )
-{
-#ifdef SAVE_SAMPLE
- fclose(sample[0]);
-#endif
-}
-
-
-
-static void OPL_initalize(FM_OPL *OPL)
-{
- int i;
-
- /* frequency base */
- OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0;
-#if 0
- OPL->rate = (double)OPL->clock / 72.0;
- OPL->freqbase = 1.0;
-#endif
-
- /*logerror("freqbase=%f\n", OPL->freqbase);*/
-
- /* Timer base time */
- //OPL->TimerBase = attotime_mul(ATTOTIME_IN_HZ(OPL->clock), 72);
-
- /* make fnumber -> increment counter table */
- for( i=0 ; i < 1024 ; i++ )
- {
- /* opn phase increment counter = 20bit */
- OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
-#if 0
- logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",
- i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );
-#endif
- }
-
-#if 0
- for( i=0 ; i < 16 ; i++ )
- {
- logerror("FMOPL.C: sl_tab[%i] = %08x\n",
- i, sl_tab[i] );
- }
- for( i=0 ; i < 8 ; i++ )
- {
- int j;
- logerror("FMOPL.C: ksl_tab[oct=%2i] =",i);
- for (j=0; j<16; j++)
- {
- logerror("%08x ", ksl_tab[i*16+j] );
- }
- logerror("\n");
- }
-#endif
-
-
- /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
- /* One entry from LFO_AM_TABLE lasts for 64 samples */
- OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase;
-
- /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
- OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase;
-
- /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
-
- /* Noise generator: a step takes 1 sample */
- OPL->noise_f = (1.0 / 1.0) * (1<freqbase;
-
- OPL->eg_timer_add = (1<freqbase;
- OPL->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, OPL->eg_timer_overflow);*/
-
-}
-
-INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
-{
- if( !SLOT->key )
- {
- /* restart Phase Generator */
- SLOT->Cnt = 0;
- /* phase -> Attack */
- SLOT->state = EG_ATT;
- }
- SLOT->key |= key_set;
-}
-
-INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
-{
- if( SLOT->key )
- {
- SLOT->key &= key_clr;
-
- if( !SLOT->key )
- {
- /* phase -> Release */
- if (SLOT->state>EG_REL)
- SLOT->state = EG_REL;
- }
- }
-}
-
-/* update phase increment counter of operator (also update the EG rates if necessary) */
-INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
-{
- int ksr;
-
- /* (frequency) phase increment counter */
- SLOT->Incr = CH->fc * SLOT->mul;
- ksr = CH->kcode >> SLOT->KSR;
-
- if( SLOT->ksr != ksr )
- {
- SLOT->ksr = ksr;
-
- /* calculate envelope generator rates */
- if ((SLOT->ar + SLOT->ksr) < 16+62)
- {
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- }
- else
- {
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
- }
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
- }
-}
-
-/* set multi,am,vib,EG-TYP,KSR,mul */
-INLINE void set_mul(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->mul = mul_tab[v&0x0f];
- SLOT->KSR = (v&0x10) ? 0 : 2;
- SLOT->eg_type = (v&0x20);
- SLOT->vib = (v&0x40);
- SLOT->AMmask = (v&0x80) ? ~0 : 0;
- CALC_FCSLOT(CH,SLOT);
-}
-
-/* set ksl & tl */
-INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
- int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
-
- SLOT->ksl = ksl ? 3-ksl : 31;
- SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
-
- SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
-}
-
-/* set attack rate & decay rate */
-INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0;
-
- if ((SLOT->ar + SLOT->ksr) < 16+62)
- {
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- }
- else
- {
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
- }
-
- SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
-}
-
-/* set sustain level & release rate */
-INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
-{
- OPL_CH *CH = &OPL->P_CH[slot/2];
- OPL_SLOT *SLOT = &CH->SLOT[slot&1];
-
- SLOT->sl = sl_tab[ v>>4 ];
-
- SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
-}
-
-
-/* write a value v to register r on OPL chip */
-static void OPLWriteReg(FM_OPL *OPL, int r, int v)
-{
- OPL_CH *CH;
- int slot;
- UINT32 block_fnum;
-
-
- /* adjust bus to 8 bits */
- r &= 0xff;
- v &= 0xff;
-
- /*if (LOG_CYM_FILE && (cymfile) && (r!=0) )
- {
- fputc( (unsigned char)r, cymfile );
- fputc( (unsigned char)v, cymfile );
- }*/
-
-
- switch(r&0xe0)
- {
- case 0x00: /* 00-1f:control */
- switch(r&0x1f)
- {
- case 0x01: /* waveform select enable */
- if(OPL->type&OPL_TYPE_WAVESEL)
- {
- OPL->wavesel = v&0x20;
- /* do not change the waveform previously selected */
- }
- break;
- case 0x02: /* Timer 1 */
- OPL->T[0] = (256-v)*4;
- break;
- case 0x03: /* Timer 2 */
- OPL->T[1] = (256-v)*16;
- break;
- case 0x04: /* IRQ clear / mask and Timer enable */
- if(v&0x80)
- { /* IRQ flag clear */
- OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */
- }
- else
- { /* set IRQ mask ,timer enable*/
- /*UINT8 st1 = v&1;
- UINT8 st2 = (v>>1)&1;*/
-
- /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
- OPL_STATUS_RESET(OPL, v & (0x78-0x08) );
- OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );
-
- /* timer 2 */
- /*if(OPL->st[1] != st2)
- {
- attotime period = st2 ? attotime_mul(OPL->TimerBase, OPL->T[1]) : attotime_zero;
- OPL->st[1] = st2;
- if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);
- }*/
- /* timer 1 */
- /*if(OPL->st[0] != st1)
- {
- attotime period = st1 ? attotime_mul(OPL->TimerBase, OPL->T[0]) : attotime_zero;
- OPL->st[0] = st1;
- if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);
- }*/
- }
- break;
-#if BUILD_Y8950
- case 0x06: /* Key Board OUT */
- if(OPL->type&OPL_TYPE_KEYBOARD)
- {
- if(OPL->keyboardhandler_w)
- OPL->keyboardhandler_w(OPL->keyboard_param,v);
- /*else
- logerror("Y8950: write unmapped KEYBOARD port\n");*/
- }
- break;
- case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
- break;
-#endif
- case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
- OPL->mode = v;
-#if BUILD_Y8950
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */
-#endif
- break;
-
-#if BUILD_Y8950
- case 0x09: /* START ADD */
- case 0x0a:
- case 0x0b: /* STOP ADD */
- case 0x0c:
- case 0x0d: /* PRESCALE */
- case 0x0e:
- case 0x0f: /* ADPCM data write */
- case 0x10: /* DELTA-N */
- case 0x11: /* DELTA-N */
- case 0x12: /* ADPCM volume */
- if(OPL->type&OPL_TYPE_ADPCM)
- YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
- break;
-
- case 0x15: /* DAC data high 8 bits (F7,F6...F2) */
- case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */
- case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */
- /*logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);*/
- break;
-
- case 0x18: /* I/O CTRL (Direction) */
- if(OPL->type&OPL_TYPE_IO)
- OPL->portDirection = v&0x0f;
- break;
- case 0x19: /* I/O DATA */
- if(OPL->type&OPL_TYPE_IO)
- {
- OPL->portLatch = v;
- if(OPL->porthandler_w)
- OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
- }
- break;
-#endif
- default:
- /*logerror("FMOPL.C: write to unknown register: %02x\n",r);*/
- break;
- }
- break;
- case 0x20: /* am ON, vib ON, ksr, eg_type, mul */
- slot = slot_array[r&0x1f];
- if(slot < 0) return;
- set_mul(OPL,slot,v);
- break;
- case 0x40:
- slot = slot_array[r&0x1f];
- if(slot < 0) return;
- set_ksl_tl(OPL,slot,v);
- break;
- case 0x60:
- slot = slot_array[r&0x1f];
- if(slot < 0) return;
- set_ar_dr(OPL,slot,v);
- break;
- case 0x80:
- slot = slot_array[r&0x1f];
- if(slot < 0) return;
- set_sl_rr(OPL,slot,v);
- break;
- case 0xa0:
- if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
- {
- OPL->lfo_am_depth = v & 0x80;
- OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
-
- OPL->rhythm = v&0x3f;
-
- if(OPL->rhythm&0x20)
- {
- /* BD key on/off */
- if(v&0x10)
- {
- FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);
- FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);
- }
- else
- {
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
- }
- /* HH key on/off */
- if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);
- else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
- /* SD key on/off */
- if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);
- else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
- /* TOM key on/off */
- if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);
- else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
- /* TOP-CY key on/off */
- if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);
- else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
- }
- else
- {
- /* BD key off */
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
- FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
- /* HH key off */
- FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
- /* SD key off */
- FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
- /* TOM key off */
- FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
- /* TOP-CY off */
- FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
- }
- return;
- }
- /* keyon,block,fnum */
- if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
- if(!(r&0x10))
- { /* a0-a8 */
- block_fnum = (CH->block_fnum&0x1f00) | v;
- }
- else
- { /* b0-b8 */
- block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
-
- if(v&0x20)
- {
- FM_KEYON (&CH->SLOT[SLOT1], 1);
- FM_KEYON (&CH->SLOT[SLOT2], 1);
- }
- else
- {
- FM_KEYOFF(&CH->SLOT[SLOT1],~1);
- FM_KEYOFF(&CH->SLOT[SLOT2],~1);
- }
- }
- /* update */
- if(CH->block_fnum != block_fnum)
- {
- UINT8 block = block_fnum >> 10;
-
- CH->block_fnum = block_fnum;
-
- CH->ksl_base = ksl_tab[block_fnum>>6];
- CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);
-
- /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
- CH->kcode = (CH->block_fnum&0x1c00)>>9;
-
- /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */
- /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */
- /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
- if (OPL->mode&0x40)
- CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */
- else
- CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */
-
- /* refresh Total Level in both SLOTs of this channel */
- CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
- CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
-
- /* refresh frequency counter in both SLOTs of this channel */
- CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
- CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
- }
- break;
- case 0xc0:
- /* FB,C */
- if( (r&0x0f) > 8) return;
- CH = &OPL->P_CH[r&0x0f];
- CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
- CH->SLOT[SLOT1].CON = v&1;
- CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;
- break;
- case 0xe0: /* waveform select */
- /* simply ignore write to the waveform select register if selecting not enabled in test register */
- if(OPL->wavesel)
- {
- slot = slot_array[r&0x1f];
- if(slot < 0) return;
- CH = &OPL->P_CH[slot/2];
-
- CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;
- }
- break;
- }
-}
-
-/*static TIMER_CALLBACK( cymfile_callback )
-{
- if (cymfile)
- {
- fputc( (unsigned char)0, cymfile );
- }
-}*/
-
-/* lock/unlock for common table */
-#if 0
-static int OPL_LockTable(/*const device_config *device*/)
-{
- num_lock++;
- if(num_lock>1) return 0;
-
- /* first time */
-
- cur_chip = NULL;
- /* allocate total level table (128kb space) */
- if( !init_tables() )
- {
- num_lock--;
- return -1;
- }
-
-#if 0
- if (LOG_CYM_FILE)
- {
- cymfile = fopen("3812_.cym","wb");
- if (cymfile)
- timer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); /*110 Hz pulse timer*/
- else
- logerror("Could not create file 3812_.cym\n");
- }
-#endif
-
- return 0;
-}
-
-static void OPL_UnLockTable(void)
-{
- if(num_lock) num_lock--;
- if(num_lock) return;
-
- /* last time */
-
- cur_chip = NULL;
- OPLCloseTable();
-
- /*if (cymfile)
- fclose (cymfile);
- cymfile = NULL;*/
-}
-#endif
-
-static void OPLResetChip(FM_OPL *OPL)
-{
- int c,s;
- int i;
-
- OPL->eg_timer = 0;
- OPL->eg_cnt = 0;
-
- OPL->noise_rng = 1; /* noise shift register */
- OPL->mode = 0; /* normal mode */
- OPL_STATUS_RESET(OPL,0x7f);
-
- /* reset with register write */
- OPLWriteReg(OPL,0x01,0); /* wavesel disable */
- OPLWriteReg(OPL,0x02,0); /* Timer1 */
- OPLWriteReg(OPL,0x03,0); /* Timer2 */
- OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
- for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
-
- /* reset operator parameters */
- for( c = 0 ; c < 9 ; c++ )
- {
- OPL_CH *CH = &OPL->P_CH[c];
- for(s = 0 ; s < 2 ; s++ )
- {
- /* wave table */
- CH->SLOT[s].wavetable = 0;
- CH->SLOT[s].state = EG_OFF;
- CH->SLOT[s].volume = MAX_ATT_INDEX;
- }
- }
-#if BUILD_Y8950
- if(OPL->type&OPL_TYPE_ADPCM)
- {
- YM_DELTAT *DELTAT = OPL->deltat;
-
- DELTAT->freqbase = OPL->freqbase;
- DELTAT->output_pointer = &OPL->output_deltat[0];
- DELTAT->portshift = 5;
- DELTAT->output_range = 1<<23;
- YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);
- }
-#endif
-}
-
-
-#if 0
-static STATE_POSTLOAD( OPL_postload )
-{
- FM_OPL *OPL = (FM_OPL *)param;
- int slot, ch;
-
- for( ch=0 ; ch < 9 ; ch++ )
- {
- OPL_CH *CH = &OPL->P_CH[ch];
-
- /* Look up key scale level */
- UINT32 block_fnum = CH->block_fnum;
- CH->ksl_base = ksl_tab[block_fnum >> 6];
- CH->fc = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));
-
- for( slot=0 ; slot < 2 ; slot++ )
- {
- OPL_SLOT *SLOT = &CH->SLOT[slot];
-
- /* Calculate key scale rate */
- SLOT->ksr = CH->kcode >> SLOT->KSR;
-
- /* Calculate attack, decay and release rates */
- if ((SLOT->ar + SLOT->ksr) < 16+62)
- {
- SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
- SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
- }
- else
- {
- SLOT->eg_sh_ar = 0;
- SLOT->eg_sel_ar = 13*RATE_STEPS;
- }
- SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
- SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
- SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
- SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
-
- /* Calculate phase increment */
- SLOT->Incr = CH->fc * SLOT->mul;
-
- /* Total level */
- SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
-
- /* Connect output */
- SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;
- }
- }
-#if BUILD_Y8950
- if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
- {
- // We really should call the postlod function for the YM_DELTAT, but it's hard without registers
- // (see the way the YM2610 does it)
- //YM_DELTAT_postload(OPL->deltat, REGS);
- }
-#endif
-}
-
-
-static void OPLsave_state_channel(const device_config *device, OPL_CH *CH)
-{
- int slot, ch;
-
- for( ch=0 ; ch < 9 ; ch++, CH++ )
- {
- /* channel */
- state_save_register_device_item(device, ch, CH->block_fnum);
- state_save_register_device_item(device, ch, CH->kcode);
- /* slots */
- for( slot=0 ; slot < 2 ; slot++ )
- {
- OPL_SLOT *SLOT = &CH->SLOT[slot];
-
- state_save_register_device_item(device, ch * 2 + slot, SLOT->ar);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->dr);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->rr);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->KSR);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->ksl);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->mul);
-
- state_save_register_device_item(device, ch * 2 + slot, SLOT->Cnt);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->FB);
- state_save_register_device_item_array(device, ch * 2 + slot, SLOT->op1_out);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->CON);
-
- state_save_register_device_item(device, ch * 2 + slot, SLOT->eg_type);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->state);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->TL);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->volume);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->sl);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->key);
-
- state_save_register_device_item(device, ch * 2 + slot, SLOT->AMmask);
- state_save_register_device_item(device, ch * 2 + slot, SLOT->vib);
-
- state_save_register_device_item(device, ch * 2 + slot, SLOT->wavetable);
- }
- }
-}
-
-
-/* Register savestate for a virtual YM3812/YM3526Y8950 */
-
-static void OPL_save_state(FM_OPL *OPL, const device_config *device)
-{
- OPLsave_state_channel(device, OPL->P_CH);
-
- state_save_register_device_item(device, 0, OPL->eg_cnt);
- state_save_register_device_item(device, 0, OPL->eg_timer);
-
- state_save_register_device_item(device, 0, OPL->rhythm);
-
- state_save_register_device_item(device, 0, OPL->lfo_am_depth);
- state_save_register_device_item(device, 0, OPL->lfo_pm_depth_range);
- state_save_register_device_item(device, 0, OPL->lfo_am_cnt);
- state_save_register_device_item(device, 0, OPL->lfo_pm_cnt);
-
- state_save_register_device_item(device, 0, OPL->noise_rng);
- state_save_register_device_item(device, 0, OPL->noise_p);
-
- if( OPL->type & OPL_TYPE_WAVESEL )
- {
- state_save_register_device_item(device, 0, OPL->wavesel);
- }
-
- state_save_register_device_item_array(device, 0, OPL->T);
- state_save_register_device_item_array(device, 0, OPL->st);
-
-#if BUILD_Y8950
- if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
- {
- YM_DELTAT_savestate(device, OPL->deltat);
- }
-
- if ( OPL->type & OPL_TYPE_IO )
- {
- state_save_register_device_item(device, 0, OPL->portDirection);
- state_save_register_device_item(device, 0, OPL->portLatch);
- }
-#endif
-
- state_save_register_device_item(device, 0, OPL->address);
- state_save_register_device_item(device, 0, OPL->status);
- state_save_register_device_item(device, 0, OPL->statusmask);
- state_save_register_device_item(device, 0, OPL->mode);
-
- state_save_register_postload(device->machine, OPL_postload, OPL);
-}
-#endif
-
-
-/* Create one of virtual YM3812/YM3526/Y8950 */
-/* 'clock' is chip clock in Hz */
-/* 'rate' is sampling rate */
-static FM_OPL *OPLCreate(UINT32 clock, UINT32 rate, int type)
-{
- char *ptr;
- FM_OPL *OPL;
- int state_size;
-
- //if (OPL_LockTable(device) == -1) return NULL;
- init_tables();
-
- /* calculate OPL state size */
- state_size = sizeof(FM_OPL);
-
-#if BUILD_Y8950
- if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
-#endif
-
- /* allocate memory block */
- ptr = (char *)malloc(state_size);
-
- if (ptr==NULL)
- return 0;
-
- /* clear */
- memset(ptr,0,state_size);
-
- OPL = (FM_OPL *)ptr;
-
- ptr += sizeof(FM_OPL);
-
-#if BUILD_Y8950
- if (type&OPL_TYPE_ADPCM)
- {
- OPL->deltat = (YM_DELTAT *)ptr;
- }
- ptr += sizeof(YM_DELTAT);
-#endif
-
- OPL->type = type;
- OPL->clock = clock;
- OPL->rate = rate;
-
- /* init global tables */
- OPL_initalize(OPL);
-
- return OPL;
-}
-
-/* Destroy one of virtual YM3812 */
-static void OPLDestroy(FM_OPL *OPL)
-{
- //OPL_UnLockTable();
- free(OPL);
-}
-
-/* Optional handlers */
-
-/*static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)
-{
- OPL->timer_handler = timer_handler;
- OPL->TimerParam = param;
-}*/
-static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)
-{
- OPL->IRQHandler = IRQHandler;
- OPL->IRQParam = param;
-}
-static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)
-{
- OPL->UpdateHandler = UpdateHandler;
- OPL->UpdateParam = param;
-}
-
-static int OPLWrite(FM_OPL *OPL,int a,int v)
-{
- if( !(a&1) )
- { /* address port */
- OPL->address = v & 0xff;
- }
- else
- { /* data port */
- if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
- OPLWriteReg(OPL,OPL->address,v);
- }
- return OPL->status>>7;
-}
-
-static unsigned char OPLRead(FM_OPL *OPL,int a)
-{
- if( !(a&1) )
- {
- /* status port */
-
- #if BUILD_Y8950
-
- if(OPL->type&OPL_TYPE_ADPCM) /* Y8950 */
- {
- return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1);
- }
-
- #endif
-
- /* OPL and OPL2 */
- return OPL->status & (OPL->statusmask|0x80);
- }
-
-#if BUILD_Y8950
- /* data port */
- switch(OPL->address)
- {
- case 0x05: /* KeyBoard IN */
- if(OPL->type&OPL_TYPE_KEYBOARD)
- {
- if(OPL->keyboardhandler_r)
- return OPL->keyboardhandler_r(OPL->keyboard_param);
- /*else
- logerror("Y8950: read unmapped KEYBOARD port\n");*/
- }
- return 0;
-
- case 0x0f: /* ADPCM-DATA */
- if(OPL->type&OPL_TYPE_ADPCM)
- {
- UINT8 val;
-
- val = YM_DELTAT_ADPCM_Read(OPL->deltat);
- /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/
- return val;
- }
- return 0;
-
- case 0x19: /* I/O DATA */
- if(OPL->type&OPL_TYPE_IO)
- {
- if(OPL->porthandler_r)
- return OPL->porthandler_r(OPL->port_param);
- /*else
- logerror("Y8950:read unmapped I/O port\n");*/
- }
- return 0;
- case 0x1a: /* PCM-DATA */
- if(OPL->type&OPL_TYPE_ADPCM)
- {
- /*logerror("Y8950 A/D convertion is accessed but not implemented !\n");*/
- return 0x80; /* 2's complement PCM data - result from A/D convertion */
- }
- return 0;
- }
-#endif
-
- return 0xff;
-}
-
-/* CSM Key Controll */
-INLINE void CSMKeyControll(OPL_CH *CH)
-{
- FM_KEYON (&CH->SLOT[SLOT1], 4);
- FM_KEYON (&CH->SLOT[SLOT2], 4);
-
- /* The key off should happen exactly one sample later - not implemented correctly yet */
-
- FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
- FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
-}
-
-
-static int OPLTimerOver(FM_OPL *OPL,int c)
-{
- if( c )
- { /* Timer B */
- OPL_STATUS_SET(OPL,0x20);
- }
- else
- { /* Timer A */
- OPL_STATUS_SET(OPL,0x40);
- /* CSM mode key,TL controll */
- if( OPL->mode & 0x80 )
- { /* CSM mode total level latch and auto key on */
- int ch;
- if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
- for(ch=0; ch<9; ch++)
- CSMKeyControll( &OPL->P_CH[ch] );
- }
- }
- /* reload timer */
- //if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,attotime_mul(OPL->TimerBase, OPL->T[c]));
- return OPL->status>>7;
-}
-
-
-#define MAX_OPL_CHIPS 2
-
-
-#if (BUILD_YM3812)
-
-void * ym3812_init(UINT32 clock, UINT32 rate)
-{
- /* emulator create */
- FM_OPL *YM3812 = OPLCreate(clock,rate,OPL_TYPE_YM3812);
- if (YM3812)
- {
- //OPL_save_state(YM3812);
- ym3812_reset_chip(YM3812);
- }
- return YM3812;
-}
-
-void ym3812_shutdown(void *chip)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
-
- /* emulator shutdown */
- OPLDestroy(YM3812);
-}
-void ym3812_reset_chip(void *chip)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLResetChip(YM3812);
-}
-
-int ym3812_write(void *chip, int a, int v)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- return OPLWrite(YM3812, a, v);
-}
-
-unsigned char ym3812_read(void *chip, int a)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- /* YM3812 always returns bit2 and bit1 in HIGH state */
- return OPLRead(YM3812, a) | 0x06 ;
-}
-int ym3812_timer_over(void *chip, int c)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- return OPLTimerOver(YM3812, c);
-}
-
-/*void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetTimerHandler(YM3812, timer_handler, param);
-}*/
-void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetIRQHandler(YM3812, IRQHandler, param);
-}
-void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
-{
- FM_OPL *YM3812 = (FM_OPL *)chip;
- OPLSetUpdateHandler(YM3812, UpdateHandler, param);
-}
-
-
-/*
-** Generate samples for one of the YM3812's
-**
-** 'which' is the virtual YM3812 number
-** '*buffer' is the output buffer pointer
-** 'length' is the number of samples that should be generated
-*/
-void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
-{
- FM_OPL *OPL = (FM_OPL *)chip;
- UINT8 rhythm = OPL->rhythm&0x20;
- OPLSAMPLE *buf = buffer;
- int i;
-
- /* rhythm slots */
- OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
- OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
- OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
- OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
- for( i=0; i < length ; i++ )
- {
- int lt;
-
- OPL->output[0] = 0;
-
- advance_lfo(OPL);
-
- /* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
-
- if(!rhythm)
- {
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
- }
- else /* Rhythm part */
- {
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
- }
-
- lt = OPL->output[0];
-
- lt >>= FINAL_SH;
-
- /* limit check */
- lt = limit( lt , MAXOUT, MINOUT );
-
- #ifdef SAVE_SAMPLE
- if (which==0)
- {
- SAVE_ALL_CHANNELS
- }
- #endif
-
- /* store to sound buffer */
- buf[i] = lt;
-
- advance(OPL);
- }
-
-}
-#endif /* BUILD_YM3812 */
-
-
-
-#if (BUILD_YM3526)
-
-void *ym3526_init(UINT32 clock, UINT32 rate)
-{
- /* emulator create */
- FM_OPL *YM3526 = OPLCreate(clock,rate,OPL_TYPE_YM3526);
- if (YM3526)
- {
- /*OPL_save_state(YM3526);*/
- ym3526_reset_chip(YM3526);
- }
- return YM3526;
-}
-
-void ym3526_shutdown(void *chip)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- /* emulator shutdown */
- OPLDestroy(YM3526);
-}
-void ym3526_reset_chip(void *chip)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLResetChip(YM3526);
-}
-
-int ym3526_write(void *chip, int a, int v)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- return OPLWrite(YM3526, a, v);
-}
-
-unsigned char ym3526_read(void *chip, int a)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- /* YM3526 always returns bit2 and bit1 in HIGH state */
- return OPLRead(YM3526, a) | 0x06 ;
-}
-int ym3526_timer_over(void *chip, int c)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- return OPLTimerOver(YM3526, c);
-}
-
-/*void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetTimerHandler(YM3526, timer_handler, param);
-}*/
-void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetIRQHandler(YM3526, IRQHandler, param);
-}
-void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
-{
- FM_OPL *YM3526 = (FM_OPL *)chip;
- OPLSetUpdateHandler(YM3526, UpdateHandler, param);
-}
-
-
-/*
-** Generate samples for one of the YM3526's
-**
-** 'which' is the virtual YM3526 number
-** '*buffer' is the output buffer pointer
-** 'length' is the number of samples that should be generated
-*/
-void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
-{
- FM_OPL *OPL = (FM_OPL *)chip;
- UINT8 rhythm = OPL->rhythm&0x20;
- OPLSAMPLE *buf = buffer;
- int i;
-
- /* rhythm slots */
- OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
- OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
- OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
- OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
- for( i=0; i < length ; i++ )
- {
- int lt;
-
- OPL->output[0] = 0;
-
- advance_lfo(OPL);
-
- /* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
-
- if(!rhythm)
- {
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
- }
- else /* Rhythm part */
- {
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
- }
-
- lt = OPL->output[0];
-
- lt >>= FINAL_SH;
-
- /* limit check */
- lt = limit( lt , MAXOUT, MINOUT );
-
- #ifdef SAVE_SAMPLE
- if (which==0)
- {
- SAVE_ALL_CHANNELS
- }
- #endif
-
- /* store to sound buffer */
- buf[i] = lt;
-
- advance(OPL);
- }
-
-}
-#endif /* BUILD_YM3526 */
-
-
-
-
-#if BUILD_Y8950
-
-static void Y8950_deltat_status_set(void *chip, UINT8 changebits)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPL_STATUS_SET(Y8950, changebits);
-}
-static void Y8950_deltat_status_reset(void *chip, UINT8 changebits)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPL_STATUS_RESET(Y8950, changebits);
-}
-
-void *y8950_init(UINT32 clock, UINT32 rate)
-{
- /* emulator create */
- FM_OPL *Y8950 = OPLCreate(clock,rate,OPL_TYPE_Y8950);
- if (Y8950)
- {
- Y8950->deltat->status_set_handler = Y8950_deltat_status_set;
- Y8950->deltat->status_reset_handler = Y8950_deltat_status_reset;
- Y8950->deltat->status_change_which_chip = Y8950;
- Y8950->deltat->status_change_EOS_bit = 0x10; /* status flag: set bit4 on End Of Sample */
- Y8950->deltat->status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */
-
- /*Y8950->deltat->write_time = 10.0 / clock;*/ /* a single byte write takes 10 cycles of main clock */
- /*Y8950->deltat->read_time = 8.0 / clock;*/ /* a single byte read takes 8 cycles of main clock */
- /* reset */
- /*OPL_save_state(Y8950);*/
- y8950_reset_chip(Y8950);
- }
-
- return Y8950;
-}
-
-void y8950_shutdown(void *chip)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- /* emulator shutdown */
- OPLDestroy(Y8950);
-}
-void y8950_reset_chip(void *chip)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLResetChip(Y8950);
-}
-
-int y8950_write(void *chip, int a, int v)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- return OPLWrite(Y8950, a, v);
-}
-
-unsigned char y8950_read(void *chip, int a)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- return OPLRead(Y8950, a);
-}
-int y8950_timer_over(void *chip, int c)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- return OPLTimerOver(Y8950, c);
-}
-
-/*void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetTimerHandler(Y8950, timer_handler, param);
-}*/
-void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetIRQHandler(Y8950, IRQHandler, param);
-}
-void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
-{
- FM_OPL *Y8950 = (FM_OPL *)chip;
- OPLSetUpdateHandler(Y8950, UpdateHandler, param);
-}
-
-void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )
-{
- FM_OPL *OPL = (FM_OPL *)chip;
- OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr);
- OPL->deltat->memory_size = deltat_mem_size;
-}
-
-/*
-** Generate samples for one of the Y8950's
-**
-** 'which' is the virtual Y8950 number
-** '*buffer' is the output buffer pointer
-** 'length' is the number of samples that should be generated
-*/
-void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
-{
- int i;
- FM_OPL *OPL = (FM_OPL *)chip;
- UINT8 rhythm = OPL->rhythm&0x20;
- YM_DELTAT *DELTAT = OPL->deltat;
- OPLSAMPLE *buf = buffer;
-
- /* rhythm slots */
- OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
- OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
- OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
- OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
-
- for( i=0; i < length ; i++ )
- {
- int lt;
-
- OPL->output[0] = 0;
- OPL->output_deltat[0] = 0;
-
- advance_lfo(OPL);
-
- /* deltaT ADPCM */
- if( DELTAT->portstate&0x80 )
- YM_DELTAT_ADPCM_CALC(DELTAT);
-
- /* FM part */
- OPL_CALC_CH(OPL, &OPL->P_CH[0]);
- OPL_CALC_CH(OPL, &OPL->P_CH[1]);
- OPL_CALC_CH(OPL, &OPL->P_CH[2]);
- OPL_CALC_CH(OPL, &OPL->P_CH[3]);
- OPL_CALC_CH(OPL, &OPL->P_CH[4]);
- OPL_CALC_CH(OPL, &OPL->P_CH[5]);
-
- if(!rhythm)
- {
- OPL_CALC_CH(OPL, &OPL->P_CH[6]);
- OPL_CALC_CH(OPL, &OPL->P_CH[7]);
- OPL_CALC_CH(OPL, &OPL->P_CH[8]);
- }
- else /* Rhythm part */
- {
- OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
- }
-
- lt = OPL->output[0] + (OPL->output_deltat[0]>>11);
-
- lt >>= FINAL_SH;
-
- /* limit check */
- lt = limit( lt , MAXOUT, MINOUT );
-
- #ifdef SAVE_SAMPLE
- if (which==0)
- {
- SAVE_ALL_CHANNELS
- }
- #endif
-
- /* store to sound buffer */
- buf[i] = lt;
-
- advance(OPL);
- }
-
-}
-
-void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)
-{
- FM_OPL *OPL = (FM_OPL *)chip;
- OPL->porthandler_w = PortHandler_w;
- OPL->porthandler_r = PortHandler_r;
- OPL->port_param = param;
-}
-
-void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)
-{
- FM_OPL *OPL = (FM_OPL *)chip;
- OPL->keyboardhandler_w = KeyboardHandler_w;
- OPL->keyboardhandler_r = KeyboardHandler_r;
- OPL->keyboard_param = param;
-}
-
-#endif
-
+/*
+**
+** File: fmopl.c - software implementation of FM sound generator
+** types OPL and OPL2
+**
+** Copyright Jarek Burczynski (bujar at mame dot net)
+** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development
+**
+** Version 0.72
+**
+
+Revision History:
+
+04-08-2003 Jarek Burczynski:
+ - removed BFRDY hack. BFRDY is busy flag, and it should be 0 only when the chip
+ handles memory read/write or during the adpcm synthesis when the chip
+ requests another byte of ADPCM data.
+
+24-07-2003 Jarek Burczynski:
+ - added a small hack for Y8950 status BFRDY flag (bit 3 should be set after
+ some (unknown) delay). Right now it's always set.
+
+14-06-2003 Jarek Burczynski:
+ - implemented all of the status register flags in Y8950 emulation
+ - renamed y8950_set_delta_t_memory() parameters from _rom_ to _mem_ since
+ they can be either RAM or ROM
+
+08-10-2002 Jarek Burczynski (thanks to Dox for the YM3526 chip)
+ - corrected ym3526_read() to always set bit 2 and bit 1
+ to HIGH state - identical to ym3812_read (verified on real YM3526)
+
+04-28-2002 Jarek Burczynski:
+ - binary exact Envelope Generator (verified on real YM3812);
+ compared to YM2151: the EG clock is equal to internal_clock,
+ rates are 2 times slower and volume resolution is one bit less
+ - modified interface functions (they no longer return pointer -
+ that's internal to the emulator now):
+ - new wrapper functions for OPLCreate: ym3526_init(), ym3812_init() and y8950_init()
+ - corrected 'off by one' error in feedback calculations (when feedback is off)
+ - enabled waveform usage (credit goes to Vlad Romascanu and zazzal22)
+ - speeded up noise generator calculations (Nicola Salmoria)
+
+03-24-2002 Jarek Burczynski (thanks to Dox for the YM3812 chip)
+ Complete rewrite (all verified on real YM3812):
+ - corrected sin_tab and tl_tab data
+ - corrected operator output calculations
+ - corrected waveform_select_enable register;
+ simply: ignore all writes to waveform_select register when
+ waveform_select_enable == 0 and do not change the waveform previously selected.
+ - corrected KSR handling
+ - corrected Envelope Generator: attack shape, Sustain mode and
+ Percussive/Non-percussive modes handling
+ - Envelope Generator rates are two times slower now
+ - LFO amplitude (tremolo) and phase modulation (vibrato)
+ - rhythm sounds phase generation
+ - white noise generator (big thanks to Olivier Galibert for mentioning Berlekamp-Massey algorithm)
+ - corrected key on/off handling (the 'key' signal is ORed from three sources: FM, rhythm and CSM)
+ - funky details (like ignoring output of operator 1 in BD rhythm sound when connect == 1)
+
+12-28-2001 Acho A. Tang
+ - reflected Delta-T EOS status on Y8950 status port.
+ - fixed subscription range of attack/decay tables
+
+
+ To do:
+ add delay before key off in CSM mode (see CSMKeyControll)
+ verify volume of the FM part on the Y8950
+*/
+
+#include
+#include
+#define _USE_MATH_DEFINES
+#include
+#include "fmopl.h"
+#include "ymdeltat.h"
+
+#ifndef INLINE
+#define INLINE __inline
+#endif
+#ifndef NULL
+ #define NULL ((void *)0)
+#endif
+#ifndef logerror
+#define logerror (void)
+#endif
+
+#ifndef M_PI
+ #define M_PI 3.14159265358979323846
+#endif
+
+/* output final shift */
+#if (OPL_SAMPLE_BITS==16)
+ #define FINAL_SH (0)
+ #define MAXOUT (+32767)
+ #define MINOUT (-32768)
+#else
+ #define FINAL_SH (8)
+ #define MAXOUT (+127)
+ #define MINOUT (-128)
+#endif
+
+
+#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */
+#define EG_SH 16 /* 16.16 fixed point (EG timing) */
+#define LFO_SH 24 /* 8.24 fixed point (LFO calculations) */
+#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */
+
+#define FREQ_MASK ((1<=0)
+ {
+ if (value < 0x0200)
+ return (value & ~0);
+ if (value < 0x0400)
+ return (value & ~1);
+ if (value < 0x0800)
+ return (value & ~3);
+ if (value < 0x1000)
+ return (value & ~7);
+ if (value < 0x2000)
+ return (value & ~15);
+ if (value < 0x4000)
+ return (value & ~31);
+ return (value & ~63);
+ }
+ /*else value < 0*/
+ if (value > -0x0200)
+ return (~abs(value) & ~0);
+ if (value > -0x0400)
+ return (~abs(value) & ~1);
+ if (value > -0x0800)
+ return (~abs(value) & ~3);
+ if (value > -0x1000)
+ return (~abs(value) & ~7);
+ if (value > -0x2000)
+ return (~abs(value) & ~15);
+ if (value > -0x4000)
+ return (~abs(value) & ~31);
+ return (~abs(value) & ~63);
+}
+
+
+static FILE *sample[1];
+ #if 1 /*save to MONO file */
+ #define SAVE_ALL_CHANNELS \
+ { signed int pom = acc_calc(lt); \
+ fputc((unsigned short)pom&0xff,sample[0]); \
+ fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
+ }
+ #else /*save to STEREO file */
+ #define SAVE_ALL_CHANNELS \
+ { signed int pom = lt; \
+ fputc((unsigned short)pom&0xff,sample[0]); \
+ fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
+ pom = rt; \
+ fputc((unsigned short)pom&0xff,sample[0]); \
+ fputc(((unsigned short)pom>>8)&0xff,sample[0]); \
+ }
+ #endif
+#endif
+
+#define LOG_CYM_FILE 0
+//static FILE * cymfile = NULL;
+
+
+
+#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
+#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
+#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
+#define OPL_TYPE_IO 0x08 /* I/O port */
+
+/* ---------- Generic interface section ---------- */
+#define OPL_TYPE_YM3526 (0)
+#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
+#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
+
+
+
+typedef struct{
+ UINT32 ar; /* attack rate: AR<<2 */
+ UINT32 dr; /* decay rate: DR<<2 */
+ UINT32 rr; /* release rate:RR<<2 */
+ UINT8 KSR; /* key scale rate */
+ UINT8 ksl; /* keyscale level */
+ UINT8 ksr; /* key scale rate: kcode>>KSR */
+ UINT8 mul; /* multiple: mul_tab[ML] */
+
+ /* Phase Generator */
+ UINT32 Cnt; /* frequency counter */
+ UINT32 Incr; /* frequency counter step */
+ UINT8 FB; /* feedback shift value */
+ INT32 *connect1; /* slot1 output pointer */
+ INT32 op1_out[2]; /* slot1 output for feedback */
+ UINT8 CON; /* connection (algorithm) type */
+
+ /* Envelope Generator */
+ UINT8 eg_type; /* percussive/non-percussive mode */
+ UINT8 state; /* phase type */
+ UINT32 TL; /* total level: TL << 2 */
+ INT32 TLL; /* adjusted now TL */
+ INT32 volume; /* envelope counter */
+ UINT32 sl; /* sustain level: sl_tab[SL] */
+ UINT8 eg_sh_ar; /* (attack state) */
+ UINT8 eg_sel_ar; /* (attack state) */
+ UINT8 eg_sh_dr; /* (decay state) */
+ UINT8 eg_sel_dr; /* (decay state) */
+ UINT8 eg_sh_rr; /* (release state) */
+ UINT8 eg_sel_rr; /* (release state) */
+ UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */
+
+ /* LFO */
+ UINT32 AMmask; /* LFO Amplitude Modulation enable mask */
+ UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/
+
+ /* waveform select */
+ UINT16 wavetable;
+} OPL_SLOT;
+
+typedef struct{
+ OPL_SLOT SLOT[2];
+ /* phase generator state */
+ UINT32 block_fnum; /* block+fnum */
+ UINT32 fc; /* Freq. Increment base */
+ UINT32 ksl_base; /* KeyScaleLevel Base step */
+ UINT8 kcode; /* key code (for key scaling) */
+} OPL_CH;
+
+/* OPL state */
+typedef struct fm_opl_f {
+ /* FM channel slots */
+ OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
+
+ UINT32 eg_cnt; /* global envelope generator counter */
+ UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/72 */
+ UINT32 eg_timer_add; /* step of eg_timer */
+ UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 1 sample (on real chip) */
+
+ UINT8 rhythm; /* Rhythm mode */
+
+ UINT32 fn_tab[1024]; /* fnumber->increment counter */
+
+ /* LFO */
+ UINT8 lfo_am_depth;
+ UINT8 lfo_pm_depth_range;
+ UINT32 lfo_am_cnt;
+ UINT32 lfo_am_inc;
+ UINT32 lfo_pm_cnt;
+ UINT32 lfo_pm_inc;
+
+ UINT32 noise_rng; /* 23 bit noise shift register */
+ UINT32 noise_p; /* current noise 'phase' */
+ UINT32 noise_f; /* current noise period */
+
+ UINT8 wavesel; /* waveform select enable flag */
+
+ UINT32 T[2]; /* timer counters */
+ UINT8 st[2]; /* timer enable */
+
+#if BUILD_Y8950
+ /* Delta-T ADPCM unit (Y8950) */
+
+ YM_DELTAT *deltat;
+
+ /* Keyboard and I/O ports interface */
+ UINT8 portDirection;
+ UINT8 portLatch;
+ OPL_PORTHANDLER_R porthandler_r;
+ OPL_PORTHANDLER_W porthandler_w;
+ void * port_param;
+ OPL_PORTHANDLER_R keyboardhandler_r;
+ OPL_PORTHANDLER_W keyboardhandler_w;
+ void * keyboard_param;
+#endif
+
+ /* external event callback handlers */
+ //OPL_TIMERHANDLER timer_handler; /* TIMER handler */
+ void *TimerParam; /* TIMER parameter */
+ OPL_IRQHANDLER IRQHandler; /* IRQ handler */
+ void *IRQParam; /* IRQ parameter */
+ OPL_UPDATEHANDLER UpdateHandler;/* stream update handler */
+ void *UpdateParam; /* stream update parameter */
+
+ UINT8 type; /* chip type */
+ UINT8 address; /* address register */
+ UINT8 status; /* status flag */
+ UINT8 statusmask; /* status mask */
+ UINT8 mode; /* Reg.08 : CSM,notesel,etc. */
+
+ UINT32 clock; /* master clock (Hz) */
+ UINT32 rate; /* sampling rate (Hz) */
+ double freqbase; /* frequency base */
+ //attotime TimerBase; /* Timer base time (==sampling time)*/
+
+ OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
+
+ signed int phase_modulation; /* phase modulation input (SLOT 2) */
+ signed int output[1];
+
+#if BUILD_Y8950
+ INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
+#endif
+
+ UINT32 LFO_AM;
+ INT32 LFO_PM;
+} FM_OPL;
+
+
+
+/* mapping of register number (offset) to slot number used by the emulator */
+static const int slot_array[32]=
+{
+ 0, 2, 4, 1, 3, 5,-1,-1,
+ 6, 8,10, 7, 9,11,-1,-1,
+ 12,14,16,13,15,17,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1
+};
+
+/* key scale level */
+/* table is 3dB/octave , DV converts this into 6dB/octave */
+/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
+#define DV (0.1875/2.0)
+static const UINT32 ksl_tab[8*16]=
+{
+ /* OCT 0 */
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ /* OCT 1 */
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 0.750/DV), UINT32( 1.125/DV), UINT32( 1.500/DV),
+ UINT32( 1.875/DV), UINT32( 2.250/DV), UINT32( 2.625/DV), UINT32( 3.000/DV),
+ /* OCT 2 */
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV),
+ UINT32( 0.000/DV), UINT32( 1.125/DV), UINT32( 1.875/DV), UINT32( 2.625/DV),
+ UINT32( 3.000/DV), UINT32( 3.750/DV), UINT32( 4.125/DV), UINT32( 4.500/DV),
+ UINT32( 4.875/DV), UINT32( 5.250/DV), UINT32( 5.625/DV), UINT32( 6.000/DV),
+ /* OCT 3 */
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 1.875/DV),
+ UINT32( 3.000/DV), UINT32( 4.125/DV), UINT32( 4.875/DV), UINT32( 5.625/DV),
+ UINT32( 6.000/DV), UINT32( 6.750/DV), UINT32( 7.125/DV), UINT32( 7.500/DV),
+ UINT32( 7.875/DV), UINT32( 8.250/DV), UINT32( 8.625/DV), UINT32( 9.000/DV),
+ /* OCT 4 */
+ UINT32( 0.000/DV), UINT32( 0.000/DV), UINT32( 3.000/DV), UINT32( 4.875/DV),
+ UINT32( 6.000/DV), UINT32( 7.125/DV), UINT32( 7.875/DV), UINT32( 8.625/DV),
+ UINT32( 9.000/DV), UINT32( 9.750/DV), UINT32(10.125/DV), UINT32(10.500/DV),
+ UINT32(10.875/DV), UINT32(11.250/DV), UINT32(11.625/DV), UINT32(12.000/DV),
+ /* OCT 5 */
+ UINT32( 0.000/DV), UINT32( 3.000/DV), UINT32( 6.000/DV), UINT32( 7.875/DV),
+ UINT32( 9.000/DV), UINT32(10.125/DV), UINT32(10.875/DV), UINT32(11.625/DV),
+ UINT32(12.000/DV), UINT32(12.750/DV), UINT32(13.125/DV), UINT32(13.500/DV),
+ UINT32(13.875/DV), UINT32(14.250/DV), UINT32(14.625/DV), UINT32(15.000/DV),
+ /* OCT 6 */
+ UINT32( 0.000/DV), UINT32( 6.000/DV), UINT32( 9.000/DV), UINT32(10.875/DV),
+ UINT32(12.000/DV), UINT32(13.125/DV), UINT32(13.875/DV), UINT32(14.625/DV),
+ UINT32(15.000/DV), UINT32(15.750/DV), UINT32(16.125/DV), UINT32(16.500/DV),
+ UINT32(16.875/DV), UINT32(17.250/DV), UINT32(17.625/DV), UINT32(18.000/DV),
+ /* OCT 7 */
+ UINT32( 0.000/DV), UINT32( 9.000/DV), UINT32(12.000/DV), UINT32(13.875/DV),
+ UINT32(15.000/DV), UINT32(16.125/DV), UINT32(16.875/DV), UINT32(17.625/DV),
+ UINT32(18.000/DV), UINT32(18.750/DV), UINT32(19.125/DV), UINT32(19.500/DV),
+ UINT32(19.875/DV), UINT32(20.250/DV), UINT32(20.625/DV), UINT32(21.000/DV)
+};
+#undef DV
+
+/* sustain level table (3dB per step) */
+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
+#define SC(db) (UINT32) ( db * (2.0/ENV_STEP) )
+static const UINT32 sl_tab[16]={
+ SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+ SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
+};
+#undef SC
+
+
+#define RATE_STEPS (8)
+static const unsigned char eg_inc[15*RATE_STEPS]={
+
+/*cycle:0 1 2 3 4 5 6 7*/
+
+/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
+/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
+/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
+/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
+
+/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
+/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
+/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
+/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
+
+/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
+/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
+/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
+/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
+
+/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
+/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
+/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
+};
+
+
+#define O(a) (a*RATE_STEPS)
+
+/*note that there is no O(13) in this table - it's directly in the code */
+static const unsigned char eg_rate_select[16+64+16]={ /* Envelope Generator rates (16 + 64 rates + 16 RKS) */
+/* 16 infinite time rates */
+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
+
+/* rates 00-12 */
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+
+/* rate 13 */
+O( 4),O( 5),O( 6),O( 7),
+
+/* rate 14 */
+O( 8),O( 9),O(10),O(11),
+
+/* rate 15 */
+O(12),O(12),O(12),O(12),
+
+/* 16 dummy rates (same as 15 3) */
+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
+
+};
+#undef O
+
+/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
+/*shift 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 */
+/*mask 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0 */
+
+#define O(a) (a*1)
+static const unsigned char eg_rate_shift[16+64+16]={ /* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
+/* 16 infinite time rates */
+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
+
+/* rates 00-12 */
+O(12),O(12),O(12),O(12),
+O(11),O(11),O(11),O(11),
+O(10),O(10),O(10),O(10),
+O( 9),O( 9),O( 9),O( 9),
+O( 8),O( 8),O( 8),O( 8),
+O( 7),O( 7),O( 7),O( 7),
+O( 6),O( 6),O( 6),O( 6),
+O( 5),O( 5),O( 5),O( 5),
+O( 4),O( 4),O( 4),O( 4),
+O( 3),O( 3),O( 3),O( 3),
+O( 2),O( 2),O( 2),O( 2),
+O( 1),O( 1),O( 1),O( 1),
+O( 0),O( 0),O( 0),O( 0),
+
+/* rate 13 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* rate 14 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* rate 15 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* 16 dummy rates (same as 15 3) */
+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
+
+};
+#undef O
+
+
+/* multiple table */
+#define ML 2
+static const UINT8 mul_tab[16]= {
+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
+ UINT8( 0.50*ML),UINT8( 1.00*ML),UINT8( 2.00*ML),UINT8( 3.00*ML),UINT8( 4.00*ML),UINT8( 5.00*ML),UINT8( 6.00*ML),UINT8( 7.00*ML),
+ UINT8( 8.00*ML),UINT8( 9.00*ML),UINT8(10.00*ML),UINT8(10.00*ML),UINT8(12.00*ML),UINT8(12.00*ML),UINT8(15.00*ML),UINT8(15.00*ML)
+};
+#undef ML
+
+/* TL_TAB_LEN is calculated as:
+* 12 - sinus amplitude bits (Y axis)
+* 2 - sinus sign bit (Y axis)
+* TL_RES_LEN - sinus resolution (X axis)
+*/
+#define TL_TAB_LEN (12*2*TL_RES_LEN)
+static signed int tl_tab[TL_TAB_LEN];
+
+#define ENV_QUIET (TL_TAB_LEN>>4)
+
+/* sin waveform table in 'decibel' scale */
+/* four waveforms on OPL2 type chips */
+static unsigned int sin_tab[SIN_LEN * 4];
+
+
+/* LFO Amplitude Modulation table (verified on real YM3812)
+ 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
+
+ Length: 210 elements.
+
+ Each of the elements has to be repeated
+ exactly 64 times (on 64 consecutive samples).
+ The whole table takes: 64 * 210 = 13440 samples.
+
+ When AM = 1 data is used directly
+ When AM = 0 data is divided by 4 before being used (loosing precision is important)
+*/
+
+#define LFO_AM_TAB_ELEMENTS 210
+
+static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
+0,0,0,0,0,0,0,
+1,1,1,1,
+2,2,2,2,
+3,3,3,3,
+4,4,4,4,
+5,5,5,5,
+6,6,6,6,
+7,7,7,7,
+8,8,8,8,
+9,9,9,9,
+10,10,10,10,
+11,11,11,11,
+12,12,12,12,
+13,13,13,13,
+14,14,14,14,
+15,15,15,15,
+16,16,16,16,
+17,17,17,17,
+18,18,18,18,
+19,19,19,19,
+20,20,20,20,
+21,21,21,21,
+22,22,22,22,
+23,23,23,23,
+24,24,24,24,
+25,25,25,25,
+26,26,26,
+25,25,25,25,
+24,24,24,24,
+23,23,23,23,
+22,22,22,22,
+21,21,21,21,
+20,20,20,20,
+19,19,19,19,
+18,18,18,18,
+17,17,17,17,
+16,16,16,16,
+15,15,15,15,
+14,14,14,14,
+13,13,13,13,
+12,12,12,12,
+11,11,11,11,
+10,10,10,10,
+9,9,9,9,
+8,8,8,8,
+7,7,7,7,
+6,6,6,6,
+5,5,5,5,
+4,4,4,4,
+3,3,3,3,
+2,2,2,2,
+1,1,1,1
+};
+
+/* LFO Phase Modulation table (verified on real YM3812) */
+static const INT8 lfo_pm_table[8*8*2] = {
+
+/* FNUM2/FNUM = 00 0xxxxxxx (0x0000) */
+0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
+0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 00 1xxxxxxx (0x0080) */
+0, 0, 0, 0, 0, 0, 0, 0, /*LFO PM depth = 0*/
+1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 01 0xxxxxxx (0x0100) */
+1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/
+2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 01 1xxxxxxx (0x0180) */
+1, 0, 0, 0,-1, 0, 0, 0, /*LFO PM depth = 0*/
+3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 10 0xxxxxxx (0x0200) */
+2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/
+4, 2, 0,-2,-4,-2, 0, 2, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 10 1xxxxxxx (0x0280) */
+2, 1, 0,-1,-2,-1, 0, 1, /*LFO PM depth = 0*/
+5, 2, 0,-2,-5,-2, 0, 2, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 11 0xxxxxxx (0x0300) */
+3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/
+6, 3, 0,-3,-6,-3, 0, 3, /*LFO PM depth = 1*/
+
+/* FNUM2/FNUM = 11 1xxxxxxx (0x0380) */
+3, 1, 0,-1,-3,-1, 0, 1, /*LFO PM depth = 0*/
+7, 3, 0,-3,-7,-3, 0, 3 /*LFO PM depth = 1*/
+};
+
+
+/* lock level of common table */
+//static int num_lock = 0;
+
+
+//static void *cur_chip = NULL; /* current chip pointer */
+
+INLINE int limit( int val, int max, int min ) {
+ if ( val > max )
+ val = max;
+ else if ( val < min )
+ val = min;
+
+ return val;
+}
+
+
+/* status set and IRQ handling */
+INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
+{
+ /* set status flag */
+ OPL->status |= flag;
+ if(!(OPL->status & 0x80))
+ {
+ if(OPL->status & OPL->statusmask)
+ { /* IRQ on */
+ OPL->status |= 0x80;
+ /* callback user interrupt handler (IRQ is OFF to ON) */
+ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
+ }
+ }
+}
+
+/* status reset and IRQ handling */
+INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
+{
+ /* reset status flag */
+ OPL->status &=~flag;
+ if((OPL->status & 0x80))
+ {
+ if (!(OPL->status & OPL->statusmask) )
+ {
+ OPL->status &= 0x7f;
+ /* callback user interrupt handler (IRQ is ON to OFF) */
+ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
+ }
+ }
+}
+
+/* IRQ mask set */
+INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
+{
+ OPL->statusmask = flag;
+ /* IRQ handling check */
+ OPL_STATUS_SET(OPL,0);
+ OPL_STATUS_RESET(OPL,0);
+}
+
+
+/* advance LFO to next sample */
+INLINE void advance_lfo(FM_OPL *OPL)
+{
+ UINT8 tmp;
+
+ /* LFO */
+ OPL->lfo_am_cnt += OPL->lfo_am_inc;
+ if (OPL->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<lfo_am_cnt >> LFO_SH ];
+
+ if (OPL->lfo_am_depth)
+ OPL->LFO_AM = tmp;
+ else
+ OPL->LFO_AM = tmp>>2;
+
+ OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
+ OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
+}
+
+/* advance to next sample */
+INLINE void advance(FM_OPL *OPL)
+{
+ OPL_CH *CH;
+ OPL_SLOT *op;
+ int i;
+
+ OPL->eg_timer += OPL->eg_timer_add;
+
+ while (OPL->eg_timer >= OPL->eg_timer_overflow)
+ {
+ OPL->eg_timer -= OPL->eg_timer_overflow;
+
+ OPL->eg_cnt++;
+
+ for (i=0; i<9*2; i++)
+ {
+ CH = &OPL->P_CH[i/2];
+ op = &CH->SLOT[i&1];
+
+ /* Envelope Generator */
+ switch(op->state)
+ {
+ case EG_ATT: /* attack phase */
+ if ( !(OPL->eg_cnt & ((1<eg_sh_ar)-1) ) )
+ {
+ op->volume += (~op->volume *
+ (eg_inc[op->eg_sel_ar + ((OPL->eg_cnt>>op->eg_sh_ar)&7)])
+ ) >>3;
+
+ if (op->volume <= MIN_ATT_INDEX)
+ {
+ op->volume = MIN_ATT_INDEX;
+ op->state = EG_DEC;
+ }
+
+ }
+ break;
+
+ case EG_DEC: /* decay phase */
+ if ( !(OPL->eg_cnt & ((1<eg_sh_dr)-1) ) )
+ {
+ op->volume += eg_inc[op->eg_sel_dr + ((OPL->eg_cnt>>op->eg_sh_dr)&7)];
+
+ if ( op->volume >= op->sl )
+ op->state = EG_SUS;
+
+ }
+ break;
+
+ case EG_SUS: /* sustain phase */
+
+ /* this is important behaviour:
+ one can change percusive/non-percussive modes on the fly and
+ the chip will remain in sustain phase - verified on real YM3812 */
+
+ if(op->eg_type) /* non-percussive mode */
+ {
+ /* do nothing */
+ }
+ else /* percussive mode */
+ {
+ /* during sustain phase chip adds Release Rate (in percussive mode) */
+ if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) )
+ {
+ op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
+
+ if ( op->volume >= MAX_ATT_INDEX )
+ op->volume = MAX_ATT_INDEX;
+ }
+ /* else do nothing in sustain phase */
+ }
+ break;
+
+ case EG_REL: /* release phase */
+ if ( !(OPL->eg_cnt & ((1<eg_sh_rr)-1) ) )
+ {
+ op->volume += eg_inc[op->eg_sel_rr + ((OPL->eg_cnt>>op->eg_sh_rr)&7)];
+
+ if ( op->volume >= MAX_ATT_INDEX )
+ {
+ op->volume = MAX_ATT_INDEX;
+ op->state = EG_OFF;
+ }
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ for (i=0; i<9*2; i++)
+ {
+ CH = &OPL->P_CH[i/2];
+ op = &CH->SLOT[i&1];
+
+ /* Phase Generator */
+ if(op->vib)
+ {
+ UINT8 block;
+ unsigned int block_fnum = CH->block_fnum;
+
+ unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
+
+ signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];
+
+ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
+ {
+ block_fnum += lfo_fn_table_index_offset;
+ block = (block_fnum&0x1c00) >> 10;
+ op->Cnt += (OPL->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
+ }
+ else /* LFO phase modulation = zero */
+ {
+ op->Cnt += op->Incr;
+ }
+ }
+ else /* LFO phase modulation disabled for this operator */
+ {
+ op->Cnt += op->Incr;
+ }
+ }
+
+ /* The Noise Generator of the YM3812 is 23-bit shift register.
+ * Period is equal to 2^23-2 samples.
+ * Register works at sampling frequency of the chip, so output
+ * can change on every sample.
+ *
+ * Output of the register and input to the bit 22 is:
+ * bit0 XOR bit14 XOR bit15 XOR bit22
+ *
+ * Simply use bit 22 as the noise output.
+ */
+
+ OPL->noise_p += OPL->noise_f;
+ i = OPL->noise_p >> FREQ_SH; /* number of events (shifts of the shift register) */
+ OPL->noise_p &= FREQ_MASK;
+ while (i)
+ {
+ /*
+ UINT32 j;
+ j = ( (OPL->noise_rng) ^ (OPL->noise_rng>>14) ^ (OPL->noise_rng>>15) ^ (OPL->noise_rng>>22) ) & 1;
+ OPL->noise_rng = (j<<22) | (OPL->noise_rng>>1);
+ */
+
+ /*
+ Instead of doing all the logic operations above, we
+ use a trick here (and use bit 0 as the noise output).
+ The difference is only that the noise bit changes one
+ step ahead. This doesn't matter since we don't know
+ what is real state of the noise_rng after the reset.
+ */
+
+ if (OPL->noise_rng & 1) OPL->noise_rng ^= 0x800302;
+ OPL->noise_rng >>= 1;
+
+ i--;
+ }
+}
+
+
+INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
+{
+ UINT32 p;
+
+ p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<16))) >> FREQ_SH ) & SIN_MASK) ];
+
+ if (p >= TL_TAB_LEN)
+ return 0;
+ return tl_tab[p];
+}
+
+INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
+{
+ UINT32 p;
+
+ p = (env<<4) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + pm )) >> FREQ_SH ) & SIN_MASK) ];
+
+ if (p >= TL_TAB_LEN)
+ return 0;
+ return tl_tab[p];
+}
+
+
+#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))
+
+/* calculate output */
+INLINE void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )
+{
+ OPL_SLOT *SLOT;
+ unsigned int env;
+ signed int out;
+
+ OPL->phase_modulation = 0;
+
+ /* SLOT 1 */
+ SLOT = &CH->SLOT[SLOT1];
+ env = volume_calc(SLOT);
+ out = SLOT->op1_out[0] + SLOT->op1_out[1];
+ SLOT->op1_out[0] = SLOT->op1_out[1];
+ *SLOT->connect1 += SLOT->op1_out[0];
+ SLOT->op1_out[1] = 0;
+ if( env < ENV_QUIET )
+ {
+ if (!SLOT->FB)
+ out = 0;
+ SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable );
+ }
+
+ /* SLOT 2 */
+ SLOT++;
+ env = volume_calc(SLOT);
+ if( env < ENV_QUIET )
+ OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);
+}
+
+/*
+ operators used in the rhythm sounds generation process:
+
+ Envelope Generator:
+
+channel operator register number Bass High Snare Tom Top
+/ slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
+ 6 / 0 12 50 70 90 f0 +
+ 6 / 1 15 53 73 93 f3 +
+ 7 / 0 13 51 71 91 f1 +
+ 7 / 1 16 54 74 94 f4 +
+ 8 / 0 14 52 72 92 f2 +
+ 8 / 1 17 55 75 95 f5 +
+
+ Phase Generator:
+
+channel operator register number Bass High Snare Tom Top
+/ slot number MULTIPLE Drum Hat Drum Tom Cymbal
+ 6 / 0 12 30 +
+ 6 / 1 15 33 +
+ 7 / 0 13 31 + + +
+ 7 / 1 16 34 ----- n o t u s e d -----
+ 8 / 0 14 32 +
+ 8 / 1 17 35 + +
+
+channel operator register number Bass High Snare Tom Top
+number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
+ 6 12,15 B6 A6 +
+
+ 7 13,16 B7 A7 + + +
+
+ 8 14,17 B8 A8 + + +
+
+*/
+
+/* calculate rhythm */
+
+INLINE void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )
+{
+ OPL_SLOT *SLOT;
+ signed int out;
+ unsigned int env;
+
+
+ /* Bass Drum (verified on real YM3812):
+ - depends on the channel 6 'connect' register:
+ when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
+ when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
+ - output sample always is multiplied by 2
+ */
+
+ OPL->phase_modulation = 0;
+ /* SLOT 1 */
+ SLOT = &CH[6].SLOT[SLOT1];
+ env = volume_calc(SLOT);
+
+ out = SLOT->op1_out[0] + SLOT->op1_out[1];
+ SLOT->op1_out[0] = SLOT->op1_out[1];
+
+ if (!SLOT->CON)
+ OPL->phase_modulation = SLOT->op1_out[0];
+ /* else ignore output of operator 1 */
+
+ SLOT->op1_out[1] = 0;
+ if( env < ENV_QUIET )
+ {
+ if (!SLOT->FB)
+ out = 0;
+ SLOT->op1_out[1] = op_calc1(SLOT->Cnt, env, (out<FB), SLOT->wavetable );
+ }
+
+ /* SLOT 2 */
+ SLOT++;
+ env = volume_calc(SLOT);
+ if( env < ENV_QUIET )
+ OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;
+
+
+ /* Phase generation is based on: */
+ /* HH (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases) */
+ /* SD (16) channel 7->slot 1 */
+ /* TOM (14) channel 8->slot 1 */
+ /* TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
+
+ /* Envelope generation based on: */
+ /* HH channel 7->slot1 */
+ /* SD channel 7->slot2 */
+ /* TOM channel 8->slot1 */
+ /* TOP channel 8->slot2 */
+
+
+ /* The following formulas can be well optimized.
+ I leave them in direct form for now (in case I've missed something).
+ */
+
+ /* High Hat (verified on real YM3812) */
+ env = volume_calc(OPL->SLOT7_1);
+ if( env < ENV_QUIET )
+ {
+
+ /* high hat phase generation:
+ phase = d0 or 234 (based on frequency only)
+ phase = 34 or 2d0 (based on noise)
+ */
+
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char bit7 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
+ unsigned char bit3 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
+ unsigned char bit2 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
+
+ unsigned char res1 = (bit2 ^ bit7) | bit3;
+
+ /* when res1 = 0 phase = 0x000 | 0xd0; */
+ /* when res1 = 1 phase = 0x200 | (0xd0>>2); */
+ UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
+
+ /* enable gate based on frequency of operator 2 in channel 8 */
+ unsigned char bit5e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
+ unsigned char bit3e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
+
+ unsigned char res2 = (bit3e ^ bit5e);
+
+ /* when res2 = 0 pass the phase from calculation above (res1); */
+ /* when res2 = 1 phase = 0x200 | (0xd0>>2); */
+ if (res2)
+ phase = (0x200|(0xd0>>2));
+
+
+ /* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
+ /* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
+ if (phase&0x200)
+ {
+ if (noise)
+ phase = 0x200|0xd0;
+ }
+ else
+ /* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
+ /* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
+ {
+ if (noise)
+ phase = 0xd0>>2;
+ }
+
+ OPL->output[0] += op_calc(phase<SLOT7_1->wavetable) * 2;
+ }
+
+ /* Snare Drum (verified on real YM3812) */
+ env = volume_calc(OPL->SLOT7_2);
+ if( env < ENV_QUIET )
+ {
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char bit8 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>8)&1;
+
+ /* when bit8 = 0 phase = 0x100; */
+ /* when bit8 = 1 phase = 0x200; */
+ UINT32 phase = bit8 ? 0x200 : 0x100;
+
+ /* Noise bit XOR'es phase by 0x100 */
+ /* when noisebit = 0 pass the phase from calculation above */
+ /* when noisebit = 1 phase ^= 0x100; */
+ /* in other words: phase ^= (noisebit<<8); */
+ if (noise)
+ phase ^= 0x100;
+
+ OPL->output[0] += op_calc(phase<SLOT7_2->wavetable) * 2;
+ }
+
+ /* Tom Tom (verified on real YM3812) */
+ env = volume_calc(OPL->SLOT8_1);
+ if( env < ENV_QUIET )
+ OPL->output[0] += op_calc(OPL->SLOT8_1->Cnt, env, 0, OPL->SLOT8_1->wavetable) * 2;
+
+ /* Top Cymbal (verified on real YM3812) */
+ env = volume_calc(OPL->SLOT8_2);
+ if( env < ENV_QUIET )
+ {
+ /* base frequency derived from operator 1 in channel 7 */
+ unsigned char bit7 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>7)&1;
+ unsigned char bit3 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>3)&1;
+ unsigned char bit2 = ((OPL->SLOT7_1->Cnt>>FREQ_SH)>>2)&1;
+
+ unsigned char res1 = (bit2 ^ bit7) | bit3;
+
+ /* when res1 = 0 phase = 0x000 | 0x100; */
+ /* when res1 = 1 phase = 0x200 | 0x100; */
+ UINT32 phase = res1 ? 0x300 : 0x100;
+
+ /* enable gate based on frequency of operator 2 in channel 8 */
+ unsigned char bit5e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>5)&1;
+ unsigned char bit3e= ((OPL->SLOT8_2->Cnt>>FREQ_SH)>>3)&1;
+
+ unsigned char res2 = (bit3e ^ bit5e);
+ /* when res2 = 0 pass the phase from calculation above (res1); */
+ /* when res2 = 1 phase = 0x200 | 0x100; */
+ if (res2)
+ phase = 0x300;
+
+ OPL->output[0] += op_calc(phase<SLOT8_2->wavetable) * 2;
+ }
+
+}
+
+
+/* generic table initialize */
+static int init_tables(void)
+{
+ signed int i,x;
+ signed int n;
+ double o,m;
+
+
+ for (x=0; x>= 4; /* 12 bits here */
+ if (n&1) /* round to nearest */
+ n = (n>>1)+1;
+ else
+ n = n>>1;
+ /* 11 bits here (rounded) */
+ n <<= 1; /* 12 bits here (as in real chip) */
+ tl_tab[ x*2 + 0 ] = n;
+ tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
+
+ for (i=1; i<12; i++)
+ {
+ tl_tab[ x*2+0 + i*2*TL_RES_LEN ] = tl_tab[ x*2+0 ]>>i;
+ tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
+ }
+ #if 0
+ logerror("tl %04i", x*2);
+ for (i=0; i<12; i++)
+ logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );
+ logerror("\n");
+ #endif
+ }
+ /*logerror("FMOPL.C: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
+
+
+ for (i=0; i0.0)
+ o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */
+ else
+ o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */
+
+ o = o / (ENV_STEP/4);
+
+ n = (int)(2.0*o);
+ if (n&1) /* round to nearest */
+ n = (n>>1)+1;
+ else
+ n = n>>1;
+
+ sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
+
+ /*logerror("FMOPL.C: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
+ }
+
+ for (i=0; i>1) ];
+
+ /* waveform 3: _ _ _ _ */
+ /* / |_/ |_/ |_/ |_*/
+ /* abs(output only first quarter of the sinus waveform) */
+
+ if (i & (1<<(SIN_BITS-2)) )
+ sin_tab[3*SIN_LEN+i] = TL_TAB_LEN;
+ else
+ sin_tab[3*SIN_LEN+i] = sin_tab[i & (SIN_MASK>>2)];
+
+ /*logerror("FMOPL.C: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );
+ logerror("FMOPL.C: sin2[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[2*SIN_LEN+i], tl_tab[sin_tab[2*SIN_LEN+i]] );
+ logerror("FMOPL.C: sin3[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[3*SIN_LEN+i], tl_tab[sin_tab[3*SIN_LEN+i]] );*/
+ }
+ /*logerror("FMOPL.C: ENV_QUIET= %08x (dec*8=%i)\n", ENV_QUIET, ENV_QUIET*8 );*/
+
+
+#ifdef SAVE_SAMPLE
+ sample[0]=fopen("sampsum.pcm","wb");
+#endif
+
+ return 1;
+}
+
+static void OPLCloseTable( void )
+{
+#ifdef SAVE_SAMPLE
+ fclose(sample[0]);
+#endif
+}
+
+
+
+static void OPL_initalize(FM_OPL *OPL)
+{
+ int i;
+
+ /* frequency base */
+ OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / 72.0) / OPL->rate : 0;
+#if 0
+ OPL->rate = (double)OPL->clock / 72.0;
+ OPL->freqbase = 1.0;
+#endif
+
+ /*logerror("freqbase=%f\n", OPL->freqbase);*/
+
+ /* Timer base time */
+ //OPL->TimerBase = attotime_mul(ATTOTIME_IN_HZ(OPL->clock), 72);
+
+ /* make fnumber -> increment counter table */
+ for( i=0 ; i < 1024 ; i++ )
+ {
+ /* opn phase increment counter = 20bit */
+ OPL->fn_tab[i] = (UINT32)( (double)i * 64 * OPL->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
+#if 0
+ logerror("FMOPL.C: fn_tab[%4i] = %08x (dec=%8i)\n",
+ i, OPL->fn_tab[i]>>6, OPL->fn_tab[i]>>6 );
+#endif
+ }
+
+#if 0
+ for( i=0 ; i < 16 ; i++ )
+ {
+ logerror("FMOPL.C: sl_tab[%i] = %08x\n",
+ i, sl_tab[i] );
+ }
+ for( i=0 ; i < 8 ; i++ )
+ {
+ int j;
+ logerror("FMOPL.C: ksl_tab[oct=%2i] =",i);
+ for (j=0; j<16; j++)
+ {
+ logerror("%08x ", ksl_tab[i*16+j] );
+ }
+ logerror("\n");
+ }
+#endif
+
+
+ /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
+ /* One entry from LFO_AM_TABLE lasts for 64 samples */
+ OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase;
+
+ /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
+ OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase;
+
+ /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
+
+ /* Noise generator: a step takes 1 sample */
+ OPL->noise_f = (1.0 / 1.0) * (1<freqbase;
+
+ OPL->eg_timer_add = (1<freqbase;
+ OPL->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, OPL->eg_timer_overflow);*/
+
+}
+
+INLINE void FM_KEYON(OPL_SLOT *SLOT, UINT32 key_set)
+{
+ if( !SLOT->key )
+ {
+ /* restart Phase Generator */
+ SLOT->Cnt = 0;
+ /* phase -> Attack */
+ SLOT->state = EG_ATT;
+ }
+ SLOT->key |= key_set;
+}
+
+INLINE void FM_KEYOFF(OPL_SLOT *SLOT, UINT32 key_clr)
+{
+ if( SLOT->key )
+ {
+ SLOT->key &= key_clr;
+
+ if( !SLOT->key )
+ {
+ /* phase -> Release */
+ if (SLOT->state>EG_REL)
+ SLOT->state = EG_REL;
+ }
+ }
+}
+
+/* update phase increment counter of operator (also update the EG rates if necessary) */
+INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
+{
+ int ksr;
+
+ /* (frequency) phase increment counter */
+ SLOT->Incr = CH->fc * SLOT->mul;
+ ksr = CH->kcode >> SLOT->KSR;
+
+ if( SLOT->ksr != ksr )
+ {
+ SLOT->ksr = ksr;
+
+ /* calculate envelope generator rates */
+ if ((SLOT->ar + SLOT->ksr) < 16+62)
+ {
+ SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
+ SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+ }
+ else
+ {
+ SLOT->eg_sh_ar = 0;
+ SLOT->eg_sel_ar = 13*RATE_STEPS;
+ }
+ SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
+ SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
+ SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
+ SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+ }
+}
+
+/* set multi,am,vib,EG-TYP,KSR,mul */
+INLINE void set_mul(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+ SLOT->mul = mul_tab[v&0x0f];
+ SLOT->KSR = (v&0x10) ? 0 : 2;
+ SLOT->eg_type = (v&0x20);
+ SLOT->vib = (v&0x40);
+ SLOT->AMmask = (v&0x80) ? ~0 : 0;
+ CALC_FCSLOT(CH,SLOT);
+}
+
+/* set ksl & tl */
+INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+ int ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
+
+ SLOT->ksl = ksl ? 3-ksl : 31;
+ SLOT->TL = (v&0x3f)<<(ENV_BITS-1-7); /* 7 bits TL (bit 6 = always 0) */
+
+ SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+}
+
+/* set attack rate & decay rate */
+INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+ SLOT->ar = (v>>4) ? 16 + ((v>>4) <<2) : 0;
+
+ if ((SLOT->ar + SLOT->ksr) < 16+62)
+ {
+ SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
+ SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+ }
+ else
+ {
+ SLOT->eg_sh_ar = 0;
+ SLOT->eg_sel_ar = 13*RATE_STEPS;
+ }
+
+ SLOT->dr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+ SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
+ SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
+}
+
+/* set sustain level & release rate */
+INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+ SLOT->sl = sl_tab[ v>>4 ];
+
+ SLOT->rr = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+ SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
+ SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+}
+
+
+/* write a value v to register r on OPL chip */
+static void OPLWriteReg(FM_OPL *OPL, int r, int v)
+{
+ OPL_CH *CH;
+ int slot;
+ UINT32 block_fnum;
+
+
+ /* adjust bus to 8 bits */
+ r &= 0xff;
+ v &= 0xff;
+
+ /*if (LOG_CYM_FILE && (cymfile) && (r!=0) )
+ {
+ fputc( (unsigned char)r, cymfile );
+ fputc( (unsigned char)v, cymfile );
+ }*/
+
+
+ switch(r&0xe0)
+ {
+ case 0x00: /* 00-1f:control */
+ switch(r&0x1f)
+ {
+ case 0x01: /* waveform select enable */
+ if(OPL->type&OPL_TYPE_WAVESEL)
+ {
+ OPL->wavesel = v&0x20;
+ /* do not change the waveform previously selected */
+ }
+ break;
+ case 0x02: /* Timer 1 */
+ OPL->T[0] = (256-v)*4;
+ break;
+ case 0x03: /* Timer 2 */
+ OPL->T[1] = (256-v)*16;
+ break;
+ case 0x04: /* IRQ clear / mask and Timer enable */
+ if(v&0x80)
+ { /* IRQ flag clear */
+ OPL_STATUS_RESET(OPL,0x7f-0x08); /* don't reset BFRDY flag or we will have to call deltat module to set the flag */
+ }
+ else
+ { /* set IRQ mask ,timer enable*/
+ /*UINT8 st1 = v&1;
+ UINT8 st2 = (v>>1)&1;*/
+
+ /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
+ OPL_STATUS_RESET(OPL, v & (0x78-0x08) );
+ OPL_STATUSMASK_SET(OPL, (~v) & 0x78 );
+
+ /* timer 2 */
+ /*if(OPL->st[1] != st2)
+ {
+ attotime period = st2 ? attotime_mul(OPL->TimerBase, OPL->T[1]) : attotime_zero;
+ OPL->st[1] = st2;
+ if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,1,period);
+ }*/
+ /* timer 1 */
+ /*if(OPL->st[0] != st1)
+ {
+ attotime period = st1 ? attotime_mul(OPL->TimerBase, OPL->T[0]) : attotime_zero;
+ OPL->st[0] = st1;
+ if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,0,period);
+ }*/
+ }
+ break;
+#if BUILD_Y8950
+ case 0x06: /* Key Board OUT */
+ if(OPL->type&OPL_TYPE_KEYBOARD)
+ {
+ if(OPL->keyboardhandler_w)
+ OPL->keyboardhandler_w(OPL->keyboard_param,v);
+ /*else
+ logerror("Y8950: write unmapped KEYBOARD port\n");*/
+ }
+ break;
+ case 0x07: /* DELTA-T control 1 : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ break;
+#endif
+ case 0x08: /* MODE,DELTA-T control 2 : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
+ OPL->mode = v;
+#if BUILD_Y8950
+ if(OPL->type&OPL_TYPE_ADPCM)
+ YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v&0x0f); /* mask 4 LSBs in register 08 for DELTA-T unit */
+#endif
+ break;
+
+#if BUILD_Y8950
+ case 0x09: /* START ADD */
+ case 0x0a:
+ case 0x0b: /* STOP ADD */
+ case 0x0c:
+ case 0x0d: /* PRESCALE */
+ case 0x0e:
+ case 0x0f: /* ADPCM data write */
+ case 0x10: /* DELTA-N */
+ case 0x11: /* DELTA-N */
+ case 0x12: /* ADPCM volume */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ break;
+
+ case 0x15: /* DAC data high 8 bits (F7,F6...F2) */
+ case 0x16: /* DAC data low 2 bits (F1, F0 in bits 7,6) */
+ case 0x17: /* DAC data shift (S2,S1,S0 in bits 2,1,0) */
+ /*logerror("FMOPL.C: DAC data register written, but not implemented reg=%02x val=%02x\n",r,v);*/
+ break;
+
+ case 0x18: /* I/O CTRL (Direction) */
+ if(OPL->type&OPL_TYPE_IO)
+ OPL->portDirection = v&0x0f;
+ break;
+ case 0x19: /* I/O DATA */
+ if(OPL->type&OPL_TYPE_IO)
+ {
+ OPL->portLatch = v;
+ if(OPL->porthandler_w)
+ OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
+ }
+ break;
+#endif
+ default:
+ /*logerror("FMOPL.C: write to unknown register: %02x\n",r);*/
+ break;
+ }
+ break;
+ case 0x20: /* am ON, vib ON, ksr, eg_type, mul */
+ slot = slot_array[r&0x1f];
+ if(slot < 0) return;
+ set_mul(OPL,slot,v);
+ break;
+ case 0x40:
+ slot = slot_array[r&0x1f];
+ if(slot < 0) return;
+ set_ksl_tl(OPL,slot,v);
+ break;
+ case 0x60:
+ slot = slot_array[r&0x1f];
+ if(slot < 0) return;
+ set_ar_dr(OPL,slot,v);
+ break;
+ case 0x80:
+ slot = slot_array[r&0x1f];
+ if(slot < 0) return;
+ set_sl_rr(OPL,slot,v);
+ break;
+ case 0xa0:
+ if (r == 0xbd) /* am depth, vibrato depth, r,bd,sd,tom,tc,hh */
+ {
+ OPL->lfo_am_depth = v & 0x80;
+ OPL->lfo_pm_depth_range = (v&0x40) ? 8 : 0;
+
+ OPL->rhythm = v&0x3f;
+
+ if(OPL->rhythm&0x20)
+ {
+ /* BD key on/off */
+ if(v&0x10)
+ {
+ FM_KEYON (&OPL->P_CH[6].SLOT[SLOT1], 2);
+ FM_KEYON (&OPL->P_CH[6].SLOT[SLOT2], 2);
+ }
+ else
+ {
+ FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
+ FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
+ }
+ /* HH key on/off */
+ if(v&0x01) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT1], 2);
+ else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
+ /* SD key on/off */
+ if(v&0x08) FM_KEYON (&OPL->P_CH[7].SLOT[SLOT2], 2);
+ else FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
+ /* TOM key on/off */
+ if(v&0x04) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT1], 2);
+ else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
+ /* TOP-CY key on/off */
+ if(v&0x02) FM_KEYON (&OPL->P_CH[8].SLOT[SLOT2], 2);
+ else FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
+ }
+ else
+ {
+ /* BD key off */
+ FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1],~2);
+ FM_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2],~2);
+ /* HH key off */
+ FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1],~2);
+ /* SD key off */
+ FM_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2],~2);
+ /* TOM key off */
+ FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1],~2);
+ /* TOP-CY off */
+ FM_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2],~2);
+ }
+ return;
+ }
+ /* keyon,block,fnum */
+ if( (r&0x0f) > 8) return;
+ CH = &OPL->P_CH[r&0x0f];
+ if(!(r&0x10))
+ { /* a0-a8 */
+ block_fnum = (CH->block_fnum&0x1f00) | v;
+ }
+ else
+ { /* b0-b8 */
+ block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
+
+ if(v&0x20)
+ {
+ FM_KEYON (&CH->SLOT[SLOT1], 1);
+ FM_KEYON (&CH->SLOT[SLOT2], 1);
+ }
+ else
+ {
+ FM_KEYOFF(&CH->SLOT[SLOT1],~1);
+ FM_KEYOFF(&CH->SLOT[SLOT2],~1);
+ }
+ }
+ /* update */
+ if(CH->block_fnum != block_fnum)
+ {
+ UINT8 block = block_fnum >> 10;
+
+ CH->block_fnum = block_fnum;
+
+ CH->ksl_base = ksl_tab[block_fnum>>6];
+ CH->fc = OPL->fn_tab[block_fnum&0x03ff] >> (7-block);
+
+ /* BLK 2,1,0 bits -> bits 3,2,1 of kcode */
+ CH->kcode = (CH->block_fnum&0x1c00)>>9;
+
+ /* the info below is actually opposite to what is stated in the Manuals (verifed on real YM3812) */
+ /* if notesel == 0 -> lsb of kcode is bit 10 (MSB) of fnum */
+ /* if notesel == 1 -> lsb of kcode is bit 9 (MSB-1) of fnum */
+ if (OPL->mode&0x40)
+ CH->kcode |= (CH->block_fnum&0x100)>>8; /* notesel == 1 */
+ else
+ CH->kcode |= (CH->block_fnum&0x200)>>9; /* notesel == 0 */
+
+ /* refresh Total Level in both SLOTs of this channel */
+ CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
+ CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
+
+ /* refresh frequency counter in both SLOTs of this channel */
+ CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
+ CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
+ }
+ break;
+ case 0xc0:
+ /* FB,C */
+ if( (r&0x0f) > 8) return;
+ CH = &OPL->P_CH[r&0x0f];
+ CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
+ CH->SLOT[SLOT1].CON = v&1;
+ CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;
+ break;
+ case 0xe0: /* waveform select */
+ /* simply ignore write to the waveform select register if selecting not enabled in test register */
+ if(OPL->wavesel)
+ {
+ slot = slot_array[r&0x1f];
+ if(slot < 0) return;
+ CH = &OPL->P_CH[slot/2];
+
+ CH->SLOT[slot&1].wavetable = (v&0x03)*SIN_LEN;
+ }
+ break;
+ }
+}
+
+/*static TIMER_CALLBACK( cymfile_callback )
+{
+ if (cymfile)
+ {
+ fputc( (unsigned char)0, cymfile );
+ }
+}*/
+
+/* lock/unlock for common table */
+#if 0
+static int OPL_LockTable(/*const device_config *device*/)
+{
+ num_lock++;
+ if(num_lock>1) return 0;
+
+ /* first time */
+
+ cur_chip = NULL;
+ /* allocate total level table (128kb space) */
+ if( !init_tables() )
+ {
+ num_lock--;
+ return -1;
+ }
+
+#if 0
+ if (LOG_CYM_FILE)
+ {
+ cymfile = fopen("3812_.cym","wb");
+ if (cymfile)
+ timer_pulse ( device->machine, ATTOTIME_IN_HZ(110), NULL, 0, cymfile_callback); /*110 Hz pulse timer*/
+ else
+ logerror("Could not create file 3812_.cym\n");
+ }
+#endif
+
+ return 0;
+}
+
+static void OPL_UnLockTable(void)
+{
+ if(num_lock) num_lock--;
+ if(num_lock) return;
+
+ /* last time */
+
+ cur_chip = NULL;
+ OPLCloseTable();
+
+ /*if (cymfile)
+ fclose (cymfile);
+ cymfile = NULL;*/
+}
+#endif
+
+static void OPLResetChip(FM_OPL *OPL)
+{
+ int c,s;
+ int i;
+
+ OPL->eg_timer = 0;
+ OPL->eg_cnt = 0;
+
+ OPL->noise_rng = 1; /* noise shift register */
+ OPL->mode = 0; /* normal mode */
+ OPL_STATUS_RESET(OPL,0x7f);
+
+ /* reset with register write */
+ OPLWriteReg(OPL,0x01,0); /* wavesel disable */
+ OPLWriteReg(OPL,0x02,0); /* Timer1 */
+ OPLWriteReg(OPL,0x03,0); /* Timer2 */
+ OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
+ for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
+
+ /* reset operator parameters */
+ for( c = 0 ; c < 9 ; c++ )
+ {
+ OPL_CH *CH = &OPL->P_CH[c];
+ for(s = 0 ; s < 2 ; s++ )
+ {
+ /* wave table */
+ CH->SLOT[s].wavetable = 0;
+ CH->SLOT[s].state = EG_OFF;
+ CH->SLOT[s].volume = MAX_ATT_INDEX;
+ }
+ }
+#if BUILD_Y8950
+ if(OPL->type&OPL_TYPE_ADPCM)
+ {
+ YM_DELTAT *DELTAT = OPL->deltat;
+
+ DELTAT->freqbase = OPL->freqbase;
+ DELTAT->output_pointer = &OPL->output_deltat[0];
+ DELTAT->portshift = 5;
+ DELTAT->output_range = 1<<23;
+ YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);
+ }
+#endif
+}
+
+
+#if 0
+static STATE_POSTLOAD( OPL_postload )
+{
+ FM_OPL *OPL = (FM_OPL *)param;
+ int slot, ch;
+
+ for( ch=0 ; ch < 9 ; ch++ )
+ {
+ OPL_CH *CH = &OPL->P_CH[ch];
+
+ /* Look up key scale level */
+ UINT32 block_fnum = CH->block_fnum;
+ CH->ksl_base = ksl_tab[block_fnum >> 6];
+ CH->fc = OPL->fn_tab[block_fnum & 0x03ff] >> (7 - (block_fnum >> 10));
+
+ for( slot=0 ; slot < 2 ; slot++ )
+ {
+ OPL_SLOT *SLOT = &CH->SLOT[slot];
+
+ /* Calculate key scale rate */
+ SLOT->ksr = CH->kcode >> SLOT->KSR;
+
+ /* Calculate attack, decay and release rates */
+ if ((SLOT->ar + SLOT->ksr) < 16+62)
+ {
+ SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
+ SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+ }
+ else
+ {
+ SLOT->eg_sh_ar = 0;
+ SLOT->eg_sel_ar = 13*RATE_STEPS;
+ }
+ SLOT->eg_sh_dr = eg_rate_shift [SLOT->dr + SLOT->ksr ];
+ SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
+ SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr ];
+ SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+
+ /* Calculate phase increment */
+ SLOT->Incr = CH->fc * SLOT->mul;
+
+ /* Total level */
+ SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
+
+ /* Connect output */
+ SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;
+ }
+ }
+#if BUILD_Y8950
+ if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
+ {
+ // We really should call the postlod function for the YM_DELTAT, but it's hard without registers
+ // (see the way the YM2610 does it)
+ //YM_DELTAT_postload(OPL->deltat, REGS);
+ }
+#endif
+}
+
+
+static void OPLsave_state_channel(const device_config *device, OPL_CH *CH)
+{
+ int slot, ch;
+
+ for( ch=0 ; ch < 9 ; ch++, CH++ )
+ {
+ /* channel */
+ state_save_register_device_item(device, ch, CH->block_fnum);
+ state_save_register_device_item(device, ch, CH->kcode);
+ /* slots */
+ for( slot=0 ; slot < 2 ; slot++ )
+ {
+ OPL_SLOT *SLOT = &CH->SLOT[slot];
+
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->ar);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->dr);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->rr);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->KSR);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->ksl);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->mul);
+
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->Cnt);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->FB);
+ state_save_register_device_item_array(device, ch * 2 + slot, SLOT->op1_out);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->CON);
+
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->eg_type);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->state);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->TL);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->volume);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->sl);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->key);
+
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->AMmask);
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->vib);
+
+ state_save_register_device_item(device, ch * 2 + slot, SLOT->wavetable);
+ }
+ }
+}
+
+
+/* Register savestate for a virtual YM3812/YM3526Y8950 */
+
+static void OPL_save_state(FM_OPL *OPL, const device_config *device)
+{
+ OPLsave_state_channel(device, OPL->P_CH);
+
+ state_save_register_device_item(device, 0, OPL->eg_cnt);
+ state_save_register_device_item(device, 0, OPL->eg_timer);
+
+ state_save_register_device_item(device, 0, OPL->rhythm);
+
+ state_save_register_device_item(device, 0, OPL->lfo_am_depth);
+ state_save_register_device_item(device, 0, OPL->lfo_pm_depth_range);
+ state_save_register_device_item(device, 0, OPL->lfo_am_cnt);
+ state_save_register_device_item(device, 0, OPL->lfo_pm_cnt);
+
+ state_save_register_device_item(device, 0, OPL->noise_rng);
+ state_save_register_device_item(device, 0, OPL->noise_p);
+
+ if( OPL->type & OPL_TYPE_WAVESEL )
+ {
+ state_save_register_device_item(device, 0, OPL->wavesel);
+ }
+
+ state_save_register_device_item_array(device, 0, OPL->T);
+ state_save_register_device_item_array(device, 0, OPL->st);
+
+#if BUILD_Y8950
+ if ( (OPL->type & OPL_TYPE_ADPCM) && (OPL->deltat) )
+ {
+ YM_DELTAT_savestate(device, OPL->deltat);
+ }
+
+ if ( OPL->type & OPL_TYPE_IO )
+ {
+ state_save_register_device_item(device, 0, OPL->portDirection);
+ state_save_register_device_item(device, 0, OPL->portLatch);
+ }
+#endif
+
+ state_save_register_device_item(device, 0, OPL->address);
+ state_save_register_device_item(device, 0, OPL->status);
+ state_save_register_device_item(device, 0, OPL->statusmask);
+ state_save_register_device_item(device, 0, OPL->mode);
+
+ state_save_register_postload(device->machine, OPL_postload, OPL);
+}
+#endif
+
+
+/* Create one of virtual YM3812/YM3526/Y8950 */
+/* 'clock' is chip clock in Hz */
+/* 'rate' is sampling rate */
+static FM_OPL *OPLCreate(UINT32 clock, UINT32 rate, int type)
+{
+ char *ptr;
+ FM_OPL *OPL;
+ int state_size;
+
+ //if (OPL_LockTable(device) == -1) return NULL;
+ init_tables();
+
+ /* calculate OPL state size */
+ state_size = sizeof(FM_OPL);
+
+#if BUILD_Y8950
+ if (type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
+#endif
+
+ /* allocate memory block */
+ ptr = (char *)malloc(state_size);
+
+ if (ptr==NULL)
+ return 0;
+
+ /* clear */
+ memset(ptr,0,state_size);
+
+ OPL = (FM_OPL *)ptr;
+
+ ptr += sizeof(FM_OPL);
+
+#if BUILD_Y8950
+ if (type&OPL_TYPE_ADPCM)
+ {
+ OPL->deltat = (YM_DELTAT *)ptr;
+ }
+ ptr += sizeof(YM_DELTAT);
+#endif
+
+ OPL->type = type;
+ OPL->clock = clock;
+ OPL->rate = rate;
+
+ /* init global tables */
+ OPL_initalize(OPL);
+
+ return OPL;
+}
+
+/* Destroy one of virtual YM3812 */
+static void OPLDestroy(FM_OPL *OPL)
+{
+ //OPL_UnLockTable();
+ free(OPL);
+}
+
+/* Optional handlers */
+
+/*static void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER timer_handler,void *param)
+{
+ OPL->timer_handler = timer_handler;
+ OPL->TimerParam = param;
+}*/
+static void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,void *param)
+{
+ OPL->IRQHandler = IRQHandler;
+ OPL->IRQParam = param;
+}
+static void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,void *param)
+{
+ OPL->UpdateHandler = UpdateHandler;
+ OPL->UpdateParam = param;
+}
+
+static int OPLWrite(FM_OPL *OPL,int a,int v)
+{
+ if( !(a&1) )
+ { /* address port */
+ OPL->address = v & 0xff;
+ }
+ else
+ { /* data port */
+ if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+ OPLWriteReg(OPL,OPL->address,v);
+ }
+ return OPL->status>>7;
+}
+
+static unsigned char OPLRead(FM_OPL *OPL,int a)
+{
+ if( !(a&1) )
+ {
+ /* status port */
+
+ #if BUILD_Y8950
+
+ if(OPL->type&OPL_TYPE_ADPCM) /* Y8950 */
+ {
+ return (OPL->status & (OPL->statusmask|0x80)) | (OPL->deltat->PCM_BSY&1);
+ }
+
+ #endif
+
+ /* OPL and OPL2 */
+ return OPL->status & (OPL->statusmask|0x80);
+ }
+
+#if BUILD_Y8950
+ /* data port */
+ switch(OPL->address)
+ {
+ case 0x05: /* KeyBoard IN */
+ if(OPL->type&OPL_TYPE_KEYBOARD)
+ {
+ if(OPL->keyboardhandler_r)
+ return OPL->keyboardhandler_r(OPL->keyboard_param);
+ /*else
+ logerror("Y8950: read unmapped KEYBOARD port\n");*/
+ }
+ return 0;
+
+ case 0x0f: /* ADPCM-DATA */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ {
+ UINT8 val;
+
+ val = YM_DELTAT_ADPCM_Read(OPL->deltat);
+ /*logerror("Y8950: read ADPCM value read=%02x\n",val);*/
+ return val;
+ }
+ return 0;
+
+ case 0x19: /* I/O DATA */
+ if(OPL->type&OPL_TYPE_IO)
+ {
+ if(OPL->porthandler_r)
+ return OPL->porthandler_r(OPL->port_param);
+ /*else
+ logerror("Y8950:read unmapped I/O port\n");*/
+ }
+ return 0;
+ case 0x1a: /* PCM-DATA */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ {
+ /*logerror("Y8950 A/D convertion is accessed but not implemented !\n");*/
+ return 0x80; /* 2's complement PCM data - result from A/D convertion */
+ }
+ return 0;
+ }
+#endif
+
+ return 0xff;
+}
+
+/* CSM Key Controll */
+INLINE void CSMKeyControll(OPL_CH *CH)
+{
+ FM_KEYON (&CH->SLOT[SLOT1], 4);
+ FM_KEYON (&CH->SLOT[SLOT2], 4);
+
+ /* The key off should happen exactly one sample later - not implemented correctly yet */
+
+ FM_KEYOFF(&CH->SLOT[SLOT1], ~4);
+ FM_KEYOFF(&CH->SLOT[SLOT2], ~4);
+}
+
+
+static int OPLTimerOver(FM_OPL *OPL,int c)
+{
+ if( c )
+ { /* Timer B */
+ OPL_STATUS_SET(OPL,0x20);
+ }
+ else
+ { /* Timer A */
+ OPL_STATUS_SET(OPL,0x40);
+ /* CSM mode key,TL controll */
+ if( OPL->mode & 0x80 )
+ { /* CSM mode total level latch and auto key on */
+ int ch;
+ if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+ for(ch=0; ch<9; ch++)
+ CSMKeyControll( &OPL->P_CH[ch] );
+ }
+ }
+ /* reload timer */
+ //if (OPL->timer_handler) (OPL->timer_handler)(OPL->TimerParam,c,attotime_mul(OPL->TimerBase, OPL->T[c]));
+ return OPL->status>>7;
+}
+
+
+#define MAX_OPL_CHIPS 2
+
+
+#if (BUILD_YM3812)
+
+void * ym3812_init(UINT32 clock, UINT32 rate)
+{
+ /* emulator create */
+ FM_OPL *YM3812 = OPLCreate(clock,rate,OPL_TYPE_YM3812);
+ if (YM3812)
+ {
+ //OPL_save_state(YM3812);
+ ym3812_reset_chip(YM3812);
+ }
+ return YM3812;
+}
+
+void ym3812_shutdown(void *chip)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+
+ /* emulator shutdown */
+ OPLDestroy(YM3812);
+}
+void ym3812_reset_chip(void *chip)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ OPLResetChip(YM3812);
+}
+
+int ym3812_write(void *chip, int a, int v)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ return OPLWrite(YM3812, a, v);
+}
+
+unsigned char ym3812_read(void *chip, int a)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ /* YM3812 always returns bit2 and bit1 in HIGH state */
+ return OPLRead(YM3812, a) | 0x06 ;
+}
+int ym3812_timer_over(void *chip, int c)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ return OPLTimerOver(YM3812, c);
+}
+
+/*void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ OPLSetTimerHandler(YM3812, timer_handler, param);
+}*/
+void ym3812_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ OPLSetIRQHandler(YM3812, IRQHandler, param);
+}
+void ym3812_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+{
+ FM_OPL *YM3812 = (FM_OPL *)chip;
+ OPLSetUpdateHandler(YM3812, UpdateHandler, param);
+}
+
+
+/*
+** Generate samples for one of the YM3812's
+**
+** 'which' is the virtual YM3812 number
+** '*buffer' is the output buffer pointer
+** 'length' is the number of samples that should be generated
+*/
+void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
+{
+ FM_OPL *OPL = (FM_OPL *)chip;
+ UINT8 rhythm = OPL->rhythm&0x20;
+ OPLSAMPLE *buf = buffer;
+ int i;
+
+ /* rhythm slots */
+ OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
+ OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
+ OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
+ OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
+ for( i=0; i < length ; i++ )
+ {
+ int lt;
+
+ OPL->output[0] = 0;
+
+ advance_lfo(OPL);
+
+ /* FM part */
+ OPL_CALC_CH(OPL, &OPL->P_CH[0]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[1]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[2]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[3]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[4]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+
+ if(!rhythm)
+ {
+ OPL_CALC_CH(OPL, &OPL->P_CH[6]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[7]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ }
+ else /* Rhythm part */
+ {
+ OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ }
+
+ lt = OPL->output[0];
+
+ lt >>= FINAL_SH;
+
+ /* limit check */
+ lt = limit( lt , MAXOUT, MINOUT );
+
+ #ifdef SAVE_SAMPLE
+ if (which==0)
+ {
+ SAVE_ALL_CHANNELS
+ }
+ #endif
+
+ /* store to sound buffer */
+ buf[i] = lt;
+
+ advance(OPL);
+ }
+
+}
+#endif /* BUILD_YM3812 */
+
+
+
+#if (BUILD_YM3526)
+
+void *ym3526_init(UINT32 clock, UINT32 rate)
+{
+ /* emulator create */
+ FM_OPL *YM3526 = OPLCreate(clock,rate,OPL_TYPE_YM3526);
+ if (YM3526)
+ {
+ /*OPL_save_state(YM3526);*/
+ ym3526_reset_chip(YM3526);
+ }
+ return YM3526;
+}
+
+void ym3526_shutdown(void *chip)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ /* emulator shutdown */
+ OPLDestroy(YM3526);
+}
+void ym3526_reset_chip(void *chip)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ OPLResetChip(YM3526);
+}
+
+int ym3526_write(void *chip, int a, int v)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ return OPLWrite(YM3526, a, v);
+}
+
+unsigned char ym3526_read(void *chip, int a)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ /* YM3526 always returns bit2 and bit1 in HIGH state */
+ return OPLRead(YM3526, a) | 0x06 ;
+}
+int ym3526_timer_over(void *chip, int c)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ return OPLTimerOver(YM3526, c);
+}
+
+/*void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ OPLSetTimerHandler(YM3526, timer_handler, param);
+}*/
+void ym3526_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ OPLSetIRQHandler(YM3526, IRQHandler, param);
+}
+void ym3526_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+{
+ FM_OPL *YM3526 = (FM_OPL *)chip;
+ OPLSetUpdateHandler(YM3526, UpdateHandler, param);
+}
+
+
+/*
+** Generate samples for one of the YM3526's
+**
+** 'which' is the virtual YM3526 number
+** '*buffer' is the output buffer pointer
+** 'length' is the number of samples that should be generated
+*/
+void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
+{
+ FM_OPL *OPL = (FM_OPL *)chip;
+ UINT8 rhythm = OPL->rhythm&0x20;
+ OPLSAMPLE *buf = buffer;
+ int i;
+
+ /* rhythm slots */
+ OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
+ OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
+ OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
+ OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
+ for( i=0; i < length ; i++ )
+ {
+ int lt;
+
+ OPL->output[0] = 0;
+
+ advance_lfo(OPL);
+
+ /* FM part */
+ OPL_CALC_CH(OPL, &OPL->P_CH[0]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[1]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[2]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[3]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[4]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+
+ if(!rhythm)
+ {
+ OPL_CALC_CH(OPL, &OPL->P_CH[6]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[7]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ }
+ else /* Rhythm part */
+ {
+ OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ }
+
+ lt = OPL->output[0];
+
+ lt >>= FINAL_SH;
+
+ /* limit check */
+ lt = limit( lt , MAXOUT, MINOUT );
+
+ #ifdef SAVE_SAMPLE
+ if (which==0)
+ {
+ SAVE_ALL_CHANNELS
+ }
+ #endif
+
+ /* store to sound buffer */
+ buf[i] = lt;
+
+ advance(OPL);
+ }
+
+}
+#endif /* BUILD_YM3526 */
+
+
+
+
+#if BUILD_Y8950
+
+static void Y8950_deltat_status_set(void *chip, UINT8 changebits)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPL_STATUS_SET(Y8950, changebits);
+}
+static void Y8950_deltat_status_reset(void *chip, UINT8 changebits)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPL_STATUS_RESET(Y8950, changebits);
+}
+
+void *y8950_init(UINT32 clock, UINT32 rate)
+{
+ /* emulator create */
+ FM_OPL *Y8950 = OPLCreate(clock,rate,OPL_TYPE_Y8950);
+ if (Y8950)
+ {
+ Y8950->deltat->status_set_handler = Y8950_deltat_status_set;
+ Y8950->deltat->status_reset_handler = Y8950_deltat_status_reset;
+ Y8950->deltat->status_change_which_chip = Y8950;
+ Y8950->deltat->status_change_EOS_bit = 0x10; /* status flag: set bit4 on End Of Sample */
+ Y8950->deltat->status_change_BRDY_bit = 0x08; /* status flag: set bit3 on BRDY (End Of: ADPCM analysis/synthesis, memory reading/writing) */
+
+ /*Y8950->deltat->write_time = 10.0 / clock;*/ /* a single byte write takes 10 cycles of main clock */
+ /*Y8950->deltat->read_time = 8.0 / clock;*/ /* a single byte read takes 8 cycles of main clock */
+ /* reset */
+ /*OPL_save_state(Y8950);*/
+ y8950_reset_chip(Y8950);
+ }
+
+ return Y8950;
+}
+
+void y8950_shutdown(void *chip)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ /* emulator shutdown */
+ OPLDestroy(Y8950);
+}
+void y8950_reset_chip(void *chip)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPLResetChip(Y8950);
+}
+
+int y8950_write(void *chip, int a, int v)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ return OPLWrite(Y8950, a, v);
+}
+
+unsigned char y8950_read(void *chip, int a)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ return OPLRead(Y8950, a);
+}
+int y8950_timer_over(void *chip, int c)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ return OPLTimerOver(Y8950, c);
+}
+
+/*void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER timer_handler, void *param)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPLSetTimerHandler(Y8950, timer_handler, param);
+}*/
+void y8950_set_irq_handler(void *chip,OPL_IRQHANDLER IRQHandler,void *param)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPLSetIRQHandler(Y8950, IRQHandler, param);
+}
+void y8950_set_update_handler(void *chip,OPL_UPDATEHANDLER UpdateHandler,void *param)
+{
+ FM_OPL *Y8950 = (FM_OPL *)chip;
+ OPLSetUpdateHandler(Y8950, UpdateHandler, param);
+}
+
+void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size )
+{
+ FM_OPL *OPL = (FM_OPL *)chip;
+ OPL->deltat->memory = (UINT8 *)(deltat_mem_ptr);
+ OPL->deltat->memory_size = deltat_mem_size;
+}
+
+/*
+** Generate samples for one of the Y8950's
+**
+** 'which' is the virtual Y8950 number
+** '*buffer' is the output buffer pointer
+** 'length' is the number of samples that should be generated
+*/
+void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
+{
+ int i;
+ FM_OPL *OPL = (FM_OPL *)chip;
+ UINT8 rhythm = OPL->rhythm&0x20;
+ YM_DELTAT *DELTAT = OPL->deltat;
+ OPLSAMPLE *buf = buffer;
+
+ /* rhythm slots */
+ OPL->SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
+ OPL->SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
+ OPL->SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
+ OPL->SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
+
+ for( i=0; i < length ; i++ )
+ {
+ int lt;
+
+ OPL->output[0] = 0;
+ OPL->output_deltat[0] = 0;
+
+ advance_lfo(OPL);
+
+ /* deltaT ADPCM */
+ if( DELTAT->portstate&0x80 )
+ YM_DELTAT_ADPCM_CALC(DELTAT);
+
+ /* FM part */
+ OPL_CALC_CH(OPL, &OPL->P_CH[0]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[1]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[2]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[3]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[4]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[5]);
+
+ if(!rhythm)
+ {
+ OPL_CALC_CH(OPL, &OPL->P_CH[6]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[7]);
+ OPL_CALC_CH(OPL, &OPL->P_CH[8]);
+ }
+ else /* Rhythm part */
+ {
+ OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
+ }
+
+ lt = OPL->output[0] + (OPL->output_deltat[0]>>11);
+
+ lt >>= FINAL_SH;
+
+ /* limit check */
+ lt = limit( lt , MAXOUT, MINOUT );
+
+ #ifdef SAVE_SAMPLE
+ if (which==0)
+ {
+ SAVE_ALL_CHANNELS
+ }
+ #endif
+
+ /* store to sound buffer */
+ buf[i] = lt;
+
+ advance(OPL);
+ }
+
+}
+
+void y8950_set_port_handler(void *chip,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,void * param)
+{
+ FM_OPL *OPL = (FM_OPL *)chip;
+ OPL->porthandler_w = PortHandler_w;
+ OPL->porthandler_r = PortHandler_r;
+ OPL->port_param = param;
+}
+
+void y8950_set_keyboard_handler(void *chip,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,void * param)
+{
+ FM_OPL *OPL = (FM_OPL *)chip;
+ OPL->keyboardhandler_w = KeyboardHandler_w;
+ OPL->keyboardhandler_r = KeyboardHandler_r;
+ OPL->keyboard_param = param;
+}
+
+#endif
+
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/fmopl.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/fmopl.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/fmopl.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/fmopl.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,116 +1,116 @@
-#pragma once
-
-#ifndef __FMOPL_H__
-#define __FMOPL_H__
-
-/* --- select emulation chips --- */
-#define BUILD_YM3812 (1)
-#define BUILD_YM3526 (1)
-#define BUILD_Y8950 (1)
-
-/* select output bits size of output : 8 or 16 */
-#define OPL_SAMPLE_BITS 16
-
-/* compiler dependence */
-#ifndef __OSDCOMM_H__
-#define __OSDCOMM_H__
-typedef unsigned char UINT8; /* unsigned 8bit */
-typedef unsigned short UINT16; /* unsigned 16bit */
-typedef unsigned int UINT32; /* unsigned 32bit */
-typedef signed char INT8; /* signed 8bit */
-typedef signed short INT16; /* signed 16bit */
-typedef signed int INT32; /* signed 32bit */
-
-typedef INT32 stream_sample_t;
-
-#endif /* __OSDCOMM_H__ */
-
-typedef stream_sample_t OPLSAMPLE;
-/*
-#if (OPL_SAMPLE_BITS==16)
-typedef INT16 OPLSAMPLE;
-#endif
-#if (OPL_SAMPLE_BITS==8)
-typedef INT8 OPLSAMPLE;
-#endif
-*/
-
-//typedef void (*OPL_TIMERHANDLER)(void *param,int timer,attotime period);
-typedef void (*OPL_IRQHANDLER)(void *param,int irq);
-typedef void (*OPL_UPDATEHANDLER)(void *param,int min_interval_us);
-typedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);
-typedef unsigned char (*OPL_PORTHANDLER_R)(void *param);
-
-
-#if BUILD_YM3812
-
-void *ym3812_init(UINT32 clock, UINT32 rate);
-void ym3812_shutdown(void *chip);
-void ym3812_reset_chip(void *chip);
-int ym3812_write(void *chip, int a, int v);
-unsigned char ym3812_read(void *chip, int a);
-int ym3812_timer_over(void *chip, int c);
-void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length);
-
-//void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
-void ym3812_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
-void ym3812_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
-
-#endif /* BUILD_YM3812 */
-
-
-#if BUILD_YM3526
-
-/*
-** Initialize YM3526 emulator(s).
-**
-** 'num' is the number of virtual YM3526's to allocate
-** 'clock' is the chip clock in Hz
-** 'rate' is sampling rate
-*/
-void *ym3526_init(UINT32 clock, UINT32 rate);
-/* shutdown the YM3526 emulators*/
-void ym3526_shutdown(void *chip);
-void ym3526_reset_chip(void *chip);
-int ym3526_write(void *chip, int a, int v);
-unsigned char ym3526_read(void *chip, int a);
-int ym3526_timer_over(void *chip, int c);
-/*
-** Generate samples for one of the YM3526's
-**
-** 'which' is the virtual YM3526 number
-** '*buffer' is the output buffer pointer
-** 'length' is the number of samples that should be generated
-*/
-void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length);
-
-//void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
-void ym3526_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
-void ym3526_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
-
-#endif /* BUILD_YM3526 */
-
-
-#if BUILD_Y8950
-
-/* Y8950 port handlers */
-void y8950_set_port_handler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);
-void y8950_set_keyboard_handler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);
-void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );
-
-void * y8950_init(UINT32 clock, UINT32 rate);
-void y8950_shutdown(void *chip);
-void y8950_reset_chip(void *chip);
-int y8950_write(void *chip, int a, int v);
-unsigned char y8950_read (void *chip, int a);
-int y8950_timer_over(void *chip, int c);
-void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length);
-
-//void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
-void y8950_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
-void y8950_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
-
-#endif /* BUILD_Y8950 */
-
-
-#endif /* __FMOPL_H__ */
+#pragma once
+
+#ifndef __FMOPL_H__
+#define __FMOPL_H__
+
+/* --- select emulation chips --- */
+#define BUILD_YM3812 (1)
+#define BUILD_YM3526 (1)
+#define BUILD_Y8950 (1)
+
+/* select output bits size of output : 8 or 16 */
+#define OPL_SAMPLE_BITS 16
+
+/* compiler dependence */
+#ifndef __OSDCOMM_H__
+#define __OSDCOMM_H__
+typedef unsigned char UINT8; /* unsigned 8bit */
+typedef unsigned short UINT16; /* unsigned 16bit */
+typedef unsigned int UINT32; /* unsigned 32bit */
+typedef signed char INT8; /* signed 8bit */
+typedef signed short INT16; /* signed 16bit */
+typedef signed int INT32; /* signed 32bit */
+
+typedef INT32 stream_sample_t;
+
+#endif /* __OSDCOMM_H__ */
+
+typedef stream_sample_t OPLSAMPLE;
+/*
+#if (OPL_SAMPLE_BITS==16)
+typedef INT16 OPLSAMPLE;
+#endif
+#if (OPL_SAMPLE_BITS==8)
+typedef INT8 OPLSAMPLE;
+#endif
+*/
+
+//typedef void (*OPL_TIMERHANDLER)(void *param,int timer,attotime period);
+typedef void (*OPL_IRQHANDLER)(void *param,int irq);
+typedef void (*OPL_UPDATEHANDLER)(void *param,int min_interval_us);
+typedef void (*OPL_PORTHANDLER_W)(void *param,unsigned char data);
+typedef unsigned char (*OPL_PORTHANDLER_R)(void *param);
+
+
+#if BUILD_YM3812
+
+void *ym3812_init(UINT32 clock, UINT32 rate);
+void ym3812_shutdown(void *chip);
+void ym3812_reset_chip(void *chip);
+int ym3812_write(void *chip, int a, int v);
+unsigned char ym3812_read(void *chip, int a);
+int ym3812_timer_over(void *chip, int c);
+void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length);
+
+//void ym3812_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
+void ym3812_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
+void ym3812_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
+
+#endif /* BUILD_YM3812 */
+
+
+#if BUILD_YM3526
+
+/*
+** Initialize YM3526 emulator(s).
+**
+** 'num' is the number of virtual YM3526's to allocate
+** 'clock' is the chip clock in Hz
+** 'rate' is sampling rate
+*/
+void *ym3526_init(UINT32 clock, UINT32 rate);
+/* shutdown the YM3526 emulators*/
+void ym3526_shutdown(void *chip);
+void ym3526_reset_chip(void *chip);
+int ym3526_write(void *chip, int a, int v);
+unsigned char ym3526_read(void *chip, int a);
+int ym3526_timer_over(void *chip, int c);
+/*
+** Generate samples for one of the YM3526's
+**
+** 'which' is the virtual YM3526 number
+** '*buffer' is the output buffer pointer
+** 'length' is the number of samples that should be generated
+*/
+void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length);
+
+//void ym3526_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
+void ym3526_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
+void ym3526_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
+
+#endif /* BUILD_YM3526 */
+
+
+#if BUILD_Y8950
+
+/* Y8950 port handlers */
+void y8950_set_port_handler(void *chip, OPL_PORTHANDLER_W PortHandler_w, OPL_PORTHANDLER_R PortHandler_r, void *param);
+void y8950_set_keyboard_handler(void *chip, OPL_PORTHANDLER_W KeyboardHandler_w, OPL_PORTHANDLER_R KeyboardHandler_r, void *param);
+void y8950_set_delta_t_memory(void *chip, void * deltat_mem_ptr, int deltat_mem_size );
+
+void * y8950_init(UINT32 clock, UINT32 rate);
+void y8950_shutdown(void *chip);
+void y8950_reset_chip(void *chip);
+int y8950_write(void *chip, int a, int v);
+unsigned char y8950_read (void *chip, int a);
+int y8950_timer_over(void *chip, int c);
+void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length);
+
+//void y8950_set_timer_handler(void *chip, OPL_TIMERHANDLER TimerHandler, void *param);
+void y8950_set_irq_handler(void *chip, OPL_IRQHANDLER IRQHandler, void *param);
+void y8950_set_update_handler(void *chip, OPL_UPDATEHANDLER UpdateHandler, void *param);
+
+#endif /* BUILD_Y8950 */
+
+
+#endif /* __FMOPL_H__ */
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Apu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Apu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Apu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Apu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,414 +1,407 @@
-// Gb_Snd_Emu $vers. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-//#include "gb_apu_logger.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const vol_reg = 0xFF24;
-int const stereo_reg = 0xFF25;
-int const status_reg = 0xFF26;
-int const wave_ram = 0xFF30;
-
-int const power_mask = 0x80;
-
-void Gb_Apu::treble_eq( blip_eq_t const& eq )
-{
- norm_synth.treble_eq( eq );
- fast_synth.treble_eq( eq );
-}
-
-inline int Gb_Apu::calc_output( int osc ) const
-{
- int bits = regs [stereo_reg - io_addr] >> osc;
- return (bits >> 3 & 2) | (bits & 1);
-}
-
-void Gb_Apu::set_output( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
- require( !center || (center && !left && !right) || (center && left && right) );
- require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
-
- if ( !center || !left || !right )
- {
- left = center;
- right = center;
- }
-
- Gb_Osc& o = *oscs [i];
- o.outputs [1] = right;
- o.outputs [2] = left;
- o.outputs [3] = center;
- o.output = o.outputs [calc_output( i )];
-}
-
-void Gb_Apu::synth_volume( int iv )
-{
- double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
- norm_synth.volume( v );
- fast_synth.volume( v );
-}
-
-void Gb_Apu::apply_volume()
-{
- // TODO: Doesn't handle differing left and right volumes (panning).
- // Not worth the complexity.
- int data = regs [vol_reg - io_addr];
- int left = data >> 4 & 7;
- int right = data & 7;
- //if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
- //if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
- synth_volume( max( left, right ) + 1 );
-}
-
-void Gb_Apu::volume( double v )
-{
- if ( volume_ != v )
- {
- volume_ = v;
- apply_volume();
- }
-}
-
-void Gb_Apu::reset_regs()
-{
- for ( int i = 0; i < 0x20; i++ )
- regs [i] = 0;
-
- square1.reset();
- square2.reset();
- wave .reset();
- noise .reset();
-
- apply_volume();
-}
-
-void Gb_Apu::reset_lengths()
-{
- square1.length_ctr = 64;
- square2.length_ctr = 64;
- wave .length_ctr = 256;
- noise .length_ctr = 64;
-}
-
-void Gb_Apu::reduce_clicks( bool reduce )
-{
- reduce_clicks_ = reduce;
-
- // Click reduction makes DAC off generate same output as volume 0
- int dac_off_amp = 0;
- if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks
- dac_off_amp = -Gb_Osc::dac_bias;
-
- for ( int i = 0; i < osc_count; i++ )
- oscs [i]->dac_off_amp = dac_off_amp;
-
- // AGB always eliminates clicks on wave channel using same method
- if ( wave.mode == mode_agb )
- wave.dac_off_amp = -Gb_Osc::dac_bias;
-}
-
-void Gb_Apu::reset( mode_t mode, bool agb_wave )
-{
- // Hardware mode
- if ( agb_wave )
- mode = mode_agb; // using AGB wave features implies AGB hardware
- wave.agb_mask = agb_wave ? 0xFF : 0;
- for ( int i = 0; i < osc_count; i++ )
- oscs [i]->mode = mode;
- reduce_clicks( reduce_clicks_ );
-
- // Reset state
- frame_time = 0;
- last_time = 0;
- frame_phase = 0;
-
- reset_regs();
- reset_lengths();
-
- // Load initial wave RAM
- static byte const initial_wave [2] [16] = {
- {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
- {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
- };
- for ( int b = 2; --b >= 0; )
- {
- // Init both banks (does nothing if not in AGB mode)
- // TODO: verify that this works
- write_register( 0, 0xFF1A, b * 0x40 );
- for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
- write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
- }
-}
-
-void Gb_Apu::set_tempo( double t )
-{
- frame_period = 4194304 / 512; // 512 Hz
- if ( t != 1.0 )
- frame_period = t ? blip_time_t (frame_period / t) : blip_time_t(0);
-}
-
-void Gb_Apu::set_hacks( unsigned int mask )
-{
- wave.set_volume_hack((mask & 1) != 0);
- noise.set_volume_hack((mask & 2) == 0);
-}
-
-Gb_Apu::Gb_Apu()
-{
- wave.wave_ram = ®s [wave_ram - io_addr];
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &wave;
- oscs [3] = &noise;
-
- for ( int i = osc_count; --i >= 0; )
- {
- Gb_Osc& o = *oscs [i];
- o.regs = ®s [i * 5];
- o.output = NULL;
- o.outputs [0] = NULL;
- o.outputs [1] = NULL;
- o.outputs [2] = NULL;
- o.outputs [3] = NULL;
- o.norm_synth = &norm_synth;
- o.fast_synth = &fast_synth;
- }
-
- reduce_clicks_ = false;
- set_tempo( 1.0 );
- volume_ = 1.0;
- reset();
- set_hacks(4);
-}
-
-void Gb_Apu::run_until_( blip_time_t end_time )
-{
- if ( !frame_period )
- frame_time += end_time - last_time;
-
- while ( true )
- {
- // run oscillators
- blip_time_t time = end_time;
- if ( time > frame_time )
- time = frame_time;
-
- square1.run( last_time, time );
- square2.run( last_time, time );
- wave .run( last_time, time );
- noise .run( last_time, time );
- last_time = time;
-
- if ( time == end_time )
- break;
-
- // run frame sequencer
- assert( frame_period );
- frame_time += frame_period * Gb_Osc::clk_mul;
- switch ( frame_phase++ )
- {
- case 2:
- case 6:
- // 128 Hz
- square1.clock_sweep();
- case 0:
- case 4:
- // 256 Hz
- square1.clock_length();
- square2.clock_length();
- wave .clock_length();
- noise .clock_length();
- break;
-
- case 7:
- // 64 Hz
- frame_phase = 0;
- square1.clock_envelope();
- square2.clock_envelope();
- noise .clock_envelope();
- }
- }
-}
-
-inline void Gb_Apu::run_until( blip_time_t time )
-{
- require( time >= last_time ); // end_time must not be before previous time
- if ( time > last_time )
- run_until_( time );
-}
-
-void Gb_Apu::end_frame( blip_time_t end_time )
-{
- #ifdef LOG_FRAME
- LOG_FRAME( end_time );
- #endif
-
- if ( end_time > last_time )
- run_until( end_time );
-
- frame_time -= end_time;
- assert( frame_time >= 0 );
-
- last_time -= end_time;
- assert( last_time >= 0 );
-}
-
-void Gb_Apu::silence_osc( Gb_Osc& o )
-{
- int delta = -o.last_amp;
- if ( reduce_clicks_ )
- delta += o.dac_off_amp;
-
- if ( delta )
- {
- o.last_amp = o.dac_off_amp;
- if ( o.output )
- {
- o.output->set_modified();
- fast_synth.offset( last_time, delta, o.output );
- }
- }
-}
-
-void Gb_Apu::apply_stereo()
-{
- for ( int i = osc_count; --i >= 0; )
- {
- Gb_Osc& o = *oscs [i];
- Blip_Buffer* out = o.outputs [calc_output( i )];
- if ( o.output != out )
- {
- silence_osc( o );
- o.output = out;
- }
- }
-}
-
-void Gb_Apu::write_register( blip_time_t time, int addr, int data )
-{
- require( (unsigned) data < 0x100 );
-
- int reg = addr - io_addr;
- if ( (unsigned) reg >= io_size )
- {
- require( false );
- return;
- }
-
- #ifdef LOG_WRITE
- LOG_WRITE( time, addr, data );
- #endif
-
- if ( addr < status_reg && !(regs [status_reg - io_addr] & power_mask) )
- {
- // Power is off
-
- // length counters can only be written in DMG mode
- if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
- return;
-
- if ( reg < 10 )
- data &= 0x3F; // clear square duty
- }
-
- run_until( time );
-
- if ( addr >= wave_ram )
- {
- wave.write( addr, data );
- }
- else
- {
- int old_data = regs [reg];
- regs [reg] = data;
-
- if ( addr < vol_reg )
- {
- // Oscillator
- write_osc( reg, old_data, data );
- }
- else if ( addr == vol_reg && data != old_data )
- {
- // Master volume
- for ( int i = osc_count; --i >= 0; )
- silence_osc( *oscs [i] );
-
- apply_volume();
- }
- else if ( addr == stereo_reg )
- {
- // Stereo panning
- apply_stereo();
- }
- else if ( addr == status_reg && (data ^ old_data) & power_mask )
- {
- // Power control
- frame_phase = 0;
- for ( int i = osc_count; --i >= 0; )
- silence_osc( *oscs [i] );
-
- reset_regs();
- if ( wave.mode != mode_dmg )
- reset_lengths();
-
- regs [status_reg - io_addr] = data;
- }
- }
-}
-
-int Gb_Apu::read_register( blip_time_t time, int addr )
-{
- if ( addr >= status_reg )
- run_until( time );
-
- int reg = addr - io_addr;
- if ( (unsigned) reg >= io_size )
- {
- require( false );
- return 0;
- }
-
- if ( addr >= wave_ram )
- return wave.read( addr );
-
- // Value read back has some bits always set
- static byte const masks [] = {
- 0x80,0x3F,0x00,0xFF,0xBF,
- 0xFF,0x3F,0x00,0xFF,0xBF,
- 0x7F,0xFF,0x9F,0xFF,0xBF,
- 0xFF,0xFF,0x00,0x00,0xBF,
- 0x00,0x00,0x70,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
- };
- int mask = masks [reg];
- if ( wave.agb_mask && (reg == 10 || reg == 12) )
- mask = 0x1F; // extra implemented bits in wave regs on AGB
- int data = regs [reg] | mask;
-
- // Status register
- if ( addr == status_reg )
- {
- data &= 0xF0;
- data |= (int) square1.enabled << 0;
- data |= (int) square2.enabled << 1;
- data |= (int) wave .enabled << 2;
- data |= (int) noise .enabled << 3;
- }
-
- return data;
-}
+// Gb_Snd_Emu $vers. http://www.slack.net/~ant/
+
+#include "Gb_Apu.h"
+
+//#include "gb_apu_logger.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const vol_reg = 0xFF24;
+int const stereo_reg = 0xFF25;
+int const status_reg = 0xFF26;
+int const wave_ram = 0xFF30;
+
+int const power_mask = 0x80;
+
+void Gb_Apu::treble_eq( blip_eq_t const& eq )
+{
+ norm_synth.treble_eq( eq );
+ fast_synth.treble_eq( eq );
+}
+
+inline int Gb_Apu::calc_output( int osc ) const
+{
+ int bits = regs [stereo_reg - io_addr] >> osc;
+ return (bits >> 3 & 2) | (bits & 1);
+}
+
+void Gb_Apu::set_output( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+ // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
+ require( !center || (center && !left && !right) || (center && left && right) );
+ require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
+
+ if ( !center || !left || !right )
+ {
+ left = center;
+ right = center;
+ }
+
+ Gb_Osc& o = *oscs [i];
+ o.outputs [1] = right;
+ o.outputs [2] = left;
+ o.outputs [3] = center;
+ o.output = o.outputs [calc_output( i )];
+}
+
+void Gb_Apu::synth_volume( int iv )
+{
+ double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
+ norm_synth.volume( v );
+ fast_synth.volume( v );
+}
+
+void Gb_Apu::apply_volume()
+{
+ // TODO: Doesn't handle differing left and right volumes (panning).
+ // Not worth the complexity.
+ int data = regs [vol_reg - io_addr];
+ int left = data >> 4 & 7;
+ int right = data & 7;
+ //if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
+ //if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
+ synth_volume( max( left, right ) + 1 );
+}
+
+void Gb_Apu::volume( double v )
+{
+ if ( volume_ != v )
+ {
+ volume_ = v;
+ apply_volume();
+ }
+}
+
+void Gb_Apu::reset_regs()
+{
+ for ( int i = 0; i < 0x20; i++ )
+ regs [i] = 0;
+
+ square1.reset();
+ square2.reset();
+ wave .reset();
+ noise .reset();
+
+ apply_volume();
+}
+
+void Gb_Apu::reset_lengths()
+{
+ square1.length_ctr = 64;
+ square2.length_ctr = 64;
+ wave .length_ctr = 256;
+ noise .length_ctr = 64;
+}
+
+void Gb_Apu::reduce_clicks( bool reduce )
+{
+ reduce_clicks_ = reduce;
+
+ // Click reduction makes DAC off generate same output as volume 0
+ int dac_off_amp = 0;
+ if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks
+ dac_off_amp = -Gb_Osc::dac_bias;
+
+ for ( int i = 0; i < osc_count; i++ )
+ oscs [i]->dac_off_amp = dac_off_amp;
+
+ // AGB always eliminates clicks on wave channel using same method
+ if ( wave.mode == mode_agb )
+ wave.dac_off_amp = -Gb_Osc::dac_bias;
+}
+
+void Gb_Apu::reset( mode_t mode, bool agb_wave )
+{
+ // Hardware mode
+ if ( agb_wave )
+ mode = mode_agb; // using AGB wave features implies AGB hardware
+ wave.agb_mask = agb_wave ? 0xFF : 0;
+ for ( int i = 0; i < osc_count; i++ )
+ oscs [i]->mode = mode;
+ reduce_clicks( reduce_clicks_ );
+
+ // Reset state
+ frame_time = 0;
+ last_time = 0;
+ frame_phase = 0;
+
+ reset_regs();
+ reset_lengths();
+
+ // Load initial wave RAM
+ static byte const initial_wave [2] [16] = {
+ {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
+ {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
+ };
+ for ( int b = 2; --b >= 0; )
+ {
+ // Init both banks (does nothing if not in AGB mode)
+ // TODO: verify that this works
+ write_register( 0, 0xFF1A, b * 0x40 );
+ for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
+ write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
+ }
+}
+
+void Gb_Apu::set_tempo( double t )
+{
+ frame_period = 4194304 / 512; // 512 Hz
+ if ( t != 1.0 )
+ frame_period = t ? blip_time_t (frame_period / t) : blip_time_t(0);
+}
+
+Gb_Apu::Gb_Apu()
+{
+ wave.wave_ram = ®s [wave_ram - io_addr];
+
+ oscs [0] = &square1;
+ oscs [1] = &square2;
+ oscs [2] = &wave;
+ oscs [3] = &noise;
+
+ for ( int i = osc_count; --i >= 0; )
+ {
+ Gb_Osc& o = *oscs [i];
+ o.regs = ®s [i * 5];
+ o.output = NULL;
+ o.outputs [0] = NULL;
+ o.outputs [1] = NULL;
+ o.outputs [2] = NULL;
+ o.outputs [3] = NULL;
+ o.norm_synth = &norm_synth;
+ o.fast_synth = &fast_synth;
+ }
+
+ reduce_clicks_ = false;
+ set_tempo( 1.0 );
+ volume_ = 1.0;
+ reset();
+}
+
+void Gb_Apu::run_until_( blip_time_t end_time )
+{
+ if ( !frame_period )
+ frame_time += end_time - last_time;
+
+ while ( true )
+ {
+ // run oscillators
+ blip_time_t time = end_time;
+ if ( time > frame_time )
+ time = frame_time;
+
+ square1.run( last_time, time );
+ square2.run( last_time, time );
+ wave .run( last_time, time );
+ noise .run( last_time, time );
+ last_time = time;
+
+ if ( time == end_time )
+ break;
+
+ // run frame sequencer
+ assert( frame_period );
+ frame_time += frame_period * Gb_Osc::clk_mul;
+ switch ( frame_phase++ )
+ {
+ case 2:
+ case 6:
+ // 128 Hz
+ square1.clock_sweep();
+ case 0:
+ case 4:
+ // 256 Hz
+ square1.clock_length();
+ square2.clock_length();
+ wave .clock_length();
+ noise .clock_length();
+ break;
+
+ case 7:
+ // 64 Hz
+ frame_phase = 0;
+ square1.clock_envelope();
+ square2.clock_envelope();
+ noise .clock_envelope();
+ }
+ }
+}
+
+inline void Gb_Apu::run_until( blip_time_t time )
+{
+ require( time >= last_time ); // end_time must not be before previous time
+ if ( time > last_time )
+ run_until_( time );
+}
+
+void Gb_Apu::end_frame( blip_time_t end_time )
+{
+ #ifdef LOG_FRAME
+ LOG_FRAME( end_time );
+ #endif
+
+ if ( end_time > last_time )
+ run_until( end_time );
+
+ frame_time -= end_time;
+ assert( frame_time >= 0 );
+
+ last_time -= end_time;
+ assert( last_time >= 0 );
+}
+
+void Gb_Apu::silence_osc( Gb_Osc& o )
+{
+ int delta = -o.last_amp;
+ if ( reduce_clicks_ )
+ delta += o.dac_off_amp;
+
+ if ( delta )
+ {
+ o.last_amp = o.dac_off_amp;
+ if ( o.output )
+ {
+ o.output->set_modified();
+ fast_synth.offset( last_time, delta, o.output );
+ }
+ }
+}
+
+void Gb_Apu::apply_stereo()
+{
+ for ( int i = osc_count; --i >= 0; )
+ {
+ Gb_Osc& o = *oscs [i];
+ Blip_Buffer* out = o.outputs [calc_output( i )];
+ if ( o.output != out )
+ {
+ silence_osc( o );
+ o.output = out;
+ }
+ }
+}
+
+void Gb_Apu::write_register( blip_time_t time, int addr, int data )
+{
+ require( (unsigned) data < 0x100 );
+
+ int reg = addr - io_addr;
+ if ( (unsigned) reg >= io_size )
+ {
+ require( false );
+ return;
+ }
+
+ #ifdef LOG_WRITE
+ LOG_WRITE( time, addr, data );
+ #endif
+
+ if ( addr < status_reg && !(regs [status_reg - io_addr] & power_mask) )
+ {
+ // Power is off
+
+ // length counters can only be written in DMG mode
+ if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
+ return;
+
+ if ( reg < 10 )
+ data &= 0x3F; // clear square duty
+ }
+
+ run_until( time );
+
+ if ( addr >= wave_ram )
+ {
+ wave.write( addr, data );
+ }
+ else
+ {
+ int old_data = regs [reg];
+ regs [reg] = data;
+
+ if ( addr < vol_reg )
+ {
+ // Oscillator
+ write_osc( reg, old_data, data );
+ }
+ else if ( addr == vol_reg && data != old_data )
+ {
+ // Master volume
+ for ( int i = osc_count; --i >= 0; )
+ silence_osc( *oscs [i] );
+
+ apply_volume();
+ }
+ else if ( addr == stereo_reg )
+ {
+ // Stereo panning
+ apply_stereo();
+ }
+ else if ( addr == status_reg && (data ^ old_data) & power_mask )
+ {
+ // Power control
+ frame_phase = 0;
+ for ( int i = osc_count; --i >= 0; )
+ silence_osc( *oscs [i] );
+
+ reset_regs();
+ if ( wave.mode != mode_dmg )
+ reset_lengths();
+
+ regs [status_reg - io_addr] = data;
+ }
+ }
+}
+
+int Gb_Apu::read_register( blip_time_t time, int addr )
+{
+ if ( addr >= status_reg )
+ run_until( time );
+
+ int reg = addr - io_addr;
+ if ( (unsigned) reg >= io_size )
+ {
+ require( false );
+ return 0;
+ }
+
+ if ( addr >= wave_ram )
+ return wave.read( addr );
+
+ // Value read back has some bits always set
+ static byte const masks [] = {
+ 0x80,0x3F,0x00,0xFF,0xBF,
+ 0xFF,0x3F,0x00,0xFF,0xBF,
+ 0x7F,0xFF,0x9F,0xFF,0xBF,
+ 0xFF,0xFF,0x00,0x00,0xBF,
+ 0x00,0x00,0x70,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+ };
+ int mask = masks [reg];
+ if ( wave.agb_mask && (reg == 10 || reg == 12) )
+ mask = 0x1F; // extra implemented bits in wave regs on AGB
+ int data = regs [reg] | mask;
+
+ // Status register
+ if ( addr == status_reg )
+ {
+ data &= 0xF0;
+ data |= (int) square1.enabled << 0;
+ data |= (int) square2.enabled << 1;
+ data |= (int) wave .enabled << 2;
+ data |= (int) noise .enabled << 3;
+ }
+
+ return data;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Apu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Apu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Apu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Apu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,198 +1,193 @@
-// Nintendo Game Boy sound hardware emulator with save state support
-
-// Gb_Snd_Emu $vers
-#ifndef GB_APU_H
-#define GB_APU_H
-
-#include "Gb_Oscs.h"
-
-struct gb_apu_state_t;
-
-class Gb_Apu {
-public:
-// Basics
-
- // Sets buffer(s) to generate sound into, or NULL to mute. If only center is not NULL,
- // output is mono.
- void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL );
-
- // Emulates to time t, then writes data to addr
- void write_register( blip_time_t t, int addr, int data );
-
- // Emulates to time t, then subtracts t from the current time.
- // OK if previous write call had time slightly after t.
- void end_frame( blip_time_t t );
-
-// More features
-
- // Clock rate sound hardware runs at
- enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
-
- // Registers are at io_addr to io_addr+io_size-1
- enum { io_addr = 0xFF10 };
- enum { io_size = 0x30 };
-
- // Emulates to time t, then reads from addr
- int read_register( blip_time_t t, int addr );
-
- // Resets hardware to state after power, BEFORE boot ROM runs. Mode selects
- // sound hardware. If agb_wave is true, enables AGB's extra wave features.
- enum mode_t {
- mode_dmg, // Game Boy monochrome
- mode_cgb, // Game Boy Color
- mode_agb // Game Boy Advance
- };
- void reset( mode_t mode = mode_cgb, bool agb_wave = false );
-
- // Same as set_output(), but for a particular channel
- // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
- enum { osc_count = 4 }; // 0 <= chan < osc_count
- void set_output( int chan, Blip_Buffer* center,
- Blip_Buffer* left = NULL, Blip_Buffer* right = NULL );
-
- // Sets overall volume, where 1.0 is normal
- void volume( double );
-
- // Sets treble equalization
- void treble_eq( blip_eq_t const& );
-
- // Treble and bass values for various hardware.
- enum {
- speaker_treble = -47, // speaker on system
- speaker_bass = 2000,
- dmg_treble = 0, // headphones on each system
- dmg_bass = 30,
- cgb_treble = 0,
- cgb_bass = 300, // CGB has much less bass
- agb_treble = 0,
- agb_bass = 30
- };
-
- // If true, reduces clicking by disabling DAC biasing. Note that this reduces
- // emulation accuracy, since the clicks are authentic.
- void reduce_clicks( bool reduce = true );
-
- // Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the
- // tempo in a music player.
- void set_tempo( double );
-
- // Saves full emulation state to state_out. Data format is portable and
- // includes some extra space to avoid expansion in case more state needs
- // to be stored in the future.
- void save_state( gb_apu_state_t* state_out );
-
- // Loads state. You should call reset() BEFORE this.
- blargg_err_t load_state( gb_apu_state_t const& in );
-
- // Enable hacks (bitmask):
- // 0x01 = Double wave channel volume
- // 0x02 = Low noise channel volume (disable doubling it)
- void set_hacks( unsigned int mask );
-
-private:
- // noncopyable
- Gb_Apu( const Gb_Apu& );
- Gb_Apu& operator = ( const Gb_Apu& );
-
-// Implementation
-public:
- Gb_Apu();
-
- // Use set_output() in place of these
- BLARGG_DEPRECATED( void output ( Blip_Buffer* c ); )
- BLARGG_DEPRECATED( void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ); )
- BLARGG_DEPRECATED( void osc_output( int i, Blip_Buffer* c ) { set_output( i, c, c, c ); } )
- BLARGG_DEPRECATED( void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( i, c, l, r ); } )
-
- BLARGG_DEPRECATED_TEXT( enum { start_addr = 0xFF10 }; )
- BLARGG_DEPRECATED_TEXT( enum { end_addr = 0xFF3F }; )
- BLARGG_DEPRECATED_TEXT( enum { register_count = end_addr - start_addr + 1 }; )
-
-private:
- Gb_Osc* oscs [osc_count];
- blip_time_t last_time; // time sound emulator has been run to
- blip_time_t frame_period; // clocks between each frame sequencer step
- double volume_;
- bool reduce_clicks_;
-
- Gb_Sweep_Square square1;
- Gb_Square square2;
- Gb_Wave wave;
- Gb_Noise noise;
- blip_time_t frame_time; // time of next frame sequencer action
- int frame_phase; // phase of next frame sequencer step
- enum { regs_size = io_size + 0x10 };
- BOOST::uint8_t regs [regs_size];// last values written to registers
-
- // large objects after everything else
- Blip_Synth_Norm norm_synth;
- Blip_Synth_Fast fast_synth;
-
- void reset_lengths();
- void reset_regs();
- int calc_output( int osc ) const;
- void apply_stereo();
- void apply_volume();
- void synth_volume( int );
- void run_until_( blip_time_t );
- void run_until( blip_time_t );
- void silence_osc( Gb_Osc& );
- void write_osc( int reg, int old_data, int data );
- const char* save_load( gb_apu_state_t*, bool save );
- void save_load2( gb_apu_state_t*, bool save );
- friend class Gb_Apu2;
-};
-
-// Format of save state. Should be stable across versions of the library,
-// with earlier versions properly opening later save states. Includes some
-// room for expansion so the state size shouldn't increase.
-struct gb_apu_state_t
-{
-#if GB_APU_CUSTOM_STATE
- // Values stored as plain int so your code can read/write them easily.
- // Structure can NOT be written to disk, since format is not portable.
- typedef int val_t;
-#else
- // Values written in portable little-endian format, allowing structure
- // to be written directly to disk.
- typedef unsigned char val_t [4];
-#endif
-
- enum { format0 = 0x50414247 }; // 'GBAP'
-
- val_t format; // format of all following data
- val_t version; // later versions just add fields to end
-
- unsigned char regs [0x40];
- val_t frame_time;
- val_t frame_phase;
-
- val_t sweep_freq;
- val_t sweep_delay;
- val_t sweep_enabled;
- val_t sweep_neg;
- val_t noise_divider;
- val_t wave_buf;
-
- val_t delay [4];
- val_t length_ctr [4];
- val_t phase [4];
- val_t enabled [4];
-
- val_t env_delay [3];
- val_t env_volume [3];
- val_t env_enabled [3];
-
- val_t unused [13]; // for future expansion
-};
-
-inline void Gb_Apu::set_output( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- for ( int i = osc_count; --i >= 0; )
- set_output( i, c, l, r );
-}
-
-BLARGG_DEPRECATED_TEXT( inline void Gb_Apu::output( Blip_Buffer* c ) { set_output( c, c, c ); } )
-BLARGG_DEPRECATED_TEXT( inline void Gb_Apu::output( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); } )
-
-#endif
+// Nintendo Game Boy sound hardware emulator with save state support
+
+// Gb_Snd_Emu $vers
+#ifndef GB_APU_H
+#define GB_APU_H
+
+#include "Gb_Oscs.h"
+
+struct gb_apu_state_t;
+
+class Gb_Apu {
+public:
+// Basics
+
+ // Sets buffer(s) to generate sound into, or NULL to mute. If only center is not NULL,
+ // output is mono.
+ void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL );
+
+ // Emulates to time t, then writes data to addr
+ void write_register( blip_time_t t, int addr, int data );
+
+ // Emulates to time t, then subtracts t from the current time.
+ // OK if previous write call had time slightly after t.
+ void end_frame( blip_time_t t );
+
+// More features
+
+ // Clock rate sound hardware runs at
+ enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
+
+ // Registers are at io_addr to io_addr+io_size-1
+ enum { io_addr = 0xFF10 };
+ enum { io_size = 0x30 };
+
+ // Emulates to time t, then reads from addr
+ int read_register( blip_time_t t, int addr );
+
+ // Resets hardware to state after power, BEFORE boot ROM runs. Mode selects
+ // sound hardware. If agb_wave is true, enables AGB's extra wave features.
+ enum mode_t {
+ mode_dmg, // Game Boy monochrome
+ mode_cgb, // Game Boy Color
+ mode_agb // Game Boy Advance
+ };
+ void reset( mode_t mode = mode_cgb, bool agb_wave = false );
+
+ // Same as set_output(), but for a particular channel
+ // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
+ enum { osc_count = 4 }; // 0 <= chan < osc_count
+ void set_output( int chan, Blip_Buffer* center,
+ Blip_Buffer* left = NULL, Blip_Buffer* right = NULL );
+
+ // Sets overall volume, where 1.0 is normal
+ void volume( double );
+
+ // Sets treble equalization
+ void treble_eq( blip_eq_t const& );
+
+ // Treble and bass values for various hardware.
+ enum {
+ speaker_treble = -47, // speaker on system
+ speaker_bass = 2000,
+ dmg_treble = 0, // headphones on each system
+ dmg_bass = 30,
+ cgb_treble = 0,
+ cgb_bass = 300, // CGB has much less bass
+ agb_treble = 0,
+ agb_bass = 30
+ };
+
+ // If true, reduces clicking by disabling DAC biasing. Note that this reduces
+ // emulation accuracy, since the clicks are authentic.
+ void reduce_clicks( bool reduce = true );
+
+ // Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the
+ // tempo in a music player.
+ void set_tempo( double );
+
+ // Saves full emulation state to state_out. Data format is portable and
+ // includes some extra space to avoid expansion in case more state needs
+ // to be stored in the future.
+ void save_state( gb_apu_state_t* state_out );
+
+ // Loads state. You should call reset() BEFORE this.
+ blargg_err_t load_state( gb_apu_state_t const& in );
+
+private:
+ // noncopyable
+ Gb_Apu( const Gb_Apu& );
+ Gb_Apu& operator = ( const Gb_Apu& );
+
+// Implementation
+public:
+ Gb_Apu();
+
+ // Use set_output() in place of these
+ BLARGG_DEPRECATED( void output ( Blip_Buffer* c ); )
+ BLARGG_DEPRECATED( void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ); )
+ BLARGG_DEPRECATED( void osc_output( int i, Blip_Buffer* c ) { set_output( i, c, c, c ); } )
+ BLARGG_DEPRECATED( void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( i, c, l, r ); } )
+
+ BLARGG_DEPRECATED_TEXT( enum { start_addr = 0xFF10 }; )
+ BLARGG_DEPRECATED_TEXT( enum { end_addr = 0xFF3F }; )
+ BLARGG_DEPRECATED_TEXT( enum { register_count = end_addr - start_addr + 1 }; )
+
+private:
+ Gb_Osc* oscs [osc_count];
+ blip_time_t last_time; // time sound emulator has been run to
+ blip_time_t frame_period; // clocks between each frame sequencer step
+ double volume_;
+ bool reduce_clicks_;
+
+ Gb_Sweep_Square square1;
+ Gb_Square square2;
+ Gb_Wave wave;
+ Gb_Noise noise;
+ blip_time_t frame_time; // time of next frame sequencer action
+ int frame_phase; // phase of next frame sequencer step
+ enum { regs_size = io_size + 0x10 };
+ BOOST::uint8_t regs [regs_size];// last values written to registers
+
+ // large objects after everything else
+ Blip_Synth_Norm norm_synth;
+ Blip_Synth_Fast fast_synth;
+
+ void reset_lengths();
+ void reset_regs();
+ int calc_output( int osc ) const;
+ void apply_stereo();
+ void apply_volume();
+ void synth_volume( int );
+ void run_until_( blip_time_t );
+ void run_until( blip_time_t );
+ void silence_osc( Gb_Osc& );
+ void write_osc( int reg, int old_data, int data );
+ const char* save_load( gb_apu_state_t*, bool save );
+ void save_load2( gb_apu_state_t*, bool save );
+ friend class Gb_Apu2;
+};
+
+// Format of save state. Should be stable across versions of the library,
+// with earlier versions properly opening later save states. Includes some
+// room for expansion so the state size shouldn't increase.
+struct gb_apu_state_t
+{
+#if GB_APU_CUSTOM_STATE
+ // Values stored as plain int so your code can read/write them easily.
+ // Structure can NOT be written to disk, since format is not portable.
+ typedef int val_t;
+#else
+ // Values written in portable little-endian format, allowing structure
+ // to be written directly to disk.
+ typedef unsigned char val_t [4];
+#endif
+
+ enum { format0 = 0x50414247 }; // 'GBAP'
+
+ val_t format; // format of all following data
+ val_t version; // later versions just add fields to end
+
+ unsigned char regs [0x40];
+ val_t frame_time;
+ val_t frame_phase;
+
+ val_t sweep_freq;
+ val_t sweep_delay;
+ val_t sweep_enabled;
+ val_t sweep_neg;
+ val_t noise_divider;
+ val_t wave_buf;
+
+ val_t delay [4];
+ val_t length_ctr [4];
+ val_t phase [4];
+ val_t enabled [4];
+
+ val_t env_delay [3];
+ val_t env_volume [3];
+ val_t env_enabled [3];
+
+ val_t unused [13]; // for future expansion
+};
+
+inline void Gb_Apu::set_output( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+ for ( int i = osc_count; --i >= 0; )
+ set_output( i, c, l, r );
+}
+
+BLARGG_DEPRECATED_TEXT( inline void Gb_Apu::output( Blip_Buffer* c ) { set_output( c, c, c ); } )
+BLARGG_DEPRECATED_TEXT( inline void Gb_Apu::output( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); } )
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,720 +1,719 @@
-// Gb_Snd_Emu $vers. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-bool const cgb_02 = false; // enables bug in early CGB units that causes problems in some games
-bool const cgb_05 = false; // enables CGB-05 zombie behavior
-
-int const trigger_mask = 0x80;
-int const length_enabled = 0x40;
-
-void Gb_Osc::reset()
-{
- output = NULL;
- last_amp = 0;
- delay = 0;
- phase = 0;
- enabled = false;
-}
-
-inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
-{
- output->set_modified();
- int delta = new_amp - last_amp;
- if ( delta )
- {
- last_amp = new_amp;
- fast_synth->offset( time, delta, output );
- }
-}
-
-// Units
-
-void Gb_Osc::clock_length()
-{
- if ( (regs [4] & length_enabled) && length_ctr )
- {
- if ( --length_ctr <= 0 )
- enabled = false;
- }
-}
-
-inline int Gb_Env::reload_env_timer()
-{
- int raw = regs [2] & 7;
- env_delay = (raw ? raw : 8);
- return raw;
-}
-
-void Gb_Env::clock_envelope()
-{
- if ( env_enabled && --env_delay <= 0 && reload_env_timer() )
- {
- int v = volume + (regs [2] & 0x08 ? +1 : -1);
- if ( 0 <= v && v <= 15 )
- volume = v;
- else
- env_enabled = false;
- }
-}
-
-inline void Gb_Sweep_Square::reload_sweep_timer()
-{
- sweep_delay = (regs [0] & period_mask) >> 4;
- if ( !sweep_delay )
- sweep_delay = 8;
-}
-
-void Gb_Sweep_Square::calc_sweep( bool update )
-{
- int const shift = regs [0] & shift_mask;
- int const delta = sweep_freq >> shift;
- sweep_neg = (regs [0] & 0x08) != 0;
- int const freq = sweep_freq + (sweep_neg ? -delta : delta);
-
- if ( freq > 0x7FF )
- {
- enabled = false;
- }
- else if ( shift && update )
- {
- sweep_freq = freq;
-
- regs [3] = freq & 0xFF;
- regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07);
- }
-}
-
-void Gb_Sweep_Square::clock_sweep()
-{
- if ( --sweep_delay <= 0 )
- {
- reload_sweep_timer();
- if ( sweep_enabled && (regs [0] & period_mask) )
- {
- calc_sweep( true );
- calc_sweep( false );
- }
- }
-}
-
-int Gb_Wave::access( int addr ) const
-{
- if ( enabled )
- {
- addr = phase & (bank_size - 1);
- if ( mode == Gb_Apu::mode_dmg )
- {
- addr++;
- if ( delay > clk_mul )
- return -1; // can only access within narrow time window while playing
- }
- addr >>= 1;
- }
- return addr & 0x0F;
-}
-
-// write_register
-
-int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data )
-{
- int data = regs [4];
-
- if ( (frame_phase & 1) && !(old_data & length_enabled) && length_ctr )
- {
- if ( (data & length_enabled) || cgb_02 )
- length_ctr--;
- }
-
- if ( data & trigger_mask )
- {
- enabled = true;
- if ( !length_ctr )
- {
- length_ctr = max_len;
- if ( (frame_phase & 1) && (data & length_enabled) )
- length_ctr--;
- }
- }
-
- if ( !length_ctr )
- enabled = false;
-
- return data & trigger_mask;
-}
-
-inline void Gb_Env::zombie_volume( int old, int data )
-{
- int v = volume;
- if ( mode == Gb_Apu::mode_agb || cgb_05 )
- {
- // CGB-05 behavior, very close to AGB behavior as well
- if ( (old ^ data) & 8 )
- {
- if ( !(old & 8) )
- {
- v++;
- if ( old & 7 )
- v++;
- }
-
- v = 16 - v;
- }
- else if ( (old & 0x0F) == 8 )
- {
- v++;
- }
- }
- else
- {
- // CGB-04&02 behavior, very close to MGB behavior as well
- if ( !(old & 7) && env_enabled )
- v++;
- else if ( !(old & 8) )
- v += 2;
-
- if ( (old ^ data) & 8 )
- v = 16 - v;
- }
- volume = v & 0x0F;
-}
-
-bool Gb_Env::write_register( int frame_phase, int reg, int old, int data )
-{
- int const max_len = 64;
-
- switch ( reg )
- {
- case 1:
- length_ctr = max_len - (data & (max_len - 1));
- break;
-
- case 2:
- if ( !dac_enabled() )
- enabled = false;
-
- zombie_volume( old, data );
-
- if ( (data & 7) && env_delay == 8 )
- {
- env_delay = 1;
- clock_envelope(); // TODO: really happens at next length clock
- }
- break;
-
- case 4:
- if ( write_trig( frame_phase, max_len, old ) )
- {
- volume = regs [2] >> 4;
- reload_env_timer();
- env_enabled = true;
- if ( frame_phase == 7 )
- env_delay++;
- if ( !dac_enabled() )
- enabled = false;
- return true;
- }
- }
- return false;
-}
-
-bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data )
-{
- bool result = Gb_Env::write_register( frame_phase, reg, old_data, data );
- if ( result )
- delay = (delay & (4 * clk_mul - 1)) + period();
- return result;
-}
-
-inline void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data )
-{
- if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) )
- {
- phase = 0x7FFF;
- delay += 8 * clk_mul;
- }
-}
-
-inline void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data )
-{
- if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) )
- enabled = false; // sweep negate disabled after used
-
- if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) )
- {
- sweep_freq = frequency();
- sweep_neg = false;
- reload_sweep_timer();
- sweep_enabled = (regs [0] & (period_mask | shift_mask)) != 0;
- if ( regs [0] & shift_mask )
- calc_sweep( false );
- }
-}
-
-void Gb_Wave::corrupt_wave()
-{
- int pos = ((phase + 1) & (bank_size - 1)) >> 1;
- if ( pos < 4 )
- wave_ram [0] = wave_ram [pos];
- else
- for ( int i = 4; --i >= 0; )
- wave_ram [i] = wave_ram [(pos & ~3) + i];
-}
-
-inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data )
-{
- int const max_len = 256;
-
- switch ( reg )
- {
- case 0:
- if ( !dac_enabled() )
- enabled = false;
- break;
-
- case 1:
- length_ctr = max_len - data;
- break;
-
- case 4:
- bool was_enabled = enabled;
- if ( write_trig( frame_phase, max_len, old_data ) )
- {
- if ( !dac_enabled() )
- enabled = false;
- else if ( mode == Gb_Apu::mode_dmg && was_enabled &&
- (unsigned) (delay - 2 * clk_mul) < 2 * clk_mul )
- corrupt_wave();
-
- phase = 0;
- delay = period() + 6 * clk_mul;
- }
- }
-}
-
-void Gb_Apu::write_osc( int reg, int old_data, int data )
-{
- int index = (reg * 3 + 3) >> 4; // avoids divide
- assert( index == reg / 5 );
- reg -= index * 5;
- switch ( index )
- {
- case 0: square1.write_register( frame_phase, reg, old_data, data ); break;
- case 1: square2.write_register( frame_phase, reg, old_data, data ); break;
- case 2: wave .write_register( frame_phase, reg, old_data, data ); break;
- case 3: noise .write_register( frame_phase, reg, old_data, data ); break;
- }
-}
-
-// Synthesis
-
-void Gb_Square::run( blip_time_t time, blip_time_t end_time )
-{
- // Calc duty and phase
- static byte const duty_offsets [4] = { 1, 1, 3, 7 };
- static byte const duties [4] = { 1, 2, 4, 6 };
- int const duty_code = regs [1] >> 6;
- int duty_offset = duty_offsets [duty_code];
- int duty = duties [duty_code];
- if ( mode == Gb_Apu::mode_agb )
- {
- // AGB uses inverted duty
- duty_offset -= duty;
- duty = 8 - duty;
- }
- int ph = (this->phase + duty_offset) & 7;
-
- // Determine what will be generated
- int vol = 0;
- Blip_Buffer* const out = this->output;
- if ( out )
- {
- int amp = dac_off_amp;
- if ( dac_enabled() )
- {
- if ( enabled )
- vol = this->volume;
-
- amp = -dac_bias;
- if ( mode == Gb_Apu::mode_agb )
- amp = -(vol >> 1);
-
- // Play inaudible frequencies as constant amplitude
- if ( frequency() >= 0x7FA && delay < 32 * clk_mul )
- {
- amp += (vol * duty) >> 3;
- vol = 0;
- }
-
- if ( ph < duty )
- {
- amp += vol;
- vol = -vol;
- }
- }
- update_amp( time, amp );
- }
-
- // Generate wave
- time += delay;
- if ( time < end_time )
- {
- int const per = this->period();
- if ( !vol )
- {
- #if GB_APU_FAST
- time = end_time;
- #else
- // Maintain phase when not playing
- int count = (end_time - time + per - 1) / per;
- ph += count; // will be masked below
- time += (blip_time_t) count * per;
- #endif
- }
- else
- {
- // Output amplitude transitions
- int delta = vol;
- do
- {
- ph = (ph + 1) & 7;
- if ( ph == 0 || ph == duty )
- {
- norm_synth->offset_inline( time, delta, out );
- delta = -delta;
- }
- time += per;
- }
- while ( time < end_time );
-
- if ( delta != vol )
- last_amp -= delta;
- }
- this->phase = (ph - duty_offset) & 7;
- }
- delay = time - end_time;
-}
-
-#if !GB_APU_FAST
-// Quickly runs LFSR for a large number of clocks. For use when noise is generating
-// no sound.
-static unsigned run_lfsr( unsigned s, unsigned mask, int count )
-{
- bool const optimized = true; // set to false to use only unoptimized loop in middle
-
- // optimization used in several places:
- // ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)
-
- if ( mask == 0x4000 && optimized )
- {
- if ( count >= 32767 )
- count %= 32767;
-
- // Convert from Fibonacci to Galois configuration,
- // shifted left 1 bit
- s ^= (s & 1) * 0x8000;
-
- // Each iteration is equivalent to clocking LFSR 255 times
- while ( (count -= 255) > 0 )
- s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
- count += 255;
-
- // Each iteration is equivalent to clocking LFSR 15 times
- // (interesting similarity to single clocking below)
- while ( (count -= 15) > 0 )
- s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
- count += 15;
-
- // Remaining singles
- while ( --count >= 0 )
- s = ((s & 2) * (3 << 13)) ^ (s >> 1);
-
- // Convert back to Fibonacci configuration
- s &= 0x7FFF;
- }
- else if ( count < 8 || !optimized )
- {
- // won't fully replace upper 8 bits, so have to do the unoptimized way
- while ( --count >= 0 )
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable:4146)
-#endif
- s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2));
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
- }
- else
- {
- if ( count > 127 )
- {
- count %= 127;
- if ( !count )
- count = 127; // must run at least once
- }
-
- // Need to keep one extra bit of history
- s = s << 1 & 0xFF;
-
- // Convert from Fibonacci to Galois configuration,
- // shifted left 2 bits
- s ^= (s & 2) * 0x80;
-
- // Each iteration is equivalent to clocking LFSR 7 times
- // (interesting similarity to single clocking below)
- while ( (count -= 7) > 0 )
- s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
- count += 7;
-
- // Remaining singles
- while ( --count >= 0 )
- s = ((s & 4) * (3 << 5)) ^ (s >> 1);
-
- // Convert back to Fibonacci configuration and
- // repeat last 8 bits above significant 7
- s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
- }
-
- return s;
-}
-#endif
-
-void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
-{
- // Determine what will be generated
- int vol = 0;
- Blip_Buffer* const out = this->output;
- if ( out )
- {
- int amp = dac_off_amp;
- if ( dac_enabled() )
- {
- if ( enabled )
- vol = this->volume;
-
- amp = -dac_bias;
- if ( mode == Gb_Apu::mode_agb )
- amp = -(vol >> 1);
-
- if ( !(phase & 1) )
- {
- amp += vol;
- vol = -vol;
- }
- }
-
- // AGB negates final output
- if ( mode == Gb_Apu::mode_agb )
- {
- vol = -vol;
- amp = -amp;
- }
-
- update_amp( time, amp );
- }
-
- // Run timer and calculate time of next LFSR clock
- static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
- int const period1 = period1s [regs [3] & 7] * clk_mul;
-
- #if GB_APU_FAST
- time += delay;
- #else
- {
- int extra = (end_time - time) - delay;
- int const per2 = this->period2();
- time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
-
- int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
- divider = (divider - count) & period2_mask;
- delay = count * period1 - extra;
- }
- #endif
-
- // Generate wave
- if ( time < end_time )
- {
- unsigned const mask = this->lfsr_mask();
- unsigned bits = this->phase;
-
- int per = period2( period1 * 8 );
- #if GB_APU_FAST
- // Noise can be THE biggest time hog; adjust as necessary
- int const min_period = 24;
- if ( per < min_period )
- per = min_period;
- #endif
- if ( period2_index() >= 0xE )
- {
- time = end_time;
- }
- else if ( !vol )
- {
- #if GB_APU_FAST
- time = end_time;
- #else
- // Maintain phase when not playing
- int count = (end_time - time + per - 1) / per;
- time += (blip_time_t) count * per;
- bits = run_lfsr( bits, ~mask, count );
- #endif
- }
- else
- {
- Blip_Synth_Fast const* const synth = fast_synth; // cache
-
- // Output amplitude transitions
- if (volume_hack) vol <<= 1;
- int delta = -vol;
- do
- {
- unsigned changed = bits + 1;
- bits = bits >> 1 & mask;
- if ( changed & 2 )
- {
- bits |= ~mask;
- delta = -delta;
- synth->offset_inline( time, delta, out );
- }
- time += per;
- }
- while ( time < end_time );
-
- if ( delta == vol )
- last_amp += delta;
- }
- this->phase = bits;
- }
-
- #if GB_APU_FAST
- delay = time - end_time;
- #endif
-}
-
-void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
-{
- // Calc volume
-#if GB_APU_NO_AGB
- static byte const shifts [4] = { 4+4, 0+4, 1+4, 2+4 };
- int const volume_idx = regs [2] >> 5 & 3;
- int const volume_shift = shifts [volume_idx] - (volume_hack ? 1 : 0);
- int const volume_mul = 1;
-#else
- static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
- int const volume_shift = 2 + 4 - (volume_hack ? 1 : 0);
- int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
- int const volume_mul = volumes [volume_idx];
-#endif
-
- // Determine what will be generated
- int playing = false;
- Blip_Buffer* const out = this->output;
- if ( out )
- {
- int amp = dac_off_amp;
- if ( dac_enabled() )
- {
- // Play inaudible frequencies as constant amplitude
- amp = 8 << 4; // really depends on average of all samples in wave
-
- // if delay is larger, constant amplitude won't start yet
- if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
- {
- if ( volume_mul && volume_shift != 4+4 )
- playing = (int) enabled;
-
- amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing;
- }
-
- amp = ((amp * volume_mul) >> volume_shift) - dac_bias;
- }
- update_amp( time, amp );
- }
-
- // Generate wave
- time += delay;
- if ( time < end_time )
- {
- byte const* wave = this->wave_ram;
-
- // wave size and bank
- #if GB_APU_NO_AGB
- int const wave_mask = 0x1F;
- int const swap_banks = 0;
- #else
- int const size20_mask = 0x20;
- int const flags = regs [0] & agb_mask;
- int const wave_mask = (flags & size20_mask) | 0x1F;
- int swap_banks = 0;
- if ( flags & bank40_mask )
- {
- swap_banks = flags & size20_mask;
- wave += bank_size/2 - (swap_banks >> 1);
- }
- #endif
-
- int ph = this->phase ^ swap_banks;
- ph = (ph + 1) & wave_mask; // pre-advance
-
- int const per = this->period();
- if ( !playing )
- {
- #if GB_APU_FAST
- time = end_time;
- #else
- // Maintain phase when not playing
- int count = (end_time - time + per - 1) / per;
- ph += count; // will be masked below
- time += (blip_time_t) count * per;
- #endif
- }
- else
- {
- Blip_Synth_Fast const* const synth = fast_synth; // cache
-
- // Output amplitude transitions
- int lamp = this->last_amp + dac_bias;
- do
- {
- // Extract nibble
- int nibble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
- ph = (ph + 1) & wave_mask;
-
- // Scale by volume
- int amp = (nibble * volume_mul) >> volume_shift;
-
- int delta = amp - lamp;
- if ( delta )
- {
- lamp = amp;
- synth->offset_inline( time, delta, out );
- }
- time += per;
- }
- while ( time < end_time );
- this->last_amp = lamp - dac_bias;
- }
- ph = (ph - 1) & wave_mask; // undo pre-advance and mask position
-
- // Keep track of last byte read
- if ( enabled )
- sample_buf = wave [ph >> 1];
-
- this->phase = ph ^ swap_banks; // undo swapped banks
- }
- delay = time - end_time;
-}
+// Gb_Snd_Emu $vers. http://www.slack.net/~ant/
+
+#include "Gb_Apu.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+bool const cgb_02 = false; // enables bug in early CGB units that causes problems in some games
+bool const cgb_05 = false; // enables CGB-05 zombie behavior
+
+int const trigger_mask = 0x80;
+int const length_enabled = 0x40;
+
+void Gb_Osc::reset()
+{
+ output = NULL;
+ last_amp = 0;
+ delay = 0;
+ phase = 0;
+ enabled = false;
+}
+
+inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
+{
+ output->set_modified();
+ int delta = new_amp - last_amp;
+ if ( delta )
+ {
+ last_amp = new_amp;
+ fast_synth->offset( time, delta, output );
+ }
+}
+
+// Units
+
+void Gb_Osc::clock_length()
+{
+ if ( (regs [4] & length_enabled) && length_ctr )
+ {
+ if ( --length_ctr <= 0 )
+ enabled = false;
+ }
+}
+
+inline int Gb_Env::reload_env_timer()
+{
+ int raw = regs [2] & 7;
+ env_delay = (raw ? raw : 8);
+ return raw;
+}
+
+void Gb_Env::clock_envelope()
+{
+ if ( env_enabled && --env_delay <= 0 && reload_env_timer() )
+ {
+ int v = volume + (regs [2] & 0x08 ? +1 : -1);
+ if ( 0 <= v && v <= 15 )
+ volume = v;
+ else
+ env_enabled = false;
+ }
+}
+
+inline void Gb_Sweep_Square::reload_sweep_timer()
+{
+ sweep_delay = (regs [0] & period_mask) >> 4;
+ if ( !sweep_delay )
+ sweep_delay = 8;
+}
+
+void Gb_Sweep_Square::calc_sweep( bool update )
+{
+ int const shift = regs [0] & shift_mask;
+ int const delta = sweep_freq >> shift;
+ sweep_neg = (regs [0] & 0x08) != 0;
+ int const freq = sweep_freq + (sweep_neg ? -delta : delta);
+
+ if ( freq > 0x7FF )
+ {
+ enabled = false;
+ }
+ else if ( shift && update )
+ {
+ sweep_freq = freq;
+
+ regs [3] = freq & 0xFF;
+ regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07);
+ }
+}
+
+void Gb_Sweep_Square::clock_sweep()
+{
+ if ( --sweep_delay <= 0 )
+ {
+ reload_sweep_timer();
+ if ( sweep_enabled && (regs [0] & period_mask) )
+ {
+ calc_sweep( true );
+ calc_sweep( false );
+ }
+ }
+}
+
+int Gb_Wave::access( int addr ) const
+{
+ if ( enabled )
+ {
+ addr = phase & (bank_size - 1);
+ if ( mode == Gb_Apu::mode_dmg )
+ {
+ addr++;
+ if ( delay > clk_mul )
+ return -1; // can only access within narrow time window while playing
+ }
+ addr >>= 1;
+ }
+ return addr & 0x0F;
+}
+
+// write_register
+
+int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data )
+{
+ int data = regs [4];
+
+ if ( (frame_phase & 1) && !(old_data & length_enabled) && length_ctr )
+ {
+ if ( (data & length_enabled) || cgb_02 )
+ length_ctr--;
+ }
+
+ if ( data & trigger_mask )
+ {
+ enabled = true;
+ if ( !length_ctr )
+ {
+ length_ctr = max_len;
+ if ( (frame_phase & 1) && (data & length_enabled) )
+ length_ctr--;
+ }
+ }
+
+ if ( !length_ctr )
+ enabled = false;
+
+ return data & trigger_mask;
+}
+
+inline void Gb_Env::zombie_volume( int old, int data )
+{
+ int v = volume;
+ if ( mode == Gb_Apu::mode_agb || cgb_05 )
+ {
+ // CGB-05 behavior, very close to AGB behavior as well
+ if ( (old ^ data) & 8 )
+ {
+ if ( !(old & 8) )
+ {
+ v++;
+ if ( old & 7 )
+ v++;
+ }
+
+ v = 16 - v;
+ }
+ else if ( (old & 0x0F) == 8 )
+ {
+ v++;
+ }
+ }
+ else
+ {
+ // CGB-04&02 behavior, very close to MGB behavior as well
+ if ( !(old & 7) && env_enabled )
+ v++;
+ else if ( !(old & 8) )
+ v += 2;
+
+ if ( (old ^ data) & 8 )
+ v = 16 - v;
+ }
+ volume = v & 0x0F;
+}
+
+bool Gb_Env::write_register( int frame_phase, int reg, int old, int data )
+{
+ int const max_len = 64;
+
+ switch ( reg )
+ {
+ case 1:
+ length_ctr = max_len - (data & (max_len - 1));
+ break;
+
+ case 2:
+ if ( !dac_enabled() )
+ enabled = false;
+
+ zombie_volume( old, data );
+
+ if ( (data & 7) && env_delay == 8 )
+ {
+ env_delay = 1;
+ clock_envelope(); // TODO: really happens at next length clock
+ }
+ break;
+
+ case 4:
+ if ( write_trig( frame_phase, max_len, old ) )
+ {
+ volume = regs [2] >> 4;
+ reload_env_timer();
+ env_enabled = true;
+ if ( frame_phase == 7 )
+ env_delay++;
+ if ( !dac_enabled() )
+ enabled = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data )
+{
+ bool result = Gb_Env::write_register( frame_phase, reg, old_data, data );
+ if ( result )
+ delay = (delay & (4 * clk_mul - 1)) + period();
+ return result;
+}
+
+inline void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data )
+{
+ if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) )
+ {
+ phase = 0x7FFF;
+ delay += 8 * clk_mul;
+ }
+}
+
+inline void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data )
+{
+ if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) )
+ enabled = false; // sweep negate disabled after used
+
+ if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) )
+ {
+ sweep_freq = frequency();
+ sweep_neg = false;
+ reload_sweep_timer();
+ sweep_enabled = (regs [0] & (period_mask | shift_mask)) != 0;
+ if ( regs [0] & shift_mask )
+ calc_sweep( false );
+ }
+}
+
+void Gb_Wave::corrupt_wave()
+{
+ int pos = ((phase + 1) & (bank_size - 1)) >> 1;
+ if ( pos < 4 )
+ wave_ram [0] = wave_ram [pos];
+ else
+ for ( int i = 4; --i >= 0; )
+ wave_ram [i] = wave_ram [(pos & ~3) + i];
+}
+
+inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data )
+{
+ int const max_len = 256;
+
+ switch ( reg )
+ {
+ case 0:
+ if ( !dac_enabled() )
+ enabled = false;
+ break;
+
+ case 1:
+ length_ctr = max_len - data;
+ break;
+
+ case 4:
+ bool was_enabled = enabled;
+ if ( write_trig( frame_phase, max_len, old_data ) )
+ {
+ if ( !dac_enabled() )
+ enabled = false;
+ else if ( mode == Gb_Apu::mode_dmg && was_enabled &&
+ (unsigned) (delay - 2 * clk_mul) < 2 * clk_mul )
+ corrupt_wave();
+
+ phase = 0;
+ delay = period() + 6 * clk_mul;
+ }
+ }
+}
+
+void Gb_Apu::write_osc( int reg, int old_data, int data )
+{
+ int index = (reg * 3 + 3) >> 4; // avoids divide
+ assert( index == reg / 5 );
+ reg -= index * 5;
+ switch ( index )
+ {
+ case 0: square1.write_register( frame_phase, reg, old_data, data ); break;
+ case 1: square2.write_register( frame_phase, reg, old_data, data ); break;
+ case 2: wave .write_register( frame_phase, reg, old_data, data ); break;
+ case 3: noise .write_register( frame_phase, reg, old_data, data ); break;
+ }
+}
+
+// Synthesis
+
+void Gb_Square::run( blip_time_t time, blip_time_t end_time )
+{
+ // Calc duty and phase
+ static byte const duty_offsets [4] = { 1, 1, 3, 7 };
+ static byte const duties [4] = { 1, 2, 4, 6 };
+ int const duty_code = regs [1] >> 6;
+ int duty_offset = duty_offsets [duty_code];
+ int duty = duties [duty_code];
+ if ( mode == Gb_Apu::mode_agb )
+ {
+ // AGB uses inverted duty
+ duty_offset -= duty;
+ duty = 8 - duty;
+ }
+ int ph = (this->phase + duty_offset) & 7;
+
+ // Determine what will be generated
+ int vol = 0;
+ Blip_Buffer* const out = this->output;
+ if ( out )
+ {
+ int amp = dac_off_amp;
+ if ( dac_enabled() )
+ {
+ if ( enabled )
+ vol = this->volume;
+
+ amp = -dac_bias;
+ if ( mode == Gb_Apu::mode_agb )
+ amp = -(vol >> 1);
+
+ // Play inaudible frequencies as constant amplitude
+ if ( frequency() >= 0x7FA && delay < 32 * clk_mul )
+ {
+ amp += (vol * duty) >> 3;
+ vol = 0;
+ }
+
+ if ( ph < duty )
+ {
+ amp += vol;
+ vol = -vol;
+ }
+ }
+ update_amp( time, amp );
+ }
+
+ // Generate wave
+ time += delay;
+ if ( time < end_time )
+ {
+ int const per = this->period();
+ if ( !vol )
+ {
+ #if GB_APU_FAST
+ time = end_time;
+ #else
+ // Maintain phase when not playing
+ int count = (end_time - time + per - 1) / per;
+ ph += count; // will be masked below
+ time += (blip_time_t) count * per;
+ #endif
+ }
+ else
+ {
+ // Output amplitude transitions
+ int delta = vol;
+ do
+ {
+ ph = (ph + 1) & 7;
+ if ( ph == 0 || ph == duty )
+ {
+ norm_synth->offset_inline( time, delta, out );
+ delta = -delta;
+ }
+ time += per;
+ }
+ while ( time < end_time );
+
+ if ( delta != vol )
+ last_amp -= delta;
+ }
+ this->phase = (ph - duty_offset) & 7;
+ }
+ delay = time - end_time;
+}
+
+#if !GB_APU_FAST
+// Quickly runs LFSR for a large number of clocks. For use when noise is generating
+// no sound.
+static unsigned run_lfsr( unsigned s, unsigned mask, int count )
+{
+ bool const optimized = true; // set to false to use only unoptimized loop in middle
+
+ // optimization used in several places:
+ // ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)
+
+ if ( mask == 0x4000 && optimized )
+ {
+ if ( count >= 32767 )
+ count %= 32767;
+
+ // Convert from Fibonacci to Galois configuration,
+ // shifted left 1 bit
+ s ^= (s & 1) * 0x8000;
+
+ // Each iteration is equivalent to clocking LFSR 255 times
+ while ( (count -= 255) > 0 )
+ s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
+ count += 255;
+
+ // Each iteration is equivalent to clocking LFSR 15 times
+ // (interesting similarity to single clocking below)
+ while ( (count -= 15) > 0 )
+ s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
+ count += 15;
+
+ // Remaining singles
+ while ( --count >= 0 )
+ s = ((s & 2) * (3 << 13)) ^ (s >> 1);
+
+ // Convert back to Fibonacci configuration
+ s &= 0x7FFF;
+ }
+ else if ( count < 8 || !optimized )
+ {
+ // won't fully replace upper 8 bits, so have to do the unoptimized way
+ while ( --count >= 0 )
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4146)
+#endif
+ s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2));
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+ }
+ else
+ {
+ if ( count > 127 )
+ {
+ count %= 127;
+ if ( !count )
+ count = 127; // must run at least once
+ }
+
+ // Need to keep one extra bit of history
+ s = s << 1 & 0xFF;
+
+ // Convert from Fibonacci to Galois configuration,
+ // shifted left 2 bits
+ s ^= (s & 2) * 0x80;
+
+ // Each iteration is equivalent to clocking LFSR 7 times
+ // (interesting similarity to single clocking below)
+ while ( (count -= 7) > 0 )
+ s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
+ count += 7;
+
+ // Remaining singles
+ while ( --count >= 0 )
+ s = ((s & 4) * (3 << 5)) ^ (s >> 1);
+
+ // Convert back to Fibonacci configuration and
+ // repeat last 8 bits above significant 7
+ s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
+ }
+
+ return s;
+}
+#endif
+
+void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
+{
+ // Determine what will be generated
+ int vol = 0;
+ Blip_Buffer* const out = this->output;
+ if ( out )
+ {
+ int amp = dac_off_amp;
+ if ( dac_enabled() )
+ {
+ if ( enabled )
+ vol = this->volume;
+
+ amp = -dac_bias;
+ if ( mode == Gb_Apu::mode_agb )
+ amp = -(vol >> 1);
+
+ if ( !(phase & 1) )
+ {
+ amp += vol;
+ vol = -vol;
+ }
+ }
+
+ // AGB negates final output
+ if ( mode == Gb_Apu::mode_agb )
+ {
+ vol = -vol;
+ amp = -amp;
+ }
+
+ update_amp( time, amp );
+ }
+
+ // Run timer and calculate time of next LFSR clock
+ static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
+ int const period1 = period1s [regs [3] & 7] * clk_mul;
+
+ #if GB_APU_FAST
+ time += delay;
+ #else
+ {
+ int extra = (end_time - time) - delay;
+ int const per2 = this->period2();
+ time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
+
+ int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
+ divider = (divider - count) & period2_mask;
+ delay = count * period1 - extra;
+ }
+ #endif
+
+ // Generate wave
+ if ( time < end_time )
+ {
+ unsigned const mask = this->lfsr_mask();
+ unsigned bits = this->phase;
+
+ int per = period2( period1 * 8 );
+ #if GB_APU_FAST
+ // Noise can be THE biggest time hog; adjust as necessary
+ int const min_period = 24;
+ if ( per < min_period )
+ per = min_period;
+ #endif
+ if ( period2_index() >= 0xE )
+ {
+ time = end_time;
+ }
+ else if ( !vol )
+ {
+ #if GB_APU_FAST
+ time = end_time;
+ #else
+ // Maintain phase when not playing
+ int count = (end_time - time + per - 1) / per;
+ time += (blip_time_t) count * per;
+ bits = run_lfsr( bits, ~mask, count );
+ #endif
+ }
+ else
+ {
+ Blip_Synth_Fast const* const synth = fast_synth; // cache
+
+ // Output amplitude transitions
+ int delta = -vol;
+ do
+ {
+ unsigned changed = bits + 1;
+ bits = bits >> 1 & mask;
+ if ( changed & 2 )
+ {
+ bits |= ~mask;
+ delta = -delta;
+ synth->offset_inline( time, delta, out );
+ }
+ time += per;
+ }
+ while ( time < end_time );
+
+ if ( delta == vol )
+ last_amp += delta;
+ }
+ this->phase = bits;
+ }
+
+ #if GB_APU_FAST
+ delay = time - end_time;
+ #endif
+}
+
+void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
+{
+ // Calc volume
+#if GB_APU_NO_AGB
+ static byte const shifts [4] = { 4+4, 0+4, 1+4, 2+4 };
+ int const volume_idx = regs [2] >> 5 & 3;
+ int const volume_shift = shifts [volume_idx];
+ int const volume_mul = 1;
+#else
+ static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
+ int const volume_shift = 2 + 4;
+ int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
+ int const volume_mul = volumes [volume_idx];
+#endif
+
+ // Determine what will be generated
+ int playing = false;
+ Blip_Buffer* const out = this->output;
+ if ( out )
+ {
+ int amp = dac_off_amp;
+ if ( dac_enabled() )
+ {
+ // Play inaudible frequencies as constant amplitude
+ amp = 8 << 4; // really depends on average of all samples in wave
+
+ // if delay is larger, constant amplitude won't start yet
+ if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
+ {
+ if ( volume_mul && volume_shift != 4+4 )
+ playing = (int) enabled;
+
+ amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing;
+ }
+
+ amp = ((amp * volume_mul) >> volume_shift) - dac_bias;
+ }
+ update_amp( time, amp );
+ }
+
+ // Generate wave
+ time += delay;
+ if ( time < end_time )
+ {
+ byte const* wave = this->wave_ram;
+
+ // wave size and bank
+ #if GB_APU_NO_AGB
+ int const wave_mask = 0x1F;
+ int const swap_banks = 0;
+ #else
+ int const size20_mask = 0x20;
+ int const flags = regs [0] & agb_mask;
+ int const wave_mask = (flags & size20_mask) | 0x1F;
+ int swap_banks = 0;
+ if ( flags & bank40_mask )
+ {
+ swap_banks = flags & size20_mask;
+ wave += bank_size/2 - (swap_banks >> 1);
+ }
+ #endif
+
+ int ph = this->phase ^ swap_banks;
+ ph = (ph + 1) & wave_mask; // pre-advance
+
+ int const per = this->period();
+ if ( !playing )
+ {
+ #if GB_APU_FAST
+ time = end_time;
+ #else
+ // Maintain phase when not playing
+ int count = (end_time - time + per - 1) / per;
+ ph += count; // will be masked below
+ time += (blip_time_t) count * per;
+ #endif
+ }
+ else
+ {
+ Blip_Synth_Fast const* const synth = fast_synth; // cache
+
+ // Output amplitude transitions
+ int lamp = this->last_amp + dac_bias;
+ do
+ {
+ // Extract nibble
+ int nibble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
+ ph = (ph + 1) & wave_mask;
+
+ // Scale by volume
+ int amp = (nibble * volume_mul) >> volume_shift;
+
+ int delta = amp - lamp;
+ if ( delta )
+ {
+ lamp = amp;
+ synth->offset_inline( time, delta, out );
+ }
+ time += per;
+ }
+ while ( time < end_time );
+ this->last_amp = lamp - dac_bias;
+ }
+ ph = (ph - 1) & wave_mask; // undo pre-advance and mask position
+
+ // Keep track of last byte read
+ if ( enabled )
+ sample_buf = wave [ph >> 1];
+
+ this->phase = ph ^ swap_banks; // undo swapped banks
+ }
+ delay = time - end_time;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gb_Oscs.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,203 +1,188 @@
-// Private oscillators used by Gb_Apu
-
-// Gb_Snd_Emu $vers
-#ifndef GB_OSCS_H
-#define GB_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-#ifndef GB_APU_OVERCLOCK
- #define GB_APU_OVERCLOCK 1
-#endif
-
-#if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1)
- #error "GB_APU_OVERCLOCK must be a power of 2"
-#endif
-
-class Gb_Osc {
-protected:
-
- // 11-bit frequency in NRx3 and NRx4
- int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
-
- void update_amp( blip_time_t, int new_amp );
- int write_trig( int frame_phase, int max_len, int old_data );
-public:
-
- enum { clk_mul = GB_APU_OVERCLOCK };
- enum { dac_bias = 7 };
-
- Blip_Buffer* outputs [4];// NULL, right, left, center
- Blip_Buffer* output; // where to output sound
- BOOST::uint8_t* regs; // osc's 5 registers
- int mode; // mode_dmg, mode_cgb, mode_agb
- int dac_off_amp;// amplitude when DAC is off
- int last_amp; // current amplitude in Blip_Buffer
- Blip_Synth_Norm const* norm_synth;
- Blip_Synth_Fast const* fast_synth;
-
- int delay; // clocks until frequency timer expires
- int length_ctr; // length counter
- unsigned phase; // waveform phase (or equivalent)
- bool enabled; // internal enabled flag
-
- void clock_length();
- void reset();
-};
-
-class Gb_Env : public Gb_Osc {
-public:
- int env_delay;
- int volume;
- bool env_enabled;
-
- void clock_envelope();
- bool write_register( int frame_phase, int reg, int old_data, int data );
-
- void reset()
- {
- env_delay = 0;
- volume = 0;
- Gb_Osc::reset();
- }
-protected:
- // Non-zero if DAC is enabled
- int dac_enabled() const { return regs [2] & 0xF8; }
-private:
- void zombie_volume( int old, int data );
- int reload_env_timer();
-};
-
-class Gb_Square : public Gb_Env {
-public:
- bool write_register( int frame_phase, int reg, int old_data, int data );
- void run( blip_time_t, blip_time_t );
-
- void reset()
- {
- Gb_Env::reset();
- delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
- }
-private:
- // Frequency timer period
- int period() const { return (2048 - frequency()) * (4 * clk_mul); }
-};
-
-class Gb_Sweep_Square : public Gb_Square {
-public:
- int sweep_freq;
- int sweep_delay;
- bool sweep_enabled;
- bool sweep_neg;
-
- void clock_sweep();
- void write_register( int frame_phase, int reg, int old_data, int data );
-
- void reset()
- {
- sweep_freq = 0;
- sweep_delay = 0;
- sweep_enabled = false;
- sweep_neg = false;
- Gb_Square::reset();
- }
-private:
- enum { period_mask = 0x70 };
- enum { shift_mask = 0x07 };
-
- void calc_sweep( bool update );
- void reload_sweep_timer();
-};
-
-class Gb_Noise : public Gb_Env {
-public:
-
- int divider; // noise has more complex frequency divider setup
-
- bool volume_hack;
-
- void run( blip_time_t, blip_time_t );
- void write_register( int frame_phase, int reg, int old_data, int data );
-
- void reset()
- {
- divider = 0;
- Gb_Env::reset();
- delay = 4 * clk_mul; // TODO: remove?
- volume_hack = true;
- }
-
- void set_volume_hack( bool enable );
-
-private:
- enum { period2_mask = 0x1FFFF };
-
- int period2_index() const { return regs [3] >> 4; }
- int period2( int base = 8 ) const { return base << period2_index(); }
- unsigned lfsr_mask() const { return (regs [3] & 0x08) ? ~0x4040 : ~0x4000; }
-};
-
-inline void Gb_Noise::set_volume_hack( bool enable ) { volume_hack = enable; }
-
-class Gb_Wave : public Gb_Osc {
-public:
- int sample_buf; // last wave RAM byte read (hardware has this as well)
-
- bool volume_hack;
-
- void write_register( int frame_phase, int reg, int old_data, int data );
- void run( blip_time_t, blip_time_t );
-
- // Reads/writes wave RAM
- int read( int addr ) const;
- void write( int addr, int data );
-
- void reset()
- {
- sample_buf = 0;
- Gb_Osc::reset();
- volume_hack = false;
- }
-
-private:
- enum { bank40_mask = 0x40 };
- enum { bank_size = 32 };
-
- int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
- BOOST::uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU
-
- friend class Gb_Apu;
-
- // Frequency timer period
- int period() const { return (2048 - frequency()) * (2 * clk_mul); }
-
- // Non-zero if DAC is enabled
- int dac_enabled() const { return regs [0] & 0x80; }
-
- void corrupt_wave();
-
- void set_volume_hack( bool enable );
-
- BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
-
- // Wave index that would be accessed, or -1 if no access would occur
- int access( int addr ) const;
-};
-
-inline void Gb_Wave::set_volume_hack( bool enable ) { volume_hack = enable; }
-
-inline int Gb_Wave::read( int addr ) const
-{
- int index = access( addr );
- return (index < 0 ? 0xFF : wave_bank() [index]);
-}
-
-inline void Gb_Wave::write( int addr, int data )
-{
- int index = access( addr );
- if ( index >= 0 )
- wave_bank() [index] = data;;
-}
-
-#endif
+// Private oscillators used by Gb_Apu
+
+// Gb_Snd_Emu $vers
+#ifndef GB_OSCS_H
+#define GB_OSCS_H
+
+#include "blargg_common.h"
+#include "Blip_Buffer.h"
+
+#ifndef GB_APU_OVERCLOCK
+ #define GB_APU_OVERCLOCK 1
+#endif
+
+#if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1)
+ #error "GB_APU_OVERCLOCK must be a power of 2"
+#endif
+
+class Gb_Osc {
+protected:
+
+ // 11-bit frequency in NRx3 and NRx4
+ int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
+
+ void update_amp( blip_time_t, int new_amp );
+ int write_trig( int frame_phase, int max_len, int old_data );
+public:
+
+ enum { clk_mul = GB_APU_OVERCLOCK };
+ enum { dac_bias = 7 };
+
+ Blip_Buffer* outputs [4];// NULL, right, left, center
+ Blip_Buffer* output; // where to output sound
+ BOOST::uint8_t* regs; // osc's 5 registers
+ int mode; // mode_dmg, mode_cgb, mode_agb
+ int dac_off_amp;// amplitude when DAC is off
+ int last_amp; // current amplitude in Blip_Buffer
+ Blip_Synth_Norm const* norm_synth;
+ Blip_Synth_Fast const* fast_synth;
+
+ int delay; // clocks until frequency timer expires
+ int length_ctr; // length counter
+ unsigned phase; // waveform phase (or equivalent)
+ bool enabled; // internal enabled flag
+
+ void clock_length();
+ void reset();
+};
+
+class Gb_Env : public Gb_Osc {
+public:
+ int env_delay;
+ int volume;
+ bool env_enabled;
+
+ void clock_envelope();
+ bool write_register( int frame_phase, int reg, int old_data, int data );
+
+ void reset()
+ {
+ env_delay = 0;
+ volume = 0;
+ Gb_Osc::reset();
+ }
+protected:
+ // Non-zero if DAC is enabled
+ int dac_enabled() const { return regs [2] & 0xF8; }
+private:
+ void zombie_volume( int old, int data );
+ int reload_env_timer();
+};
+
+class Gb_Square : public Gb_Env {
+public:
+ bool write_register( int frame_phase, int reg, int old_data, int data );
+ void run( blip_time_t, blip_time_t );
+
+ void reset()
+ {
+ Gb_Env::reset();
+ delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
+ }
+private:
+ // Frequency timer period
+ int period() const { return (2048 - frequency()) * (4 * clk_mul); }
+};
+
+class Gb_Sweep_Square : public Gb_Square {
+public:
+ int sweep_freq;
+ int sweep_delay;
+ bool sweep_enabled;
+ bool sweep_neg;
+
+ void clock_sweep();
+ void write_register( int frame_phase, int reg, int old_data, int data );
+
+ void reset()
+ {
+ sweep_freq = 0;
+ sweep_delay = 0;
+ sweep_enabled = false;
+ sweep_neg = false;
+ Gb_Square::reset();
+ }
+private:
+ enum { period_mask = 0x70 };
+ enum { shift_mask = 0x07 };
+
+ void calc_sweep( bool update );
+ void reload_sweep_timer();
+};
+
+class Gb_Noise : public Gb_Env {
+public:
+ int divider; // noise has more complex frequency divider setup
+
+ void run( blip_time_t, blip_time_t );
+ void write_register( int frame_phase, int reg, int old_data, int data );
+
+ void reset()
+ {
+ divider = 0;
+ Gb_Env::reset();
+ delay = 4 * clk_mul; // TODO: remove?
+ }
+
+private:
+ enum { period2_mask = 0x1FFFF };
+
+ int period2_index() const { return regs [3] >> 4; }
+ int period2( int base = 8 ) const { return base << period2_index(); }
+ unsigned lfsr_mask() const { return (regs [3] & 0x08) ? ~0x4040 : ~0x4000; }
+};
+
+class Gb_Wave : public Gb_Osc {
+public:
+ int sample_buf; // last wave RAM byte read (hardware has this as well)
+
+ void write_register( int frame_phase, int reg, int old_data, int data );
+ void run( blip_time_t, blip_time_t );
+
+ // Reads/writes wave RAM
+ int read( int addr ) const;
+ void write( int addr, int data );
+
+ void reset()
+ {
+ sample_buf = 0;
+ Gb_Osc::reset();
+ }
+
+private:
+ enum { bank40_mask = 0x40 };
+ enum { bank_size = 32 };
+
+ int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
+ BOOST::uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU
+
+ friend class Gb_Apu;
+
+ // Frequency timer period
+ int period() const { return (2048 - frequency()) * (2 * clk_mul); }
+
+ // Non-zero if DAC is enabled
+ int dac_enabled() const { return regs [0] & 0x80; }
+
+ void corrupt_wave();
+
+ BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
+
+ // Wave index that would be accessed, or -1 if no access would occur
+ int access( int addr ) const;
+};
+
+inline int Gb_Wave::read( int addr ) const
+{
+ int index = access( addr );
+ return (index < 0 ? 0xFF : wave_bank() [index]);
+}
+
+inline void Gb_Wave::write( int addr, int data )
+{
+ int index = access( addr );
+ if ( index >= 0 )
+ wave_bank() [index] = data;;
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gbs_Core.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gbs_Core.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gbs_Core.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gbs_Core.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -48,7 +48,7 @@
if ( !header_.valid_tag() )
return blargg_err_file_type;
- if ( header_.vers != 1 )
+ if ( header_.vers < 1 || header_.vers > 2 )
set_warning( "Unknown file version" );
if ( header_.timer_mode & 0x78 )
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gbs_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gbs_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gbs_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gbs_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,167 +1,167 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Gbs_Emu.h"
-
-/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000, 0,0,0,0,0,0,0,0 };
-Gbs_Emu::equalizer_t const Gbs_Emu::cgb_eq = { 0.0, 300, 0,0,0,0,0,0,0,0 };
-Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 30, 0,0,0,0,0,0,0,0 }; // DMG
-
-Gbs_Emu::Gbs_Emu()
-{
- sound_hardware = sound_gbs;
- enable_clicking( false );
- set_type( gme_gbs_type );
- set_silence_lookahead( 6 );
- set_max_initial_silence( 21 );
- set_gain( 1.2 );
-
- // kind of midway between headphones and speaker
- static equalizer_t const eq = { -1.0, 120, 0,0,0,0,0,0,0,0 };
- set_equalizer( eq );
-}
-
-Gbs_Emu::~Gbs_Emu() { }
-
-void Gbs_Emu::unload()
-{
- core_.unload();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
-}
-
-static void hash_gbs_file( Gbs_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.vers, sizeof(h.vers) );
- out.hash_( &h.track_count, sizeof(h.track_count) );
- out.hash_( &h.first_track, sizeof(h.first_track) );
- out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
- out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
- out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
- out.hash_( &h.stack_ptr[0], sizeof(h.stack_ptr) );
- out.hash_( &h.timer_modulo, sizeof(h.timer_modulo) );
- out.hash_( &h.timer_mode, sizeof(h.timer_mode) );
- out.hash_( data, data_size );
-}
-
-blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_gbs_fields( header(), out );
- return blargg_ok;
-}
-
-struct Gbs_File : Gme_Info_
-{
- Gbs_Emu::header_t const* h;
-
- Gbs_File() { set_type( gme_gbs_type ); }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- h = ( Gbs_Emu::header_t * ) begin;
-
- set_track_count( h->track_count );
- if ( !h->valid_tag() )
- return blargg_err_file_type;
-
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_gbs_fields( Gbs_Emu::header_t( *h ), out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_gbs_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
-static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
-
-gme_type_t_ const gme_gbs_type [1] = {{ "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 }};
-
-// Setup
-
-blargg_err_t Gbs_Emu::load_( Data_Reader& in )
-{
- RETURN_ERR( core_.load( in ) );
- set_warning( core_.warning() );
- set_track_count( header().track_count );
- set_voice_count( Gb_Apu::osc_count );
- core_.apu().volume( gain() );
-
- static const char* const names [Gb_Apu::osc_count] = {
- "Square 1", "Square 2", "Wave", "Noise"
- };
- set_voice_names( names );
-
- static int const types [Gb_Apu::osc_count] = {
- wave_type+1, wave_type+2, wave_type+3, mixed_type+1
- };
- set_voice_types( types );
-
- return setup_buffer( 4194304 );
-}
-
-void Gbs_Emu::update_eq( blip_eq_t const& eq )
-{
- core_.apu().treble_eq( eq );
-}
-
-void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- core_.apu().set_output( i, c, l, r );
-}
-
-void Gbs_Emu::set_tempo_( double t )
-{
- core_.set_tempo( t );
-}
-
-blargg_err_t Gbs_Emu::start_track_( int track )
-{
- sound_t mode = sound_hardware;
- if ( mode == sound_gbs )
- mode = (header().timer_mode & 0x80) ? sound_cgb : sound_dmg;
-
- RETURN_ERR( core_.start_track( track, (Gb_Apu::mode_t) mode ) );
-
- // clear buffer AFTER track is started, eliminating initial click
- return Classic_Emu::start_track_( track );
-}
-
-blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
-{
- return core_.end_frame( duration );
-}
-
-blargg_err_t Gbs_Emu::hash_( Hash_Function& out ) const
-{
- hash_gbs_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
- return blargg_ok;
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Gbs_Emu.h"
+
+/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000, 0,0,0,0,0,0,0,0 };
+Gbs_Emu::equalizer_t const Gbs_Emu::cgb_eq = { 0.0, 300, 0,0,0,0,0,0,0,0 };
+Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 30, 0,0,0,0,0,0,0,0 }; // DMG
+
+Gbs_Emu::Gbs_Emu()
+{
+ sound_hardware = sound_gbs;
+ enable_clicking( false );
+ set_type( gme_gbs_type );
+ set_silence_lookahead( 6 );
+ set_max_initial_silence( 21 );
+ set_gain( 1.2 );
+
+ // kind of midway between headphones and speaker
+ static equalizer_t const eq = { -1.0, 120, 0,0,0,0,0,0,0,0 };
+ set_equalizer( eq );
+}
+
+Gbs_Emu::~Gbs_Emu() { }
+
+void Gbs_Emu::unload()
+{
+ core_.unload();
+ Music_Emu::unload();
+}
+
+// Track info
+
+static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
+{
+ GME_COPY_FIELD( h, out, game );
+ GME_COPY_FIELD( h, out, author );
+ GME_COPY_FIELD( h, out, copyright );
+}
+
+static void hash_gbs_file( Gbs_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.vers, sizeof(h.vers) );
+ out.hash_( &h.track_count, sizeof(h.track_count) );
+ out.hash_( &h.first_track, sizeof(h.first_track) );
+ out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
+ out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
+ out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
+ out.hash_( &h.stack_ptr[0], sizeof(h.stack_ptr) );
+ out.hash_( &h.timer_modulo, sizeof(h.timer_modulo) );
+ out.hash_( &h.timer_mode, sizeof(h.timer_mode) );
+ out.hash_( data, data_size );
+}
+
+blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
+{
+ copy_gbs_fields( header(), out );
+ return blargg_ok;
+}
+
+struct Gbs_File : Gme_Info_
+{
+ Gbs_Emu::header_t const* h;
+
+ Gbs_File() { set_type( gme_gbs_type ); }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ h = ( Gbs_Emu::header_t * ) begin;
+
+ set_track_count( h->track_count );
+ if ( !h->valid_tag() )
+ return blargg_err_file_type;
+
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_gbs_fields( Gbs_Emu::header_t( *h ), out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_gbs_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
+static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
+
+gme_type_t_ const gme_gbs_type [1] = {{ "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 }};
+
+// Setup
+
+blargg_err_t Gbs_Emu::load_( Data_Reader& in )
+{
+ RETURN_ERR( core_.load( in ) );
+ set_warning( core_.warning() );
+ set_track_count( header().track_count );
+ set_voice_count( Gb_Apu::osc_count );
+ core_.apu().volume( gain() );
+
+ static const char* const names [Gb_Apu::osc_count] = {
+ "Square 1", "Square 2", "Wave", "Noise"
+ };
+ set_voice_names( names );
+
+ static int const types [Gb_Apu::osc_count] = {
+ wave_type+1, wave_type+2, wave_type+3, mixed_type+1
+ };
+ set_voice_types( types );
+
+ return setup_buffer( 4194304 );
+}
+
+void Gbs_Emu::update_eq( blip_eq_t const& eq )
+{
+ core_.apu().treble_eq( eq );
+}
+
+void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+ core_.apu().set_output( i, c, l, r );
+}
+
+void Gbs_Emu::set_tempo_( double t )
+{
+ core_.set_tempo( t );
+}
+
+blargg_err_t Gbs_Emu::start_track_( int track )
+{
+ sound_t mode = sound_hardware;
+ if ( mode == sound_gbs )
+ mode = (header().timer_mode & 0x80) ? sound_cgb : sound_dmg;
+
+ RETURN_ERR( core_.start_track( track, (Gb_Apu::mode_t) mode ) );
+
+ // clear buffer AFTER track is started, eliminating initial click
+ return Classic_Emu::start_track_( track );
+}
+
+blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
+{
+ return core_.end_frame( duration );
+}
+
+blargg_err_t Gbs_Emu::hash_( Hash_Function& out ) const
+{
+ hash_gbs_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
+ return blargg_ok;
}
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,468 +1,469 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#if !GME_DISABLE_EFFECTS
-#include "Effects_Buffer.h"
-#endif
-#include "blargg_endian.h"
-#include
-#include
-
-/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifndef GME_TYPE_LIST
-
-// Default list of all supported game music types (copy this to blargg_config.h
-// if you want to modify it)
-#define GME_TYPE_LIST \
- gme_ay_type,\
- gme_gbs_type,\
- gme_gym_type,\
- gme_hes_type,\
- gme_kss_type,\
- gme_nsf_type,\
- gme_nsfe_type,\
- gme_sap_type,\
- gme_sfm_type,\
- gme_sgc_type,\
- gme_spc_type,\
- gme_vgm_type,\
- gme_vgz_type
-
-#endif
-
-static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 };
-
-gme_type_t const* gme_type_list()
-{
- return gme_type_list_;
-}
-
-const char* gme_identify_header( void const* header )
-{
- switch ( get_be32( header ) )
- {
- case BLARGG_4CHAR('Z','X','A','Y'): return "AY";
- case BLARGG_4CHAR('G','B','S',0x01): return "GBS";
- case BLARGG_4CHAR('G','Y','M','X'): return "GYM";
- case BLARGG_4CHAR('H','E','S','M'): return "HES";
- case BLARGG_4CHAR('K','S','C','C'):
- case BLARGG_4CHAR('K','S','S','X'): return "KSS";
- case BLARGG_4CHAR('N','E','S','M'): return "NSF";
- case BLARGG_4CHAR('N','S','F','E'): return "NSFE";
- case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
- case BLARGG_4CHAR('S','F','M','1'): return "SFM";
- case BLARGG_4CHAR('S','G','C',0x1A): return "SGC";
- case BLARGG_4CHAR('S','N','E','S'): return "SPC";
- case BLARGG_4CHAR('V','g','m',' '): return "VGM";
- }
- return "";
-}
-
-static void to_uppercase( const char in [], int len, char out [] )
-{
- for ( int i = 0; i < len; i++ )
- {
- if ( !(out [i] = toupper( in [i] )) )
- return;
- }
- *out = 0; // extension too long
-}
-
-gme_type_t gme_identify_extension( const char extension_ [] )
-{
- char const* end = strrchr( extension_, '.' );
- if ( end )
- extension_ = end + 1;
-
- char extension [6];
- to_uppercase( extension_, sizeof extension, extension );
-
- gme_type_t const* types = gme_type_list_;
- for ( ; *types; types++ )
- if ( !strcmp( extension, (*types)->extension_ ) )
- break;
- return *types;
-}
-
-gme_err_t gme_identify_file( const char path [], gme_type_t* type_out )
-{
- *type_out = gme_identify_extension( path );
- // TODO: don't examine header if file has extension?
- if ( !*type_out )
- {
- char header [4];
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- RETURN_ERR( in.read( header, sizeof header ) );
- *type_out = gme_identify_extension( gme_identify_header( header ) );
- }
- return blargg_ok;
-}
-
-gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
-{
- require( (data || !size) && out );
- *out = NULL;
-
- gme_type_t file_type = 0;
- if ( size >= 4 )
- file_type = gme_identify_extension( gme_identify_header( data ) );
- if ( !file_type )
- return blargg_err_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- gme_err_t err = gme_load_data( emu, data, size );
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate )
-{
- require( path && out );
- *out = NULL;
-
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
-
- char header [4];
- int header_size = 0;
-
- gme_type_t file_type = gme_identify_extension( path );
- if ( !file_type )
- {
- header_size = sizeof header;
- RETURN_ERR( in.read( header, sizeof header ) );
- file_type = gme_identify_extension( gme_identify_header( header ) );
- }
- if ( !file_type )
- return blargg_err_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- // optimization: avoids seeking/re-reading header
- Remaining_Reader rem( header, header_size, &in );
- gme_err_t err = emu->load( rem );
- in.close();
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-Music_Emu* gme_new_emu( gme_type_t type, int rate )
-{
- if ( type )
- {
- if ( rate == gme_info_only )
- return type->new_info();
-
- Music_Emu* gme = type->new_emu();
- if ( gme )
- {
- #if !GME_DISABLE_EFFECTS
- if ( type->flags_ & 1 )
- {
- gme->effects_buffer_ = BLARGG_NEW Simple_Effects_Buffer;
- if ( gme->effects_buffer_ )
- gme->set_buffer( gme->effects_buffer_ );
- }
-
- if ( !(type->flags_ & 1) || gme->effects_buffer_ )
- #endif
- {
- if ( !gme->set_sample_rate( rate ) )
- {
- check( gme->type() == type );
- return gme;
- }
- }
- delete gme;
- }
- }
- return NULL;
-}
-
-gme_err_t gme_load_file( Music_Emu* gme, const char path [] ) { return gme->load_file( path ); }
-
-gme_err_t gme_load_data( Music_Emu* gme, void const* data, long size )
-{
- Mem_File_Reader in( data, size );
- return gme->load( in );
-}
-
-gme_err_t gme_load_custom( Music_Emu* gme, gme_reader_t func, long size, void* data )
-{
- Callback_Reader in( func, size, data );
- return gme->load( in );
-}
-
-void gme_delete( Music_Emu* gme ) { delete gme; }
-
-gme_type_t gme_type( Music_Emu const* gme ) { return gme->type(); }
-
-const char* gme_type_system( gme_type_t_ const* type ) { return type->system; }
-
-const char* gme_warning( Music_Emu* gme ) { return gme->warning(); }
-
-int gme_track_count( Music_Emu const* gme ) { return gme->track_count(); }
-
-struct gme_info_t_ : gme_info_t
-{
- track_info_t info;
-
- BLARGG_DISABLE_NOTHROW
-};
-
-gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
-{
- *out = NULL;
-
- gme_info_t_* info = BLARGG_NEW gme_info_t_;
- CHECK_ALLOC( info );
-
- gme_err_t err = me->track_info( &info->info, track );
- if ( err )
- {
- gme_free_info( info );
- return err;
- }
-
- #define COPY(name) info->name = info->info.name;
-
- COPY( length );
- COPY( intro_length );
- COPY( loop_length );
-
- info->i4 = -1;
- info->i5 = -1;
- info->i6 = -1;
- info->i7 = -1;
- info->i8 = -1;
- info->i9 = -1;
- info->i10 = -1;
- info->i11 = -1;
- info->i12 = -1;
- info->i13 = -1;
- info->i14 = -1;
- info->i15 = -1;
-
- info->s7 = "";
- info->s8 = "";
- info->s9 = "";
- info->s10 = "";
- info->s11 = "";
- info->s12 = "";
- info->s13 = "";
- info->s14 = "";
- info->s15 = "";
-
- COPY( system );
- COPY( game );
- COPY( song );
- COPY( author );
- COPY( copyright );
- COPY( comment );
- COPY( dumper );
-
- #undef COPY
-
- info->play_length = info->length;
- if ( info->play_length <= 0 )
- {
- info->play_length = info->intro_length + 2 * info->loop_length; // intro + 2 loops
- if ( info->play_length <= 0 )
- info->play_length = 150 * 1000; // 2.5 minutes
- }
-
- *out = info;
-
- return blargg_ok;
-}
-
-gme_err_t gme_set_track_info( Music_Emu * me, gme_info_t* in, int track )
-{
- track_info_t* info = BLARGG_NEW track_info_t;
- CHECK_ALLOC( info );
-
-#define COPY(name) info->name = in->name;
-
- COPY( length );
- COPY( intro_length );
- COPY( loop_length );
-
-#undef COPY
-#define COPY(name) if ( in->name ) strncpy( info->name, in->name, sizeof(info->name) - 1 ), info->name[sizeof(info->name)-1] = '\0'; else info->name[0] = '\0';
-
- COPY( system );
- COPY( game );
- COPY( song );
- COPY( author );
- COPY( copyright );
- COPY( comment );
- COPY( dumper );
-
-#undef COPY
-
- blargg_err_t err = me->set_track_info( info, track );
-
- delete info;
-
- return err;
-}
-
-void gme_free_info( gme_info_t* info )
-{
- delete STATIC_CAST(gme_info_t_*,info);
-}
-
-void* gme_user_data ( Music_Emu const* gme ) { return gme->user_data(); }
-void gme_set_user_data ( Music_Emu* gme, void* new_user_data ) { gme->set_user_data( new_user_data ); }
-void gme_set_user_cleanup(Music_Emu* gme, gme_user_cleanup_t func ){ gme->set_user_cleanup( func ); }
-
-gme_err_t gme_start_track ( Music_Emu* gme, int index ) { return gme->start_track( index ); }
-gme_err_t gme_play ( Music_Emu* gme, int n, short p [] ) { return gme->play( n, p ); }
-void gme_set_fade ( Music_Emu* gme, int start_msec, int length_msec ) { gme->set_fade( start_msec, length_msec ); }
-gme_bool gme_track_ended ( Music_Emu const* gme ) { return gme->track_ended(); }
-int gme_tell ( Music_Emu const* gme ) { return gme->tell(); }
-gme_err_t gme_seek ( Music_Emu* gme, int msec ) { return gme->seek( msec ); }
-gme_err_t gme_skip ( Music_Emu* gme, int samples ) { return gme->skip( samples ); }
-int gme_voice_count ( Music_Emu const* gme ) { return gme->voice_count(); }
-void gme_ignore_silence ( Music_Emu* gme, gme_bool disable ) { gme->ignore_silence( disable != 0 ); }
-void gme_set_tempo ( Music_Emu* gme, double t ) { gme->set_tempo( t ); }
-void gme_mute_voice ( Music_Emu* gme, int index, gme_bool mute ){ gme->mute_voice( index, mute != 0 ); }
-void gme_mute_voices ( Music_Emu* gme, int mask ) { gme->mute_voices( mask ); }
-void gme_set_equalizer ( Music_Emu* gme, gme_equalizer_t const* eq ) { gme->set_equalizer( *eq ); }
-void gme_equalizer ( Music_Emu const* gme, gme_equalizer_t* o ) { *o = gme->equalizer(); }
-const char* gme_voice_name ( Music_Emu const* gme, int i ) { return gme->voice_name( i ); }
-gme_err_t gme_save ( Music_Emu const* gme, gme_writer_t writer, void* your_data ) { return gme->save( writer, your_data ); }
-
-void gme_effects( Music_Emu const* gme, gme_effects_t* out )
-{
- static gme_effects_t const zero = { 0, 0, 0,0,0,0,0,0, 0, 0, 0,0,0,0,0,0 };
- *out = zero;
-
- #if !GME_DISABLE_EFFECTS
- {
- Simple_Effects_Buffer* b = STATIC_CAST(Simple_Effects_Buffer*,gme->effects_buffer_);
- if ( b )
- {
- out->enabled = b->config().enabled;
- out->echo = b->config().echo;
- out->stereo = b->config().stereo;
- out->surround = b->config().surround;
- }
- }
- #endif
-}
-
-void gme_set_effects( Music_Emu* gme, gme_effects_t const* in )
-{
- #if !GME_DISABLE_EFFECTS
- {
- Simple_Effects_Buffer* b = STATIC_CAST(Simple_Effects_Buffer*,gme->effects_buffer_);
- if ( b )
- {
- b->config().enabled = false;
- if ( in )
- {
- b->config().enabled = in->enabled;
- b->config().echo = in->echo;
- b->config().stereo = in->stereo;
- b->config().surround = in->surround;
- }
- b->apply_config();
- }
- }
- #endif
-}
-
-void gme_set_stereo_depth( Music_Emu* gme, double depth )
-{
- #if !GME_DISABLE_EFFECTS
- {
- if ( gme->effects_buffer_ )
- {
- gme_effects_t cfg;
- gme_effects( gme, &cfg );
- cfg.enabled = (depth > 0.0);
- cfg.echo = depth;
- cfg.stereo = depth;
- cfg.surround = true;
- gme_set_effects( gme, &cfg );
- }
- }
- #endif
-}
-
-#define ENTRY( name ) { blargg_err_##name, gme_err_##name }
-static blargg_err_to_code_t const gme_codes [] =
-{
- ENTRY( generic ),
- ENTRY( memory ),
- ENTRY( caller ),
- ENTRY( internal ),
- ENTRY( limitation ),
-
- ENTRY( file_missing ),
- ENTRY( file_read ),
- ENTRY( file_io ),
- ENTRY( file_eof ),
-
- ENTRY( file_type ),
- ENTRY( file_feature ),
- ENTRY( file_corrupt ),
-
- { 0, -1 }
-};
-#undef ENTRY
-
-static int err_code( gme_err_t err )
-{
- return blargg_err_to_code( err, gme_codes );
-}
-
-int gme_err_code( gme_err_t err )
-{
- int code = err_code( err );
- return (code >= 0 ? code : gme_err_generic);
-}
-
-gme_err_t gme_code_to_err( int code )
-{
- return blargg_code_to_err( code, gme_codes );
-}
-
-const char* gme_err_details( gme_err_t err )
-{
- // If we don't have error code assigned, return entire string
- return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
-}
-
-const char* gme_err_str( gme_err_t err )
-{
- return blargg_err_str( err );
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Music_Emu.h"
+
+#if !GME_DISABLE_EFFECTS
+#include "Effects_Buffer.h"
+#endif
+#include "blargg_endian.h"
+#include
+#include
+
+/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifndef GME_TYPE_LIST
+
+// Default list of all supported game music types (copy this to blargg_config.h
+// if you want to modify it)
+#define GME_TYPE_LIST \
+ gme_ay_type,\
+ gme_gbs_type,\
+ gme_gym_type,\
+ gme_hes_type,\
+ gme_kss_type,\
+ gme_nsf_type,\
+ gme_nsfe_type,\
+ gme_sap_type,\
+ gme_sfm_type,\
+ gme_sgc_type,\
+ gme_spc_type,\
+ gme_vgm_type,\
+ gme_vgz_type
+
+#endif
+
+static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 };
+
+gme_type_t const* gme_type_list()
+{
+ return gme_type_list_;
+}
+
+const char* gme_identify_header( void const* header )
+{
+ switch ( get_be32( header ) )
+ {
+ case BLARGG_4CHAR('Z','X','A','Y'): return "AY";
+ case BLARGG_4CHAR('G','B','S',0x01):
+ case BLARGG_4CHAR('G','B','S',0x02): return "GBS";
+ case BLARGG_4CHAR('G','Y','M','X'): return "GYM";
+ case BLARGG_4CHAR('H','E','S','M'): return "HES";
+ case BLARGG_4CHAR('K','S','C','C'):
+ case BLARGG_4CHAR('K','S','S','X'): return "KSS";
+ case BLARGG_4CHAR('N','E','S','M'): return "NSF";
+ case BLARGG_4CHAR('N','S','F','E'): return "NSFE";
+ case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
+ case BLARGG_4CHAR('S','F','M','1'): return "SFM";
+ case BLARGG_4CHAR('S','G','C',0x1A): return "SGC";
+ case BLARGG_4CHAR('S','N','E','S'): return "SPC";
+ case BLARGG_4CHAR('V','g','m',' '): return "VGM";
+ }
+ return "";
+}
+
+static void to_uppercase( const char in [], int len, char out [] )
+{
+ for ( int i = 0; i < len; i++ )
+ {
+ if ( !(out [i] = toupper( in [i] )) )
+ return;
+ }
+ *out = 0; // extension too long
+}
+
+gme_type_t gme_identify_extension( const char extension_ [] )
+{
+ char const* end = strrchr( extension_, '.' );
+ if ( end )
+ extension_ = end + 1;
+
+ char extension [6];
+ to_uppercase( extension_, sizeof extension, extension );
+
+ gme_type_t const* types = gme_type_list_;
+ for ( ; *types; types++ )
+ if ( !strcmp( extension, (*types)->extension_ ) )
+ break;
+ return *types;
+}
+
+gme_err_t gme_identify_file( const char path [], gme_type_t* type_out )
+{
+ *type_out = gme_identify_extension( path );
+ // TODO: don't examine header if file has extension?
+ if ( !*type_out )
+ {
+ char header [4];
+ GME_FILE_READER in;
+ RETURN_ERR( in.open( path ) );
+ RETURN_ERR( in.read( header, sizeof header ) );
+ *type_out = gme_identify_extension( gme_identify_header( header ) );
+ }
+ return blargg_ok;
+}
+
+gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
+{
+ require( (data || !size) && out );
+ *out = NULL;
+
+ gme_type_t file_type = 0;
+ if ( size >= 4 )
+ file_type = gme_identify_extension( gme_identify_header( data ) );
+ if ( !file_type )
+ return blargg_err_file_type;
+
+ Music_Emu* emu = gme_new_emu( file_type, sample_rate );
+ CHECK_ALLOC( emu );
+
+ gme_err_t err = gme_load_data( emu, data, size );
+
+ if ( err )
+ delete emu;
+ else
+ *out = emu;
+
+ return err;
+}
+
+gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate )
+{
+ require( path && out );
+ *out = NULL;
+
+ GME_FILE_READER in;
+ RETURN_ERR( in.open( path ) );
+
+ char header [4];
+ int header_size = 0;
+
+ gme_type_t file_type = gme_identify_extension( path );
+ if ( !file_type )
+ {
+ header_size = sizeof header;
+ RETURN_ERR( in.read( header, sizeof header ) );
+ file_type = gme_identify_extension( gme_identify_header( header ) );
+ }
+ if ( !file_type )
+ return blargg_err_file_type;
+
+ Music_Emu* emu = gme_new_emu( file_type, sample_rate );
+ CHECK_ALLOC( emu );
+
+ // optimization: avoids seeking/re-reading header
+ Remaining_Reader rem( header, header_size, &in );
+ gme_err_t err = emu->load( rem );
+ in.close();
+
+ if ( err )
+ delete emu;
+ else
+ *out = emu;
+
+ return err;
+}
+
+Music_Emu* gme_new_emu( gme_type_t type, int rate )
+{
+ if ( type )
+ {
+ if ( rate == gme_info_only )
+ return type->new_info();
+
+ Music_Emu* gme = type->new_emu();
+ if ( gme )
+ {
+ #if !GME_DISABLE_EFFECTS
+ if ( type->flags_ & 1 )
+ {
+ gme->effects_buffer_ = BLARGG_NEW Simple_Effects_Buffer;
+ if ( gme->effects_buffer_ )
+ gme->set_buffer( gme->effects_buffer_ );
+ }
+
+ if ( !(type->flags_ & 1) || gme->effects_buffer_ )
+ #endif
+ {
+ if ( !gme->set_sample_rate( rate ) )
+ {
+ check( gme->type() == type );
+ return gme;
+ }
+ }
+ delete gme;
+ }
+ }
+ return NULL;
+}
+
+gme_err_t gme_load_file( Music_Emu* gme, const char path [] ) { return gme->load_file( path ); }
+
+gme_err_t gme_load_data( Music_Emu* gme, void const* data, long size )
+{
+ Mem_File_Reader in( data, size );
+ return gme->load( in );
+}
+
+gme_err_t gme_load_custom( Music_Emu* gme, gme_reader_t func, long size, void* data )
+{
+ Callback_Reader in( func, size, data );
+ return gme->load( in );
+}
+
+void gme_delete( Music_Emu* gme ) { delete gme; }
+
+gme_type_t gme_type( Music_Emu const* gme ) { return gme->type(); }
+
+const char* gme_type_system( gme_type_t_ const* type ) { return type->system; }
+
+const char* gme_warning( Music_Emu* gme ) { return gme->warning(); }
+
+int gme_track_count( Music_Emu const* gme ) { return gme->track_count(); }
+
+struct gme_info_t_ : gme_info_t
+{
+ track_info_t info;
+
+ BLARGG_DISABLE_NOTHROW
+};
+
+gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
+{
+ *out = NULL;
+
+ gme_info_t_* info = BLARGG_NEW gme_info_t_;
+ CHECK_ALLOC( info );
+
+ gme_err_t err = me->track_info( &info->info, track );
+ if ( err )
+ {
+ gme_free_info( info );
+ return err;
+ }
+
+ #define COPY(name) info->name = info->info.name;
+
+ COPY( length );
+ COPY( intro_length );
+ COPY( loop_length );
+
+ info->i4 = -1;
+ info->i5 = -1;
+ info->i6 = -1;
+ info->i7 = -1;
+ info->i8 = -1;
+ info->i9 = -1;
+ info->i10 = -1;
+ info->i11 = -1;
+ info->i12 = -1;
+ info->i13 = -1;
+ info->i14 = -1;
+ info->i15 = -1;
+
+ info->s7 = "";
+ info->s8 = "";
+ info->s9 = "";
+ info->s10 = "";
+ info->s11 = "";
+ info->s12 = "";
+ info->s13 = "";
+ info->s14 = "";
+ info->s15 = "";
+
+ COPY( system );
+ COPY( game );
+ COPY( song );
+ COPY( author );
+ COPY( copyright );
+ COPY( comment );
+ COPY( dumper );
+
+ #undef COPY
+
+ info->play_length = info->length;
+ if ( info->play_length <= 0 )
+ {
+ info->play_length = info->intro_length + 2 * info->loop_length; // intro + 2 loops
+ if ( info->play_length <= 0 )
+ info->play_length = 150 * 1000; // 2.5 minutes
+ }
+
+ *out = info;
+
+ return blargg_ok;
+}
+
+gme_err_t gme_set_track_info( Music_Emu * me, gme_info_t* in, int track )
+{
+ track_info_t* info = BLARGG_NEW track_info_t;
+ CHECK_ALLOC( info );
+
+#define COPY(name) info->name = in->name;
+
+ COPY( length );
+ COPY( intro_length );
+ COPY( loop_length );
+
+#undef COPY
+#define COPY(name) if ( in->name ) strncpy( info->name, in->name, sizeof(info->name) - 1 ), info->name[sizeof(info->name)-1] = '\0'; else info->name[0] = '\0';
+
+ COPY( system );
+ COPY( game );
+ COPY( song );
+ COPY( author );
+ COPY( copyright );
+ COPY( comment );
+ COPY( dumper );
+
+#undef COPY
+
+ blargg_err_t err = me->set_track_info( info, track );
+
+ delete info;
+
+ return err;
+}
+
+void gme_free_info( gme_info_t* info )
+{
+ delete STATIC_CAST(gme_info_t_*,info);
+}
+
+void* gme_user_data ( Music_Emu const* gme ) { return gme->user_data(); }
+void gme_set_user_data ( Music_Emu* gme, void* new_user_data ) { gme->set_user_data( new_user_data ); }
+void gme_set_user_cleanup(Music_Emu* gme, gme_user_cleanup_t func ){ gme->set_user_cleanup( func ); }
+
+gme_err_t gme_start_track ( Music_Emu* gme, int index ) { return gme->start_track( index ); }
+gme_err_t gme_play ( Music_Emu* gme, int n, short p [] ) { return gme->play( n, p ); }
+void gme_set_fade ( Music_Emu* gme, int start_msec, int length_msec ) { gme->set_fade( start_msec, length_msec ); }
+gme_bool gme_track_ended ( Music_Emu const* gme ) { return gme->track_ended(); }
+int gme_tell ( Music_Emu const* gme ) { return gme->tell(); }
+gme_err_t gme_seek ( Music_Emu* gme, int msec ) { return gme->seek( msec ); }
+gme_err_t gme_skip ( Music_Emu* gme, int samples ) { return gme->skip( samples ); }
+int gme_voice_count ( Music_Emu const* gme ) { return gme->voice_count(); }
+void gme_ignore_silence ( Music_Emu* gme, gme_bool disable ) { gme->ignore_silence( disable != 0 ); }
+void gme_set_tempo ( Music_Emu* gme, double t ) { gme->set_tempo( t ); }
+void gme_mute_voice ( Music_Emu* gme, int index, gme_bool mute ){ gme->mute_voice( index, mute != 0 ); }
+void gme_mute_voices ( Music_Emu* gme, int mask ) { gme->mute_voices( mask ); }
+void gme_set_equalizer ( Music_Emu* gme, gme_equalizer_t const* eq ) { gme->set_equalizer( *eq ); }
+void gme_equalizer ( Music_Emu const* gme, gme_equalizer_t* o ) { *o = gme->equalizer(); }
+const char* gme_voice_name ( Music_Emu const* gme, int i ) { return gme->voice_name( i ); }
+gme_err_t gme_save ( Music_Emu const* gme, gme_writer_t writer, void* your_data ) { return gme->save( writer, your_data ); }
+
+void gme_effects( Music_Emu const* gme, gme_effects_t* out )
+{
+ static gme_effects_t const zero = { 0, 0, 0,0,0,0,0,0, 0, 0, 0,0,0,0,0,0 };
+ *out = zero;
+
+ #if !GME_DISABLE_EFFECTS
+ {
+ Simple_Effects_Buffer* b = STATIC_CAST(Simple_Effects_Buffer*,gme->effects_buffer_);
+ if ( b )
+ {
+ out->enabled = b->config().enabled;
+ out->echo = b->config().echo;
+ out->stereo = b->config().stereo;
+ out->surround = b->config().surround;
+ }
+ }
+ #endif
+}
+
+void gme_set_effects( Music_Emu* gme, gme_effects_t const* in )
+{
+ #if !GME_DISABLE_EFFECTS
+ {
+ Simple_Effects_Buffer* b = STATIC_CAST(Simple_Effects_Buffer*,gme->effects_buffer_);
+ if ( b )
+ {
+ b->config().enabled = false;
+ if ( in )
+ {
+ b->config().enabled = in->enabled;
+ b->config().echo = in->echo;
+ b->config().stereo = in->stereo;
+ b->config().surround = in->surround;
+ }
+ b->apply_config();
+ }
+ }
+ #endif
+}
+
+void gme_set_stereo_depth( Music_Emu* gme, double depth )
+{
+ #if !GME_DISABLE_EFFECTS
+ {
+ if ( gme->effects_buffer_ )
+ {
+ gme_effects_t cfg;
+ gme_effects( gme, &cfg );
+ cfg.enabled = (depth > 0.0);
+ cfg.echo = depth;
+ cfg.stereo = depth;
+ cfg.surround = true;
+ gme_set_effects( gme, &cfg );
+ }
+ }
+ #endif
+}
+
+#define ENTRY( name ) { blargg_err_##name, gme_err_##name }
+static blargg_err_to_code_t const gme_codes [] =
+{
+ ENTRY( generic ),
+ ENTRY( memory ),
+ ENTRY( caller ),
+ ENTRY( internal ),
+ ENTRY( limitation ),
+
+ ENTRY( file_missing ),
+ ENTRY( file_read ),
+ ENTRY( file_io ),
+ ENTRY( file_eof ),
+
+ ENTRY( file_type ),
+ ENTRY( file_feature ),
+ ENTRY( file_corrupt ),
+
+ { 0, -1 }
+};
+#undef ENTRY
+
+static int err_code( gme_err_t err )
+{
+ return blargg_err_to_code( err, gme_codes );
+}
+
+int gme_err_code( gme_err_t err )
+{
+ int code = err_code( err );
+ return (code >= 0 ? code : gme_err_generic);
+}
+
+gme_err_t gme_code_to_err( int code )
+{
+ return blargg_code_to_err( code, gme_codes );
+}
+
+const char* gme_err_details( gme_err_t err )
+{
+ // If we don't have error code assigned, return entire string
+ return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
+}
+
+const char* gme_err_str( gme_err_t err )
+{
+ return blargg_err_str( err );
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,4 +1,4 @@
-#include "gme_custom_dprintf.h"
-
-
-gme_custom_dprintf_callback gme_custom_dprintf = 0;
+#include "gme_custom_dprintf.h"
+
+
+gme_custom_dprintf_callback gme_custom_dprintf = 0;
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme_custom_dprintf.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,28 +1,28 @@
-#ifndef GME_CUSTOM_DPRINTF_H
-#define GME_CUSTOM_DPRINTF_H
-
-
-#ifdef CUSTOM_DPRINTF_FUNCTION
-
-
-#include
-
-
-#ifdef _cplusplus
-extern "C" {
-#endif
-
-
-typedef void (*gme_custom_dprintf_callback)( const char * fmt, va_list vl );
-extern gme_custom_dprintf_callback gme_custom_dprintf;
-
-
-#ifdef _cplusplus
-}
-#endif
-
-
-#endif
-
-
-#endif
+#ifndef GME_CUSTOM_DPRINTF_H
+#define GME_CUSTOM_DPRINTF_H
+
+
+#ifdef CUSTOM_DPRINTF_FUNCTION
+
+
+#include
+
+
+#ifdef _cplusplus
+extern "C" {
+#endif
+
+
+typedef void (*gme_custom_dprintf_callback)( const char * fmt, va_list vl );
+extern gme_custom_dprintf_callback gme_custom_dprintf;
+
+
+#ifdef _cplusplus
+}
+#endif
+
+
+#endif
+
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gme_File.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gme_File.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gme_File.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gme_File.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,183 +1,183 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Gme_File.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Gme_File::unload()
-{
- clear_playlist(); // BEFORE clearing track count
- track_count_ = 0;
- raw_track_count_ = 0;
- Gme_Loader::unload();
-}
-
-Gme_File::Gme_File()
-{
- type_ = NULL;
- user_data_ = NULL;
- user_cleanup_ = NULL;
- Gme_File::unload(); // clears fields
-}
-
-Gme_File::~Gme_File()
-{
- if ( user_cleanup_ )
- user_cleanup_( user_data_ );
-}
-
-blargg_err_t Gme_File::post_load()
-{
- if ( !track_count() )
- set_track_count( type()->track_count );
- return Gme_Loader::post_load();
-}
-
-void Gme_File::clear_playlist()
-{
- playlist.clear();
- clear_playlist_();
- track_count_ = raw_track_count_;
-}
-
-void Gme_File::copy_field_( char out [], const char* in, int in_size )
-{
- if ( !in || !*in )
- return;
-
- // remove spaces/junk from beginning
- while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
- {
- in++;
- in_size--;
- }
-
- // truncate
- if ( in_size > max_field_ )
- in_size = max_field_;
-
- // find terminator
- int len = 0;
- while ( len < in_size && in [len] )
- len++;
-
- // remove spaces/junk from end
- while ( len && unsigned (in [len - 1]) <= ' ' )
- len--;
-
- // copy
- out [len] = 0;
- memcpy( out, in, len );
-
- // strip out stupid fields that should have been left blank
- if ( !strcmp( out, "?" ) || !strcmp( out, ">" ) || !strcmp( out, "< ? >" ) )
- out [0] = 0;
-}
-
-void Gme_File::copy_field_( char out [], const char* in )
-{
- copy_field_( out, in, max_field_ );
-}
-
-blargg_err_t Gme_File::remap_track_( int* track_io ) const
-{
- if ( (unsigned) *track_io >= (unsigned) track_count() )
- return BLARGG_ERR( BLARGG_ERR_CALLER, "invalid track" );
-
- if ( (unsigned) *track_io < (unsigned) playlist.size() )
- {
- M3u_Playlist::entry_t const& e = playlist [*track_io];
- *track_io = 0;
- if ( e.track >= 0 )
- {
- *track_io = e.track;
- // TODO: really needs to be removed?
- //if ( !(type_->flags_ & 0x02) )
- // *track_io -= e.decimal_track;
- }
- if ( *track_io >= raw_track_count_ )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "invalid track in m3u playlist" );
- }
- else
- {
- check( !playlist.size() );
- }
- return blargg_ok;
-}
-
-blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
-{
- out->track_count = track_count();
- out->length = -1;
- out->loop_length = -1;
- out->intro_length = -1;
- out->fade_length = -1;
- out->play_length = -1;
- out->repeat_count = -1;
- out->song [0] = 0;
- out->game [0] = 0;
- out->author [0] = 0;
- out->composer [0] = 0;
- out->engineer [0] = 0;
- out->sequencer [0] = 0;
- out->tagger [0] = 0;
- out->copyright [0] = 0;
- out->date [0] = 0;
- out->comment [0] = 0;
- out->dumper [0] = 0;
- out->system [0] = 0;
- out->disc [0] = 0;
- out->track [0] = 0;
- out->ost [0] = 0;
-
- copy_field_( out->system, type()->system );
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- RETURN_ERR( track_info_( out, remapped ) );
-
- // override with m3u info
- if ( playlist.size() )
- {
- M3u_Playlist::info_t const& i = playlist.info();
- copy_field_( out->game , i.title );
- copy_field_( out->author , i.artist );
- copy_field_( out->engineer , i.engineer );
- copy_field_( out->composer , i.composer );
- copy_field_( out->sequencer, i.sequencer );
- copy_field_( out->copyright, i.copyright );
- copy_field_( out->dumper , i.ripping );
- copy_field_( out->tagger , i.tagging );
- copy_field_( out->date , i.date );
-
- M3u_Playlist::entry_t const& e = playlist [track];
- if ( e.length >= 0 ) out->length = e.length;
- if ( e.intro >= 0 ) out->intro_length = e.intro;
- if ( e.loop >= 0 ) out->loop_length = e.loop;
- if ( e.fade >= 0 ) out->fade_length = e.fade;
- if ( e.repeat >= 0 ) out->repeat_count = e.repeat;
- copy_field_( out->song, e.name );
- }
-
- // play_length
- out->play_length = out->length;
- if ( out->play_length <= 0 )
- {
- out->play_length = out->intro_length + 2 * out->loop_length; // intro + 2 loops
- if ( out->play_length <= 0 )
- out->play_length = 150 * 1000; // 2.5 minutes
- }
-
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Gme_File.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Gme_File::unload()
+{
+ clear_playlist(); // BEFORE clearing track count
+ track_count_ = 0;
+ raw_track_count_ = 0;
+ Gme_Loader::unload();
+}
+
+Gme_File::Gme_File()
+{
+ type_ = NULL;
+ user_data_ = NULL;
+ user_cleanup_ = NULL;
+ Gme_File::unload(); // clears fields
+}
+
+Gme_File::~Gme_File()
+{
+ if ( user_cleanup_ )
+ user_cleanup_( user_data_ );
+}
+
+blargg_err_t Gme_File::post_load()
+{
+ if ( !track_count() )
+ set_track_count( type()->track_count );
+ return Gme_Loader::post_load();
+}
+
+void Gme_File::clear_playlist()
+{
+ playlist.clear();
+ clear_playlist_();
+ track_count_ = raw_track_count_;
+}
+
+void Gme_File::copy_field_( char out [], const char* in, int in_size )
+{
+ if ( !in || !*in )
+ return;
+
+ // remove spaces/junk from beginning
+ while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
+ {
+ in++;
+ in_size--;
+ }
+
+ // truncate
+ if ( in_size > max_field_ )
+ in_size = max_field_;
+
+ // find terminator
+ int len = 0;
+ while ( len < in_size && in [len] )
+ len++;
+
+ // remove spaces/junk from end
+ while ( len && unsigned (in [len - 1]) <= ' ' )
+ len--;
+
+ // copy
+ out [len] = 0;
+ memcpy( out, in, len );
+
+ // strip out stupid fields that should have been left blank
+ if ( !strcmp( out, "?" ) || !strcmp( out, ">" ) || !strcmp( out, "< ? >" ) )
+ out [0] = 0;
+}
+
+void Gme_File::copy_field_( char out [], const char* in )
+{
+ copy_field_( out, in, max_field_ );
+}
+
+blargg_err_t Gme_File::remap_track_( int* track_io ) const
+{
+ if ( (unsigned) *track_io >= (unsigned) track_count() )
+ return BLARGG_ERR( BLARGG_ERR_CALLER, "invalid track" );
+
+ if ( (unsigned) *track_io < (unsigned) playlist.size() )
+ {
+ M3u_Playlist::entry_t const& e = playlist [*track_io];
+ *track_io = 0;
+ if ( e.track >= 0 )
+ {
+ *track_io = e.track;
+ // TODO: really needs to be removed?
+ //if ( !(type_->flags_ & 0x02) )
+ // *track_io -= e.decimal_track;
+ }
+ if ( *track_io >= raw_track_count_ )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "invalid track in m3u playlist" );
+ }
+ else
+ {
+ check( !playlist.size() );
+ }
+ return blargg_ok;
+}
+
+blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
+{
+ out->track_count = track_count();
+ out->length = -1;
+ out->loop_length = -1;
+ out->intro_length = -1;
+ out->fade_length = -1;
+ out->play_length = -1;
+ out->repeat_count = -1;
+ out->song [0] = 0;
+ out->game [0] = 0;
+ out->author [0] = 0;
+ out->composer [0] = 0;
+ out->engineer [0] = 0;
+ out->sequencer [0] = 0;
+ out->tagger [0] = 0;
+ out->copyright [0] = 0;
+ out->date [0] = 0;
+ out->comment [0] = 0;
+ out->dumper [0] = 0;
+ out->system [0] = 0;
+ out->disc [0] = 0;
+ out->track [0] = 0;
+ out->ost [0] = 0;
+
+ copy_field_( out->system, type()->system );
+
+ int remapped = track;
+ RETURN_ERR( remap_track_( &remapped ) );
+ RETURN_ERR( track_info_( out, remapped ) );
+
+ // override with m3u info
+ if ( playlist.size() )
+ {
+ M3u_Playlist::info_t const& i = playlist.info();
+ copy_field_( out->game , i.title );
+ copy_field_( out->author , i.artist );
+ copy_field_( out->engineer , i.engineer );
+ copy_field_( out->composer , i.composer );
+ copy_field_( out->sequencer, i.sequencer );
+ copy_field_( out->copyright, i.copyright );
+ copy_field_( out->dumper , i.ripping );
+ copy_field_( out->tagger , i.tagging );
+ copy_field_( out->date , i.date );
+
+ M3u_Playlist::entry_t const& e = playlist [track];
+ if ( e.length >= 0 ) out->length = e.length;
+ if ( e.intro >= 0 ) out->intro_length = e.intro;
+ if ( e.loop >= 0 ) out->loop_length = e.loop;
+ if ( e.fade >= 0 ) out->fade_length = e.fade;
+ if ( e.repeat >= 0 ) out->repeat_count = e.repeat;
+ copy_field_( out->song, e.name );
+ }
+
+ // play_length
+ out->play_length = out->length;
+ if ( out->play_length <= 0 )
+ {
+ out->play_length = out->intro_length + 2 * out->loop_length; // intro + 2 loops
+ if ( out->play_length <= 0 )
+ out->play_length = 150 * 1000; // 2.5 minutes
+ }
+
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gme_File.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gme_File.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gme_File.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gme_File.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,153 +1,153 @@
-// Common interface for track information
-
-// Game_Music_Emu $vers
-#ifndef GME_FILE_H
-#define GME_FILE_H
-
-#include "gme.h"
-#include "Gme_Loader.h"
-#include "M3u_Playlist.h"
-
-struct track_info_t
-{
- int track_count;
-
- /* times in milliseconds; -1 if unknown */
- int length; /* total length, if file specifies it */
- int intro_length; /* length of song up to looping section */
- int loop_length; /* length of looping section */
- int fade_length;
- int repeat_count;
-
- /* Length if available, otherwise intro_length+loop_length*2 if available,
- otherwise a default of 150000 (2.5 minutes). */
- int play_length;
-
- /* empty string if not available */
- char system [256];
- char game [256];
- char song [256];
- char author [256];
- char composer [256];
- char engineer [256];
- char sequencer [256];
- char tagger [256];
- char copyright [256];
- char date [256];
- char comment [256];
- char dumper [256];
- char disc [256];
- char track [256];
- char ost [256];
-};
-enum { gme_max_field = 255 };
-
-class Gme_File : public Gme_Loader {
-public:
- // Type of emulator. For example if this returns gme_nsfe_type, this object
- // is an NSFE emulator, and you can downcast to an Nsfe_Emu* if necessary.
- gme_type_t type() const;
-
- // Loads an m3u playlist. Must be done AFTER loading main music file.
- blargg_err_t load_m3u( const char path [] );
- blargg_err_t load_m3u( Data_Reader& in );
-
- // Clears any loaded m3u playlist and any internal playlist that the music
- // format supports (NSFE for example).
- void clear_playlist();
-
- // Number of tracks or 0 if no file has been loaded
- int track_count() const;
-
- // Gets information for a track (length, name, author, etc.)
- // See gme.h for definition of struct track_info_t.
- blargg_err_t track_info( track_info_t* out, int track ) const;
-
-// User data/cleanup
-
- // Sets/gets pointer to data you want to associate with this emulator.
- // You can use this for whatever you want.
- void set_user_data( void* p ) { user_data_ = p; }
- void* user_data() const { return user_data_; }
-
- // Registers cleanup function to be called when deleting emulator, or NULL to
- // clear it. Passes user_data to cleanup function.
- void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
-
-public:
- Gme_File();
- ~Gme_File();
-
-protected:
- // Services
- void set_type( gme_type_t t ) { type_ = t; }
- void set_track_count( int n ) { track_count_ = raw_track_count_ = n; }
-
- // Must be overridden
- virtual blargg_err_t track_info_( track_info_t* out, int track ) const BLARGG_PURE( ; )
-
- // Optionally overridden
- virtual void clear_playlist_() { }
-
-protected: // Gme_Loader overrides
- virtual void unload();
- virtual blargg_err_t post_load();
-
-protected:
- blargg_err_t remap_track_( int* track_io ) const; // need by Music_Emu
-private:
- gme_type_t type_;
- void* user_data_;
- gme_user_cleanup_t user_cleanup_;
- int track_count_;
- int raw_track_count_;
- M3u_Playlist playlist;
- char playlist_warning [64];
-
- blargg_err_t load_m3u_( blargg_err_t );
-
-public:
- // track_info field copying
- enum { max_field_ = 255 };
- static void copy_field_( char out [], const char* in );
- static void copy_field_( char out [], const char* in, int len );
-};
-
-struct gme_type_t_
-{
- const char* system; /* name of system this music file type is generally for */
- int track_count; /* non-zero for formats with a fixed number of tracks */
- Music_Emu* (*new_emu)(); /* Create new emulator for this type (C++ only) */
- Music_Emu* (*new_info)();/* Create new info reader for this type (C++ only) */
-
- /* internal */
- const char* extension_;
- int flags_;
-};
-
-/* Emulator type constants for each supported file type */
-extern const gme_type_t_
- gme_ay_type [1],
- gme_gbs_type [1],
- gme_gym_type [1],
- gme_hes_type [1],
- gme_kss_type [1],
- gme_nsf_type [1],
- gme_nsfe_type [1],
- gme_sap_type [1],
- gme_sfm_type [1],
- gme_sgc_type [1],
- gme_spc_type [1],
- gme_vgm_type [1],
- gme_vgz_type [1];
-
-#define GME_COPY_FIELD( in, out, name ) \
- { Gme_File::copy_field_( out->name, in.name, sizeof in.name ); }
-
-inline gme_type_t Gme_File::type() const { return type_; }
-
-inline int Gme_File::track_count() const { return track_count_; }
-
-inline blargg_err_t Gme_File::track_info_( track_info_t*, int ) const { return blargg_ok; }
-
-#endif
+// Common interface for track information
+
+// Game_Music_Emu $vers
+#ifndef GME_FILE_H
+#define GME_FILE_H
+
+#include "gme.h"
+#include "Gme_Loader.h"
+#include "M3u_Playlist.h"
+
+struct track_info_t
+{
+ int track_count;
+
+ /* times in milliseconds; -1 if unknown */
+ int length; /* total length, if file specifies it */
+ int intro_length; /* length of song up to looping section */
+ int loop_length; /* length of looping section */
+ int fade_length;
+ int repeat_count;
+
+ /* Length if available, otherwise intro_length+loop_length*2 if available,
+ otherwise a default of 150000 (2.5 minutes). */
+ int play_length;
+
+ /* empty string if not available */
+ char system [256];
+ char game [256];
+ char song [256];
+ char author [256];
+ char composer [256];
+ char engineer [256];
+ char sequencer [256];
+ char tagger [256];
+ char copyright [256];
+ char date [256];
+ char comment [256];
+ char dumper [256];
+ char disc [256];
+ char track [256];
+ char ost [256];
+};
+enum { gme_max_field = 255 };
+
+class Gme_File : public Gme_Loader {
+public:
+ // Type of emulator. For example if this returns gme_nsfe_type, this object
+ // is an NSFE emulator, and you can downcast to an Nsfe_Emu* if necessary.
+ gme_type_t type() const;
+
+ // Loads an m3u playlist. Must be done AFTER loading main music file.
+ blargg_err_t load_m3u( const char path [] );
+ blargg_err_t load_m3u( Data_Reader& in );
+
+ // Clears any loaded m3u playlist and any internal playlist that the music
+ // format supports (NSFE for example).
+ void clear_playlist();
+
+ // Number of tracks or 0 if no file has been loaded
+ int track_count() const;
+
+ // Gets information for a track (length, name, author, etc.)
+ // See gme.h for definition of struct track_info_t.
+ blargg_err_t track_info( track_info_t* out, int track ) const;
+
+// User data/cleanup
+
+ // Sets/gets pointer to data you want to associate with this emulator.
+ // You can use this for whatever you want.
+ void set_user_data( void* p ) { user_data_ = p; }
+ void* user_data() const { return user_data_; }
+
+ // Registers cleanup function to be called when deleting emulator, or NULL to
+ // clear it. Passes user_data to cleanup function.
+ void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
+
+public:
+ Gme_File();
+ ~Gme_File();
+
+protected:
+ // Services
+ void set_type( gme_type_t t ) { type_ = t; }
+ void set_track_count( int n ) { track_count_ = raw_track_count_ = n; }
+
+ // Must be overridden
+ virtual blargg_err_t track_info_( track_info_t* out, int track ) const BLARGG_PURE( ; )
+
+ // Optionally overridden
+ virtual void clear_playlist_() { }
+
+protected: // Gme_Loader overrides
+ virtual void unload();
+ virtual blargg_err_t post_load();
+
+protected:
+ blargg_err_t remap_track_( int* track_io ) const; // need by Music_Emu
+private:
+ gme_type_t type_;
+ void* user_data_;
+ gme_user_cleanup_t user_cleanup_;
+ int track_count_;
+ int raw_track_count_;
+ M3u_Playlist playlist;
+ char playlist_warning [64];
+
+ blargg_err_t load_m3u_( blargg_err_t );
+
+public:
+ // track_info field copying
+ enum { max_field_ = 255 };
+ static void copy_field_( char out [], const char* in );
+ static void copy_field_( char out [], const char* in, int len );
+};
+
+struct gme_type_t_
+{
+ const char* system; /* name of system this music file type is generally for */
+ int track_count; /* non-zero for formats with a fixed number of tracks */
+ Music_Emu* (*new_emu)(); /* Create new emulator for this type (C++ only) */
+ Music_Emu* (*new_info)();/* Create new info reader for this type (C++ only) */
+
+ /* internal */
+ const char* extension_;
+ int flags_;
+};
+
+/* Emulator type constants for each supported file type */
+extern const gme_type_t_
+ gme_ay_type [1],
+ gme_gbs_type [1],
+ gme_gym_type [1],
+ gme_hes_type [1],
+ gme_kss_type [1],
+ gme_nsf_type [1],
+ gme_nsfe_type [1],
+ gme_sap_type [1],
+ gme_sfm_type [1],
+ gme_sgc_type [1],
+ gme_spc_type [1],
+ gme_vgm_type [1],
+ gme_vgz_type [1];
+
+#define GME_COPY_FIELD( in, out, name ) \
+ { Gme_File::copy_field_( out->name, in.name, sizeof in.name ); }
+
+inline gme_type_t Gme_File::type() const { return type_; }
+
+inline int Gme_File::track_count() const { return track_count_; }
+
+inline blargg_err_t Gme_File::track_info_( track_info_t*, int ) const { return blargg_ok; }
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,307 +1,307 @@
-/* Loads and plays video game music files into sample buffer */
-
-/* Game_Music_Emu $vers */
-#ifndef GME_H
-#define GME_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/* Pointer to error, or NULL if function was successful. See Errors below. */
-#ifndef gme_err_t /* (#ifndef allows better testing of library) */
- typedef const char* gme_err_t;
-#endif
-
-/* First parameter of most functions is gme_t*, or const gme_t* if nothing is
-changed. */
-typedef struct gme_t gme_t;
-
-/* Boolean; false = 0, true = 1 */
-typedef int gme_bool;
-
-
-/******** Basic operations ********/
-
-/* Opens game music file and points *out at it. If error, sets *out to NULL. */
-gme_err_t gme_open_file( const char path [], gme_t** out, int sample_rate );
-
-/* Number of tracks */
-int gme_track_count( const gme_t* );
-
-/* Starts a track, where 0 is the first track. Requires that 0 <= index < gme_track_count(). */
-gme_err_t gme_start_track( gme_t*, int index );
-
-/* Generates 'count' 16-bit signed samples info 'out'. Output is in stereo, so count
-must be even. */
-gme_err_t gme_play( gme_t*, int count, short out [] );
-
-/* Closes file and frees memory. OK to pass NULL. */
-void gme_delete( gme_t* );
-
-
-/******** Track position/length ********/
-
-/* Sets time to start fading track out. Once fade ends track_ended() returns true.
-Fade time can be changed while track is playing. */
-void gme_set_fade( gme_t*, int start_msec, int length_msec );
-
-/* True if a track has reached its end */
-gme_bool gme_track_ended( const gme_t* );
-
-/* Number of milliseconds played since beginning of track (1000 = one second) */
-int gme_tell( const gme_t* );
-
-/* Seeks to new time in track. Seeking backwards or far forward can take a while. */
-gme_err_t gme_seek( gme_t*, int msec );
-
-/* Skips the specified number of samples. */
-gme_err_t gme_skip( gme_t*, int samples );
-
-
-/******** Informational ********/
-
-/* Use in place of sample rate for open/load if you only need to get track
-information from a music file */
-enum { gme_info_only = -1 };
-
-/* Most recent warning string, or NULL if none. Clears current warning after returning.
-Warning is also cleared when loading a file and starting a track. */
-const char* gme_warning( gme_t* );
-
-/* Loads m3u playlist file (must be done after loading music) */
-gme_err_t gme_load_m3u( gme_t*, const char path [] );
-
-/* Clears any loaded m3u playlist and any internal playlist that the music format
-supports (NSFE for example). */
-void gme_clear_playlist( gme_t* );
-
-/* Passes back pointer to information for a particular track (length, name, author, etc.).
-Must be freed after use. */
-typedef struct gme_info_t gme_info_t;
-gme_err_t gme_track_info( const gme_t*, gme_info_t** out, int track );
-
-gme_err_t gme_set_track_info( gme_t*, const gme_info_t* in, int track );
-
-/* Frees track information */
-void gme_free_info( gme_info_t* );
-
-struct gme_info_t
-{
- /* times in milliseconds; -1 if unknown */
- int length; /* total length, if file specifies it */
- int intro_length; /* length of song up to looping section */
- int loop_length; /* length of looping section */
-
- /* Length if available, otherwise intro_length+loop_length*2 if available,
- otherwise a default of 150000 (2.5 minutes). */
- int play_length;
-
- int i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */
-
- /* empty string ("") if not available */
- const char* system;
- const char* game;
- const char* song;
- const char* author;
- const char* copyright;
- const char* comment;
- const char* dumper;
-
- const char *s7,*s8,*s9,*s10,*s11,*s12,*s13,*s14,*s15; /* reserved */
-};
-
-
-/******** Advanced playback ********/
-
-/* Disables automatic end-of-track detection and skipping of silence at beginning
-if ignore is true */
-void gme_ignore_silence( gme_t*, gme_bool ignore );
-
-/* Adjusts song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed, etc.
-Track length as returned by track_info() ignores tempo (assumes it's 1.0). */
-void gme_set_tempo( gme_t*, double tempo );
-
-/* Number of voices used by currently loaded file */
-int gme_voice_count( const gme_t* );
-
-/* Name of voice i, from 0 to gme_voice_count() - 1 */
-const char* gme_voice_name( const gme_t*, int i );
-
-/* Mutes/unmutes single voice i, where voice 0 is first voice */
-void gme_mute_voice( gme_t*, int index, gme_bool mute );
-
-/* Sets muting state of ALL voices at once using a bit mask, where -1 mutes all
-voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
-void gme_mute_voices( gme_t*, int muting_mask );
-
-/* Frequency equalizer parameters (see gme.txt) */
-typedef struct gme_equalizer_t
-{
- double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
- double bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */
-
- double d2,d3,d4,d5,d6,d7,d8,d9; /* reserved */
-} gme_equalizer_t;
-
-/* Gets current frequency equalizer parameters */
-void gme_equalizer( const gme_t*, gme_equalizer_t* out );
-
-/* Changes frequency equalizer parameters */
-void gme_set_equalizer( gme_t*, gme_equalizer_t const* eq );
-
-
-
-/******** Effects processor ********/
-
-/* Adds stereo surround and echo to music that's usually mono or has little
-stereo. Has no effect on GYM, SPC, and Sega Genesis VGM music. */
-
-/* Simplified control using a single value, where 0.0 = off and 1.0 = maximum */
-void gme_set_stereo_depth( gme_t*, double depth );
-
-struct gme_effects_t
-{
- double echo; /* Amount of echo, where 0.0 = none, 1.0 = lots */
- double stereo; /* Separation, where 0.0 = mono, 1.0 = hard left and right */
-
- double d2,d3,d4,d5,d6,d7; /* reserved */
-
- gme_bool enabled; /* If 0, no effects are added */
- gme_bool surround;/* If 1, some channels are put in "back", using phase inversion */
-
- int i1,i3,i4,i5,i6,i7; /* reserved */
-};
-typedef struct gme_effects_t gme_effects_t;
-
-/* Sets effects configuration, or disables effects if NULL */
-void gme_set_effects( gme_t*, gme_effects_t const* );
-
-/* Passes back current effects configuration */
-void gme_effects( const gme_t*, gme_effects_t* out );
-
-
-/******** Game music types ********/
-
-/* Music file type identifier. Can also hold NULL. */
-typedef const struct gme_type_t_* gme_type_t;
-
-/* Type of this emulator */
-gme_type_t gme_type( const gme_t* );
-
-/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
-to this library to support new music types without having to be updated. */
-gme_type_t const* gme_type_list();
-
-/* Name of game system for this music file type */
-const char* gme_type_system( gme_type_t );
-
-/* True if this music file type supports multiple tracks */
-gme_bool gme_type_multitrack( gme_type_t );
-
-
-/******** Advanced file loading ********/
-
-/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
-gme_err_t gme_open_data( void const* data, long size, gme_t** emu_out, int sample_rate );
-
-/* Determines likely game music type based on first four bytes of file. Returns
-string containing proper file suffix ("NSF", "SPC", etc.) or "" if file header
-is not recognized. */
-const char* gme_identify_header( void const* header );
-
-/* Gets corresponding music type for file path or extension passed in. */
-gme_type_t gme_identify_extension( const char path_or_extension [] );
-
-/* Determines file type based on file's extension or header (if extension isn't recognized).
-Sets *type_out to type, or 0 if unrecognized or error. */
-gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
-
-/* Creates new emulator and sets sample rate. Returns NULL if out of memory. If you only need
-track information, pass gme_info_only for sample_rate. */
-gme_t* gme_new_emu( gme_type_t, int sample_rate );
-
-/* Loads music file into emulator */
-gme_err_t gme_load_file( gme_t*, const char path [] );
-
-/* Loads music file from memory into emulator. Makes a copy of data passed. */
-gme_err_t gme_load_data( gme_t*, void const* data, long size );
-
-/* Loads music file using custom data reader function that will be called to
-read file data. Most emulators load the entire file in one read call. */
-typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );
-gme_err_t gme_load_custom( gme_t*, gme_reader_t, long file_size, void* your_data );
-
-/* Loads m3u playlist file from memory (must be done after loading music) */
-gme_err_t gme_load_m3u_data( gme_t*, void const* data, long size );
-
-
-/******** Saving ********/
-typedef gme_err_t (*gme_writer_t)( void* your_data, void const* in, long count );
-gme_err_t gme_save( gme_t const*, gme_writer_t, void* your_data );
-
-/******** User data ********/
-
-/* Sets/gets pointer to data you want to associate with this emulator.
-You can use this for whatever you want. */
-void gme_set_user_data( gme_t*, void* new_user_data );
-void* gme_user_data( const gme_t* );
-
-/* Registers cleanup function to be called when deleting emulator, or NULL to
-clear it. Passes user_data when calling cleanup function. */
-typedef void (*gme_user_cleanup_t)( void* user_data );
-void gme_set_user_cleanup( gme_t*, gme_user_cleanup_t func );
-
-
-/******** Errors ********/
-
-/* Internally, a gme_err_t is a const char* that points to a normal C string.
-This means that other strings can be passed to the following functions. In the
-descriptions below, these other strings are referred to as being not gme_err_t
-strings. */
-
-/* Error string associated with err. Returns "" if err is NULL. Returns err
-unchanged if it isn't a gme_err_t string. */
-const char* gme_err_str( gme_err_t err );
-
-/* Details of error beyond main cause, or "" if none or err is NULL. Returns
-err unchanged if it isn't a gme_err_t string. */
-const char* gme_err_details( gme_err_t err );
-
-/* Numeric code corresponding to err. Returns gme_ok if err is NULL. Returns
-gme_err_generic if err isn't a gme_err_t string. */
-int gme_err_code( gme_err_t err );
-
-enum {
- gme_ok = 0,/* Successful call. Guaranteed to be zero. */
- gme_err_generic = 0x01,/* Error of unspecified type */
- gme_err_memory = 0x02,/* Out of memory */
- gme_err_caller = 0x03,/* Caller violated requirements of function */
- gme_err_internal = 0x04,/* Internal problem, corruption, etc. */
- gme_err_limitation = 0x05,/* Exceeded program limit */
-
- gme_err_file_missing = 0x20,/* File not found at specified path */
- gme_err_file_read = 0x21,/* Couldn't open file for reading */
- gme_err_file_io = 0x23,/* Read/write error */
- gme_err_file_eof = 0x25,/* Tried to read past end of file */
-
- gme_err_file_type = 0x30,/* File is of wrong type */
- gme_err_file_feature = 0x32,/* File requires unsupported feature */
- gme_err_file_corrupt = 0x33 /* File is corrupt */
-};
-
-/* gme_err_t corresponding to numeric code. Note that this might not recover
-the original gme_err_t before it was converted to a numeric code; in
-particular, gme_err_details(gme_code_to_err(code)) will be "" in most cases. */
-gme_err_t gme_code_to_err( int code );
-
-
-
-/* Deprecated */
-typedef gme_t Music_Emu;
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
+/* Loads and plays video game music files into sample buffer */
+
+/* Game_Music_Emu $vers */
+#ifndef GME_H
+#define GME_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Pointer to error, or NULL if function was successful. See Errors below. */
+#ifndef gme_err_t /* (#ifndef allows better testing of library) */
+ typedef const char* gme_err_t;
+#endif
+
+/* First parameter of most functions is gme_t*, or const gme_t* if nothing is
+changed. */
+typedef struct gme_t gme_t;
+
+/* Boolean; false = 0, true = 1 */
+typedef int gme_bool;
+
+
+/******** Basic operations ********/
+
+/* Opens game music file and points *out at it. If error, sets *out to NULL. */
+gme_err_t gme_open_file( const char path [], gme_t** out, int sample_rate );
+
+/* Number of tracks */
+int gme_track_count( const gme_t* );
+
+/* Starts a track, where 0 is the first track. Requires that 0 <= index < gme_track_count(). */
+gme_err_t gme_start_track( gme_t*, int index );
+
+/* Generates 'count' 16-bit signed samples info 'out'. Output is in stereo, so count
+must be even. */
+gme_err_t gme_play( gme_t*, int count, short out [] );
+
+/* Closes file and frees memory. OK to pass NULL. */
+void gme_delete( gme_t* );
+
+
+/******** Track position/length ********/
+
+/* Sets time to start fading track out. Once fade ends track_ended() returns true.
+Fade time can be changed while track is playing. */
+void gme_set_fade( gme_t*, int start_msec, int length_msec );
+
+/* True if a track has reached its end */
+gme_bool gme_track_ended( const gme_t* );
+
+/* Number of milliseconds played since beginning of track (1000 = one second) */
+int gme_tell( const gme_t* );
+
+/* Seeks to new time in track. Seeking backwards or far forward can take a while. */
+gme_err_t gme_seek( gme_t*, int msec );
+
+/* Skips the specified number of samples. */
+gme_err_t gme_skip( gme_t*, int samples );
+
+
+/******** Informational ********/
+
+/* Use in place of sample rate for open/load if you only need to get track
+information from a music file */
+enum { gme_info_only = -1 };
+
+/* Most recent warning string, or NULL if none. Clears current warning after returning.
+Warning is also cleared when loading a file and starting a track. */
+const char* gme_warning( gme_t* );
+
+/* Loads m3u playlist file (must be done after loading music) */
+gme_err_t gme_load_m3u( gme_t*, const char path [] );
+
+/* Clears any loaded m3u playlist and any internal playlist that the music format
+supports (NSFE for example). */
+void gme_clear_playlist( gme_t* );
+
+/* Passes back pointer to information for a particular track (length, name, author, etc.).
+Must be freed after use. */
+typedef struct gme_info_t gme_info_t;
+gme_err_t gme_track_info( const gme_t*, gme_info_t** out, int track );
+
+gme_err_t gme_set_track_info( gme_t*, const gme_info_t* in, int track );
+
+/* Frees track information */
+void gme_free_info( gme_info_t* );
+
+struct gme_info_t
+{
+ /* times in milliseconds; -1 if unknown */
+ int length; /* total length, if file specifies it */
+ int intro_length; /* length of song up to looping section */
+ int loop_length; /* length of looping section */
+
+ /* Length if available, otherwise intro_length+loop_length*2 if available,
+ otherwise a default of 150000 (2.5 minutes). */
+ int play_length;
+
+ int i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */
+
+ /* empty string ("") if not available */
+ const char* system;
+ const char* game;
+ const char* song;
+ const char* author;
+ const char* copyright;
+ const char* comment;
+ const char* dumper;
+
+ const char *s7,*s8,*s9,*s10,*s11,*s12,*s13,*s14,*s15; /* reserved */
+};
+
+
+/******** Advanced playback ********/
+
+/* Disables automatic end-of-track detection and skipping of silence at beginning
+if ignore is true */
+void gme_ignore_silence( gme_t*, gme_bool ignore );
+
+/* Adjusts song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed, etc.
+Track length as returned by track_info() ignores tempo (assumes it's 1.0). */
+void gme_set_tempo( gme_t*, double tempo );
+
+/* Number of voices used by currently loaded file */
+int gme_voice_count( const gme_t* );
+
+/* Name of voice i, from 0 to gme_voice_count() - 1 */
+const char* gme_voice_name( const gme_t*, int i );
+
+/* Mutes/unmutes single voice i, where voice 0 is first voice */
+void gme_mute_voice( gme_t*, int index, gme_bool mute );
+
+/* Sets muting state of ALL voices at once using a bit mask, where -1 mutes all
+voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
+void gme_mute_voices( gme_t*, int muting_mask );
+
+/* Frequency equalizer parameters (see gme.txt) */
+typedef struct gme_equalizer_t
+{
+ double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
+ double bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */
+
+ double d2,d3,d4,d5,d6,d7,d8,d9; /* reserved */
+} gme_equalizer_t;
+
+/* Gets current frequency equalizer parameters */
+void gme_equalizer( const gme_t*, gme_equalizer_t* out );
+
+/* Changes frequency equalizer parameters */
+void gme_set_equalizer( gme_t*, gme_equalizer_t const* eq );
+
+
+
+/******** Effects processor ********/
+
+/* Adds stereo surround and echo to music that's usually mono or has little
+stereo. Has no effect on GYM, SPC, and Sega Genesis VGM music. */
+
+/* Simplified control using a single value, where 0.0 = off and 1.0 = maximum */
+void gme_set_stereo_depth( gme_t*, double depth );
+
+struct gme_effects_t
+{
+ double echo; /* Amount of echo, where 0.0 = none, 1.0 = lots */
+ double stereo; /* Separation, where 0.0 = mono, 1.0 = hard left and right */
+
+ double d2,d3,d4,d5,d6,d7; /* reserved */
+
+ gme_bool enabled; /* If 0, no effects are added */
+ gme_bool surround;/* If 1, some channels are put in "back", using phase inversion */
+
+ int i1,i3,i4,i5,i6,i7; /* reserved */
+};
+typedef struct gme_effects_t gme_effects_t;
+
+/* Sets effects configuration, or disables effects if NULL */
+void gme_set_effects( gme_t*, gme_effects_t const* );
+
+/* Passes back current effects configuration */
+void gme_effects( const gme_t*, gme_effects_t* out );
+
+
+/******** Game music types ********/
+
+/* Music file type identifier. Can also hold NULL. */
+typedef const struct gme_type_t_* gme_type_t;
+
+/* Type of this emulator */
+gme_type_t gme_type( const gme_t* );
+
+/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
+to this library to support new music types without having to be updated. */
+gme_type_t const* gme_type_list();
+
+/* Name of game system for this music file type */
+const char* gme_type_system( gme_type_t );
+
+/* True if this music file type supports multiple tracks */
+gme_bool gme_type_multitrack( gme_type_t );
+
+
+/******** Advanced file loading ********/
+
+/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
+gme_err_t gme_open_data( void const* data, long size, gme_t** emu_out, int sample_rate );
+
+/* Determines likely game music type based on first four bytes of file. Returns
+string containing proper file suffix ("NSF", "SPC", etc.) or "" if file header
+is not recognized. */
+const char* gme_identify_header( void const* header );
+
+/* Gets corresponding music type for file path or extension passed in. */
+gme_type_t gme_identify_extension( const char path_or_extension [] );
+
+/* Determines file type based on file's extension or header (if extension isn't recognized).
+Sets *type_out to type, or 0 if unrecognized or error. */
+gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
+
+/* Creates new emulator and sets sample rate. Returns NULL if out of memory. If you only need
+track information, pass gme_info_only for sample_rate. */
+gme_t* gme_new_emu( gme_type_t, int sample_rate );
+
+/* Loads music file into emulator */
+gme_err_t gme_load_file( gme_t*, const char path [] );
+
+/* Loads music file from memory into emulator. Makes a copy of data passed. */
+gme_err_t gme_load_data( gme_t*, void const* data, long size );
+
+/* Loads music file using custom data reader function that will be called to
+read file data. Most emulators load the entire file in one read call. */
+typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );
+gme_err_t gme_load_custom( gme_t*, gme_reader_t, long file_size, void* your_data );
+
+/* Loads m3u playlist file from memory (must be done after loading music) */
+gme_err_t gme_load_m3u_data( gme_t*, void const* data, long size );
+
+
+/******** Saving ********/
+typedef gme_err_t (*gme_writer_t)( void* your_data, void const* in, long count );
+gme_err_t gme_save( gme_t const*, gme_writer_t, void* your_data );
+
+/******** User data ********/
+
+/* Sets/gets pointer to data you want to associate with this emulator.
+You can use this for whatever you want. */
+void gme_set_user_data( gme_t*, void* new_user_data );
+void* gme_user_data( const gme_t* );
+
+/* Registers cleanup function to be called when deleting emulator, or NULL to
+clear it. Passes user_data when calling cleanup function. */
+typedef void (*gme_user_cleanup_t)( void* user_data );
+void gme_set_user_cleanup( gme_t*, gme_user_cleanup_t func );
+
+
+/******** Errors ********/
+
+/* Internally, a gme_err_t is a const char* that points to a normal C string.
+This means that other strings can be passed to the following functions. In the
+descriptions below, these other strings are referred to as being not gme_err_t
+strings. */
+
+/* Error string associated with err. Returns "" if err is NULL. Returns err
+unchanged if it isn't a gme_err_t string. */
+const char* gme_err_str( gme_err_t err );
+
+/* Details of error beyond main cause, or "" if none or err is NULL. Returns
+err unchanged if it isn't a gme_err_t string. */
+const char* gme_err_details( gme_err_t err );
+
+/* Numeric code corresponding to err. Returns gme_ok if err is NULL. Returns
+gme_err_generic if err isn't a gme_err_t string. */
+int gme_err_code( gme_err_t err );
+
+enum {
+ gme_ok = 0,/* Successful call. Guaranteed to be zero. */
+ gme_err_generic = 0x01,/* Error of unspecified type */
+ gme_err_memory = 0x02,/* Out of memory */
+ gme_err_caller = 0x03,/* Caller violated requirements of function */
+ gme_err_internal = 0x04,/* Internal problem, corruption, etc. */
+ gme_err_limitation = 0x05,/* Exceeded program limit */
+
+ gme_err_file_missing = 0x20,/* File not found at specified path */
+ gme_err_file_read = 0x21,/* Couldn't open file for reading */
+ gme_err_file_io = 0x23,/* Read/write error */
+ gme_err_file_eof = 0x25,/* Tried to read past end of file */
+
+ gme_err_file_type = 0x30,/* File is of wrong type */
+ gme_err_file_feature = 0x32,/* File requires unsupported feature */
+ gme_err_file_corrupt = 0x33 /* File is corrupt */
+};
+
+/* gme_err_t corresponding to numeric code. Note that this might not recover
+the original gme_err_t before it was converted to a numeric code; in
+particular, gme_err_details(gme_code_to_err(code)) will be "" in most cases. */
+gme_err_t gme_code_to_err( int code );
+
+
+
+/* Deprecated */
+typedef gme_t Music_Emu;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.txt kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.txt
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/gme.txt 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/gme.txt 2013-05-31 22:59:22.000000000 +0000
@@ -1,468 +1,468 @@
-Game_Music_Emu 0.6.0 Pre-release
---------------------
-Author : Shay Green
-Author : Chris Moeller
-Website: http://www.slack.net/~ant/libs/
-Website: http://bitbucket.com/kode54/Game_Music_Emu
-Forum : http://groups.google.com/group/blargg-sound-libs
-License: GNU Lesser General Public License (LGPL)
-
-NOTE: This file has not been fully updated yet!
-
-Contents
---------
-* Overview
-* C and C++ interfaces
-* Function reference
-* Error handling
-* Emulator types
-* M3U playlist support
-* Information fields
-* Track length
-* Loading file data
-* Sound parameters
-* VGM/GYM YM2413 & YM2612 FM sound
-* Modular construction
-* Obscure features
-* Solving problems
-* Deprecated features
-* Thanks
-
-
-Overview
---------
-This library can open game music files, play tracks, and read game and
-track information tags. To play a game music file, do the following:
-
-* Open the file with gme_open_file()
-* Start a track with gme_start_track();
-* Generate samples as needed with gme_play()
-* Play samples through speaker using your operating system
-* Delete emulator when done with gme_delete()
-
-Your code must arrange for the generated samples to be played through
-the computer's speaker using whatever method your operating system
-requires.
-
-There are many additional features available; you can:
-
-* Determine of the type of a music file without opening it with
-gme_identify_*()
-* Load just the file's information tags with gme_info_only
-* Load from a block of memory rather than a file with gme_load_data()
-* Arrange for a fade-out at a particular time with gme_set_fade
-* Find when a track has ended with gme_track_ended()
-* Seek to a new time in the track with gme_seek()
-* Load an extended m3u playlist with gme_load_m3u()
-* Get a list of the voices (channels) and mute them individually with
-gme_voice_names() and gme_mute_voice()
-* Change the playback tempo without affecting pitch with gme_set_tempo()
-* Adjust treble/bass equalization with gme_set_equalizer()
-* Associate your own data with an emulator and later get it back with
-gme_set_user_data()
-* Register a function of yours to be called back when the emulator is
-deleted with gme_set_user_cleanup()
-
-Refer to gme.h for a comprehensive summary of features.
-
-
-C and C++ interfaces
---------------------
-While the library is written in C++, an extensive C interface is
-provided in gme.h. This C interface will be referred to throughout this
-documentation unless a feature is only available in the full C++
-interface. All C interface functions and other names have the gme_
-prefix, so you can recognize a C++-only feature by the lack of gme_ in
-the names used (contact me if you'd like a feature added to the C
-interface). If you're building a shared library, I highly recommend
-sticking to the C interface only, because it will be more stable between
-releases of the library than the C++ interface. Finally, the C and C++
-interfaces can be freely mixed without problems. Compare demo/basics.c
-with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
-between each other.
-
-
-Function reference
-------------------
-Read the following header files for a complete reference to functions
-and features. The second group of header files can only be used in C++.
-
-blargg_config.h Library configuration
-gme.h C interface (also usable from C++)
-
-Gme_File.h File loading and track information
-Music_Emu.h Track playback and adjustments
-Data_Reader.h Custom data readers
-Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
-M3u_Playlist.h M3U playlist support
-Gbs_Emu.h GBS equalizer settings
-Nsf_Emu.h NSF equalizer settings
-Spc_Emu.h SPC surround disable
-Vgm_Emu.h VGM oversampling disable and custom buffer query
-
-
-Error handling
---------------
-Functions which can fail have a return type of gme_err_t (blargg_err_t
-in the C++ interfaces), which is a pointer to an error string (const
-char*). If a function is successful it returns NULL. Errors that you can
-easily avoid are checked with debug assertions; gme_err_t return values
-are only used for genuine run-time errors that can't be easily predicted
-in advance (out of memory, I/O errors, incompatible file data). Your
-code should check all error values.
-
-To improve usability for C programmers, C++ programmers unfamiliar with
-exceptions, and compatibility with older C++ compilers, the library does
-*not* throw any C++ exceptions and uses malloc() instead of the standard
-operator new. This means that you *must* check for NULL when creating a
-library object with the new operator.
-
-When loading a music file in the wrong emulator or trying to load a
-non-music file, gme_wrong_file_type is returned. You can check for this
-error in C++ like this:
-
- gme_err_t err = gme_open_file( path, &emu );
- if ( err == gme_wrong_file_type )
- ...
-
-To check for minor problems, call gme_warning() to get a string
-describing the last warning. Your player should allow the user some way
-of knowing when this is the case, since these minor errors could affect
-playback. Without this information the user can't solve problems as
-well. When playing a track, gme_warning() returns minor playback-related
-problems (major playback problems end the track immediately and set the
-warning string).
-
-
-Emulator types
---------------
-The library includes several game music emulators that each support a
-different file type. Each is identified by a gme_type_t constant defined
-in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
-gme_open_file() or gme_open_data(), the library does the work of
-determining the file type and creating an appropriate emulator. If you
-want more control over this process, read on.
-
-There are two basic ways to identify a game music file's type: look at
-its file extension, or read the header data. The library includes
-functions to help with both methods. The first is preferable because it
-is fast and the most common way to identify files. Sometimes the
-extension is lost or wrong, so the header must be read.
-
-Use gme_identify_extension() to find the correct game music type based
-on a filename. To identify a file based on its extension and header
-contents, use gme_identify_file(). If you read the header data yourself,
-use gme_identify_header().
-
-If you want to remove support for some music types to reduce your
-executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
-support just NSF and GBS, use this:
-
- #define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
-
-
-M3U playlist support
---------------------
-The library supports playlists in an extended m3u format with
-gme_load_m3u() to give track names and times to multi-song formats: AY,
-GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
-itself is not well-defined so some m3u files won't work properly
-(particularly those provided with KSS files). Only m3u files referencing
-a single file are supported; your code must handle m3u files covering
-more than one game music file, though it can use the built-in m3u
-parsing provided by the library.
-
-
-Information fields
-------------------
-Support is provided for the various text fields and length information
-in a file with gme_track_info(). If you just need track information for
-a file (for example, building a playlist), use gme_new_info() in place
-of gme_new_emu(), load the file normally, then you can access the track
-count and info, but nothing else.
-
- M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
- -------------------------------------------------------
-Track Count | * * * * * * * * *
- |
-System | * * * * * * * * * *
- |
-Game | * * * * * * *
- |
-Song | * * * * * * *
- |
-Author | * * * * * * * *
- |
-Copyright | * * * * * * * *
- |
-Comment | * * * *
- |
-Dumper | * * * *
- |
-Length | * * * * * *
- |
-Intro Length| * * *
- |
-Loop Length | * * *
-
-As listed above, the HES and KSS file formats don't include a track
-count, and tracks are often scattered over the 0-255 range, so an m3u
-playlist for these is a must.
-
-Unavailable text fields are set to an empty string and times to -1. Your
-code should be prepared for any combination of available and unavailable
-fields, as a particular music file might not use all of the supported
-fields listed above.
-
-Currently text fields are truncated to 255 characters. Obscure fields of
-some formats are not currently decoded; contact me if you want one
-added.
-
-
-Track length
-------------
-The library leaves it up to you as to when to stop playing a track. You
-can ask for available length information and then tell the library what
-time it should start fading the track with gme_set_fade(). By default it
-also continually checks for 6 or more seconds of silence to mark the end
-of a track. Here is a reasonable algorithm you can use to decide how
-long to play a track:
-
-* If the track length is > 0, use it
-* If the loop length > 0, play for intro + loop * 2
-* Otherwise, default to 2.5 minutes (150000 msec)
-
-If you want to play a track longer than normal, be sure the loop length
-isn't zero. See Music_Player.cpp around line 145 for example code.
-
-By default, the library skips silence at the beginning of a track. It
-also continually checks for the end of a non-looping track by watching
-for 6 seconds of unbroken silence. When doing this is scans *ahead* by
-several seconds so it can report the end of the track after only one
-second of silence has actually played. This feature can be disabled with
-gme_ignore_silence().
-
-
-Loading file data
------------------
-The library allows file data to be loaded in many different ways. All
-load functions return an error which you should check. The following
-examples assume these variables:
-
- Music_Emu* emu;
- gme_err_t error;
-
-If you're letting the library determine a file's type, you can use
-either gme_open_file() or gme_open_data():
-
- error = gme_open_file( pathname, &emu );
- error = gme_open_data( pointer, size, &emu );
-
-If you're manually determining file type and using used gme_new_emu() to
-create an emulator, you can use the following methods of loading:
-
-* From a block of memory:
-
- error = gme_load_data( emu, pointer, size );
-
-* Have library call your function to read data:
-
- gme_err_t my_read( void* my_data, void* out, long count )
- {
- // code that reads 'count' bytes into 'out' buffer
- // and return 0 if no error
- }
-
- error = gme_load_custom( emu, my_read, file_size, my_data );
-
-* If you must load the file data into memory yourself, you can have the
-library use your data directly *without* making a copy. If you do this,
-you must not free the data until you're done playing the file.
-
- error = emu->load_mem( pointer, size );
-
-* If you've already read the first bytes of a file (perhaps to determine
-the file type) and want to avoid seeking back to the beginning for
-performance reasons, use Remaining_Reader:
-
- Std_File_Reader in;
- error = in.open( file_path );
-
- char header [4];
- error = in.read( &header, sizeof header );
- ...
-
- Remaining_Reader rem( &header, sizeof header, &in );
- error = emu->load( rem );
-
-If you merely need access to a file's header after loading, use the
-emulator-specific header() functions, after casting the Music_Emu
-pointer to the specific emulator's type. This example examines the
-chip_flags field of the header if it's an NSF file:
-
- if ( music_emu->type() == gme_nsf_type )
- {
- Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
- if ( nsf_emu->header().chip_flags & 0x01 )
- ...
- }
-
-Contact me if you want more information about loading files.
-
-
-Sound parameters
-----------------
-All emulators support an arbitrary output sampling rate. A rate of 44100
-Hz should work well on most systems. Since band-limited synthesis is
-used, a sampling rate above 48000 Hz is not necessary and will actually
-reduce sound quality and performance.
-
-All emulators also support adjustable gain, mainly for the purpose of
-getting consistent volume between different music formats and avoiding
-excessive modulation. The gain can only be set *before* setting the
-emulator's sampling rate, so it's not useful as a general volume
-control. The default gains of emulators are set so that they give
-generally similar volumes, though some soundtracks are significantly
-louder or quieter than normal.
-
-Some emulators support adjustable treble and bass frequency equalization
-(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
-Parameters are specified using gme_equalizer_t eq = { treble_dB,
-bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
-normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
-for an extra crisp sound. Bass_freq sets the frequency where bass
-response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
-and 15000 Hz removes all bass. For example, the following makes the
-sound extra-crisp but lacking bass:
-
- gme_equalizer_t eq = { 5.0, 1000 };
- gme_set_equalizer( music_emu, &eq );
-
-Each emulator's equalization defaults to approximate the particular
-console's sound quality; this default can be determined by calling
-equalizer() just after creating the emulator. The Music_Emu::tv_eq
-profile gives sound as if coming from a TV speaker, and some emulators
-include other profiles for different versions of the system. For
-example, to use Famicom sound equalization with the NSF emulator, do the
-following:
-
- music_emu->set_equalizer( Nsf_Emu::famicom_eq );
-
-
-VGM/GYM YM2413 & YM2612 FM sound
---------------------------------
-The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
-chip emulator based on the Gens project. Because this has some
-inaccuracies, other YM2612 emulators can be used in its place by
-re-implementing the interface in YM2612_Emu.h. Available on my website
-is a modified version of MAME's YM2612 emulator, which sounds better in
-some ways and whose author is still making improvements.
-
-VGM music files using the YM2413 FM sound chip are also supported, but a
-YM2413 emulator isn't included with the library due to technical
-reasons. I have put one of the available YM2413 emulators on my website
-that can be used directly.
-
-
-Modular construction
---------------------
-The library is made of many fairly independent modules. If you're using
-only one music file emulator, you can eliminate many of the library
-sources from your program. Refer to the files list in readme.txt to get
-a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
-(see "Emulator types" above). Post to the forum if you'd like me to put
-together a smaller version for a particular use, as this only takes me a
-few minutes to do.
-
-If you want to use one of the individual sound chip emulators (or CPU
-cores) in your own console emulator, first check the libraries page on
-my website since I have released several of them as stand alone
-libraries with included documentation and examples on their use. If you
-don't find it as a standalone library, contact me and I'll consider
-separating it.
-
-The "classic" sound chips use my Blip_Buffer library, which greatly
-simplifies their implementation and efficiently handles band-limited
-synthesis. It is also available as a stand alone library with
-documentation and many examples.
-
-
-Obscure features
-----------------
-The library's flexibility allows many possibilities. Contact me if you
-want help implementing ideas or removing limitations.
-
-* Uses no global/static variables, allowing multiple instances of any
-emulator. This is useful in a music player if you want to allow
-simultaneous recording or scanning of other tracks while one is already
-playing. This will also be useful if your platform disallows global
-data.
-
-* Emulators that support a custom sound buffer can have *every* voice
-routed to a different Blip_Buffer, allowing custom processing on each
-voice. For example you could record a Game Boy track as a 4-channel
-sound file.
-
-* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
-synthesis on "classic" emulators, which might help on some really old
-processors. This significantly lowers sound quality and prevents treble
-equalization. Try this if your platform's processor isn't fast enough
-for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
-processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
-the quality loss.
-
-
-Solving problems
-----------------
-If you're having problems, try the following:
-
-* If you're getting garbled sound, try this simple siren generator in
-place of your call to play(). This will quickly tell whether the problem
-is in the library or in your code.
-
- static void play_siren( long count, short* out )
- {
- static double a, a2;
- while ( count-- )
- *out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
- }
-
-* Enable debugging support in your environment. This enables assertions
-and other run-time checks.
-
-* Turn the compiler's optimizer is off. Sometimes an optimizer generates
-bad code.
-
-* If multiple threads are being used, ensure that only one at a time is
-accessing a given set of objects from the library. This library is not
-in general thread-safe, though independent objects can be used in
-separate threads.
-
-* If all else fails, see if the demos work.
-
-
-Deprecated features
--------------------
-The following functions and other features have been deprecated and will
-be removed in a future release of the library. Alternatives to the
-deprecated features are listed to the right.
-
-Music_Emu::error_count() warning()
-load( header, reader ) see "Loading file data" above
-Spc_Emu::trailer() track_info()
-Spc_Emu::trailer_size()
-Gym_Emu::track_length() track_info()
-Vgm_Emu::gd3_data() track_info()
-Nsfe_Emu::disable_playlist() clear_playlist()
-
-
-Thanks
-------
-Big thanks to Chris Moeller (kode54) for help with library testing and
-feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
-for original work on openspc++ that was used when developing Spc_Emu.
-Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
-start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
-nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
-and giving feedback for the library in their respective game music
-players.
+Game_Music_Emu 0.6.0 Pre-release
+--------------------
+Author : Shay Green
+Author : Chris Moeller
+Website: http://www.slack.net/~ant/libs/
+Website: http://bitbucket.com/kode54/Game_Music_Emu
+Forum : http://groups.google.com/group/blargg-sound-libs
+License: GNU Lesser General Public License (LGPL)
+
+NOTE: This file has not been fully updated yet!
+
+Contents
+--------
+* Overview
+* C and C++ interfaces
+* Function reference
+* Error handling
+* Emulator types
+* M3U playlist support
+* Information fields
+* Track length
+* Loading file data
+* Sound parameters
+* VGM/GYM YM2413 & YM2612 FM sound
+* Modular construction
+* Obscure features
+* Solving problems
+* Deprecated features
+* Thanks
+
+
+Overview
+--------
+This library can open game music files, play tracks, and read game and
+track information tags. To play a game music file, do the following:
+
+* Open the file with gme_open_file()
+* Start a track with gme_start_track();
+* Generate samples as needed with gme_play()
+* Play samples through speaker using your operating system
+* Delete emulator when done with gme_delete()
+
+Your code must arrange for the generated samples to be played through
+the computer's speaker using whatever method your operating system
+requires.
+
+There are many additional features available; you can:
+
+* Determine of the type of a music file without opening it with
+gme_identify_*()
+* Load just the file's information tags with gme_info_only
+* Load from a block of memory rather than a file with gme_load_data()
+* Arrange for a fade-out at a particular time with gme_set_fade
+* Find when a track has ended with gme_track_ended()
+* Seek to a new time in the track with gme_seek()
+* Load an extended m3u playlist with gme_load_m3u()
+* Get a list of the voices (channels) and mute them individually with
+gme_voice_names() and gme_mute_voice()
+* Change the playback tempo without affecting pitch with gme_set_tempo()
+* Adjust treble/bass equalization with gme_set_equalizer()
+* Associate your own data with an emulator and later get it back with
+gme_set_user_data()
+* Register a function of yours to be called back when the emulator is
+deleted with gme_set_user_cleanup()
+
+Refer to gme.h for a comprehensive summary of features.
+
+
+C and C++ interfaces
+--------------------
+While the library is written in C++, an extensive C interface is
+provided in gme.h. This C interface will be referred to throughout this
+documentation unless a feature is only available in the full C++
+interface. All C interface functions and other names have the gme_
+prefix, so you can recognize a C++-only feature by the lack of gme_ in
+the names used (contact me if you'd like a feature added to the C
+interface). If you're building a shared library, I highly recommend
+sticking to the C interface only, because it will be more stable between
+releases of the library than the C++ interface. Finally, the C and C++
+interfaces can be freely mixed without problems. Compare demo/basics.c
+with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
+between each other.
+
+
+Function reference
+------------------
+Read the following header files for a complete reference to functions
+and features. The second group of header files can only be used in C++.
+
+blargg_config.h Library configuration
+gme.h C interface (also usable from C++)
+
+Gme_File.h File loading and track information
+Music_Emu.h Track playback and adjustments
+Data_Reader.h Custom data readers
+Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
+M3u_Playlist.h M3U playlist support
+Gbs_Emu.h GBS equalizer settings
+Nsf_Emu.h NSF equalizer settings
+Spc_Emu.h SPC surround disable
+Vgm_Emu.h VGM oversampling disable and custom buffer query
+
+
+Error handling
+--------------
+Functions which can fail have a return type of gme_err_t (blargg_err_t
+in the C++ interfaces), which is a pointer to an error string (const
+char*). If a function is successful it returns NULL. Errors that you can
+easily avoid are checked with debug assertions; gme_err_t return values
+are only used for genuine run-time errors that can't be easily predicted
+in advance (out of memory, I/O errors, incompatible file data). Your
+code should check all error values.
+
+To improve usability for C programmers, C++ programmers unfamiliar with
+exceptions, and compatibility with older C++ compilers, the library does
+*not* throw any C++ exceptions and uses malloc() instead of the standard
+operator new. This means that you *must* check for NULL when creating a
+library object with the new operator.
+
+When loading a music file in the wrong emulator or trying to load a
+non-music file, gme_wrong_file_type is returned. You can check for this
+error in C++ like this:
+
+ gme_err_t err = gme_open_file( path, &emu );
+ if ( err == gme_wrong_file_type )
+ ...
+
+To check for minor problems, call gme_warning() to get a string
+describing the last warning. Your player should allow the user some way
+of knowing when this is the case, since these minor errors could affect
+playback. Without this information the user can't solve problems as
+well. When playing a track, gme_warning() returns minor playback-related
+problems (major playback problems end the track immediately and set the
+warning string).
+
+
+Emulator types
+--------------
+The library includes several game music emulators that each support a
+different file type. Each is identified by a gme_type_t constant defined
+in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
+gme_open_file() or gme_open_data(), the library does the work of
+determining the file type and creating an appropriate emulator. If you
+want more control over this process, read on.
+
+There are two basic ways to identify a game music file's type: look at
+its file extension, or read the header data. The library includes
+functions to help with both methods. The first is preferable because it
+is fast and the most common way to identify files. Sometimes the
+extension is lost or wrong, so the header must be read.
+
+Use gme_identify_extension() to find the correct game music type based
+on a filename. To identify a file based on its extension and header
+contents, use gme_identify_file(). If you read the header data yourself,
+use gme_identify_header().
+
+If you want to remove support for some music types to reduce your
+executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
+support just NSF and GBS, use this:
+
+ #define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
+
+
+M3U playlist support
+--------------------
+The library supports playlists in an extended m3u format with
+gme_load_m3u() to give track names and times to multi-song formats: AY,
+GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
+itself is not well-defined so some m3u files won't work properly
+(particularly those provided with KSS files). Only m3u files referencing
+a single file are supported; your code must handle m3u files covering
+more than one game music file, though it can use the built-in m3u
+parsing provided by the library.
+
+
+Information fields
+------------------
+Support is provided for the various text fields and length information
+in a file with gme_track_info(). If you just need track information for
+a file (for example, building a playlist), use gme_new_info() in place
+of gme_new_emu(), load the file normally, then you can access the track
+count and info, but nothing else.
+
+ M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
+ -------------------------------------------------------
+Track Count | * * * * * * * * *
+ |
+System | * * * * * * * * * *
+ |
+Game | * * * * * * *
+ |
+Song | * * * * * * *
+ |
+Author | * * * * * * * *
+ |
+Copyright | * * * * * * * *
+ |
+Comment | * * * *
+ |
+Dumper | * * * *
+ |
+Length | * * * * * *
+ |
+Intro Length| * * *
+ |
+Loop Length | * * *
+
+As listed above, the HES and KSS file formats don't include a track
+count, and tracks are often scattered over the 0-255 range, so an m3u
+playlist for these is a must.
+
+Unavailable text fields are set to an empty string and times to -1. Your
+code should be prepared for any combination of available and unavailable
+fields, as a particular music file might not use all of the supported
+fields listed above.
+
+Currently text fields are truncated to 255 characters. Obscure fields of
+some formats are not currently decoded; contact me if you want one
+added.
+
+
+Track length
+------------
+The library leaves it up to you as to when to stop playing a track. You
+can ask for available length information and then tell the library what
+time it should start fading the track with gme_set_fade(). By default it
+also continually checks for 6 or more seconds of silence to mark the end
+of a track. Here is a reasonable algorithm you can use to decide how
+long to play a track:
+
+* If the track length is > 0, use it
+* If the loop length > 0, play for intro + loop * 2
+* Otherwise, default to 2.5 minutes (150000 msec)
+
+If you want to play a track longer than normal, be sure the loop length
+isn't zero. See Music_Player.cpp around line 145 for example code.
+
+By default, the library skips silence at the beginning of a track. It
+also continually checks for the end of a non-looping track by watching
+for 6 seconds of unbroken silence. When doing this is scans *ahead* by
+several seconds so it can report the end of the track after only one
+second of silence has actually played. This feature can be disabled with
+gme_ignore_silence().
+
+
+Loading file data
+-----------------
+The library allows file data to be loaded in many different ways. All
+load functions return an error which you should check. The following
+examples assume these variables:
+
+ Music_Emu* emu;
+ gme_err_t error;
+
+If you're letting the library determine a file's type, you can use
+either gme_open_file() or gme_open_data():
+
+ error = gme_open_file( pathname, &emu );
+ error = gme_open_data( pointer, size, &emu );
+
+If you're manually determining file type and using used gme_new_emu() to
+create an emulator, you can use the following methods of loading:
+
+* From a block of memory:
+
+ error = gme_load_data( emu, pointer, size );
+
+* Have library call your function to read data:
+
+ gme_err_t my_read( void* my_data, void* out, long count )
+ {
+ // code that reads 'count' bytes into 'out' buffer
+ // and return 0 if no error
+ }
+
+ error = gme_load_custom( emu, my_read, file_size, my_data );
+
+* If you must load the file data into memory yourself, you can have the
+library use your data directly *without* making a copy. If you do this,
+you must not free the data until you're done playing the file.
+
+ error = emu->load_mem( pointer, size );
+
+* If you've already read the first bytes of a file (perhaps to determine
+the file type) and want to avoid seeking back to the beginning for
+performance reasons, use Remaining_Reader:
+
+ Std_File_Reader in;
+ error = in.open( file_path );
+
+ char header [4];
+ error = in.read( &header, sizeof header );
+ ...
+
+ Remaining_Reader rem( &header, sizeof header, &in );
+ error = emu->load( rem );
+
+If you merely need access to a file's header after loading, use the
+emulator-specific header() functions, after casting the Music_Emu
+pointer to the specific emulator's type. This example examines the
+chip_flags field of the header if it's an NSF file:
+
+ if ( music_emu->type() == gme_nsf_type )
+ {
+ Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
+ if ( nsf_emu->header().chip_flags & 0x01 )
+ ...
+ }
+
+Contact me if you want more information about loading files.
+
+
+Sound parameters
+----------------
+All emulators support an arbitrary output sampling rate. A rate of 44100
+Hz should work well on most systems. Since band-limited synthesis is
+used, a sampling rate above 48000 Hz is not necessary and will actually
+reduce sound quality and performance.
+
+All emulators also support adjustable gain, mainly for the purpose of
+getting consistent volume between different music formats and avoiding
+excessive modulation. The gain can only be set *before* setting the
+emulator's sampling rate, so it's not useful as a general volume
+control. The default gains of emulators are set so that they give
+generally similar volumes, though some soundtracks are significantly
+louder or quieter than normal.
+
+Some emulators support adjustable treble and bass frequency equalization
+(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
+Parameters are specified using gme_equalizer_t eq = { treble_dB,
+bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
+normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
+for an extra crisp sound. Bass_freq sets the frequency where bass
+response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
+and 15000 Hz removes all bass. For example, the following makes the
+sound extra-crisp but lacking bass:
+
+ gme_equalizer_t eq = { 5.0, 1000 };
+ gme_set_equalizer( music_emu, &eq );
+
+Each emulator's equalization defaults to approximate the particular
+console's sound quality; this default can be determined by calling
+equalizer() just after creating the emulator. The Music_Emu::tv_eq
+profile gives sound as if coming from a TV speaker, and some emulators
+include other profiles for different versions of the system. For
+example, to use Famicom sound equalization with the NSF emulator, do the
+following:
+
+ music_emu->set_equalizer( Nsf_Emu::famicom_eq );
+
+
+VGM/GYM YM2413 & YM2612 FM sound
+--------------------------------
+The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
+chip emulator based on the Gens project. Because this has some
+inaccuracies, other YM2612 emulators can be used in its place by
+re-implementing the interface in YM2612_Emu.h. Available on my website
+is a modified version of MAME's YM2612 emulator, which sounds better in
+some ways and whose author is still making improvements.
+
+VGM music files using the YM2413 FM sound chip are also supported, but a
+YM2413 emulator isn't included with the library due to technical
+reasons. I have put one of the available YM2413 emulators on my website
+that can be used directly.
+
+
+Modular construction
+--------------------
+The library is made of many fairly independent modules. If you're using
+only one music file emulator, you can eliminate many of the library
+sources from your program. Refer to the files list in readme.txt to get
+a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
+(see "Emulator types" above). Post to the forum if you'd like me to put
+together a smaller version for a particular use, as this only takes me a
+few minutes to do.
+
+If you want to use one of the individual sound chip emulators (or CPU
+cores) in your own console emulator, first check the libraries page on
+my website since I have released several of them as stand alone
+libraries with included documentation and examples on their use. If you
+don't find it as a standalone library, contact me and I'll consider
+separating it.
+
+The "classic" sound chips use my Blip_Buffer library, which greatly
+simplifies their implementation and efficiently handles band-limited
+synthesis. It is also available as a stand alone library with
+documentation and many examples.
+
+
+Obscure features
+----------------
+The library's flexibility allows many possibilities. Contact me if you
+want help implementing ideas or removing limitations.
+
+* Uses no global/static variables, allowing multiple instances of any
+emulator. This is useful in a music player if you want to allow
+simultaneous recording or scanning of other tracks while one is already
+playing. This will also be useful if your platform disallows global
+data.
+
+* Emulators that support a custom sound buffer can have *every* voice
+routed to a different Blip_Buffer, allowing custom processing on each
+voice. For example you could record a Game Boy track as a 4-channel
+sound file.
+
+* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
+synthesis on "classic" emulators, which might help on some really old
+processors. This significantly lowers sound quality and prevents treble
+equalization. Try this if your platform's processor isn't fast enough
+for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
+processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
+the quality loss.
+
+
+Solving problems
+----------------
+If you're having problems, try the following:
+
+* If you're getting garbled sound, try this simple siren generator in
+place of your call to play(). This will quickly tell whether the problem
+is in the library or in your code.
+
+ static void play_siren( long count, short* out )
+ {
+ static double a, a2;
+ while ( count-- )
+ *out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
+ }
+
+* Enable debugging support in your environment. This enables assertions
+and other run-time checks.
+
+* Turn the compiler's optimizer is off. Sometimes an optimizer generates
+bad code.
+
+* If multiple threads are being used, ensure that only one at a time is
+accessing a given set of objects from the library. This library is not
+in general thread-safe, though independent objects can be used in
+separate threads.
+
+* If all else fails, see if the demos work.
+
+
+Deprecated features
+-------------------
+The following functions and other features have been deprecated and will
+be removed in a future release of the library. Alternatives to the
+deprecated features are listed to the right.
+
+Music_Emu::error_count() warning()
+load( header, reader ) see "Loading file data" above
+Spc_Emu::trailer() track_info()
+Spc_Emu::trailer_size()
+Gym_Emu::track_length() track_info()
+Vgm_Emu::gd3_data() track_info()
+Nsfe_Emu::disable_playlist() clear_playlist()
+
+
+Thanks
+------
+Big thanks to Chris Moeller (kode54) for help with library testing and
+feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
+for original work on openspc++ that was used when developing Spc_Emu.
+Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
+start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
+nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
+and giving feedback for the library in their respective game music
+players.
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gym_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gym_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gym_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gym_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,428 +1,428 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Gym_Emu.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const min_tempo = 0.25;
-double const oversample = 5 / 3.0;
-double const fm_gain = 3.0;
-
-int const base_clock = 53700300;
-int const clock_rate = base_clock / 15;
-
-Gym_Emu::Gym_Emu()
-{
- resampler.set_callback( play_frame_, this );
- pos = NULL;
- disable_oversampling_ = false;
- set_type( gme_gym_type );
- set_silence_lookahead( 1 ); // tracks should already be trimmed
- pcm_buf = stereo_buf.center();
-}
-
-Gym_Emu::~Gym_Emu() { }
-
-// Track info
-
-static void get_gym_info( Gym_Emu::header_t const& h, int length, track_info_t* out )
-{
- if ( 0 != memcmp( h.tag, "GYMX", 4 ) )
- return;
-
- length = length * 50 / 3; // 1000 / 60
- int loop = get_le32( h.loop_start );
- if ( loop )
- {
- out->intro_length = loop * 50 / 3;
- out->loop_length = length - out->intro_length;
- }
- else
- {
- out->length = length;
- out->intro_length = length; // make it clear that track is no longer than length
- out->loop_length = 0;
- }
-
- // more stupidity where the field should have been left blank
- if ( strcmp( h.song, "Unknown Song" ) )
- GME_COPY_FIELD( h, out, song );
-
- if ( strcmp( h.game, "Unknown Game" ) )
- GME_COPY_FIELD( h, out, game );
-
- if ( strcmp( h.copyright, "Unknown Publisher" ) )
- GME_COPY_FIELD( h, out, copyright );
-
- if ( strcmp( h.dumper, "Unknown Person" ) )
- GME_COPY_FIELD( h, out, dumper );
-
- if ( strcmp( h.comment, "Header added by YMAMP" ) )
- GME_COPY_FIELD( h, out, comment );
-}
-
-static void hash_gym_file( Gym_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.loop_start[0], sizeof(h.loop_start) );
- out.hash_( &h.packed[0], sizeof(h.packed) );
- out.hash_( data, data_size );
-}
-
-static int gym_track_length( byte const p [], byte const* end )
-{
- int time = 0;
- while ( p < end )
- {
- switch ( *p++ )
- {
- case 0:
- time++;
- break;
-
- case 1:
- case 2:
- p += 2;
- break;
-
- case 3:
- p += 1;
- break;
- }
- }
- return time;
-}
-
-blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
-{
- get_gym_info( header_, gym_track_length( log_begin(), file_end() ), out );
- return blargg_ok;
-}
-
-static blargg_err_t check_header( byte const in [], int size, int* data_offset = NULL )
-{
- if ( size < 4 )
- return blargg_err_file_type;
-
- if ( memcmp( in, "GYMX", 4 ) == 0 )
- {
- if ( size < Gym_Emu::header_t::size + 1 )
- return blargg_err_file_type;
-
- if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
- return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "packed GYM file" );
-
- if ( data_offset )
- *data_offset = Gym_Emu::header_t::size;
- }
- else if ( *in > 3 )
- {
- return blargg_err_file_type;
- }
-
- return blargg_ok;
-}
-
-struct Gym_File : Gme_Info_
-{
- int data_offset;
-
- Gym_File() { set_type( gme_gym_type ); }
-
- blargg_err_t load_mem_( byte const in [], int size )
- {
- data_offset = 0;
- return check_header( in, size, &data_offset );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- int length = gym_track_length( &file_begin() [data_offset], file_end() );
- get_gym_info( *(Gym_Emu::header_t const*) file_begin(), length, out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- Gym_Emu::header_t const* h = ( Gym_Emu::header_t const* ) file_begin();
- byte const* data = &file_begin() [data_offset];
-
- hash_gym_file( *h, data, file_end() - data, out );
-
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
-static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
-
-gme_type_t_ const gme_gym_type [1] = {{ "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 }};
-
-// Setup
-
-blargg_err_t Gym_Emu::set_sample_rate_( int sample_rate )
-{
- blip_eq_t eq( -32, 8000, sample_rate );
- apu.treble_eq( eq );
- pcm_synth.treble_eq( eq );
-
- apu.volume( 0.135 * fm_gain * gain() );
-
- double factor = oversample;
- if ( disable_oversampling_ )
- factor = (double) base_clock / 7 / 144 / sample_rate;
- RETURN_ERR( resampler.setup( factor, 0.990, fm_gain * gain() ) );
- factor = resampler.rate();
- double fm_rate = sample_rate * factor;
-
- RETURN_ERR( stereo_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
- stereo_buf.clock_rate( clock_rate );
-
- RETURN_ERR( fm.set_rate( fm_rate, base_clock / 7.0 ) );
- RETURN_ERR( resampler.reset( (int) (1.0 / 60 / min_tempo * sample_rate) ) );
-
- return blargg_ok;
-}
-
-void Gym_Emu::set_tempo_( double t )
-{
- if ( t < min_tempo )
- {
- set_tempo( min_tempo );
- return;
- }
-
- if ( stereo_buf.sample_rate() )
- {
- double denom = tempo() * 60;
- clocks_per_frame = (int) (clock_rate / denom);
- resampler.resize( (int) (sample_rate() / denom) );
- }
-}
-
-void Gym_Emu::mute_voices_( int mask )
-{
- Music_Emu::mute_voices_( mask );
- fm.mute_voices( mask );
- apu.set_output( (mask & 0x80) ? 0 : stereo_buf.center() );
- pcm_synth.volume( (mask & 0x40) ? 0.0 : 0.125 / 256 * fm_gain * gain() );
-}
-
-blargg_err_t Gym_Emu::load_mem_( byte const in [], int size )
-{
- assert( offsetof (header_t,packed [4]) == header_t::size );
- log_offset = 0;
- RETURN_ERR( check_header( in, size, &log_offset ) );
-
- loop_begin = NULL;
-
- static const char* const names [] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
- };
- set_voice_names( names );
-
- set_voice_count( 8 );
-
- if ( log_offset )
- header_ = *(header_t const*) in;
- else
- memset( &header_, 0, sizeof header_ );
-
- return blargg_ok;
-}
-
-// Emulation
-
-blargg_err_t Gym_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
-
- pos = log_begin();
- loop_remain = get_le32( header_.loop_start );
-
- prev_pcm_count = 0;
- pcm_enabled = 0;
- pcm_amp = -1;
-
- fm.reset();
- apu.reset();
- stereo_buf.clear();
- resampler.clear();
- pcm_buf = stereo_buf.center();
- return blargg_ok;
-}
-
-void Gym_Emu::run_pcm( byte const pcm_in [], int pcm_count )
-{
- // Guess beginning and end of sample and adjust rate and buffer position accordingly.
-
- // count dac samples in next frame
- int next_pcm_count = 0;
- const byte* p = this->pos;
- int cmd;
- while ( (cmd = *p++) != 0 )
- {
- int data = *p++;
- if ( cmd <= 2 )
- ++p;
- if ( cmd == 1 && data == 0x2A )
- next_pcm_count++;
- }
-
- // detect beginning and end of sample
- int rate_count = pcm_count;
- int start = 0;
- if ( !prev_pcm_count && next_pcm_count && pcm_count < next_pcm_count )
- {
- rate_count = next_pcm_count;
- start = next_pcm_count - pcm_count;
- }
- else if ( prev_pcm_count && !next_pcm_count && pcm_count < prev_pcm_count )
- {
- rate_count = prev_pcm_count;
- }
-
- // Evenly space samples within buffer section being used
- blip_resampled_time_t period = pcm_buf->resampled_duration( clocks_per_frame ) / rate_count;
-
- blip_resampled_time_t time = pcm_buf->resampled_time( 0 ) + period * start + (unsigned) period / 2;
-
- int pcm_amp = this->pcm_amp;
- if ( pcm_amp < 0 )
- pcm_amp = pcm_in [0];
-
- for ( int i = 0; i < pcm_count; i++ )
- {
- int delta = pcm_in [i] - pcm_amp;
- pcm_amp += delta;
- pcm_synth.offset_resampled( time, delta, pcm_buf );
- time += period;
- }
- this->pcm_amp = pcm_amp;
- pcm_buf->set_modified();
-}
-
-void Gym_Emu::parse_frame()
-{
- byte pcm [1024]; // all PCM writes for frame
- int pcm_size = 0;
- const byte* pos = this->pos;
-
- if ( loop_remain && !--loop_remain )
- loop_begin = pos; // find loop on first time through sequence
-
- int cmd;
- while ( (cmd = *pos++) != 0 )
- {
- int data = *pos++;
- if ( cmd == 1 )
- {
- int data2 = *pos++;
- if ( data == 0x2A )
- {
- pcm [pcm_size] = data2;
- if ( pcm_size < (int) sizeof pcm - 1 )
- pcm_size += pcm_enabled;
- }
- else
- {
- if ( data == 0x2B )
- pcm_enabled = data2 >> 7 & 1;
-
- fm.write0( data, data2 );
- }
- }
- else if ( cmd == 2 )
- {
- int data2 = *pos++;
- if ( data == 0xB6 )
- {
- Blip_Buffer * pcm_buf = NULL;
- switch ( data2 >> 6 )
- {
- case 0: pcm_buf = NULL; break;
- case 1: pcm_buf = stereo_buf.right(); break;
- case 2: pcm_buf = stereo_buf.left(); break;
- case 3: pcm_buf = stereo_buf.center(); break;
- }
- /*if ( this->pcm_buf != pcm_buf )
- {
- if ( this->pcm_buf ) pcm_synth.offset_inline( 0, -pcm_amp, this->pcm_buf );
- if ( pcm_buf ) pcm_synth.offset_inline( 0, pcm_amp, pcm_buf );
- }*/
- this->pcm_buf = pcm_buf;
- }
- fm.write1( data, data2 );
- }
- else if ( cmd == 3 )
- {
- apu.write_data( 0, data );
- }
- else
- {
- // to do: many GYM streams are full of errors, and error count should
- // reflect cases where music is really having problems
- //log_error();
- --pos; // put data back
- }
- }
-
- if ( pos >= file_end() )
- {
- // Reached end
- check( pos == file_end() );
-
- if ( loop_begin )
- pos = loop_begin;
- else
- set_track_ended();
- }
- this->pos = pos;
-
- // PCM
- if ( pcm_buf && pcm_size )
- run_pcm( pcm, pcm_size );
- prev_pcm_count = pcm_size;
-}
-
-inline int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] )
-{
- if ( !track_ended() )
- parse_frame();
-
- apu.end_frame( blip_time );
-
- memset( buf, 0, sample_count * sizeof *buf );
- fm.run( sample_count >> 1, buf );
-
- return sample_count;
-}
-
-int Gym_Emu::play_frame_( void* p, blip_time_t a, int b, sample_t c [] )
-{
- return STATIC_CAST(Gym_Emu*,p)->play_frame( a, b, c );
-}
-
-blargg_err_t Gym_Emu::play_( int count, sample_t out [] )
-{
- resampler.dual_play( count, out, stereo_buf );
- return blargg_ok;
-}
-
-blargg_err_t Gym_Emu::hash_( Hash_Function& out ) const
-{
- hash_gym_file( header(), log_begin(), file_end() - log_begin(), out );
- return blargg_ok;
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Gym_Emu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+double const min_tempo = 0.25;
+double const oversample = 5 / 3.0;
+double const fm_gain = 3.0;
+
+int const base_clock = 53700300;
+int const clock_rate = base_clock / 15;
+
+Gym_Emu::Gym_Emu()
+{
+ resampler.set_callback( play_frame_, this );
+ pos = NULL;
+ disable_oversampling_ = false;
+ set_type( gme_gym_type );
+ set_silence_lookahead( 1 ); // tracks should already be trimmed
+ pcm_buf = stereo_buf.center();
+}
+
+Gym_Emu::~Gym_Emu() { }
+
+// Track info
+
+static void get_gym_info( Gym_Emu::header_t const& h, int length, track_info_t* out )
+{
+ if ( 0 != memcmp( h.tag, "GYMX", 4 ) )
+ return;
+
+ length = length * 50 / 3; // 1000 / 60
+ int loop = get_le32( h.loop_start );
+ if ( loop )
+ {
+ out->intro_length = loop * 50 / 3;
+ out->loop_length = length - out->intro_length;
+ }
+ else
+ {
+ out->length = length;
+ out->intro_length = length; // make it clear that track is no longer than length
+ out->loop_length = 0;
+ }
+
+ // more stupidity where the field should have been left blank
+ if ( strcmp( h.song, "Unknown Song" ) )
+ GME_COPY_FIELD( h, out, song );
+
+ if ( strcmp( h.game, "Unknown Game" ) )
+ GME_COPY_FIELD( h, out, game );
+
+ if ( strcmp( h.copyright, "Unknown Publisher" ) )
+ GME_COPY_FIELD( h, out, copyright );
+
+ if ( strcmp( h.dumper, "Unknown Person" ) )
+ GME_COPY_FIELD( h, out, dumper );
+
+ if ( strcmp( h.comment, "Header added by YMAMP" ) )
+ GME_COPY_FIELD( h, out, comment );
+}
+
+static void hash_gym_file( Gym_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.loop_start[0], sizeof(h.loop_start) );
+ out.hash_( &h.packed[0], sizeof(h.packed) );
+ out.hash_( data, data_size );
+}
+
+static int gym_track_length( byte const p [], byte const* end )
+{
+ int time = 0;
+ while ( p < end )
+ {
+ switch ( *p++ )
+ {
+ case 0:
+ time++;
+ break;
+
+ case 1:
+ case 2:
+ p += 2;
+ break;
+
+ case 3:
+ p += 1;
+ break;
+ }
+ }
+ return time;
+}
+
+blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
+{
+ get_gym_info( header_, gym_track_length( log_begin(), file_end() ), out );
+ return blargg_ok;
+}
+
+static blargg_err_t check_header( byte const in [], int size, int* data_offset = NULL )
+{
+ if ( size < 4 )
+ return blargg_err_file_type;
+
+ if ( memcmp( in, "GYMX", 4 ) == 0 )
+ {
+ if ( size < Gym_Emu::header_t::size + 1 )
+ return blargg_err_file_type;
+
+ if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "packed GYM file" );
+
+ if ( data_offset )
+ *data_offset = Gym_Emu::header_t::size;
+ }
+ else if ( *in > 3 )
+ {
+ return blargg_err_file_type;
+ }
+
+ return blargg_ok;
+}
+
+struct Gym_File : Gme_Info_
+{
+ int data_offset;
+
+ Gym_File() { set_type( gme_gym_type ); }
+
+ blargg_err_t load_mem_( byte const in [], int size )
+ {
+ data_offset = 0;
+ return check_header( in, size, &data_offset );
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ int length = gym_track_length( &file_begin() [data_offset], file_end() );
+ get_gym_info( *(Gym_Emu::header_t const*) file_begin(), length, out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ Gym_Emu::header_t const* h = ( Gym_Emu::header_t const* ) file_begin();
+ byte const* data = &file_begin() [data_offset];
+
+ hash_gym_file( *h, data, file_end() - data, out );
+
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
+static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
+
+gme_type_t_ const gme_gym_type [1] = {{ "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 }};
+
+// Setup
+
+blargg_err_t Gym_Emu::set_sample_rate_( int sample_rate )
+{
+ blip_eq_t eq( -32, 8000, sample_rate );
+ apu.treble_eq( eq );
+ pcm_synth.treble_eq( eq );
+
+ apu.volume( 0.135 * fm_gain * gain() );
+
+ double factor = oversample;
+ if ( disable_oversampling_ )
+ factor = (double) base_clock / 7 / 144 / sample_rate;
+ RETURN_ERR( resampler.setup( factor, 0.990, fm_gain * gain() ) );
+ factor = resampler.rate();
+ double fm_rate = sample_rate * factor;
+
+ RETURN_ERR( stereo_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
+ stereo_buf.clock_rate( clock_rate );
+
+ RETURN_ERR( fm.set_rate( fm_rate, base_clock / 7.0 ) );
+ RETURN_ERR( resampler.reset( (int) (1.0 / 60 / min_tempo * sample_rate) ) );
+
+ return blargg_ok;
+}
+
+void Gym_Emu::set_tempo_( double t )
+{
+ if ( t < min_tempo )
+ {
+ set_tempo( min_tempo );
+ return;
+ }
+
+ if ( stereo_buf.sample_rate() )
+ {
+ double denom = tempo() * 60;
+ clocks_per_frame = (int) (clock_rate / denom);
+ resampler.resize( (int) (sample_rate() / denom) );
+ }
+}
+
+void Gym_Emu::mute_voices_( int mask )
+{
+ Music_Emu::mute_voices_( mask );
+ fm.mute_voices( mask );
+ apu.set_output( (mask & 0x80) ? 0 : stereo_buf.center() );
+ pcm_synth.volume( (mask & 0x40) ? 0.0 : 0.125 / 256 * fm_gain * gain() );
+}
+
+blargg_err_t Gym_Emu::load_mem_( byte const in [], int size )
+{
+ assert( offsetof (header_t,packed [4]) == header_t::size );
+ log_offset = 0;
+ RETURN_ERR( check_header( in, size, &log_offset ) );
+
+ loop_begin = NULL;
+
+ static const char* const names [] = {
+ "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
+ };
+ set_voice_names( names );
+
+ set_voice_count( 8 );
+
+ if ( log_offset )
+ header_ = *(header_t const*) in;
+ else
+ memset( &header_, 0, sizeof header_ );
+
+ return blargg_ok;
+}
+
+// Emulation
+
+blargg_err_t Gym_Emu::start_track_( int track )
+{
+ RETURN_ERR( Music_Emu::start_track_( track ) );
+
+ pos = log_begin();
+ loop_remain = get_le32( header_.loop_start );
+
+ prev_pcm_count = 0;
+ pcm_enabled = 0;
+ pcm_amp = -1;
+
+ fm.reset();
+ apu.reset();
+ stereo_buf.clear();
+ resampler.clear();
+ pcm_buf = stereo_buf.center();
+ return blargg_ok;
+}
+
+void Gym_Emu::run_pcm( byte const pcm_in [], int pcm_count )
+{
+ // Guess beginning and end of sample and adjust rate and buffer position accordingly.
+
+ // count dac samples in next frame
+ int next_pcm_count = 0;
+ const byte* p = this->pos;
+ int cmd;
+ while ( (cmd = *p++) != 0 )
+ {
+ int data = *p++;
+ if ( cmd <= 2 )
+ ++p;
+ if ( cmd == 1 && data == 0x2A )
+ next_pcm_count++;
+ }
+
+ // detect beginning and end of sample
+ int rate_count = pcm_count;
+ int start = 0;
+ if ( !prev_pcm_count && next_pcm_count && pcm_count < next_pcm_count )
+ {
+ rate_count = next_pcm_count;
+ start = next_pcm_count - pcm_count;
+ }
+ else if ( prev_pcm_count && !next_pcm_count && pcm_count < prev_pcm_count )
+ {
+ rate_count = prev_pcm_count;
+ }
+
+ // Evenly space samples within buffer section being used
+ blip_resampled_time_t period = pcm_buf->resampled_duration( clocks_per_frame ) / rate_count;
+
+ blip_resampled_time_t time = pcm_buf->resampled_time( 0 ) + period * start + (unsigned) period / 2;
+
+ int pcm_amp = this->pcm_amp;
+ if ( pcm_amp < 0 )
+ pcm_amp = pcm_in [0];
+
+ for ( int i = 0; i < pcm_count; i++ )
+ {
+ int delta = pcm_in [i] - pcm_amp;
+ pcm_amp += delta;
+ pcm_synth.offset_resampled( time, delta, pcm_buf );
+ time += period;
+ }
+ this->pcm_amp = pcm_amp;
+ pcm_buf->set_modified();
+}
+
+void Gym_Emu::parse_frame()
+{
+ byte pcm [1024]; // all PCM writes for frame
+ int pcm_size = 0;
+ const byte* pos = this->pos;
+
+ if ( loop_remain && !--loop_remain )
+ loop_begin = pos; // find loop on first time through sequence
+
+ int cmd;
+ while ( (cmd = *pos++) != 0 )
+ {
+ int data = *pos++;
+ if ( cmd == 1 )
+ {
+ int data2 = *pos++;
+ if ( data == 0x2A )
+ {
+ pcm [pcm_size] = data2;
+ if ( pcm_size < (int) sizeof pcm - 1 )
+ pcm_size += pcm_enabled;
+ }
+ else
+ {
+ if ( data == 0x2B )
+ pcm_enabled = data2 >> 7 & 1;
+
+ fm.write0( data, data2 );
+ }
+ }
+ else if ( cmd == 2 )
+ {
+ int data2 = *pos++;
+ if ( data == 0xB6 )
+ {
+ Blip_Buffer * pcm_buf = NULL;
+ switch ( data2 >> 6 )
+ {
+ case 0: pcm_buf = NULL; break;
+ case 1: pcm_buf = stereo_buf.right(); break;
+ case 2: pcm_buf = stereo_buf.left(); break;
+ case 3: pcm_buf = stereo_buf.center(); break;
+ }
+ /*if ( this->pcm_buf != pcm_buf )
+ {
+ if ( this->pcm_buf ) pcm_synth.offset_inline( 0, -pcm_amp, this->pcm_buf );
+ if ( pcm_buf ) pcm_synth.offset_inline( 0, pcm_amp, pcm_buf );
+ }*/
+ this->pcm_buf = pcm_buf;
+ }
+ fm.write1( data, data2 );
+ }
+ else if ( cmd == 3 )
+ {
+ apu.write_data( 0, data );
+ }
+ else
+ {
+ // to do: many GYM streams are full of errors, and error count should
+ // reflect cases where music is really having problems
+ //log_error();
+ --pos; // put data back
+ }
+ }
+
+ if ( pos >= file_end() )
+ {
+ // Reached end
+ check( pos == file_end() );
+
+ if ( loop_begin )
+ pos = loop_begin;
+ else
+ set_track_ended();
+ }
+ this->pos = pos;
+
+ // PCM
+ if ( pcm_buf && pcm_size )
+ run_pcm( pcm, pcm_size );
+ prev_pcm_count = pcm_size;
+}
+
+inline int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] )
+{
+ if ( !track_ended() )
+ parse_frame();
+
+ apu.end_frame( blip_time );
+
+ memset( buf, 0, sample_count * sizeof *buf );
+ fm.run( sample_count >> 1, buf );
+
+ return sample_count;
+}
+
+int Gym_Emu::play_frame_( void* p, blip_time_t a, int b, sample_t c [] )
+{
+ return STATIC_CAST(Gym_Emu*,p)->play_frame( a, b, c );
+}
+
+blargg_err_t Gym_Emu::play_( int count, sample_t out [] )
+{
+ resampler.dual_play( count, out, stereo_buf );
+ return blargg_ok;
+}
+
+blargg_err_t Gym_Emu::hash_( Hash_Function& out ) const
+{
+ hash_gym_file( header(), log_begin(), file_end() - log_begin(), out );
+ return blargg_ok;
}
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gym_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gym_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Gym_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Gym_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,88 +1,88 @@
-// Sega Genesis/Mega Drive GYM music file emulator
-// Performs PCM timing recovery to improve sample quality.
-
-// Game_Music_Emu $vers
-#ifndef GYM_EMU_H
-#define GYM_EMU_H
-
-#include "Dual_Resampler.h"
-#include "Ym2612_Emu.h"
-#include "Music_Emu.h"
-#include "Sms_Apu.h"
-
-class Gym_Emu : public Music_Emu {
-public:
-
- // GYM file header (optional; many files have NO header at all)
- struct header_t
- {
- enum { size = 428 };
-
- char tag [ 4];
- char song [ 32];
- char game [ 32];
- char copyright [ 32];
- char emulator [ 32];
- char dumper [ 32];
- char comment [256];
- byte loop_start [ 4]; // in 1/60 seconds, 0 if not looped
- byte packed [ 4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_gym_type; }
-
- // Disables running FM chips at higher than normal rate. Will result in slightly
- // more aliasing of high notes.
- void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
-
- blargg_err_t hash_( Hash_Function& ) const;
-
-// Implementation
-public:
- Gym_Emu();
- ~Gym_Emu();
-
-protected:
- virtual blargg_err_t load_mem_( byte const [], int );
- virtual blargg_err_t track_info_( track_info_t*, int track ) const;
- virtual blargg_err_t set_sample_rate_( int sample_rate );
- virtual blargg_err_t start_track_( int );
- virtual blargg_err_t play_( int count, sample_t [] );
- virtual void mute_voices_( int );
- virtual void set_tempo_( double );
-
-private:
- // Log
- byte const* pos; // current position
- byte const* loop_begin;
- int log_offset; // size of header (0 or header_t::size)
- int loop_remain; // frames remaining until loop_begin has been located
- int clocks_per_frame;
-
- bool disable_oversampling_;
-
- // PCM
- int pcm_amp;
- int prev_pcm_count; // for detecting beginning/end of group of samples
- int pcm_enabled;
-
- // large objects
- Dual_Resampler resampler;
- Stereo_Buffer stereo_buf;
- Blip_Buffer * pcm_buf;
- Ym2612_Emu fm;
- Sms_Apu apu;
- Blip_Synth_Fast pcm_synth;
- header_t header_;
-
- byte const* log_begin() const { return file_begin() + log_offset; }
- void parse_frame();
- void run_pcm( byte const in [], int count );
- int play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] );
- static int play_frame_( void*, blip_time_t, int, sample_t [] );
-};
-
-#endif
+// Sega Genesis/Mega Drive GYM music file emulator
+// Performs PCM timing recovery to improve sample quality.
+
+// Game_Music_Emu $vers
+#ifndef GYM_EMU_H
+#define GYM_EMU_H
+
+#include "Dual_Resampler.h"
+#include "Ym2612_Emu.h"
+#include "Music_Emu.h"
+#include "Sms_Apu.h"
+
+class Gym_Emu : public Music_Emu {
+public:
+
+ // GYM file header (optional; many files have NO header at all)
+ struct header_t
+ {
+ enum { size = 428 };
+
+ char tag [ 4];
+ char song [ 32];
+ char game [ 32];
+ char copyright [ 32];
+ char emulator [ 32];
+ char dumper [ 32];
+ char comment [256];
+ byte loop_start [ 4]; // in 1/60 seconds, 0 if not looped
+ byte packed [ 4];
+ };
+
+ // Header for currently loaded file
+ header_t const& header() const { return header_; }
+
+ static gme_type_t static_type() { return gme_gym_type; }
+
+ // Disables running FM chips at higher than normal rate. Will result in slightly
+ // more aliasing of high notes.
+ void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
+
+ blargg_err_t hash_( Hash_Function& ) const;
+
+// Implementation
+public:
+ Gym_Emu();
+ ~Gym_Emu();
+
+protected:
+ virtual blargg_err_t load_mem_( byte const [], int );
+ virtual blargg_err_t track_info_( track_info_t*, int track ) const;
+ virtual blargg_err_t set_sample_rate_( int sample_rate );
+ virtual blargg_err_t start_track_( int );
+ virtual blargg_err_t play_( int count, sample_t [] );
+ virtual void mute_voices_( int );
+ virtual void set_tempo_( double );
+
+private:
+ // Log
+ byte const* pos; // current position
+ byte const* loop_begin;
+ int log_offset; // size of header (0 or header_t::size)
+ int loop_remain; // frames remaining until loop_begin has been located
+ int clocks_per_frame;
+
+ bool disable_oversampling_;
+
+ // PCM
+ int pcm_amp;
+ int prev_pcm_count; // for detecting beginning/end of group of samples
+ int pcm_enabled;
+
+ // large objects
+ Dual_Resampler resampler;
+ Stereo_Buffer stereo_buf;
+ Blip_Buffer * pcm_buf;
+ Ym2612_Emu fm;
+ Sms_Apu apu;
+ Blip_Synth_Fast pcm_synth;
+ header_t header_;
+
+ byte const* log_begin() const { return file_begin() + log_offset; }
+ void parse_frame();
+ void run_pcm( byte const in [], int count );
+ int play_frame( blip_time_t blip_time, int sample_count, sample_t buf [] );
+ static int play_frame_( void*, blip_time_t, int, sample_t [] );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Hes_Apu_Adpcm.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Hes_Apu_Adpcm.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Hes_Apu_Adpcm.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Hes_Apu_Adpcm.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,309 +1,309 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Hes_Apu_Adpcm.h"
-
-/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Hes_Apu_Adpcm::Hes_Apu_Adpcm()
-{
- output = NULL;
-
- memset( &state, 0, sizeof( state ) );
-
- reset();
-}
-
-void Hes_Apu_Adpcm::reset()
-{
- last_time = 0;
- next_timer = 0;
- last_amp = 0;
-
- memset( &state.pcmbuf, 0, sizeof(state.pcmbuf) );
- memset( &state.port, 0, sizeof(state.port) );
-
- state.ad_sample = 0;
- state.ad_ref_index = 0;
-
- state.addr = 0;
- state.freq = 0;
- state.writeptr = 0;
- state.readptr = 0;
- state.playflag = 0;
- state.repeatflag = 0;
- state.length = 0;
- state.volume = 0xFF;
- state.fadetimer = 0;
- state.fadecount = 0;
-}
-
-void Hes_Apu_Adpcm::set_output( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
- require( !center || (center && !left && !right) || (center && left && right) );
- require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
-
- if ( !center || !left || !right )
- {
- left = center;
- right = center;
- }
-
- output = center;
-}
-
-void Hes_Apu_Adpcm::run_until( blip_time_t end_time )
-{
- int volume = state.volume;
- int fadetimer = state.fadetimer;
- int fadecount = state.fadecount;
- int last_time = this->last_time;
- double next_timer = this->next_timer;
- int last_amp = this->last_amp;
-
- Blip_Buffer* output = this->output; // cache often-used values
-
- while ( state.playflag && last_time < end_time )
- {
- while ( last_time >= next_timer )
- {
- if ( fadetimer )
- {
- if ( fadecount > 0 )
- {
- fadecount--;
- volume = 0xFF * fadecount / fadetimer;
- }
- else if ( fadecount < 0 )
- {
- fadecount++;
- volume = 0xFF - ( 0xFF * fadecount / fadetimer );
- }
- }
- next_timer += 7159.091;
- }
- int amp;
- if ( state.ad_low_nibble )
- {
- amp = adpcm_decode( state.pcmbuf[ state.playptr ] & 0x0F );
- state.ad_low_nibble = false;
- state.playptr++;
- state.playedsamplecount++;
- if ( state.playedsamplecount == state.playlength )
- {
- state.playflag = 0;
- }
- }
- else
- {
- amp = adpcm_decode( state.pcmbuf[ state.playptr ] >> 4 );
- state.ad_low_nibble = true;
- }
- amp = amp * volume / 0xFF;
- int delta = amp - last_amp;
- if ( output && delta )
- {
- last_amp = amp;
- synth.offset_inline( last_time, delta, output );
- }
- last_time += state.freq;
- }
-
- if ( !state.playflag )
- {
- while ( next_timer <= end_time ) next_timer += 7159.091;
- last_time = end_time;
- }
-
- this->last_time = last_time;
- this->next_timer = next_timer;
- this->last_amp = last_amp;
- state.volume = volume;
- state.fadetimer = fadetimer;
- state.fadecount = fadecount;
-}
-
-void Hes_Apu_Adpcm::write_data( blip_time_t time, int addr, int data )
-{
- if ( time > last_time ) run_until( time );
-
- data &= 0xFF;
- state.port[ addr & 15 ] = data;
- switch ( addr & 15 )
- {
- case 8:
- state.addr &= 0xFF00;
- state.addr |= data;
- break;
- case 9:
- state.addr &= 0xFF;
- state.addr |= data << 8;
- break;
- case 10:
- state.pcmbuf[ state.writeptr++ ] = data;
- state.playlength ++;
- break;
- case 11:
- dprintf("ADPCM DMA 0x%02X", data);
- break;
- case 13:
- if ( data & 0x80 )
- {
- state.addr = 0;
- state.freq = 0;
- state.writeptr = 0;
- state.readptr = 0;
- state.playflag = 0;
- state.repeatflag = 0;
- state.length = 0;
- state.volume = 0xFF;
- }
- if ( ( data & 3 ) == 3 )
- {
- state.writeptr = state.addr;
- }
- if ( data & 8 )
- {
- state.readptr = state.addr ? state.addr - 1 : state.addr;
- }
- if ( data & 0x10 )
- {
- state.length = state.addr;
- }
- state.repeatflag = data & 0x20;
- state.playflag = data & 0x40;
- if ( state.playflag )
- {
- state.playptr = state.readptr;
- state.playlength = state.length + 1;
- state.playedsamplecount = 0;
- state.ad_sample = 0;
- state.ad_low_nibble = false;
- }
- break;
- case 14:
- state.freq = 7159091 / ( 32000 / ( 16 - ( data & 15 ) ) );
- break;
- case 15:
- switch ( data & 15 )
- {
- case 0:
- case 8:
- case 12:
- state.fadetimer = -100;
- state.fadecount = state.fadetimer;
- break;
- case 10:
- state.fadetimer = 5000;
- state.fadecount = state.fadetimer;
- break;
- case 14:
- state.fadetimer = 1500;
- state.fadecount = state.fadetimer;
- break;
- }
- break;
- }
-}
-
-int Hes_Apu_Adpcm::read_data( blip_time_t time, int addr )
-{
- if ( time > last_time ) run_until( time );
-
- switch ( addr & 15 )
- {
- case 10:
- return state.pcmbuf [state.readptr++];
- case 11:
- return state.port [11] & ~1;
- case 12:
- if (!state.playflag)
- {
- state.port [12] |= 1;
- state.port [12] &= ~8;
- }
- else
- {
- state.port [12] &= ~1;
- state.port [12] |= 8;
- }
- return state.port [12];
- case 13:
- return state.port [13];
- }
-
- return 0xFF;
-}
-
-void Hes_Apu_Adpcm::end_frame( blip_time_t end_time )
-{
- run_until( end_time );
- last_time -= end_time;
- next_timer -= (double)end_time;
- check( last_time >= 0 );
- if ( output )
- output->set_modified();
-}
-
-static short stepsize[49] = {
- 16, 17, 19, 21, 23, 25, 28,
- 31, 34, 37, 41, 45, 50, 55,
- 60, 66, 73, 80, 88, 97, 107,
- 118, 130, 143, 157, 173, 190, 209,
- 230, 253, 279, 307, 337, 371, 408,
- 449, 494, 544, 598, 658, 724, 796,
- 876, 963,1060,1166,1282,1411,1552
-};
-
-int Hes_Apu_Adpcm::adpcm_decode( int code )
-{
- int step = stepsize[state.ad_ref_index];
- int delta;
- int c = code & 7;
-#if 1
- delta = 0;
- if ( c & 4 ) delta += step;
- step >>= 1;
- if ( c & 2 ) delta += step;
- step >>= 1;
- if ( c & 1 ) delta += step;
- step >>= 1;
- delta += step;
-#else
- delta = ( ( c + c + 1 ) * step ) / 8; // maybe faster, but introduces rounding
-#endif
- if ( c != code )
- {
- state.ad_sample -= delta;
- if ( state.ad_sample < -2048 )
- state.ad_sample = -2048;
- }
- else
- {
- state.ad_sample += delta;
- if ( state.ad_sample > 2047 )
- state.ad_sample = 2047;
- }
-
- static int const steps [8] = {
- -1, -1, -1, -1, 2, 4, 6, 8
- };
- state.ad_ref_index += steps [c];
- if ( state.ad_ref_index < 0 )
- state.ad_ref_index = 0;
- else if ( state.ad_ref_index > 48 )
- state.ad_ref_index = 48;
-
- return state.ad_sample;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Hes_Apu_Adpcm.h"
+
+/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Hes_Apu_Adpcm::Hes_Apu_Adpcm()
+{
+ output = NULL;
+
+ memset( &state, 0, sizeof( state ) );
+
+ reset();
+}
+
+void Hes_Apu_Adpcm::reset()
+{
+ last_time = 0;
+ next_timer = 0;
+ last_amp = 0;
+
+ memset( &state.pcmbuf, 0, sizeof(state.pcmbuf) );
+ memset( &state.port, 0, sizeof(state.port) );
+
+ state.ad_sample = 0;
+ state.ad_ref_index = 0;
+
+ state.addr = 0;
+ state.freq = 0;
+ state.writeptr = 0;
+ state.readptr = 0;
+ state.playflag = 0;
+ state.repeatflag = 0;
+ state.length = 0;
+ state.volume = 0xFF;
+ state.fadetimer = 0;
+ state.fadecount = 0;
+}
+
+void Hes_Apu_Adpcm::set_output( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+ // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
+ require( !center || (center && !left && !right) || (center && left && right) );
+ require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
+
+ if ( !center || !left || !right )
+ {
+ left = center;
+ right = center;
+ }
+
+ output = center;
+}
+
+void Hes_Apu_Adpcm::run_until( blip_time_t end_time )
+{
+ int volume = state.volume;
+ int fadetimer = state.fadetimer;
+ int fadecount = state.fadecount;
+ int last_time = this->last_time;
+ double next_timer = this->next_timer;
+ int last_amp = this->last_amp;
+
+ Blip_Buffer* output = this->output; // cache often-used values
+
+ while ( state.playflag && last_time < end_time )
+ {
+ while ( last_time >= next_timer )
+ {
+ if ( fadetimer )
+ {
+ if ( fadecount > 0 )
+ {
+ fadecount--;
+ volume = 0xFF * fadecount / fadetimer;
+ }
+ else if ( fadecount < 0 )
+ {
+ fadecount++;
+ volume = 0xFF - ( 0xFF * fadecount / fadetimer );
+ }
+ }
+ next_timer += 7159.091;
+ }
+ int amp;
+ if ( state.ad_low_nibble )
+ {
+ amp = adpcm_decode( state.pcmbuf[ state.playptr ] & 0x0F );
+ state.ad_low_nibble = false;
+ state.playptr++;
+ state.playedsamplecount++;
+ if ( state.playedsamplecount == state.playlength )
+ {
+ state.playflag = 0;
+ }
+ }
+ else
+ {
+ amp = adpcm_decode( state.pcmbuf[ state.playptr ] >> 4 );
+ state.ad_low_nibble = true;
+ }
+ amp = amp * volume / 0xFF;
+ int delta = amp - last_amp;
+ if ( output && delta )
+ {
+ last_amp = amp;
+ synth.offset_inline( last_time, delta, output );
+ }
+ last_time += state.freq;
+ }
+
+ if ( !state.playflag )
+ {
+ while ( next_timer <= end_time ) next_timer += 7159.091;
+ last_time = end_time;
+ }
+
+ this->last_time = last_time;
+ this->next_timer = next_timer;
+ this->last_amp = last_amp;
+ state.volume = volume;
+ state.fadetimer = fadetimer;
+ state.fadecount = fadecount;
+}
+
+void Hes_Apu_Adpcm::write_data( blip_time_t time, int addr, int data )
+{
+ if ( time > last_time ) run_until( time );
+
+ data &= 0xFF;
+ state.port[ addr & 15 ] = data;
+ switch ( addr & 15 )
+ {
+ case 8:
+ state.addr &= 0xFF00;
+ state.addr |= data;
+ break;
+ case 9:
+ state.addr &= 0xFF;
+ state.addr |= data << 8;
+ break;
+ case 10:
+ state.pcmbuf[ state.writeptr++ ] = data;
+ state.playlength ++;
+ break;
+ case 11:
+ dprintf("ADPCM DMA 0x%02X", data);
+ break;
+ case 13:
+ if ( data & 0x80 )
+ {
+ state.addr = 0;
+ state.freq = 0;
+ state.writeptr = 0;
+ state.readptr = 0;
+ state.playflag = 0;
+ state.repeatflag = 0;
+ state.length = 0;
+ state.volume = 0xFF;
+ }
+ if ( ( data & 3 ) == 3 )
+ {
+ state.writeptr = state.addr;
+ }
+ if ( data & 8 )
+ {
+ state.readptr = state.addr ? state.addr - 1 : state.addr;
+ }
+ if ( data & 0x10 )
+ {
+ state.length = state.addr;
+ }
+ state.repeatflag = data & 0x20;
+ state.playflag = data & 0x40;
+ if ( state.playflag )
+ {
+ state.playptr = state.readptr;
+ state.playlength = state.length + 1;
+ state.playedsamplecount = 0;
+ state.ad_sample = 0;
+ state.ad_low_nibble = false;
+ }
+ break;
+ case 14:
+ state.freq = 7159091 / ( 32000 / ( 16 - ( data & 15 ) ) );
+ break;
+ case 15:
+ switch ( data & 15 )
+ {
+ case 0:
+ case 8:
+ case 12:
+ state.fadetimer = -100;
+ state.fadecount = state.fadetimer;
+ break;
+ case 10:
+ state.fadetimer = 5000;
+ state.fadecount = state.fadetimer;
+ break;
+ case 14:
+ state.fadetimer = 1500;
+ state.fadecount = state.fadetimer;
+ break;
+ }
+ break;
+ }
+}
+
+int Hes_Apu_Adpcm::read_data( blip_time_t time, int addr )
+{
+ if ( time > last_time ) run_until( time );
+
+ switch ( addr & 15 )
+ {
+ case 10:
+ return state.pcmbuf [state.readptr++];
+ case 11:
+ return state.port [11] & ~1;
+ case 12:
+ if (!state.playflag)
+ {
+ state.port [12] |= 1;
+ state.port [12] &= ~8;
+ }
+ else
+ {
+ state.port [12] &= ~1;
+ state.port [12] |= 8;
+ }
+ return state.port [12];
+ case 13:
+ return state.port [13];
+ }
+
+ return 0xFF;
+}
+
+void Hes_Apu_Adpcm::end_frame( blip_time_t end_time )
+{
+ run_until( end_time );
+ last_time -= end_time;
+ next_timer -= (double)end_time;
+ check( last_time >= 0 );
+ if ( output )
+ output->set_modified();
+}
+
+static short stepsize[49] = {
+ 16, 17, 19, 21, 23, 25, 28,
+ 31, 34, 37, 41, 45, 50, 55,
+ 60, 66, 73, 80, 88, 97, 107,
+ 118, 130, 143, 157, 173, 190, 209,
+ 230, 253, 279, 307, 337, 371, 408,
+ 449, 494, 544, 598, 658, 724, 796,
+ 876, 963,1060,1166,1282,1411,1552
+};
+
+int Hes_Apu_Adpcm::adpcm_decode( int code )
+{
+ int step = stepsize[state.ad_ref_index];
+ int delta;
+ int c = code & 7;
+#if 1
+ delta = 0;
+ if ( c & 4 ) delta += step;
+ step >>= 1;
+ if ( c & 2 ) delta += step;
+ step >>= 1;
+ if ( c & 1 ) delta += step;
+ step >>= 1;
+ delta += step;
+#else
+ delta = ( ( c + c + 1 ) * step ) / 8; // maybe faster, but introduces rounding
+#endif
+ if ( c != code )
+ {
+ state.ad_sample -= delta;
+ if ( state.ad_sample < -2048 )
+ state.ad_sample = -2048;
+ }
+ else
+ {
+ state.ad_sample += delta;
+ if ( state.ad_sample > 2047 )
+ state.ad_sample = 2047;
+ }
+
+ static int const steps [8] = {
+ -1, -1, -1, -1, 2, 4, 6, 8
+ };
+ state.ad_ref_index += steps [c];
+ if ( state.ad_ref_index < 0 )
+ state.ad_ref_index = 0;
+ else if ( state.ad_ref_index > 48 )
+ state.ad_ref_index = 48;
+
+ return state.ad_sample;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Hes_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Hes_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Hes_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Hes_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,192 +1,192 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Hes_Emu.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Hes_Emu::Hes_Emu()
-{
- set_type( gme_hes_type );
- set_silence_lookahead( 6 );
- set_gain( 1.11 );
-}
-
-Hes_Emu::~Hes_Emu() { }
-
-void Hes_Emu::unload()
-{
- core.unload();
- Music_Emu::unload();
-}
-
-static byte const* copy_field( byte const in [], char* out )
-{
- if ( in )
- {
- int len = 0x20;
- if ( in [0x1F] && !in [0x2F] )
- len = 0x30; // fields are sometimes 16 bytes longer (ugh)
-
- // since text fields are where any data could be, detect non-text
- // and fields with data after zero byte terminator
-
- int i = 0;
- for ( ; i < len && in [i]; i++ )
- if ( (unsigned) (in [i] - ' ') >= 0xFF - ' ' ) // also treat 0xFF as non-text
- return 0; // non-ASCII found
-
- for ( ; i < len; i++ )
- if ( in [i] )
- return 0; // data after terminator
-
- Gme_File::copy_field_( out, (char const*) in, len );
- in += len;
- }
- return in;
-}
-
-static byte const* copy_hes_fields( byte const in [], track_info_t* out )
-{
- byte const* in_offset = in;
- if ( *in_offset >= ' ' )
- {
- in_offset = copy_field( in_offset, out->game );
- in_offset = copy_field( in_offset, out->author );
- in_offset = copy_field( in_offset, out->copyright );
- }
- return in_offset ? in_offset : in;
-}
-
-static void hash_hes_file( Hes_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.vers, sizeof(h.vers) );
- out.hash_( &h.first_track, sizeof(h.first_track) );
- out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
- out.hash_( &h.banks[0], sizeof(h.banks) );
- out.hash_( &h.data_size[0], sizeof(h.data_size) );
- out.hash_( &h.addr[0], sizeof(h.addr) );
- out.hash_( &h.unused[0], sizeof(h.unused) );
- out.hash_( data, Hes_Core::info_offset );
-
- track_info_t temp; // GCC whines about passing a pointer to a temporary here
- byte const* more_data = copy_hes_fields( data + Hes_Core::info_offset, &temp );
- out.hash_( more_data, data_size - ( more_data - data ) );
-}
-
-blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_hes_fields( core.data() + core.info_offset, out );
- return blargg_ok;
-}
-
-struct Hes_File : Gme_Info_
-{
- enum { fields_offset = Hes_Core::header_t::size + Hes_Core::info_offset };
-
- union header_t {
- Hes_Core::header_t header;
- byte data [fields_offset + 0x30 * 3];
- } const* h;
-
- Hes_File()
- {
- set_type( gme_hes_type );
- }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- h = ( header_t const* ) begin;
-
- if ( !h->header.valid_tag() )
- return blargg_err_file_type;
-
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_hes_fields( h->data + fields_offset, out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_hes_file( h->header, file_begin() + h->header.size, file_end() - file_begin() - h->header.size, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
-static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
-
-gme_type_t_ const gme_hes_type [1] = {{ "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 }};
-
-blargg_err_t Hes_Emu::load_( Data_Reader& in )
-{
- RETURN_ERR( core.load( in ) );
-
- static const char* const names [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2", "ADPCM"
- };
- set_voice_names( names );
-
- static int const types [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = {
- wave_type+0, wave_type+1, wave_type+2, wave_type+3, mixed_type+0, mixed_type+1, mixed_type+2
- };
- set_voice_types( types );
-
- set_voice_count( core.apu().osc_count + core.adpcm().osc_count );
- core.apu().volume( gain() );
- core.adpcm().volume( gain() );
-
- return setup_buffer( 7159091 );
-}
-
-void Hes_Emu::update_eq( blip_eq_t const& eq )
-{
- core.apu().treble_eq( eq );
- core.adpcm().treble_eq( eq );
-}
-
-void Hes_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- if ( i < core.apu().osc_count )
- core.apu().set_output( i, c, l, r );
- else if ( i == core.apu().osc_count )
- core.adpcm().set_output( 0, c, l, r );
-}
-
-void Hes_Emu::set_tempo_( double t )
-{
- core.set_tempo( t );
-}
-
-blargg_err_t Hes_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
- return core.start_track( track );
-}
-
-blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
-{
- return core.end_frame( duration_ );
-}
-
-blargg_err_t Hes_Emu::hash_( Hash_Function& out ) const
-{
- hash_hes_file( header(), core.data(), core.data_size(), out );
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Hes_Emu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Hes_Emu::Hes_Emu()
+{
+ set_type( gme_hes_type );
+ set_silence_lookahead( 6 );
+ set_gain( 1.11 );
+}
+
+Hes_Emu::~Hes_Emu() { }
+
+void Hes_Emu::unload()
+{
+ core.unload();
+ Music_Emu::unload();
+}
+
+static byte const* copy_field( byte const in [], char* out )
+{
+ if ( in )
+ {
+ int len = 0x20;
+ if ( in [0x1F] && !in [0x2F] )
+ len = 0x30; // fields are sometimes 16 bytes longer (ugh)
+
+ // since text fields are where any data could be, detect non-text
+ // and fields with data after zero byte terminator
+
+ int i = 0;
+ for ( ; i < len && in [i]; i++ )
+ if ( (unsigned) (in [i] - ' ') >= 0xFF - ' ' ) // also treat 0xFF as non-text
+ return 0; // non-ASCII found
+
+ for ( ; i < len; i++ )
+ if ( in [i] )
+ return 0; // data after terminator
+
+ Gme_File::copy_field_( out, (char const*) in, len );
+ in += len;
+ }
+ return in;
+}
+
+static byte const* copy_hes_fields( byte const in [], track_info_t* out )
+{
+ byte const* in_offset = in;
+ if ( *in_offset >= ' ' )
+ {
+ in_offset = copy_field( in_offset, out->game );
+ in_offset = copy_field( in_offset, out->author );
+ in_offset = copy_field( in_offset, out->copyright );
+ }
+ return in_offset ? in_offset : in;
+}
+
+static void hash_hes_file( Hes_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.vers, sizeof(h.vers) );
+ out.hash_( &h.first_track, sizeof(h.first_track) );
+ out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
+ out.hash_( &h.banks[0], sizeof(h.banks) );
+ out.hash_( &h.data_size[0], sizeof(h.data_size) );
+ out.hash_( &h.addr[0], sizeof(h.addr) );
+ out.hash_( &h.unused[0], sizeof(h.unused) );
+ out.hash_( data, Hes_Core::info_offset );
+
+ track_info_t temp; // GCC whines about passing a pointer to a temporary here
+ byte const* more_data = copy_hes_fields( data + Hes_Core::info_offset, &temp );
+ out.hash_( more_data, data_size - ( more_data - data ) );
+}
+
+blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
+{
+ copy_hes_fields( core.data() + core.info_offset, out );
+ return blargg_ok;
+}
+
+struct Hes_File : Gme_Info_
+{
+ enum { fields_offset = Hes_Core::header_t::size + Hes_Core::info_offset };
+
+ union header_t {
+ Hes_Core::header_t header;
+ byte data [fields_offset + 0x30 * 3];
+ } const* h;
+
+ Hes_File()
+ {
+ set_type( gme_hes_type );
+ }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ h = ( header_t const* ) begin;
+
+ if ( !h->header.valid_tag() )
+ return blargg_err_file_type;
+
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_hes_fields( h->data + fields_offset, out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_hes_file( h->header, file_begin() + h->header.size, file_end() - file_begin() - h->header.size, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
+static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
+
+gme_type_t_ const gme_hes_type [1] = {{ "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 }};
+
+blargg_err_t Hes_Emu::load_( Data_Reader& in )
+{
+ RETURN_ERR( core.load( in ) );
+
+ static const char* const names [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = {
+ "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2", "ADPCM"
+ };
+ set_voice_names( names );
+
+ static int const types [Hes_Apu::osc_count + Hes_Apu_Adpcm::osc_count] = {
+ wave_type+0, wave_type+1, wave_type+2, wave_type+3, mixed_type+0, mixed_type+1, mixed_type+2
+ };
+ set_voice_types( types );
+
+ set_voice_count( core.apu().osc_count + core.adpcm().osc_count );
+ core.apu().volume( gain() );
+ core.adpcm().volume( gain() );
+
+ return setup_buffer( 7159091 );
+}
+
+void Hes_Emu::update_eq( blip_eq_t const& eq )
+{
+ core.apu().treble_eq( eq );
+ core.adpcm().treble_eq( eq );
+}
+
+void Hes_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+ if ( i < core.apu().osc_count )
+ core.apu().set_output( i, c, l, r );
+ else if ( i == core.apu().osc_count )
+ core.adpcm().set_output( 0, c, l, r );
+}
+
+void Hes_Emu::set_tempo_( double t )
+{
+ core.set_tempo( t );
+}
+
+blargg_err_t Hes_Emu::start_track_( int track )
+{
+ RETURN_ERR( Classic_Emu::start_track_( track ) );
+ return core.start_track( track );
+}
+
+blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
+{
+ return core.end_frame( duration_ );
+}
+
+blargg_err_t Hes_Emu::hash_( Hash_Function& out ) const
+{
+ hash_hes_file( header(), core.data(), core.data_size(), out );
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/higan/dsp/SPC_DSP.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/higan/dsp/SPC_DSP.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/higan/dsp/SPC_DSP.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/higan/dsp/SPC_DSP.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -135,302 +135,302 @@
1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
};
-static short const cubic [514] =
-{
- 0, -4, -8, -12, -16, -20, -23, -27, -30, -34, -37, -41, -44, -47, -50, -53,
- -56, -59, -62, -65, -68, -71, -73, -76, -78, -81, -84, -87, -89, -91, -93, -95,
- -98,-100,-102,-104,-106,-109,-110,-112,-113,-116,-117,-119,-121,-122,-123,-125,
--126,-128,-129,-131,-132,-134,-134,-136,-136,-138,-138,-140,-141,-141,-142,-143,
--144,-144,-145,-146,-147,-148,-147,-148,-148,-149,-149,-150,-150,-150,-150,-151,
--151,-151,-151,-151,-152,-152,-151,-152,-151,-152,-151,-151,-151,-151,-150,-150,
--150,-149,-149,-149,-149,-148,-147,-147,-146,-146,-145,-145,-144,-144,-143,-142,
--141,-141,-140,-139,-139,-138,-137,-136,-135,-135,-133,-133,-132,-131,-130,-129,
--128,-127,-126,-125,-124,-123,-121,-121,-119,-118,-117,-116,-115,-114,-112,-111,
--110,-109,-107,-106,-105,-104,-102,-102,-100, -99, -97, -97, -95, -94, -92, -91,
- -90, -88, -87, -86, -85, -84, -82, -81, -79, -78, -76, -76, -74, -73, -71, -70,
- -68, -67, -66, -65, -63, -62, -60, -60, -58, -57, -55, -55, -53, -52, -50, -49,
- -48, -46, -45, -44, -43, -42, -40, -39, -38, -37, -36, -35, -34, -32, -31, -30,
- -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -19, -17, -16, -15, -14,
- -14, -13, -12, -11, -11, -10, -9, -9, -8, -8, -7, -7, -6, -5, -4, -4,
- -3, -3, -3, -2, -2, -2, -1, -1, 0, -1, 0, -1, 0, 0, 0, 0,
- 0,
-2048,2048,2048,2048,2047,2047,2046,2045,2043,2042,2041,2039,2037,2035,2033,2031,
-2028,2026,2024,2021,2018,2015,2012,2009,2005,2002,1999,1995,1991,1987,1982,1978,
-1974,1969,1965,1960,1955,1951,1946,1940,1934,1929,1924,1918,1912,1906,1900,1895,
-1888,1882,1875,1869,1862,1856,1849,1842,1835,1828,1821,1814,1806,1799,1791,1783,
-1776,1768,1760,1753,1744,1737,1728,1720,1711,1703,1695,1686,1677,1668,1659,1651,
-1641,1633,1623,1614,1605,1596,1587,1577,1567,1559,1549,1539,1529,1520,1510,1499,
-1490,1480,1470,1460,1450,1440,1430,1420,1408,1398,1389,1378,1367,1357,1346,1336,
-1325,1315,1304,1293,1282,1272,1261,1250,1239,1229,1218,1207,1196,1185,1174,1163,
-1152,1141,1130,1119,1108,1097,1086,1075,1063,1052,1042,1030,1019,1008, 997, 986,
- 974, 964, 952, 941, 930, 919, 908, 897, 886, 875, 864, 853, 842, 831, 820, 809,
- 798, 787, 776, 765, 754, 744, 733, 722, 711, 700, 690, 679, 668, 658, 647, 637,
- 626, 616, 605, 595, 584, 574, 564, 554, 543, 534, 524, 514, 503, 494, 483, 473,
- 464, 454, 444, 435, 425, 416, 407, 397, 387, 378, 370, 360, 351, 342, 333, 325,
- 315, 307, 298, 290, 281, 273, 265, 256, 248, 241, 233, 225, 216, 209, 201, 193,
- 186, 178, 171, 164, 157, 150, 143, 137, 129, 123, 117, 110, 103, 97, 91, 85,
- 79, 74, 68, 62, 56, 51, 46, 41, 35, 31, 27, 22, 17, 13, 8, 4,
- 0
-};
-
-static short const sinc [2048] =
-{
- 39, -315, 666, 15642, 666, -315, 39, -38,
- 38, -302, 613, 15642, 718, -328, 41, -38,
- 36, -288, 561, 15641, 772, -342, 42, -38,
- 35, -275, 510, 15639, 826, -355, 44, -38,
- 33, -263, 459, 15636, 880, -369, 46, -38,
- 32, -250, 408, 15632, 935, -383, 47, -38,
- 31, -237, 358, 15628, 990, -396, 49, -38,
- 29, -224, 309, 15622, 1046, -410, 51, -38,
- 28, -212, 259, 15616, 1103, -425, 53, -38,
- 27, -200, 211, 15609, 1159, -439, 54, -38,
- 25, -188, 163, 15601, 1216, -453, 56, -38,
- 24, -175, 115, 15593, 1274, -467, 58, -38,
- 23, -164, 68, 15583, 1332, -482, 60, -38,
- 22, -152, 22, 15573, 1391, -496, 62, -37,
- 21, -140, -24, 15562, 1450, -511, 64, -37,
- 19, -128, -70, 15550, 1509, -526, 66, -37,
- 18, -117, -115, 15538, 1569, -540, 68, -37,
- 17, -106, -159, 15524, 1629, -555, 70, -37,
- 16, -94, -203, 15510, 1690, -570, 72, -36,
- 15, -83, -247, 15495, 1751, -585, 74, -36,
- 14, -72, -289, 15479, 1813, -600, 76, -36,
- 13, -62, -332, 15462, 1875, -616, 79, -36,
- 12, -51, -374, 15445, 1937, -631, 81, -35,
- 11, -40, -415, 15426, 2000, -646, 83, -35,
- 11, -30, -456, 15407, 2063, -662, 85, -35,
- 10, -20, -496, 15387, 2127, -677, 88, -34,
- 9, -9, -536, 15366, 2191, -693, 90, -34,
- 8, 1, -576, 15345, 2256, -708, 92, -34,
- 7, 10, -614, 15323, 2321, -724, 95, -33,
- 7, 20, -653, 15300, 2386, -740, 97, -33,
- 6, 30, -690, 15276, 2451, -755, 99, -33,
- 5, 39, -728, 15251, 2517, -771, 102, -32,
- 5, 49, -764, 15226, 2584, -787, 104, -32,
- 4, 58, -801, 15200, 2651, -803, 107, -32,
- 3, 67, -836, 15173, 2718, -819, 109, -31,
- 3, 76, -871, 15145, 2785, -835, 112, -31,
- 2, 85, -906, 15117, 2853, -851, 115, -30,
- 2, 93, -940, 15087, 2921, -867, 117, -30,
- 1, 102, -974, 15057, 2990, -883, 120, -29,
- 1, 110, -1007, 15027, 3059, -899, 122, -29,
- 0, 118, -1039, 14995, 3128, -915, 125, -29,
- 0, 127, -1071, 14963, 3198, -931, 128, -28,
- -1, 135, -1103, 14930, 3268, -948, 131, -28,
- -1, 142, -1134, 14896, 3338, -964, 133, -27,
- -1, 150, -1164, 14862, 3409, -980, 136, -27,
- -2, 158, -1194, 14827, 3480, -996, 139, -26,
- -2, 165, -1224, 14791, 3551, -1013, 142, -26,
- -3, 172, -1253, 14754, 3622, -1029, 144, -25,
- -3, 179, -1281, 14717, 3694, -1045, 147, -25,
- -3, 187, -1309, 14679, 3766, -1062, 150, -24,
- -3, 193, -1337, 14640, 3839, -1078, 153, -24,
- -4, 200, -1363, 14601, 3912, -1094, 156, -23,
- -4, 207, -1390, 14561, 3985, -1110, 159, -23,
- -4, 213, -1416, 14520, 4058, -1127, 162, -22,
- -4, 220, -1441, 14479, 4131, -1143, 165, -22,
- -4, 226, -1466, 14437, 4205, -1159, 168, -22,
- -5, 232, -1490, 14394, 4279, -1175, 171, -21,
- -5, 238, -1514, 14350, 4354, -1192, 174, -21,
- -5, 244, -1537, 14306, 4428, -1208, 177, -20,
- -5, 249, -1560, 14261, 4503, -1224, 180, -20,
- -5, 255, -1583, 14216, 4578, -1240, 183, -19,
- -5, 260, -1604, 14169, 4653, -1256, 186, -19,
- -5, 265, -1626, 14123, 4729, -1272, 189, -18,
- -5, 271, -1647, 14075, 4805, -1288, 192, -18,
- -5, 276, -1667, 14027, 4881, -1304, 195, -17,
- -6, 280, -1687, 13978, 4957, -1320, 198, -17,
- -6, 285, -1706, 13929, 5033, -1336, 201, -16,
- -6, 290, -1725, 13879, 5110, -1352, 204, -16,
- -6, 294, -1744, 13829, 5186, -1368, 207, -15,
- -6, 299, -1762, 13777, 5263, -1383, 210, -15,
- -6, 303, -1779, 13726, 5340, -1399, 213, -14,
- -6, 307, -1796, 13673, 5418, -1414, 216, -14,
- -6, 311, -1813, 13620, 5495, -1430, 219, -13,
- -5, 315, -1829, 13567, 5573, -1445, 222, -13,
- -5, 319, -1844, 13512, 5651, -1461, 225, -13,
- -5, 322, -1859, 13458, 5728, -1476, 229, -12,
- -5, 326, -1874, 13402, 5806, -1491, 232, -12,
- -5, 329, -1888, 13347, 5885, -1506, 235, -11,
- -5, 332, -1902, 13290, 5963, -1521, 238, -11,
- -5, 335, -1915, 13233, 6041, -1536, 241, -10,
- -5, 338, -1928, 13176, 6120, -1551, 244, -10,
- -5, 341, -1940, 13118, 6199, -1566, 247, -10,
- -5, 344, -1952, 13059, 6277, -1580, 250, -9,
- -5, 347, -1964, 13000, 6356, -1595, 253, -9,
- -5, 349, -1975, 12940, 6435, -1609, 256, -8,
- -4, 352, -1986, 12880, 6514, -1623, 259, -8,
- -4, 354, -1996, 12819, 6594, -1637, 262, -8,
- -4, 356, -2005, 12758, 6673, -1651, 265, -7,
- -4, 358, -2015, 12696, 6752, -1665, 268, -7,
- -4, 360, -2024, 12634, 6831, -1679, 271, -7,
- -4, 362, -2032, 12572, 6911, -1693, 274, -6,
- -4, 364, -2040, 12509, 6990, -1706, 277, -6,
- -4, 366, -2048, 12445, 7070, -1719, 280, -6,
- -3, 367, -2055, 12381, 7149, -1732, 283, -5,
- -3, 369, -2062, 12316, 7229, -1745, 286, -5,
- -3, 370, -2068, 12251, 7308, -1758, 289, -5,
- -3, 371, -2074, 12186, 7388, -1771, 291, -4,
- -3, 372, -2079, 12120, 7467, -1784, 294, -4,
- -3, 373, -2084, 12054, 7547, -1796, 297, -4,
- -3, 374, -2089, 11987, 7626, -1808, 300, -4,
- -2, 375, -2094, 11920, 7706, -1820, 303, -3,
- -2, 376, -2098, 11852, 7785, -1832, 305, -3,
- -2, 376, -2101, 11785, 7865, -1844, 308, -3,
- -2, 377, -2104, 11716, 7944, -1855, 311, -3,
- -2, 377, -2107, 11647, 8024, -1866, 313, -2,
- -2, 378, -2110, 11578, 8103, -1877, 316, -2,
- -2, 378, -2112, 11509, 8182, -1888, 318, -2,
- -1, 378, -2113, 11439, 8262, -1899, 321, -2,
- -1, 378, -2115, 11369, 8341, -1909, 323, -2,
- -1, 378, -2116, 11298, 8420, -1920, 326, -2,
- -1, 378, -2116, 11227, 8499, -1930, 328, -1,
- -1, 378, -2116, 11156, 8578, -1940, 331, -1,
- -1, 378, -2116, 11084, 8656, -1949, 333, -1,
- -1, 377, -2116, 11012, 8735, -1959, 335, -1,
- -1, 377, -2115, 10940, 8814, -1968, 337, -1,
- -1, 377, -2114, 10867, 8892, -1977, 340, -1,
- -1, 376, -2112, 10795, 8971, -1985, 342, -1,
- 0, 375, -2111, 10721, 9049, -1994, 344, -1,
- 0, 375, -2108, 10648, 9127, -2002, 346, 0,
- 0, 374, -2106, 10574, 9205, -2010, 348, 0,
- 0, 373, -2103, 10500, 9283, -2018, 350, 0,
- 0, 372, -2100, 10426, 9360, -2025, 352, 0,
- 0, 371, -2097, 10351, 9438, -2032, 354, 0,
- 0, 370, -2093, 10276, 9515, -2039, 355, 0,
- 0, 369, -2089, 10201, 9592, -2046, 357, 0,
- 0, 367, -2084, 10126, 9669, -2052, 359, 0,
- 0, 366, -2080, 10050, 9745, -2058, 360, 0,
- 0, 365, -2075, 9974, 9822, -2064, 362, 0,
- 0, 363, -2070, 9898, 9898, -2070, 363, 0,
- 0, 362, -2064, 9822, 9974, -2075, 365, 0,
- 0, 360, -2058, 9745, 10050, -2080, 366, 0,
- 0, 359, -2052, 9669, 10126, -2084, 367, 0,
- 0, 357, -2046, 9592, 10201, -2089, 369, 0,
- 0, 355, -2039, 9515, 10276, -2093, 370, 0,
- 0, 354, -2032, 9438, 10351, -2097, 371, 0,
- 0, 352, -2025, 9360, 10426, -2100, 372, 0,
- 0, 350, -2018, 9283, 10500, -2103, 373, 0,
- 0, 348, -2010, 9205, 10574, -2106, 374, 0,
- 0, 346, -2002, 9127, 10648, -2108, 375, 0,
- -1, 344, -1994, 9049, 10721, -2111, 375, 0,
- -1, 342, -1985, 8971, 10795, -2112, 376, -1,
- -1, 340, -1977, 8892, 10867, -2114, 377, -1,
- -1, 337, -1968, 8814, 10940, -2115, 377, -1,
- -1, 335, -1959, 8735, 11012, -2116, 377, -1,
- -1, 333, -1949, 8656, 11084, -2116, 378, -1,
- -1, 331, -1940, 8578, 11156, -2116, 378, -1,
- -1, 328, -1930, 8499, 11227, -2116, 378, -1,
- -2, 326, -1920, 8420, 11298, -2116, 378, -1,
- -2, 323, -1909, 8341, 11369, -2115, 378, -1,
- -2, 321, -1899, 8262, 11439, -2113, 378, -1,
- -2, 318, -1888, 8182, 11509, -2112, 378, -2,
- -2, 316, -1877, 8103, 11578, -2110, 378, -2,
- -2, 313, -1866, 8024, 11647, -2107, 377, -2,
- -3, 311, -1855, 7944, 11716, -2104, 377, -2,
- -3, 308, -1844, 7865, 11785, -2101, 376, -2,
- -3, 305, -1832, 7785, 11852, -2098, 376, -2,
- -3, 303, -1820, 7706, 11920, -2094, 375, -2,
- -4, 300, -1808, 7626, 11987, -2089, 374, -3,
- -4, 297, -1796, 7547, 12054, -2084, 373, -3,
- -4, 294, -1784, 7467, 12120, -2079, 372, -3,
- -4, 291, -1771, 7388, 12186, -2074, 371, -3,
- -5, 289, -1758, 7308, 12251, -2068, 370, -3,
- -5, 286, -1745, 7229, 12316, -2062, 369, -3,
- -5, 283, -1732, 7149, 12381, -2055, 367, -3,
- -6, 280, -1719, 7070, 12445, -2048, 366, -4,
- -6, 277, -1706, 6990, 12509, -2040, 364, -4,
- -6, 274, -1693, 6911, 12572, -2032, 362, -4,
- -7, 271, -1679, 6831, 12634, -2024, 360, -4,
- -7, 268, -1665, 6752, 12696, -2015, 358, -4,
- -7, 265, -1651, 6673, 12758, -2005, 356, -4,
- -8, 262, -1637, 6594, 12819, -1996, 354, -4,
- -8, 259, -1623, 6514, 12880, -1986, 352, -4,
- -8, 256, -1609, 6435, 12940, -1975, 349, -5,
- -9, 253, -1595, 6356, 13000, -1964, 347, -5,
- -9, 250, -1580, 6277, 13059, -1952, 344, -5,
- -10, 247, -1566, 6199, 13118, -1940, 341, -5,
- -10, 244, -1551, 6120, 13176, -1928, 338, -5,
- -10, 241, -1536, 6041, 13233, -1915, 335, -5,
- -11, 238, -1521, 5963, 13290, -1902, 332, -5,
- -11, 235, -1506, 5885, 13347, -1888, 329, -5,
- -12, 232, -1491, 5806, 13402, -1874, 326, -5,
- -12, 229, -1476, 5728, 13458, -1859, 322, -5,
- -13, 225, -1461, 5651, 13512, -1844, 319, -5,
- -13, 222, -1445, 5573, 13567, -1829, 315, -5,
- -13, 219, -1430, 5495, 13620, -1813, 311, -6,
- -14, 216, -1414, 5418, 13673, -1796, 307, -6,
- -14, 213, -1399, 5340, 13726, -1779, 303, -6,
- -15, 210, -1383, 5263, 13777, -1762, 299, -6,
- -15, 207, -1368, 5186, 13829, -1744, 294, -6,
- -16, 204, -1352, 5110, 13879, -1725, 290, -6,
- -16, 201, -1336, 5033, 13929, -1706, 285, -6,
- -17, 198, -1320, 4957, 13978, -1687, 280, -6,
- -17, 195, -1304, 4881, 14027, -1667, 276, -5,
- -18, 192, -1288, 4805, 14075, -1647, 271, -5,
- -18, 189, -1272, 4729, 14123, -1626, 265, -5,
- -19, 186, -1256, 4653, 14169, -1604, 260, -5,
- -19, 183, -1240, 4578, 14216, -1583, 255, -5,
- -20, 180, -1224, 4503, 14261, -1560, 249, -5,
- -20, 177, -1208, 4428, 14306, -1537, 244, -5,
- -21, 174, -1192, 4354, 14350, -1514, 238, -5,
- -21, 171, -1175, 4279, 14394, -1490, 232, -5,
- -22, 168, -1159, 4205, 14437, -1466, 226, -4,
- -22, 165, -1143, 4131, 14479, -1441, 220, -4,
- -22, 162, -1127, 4058, 14520, -1416, 213, -4,
- -23, 159, -1110, 3985, 14561, -1390, 207, -4,
- -23, 156, -1094, 3912, 14601, -1363, 200, -4,
- -24, 153, -1078, 3839, 14640, -1337, 193, -3,
- -24, 150, -1062, 3766, 14679, -1309, 187, -3,
- -25, 147, -1045, 3694, 14717, -1281, 179, -3,
- -25, 144, -1029, 3622, 14754, -1253, 172, -3,
- -26, 142, -1013, 3551, 14791, -1224, 165, -2,
- -26, 139, -996, 3480, 14827, -1194, 158, -2,
- -27, 136, -980, 3409, 14862, -1164, 150, -1,
- -27, 133, -964, 3338, 14896, -1134, 142, -1,
- -28, 131, -948, 3268, 14930, -1103, 135, -1,
- -28, 128, -931, 3198, 14963, -1071, 127, 0,
- -29, 125, -915, 3128, 14995, -1039, 118, 0,
- -29, 122, -899, 3059, 15027, -1007, 110, 1,
- -29, 120, -883, 2990, 15057, -974, 102, 1,
- -30, 117, -867, 2921, 15087, -940, 93, 2,
- -30, 115, -851, 2853, 15117, -906, 85, 2,
- -31, 112, -835, 2785, 15145, -871, 76, 3,
- -31, 109, -819, 2718, 15173, -836, 67, 3,
- -32, 107, -803, 2651, 15200, -801, 58, 4,
- -32, 104, -787, 2584, 15226, -764, 49, 5,
- -32, 102, -771, 2517, 15251, -728, 39, 5,
- -33, 99, -755, 2451, 15276, -690, 30, 6,
- -33, 97, -740, 2386, 15300, -653, 20, 7,
- -33, 95, -724, 2321, 15323, -614, 10, 7,
- -34, 92, -708, 2256, 15345, -576, 1, 8,
- -34, 90, -693, 2191, 15366, -536, -9, 9,
- -34, 88, -677, 2127, 15387, -496, -20, 10,
- -35, 85, -662, 2063, 15407, -456, -30, 11,
- -35, 83, -646, 2000, 15426, -415, -40, 11,
- -35, 81, -631, 1937, 15445, -374, -51, 12,
- -36, 79, -616, 1875, 15462, -332, -62, 13,
- -36, 76, -600, 1813, 15479, -289, -72, 14,
- -36, 74, -585, 1751, 15495, -247, -83, 15,
- -36, 72, -570, 1690, 15510, -203, -94, 16,
- -37, 70, -555, 1629, 15524, -159, -106, 17,
- -37, 68, -540, 1569, 15538, -115, -117, 18,
- -37, 66, -526, 1509, 15550, -70, -128, 19,
- -37, 64, -511, 1450, 15562, -24, -140, 21,
- -37, 62, -496, 1391, 15573, 22, -152, 22,
- -38, 60, -482, 1332, 15583, 68, -164, 23,
- -38, 58, -467, 1274, 15593, 115, -175, 24,
- -38, 56, -453, 1216, 15601, 163, -188, 25,
- -38, 54, -439, 1159, 15609, 211, -200, 27,
- -38, 53, -425, 1103, 15616, 259, -212, 28,
- -38, 51, -410, 1046, 15622, 309, -224, 29,
- -38, 49, -396, 990, 15628, 358, -237, 31,
- -38, 47, -383, 935, 15632, 408, -250, 32,
- -38, 46, -369, 880, 15636, 459, -263, 33,
- -38, 44, -355, 826, 15639, 510, -275, 35,
- -38, 42, -342, 772, 15641, 561, -288, 36,
- -38, 41, -328, 718, 15642, 613, -302, 38,
+static short const cubic [514] =
+{
+ 0, -4, -8, -12, -16, -20, -23, -27, -30, -34, -37, -41, -44, -47, -50, -53,
+ -56, -59, -62, -65, -68, -71, -73, -76, -78, -81, -84, -87, -89, -91, -93, -95,
+ -98,-100,-102,-104,-106,-109,-110,-112,-113,-116,-117,-119,-121,-122,-123,-125,
+-126,-128,-129,-131,-132,-134,-134,-136,-136,-138,-138,-140,-141,-141,-142,-143,
+-144,-144,-145,-146,-147,-148,-147,-148,-148,-149,-149,-150,-150,-150,-150,-151,
+-151,-151,-151,-151,-152,-152,-151,-152,-151,-152,-151,-151,-151,-151,-150,-150,
+-150,-149,-149,-149,-149,-148,-147,-147,-146,-146,-145,-145,-144,-144,-143,-142,
+-141,-141,-140,-139,-139,-138,-137,-136,-135,-135,-133,-133,-132,-131,-130,-129,
+-128,-127,-126,-125,-124,-123,-121,-121,-119,-118,-117,-116,-115,-114,-112,-111,
+-110,-109,-107,-106,-105,-104,-102,-102,-100, -99, -97, -97, -95, -94, -92, -91,
+ -90, -88, -87, -86, -85, -84, -82, -81, -79, -78, -76, -76, -74, -73, -71, -70,
+ -68, -67, -66, -65, -63, -62, -60, -60, -58, -57, -55, -55, -53, -52, -50, -49,
+ -48, -46, -45, -44, -43, -42, -40, -39, -38, -37, -36, -35, -34, -32, -31, -30,
+ -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -19, -17, -16, -15, -14,
+ -14, -13, -12, -11, -11, -10, -9, -9, -8, -8, -7, -7, -6, -5, -4, -4,
+ -3, -3, -3, -2, -2, -2, -1, -1, 0, -1, 0, -1, 0, 0, 0, 0,
+ 0,
+2048,2048,2048,2048,2047,2047,2046,2045,2043,2042,2041,2039,2037,2035,2033,2031,
+2028,2026,2024,2021,2018,2015,2012,2009,2005,2002,1999,1995,1991,1987,1982,1978,
+1974,1969,1965,1960,1955,1951,1946,1940,1934,1929,1924,1918,1912,1906,1900,1895,
+1888,1882,1875,1869,1862,1856,1849,1842,1835,1828,1821,1814,1806,1799,1791,1783,
+1776,1768,1760,1753,1744,1737,1728,1720,1711,1703,1695,1686,1677,1668,1659,1651,
+1641,1633,1623,1614,1605,1596,1587,1577,1567,1559,1549,1539,1529,1520,1510,1499,
+1490,1480,1470,1460,1450,1440,1430,1420,1408,1398,1389,1378,1367,1357,1346,1336,
+1325,1315,1304,1293,1282,1272,1261,1250,1239,1229,1218,1207,1196,1185,1174,1163,
+1152,1141,1130,1119,1108,1097,1086,1075,1063,1052,1042,1030,1019,1008, 997, 986,
+ 974, 964, 952, 941, 930, 919, 908, 897, 886, 875, 864, 853, 842, 831, 820, 809,
+ 798, 787, 776, 765, 754, 744, 733, 722, 711, 700, 690, 679, 668, 658, 647, 637,
+ 626, 616, 605, 595, 584, 574, 564, 554, 543, 534, 524, 514, 503, 494, 483, 473,
+ 464, 454, 444, 435, 425, 416, 407, 397, 387, 378, 370, 360, 351, 342, 333, 325,
+ 315, 307, 298, 290, 281, 273, 265, 256, 248, 241, 233, 225, 216, 209, 201, 193,
+ 186, 178, 171, 164, 157, 150, 143, 137, 129, 123, 117, 110, 103, 97, 91, 85,
+ 79, 74, 68, 62, 56, 51, 46, 41, 35, 31, 27, 22, 17, 13, 8, 4,
+ 0
+};
+
+static short const sinc [2048] =
+{
+ 39, -315, 666, 15642, 666, -315, 39, -38,
+ 38, -302, 613, 15642, 718, -328, 41, -38,
+ 36, -288, 561, 15641, 772, -342, 42, -38,
+ 35, -275, 510, 15639, 826, -355, 44, -38,
+ 33, -263, 459, 15636, 880, -369, 46, -38,
+ 32, -250, 408, 15632, 935, -383, 47, -38,
+ 31, -237, 358, 15628, 990, -396, 49, -38,
+ 29, -224, 309, 15622, 1046, -410, 51, -38,
+ 28, -212, 259, 15616, 1103, -425, 53, -38,
+ 27, -200, 211, 15609, 1159, -439, 54, -38,
+ 25, -188, 163, 15601, 1216, -453, 56, -38,
+ 24, -175, 115, 15593, 1274, -467, 58, -38,
+ 23, -164, 68, 15583, 1332, -482, 60, -38,
+ 22, -152, 22, 15573, 1391, -496, 62, -37,
+ 21, -140, -24, 15562, 1450, -511, 64, -37,
+ 19, -128, -70, 15550, 1509, -526, 66, -37,
+ 18, -117, -115, 15538, 1569, -540, 68, -37,
+ 17, -106, -159, 15524, 1629, -555, 70, -37,
+ 16, -94, -203, 15510, 1690, -570, 72, -36,
+ 15, -83, -247, 15495, 1751, -585, 74, -36,
+ 14, -72, -289, 15479, 1813, -600, 76, -36,
+ 13, -62, -332, 15462, 1875, -616, 79, -36,
+ 12, -51, -374, 15445, 1937, -631, 81, -35,
+ 11, -40, -415, 15426, 2000, -646, 83, -35,
+ 11, -30, -456, 15407, 2063, -662, 85, -35,
+ 10, -20, -496, 15387, 2127, -677, 88, -34,
+ 9, -9, -536, 15366, 2191, -693, 90, -34,
+ 8, 1, -576, 15345, 2256, -708, 92, -34,
+ 7, 10, -614, 15323, 2321, -724, 95, -33,
+ 7, 20, -653, 15300, 2386, -740, 97, -33,
+ 6, 30, -690, 15276, 2451, -755, 99, -33,
+ 5, 39, -728, 15251, 2517, -771, 102, -32,
+ 5, 49, -764, 15226, 2584, -787, 104, -32,
+ 4, 58, -801, 15200, 2651, -803, 107, -32,
+ 3, 67, -836, 15173, 2718, -819, 109, -31,
+ 3, 76, -871, 15145, 2785, -835, 112, -31,
+ 2, 85, -906, 15117, 2853, -851, 115, -30,
+ 2, 93, -940, 15087, 2921, -867, 117, -30,
+ 1, 102, -974, 15057, 2990, -883, 120, -29,
+ 1, 110, -1007, 15027, 3059, -899, 122, -29,
+ 0, 118, -1039, 14995, 3128, -915, 125, -29,
+ 0, 127, -1071, 14963, 3198, -931, 128, -28,
+ -1, 135, -1103, 14930, 3268, -948, 131, -28,
+ -1, 142, -1134, 14896, 3338, -964, 133, -27,
+ -1, 150, -1164, 14862, 3409, -980, 136, -27,
+ -2, 158, -1194, 14827, 3480, -996, 139, -26,
+ -2, 165, -1224, 14791, 3551, -1013, 142, -26,
+ -3, 172, -1253, 14754, 3622, -1029, 144, -25,
+ -3, 179, -1281, 14717, 3694, -1045, 147, -25,
+ -3, 187, -1309, 14679, 3766, -1062, 150, -24,
+ -3, 193, -1337, 14640, 3839, -1078, 153, -24,
+ -4, 200, -1363, 14601, 3912, -1094, 156, -23,
+ -4, 207, -1390, 14561, 3985, -1110, 159, -23,
+ -4, 213, -1416, 14520, 4058, -1127, 162, -22,
+ -4, 220, -1441, 14479, 4131, -1143, 165, -22,
+ -4, 226, -1466, 14437, 4205, -1159, 168, -22,
+ -5, 232, -1490, 14394, 4279, -1175, 171, -21,
+ -5, 238, -1514, 14350, 4354, -1192, 174, -21,
+ -5, 244, -1537, 14306, 4428, -1208, 177, -20,
+ -5, 249, -1560, 14261, 4503, -1224, 180, -20,
+ -5, 255, -1583, 14216, 4578, -1240, 183, -19,
+ -5, 260, -1604, 14169, 4653, -1256, 186, -19,
+ -5, 265, -1626, 14123, 4729, -1272, 189, -18,
+ -5, 271, -1647, 14075, 4805, -1288, 192, -18,
+ -5, 276, -1667, 14027, 4881, -1304, 195, -17,
+ -6, 280, -1687, 13978, 4957, -1320, 198, -17,
+ -6, 285, -1706, 13929, 5033, -1336, 201, -16,
+ -6, 290, -1725, 13879, 5110, -1352, 204, -16,
+ -6, 294, -1744, 13829, 5186, -1368, 207, -15,
+ -6, 299, -1762, 13777, 5263, -1383, 210, -15,
+ -6, 303, -1779, 13726, 5340, -1399, 213, -14,
+ -6, 307, -1796, 13673, 5418, -1414, 216, -14,
+ -6, 311, -1813, 13620, 5495, -1430, 219, -13,
+ -5, 315, -1829, 13567, 5573, -1445, 222, -13,
+ -5, 319, -1844, 13512, 5651, -1461, 225, -13,
+ -5, 322, -1859, 13458, 5728, -1476, 229, -12,
+ -5, 326, -1874, 13402, 5806, -1491, 232, -12,
+ -5, 329, -1888, 13347, 5885, -1506, 235, -11,
+ -5, 332, -1902, 13290, 5963, -1521, 238, -11,
+ -5, 335, -1915, 13233, 6041, -1536, 241, -10,
+ -5, 338, -1928, 13176, 6120, -1551, 244, -10,
+ -5, 341, -1940, 13118, 6199, -1566, 247, -10,
+ -5, 344, -1952, 13059, 6277, -1580, 250, -9,
+ -5, 347, -1964, 13000, 6356, -1595, 253, -9,
+ -5, 349, -1975, 12940, 6435, -1609, 256, -8,
+ -4, 352, -1986, 12880, 6514, -1623, 259, -8,
+ -4, 354, -1996, 12819, 6594, -1637, 262, -8,
+ -4, 356, -2005, 12758, 6673, -1651, 265, -7,
+ -4, 358, -2015, 12696, 6752, -1665, 268, -7,
+ -4, 360, -2024, 12634, 6831, -1679, 271, -7,
+ -4, 362, -2032, 12572, 6911, -1693, 274, -6,
+ -4, 364, -2040, 12509, 6990, -1706, 277, -6,
+ -4, 366, -2048, 12445, 7070, -1719, 280, -6,
+ -3, 367, -2055, 12381, 7149, -1732, 283, -5,
+ -3, 369, -2062, 12316, 7229, -1745, 286, -5,
+ -3, 370, -2068, 12251, 7308, -1758, 289, -5,
+ -3, 371, -2074, 12186, 7388, -1771, 291, -4,
+ -3, 372, -2079, 12120, 7467, -1784, 294, -4,
+ -3, 373, -2084, 12054, 7547, -1796, 297, -4,
+ -3, 374, -2089, 11987, 7626, -1808, 300, -4,
+ -2, 375, -2094, 11920, 7706, -1820, 303, -3,
+ -2, 376, -2098, 11852, 7785, -1832, 305, -3,
+ -2, 376, -2101, 11785, 7865, -1844, 308, -3,
+ -2, 377, -2104, 11716, 7944, -1855, 311, -3,
+ -2, 377, -2107, 11647, 8024, -1866, 313, -2,
+ -2, 378, -2110, 11578, 8103, -1877, 316, -2,
+ -2, 378, -2112, 11509, 8182, -1888, 318, -2,
+ -1, 378, -2113, 11439, 8262, -1899, 321, -2,
+ -1, 378, -2115, 11369, 8341, -1909, 323, -2,
+ -1, 378, -2116, 11298, 8420, -1920, 326, -2,
+ -1, 378, -2116, 11227, 8499, -1930, 328, -1,
+ -1, 378, -2116, 11156, 8578, -1940, 331, -1,
+ -1, 378, -2116, 11084, 8656, -1949, 333, -1,
+ -1, 377, -2116, 11012, 8735, -1959, 335, -1,
+ -1, 377, -2115, 10940, 8814, -1968, 337, -1,
+ -1, 377, -2114, 10867, 8892, -1977, 340, -1,
+ -1, 376, -2112, 10795, 8971, -1985, 342, -1,
+ 0, 375, -2111, 10721, 9049, -1994, 344, -1,
+ 0, 375, -2108, 10648, 9127, -2002, 346, 0,
+ 0, 374, -2106, 10574, 9205, -2010, 348, 0,
+ 0, 373, -2103, 10500, 9283, -2018, 350, 0,
+ 0, 372, -2100, 10426, 9360, -2025, 352, 0,
+ 0, 371, -2097, 10351, 9438, -2032, 354, 0,
+ 0, 370, -2093, 10276, 9515, -2039, 355, 0,
+ 0, 369, -2089, 10201, 9592, -2046, 357, 0,
+ 0, 367, -2084, 10126, 9669, -2052, 359, 0,
+ 0, 366, -2080, 10050, 9745, -2058, 360, 0,
+ 0, 365, -2075, 9974, 9822, -2064, 362, 0,
+ 0, 363, -2070, 9898, 9898, -2070, 363, 0,
+ 0, 362, -2064, 9822, 9974, -2075, 365, 0,
+ 0, 360, -2058, 9745, 10050, -2080, 366, 0,
+ 0, 359, -2052, 9669, 10126, -2084, 367, 0,
+ 0, 357, -2046, 9592, 10201, -2089, 369, 0,
+ 0, 355, -2039, 9515, 10276, -2093, 370, 0,
+ 0, 354, -2032, 9438, 10351, -2097, 371, 0,
+ 0, 352, -2025, 9360, 10426, -2100, 372, 0,
+ 0, 350, -2018, 9283, 10500, -2103, 373, 0,
+ 0, 348, -2010, 9205, 10574, -2106, 374, 0,
+ 0, 346, -2002, 9127, 10648, -2108, 375, 0,
+ -1, 344, -1994, 9049, 10721, -2111, 375, 0,
+ -1, 342, -1985, 8971, 10795, -2112, 376, -1,
+ -1, 340, -1977, 8892, 10867, -2114, 377, -1,
+ -1, 337, -1968, 8814, 10940, -2115, 377, -1,
+ -1, 335, -1959, 8735, 11012, -2116, 377, -1,
+ -1, 333, -1949, 8656, 11084, -2116, 378, -1,
+ -1, 331, -1940, 8578, 11156, -2116, 378, -1,
+ -1, 328, -1930, 8499, 11227, -2116, 378, -1,
+ -2, 326, -1920, 8420, 11298, -2116, 378, -1,
+ -2, 323, -1909, 8341, 11369, -2115, 378, -1,
+ -2, 321, -1899, 8262, 11439, -2113, 378, -1,
+ -2, 318, -1888, 8182, 11509, -2112, 378, -2,
+ -2, 316, -1877, 8103, 11578, -2110, 378, -2,
+ -2, 313, -1866, 8024, 11647, -2107, 377, -2,
+ -3, 311, -1855, 7944, 11716, -2104, 377, -2,
+ -3, 308, -1844, 7865, 11785, -2101, 376, -2,
+ -3, 305, -1832, 7785, 11852, -2098, 376, -2,
+ -3, 303, -1820, 7706, 11920, -2094, 375, -2,
+ -4, 300, -1808, 7626, 11987, -2089, 374, -3,
+ -4, 297, -1796, 7547, 12054, -2084, 373, -3,
+ -4, 294, -1784, 7467, 12120, -2079, 372, -3,
+ -4, 291, -1771, 7388, 12186, -2074, 371, -3,
+ -5, 289, -1758, 7308, 12251, -2068, 370, -3,
+ -5, 286, -1745, 7229, 12316, -2062, 369, -3,
+ -5, 283, -1732, 7149, 12381, -2055, 367, -3,
+ -6, 280, -1719, 7070, 12445, -2048, 366, -4,
+ -6, 277, -1706, 6990, 12509, -2040, 364, -4,
+ -6, 274, -1693, 6911, 12572, -2032, 362, -4,
+ -7, 271, -1679, 6831, 12634, -2024, 360, -4,
+ -7, 268, -1665, 6752, 12696, -2015, 358, -4,
+ -7, 265, -1651, 6673, 12758, -2005, 356, -4,
+ -8, 262, -1637, 6594, 12819, -1996, 354, -4,
+ -8, 259, -1623, 6514, 12880, -1986, 352, -4,
+ -8, 256, -1609, 6435, 12940, -1975, 349, -5,
+ -9, 253, -1595, 6356, 13000, -1964, 347, -5,
+ -9, 250, -1580, 6277, 13059, -1952, 344, -5,
+ -10, 247, -1566, 6199, 13118, -1940, 341, -5,
+ -10, 244, -1551, 6120, 13176, -1928, 338, -5,
+ -10, 241, -1536, 6041, 13233, -1915, 335, -5,
+ -11, 238, -1521, 5963, 13290, -1902, 332, -5,
+ -11, 235, -1506, 5885, 13347, -1888, 329, -5,
+ -12, 232, -1491, 5806, 13402, -1874, 326, -5,
+ -12, 229, -1476, 5728, 13458, -1859, 322, -5,
+ -13, 225, -1461, 5651, 13512, -1844, 319, -5,
+ -13, 222, -1445, 5573, 13567, -1829, 315, -5,
+ -13, 219, -1430, 5495, 13620, -1813, 311, -6,
+ -14, 216, -1414, 5418, 13673, -1796, 307, -6,
+ -14, 213, -1399, 5340, 13726, -1779, 303, -6,
+ -15, 210, -1383, 5263, 13777, -1762, 299, -6,
+ -15, 207, -1368, 5186, 13829, -1744, 294, -6,
+ -16, 204, -1352, 5110, 13879, -1725, 290, -6,
+ -16, 201, -1336, 5033, 13929, -1706, 285, -6,
+ -17, 198, -1320, 4957, 13978, -1687, 280, -6,
+ -17, 195, -1304, 4881, 14027, -1667, 276, -5,
+ -18, 192, -1288, 4805, 14075, -1647, 271, -5,
+ -18, 189, -1272, 4729, 14123, -1626, 265, -5,
+ -19, 186, -1256, 4653, 14169, -1604, 260, -5,
+ -19, 183, -1240, 4578, 14216, -1583, 255, -5,
+ -20, 180, -1224, 4503, 14261, -1560, 249, -5,
+ -20, 177, -1208, 4428, 14306, -1537, 244, -5,
+ -21, 174, -1192, 4354, 14350, -1514, 238, -5,
+ -21, 171, -1175, 4279, 14394, -1490, 232, -5,
+ -22, 168, -1159, 4205, 14437, -1466, 226, -4,
+ -22, 165, -1143, 4131, 14479, -1441, 220, -4,
+ -22, 162, -1127, 4058, 14520, -1416, 213, -4,
+ -23, 159, -1110, 3985, 14561, -1390, 207, -4,
+ -23, 156, -1094, 3912, 14601, -1363, 200, -4,
+ -24, 153, -1078, 3839, 14640, -1337, 193, -3,
+ -24, 150, -1062, 3766, 14679, -1309, 187, -3,
+ -25, 147, -1045, 3694, 14717, -1281, 179, -3,
+ -25, 144, -1029, 3622, 14754, -1253, 172, -3,
+ -26, 142, -1013, 3551, 14791, -1224, 165, -2,
+ -26, 139, -996, 3480, 14827, -1194, 158, -2,
+ -27, 136, -980, 3409, 14862, -1164, 150, -1,
+ -27, 133, -964, 3338, 14896, -1134, 142, -1,
+ -28, 131, -948, 3268, 14930, -1103, 135, -1,
+ -28, 128, -931, 3198, 14963, -1071, 127, 0,
+ -29, 125, -915, 3128, 14995, -1039, 118, 0,
+ -29, 122, -899, 3059, 15027, -1007, 110, 1,
+ -29, 120, -883, 2990, 15057, -974, 102, 1,
+ -30, 117, -867, 2921, 15087, -940, 93, 2,
+ -30, 115, -851, 2853, 15117, -906, 85, 2,
+ -31, 112, -835, 2785, 15145, -871, 76, 3,
+ -31, 109, -819, 2718, 15173, -836, 67, 3,
+ -32, 107, -803, 2651, 15200, -801, 58, 4,
+ -32, 104, -787, 2584, 15226, -764, 49, 5,
+ -32, 102, -771, 2517, 15251, -728, 39, 5,
+ -33, 99, -755, 2451, 15276, -690, 30, 6,
+ -33, 97, -740, 2386, 15300, -653, 20, 7,
+ -33, 95, -724, 2321, 15323, -614, 10, 7,
+ -34, 92, -708, 2256, 15345, -576, 1, 8,
+ -34, 90, -693, 2191, 15366, -536, -9, 9,
+ -34, 88, -677, 2127, 15387, -496, -20, 10,
+ -35, 85, -662, 2063, 15407, -456, -30, 11,
+ -35, 83, -646, 2000, 15426, -415, -40, 11,
+ -35, 81, -631, 1937, 15445, -374, -51, 12,
+ -36, 79, -616, 1875, 15462, -332, -62, 13,
+ -36, 76, -600, 1813, 15479, -289, -72, 14,
+ -36, 74, -585, 1751, 15495, -247, -83, 15,
+ -36, 72, -570, 1690, 15510, -203, -94, 16,
+ -37, 70, -555, 1629, 15524, -159, -106, 17,
+ -37, 68, -540, 1569, 15538, -115, -117, 18,
+ -37, 66, -526, 1509, 15550, -70, -128, 19,
+ -37, 64, -511, 1450, 15562, -24, -140, 21,
+ -37, 62, -496, 1391, 15573, 22, -152, 22,
+ -38, 60, -482, 1332, 15583, 68, -164, 23,
+ -38, 58, -467, 1274, 15593, 115, -175, 24,
+ -38, 56, -453, 1216, 15601, 163, -188, 25,
+ -38, 54, -439, 1159, 15609, 211, -200, 27,
+ -38, 53, -425, 1103, 15616, 259, -212, 28,
+ -38, 51, -410, 1046, 15622, 309, -224, 29,
+ -38, 49, -396, 990, 15628, 358, -237, 31,
+ -38, 47, -383, 935, 15632, 408, -250, 32,
+ -38, 46, -369, 880, 15636, 459, -263, 33,
+ -38, 44, -355, 826, 15639, 510, -275, 35,
+ -38, 42, -342, 772, 15641, 561, -288, 36,
+ -38, 41, -328, 718, 15642, 613, -302, 38,
};
inline int SPC_DSP::interpolate( voice_t const* v )
@@ -453,67 +453,67 @@
return out;
}
-inline int SPC_DSP::interpolate_cubic( voice_t const* v )
-{
- // Make pointers into cubic based on fractional position between samples
- int offset = v->interp_pos >> 4 & 0xFF;
- short const* fwd = cubic + offset;
- short const* rev = cubic + 256 - offset; // mirror left half of cubic
-
- int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
- int out;
- out = fwd [ 0] * in [0];
- out += fwd [257] * in [1];
- out += rev [257] * in [2];
- out += rev [ 0] * in [3];
- out >>= 11;
-
- CLAMP16( out );
- out &= ~1;
- return out;
-}
-
-inline int SPC_DSP::interpolate_sinc( voice_t const* v )
-{
- // Make pointers into cubic based on fractional position between samples
- int offset = v->interp_pos & 0xFF0;
- short const* filt = (short const*) (((char const*)sinc) + offset);
-
- int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
- int out;
- out = filt [0] * in [0];
- out += filt [1] * in [1];
- out += filt [2] * in [2];
- out += filt [3] * in [3];
- out += filt [4] * in [4];
- out += filt [5] * in [5];
- out += filt [6] * in [6];
- out += filt [7] * in [7];
- out >>= 14;
-
- CLAMP16( out );
- out &= ~1;
- return out;
-}
-
-inline int SPC_DSP::interpolate_linear( voice_t const* v )
-{
- int fract = v->interp_pos & 0xFFF;
-
- int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
- int out;
- out = (0x1000 - fract) * in [0];
- out += fract * in [1];
- out >>= 12;
-
- // no need to clamp
- out &= ~1;
- return out;
-}
-
-inline int SPC_DSP::interpolate_nearest( voice_t const* v )
-{
- return v->buf [(v->interp_pos >> 12) + v->buf_pos] & ~1;
+inline int SPC_DSP::interpolate_cubic( voice_t const* v )
+{
+ // Make pointers into cubic based on fractional position between samples
+ int offset = v->interp_pos >> 4 & 0xFF;
+ short const* fwd = cubic + offset;
+ short const* rev = cubic + 256 - offset; // mirror left half of cubic
+
+ int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
+ int out;
+ out = fwd [ 0] * in [0];
+ out += fwd [257] * in [1];
+ out += rev [257] * in [2];
+ out += rev [ 0] * in [3];
+ out >>= 11;
+
+ CLAMP16( out );
+ out &= ~1;
+ return out;
+}
+
+inline int SPC_DSP::interpolate_sinc( voice_t const* v )
+{
+ // Make pointers into cubic based on fractional position between samples
+ int offset = v->interp_pos & 0xFF0;
+ short const* filt = (short const*) (((char const*)sinc) + offset);
+
+ int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
+ int out;
+ out = filt [0] * in [0];
+ out += filt [1] * in [1];
+ out += filt [2] * in [2];
+ out += filt [3] * in [3];
+ out += filt [4] * in [4];
+ out += filt [5] * in [5];
+ out += filt [6] * in [6];
+ out += filt [7] * in [7];
+ out >>= 14;
+
+ CLAMP16( out );
+ out &= ~1;
+ return out;
+}
+
+inline int SPC_DSP::interpolate_linear( voice_t const* v )
+{
+ int fract = v->interp_pos & 0xFFF;
+
+ int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
+ int out;
+ out = (0x1000 - fract) * in [0];
+ out += fract * in [1];
+ out >>= 12;
+
+ // no need to clamp
+ out &= ~1;
+ return out;
+}
+
+inline int SPC_DSP::interpolate_nearest( voice_t const* v )
+{
+ return v->buf [(v->interp_pos >> 12) + v->buf_pos] & ~1;
}
@@ -817,29 +817,29 @@
// Gaussian interpolation
{
int output;
-
- switch ( m.interpolation_level )
- {
- case 0:
- default:
- output = interpolate( v );
- break;
-
- case 1:
- output = interpolate_cubic( v );
- break;
-
- case 2:
- output = interpolate_sinc( v );
- break;
-
- case -1:
- output = interpolate_linear( v );
- break;
-
- case -2:
- output = interpolate_nearest( v );
- break;
+
+ switch ( m.interpolation_level )
+ {
+ case 0:
+ default:
+ output = interpolate( v );
+ break;
+
+ case 1:
+ output = interpolate_cubic( v );
+ break;
+
+ case 2:
+ output = interpolate_sinc( v );
+ break;
+
+ case -1:
+ output = interpolate_linear( v );
+ break;
+
+ case -2:
+ output = interpolate_nearest( v );
+ break;
}
// Noise
@@ -887,10 +887,10 @@
// Apply left/right volume
int amp = (m.t_output * vol) >> 7;
- int abs_amp = abs( amp );
- if ( abs_amp > m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] )
- m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] = abs_amp;
-
+ int abs_amp = abs( amp );
+ if ( abs_amp > m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] )
+ m.max_level[v - (const SPC_DSP::voice_t *)&m.voices][ch] = abs_amp;
+
// Add to output total
m.t_main_out [ch] += amp;
CLAMP16( m.t_main_out [ch] );
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Kss_Cpu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Kss_Cpu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Kss_Cpu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Kss_Cpu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,35 +1,35 @@
-// $package. http://www.slack.net/~ant/
-
-#include "Kss_Core.h"
-
-#include "blargg_endian.h"
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#define OUT_PORT( addr, data ) cpu_out( TIME(), addr, data )
-#define IN_PORT( addr ) cpu_in( TIME(), addr )
-#define WRITE_MEM( addr, data ) {FLUSH_TIME(); cpu_write( addr, data );}
-#define IDLE_ADDR idle_addr
-#define CPU cpu
-
-#define CPU_BEGIN \
-bool Kss_Core::run_cpu( time_t end_time )\
-{\
- cpu.set_end_time( end_time );
-
- #include "Z80_Cpu_run.h"
-
- return warning;
-}
+// $package. http://www.slack.net/~ant/
+
+#include "Kss_Core.h"
+
+#include "blargg_endian.h"
+//#include "z80_cpu_log.h"
+
+/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#define OUT_PORT( addr, data ) cpu_out( TIME(), addr, data )
+#define IN_PORT( addr ) cpu_in( TIME(), addr )
+#define WRITE_MEM( addr, data ) {FLUSH_TIME(); cpu_write( addr, data );}
+#define IDLE_ADDR idle_addr
+#define CPU cpu
+
+#define CPU_BEGIN \
+bool Kss_Core::run_cpu( time_t end_time )\
+{\
+ cpu.set_end_time( end_time );
+
+ #include "Z80_Cpu_run.h"
+
+ return warning;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/license.txt kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/license.txt
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/license.txt 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/license.txt 2013-05-31 22:59:22.000000000 +0000
@@ -1,504 +1,504 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- , 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,476 +1,476 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "M3u_Playlist.h"
-#include "Music_Emu.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// gme functions defined here to avoid linking in m3u code unless it's used
-
-blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
-{
- if ( !err )
- {
- require( raw_track_count_ ); // file must be loaded first
- if ( playlist.size() )
- track_count_ = playlist.size();
-
- int line = playlist.first_error();
- if ( line )
- {
- // avoid using bloated printf()
- char* out = &playlist_warning [sizeof playlist_warning];
- *--out = 0;
- do {
- *--out = line % 10 + '0';
- } while ( (line /= 10) > 0 );
-
- static const char str [] = "Problem in m3u at line ";
- out -= sizeof str - 1;
- memcpy( out, str, sizeof str - 1 );
- set_warning( out );
- }
- }
- return err;
-}
-
-blargg_err_t Gme_File::load_m3u( const char path [] ) { return load_m3u_( playlist.load( path ) ); }
-
-blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
-
-gme_err_t gme_load_m3u( Music_Emu* me, const char path [] ) { return me->load_m3u( path ); }
-
-gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
-{
- Mem_File_Reader in( data, size );
- return me->load_m3u( in );
-}
-
-static char* skip_white( char* in )
-{
- while ( unsigned (*in - 1) <= ' ' - 1 )
- in++;
- return in;
-}
-
-inline unsigned from_dec( unsigned n ) { return n - '0'; }
-
-static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
-{
- entry.file = in;
- entry.type = "";
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in filename
- {
- char* p = skip_white( in );
- if ( *p == '$' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
- {
- entry.type = ++in;
- while ( (c = *in) != 0 && c != ',' )
- in++;
- if ( c == ',' )
- {
- *in++ = 0; // terminate type
- in = skip_white( in );
- }
- break;
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static char* next_field( char* in, int* result )
-{
- while ( 1 )
- {
- in = skip_white( in );
-
- if ( !*in )
- break;
-
- if ( *in == ',' )
- {
- in++;
- break;
- }
-
- *result = 1;
- in++;
- }
- return skip_white( in );
-}
-
-static char* parse_int_( char* in, int* out )
-{
- int n = 0;
- while ( 1 )
- {
- unsigned d = from_dec( *in );
- if ( d > 9 )
- break;
- in++;
- n = n * 10 + d;
- *out = n;
- }
- return in;
-}
-
-static char* parse_int( char* in, int* out, int* result )
-{
- return next_field( parse_int_( in, out ), result );
-}
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
-{
- if ( *in == '$' )
- {
- in++;
- int n = 0;
- while ( 1 )
- {
- int h = from_hex_char( *in );
- if ( h > 15 )
- break;
- in++;
- n = n * 16 + h;
- entry.track = n;
- }
- }
- else
- {
- in = parse_int_( in, &entry.track );
- if ( entry.track >= 0 )
- entry.decimal_track = 1;
- }
- return next_field( in, result );
-}
-
-static char* parse_time_( char* in, int* out )
-{
- *out = -1;
- int n = -1;
- in = parse_int_( in, &n );
- if ( n >= 0 )
- {
- *out = n;
- while ( *in == ':' )
- {
- n = -1;
- in = parse_int_( in + 1, &n );
- if ( n >= 0 )
- *out = *out * 60 + n;
- }
- *out *= 1000;
- if ( *in == '.' )
- {
- n = -1;
- in = parse_int_( in + 1, &n );
- if ( n >= 0 )
- *out = *out + n;
- }
- }
- return in;
-}
-
-static char* parse_time( char* in, int* out, int* result )
-{
- return next_field( parse_time_( in, out ), result );
-}
-
-static char* parse_name( char* in )
-{
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in string
- {
- char* p = skip_white( in );
- if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static int parse_line( char* in, M3u_Playlist::entry_t& entry )
-{
- int result = 0;
-
- // file
- entry.file = in;
- entry.type = "";
- in = parse_filename( in, entry );
-
- // track
- entry.track = -1;
- entry.decimal_track = 0;
- in = parse_track( in, entry, &result );
-
- // name
- entry.name = in;
- in = parse_name( in );
-
- // time
- entry.length = -1;
- in = parse_time( in, &entry.length, &result );
-
- // loop
- entry.intro = -1;
- entry.loop = -1;
- if ( *in == '-' )
- {
- entry.loop = entry.length;
- in++;
- }
- else
- {
- in = parse_time_( in, &entry.loop );
- if ( entry.loop >= 0 )
- {
- entry.intro = entry.length - entry.loop;
- if ( *in == '-' ) // trailing '-' means that intro length was specified
- {
- in++;
- entry.intro = entry.loop;
- entry.loop = entry.length - entry.intro;
- }
- }
- }
- in = next_field( in, &result );
-
- // fade
- entry.fade = -1;
- in = parse_time( in, &entry.fade, &result );
-
- // repeat
- entry.repeat = -1;
- in = parse_int( in, &entry.repeat, &result );
-
- return result;
-}
-
-static void parse_comment( char* in, M3u_Playlist::info_t& info, char *& last_comment_value, bool first )
-{
- in = skip_white( in + 1 );
- const char* field = in;
- if ( *field != '@' )
- while ( *in && *in != ':' )
- in++;
-
- if ( *in == ':' )
- {
- const char* text = skip_white( in + 1 );
- if ( *text )
- {
- *in = 0;
- if ( !strcmp( "Composer" , field ) ) info.composer = text;
- else if ( !strcmp( "Engineer" , field ) ) info.engineer = text;
- else if ( !strcmp( "Ripping" , field ) ) info.ripping = text;
- else if ( !strcmp( "Tagging" , field ) ) info.tagging = text;
- else if ( !strcmp( "Game" , field ) ) info.title = text;
- else if ( !strcmp( "Artist" , field ) ) info.artist = text;
- else if ( !strcmp( "Copyright", field ) ) info.copyright = text;
- else
- text = 0;
- if ( text )
- return;
- *in = ':';
- }
- }
- else if ( *field == '@' )
- {
- ++field;
- in = (char*)field;
- while ( *in && *in > ' ' )
- in++;
- const char* text = skip_white( in );
- if ( *text )
- {
- char saved = *in;
- *in = 0;
- if ( !strcmp( "TITLE" , field ) ) info.title = text;
- else if ( !strcmp( "ARTIST", field ) ) info.artist = text;
- else if ( !strcmp( "DATE", field ) ) info.date = text;
- else if ( !strcmp( "COMPOSER", field ) ) info.composer = text;
- else if ( !strcmp( "SEQUENCER", field ) ) info.sequencer = text;
- else if ( !strcmp( "ENGINEER", field ) ) info.engineer = text;
- else if ( !strcmp( "RIPPER", field ) ) info.ripping = text;
- else if ( !strcmp( "TAGGER", field ) ) info.tagging = text;
- else
- text = 0;
- if ( text )
- {
- last_comment_value = (char*)text;
- return;
- }
- *in = saved;
- }
- }
- else if ( last_comment_value )
- {
- size_t len = strlen( last_comment_value );
- last_comment_value[ len ] = ',';
- last_comment_value[ len + 1 ] = ' ';
- size_t field_len = strlen( field );
- memmove( last_comment_value + len + 2, field, field_len );
- last_comment_value[ len + 2 + field_len ] = 0;
- return;
- }
-
- if ( first )
- info.title = field;
-}
-
-blargg_err_t M3u_Playlist::parse_()
-{
- info_.title = "";
- info_.artist = "";
- info_.date = "";
- info_.composer = "";
- info_.sequencer = "";
- info_.engineer = "";
- info_.ripping = "";
- info_.tagging = "";
- info_.copyright = "";
-
- int const CR = 13;
- int const LF = 10;
-
- data.end() [-1] = LF; // terminate input
-
- first_error_ = 0;
- bool first_comment = true;
- int line = 0;
- int count = 0;
- char* in = data.begin();
- char* last_comment_value = 0;
- while ( in < data.end() )
- {
- // find end of line and terminate it
- line++;
- char* begin = in;
- while ( *in != CR && *in != LF )
- {
- if ( !*in )
- return blargg_err_file_type;
- in++;
- }
- if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
- *in++ = 0;
- *in++ = 0;
-
- // parse line
- if ( *begin == '#' )
- {
- parse_comment( begin, info_, last_comment_value, first_comment );
- first_comment = false;
- }
- else if ( *begin )
- {
- if ( (int) entries.size() <= count )
- RETURN_ERR( entries.resize( count * 2 + 64 ) );
-
- if ( !parse_line( begin, entries [count] ) )
- count++;
- else if ( !first_error_ )
- first_error_ = line;
- first_comment = false;
- }
- else last_comment_value = 0;
- }
- if ( count <= 0 )
- return blargg_err_file_type;
-
- // Treat first comment as title only if another field is also specified
- if ( !(info_.artist [0] | info_.composer [0] | info_.date [0] | info_.engineer [0] | info_.ripping [0] | info_.sequencer [0] | info_.tagging [0] | info_.copyright[0]) )
- info_.title = "";
-
- return entries.resize( count );
-}
-
-blargg_err_t M3u_Playlist::parse()
-{
- blargg_err_t err = parse_();
- if ( err )
- clear_();
- return err;
-}
-
-blargg_err_t M3u_Playlist::load( Data_Reader& in )
-{
- RETURN_ERR( data.resize( in.remain() + 1 ) );
- RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
- return parse();
-}
-
-blargg_err_t M3u_Playlist::load( const char path [] )
-{
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- return load( in );
-}
-
-blargg_err_t M3u_Playlist::load( void const* in, long size )
-{
- RETURN_ERR( data.resize( size + 1 ) );
- memcpy( data.begin(), in, size );
- return parse();
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "M3u_Playlist.h"
+#include "Music_Emu.h"
+
+/* Copyright (C) 2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// gme functions defined here to avoid linking in m3u code unless it's used
+
+blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
+{
+ if ( !err )
+ {
+ require( raw_track_count_ ); // file must be loaded first
+ if ( playlist.size() )
+ track_count_ = playlist.size();
+
+ int line = playlist.first_error();
+ if ( line )
+ {
+ // avoid using bloated printf()
+ char* out = &playlist_warning [sizeof playlist_warning];
+ *--out = 0;
+ do {
+ *--out = line % 10 + '0';
+ } while ( (line /= 10) > 0 );
+
+ static const char str [] = "Problem in m3u at line ";
+ out -= sizeof str - 1;
+ memcpy( out, str, sizeof str - 1 );
+ set_warning( out );
+ }
+ }
+ return err;
+}
+
+blargg_err_t Gme_File::load_m3u( const char path [] ) { return load_m3u_( playlist.load( path ) ); }
+
+blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
+
+gme_err_t gme_load_m3u( Music_Emu* me, const char path [] ) { return me->load_m3u( path ); }
+
+gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
+{
+ Mem_File_Reader in( data, size );
+ return me->load_m3u( in );
+}
+
+static char* skip_white( char* in )
+{
+ while ( unsigned (*in - 1) <= ' ' - 1 )
+ in++;
+ return in;
+}
+
+inline unsigned from_dec( unsigned n ) { return n - '0'; }
+
+static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
+{
+ entry.file = in;
+ entry.type = "";
+ char* out = in;
+ while ( 1 )
+ {
+ int c = *in;
+ if ( !c ) break;
+ in++;
+
+ if ( c == ',' ) // commas in filename
+ {
+ char* p = skip_white( in );
+ if ( *p == '$' || from_dec( *p ) <= 9 )
+ {
+ in = p;
+ break;
+ }
+ }
+
+ if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
+ {
+ entry.type = ++in;
+ while ( (c = *in) != 0 && c != ',' )
+ in++;
+ if ( c == ',' )
+ {
+ *in++ = 0; // terminate type
+ in = skip_white( in );
+ }
+ break;
+ }
+
+ if ( c == '\\' ) // \ prefix for special characters
+ {
+ c = *in;
+ if ( !c ) break;
+ in++;
+ }
+ *out++ = (char) c;
+ }
+ *out = 0; // terminate string
+ return in;
+}
+
+static char* next_field( char* in, int* result )
+{
+ while ( 1 )
+ {
+ in = skip_white( in );
+
+ if ( !*in )
+ break;
+
+ if ( *in == ',' )
+ {
+ in++;
+ break;
+ }
+
+ *result = 1;
+ in++;
+ }
+ return skip_white( in );
+}
+
+static char* parse_int_( char* in, int* out )
+{
+ int n = 0;
+ while ( 1 )
+ {
+ unsigned d = from_dec( *in );
+ if ( d > 9 )
+ break;
+ in++;
+ n = n * 10 + d;
+ *out = n;
+ }
+ return in;
+}
+
+static char* parse_int( char* in, int* out, int* result )
+{
+ return next_field( parse_int_( in, out ), result );
+}
+
+// Returns 16 or greater if not hex
+inline int from_hex_char( int h )
+{
+ h -= 0x30;
+ if ( (unsigned) h > 9 )
+ h = ((h - 0x11) & 0xDF) + 10;
+ return h;
+}
+
+static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
+{
+ if ( *in == '$' )
+ {
+ in++;
+ int n = 0;
+ while ( 1 )
+ {
+ int h = from_hex_char( *in );
+ if ( h > 15 )
+ break;
+ in++;
+ n = n * 16 + h;
+ entry.track = n;
+ }
+ }
+ else
+ {
+ in = parse_int_( in, &entry.track );
+ if ( entry.track >= 0 )
+ entry.decimal_track = 1;
+ }
+ return next_field( in, result );
+}
+
+static char* parse_time_( char* in, int* out )
+{
+ *out = -1;
+ int n = -1;
+ in = parse_int_( in, &n );
+ if ( n >= 0 )
+ {
+ *out = n;
+ while ( *in == ':' )
+ {
+ n = -1;
+ in = parse_int_( in + 1, &n );
+ if ( n >= 0 )
+ *out = *out * 60 + n;
+ }
+ *out *= 1000;
+ if ( *in == '.' )
+ {
+ n = -1;
+ in = parse_int_( in + 1, &n );
+ if ( n >= 0 )
+ *out = *out + n;
+ }
+ }
+ return in;
+}
+
+static char* parse_time( char* in, int* out, int* result )
+{
+ return next_field( parse_time_( in, out ), result );
+}
+
+static char* parse_name( char* in )
+{
+ char* out = in;
+ while ( 1 )
+ {
+ int c = *in;
+ if ( !c ) break;
+ in++;
+
+ if ( c == ',' ) // commas in string
+ {
+ char* p = skip_white( in );
+ if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
+ {
+ in = p;
+ break;
+ }
+ }
+
+ if ( c == '\\' ) // \ prefix for special characters
+ {
+ c = *in;
+ if ( !c ) break;
+ in++;
+ }
+ *out++ = (char) c;
+ }
+ *out = 0; // terminate string
+ return in;
+}
+
+static int parse_line( char* in, M3u_Playlist::entry_t& entry )
+{
+ int result = 0;
+
+ // file
+ entry.file = in;
+ entry.type = "";
+ in = parse_filename( in, entry );
+
+ // track
+ entry.track = -1;
+ entry.decimal_track = 0;
+ in = parse_track( in, entry, &result );
+
+ // name
+ entry.name = in;
+ in = parse_name( in );
+
+ // time
+ entry.length = -1;
+ in = parse_time( in, &entry.length, &result );
+
+ // loop
+ entry.intro = -1;
+ entry.loop = -1;
+ if ( *in == '-' )
+ {
+ entry.loop = entry.length;
+ in++;
+ }
+ else
+ {
+ in = parse_time_( in, &entry.loop );
+ if ( entry.loop >= 0 )
+ {
+ entry.intro = entry.length - entry.loop;
+ if ( *in == '-' ) // trailing '-' means that intro length was specified
+ {
+ in++;
+ entry.intro = entry.loop;
+ entry.loop = entry.length - entry.intro;
+ }
+ }
+ }
+ in = next_field( in, &result );
+
+ // fade
+ entry.fade = -1;
+ in = parse_time( in, &entry.fade, &result );
+
+ // repeat
+ entry.repeat = -1;
+ in = parse_int( in, &entry.repeat, &result );
+
+ return result;
+}
+
+static void parse_comment( char* in, M3u_Playlist::info_t& info, char *& last_comment_value, bool first )
+{
+ in = skip_white( in + 1 );
+ const char* field = in;
+ if ( *field != '@' )
+ while ( *in && *in != ':' )
+ in++;
+
+ if ( *in == ':' )
+ {
+ const char* text = skip_white( in + 1 );
+ if ( *text )
+ {
+ *in = 0;
+ if ( !strcmp( "Composer" , field ) ) info.composer = text;
+ else if ( !strcmp( "Engineer" , field ) ) info.engineer = text;
+ else if ( !strcmp( "Ripping" , field ) ) info.ripping = text;
+ else if ( !strcmp( "Tagging" , field ) ) info.tagging = text;
+ else if ( !strcmp( "Game" , field ) ) info.title = text;
+ else if ( !strcmp( "Artist" , field ) ) info.artist = text;
+ else if ( !strcmp( "Copyright", field ) ) info.copyright = text;
+ else
+ text = 0;
+ if ( text )
+ return;
+ *in = ':';
+ }
+ }
+ else if ( *field == '@' )
+ {
+ ++field;
+ in = (char*)field;
+ while ( *in && *in > ' ' )
+ in++;
+ const char* text = skip_white( in );
+ if ( *text )
+ {
+ char saved = *in;
+ *in = 0;
+ if ( !strcmp( "TITLE" , field ) ) info.title = text;
+ else if ( !strcmp( "ARTIST", field ) ) info.artist = text;
+ else if ( !strcmp( "DATE", field ) ) info.date = text;
+ else if ( !strcmp( "COMPOSER", field ) ) info.composer = text;
+ else if ( !strcmp( "SEQUENCER", field ) ) info.sequencer = text;
+ else if ( !strcmp( "ENGINEER", field ) ) info.engineer = text;
+ else if ( !strcmp( "RIPPER", field ) ) info.ripping = text;
+ else if ( !strcmp( "TAGGER", field ) ) info.tagging = text;
+ else
+ text = 0;
+ if ( text )
+ {
+ last_comment_value = (char*)text;
+ return;
+ }
+ *in = saved;
+ }
+ }
+ else if ( last_comment_value )
+ {
+ size_t len = strlen( last_comment_value );
+ last_comment_value[ len ] = ',';
+ last_comment_value[ len + 1 ] = ' ';
+ size_t field_len = strlen( field );
+ memmove( last_comment_value + len + 2, field, field_len );
+ last_comment_value[ len + 2 + field_len ] = 0;
+ return;
+ }
+
+ if ( first )
+ info.title = field;
+}
+
+blargg_err_t M3u_Playlist::parse_()
+{
+ info_.title = "";
+ info_.artist = "";
+ info_.date = "";
+ info_.composer = "";
+ info_.sequencer = "";
+ info_.engineer = "";
+ info_.ripping = "";
+ info_.tagging = "";
+ info_.copyright = "";
+
+ int const CR = 13;
+ int const LF = 10;
+
+ data.end() [-1] = LF; // terminate input
+
+ first_error_ = 0;
+ bool first_comment = true;
+ int line = 0;
+ int count = 0;
+ char* in = data.begin();
+ char* last_comment_value = 0;
+ while ( in < data.end() )
+ {
+ // find end of line and terminate it
+ line++;
+ char* begin = in;
+ while ( *in != CR && *in != LF )
+ {
+ if ( !*in )
+ return blargg_err_file_type;
+ in++;
+ }
+ if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
+ *in++ = 0;
+ *in++ = 0;
+
+ // parse line
+ if ( *begin == '#' )
+ {
+ parse_comment( begin, info_, last_comment_value, first_comment );
+ first_comment = false;
+ }
+ else if ( *begin )
+ {
+ if ( (int) entries.size() <= count )
+ RETURN_ERR( entries.resize( count * 2 + 64 ) );
+
+ if ( !parse_line( begin, entries [count] ) )
+ count++;
+ else if ( !first_error_ )
+ first_error_ = line;
+ first_comment = false;
+ }
+ else last_comment_value = 0;
+ }
+ if ( count <= 0 )
+ return blargg_err_file_type;
+
+ // Treat first comment as title only if another field is also specified
+ if ( !(info_.artist [0] | info_.composer [0] | info_.date [0] | info_.engineer [0] | info_.ripping [0] | info_.sequencer [0] | info_.tagging [0] | info_.copyright[0]) )
+ info_.title = "";
+
+ return entries.resize( count );
+}
+
+blargg_err_t M3u_Playlist::parse()
+{
+ blargg_err_t err = parse_();
+ if ( err )
+ clear_();
+ return err;
+}
+
+blargg_err_t M3u_Playlist::load( Data_Reader& in )
+{
+ RETURN_ERR( data.resize( in.remain() + 1 ) );
+ RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
+ return parse();
+}
+
+blargg_err_t M3u_Playlist::load( const char path [] )
+{
+ GME_FILE_READER in;
+ RETURN_ERR( in.open( path ) );
+ return load( in );
+}
+
+blargg_err_t M3u_Playlist::load( void const* in, long size )
+{
+ RETURN_ERR( data.resize( size + 1 ) );
+ memcpy( data.begin(), in, size );
+ return parse();
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/M3u_Playlist.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,87 +1,87 @@
-// M3U playlist file parser, with support for subtrack information
-
-// Game_Music_Emu $vers
-#ifndef M3U_PLAYLIST_H
-#define M3U_PLAYLIST_H
-
-#include "blargg_common.h"
-#include "Data_Reader.h"
-
-class M3u_Playlist {
-public:
- // Load playlist data
- blargg_err_t load( const char* path );
- blargg_err_t load( Data_Reader& in );
- blargg_err_t load( void const* data, long size );
-
- // Line number of first parse error, 0 if no error. Any lines with parse
- // errors are ignored.
- int first_error() const { return first_error_; }
-
- // All string pointers point to valid string, or "" if not available
- struct info_t
- {
- const char* title;
- const char* artist;
- const char* date;
- const char* composer;
- const char* sequencer;
- const char* engineer;
- const char* ripping;
- const char* tagging;
- const char* copyright;
- };
- info_t const& info() const { return info_; }
-
- struct entry_t
- {
- const char* file; // filename without stupid ::TYPE suffix
- const char* type; // if filename has ::TYPE suffix, this is "TYPE", otherwise ""
- const char* name;
- bool decimal_track; // true if track was specified in decimal
- // integers are -1 if not present
- int track;
- int length; // milliseconds
- int intro;
- int loop;
- int fade;
- int repeat; // count
- };
- entry_t const& operator [] ( int i ) const { return entries [i]; }
- int size() const { return entries.size(); }
-
- void clear();
-
-private:
- blargg_vector entries;
- blargg_vector data;
- int first_error_;
- info_t info_;
-
- blargg_err_t parse();
- blargg_err_t parse_();
- void clear_();
-};
-
-inline void M3u_Playlist::clear_()
-{
- info_.title = "";
- info_.artist = "";
- info_.date = "";
- info_.composer = "";
- info_.sequencer = "";
- info_.engineer = "";
- info_.ripping = "";
- info_.tagging = "";
- info_.copyright = "";
- entries.clear();
- data.clear();
-}
-
-inline void M3u_Playlist::clear()
-{
- first_error_ = 0;
- clear_();
-}
-
-#endif
+// M3U playlist file parser, with support for subtrack information
+
+// Game_Music_Emu $vers
+#ifndef M3U_PLAYLIST_H
+#define M3U_PLAYLIST_H
+
+#include "blargg_common.h"
+#include "Data_Reader.h"
+
+class M3u_Playlist {
+public:
+ // Load playlist data
+ blargg_err_t load( const char* path );
+ blargg_err_t load( Data_Reader& in );
+ blargg_err_t load( void const* data, long size );
+
+ // Line number of first parse error, 0 if no error. Any lines with parse
+ // errors are ignored.
+ int first_error() const { return first_error_; }
+
+ // All string pointers point to valid string, or "" if not available
+ struct info_t
+ {
+ const char* title;
+ const char* artist;
+ const char* date;
+ const char* composer;
+ const char* sequencer;
+ const char* engineer;
+ const char* ripping;
+ const char* tagging;
+ const char* copyright;
+ };
+ info_t const& info() const { return info_; }
+
+ struct entry_t
+ {
+ const char* file; // filename without stupid ::TYPE suffix
+ const char* type; // if filename has ::TYPE suffix, this is "TYPE", otherwise ""
+ const char* name;
+ bool decimal_track; // true if track was specified in decimal
+ // integers are -1 if not present
+ int track;
+ int length; // milliseconds
+ int intro;
+ int loop;
+ int fade;
+ int repeat; // count
+ };
+ entry_t const& operator [] ( int i ) const { return entries [i]; }
+ int size() const { return entries.size(); }
+
+ void clear();
+
+private:
+ blargg_vector entries;
+ blargg_vector data;
+ int first_error_;
+ info_t info_;
+
+ blargg_err_t parse();
+ blargg_err_t parse_();
+ void clear_();
+};
+
+inline void M3u_Playlist::clear_()
+{
+ info_.title = "";
+ info_.artist = "";
+ info_.date = "";
+ info_.composer = "";
+ info_.sequencer = "";
+ info_.engineer = "";
+ info_.ripping = "";
+ info_.tagging = "";
+ info_.copyright = "";
+ entries.clear();
+ data.clear();
+}
+
+inline void M3u_Playlist::clear()
+{
+ first_error_ = 0;
+ clear_();
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Multi_Buffer.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Multi_Buffer.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Multi_Buffer.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Multi_Buffer.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,290 +1,290 @@
-// Blip_Buffer $vers. http://www.slack.net/~ant/
-
-#include "Multi_Buffer.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
- length_ = 0;
- sample_rate_ = 0;
- channels_changed_count_ = 1;
- channel_types_ = NULL;
- channel_count_ = 0;
- immediate_removal_ = true;
-}
-
-Multi_Buffer::channel_t Multi_Buffer::channel( int /*index*/ )
-{
- channel_t ch;
- ch.center = ch.left = ch.right = NULL;
- return ch;
-}
-
-// Silent_Buffer
-
-Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
-{
- // TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
- chan.left = NULL;
- chan.center = NULL;
- chan.right = NULL;
-}
-
-// Mono_Buffer
-
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
- chan.center = &buf;
- chan.left = &buf;
- chan.right = &buf;
-}
-
-Mono_Buffer::~Mono_Buffer() { }
-
-blargg_err_t Mono_Buffer::set_sample_rate( int rate, int msec )
-{
- RETURN_ERR( buf.set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
-}
-
-
-// Tracked_Blip_Buffer
-
-int const blip_buffer_extra = 32; // TODO: explain why this value
-
-Tracked_Blip_Buffer::Tracked_Blip_Buffer()
-{
- last_non_silence = 0;
-}
-
-void Tracked_Blip_Buffer::clear()
-{
- last_non_silence = 0;
- Blip_Buffer::clear();
-}
-
-void Tracked_Blip_Buffer::end_frame( blip_time_t t )
-{
- Blip_Buffer::end_frame( t );
- if ( modified() )
- {
- clear_modified();
- last_non_silence = samples_avail() + blip_buffer_extra;
- }
-}
-
-unsigned Tracked_Blip_Buffer::non_silent() const
-{
- return last_non_silence | unsettled();
-}
-
-inline void Tracked_Blip_Buffer::remove_( int n )
-{
- if ( (last_non_silence -= n) < 0 )
- last_non_silence = 0;
-}
-
-void Tracked_Blip_Buffer::remove_silence( int n )
-{
- remove_( n );
- Blip_Buffer::remove_silence( n );
-}
-
-void Tracked_Blip_Buffer::remove_samples( int n )
-{
- remove_( n );
- Blip_Buffer::remove_samples( n );
-}
-
-void Tracked_Blip_Buffer::remove_all_samples()
-{
- int avail = samples_avail();
- if ( !non_silent() )
- remove_silence( avail );
- else
- remove_samples( avail );
-}
-
-int Tracked_Blip_Buffer::read_samples( blip_sample_t out [], int count )
-{
- count = Blip_Buffer::read_samples( out, count );
- remove_( count );
- return count;
-}
-
-// Stereo_Buffer
-
-int const stereo = 2;
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
- chan.center = mixer.bufs [2] = &bufs [2];
- chan.left = mixer.bufs [0] = &bufs [0];
- chan.right = mixer.bufs [1] = &bufs [1];
- mixer.samples_read = 0;
-}
-
-Stereo_Buffer::~Stereo_Buffer() { }
-
-blargg_err_t Stereo_Buffer::set_sample_rate( int rate, int msec )
-{
- mixer.samples_read = 0;
- for ( int i = bufs_size; --i >= 0; )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( int rate )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].bass_freq( bass );
-}
-
-void Stereo_Buffer::clear()
-{
- mixer.samples_read = 0;
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t time )
-{
- for ( int i = bufs_size; --i >= 0; )
- bufs [i].end_frame( time );
-}
-
-int Stereo_Buffer::read_samples( blip_sample_t out [], int out_size )
-{
- require( (out_size & 1) == 0 ); // must read an even number of samples
- out_size = min( out_size, samples_avail() );
-
- int pair_count = int (out_size >> 1);
- if ( pair_count )
- {
- mixer.read_pairs( out, pair_count );
-
- if ( samples_avail() <= 0 || immediate_removal() )
- {
- for ( int i = bufs_size; --i >= 0; )
- {
- buf_t& b = bufs [i];
- // TODO: might miss non-silence settling since it checks END of last read
- if ( !b.non_silent() )
- b.remove_silence( mixer.samples_read );
- else
- b.remove_samples( mixer.samples_read );
- }
- mixer.samples_read = 0;
- }
- }
- return out_size;
-}
-
-
-// Stereo_Mixer
-
-// mixers use a single index value to improve performance on register-challenged processors
-// offset goes from negative to zero
-
-void Stereo_Mixer::read_pairs( blip_sample_t out [], int count )
-{
- // TODO: if caller never marks buffers as modified, uses mono
- // except that buffer isn't cleared, so caller can encounter
- // subtle problems and not realize the cause.
- samples_read += count;
- if ( bufs [0]->non_silent() | bufs [1]->non_silent() )
- mix_stereo( out, count );
- else
- mix_mono( out, count );
-}
-
-void Stereo_Mixer::mix_mono( blip_sample_t out_ [], int count )
-{
- int const bass = bufs [2]->highpass_shift();
- Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
- int center_sum = bufs [2]->integrator();
-
- typedef blip_sample_t stereo_blip_sample_t [stereo];
- stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
- int offset = -count;
- do
- {
- int s = center_sum >> bufs [2]->delta_bits;
-
- center_sum -= center_sum >> bass;
- center_sum += center [offset];
-
- BLIP_CLAMP( s, s );
-
- out [offset] [0] = (blip_sample_t) s;
- out [offset] [1] = (blip_sample_t) s;
- }
- while ( ++offset );
-
- bufs [2]->set_integrator( center_sum );
-}
-
-void Stereo_Mixer::mix_stereo( blip_sample_t out_ [], int count )
-{
- blip_sample_t* BLARGG_RESTRICT out = out_ + count * stereo;
-
- // do left + center and right + center separately to reduce register load
- Tracked_Blip_Buffer* const* buf = &bufs [2];
- while ( true ) // loop runs twice
- {
- --buf;
- --out;
-
- int const bass = bufs [2]->highpass_shift();
- Blip_Buffer::delta_t const* side = (*buf)->read_pos() + samples_read;
- Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
-
- int side_sum = (*buf)->integrator();
- int center_sum = bufs [2]->integrator();
-
- int offset = -count;
- do
- {
- int s = (center_sum + side_sum) >> Blip_Buffer::delta_bits;
-
- side_sum -= side_sum >> bass;
- center_sum -= center_sum >> bass;
-
- side_sum += side [offset];
- center_sum += center [offset];
-
- BLIP_CLAMP( s, s );
-
- ++offset; // before write since out is decremented to slightly before end
- out [offset * stereo] = (blip_sample_t) s;
- }
- while ( offset );
-
- (*buf)->set_integrator( side_sum );
-
- if ( buf != bufs )
- continue;
-
- // only end center once
- bufs [2]->set_integrator( center_sum );
- break;
- }
-}
+// Blip_Buffer $vers. http://www.slack.net/~ant/
+
+#include "Multi_Buffer.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
+{
+ length_ = 0;
+ sample_rate_ = 0;
+ channels_changed_count_ = 1;
+ channel_types_ = NULL;
+ channel_count_ = 0;
+ immediate_removal_ = true;
+}
+
+Multi_Buffer::channel_t Multi_Buffer::channel( int /*index*/ )
+{
+ channel_t ch;
+ ch.center = ch.left = ch.right = NULL;
+ return ch;
+}
+
+// Silent_Buffer
+
+Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
+{
+ // TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
+ chan.left = NULL;
+ chan.center = NULL;
+ chan.right = NULL;
+}
+
+// Mono_Buffer
+
+Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
+{
+ chan.center = &buf;
+ chan.left = &buf;
+ chan.right = &buf;
+}
+
+Mono_Buffer::~Mono_Buffer() { }
+
+blargg_err_t Mono_Buffer::set_sample_rate( int rate, int msec )
+{
+ RETURN_ERR( buf.set_sample_rate( rate, msec ) );
+ return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
+}
+
+
+// Tracked_Blip_Buffer
+
+int const blip_buffer_extra = 32; // TODO: explain why this value
+
+Tracked_Blip_Buffer::Tracked_Blip_Buffer()
+{
+ last_non_silence = 0;
+}
+
+void Tracked_Blip_Buffer::clear()
+{
+ last_non_silence = 0;
+ Blip_Buffer::clear();
+}
+
+void Tracked_Blip_Buffer::end_frame( blip_time_t t )
+{
+ Blip_Buffer::end_frame( t );
+ if ( modified() )
+ {
+ clear_modified();
+ last_non_silence = samples_avail() + blip_buffer_extra;
+ }
+}
+
+unsigned Tracked_Blip_Buffer::non_silent() const
+{
+ return last_non_silence | unsettled();
+}
+
+inline void Tracked_Blip_Buffer::remove_( int n )
+{
+ if ( (last_non_silence -= n) < 0 )
+ last_non_silence = 0;
+}
+
+void Tracked_Blip_Buffer::remove_silence( int n )
+{
+ remove_( n );
+ Blip_Buffer::remove_silence( n );
+}
+
+void Tracked_Blip_Buffer::remove_samples( int n )
+{
+ remove_( n );
+ Blip_Buffer::remove_samples( n );
+}
+
+void Tracked_Blip_Buffer::remove_all_samples()
+{
+ int avail = samples_avail();
+ if ( !non_silent() )
+ remove_silence( avail );
+ else
+ remove_samples( avail );
+}
+
+int Tracked_Blip_Buffer::read_samples( blip_sample_t out [], int count )
+{
+ count = Blip_Buffer::read_samples( out, count );
+ remove_( count );
+ return count;
+}
+
+// Stereo_Buffer
+
+int const stereo = 2;
+
+Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
+{
+ chan.center = mixer.bufs [2] = &bufs [2];
+ chan.left = mixer.bufs [0] = &bufs [0];
+ chan.right = mixer.bufs [1] = &bufs [1];
+ mixer.samples_read = 0;
+}
+
+Stereo_Buffer::~Stereo_Buffer() { }
+
+blargg_err_t Stereo_Buffer::set_sample_rate( int rate, int msec )
+{
+ mixer.samples_read = 0;
+ for ( int i = bufs_size; --i >= 0; )
+ RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
+ return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
+}
+
+void Stereo_Buffer::clock_rate( int rate )
+{
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].clock_rate( rate );
+}
+
+void Stereo_Buffer::bass_freq( int bass )
+{
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].bass_freq( bass );
+}
+
+void Stereo_Buffer::clear()
+{
+ mixer.samples_read = 0;
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].clear();
+}
+
+void Stereo_Buffer::end_frame( blip_time_t time )
+{
+ for ( int i = bufs_size; --i >= 0; )
+ bufs [i].end_frame( time );
+}
+
+int Stereo_Buffer::read_samples( blip_sample_t out [], int out_size )
+{
+ require( (out_size & 1) == 0 ); // must read an even number of samples
+ out_size = min( out_size, samples_avail() );
+
+ int pair_count = int (out_size >> 1);
+ if ( pair_count )
+ {
+ mixer.read_pairs( out, pair_count );
+
+ if ( samples_avail() <= 0 || immediate_removal() )
+ {
+ for ( int i = bufs_size; --i >= 0; )
+ {
+ buf_t& b = bufs [i];
+ // TODO: might miss non-silence settling since it checks END of last read
+ if ( !b.non_silent() )
+ b.remove_silence( mixer.samples_read );
+ else
+ b.remove_samples( mixer.samples_read );
+ }
+ mixer.samples_read = 0;
+ }
+ }
+ return out_size;
+}
+
+
+// Stereo_Mixer
+
+// mixers use a single index value to improve performance on register-challenged processors
+// offset goes from negative to zero
+
+void Stereo_Mixer::read_pairs( blip_sample_t out [], int count )
+{
+ // TODO: if caller never marks buffers as modified, uses mono
+ // except that buffer isn't cleared, so caller can encounter
+ // subtle problems and not realize the cause.
+ samples_read += count;
+ if ( bufs [0]->non_silent() | bufs [1]->non_silent() )
+ mix_stereo( out, count );
+ else
+ mix_mono( out, count );
+}
+
+void Stereo_Mixer::mix_mono( blip_sample_t out_ [], int count )
+{
+ int const bass = bufs [2]->highpass_shift();
+ Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
+ int center_sum = bufs [2]->integrator();
+
+ typedef blip_sample_t stereo_blip_sample_t [stereo];
+ stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
+ int offset = -count;
+ do
+ {
+ int s = center_sum >> bufs [2]->delta_bits;
+
+ center_sum -= center_sum >> bass;
+ center_sum += center [offset];
+
+ BLIP_CLAMP( s, s );
+
+ out [offset] [0] = (blip_sample_t) s;
+ out [offset] [1] = (blip_sample_t) s;
+ }
+ while ( ++offset );
+
+ bufs [2]->set_integrator( center_sum );
+}
+
+void Stereo_Mixer::mix_stereo( blip_sample_t out_ [], int count )
+{
+ blip_sample_t* BLARGG_RESTRICT out = out_ + count * stereo;
+
+ // do left + center and right + center separately to reduce register load
+ Tracked_Blip_Buffer* const* buf = &bufs [2];
+ while ( true ) // loop runs twice
+ {
+ --buf;
+ --out;
+
+ int const bass = bufs [2]->highpass_shift();
+ Blip_Buffer::delta_t const* side = (*buf)->read_pos() + samples_read;
+ Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
+
+ int side_sum = (*buf)->integrator();
+ int center_sum = bufs [2]->integrator();
+
+ int offset = -count;
+ do
+ {
+ int s = (center_sum + side_sum) >> Blip_Buffer::delta_bits;
+
+ side_sum -= side_sum >> bass;
+ center_sum -= center_sum >> bass;
+
+ side_sum += side [offset];
+ center_sum += center [offset];
+
+ BLIP_CLAMP( s, s );
+
+ ++offset; // before write since out is decremented to slightly before end
+ out [offset * stereo] = (blip_sample_t) s;
+ }
+ while ( offset );
+
+ (*buf)->set_integrator( side_sum );
+
+ if ( buf != bufs )
+ continue;
+
+ // only end center once
+ bufs [2]->set_integrator( center_sum );
+ break;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Music_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Music_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Music_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Music_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,244 +1,244 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const stereo = 2; // number of channels for stereo
-
-Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180, 0,0,0,0,0,0,0,0 };
-
-void Music_Emu::clear_track_vars()
-{
- current_track_ = -1;
- warning(); // clear warning
- track_filter.stop();
-}
-
-void Music_Emu::unload()
-{
- voice_count_ = 0;
- clear_track_vars();
- Gme_File::unload();
-}
-
-Music_Emu::gme_t()
-{
- effects_buffer_ = NULL;
- sample_rate_ = 0;
- mute_mask_ = 0;
- tempo_ = 1.0;
- gain_ = 1.0;
-
- fade_set = false;
-
- // defaults
- tfilter = track_filter.setup();
- set_max_initial_silence( 15 );
- set_silence_lookahead( 3 );
- ignore_silence( false );
-
- equalizer_.treble = -1.0;
- equalizer_.bass = 60;
-
- static const char* const names [] = {
- "Voice 1", "Voice 2", "Voice 3", "Voice 4",
- "Voice 5", "Voice 6", "Voice 7", "Voice 8"
- };
- set_voice_names( names );
- Music_Emu::unload(); // clears fields
-}
-
-Music_Emu::~gme_t()
-{
- assert( !effects_buffer_ );
-}
-
-blargg_err_t Music_Emu::set_sample_rate( int rate )
-{
- require( !sample_rate() ); // sample rate can't be changed once set
- RETURN_ERR( set_sample_rate_( rate ) );
- RETURN_ERR( track_filter.init( this ) );
- sample_rate_ = rate;
- tfilter.max_silence = 6 * stereo * sample_rate();
- return blargg_ok;
-}
-
-void Music_Emu::pre_load()
-{
- require( sample_rate() ); // set_sample_rate() must be called before loading a file
- Gme_File::pre_load();
-}
-
-void Music_Emu::set_equalizer( equalizer_t const& eq )
-{
- // TODO: why is GCC generating memcpy call here?
- // Without the 'if', valgrind flags it.
- if ( &eq != &equalizer_ )
- equalizer_ = eq;
- set_equalizer_( eq );
-}
-
-void Music_Emu::mute_voice( int index, bool mute )
-{
- require( (unsigned) index < (unsigned) voice_count() );
- int bit = 1 << index;
- int mask = mute_mask_ | bit;
- if ( !mute )
- mask ^= bit;
- mute_voices( mask );
-}
-
-void Music_Emu::mute_voices( int mask )
-{
- require( sample_rate() ); // sample rate must be set first
- mute_mask_ = mask;
- mute_voices_( mask );
-}
-
-const char* Music_Emu::voice_name( int i ) const
-{
- if ( (unsigned) i < (unsigned) voice_count_ )
- return voice_names_ [i];
-
- //check( false ); // TODO: enable?
- return "";
-}
-
-void Music_Emu::set_tempo( double t )
-{
- require( sample_rate() ); // sample rate must be set first
- double const min = 0.02;
- double const max = 4.00;
- if ( t < min ) t = min;
- if ( t > max ) t = max;
- tempo_ = t;
- set_tempo_( t );
-}
-
-blargg_err_t Music_Emu::post_load()
-{
- set_tempo( tempo_ );
- remute_voices();
- return Gme_File::post_load();
-}
-
-// Tell/Seek
-
-int Music_Emu::msec_to_samples( int msec ) const
-{
- int sec = msec / 1000;
- msec -= sec * 1000;
- return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
-}
-
-int Music_Emu::tell() const
-{
- int rate = sample_rate() * stereo;
- int sec = track_filter.sample_count() / rate;
- return sec * 1000 + (track_filter.sample_count() - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Music_Emu::seek( int msec )
-{
- int time = msec_to_samples( msec );
- if ( time < track_filter.sample_count() )
- {
- RETURN_ERR( start_track( current_track_ ) );
- if ( fade_set )
- set_fade( length_msec, fade_msec );
- }
- return skip( time - track_filter.sample_count() );
-}
-
-blargg_err_t Music_Emu::skip( int count )
-{
- require( current_track() >= 0 ); // start_track() must have been called already
- return track_filter.skip( count );
-}
-
-blargg_err_t Music_Emu::skip_( int count )
-{
- // for long skip, mute sound
- const int threshold = 32768;
- if ( count > threshold )
- {
- int saved_mute = mute_mask_;
- mute_voices( ~0 );
-
- int n = count - threshold/2;
- n &= ~(2048-1); // round to multiple of 2048
- count -= n;
- RETURN_ERR( track_filter.skip_( n ) );
-
- mute_voices( saved_mute );
- }
-
- return track_filter.skip_( count );
-}
-
-// Playback
-
-blargg_err_t Music_Emu::start_track( int track )
-{
- clear_track_vars();
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- current_track_ = track;
- blargg_err_t err = start_track_( remapped );
- if ( err )
- {
- current_track_ = -1;
- return err;
- }
-
- // convert filter times to samples
- Track_Filter::setup_t s = tfilter;
- s.max_initial *= sample_rate() * stereo;
- #if GME_DISABLE_SILENCE_LOOKAHEAD
- s.lookahead = 1;
- #endif
- track_filter.setup( s );
-
- return track_filter.start_track();
-}
-
-void Music_Emu::set_fade( int start_msec, int length_msec )
-{
- fade_set = true;
- this->length_msec = start_msec;
- this->fade_msec = length_msec;
- track_filter.set_fade( msec_to_samples( start_msec ),
- length_msec * sample_rate() / (1000 / stereo) );
-}
-
-blargg_err_t Music_Emu::play( int out_count, sample_t out [] )
-{
- require( current_track() >= 0 );
- require( out_count % stereo == 0 );
-
- return track_filter.play( out_count, out );
-}
-
-// Gme_Info_
-
-blargg_err_t Gme_Info_::set_sample_rate_( int ) { return blargg_ok; }
-void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
-blargg_err_t Gme_Info_::post_load() { return Gme_File::post_load(); } // skip Music_Emu
-void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
-void Gme_Info_::mute_voices_( int ) { check( false ); }
-void Gme_Info_::set_tempo_( double ) { }
-blargg_err_t Gme_Info_::start_track_( int ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }
-blargg_err_t Gme_Info_::play_( int, sample_t [] ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Music_Emu.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const stereo = 2; // number of channels for stereo
+
+Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180, 0,0,0,0,0,0,0,0 };
+
+void Music_Emu::clear_track_vars()
+{
+ current_track_ = -1;
+ warning(); // clear warning
+ track_filter.stop();
+}
+
+void Music_Emu::unload()
+{
+ voice_count_ = 0;
+ clear_track_vars();
+ Gme_File::unload();
+}
+
+Music_Emu::gme_t()
+{
+ effects_buffer_ = NULL;
+ sample_rate_ = 0;
+ mute_mask_ = 0;
+ tempo_ = 1.0;
+ gain_ = 1.0;
+
+ fade_set = false;
+
+ // defaults
+ tfilter = track_filter.setup();
+ set_max_initial_silence( 15 );
+ set_silence_lookahead( 3 );
+ ignore_silence( false );
+
+ equalizer_.treble = -1.0;
+ equalizer_.bass = 60;
+
+ static const char* const names [] = {
+ "Voice 1", "Voice 2", "Voice 3", "Voice 4",
+ "Voice 5", "Voice 6", "Voice 7", "Voice 8"
+ };
+ set_voice_names( names );
+ Music_Emu::unload(); // clears fields
+}
+
+Music_Emu::~gme_t()
+{
+ assert( !effects_buffer_ );
+}
+
+blargg_err_t Music_Emu::set_sample_rate( int rate )
+{
+ require( !sample_rate() ); // sample rate can't be changed once set
+ RETURN_ERR( set_sample_rate_( rate ) );
+ RETURN_ERR( track_filter.init( this ) );
+ sample_rate_ = rate;
+ tfilter.max_silence = 6 * stereo * sample_rate();
+ return blargg_ok;
+}
+
+void Music_Emu::pre_load()
+{
+ require( sample_rate() ); // set_sample_rate() must be called before loading a file
+ Gme_File::pre_load();
+}
+
+void Music_Emu::set_equalizer( equalizer_t const& eq )
+{
+ // TODO: why is GCC generating memcpy call here?
+ // Without the 'if', valgrind flags it.
+ if ( &eq != &equalizer_ )
+ equalizer_ = eq;
+ set_equalizer_( eq );
+}
+
+void Music_Emu::mute_voice( int index, bool mute )
+{
+ require( (unsigned) index < (unsigned) voice_count() );
+ int bit = 1 << index;
+ int mask = mute_mask_ | bit;
+ if ( !mute )
+ mask ^= bit;
+ mute_voices( mask );
+}
+
+void Music_Emu::mute_voices( int mask )
+{
+ require( sample_rate() ); // sample rate must be set first
+ mute_mask_ = mask;
+ mute_voices_( mask );
+}
+
+const char* Music_Emu::voice_name( int i ) const
+{
+ if ( (unsigned) i < (unsigned) voice_count_ )
+ return voice_names_ [i];
+
+ //check( false ); // TODO: enable?
+ return "";
+}
+
+void Music_Emu::set_tempo( double t )
+{
+ require( sample_rate() ); // sample rate must be set first
+ double const min = 0.02;
+ double const max = 4.00;
+ if ( t < min ) t = min;
+ if ( t > max ) t = max;
+ tempo_ = t;
+ set_tempo_( t );
+}
+
+blargg_err_t Music_Emu::post_load()
+{
+ set_tempo( tempo_ );
+ remute_voices();
+ return Gme_File::post_load();
+}
+
+// Tell/Seek
+
+int Music_Emu::msec_to_samples( int msec ) const
+{
+ int sec = msec / 1000;
+ msec -= sec * 1000;
+ return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
+}
+
+int Music_Emu::tell() const
+{
+ int rate = sample_rate() * stereo;
+ int sec = track_filter.sample_count() / rate;
+ return sec * 1000 + (track_filter.sample_count() - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Music_Emu::seek( int msec )
+{
+ int time = msec_to_samples( msec );
+ if ( time < track_filter.sample_count() )
+ {
+ RETURN_ERR( start_track( current_track_ ) );
+ if ( fade_set )
+ set_fade( length_msec, fade_msec );
+ }
+ return skip( time - track_filter.sample_count() );
+}
+
+blargg_err_t Music_Emu::skip( int count )
+{
+ require( current_track() >= 0 ); // start_track() must have been called already
+ return track_filter.skip( count );
+}
+
+blargg_err_t Music_Emu::skip_( int count )
+{
+ // for long skip, mute sound
+ const int threshold = 32768;
+ if ( count > threshold )
+ {
+ int saved_mute = mute_mask_;
+ mute_voices( ~0 );
+
+ int n = count - threshold/2;
+ n &= ~(2048-1); // round to multiple of 2048
+ count -= n;
+ RETURN_ERR( track_filter.skip_( n ) );
+
+ mute_voices( saved_mute );
+ }
+
+ return track_filter.skip_( count );
+}
+
+// Playback
+
+blargg_err_t Music_Emu::start_track( int track )
+{
+ clear_track_vars();
+
+ int remapped = track;
+ RETURN_ERR( remap_track_( &remapped ) );
+ current_track_ = track;
+ blargg_err_t err = start_track_( remapped );
+ if ( err )
+ {
+ current_track_ = -1;
+ return err;
+ }
+
+ // convert filter times to samples
+ Track_Filter::setup_t s = tfilter;
+ s.max_initial *= sample_rate() * stereo;
+ #if GME_DISABLE_SILENCE_LOOKAHEAD
+ s.lookahead = 1;
+ #endif
+ track_filter.setup( s );
+
+ return track_filter.start_track();
+}
+
+void Music_Emu::set_fade( int start_msec, int length_msec )
+{
+ fade_set = true;
+ this->length_msec = start_msec;
+ this->fade_msec = length_msec;
+ track_filter.set_fade( start_msec < 0 ? Track_Filter::indefinite_count : msec_to_samples( start_msec ),
+ length_msec * sample_rate() / (1000 / stereo) );
+}
+
+blargg_err_t Music_Emu::play( int out_count, sample_t out [] )
+{
+ require( current_track() >= 0 );
+ require( out_count % stereo == 0 );
+
+ return track_filter.play( out_count, out );
+}
+
+// Gme_Info_
+
+blargg_err_t Gme_Info_::set_sample_rate_( int ) { return blargg_ok; }
+void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
+blargg_err_t Gme_Info_::post_load() { return Gme_File::post_load(); } // skip Music_Emu
+void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
+void Gme_Info_::mute_voices_( int ) { check( false ); }
+void Gme_Info_::set_tempo_( double ) { }
+blargg_err_t Gme_Info_::start_track_( int ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }
+blargg_err_t Gme_Info_::play_( int, sample_t [] ) { return BLARGG_ERR( BLARGG_ERR_CALLER, "can't play file opened for info only" ); }
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Music_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Music_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Music_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Music_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,280 +1,280 @@
-// Common interface to game music file emulators
-
-// Game_Music_Emu $vers
-#ifndef MUSIC_EMU_H
-#define MUSIC_EMU_H
-
-#include "Gme_File.h"
-#include "Track_Filter.h"
-#include "blargg_errors.h"
-class Multi_Buffer;
-
-struct gme_t : public Gme_File, private Track_Filter::callbacks_t {
-public:
- // Sets output sample rate. Must be called only once before loading file.
- blargg_err_t set_sample_rate( int sample_rate );
-
- // Sample rate sound is generated at
- int sample_rate() const;
-
-// File loading
-
- // See Gme_Loader.h
-
-// Basic playback
-
- // Starts a track, where 0 is the first track. Also clears warning string.
- blargg_err_t start_track( int );
-
- // Generates 'count' samples info 'buf'. Output is in stereo. Any emulation
- // errors set warning string, and major errors also end track.
- typedef short sample_t;
- blargg_err_t play( int count, sample_t* buf );
-
-// Track information
-
- // See Gme_File.h
-
- // Index of current track or -1 if one hasn't been started
- int current_track() const;
-
- // Info for currently playing track
- using Gme_File::track_info;
- blargg_err_t track_info( track_info_t* out ) const;
- blargg_err_t set_track_info( const track_info_t* in );
- blargg_err_t set_track_info( const track_info_t* in, int track_number );
-
- struct Hash_Function
- {
- virtual void hash_( byte const* data, size_t size ) BLARGG_PURE( ; )
- };
- virtual blargg_err_t hash_( Hash_Function& ) const BLARGG_PURE( ; )
-
- blargg_err_t save( gme_writer_t writer, void* your_data) const;
-
-// Track status/control
-
- // Number of milliseconds played since beginning of track (1000 per second)
- int tell() const;
-
- // Seeks to new time in track. Seeking backwards or far forward can take a while.
- blargg_err_t seek( int msec );
-
- // Skips n samples
- blargg_err_t skip( int n );
-
- // True if a track has reached its end
- bool track_ended() const;
-
- // Sets start time and length of track fade out. Once fade ends track_ended() returns
- // true. Fade time must be set after track has been started, and can be changed
- // at any time.
- void set_fade( int start_msec, int length_msec = 8000 );
-
- // Disables automatic end-of-track detection and skipping of silence at beginning
- void ignore_silence( bool disable = true );
-
-// Voices
-
- // Number of voices used by currently loaded file
- int voice_count() const;
-
- // Name of voice i, from 0 to voice_count()-1
- const char* voice_name( int i ) const;
-
- // Mutes/unmutes voice i, where voice 0 is first voice
- void mute_voice( int index, bool mute = true );
-
- // Sets muting state of all voices at once using a bit mask, where -1 mutes them all,
- // 0 unmutes them all, 0x01 mutes just the first voice, etc.
- void mute_voices( int mask );
-
-// Sound customization
-
- // Adjusts song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
- // Track length as returned by track_info() assumes a tempo of 1.0.
- void set_tempo( double );
-
- // Changes overall output amplitude, where 1.0 results in minimal clamping.
- // Must be called before set_sample_rate().
- void set_gain( double );
-
- // Requests use of custom multichannel buffer. Only supported by "classic" emulators;
- // on others this has no effect. Should be called only once *before* set_sample_rate().
- virtual void set_buffer( class Multi_Buffer* ) { }
-
-// Sound equalization (treble/bass)
-
- // Frequency equalizer parameters (see gme.txt)
- // See gme.h for definition of struct gme_equalizer_t.
- typedef gme_equalizer_t equalizer_t;
-
- // Current frequency equalizater parameters
- equalizer_t const& equalizer() const;
-
- // Sets frequency equalizer parameters
- void set_equalizer( equalizer_t const& );
-
- // Equalizer preset for a TV speaker
- static equalizer_t const tv_eq;
-
-// Derived interface
-protected:
- // Cause any further generated samples to be silence, instead of calling play_()
- void set_track_ended() { track_filter.set_track_ended(); }
-
- // If more than secs of silence are encountered, track is ended
- void set_max_initial_silence( int secs ) { tfilter.max_initial = secs; }
-
- // Sets rate emulator is run at when scanning ahead for silence. 1=100%, 2=200% etc.
- void set_silence_lookahead( int rate ) { tfilter.lookahead = rate; }
-
- // Sets number of voices
- void set_voice_count( int n ) { voice_count_ = n; }
-
- // Sets names of voices
- void set_voice_names( const char* const names [] );
-
- // Current gain
- double gain() const { return gain_; }
-
- // Current tempo
- double tempo() const { return tempo_; }
-
- // Re-applies muting mask using mute_voices_()
- void remute_voices();
-
-// Overrides should do the indicated task
-
- // Set sample rate as close as possible to sample_rate, then call
- // Music_Emu::set_sample_rate_() with the actual rate used.
- virtual blargg_err_t set_sample_rate_( int sample_rate ) BLARGG_PURE( ; )
-
- // Set equalizer parameters
- virtual void set_equalizer_( equalizer_t const& ) { }
-
- // Mute voices based on mask
- virtual void mute_voices_( int mask ) BLARGG_PURE( ; )
-
- // Set tempo to t, which is constrained to the range 0.02 to 4.0.
- virtual void set_tempo_( double t ) BLARGG_PURE( ; )
-
- // Start track t, where 0 is the first track
- virtual blargg_err_t start_track_( int t ) BLARGG_PURE( ; ) // tempo is set before this
-
- // Generate count samples into *out. Count will always be even.
- virtual blargg_err_t play_( int count, sample_t out [] ) BLARGG_PURE( ; )
-
- // Skip count samples. Count will always be even.
- virtual blargg_err_t skip_( int count );
-
- // Save current state of file to specified writer.
- virtual blargg_err_t save_( gme_writer_t, void* ) const { return "Not supported by this format"; }
-
- // Set track info
- virtual blargg_err_t set_track_info_( const track_info_t*, int ) { return "Not supported by this format"; }
-
-// Implementation
-public:
- gme_t();
- ~gme_t();
- BLARGG_DEPRECATED( const char** voice_names() const { return CONST_CAST(const char**,voice_names_); } )
-
-protected:
- virtual void unload();
- virtual void pre_load();
- virtual blargg_err_t post_load();
-
-private:
- Track_Filter::setup_t tfilter;
- Track_Filter track_filter;
- equalizer_t equalizer_;
- const char* const* voice_names_;
- int voice_count_;
- int mute_mask_;
- double tempo_;
- double gain_;
- int sample_rate_;
- int current_track_;
-
- bool fade_set;
- int length_msec;
- int fade_msec;
-
- void clear_track_vars();
- int msec_to_samples( int msec ) const;
-
- friend Music_Emu* gme_new_emu( gme_type_t, int );
- friend void gme_effects( Music_Emu const*, gme_effects_t* );
- friend void gme_set_effects( Music_Emu*, gme_effects_t const* );
- friend void gme_set_stereo_depth( Music_Emu*, double );
- friend const char** gme_voice_names ( Music_Emu const* );
-
-protected:
- Multi_Buffer* effects_buffer_;
-};
-
-// base class for info-only derivations
-struct Gme_Info_ : Music_Emu
-{
- virtual blargg_err_t set_sample_rate_( int sample_rate );
- virtual void set_equalizer_( equalizer_t const& );
- virtual void mute_voices_( int mask );
- virtual void set_tempo_( double );
- virtual blargg_err_t start_track_( int );
- virtual blargg_err_t play_( int count, sample_t out [] );
- virtual void pre_load();
- virtual blargg_err_t post_load();
-};
-
-inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
-{
- return track_info( out, current_track_ );
-}
-
-inline blargg_err_t Music_Emu::save(gme_writer_t writer, void *your_data) const
-{
- return save_( writer, your_data );
-}
-
-inline blargg_err_t Music_Emu::set_track_info(const track_info_t *in)
-{
- return set_track_info_( in, current_track_ );
-}
-
-inline blargg_err_t Music_Emu::set_track_info(const track_info_t *in, int track)
-{
- return set_track_info_( in, track );
-}
-
-inline int Music_Emu::sample_rate() const { return sample_rate_; }
-inline int Music_Emu::voice_count() const { return voice_count_; }
-inline int Music_Emu::current_track() const { return current_track_; }
-inline bool Music_Emu::track_ended() const { return track_filter.track_ended(); }
-inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
-
-inline void Music_Emu::ignore_silence( bool b ) { track_filter.ignore_silence( b ); }
-inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
-inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
-
-inline void Music_Emu::set_voice_names( const char* const p [] ) { voice_names_ = p; }
-
-inline void Music_Emu::mute_voices_( int ) { }
-
-inline void Music_Emu::set_gain( double g )
-{
- assert( !sample_rate() ); // you must set gain before setting sample rate
- gain_ = g;
-}
-
-inline blargg_err_t Music_Emu::start_track_( int ) { return blargg_ok; }
-
-inline blargg_err_t Music_Emu::set_sample_rate_( int ) { return blargg_ok; }
-
-inline blargg_err_t Music_Emu::play_( int, sample_t [] ) { return blargg_ok; }
-
-inline blargg_err_t Music_Emu::hash_( Hash_Function& ) const { return BLARGG_ERR( BLARGG_ERR_CALLER, "no hashing function defined" ); }
-
-inline void Music_Emu::Hash_Function::hash_( byte const*, size_t ) { }
-
-#endif
+// Common interface to game music file emulators
+
+// Game_Music_Emu $vers
+#ifndef MUSIC_EMU_H
+#define MUSIC_EMU_H
+
+#include "Gme_File.h"
+#include "Track_Filter.h"
+#include "blargg_errors.h"
+class Multi_Buffer;
+
+struct gme_t : public Gme_File, private Track_Filter::callbacks_t {
+public:
+ // Sets output sample rate. Must be called only once before loading file.
+ blargg_err_t set_sample_rate( int sample_rate );
+
+ // Sample rate sound is generated at
+ int sample_rate() const;
+
+// File loading
+
+ // See Gme_Loader.h
+
+// Basic playback
+
+ // Starts a track, where 0 is the first track. Also clears warning string.
+ blargg_err_t start_track( int );
+
+ // Generates 'count' samples info 'buf'. Output is in stereo. Any emulation
+ // errors set warning string, and major errors also end track.
+ typedef short sample_t;
+ blargg_err_t play( int count, sample_t* buf );
+
+// Track information
+
+ // See Gme_File.h
+
+ // Index of current track or -1 if one hasn't been started
+ int current_track() const;
+
+ // Info for currently playing track
+ using Gme_File::track_info;
+ blargg_err_t track_info( track_info_t* out ) const;
+ blargg_err_t set_track_info( const track_info_t* in );
+ blargg_err_t set_track_info( const track_info_t* in, int track_number );
+
+ struct Hash_Function
+ {
+ virtual void hash_( byte const* data, size_t size ) BLARGG_PURE( ; )
+ };
+ virtual blargg_err_t hash_( Hash_Function& ) const BLARGG_PURE( ; )
+
+ blargg_err_t save( gme_writer_t writer, void* your_data) const;
+
+// Track status/control
+
+ // Number of milliseconds played since beginning of track (1000 per second)
+ int tell() const;
+
+ // Seeks to new time in track. Seeking backwards or far forward can take a while.
+ blargg_err_t seek( int msec );
+
+ // Skips n samples
+ blargg_err_t skip( int n );
+
+ // True if a track has reached its end
+ bool track_ended() const;
+
+ // Sets start time and length of track fade out. Once fade ends track_ended() returns
+ // true. Fade time must be set after track has been started, and can be changed
+ // at any time.
+ void set_fade( int start_msec, int length_msec = 8000 );
+
+ // Disables automatic end-of-track detection and skipping of silence at beginning
+ void ignore_silence( bool disable = true );
+
+// Voices
+
+ // Number of voices used by currently loaded file
+ int voice_count() const;
+
+ // Name of voice i, from 0 to voice_count()-1
+ const char* voice_name( int i ) const;
+
+ // Mutes/unmutes voice i, where voice 0 is first voice
+ void mute_voice( int index, bool mute = true );
+
+ // Sets muting state of all voices at once using a bit mask, where -1 mutes them all,
+ // 0 unmutes them all, 0x01 mutes just the first voice, etc.
+ void mute_voices( int mask );
+
+// Sound customization
+
+ // Adjusts song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
+ // Track length as returned by track_info() assumes a tempo of 1.0.
+ void set_tempo( double );
+
+ // Changes overall output amplitude, where 1.0 results in minimal clamping.
+ // Must be called before set_sample_rate().
+ void set_gain( double );
+
+ // Requests use of custom multichannel buffer. Only supported by "classic" emulators;
+ // on others this has no effect. Should be called only once *before* set_sample_rate().
+ virtual void set_buffer( class Multi_Buffer* ) { }
+
+// Sound equalization (treble/bass)
+
+ // Frequency equalizer parameters (see gme.txt)
+ // See gme.h for definition of struct gme_equalizer_t.
+ typedef gme_equalizer_t equalizer_t;
+
+ // Current frequency equalizater parameters
+ equalizer_t const& equalizer() const;
+
+ // Sets frequency equalizer parameters
+ void set_equalizer( equalizer_t const& );
+
+ // Equalizer preset for a TV speaker
+ static equalizer_t const tv_eq;
+
+// Derived interface
+protected:
+ // Cause any further generated samples to be silence, instead of calling play_()
+ void set_track_ended() { track_filter.set_track_ended(); }
+
+ // If more than secs of silence are encountered, track is ended
+ void set_max_initial_silence( int secs ) { tfilter.max_initial = secs; }
+
+ // Sets rate emulator is run at when scanning ahead for silence. 1=100%, 2=200% etc.
+ void set_silence_lookahead( int rate ) { tfilter.lookahead = rate; }
+
+ // Sets number of voices
+ void set_voice_count( int n ) { voice_count_ = n; }
+
+ // Sets names of voices
+ void set_voice_names( const char* const names [] );
+
+ // Current gain
+ double gain() const { return gain_; }
+
+ // Current tempo
+ double tempo() const { return tempo_; }
+
+ // Re-applies muting mask using mute_voices_()
+ void remute_voices();
+
+// Overrides should do the indicated task
+
+ // Set sample rate as close as possible to sample_rate, then call
+ // Music_Emu::set_sample_rate_() with the actual rate used.
+ virtual blargg_err_t set_sample_rate_( int sample_rate ) BLARGG_PURE( ; )
+
+ // Set equalizer parameters
+ virtual void set_equalizer_( equalizer_t const& ) { }
+
+ // Mute voices based on mask
+ virtual void mute_voices_( int mask ) BLARGG_PURE( ; )
+
+ // Set tempo to t, which is constrained to the range 0.02 to 4.0.
+ virtual void set_tempo_( double t ) BLARGG_PURE( ; )
+
+ // Start track t, where 0 is the first track
+ virtual blargg_err_t start_track_( int t ) BLARGG_PURE( ; ) // tempo is set before this
+
+ // Generate count samples into *out. Count will always be even.
+ virtual blargg_err_t play_( int count, sample_t out [] ) BLARGG_PURE( ; )
+
+ // Skip count samples. Count will always be even.
+ virtual blargg_err_t skip_( int count );
+
+ // Save current state of file to specified writer.
+ virtual blargg_err_t save_( gme_writer_t, void* ) const { return "Not supported by this format"; }
+
+ // Set track info
+ virtual blargg_err_t set_track_info_( const track_info_t*, int ) { return "Not supported by this format"; }
+
+// Implementation
+public:
+ gme_t();
+ ~gme_t();
+ BLARGG_DEPRECATED( const char** voice_names() const { return CONST_CAST(const char**,voice_names_); } )
+
+protected:
+ virtual void unload();
+ virtual void pre_load();
+ virtual blargg_err_t post_load();
+
+private:
+ Track_Filter::setup_t tfilter;
+ Track_Filter track_filter;
+ equalizer_t equalizer_;
+ const char* const* voice_names_;
+ int voice_count_;
+ int mute_mask_;
+ double tempo_;
+ double gain_;
+ int sample_rate_;
+ int current_track_;
+
+ bool fade_set;
+ int length_msec;
+ int fade_msec;
+
+ void clear_track_vars();
+ int msec_to_samples( int msec ) const;
+
+ friend Music_Emu* gme_new_emu( gme_type_t, int );
+ friend void gme_effects( Music_Emu const*, gme_effects_t* );
+ friend void gme_set_effects( Music_Emu*, gme_effects_t const* );
+ friend void gme_set_stereo_depth( Music_Emu*, double );
+ friend const char** gme_voice_names ( Music_Emu const* );
+
+protected:
+ Multi_Buffer* effects_buffer_;
+};
+
+// base class for info-only derivations
+struct Gme_Info_ : Music_Emu
+{
+ virtual blargg_err_t set_sample_rate_( int sample_rate );
+ virtual void set_equalizer_( equalizer_t const& );
+ virtual void mute_voices_( int mask );
+ virtual void set_tempo_( double );
+ virtual blargg_err_t start_track_( int );
+ virtual blargg_err_t play_( int count, sample_t out [] );
+ virtual void pre_load();
+ virtual blargg_err_t post_load();
+};
+
+inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
+{
+ return track_info( out, current_track_ );
+}
+
+inline blargg_err_t Music_Emu::save(gme_writer_t writer, void *your_data) const
+{
+ return save_( writer, your_data );
+}
+
+inline blargg_err_t Music_Emu::set_track_info(const track_info_t *in)
+{
+ return set_track_info_( in, current_track_ );
+}
+
+inline blargg_err_t Music_Emu::set_track_info(const track_info_t *in, int track)
+{
+ return set_track_info_( in, track );
+}
+
+inline int Music_Emu::sample_rate() const { return sample_rate_; }
+inline int Music_Emu::voice_count() const { return voice_count_; }
+inline int Music_Emu::current_track() const { return current_track_; }
+inline bool Music_Emu::track_ended() const { return track_filter.track_ended(); }
+inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
+
+inline void Music_Emu::ignore_silence( bool b ) { track_filter.ignore_silence( b ); }
+inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
+inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
+
+inline void Music_Emu::set_voice_names( const char* const p [] ) { voice_names_ = p; }
+
+inline void Music_Emu::mute_voices_( int ) { }
+
+inline void Music_Emu::set_gain( double g )
+{
+ assert( !sample_rate() ); // you must set gain before setting sample rate
+ gain_ = g;
+}
+
+inline blargg_err_t Music_Emu::start_track_( int ) { return blargg_ok; }
+
+inline blargg_err_t Music_Emu::set_sample_rate_( int ) { return blargg_ok; }
+
+inline blargg_err_t Music_Emu::play_( int, sample_t [] ) { return blargg_ok; }
+
+inline blargg_err_t Music_Emu::hash_( Hash_Function& ) const { return BLARGG_ERR( BLARGG_ERR_CALLER, "no hashing function defined" ); }
+
+inline void Music_Emu::Hash_Function::hash_( byte const*, size_t ) { }
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Cpu_run.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Cpu_run.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Cpu_run.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Cpu_run.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,1121 +1,1121 @@
-// NES 6502 CPU emulator run function
-
-#if 0
-/* Define these macros in the source file before #including this file.
-- Parameters might be expressions, so they are best evaluated only once,
-though they NEVER have side-effects, so multiple evaluation is OK.
-- Output parameters might be a multiple-assignment expression like "a=x",
-so they must NOT be parenthesized.
-- Except where noted, time() and related functions will NOT work
-correctly inside a macro. TIME() is always correct, and FLUSH_TIME() and
-CACHE_TIME() allow the time changing functions to work.
-- Macros "returning" void may use a {} statement block. */
-
- // 0 <= addr <= 0xFFFF + page_size
- // time functions can be used
- int READ_MEM( addr_t );
- void WRITE_MEM( addr_t, int data );
- // 0 <= READ_MEM() <= 0xFF
-
- // 0 <= addr <= 0x1FF
- int READ_LOW( addr_t );
- void WRITE_LOW( addr_t, int data );
- // 0 <= READ_LOW() <= 0xFF
-
- // Often-used instructions attempt these before using a normal memory access.
- // Optional; defaults to READ_MEM() and WRITE_MEM()
- bool CAN_READ_FAST( addr_t ); // if true, uses result of READ_FAST
- void READ_FAST( addr_t, int& out ); // ALWAYS called BEFORE CAN_READ_FAST
- bool CAN_WRITE_FAST( addr_t ); // if true, uses WRITE_FAST instead of WRITE_MEM
- void WRITE_FAST( addr_t, int data );
-
- // Used by instructions most often used to access the NES PPU (LDA abs and BIT abs).
- // Optional; defaults to READ_MEM.
- void READ_PPU( addr_t, int& out );
- // 0 <= out <= 0xFF
-
-// The following can be used within macros:
-
- // Current time
- time_t TIME();
-
- // Allows use of time functions
- void FLUSH_TIME();
-
- // Must be used before end of macro if FLUSH_TIME() was used earlier
- void CACHE_TIME();
-
-// Configuration (optional; commented behavior if defined)
-
- // Emulates dummy reads for indexed instructions
- #define NES_CPU_DUMMY_READS 1
-
- // Optimizes as if map_code( 0, 0x10000 + cpu_padding, FLAT_MEM ) is always in effect
- #define FLAT_MEM my_mem_array
-
- // Expanded just before beginning of code, to help debugger
- #define CPU_BEGIN void my_run_cpu() {
-
-#endif
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// Allows MWCW debugger to step through code properly
-#ifdef CPU_BEGIN
- CPU_BEGIN
-#endif
-
-// Time
-#define TIME() (s_time + s.base)
-#define FLUSH_TIME() {s.time = s_time - time_offset;}
-#define CACHE_TIME() {s_time = s.time + time_offset;}
-
-// Defaults
-#ifndef CAN_WRITE_FAST
- #define CAN_WRITE_FAST( addr ) 0
- #define WRITE_FAST( addr, data )
-#endif
-
-#ifndef CAN_READ_FAST
- #define CAN_READ_FAST( addr ) 0
- #define READ_FAST( addr, out )
-#endif
-
-#ifndef READ_PPU
- #define READ_PPU( addr, out )\
- {\
- FLUSH_TIME();\
- out = READ_MEM( addr );\
- CACHE_TIME();\
- }
-#endif
-
-#define READ_STACK READ_LOW
-#define WRITE_STACK WRITE_LOW
-
-// Dummy reads
-#if NES_CPU_DUMMY_READS
- // TODO: optimize time handling
- #define DUMMY_READ( addr, idx ) \
- if ( (addr & 0xFF) < idx )\
- {\
- int const time_offset = 1;\
- FLUSH_TIME();\
- READ_MEM( (addr - 0x100) );\
- CACHE_TIME();\
- }
-#else
- #define DUMMY_READ( addr, idx )
-#endif
-
-// Code
-#ifdef FLAT_MEM
- #define CODE_PAGE( addr ) (FLAT_MEM)
- #define CODE_OFFSET( addr ) (addr)
-#else
- #define CODE_PAGE( addr ) (s.code_map [NES_CPU_PAGE( addr )])
- #define CODE_OFFSET( addr ) NES_CPU_OFFSET( addr )
-#endif
-#define READ_CODE( addr ) (CODE_PAGE( addr ) [CODE_OFFSET( addr )])
-
-// Stack
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define SP( o ) ((sp + (o - (o>0)*0x100)) | 0x100)
-
-// Truncation
-#define BYTE( n ) ((BOOST::uint8_t ) (n)) /* (unsigned) n & 0xFF */
-#define SBYTE( n ) ((BOOST::int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
-#define WORD( n ) ((BOOST::uint16_t) (n)) /* (unsigned) n & 0xFFFF */
-
-// Flags with hex value for clarity when used as mask.
-// Stored in indicated variable during emulation.
-int const n80 = 0x80; // nz
-int const v40 = 0x40; // flags
-int const r20 = 0x20;
-int const b10 = 0x10;
-int const d08 = 0x08; // flags
-int const i04 = 0x04; // flags
-int const z02 = 0x02; // nz
-int const c01 = 0x01; // c
-
-#define IS_NEG (nz & 0x8080)
-
-#define GET_FLAGS( out ) \
-{\
- out = flags & (v40 | d08 | i04);\
- out += ((nz >> 8) | nz) & n80;\
- out += c >> 8 & c01;\
- if ( !BYTE( nz ) )\
- out += z02;\
-}
-
-#define SET_FLAGS( in ) \
-{\
- flags = in & (v40 | d08 | i04);\
- c = nz = in << 8;\
- nz += ~in & z02;\
-}
-
-{
- int const time_offset = 0;
-
- // Local state
- Nes_Cpu::cpu_state_t s;
- #ifdef FLAT_MEM
- s.base = CPU.cpu_state_.base;
- #else
- s = CPU.cpu_state_;
- #endif
- CPU.cpu_state = &s;
- int s_time = CPU.cpu_state_.time; // helps even on x86
-
- // Registers
- int pc = CPU.r.pc;
- int a = CPU.r.a;
- int x = CPU.r.x;
- int y = CPU.r.y;
- int sp;
- SET_SP( CPU.r.sp );
-
- // Flags
- int flags;
- int c; // carry set if (c & 0x100) != 0
- int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- int temp = CPU.r.flags;
- SET_FLAGS( temp );
- }
-
-loop:
-
- // Check all values
- check( (unsigned) sp - 0x100 < 0x100 );
- check( (unsigned) pc < 0x10000 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- // Read instruction
- byte const* instr = CODE_PAGE( pc );
- int opcode;
-
- if ( CODE_OFFSET(~0) == ~0 )
- {
- opcode = instr [pc];
- pc++;
- instr += pc;
- }
- else
- {
- instr += CODE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- }
-
- // local to function in case it helps optimizer
- static byte const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
- 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
- 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
- 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
- 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
- 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
- 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
- }; // 0x00 was 7 and 0x22 was 2
-
- // Update time
- if ( s_time >= 0 )
- goto out_of_time;
-
- #ifdef CPU_INSTR_HOOK
- { CPU_INSTR_HOOK( (pc-1), (&instr [-1]), a, x, y, GET_SP(), TIME() ); }
- #endif
-
- s_time += clock_table [opcode];
-
- int data;
- data = *instr;
-
- switch ( opcode )
- {
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB())
-#define GET_ADDR() GET_LE16( instr )
-
-#define PAGE_PENALTY( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC( reg, n ) reg = BYTE( nz = reg + n ); goto loop;
-
-#define IND_Y( cross, out ) {\
- int temp = READ_LOW( data ) + y;\
- out = temp + 0x100 * READ_LOW( BYTE( data + 1 ) );\
- cross( temp );\
- }
-
-#define IND_X( out ) {\
- int temp = data + x;\
- out = 0x100 * READ_LOW( BYTE( temp + 1 ) ) + READ_LOW( BYTE( temp ) );\
- }
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
- IND_X( data )\
- goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
- IND_Y( PAGE_PENALTY, data )\
- goto ptr##op;\
-case op + 0x10: /* zp,X */\
- data = BYTE( data + x );\
-case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
-case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
-case op + 0x18: /* abs,X */\
- data += x;\
-ind##op:\
- PAGE_PENALTY( data );\
-case op + 0x08: /* abs */\
- ADD_PAGE( data );\
-ptr##op:\
- FLUSH_TIME();\
- data = READ_MEM( data );\
- CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- ++pc;\
- if ( !(cond) ) goto loop;\
- s_time++;\
- int offset = SBYTE( data );\
- s_time += (BYTE(pc) + offset) >> 8 & 1;\
- pc = WORD( pc + offset );\
- goto loop;\
-}
-
-// Often-Used
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( BYTE( data + x ) );
- pc++;
- goto loop;
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
- case 0xD0: // BNE
- BRANCH( BYTE( nz ) );
-
- case 0x20: { // JSR
- int temp = pc + 1;
- pc = GET_ADDR();
- WRITE_STACK( SP( -1 ), temp >> 8 );
- sp = SP( -2 );
- WRITE_STACK( sp, temp );
- goto loop;
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0xE8: // INX
- INC_DEC( x, 1 )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0xF0: // BEQ
- BRANCH( !BYTE( nz ) );
-
- case 0x95: // STA zp,x
- data = BYTE( data + x );
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xC8: // INY
- INC_DEC( y, 1 )
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAD:{// LDA abs
- int addr = GET_ADDR();
- pc += 2;
- READ_PPU( addr, a = nz );
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 1 + READ_STACK( sp );
- pc += 0x100 * READ_STACK( SP( 1 ) );
- sp = SP( 2 );
- goto loop;
-
- {
- int addr;
-
- case 0x8D: // STA abs
- addr = GET_ADDR();
- pc += 2;
- if ( CAN_WRITE_FAST( addr ) )
- {
- WRITE_FAST( addr, a );
- goto loop;
- }
- sta_ptr:
- FLUSH_TIME();
- WRITE_MEM( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x99: // STA abs,Y
- addr = y + GET_ADDR();
- pc += 2;
- if ( CAN_WRITE_FAST( addr ) )
- {
- WRITE_FAST( addr, a );
- goto loop;
- }
- goto sta_abs_x;
-
- case 0x9D: // STA abs,X (slightly more common than STA abs)
- addr = x + GET_ADDR();
- pc += 2;
- if ( CAN_WRITE_FAST( addr ) )
- {
- WRITE_FAST( addr, a );
- goto loop;
- }
- DUMMY_READ( addr, x );
- sta_abs_x:
- FLUSH_TIME();
- WRITE_MEM( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x91: // STA (ind),Y
- #define NO_PAGE_PENALTY( lsb )
- IND_Y( NO_PAGE_PENALTY, addr )
- pc++;
- DUMMY_READ( addr, y );
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- IND_X( addr )
- pc++;
- goto sta_ptr;
-
- }
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
- // common read instructions
- {
- int addr;
-
- case 0xA1: // LDA (ind,X)
- IND_X( addr )
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- PAGE_PENALTY( addr );
- addr += 0x100 * READ_LOW( BYTE( data + 1 ) );
- pc++;
- READ_FAST( addr, a = nz );
- if ( CAN_READ_FAST( addr ) )
- goto loop;
- DUMMY_READ( addr, y );
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- PAGE_PENALTY( data + y );
- addr = GET_ADDR() + y;
- pc += 2;
- READ_FAST( addr, a = nz );
- if ( CAN_READ_FAST( addr ) )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xBD: // LDA abs,X
- PAGE_PENALTY( data + x );
- addr = GET_ADDR() + x;
- pc += 2;
- READ_FAST( addr, a = nz );
- if ( CAN_READ_FAST( addr ) )
- goto loop;
- DUMMY_READ( addr, x );
- a_nz_read_addr:
- FLUSH_TIME();
- a = nz = READ_MEM( addr );
- CACHE_TIME();
- goto loop;
-
- }
-
-// Branch
-
- case 0x50: // BVC
- BRANCH( !(flags & v40) )
-
- case 0x70: // BVS
- BRANCH( flags & v40 )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
-// Load/store
-
- case 0x94: // STY zp,x
- data = BYTE( data + x );
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = BYTE( data + y );
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = BYTE( data + y );
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = BYTE( data + x );
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- PAGE_PENALTY( data );
- case 0xAC:{// LDY abs
- int addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ_MEM( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xBE: // LDX abs,y
- data += y;
- PAGE_PENALTY( data );
- case 0xAE:{// LDX abs
- int addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- x = nz = READ_MEM( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- int temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- int addr = GET_ADDR();
- pc += 2;
- if ( CAN_WRITE_FAST( addr ) )
- {
- WRITE_FAST( addr, temp );
- goto loop;
- }
- FLUSH_TIME();
- WRITE_MEM( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- int addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ_MEM( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- int addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ_MEM( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
- case 0x2C:{// BIT abs
- int addr = GET_ADDR();
- pc += 2;
- READ_PPU( addr, nz );
- flags = (flags & ~v40) + (nz & v40);
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
- }
-
- case 0x24: // BIT zp
- nz = READ_LOW( data );
- pc++;
- flags = (flags & ~v40) + (nz & v40);
- if ( a & nz )
- goto loop; // Z should be clear, and nz must be non-zero if nz & a is
- nz <<= 8; // set Z flag without affecting N flag
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- case 0xEB: // unofficial equivalent
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- int carry = c >> 8 & 1;
- int ov = (a ^ 0x80) + carry + SBYTE( data );
- flags = (flags & ~v40) + (ov >> 2 & v40);
- c = nz = a + data + carry;
- pc++;
- a = BYTE( nz );
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz += a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = BYTE( nz );
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- int temp = c >> 8 & 1;
- c = nz;
- nz += temp;
- a = BYTE( nz );
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE( data );
- FLUSH_TIME();
- int temp = READ_MEM( data );
- nz = (c >> 1 & 0x80) + (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE( data );
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz += (c = READ_MEM( data ) << 1);
- rotate_common:
- pc++;
- WRITE_MEM( data, BYTE( nz ) );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = BYTE( data + x );
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = BYTE( data + x );
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) + (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = BYTE( data + x );
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = BYTE( data + x );
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz += (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
- case 0xCA: // DEX
- INC_DEC( x, -1 )
-
- case 0x88: // DEY
- INC_DEC( y, -1 )
-
- case 0xF6: // INC zp,x
- data = BYTE( data + x );
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = BYTE( data + x );
- case 0xC6: // DEC zp
- nz = -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = -1;
- inc_common:
- FLUSH_TIME();
- pc += 2;
- nz += READ_MEM( data );
- WRITE_MEM( data, BYTE( nz ) );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xAA: // TAX
- x = nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- sp = SP( -1 );
- WRITE_STACK( sp, a );
- goto loop;
-
- case 0x68: // PLA
- a = nz = READ_STACK( sp );
- sp = SP( 1 );
- goto loop;
-
- case 0x40:{// RTI
- pc = READ_STACK( SP( 1 ) );
- pc += READ_STACK( SP( 2 ) ) * 0x100;
- int temp = READ_STACK( sp );
- sp = SP( 3 );
- data = flags;
- SET_FLAGS( temp );
- CPU.r.flags = flags; // update externally-visible I flag
- int delta = s.base - CPU.irq_time_;
- if ( delta <= 0 ) goto loop; // end_time < irq_time
- if ( flags & i04 ) goto loop;
- s_time += delta;
- s.base = CPU.irq_time_;
- goto loop;
- }
-
- case 0x28:{// PLP
- int temp = READ_STACK( sp );
- sp = SP( 1 );
- int changed = flags ^ temp;
- SET_FLAGS( temp );
- if ( !(changed & i04) )
- goto loop; // I flag didn't change
- if ( flags & i04 )
- goto handle_sei;
- goto handle_cli;
- }
-
- case 0x08:{// PHP
- int temp;
- GET_FLAGS( temp );
- sp = SP( -1 );
- WRITE_STACK( sp, temp | (b10 | r20) );
- goto loop;
- }
-
- case 0x6C:{// JMP (ind)
- data = GET_ADDR();
- byte const* page = CODE_PAGE( data );
- pc = page [CODE_OFFSET( data )];
- data = (data & 0xFF00) + ((data + 1) & 0xFF);
- pc += page [CODE_OFFSET( data )] * 0x100;
- goto loop;
- }
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Flags
-
- case 0x38: // SEC
- c = 0x100;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- flags &= ~v40;
- goto loop;
-
- case 0xD8: // CLD
- flags &= ~d08;
- goto loop;
-
- case 0xF8: // SED
- flags |= d08;
- goto loop;
-
- case 0x58: // CLI
- if ( !(flags & i04) )
- goto loop;
- flags &= ~i04;
- handle_cli: {
- //dprintf( "CLI at %d\n", TIME );
- CPU.r.flags = flags; // update externally-visible I flag
- int delta = s.base - CPU.irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME() < CPU.irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = CPU.irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- // delayed irq until after next instruction
- s.base += s_time + 1;
- s_time = -1;
- goto loop;
- }
-
- // TODO: implement
- delayed_cli:
- dprintf( "Delayed CLI not emulated\n" );
- goto loop;
- }
-
- case 0x78: // SEI
- if ( flags & i04 )
- goto loop;
- flags |= i04;
- handle_sei: {
- CPU.r.flags = flags; // update externally-visible I flag
- int delta = s.base - CPU.end_time_;
- s.base = CPU.end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- dprintf( "Delayed SEI not emulated\n" );
- goto loop;
- }
-
-// Unofficial
-
- // SKW - skip word
- case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
- PAGE_PENALTY( data + x );
- case 0x0C:
- pc++;
- // SKB - skip byte
- case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
- case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
- pc++;
- goto loop;
-
- // NOP
- case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
- goto loop;
-
- case Nes_Cpu::halt_opcode: // HLT - halt processor
- if ( pc-- > 0x10000 )
- {
- // handle wrap-around (assumes caller has put page of HLT at 0x10000)
- pc = WORD( pc );
- goto loop;
- }
- case 0x02: case 0x12: case 0x32: case 0x42: case 0x52:
- case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
- goto stop;
-
-// Unimplemented
-
- case 0xFF: // force 256-entry jump table for optimization purposes
- c |= 1; // compiler doesn't know that this won't affect anything
- default:
- check( (unsigned) opcode < 0x100 );
-
- #ifdef UNIMPL_INSTR
- UNIMPL_INSTR();
- #endif
-
- // At least skip over proper number of bytes instruction uses
- static unsigned char const illop_lens [8] = {
- 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
- };
- int opcode = instr [-1];
- int len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
- if ( opcode == 0x9C )
- len = 2;
- pc += len;
- CPU.error_count_++;
-
- // Account for extra clock
- if ( (opcode >> 4) == 0x0B )
- {
- if ( opcode == 0xB3 )
- data = READ_LOW( data );
- if ( opcode != 0xB7 )
- PAGE_PENALTY( data + y );
- }
- goto loop;
- }
- assert( false ); // catch missing 'goto loop' or accidental 'break'
-
- int result_;
-handle_brk:
- pc++;
- result_ = b10 | 4;
-
-#ifdef CPU_DONE
-interrupt:
-#endif
- {
- s_time += 7;
-
- // Save PC and read vector
- WRITE_STACK( SP( -1 ), pc >> 8 );
- WRITE_STACK( SP( -2 ), pc );
- pc = GET_LE16( &READ_CODE( 0xFFFA ) + (result_ & 4) );
-
- // Save flags
- int temp;
- GET_FLAGS( temp );
- temp |= r20 + (result_ & b10); // B flag set for BRK
- sp = SP( -3 );
- WRITE_STACK( sp, temp );
-
- // Update I flag in externally-visible flags
- CPU.r.flags = (flags |= i04);
-
- // Update time
- int delta = s.base - CPU.end_time_;
- if ( delta >= 0 )
- goto loop;
- s_time += delta;
- s.base = CPU.end_time_;
- goto loop;
- }
-
-out_of_time:
- pc--;
-
- // Optional action that triggers interrupt or changes irq/end time
- #ifdef CPU_DONE
- {
- CPU_DONE( result_ );
- if ( result_ >= 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
- }
- #endif
-stop:
-
- // Flush cached state
- CPU.r.pc = pc;
- CPU.r.sp = GET_SP();
- CPU.r.a = a;
- CPU.r.x = x;
- CPU.r.y = y;
-
- int temp;
- GET_FLAGS( temp );
- CPU.r.flags = temp;
-
- CPU.cpu_state_.base = s.base;
- CPU.cpu_state_.time = s_time;
- CPU.cpu_state = &CPU.cpu_state_;
-}
+// NES 6502 CPU emulator run function
+
+#if 0
+/* Define these macros in the source file before #including this file.
+- Parameters might be expressions, so they are best evaluated only once,
+though they NEVER have side-effects, so multiple evaluation is OK.
+- Output parameters might be a multiple-assignment expression like "a=x",
+so they must NOT be parenthesized.
+- Except where noted, time() and related functions will NOT work
+correctly inside a macro. TIME() is always correct, and FLUSH_TIME() and
+CACHE_TIME() allow the time changing functions to work.
+- Macros "returning" void may use a {} statement block. */
+
+ // 0 <= addr <= 0xFFFF + page_size
+ // time functions can be used
+ int READ_MEM( addr_t );
+ void WRITE_MEM( addr_t, int data );
+ // 0 <= READ_MEM() <= 0xFF
+
+ // 0 <= addr <= 0x1FF
+ int READ_LOW( addr_t );
+ void WRITE_LOW( addr_t, int data );
+ // 0 <= READ_LOW() <= 0xFF
+
+ // Often-used instructions attempt these before using a normal memory access.
+ // Optional; defaults to READ_MEM() and WRITE_MEM()
+ bool CAN_READ_FAST( addr_t ); // if true, uses result of READ_FAST
+ void READ_FAST( addr_t, int& out ); // ALWAYS called BEFORE CAN_READ_FAST
+ bool CAN_WRITE_FAST( addr_t ); // if true, uses WRITE_FAST instead of WRITE_MEM
+ void WRITE_FAST( addr_t, int data );
+
+ // Used by instructions most often used to access the NES PPU (LDA abs and BIT abs).
+ // Optional; defaults to READ_MEM.
+ void READ_PPU( addr_t, int& out );
+ // 0 <= out <= 0xFF
+
+// The following can be used within macros:
+
+ // Current time
+ time_t TIME();
+
+ // Allows use of time functions
+ void FLUSH_TIME();
+
+ // Must be used before end of macro if FLUSH_TIME() was used earlier
+ void CACHE_TIME();
+
+// Configuration (optional; commented behavior if defined)
+
+ // Emulates dummy reads for indexed instructions
+ #define NES_CPU_DUMMY_READS 1
+
+ // Optimizes as if map_code( 0, 0x10000 + cpu_padding, FLAT_MEM ) is always in effect
+ #define FLAT_MEM my_mem_array
+
+ // Expanded just before beginning of code, to help debugger
+ #define CPU_BEGIN void my_run_cpu() {
+
+#endif
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+// Allows MWCW debugger to step through code properly
+#ifdef CPU_BEGIN
+ CPU_BEGIN
+#endif
+
+// Time
+#define TIME() (s_time + s.base)
+#define FLUSH_TIME() {s.time = s_time - time_offset;}
+#define CACHE_TIME() {s_time = s.time + time_offset;}
+
+// Defaults
+#ifndef CAN_WRITE_FAST
+ #define CAN_WRITE_FAST( addr ) 0
+ #define WRITE_FAST( addr, data )
+#endif
+
+#ifndef CAN_READ_FAST
+ #define CAN_READ_FAST( addr ) 0
+ #define READ_FAST( addr, out )
+#endif
+
+#ifndef READ_PPU
+ #define READ_PPU( addr, out )\
+ {\
+ FLUSH_TIME();\
+ out = READ_MEM( addr );\
+ CACHE_TIME();\
+ }
+#endif
+
+#define READ_STACK READ_LOW
+#define WRITE_STACK WRITE_LOW
+
+// Dummy reads
+#if NES_CPU_DUMMY_READS
+ // TODO: optimize time handling
+ #define DUMMY_READ( addr, idx ) \
+ if ( (addr & 0xFF) < idx )\
+ {\
+ int const time_offset = 1;\
+ FLUSH_TIME();\
+ READ_MEM( (addr - 0x100) );\
+ CACHE_TIME();\
+ }
+#else
+ #define DUMMY_READ( addr, idx )
+#endif
+
+// Code
+#ifdef FLAT_MEM
+ #define CODE_PAGE( addr ) (FLAT_MEM)
+ #define CODE_OFFSET( addr ) (addr)
+#else
+ #define CODE_PAGE( addr ) (s.code_map [NES_CPU_PAGE( addr )])
+ #define CODE_OFFSET( addr ) NES_CPU_OFFSET( addr )
+#endif
+#define READ_CODE( addr ) (CODE_PAGE( addr ) [CODE_OFFSET( addr )])
+
+// Stack
+#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
+#define GET_SP() ((sp - 1) & 0xFF)
+#define SP( o ) ((sp + (o - (o>0)*0x100)) | 0x100)
+
+// Truncation
+#define BYTE( n ) ((BOOST::uint8_t ) (n)) /* (unsigned) n & 0xFF */
+#define SBYTE( n ) ((BOOST::int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
+#define WORD( n ) ((BOOST::uint16_t) (n)) /* (unsigned) n & 0xFFFF */
+
+// Flags with hex value for clarity when used as mask.
+// Stored in indicated variable during emulation.
+int const n80 = 0x80; // nz
+int const v40 = 0x40; // flags
+int const r20 = 0x20;
+int const b10 = 0x10;
+int const d08 = 0x08; // flags
+int const i04 = 0x04; // flags
+int const z02 = 0x02; // nz
+int const c01 = 0x01; // c
+
+#define IS_NEG (nz & 0x8080)
+
+#define GET_FLAGS( out ) \
+{\
+ out = flags & (v40 | d08 | i04);\
+ out += ((nz >> 8) | nz) & n80;\
+ out += c >> 8 & c01;\
+ if ( !BYTE( nz ) )\
+ out += z02;\
+}
+
+#define SET_FLAGS( in ) \
+{\
+ flags = in & (v40 | d08 | i04);\
+ c = nz = in << 8;\
+ nz += ~in & z02;\
+}
+
+{
+ int const time_offset = 0;
+
+ // Local state
+ Nes_Cpu::cpu_state_t s;
+ #ifdef FLAT_MEM
+ s.base = CPU.cpu_state_.base;
+ #else
+ s = CPU.cpu_state_;
+ #endif
+ CPU.cpu_state = &s;
+ int s_time = CPU.cpu_state_.time; // helps even on x86
+
+ // Registers
+ int pc = CPU.r.pc;
+ int a = CPU.r.a;
+ int x = CPU.r.x;
+ int y = CPU.r.y;
+ int sp;
+ SET_SP( CPU.r.sp );
+
+ // Flags
+ int flags;
+ int c; // carry set if (c & 0x100) != 0
+ int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
+ {
+ int temp = CPU.r.flags;
+ SET_FLAGS( temp );
+ }
+
+loop:
+
+ // Check all values
+ check( (unsigned) sp - 0x100 < 0x100 );
+ check( (unsigned) pc < 0x10000 );
+ check( (unsigned) a < 0x100 );
+ check( (unsigned) x < 0x100 );
+ check( (unsigned) y < 0x100 );
+
+ // Read instruction
+ byte const* instr = CODE_PAGE( pc );
+ int opcode;
+
+ if ( CODE_OFFSET(~0) == ~0 )
+ {
+ opcode = instr [pc];
+ pc++;
+ instr += pc;
+ }
+ else
+ {
+ instr += CODE_OFFSET( pc );
+ opcode = *instr++;
+ pc++;
+ }
+
+ // local to function in case it helps optimizer
+ static byte const clock_table [256] =
+ {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
+ 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
+ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
+ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
+ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
+ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
+ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
+ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
+ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
+ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
+ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
+ }; // 0x00 was 7 and 0x22 was 2
+
+ // Update time
+ if ( s_time >= 0 )
+ goto out_of_time;
+
+ #ifdef CPU_INSTR_HOOK
+ { CPU_INSTR_HOOK( (pc-1), (&instr [-1]), a, x, y, GET_SP(), TIME() ); }
+ #endif
+
+ s_time += clock_table [opcode];
+
+ int data;
+ data = *instr;
+
+ switch ( opcode )
+ {
+
+// Macros
+
+#define GET_MSB() (instr [1])
+#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB())
+#define GET_ADDR() GET_LE16( instr )
+
+#define PAGE_PENALTY( lsb ) s_time += (lsb) >> 8;
+
+#define INC_DEC( reg, n ) reg = BYTE( nz = reg + n ); goto loop;
+
+#define IND_Y( cross, out ) {\
+ int temp = READ_LOW( data ) + y;\
+ out = temp + 0x100 * READ_LOW( BYTE( data + 1 ) );\
+ cross( temp );\
+ }
+
+#define IND_X( out ) {\
+ int temp = data + x;\
+ out = 0x100 * READ_LOW( BYTE( temp + 1 ) ) + READ_LOW( BYTE( temp ) );\
+ }
+
+#define ARITH_ADDR_MODES( op )\
+case op - 0x04: /* (ind,x) */\
+ IND_X( data )\
+ goto ptr##op;\
+case op + 0x0C: /* (ind),y */\
+ IND_Y( PAGE_PENALTY, data )\
+ goto ptr##op;\
+case op + 0x10: /* zp,X */\
+ data = BYTE( data + x );\
+case op + 0x00: /* zp */\
+ data = READ_LOW( data );\
+ goto imm##op;\
+case op + 0x14: /* abs,Y */\
+ data += y;\
+ goto ind##op;\
+case op + 0x18: /* abs,X */\
+ data += x;\
+ind##op:\
+ PAGE_PENALTY( data );\
+case op + 0x08: /* abs */\
+ ADD_PAGE( data );\
+ptr##op:\
+ FLUSH_TIME();\
+ data = READ_MEM( data );\
+ CACHE_TIME();\
+case op + 0x04: /* imm */\
+imm##op:
+
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define BRANCH( cond )\
+{\
+ ++pc;\
+ if ( !(cond) ) goto loop;\
+ s_time++;\
+ int offset = SBYTE( data );\
+ s_time += (BYTE(pc) + offset) >> 8 & 1;\
+ pc = WORD( pc + offset );\
+ goto loop;\
+}
+
+// Often-Used
+
+ case 0xB5: // LDA zp,x
+ a = nz = READ_LOW( BYTE( data + x ) );
+ pc++;
+ goto loop;
+
+ case 0xA5: // LDA zp
+ a = nz = READ_LOW( data );
+ pc++;
+ goto loop;
+
+ case 0xD0: // BNE
+ BRANCH( BYTE( nz ) );
+
+ case 0x20: { // JSR
+ int temp = pc + 1;
+ pc = GET_ADDR();
+ WRITE_STACK( SP( -1 ), temp >> 8 );
+ sp = SP( -2 );
+ WRITE_STACK( sp, temp );
+ goto loop;
+ }
+
+ case 0x4C: // JMP abs
+ pc = GET_ADDR();
+ goto loop;
+
+ case 0xE8: // INX
+ INC_DEC( x, 1 )
+
+ case 0x10: // BPL
+ BRANCH( !IS_NEG )
+
+ ARITH_ADDR_MODES( 0xC5 ) // CMP
+ nz = a - data;
+ pc++;
+ c = ~nz;
+ nz &= 0xFF;
+ goto loop;
+
+ case 0x30: // BMI
+ BRANCH( IS_NEG )
+
+ case 0xF0: // BEQ
+ BRANCH( !BYTE( nz ) );
+
+ case 0x95: // STA zp,x
+ data = BYTE( data + x );
+ case 0x85: // STA zp
+ pc++;
+ WRITE_LOW( data, a );
+ goto loop;
+
+ case 0xC8: // INY
+ INC_DEC( y, 1 )
+
+ case 0xA8: // TAY
+ y = a;
+ nz = a;
+ goto loop;
+
+ case 0x98: // TYA
+ a = y;
+ nz = y;
+ goto loop;
+
+ case 0xAD:{// LDA abs
+ int addr = GET_ADDR();
+ pc += 2;
+ READ_PPU( addr, a = nz );
+ goto loop;
+ }
+
+ case 0x60: // RTS
+ pc = 1 + READ_STACK( sp );
+ pc += 0x100 * READ_STACK( SP( 1 ) );
+ sp = SP( 2 );
+ goto loop;
+
+ {
+ int addr;
+
+ case 0x8D: // STA abs
+ addr = GET_ADDR();
+ pc += 2;
+ if ( CAN_WRITE_FAST( addr ) )
+ {
+ WRITE_FAST( addr, a );
+ goto loop;
+ }
+ sta_ptr:
+ FLUSH_TIME();
+ WRITE_MEM( addr, a );
+ CACHE_TIME();
+ goto loop;
+
+ case 0x99: // STA abs,Y
+ addr = y + GET_ADDR();
+ pc += 2;
+ if ( CAN_WRITE_FAST( addr ) )
+ {
+ WRITE_FAST( addr, a );
+ goto loop;
+ }
+ goto sta_abs_x;
+
+ case 0x9D: // STA abs,X (slightly more common than STA abs)
+ addr = x + GET_ADDR();
+ pc += 2;
+ if ( CAN_WRITE_FAST( addr ) )
+ {
+ WRITE_FAST( addr, a );
+ goto loop;
+ }
+ DUMMY_READ( addr, x );
+ sta_abs_x:
+ FLUSH_TIME();
+ WRITE_MEM( addr, a );
+ CACHE_TIME();
+ goto loop;
+
+ case 0x91: // STA (ind),Y
+ #define NO_PAGE_PENALTY( lsb )
+ IND_Y( NO_PAGE_PENALTY, addr )
+ pc++;
+ DUMMY_READ( addr, y );
+ goto sta_ptr;
+
+ case 0x81: // STA (ind,X)
+ IND_X( addr )
+ pc++;
+ goto sta_ptr;
+
+ }
+
+ case 0xA9: // LDA #imm
+ pc++;
+ a = data;
+ nz = data;
+ goto loop;
+
+ // common read instructions
+ {
+ int addr;
+
+ case 0xA1: // LDA (ind,X)
+ IND_X( addr )
+ pc++;
+ goto a_nz_read_addr;
+
+ case 0xB1:// LDA (ind),Y
+ addr = READ_LOW( data ) + y;
+ PAGE_PENALTY( addr );
+ addr += 0x100 * READ_LOW( BYTE( data + 1 ) );
+ pc++;
+ READ_FAST( addr, a = nz );
+ if ( CAN_READ_FAST( addr ) )
+ goto loop;
+ DUMMY_READ( addr, y );
+ goto a_nz_read_addr;
+
+ case 0xB9: // LDA abs,Y
+ PAGE_PENALTY( data + y );
+ addr = GET_ADDR() + y;
+ pc += 2;
+ READ_FAST( addr, a = nz );
+ if ( CAN_READ_FAST( addr ) )
+ goto loop;
+ goto a_nz_read_addr;
+
+ case 0xBD: // LDA abs,X
+ PAGE_PENALTY( data + x );
+ addr = GET_ADDR() + x;
+ pc += 2;
+ READ_FAST( addr, a = nz );
+ if ( CAN_READ_FAST( addr ) )
+ goto loop;
+ DUMMY_READ( addr, x );
+ a_nz_read_addr:
+ FLUSH_TIME();
+ a = nz = READ_MEM( addr );
+ CACHE_TIME();
+ goto loop;
+
+ }
+
+// Branch
+
+ case 0x50: // BVC
+ BRANCH( !(flags & v40) )
+
+ case 0x70: // BVS
+ BRANCH( flags & v40 )
+
+ case 0xB0: // BCS
+ BRANCH( c & 0x100 )
+
+ case 0x90: // BCC
+ BRANCH( !(c & 0x100) )
+
+// Load/store
+
+ case 0x94: // STY zp,x
+ data = BYTE( data + x );
+ case 0x84: // STY zp
+ pc++;
+ WRITE_LOW( data, y );
+ goto loop;
+
+ case 0x96: // STX zp,y
+ data = BYTE( data + y );
+ case 0x86: // STX zp
+ pc++;
+ WRITE_LOW( data, x );
+ goto loop;
+
+ case 0xB6: // LDX zp,y
+ data = BYTE( data + y );
+ case 0xA6: // LDX zp
+ data = READ_LOW( data );
+ case 0xA2: // LDX #imm
+ pc++;
+ x = data;
+ nz = data;
+ goto loop;
+
+ case 0xB4: // LDY zp,x
+ data = BYTE( data + x );
+ case 0xA4: // LDY zp
+ data = READ_LOW( data );
+ case 0xA0: // LDY #imm
+ pc++;
+ y = data;
+ nz = data;
+ goto loop;
+
+ case 0xBC: // LDY abs,X
+ data += x;
+ PAGE_PENALTY( data );
+ case 0xAC:{// LDY abs
+ int addr = data + 0x100 * GET_MSB();
+ pc += 2;
+ FLUSH_TIME();
+ y = nz = READ_MEM( addr );
+ CACHE_TIME();
+ goto loop;
+ }
+
+ case 0xBE: // LDX abs,y
+ data += y;
+ PAGE_PENALTY( data );
+ case 0xAE:{// LDX abs
+ int addr = data + 0x100 * GET_MSB();
+ pc += 2;
+ FLUSH_TIME();
+ x = nz = READ_MEM( addr );
+ CACHE_TIME();
+ goto loop;
+ }
+
+ {
+ int temp;
+ case 0x8C: // STY abs
+ temp = y;
+ goto store_abs;
+
+ case 0x8E: // STX abs
+ temp = x;
+ store_abs:
+ int addr = GET_ADDR();
+ pc += 2;
+ if ( CAN_WRITE_FAST( addr ) )
+ {
+ WRITE_FAST( addr, temp );
+ goto loop;
+ }
+ FLUSH_TIME();
+ WRITE_MEM( addr, temp );
+ CACHE_TIME();
+ goto loop;
+ }
+
+// Compare
+
+ case 0xEC:{// CPX abs
+ int addr = GET_ADDR();
+ pc++;
+ FLUSH_TIME();
+ data = READ_MEM( addr );
+ CACHE_TIME();
+ goto cpx_data;
+ }
+
+ case 0xE4: // CPX zp
+ data = READ_LOW( data );
+ case 0xE0: // CPX #imm
+ cpx_data:
+ nz = x - data;
+ pc++;
+ c = ~nz;
+ nz &= 0xFF;
+ goto loop;
+
+ case 0xCC:{// CPY abs
+ int addr = GET_ADDR();
+ pc++;
+ FLUSH_TIME();
+ data = READ_MEM( addr );
+ CACHE_TIME();
+ goto cpy_data;
+ }
+
+ case 0xC4: // CPY zp
+ data = READ_LOW( data );
+ case 0xC0: // CPY #imm
+ cpy_data:
+ nz = y - data;
+ pc++;
+ c = ~nz;
+ nz &= 0xFF;
+ goto loop;
+
+// Logical
+
+ ARITH_ADDR_MODES( 0x25 ) // AND
+ nz = (a &= data);
+ pc++;
+ goto loop;
+
+ ARITH_ADDR_MODES( 0x45 ) // EOR
+ nz = (a ^= data);
+ pc++;
+ goto loop;
+
+ ARITH_ADDR_MODES( 0x05 ) // ORA
+ nz = (a |= data);
+ pc++;
+ goto loop;
+
+ case 0x2C:{// BIT abs
+ int addr = GET_ADDR();
+ pc += 2;
+ READ_PPU( addr, nz );
+ flags = (flags & ~v40) + (nz & v40);
+ if ( a & nz )
+ goto loop;
+ nz <<= 8; // result must be zero, even if N bit is set
+ goto loop;
+ }
+
+ case 0x24: // BIT zp
+ nz = READ_LOW( data );
+ pc++;
+ flags = (flags & ~v40) + (nz & v40);
+ if ( a & nz )
+ goto loop; // Z should be clear, and nz must be non-zero if nz & a is
+ nz <<= 8; // set Z flag without affecting N flag
+ goto loop;
+
+// Add/subtract
+
+ ARITH_ADDR_MODES( 0xE5 ) // SBC
+ case 0xEB: // unofficial equivalent
+ data ^= 0xFF;
+ goto adc_imm;
+
+ ARITH_ADDR_MODES( 0x65 ) // ADC
+ adc_imm: {
+ int carry = c >> 8 & 1;
+ int ov = (a ^ 0x80) + carry + SBYTE( data );
+ flags = (flags & ~v40) + (ov >> 2 & v40);
+ c = nz = a + data + carry;
+ pc++;
+ a = BYTE( nz );
+ goto loop;
+ }
+
+// Shift/rotate
+
+ case 0x4A: // LSR A
+ c = 0;
+ case 0x6A: // ROR A
+ nz = c >> 1 & 0x80;
+ c = a << 8;
+ nz += a >> 1;
+ a = nz;
+ goto loop;
+
+ case 0x0A: // ASL A
+ nz = a << 1;
+ c = nz;
+ a = BYTE( nz );
+ goto loop;
+
+ case 0x2A: { // ROL A
+ nz = a << 1;
+ int temp = c >> 8 & 1;
+ c = nz;
+ nz += temp;
+ a = BYTE( nz );
+ goto loop;
+ }
+
+ case 0x5E: // LSR abs,X
+ data += x;
+ case 0x4E: // LSR abs
+ c = 0;
+ case 0x6E: // ROR abs
+ ror_abs: {
+ ADD_PAGE( data );
+ FLUSH_TIME();
+ int temp = READ_MEM( data );
+ nz = (c >> 1 & 0x80) + (temp >> 1);
+ c = temp << 8;
+ goto rotate_common;
+ }
+
+ case 0x3E: // ROL abs,X
+ data += x;
+ goto rol_abs;
+
+ case 0x1E: // ASL abs,X
+ data += x;
+ case 0x0E: // ASL abs
+ c = 0;
+ case 0x2E: // ROL abs
+ rol_abs:
+ ADD_PAGE( data );
+ nz = c >> 8 & 1;
+ FLUSH_TIME();
+ nz += (c = READ_MEM( data ) << 1);
+ rotate_common:
+ pc++;
+ WRITE_MEM( data, BYTE( nz ) );
+ CACHE_TIME();
+ goto loop;
+
+ case 0x7E: // ROR abs,X
+ data += x;
+ goto ror_abs;
+
+ case 0x76: // ROR zp,x
+ data = BYTE( data + x );
+ goto ror_zp;
+
+ case 0x56: // LSR zp,x
+ data = BYTE( data + x );
+ case 0x46: // LSR zp
+ c = 0;
+ case 0x66: // ROR zp
+ ror_zp: {
+ int temp = READ_LOW( data );
+ nz = (c >> 1 & 0x80) + (temp >> 1);
+ c = temp << 8;
+ goto write_nz_zp;
+ }
+
+ case 0x36: // ROL zp,x
+ data = BYTE( data + x );
+ goto rol_zp;
+
+ case 0x16: // ASL zp,x
+ data = BYTE( data + x );
+ case 0x06: // ASL zp
+ c = 0;
+ case 0x26: // ROL zp
+ rol_zp:
+ nz = c >> 8 & 1;
+ nz += (c = READ_LOW( data ) << 1);
+ goto write_nz_zp;
+
+// Increment/decrement
+
+ case 0xCA: // DEX
+ INC_DEC( x, -1 )
+
+ case 0x88: // DEY
+ INC_DEC( y, -1 )
+
+ case 0xF6: // INC zp,x
+ data = BYTE( data + x );
+ case 0xE6: // INC zp
+ nz = 1;
+ goto add_nz_zp;
+
+ case 0xD6: // DEC zp,x
+ data = BYTE( data + x );
+ case 0xC6: // DEC zp
+ nz = -1;
+ add_nz_zp:
+ nz += READ_LOW( data );
+ write_nz_zp:
+ pc++;
+ WRITE_LOW( data, nz );
+ goto loop;
+
+ case 0xFE: // INC abs,x
+ data = x + GET_ADDR();
+ goto inc_ptr;
+
+ case 0xEE: // INC abs
+ data = GET_ADDR();
+ inc_ptr:
+ nz = 1;
+ goto inc_common;
+
+ case 0xDE: // DEC abs,x
+ data = x + GET_ADDR();
+ goto dec_ptr;
+
+ case 0xCE: // DEC abs
+ data = GET_ADDR();
+ dec_ptr:
+ nz = -1;
+ inc_common:
+ FLUSH_TIME();
+ pc += 2;
+ nz += READ_MEM( data );
+ WRITE_MEM( data, BYTE( nz ) );
+ CACHE_TIME();
+ goto loop;
+
+// Transfer
+
+ case 0xAA: // TAX
+ x = nz = a;
+ goto loop;
+
+ case 0x8A: // TXA
+ a = nz = x;
+ goto loop;
+
+ case 0x9A: // TXS
+ SET_SP( x ); // verified (no flag change)
+ goto loop;
+
+ case 0xBA: // TSX
+ x = nz = GET_SP();
+ goto loop;
+
+// Stack
+
+ case 0x48: // PHA
+ sp = SP( -1 );
+ WRITE_STACK( sp, a );
+ goto loop;
+
+ case 0x68: // PLA
+ a = nz = READ_STACK( sp );
+ sp = SP( 1 );
+ goto loop;
+
+ case 0x40:{// RTI
+ pc = READ_STACK( SP( 1 ) );
+ pc += READ_STACK( SP( 2 ) ) * 0x100;
+ int temp = READ_STACK( sp );
+ sp = SP( 3 );
+ data = flags;
+ SET_FLAGS( temp );
+ CPU.r.flags = flags; // update externally-visible I flag
+ int delta = s.base - CPU.irq_time_;
+ if ( delta <= 0 ) goto loop; // end_time < irq_time
+ if ( flags & i04 ) goto loop;
+ s_time += delta;
+ s.base = CPU.irq_time_;
+ goto loop;
+ }
+
+ case 0x28:{// PLP
+ int temp = READ_STACK( sp );
+ sp = SP( 1 );
+ int changed = flags ^ temp;
+ SET_FLAGS( temp );
+ if ( !(changed & i04) )
+ goto loop; // I flag didn't change
+ if ( flags & i04 )
+ goto handle_sei;
+ goto handle_cli;
+ }
+
+ case 0x08:{// PHP
+ int temp;
+ GET_FLAGS( temp );
+ sp = SP( -1 );
+ WRITE_STACK( sp, temp | (b10 | r20) );
+ goto loop;
+ }
+
+ case 0x6C:{// JMP (ind)
+ data = GET_ADDR();
+ byte const* page = CODE_PAGE( data );
+ pc = page [CODE_OFFSET( data )];
+ data = (data & 0xFF00) + ((data + 1) & 0xFF);
+ pc += page [CODE_OFFSET( data )] * 0x100;
+ goto loop;
+ }
+
+ case 0x00: // BRK
+ goto handle_brk;
+
+// Flags
+
+ case 0x38: // SEC
+ c = 0x100;
+ goto loop;
+
+ case 0x18: // CLC
+ c = 0;
+ goto loop;
+
+ case 0xB8: // CLV
+ flags &= ~v40;
+ goto loop;
+
+ case 0xD8: // CLD
+ flags &= ~d08;
+ goto loop;
+
+ case 0xF8: // SED
+ flags |= d08;
+ goto loop;
+
+ case 0x58: // CLI
+ if ( !(flags & i04) )
+ goto loop;
+ flags &= ~i04;
+ handle_cli: {
+ //dprintf( "CLI at %d\n", TIME );
+ CPU.r.flags = flags; // update externally-visible I flag
+ int delta = s.base - CPU.irq_time_;
+ if ( delta <= 0 )
+ {
+ if ( TIME() < CPU.irq_time_ )
+ goto loop;
+ goto delayed_cli;
+ }
+ s.base = CPU.irq_time_;
+ s_time += delta;
+ if ( s_time < 0 )
+ goto loop;
+
+ if ( delta >= s_time + 1 )
+ {
+ // delayed irq until after next instruction
+ s.base += s_time + 1;
+ s_time = -1;
+ goto loop;
+ }
+
+ // TODO: implement
+ delayed_cli:
+ dprintf( "Delayed CLI not emulated\n" );
+ goto loop;
+ }
+
+ case 0x78: // SEI
+ if ( flags & i04 )
+ goto loop;
+ flags |= i04;
+ handle_sei: {
+ CPU.r.flags = flags; // update externally-visible I flag
+ int delta = s.base - CPU.end_time_;
+ s.base = CPU.end_time_;
+ s_time += delta;
+ if ( s_time < 0 )
+ goto loop;
+
+ dprintf( "Delayed SEI not emulated\n" );
+ goto loop;
+ }
+
+// Unofficial
+
+ // SKW - skip word
+ case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
+ PAGE_PENALTY( data + x );
+ case 0x0C:
+ pc++;
+ // SKB - skip byte
+ case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
+ case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
+ pc++;
+ goto loop;
+
+ // NOP
+ case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
+ goto loop;
+
+ case Nes_Cpu::halt_opcode: // HLT - halt processor
+ if ( pc-- > 0x10000 )
+ {
+ // handle wrap-around (assumes caller has put page of HLT at 0x10000)
+ pc = WORD( pc );
+ goto loop;
+ }
+ case 0x02: case 0x12: case 0x32: case 0x42: case 0x52:
+ case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
+ goto stop;
+
+// Unimplemented
+
+ case 0xFF: // force 256-entry jump table for optimization purposes
+ c |= 1; // compiler doesn't know that this won't affect anything
+ default:
+ check( (unsigned) opcode < 0x100 );
+
+ #ifdef UNIMPL_INSTR
+ UNIMPL_INSTR();
+ #endif
+
+ // At least skip over proper number of bytes instruction uses
+ static unsigned char const illop_lens [8] = {
+ 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
+ };
+ int opcode = instr [-1];
+ int len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
+ if ( opcode == 0x9C )
+ len = 2;
+ pc += len;
+ CPU.error_count_++;
+
+ // Account for extra clock
+ if ( (opcode >> 4) == 0x0B )
+ {
+ if ( opcode == 0xB3 )
+ data = READ_LOW( data );
+ if ( opcode != 0xB7 )
+ PAGE_PENALTY( data + y );
+ }
+ goto loop;
+ }
+ assert( false ); // catch missing 'goto loop' or accidental 'break'
+
+ int result_;
+handle_brk:
+ pc++;
+ result_ = b10 | 4;
+
+#ifdef CPU_DONE
+interrupt:
+#endif
+ {
+ s_time += 7;
+
+ // Save PC and read vector
+ WRITE_STACK( SP( -1 ), pc >> 8 );
+ WRITE_STACK( SP( -2 ), pc );
+ pc = GET_LE16( &READ_CODE( 0xFFFA ) + (result_ & 4) );
+
+ // Save flags
+ int temp;
+ GET_FLAGS( temp );
+ temp |= r20 + (result_ & b10); // B flag set for BRK
+ sp = SP( -3 );
+ WRITE_STACK( sp, temp );
+
+ // Update I flag in externally-visible flags
+ CPU.r.flags = (flags |= i04);
+
+ // Update time
+ int delta = s.base - CPU.end_time_;
+ if ( delta >= 0 )
+ goto loop;
+ s_time += delta;
+ s.base = CPU.end_time_;
+ goto loop;
+ }
+
+out_of_time:
+ pc--;
+
+ // Optional action that triggers interrupt or changes irq/end time
+ #ifdef CPU_DONE
+ {
+ CPU_DONE( result_ );
+ if ( result_ >= 0 )
+ goto interrupt;
+ if ( s_time < 0 )
+ goto loop;
+ }
+ #endif
+stop:
+
+ // Flush cached state
+ CPU.r.pc = pc;
+ CPU.r.sp = GET_SP();
+ CPU.r.a = a;
+ CPU.r.x = x;
+ CPU.r.y = y;
+
+ int temp;
+ GET_FLAGS( temp );
+ CPU.r.flags = temp;
+
+ CPU.cpu_state_.base = s.base;
+ CPU.cpu_state_.time = s_time;
+ CPU.cpu_state = &CPU.cpu_state_;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Namco_Apu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Namco_Apu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Namco_Apu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Namco_Apu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,152 +1,151 @@
-// Nes_Snd_Emu $vers. http://www.slack.net/~ant/
-
-#include "Nes_Namco_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Namco_Apu::Nes_Namco_Apu()
-{
- set_output( NULL );
- volume( 1.0 );
- reset();
-}
-
-void Nes_Namco_Apu::reset()
-{
- last_time = 0;
- addr_reg = 0;
-
- int i;
- for ( i = 0; i < reg_count; i++ )
- reg [i] = 0;
-
- for ( i = 0; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- osc.delay = 0;
- osc.last_amp = 0;
- osc.wave_pos = 0;
- }
-}
-
-void Nes_Namco_Apu::set_output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; ++i )
- set_output( i, buf );
-}
-
-/*
-void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
-{
- reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
-
- static const char hex [17] = "0123456789ABCDEF";
- int i;
- for ( i = 0; i < reg_count; i++ )
- reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], ® [i] );
-
- for ( i = 0; i < osc_count; i++ )
- {
- reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
- reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
- }
-}
-*/
-
-void Nes_Namco_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
-{
- int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
- for ( int i = osc_count - active_oscs; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- Blip_Buffer* output = osc.output;
- if ( !output )
- continue;
-
- blip_resampled_time_t time =
- output->resampled_time( last_time ) + osc.delay;
- blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
- osc.delay = 0;
- if ( time < end_time )
- {
- const BOOST::uint8_t* osc_reg = ® [i * 8 + 0x40];
- if ( !(osc_reg [4] & 0xE0) )
- continue;
-
- int volume = osc_reg [7] & 15;
- if ( !volume )
- continue;
-
- int freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100 + osc_reg [0];
- if ( freq < 64 * active_oscs )
- continue; // prevent low frequencies from excessively delaying freq changes
-
- int const master_clock_divider = 12; // NES time derived via divider of master clock
- int const n106_divider = 45; // N106 then divides master clock by this
- int const max_freq = 0x3FFFF;
- int const lowest_freq_period = (max_freq + 1) * n106_divider / master_clock_divider;
- // divide by 8 to avoid overflow
- blip_resampled_time_t period =
- output->resampled_duration( lowest_freq_period / 8 ) / freq * 8 * active_oscs;
-
- int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
- if ( !wave_size )
- continue;
-
- int last_amp = osc.last_amp;
- int wave_pos = osc.wave_pos;
-
- output->set_modified();
-
- do
- {
- // read wave sample
- int addr = wave_pos + osc_reg [6];
- int sample = reg [addr >> 1] >> (addr << 2 & 4);
- wave_pos++;
- sample = (sample & 15) * volume;
-
- // output impulse if amplitude changed
- int delta = sample - last_amp;
- if ( delta )
- {
- last_amp = sample;
- synth.offset_resampled( time, delta, output );
- }
-
- // next sample
- time += period;
- if ( wave_pos >= wave_size )
- wave_pos = 0;
- }
- while ( time < end_time );
-
- osc.wave_pos = wave_pos;
- osc.last_amp = last_amp;
- }
- osc.delay = time - end_time;
- }
-
- last_time = nes_end_time;
-}
-
+// Nes_Snd_Emu $vers. http://www.slack.net/~ant/
+
+#include "Nes_Namco_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Nes_Namco_Apu::Nes_Namco_Apu()
+{
+ set_output( NULL );
+ volume( 1.0 );
+ reset();
+}
+
+void Nes_Namco_Apu::reset()
+{
+ last_time = 0;
+ addr_reg = 0;
+
+ int i;
+ for ( i = 0; i < reg_count; i++ )
+ reg [i] = 0;
+
+ for ( i = 0; i < osc_count; i++ )
+ {
+ Namco_Osc& osc = oscs [i];
+ osc.delay = 0;
+ osc.last_amp = 0;
+ osc.wave_pos = 0;
+ }
+}
+
+void Nes_Namco_Apu::set_output( Blip_Buffer* buf )
+{
+ for ( int i = 0; i < osc_count; ++i )
+ set_output( i, buf );
+}
+
+/*
+void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
+{
+ reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
+
+ static const char hex [17] = "0123456789ABCDEF";
+ int i;
+ for ( i = 0; i < reg_count; i++ )
+ reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], ® [i] );
+
+ for ( i = 0; i < osc_count; i++ )
+ {
+ reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
+ reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
+ }
+}
+*/
+
+void Nes_Namco_Apu::end_frame( blip_time_t time )
+{
+ if ( time > last_time )
+ run_until( time );
+
+ assert( last_time >= time );
+ last_time -= time;
+}
+
+void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
+{
+ int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
+ for ( int i = osc_count - active_oscs; i < osc_count; i++ )
+ {
+ Namco_Osc& osc = oscs [i];
+ Blip_Buffer* output = osc.output;
+ if ( !output )
+ continue;
+
+ blip_resampled_time_t time =
+ output->resampled_time( last_time ) + osc.delay;
+ blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
+ osc.delay = 0;
+ if ( time < end_time )
+ {
+ const BOOST::uint8_t* osc_reg = ® [i * 8 + 0x40];
+ if ( !(osc_reg [4] & 0xE0) )
+ continue;
+
+ int volume = osc_reg [7] & 15;
+ if ( !volume )
+ continue;
+
+ int freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100 + osc_reg [0];
+ if ( freq < 64 * active_oscs )
+ continue; // prevent low frequencies from excessively delaying freq changes
+
+ int const master_clock_divider = 12; // NES time derived via divider of master clock
+ int const n106_divider = 45; // N106 then divides master clock by this
+ int const max_freq = 0x3FFFF;
+ int const lowest_freq_period = (max_freq + 1) * n106_divider / master_clock_divider;
+ // divide by 8 to avoid overflow
+ blip_resampled_time_t period =
+ output->resampled_duration( lowest_freq_period / 8 ) / freq * 8 * active_oscs;
+
+ int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
+ if ( !wave_size )
+ continue;
+
+ int last_amp = osc.last_amp;
+ int wave_pos = osc.wave_pos;
+
+ output->set_modified();
+
+ do
+ {
+ // read wave sample
+ int addr = wave_pos + osc_reg [6];
+ int sample = reg [addr >> 1] >> (addr << 2 & 4);
+ wave_pos++;
+ sample = (sample & 15) * volume;
+
+ // output impulse if amplitude changed
+ int delta = sample - last_amp;
+ if ( delta )
+ {
+ last_amp = sample;
+ synth.offset_resampled( time, delta, output );
+ }
+
+ // next sample
+ time += period;
+ if ( wave_pos >= wave_size )
+ wave_pos = 0;
+ }
+ while ( time < end_time );
+
+ osc.wave_pos = wave_pos;
+ osc.last_amp = last_amp;
+ }
+ osc.delay = time - end_time;
+ }
+
+ last_time = nes_end_time;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/nestypes.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/nestypes.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/nestypes.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/nestypes.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,39 +1,39 @@
-#ifndef NESTYPES_H__
-#define NESTYPES_H__
-
-#if defined(_MSC_VER)
-#define NEVER_REACH __assume(0);
-#define inline __inline
-#elif defined(__BORLANDC__)
-#define __fastcall __msfastcall
-#elif defined(__GNUC__)
-#define __inline __inline__
-#define __fastcall
-#else
-#define __inline
-#define __fastcall
-#endif
-#ifndef NEVER_REACH
-#define NEVER_REACH
-#endif
-
-typedef int Int;
-typedef unsigned int Uint;
-typedef signed int Int32;
-typedef unsigned int Uint32;
-typedef signed short Int16;
-typedef unsigned short Uint16;
-typedef signed char Int8;
-typedef unsigned char Uint8;
-typedef char Char;
-
-#include
-
-#define XSLEEP(n) ((void)0)
-#define XMALLOC(s) malloc(s)
-#define XREALLOC(p,s) realloc(p,s)
-#define XFREE(p) free(p)
-#define XMEMCPY(d,s,n) memcpy(d,s,n)
-#define XMEMSET(d,c,n) memset(d,c,n)
-
-#endif /* NESTYPES_H__ */
+#ifndef NESTYPES_H__
+#define NESTYPES_H__
+
+#if defined(_MSC_VER)
+#define NEVER_REACH __assume(0);
+#define inline __inline
+#elif defined(__BORLANDC__)
+#define __fastcall __msfastcall
+#elif defined(__GNUC__)
+#define __inline __inline__
+#define __fastcall
+#else
+#define __inline
+#define __fastcall
+#endif
+#ifndef NEVER_REACH
+#define NEVER_REACH
+#endif
+
+typedef int Int;
+typedef unsigned int Uint;
+typedef signed int Int32;
+typedef unsigned int Uint32;
+typedef signed short Int16;
+typedef unsigned short Uint16;
+typedef signed char Int8;
+typedef unsigned char Uint8;
+typedef char Char;
+
+#include
+
+#define XSLEEP(n) ((void)0)
+#define XMALLOC(s) malloc(s)
+#define XREALLOC(p,s) realloc(p,s)
+#define XFREE(p) free(p)
+#define XMEMCPY(d,s,n) memcpy(d,s,n)
+#define XMEMSET(d,c,n) memset(d,c,n)
+
+#endif /* NESTYPES_H__ */
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Vrc7_Apu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Vrc7_Apu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nes_Vrc7_Apu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nes_Vrc7_Apu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,206 +1,206 @@
-#include "Nes_Vrc7_Apu.h"
-
-#include "ym2413.h"
-#include
-
-#include "blargg_source.h"
-
-int const period = 36; // NES CPU clocks per FM clock
-
-Nes_Vrc7_Apu::Nes_Vrc7_Apu()
-{
- opll = 0;
-}
-
-blargg_err_t Nes_Vrc7_Apu::init()
-{
- CHECK_ALLOC( opll = ym2413_init( 3579545, 3579545 / 72, 1 ) );
-
- set_output( 0 );
- volume( 1.0 );
- reset();
- return 0;
-}
-
-Nes_Vrc7_Apu::~Nes_Vrc7_Apu()
-{
- if ( opll )
- ym2413_shutdown( opll );
-}
-
-void Nes_Vrc7_Apu::set_output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; ++i )
- oscs [i].output = buf;
- output_changed();
-}
-
-void Nes_Vrc7_Apu::output_changed()
-{
- mono.output = oscs [0].output;
- for ( int i = osc_count; --i; )
- {
- if ( mono.output != oscs [i].output )
- {
- mono.output = 0;
- break;
- }
- }
-
- if ( mono.output )
- {
- for ( int i = osc_count; --i; )
- {
- mono.last_amp += oscs [i].last_amp;
- oscs [i].last_amp = 0;
- }
- }
-}
-
-void Nes_Vrc7_Apu::reset()
-{
- addr = 0;
- next_time = 0;
- mono.last_amp = 0;
-
- for ( int i = osc_count; --i >= 0; )
- {
- Vrc7_Osc& osc = oscs [i];
- osc.last_amp = 0;
- for ( int j = 0; j < 3; ++j )
- osc.regs [j] = 0;
- }
-
- ym2413_reset_chip( opll );
-}
-
-void Nes_Vrc7_Apu::write_reg( int data )
-{
- addr = data;
-}
-
-void Nes_Vrc7_Apu::write_data( blip_time_t time, int data )
-{
- int type = (addr >> 4) - 1;
- int chan = addr & 15;
- if ( (unsigned) type < 3 && chan < osc_count )
- oscs [chan].regs [type] = data;
-
- if ( time > next_time )
- run_until( time );
- ym2413_write( opll, 0, addr );
- ym2413_write( opll, 1, data );
-}
-
-void Nes_Vrc7_Apu::end_frame( blip_time_t time )
-{
- if ( time > next_time )
- run_until( time );
-
- next_time -= time;
- assert( next_time >= 0 );
-
- for ( int i = osc_count; --i >= 0; )
- {
- Blip_Buffer* output = oscs [i].output;
- if ( output )
- output->set_modified();
- }
-}
-
-void Nes_Vrc7_Apu::save_snapshot( vrc7_snapshot_t* out ) const
-{
- out->latch = addr;
- out->delay = next_time;
- for ( int i = osc_count; --i >= 0; )
- {
- for ( int j = 0; j < 3; ++j )
- out->regs [i] [j] = oscs [i].regs [j];
- }
- memcpy( out->inst, ym2413_get_inst0( opll ), 8 );
-}
-
-void Nes_Vrc7_Apu::load_snapshot( vrc7_snapshot_t const& in )
-{
- assert( offsetof (vrc7_snapshot_t,delay) == 28 - 1 );
-
- reset();
- next_time = in.delay;
- write_reg( in.latch );
- int i;
- for ( i = 0; i < osc_count; ++i )
- {
- for ( int j = 0; j < 3; ++j )
- oscs [i].regs [j] = in.regs [i] [j];
- }
-
- for ( i = 0; i < 8; ++i )
- {
- ym2413_write( opll, 0, i );
- ym2413_write( opll, 1, in.inst [i] );
- }
-
- for ( i = 0; i < 3; ++i )
- {
- for ( int j = 0; j < 6; ++j )
- {
- ym2413_write( opll, 0, 0x10 + i * 0x10 + j );
- ym2413_write( opll, 1, oscs [j].regs [i] );
- }
- }
-}
-
-void Nes_Vrc7_Apu::run_until( blip_time_t end_time )
-{
- require( end_time > next_time );
-
- blip_time_t time = next_time;
- void* opll = this->opll; // cache
- Blip_Buffer* const mono_output = mono.output;
- if ( mono_output )
- {
- // optimal case
- do
- {
- ym2413_advance_lfo( opll );
- int amp = 0;
- for ( int i = 0; i < osc_count; i++ )
- amp += ym2413_calcch( opll, i );
- ym2413_advance( opll );
- int delta = amp - mono.last_amp;
- if ( delta )
- {
- mono.last_amp = amp;
- synth.offset_inline( time, delta, mono_output );
- }
- time += period;
- }
- while ( time < end_time );
- }
- else
- {
- mono.last_amp = 0;
- do
- {
- ym2413_advance_lfo( opll );
- for ( int i = 0; i < osc_count; ++i )
- {
- Vrc7_Osc& osc = oscs [i];
- if ( osc.output )
- {
- int amp = ym2413_calcch( opll, i );
- int delta = amp - osc.last_amp;
- if ( delta )
- {
- osc.last_amp = amp;
- synth.offset( time, delta, osc.output );
- }
- }
- }
- ym2413_advance( opll );
- time += period;
- }
- while ( time < end_time );
- }
- next_time = time;
-}
+#include "Nes_Vrc7_Apu.h"
+
+#include "ym2413.h"
+#include
+
+#include "blargg_source.h"
+
+int const period = 36; // NES CPU clocks per FM clock
+
+Nes_Vrc7_Apu::Nes_Vrc7_Apu()
+{
+ opll = 0;
+}
+
+blargg_err_t Nes_Vrc7_Apu::init()
+{
+ CHECK_ALLOC( opll = ym2413_init( 3579545, 3579545 / 72, 1 ) );
+
+ set_output( 0 );
+ volume( 1.0 );
+ reset();
+ return 0;
+}
+
+Nes_Vrc7_Apu::~Nes_Vrc7_Apu()
+{
+ if ( opll )
+ ym2413_shutdown( opll );
+}
+
+void Nes_Vrc7_Apu::set_output( Blip_Buffer* buf )
+{
+ for ( int i = 0; i < osc_count; ++i )
+ oscs [i].output = buf;
+ output_changed();
+}
+
+void Nes_Vrc7_Apu::output_changed()
+{
+ mono.output = oscs [0].output;
+ for ( int i = osc_count; --i; )
+ {
+ if ( mono.output != oscs [i].output )
+ {
+ mono.output = 0;
+ break;
+ }
+ }
+
+ if ( mono.output )
+ {
+ for ( int i = osc_count; --i; )
+ {
+ mono.last_amp += oscs [i].last_amp;
+ oscs [i].last_amp = 0;
+ }
+ }
+}
+
+void Nes_Vrc7_Apu::reset()
+{
+ addr = 0;
+ next_time = 0;
+ mono.last_amp = 0;
+
+ for ( int i = osc_count; --i >= 0; )
+ {
+ Vrc7_Osc& osc = oscs [i];
+ osc.last_amp = 0;
+ for ( int j = 0; j < 3; ++j )
+ osc.regs [j] = 0;
+ }
+
+ ym2413_reset_chip( opll );
+}
+
+void Nes_Vrc7_Apu::write_reg( int data )
+{
+ addr = data;
+}
+
+void Nes_Vrc7_Apu::write_data( blip_time_t time, int data )
+{
+ int type = (addr >> 4) - 1;
+ int chan = addr & 15;
+ if ( (unsigned) type < 3 && chan < osc_count )
+ oscs [chan].regs [type] = data;
+
+ if ( time > next_time )
+ run_until( time );
+ ym2413_write( opll, 0, addr );
+ ym2413_write( opll, 1, data );
+}
+
+void Nes_Vrc7_Apu::end_frame( blip_time_t time )
+{
+ if ( time > next_time )
+ run_until( time );
+
+ next_time -= time;
+ assert( next_time >= 0 );
+
+ for ( int i = osc_count; --i >= 0; )
+ {
+ Blip_Buffer* output = oscs [i].output;
+ if ( output )
+ output->set_modified();
+ }
+}
+
+void Nes_Vrc7_Apu::save_snapshot( vrc7_snapshot_t* out ) const
+{
+ out->latch = addr;
+ out->delay = next_time;
+ for ( int i = osc_count; --i >= 0; )
+ {
+ for ( int j = 0; j < 3; ++j )
+ out->regs [i] [j] = oscs [i].regs [j];
+ }
+ memcpy( out->inst, ym2413_get_inst0( opll ), 8 );
+}
+
+void Nes_Vrc7_Apu::load_snapshot( vrc7_snapshot_t const& in )
+{
+ assert( offsetof (vrc7_snapshot_t,delay) == 28 - 1 );
+
+ reset();
+ next_time = in.delay;
+ write_reg( in.latch );
+ int i;
+ for ( i = 0; i < osc_count; ++i )
+ {
+ for ( int j = 0; j < 3; ++j )
+ oscs [i].regs [j] = in.regs [i] [j];
+ }
+
+ for ( i = 0; i < 8; ++i )
+ {
+ ym2413_write( opll, 0, i );
+ ym2413_write( opll, 1, in.inst [i] );
+ }
+
+ for ( i = 0; i < 3; ++i )
+ {
+ for ( int j = 0; j < 6; ++j )
+ {
+ ym2413_write( opll, 0, 0x10 + i * 0x10 + j );
+ ym2413_write( opll, 1, oscs [j].regs [i] );
+ }
+ }
+}
+
+void Nes_Vrc7_Apu::run_until( blip_time_t end_time )
+{
+ require( end_time > next_time );
+
+ blip_time_t time = next_time;
+ void* opll = this->opll; // cache
+ Blip_Buffer* const mono_output = mono.output;
+ if ( mono_output )
+ {
+ // optimal case
+ do
+ {
+ ym2413_advance_lfo( opll );
+ int amp = 0;
+ for ( int i = 0; i < osc_count; i++ )
+ amp += ym2413_calcch( opll, i );
+ ym2413_advance( opll );
+ int delta = amp - mono.last_amp;
+ if ( delta )
+ {
+ mono.last_amp = amp;
+ synth.offset_inline( time, delta, mono_output );
+ }
+ time += period;
+ }
+ while ( time < end_time );
+ }
+ else
+ {
+ mono.last_amp = 0;
+ do
+ {
+ ym2413_advance_lfo( opll );
+ for ( int i = 0; i < osc_count; ++i )
+ {
+ Vrc7_Osc& osc = oscs [i];
+ if ( osc.output )
+ {
+ int amp = ym2413_calcch( opll, i );
+ int delta = amp - osc.last_amp;
+ if ( delta )
+ {
+ osc.last_amp = amp;
+ synth.offset( time, delta, osc.output );
+ }
+ }
+ }
+ ym2413_advance( opll );
+ time += period;
+ }
+ while ( time < end_time );
+ }
+ next_time = time;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nsfe_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nsfe_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nsfe_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nsfe_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,329 +1,329 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Nsfe_Emu.h"
-
-#include "blargg_endian.h"
-#include
-
-/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
-
-Nsfe_Info::~Nsfe_Info() { }
-
-inline void Nsfe_Info::unload()
-{
- data.clear();
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-}
-
-// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
-void Nsfe_Info::disable_playlist( bool b )
-{
- playlist_disabled = b;
- info.track_count = playlist.size();
- if ( !info.track_count || playlist_disabled )
- info.track_count = actual_track_count_;
-}
-
-int Nsfe_Info::remap_track( int track ) const
-{
- if ( !playlist_disabled && (unsigned) track < playlist.size() )
- track = playlist [track];
- return track;
-}
-
-// Read multiple strings and separate into individual strings
-static blargg_err_t read_strs( Data_Reader& in, int size, blargg_vector& chars,
- blargg_vector& strs )
-{
- RETURN_ERR( chars.resize( size + 1 ) );
- chars [size] = 0; // in case last string doesn't have terminator
- RETURN_ERR( in.read( &chars [0], size ) );
-
- RETURN_ERR( strs.resize( 128 ) );
- int count = 0;
- for ( int i = 0; i < size; i++ )
- {
- if ( (int) strs.size() <= count )
- RETURN_ERR( strs.resize( count * 2 ) );
- strs [count++] = &chars [i];
- while ( i < size && chars [i] )
- i++;
- }
-
- return strs.resize( count );
-}
-
-// Copy in to out, where out has out_max characters allocated. Truncate to
-// out_max - 1 characters.
-static void copy_str( const char in [], char out [], int out_max )
-{
- out [out_max - 1] = 0;
- strncpy( out, in, out_max - 1 );
-}
-
-struct nsfe_info_t
-{
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte speed_flags;
- byte chip_flags;
- byte track_count;
- byte first_track;
- byte unused [6];
-};
-
-blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsfe_Emu* nsf_emu )
-{
- int const nsfe_info_size = 16;
- assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
-
- // check header
- byte signature [4];
- blargg_err_t err = in.read( signature, sizeof signature );
- if ( err )
- return (blargg_is_err_type( err, blargg_err_file_eof ) ? blargg_err_file_type : err);
- if ( memcmp( signature, "NSFE", 4 ) )
- return blargg_err_file_type;
-
- // free previous info
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-
- // default nsf header
- static const Nsf_Emu::header_t base_header =
- {
- {'N','E','S','M','\x1A'},// tag
- 1, // version
- 1, 1, // track count, first track
- {0,0},{0,0},{0,0}, // addresses
- "","","", // strings
- {0x1A, 0x41}, // NTSC rate
- {0,0,0,0,0,0,0,0}, // banks
- {0x20, 0x4E}, // PAL rate
- 0, 0, // flags
- {0,0,0,0} // unused
- };
- Nsf_Emu::header_t& header = info;
- header = base_header;
-
- // parse tags
- int phase = 0;
- while ( phase != 3 )
- {
- // read size and tag
- byte block_header [2] [4];
- RETURN_ERR( in.read( block_header, sizeof block_header ) );
- int size = get_le32( block_header [0] );
- int tag = get_le32( block_header [1] );
-
- //dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
-
- switch ( tag )
- {
- case BLARGG_4CHAR('O','F','N','I'): {
- check( phase == 0 );
- if ( size < 8 )
- return blargg_err_file_corrupt;
-
- nsfe_info_t finfo;
- finfo.track_count = 1;
- finfo.first_track = 0;
-
- RETURN_ERR( in.read( &finfo, min( size, (int) nsfe_info_size ) ) );
- if ( size > nsfe_info_size )
- RETURN_ERR( in.skip( size - nsfe_info_size ) );
- phase = 1;
- info.speed_flags = finfo.speed_flags;
- info.chip_flags = finfo.chip_flags;
- info.track_count = finfo.track_count;
- this->actual_track_count_ = finfo.track_count;
- info.first_track = finfo.first_track;
- memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
- break;
- }
-
- case BLARGG_4CHAR('K','N','A','B'):
- if ( size > (int) sizeof info.banks )
- return blargg_err_file_corrupt;
- RETURN_ERR( in.read( info.banks, size ) );
- break;
-
- case BLARGG_4CHAR('h','t','u','a'): {
- blargg_vector chars;
- blargg_vector strs;
- RETURN_ERR( read_strs( in, size, chars, strs ) );
- int n = strs.size();
-
- if ( n > 3 )
- copy_str( strs [3], info.dumper, sizeof info.dumper );
-
- if ( n > 2 )
- copy_str( strs [2], info.copyright, sizeof info.copyright );
-
- if ( n > 1 )
- copy_str( strs [1], info.author, sizeof info.author );
-
- if ( n > 0 )
- copy_str( strs [0], info.game, sizeof info.game );
-
- break;
- }
-
- case BLARGG_4CHAR('e','m','i','t'):
- RETURN_ERR( track_times.resize( size / 4 ) );
- RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
- break;
-
- case BLARGG_4CHAR('l','b','l','t'):
- RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
- break;
-
- case BLARGG_4CHAR('t','s','l','p'):
- RETURN_ERR( playlist.resize( size ) );
- RETURN_ERR( in.read( &playlist [0], size ) );
- break;
-
- case BLARGG_4CHAR('A','T','A','D'): {
- check( phase == 1 );
- phase = 2;
- if ( !nsf_emu )
- {
- RETURN_ERR( data.resize( size ) );
- RETURN_ERR( in.read( data.begin(), size ) );
- }
- else
- {
- Subset_Reader sub( &in, size ); // limit emu to nsf data
- Remaining_Reader rem( &header, header.size, &sub );
- RETURN_ERR( nsf_emu->Nsf_Emu::load_( rem ) );
- check( rem.remain() == 0 );
- }
- break;
- }
-
- case BLARGG_4CHAR('D','N','E','N'):
- check( phase == 2 );
- phase = 3;
- break;
-
- default:
- // tags that can be skipped start with a lowercase character
- check( islower( (tag >> 24) & 0xFF ) );
- RETURN_ERR( in.skip( size ) );
- break;
- }
- }
-
- return blargg_ok;
-}
-
-blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
-{
- int remapped = remap_track( track );
- if ( (unsigned) remapped < track_times.size() )
- {
- int length = (BOOST::int32_t) get_le32( track_times [remapped] );
- if ( length > 0 )
- out->length = length;
- }
- if ( (unsigned) remapped < track_names.size() )
- Gme_File::copy_field_( out->song, track_names [remapped] );
-
- GME_COPY_FIELD( info, out, game );
- GME_COPY_FIELD( info, out, author );
- GME_COPY_FIELD( info, out, copyright );
- GME_COPY_FIELD( info, out, dumper );
- return blargg_ok;
-}
-
-Nsfe_Emu::Nsfe_Emu()
-{
- set_type( gme_nsfe_type );
-}
-
-Nsfe_Emu::~Nsfe_Emu() { }
-
-void Nsfe_Emu::unload()
-{
- info.unload();
- Nsf_Emu::unload();
-}
-
-blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
-{
- return info.track_info_( out, track );
-}
-
-struct Nsfe_File : Gme_Info_
-{
- Nsfe_Info info;
-
- Nsfe_File() { set_type( gme_nsfe_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- RETURN_ERR( info.load( in, 0 ) );
- info.disable_playlist( false );
- set_track_count( info.info.track_count );
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- return info.track_info_( out, track );
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_nsf_file( info.info, info.data.begin(), info.data.end() - info.data.begin(), out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
-static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
-
-gme_type_t_ const gme_nsfe_type [1] = {{ "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 }};
-
-blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
-{
- RETURN_ERR( info.load( in, this ) );
- disable_playlist_( false );
- return blargg_ok;
-}
-
-void Nsfe_Emu::disable_playlist_( bool b )
-{
- info.disable_playlist( b );
- set_track_count( info.info.track_count );
-}
-
-void Nsfe_Emu::clear_playlist_()
-{
- disable_playlist_( true );
- Nsf_Emu::clear_playlist_();
-}
-
-blargg_err_t Nsfe_Emu::start_track_( int track )
-{
- return Nsf_Emu::start_track_( info.remap_track( track ) );
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Nsfe_Emu.h"
+
+#include "blargg_endian.h"
+#include
+
+/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
+
+Nsfe_Info::~Nsfe_Info() { }
+
+inline void Nsfe_Info::unload()
+{
+ data.clear();
+ track_name_data.clear();
+ track_names.clear();
+ playlist.clear();
+ track_times.clear();
+}
+
+// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
+void Nsfe_Info::disable_playlist( bool b )
+{
+ playlist_disabled = b;
+ info.track_count = playlist.size();
+ if ( !info.track_count || playlist_disabled )
+ info.track_count = actual_track_count_;
+}
+
+int Nsfe_Info::remap_track( int track ) const
+{
+ if ( !playlist_disabled && (unsigned) track < playlist.size() )
+ track = playlist [track];
+ return track;
+}
+
+// Read multiple strings and separate into individual strings
+static blargg_err_t read_strs( Data_Reader& in, int size, blargg_vector& chars,
+ blargg_vector& strs )
+{
+ RETURN_ERR( chars.resize( size + 1 ) );
+ chars [size] = 0; // in case last string doesn't have terminator
+ RETURN_ERR( in.read( &chars [0], size ) );
+
+ RETURN_ERR( strs.resize( 128 ) );
+ int count = 0;
+ for ( int i = 0; i < size; i++ )
+ {
+ if ( (int) strs.size() <= count )
+ RETURN_ERR( strs.resize( count * 2 ) );
+ strs [count++] = &chars [i];
+ while ( i < size && chars [i] )
+ i++;
+ }
+
+ return strs.resize( count );
+}
+
+// Copy in to out, where out has out_max characters allocated. Truncate to
+// out_max - 1 characters.
+static void copy_str( const char in [], char out [], int out_max )
+{
+ out [out_max - 1] = 0;
+ strncpy( out, in, out_max - 1 );
+}
+
+struct nsfe_info_t
+{
+ byte load_addr [2];
+ byte init_addr [2];
+ byte play_addr [2];
+ byte speed_flags;
+ byte chip_flags;
+ byte track_count;
+ byte first_track;
+ byte unused [6];
+};
+
+blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsfe_Emu* nsf_emu )
+{
+ int const nsfe_info_size = 16;
+ assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
+
+ // check header
+ byte signature [4];
+ blargg_err_t err = in.read( signature, sizeof signature );
+ if ( err )
+ return (blargg_is_err_type( err, blargg_err_file_eof ) ? blargg_err_file_type : err);
+ if ( memcmp( signature, "NSFE", 4 ) )
+ return blargg_err_file_type;
+
+ // free previous info
+ track_name_data.clear();
+ track_names.clear();
+ playlist.clear();
+ track_times.clear();
+
+ // default nsf header
+ static const Nsf_Emu::header_t base_header =
+ {
+ {'N','E','S','M','\x1A'},// tag
+ 1, // version
+ 1, 1, // track count, first track
+ {0,0},{0,0},{0,0}, // addresses
+ "","","", // strings
+ {0x1A, 0x41}, // NTSC rate
+ {0,0,0,0,0,0,0,0}, // banks
+ {0x20, 0x4E}, // PAL rate
+ 0, 0, // flags
+ {0,0,0,0} // unused
+ };
+ Nsf_Emu::header_t& header = info;
+ header = base_header;
+
+ // parse tags
+ int phase = 0;
+ while ( phase != 3 )
+ {
+ // read size and tag
+ byte block_header [2] [4];
+ RETURN_ERR( in.read( block_header, sizeof block_header ) );
+ int size = get_le32( block_header [0] );
+ int tag = get_le32( block_header [1] );
+
+ //dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
+
+ switch ( tag )
+ {
+ case BLARGG_4CHAR('O','F','N','I'): {
+ check( phase == 0 );
+ if ( size < 8 )
+ return blargg_err_file_corrupt;
+
+ nsfe_info_t finfo;
+ finfo.track_count = 1;
+ finfo.first_track = 0;
+
+ RETURN_ERR( in.read( &finfo, min( size, (int) nsfe_info_size ) ) );
+ if ( size > nsfe_info_size )
+ RETURN_ERR( in.skip( size - nsfe_info_size ) );
+ phase = 1;
+ info.speed_flags = finfo.speed_flags;
+ info.chip_flags = finfo.chip_flags;
+ info.track_count = finfo.track_count;
+ this->actual_track_count_ = finfo.track_count;
+ info.first_track = finfo.first_track;
+ memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
+ break;
+ }
+
+ case BLARGG_4CHAR('K','N','A','B'):
+ if ( size > (int) sizeof info.banks )
+ return blargg_err_file_corrupt;
+ RETURN_ERR( in.read( info.banks, size ) );
+ break;
+
+ case BLARGG_4CHAR('h','t','u','a'): {
+ blargg_vector chars;
+ blargg_vector strs;
+ RETURN_ERR( read_strs( in, size, chars, strs ) );
+ int n = strs.size();
+
+ if ( n > 3 )
+ copy_str( strs [3], info.dumper, sizeof info.dumper );
+
+ if ( n > 2 )
+ copy_str( strs [2], info.copyright, sizeof info.copyright );
+
+ if ( n > 1 )
+ copy_str( strs [1], info.author, sizeof info.author );
+
+ if ( n > 0 )
+ copy_str( strs [0], info.game, sizeof info.game );
+
+ break;
+ }
+
+ case BLARGG_4CHAR('e','m','i','t'):
+ RETURN_ERR( track_times.resize( size / 4 ) );
+ RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
+ break;
+
+ case BLARGG_4CHAR('l','b','l','t'):
+ RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
+ break;
+
+ case BLARGG_4CHAR('t','s','l','p'):
+ RETURN_ERR( playlist.resize( size ) );
+ RETURN_ERR( in.read( &playlist [0], size ) );
+ break;
+
+ case BLARGG_4CHAR('A','T','A','D'): {
+ check( phase == 1 );
+ phase = 2;
+ if ( !nsf_emu )
+ {
+ RETURN_ERR( data.resize( size ) );
+ RETURN_ERR( in.read( data.begin(), size ) );
+ }
+ else
+ {
+ Subset_Reader sub( &in, size ); // limit emu to nsf data
+ Remaining_Reader rem( &header, header.size, &sub );
+ RETURN_ERR( nsf_emu->Nsf_Emu::load_( rem ) );
+ check( rem.remain() == 0 );
+ }
+ break;
+ }
+
+ case BLARGG_4CHAR('D','N','E','N'):
+ check( phase == 2 );
+ phase = 3;
+ break;
+
+ default:
+ // tags that can be skipped start with a lowercase character
+ check( islower( (tag >> 24) & 0xFF ) );
+ RETURN_ERR( in.skip( size ) );
+ break;
+ }
+ }
+
+ return blargg_ok;
+}
+
+blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
+{
+ int remapped = remap_track( track );
+ if ( (unsigned) remapped < track_times.size() )
+ {
+ int length = (BOOST::int32_t) get_le32( track_times [remapped] );
+ if ( length > 0 )
+ out->length = length;
+ }
+ if ( (unsigned) remapped < track_names.size() )
+ Gme_File::copy_field_( out->song, track_names [remapped] );
+
+ GME_COPY_FIELD( info, out, game );
+ GME_COPY_FIELD( info, out, author );
+ GME_COPY_FIELD( info, out, copyright );
+ GME_COPY_FIELD( info, out, dumper );
+ return blargg_ok;
+}
+
+Nsfe_Emu::Nsfe_Emu()
+{
+ set_type( gme_nsfe_type );
+}
+
+Nsfe_Emu::~Nsfe_Emu() { }
+
+void Nsfe_Emu::unload()
+{
+ info.unload();
+ Nsf_Emu::unload();
+}
+
+blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
+{
+ return info.track_info_( out, track );
+}
+
+struct Nsfe_File : Gme_Info_
+{
+ Nsfe_Info info;
+
+ Nsfe_File() { set_type( gme_nsfe_type ); }
+
+ blargg_err_t load_( Data_Reader& in )
+ {
+ RETURN_ERR( info.load( in, 0 ) );
+ info.disable_playlist( false );
+ set_track_count( info.info.track_count );
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int track ) const
+ {
+ return info.track_info_( out, track );
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_nsf_file( info.info, info.data.begin(), info.data.end() - info.data.begin(), out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
+static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
+
+gme_type_t_ const gme_nsfe_type [1] = {{ "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 }};
+
+blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
+{
+ RETURN_ERR( info.load( in, this ) );
+ disable_playlist_( false );
+ return blargg_ok;
+}
+
+void Nsfe_Emu::disable_playlist_( bool b )
+{
+ info.disable_playlist( b );
+ set_track_count( info.info.track_count );
+}
+
+void Nsfe_Emu::clear_playlist_()
+{
+ disable_playlist_( true );
+ Nsf_Emu::clear_playlist_();
+}
+
+blargg_err_t Nsfe_Emu::start_track_( int track )
+{
+ return Nsf_Emu::start_track_( info.remap_track( track ) );
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nsf_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nsf_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Nsf_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Nsf_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,26 +1,26 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Nsf_Emu.h"
-
-#if !NSF_EMU_APU_ONLY
- #include "Nes_Namco_Apu.h"
- #include "Nes_Vrc6_Apu.h"
- #include "Nes_Fme7_Apu.h"
- #include "Nes_Fds_Apu.h"
- #include "Nes_Mmc5_Apu.h"
- #include "Nes_Vrc7_Apu.h"
-#endif
-
-/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Nsf_Emu.h"
+
+#if !NSF_EMU_APU_ONLY
+ #include "Nes_Namco_Apu.h"
+ #include "Nes_Vrc6_Apu.h"
+ #include "Nes_Fme7_Apu.h"
+ #include "Nes_Fds_Apu.h"
+ #include "Nes_Mmc5_Apu.h"
+ #include "Nes_Vrc7_Apu.h"
+#endif
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
@@ -29,314 +29,314 @@
Nsf_Emu::Nsf_Emu()
{
- set_type( gme_nsf_type );
- set_silence_lookahead( 6 );
- set_gain( 1.4 );
- set_equalizer( nes_eq );
-}
-
-Nsf_Emu::~Nsf_Emu()
-{
- unload();
-}
-
-void Nsf_Emu::unload()
-{
- core_.unload();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
- if ( h.chip_flags )
- Music_Emu::copy_field_( out->system, "Famicom" );
-}
-
-void hash_nsf_file( Nsf_Core::header_t const& h, unsigned char const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.vers, sizeof(h.vers) );
- out.hash_( &h.track_count, sizeof(h.track_count) );
- out.hash_( &h.first_track, sizeof(h.first_track) );
- out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
- out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
- out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
- out.hash_( &h.ntsc_speed[0], sizeof(h.ntsc_speed) );
- out.hash_( &h.banks[0], sizeof(h.banks) );
- out.hash_( &h.pal_speed[0], sizeof(h.pal_speed) );
- out.hash_( &h.speed_flags, sizeof(h.speed_flags) );
- out.hash_( &h.chip_flags, sizeof(h.chip_flags) );
- out.hash_( &h.unused[0], sizeof(h.unused) );
-
- out.hash_( data, data_size );
-}
-
-blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_nsf_fields( header(), out );
- return blargg_ok;
-}
-
-static blargg_err_t check_nsf_header( Nsf_Emu::header_t const& h )
-{
- if ( !h.valid_tag() )
- return blargg_err_file_type;
- return blargg_ok;
-}
-
-struct Nsf_File : Gme_Info_
-{
- Nsf_Emu::header_t const* h;
-
- Nsf_File() { set_type( gme_nsf_type ); }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- h = ( Nsf_Emu::header_t const* ) begin;
-
- if ( h->vers != 1 )
- set_warning( "Unknown file version" );
-
- int unsupported_chips = ~Nsf_Core::chips_mask;
- #if NSF_EMU_NO_VRC7
- unsupported_chips |= Nsf_Emu::header_t::vrc7_mask;
- #endif
- if ( h->chip_flags & unsupported_chips )
- set_warning( "Uses unsupported audio expansion hardware" );
-
- set_track_count( h->track_count );
- return check_nsf_header( *h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_nsf_fields( *h, out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_nsf_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
-static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
-
-gme_type_t_ const gme_nsf_type [1] = {{ "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 }};
-
-// Setup
-
-void Nsf_Emu::set_tempo_( double t )
-{
- core_.set_tempo( t );
-}
-
-void Nsf_Emu::append_voices( const char* const names [], int const types [], int count )
-{
- assert( voice_count_ + count < max_voices );
- for ( int i = 0; i < count; i++ )
- {
- voice_names_ [voice_count_ + i] = names [i];
- voice_types_ [voice_count_ + i] = types [i];
- }
- voice_count_ += count;
- set_voice_count( voice_count_ );
- set_voice_types( voice_types_ );
-}
-
-blargg_err_t Nsf_Emu::init_sound()
-{
- voice_count_ = 0;
- set_voice_names( voice_names_ );
-
- {
- int const count = Nes_Apu::osc_count;
- static const char* const names [Nes_Apu::osc_count] = {
- "Square 1", "Square 2", "Triangle", "Noise", "DMC"
- };
- static int const types [count] = {
- wave_type+1, wave_type+2, mixed_type+1, noise_type+0, mixed_type+1
- };
- append_voices( names, types, count );
- }
-
- // Make adjusted_gain * 0.75 = 1.0 so usual APU and one sound chip uses 1.0
- double adjusted_gain = 1.0 / 0.75 * gain();
-
-#if !NSF_EMU_APU_ONLY
- // TODO: order of chips here must match that in set_voice()
-
- if ( core_.vrc6_apu() )
- {
- int const count = Nes_Vrc6_Apu::osc_count;
- static const char* const names [count] = {
- "Square 3", "Square 4", "Saw Wave"
- };
- static int const types [count] = {
- wave_type+3, wave_type+4, wave_type+5,
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.fme7_apu() )
- {
- int const count = Nes_Fme7_Apu::osc_count;
- static const char* const names [count] = {
- "Square 3", "Square 4", "Square 5"
- };
- static int const types [count] = {
- wave_type+3, wave_type+4, wave_type+5,
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.mmc5_apu() )
- {
- int const count = Nes_Mmc5_Apu::osc_count;
- static const char* const names [count] = {
- "Square 3", "Square 4", "PCM"
- };
- static int const types [count] = {
- wave_type+3, wave_type+4, mixed_type+2
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.fds_apu() )
- {
- int const count = Nes_Fds_Apu::osc_count;
- static const char* const names [count] = {
- "FM"
- };
- static int const types [count] = {
- wave_type+0
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.namco_apu() )
- {
- int const count = Nes_Namco_Apu::osc_count;
- static const char* const names [count] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8"
- };
- static int const types [count] = {
- wave_type+3, wave_type+4, wave_type+5, wave_type+ 6,
- wave_type+7, wave_type+8, wave_type+9, wave_type+10,
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.vrc7_apu() )
- {
- int const count = Nes_Vrc7_Apu::osc_count;
- static const char* const names [count] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"
- };
- static int const types [count] = {
- wave_type+3, wave_type+4, wave_type+5, wave_type+6,
- wave_type+7, wave_type+8
- };
- append_voices( names, types, count );
- adjusted_gain *= 0.75;
- }
-
- if ( core_.vrc7_apu() ) core_.vrc7_apu() ->volume( adjusted_gain );
- if ( core_.namco_apu() ) core_.namco_apu()->volume( adjusted_gain );
- if ( core_.vrc6_apu() ) core_.vrc6_apu() ->volume( adjusted_gain );
- if ( core_.fme7_apu() ) core_.fme7_apu() ->volume( adjusted_gain );
- if ( core_.mmc5_apu() ) core_.mmc5_apu() ->volume( adjusted_gain );
- if ( core_.fds_apu() ) core_.fds_apu() ->volume( adjusted_gain );
-#endif
-
- if ( adjusted_gain > gain() )
- adjusted_gain = gain(); // only occurs if no other sound chips
-
- core_.nes_apu()->volume( adjusted_gain );
-
- return blargg_ok;
-}
-
-blargg_err_t Nsf_Emu::load_( Data_Reader& in )
-{
- RETURN_ERR( core_.load( in ) );
- set_track_count( header().track_count );
- RETURN_ERR( check_nsf_header( header() ) );
- set_warning( core_.warning() );
- RETURN_ERR( init_sound() );
- set_tempo( tempo() );
- return setup_buffer( (int) (header().clock_rate() + 0.5) );
-}
-
-void Nsf_Emu::update_eq( blip_eq_t const& eq )
-{
- core_.nes_apu()->treble_eq( eq );
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( core_.namco_apu() ) core_.namco_apu()->treble_eq( eq );
- if ( core_.vrc6_apu() ) core_.vrc6_apu() ->treble_eq( eq );
- if ( core_.fme7_apu() ) core_.fme7_apu() ->treble_eq( eq );
- if ( core_.mmc5_apu() ) core_.mmc5_apu() ->treble_eq( eq );
- if ( core_.fds_apu() ) core_.fds_apu() ->treble_eq( eq );
- if ( core_.vrc7_apu() ) core_.vrc7_apu() ->treble_eq( eq );
- }
- #endif
-}
-
-void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
-{
- #define HANDLE_CHIP( chip ) \
- if ( chip && (i -= chip->osc_count) < 0 )\
- {\
- chip->set_output( i + chip->osc_count, buf );\
- return;\
- }\
-
- HANDLE_CHIP( core_.nes_apu() );
-
- #if !NSF_EMU_APU_ONLY
- {
- // TODO: order of chips here must match that in init_sound()
- HANDLE_CHIP( core_.vrc6_apu() );
- HANDLE_CHIP( core_.fme7_apu() );
- HANDLE_CHIP( core_.mmc5_apu() );
- HANDLE_CHIP( core_.fds_apu() );
- HANDLE_CHIP( core_.namco_apu() );
- HANDLE_CHIP( core_.vrc7_apu() );
- }
- #endif
-}
-
-blargg_err_t Nsf_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
- return core_.start_track( track );
-}
-
-blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
-{
- core_.end_frame( duration );
- const char* w = core_.warning();
- if ( w )
- set_warning( w );
- return blargg_ok;
-}
-
-blargg_err_t Nsf_Emu::hash_( Hash_Function& out ) const
-{
- hash_nsf_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
- return blargg_ok;
+ set_type( gme_nsf_type );
+ set_silence_lookahead( 6 );
+ set_gain( 1.4 );
+ set_equalizer( nes_eq );
+}
+
+Nsf_Emu::~Nsf_Emu()
+{
+ unload();
+}
+
+void Nsf_Emu::unload()
+{
+ core_.unload();
+ Music_Emu::unload();
+}
+
+// Track info
+
+static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
+{
+ GME_COPY_FIELD( h, out, game );
+ GME_COPY_FIELD( h, out, author );
+ GME_COPY_FIELD( h, out, copyright );
+ if ( h.chip_flags )
+ Music_Emu::copy_field_( out->system, "Famicom" );
+}
+
+void hash_nsf_file( Nsf_Core::header_t const& h, unsigned char const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.vers, sizeof(h.vers) );
+ out.hash_( &h.track_count, sizeof(h.track_count) );
+ out.hash_( &h.first_track, sizeof(h.first_track) );
+ out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
+ out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
+ out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
+ out.hash_( &h.ntsc_speed[0], sizeof(h.ntsc_speed) );
+ out.hash_( &h.banks[0], sizeof(h.banks) );
+ out.hash_( &h.pal_speed[0], sizeof(h.pal_speed) );
+ out.hash_( &h.speed_flags, sizeof(h.speed_flags) );
+ out.hash_( &h.chip_flags, sizeof(h.chip_flags) );
+ out.hash_( &h.unused[0], sizeof(h.unused) );
+
+ out.hash_( data, data_size );
+}
+
+blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
+{
+ copy_nsf_fields( header(), out );
+ return blargg_ok;
+}
+
+static blargg_err_t check_nsf_header( Nsf_Emu::header_t const& h )
+{
+ if ( !h.valid_tag() )
+ return blargg_err_file_type;
+ return blargg_ok;
+}
+
+struct Nsf_File : Gme_Info_
+{
+ Nsf_Emu::header_t const* h;
+
+ Nsf_File() { set_type( gme_nsf_type ); }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ h = ( Nsf_Emu::header_t const* ) begin;
+
+ if ( h->vers != 1 )
+ set_warning( "Unknown file version" );
+
+ int unsupported_chips = ~Nsf_Core::chips_mask;
+ #if NSF_EMU_NO_VRC7
+ unsupported_chips |= Nsf_Emu::header_t::vrc7_mask;
+ #endif
+ if ( h->chip_flags & unsupported_chips )
+ set_warning( "Uses unsupported audio expansion hardware" );
+
+ set_track_count( h->track_count );
+ return check_nsf_header( *h );
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_nsf_fields( *h, out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_nsf_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
+static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
+
+gme_type_t_ const gme_nsf_type [1] = {{ "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 }};
+
+// Setup
+
+void Nsf_Emu::set_tempo_( double t )
+{
+ core_.set_tempo( t );
+}
+
+void Nsf_Emu::append_voices( const char* const names [], int const types [], int count )
+{
+ assert( voice_count_ + count < max_voices );
+ for ( int i = 0; i < count; i++ )
+ {
+ voice_names_ [voice_count_ + i] = names [i];
+ voice_types_ [voice_count_ + i] = types [i];
+ }
+ voice_count_ += count;
+ set_voice_count( voice_count_ );
+ set_voice_types( voice_types_ );
+}
+
+blargg_err_t Nsf_Emu::init_sound()
+{
+ voice_count_ = 0;
+ set_voice_names( voice_names_ );
+
+ {
+ int const count = Nes_Apu::osc_count;
+ static const char* const names [Nes_Apu::osc_count] = {
+ "Square 1", "Square 2", "Triangle", "Noise", "DMC"
+ };
+ static int const types [count] = {
+ wave_type+1, wave_type+2, mixed_type+1, noise_type+0, mixed_type+1
+ };
+ append_voices( names, types, count );
+ }
+
+ // Make adjusted_gain * 0.75 = 1.0 so usual APU and one sound chip uses 1.0
+ double adjusted_gain = 1.0 / 0.75 * gain();
+
+#if !NSF_EMU_APU_ONLY
+ // TODO: order of chips here must match that in set_voice()
+
+ if ( core_.vrc6_apu() )
+ {
+ int const count = Nes_Vrc6_Apu::osc_count;
+ static const char* const names [count] = {
+ "Square 3", "Square 4", "Saw Wave"
+ };
+ static int const types [count] = {
+ wave_type+3, wave_type+4, wave_type+5,
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.fme7_apu() )
+ {
+ int const count = Nes_Fme7_Apu::osc_count;
+ static const char* const names [count] = {
+ "Square 3", "Square 4", "Square 5"
+ };
+ static int const types [count] = {
+ wave_type+3, wave_type+4, wave_type+5,
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.mmc5_apu() )
+ {
+ int const count = Nes_Mmc5_Apu::osc_count;
+ static const char* const names [count] = {
+ "Square 3", "Square 4", "PCM"
+ };
+ static int const types [count] = {
+ wave_type+3, wave_type+4, mixed_type+2
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.fds_apu() )
+ {
+ int const count = Nes_Fds_Apu::osc_count;
+ static const char* const names [count] = {
+ "FM"
+ };
+ static int const types [count] = {
+ wave_type+0
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.namco_apu() )
+ {
+ int const count = Nes_Namco_Apu::osc_count;
+ static const char* const names [count] = {
+ "Wave 1", "Wave 2", "Wave 3", "Wave 4",
+ "Wave 5", "Wave 6", "Wave 7", "Wave 8"
+ };
+ static int const types [count] = {
+ wave_type+3, wave_type+4, wave_type+5, wave_type+ 6,
+ wave_type+7, wave_type+8, wave_type+9, wave_type+10,
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.vrc7_apu() )
+ {
+ int const count = Nes_Vrc7_Apu::osc_count;
+ static const char* const names [count] = {
+ "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"
+ };
+ static int const types [count] = {
+ wave_type+3, wave_type+4, wave_type+5, wave_type+6,
+ wave_type+7, wave_type+8
+ };
+ append_voices( names, types, count );
+ adjusted_gain *= 0.75;
+ }
+
+ if ( core_.vrc7_apu() ) core_.vrc7_apu() ->volume( adjusted_gain );
+ if ( core_.namco_apu() ) core_.namco_apu()->volume( adjusted_gain );
+ if ( core_.vrc6_apu() ) core_.vrc6_apu() ->volume( adjusted_gain );
+ if ( core_.fme7_apu() ) core_.fme7_apu() ->volume( adjusted_gain );
+ if ( core_.mmc5_apu() ) core_.mmc5_apu() ->volume( adjusted_gain );
+ if ( core_.fds_apu() ) core_.fds_apu() ->volume( adjusted_gain );
+#endif
+
+ if ( adjusted_gain > gain() )
+ adjusted_gain = gain(); // only occurs if no other sound chips
+
+ core_.nes_apu()->volume( adjusted_gain );
+
+ return blargg_ok;
+}
+
+blargg_err_t Nsf_Emu::load_( Data_Reader& in )
+{
+ RETURN_ERR( core_.load( in ) );
+ set_track_count( header().track_count );
+ RETURN_ERR( check_nsf_header( header() ) );
+ set_warning( core_.warning() );
+ RETURN_ERR( init_sound() );
+ set_tempo( tempo() );
+ return setup_buffer( (int) (header().clock_rate() + 0.5) );
+}
+
+void Nsf_Emu::update_eq( blip_eq_t const& eq )
+{
+ core_.nes_apu()->treble_eq( eq );
+
+ #if !NSF_EMU_APU_ONLY
+ {
+ if ( core_.namco_apu() ) core_.namco_apu()->treble_eq( eq );
+ if ( core_.vrc6_apu() ) core_.vrc6_apu() ->treble_eq( eq );
+ if ( core_.fme7_apu() ) core_.fme7_apu() ->treble_eq( eq );
+ if ( core_.mmc5_apu() ) core_.mmc5_apu() ->treble_eq( eq );
+ if ( core_.fds_apu() ) core_.fds_apu() ->treble_eq( eq );
+ if ( core_.vrc7_apu() ) core_.vrc7_apu() ->treble_eq( eq );
+ }
+ #endif
+}
+
+void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
+{
+ #define HANDLE_CHIP( chip ) \
+ if ( chip && (i -= chip->osc_count) < 0 )\
+ {\
+ chip->set_output( i + chip->osc_count, buf );\
+ return;\
+ }\
+
+ HANDLE_CHIP( core_.nes_apu() );
+
+ #if !NSF_EMU_APU_ONLY
+ {
+ // TODO: order of chips here must match that in init_sound()
+ HANDLE_CHIP( core_.vrc6_apu() );
+ HANDLE_CHIP( core_.fme7_apu() );
+ HANDLE_CHIP( core_.mmc5_apu() );
+ HANDLE_CHIP( core_.fds_apu() );
+ HANDLE_CHIP( core_.namco_apu() );
+ HANDLE_CHIP( core_.vrc7_apu() );
+ }
+ #endif
+}
+
+blargg_err_t Nsf_Emu::start_track_( int track )
+{
+ RETURN_ERR( Classic_Emu::start_track_( track ) );
+ return core_.start_track( track );
+}
+
+blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
+{
+ core_.end_frame( duration );
+ const char* w = core_.warning();
+ if ( w )
+ set_warning( w );
+ return blargg_ok;
+}
+
+blargg_err_t Nsf_Emu::hash_( Hash_Function& out ) const
+{
+ hash_nsf_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
+ return blargg_ok;
}
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Opl_Apu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Opl_Apu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Opl_Apu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Opl_Apu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,242 +1,242 @@
-#include "Opl_Apu.h"
-
-#include "blargg_source.h"
-
-#include "ym2413.h"
-#include "fmopl.h"
-
-Opl_Apu::Opl_Apu() { opl = 0; opl_memory = 0; }
-
-blargg_err_t Opl_Apu::init( long clock, long rate, blip_time_t period, type_t type )
-{
- type_ = type;
- clock_ = clock;
- rate_ = rate;
- period_ = period;
- set_output( 0, 0 );
- volume( 1.0 );
- switch (type)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- opl = ym2413_init( clock, rate, 0 );
- break;
-
- case type_vrc7:
- opl = ym2413_init( clock, rate, 1 );
- break;
-
- case type_opl:
- opl = ym3526_init( clock, rate );
- break;
-
- case type_msxaudio:
- //logfile = fopen("c:\\temp\\msxaudio.log", "wb");
- opl = y8950_init( clock, rate );
- opl_memory = malloc( 32768 );
- y8950_set_delta_t_memory( opl, opl_memory, 32768 );
- break;
-
- case type_opl2:
- opl = ym3812_init( clock, rate );
- break;
- }
- reset();
- return 0;
-}
-
-Opl_Apu::~Opl_Apu()
-{
- if (opl)
- {
- switch (type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- ym2413_shutdown( opl );
- break;
-
- case type_opl:
- ym3526_shutdown( opl );
- break;
-
- case type_msxaudio:
- y8950_shutdown( opl );
- free( opl_memory );
- //fclose( logfile );
- break;
-
- case type_opl2:
- ym3812_shutdown( opl );
- break;
- }
- }
-}
-
-void Opl_Apu::reset()
-{
- addr = 0;
- next_time = 0;
- last_amp = 0;
-
- switch (type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- ym2413_reset_chip( opl );
- break;
-
- case type_opl:
- ym3526_reset_chip( opl );
- break;
-
- case type_msxaudio:
- y8950_reset_chip( opl );
- break;
-
- case type_opl2:
- ym3812_reset_chip( opl );
- break;
- }
-}
-
-void Opl_Apu::write_data( blip_time_t time, int data )
-{
- run_until( time );
- switch (type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- ym2413_write( opl, 0, addr );
- ym2413_write( opl, 1, data );
- break;
-
- case type_opl:
- ym3526_write( opl, 0, addr );
- ym3526_write( opl, 1, data );
- break;
-
- case type_msxaudio:
- /*if ( addr >= 7 && addr <= 7 + 11 )
- {
- unsigned char temp [2] = { addr - 7, data };
- fwrite( &temp, 1, 2, logfile );
- }*/
- y8950_write( opl, 0, addr );
- y8950_write( opl, 1, data );
- break;
-
- case type_opl2:
- ym3812_write( opl, 0, addr );
- ym3812_write( opl, 1, data );
- break;
- }
-}
-
-int Opl_Apu::read( blip_time_t time, int port )
-{
- run_until( time );
- switch (type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- return ym2413_read( opl, port );
-
- case type_opl:
- return ym3526_read( opl, port );
-
- case type_msxaudio:
- {
- int ret = y8950_read( opl, port );
- /*unsigned char temp [2] = { port + 0x80, ret };
- fwrite( &temp, 1, 2, logfile );*/
- return ret;
- }
-
- case type_opl2:
- return ym3812_read( opl, port );
- }
-
- return 0;
-}
-
-void Opl_Apu::end_frame( blip_time_t time )
-{
- run_until( time );
- next_time -= time;
-
- if ( output_ )
- output_->set_modified();
-}
-
-void Opl_Apu::run_until( blip_time_t end_time )
-{
- if ( end_time > next_time )
- {
- blip_time_t time_delta = end_time - next_time;
- blip_time_t time = next_time;
- unsigned count = time_delta / period_ + 1;
- switch (type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- {
- SAMP bufMO[ 1024 ];
- SAMP bufRO[ 1024 ];
- SAMP * buffers[2] = { bufMO, bufRO };
-
- while ( count > 0 )
- {
- unsigned todo = count;
- if ( todo > 1024 ) todo = 1024;
- ym2413_update_one( opl, buffers, todo );
-
- if ( output_ )
- {
- int last_amp = this->last_amp;
- for ( unsigned i = 0; i < todo; i++ )
- {
- int amp = bufMO [i] + bufRO [i];
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth.offset_inline( time, delta, output_ );
- }
- time += period_;
- }
- this->last_amp = last_amp;
- }
- else time += period_ * todo;
-
- count -= todo;
- }
- }
- break;
-
- case type_opl:
- case type_msxaudio:
- case type_opl2:
- {
- OPLSAMPLE buffer[ 1024 ];
-
- while ( count > 0 )
- {
- unsigned todo = count;
- if ( todo > 1024 ) todo = 1024;
- switch (type_)
- {
+#include "Opl_Apu.h"
+
+#include "blargg_source.h"
+
+#include "ym2413.h"
+#include "fmopl.h"
+
+Opl_Apu::Opl_Apu() { opl = 0; opl_memory = 0; }
+
+blargg_err_t Opl_Apu::init( long clock, long rate, blip_time_t period, type_t type )
+{
+ type_ = type;
+ clock_ = clock;
+ rate_ = rate;
+ period_ = period;
+ set_output( 0, 0 );
+ volume( 1.0 );
+ switch (type)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ opl = ym2413_init( clock, rate, 0 );
+ break;
+
+ case type_vrc7:
+ opl = ym2413_init( clock, rate, 1 );
+ break;
+
+ case type_opl:
+ opl = ym3526_init( clock, rate );
+ break;
+
+ case type_msxaudio:
+ //logfile = fopen("c:\\temp\\msxaudio.log", "wb");
+ opl = y8950_init( clock, rate );
+ opl_memory = malloc( 32768 );
+ y8950_set_delta_t_memory( opl, opl_memory, 32768 );
+ break;
+
+ case type_opl2:
+ opl = ym3812_init( clock, rate );
+ break;
+ }
+ reset();
+ return 0;
+}
+
+Opl_Apu::~Opl_Apu()
+{
+ if (opl)
+ {
+ switch (type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ ym2413_shutdown( opl );
+ break;
+
+ case type_opl:
+ ym3526_shutdown( opl );
+ break;
+
+ case type_msxaudio:
+ y8950_shutdown( opl );
+ free( opl_memory );
+ //fclose( logfile );
+ break;
+
+ case type_opl2:
+ ym3812_shutdown( opl );
+ break;
+ }
+ }
+}
+
+void Opl_Apu::reset()
+{
+ addr = 0;
+ next_time = 0;
+ last_amp = 0;
+
+ switch (type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ ym2413_reset_chip( opl );
+ break;
+
+ case type_opl:
+ ym3526_reset_chip( opl );
+ break;
+
+ case type_msxaudio:
+ y8950_reset_chip( opl );
+ break;
+
+ case type_opl2:
+ ym3812_reset_chip( opl );
+ break;
+ }
+}
+
+void Opl_Apu::write_data( blip_time_t time, int data )
+{
+ run_until( time );
+ switch (type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ ym2413_write( opl, 0, addr );
+ ym2413_write( opl, 1, data );
+ break;
+
+ case type_opl:
+ ym3526_write( opl, 0, addr );
+ ym3526_write( opl, 1, data );
+ break;
+
+ case type_msxaudio:
+ /*if ( addr >= 7 && addr <= 7 + 11 )
+ {
+ unsigned char temp [2] = { addr - 7, data };
+ fwrite( &temp, 1, 2, logfile );
+ }*/
+ y8950_write( opl, 0, addr );
+ y8950_write( opl, 1, data );
+ break;
+
+ case type_opl2:
+ ym3812_write( opl, 0, addr );
+ ym3812_write( opl, 1, data );
+ break;
+ }
+}
+
+int Opl_Apu::read( blip_time_t time, int port )
+{
+ run_until( time );
+ switch (type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ return ym2413_read( opl, port );
+
+ case type_opl:
+ return ym3526_read( opl, port );
+
+ case type_msxaudio:
+ {
+ int ret = y8950_read( opl, port );
+ /*unsigned char temp [2] = { port + 0x80, ret };
+ fwrite( &temp, 1, 2, logfile );*/
+ return ret;
+ }
+
+ case type_opl2:
+ return ym3812_read( opl, port );
+ }
+
+ return 0;
+}
+
+void Opl_Apu::end_frame( blip_time_t time )
+{
+ run_until( time );
+ next_time -= time;
+
+ if ( output_ )
+ output_->set_modified();
+}
+
+void Opl_Apu::run_until( blip_time_t end_time )
+{
+ if ( end_time > next_time )
+ {
+ blip_time_t time_delta = end_time - next_time;
+ blip_time_t time = next_time;
+ unsigned count = time_delta / period_ + 1;
+ switch (type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ {
+ SAMP bufMO[ 1024 ];
+ SAMP bufRO[ 1024 ];
+ SAMP * buffers[2] = { bufMO, bufRO };
+
+ while ( count > 0 )
+ {
+ unsigned todo = count;
+ if ( todo > 1024 ) todo = 1024;
+ ym2413_update_one( opl, buffers, todo );
+
+ if ( output_ )
+ {
+ int last_amp = this->last_amp;
+ for ( unsigned i = 0; i < todo; i++ )
+ {
+ int amp = bufMO [i] + bufRO [i];
+ int delta = amp - last_amp;
+ if ( delta )
+ {
+ last_amp = amp;
+ synth.offset_inline( time, delta, output_ );
+ }
+ time += period_;
+ }
+ this->last_amp = last_amp;
+ }
+ else time += period_ * todo;
+
+ count -= todo;
+ }
+ }
+ break;
+
+ case type_opl:
+ case type_msxaudio:
+ case type_opl2:
+ {
+ OPLSAMPLE buffer[ 1024 ];
+
+ while ( count > 0 )
+ {
+ unsigned todo = count;
+ if ( todo > 1024 ) todo = 1024;
+ switch (type_)
+ {
case type_opl: ym3526_update_one( opl, buffer, todo ); break;
case type_msxaudio: y8950_update_one( opl, buffer, todo ); break;
case type_opl2: ym3812_update_one( opl, buffer, todo ); break;
@@ -244,28 +244,28 @@
}
if ( output_ )
- {
- int last_amp = this->last_amp;
- for ( unsigned i = 0; i < todo; i++ )
- {
- int amp = buffer [i];
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth.offset_inline( time, delta, output_ );
- }
- time += period_;
- }
- this->last_amp = last_amp;
- }
- else time += period_ * todo;
-
- count -= todo;
- }
- }
- break;
- }
- next_time = time;
- }
+ {
+ int last_amp = this->last_amp;
+ for ( unsigned i = 0; i < todo; i++ )
+ {
+ int amp = buffer [i];
+ int delta = amp - last_amp;
+ if ( delta )
+ {
+ last_amp = amp;
+ synth.offset_inline( time, delta, output_ );
+ }
+ time += period_;
+ }
+ this->last_amp = last_amp;
+ }
+ else time += period_ * todo;
+
+ count -= todo;
+ }
+ }
+ break;
+ }
+ next_time = time;
+ }
}
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Opl_Apu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Opl_Apu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Opl_Apu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Opl_Apu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,63 +1,63 @@
-#ifndef OPL_APU_H
-#define OPL_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-#include
-
-class Opl_Apu {
-public:
- Opl_Apu();
- ~Opl_Apu();
-
- enum type_t { type_opll = 0x10, type_msxmusic = 0x11, type_smsfmunit = 0x12,
- type_vrc7 = 0x13, type_opl = 0x20, type_msxaudio = 0x21, type_opl2 = 0x22 };
- blargg_err_t init( long clock, long rate, blip_time_t period, type_t );
-
- void reset();
- void volume( double v ) { synth.volume( 1.0 / (4096 * 6) * v ); }
- void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
- enum { osc_count = 1 };
- void osc_output( int index, Blip_Buffer* );
- void set_output( int i, Blip_Buffer* buf, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { osc_output( 0, buf ); }
- void end_frame( blip_time_t );
-
- void write_addr( int data ) { addr = data; }
- void write_data( blip_time_t, int data );
-
- int read( blip_time_t, int port );
-
- static bool supported() { return true; }
-
-private:
- // noncopyable
- Opl_Apu( const Opl_Apu& );
- Opl_Apu& operator = ( const Opl_Apu& );
-
- Blip_Buffer* output_;
- type_t type_;
- void* opl;
- void* opl_memory;
- //FILE* logfile;
- unsigned char regs[ 0x100 ];
- blip_time_t next_time;
- int last_amp;
- int addr;
-
- long clock_;
- long rate_;
- blip_time_t period_;
-
- Blip_Synth_Fast synth;
-
- void run_until( blip_time_t );
-};
-
-inline void Opl_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- output_ = buf;
-}
-
-#endif
+#ifndef OPL_APU_H
+#define OPL_APU_H
+
+#include "blargg_common.h"
+#include "Blip_Buffer.h"
+
+#include
+
+class Opl_Apu {
+public:
+ Opl_Apu();
+ ~Opl_Apu();
+
+ enum type_t { type_opll = 0x10, type_msxmusic = 0x11, type_smsfmunit = 0x12,
+ type_vrc7 = 0x13, type_opl = 0x20, type_msxaudio = 0x21, type_opl2 = 0x22 };
+ blargg_err_t init( long clock, long rate, blip_time_t period, type_t );
+
+ void reset();
+ void volume( double v ) { synth.volume( 1.0 / (4096 * 6) * v ); }
+ void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
+ enum { osc_count = 1 };
+ void osc_output( int index, Blip_Buffer* );
+ void set_output( int i, Blip_Buffer* buf, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { osc_output( 0, buf ); }
+ void end_frame( blip_time_t );
+
+ void write_addr( int data ) { addr = data; }
+ void write_data( blip_time_t, int data );
+
+ int read( blip_time_t, int port );
+
+ static bool supported() { return true; }
+
+private:
+ // noncopyable
+ Opl_Apu( const Opl_Apu& );
+ Opl_Apu& operator = ( const Opl_Apu& );
+
+ Blip_Buffer* output_;
+ type_t type_;
+ void* opl;
+ void* opl_memory;
+ //FILE* logfile;
+ unsigned char regs[ 0x100 ];
+ blip_time_t next_time;
+ int last_amp;
+ int addr;
+
+ long clock_;
+ long rate_;
+ blip_time_t period_;
+
+ Blip_Synth_Fast synth;
+
+ void run_until( blip_time_t );
+};
+
+inline void Opl_Apu::osc_output( int i, Blip_Buffer* buf )
+{
+ assert( (unsigned) i < osc_count );
+ output_ = buf;
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/pwm.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/pwm.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/pwm.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/pwm.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,27 +1,27 @@
-/***************************************************************************
- * Gens: PWM audio emulator. *
- * *
- * Copyright (c) 1999-2002 by Stphane Dallongeville *
- * Copyright (c) 2003-2004 by Stphane Akhoun *
- * Copyright (c) 2008-2009 by David Korth *
- * *
- * This program is free software; you can redistribute it and/or modify it *
- * under the terms of the GNU General Public License as published by the *
- * Free Software Foundation; either version 2 of the License, or (at your *
- * option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License along *
- * with this program; if not, write to the Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
- ***************************************************************************/
-
-#include "pwm.h"
-
+/***************************************************************************
+ * Gens: PWM audio emulator. *
+ * *
+ * Copyright (c) 1999-2002 by Stphane Dallongeville *
+ * Copyright (c) 2003-2004 by Stphane Akhoun *
+ * Copyright (c) 2008-2009 by David Korth *
+ * *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the *
+ * Free Software Foundation; either version 2 of the License, or (at your *
+ * option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "pwm.h"
+
#include
#include
@@ -31,251 +31,251 @@
//#include "gens_core/mem/mem_sh2.h"
//#include "gens_core/cpu/sh2/sh2.h"
-
-#define CHILLY_WILLY_SCALE 1
-
-#if PWM_BUF_SIZE == 8
-unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =
-{
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
-};
-#elif PWM_BUF_SIZE == 4
-unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =
-{
- 0x40, 0x00, 0x00, 0x80,
- 0x80, 0x40, 0x00, 0x00,
- 0x00, 0x80, 0x40, 0x00,
- 0x00, 0x00, 0x80, 0x40,
-};
-#else
-#error PWM_BUF_SIZE must equal 4 or 8.
-#endif /* PWM_BUF_SIZE */
-
-typedef struct _pwm_chip
-{
- unsigned short PWM_FIFO_R[8];
- unsigned short PWM_FIFO_L[8];
- unsigned int PWM_RP_R;
- unsigned int PWM_WP_R;
- unsigned int PWM_RP_L;
- unsigned int PWM_WP_L;
- unsigned int PWM_Cycles;
- unsigned int PWM_Cycle;
- unsigned int PWM_Cycle_Cnt;
- unsigned int PWM_Int;
- unsigned int PWM_Int_Cnt;
- unsigned int PWM_Mode;
- //unsigned int PWM_Enable;
- unsigned int PWM_Out_R;
- unsigned int PWM_Out_L;
-
- unsigned int PWM_Cycle_Tmp;
- unsigned int PWM_Cycles_Tmp;
- unsigned int PWM_Int_Tmp;
- unsigned int PWM_FIFO_L_Tmp;
- unsigned int PWM_FIFO_R_Tmp;
-
-#if CHILLY_WILLY_SCALE
-// TODO: Fix Chilly Willy's new scaling algorithm.
- /* PWM scaling variables. */
- int PWM_Offset;
- int PWM_Scale;
- //int PWM_Loudness;
-#endif
-
- int clock;
-} pwm_chip;
-#if CHILLY_WILLY_SCALE
-// TODO: Fix Chilly Willy's new scaling algorithm.
-#define PWM_Loudness 0
-#endif
-
-void PWM_Init(pwm_chip* chip);
-void PWM_Recalc_Scale(pwm_chip* chip);
-
-void PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle);
-void PWM_Set_Int(pwm_chip* chip, unsigned int int_time);
-
-void PWM_Update(pwm_chip* chip, int **buf, int length);
-
-
-/**
- * PWM_Init(): Initialize the PWM audio emulator.
- */
-void PWM_Init(pwm_chip* chip)
-{
- chip->PWM_Mode = 0;
- chip->PWM_Out_R = 0;
- chip->PWM_Out_L = 0;
-
- memset(chip->PWM_FIFO_R, 0x00, sizeof(chip->PWM_FIFO_R));
- memset(chip->PWM_FIFO_L, 0x00, sizeof(chip->PWM_FIFO_L));
-
- chip->PWM_RP_R = 0;
- chip->PWM_WP_R = 0;
- chip->PWM_RP_L = 0;
- chip->PWM_WP_L = 0;
- chip->PWM_Cycle_Tmp = 0;
- chip->PWM_Int_Tmp = 0;
- chip->PWM_FIFO_L_Tmp = 0;
- chip->PWM_FIFO_R_Tmp = 0;
-
- //PWM_Loudness = 0;
- PWM_Set_Cycle(chip, 0);
- PWM_Set_Int(chip, 0);
-}
-
-
-#if CHILLY_WILLY_SCALE
-// TODO: Fix Chilly Willy's new scaling algorithm.
-void PWM_Recalc_Scale(pwm_chip* chip)
-{
- chip->PWM_Offset = (chip->PWM_Cycle / 2) + 1;
- chip->PWM_Scale = 0x7FFF00 / chip->PWM_Offset;
-}
-#endif
-
-
-void PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle)
-{
- cycle--;
- chip->PWM_Cycle = (cycle & 0xFFF);
- chip->PWM_Cycle_Cnt = chip->PWM_Cycles;
-
-#if CHILLY_WILLY_SCALE
- // TODO: Fix Chilly Willy's new scaling algorithm.
- PWM_Recalc_Scale(chip);
-#endif
-}
-
-
-void PWM_Set_Int(pwm_chip* chip, unsigned int int_time)
-{
- int_time &= 0x0F;
- if (int_time)
- chip->PWM_Int = chip->PWM_Int_Cnt = int_time;
- else
- chip->PWM_Int = chip->PWM_Int_Cnt = 16;
-}
-
-
-void PWM_Clear_Timer(pwm_chip* chip)
-{
- chip->PWM_Cycle_Cnt = 0;
-}
-
-
-/**
- * PWM_SHIFT(): Shift PWM data.
- * @param src: Channel (L or R) with the source data.
- * @param dest Channel (L or R) for the destination.
- */
-#define PWM_SHIFT(src, dest) \
-{ \
- /* Make sure the source FIFO isn't empty. */ \
- if (PWM_RP_##src != PWM_WP_##src) \
- { \
- /* Get destination channel output from the source channel FIFO. */ \
- PWM_Out_##dest = PWM_FIFO_##src[PWM_RP_##src]; \
- \
- /* Increment the source channel read pointer, resetting to 0 if it overflows. */ \
- PWM_RP_##src = (PWM_RP_##src + 1) & (PWM_BUF_SIZE - 1); \
- } \
-}
-
-
-/*static void PWM_Shift_Data(void)
-{
- switch (PWM_Mode & 0x0F)
- {
- case 0x01:
- case 0x0D:
- // Rx_LL: Right -> Ignore, Left -> Left
- PWM_SHIFT(L, L);
- break;
-
- case 0x02:
- case 0x0E:
- // Rx_LR: Right -> Ignore, Left -> Right
- PWM_SHIFT(L, R);
- break;
-
- case 0x04:
- case 0x07:
- // RL_Lx: Right -> Left, Left -> Ignore
- PWM_SHIFT(R, L);
- break;
-
- case 0x05:
- case 0x09:
- // RR_LL: Right -> Right, Left -> Left
- PWM_SHIFT(L, L);
- PWM_SHIFT(R, R);
- break;
-
- case 0x06:
- case 0x0A:
- // RL_LR: Right -> Left, Left -> Right
- PWM_SHIFT(L, R);
- PWM_SHIFT(R, L);
- break;
-
- case 0x08:
- case 0x0B:
- // RR_Lx: Right -> Right, Left -> Ignore
- PWM_SHIFT(R, R);
- break;
-
- case 0x00:
- case 0x03:
- case 0x0C:
- case 0x0F:
- default:
- // Rx_Lx: Right -> Ignore, Left -> Ignore
- break;
- }
-}
-
-
-void PWM_Update_Timer(unsigned int cycle)
-{
- // Don't do anything if PWM is disabled in the Sound menu.
-
- // Don't do anything if PWM isn't active.
- if ((PWM_Mode & 0x0F) == 0x00)
- return;
-
- if (PWM_Cycle == 0x00 || (PWM_Cycle_Cnt > cycle))
- return;
-
- PWM_Shift_Data();
-
- PWM_Cycle_Cnt += PWM_Cycle;
-
- PWM_Int_Cnt--;
- if (PWM_Int_Cnt == 0)
- {
- PWM_Int_Cnt = PWM_Int;
-
- if (PWM_Mode & 0x0080)
- {
- // RPT => generate DREQ1 as well as INT
- SH2_DMA1_Request(&M_SH2, 1);
- SH2_DMA1_Request(&S_SH2, 1);
- }
-
- if (_32X_MINT & 1)
- SH2_Interrupt(&M_SH2, 6);
- if (_32X_SINT & 1)
- SH2_Interrupt(&S_SH2, 6);
- }
+
+#define CHILLY_WILLY_SCALE 1
+
+#if PWM_BUF_SIZE == 8
+unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =
+{
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+};
+#elif PWM_BUF_SIZE == 4
+unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE] =
+{
+ 0x40, 0x00, 0x00, 0x80,
+ 0x80, 0x40, 0x00, 0x00,
+ 0x00, 0x80, 0x40, 0x00,
+ 0x00, 0x00, 0x80, 0x40,
+};
+#else
+#error PWM_BUF_SIZE must equal 4 or 8.
+#endif /* PWM_BUF_SIZE */
+
+typedef struct _pwm_chip
+{
+ unsigned short PWM_FIFO_R[8];
+ unsigned short PWM_FIFO_L[8];
+ unsigned int PWM_RP_R;
+ unsigned int PWM_WP_R;
+ unsigned int PWM_RP_L;
+ unsigned int PWM_WP_L;
+ unsigned int PWM_Cycles;
+ unsigned int PWM_Cycle;
+ unsigned int PWM_Cycle_Cnt;
+ unsigned int PWM_Int;
+ unsigned int PWM_Int_Cnt;
+ unsigned int PWM_Mode;
+ //unsigned int PWM_Enable;
+ unsigned int PWM_Out_R;
+ unsigned int PWM_Out_L;
+
+ unsigned int PWM_Cycle_Tmp;
+ unsigned int PWM_Cycles_Tmp;
+ unsigned int PWM_Int_Tmp;
+ unsigned int PWM_FIFO_L_Tmp;
+ unsigned int PWM_FIFO_R_Tmp;
+
+#if CHILLY_WILLY_SCALE
+// TODO: Fix Chilly Willy's new scaling algorithm.
+ /* PWM scaling variables. */
+ int PWM_Offset;
+ int PWM_Scale;
+ //int PWM_Loudness;
+#endif
+
+ int clock;
+} pwm_chip;
+#if CHILLY_WILLY_SCALE
+// TODO: Fix Chilly Willy's new scaling algorithm.
+#define PWM_Loudness 0
+#endif
+
+void PWM_Init(pwm_chip* chip);
+void PWM_Recalc_Scale(pwm_chip* chip);
+
+void PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle);
+void PWM_Set_Int(pwm_chip* chip, unsigned int int_time);
+
+void PWM_Update(pwm_chip* chip, int **buf, int length);
+
+
+/**
+ * PWM_Init(): Initialize the PWM audio emulator.
+ */
+void PWM_Init(pwm_chip* chip)
+{
+ chip->PWM_Mode = 0;
+ chip->PWM_Out_R = 0;
+ chip->PWM_Out_L = 0;
+
+ memset(chip->PWM_FIFO_R, 0x00, sizeof(chip->PWM_FIFO_R));
+ memset(chip->PWM_FIFO_L, 0x00, sizeof(chip->PWM_FIFO_L));
+
+ chip->PWM_RP_R = 0;
+ chip->PWM_WP_R = 0;
+ chip->PWM_RP_L = 0;
+ chip->PWM_WP_L = 0;
+ chip->PWM_Cycle_Tmp = 0;
+ chip->PWM_Int_Tmp = 0;
+ chip->PWM_FIFO_L_Tmp = 0;
+ chip->PWM_FIFO_R_Tmp = 0;
+
+ //PWM_Loudness = 0;
+ PWM_Set_Cycle(chip, 0);
+ PWM_Set_Int(chip, 0);
+}
+
+
+#if CHILLY_WILLY_SCALE
+// TODO: Fix Chilly Willy's new scaling algorithm.
+void PWM_Recalc_Scale(pwm_chip* chip)
+{
+ chip->PWM_Offset = (chip->PWM_Cycle / 2) + 1;
+ chip->PWM_Scale = 0x7FFF00 / chip->PWM_Offset;
+}
+#endif
+
+
+void PWM_Set_Cycle(pwm_chip* chip, unsigned int cycle)
+{
+ cycle--;
+ chip->PWM_Cycle = (cycle & 0xFFF);
+ chip->PWM_Cycle_Cnt = chip->PWM_Cycles;
+
+#if CHILLY_WILLY_SCALE
+ // TODO: Fix Chilly Willy's new scaling algorithm.
+ PWM_Recalc_Scale(chip);
+#endif
+}
+
+
+void PWM_Set_Int(pwm_chip* chip, unsigned int int_time)
+{
+ int_time &= 0x0F;
+ if (int_time)
+ chip->PWM_Int = chip->PWM_Int_Cnt = int_time;
+ else
+ chip->PWM_Int = chip->PWM_Int_Cnt = 16;
+}
+
+
+void PWM_Clear_Timer(pwm_chip* chip)
+{
+ chip->PWM_Cycle_Cnt = 0;
+}
+
+
+/**
+ * PWM_SHIFT(): Shift PWM data.
+ * @param src: Channel (L or R) with the source data.
+ * @param dest Channel (L or R) for the destination.
+ */
+#define PWM_SHIFT(src, dest) \
+{ \
+ /* Make sure the source FIFO isn't empty. */ \
+ if (PWM_RP_##src != PWM_WP_##src) \
+ { \
+ /* Get destination channel output from the source channel FIFO. */ \
+ PWM_Out_##dest = PWM_FIFO_##src[PWM_RP_##src]; \
+ \
+ /* Increment the source channel read pointer, resetting to 0 if it overflows. */ \
+ PWM_RP_##src = (PWM_RP_##src + 1) & (PWM_BUF_SIZE - 1); \
+ } \
+}
+
+
+/*static void PWM_Shift_Data(void)
+{
+ switch (PWM_Mode & 0x0F)
+ {
+ case 0x01:
+ case 0x0D:
+ // Rx_LL: Right -> Ignore, Left -> Left
+ PWM_SHIFT(L, L);
+ break;
+
+ case 0x02:
+ case 0x0E:
+ // Rx_LR: Right -> Ignore, Left -> Right
+ PWM_SHIFT(L, R);
+ break;
+
+ case 0x04:
+ case 0x07:
+ // RL_Lx: Right -> Left, Left -> Ignore
+ PWM_SHIFT(R, L);
+ break;
+
+ case 0x05:
+ case 0x09:
+ // RR_LL: Right -> Right, Left -> Left
+ PWM_SHIFT(L, L);
+ PWM_SHIFT(R, R);
+ break;
+
+ case 0x06:
+ case 0x0A:
+ // RL_LR: Right -> Left, Left -> Right
+ PWM_SHIFT(L, R);
+ PWM_SHIFT(R, L);
+ break;
+
+ case 0x08:
+ case 0x0B:
+ // RR_Lx: Right -> Right, Left -> Ignore
+ PWM_SHIFT(R, R);
+ break;
+
+ case 0x00:
+ case 0x03:
+ case 0x0C:
+ case 0x0F:
+ default:
+ // Rx_Lx: Right -> Ignore, Left -> Ignore
+ break;
+ }
+}
+
+
+void PWM_Update_Timer(unsigned int cycle)
+{
+ // Don't do anything if PWM is disabled in the Sound menu.
+
+ // Don't do anything if PWM isn't active.
+ if ((PWM_Mode & 0x0F) == 0x00)
+ return;
+
+ if (PWM_Cycle == 0x00 || (PWM_Cycle_Cnt > cycle))
+ return;
+
+ PWM_Shift_Data();
+
+ PWM_Cycle_Cnt += PWM_Cycle;
+
+ PWM_Int_Cnt--;
+ if (PWM_Int_Cnt == 0)
+ {
+ PWM_Int_Cnt = PWM_Int;
+
+ if (PWM_Mode & 0x0080)
+ {
+ // RPT => generate DREQ1 as well as INT
+ SH2_DMA1_Request(&M_SH2, 1);
+ SH2_DMA1_Request(&S_SH2, 1);
+ }
+
+ if (_32X_MINT & 1)
+ SH2_Interrupt(&M_SH2, 6);
+ if (_32X_SINT & 1)
+ SH2_Interrupt(&S_SH2, 6);
+ }
}*/
@@ -283,162 +283,162 @@
{
if (PWM_In == 0)
return 0;
-
- // TODO: Chilly Willy's new scaling algorithm breaks drx's Sonic 1 32X (with PWM drums).
-#ifdef CHILLY_WILLY_SCALE
- //return (((PWM_In & 0xFFF) - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);
- // Knuckles' Chaotix: Tachy Touch uses the values 0xF?? for negative values
- // This small modification fixes the terrible pops.
- PWM_In &= 0xFFF;
- if (PWM_In & 0x800)
- PWM_In |= ~0xFFF;
- return ((PWM_In - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);
-#else
- const int PWM_adjust = ((chip->PWM_Cycle >> 1) + 1);
- int PWM_Ret = ((chip->PWM_In & 0xFFF) - PWM_adjust);
-
- // Increase PWM volume so it's audible.
- PWM_Ret <<= (5+2);
-
- // Make sure the PWM isn't oversaturated.
- if (PWM_Ret > 32767)
- PWM_Ret = 32767;
- else if (PWM_Ret < -32768)
- PWM_Ret = -32768;
-
- return PWM_Ret;
-#endif
-}
-
-
-void PWM_Update(pwm_chip* chip, int **buf, int length)
-{
- int tmpOutL;
- int tmpOutR;
- int i;
-
- //if (!PWM_Enable)
- // return;
-
- if (chip->PWM_Out_L == 0 && chip->PWM_Out_R == 0)
- {
- memset(buf[0], 0x00, length * sizeof(int));
- memset(buf[1], 0x00, length * sizeof(int));
- return;
- }
-
- // New PWM scaling algorithm provided by Chilly Willy on the Sonic Retro forums.
- tmpOutL = PWM_Update_Scale(chip, (int)chip->PWM_Out_L);
- tmpOutR = PWM_Update_Scale(chip, (int)chip->PWM_Out_R);
-
- for (i = 0; i < length; i ++)
- {
- buf[0][i] = tmpOutL;
- buf[1][i] = tmpOutR;
- }
-}
-
-
-void pwm_update(void *_chip, stream_sample_t **outputs, int samples)
-{
- pwm_chip *chip = (pwm_chip *) _chip;
-
- PWM_Update(chip, outputs, samples);
-}
-
-void * device_start_pwm(int clock)
-{
- /* allocate memory for the chip */
- //pwm_state *chip = get_safe_token(device);
- pwm_chip *chip;
- int rate;
-
- chip = (pwm_chip *) malloc(sizeof(pwm_chip));
- if (!chip) return chip;
-
- rate = 22020; // that's the rate the PWM is mostly used
- chip->clock = clock;
-
- PWM_Init(chip);
- /* allocate the stream */
- //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
-
- return chip;
-}
-
-void device_stop_pwm(void *chip)
-{
- //pwm_chip *chip = &PWM_Chip[ChipID];
- //free(chip->ram);
- free(chip);
-}
-
-void device_reset_pwm(void *_chip)
-{
- pwm_chip *chip = (pwm_chip *) _chip;
- PWM_Init(chip);
-}
-
-void pwm_chn_w(void *_chip, UINT8 Channel, UINT16 data)
-{
- pwm_chip *chip = (pwm_chip *) _chip;
-
- if (chip->clock == 1)
- { // old-style commands
- switch(Channel)
- {
- case 0x00:
- chip->PWM_Out_L = data;
- break;
- case 0x01:
- chip->PWM_Out_R = data;
- break;
- case 0x02:
- PWM_Set_Cycle(chip, data);
- break;
- case 0x03:
- chip->PWM_Out_L = data;
- chip->PWM_Out_R = data;
- break;
- }
- }
- else
- {
- switch(Channel)
- {
- case 0x00/2: // control register
- PWM_Set_Int(chip, data >> 8);
- break;
- case 0x02/2: // cycle register
- PWM_Set_Cycle(chip, data);
- break;
- case 0x04/2: // l ch
- chip->PWM_Out_L = data;
- break;
- case 0x06/2: // r ch
- chip->PWM_Out_R = data;
- if (! chip->PWM_Mode)
- {
- if (chip->PWM_Out_L == chip->PWM_Out_R)
- {
- // fixes these terrible pops when
- // starting/stopping/pausing the song
- chip->PWM_Offset = data;
- chip->PWM_Mode = 0x01;
- }
- }
- break;
- case 0x08/2: // mono ch
- chip->PWM_Out_L = data;
- chip->PWM_Out_R = data;
- if (! chip->PWM_Mode)
- {
- chip->PWM_Offset = data;
- chip->PWM_Mode = 0x01;
- }
- break;
- }
- }
-
- return;
-}
+
+ // TODO: Chilly Willy's new scaling algorithm breaks drx's Sonic 1 32X (with PWM drums).
+#ifdef CHILLY_WILLY_SCALE
+ //return (((PWM_In & 0xFFF) - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);
+ // Knuckles' Chaotix: Tachy Touch uses the values 0xF?? for negative values
+ // This small modification fixes the terrible pops.
+ PWM_In &= 0xFFF;
+ if (PWM_In & 0x800)
+ PWM_In |= ~0xFFF;
+ return ((PWM_In - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness);
+#else
+ const int PWM_adjust = ((chip->PWM_Cycle >> 1) + 1);
+ int PWM_Ret = ((chip->PWM_In & 0xFFF) - PWM_adjust);
+
+ // Increase PWM volume so it's audible.
+ PWM_Ret <<= (5+2);
+
+ // Make sure the PWM isn't oversaturated.
+ if (PWM_Ret > 32767)
+ PWM_Ret = 32767;
+ else if (PWM_Ret < -32768)
+ PWM_Ret = -32768;
+
+ return PWM_Ret;
+#endif
+}
+
+
+void PWM_Update(pwm_chip* chip, int **buf, int length)
+{
+ int tmpOutL;
+ int tmpOutR;
+ int i;
+
+ //if (!PWM_Enable)
+ // return;
+
+ if (chip->PWM_Out_L == 0 && chip->PWM_Out_R == 0)
+ {
+ memset(buf[0], 0x00, length * sizeof(int));
+ memset(buf[1], 0x00, length * sizeof(int));
+ return;
+ }
+
+ // New PWM scaling algorithm provided by Chilly Willy on the Sonic Retro forums.
+ tmpOutL = PWM_Update_Scale(chip, (int)chip->PWM_Out_L);
+ tmpOutR = PWM_Update_Scale(chip, (int)chip->PWM_Out_R);
+
+ for (i = 0; i < length; i ++)
+ {
+ buf[0][i] = tmpOutL;
+ buf[1][i] = tmpOutR;
+ }
+}
+
+
+void pwm_update(void *_chip, stream_sample_t **outputs, int samples)
+{
+ pwm_chip *chip = (pwm_chip *) _chip;
+
+ PWM_Update(chip, outputs, samples);
+}
+
+void * device_start_pwm(int clock)
+{
+ /* allocate memory for the chip */
+ //pwm_state *chip = get_safe_token(device);
+ pwm_chip *chip;
+ int rate;
+
+ chip = (pwm_chip *) malloc(sizeof(pwm_chip));
+ if (!chip) return chip;
+
+ rate = 22020; // that's the rate the PWM is mostly used
+ chip->clock = clock;
+
+ PWM_Init(chip);
+ /* allocate the stream */
+ //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
+
+ return chip;
+}
+
+void device_stop_pwm(void *chip)
+{
+ //pwm_chip *chip = &PWM_Chip[ChipID];
+ //free(chip->ram);
+ free(chip);
+}
+
+void device_reset_pwm(void *_chip)
+{
+ pwm_chip *chip = (pwm_chip *) _chip;
+ PWM_Init(chip);
+}
+
+void pwm_chn_w(void *_chip, UINT8 Channel, UINT16 data)
+{
+ pwm_chip *chip = (pwm_chip *) _chip;
+
+ if (chip->clock == 1)
+ { // old-style commands
+ switch(Channel)
+ {
+ case 0x00:
+ chip->PWM_Out_L = data;
+ break;
+ case 0x01:
+ chip->PWM_Out_R = data;
+ break;
+ case 0x02:
+ PWM_Set_Cycle(chip, data);
+ break;
+ case 0x03:
+ chip->PWM_Out_L = data;
+ chip->PWM_Out_R = data;
+ break;
+ }
+ }
+ else
+ {
+ switch(Channel)
+ {
+ case 0x00/2: // control register
+ PWM_Set_Int(chip, data >> 8);
+ break;
+ case 0x02/2: // cycle register
+ PWM_Set_Cycle(chip, data);
+ break;
+ case 0x04/2: // l ch
+ chip->PWM_Out_L = data;
+ break;
+ case 0x06/2: // r ch
+ chip->PWM_Out_R = data;
+ if (! chip->PWM_Mode)
+ {
+ if (chip->PWM_Out_L == chip->PWM_Out_R)
+ {
+ // fixes these terrible pops when
+ // starting/stopping/pausing the song
+ chip->PWM_Offset = data;
+ chip->PWM_Mode = 0x01;
+ }
+ }
+ break;
+ case 0x08/2: // mono ch
+ chip->PWM_Out_L = data;
+ chip->PWM_Out_R = data;
+ if (! chip->PWM_Mode)
+ {
+ chip->PWM_Offset = data;
+ chip->PWM_Mode = 0x01;
+ }
+ break;
+ }
+ }
+
+ return;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,66 +1,66 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Pwm_Emu.h"
-#include "pwm.h"
-
-Pwm_Emu::Pwm_Emu() { chip = 0; }
-
-Pwm_Emu::~Pwm_Emu()
-{
- if ( chip ) device_stop_pwm( chip );
-}
-
-int Pwm_Emu::set_rate( int clock )
-{
- if ( chip )
- {
- device_stop_pwm( chip );
- chip = 0;
- }
-
- chip = device_start_pwm( clock );
- if ( !chip )
- return 1;
-
- reset();
- return 0;
-}
-
-void Pwm_Emu::reset()
-{
- device_reset_pwm( chip );
-}
-
-void Pwm_Emu::write( int channel, int data )
-{
- pwm_chn_w( chip, channel, data );
-}
-
-void Pwm_Emu::run( int pair_count, sample_t* out )
-{
- stream_sample_t bufL[ 1024 ];
- stream_sample_t bufR[ 1024 ];
- stream_sample_t * buffers[2] = { bufL, bufR };
-
- while (pair_count > 0)
- {
- int todo = pair_count;
- if (todo > 1024) todo = 1024;
- pwm_update( chip, buffers, todo );
-
- for (int i = 0; i < todo; i++)
- {
- int output_l = bufL [i];
- int output_r = bufR [i];
- output_l += out [0];
- output_r += out [1];
- if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
- if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
- out [0] = output_l;
- out [1] = output_r;
- out += 2;
- }
-
- pair_count -= todo;
- }
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Pwm_Emu.h"
+#include "pwm.h"
+
+Pwm_Emu::Pwm_Emu() { chip = 0; }
+
+Pwm_Emu::~Pwm_Emu()
+{
+ if ( chip ) device_stop_pwm( chip );
+}
+
+int Pwm_Emu::set_rate( int clock )
+{
+ if ( chip )
+ {
+ device_stop_pwm( chip );
+ chip = 0;
+ }
+
+ chip = device_start_pwm( clock );
+ if ( !chip )
+ return 1;
+
+ reset();
+ return 0;
+}
+
+void Pwm_Emu::reset()
+{
+ device_reset_pwm( chip );
+}
+
+void Pwm_Emu::write( int channel, int data )
+{
+ pwm_chn_w( chip, channel, data );
+}
+
+void Pwm_Emu::run( int pair_count, sample_t* out )
+{
+ stream_sample_t bufL[ 1024 ];
+ stream_sample_t bufR[ 1024 ];
+ stream_sample_t * buffers[2] = { bufL, bufR };
+
+ while (pair_count > 0)
+ {
+ int todo = pair_count;
+ if (todo > 1024) todo = 1024;
+ pwm_update( chip, buffers, todo );
+
+ for (int i = 0; i < todo; i++)
+ {
+ int output_l = bufL [i];
+ int output_r = bufR [i];
+ output_l += out [0];
+ output_r += out [1];
+ if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
+ if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
+ out [0] = output_l;
+ out [1] = output_r;
+ out += 2;
+ }
+
+ pair_count -= todo;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Pwm_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,33 +1,34 @@
-// PWM sound chip emulator interface
-
-// Game_Music_Emu $vers
-#ifndef PWM_EMU_H
-#define PWM_EMU_H
-
-class Pwm_Emu {
- void* chip;
-public:
- Pwm_Emu();
- ~Pwm_Emu();
-
- // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( int clock );
-
- // Resets to power-up state
- void reset();
-
- // Mutes voice n if bit n (1 << n) of mask is set
- enum { channel_count = 24 };
- void mute_voices( int mask );
-
- // Writes data to channel
- void write( int channel, int data );
-
- // Runs and writes pair_count*2 samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
+// PWM sound chip emulator interface
+
+// Game_Music_Emu $vers
+#ifndef PWM_EMU_H
+#define PWM_EMU_H
+
+class Pwm_Emu {
+ void* chip;
+public:
+ Pwm_Emu();
+ ~Pwm_Emu();
+
+ // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+ // if error.
+ int set_rate( int clock );
+
+ // Resets to power-up state
+ void reset();
+
+ // Mutes voice n if bit n (1 << n) of mask is set
+ enum { channel_count = 24 };
+ void mute_voices( int mask );
+
+ // Writes data to channel
+ void write( int channel, int data );
+
+ // Runs and writes pair_count*2 samples to output
+ typedef short sample_t;
+ enum { out_chan_count = 2 }; // stereo
+ void run( int pair_count, sample_t* out );
+};
+
+#endif
+
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/pwm.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/pwm.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/pwm.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/pwm.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,71 +1,71 @@
-/***************************************************************************
- * Gens: PWM audio emulator. *
- * *
- * Copyright (c) 1999-2002 by Stphane Dallongeville *
- * Copyright (c) 2003-2004 by Stphane Akhoun *
- * Copyright (c) 2008 by David Korth *
- * *
- * This program is free software; you can redistribute it and/or modify it *
- * under the terms of the GNU General Public License as published by the *
- * Free Software Foundation; either version 2 of the License, or (at your *
- * option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License along *
- * with this program; if not, write to the Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
- ***************************************************************************/
-
-#define PWM_BUF_SIZE 4
-
-#include "mamedef.h"
-
-/*extern unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE];
-
-extern unsigned short PWM_FIFO_R[8];
-extern unsigned short PWM_FIFO_L[8];
-extern unsigned int PWM_RP_R;
-extern unsigned int PWM_WP_R;
-extern unsigned int PWM_RP_L;
-extern unsigned int PWM_WP_L;
-extern unsigned int PWM_Cycles;
-extern unsigned int PWM_Cycle;
-extern unsigned int PWM_Cycle_Cnt;
-extern unsigned int PWM_Int;
-extern unsigned int PWM_Int_Cnt;
-extern unsigned int PWM_Mode;
-extern unsigned int PWM_Enable;
-extern unsigned int PWM_Out_R;
-extern unsigned int PWM_Out_L;*/
-
-//void PWM_Init(void);
-//void PWM_Recalc_Scale(void);
-
-/* Functions called by x86 asm. */
-//void PWM_Set_Cycle(unsigned int cycle);
-//void PWM_Set_Int(unsigned int int_time);
-
-/* Functions called by C/C++ code only. */
-//void PWM_Clear_Timer(void);
-//void PWM_Update_Timer(unsigned int cycle);
-//void PWM_Update(int **buf, int length);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void pwm_update(void *chip, stream_sample_t **outputs, int samples);
-
-void * device_start_pwm(int clock);
-void device_stop_pwm(void *chip);
-void device_reset_pwm(void *chip);
-
-void pwm_chn_w(void *chip, UINT8 Channel, UINT16 data);
-
-#ifdef __cplusplus
-}
-#endif
+/***************************************************************************
+ * Gens: PWM audio emulator. *
+ * *
+ * Copyright (c) 1999-2002 by Stphane Dallongeville *
+ * Copyright (c) 2003-2004 by Stphane Akhoun *
+ * Copyright (c) 2008 by David Korth *
+ * *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the *
+ * Free Software Foundation; either version 2 of the License, or (at your *
+ * option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#define PWM_BUF_SIZE 4
+
+#include "mamedef.h"
+
+/*extern unsigned char PWM_FULL_TAB[PWM_BUF_SIZE * PWM_BUF_SIZE];
+
+extern unsigned short PWM_FIFO_R[8];
+extern unsigned short PWM_FIFO_L[8];
+extern unsigned int PWM_RP_R;
+extern unsigned int PWM_WP_R;
+extern unsigned int PWM_RP_L;
+extern unsigned int PWM_WP_L;
+extern unsigned int PWM_Cycles;
+extern unsigned int PWM_Cycle;
+extern unsigned int PWM_Cycle_Cnt;
+extern unsigned int PWM_Int;
+extern unsigned int PWM_Int_Cnt;
+extern unsigned int PWM_Mode;
+extern unsigned int PWM_Enable;
+extern unsigned int PWM_Out_R;
+extern unsigned int PWM_Out_L;*/
+
+//void PWM_Init(void);
+//void PWM_Recalc_Scale(void);
+
+/* Functions called by x86 asm. */
+//void PWM_Set_Cycle(unsigned int cycle);
+//void PWM_Set_Int(unsigned int int_time);
+
+/* Functions called by C/C++ code only. */
+//void PWM_Clear_Timer(void);
+//void PWM_Update_Timer(unsigned int cycle);
+//void PWM_Update(int **buf, int length);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void pwm_update(void *chip, stream_sample_t **outputs, int samples);
+
+void * device_start_pwm(int clock);
+void device_stop_pwm(void *chip);
+void device_reset_pwm(void *chip);
+
+void pwm_chn_w(void *chip, UINT8 Channel, UINT16 data);
+
+#ifdef __cplusplus
+}
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/qmix.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/qmix.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/qmix.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/qmix.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,462 +1,462 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// qmix - QSound mixer
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#include "qmix.h"
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define ANTICLICK_TIME (64)
-#define ANTICLICK_THRESHHOLD (32)
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define RENDERMAX (200)
-
-/////////////////////////////////////////////////////////////////////////////
-
-static const sint32 gauss_shuffled_reverse_table[1024] = {
- 366,1305, 374, 0, 362,1304, 378, 0, 358,1304, 381, 0, 354,1304, 385, 0, 351,1304, 389, 0, 347,1304, 393, 0, 343,1303, 397, 0, 339,1303, 401, 0,
- 336,1303, 405, 0, 332,1302, 410, 0, 328,1302, 414, 0, 325,1301, 418, 0, 321,1300, 422, 0, 318,1300, 426, 0, 314,1299, 430, 0, 311,1298, 434, 0,
- 307,1297, 439, 1, 304,1297, 443, 1, 300,1296, 447, 1, 297,1295, 451, 1, 293,1294, 456, 1, 290,1293, 460, 1, 286,1292, 464, 1, 283,1291, 469, 1,
- 280,1290, 473, 1, 276,1288, 477, 1, 273,1287, 482, 1, 270,1286, 486, 2, 267,1284, 491, 2, 263,1283, 495, 2, 260,1282, 499, 2, 257,1280, 504, 2,
- 254,1279, 508, 2, 251,1277, 513, 2, 248,1275, 517, 3, 245,1274, 522, 3, 242,1272, 527, 3, 239,1270, 531, 3, 236,1269, 536, 3, 233,1267, 540, 4,
- 230,1265, 545, 4, 227,1263, 550, 4, 224,1261, 554, 4, 221,1259, 559, 4, 218,1257, 563, 5, 215,1255, 568, 5, 212,1253, 573, 5, 210,1251, 577, 5,
- 207,1248, 582, 6, 204,1246, 587, 6, 201,1244, 592, 6, 199,1241, 596, 6, 196,1239, 601, 7, 193,1237, 606, 7, 191,1234, 611, 7, 188,1232, 615, 8,
- 186,1229, 620, 8, 183,1227, 625, 8, 180,1224, 630, 9, 178,1221, 635, 9, 175,1219, 640, 9, 173,1216, 644, 10, 171,1213, 649, 10, 168,1210, 654, 10,
- 166,1207, 659, 11, 163,1205, 664, 11, 161,1202, 669, 11, 159,1199, 674, 12, 156,1196, 678, 12, 154,1193, 683, 13, 152,1190, 688, 13, 150,1186, 693, 14,
- 147,1183, 698, 14, 145,1180, 703, 15, 143,1177, 708, 15, 141,1174, 713, 15, 139,1170, 718, 16, 137,1167, 723, 16, 134,1164, 728, 17, 132,1160, 732, 17,
- 130,1157, 737, 18, 128,1153, 742, 19, 126,1150, 747, 19, 124,1146, 752, 20, 122,1143, 757, 20, 120,1139, 762, 21, 118,1136, 767, 21, 117,1132, 772, 22,
- 115,1128, 777, 23, 113,1125, 782, 23, 111,1121, 787, 24, 109,1117, 792, 24, 107,1113, 797, 25, 106,1109, 802, 26, 104,1106, 806, 27, 102,1102, 811, 27,
- 100,1098, 816, 28, 99,1094, 821, 29, 97,1090, 826, 29, 95,1086, 831, 30, 94,1082, 836, 31, 92,1078, 841, 32, 90,1074, 846, 32, 89,1070, 851, 33,
- 87,1066, 855, 34, 86,1061, 860, 35, 84,1057, 865, 36, 83,1053, 870, 36, 81,1049, 875, 37, 80,1045, 880, 38, 78,1040, 884, 39, 77,1036, 889, 40,
- 76,1032, 894, 41, 74,1027, 899, 42, 73,1023, 904, 43, 71,1019, 908, 44, 70,1014, 913, 45, 69,1010, 918, 46, 67,1005, 923, 47, 66,1001, 927, 48,
- 65, 997, 932, 49, 64, 992, 937, 50, 62, 988, 941, 51, 61, 983, 946, 52, 60, 978, 951, 53, 59, 974, 955, 54, 58, 969, 960, 55, 56, 965, 965, 56,
- 55, 960, 969, 58, 54, 955, 974, 59, 53, 951, 978, 60, 52, 946, 983, 61, 51, 941, 988, 62, 50, 937, 992, 64, 49, 932, 997, 65, 48, 927,1001, 66,
- 47, 923,1005, 67, 46, 918,1010, 69, 45, 913,1014, 70, 44, 908,1019, 71, 43, 904,1023, 73, 42, 899,1027, 74, 41, 894,1032, 76, 40, 889,1036, 77,
- 39, 884,1040, 78, 38, 880,1045, 80, 37, 875,1049, 81, 36, 870,1053, 83, 36, 865,1057, 84, 35, 860,1061, 86, 34, 855,1066, 87, 33, 851,1070, 89,
- 32, 846,1074, 90, 32, 841,1078, 92, 31, 836,1082, 94, 30, 831,1086, 95, 29, 826,1090, 97, 29, 821,1094, 99, 28, 816,1098, 100, 27, 811,1102, 102,
- 27, 806,1106, 104, 26, 802,1109, 106, 25, 797,1113, 107, 24, 792,1117, 109, 24, 787,1121, 111, 23, 782,1125, 113, 23, 777,1128, 115, 22, 772,1132, 117,
- 21, 767,1136, 118, 21, 762,1139, 120, 20, 757,1143, 122, 20, 752,1146, 124, 19, 747,1150, 126, 19, 742,1153, 128, 18, 737,1157, 130, 17, 732,1160, 132,
- 17, 728,1164, 134, 16, 723,1167, 137, 16, 718,1170, 139, 15, 713,1174, 141, 15, 708,1177, 143, 15, 703,1180, 145, 14, 698,1183, 147, 14, 693,1186, 150,
- 13, 688,1190, 152, 13, 683,1193, 154, 12, 678,1196, 156, 12, 674,1199, 159, 11, 669,1202, 161, 11, 664,1205, 163, 11, 659,1207, 166, 10, 654,1210, 168,
- 10, 649,1213, 171, 10, 644,1216, 173, 9, 640,1219, 175, 9, 635,1221, 178, 9, 630,1224, 180, 8, 625,1227, 183, 8, 620,1229, 186, 8, 615,1232, 188,
- 7, 611,1234, 191, 7, 606,1237, 193, 7, 601,1239, 196, 6, 596,1241, 199, 6, 592,1244, 201, 6, 587,1246, 204, 6, 582,1248, 207, 5, 577,1251, 210,
- 5, 573,1253, 212, 5, 568,1255, 215, 5, 563,1257, 218, 4, 559,1259, 221, 4, 554,1261, 224, 4, 550,1263, 227, 4, 545,1265, 230, 4, 540,1267, 233,
- 3, 536,1269, 236, 3, 531,1270, 239, 3, 527,1272, 242, 3, 522,1274, 245, 3, 517,1275, 248, 2, 513,1277, 251, 2, 508,1279, 254, 2, 504,1280, 257,
- 2, 499,1282, 260, 2, 495,1283, 263, 2, 491,1284, 267, 2, 486,1286, 270, 1, 482,1287, 273, 1, 477,1288, 276, 1, 473,1290, 280, 1, 469,1291, 283,
- 1, 464,1292, 286, 1, 460,1293, 290, 1, 456,1294, 293, 1, 451,1295, 297, 1, 447,1296, 300, 1, 443,1297, 304, 1, 439,1297, 307, 0, 434,1298, 311,
- 0, 430,1299, 314, 0, 426,1300, 318, 0, 422,1300, 321, 0, 418,1301, 325, 0, 414,1302, 328, 0, 410,1302, 332, 0, 405,1303, 336, 0, 401,1303, 339,
- 0, 397,1303, 343, 0, 393,1304, 347, 0, 389,1304, 351, 0, 385,1304, 354, 0, 381,1304, 358, 0, 378,1304, 362, 0, 374,1305, 366, 0, 370,1305, 370,
-};
-
-static const sint32 pan_table[33] = {
- 0, 724,1024,1254,1448,1619,1774,1916,
-2048,2172,2290,2401,2508,2611,2709,2804,
-2896,2985,3072,3156,3238,3318,3396,3473,
-3547,3620,3692,3762,3831,3899,3966,4031,
-4096};
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Static information
-//
-sint32 EMU_CALL _qmix_init(void) { return 0; }
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// State information
-//
-#define QMIXSTATE ((struct QMIX_STATE*)(state))
-
-struct QMIX_CHAN {
- uint32 on;
- uint32 startbank;
- uint32 startaddr;
- uint32 curbank;
- uint32 curaddr;
- uint32 startloop;
- uint32 startend;
- uint32 curloop;
- uint32 curend;
- uint32 phase;
- uint32 pitch;
- uint32 vol;
- uint32 pan;
- sint32 current_mix_l;
- sint32 current_mix_r;
- sint32 sample[4];
- sint32 sample_last_l;
- sint32 sample_last_r;
- sint32 sample_anticlick_l;
- sint32 sample_anticlick_r;
- sint32 sample_anticlick_remaining_l;
- sint32 sample_anticlick_remaining_r;
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-static EMU_INLINE void get_anticlicked_samples(
- struct QMIX_CHAN *chan, sint32 *l, sint32 *r
-) {
- sint32 out, remain;
- remain = chan->sample_anticlick_remaining_l;
- if(remain) {
- sint32 diff = chan->sample_last_l - chan->sample_anticlick_l;
- if(diff < 0) { diff = -diff; }
- if(diff < ANTICLICK_THRESHHOLD) {
- out = chan->sample_last_l;
- chan->sample_anticlick_remaining_l = 0;
- } else {
- out = (
- chan->sample_last_l * (ANTICLICK_TIME-remain) +
- chan->sample_anticlick_l * (remain)
- ) / ANTICLICK_TIME;
- chan->sample_anticlick_remaining_l--;
- }
- } else {
- out = chan->sample_last_l;
- }
- *l = out;
-
- remain = chan->sample_anticlick_remaining_r;
- if(remain) {
- sint32 diff = chan->sample_last_r - chan->sample_anticlick_r;
- if(diff < 0) { diff = -diff; }
- if(diff < ANTICLICK_THRESHHOLD) {
- out = chan->sample_last_r;
- chan->sample_anticlick_remaining_r = 0;
- } else {
- out = (
- chan->sample_last_r * (ANTICLICK_TIME-remain) +
- chan->sample_anticlick_r * (remain)
- ) / ANTICLICK_TIME;
- chan->sample_anticlick_remaining_r--;
- }
- } else {
- out = chan->sample_last_r;
- }
- *r = out;
-
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static EMU_INLINE void anticlick(struct QMIX_CHAN *chan) {
- sint32 l, r;
- get_anticlicked_samples(chan, &l, &r);
- chan->sample_anticlick_l = l;
- chan->sample_anticlick_r = r;
- chan->sample_anticlick_remaining_l = ANTICLICK_TIME;
- chan->sample_anticlick_remaining_r = ANTICLICK_TIME;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-struct QMIX_STATE {
- uint8 *sample_rom;
- uint32 sample_rom_size;
- uint32 pitchscaler;
- struct QMIX_CHAN chan[16];
- sint32 last_in_l;
- sint32 last_in_r;
- sint32 last_out_l;
- sint32 last_out_r;
- sint32 acc_l;
- sint32 acc_r;
-};
-
-uint32 EMU_CALL _qmix_get_state_size(void) {
- return sizeof(struct QMIX_STATE);
-}
-
-void EMU_CALL _qmix_clear_state(void *state) {
- memset(state, 0, sizeof(struct QMIX_STATE));
-
-
-}
-
-void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size) {
- QMIXSTATE->sample_rom = rom;
- QMIXSTATE->sample_rom_size = size;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static EMU_INLINE void chan_advance(
- struct QMIX_STATE *state,
- struct QMIX_CHAN *chan
-) {
- uint32 rom_addr = chan->curbank + chan->curaddr;
- if(rom_addr >= state->sample_rom_size) rom_addr = 0;
- chan->sample[0] = chan->sample[1];
- chan->sample[1] = chan->sample[2];
- chan->sample[2] = chan->sample[3];
- chan->sample[3] = (sint32)((sint8)(state->sample_rom[rom_addr]));
- chan->curaddr++;
-// FIXME: MAME thinks this is >=, but is it > ?
- if(chan->curaddr >= chan->curend) {
-// if(!chan->curloop) {
-// chan->on = 0;
-// chan->curaddr--;
-// } else {
- chan->curaddr = chan->curend - chan->curloop;
-// chan->curaddr -= 1 + chan->curloop;
-// }
- }
- chan->curaddr &= 0xFFFF;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static EMU_INLINE sint32 chan_get_resampled(
- struct QMIX_STATE *state,
- struct QMIX_CHAN *chan
-) {
- sint32 sum;
- sint32 phase = chan->phase & 0xFFF;
-
-// sum = chan->sample[2];
-// sum <<= 8;
-
- const sint32 *gauss = (sint32*)
- (((sint8*)gauss_shuffled_reverse_table) + (phase & 0x0FF0));
- sum = chan->sample[0] * gauss[0];
- sum += chan->sample[1] * gauss[1];
- sum += chan->sample[2] * gauss[2];
- sum += chan->sample[3] * gauss[3];
- sum /= 8;
-
-// sum = chan->sample[1] * (0x1000-phase);
-// sum += chan->sample[2] * ( phase);
-// sum >>= 4;
-
- chan->phase += chan->pitch;
- while(chan->phase >= 0x1000) {
- chan_advance(state, chan);
- chan->phase -= 0x1000;
- }
-
- return sum;
-}
-
-static EMU_INLINE void chan_get_stereo_anticlicked(
- struct QMIX_STATE *state,
- struct QMIX_CHAN *chan,
- sint32 *l,
- sint32 *r
-) {
- if(!chan->on) {
- chan->sample_last_l = 0;
- chan->sample_last_r = 0;
- } else {
- sint32 out = chan_get_resampled(state, chan);
- chan->sample_last_l = (out * chan->current_mix_l) / 0x8000;
- chan->sample_last_r = (out * chan->current_mix_r) / 0x8000;
- // if we suddenly keyed off, perform an anticlick here
- if(!chan->on) { anticlick(chan); }
- }
- get_anticlicked_samples(chan, l, r);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-static void recalc_mix(struct QMIX_CHAN *chan) {
- sint32 realpan = (chan->pan & 0x3F) - 0x10;
- sint32 realvol = chan->vol & 0xFFFF;
- if(realpan < 0x00) realpan = 0x00;
- if(realpan > 0x20) realpan = 0x20;
-
-// chan->current_mix_l = realvol << 3;
-// chan->current_mix_r = realvol << 3;
-// if(realpan < 0x10) {
-// chan->current_mix_r *= realpan;
-// chan->current_mix_r >>= 4;
-// }
-// if(realpan > 0x10) {
-// chan->current_mix_l *= (0x20-realpan);
-// chan->current_mix_l >>= 4;
-// }
-
-// chan->current_mix_l = ((0x20-realpan) * realvol) >> 1;
-// chan->current_mix_r = (( realpan) * realvol) >> 1;
-
- chan->current_mix_l = (realvol * pan_table[0x20-realpan]) / 0x2000;
- chan->current_mix_r = (realvol * pan_table[ realpan]) / 0x2000;
-
- // perform anticlick
- //anticlick(chan);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Command handling
-//
-//#include
-
-void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data) {
- struct QMIX_CHAN *chan;
- uint32 ch = 0;
- uint32 reg = 99;
-//printf("qmix command 0x%02X:0x%04X\n",cmd,data);
- if(cmd < 0x80) {
- reg = cmd & 7;
- ch = cmd >> 3;
- } else if(cmd < 0x90) {
- reg = 8;
- ch = cmd - 0x80;
- } else if(cmd >= 0xBA && cmd < 0xCA) {
- reg = 9;
- ch = cmd - 0xBA;
- } else {
- reg = 99;
- ch = 0;
- }
- chan = QMIXSTATE->chan + ch;
- switch(reg) {
- case 0: // bank
- ch = (ch+1) & 0xF; chan = QMIXSTATE->chan + ch;
- //printf("qmix: bank ch%X = %04X\n",ch,data);
- chan->startbank = (((uint32)data) & 0x7F) << 16;
- break;
- case 1: // start
- //printf("qmix: start ch%X = %04X\n",ch,data);
- chan->startaddr = ((uint32)data) & 0xFFFF;
- break;
- case 2: // pitch
- //printf("qmix: pitch ch%X = %04X\n",ch,data);
- chan->pitch = (((uint32)(data & 0xFFFF)) * QMIXSTATE->pitchscaler) / 0x10000;
- if (chan->pitch == 0) {
- chan->on = 0;
- anticlick(chan);
- }
- break;
- case 3: // unknown
- break;
- case 4: // loop start
- //printf("qmix: loop ch%X = %04X\n",ch,data);
- chan->startloop = data;
- break;
- case 5: // end
- //printf("qmix: end ch%X = %04X\n",ch,data);
- chan->startend = data;
- break;
- case 6: // volume
- //printf("qmix: vol ch%X = %04X\n",ch,data);
-//printf("volume=%04X\n",data);
-// if(!data) {
-// chan->on = 0;
-// } else {
-// chan->on = 1;
-// chan->address = chan->start;
-// chan->phase = 0;
-// }
- //printf("qmix: unknown reg3 ch%X = %04X\n",ch,data);
- if(data == 0) {
- chan->on = 0;
- anticlick(chan);
- } else if (chan->on == 0) {
- chan->on = 1;
- chan->curbank = chan->startbank;
- chan->curaddr = chan->startaddr;
- chan->curloop = chan->startloop;
- chan->curend = chan->startend;
- chan->phase = 0;
- chan->sample[0] = 0;
- chan->sample[1] = 0;
- chan->sample[2] = 0;
- chan->sample[3] = 0;
- anticlick(chan);
- }
-
- chan->vol = data;
- recalc_mix(chan);
- break;
- case 7: // unknown
- //printf("qmix: unknown reg7 ch%X = %04X\n",ch,data);
- break;
- case 8: // pan (0x110-0x130)
- //printf("qmix: pan ch%X = %04X\n",ch,data);
-//printf("pan=%04X\n",data);
- chan->pan = data;
- recalc_mix(chan);
- break;
- case 9: // ADSR?
- //printf("qmix: unknown reg9 ch%X = %04X\n",ch,data);
- break;
- default:
- //printf("qmix: unknown reg %02X = %04X\n",cmd,data);
- break;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Rendering
-//
-static void render(
- struct QMIX_STATE *state,
- sint16 *buf,
- uint32 samples
-) {
- sint32 buf_l[RENDERMAX];
- sint32 buf_r[RENDERMAX];
- sint32 l, r;
- uint32 s;
- int ch;
- memset(buf_l, 0, 4 * samples);
- memset(buf_r, 0, 4 * samples);
- for(ch = 0; ch < 16; ch++) {
- struct QMIX_CHAN *chan = state->chan + ch;
- for(s = 0; s < samples; s++) {
- chan_get_stereo_anticlicked(state, chan, &l, &r);
- buf_l[s] += l;
- buf_r[s] += r;
- }
- }
- if(!buf) return;
- for(s = 0; s < samples; s++) {
- sint32 diff_l = buf_l[s] - state->last_in_l;
- sint32 diff_r = buf_r[s] - state->last_in_r;
- state->last_in_l = buf_l[s];
- state->last_in_r = buf_r[s];
- l = ((state->last_out_l * 255) / 256) + diff_l;
- r = ((state->last_out_r * 255) / 256) + diff_r;
- state->last_out_l = l;
- state->last_out_r = r;
-// l /= 2;
-// r /= 2;
- l *= 8;
- r *= 8;
- if(l > ( 32767)) l = ( 32767);
- if(l < (-32768)) l = (-32768);
- if(r > ( 32767)) r = ( 32767);
- if(r < (-32768)) r = (-32768);
- *buf++ = l;
- *buf++ = r;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples) {
-//printf("qmix render %u samples\n",samples);
- for(; samples >= RENDERMAX; samples -= RENDERMAX) {
- render(QMIXSTATE, buf, RENDERMAX);
- if(buf) buf += 2 * RENDERMAX;
- }
- if(samples) {
- render(QMIXSTATE, buf, samples);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate) {
- if(rate < 1) rate = 1;
- QMIXSTATE->pitchscaler = (65536 * 24000) / rate;
-}
-
-/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+//
+// qmix - QSound mixer
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "qmix.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define ANTICLICK_TIME (64)
+#define ANTICLICK_THRESHHOLD (32)
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define RENDERMAX (200)
+
+/////////////////////////////////////////////////////////////////////////////
+
+static const sint32 gauss_shuffled_reverse_table[1024] = {
+ 366,1305, 374, 0, 362,1304, 378, 0, 358,1304, 381, 0, 354,1304, 385, 0, 351,1304, 389, 0, 347,1304, 393, 0, 343,1303, 397, 0, 339,1303, 401, 0,
+ 336,1303, 405, 0, 332,1302, 410, 0, 328,1302, 414, 0, 325,1301, 418, 0, 321,1300, 422, 0, 318,1300, 426, 0, 314,1299, 430, 0, 311,1298, 434, 0,
+ 307,1297, 439, 1, 304,1297, 443, 1, 300,1296, 447, 1, 297,1295, 451, 1, 293,1294, 456, 1, 290,1293, 460, 1, 286,1292, 464, 1, 283,1291, 469, 1,
+ 280,1290, 473, 1, 276,1288, 477, 1, 273,1287, 482, 1, 270,1286, 486, 2, 267,1284, 491, 2, 263,1283, 495, 2, 260,1282, 499, 2, 257,1280, 504, 2,
+ 254,1279, 508, 2, 251,1277, 513, 2, 248,1275, 517, 3, 245,1274, 522, 3, 242,1272, 527, 3, 239,1270, 531, 3, 236,1269, 536, 3, 233,1267, 540, 4,
+ 230,1265, 545, 4, 227,1263, 550, 4, 224,1261, 554, 4, 221,1259, 559, 4, 218,1257, 563, 5, 215,1255, 568, 5, 212,1253, 573, 5, 210,1251, 577, 5,
+ 207,1248, 582, 6, 204,1246, 587, 6, 201,1244, 592, 6, 199,1241, 596, 6, 196,1239, 601, 7, 193,1237, 606, 7, 191,1234, 611, 7, 188,1232, 615, 8,
+ 186,1229, 620, 8, 183,1227, 625, 8, 180,1224, 630, 9, 178,1221, 635, 9, 175,1219, 640, 9, 173,1216, 644, 10, 171,1213, 649, 10, 168,1210, 654, 10,
+ 166,1207, 659, 11, 163,1205, 664, 11, 161,1202, 669, 11, 159,1199, 674, 12, 156,1196, 678, 12, 154,1193, 683, 13, 152,1190, 688, 13, 150,1186, 693, 14,
+ 147,1183, 698, 14, 145,1180, 703, 15, 143,1177, 708, 15, 141,1174, 713, 15, 139,1170, 718, 16, 137,1167, 723, 16, 134,1164, 728, 17, 132,1160, 732, 17,
+ 130,1157, 737, 18, 128,1153, 742, 19, 126,1150, 747, 19, 124,1146, 752, 20, 122,1143, 757, 20, 120,1139, 762, 21, 118,1136, 767, 21, 117,1132, 772, 22,
+ 115,1128, 777, 23, 113,1125, 782, 23, 111,1121, 787, 24, 109,1117, 792, 24, 107,1113, 797, 25, 106,1109, 802, 26, 104,1106, 806, 27, 102,1102, 811, 27,
+ 100,1098, 816, 28, 99,1094, 821, 29, 97,1090, 826, 29, 95,1086, 831, 30, 94,1082, 836, 31, 92,1078, 841, 32, 90,1074, 846, 32, 89,1070, 851, 33,
+ 87,1066, 855, 34, 86,1061, 860, 35, 84,1057, 865, 36, 83,1053, 870, 36, 81,1049, 875, 37, 80,1045, 880, 38, 78,1040, 884, 39, 77,1036, 889, 40,
+ 76,1032, 894, 41, 74,1027, 899, 42, 73,1023, 904, 43, 71,1019, 908, 44, 70,1014, 913, 45, 69,1010, 918, 46, 67,1005, 923, 47, 66,1001, 927, 48,
+ 65, 997, 932, 49, 64, 992, 937, 50, 62, 988, 941, 51, 61, 983, 946, 52, 60, 978, 951, 53, 59, 974, 955, 54, 58, 969, 960, 55, 56, 965, 965, 56,
+ 55, 960, 969, 58, 54, 955, 974, 59, 53, 951, 978, 60, 52, 946, 983, 61, 51, 941, 988, 62, 50, 937, 992, 64, 49, 932, 997, 65, 48, 927,1001, 66,
+ 47, 923,1005, 67, 46, 918,1010, 69, 45, 913,1014, 70, 44, 908,1019, 71, 43, 904,1023, 73, 42, 899,1027, 74, 41, 894,1032, 76, 40, 889,1036, 77,
+ 39, 884,1040, 78, 38, 880,1045, 80, 37, 875,1049, 81, 36, 870,1053, 83, 36, 865,1057, 84, 35, 860,1061, 86, 34, 855,1066, 87, 33, 851,1070, 89,
+ 32, 846,1074, 90, 32, 841,1078, 92, 31, 836,1082, 94, 30, 831,1086, 95, 29, 826,1090, 97, 29, 821,1094, 99, 28, 816,1098, 100, 27, 811,1102, 102,
+ 27, 806,1106, 104, 26, 802,1109, 106, 25, 797,1113, 107, 24, 792,1117, 109, 24, 787,1121, 111, 23, 782,1125, 113, 23, 777,1128, 115, 22, 772,1132, 117,
+ 21, 767,1136, 118, 21, 762,1139, 120, 20, 757,1143, 122, 20, 752,1146, 124, 19, 747,1150, 126, 19, 742,1153, 128, 18, 737,1157, 130, 17, 732,1160, 132,
+ 17, 728,1164, 134, 16, 723,1167, 137, 16, 718,1170, 139, 15, 713,1174, 141, 15, 708,1177, 143, 15, 703,1180, 145, 14, 698,1183, 147, 14, 693,1186, 150,
+ 13, 688,1190, 152, 13, 683,1193, 154, 12, 678,1196, 156, 12, 674,1199, 159, 11, 669,1202, 161, 11, 664,1205, 163, 11, 659,1207, 166, 10, 654,1210, 168,
+ 10, 649,1213, 171, 10, 644,1216, 173, 9, 640,1219, 175, 9, 635,1221, 178, 9, 630,1224, 180, 8, 625,1227, 183, 8, 620,1229, 186, 8, 615,1232, 188,
+ 7, 611,1234, 191, 7, 606,1237, 193, 7, 601,1239, 196, 6, 596,1241, 199, 6, 592,1244, 201, 6, 587,1246, 204, 6, 582,1248, 207, 5, 577,1251, 210,
+ 5, 573,1253, 212, 5, 568,1255, 215, 5, 563,1257, 218, 4, 559,1259, 221, 4, 554,1261, 224, 4, 550,1263, 227, 4, 545,1265, 230, 4, 540,1267, 233,
+ 3, 536,1269, 236, 3, 531,1270, 239, 3, 527,1272, 242, 3, 522,1274, 245, 3, 517,1275, 248, 2, 513,1277, 251, 2, 508,1279, 254, 2, 504,1280, 257,
+ 2, 499,1282, 260, 2, 495,1283, 263, 2, 491,1284, 267, 2, 486,1286, 270, 1, 482,1287, 273, 1, 477,1288, 276, 1, 473,1290, 280, 1, 469,1291, 283,
+ 1, 464,1292, 286, 1, 460,1293, 290, 1, 456,1294, 293, 1, 451,1295, 297, 1, 447,1296, 300, 1, 443,1297, 304, 1, 439,1297, 307, 0, 434,1298, 311,
+ 0, 430,1299, 314, 0, 426,1300, 318, 0, 422,1300, 321, 0, 418,1301, 325, 0, 414,1302, 328, 0, 410,1302, 332, 0, 405,1303, 336, 0, 401,1303, 339,
+ 0, 397,1303, 343, 0, 393,1304, 347, 0, 389,1304, 351, 0, 385,1304, 354, 0, 381,1304, 358, 0, 378,1304, 362, 0, 374,1305, 366, 0, 370,1305, 370,
+};
+
+static const sint32 pan_table[33] = {
+ 0, 724,1024,1254,1448,1619,1774,1916,
+2048,2172,2290,2401,2508,2611,2709,2804,
+2896,2985,3072,3156,3238,3318,3396,3473,
+3547,3620,3692,3762,3831,3899,3966,4031,
+4096};
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Static information
+//
+sint32 EMU_CALL _qmix_init(void) { return 0; }
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// State information
+//
+#define QMIXSTATE ((struct QMIX_STATE*)(state))
+
+struct QMIX_CHAN {
+ uint32 on;
+ uint32 startbank;
+ uint32 startaddr;
+ uint32 curbank;
+ uint32 curaddr;
+ uint32 startloop;
+ uint32 startend;
+ uint32 curloop;
+ uint32 curend;
+ uint32 phase;
+ uint32 pitch;
+ uint32 vol;
+ uint32 pan;
+ sint32 current_mix_l;
+ sint32 current_mix_r;
+ sint32 sample[4];
+ sint32 sample_last_l;
+ sint32 sample_last_r;
+ sint32 sample_anticlick_l;
+ sint32 sample_anticlick_r;
+ sint32 sample_anticlick_remaining_l;
+ sint32 sample_anticlick_remaining_r;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+static EMU_INLINE void get_anticlicked_samples(
+ struct QMIX_CHAN *chan, sint32 *l, sint32 *r
+) {
+ sint32 out, remain;
+ remain = chan->sample_anticlick_remaining_l;
+ if(remain) {
+ sint32 diff = chan->sample_last_l - chan->sample_anticlick_l;
+ if(diff < 0) { diff = -diff; }
+ if(diff < ANTICLICK_THRESHHOLD) {
+ out = chan->sample_last_l;
+ chan->sample_anticlick_remaining_l = 0;
+ } else {
+ out = (
+ chan->sample_last_l * (ANTICLICK_TIME-remain) +
+ chan->sample_anticlick_l * (remain)
+ ) / ANTICLICK_TIME;
+ chan->sample_anticlick_remaining_l--;
+ }
+ } else {
+ out = chan->sample_last_l;
+ }
+ *l = out;
+
+ remain = chan->sample_anticlick_remaining_r;
+ if(remain) {
+ sint32 diff = chan->sample_last_r - chan->sample_anticlick_r;
+ if(diff < 0) { diff = -diff; }
+ if(diff < ANTICLICK_THRESHHOLD) {
+ out = chan->sample_last_r;
+ chan->sample_anticlick_remaining_r = 0;
+ } else {
+ out = (
+ chan->sample_last_r * (ANTICLICK_TIME-remain) +
+ chan->sample_anticlick_r * (remain)
+ ) / ANTICLICK_TIME;
+ chan->sample_anticlick_remaining_r--;
+ }
+ } else {
+ out = chan->sample_last_r;
+ }
+ *r = out;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static EMU_INLINE void anticlick(struct QMIX_CHAN *chan) {
+ sint32 l, r;
+ get_anticlicked_samples(chan, &l, &r);
+ chan->sample_anticlick_l = l;
+ chan->sample_anticlick_r = r;
+ chan->sample_anticlick_remaining_l = ANTICLICK_TIME;
+ chan->sample_anticlick_remaining_r = ANTICLICK_TIME;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+struct QMIX_STATE {
+ uint8 *sample_rom;
+ uint32 sample_rom_size;
+ uint32 pitchscaler;
+ struct QMIX_CHAN chan[16];
+ sint32 last_in_l;
+ sint32 last_in_r;
+ sint32 last_out_l;
+ sint32 last_out_r;
+ sint32 acc_l;
+ sint32 acc_r;
+};
+
+uint32 EMU_CALL _qmix_get_state_size(void) {
+ return sizeof(struct QMIX_STATE);
+}
+
+void EMU_CALL _qmix_clear_state(void *state) {
+ memset(state, 0, sizeof(struct QMIX_STATE));
+
+
+}
+
+void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size) {
+ QMIXSTATE->sample_rom = rom;
+ QMIXSTATE->sample_rom_size = size;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static EMU_INLINE void chan_advance(
+ struct QMIX_STATE *state,
+ struct QMIX_CHAN *chan
+) {
+ uint32 rom_addr = chan->curbank + chan->curaddr;
+ if(rom_addr >= state->sample_rom_size) rom_addr = 0;
+ chan->sample[0] = chan->sample[1];
+ chan->sample[1] = chan->sample[2];
+ chan->sample[2] = chan->sample[3];
+ chan->sample[3] = (sint32)((sint8)(state->sample_rom[rom_addr]));
+ chan->curaddr++;
+// FIXME: MAME thinks this is >=, but is it > ?
+ if(chan->curaddr >= chan->curend) {
+// if(!chan->curloop) {
+// chan->on = 0;
+// chan->curaddr--;
+// } else {
+ chan->curaddr = chan->curend - chan->curloop;
+// chan->curaddr -= 1 + chan->curloop;
+// }
+ }
+ chan->curaddr &= 0xFFFF;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static EMU_INLINE sint32 chan_get_resampled(
+ struct QMIX_STATE *state,
+ struct QMIX_CHAN *chan
+) {
+ sint32 sum;
+ sint32 phase = chan->phase & 0xFFF;
+
+// sum = chan->sample[2];
+// sum <<= 8;
+
+ const sint32 *gauss = (sint32*)
+ (((sint8*)gauss_shuffled_reverse_table) + (phase & 0x0FF0));
+ sum = chan->sample[0] * gauss[0];
+ sum += chan->sample[1] * gauss[1];
+ sum += chan->sample[2] * gauss[2];
+ sum += chan->sample[3] * gauss[3];
+ sum /= 8;
+
+// sum = chan->sample[1] * (0x1000-phase);
+// sum += chan->sample[2] * ( phase);
+// sum >>= 4;
+
+ chan->phase += chan->pitch;
+ while(chan->phase >= 0x1000) {
+ chan_advance(state, chan);
+ chan->phase -= 0x1000;
+ }
+
+ return sum;
+}
+
+static EMU_INLINE void chan_get_stereo_anticlicked(
+ struct QMIX_STATE *state,
+ struct QMIX_CHAN *chan,
+ sint32 *l,
+ sint32 *r
+) {
+ if(!chan->on) {
+ chan->sample_last_l = 0;
+ chan->sample_last_r = 0;
+ } else {
+ sint32 out = chan_get_resampled(state, chan);
+ chan->sample_last_l = (out * chan->current_mix_l) / 0x8000;
+ chan->sample_last_r = (out * chan->current_mix_r) / 0x8000;
+ // if we suddenly keyed off, perform an anticlick here
+ if(!chan->on) { anticlick(chan); }
+ }
+ get_anticlicked_samples(chan, l, r);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+static void recalc_mix(struct QMIX_CHAN *chan) {
+ sint32 realpan = (chan->pan & 0x3F) - 0x10;
+ sint32 realvol = chan->vol & 0xFFFF;
+ if(realpan < 0x00) realpan = 0x00;
+ if(realpan > 0x20) realpan = 0x20;
+
+// chan->current_mix_l = realvol << 3;
+// chan->current_mix_r = realvol << 3;
+// if(realpan < 0x10) {
+// chan->current_mix_r *= realpan;
+// chan->current_mix_r >>= 4;
+// }
+// if(realpan > 0x10) {
+// chan->current_mix_l *= (0x20-realpan);
+// chan->current_mix_l >>= 4;
+// }
+
+// chan->current_mix_l = ((0x20-realpan) * realvol) >> 1;
+// chan->current_mix_r = (( realpan) * realvol) >> 1;
+
+ chan->current_mix_l = (realvol * pan_table[0x20-realpan]) / 0x2000;
+ chan->current_mix_r = (realvol * pan_table[ realpan]) / 0x2000;
+
+ // perform anticlick
+ //anticlick(chan);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Command handling
+//
+//#include
+
+void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data) {
+ struct QMIX_CHAN *chan;
+ uint32 ch = 0;
+ uint32 reg = 99;
+//printf("qmix command 0x%02X:0x%04X\n",cmd,data);
+ if(cmd < 0x80) {
+ reg = cmd & 7;
+ ch = cmd >> 3;
+ } else if(cmd < 0x90) {
+ reg = 8;
+ ch = cmd - 0x80;
+ } else if(cmd >= 0xBA && cmd < 0xCA) {
+ reg = 9;
+ ch = cmd - 0xBA;
+ } else {
+ reg = 99;
+ ch = 0;
+ }
+ chan = QMIXSTATE->chan + ch;
+ switch(reg) {
+ case 0: // bank
+ ch = (ch+1) & 0xF; chan = QMIXSTATE->chan + ch;
+ //printf("qmix: bank ch%X = %04X\n",ch,data);
+ chan->startbank = (((uint32)data) & 0x7F) << 16;
+ break;
+ case 1: // start
+ //printf("qmix: start ch%X = %04X\n",ch,data);
+ chan->startaddr = ((uint32)data) & 0xFFFF;
+ break;
+ case 2: // pitch
+ //printf("qmix: pitch ch%X = %04X\n",ch,data);
+ chan->pitch = (((uint32)(data & 0xFFFF)) * QMIXSTATE->pitchscaler) / 0x10000;
+ if (chan->pitch == 0) {
+ chan->on = 0;
+ anticlick(chan);
+ }
+ break;
+ case 3: // unknown
+ break;
+ case 4: // loop start
+ //printf("qmix: loop ch%X = %04X\n",ch,data);
+ chan->startloop = data;
+ break;
+ case 5: // end
+ //printf("qmix: end ch%X = %04X\n",ch,data);
+ chan->startend = data;
+ break;
+ case 6: // volume
+ //printf("qmix: vol ch%X = %04X\n",ch,data);
+//printf("volume=%04X\n",data);
+// if(!data) {
+// chan->on = 0;
+// } else {
+// chan->on = 1;
+// chan->address = chan->start;
+// chan->phase = 0;
+// }
+ //printf("qmix: unknown reg3 ch%X = %04X\n",ch,data);
+ if(data == 0) {
+ chan->on = 0;
+ anticlick(chan);
+ } else if (chan->on == 0) {
+ chan->on = 1;
+ chan->curbank = chan->startbank;
+ chan->curaddr = chan->startaddr;
+ chan->curloop = chan->startloop;
+ chan->curend = chan->startend;
+ chan->phase = 0;
+ chan->sample[0] = 0;
+ chan->sample[1] = 0;
+ chan->sample[2] = 0;
+ chan->sample[3] = 0;
+ anticlick(chan);
+ }
+
+ chan->vol = data;
+ recalc_mix(chan);
+ break;
+ case 7: // unknown
+ //printf("qmix: unknown reg7 ch%X = %04X\n",ch,data);
+ break;
+ case 8: // pan (0x110-0x130)
+ //printf("qmix: pan ch%X = %04X\n",ch,data);
+//printf("pan=%04X\n",data);
+ chan->pan = data;
+ recalc_mix(chan);
+ break;
+ case 9: // ADSR?
+ //printf("qmix: unknown reg9 ch%X = %04X\n",ch,data);
+ break;
+ default:
+ //printf("qmix: unknown reg %02X = %04X\n",cmd,data);
+ break;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Rendering
+//
+static void render(
+ struct QMIX_STATE *state,
+ sint16 *buf,
+ uint32 samples
+) {
+ sint32 buf_l[RENDERMAX];
+ sint32 buf_r[RENDERMAX];
+ sint32 l, r;
+ uint32 s;
+ int ch;
+ memset(buf_l, 0, 4 * samples);
+ memset(buf_r, 0, 4 * samples);
+ for(ch = 0; ch < 16; ch++) {
+ struct QMIX_CHAN *chan = state->chan + ch;
+ for(s = 0; s < samples; s++) {
+ chan_get_stereo_anticlicked(state, chan, &l, &r);
+ buf_l[s] += l;
+ buf_r[s] += r;
+ }
+ }
+ if(!buf) return;
+ for(s = 0; s < samples; s++) {
+ sint32 diff_l = buf_l[s] - state->last_in_l;
+ sint32 diff_r = buf_r[s] - state->last_in_r;
+ state->last_in_l = buf_l[s];
+ state->last_in_r = buf_r[s];
+ l = ((state->last_out_l * 255) / 256) + diff_l;
+ r = ((state->last_out_r * 255) / 256) + diff_r;
+ state->last_out_l = l;
+ state->last_out_r = r;
+// l /= 2;
+// r /= 2;
+ l *= 8;
+ r *= 8;
+ if(l > ( 32767)) l = ( 32767);
+ if(l < (-32768)) l = (-32768);
+ if(r > ( 32767)) r = ( 32767);
+ if(r < (-32768)) r = (-32768);
+ *buf++ = l;
+ *buf++ = r;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples) {
+//printf("qmix render %u samples\n",samples);
+ for(; samples >= RENDERMAX; samples -= RENDERMAX) {
+ render(QMIXSTATE, buf, RENDERMAX);
+ if(buf) buf += 2 * RENDERMAX;
+ }
+ if(samples) {
+ render(QMIXSTATE, buf, samples);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate) {
+ if(rate < 1) rate = 1;
+ QMIXSTATE->pitchscaler = (65536 * 24000) / rate;
+}
+
+/////////////////////////////////////////////////////////////////////////////
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/qmix.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/qmix.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/qmix.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/qmix.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,29 +1,29 @@
-/////////////////////////////////////////////////////////////////////////////
-//
-// qmix - QSound mixer
-//
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef __Q_QMIX_H__
-#define __Q_QMIX_H__
-
-#include "emuconfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-sint32 EMU_CALL _qmix_init(void);
-uint32 EMU_CALL _qmix_get_state_size(void);
-void EMU_CALL _qmix_clear_state(void *state);
-
-void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate);
-void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size);
-void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data);
-void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/////////////////////////////////////////////////////////////////////////////
+//
+// qmix - QSound mixer
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __Q_QMIX_H__
+#define __Q_QMIX_H__
+
+#include "emuconfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+sint32 EMU_CALL _qmix_init(void);
+uint32 EMU_CALL _qmix_get_state_size(void);
+void EMU_CALL _qmix_clear_state(void *state);
+
+void EMU_CALL _qmix_set_sample_rate(void *state, uint32 rate);
+void EMU_CALL _qmix_set_sample_rom(void *state, void *rom, uint32 size);
+void EMU_CALL _qmix_command(void *state, uint8 cmd, uint16 data);
+void EMU_CALL _qmix_render(void *state, sint16 *buf, uint32 samples);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,82 +1,82 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Rf5C164_Emu.h"
-#include "scd_pcm.h"
-
-Rf5C164_Emu::Rf5C164_Emu() { chip = 0; }
-
-Rf5C164_Emu::~Rf5C164_Emu()
-{
- if ( chip ) device_stop_rf5c164( chip );
-}
-
-int Rf5C164_Emu::set_rate( int clock )
-{
- if ( chip )
- {
- device_stop_rf5c164( chip );
- chip = 0;
- }
-
- chip = device_start_rf5c164( clock );
- if ( !chip )
- return 1;
-
- reset();
- return 0;
-}
-
-void Rf5C164_Emu::reset()
-{
- device_reset_rf5c164( chip );
- rf5c164_set_mute_mask( chip, 0 );
-}
-
-void Rf5C164_Emu::write( int addr, int data )
-{
- rf5c164_w( chip, addr, data );
-}
-
-void Rf5C164_Emu::write_mem( int addr, int data )
-{
- rf5c164_mem_w( chip, addr, data );
-}
-
-void Rf5C164_Emu::write_ram( int start, int length, void * data )
-{
- rf5c164_write_ram( chip, start, length, (const UINT8 *) data );
-}
-
-void Rf5C164_Emu::mute_voices( int mask )
-{
- rf5c164_set_mute_mask( chip, mask );
-}
-
-void Rf5C164_Emu::run( int pair_count, sample_t* out )
-{
- stream_sample_t bufL[ 1024 ];
- stream_sample_t bufR[ 1024 ];
- stream_sample_t * buffers[2] = { bufL, bufR };
-
- while (pair_count > 0)
- {
- int todo = pair_count;
- if (todo > 1024) todo = 1024;
- rf5c164_update( chip, buffers, todo );
-
- for (int i = 0; i < todo; i++)
- {
- int output_l = bufL [i];
- int output_r = bufR [i];
- output_l += out [0];
- output_r += out [1];
- if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
- if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
- out [0] = output_l;
- out [1] = output_r;
- out += 2;
- }
-
- pair_count -= todo;
- }
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Rf5C164_Emu.h"
+#include "scd_pcm.h"
+
+Rf5C164_Emu::Rf5C164_Emu() { chip = 0; }
+
+Rf5C164_Emu::~Rf5C164_Emu()
+{
+ if ( chip ) device_stop_rf5c164( chip );
+}
+
+int Rf5C164_Emu::set_rate( int clock )
+{
+ if ( chip )
+ {
+ device_stop_rf5c164( chip );
+ chip = 0;
+ }
+
+ chip = device_start_rf5c164( clock );
+ if ( !chip )
+ return 1;
+
+ reset();
+ return 0;
+}
+
+void Rf5C164_Emu::reset()
+{
+ device_reset_rf5c164( chip );
+ rf5c164_set_mute_mask( chip, 0 );
+}
+
+void Rf5C164_Emu::write( int addr, int data )
+{
+ rf5c164_w( chip, addr, data );
+}
+
+void Rf5C164_Emu::write_mem( int addr, int data )
+{
+ rf5c164_mem_w( chip, addr, data );
+}
+
+void Rf5C164_Emu::write_ram( int start, int length, void * data )
+{
+ rf5c164_write_ram( chip, start, length, (const UINT8 *) data );
+}
+
+void Rf5C164_Emu::mute_voices( int mask )
+{
+ rf5c164_set_mute_mask( chip, mask );
+}
+
+void Rf5C164_Emu::run( int pair_count, sample_t* out )
+{
+ stream_sample_t bufL[ 1024 ];
+ stream_sample_t bufR[ 1024 ];
+ stream_sample_t * buffers[2] = { bufL, bufR };
+
+ while (pair_count > 0)
+ {
+ int todo = pair_count;
+ if (todo > 1024) todo = 1024;
+ rf5c164_update( chip, buffers, todo );
+
+ for (int i = 0; i < todo; i++)
+ {
+ int output_l = bufL [i];
+ int output_r = bufR [i];
+ output_l += out [0];
+ output_r += out [1];
+ if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
+ if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
+ out [0] = output_l;
+ out [1] = output_r;
+ out += 2;
+ }
+
+ pair_count -= todo;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C164_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,39 +1,39 @@
-// RF5C164 sound chip emulator interface
-
-// Game_Music_Emu $vers
-#ifndef RF5C164_EMU_H
-#define RF5C164_EMU_H
-
-class Rf5C164_Emu {
- void* chip;
-public:
- Rf5C164_Emu();
- ~Rf5C164_Emu();
-
- // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( int clock );
-
- // Resets to power-up state
- void reset();
-
- // Mutes voice n if bit n (1 << n) of mask is set
- enum { channel_count = 8 };
- void mute_voices( int mask );
-
- // Writes data to addr
- void write( int addr, int data );
-
- // Writes to memory
- void write_mem( int addr, int data );
-
- // Writes length bytes from data at start offset in RAM
- void write_ram( int start, int length, void * data );
-
- // Runs and writes pair_count*2 samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
+// RF5C164 sound chip emulator interface
+
+// Game_Music_Emu $vers
+#ifndef RF5C164_EMU_H
+#define RF5C164_EMU_H
+
+class Rf5C164_Emu {
+ void* chip;
+public:
+ Rf5C164_Emu();
+ ~Rf5C164_Emu();
+
+ // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+ // if error.
+ int set_rate( int clock );
+
+ // Resets to power-up state
+ void reset();
+
+ // Mutes voice n if bit n (1 << n) of mask is set
+ enum { channel_count = 8 };
+ void mute_voices( int mask );
+
+ // Writes data to addr
+ void write( int addr, int data );
+
+ // Writes to memory
+ void write_mem( int addr, int data );
+
+ // Writes length bytes from data at start offset in RAM
+ void write_ram( int start, int length, void * data );
+
+ // Runs and writes pair_count*2 samples to output
+ typedef short sample_t;
+ enum { out_chan_count = 2 }; // stereo
+ void run( int pair_count, sample_t* out );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/rf5c68.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/rf5c68.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/rf5c68.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/rf5c68.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,448 +1,448 @@
-/*********************************************************/
-/* ricoh RF5C68(or clone) PCM controller */
-/*********************************************************/
-
-#include
-#include
-//#include "sndintrf.h"
-//#include "streams.h"
-#include "rf5c68.h"
-#include
-
-#undef NULL
-#define NULL ((void *)0)
-
-
-#define NUM_CHANNELS (8)
-#define WRITES_PER_SAMPLE 12
-
-
-
-typedef struct _pcm_channel pcm_channel;
-struct _pcm_channel
-{
- UINT8 enable;
- UINT8 env;
- UINT8 pan;
- UINT8 start;
- UINT32 addr;
- UINT16 step;
- UINT16 loopst;
- UINT8 Muted;
-};
-
-typedef struct _mem_stream mem_stream;
-struct _mem_stream
-{
- UINT32 BaseAddr;
- UINT32 EndAddr;
- UINT32 CurAddr;
- const UINT8* MemPnt;
-};
-
-
-typedef struct _rf5c68_state rf5c68_state;
-struct _rf5c68_state
-{
- //sound_stream * stream;
- pcm_channel chan[NUM_CHANNELS];
- UINT8 cbank;
- UINT8 wbank;
- UINT8 enable;
- UINT32 datasize;
- UINT8* data;
- //void (*sample_callback)(running_device* device,int channel);
- mem_stream memstrm;
-};
-
-
-static void rf5c68_mem_stream_flush(rf5c68_state *chip);
-
-/*INLINE rf5c68_state *get_safe_token(const device_config *device)
-{
- assert(device != NULL);
- assert(device->token != NULL);
- assert(device->type == SOUND);
- assert(sound_get_type(device) == SOUND_RF5C68);
- return (rf5c68_state *)device->token;
-}*/
-
-/************************************************/
-/* RF5C68 stream update */
-/************************************************/
-
-static void memstream_sample_check(rf5c68_state *chip, UINT32 addr)
-{
- mem_stream* ms = &chip->memstrm;
-
- if (addr >= ms->CurAddr)
- {
- if (addr - ms->CurAddr <= WRITES_PER_SAMPLE * 5)
- {
- ms->CurAddr -= WRITES_PER_SAMPLE * 2;
- if (ms->CurAddr < ms->BaseAddr)
- ms->CurAddr = ms->BaseAddr;
- }
- }
- else
- {
- if (ms->CurAddr - addr <= WRITES_PER_SAMPLE * 4)
- {
- rf5c68_mem_stream_flush(chip);
- }
- }
-
- return;
-}
-
-//static STREAM_UPDATE( rf5c68_update )
-void rf5c68_update(void *_chip, stream_sample_t **outputs, int samples)
-{
- //rf5c68_state *chip = (rf5c68_state *)param;
- rf5c68_state *chip = (rf5c68_state *) _chip;
- mem_stream* ms = &chip->memstrm;
- stream_sample_t *left = outputs[0];
- stream_sample_t *right = outputs[1];
- int i, j;
-
- /* start with clean buffers */
- memset(left, 0, samples * sizeof(*left));
- memset(right, 0, samples * sizeof(*right));
-
- /* bail if not enabled */
- if (!chip->enable)
- return;
-
- /* loop over channels */
- for (i = 0; i < NUM_CHANNELS; i++)
- {
- pcm_channel *chan = &chip->chan[i];
-
- /* if this channel is active, accumulate samples */
- if (chan->enable && ! chan->Muted)
- {
- int lv = (chan->pan & 0x0f) * chan->env;
- int rv = ((chan->pan >> 4) & 0x0f) * chan->env;
-
- /* loop over the sample buffer */
- for (j = 0; j < samples; j++)
- {
- int sample;
-
- /* trigger sample callback */
- /*if(chip->sample_callback)
- {
- if(((chan->addr >> 11) & 0xfff) == 0xfff)
- chip->sample_callback(chip->device,((chan->addr >> 11)/0x2000));
- }*/
-
- memstream_sample_check(chip, (chan->addr >> 11) & 0xffff);
- /* fetch the sample and handle looping */
- sample = chip->data[(chan->addr >> 11) & 0xffff];
- if (sample == 0xff)
- {
- chan->addr = chan->loopst << 11;
- sample = chip->data[(chan->addr >> 11) & 0xffff];
-
- /* if we loop to a loop point, we're effectively dead */
- if (sample == 0xff)
- break;
- }
- chan->addr += chan->step;
-
- /* add to the buffer */
- if (sample & 0x80)
- {
- sample &= 0x7f;
- left[j] += (sample * lv) >> 5;
- right[j] += (sample * rv) >> 5;
- }
- else
- {
- left[j] -= (sample * lv) >> 5;
- right[j] -= (sample * rv) >> 5;
- }
- }
- }
- }
-
- if (samples && ms->CurAddr < ms->EndAddr)
- {
- i = WRITES_PER_SAMPLE * samples;
- if (ms->CurAddr + i > ms->EndAddr)
- i = ms->EndAddr - ms->CurAddr;
-
- memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), i);
- ms->CurAddr += i;
- }
-
- // I think, this is completely useless
- /* now clamp and shift the result (output is only 10 bits) */
- /*for (j = 0; j < samples; j++)
- {
- stream_sample_t temp;
-
- temp = left[j];
- if (temp > 32767) temp = 32767;
- else if (temp < -32768) temp = -32768;
- left[j] = temp & ~0x3f;
-
- temp = right[j];
- if (temp > 32767) temp = 32767;
- else if (temp < -32768) temp = -32768;
- right[j] = temp & ~0x3f;
- }*/
-}
-
-
-/************************************************/
-/* RF5C68 start */
-/************************************************/
-
-//static DEVICE_START( rf5c68 )
-void * device_start_rf5c68()
-{
- //const rf5c68_interface* intf = (const rf5c68_interface*)device->baseconfig().static_config();
-
- /* allocate memory for the chip */
- //rf5c68_state *chip = get_safe_token(device);
- rf5c68_state *chip;
- int chn;
-
- chip = (rf5c68_state *) malloc(sizeof(rf5c68_state));
- if (!chip) return chip;
-
- chip->datasize = 0x10000;
- chip->data = (UINT8*)malloc(chip->datasize);
-
- /* allocate the stream */
- //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
-
- /* set up callback */
- /*if(intf != NULL)
- chip->sample_callback = intf->sample_end_callback;
- else
- chip->sample_callback = NULL;*/
- for (chn = 0; chn < NUM_CHANNELS; chn ++)
- chip->chan[chn].Muted = 0x00;
-
- return chip;
-}
-
-void device_stop_rf5c68(void *_chip)
-{
- rf5c68_state *chip = (rf5c68_state *) _chip;
- free(chip->data); chip->data = NULL;
- free(chip);
-}
-
-void device_reset_rf5c68(void *_chip)
-{
- rf5c68_state *chip = (rf5c68_state *) _chip;
- int i;
- pcm_channel* chan;
- mem_stream* ms = &chip->memstrm;
-
- // Clear the PCM memory.
- memset(chip->data, 0x00, chip->datasize);
-
- chip->enable = 0;
- chip->cbank = 0;
- chip->wbank = 0;
-
- /* clear channel registers */
- for (i = 0; i < NUM_CHANNELS; i ++)
- {
- chan = &chip->chan[i];
- chan->enable = 0;
- chan->env = 0;
- chan->pan = 0;
- chan->start = 0;
- chan->addr = 0;
- chan->step = 0;
- chan->loopst = 0;
- }
-
- ms->BaseAddr = 0x0000;
- ms->CurAddr = 0x0000;
- ms->EndAddr = 0x0000;
- ms->MemPnt = NULL;
-}
-
-/************************************************/
-/* RF5C68 write register */
-/************************************************/
-
-//WRITE8_DEVICE_HANDLER( rf5c68_w )
-void rf5c68_w(void *_chip, offs_t offset, UINT8 data)
-{
- //rf5c68_state *chip = get_safe_token(device);
- rf5c68_state *chip = (rf5c68_state *) _chip;
- pcm_channel *chan = &chip->chan[chip->cbank];
- int i;
-
- /* force the stream to update first */
- //stream_update(chip->stream);
-
- /* switch off the address */
- switch (offset)
- {
- case 0x00: /* envelope */
- chan->env = data;
- break;
-
- case 0x01: /* pan */
- chan->pan = data;
- break;
-
- case 0x02: /* FDL */
- chan->step = (chan->step & 0xff00) | (data & 0x00ff);
- break;
-
- case 0x03: /* FDH */
- chan->step = (chan->step & 0x00ff) | ((data << 8) & 0xff00);
- break;
-
- case 0x04: /* LSL */
- chan->loopst = (chan->loopst & 0xff00) | (data & 0x00ff);
- break;
-
- case 0x05: /* LSH */
- chan->loopst = (chan->loopst & 0x00ff) | ((data << 8) & 0xff00);
- break;
-
- case 0x06: /* ST */
- chan->start = data;
- if (!chan->enable)
- chan->addr = chan->start << (8 + 11);
- break;
-
- case 0x07: /* control reg */
- chip->enable = (data >> 7) & 1;
- if (data & 0x40)
- chip->cbank = data & 7;
- else
- chip->wbank = data & 15;
- break;
-
- case 0x08: /* channel on/off reg */
- for (i = 0; i < 8; i++)
- {
- chip->chan[i].enable = (~data >> i) & 1;
- if (!chip->chan[i].enable)
- chip->chan[i].addr = chip->chan[i].start << (8 + 11);
- }
- break;
- }
-}
-
-
-/************************************************/
-/* RF5C68 read memory */
-/************************************************/
-
-//READ8_DEVICE_HANDLER( rf5c68_mem_r )
-UINT8 rf5c68_mem_r(void *_chip, offs_t offset)
-{
- //rf5c68_state *chip = get_safe_token(device);
- rf5c68_state *chip = (rf5c68_state *) _chip;
- return chip->data[chip->wbank * 0x1000 + offset];
-}
-
-
-/************************************************/
-/* RF5C68 write memory */
-/************************************************/
-
-//WRITE8_DEVICE_HANDLER( rf5c68_mem_w )
-void rf5c68_mem_w(void *_chip, offs_t offset, UINT8 data)
-{
- //rf5c68_state *chip = get_safe_token(device);
- rf5c68_state *chip = (rf5c68_state *) _chip;
- rf5c68_mem_stream_flush(chip);
- chip->data[chip->wbank * 0x1000 | offset] = data;
-}
-
-static void rf5c68_mem_stream_flush(rf5c68_state *chip)
-{
- mem_stream* ms = &chip->memstrm;
-
- if (ms->CurAddr >= ms->EndAddr)
- return;
-
- memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), ms->EndAddr - ms->CurAddr);
- ms->CurAddr = ms->EndAddr;
-
- return;
-}
-
-void rf5c68_write_ram(void *_chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)
-{
- rf5c68_state *chip = (rf5c68_state *) _chip;
- mem_stream* ms = &chip->memstrm;
- UINT16 BytCnt;
-
- if (DataStart >= chip->datasize)
- return;
- if (DataStart + DataLength > chip->datasize)
- DataLength = chip->datasize - DataStart;
-
- //memcpy(chip->data + (chip->wbank * 0x1000 | DataStart), RAMData, DataLength);
-
- rf5c68_mem_stream_flush(chip);
-
- ms->BaseAddr = chip->wbank * 0x1000 | DataStart;
- ms->CurAddr = ms->BaseAddr;
- ms->EndAddr = ms->BaseAddr + DataLength;
- ms->MemPnt = RAMData;
-
- BytCnt = WRITES_PER_SAMPLE;
- if (ms->CurAddr + BytCnt > ms->EndAddr)
- BytCnt = ms->EndAddr - ms->CurAddr;
-
- memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), BytCnt);
- ms->CurAddr += BytCnt;
-
- return;
-}
-
-
-void rf5c68_set_mute_mask(void *_chip, UINT32 MuteMask)
-{
- rf5c68_state *chip = (rf5c68_state *) _chip;
- unsigned char CurChn;
-
- for (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++)
- chip->chan[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
-
- return;
-}
-
-
-
-/**************************************************************************
- * Generic get_info
- **************************************************************************/
-
-/*DEVICE_GET_INFO( rf5c68 )
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers ---
- case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(rf5c68_state); break;
-
- // --- the following bits of info are returned as pointers to data or functions ---
- case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( rf5c68 ); break;
- case DEVINFO_FCT_STOP: // Nothing break;
- case DEVINFO_FCT_RESET: // Nothing break;
-
- // --- the following bits of info are returned as NULL-terminated strings ---
- case DEVINFO_STR_NAME: strcpy(info->s, "RF5C68"); break;
- case DEVINFO_STR_FAMILY: strcpy(info->s, "Ricoh PCM"); break;
- case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
- case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
- case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
- }
-}*/
-
-/**************** end of file ****************/
+/*********************************************************/
+/* ricoh RF5C68(or clone) PCM controller */
+/*********************************************************/
+
+#include
+#include
+//#include "sndintrf.h"
+//#include "streams.h"
+#include "rf5c68.h"
+#include
+
+#undef NULL
+#define NULL ((void *)0)
+
+
+#define NUM_CHANNELS (8)
+#define WRITES_PER_SAMPLE 12
+
+
+
+typedef struct _pcm_channel pcm_channel;
+struct _pcm_channel
+{
+ UINT8 enable;
+ UINT8 env;
+ UINT8 pan;
+ UINT8 start;
+ UINT32 addr;
+ UINT16 step;
+ UINT16 loopst;
+ UINT8 Muted;
+};
+
+typedef struct _mem_stream mem_stream;
+struct _mem_stream
+{
+ UINT32 BaseAddr;
+ UINT32 EndAddr;
+ UINT32 CurAddr;
+ const UINT8* MemPnt;
+};
+
+
+typedef struct _rf5c68_state rf5c68_state;
+struct _rf5c68_state
+{
+ //sound_stream * stream;
+ pcm_channel chan[NUM_CHANNELS];
+ UINT8 cbank;
+ UINT8 wbank;
+ UINT8 enable;
+ UINT32 datasize;
+ UINT8* data;
+ //void (*sample_callback)(running_device* device,int channel);
+ mem_stream memstrm;
+};
+
+
+static void rf5c68_mem_stream_flush(rf5c68_state *chip);
+
+/*INLINE rf5c68_state *get_safe_token(const device_config *device)
+{
+ assert(device != NULL);
+ assert(device->token != NULL);
+ assert(device->type == SOUND);
+ assert(sound_get_type(device) == SOUND_RF5C68);
+ return (rf5c68_state *)device->token;
+}*/
+
+/************************************************/
+/* RF5C68 stream update */
+/************************************************/
+
+static void memstream_sample_check(rf5c68_state *chip, UINT32 addr)
+{
+ mem_stream* ms = &chip->memstrm;
+
+ if (addr >= ms->CurAddr)
+ {
+ if (addr - ms->CurAddr <= WRITES_PER_SAMPLE * 5)
+ {
+ ms->CurAddr -= WRITES_PER_SAMPLE * 2;
+ if (ms->CurAddr < ms->BaseAddr)
+ ms->CurAddr = ms->BaseAddr;
+ }
+ }
+ else
+ {
+ if (ms->CurAddr - addr <= WRITES_PER_SAMPLE * 4)
+ {
+ rf5c68_mem_stream_flush(chip);
+ }
+ }
+
+ return;
+}
+
+//static STREAM_UPDATE( rf5c68_update )
+void rf5c68_update(void *_chip, stream_sample_t **outputs, int samples)
+{
+ //rf5c68_state *chip = (rf5c68_state *)param;
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ mem_stream* ms = &chip->memstrm;
+ stream_sample_t *left = outputs[0];
+ stream_sample_t *right = outputs[1];
+ int i, j;
+
+ /* start with clean buffers */
+ memset(left, 0, samples * sizeof(*left));
+ memset(right, 0, samples * sizeof(*right));
+
+ /* bail if not enabled */
+ if (!chip->enable)
+ return;
+
+ /* loop over channels */
+ for (i = 0; i < NUM_CHANNELS; i++)
+ {
+ pcm_channel *chan = &chip->chan[i];
+
+ /* if this channel is active, accumulate samples */
+ if (chan->enable && ! chan->Muted)
+ {
+ int lv = (chan->pan & 0x0f) * chan->env;
+ int rv = ((chan->pan >> 4) & 0x0f) * chan->env;
+
+ /* loop over the sample buffer */
+ for (j = 0; j < samples; j++)
+ {
+ int sample;
+
+ /* trigger sample callback */
+ /*if(chip->sample_callback)
+ {
+ if(((chan->addr >> 11) & 0xfff) == 0xfff)
+ chip->sample_callback(chip->device,((chan->addr >> 11)/0x2000));
+ }*/
+
+ memstream_sample_check(chip, (chan->addr >> 11) & 0xffff);
+ /* fetch the sample and handle looping */
+ sample = chip->data[(chan->addr >> 11) & 0xffff];
+ if (sample == 0xff)
+ {
+ chan->addr = chan->loopst << 11;
+ sample = chip->data[(chan->addr >> 11) & 0xffff];
+
+ /* if we loop to a loop point, we're effectively dead */
+ if (sample == 0xff)
+ break;
+ }
+ chan->addr += chan->step;
+
+ /* add to the buffer */
+ if (sample & 0x80)
+ {
+ sample &= 0x7f;
+ left[j] += (sample * lv) >> 5;
+ right[j] += (sample * rv) >> 5;
+ }
+ else
+ {
+ left[j] -= (sample * lv) >> 5;
+ right[j] -= (sample * rv) >> 5;
+ }
+ }
+ }
+ }
+
+ if (samples && ms->CurAddr < ms->EndAddr)
+ {
+ i = WRITES_PER_SAMPLE * samples;
+ if (ms->CurAddr + i > ms->EndAddr)
+ i = ms->EndAddr - ms->CurAddr;
+
+ memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), i);
+ ms->CurAddr += i;
+ }
+
+ // I think, this is completely useless
+ /* now clamp and shift the result (output is only 10 bits) */
+ /*for (j = 0; j < samples; j++)
+ {
+ stream_sample_t temp;
+
+ temp = left[j];
+ if (temp > 32767) temp = 32767;
+ else if (temp < -32768) temp = -32768;
+ left[j] = temp & ~0x3f;
+
+ temp = right[j];
+ if (temp > 32767) temp = 32767;
+ else if (temp < -32768) temp = -32768;
+ right[j] = temp & ~0x3f;
+ }*/
+}
+
+
+/************************************************/
+/* RF5C68 start */
+/************************************************/
+
+//static DEVICE_START( rf5c68 )
+void * device_start_rf5c68()
+{
+ //const rf5c68_interface* intf = (const rf5c68_interface*)device->baseconfig().static_config();
+
+ /* allocate memory for the chip */
+ //rf5c68_state *chip = get_safe_token(device);
+ rf5c68_state *chip;
+ int chn;
+
+ chip = (rf5c68_state *) malloc(sizeof(rf5c68_state));
+ if (!chip) return chip;
+
+ chip->datasize = 0x10000;
+ chip->data = (UINT8*)malloc(chip->datasize);
+
+ /* allocate the stream */
+ //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
+
+ /* set up callback */
+ /*if(intf != NULL)
+ chip->sample_callback = intf->sample_end_callback;
+ else
+ chip->sample_callback = NULL;*/
+ for (chn = 0; chn < NUM_CHANNELS; chn ++)
+ chip->chan[chn].Muted = 0x00;
+
+ return chip;
+}
+
+void device_stop_rf5c68(void *_chip)
+{
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ free(chip->data); chip->data = NULL;
+ free(chip);
+}
+
+void device_reset_rf5c68(void *_chip)
+{
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ int i;
+ pcm_channel* chan;
+ mem_stream* ms = &chip->memstrm;
+
+ // Clear the PCM memory.
+ memset(chip->data, 0x00, chip->datasize);
+
+ chip->enable = 0;
+ chip->cbank = 0;
+ chip->wbank = 0;
+
+ /* clear channel registers */
+ for (i = 0; i < NUM_CHANNELS; i ++)
+ {
+ chan = &chip->chan[i];
+ chan->enable = 0;
+ chan->env = 0;
+ chan->pan = 0;
+ chan->start = 0;
+ chan->addr = 0;
+ chan->step = 0;
+ chan->loopst = 0;
+ }
+
+ ms->BaseAddr = 0x0000;
+ ms->CurAddr = 0x0000;
+ ms->EndAddr = 0x0000;
+ ms->MemPnt = NULL;
+}
+
+/************************************************/
+/* RF5C68 write register */
+/************************************************/
+
+//WRITE8_DEVICE_HANDLER( rf5c68_w )
+void rf5c68_w(void *_chip, offs_t offset, UINT8 data)
+{
+ //rf5c68_state *chip = get_safe_token(device);
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ pcm_channel *chan = &chip->chan[chip->cbank];
+ int i;
+
+ /* force the stream to update first */
+ //stream_update(chip->stream);
+
+ /* switch off the address */
+ switch (offset)
+ {
+ case 0x00: /* envelope */
+ chan->env = data;
+ break;
+
+ case 0x01: /* pan */
+ chan->pan = data;
+ break;
+
+ case 0x02: /* FDL */
+ chan->step = (chan->step & 0xff00) | (data & 0x00ff);
+ break;
+
+ case 0x03: /* FDH */
+ chan->step = (chan->step & 0x00ff) | ((data << 8) & 0xff00);
+ break;
+
+ case 0x04: /* LSL */
+ chan->loopst = (chan->loopst & 0xff00) | (data & 0x00ff);
+ break;
+
+ case 0x05: /* LSH */
+ chan->loopst = (chan->loopst & 0x00ff) | ((data << 8) & 0xff00);
+ break;
+
+ case 0x06: /* ST */
+ chan->start = data;
+ if (!chan->enable)
+ chan->addr = chan->start << (8 + 11);
+ break;
+
+ case 0x07: /* control reg */
+ chip->enable = (data >> 7) & 1;
+ if (data & 0x40)
+ chip->cbank = data & 7;
+ else
+ chip->wbank = data & 15;
+ break;
+
+ case 0x08: /* channel on/off reg */
+ for (i = 0; i < 8; i++)
+ {
+ chip->chan[i].enable = (~data >> i) & 1;
+ if (!chip->chan[i].enable)
+ chip->chan[i].addr = chip->chan[i].start << (8 + 11);
+ }
+ break;
+ }
+}
+
+
+/************************************************/
+/* RF5C68 read memory */
+/************************************************/
+
+//READ8_DEVICE_HANDLER( rf5c68_mem_r )
+UINT8 rf5c68_mem_r(void *_chip, offs_t offset)
+{
+ //rf5c68_state *chip = get_safe_token(device);
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ return chip->data[chip->wbank * 0x1000 + offset];
+}
+
+
+/************************************************/
+/* RF5C68 write memory */
+/************************************************/
+
+//WRITE8_DEVICE_HANDLER( rf5c68_mem_w )
+void rf5c68_mem_w(void *_chip, offs_t offset, UINT8 data)
+{
+ //rf5c68_state *chip = get_safe_token(device);
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ rf5c68_mem_stream_flush(chip);
+ chip->data[chip->wbank * 0x1000 | offset] = data;
+}
+
+static void rf5c68_mem_stream_flush(rf5c68_state *chip)
+{
+ mem_stream* ms = &chip->memstrm;
+
+ if (ms->CurAddr >= ms->EndAddr)
+ return;
+
+ memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), ms->EndAddr - ms->CurAddr);
+ ms->CurAddr = ms->EndAddr;
+
+ return;
+}
+
+void rf5c68_write_ram(void *_chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)
+{
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ mem_stream* ms = &chip->memstrm;
+ UINT16 BytCnt;
+
+ if (DataStart >= chip->datasize)
+ return;
+ if (DataStart + DataLength > chip->datasize)
+ DataLength = chip->datasize - DataStart;
+
+ //memcpy(chip->data + (chip->wbank * 0x1000 | DataStart), RAMData, DataLength);
+
+ rf5c68_mem_stream_flush(chip);
+
+ ms->BaseAddr = chip->wbank * 0x1000 | DataStart;
+ ms->CurAddr = ms->BaseAddr;
+ ms->EndAddr = ms->BaseAddr + DataLength;
+ ms->MemPnt = RAMData;
+
+ BytCnt = WRITES_PER_SAMPLE;
+ if (ms->CurAddr + BytCnt > ms->EndAddr)
+ BytCnt = ms->EndAddr - ms->CurAddr;
+
+ memcpy(chip->data + ms->CurAddr, ms->MemPnt + (ms->CurAddr - ms->BaseAddr), BytCnt);
+ ms->CurAddr += BytCnt;
+
+ return;
+}
+
+
+void rf5c68_set_mute_mask(void *_chip, UINT32 MuteMask)
+{
+ rf5c68_state *chip = (rf5c68_state *) _chip;
+ unsigned char CurChn;
+
+ for (CurChn = 0; CurChn < NUM_CHANNELS; CurChn ++)
+ chip->chan[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
+
+ return;
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+/*DEVICE_GET_INFO( rf5c68 )
+{
+ switch (state)
+ {
+ // --- the following bits of info are returned as 64-bit signed integers ---
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(rf5c68_state); break;
+
+ // --- the following bits of info are returned as pointers to data or functions ---
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( rf5c68 ); break;
+ case DEVINFO_FCT_STOP: // Nothing break;
+ case DEVINFO_FCT_RESET: // Nothing break;
+
+ // --- the following bits of info are returned as NULL-terminated strings ---
+ case DEVINFO_STR_NAME: strcpy(info->s, "RF5C68"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Ricoh PCM"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+ }
+}*/
+
+/**************** end of file ****************/
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,82 +1,82 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Rf5C68_Emu.h"
-#include "rf5c68.h"
-
-Rf5C68_Emu::Rf5C68_Emu() { chip = 0; }
-
-Rf5C68_Emu::~Rf5C68_Emu()
-{
- if ( chip ) device_stop_rf5c68( chip );
-}
-
-int Rf5C68_Emu::set_rate()
-{
- if ( chip )
- {
- device_stop_rf5c68( chip );
- chip = 0;
- }
-
- chip = device_start_rf5c68();
- if ( !chip )
- return 1;
-
- reset();
- return 0;
-}
-
-void Rf5C68_Emu::reset()
-{
- device_reset_rf5c68( chip );
- rf5c68_set_mute_mask( chip, 0 );
-}
-
-void Rf5C68_Emu::write( int addr, int data )
-{
- rf5c68_w( chip, addr, data );
-}
-
-void Rf5C68_Emu::write_mem( int addr, int data )
-{
- rf5c68_mem_w( chip, addr, data );
-}
-
-void Rf5C68_Emu::write_ram( int start, int length, void * data )
-{
- rf5c68_write_ram( chip, start, length, (const UINT8 *) data );
-}
-
-void Rf5C68_Emu::mute_voices( int mask )
-{
- rf5c68_set_mute_mask( chip, mask );
-}
-
-void Rf5C68_Emu::run( int pair_count, sample_t* out )
-{
- stream_sample_t bufL[ 1024 ];
- stream_sample_t bufR[ 1024 ];
- stream_sample_t * buffers[2] = { bufL, bufR };
-
- while (pair_count > 0)
- {
- int todo = pair_count;
- if (todo > 1024) todo = 1024;
- rf5c68_update( chip, buffers, todo );
-
- for (int i = 0; i < todo; i++)
- {
- int output_l = bufL [i];
- int output_r = bufR [i];
- output_l += out [0];
- output_r += out [1];
- if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
- if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
- out [0] = output_l;
- out [1] = output_r;
- out += 2;
- }
-
- pair_count -= todo;
- }
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Rf5C68_Emu.h"
+#include "rf5c68.h"
+
+Rf5C68_Emu::Rf5C68_Emu() { chip = 0; }
+
+Rf5C68_Emu::~Rf5C68_Emu()
+{
+ if ( chip ) device_stop_rf5c68( chip );
+}
+
+int Rf5C68_Emu::set_rate()
+{
+ if ( chip )
+ {
+ device_stop_rf5c68( chip );
+ chip = 0;
+ }
+
+ chip = device_start_rf5c68();
+ if ( !chip )
+ return 1;
+
+ reset();
+ return 0;
+}
+
+void Rf5C68_Emu::reset()
+{
+ device_reset_rf5c68( chip );
+ rf5c68_set_mute_mask( chip, 0 );
+}
+
+void Rf5C68_Emu::write( int addr, int data )
+{
+ rf5c68_w( chip, addr, data );
+}
+
+void Rf5C68_Emu::write_mem( int addr, int data )
+{
+ rf5c68_mem_w( chip, addr, data );
+}
+
+void Rf5C68_Emu::write_ram( int start, int length, void * data )
+{
+ rf5c68_write_ram( chip, start, length, (const UINT8 *) data );
+}
+
+void Rf5C68_Emu::mute_voices( int mask )
+{
+ rf5c68_set_mute_mask( chip, mask );
+}
+
+void Rf5C68_Emu::run( int pair_count, sample_t* out )
+{
+ stream_sample_t bufL[ 1024 ];
+ stream_sample_t bufR[ 1024 ];
+ stream_sample_t * buffers[2] = { bufL, bufR };
+
+ while (pair_count > 0)
+ {
+ int todo = pair_count;
+ if (todo > 1024) todo = 1024;
+ rf5c68_update( chip, buffers, todo );
+
+ for (int i = 0; i < todo; i++)
+ {
+ int output_l = bufL [i];
+ int output_r = bufR [i];
+ output_l += out [0];
+ output_r += out [1];
+ if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
+ if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
+ out [0] = output_l;
+ out [1] = output_r;
+ out += 2;
+ }
+
+ pair_count -= todo;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rf5C68_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,39 +1,39 @@
-// RF5C68 sound chip emulator interface
-
-// Game_Music_Emu $vers
-#ifndef RF5C68_EMU_H
-#define RF5C68_EMU_H
-
-class Rf5C68_Emu {
- void* chip;
-public:
- Rf5C68_Emu();
- ~Rf5C68_Emu();
-
- // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate();
-
- // Resets to power-up state
- void reset();
-
- // Mutes voice n if bit n (1 << n) of mask is set
- enum { channel_count = 8 };
- void mute_voices( int mask );
-
- // Writes data to addr
- void write( int addr, int data );
-
- // Writes to memory
- void write_mem( int addr, int data );
-
- // Writes length bytes from data at start offset in RAM
- void write_ram( int start, int length, void * data );
-
- // Runs and writes pair_count*2 samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
+// RF5C68 sound chip emulator interface
+
+// Game_Music_Emu $vers
+#ifndef RF5C68_EMU_H
+#define RF5C68_EMU_H
+
+class Rf5C68_Emu {
+ void* chip;
+public:
+ Rf5C68_Emu();
+ ~Rf5C68_Emu();
+
+ // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+ // if error.
+ int set_rate();
+
+ // Resets to power-up state
+ void reset();
+
+ // Mutes voice n if bit n (1 << n) of mask is set
+ enum { channel_count = 8 };
+ void mute_voices( int mask );
+
+ // Writes data to addr
+ void write( int addr, int data );
+
+ // Writes to memory
+ void write_mem( int addr, int data );
+
+ // Writes length bytes from data at start offset in RAM
+ void write_ram( int start, int length, void * data );
+
+ // Runs and writes pair_count*2 samples to output
+ typedef short sample_t;
+ enum { out_chan_count = 2 }; // stereo
+ void run( int pair_count, sample_t* out );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/rf5c68.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/rf5c68.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/rf5c68.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/rf5c68.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,38 +1,38 @@
-/*********************************************************/
-/* ricoh RF5C68(or clone) PCM controller */
-/*********************************************************/
-
-#pragma once
-
-#include "mamedef.h"
-
-/******************************************/
-/*WRITE8_DEVICE_HANDLER( rf5c68_w );
-
-READ8_DEVICE_HANDLER( rf5c68_mem_r );
-WRITE8_DEVICE_HANDLER( rf5c68_mem_w );
-
-DEVICE_GET_INFO( rf5c68 );
-#define SOUND_RF5C68 DEVICE_GET_INFO_NAME( rf5c68 )*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void rf5c68_update(void *chip, stream_sample_t **outputs, int samples);
-
-void * device_start_rf5c68();
-void device_stop_rf5c68(void *chip);
-void device_reset_rf5c68(void *chip);
-
-void rf5c68_w(void *chip, offs_t offset, UINT8 data);
-
-UINT8 rf5c68_mem_r(void *chip, offs_t offset);
-void rf5c68_mem_w(void *chip, offs_t offset, UINT8 data);
-void rf5c68_write_ram(void *chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);
-
-void rf5c68_set_mute_mask(void *chip, UINT32 MuteMask);
-
-#ifdef __cplusplus
-}
-#endif
+/*********************************************************/
+/* ricoh RF5C68(or clone) PCM controller */
+/*********************************************************/
+
+#pragma once
+
+#include "mamedef.h"
+
+/******************************************/
+/*WRITE8_DEVICE_HANDLER( rf5c68_w );
+
+READ8_DEVICE_HANDLER( rf5c68_mem_r );
+WRITE8_DEVICE_HANDLER( rf5c68_mem_w );
+
+DEVICE_GET_INFO( rf5c68 );
+#define SOUND_RF5C68 DEVICE_GET_INFO_NAME( rf5c68 )*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void rf5c68_update(void *chip, stream_sample_t **outputs, int samples);
+
+void * device_start_rf5c68();
+void device_stop_rf5c68(void *chip);
+void device_reset_rf5c68(void *chip);
+
+void rf5c68_w(void *chip, offs_t offset, UINT8 data);
+
+UINT8 rf5c68_mem_r(void *chip, offs_t offset);
+void rf5c68_mem_w(void *chip, offs_t offset, UINT8 data);
+void rf5c68_write_ram(void *chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);
+
+void rf5c68_set_mute_mask(void *chip, UINT32 MuteMask);
+
+#ifdef __cplusplus
+}
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rom_Data.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rom_Data.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rom_Data.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rom_Data.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,99 +1,99 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Rom_Data.h"
-
-/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Rom_Data::clear()
-{
- file_size_ = 0;
- rom_addr = 0;
- mask = 0;
- rom.clear();
-}
-
-Rom_Data::Rom_Data( int page_size ) :
- pad_size( page_size + pad_extra )
-{
- // page_size should be power of 2
- check( (page_size & (page_size - 1)) == 0 );
-
- clear();
-}
-
-Rom_Data::~Rom_Data()
-{ }
-
-// Reads file into array, placing file_offset bytes of padding before the beginning, and pad_size after the end
-blargg_err_t Rom_Data::load_( Data_Reader& in, int header_size, int file_offset )
-{
- clear();
- file_size_ = in.remain();
- if ( file_size_ <= header_size ) // <= because there must be data after header
- return blargg_err_file_type;
-
- RETURN_ERR( rom.resize( file_offset + file_size_ + pad_size ) );
-
- return in.read( rom.begin() + file_offset, file_size_ );
-}
-
-blargg_err_t Rom_Data::load( Data_Reader& in, int header_size,
- void* header_out, int fill )
-{
- int file_offset = pad_size - header_size;
- blargg_err_t err = load_( in, header_size, file_offset );
- if ( err )
- {
- clear();
- return err;
- }
-
- file_size_ -= header_size;
- memcpy( header_out, &rom [file_offset], header_size );
-
- memset( rom.begin() , fill, pad_size );
- memset( rom.end() - pad_size, fill, pad_size );
-
- return blargg_ok;
-}
-
-void Rom_Data::set_addr( int addr )
-{
- int const page_size = pad_size - pad_extra;
-
- // Minimum size that contains all bytes and is a multiple of page_size
- int const size = (addr + file_size_ + page_size - 1) / page_size * page_size;
-
- // Find lowest power of 2 that is >= size
- int power2 = 1;
- while ( power2 < size )
- power2 *= 2;
-
- mask = power2 - 1;
-
- // Address of first byte of ROM (possibly negative)
- rom_addr = addr - page_size - pad_extra;
-
- if ( rom.resize( size - rom_addr + pad_extra ) ) { } // OK if shrink fails
-}
-
-byte* Rom_Data::at_addr( int addr )
-{
- int offset = mask_addr( addr ) - rom_addr;
-
- if ( (unsigned) offset > (unsigned) (rom.size() - pad_size) )
- offset = 0; // unmapped
-
- return &rom [offset];
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Rom_Data.h"
+
+/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Rom_Data::clear()
+{
+ file_size_ = 0;
+ rom_addr = 0;
+ mask = 0;
+ rom.clear();
+}
+
+Rom_Data::Rom_Data( int page_size ) :
+ pad_size( page_size + pad_extra )
+{
+ // page_size should be power of 2
+ check( (page_size & (page_size - 1)) == 0 );
+
+ clear();
+}
+
+Rom_Data::~Rom_Data()
+{ }
+
+// Reads file into array, placing file_offset bytes of padding before the beginning, and pad_size after the end
+blargg_err_t Rom_Data::load_( Data_Reader& in, int header_size, int file_offset )
+{
+ clear();
+ file_size_ = in.remain();
+ if ( file_size_ <= header_size ) // <= because there must be data after header
+ return blargg_err_file_type;
+
+ RETURN_ERR( rom.resize( file_offset + file_size_ + pad_size ) );
+
+ return in.read( rom.begin() + file_offset, file_size_ );
+}
+
+blargg_err_t Rom_Data::load( Data_Reader& in, int header_size,
+ void* header_out, int fill )
+{
+ int file_offset = pad_size - header_size;
+ blargg_err_t err = load_( in, header_size, file_offset );
+ if ( err )
+ {
+ clear();
+ return err;
+ }
+
+ file_size_ -= header_size;
+ memcpy( header_out, &rom [file_offset], header_size );
+
+ memset( rom.begin() , fill, pad_size );
+ memset( rom.end() - pad_size, fill, pad_size );
+
+ return blargg_ok;
+}
+
+void Rom_Data::set_addr( int addr )
+{
+ int const page_size = pad_size - pad_extra;
+
+ // Minimum size that contains all bytes and is a multiple of page_size
+ int const size = (addr + file_size_ + page_size - 1) / page_size * page_size;
+
+ // Find lowest power of 2 that is >= size
+ int power2 = 1;
+ while ( power2 < size )
+ power2 *= 2;
+
+ mask = power2 - 1;
+
+ // Address of first byte of ROM (possibly negative)
+ rom_addr = addr - page_size - pad_extra;
+
+ if ( rom.resize( size - rom_addr + pad_extra ) ) { } // OK if shrink fails
+}
+
+byte* Rom_Data::at_addr( int addr )
+{
+ int offset = mask_addr( addr ) - rom_addr;
+
+ if ( (unsigned) offset > (unsigned) (rom.size() - pad_size) )
+ offset = 0; // unmapped
+
+ return &rom [offset];
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rom_Data.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rom_Data.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Rom_Data.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Rom_Data.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,94 +1,94 @@
-// Manages ROM data loaded from file in an efficient manner
-
-// Game_Music_Emu $vers
-#ifndef ROM_DATA_H
-#define ROM_DATA_H
-
-#include "blargg_common.h"
-#include "Data_Reader.h"
-
-/* Loads a ROM file into memory and allows access to it in page-sized chunks.
-
-* ROM file consists of header followed by ROM data. Instead of storing the entire
-ROM contents, the file only stores the occupied portion, with the bytes before and
-after that cleared to some value. The size and format of the header is up to the
-caller, as is the starting address of the ROM data following it. File loading is
-performed with a single read, rather than two or more that might otherwise be
-required.
-
-* Once ROM data is loaded and its address specified, a pointer to any "page" can
-be obtained. ROM data is mirrored using smallest power of 2 that contains it.
-Addresses not aligned to pages can also be used, but this might cause unexpected
-results.
-
-Example with file data of size 0x0C put at address 0x0F, with page size of 8:
-
----------------0123456789AB--------------------0123456789AB---------...
-^ ^ ^ ^ ^ ^ ^ ^ ^
-0 0x08 0x10 0x18 0x20 0x28 0x30 0x38 0x40
-
-at_addr(0x00) = pointer to 8 bytes of fill.
-at_addr(0x08) = pointer to 7 bytes of fill, followed by first byte of file.
-at_addr(0x10) = pointer to next 8 bytes of file.
-at_addr(0x18) = pointer to last 3 bytes of file, followed by 5 bytes of fill.
-at_addr(0x20) = pointer to 8 bytes of fill.
-at_addr(0x28) = pointer to 7 bytes of fill, followed by first byte of file.
-etc. */
-
-class Rom_Data {
- enum { pad_extra = 8 };
-public:
- typedef unsigned char byte;
-
- // Page_size should be a power of 2
- Rom_Data( int page_size );
-
- // Loads file into memory, then copies header to *header_out and fills
- // unmapped bank and file data padding with fill. Returns blargg_err_file_type
- // if in.remain() <= header_size.
- blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill );
-
- // Below, "file data" refers to data AFTER the header
-
- // Size of file data
- int file_size() const { return file_size_; }
-
- // Pointer to beginning of file data
- byte * begin() { return rom.begin() + pad_size; }
- byte const* begin() const { return rom.begin() + pad_size; }
-
- // Pointer to unmapped page cleared with fill value
- byte* unmapped() { return rom.begin(); }
-
- // Sets address that file data will start at. Must be set before using following
- // functions, and cannot be set more than once.
- void set_addr( int addr );
-
- // Address of first empty page (file size + addr rounded up to multiple of page_size)
- int size() const { return rom.size() - pad_extra + rom_addr; }
-
- // Masks address to nearest power of two greater than size()
- int mask_addr( int addr ) const { return addr & mask; }
-
- // Pointer to page beginning at addr, or unmapped() if outside data.
- // Mirrored using mask_addr().
- byte* at_addr( int addr );
-
- // Frees memory
- void clear();
-
-// Implementation
-public:
- ~Rom_Data();
-
-protected:
- blargg_vector rom;
- int mask;
- int rom_addr;
- int const pad_size;
- int file_size_;
-
- blargg_err_t load_( Data_Reader& in, int header_size, int file_offset );
-};
-
-#endif
+// Manages ROM data loaded from file in an efficient manner
+
+// Game_Music_Emu $vers
+#ifndef ROM_DATA_H
+#define ROM_DATA_H
+
+#include "blargg_common.h"
+#include "Data_Reader.h"
+
+/* Loads a ROM file into memory and allows access to it in page-sized chunks.
+
+* ROM file consists of header followed by ROM data. Instead of storing the entire
+ROM contents, the file only stores the occupied portion, with the bytes before and
+after that cleared to some value. The size and format of the header is up to the
+caller, as is the starting address of the ROM data following it. File loading is
+performed with a single read, rather than two or more that might otherwise be
+required.
+
+* Once ROM data is loaded and its address specified, a pointer to any "page" can
+be obtained. ROM data is mirrored using smallest power of 2 that contains it.
+Addresses not aligned to pages can also be used, but this might cause unexpected
+results.
+
+Example with file data of size 0x0C put at address 0x0F, with page size of 8:
+
+---------------0123456789AB--------------------0123456789AB---------...
+^ ^ ^ ^ ^ ^ ^ ^ ^
+0 0x08 0x10 0x18 0x20 0x28 0x30 0x38 0x40
+
+at_add[5~r(0x00) = pointer to 8 bytes of fill.
+at_addr(0x08) = pointer to 7 bytes of fill, followed by first byte of file.
+at_addr(0x10) = pointer to next 8 bytes of file.
+at_addr(0x18) = pointer to last 3 bytes of file, followed by 5 bytes of fill.
+at_addr(0x20) = pointer to 8 bytes of fill.
+at_addr(0x28) = pointer to 7 bytes of fill, followed by first byte of file.
+etc. */
+
+class Rom_Data {
+ enum { pad_extra = 8 };
+public:
+ typedef unsigned char byte;
+
+ // Page_size should be a power of 2
+ Rom_Data( int page_size );
+
+ // Loads file into memory, then copies header to *header_out and fills
+ // unmapped bank and file data padding with fill. Returns blargg_err_file_type
+ // if in.remain() <= header_size.
+ blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill );
+
+ // Below, "file data" refers to data AFTER the header
+
+ // Size of file data
+ int file_size() const { return file_size_; }
+
+ // Pointer to beginning of file data
+ byte * begin() { return rom.begin() + pad_size; }
+ byte const* begin() const { return rom.begin() + pad_size; }
+
+ // Pointer to unmapped page cleared with fill value
+ byte* unmapped() { return rom.begin(); }
+
+ // Sets address that file data will start at. Must be set before using following
+ // functions, and cannot be set more than once.
+ void set_addr( int addr );
+
+ // Address of first empty page (file size + addr rounded up to multiple of page_size)
+ int size() const { return rom.size() - pad_extra + rom_addr; }
+
+ // Masks address to nearest power of two greater than size()
+ int mask_addr( int addr ) const { return addr & mask; }
+
+ // Pointer to page beginning at addr, or unmapped() if outside data.
+ // Mirrored using mask_addr().
+ byte* at_addr( int addr );
+
+ // Frees memory
+ void clear();
+
+// Implementation
+public:
+ ~Rom_Data();
+
+protected:
+ blargg_vector rom;
+ int mask;
+ int rom_addr;
+ int const pad_size;
+ int file_size_;
+
+ blargg_err_t load_( Data_Reader& in, int header_size, int file_offset );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sap_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sap_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sap_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sap_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,410 +1,410 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Sap_Emu.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Sap_Emu::Sap_Emu()
-{
- set_type( gme_sap_type );
- set_silence_lookahead( 6 );
-}
-
-Sap_Emu::~Sap_Emu() { }
-
-// Track info
-
-// Returns 16 or greater if not hex. Handles uppercase and lowercase.
-// Thoroughly tested and rejects ALL non-hex characters.
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static int from_hex( byte const in [] )
-{
- int result = 0;
- for ( int n = 4; n--; )
- {
- int h = from_hex_char( *in++ );
- if ( h > 15 )
- return -1;
- result = result * 0x10 + h;
- }
- return result;
-}
-
-static int parse_int( byte const* io [], byte const* end )
-{
- byte const* in = *io;
- int n = 0;
- while ( in < end )
- {
- int dig = *in - '0';
- if ( (unsigned) dig > 9 )
- break;
- ++in;
- n = n * 10 + dig;
- }
- if ( in == *io )
- n = -1; // no numeric characters
- *io = in;
- return n;
-}
-
-static int from_dec( byte const in [], byte const* end )
-{
- int n = parse_int( &in, end );
- if ( in < end )
- n = -1;
- return n;
-}
-
-static void parse_string( byte const in [], byte const* end, int len, char out [] )
-{
- byte const* start = in;
- if ( *in++ == '\"' )
- {
- start++;
- while ( in < end && *in != '\"' )
- in++;
- }
- else
- {
- in = end;
- }
- len = min( len - 1, int (in - start) );
- out [len] = 0;
- memcpy( out, start, len );
-}
-
-static int parse_time( byte const in [], byte const* end )
-{
- int minutes = parse_int( &in, end );
- if ( minutes < 0 || *in != ':' )
- return 0;
-
- ++in;
- int seconds = parse_int( &in, end );
- if ( seconds < 0 )
- return 0;
-
- int time = minutes * 60000 + seconds * 1000;
- if ( *in == '.' )
- {
- byte const* start = ++in;
- int msec = parse_int( &in, end );
- if ( msec >= 0 )
- {
- // allow 1-3 digits
- for ( int n = in - start; n < 3; n++ )
- msec *= 10;
- time += msec;
- }
- }
-
- while ( in < end && *in <= ' ' )
- ++in;
-
- if ( end - in >= 4 && !memcmp( in, "LOOP", 4 ) )
- time = -time;
-
- return time;
-}
-
-static blargg_err_t parse_info( byte const in [], int size, Sap_Emu::info_t* out )
-{
- out->track_count = 1;
- out->author [0] = 0;
- out->name [0] = 0;
- out->copyright [0] = 0;
-
- for ( int i = 0; i < Sap_Emu::max_tracks; i++ )
- out->track_times [i] = 0;
-
- if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
- return blargg_err_file_type;
-
- int time_count = 0;
- byte const* file_end = in + size - 5;
- in += 5;
- while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
- {
- byte const* line_end = in;
- while ( line_end < file_end && *line_end != 0x0D )
- line_end++;
-
- char const* tag = (char const*) in;
- while ( in < line_end && *in > ' ' )
- in++;
- int tag_len = (char const*) in - tag;
-
- while ( in < line_end && *in <= ' ' ) in++;
-
- if ( tag_len <= 0 )
- {
- // skip line
- }
- else if ( !strncmp( "TIME", tag, tag_len ) && time_count < Sap_Emu::max_tracks )
- {
- out->track_times [time_count++] = parse_time( in, line_end );
- }
- else if ( !strncmp( "INIT", tag, tag_len ) )
- {
- out->init_addr = from_hex( in );
- if ( (unsigned) out->init_addr >= 0x10000 )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "init address" );
- }
- else if ( !strncmp( "PLAYER", tag, tag_len ) )
- {
- out->play_addr = from_hex( in );
- if ( (unsigned) out->play_addr >= 0x10000 )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "play address" );
- }
- else if ( !strncmp( "MUSIC", tag, tag_len ) )
- {
- out->music_addr = from_hex( in );
- if ( (unsigned) out->music_addr >= 0x10000 )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "music address" );
- }
- else if ( !strncmp( "SONGS", tag, tag_len ) )
- {
- out->track_count = from_dec( in, line_end );
- if ( out->track_count <= 0 )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "track count" );
- }
- else if ( !strncmp( "TYPE", tag, tag_len ) )
- {
- switch ( out->type = *in )
- {
- case 'S':
- out->type = 'C';
- case 'B':
- case 'C':
- case 'D':
- break;
-
- default:
- return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "player type" );
- }
- }
- else if ( !strncmp( "STEREO", tag, tag_len ) )
- {
- out->stereo = true;
- }
- else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
- {
- out->fastplay = from_dec( in, line_end );
- if ( out->fastplay <= 0 )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "fastplay value" );
- }
- else if ( !strncmp( "AUTHOR", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->author, out->author );
- }
- else if ( !strncmp( "NAME", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->name, out->name );
- }
- else if ( !strncmp( "DATE", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->copyright, out->copyright );
- }
-
- in = line_end + 2;
- }
-
- if ( in [0] != 0xFF || in [1] != 0xFF )
- return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "ROM data missing" );
- out->rom_data = in + 2;
-
- return blargg_ok;
-}
-
-static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
-{
- Gme_File::copy_field_( out->game, in.name );
- Gme_File::copy_field_( out->author, in.author );
- Gme_File::copy_field_( out->copyright, in.copyright );
-}
-
-static void hash_sap_file( Sap_Emu::info_t const& i, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- unsigned char temp[4];
- set_le32( &temp[0], i.init_addr ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.play_addr ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.music_addr ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.type ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.fastplay ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.stereo ); out.hash_( &temp[0], sizeof(temp) );
- set_le32( &temp[0], i.track_count ); out.hash_( &temp[0], sizeof(temp) );
- out.hash_( data, data_size );
-}
-
-blargg_err_t Sap_Emu::track_info_( track_info_t* out, int track ) const
-{
- copy_sap_fields( info_, out );
-
- if ( track < max_tracks )
- {
- int time = info_.track_times [track];
- if ( time )
- {
- if ( time > 0 )
- {
- out->loop_length = 0;
- }
- else
- {
- time = -time;
- out->loop_length = time;
- }
- out->length = time;
- }
- }
- return blargg_ok;
-}
-
-struct Sap_File : Gme_Info_
-{
- Sap_Emu::info_t info;
-
- Sap_File() { set_type( gme_sap_type ); }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- RETURN_ERR( parse_info( begin, size, &info ) );
- set_track_count( info.track_count );
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_sap_fields( info, out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_sap_file( info, info.rom_data, file_end() - info.rom_data, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
-static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
-
-gme_type_t_ const gme_sap_type [1] = {{ "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 }};
-
-// Setup
-
-blargg_err_t Sap_Emu::load_mem_( byte const in [], int size )
-{
- file_end = in + size;
-
- info_.warning = NULL;
- info_.type = 'B';
- info_.stereo = false;
- info_.init_addr = -1;
- info_.play_addr = -1;
- info_.music_addr = -1;
- info_.fastplay = 312;
- RETURN_ERR( parse_info( in, size, &info_ ) );
-
- set_warning( info_.warning );
- set_track_count( info_.track_count );
- set_voice_count( Sap_Apu::osc_count << info_.stereo );
- core.apu_impl().volume( gain() );
-
- static const char* const names [Sap_Apu::osc_count * 2] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8",
- };
- set_voice_names( names );
-
- static int const types [Sap_Apu::osc_count * 2] = {
- wave_type+1, wave_type+2, wave_type+3, wave_type+0,
- wave_type+5, wave_type+6, wave_type+7, wave_type+4,
- };
- set_voice_types( types );
-
- return setup_buffer( 1773447 );
-}
-
-void Sap_Emu::update_eq( blip_eq_t const& eq )
-{
- core.apu_impl().synth.treble_eq( eq );
-}
-
-void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- int i2 = i - Sap_Apu::osc_count;
- if ( i2 >= 0 )
- core.apu2().set_output( i2, right );
- else
- core.apu().set_output( i, (info_.stereo ? left : center) );
-}
-
-// Emulation
-
-void Sap_Emu::set_tempo_( double t )
-{
- core.set_tempo( t );
-}
-
-blargg_err_t Sap_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- core.setup_ram();
-
- // Copy file data to RAM
- byte const* in = info_.rom_data;
- while ( file_end - in >= 5 )
- {
- int start = get_le16( in );
- int end = get_le16( in + 2 );
- //dprintf( "Block $%04X-$%04X\n", start, end );
- in += 4;
- int len = end - start + 1;
- if ( (unsigned) len > (unsigned) (file_end - in) )
- {
- set_warning( "Invalid file data block" );
- break;
- }
-
- memcpy( core.ram() + start, in, len );
- in += len;
- if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
- in += 2;
- }
-
- return core.start_track( track, info_ );
-}
-
-blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
-{
- return core.end_frame( duration );
-}
-
-blargg_err_t Sap_Emu::hash_( Hash_Function& out ) const
-{
- hash_sap_file( info(), info().rom_data, file_end - info().rom_data, out );
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Sap_Emu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+Sap_Emu::Sap_Emu()
+{
+ set_type( gme_sap_type );
+ set_silence_lookahead( 6 );
+}
+
+Sap_Emu::~Sap_Emu() { }
+
+// Track info
+
+// Returns 16 or greater if not hex. Handles uppercase and lowercase.
+// Thoroughly tested and rejects ALL non-hex characters.
+inline int from_hex_char( int h )
+{
+ h -= 0x30;
+ if ( (unsigned) h > 9 )
+ h = ((h - 0x11) & 0xDF) + 10;
+ return h;
+}
+
+static int from_hex( byte const in [] )
+{
+ int result = 0;
+ for ( int n = 4; n--; )
+ {
+ int h = from_hex_char( *in++ );
+ if ( h > 15 )
+ return -1;
+ result = result * 0x10 + h;
+ }
+ return result;
+}
+
+static int parse_int( byte const* io [], byte const* end )
+{
+ byte const* in = *io;
+ int n = 0;
+ while ( in < end )
+ {
+ int dig = *in - '0';
+ if ( (unsigned) dig > 9 )
+ break;
+ ++in;
+ n = n * 10 + dig;
+ }
+ if ( in == *io )
+ n = -1; // no numeric characters
+ *io = in;
+ return n;
+}
+
+static int from_dec( byte const in [], byte const* end )
+{
+ int n = parse_int( &in, end );
+ if ( in < end )
+ n = -1;
+ return n;
+}
+
+static void parse_string( byte const in [], byte const* end, int len, char out [] )
+{
+ byte const* start = in;
+ if ( *in++ == '\"' )
+ {
+ start++;
+ while ( in < end && *in != '\"' )
+ in++;
+ }
+ else
+ {
+ in = end;
+ }
+ len = min( len - 1, int (in - start) );
+ out [len] = 0;
+ memcpy( out, start, len );
+}
+
+static int parse_time( byte const in [], byte const* end )
+{
+ int minutes = parse_int( &in, end );
+ if ( minutes < 0 || *in != ':' )
+ return 0;
+
+ ++in;
+ int seconds = parse_int( &in, end );
+ if ( seconds < 0 )
+ return 0;
+
+ int time = minutes * 60000 + seconds * 1000;
+ if ( *in == '.' )
+ {
+ byte const* start = ++in;
+ int msec = parse_int( &in, end );
+ if ( msec >= 0 )
+ {
+ // allow 1-3 digits
+ for ( int n = in - start; n < 3; n++ )
+ msec *= 10;
+ time += msec;
+ }
+ }
+
+ while ( in < end && *in <= ' ' )
+ ++in;
+
+ if ( end - in >= 4 && !memcmp( in, "LOOP", 4 ) )
+ time = -time;
+
+ return time;
+}
+
+static blargg_err_t parse_info( byte const in [], int size, Sap_Emu::info_t* out )
+{
+ out->track_count = 1;
+ out->author [0] = 0;
+ out->name [0] = 0;
+ out->copyright [0] = 0;
+
+ for ( int i = 0; i < Sap_Emu::max_tracks; i++ )
+ out->track_times [i] = 0;
+
+ if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
+ return blargg_err_file_type;
+
+ int time_count = 0;
+ byte const* file_end = in + size - 5;
+ in += 5;
+ while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
+ {
+ byte const* line_end = in;
+ while ( line_end < file_end && *line_end != 0x0D )
+ line_end++;
+
+ char const* tag = (char const*) in;
+ while ( in < line_end && *in > ' ' )
+ in++;
+ int tag_len = (char const*) in - tag;
+
+ while ( in < line_end && *in <= ' ' ) in++;
+
+ if ( tag_len <= 0 )
+ {
+ // skip line
+ }
+ else if ( !strncmp( "TIME", tag, tag_len ) && time_count < Sap_Emu::max_tracks )
+ {
+ out->track_times [time_count++] = parse_time( in, line_end );
+ }
+ else if ( !strncmp( "INIT", tag, tag_len ) )
+ {
+ out->init_addr = from_hex( in );
+ if ( (unsigned) out->init_addr >= 0x10000 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "init address" );
+ }
+ else if ( !strncmp( "PLAYER", tag, tag_len ) )
+ {
+ out->play_addr = from_hex( in );
+ if ( (unsigned) out->play_addr >= 0x10000 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "play address" );
+ }
+ else if ( !strncmp( "MUSIC", tag, tag_len ) )
+ {
+ out->music_addr = from_hex( in );
+ if ( (unsigned) out->music_addr >= 0x10000 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "music address" );
+ }
+ else if ( !strncmp( "SONGS", tag, tag_len ) )
+ {
+ out->track_count = from_dec( in, line_end );
+ if ( out->track_count <= 0 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "track count" );
+ }
+ else if ( !strncmp( "TYPE", tag, tag_len ) )
+ {
+ switch ( out->type = *in )
+ {
+ case 'S':
+ out->type = 'C';
+ case 'B':
+ case 'C':
+ case 'D':
+ break;
+
+ default:
+ return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "player type" );
+ }
+ }
+ else if ( !strncmp( "STEREO", tag, tag_len ) )
+ {
+ out->stereo = true;
+ }
+ else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
+ {
+ out->fastplay = from_dec( in, line_end );
+ if ( out->fastplay <= 0 )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "fastplay value" );
+ }
+ else if ( !strncmp( "AUTHOR", tag, tag_len ) )
+ {
+ parse_string( in, line_end, sizeof out->author, out->author );
+ }
+ else if ( !strncmp( "NAME", tag, tag_len ) )
+ {
+ parse_string( in, line_end, sizeof out->name, out->name );
+ }
+ else if ( !strncmp( "DATE", tag, tag_len ) )
+ {
+ parse_string( in, line_end, sizeof out->copyright, out->copyright );
+ }
+
+ in = line_end + 2;
+ }
+
+ if ( in [0] != 0xFF || in [1] != 0xFF )
+ return BLARGG_ERR( BLARGG_ERR_FILE_CORRUPT, "ROM data missing" );
+ out->rom_data = in + 2;
+
+ return blargg_ok;
+}
+
+static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
+{
+ Gme_File::copy_field_( out->game, in.name );
+ Gme_File::copy_field_( out->author, in.author );
+ Gme_File::copy_field_( out->copyright, in.copyright );
+}
+
+static void hash_sap_file( Sap_Emu::info_t const& i, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ unsigned char temp[4];
+ set_le32( &temp[0], i.init_addr ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.play_addr ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.music_addr ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.type ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.fastplay ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.stereo ); out.hash_( &temp[0], sizeof(temp) );
+ set_le32( &temp[0], i.track_count ); out.hash_( &temp[0], sizeof(temp) );
+ out.hash_( data, data_size );
+}
+
+blargg_err_t Sap_Emu::track_info_( track_info_t* out, int track ) const
+{
+ copy_sap_fields( info_, out );
+
+ if ( track < max_tracks )
+ {
+ int time = info_.track_times [track];
+ if ( time )
+ {
+ if ( time > 0 )
+ {
+ out->loop_length = 0;
+ }
+ else
+ {
+ time = -time;
+ out->loop_length = time;
+ }
+ out->length = time;
+ }
+ }
+ return blargg_ok;
+}
+
+struct Sap_File : Gme_Info_
+{
+ Sap_Emu::info_t info;
+
+ Sap_File() { set_type( gme_sap_type ); }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ RETURN_ERR( parse_info( begin, size, &info ) );
+ set_track_count( info.track_count );
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_sap_fields( info, out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_sap_file( info, info.rom_data, file_end() - info.rom_data, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
+static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
+
+gme_type_t_ const gme_sap_type [1] = {{ "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 }};
+
+// Setup
+
+blargg_err_t Sap_Emu::load_mem_( byte const in [], int size )
+{
+ file_end = in + size;
+
+ info_.warning = NULL;
+ info_.type = 'B';
+ info_.stereo = false;
+ info_.init_addr = -1;
+ info_.play_addr = -1;
+ info_.music_addr = -1;
+ info_.fastplay = 312;
+ RETURN_ERR( parse_info( in, size, &info_ ) );
+
+ set_warning( info_.warning );
+ set_track_count( info_.track_count );
+ set_voice_count( Sap_Apu::osc_count << info_.stereo );
+ core.apu_impl().volume( gain() );
+
+ static const char* const names [Sap_Apu::osc_count * 2] = {
+ "Wave 1", "Wave 2", "Wave 3", "Wave 4",
+ "Wave 5", "Wave 6", "Wave 7", "Wave 8",
+ };
+ set_voice_names( names );
+
+ static int const types [Sap_Apu::osc_count * 2] = {
+ wave_type+1, wave_type+2, wave_type+3, wave_type+0,
+ wave_type+5, wave_type+6, wave_type+7, wave_type+4,
+ };
+ set_voice_types( types );
+
+ return setup_buffer( 1773447 );
+}
+
+void Sap_Emu::update_eq( blip_eq_t const& eq )
+{
+ core.apu_impl().synth.treble_eq( eq );
+}
+
+void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
+{
+ int i2 = i - Sap_Apu::osc_count;
+ if ( i2 >= 0 )
+ core.apu2().set_output( i2, right );
+ else
+ core.apu().set_output( i, (info_.stereo ? left : center) );
+}
+
+// Emulation
+
+void Sap_Emu::set_tempo_( double t )
+{
+ core.set_tempo( t );
+}
+
+blargg_err_t Sap_Emu::start_track_( int track )
+{
+ RETURN_ERR( Classic_Emu::start_track_( track ) );
+
+ core.setup_ram();
+
+ // Copy file data to RAM
+ byte const* in = info_.rom_data;
+ while ( file_end - in >= 5 )
+ {
+ int start = get_le16( in );
+ int end = get_le16( in + 2 );
+ //dprintf( "Block $%04X-$%04X\n", start, end );
+ in += 4;
+ int len = end - start + 1;
+ if ( (unsigned) len > (unsigned) (file_end - in) )
+ {
+ set_warning( "Invalid file data block" );
+ break;
+ }
+
+ memcpy( core.ram() + start, in, len );
+ in += len;
+ if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
+ in += 2;
+ }
+
+ return core.start_track( track, info_ );
+}
+
+blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
+{
+ return core.end_frame( duration );
+}
+
+blargg_err_t Sap_Emu::hash_( Hash_Function& out ) const
+{
+ hash_sap_file( info(), info().rom_data, file_end - info().rom_data, out );
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/scd_pcm.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/scd_pcm.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/scd_pcm.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/scd_pcm.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,498 +1,498 @@
-/***********************************************************/
-/* */
-/* PCM.C : PCM RF5C164 emulator */
-/* */
-/* This source is a part of Gens project */
-/* Written by Stphane Dallongeville (gens@consolemul.com) */
-/* Copyright (c) 2002 by Stphane Dallongeville */
-/* */
-/***********************************************************/
-
-#include
-#include
-#include
-
-#include "scd_pcm.h"
-int PCM_Init(void *chip, int Rate);
-void PCM_Set_Rate(void *chip, int Rate);
-void PCM_Reset(void *chip);
-void PCM_Write_Reg(void *chip, unsigned int Reg, unsigned int Data);
-int PCM_Update(void *chip, int **buf, int Length);
-
-#define PCM_STEP_SHIFT 11
-
-static unsigned char VolTabIsInit = 0x00;
-static int PCM_Volume_Tab[256 * 256];
-
-//unsigned char Ram_PCM[64 * 1024];
-//int PCM_Enable;
-
-
-/**
- * PCM_Init(): Initialize the PCM chip.
- * @param Rate Sample rate.
- * @return 0 if successful.
- */
-int PCM_Init(void *_chip, int Rate)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- int i, j, out;
-
- if (! VolTabIsInit)
- {
- for (i = 0; i < 0x100; i++)
- {
- for (j = 0; j < 0x100; j++)
- {
- if (i & 0x80)
- {
- out = -(i & 0x7F);
- out *= j;
- PCM_Volume_Tab[(j << 8) + i] = out;
- }
- else
- {
- out = i * j;
- PCM_Volume_Tab[(j << 8) + i] = out;
- }
- }
- }
- VolTabIsInit = 0x01;
- }
-
- for (i = 0; i < 8; i ++)
- chip->Channel[i].Muted = 0x00;
-
- chip->RAMSize = 64 * 1024;
- chip->RAM = (unsigned char*)malloc(chip->RAMSize);
- PCM_Reset(chip);
- PCM_Set_Rate(chip, Rate);
-
- return 0;
-}
-
-
-/**
- * PCM_Reset(): Reset the PCM chip.
- */
-void PCM_Reset(void *_chip)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- int i;
- struct pcm_chan_* chan;
-
- // Clear the PCM memory.
- memset(chip->RAM, 0x00, chip->RAMSize);
-
- chip->Enable = 0;
- chip->Cur_Chan = 0;
- chip->Bank = 0;
-
- /* clear channel registers */
- for (i = 0; i < 8; i++)
- {
- chan = &chip->Channel[i];
- chan->Enable = 0;
- chan->ENV = 0;
- chan->PAN = 0;
- chan->St_Addr = 0;
- chan->Addr = 0;
- chan->Loop_Addr = 0;
- chan->Step = 0;
- chan->Step_B = 0;
- chan->Data = 0;
- }
-}
-
-
-/**
- * PCM_Set_Rate(): Change the PCM sample rate.
- * @param Rate New sample rate.
- */
-void PCM_Set_Rate(void *_chip, int Rate)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- int i;
-
- if (Rate == 0)
- return;
-
- //chip->Rate = (float) (32 * 1024) / (float) Rate;
- chip->Rate = (float) (31.8 * 1024) / (float) Rate;
-
- for (i = 0; i < 8; i++)
- {
- chip->Channel[i].Step =
- (int) ((float) chip->Channel[i].Step_B * chip->Rate);
- }
-}
-
-
-/**
- * PCM_Write_Reg(): Write to a PCM register.
- * @param Reg Register ID.
- * @param Data Data to write.
- */
-void PCM_Write_Reg(void *_chip, unsigned int Reg, unsigned int Data)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- int i;
- struct pcm_chan_* chan = &chip->Channel[chip->Cur_Chan];
-
- Data &= 0xFF;
-
- switch (Reg)
- {
- case 0x00:
- /* evelope register */
- chan->ENV = Data;
- chan->MUL_L = (Data * (chan->PAN & 0x0F)) >> 5;
- chan->MUL_R = (Data * (chan->PAN >> 4)) >> 5;
- break;
-
- case 0x01:
- /* pan register */
- chan->PAN = Data;
- chan->MUL_L = ((Data & 0x0F) * chan->ENV) >> 5;
- chan->MUL_R = ((Data >> 4) * chan->ENV) >> 5;
- break;
-
- case 0x02:
- /* frequency step (LB) registers */
- chan->Step_B &= 0xFF00;
- chan->Step_B += Data;
- chan->Step = (int)((float)chan->Step_B * chip->Rate);
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Step low = %.2X Step calculated = %.8X",
- // Data, chan->Step);
- break;
-
- case 0x03:
- /* frequency step (HB) registers */
- chan->Step_B &= 0x00FF;
- chan->Step_B += Data << 8;
- chan->Step = (int)((float)chan->Step_B * chip->Rate);
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Step high = %.2X Step calculated = %.8X",
- // Data, chan->Step);
- break;
-
- case 0x04:
- chan->Loop_Addr &= 0xFF00;
- chan->Loop_Addr += Data;
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Loop low = %.2X Loop = %.8X",
- // Data, chan->Loop_Addr);
- break;
-
- case 0x05:
- /* loop address registers */
- chan->Loop_Addr &= 0x00FF;
- chan->Loop_Addr += Data << 8;
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Loop high = %.2X Loop = %.8X",
- // Data, chan->Loop_Addr);
- break;
-
- case 0x06:
- /* start address registers */
- chan->St_Addr = Data << (PCM_STEP_SHIFT + 8);
- //chan->Addr = chan->St_Addr;
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Start addr = %.2X New Addr = %.8X",
- // Data, chan->Addr);
- break;
-
- case 0x07:
- /* control register */
- /* mod is H */
- if (Data & 0x40)
- {
- /* select channel */
- chip->Cur_Chan = Data & 0x07;
- }
- /* mod is L */
- else
- {
- /* pcm ram bank select */
- chip->Bank = (Data & 0x0F) << 12;
- }
-
- /* sounding bit */
- if (Data & 0x80)
- chip->Enable = 0xFF; // Used as mask
- else
- chip->Enable = 0;
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "General Enable = %.2X", Data);
- break;
-
- case 0x08:
- /* sound on/off register */
- Data ^= 0xFF;
-
- //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
- // "Channel Enable = %.2X", Data);
-
- for (i = 0; i < 8; i++)
- {
- chan = &chip->Channel[i];
- if (!chan->Enable)
- chan->Addr = chan->St_Addr;
- }
-
- for (i = 0; i < 8; i++)
- {
- chip->Channel[i].Enable = Data & (1 << i);
- }
- }
-}
-
-
-/**
- * PCM_Update(): Update the PCM buffer.
- * @param buf PCM buffer.
- * @param Length Buffer length.
- */
-int PCM_Update(void *_chip, int **buf, int Length)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- int i, j;
- int *bufL, *bufR; //, *volL, *volR;
- unsigned int Addr, k;
- struct pcm_chan_ *CH;
-
- bufL = buf[0];
- bufR = buf[1];
-
- // clear buffers
- memset(bufL, 0, Length * sizeof(int));
- memset(bufR, 0, Length * sizeof(int));
-
- // if PCM disable, no sound
- if (!chip->Enable)
- return 1;
-
-#if 0
- // faster for short update
- for (j = 0; j < Length; j++)
- {
- for (i = 0; i < 8; i++)
- {
- CH = &(chip->Channel[i]);
-
- // only loop when sounding and on
- if (CH->Enable && ! CH->Muted)
- {
- Addr = CH->Addr >> PCM_STEP_SHIFT;
-
- if (Addr & 0x10000)
- {
- for(k = CH->Old_Addr; k < 0x10000; k++)
- {
- if (chip->RAM[k] == 0xFF)
- {
- CH->Old_Addr = Addr = CH->Loop_Addr;
- CH->Addr = Addr << PCM_STEP_SHIFT;
- break;
- }
- }
-
- if (Addr & 0x10000)
- {
- //CH->Addr -= CH->Step;
- CH->Enable = 0;
- break;
- }
- }
- else
- {
- for(k = CH->Old_Addr; k <= Addr; k++)
- {
- if (chip->RAM[k] == 0xFF)
- {
- CH->Old_Addr = Addr = CH->Loop_Addr;
- CH->Addr = Addr << PCM_STEP_SHIFT;
- break;
- }
- }
- }
-
- // test for loop signal
- if (chip->RAM[Addr] == 0xFF)
- {
- Addr = CH->Loop_Addr;
- CH->Addr = Addr << PCM_STEP_SHIFT;
- }
-
- if (chip->RAM[Addr] & 0x80)
- {
- CH->Data = chip->RAM[Addr] & 0x7F;
- bufL[j] -= CH->Data * CH->MUL_L;
- bufR[j] -= CH->Data * CH->MUL_R;
- }
- else
- {
- CH->Data = chip->RAM[Addr];
- bufL[j] += CH->Data * CH->MUL_L;
- bufR[j] += CH->Data * CH->MUL_R;
- }
-
- // update address register
- //CH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;
- CH->Addr += CH->Step;
- CH->Old_Addr = Addr + 1;
- }
- }
- }
-#endif
-
-#if 1
- // for long update
- for (i = 0; i < 8; i++)
- {
- CH = &(chip->Channel[i]);
-
- // only loop when sounding and on
- if (CH->Enable && ! CH->Muted)
- {
- Addr = CH->Addr >> PCM_STEP_SHIFT;
- //volL = &(PCM_Volume_Tab[CH->MUL_L << 8]);
- //volR = &(PCM_Volume_Tab[CH->MUL_R << 8]);
-
- for (j = 0; j < Length; j++)
- {
- // test for loop signal
- if (chip->RAM[Addr] == 0xFF)
- {
- CH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;
- if (chip->RAM[Addr] == 0xFF)
- break;
- else
- j--;
- }
- else
- {
- if (chip->RAM[Addr] & 0x80)
- {
- CH->Data = chip->RAM[Addr] & 0x7F;
- bufL[j] -= CH->Data * CH->MUL_L;
- bufR[j] -= CH->Data * CH->MUL_R;
- }
- else
- {
- CH->Data = chip->RAM[Addr];
- bufL[j] += CH->Data * CH->MUL_L;
- bufR[j] += CH->Data * CH->MUL_R;
- }
-
- // update address register
- k = Addr + 1;
- CH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;
- Addr = CH->Addr >> PCM_STEP_SHIFT;
-
- for (; k < Addr; k++)
- {
- if (chip->RAM[k] == 0xFF)
- {
- CH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;
- break;
- }
- }
- }
- }
-
- if (chip->RAM[Addr] == 0xFF)
- {
- CH->Addr = CH->Loop_Addr << PCM_STEP_SHIFT;
- }
- }
- }
-#endif
-
- return 0;
-}
-
-
-void rf5c164_update(void *_chip, stream_sample_t **outputs, int samples)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
-
- PCM_Update(chip, outputs, samples);
-}
-
-void * device_start_rf5c164( int clock )
-{
- /* allocate memory for the chip */
- //rf5c164_state *chip = get_safe_token(device);
- struct pcm_chip_ *chip;
- int rate;
-
- chip = (struct pcm_chip_ *) malloc(sizeof(struct pcm_chip_));
- if (!chip) return chip;
-
- rate = clock / 384;
-
- PCM_Init(chip, rate);
- /* allocate the stream */
- //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
-
- return chip;
-}
-
-void device_stop_rf5c164(void *_chip)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- free(chip->RAM); chip->RAM = NULL;
- free(chip);
-}
-
-void device_reset_rf5c164(void *chip)
-{
- //struct pcm_chip_ *chip = &PCM_Chip[ChipID];
- PCM_Reset(chip);
-}
-
-void rf5c164_w(void *chip, offs_t offset, UINT8 data)
-{
- //struct pcm_chip_ *chip = &PCM_Chip[ChipID];
- PCM_Write_Reg(chip, offset, data);
-}
-
-void rf5c164_mem_w(void *_chip, offs_t offset, UINT8 data)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- chip->RAM[chip->Bank | offset] = data;
-}
-
-void rf5c164_write_ram(void *_chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
-
- if (DataStart >= chip->RAMSize)
- return;
- if (DataStart + DataLength > chip->RAMSize)
- DataLength = chip->RAMSize - DataStart;
-
- memcpy(chip->RAM + (chip->Bank | DataStart), RAMData, DataLength);
-
- return;
-}
-
-
-void rf5c164_set_mute_mask(void *_chip, UINT32 MuteMask)
-{
- struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
- unsigned char CurChn;
-
- for (CurChn = 0; CurChn < 8; CurChn ++)
- chip->Channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
-
- return;
-}
+/***********************************************************/
+/* */
+/* PCM.C : PCM RF5C164 emulator */
+/* */
+/* This source is a part of Gens project */
+/* Written by Stphane Dallongeville (gens@consolemul.com) */
+/* Copyright (c) 2002 by Stphane Dallongeville */
+/* */
+/***********************************************************/
+
+#include
+#include
+#include
+
+#include "scd_pcm.h"
+int PCM_Init(void *chip, int Rate);
+void PCM_Set_Rate(void *chip, int Rate);
+void PCM_Reset(void *chip);
+void PCM_Write_Reg(void *chip, unsigned int Reg, unsigned int Data);
+int PCM_Update(void *chip, int **buf, int Length);
+
+#define PCM_STEP_SHIFT 11
+
+static unsigned char VolTabIsInit = 0x00;
+static int PCM_Volume_Tab[256 * 256];
+
+//unsigned char Ram_PCM[64 * 1024];
+//int PCM_Enable;
+
+
+/**
+ * PCM_Init(): Initialize the PCM chip.
+ * @param Rate Sample rate.
+ * @return 0 if successful.
+ */
+int PCM_Init(void *_chip, int Rate)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ int i, j, out;
+
+ if (! VolTabIsInit)
+ {
+ for (i = 0; i < 0x100; i++)
+ {
+ for (j = 0; j < 0x100; j++)
+ {
+ if (i & 0x80)
+ {
+ out = -(i & 0x7F);
+ out *= j;
+ PCM_Volume_Tab[(j << 8) + i] = out;
+ }
+ else
+ {
+ out = i * j;
+ PCM_Volume_Tab[(j << 8) + i] = out;
+ }
+ }
+ }
+ VolTabIsInit = 0x01;
+ }
+
+ for (i = 0; i < 8; i ++)
+ chip->Channel[i].Muted = 0x00;
+
+ chip->RAMSize = 64 * 1024;
+ chip->RAM = (unsigned char*)malloc(chip->RAMSize);
+ PCM_Reset(chip);
+ PCM_Set_Rate(chip, Rate);
+
+ return 0;
+}
+
+
+/**
+ * PCM_Reset(): Reset the PCM chip.
+ */
+void PCM_Reset(void *_chip)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ int i;
+ struct pcm_chan_* chan;
+
+ // Clear the PCM memory.
+ memset(chip->RAM, 0x00, chip->RAMSize);
+
+ chip->Enable = 0;
+ chip->Cur_Chan = 0;
+ chip->Bank = 0;
+
+ /* clear channel registers */
+ for (i = 0; i < 8; i++)
+ {
+ chan = &chip->Channel[i];
+ chan->Enable = 0;
+ chan->ENV = 0;
+ chan->PAN = 0;
+ chan->St_Addr = 0;
+ chan->Addr = 0;
+ chan->Loop_Addr = 0;
+ chan->Step = 0;
+ chan->Step_B = 0;
+ chan->Data = 0;
+ }
+}
+
+
+/**
+ * PCM_Set_Rate(): Change the PCM sample rate.
+ * @param Rate New sample rate.
+ */
+void PCM_Set_Rate(void *_chip, int Rate)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ int i;
+
+ if (Rate == 0)
+ return;
+
+ //chip->Rate = (float) (32 * 1024) / (float) Rate;
+ chip->Rate = (float) (31.8 * 1024) / (float) Rate;
+
+ for (i = 0; i < 8; i++)
+ {
+ chip->Channel[i].Step =
+ (int) ((float) chip->Channel[i].Step_B * chip->Rate);
+ }
+}
+
+
+/**
+ * PCM_Write_Reg(): Write to a PCM register.
+ * @param Reg Register ID.
+ * @param Data Data to write.
+ */
+void PCM_Write_Reg(void *_chip, unsigned int Reg, unsigned int Data)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ int i;
+ struct pcm_chan_* chan = &chip->Channel[chip->Cur_Chan];
+
+ Data &= 0xFF;
+
+ switch (Reg)
+ {
+ case 0x00:
+ /* evelope register */
+ chan->ENV = Data;
+ chan->MUL_L = (Data * (chan->PAN & 0x0F)) >> 5;
+ chan->MUL_R = (Data * (chan->PAN >> 4)) >> 5;
+ break;
+
+ case 0x01:
+ /* pan register */
+ chan->PAN = Data;
+ chan->MUL_L = ((Data & 0x0F) * chan->ENV) >> 5;
+ chan->MUL_R = ((Data >> 4) * chan->ENV) >> 5;
+ break;
+
+ case 0x02:
+ /* frequency step (LB) registers */
+ chan->Step_B &= 0xFF00;
+ chan->Step_B += Data;
+ chan->Step = (int)((float)chan->Step_B * chip->Rate);
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Step low = %.2X Step calculated = %.8X",
+ // Data, chan->Step);
+ break;
+
+ case 0x03:
+ /* frequency step (HB) registers */
+ chan->Step_B &= 0x00FF;
+ chan->Step_B += Data << 8;
+ chan->Step = (int)((float)chan->Step_B * chip->Rate);
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Step high = %.2X Step calculated = %.8X",
+ // Data, chan->Step);
+ break;
+
+ case 0x04:
+ chan->Loop_Addr &= 0xFF00;
+ chan->Loop_Addr += Data;
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Loop low = %.2X Loop = %.8X",
+ // Data, chan->Loop_Addr);
+ break;
+
+ case 0x05:
+ /* loop address registers */
+ chan->Loop_Addr &= 0x00FF;
+ chan->Loop_Addr += Data << 8;
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Loop high = %.2X Loop = %.8X",
+ // Data, chan->Loop_Addr);
+ break;
+
+ case 0x06:
+ /* start address registers */
+ chan->St_Addr = Data << (PCM_STEP_SHIFT + 8);
+ //chan->Addr = chan->St_Addr;
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Start addr = %.2X New Addr = %.8X",
+ // Data, chan->Addr);
+ break;
+
+ case 0x07:
+ /* control register */
+ /* mod is H */
+ if (Data & 0x40)
+ {
+ /* select channel */
+ chip->Cur_Chan = Data & 0x07;
+ }
+ /* mod is L */
+ else
+ {
+ /* pcm ram bank select */
+ chip->Bank = (Data & 0x0F) << 12;
+ }
+
+ /* sounding bit */
+ if (Data & 0x80)
+ chip->Enable = 0xFF; // Used as mask
+ else
+ chip->Enable = 0;
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "General Enable = %.2X", Data);
+ break;
+
+ case 0x08:
+ /* sound on/off register */
+ Data ^= 0xFF;
+
+ //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
+ // "Channel Enable = %.2X", Data);
+
+ for (i = 0; i < 8; i++)
+ {
+ chan = &chip->Channel[i];
+ if (!chan->Enable)
+ chan->Addr = chan->St_Addr;
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ chip->Channel[i].Enable = Data & (1 << i);
+ }
+ }
+}
+
+
+/**
+ * PCM_Update(): Update the PCM buffer.
+ * @param buf PCM buffer.
+ * @param Length Buffer length.
+ */
+int PCM_Update(void *_chip, int **buf, int Length)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ int i, j;
+ int *bufL, *bufR; //, *volL, *volR;
+ unsigned int Addr, k;
+ struct pcm_chan_ *CH;
+
+ bufL = buf[0];
+ bufR = buf[1];
+
+ // clear buffers
+ memset(bufL, 0, Length * sizeof(int));
+ memset(bufR, 0, Length * sizeof(int));
+
+ // if PCM disable, no sound
+ if (!chip->Enable)
+ return 1;
+
+#if 0
+ // faster for short update
+ for (j = 0; j < Length; j++)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ CH = &(chip->Channel[i]);
+
+ // only loop when sounding and on
+ if (CH->Enable && ! CH->Muted)
+ {
+ Addr = CH->Addr >> PCM_STEP_SHIFT;
+
+ if (Addr & 0x10000)
+ {
+ for(k = CH->Old_Addr; k < 0x10000; k++)
+ {
+ if (chip->RAM[k] == 0xFF)
+ {
+ CH->Old_Addr = Addr = CH->Loop_Addr;
+ CH->Addr = Addr << PCM_STEP_SHIFT;
+ break;
+ }
+ }
+
+ if (Addr & 0x10000)
+ {
+ //CH->Addr -= CH->Step;
+ CH->Enable = 0;
+ break;
+ }
+ }
+ else
+ {
+ for(k = CH->Old_Addr; k <= Addr; k++)
+ {
+ if (chip->RAM[k] == 0xFF)
+ {
+ CH->Old_Addr = Addr = CH->Loop_Addr;
+ CH->Addr = Addr << PCM_STEP_SHIFT;
+ break;
+ }
+ }
+ }
+
+ // test for loop signal
+ if (chip->RAM[Addr] == 0xFF)
+ {
+ Addr = CH->Loop_Addr;
+ CH->Addr = Addr << PCM_STEP_SHIFT;
+ }
+
+ if (chip->RAM[Addr] & 0x80)
+ {
+ CH->Data = chip->RAM[Addr] & 0x7F;
+ bufL[j] -= CH->Data * CH->MUL_L;
+ bufR[j] -= CH->Data * CH->MUL_R;
+ }
+ else
+ {
+ CH->Data = chip->RAM[Addr];
+ bufL[j] += CH->Data * CH->MUL_L;
+ bufR[j] += CH->Data * CH->MUL_R;
+ }
+
+ // update address register
+ //CH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;
+ CH->Addr += CH->Step;
+ CH->Old_Addr = Addr + 1;
+ }
+ }
+ }
+#endif
+
+#if 1
+ // for long update
+ for (i = 0; i < 8; i++)
+ {
+ CH = &(chip->Channel[i]);
+
+ // only loop when sounding and on
+ if (CH->Enable && ! CH->Muted)
+ {
+ Addr = CH->Addr >> PCM_STEP_SHIFT;
+ //volL = &(PCM_Volume_Tab[CH->MUL_L << 8]);
+ //volR = &(PCM_Volume_Tab[CH->MUL_R << 8]);
+
+ for (j = 0; j < Length; j++)
+ {
+ // test for loop signal
+ if (chip->RAM[Addr] == 0xFF)
+ {
+ CH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;
+ if (chip->RAM[Addr] == 0xFF)
+ break;
+ else
+ j--;
+ }
+ else
+ {
+ if (chip->RAM[Addr] & 0x80)
+ {
+ CH->Data = chip->RAM[Addr] & 0x7F;
+ bufL[j] -= CH->Data * CH->MUL_L;
+ bufR[j] -= CH->Data * CH->MUL_R;
+ }
+ else
+ {
+ CH->Data = chip->RAM[Addr];
+ bufL[j] += CH->Data * CH->MUL_L;
+ bufR[j] += CH->Data * CH->MUL_R;
+ }
+
+ // update address register
+ k = Addr + 1;
+ CH->Addr = (CH->Addr + CH->Step) & 0x7FFFFFF;
+ Addr = CH->Addr >> PCM_STEP_SHIFT;
+
+ for (; k < Addr; k++)
+ {
+ if (chip->RAM[k] == 0xFF)
+ {
+ CH->Addr = (Addr = CH->Loop_Addr) << PCM_STEP_SHIFT;
+ break;
+ }
+ }
+ }
+ }
+
+ if (chip->RAM[Addr] == 0xFF)
+ {
+ CH->Addr = CH->Loop_Addr << PCM_STEP_SHIFT;
+ }
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+void rf5c164_update(void *_chip, stream_sample_t **outputs, int samples)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+
+ PCM_Update(chip, outputs, samples);
+}
+
+void * device_start_rf5c164( int clock )
+{
+ /* allocate memory for the chip */
+ //rf5c164_state *chip = get_safe_token(device);
+ struct pcm_chip_ *chip;
+ int rate;
+
+ chip = (struct pcm_chip_ *) malloc(sizeof(struct pcm_chip_));
+ if (!chip) return chip;
+
+ rate = clock / 384;
+
+ PCM_Init(chip, rate);
+ /* allocate the stream */
+ //chip->stream = stream_create(device, 0, 2, device->clock / 384, chip, rf5c68_update);
+
+ return chip;
+}
+
+void device_stop_rf5c164(void *_chip)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ free(chip->RAM); chip->RAM = NULL;
+ free(chip);
+}
+
+void device_reset_rf5c164(void *chip)
+{
+ //struct pcm_chip_ *chip = &PCM_Chip[ChipID];
+ PCM_Reset(chip);
+}
+
+void rf5c164_w(void *chip, offs_t offset, UINT8 data)
+{
+ //struct pcm_chip_ *chip = &PCM_Chip[ChipID];
+ PCM_Write_Reg(chip, offset, data);
+}
+
+void rf5c164_mem_w(void *_chip, offs_t offset, UINT8 data)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ chip->RAM[chip->Bank | offset] = data;
+}
+
+void rf5c164_write_ram(void *_chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+
+ if (DataStart >= chip->RAMSize)
+ return;
+ if (DataStart + DataLength > chip->RAMSize)
+ DataLength = chip->RAMSize - DataStart;
+
+ memcpy(chip->RAM + (chip->Bank | DataStart), RAMData, DataLength);
+
+ return;
+}
+
+
+void rf5c164_set_mute_mask(void *_chip, UINT32 MuteMask)
+{
+ struct pcm_chip_ *chip = (struct pcm_chip_ *) _chip;
+ unsigned char CurChn;
+
+ for (CurChn = 0; CurChn < 8; CurChn ++)
+ chip->Channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
+
+ return;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/scd_pcm.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/scd_pcm.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/scd_pcm.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/scd_pcm.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,57 +1,57 @@
-#include "mamedef.h"
-
-struct pcm_chan_ {
- unsigned int ENV; /* envelope register */
- unsigned int PAN; /* pan register */
- unsigned int MUL_L; /* envelope & pan product letf */
- unsigned int MUL_R; /* envelope & pan product right */
- unsigned int St_Addr; /* start address register */
- unsigned int Loop_Addr; /* loop address register */
- unsigned int Addr; /* current address register */
- unsigned int Step; /* frequency register */
- unsigned int Step_B; /* frequency register binaire */
- unsigned int Enable; /* channel on/off register */
- int Data; /* wave data */
- unsigned int Muted;
-};
-
-struct pcm_chip_
-{
- float Rate;
- int Enable;
- int Cur_Chan;
- int Bank;
-
- struct pcm_chan_ Channel[8];
-
- unsigned long int RAMSize;
- unsigned char* RAM;
-};
-
-//extern struct pcm_chip_ PCM_Chip;
-//extern unsigned char Ram_PCM[64 * 1024];
-//extern int PCM_Enable;
-
-//int PCM_Init(int Rate);
-//void PCM_Set_Rate(int Rate);
-//void PCM_Reset(void);
-//void PCM_Write_Reg(unsigned int Reg, unsigned int Data);
-//int PCM_Update(int **buf, int Length);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void rf5c164_update(void *chip, stream_sample_t **outputs, int samples);
-void * device_start_rf5c164(int clock);
-void device_stop_rf5c164(void *chip);
-void device_reset_rf5c164(void *chip);
-void rf5c164_w(void *chip, offs_t offset, UINT8 data);
-void rf5c164_mem_w(void *chip, offs_t offset, UINT8 data);
-void rf5c164_write_ram(void *chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);
-
-void rf5c164_set_mute_mask(void *chip, UINT32 MuteMask);
-
-#ifdef __cplusplus
-}
-#endif
+#include "mamedef.h"
+
+struct pcm_chan_ {
+ unsigned int ENV; /* envelope register */
+ unsigned int PAN; /* pan register */
+ unsigned int MUL_L; /* envelope & pan product letf */
+ unsigned int MUL_R; /* envelope & pan product right */
+ unsigned int St_Addr; /* start address register */
+ unsigned int Loop_Addr; /* loop address register */
+ unsigned int Addr; /* current address register */
+ unsigned int Step; /* frequency register */
+ unsigned int Step_B; /* frequency register binaire */
+ unsigned int Enable; /* channel on/off register */
+ int Data; /* wave data */
+ unsigned int Muted;
+};
+
+struct pcm_chip_
+{
+ float Rate;
+ int Enable;
+ int Cur_Chan;
+ int Bank;
+
+ struct pcm_chan_ Channel[8];
+
+ unsigned long int RAMSize;
+ unsigned char* RAM;
+};
+
+//extern struct pcm_chip_ PCM_Chip;
+//extern unsigned char Ram_PCM[64 * 1024];
+//extern int PCM_Enable;
+
+//int PCM_Init(int Rate);
+//void PCM_Set_Rate(int Rate);
+//void PCM_Reset(void);
+//void PCM_Write_Reg(unsigned int Reg, unsigned int Data);
+//int PCM_Update(int **buf, int Length);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void rf5c164_update(void *chip, stream_sample_t **outputs, int samples);
+void * device_start_rf5c164(int clock);
+void device_stop_rf5c164(void *chip);
+void device_reset_rf5c164(void *chip);
+void rf5c164_w(void *chip, offs_t offset, UINT8 data);
+void rf5c164_mem_w(void *chip, offs_t offset, UINT8 data);
+void rf5c164_write_ram(void *chip, offs_t DataStart, offs_t DataLength, const UINT8* RAMData);
+
+void rf5c164_set_mute_mask(void *chip, UINT32 MuteMask);
+
+#ifdef __cplusplus
+}
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/segapcm.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/segapcm.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/segapcm.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/segapcm.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,384 +1,384 @@
-/*********************************************************/
-/* SEGA 16ch 8bit PCM */
-/*********************************************************/
-
-#include
-#include
-#include
-//#include "sndintrf.h"
-//#include "streams.h"
-#include "segapcm.h"
-
-
-typedef struct _segapcm_state segapcm_state;
-struct _segapcm_state
-{
- UINT8 *ram;
- UINT8 low[16];
- UINT32 ROMSize;
- UINT8 *rom;
-#ifdef _DEBUG
- UINT8 *romusage;
-#endif
- int bankshift;
- int bankmask;
- int rgnmask;
- sega_pcm_interface intf;
- UINT8 Muted[16];
- //sound_stream * stream;
-};
-
-UINT8 SegaPCM_NewCore = 0x00;
-
-/*INLINE segapcm_state *get_safe_token(const device_config *device)
-{
- assert(device != NULL);
- assert(device->token != NULL);
- assert(device->type == SOUND);
- assert(sound_get_type(device) == SOUND_SEGAPCM);
- return (segapcm_state *)device->token;
-}*/
-
-//static STREAM_UPDATE( SEGAPCM_update )
-void SEGAPCM_update(void *chip, stream_sample_t **outputs, int samples)
-{
- //segapcm_state *spcm = (segapcm_state *)param;
- segapcm_state *spcm = (segapcm_state *) chip;
- int rgnmask = spcm->rgnmask;
- int ch;
-
- /* clear the buffers */
- memset(outputs[0], 0, samples*sizeof(stream_sample_t));
- memset(outputs[1], 0, samples*sizeof(stream_sample_t));
-
- // reg function
- // ------------------------------------------------
- // 0x00 ?
- // 0x01 ?
- // 0x02 volume left
- // 0x03 volume right
- // 0x04 loop address (08-15)
- // 0x05 loop address (16-23)
- // 0x06 end address
- // 0x07 address delta
- // 0x80 ?
- // 0x81 ?
- // 0x82 ?
- // 0x83 ?
- // 0x84 current address (08-15), 00-07 is internal?
- // 0x85 current address (16-23)
- // 0x86 bit 0: channel disable?
- // bit 1: loop disable
- // other bits: bank
- // 0x87 ?
-
- /* loop over channels */
- for (ch = 0; ch < 16; ch++)
- {
-if (! SegaPCM_NewCore)
-{
- /* only process active channels */
- if (!(spcm->ram[0x86+8*ch] & 1) && ! spcm->Muted[ch])
- {
- UINT8 *base = spcm->ram+8*ch;
- UINT8 flags = base[0x86];
- const UINT8 *rom = spcm->rom + ((flags & spcm->bankmask) << spcm->bankshift);
-#ifdef _DEBUG
- const UINT8 *romusage = spcm->romusage + ((flags & spcm->bankmask) << spcm->bankshift);
-#endif
- UINT32 addr = (base[5] << 16) | (base[4] << 8) | spcm->low[ch];
- UINT16 loop = (base[0x85] << 8) | base[0x84];
- UINT8 end = base[6] + 1;
- UINT8 delta = base[7];
- UINT8 voll = base[2];
- UINT8 volr = base[3];
- int i;
-
- /* loop over samples on this channel */
- for (i = 0; i < samples; i++)
- {
- INT8 v = 0;
-
- /* handle looping if we've hit the end */
- if ((addr >> 16) == end)
- {
- if (!(flags & 2))
- addr = loop << 8;
- else
- {
- flags |= 1;
- break;
- }
- }
-
- /* fetch the sample */
- v = rom[(addr >> 8) & rgnmask] - 0x80;
-#ifdef _DEBUG
- if (romusage[(addr >> 8) & rgnmask] == 0xFF && (voll || volr))
- printf("Access to empty ROM section! (0x%06lX)\n",
- ((flags & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);
-#endif
-
- /* apply panning and advance */
- outputs[0][i] += v * voll;
- outputs[1][i] += v * volr;
- addr += delta;
- }
-
- /* store back the updated address and info */
- base[0x86] = flags;
- base[4] = addr >> 8;
- base[5] = addr >> 16;
- spcm->low[ch] = flags & 1 ? 0 : addr;
- }
-}
-else
-{
- UINT8 *regs = spcm->ram+8*ch;
-
- /* only process active channels */
- if (!(regs[0x86] & 1) && ! spcm->Muted[ch])
- {
- const UINT8 *rom = spcm->rom + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);
-#ifdef _DEBUG
- const UINT8 *romusage = spcm->romusage + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);
-#endif
- UINT32 addr = (regs[0x85] << 16) | (regs[0x84] << 8) | spcm->low[ch];
- UINT32 loop = (regs[0x05] << 16) | (regs[0x04] << 8);
- UINT8 end = regs[6] + 1;
- int i;
-
- /* loop over samples on this channel */
- for (i = 0; i < samples; i++)
- {
- INT8 v = 0;
-
- /* handle looping if we've hit the end */
- if ((addr >> 16) == end)
- {
- if (regs[0x86] & 2)
- {
- regs[0x86] |= 1;
- break;
- }
- else addr = loop;
- }
-
- /* fetch the sample */
- v = rom[(addr >> 8) & rgnmask] - 0x80;
-#ifdef _DEBUG
- if (romusage[(addr >> 8) & rgnmask] == 0xFF && (regs[2] || regs[3]))
- printf("Access to empty ROM section! (0x%06lX)\n",
- ((regs[0x86] & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);
-#endif
-
- /* apply panning and advance */
- outputs[0][i] += v * regs[2];
- outputs[1][i] += v * regs[3];
- addr = (addr + regs[7]) & 0xffffff;
- }
-
- /* store back the updated address */
- regs[0x84] = addr >> 8;
- regs[0x85] = addr >> 16;
- spcm->low[ch] = regs[0x86] & 1 ? 0 : addr;
- }
-}
- }
-}
-
-//static DEVICE_START( segapcm )
-void * device_start_segapcm(int intf_bank)
-{
- const UINT32 STD_ROM_SIZE = 0x80000;
- //const sega_pcm_interface *intf = (const sega_pcm_interface *)device->static_config;
- sega_pcm_interface *intf;
- int mask, rom_mask, len;
- //segapcm_state *spcm = get_safe_token(device);
- segapcm_state *spcm;
-
- spcm = (segapcm_state *) malloc(sizeof(segapcm_state));
- if (!spcm) return spcm;
-
- intf = &spcm->intf;
- intf->bank = intf_bank;
-
- //spcm->rom = (const UINT8 *)device->region;
- //spcm->ram = auto_alloc_array(device->machine, UINT8, 0x800);
- spcm->ROMSize = STD_ROM_SIZE;
- spcm->rom = (UINT8*) malloc(STD_ROM_SIZE);
-#ifdef _DEBUG
- spcm->romusage = (UINT8*) malloc(STD_ROM_SIZE);
-#endif
- spcm->ram = (UINT8*) malloc(0x800);
-
- memset(spcm->rom, 0xFF, STD_ROM_SIZE);
-#ifdef _DEBUG
- memset(spcm->romusage, 0xFF, STD_ROM_SIZE);
-#endif
- //memset(spcm->ram, 0xff, 0x800); // RAM Clear is done at device_reset
-
- spcm->bankshift = (UINT8)(intf->bank);
- mask = intf->bank >> 16;
- if(!mask)
- mask = BANK_MASK7>>16;
-
- len = STD_ROM_SIZE;
- spcm->rgnmask = len - 1;
- for(rom_mask = 1; rom_mask < len; rom_mask *= 2);
- rom_mask--;
-
- spcm->bankmask = mask & (rom_mask >> spcm->bankshift);
-
- //spcm->stream = stream_create(device, 0, 2, device->clock / 128, spcm, SEGAPCM_update);
-
- //state_save_register_device_item_array(device, 0, spcm->low);
- //state_save_register_device_item_pointer(device, 0, spcm->ram, 0x800);
-
- for (mask = 0; mask < 16; mask ++)
- spcm->Muted[mask] = 0x00;
-
- return spcm;
-}
-
-//static DEVICE_STOP( segapcm )
-void device_stop_segapcm(void *chip)
-{
- //segapcm_state *spcm = get_safe_token(device);
- segapcm_state *spcm = (segapcm_state *) chip;
- free(spcm->rom); spcm->rom = NULL;
-#ifdef _DEBUG
- free(spcm->romusage);
-#endif
- free(spcm->ram);
-
- free(spcm);
-}
-
-//static DEVICE_RESET( segapcm )
-void device_reset_segapcm(void *chip)
-{
- //segapcm_state *spcm = get_safe_token(device);
- segapcm_state *spcm = (segapcm_state *) chip;
-
- memset(spcm->ram, 0xFF, 0x800);
-
- return;
-}
-
-
-//WRITE8_DEVICE_HANDLER( sega_pcm_w )
-void sega_pcm_w(void *chip, offs_t offset, UINT8 data)
-{
- //segapcm_state *spcm = get_safe_token(device);
- segapcm_state *spcm = (segapcm_state *) chip;
- //stream_update(spcm->stream);
-
- spcm->ram[offset & 0x07ff] = data;
-}
-
-//READ8_DEVICE_HANDLER( sega_pcm_r )
-UINT8 sega_pcm_r(void *chip, offs_t offset)
-{
- //segapcm_state *spcm = get_safe_token(device);
- segapcm_state *spcm = (segapcm_state *) chip;
- //stream_update(spcm->stream);
- return spcm->ram[offset & 0x07ff];
-}
-
-void sega_pcm_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
- const UINT8* ROMData)
-{
- segapcm_state *spcm = (segapcm_state *) chip;
-
- if (spcm->ROMSize != ROMSize)
- {
- unsigned long int mask, rom_mask;
-
- spcm->rom = (UINT8*)realloc(spcm->rom, ROMSize);
-#ifdef _DEBUG
- spcm->romusage = (UINT8*)realloc(spcm->romusage, ROMSize);
-#endif
- spcm->ROMSize = ROMSize;
- memset(spcm->rom, 0xFF, ROMSize);
-#ifdef _DEBUG
- memset(spcm->romusage, 0xFF, ROMSize);
-#endif
-
- // recalculate bankmask
- mask = spcm->intf.bank >> 16;
- if (! mask)
- mask = BANK_MASK7 >> 16;
-
- spcm->rgnmask = ROMSize - 1;
- for (rom_mask = 1; rom_mask < ROMSize; rom_mask *= 2);
- rom_mask --;
-
- spcm->bankmask = mask & (rom_mask >> spcm->bankshift);
- }
- if (DataStart > ROMSize)
- return;
- if (DataStart + DataLength > ROMSize)
- DataLength = ROMSize - DataStart;
-
- memcpy(spcm->rom + DataStart, ROMData, DataLength);
-#ifdef _DEBUG
- memset(spcm->romusage + DataStart, 0x00, DataLength);
-#endif
-
- return;
-}
-
-
-/*void sega_pcm_fwrite_romusage(UINT8 ChipID)
-{
- segapcm_state *spcm = &SPCMData[ChipID];
-
- FILE* hFile;
-
- hFile = fopen("SPCM_ROMUsage.bin", "wb");
- if (hFile == NULL)
- return;
-
- fwrite(spcm->romusage, 0x01, spcm->ROMSize, hFile);
-
- fclose(hFile);
- return;
-}*/
-
-void segapcm_set_mute_mask(void *chip, UINT32 MuteMask)
-{
- segapcm_state *spcm = (segapcm_state *) chip;
- unsigned char CurChn;
-
- for (CurChn = 0; CurChn < 16; CurChn ++)
- spcm->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;
-
- return;
-}
-
-
-/**************************************************************************
- * Generic get_info
- **************************************************************************/
-
-/*DEVICE_GET_INFO( segapcm )
-{
- switch (state)
- {
- // --- the following bits of info are returned as 64-bit signed integers ---
- case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(segapcm_state); break;
-
- // --- the following bits of info are returned as pointers to data or functions ---
- case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( segapcm ); break;
- case DEVINFO_FCT_STOP: // Nothing break;
- case DEVINFO_FCT_RESET: // Nothing break;
-
- // --- the following bits of info are returned as NULL-terminated strings ---
- case DEVINFO_STR_NAME: strcpy(info->s, "Sega PCM"); break;
- case DEVINFO_STR_FAMILY: strcpy(info->s, "Sega custom"); break;
- case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
- case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
- case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
- }
-}*/
+/*********************************************************/
+/* SEGA 16ch 8bit PCM */
+/*********************************************************/
+
+#include
+#include
+#include
+//#include "sndintrf.h"
+//#include "streams.h"
+#include "segapcm.h"
+
+
+typedef struct _segapcm_state segapcm_state;
+struct _segapcm_state
+{
+ UINT8 *ram;
+ UINT8 low[16];
+ UINT32 ROMSize;
+ UINT8 *rom;
+#ifdef _DEBUG
+ UINT8 *romusage;
+#endif
+ int bankshift;
+ int bankmask;
+ int rgnmask;
+ sega_pcm_interface intf;
+ UINT8 Muted[16];
+ //sound_stream * stream;
+};
+
+UINT8 SegaPCM_NewCore = 0x00;
+
+/*INLINE segapcm_state *get_safe_token(const device_config *device)
+{
+ assert(device != NULL);
+ assert(device->token != NULL);
+ assert(device->type == SOUND);
+ assert(sound_get_type(device) == SOUND_SEGAPCM);
+ return (segapcm_state *)device->token;
+}*/
+
+//static STREAM_UPDATE( SEGAPCM_update )
+void SEGAPCM_update(void *chip, stream_sample_t **outputs, int samples)
+{
+ //segapcm_state *spcm = (segapcm_state *)param;
+ segapcm_state *spcm = (segapcm_state *) chip;
+ int rgnmask = spcm->rgnmask;
+ int ch;
+
+ /* clear the buffers */
+ memset(outputs[0], 0, samples*sizeof(stream_sample_t));
+ memset(outputs[1], 0, samples*sizeof(stream_sample_t));
+
+ // reg function
+ // ------------------------------------------------
+ // 0x00 ?
+ // 0x01 ?
+ // 0x02 volume left
+ // 0x03 volume right
+ // 0x04 loop address (08-15)
+ // 0x05 loop address (16-23)
+ // 0x06 end address
+ // 0x07 address delta
+ // 0x80 ?
+ // 0x81 ?
+ // 0x82 ?
+ // 0x83 ?
+ // 0x84 current address (08-15), 00-07 is internal?
+ // 0x85 current address (16-23)
+ // 0x86 bit 0: channel disable?
+ // bit 1: loop disable
+ // other bits: bank
+ // 0x87 ?
+
+ /* loop over channels */
+ for (ch = 0; ch < 16; ch++)
+ {
+if (! SegaPCM_NewCore)
+{
+ /* only process active channels */
+ if (!(spcm->ram[0x86+8*ch] & 1) && ! spcm->Muted[ch])
+ {
+ UINT8 *base = spcm->ram+8*ch;
+ UINT8 flags = base[0x86];
+ const UINT8 *rom = spcm->rom + ((flags & spcm->bankmask) << spcm->bankshift);
+#ifdef _DEBUG
+ const UINT8 *romusage = spcm->romusage + ((flags & spcm->bankmask) << spcm->bankshift);
+#endif
+ UINT32 addr = (base[5] << 16) | (base[4] << 8) | spcm->low[ch];
+ UINT16 loop = (base[0x85] << 8) | base[0x84];
+ UINT8 end = base[6] + 1;
+ UINT8 delta = base[7];
+ UINT8 voll = base[2];
+ UINT8 volr = base[3];
+ int i;
+
+ /* loop over samples on this channel */
+ for (i = 0; i < samples; i++)
+ {
+ INT8 v = 0;
+
+ /* handle looping if we've hit the end */
+ if ((addr >> 16) == end)
+ {
+ if (!(flags & 2))
+ addr = loop << 8;
+ else
+ {
+ flags |= 1;
+ break;
+ }
+ }
+
+ /* fetch the sample */
+ v = rom[(addr >> 8) & rgnmask] - 0x80;
+#ifdef _DEBUG
+ if (romusage[(addr >> 8) & rgnmask] == 0xFF && (voll || volr))
+ printf("Access to empty ROM section! (0x%06lX)\n",
+ ((flags & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);
+#endif
+
+ /* apply panning and advance */
+ outputs[0][i] += v * voll;
+ outputs[1][i] += v * volr;
+ addr += delta;
+ }
+
+ /* store back the updated address and info */
+ base[0x86] = flags;
+ base[4] = addr >> 8;
+ base[5] = addr >> 16;
+ spcm->low[ch] = flags & 1 ? 0 : addr;
+ }
+}
+else
+{
+ UINT8 *regs = spcm->ram+8*ch;
+
+ /* only process active channels */
+ if (!(regs[0x86] & 1) && ! spcm->Muted[ch])
+ {
+ const UINT8 *rom = spcm->rom + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);
+#ifdef _DEBUG
+ const UINT8 *romusage = spcm->romusage + ((regs[0x86] & spcm->bankmask) << spcm->bankshift);
+#endif
+ UINT32 addr = (regs[0x85] << 16) | (regs[0x84] << 8) | spcm->low[ch];
+ UINT32 loop = (regs[0x05] << 16) | (regs[0x04] << 8);
+ UINT8 end = regs[6] + 1;
+ int i;
+
+ /* loop over samples on this channel */
+ for (i = 0; i < samples; i++)
+ {
+ INT8 v = 0;
+
+ /* handle looping if we've hit the end */
+ if ((addr >> 16) == end)
+ {
+ if (regs[0x86] & 2)
+ {
+ regs[0x86] |= 1;
+ break;
+ }
+ else addr = loop;
+ }
+
+ /* fetch the sample */
+ v = rom[(addr >> 8) & rgnmask] - 0x80;
+#ifdef _DEBUG
+ if (romusage[(addr >> 8) & rgnmask] == 0xFF && (regs[2] || regs[3]))
+ printf("Access to empty ROM section! (0x%06lX)\n",
+ ((regs[0x86] & spcm->bankmask) << spcm->bankshift) + (addr >> 8) & rgnmask);
+#endif
+
+ /* apply panning and advance */
+ outputs[0][i] += v * regs[2];
+ outputs[1][i] += v * regs[3];
+ addr = (addr + regs[7]) & 0xffffff;
+ }
+
+ /* store back the updated address */
+ regs[0x84] = addr >> 8;
+ regs[0x85] = addr >> 16;
+ spcm->low[ch] = regs[0x86] & 1 ? 0 : addr;
+ }
+}
+ }
+}
+
+//static DEVICE_START( segapcm )
+void * device_start_segapcm(int intf_bank)
+{
+ const UINT32 STD_ROM_SIZE = 0x80000;
+ //const sega_pcm_interface *intf = (const sega_pcm_interface *)device->static_config;
+ sega_pcm_interface *intf;
+ int mask, rom_mask, len;
+ //segapcm_state *spcm = get_safe_token(device);
+ segapcm_state *spcm;
+
+ spcm = (segapcm_state *) malloc(sizeof(segapcm_state));
+ if (!spcm) return spcm;
+
+ intf = &spcm->intf;
+ intf->bank = intf_bank;
+
+ //spcm->rom = (const UINT8 *)device->region;
+ //spcm->ram = auto_alloc_array(device->machine, UINT8, 0x800);
+ spcm->ROMSize = STD_ROM_SIZE;
+ spcm->rom = (UINT8*) malloc(STD_ROM_SIZE);
+#ifdef _DEBUG
+ spcm->romusage = (UINT8*) malloc(STD_ROM_SIZE);
+#endif
+ spcm->ram = (UINT8*) malloc(0x800);
+
+ memset(spcm->rom, 0xFF, STD_ROM_SIZE);
+#ifdef _DEBUG
+ memset(spcm->romusage, 0xFF, STD_ROM_SIZE);
+#endif
+ //memset(spcm->ram, 0xff, 0x800); // RAM Clear is done at device_reset
+
+ spcm->bankshift = (UINT8)(intf->bank);
+ mask = intf->bank >> 16;
+ if(!mask)
+ mask = BANK_MASK7>>16;
+
+ len = STD_ROM_SIZE;
+ spcm->rgnmask = len - 1;
+ for(rom_mask = 1; rom_mask < len; rom_mask *= 2);
+ rom_mask--;
+
+ spcm->bankmask = mask & (rom_mask >> spcm->bankshift);
+
+ //spcm->stream = stream_create(device, 0, 2, device->clock / 128, spcm, SEGAPCM_update);
+
+ //state_save_register_device_item_array(device, 0, spcm->low);
+ //state_save_register_device_item_pointer(device, 0, spcm->ram, 0x800);
+
+ for (mask = 0; mask < 16; mask ++)
+ spcm->Muted[mask] = 0x00;
+
+ return spcm;
+}
+
+//static DEVICE_STOP( segapcm )
+void device_stop_segapcm(void *chip)
+{
+ //segapcm_state *spcm = get_safe_token(device);
+ segapcm_state *spcm = (segapcm_state *) chip;
+ free(spcm->rom); spcm->rom = NULL;
+#ifdef _DEBUG
+ free(spcm->romusage);
+#endif
+ free(spcm->ram);
+
+ free(spcm);
+}
+
+//static DEVICE_RESET( segapcm )
+void device_reset_segapcm(void *chip)
+{
+ //segapcm_state *spcm = get_safe_token(device);
+ segapcm_state *spcm = (segapcm_state *) chip;
+
+ memset(spcm->ram, 0xFF, 0x800);
+
+ return;
+}
+
+
+//WRITE8_DEVICE_HANDLER( sega_pcm_w )
+void sega_pcm_w(void *chip, offs_t offset, UINT8 data)
+{
+ //segapcm_state *spcm = get_safe_token(device);
+ segapcm_state *spcm = (segapcm_state *) chip;
+ //stream_update(spcm->stream);
+
+ spcm->ram[offset & 0x07ff] = data;
+}
+
+//READ8_DEVICE_HANDLER( sega_pcm_r )
+UINT8 sega_pcm_r(void *chip, offs_t offset)
+{
+ //segapcm_state *spcm = get_safe_token(device);
+ segapcm_state *spcm = (segapcm_state *) chip;
+ //stream_update(spcm->stream);
+ return spcm->ram[offset & 0x07ff];
+}
+
+void sega_pcm_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
+ const UINT8* ROMData)
+{
+ segapcm_state *spcm = (segapcm_state *) chip;
+
+ if (spcm->ROMSize != ROMSize)
+ {
+ unsigned long int mask, rom_mask;
+
+ spcm->rom = (UINT8*)realloc(spcm->rom, ROMSize);
+#ifdef _DEBUG
+ spcm->romusage = (UINT8*)realloc(spcm->romusage, ROMSize);
+#endif
+ spcm->ROMSize = ROMSize;
+ memset(spcm->rom, 0xFF, ROMSize);
+#ifdef _DEBUG
+ memset(spcm->romusage, 0xFF, ROMSize);
+#endif
+
+ // recalculate bankmask
+ mask = spcm->intf.bank >> 16;
+ if (! mask)
+ mask = BANK_MASK7 >> 16;
+
+ spcm->rgnmask = ROMSize - 1;
+ for (rom_mask = 1; rom_mask < ROMSize; rom_mask *= 2);
+ rom_mask --;
+
+ spcm->bankmask = mask & (rom_mask >> spcm->bankshift);
+ }
+ if (DataStart > ROMSize)
+ return;
+ if (DataStart + DataLength > ROMSize)
+ DataLength = ROMSize - DataStart;
+
+ memcpy(spcm->rom + DataStart, ROMData, DataLength);
+#ifdef _DEBUG
+ memset(spcm->romusage + DataStart, 0x00, DataLength);
+#endif
+
+ return;
+}
+
+
+/*void sega_pcm_fwrite_romusage(UINT8 ChipID)
+{
+ segapcm_state *spcm = &SPCMData[ChipID];
+
+ FILE* hFile;
+
+ hFile = fopen("SPCM_ROMUsage.bin", "wb");
+ if (hFile == NULL)
+ return;
+
+ fwrite(spcm->romusage, 0x01, spcm->ROMSize, hFile);
+
+ fclose(hFile);
+ return;
+}*/
+
+void segapcm_set_mute_mask(void *chip, UINT32 MuteMask)
+{
+ segapcm_state *spcm = (segapcm_state *) chip;
+ unsigned char CurChn;
+
+ for (CurChn = 0; CurChn < 16; CurChn ++)
+ spcm->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;
+
+ return;
+}
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+/*DEVICE_GET_INFO( segapcm )
+{
+ switch (state)
+ {
+ // --- the following bits of info are returned as 64-bit signed integers ---
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(segapcm_state); break;
+
+ // --- the following bits of info are returned as pointers to data or functions ---
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( segapcm ); break;
+ case DEVINFO_FCT_STOP: // Nothing break;
+ case DEVINFO_FCT_RESET: // Nothing break;
+
+ // --- the following bits of info are returned as NULL-terminated strings ---
+ case DEVINFO_STR_NAME: strcpy(info->s, "Sega PCM"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Sega custom"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+ }
+}*/
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,77 +1,77 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "SegaPcm_Emu.h"
-#include "segapcm.h"
-
-SegaPcm_Emu::SegaPcm_Emu() { chip = 0; }
-
-SegaPcm_Emu::~SegaPcm_Emu()
-{
- if ( chip ) device_stop_segapcm( chip );
-}
-
-int SegaPcm_Emu::set_rate( int intf_type )
-{
- if ( chip )
- {
- device_stop_segapcm( chip );
- chip = 0;
- }
-
- chip = device_start_segapcm( intf_type );
- if ( !chip )
- return 1;
-
- reset();
- return 0;
-}
-
-void SegaPcm_Emu::reset()
-{
- device_reset_segapcm( chip );
- segapcm_set_mute_mask( chip, 0 );
-}
-
-void SegaPcm_Emu::write( int addr, int data )
-{
- sega_pcm_w( chip, addr, data );
-}
-
-void SegaPcm_Emu::write_rom( int size, int start, int length, void * data )
-{
- sega_pcm_write_rom( chip, size, start, length, (const UINT8 *) data );
-}
-
-void SegaPcm_Emu::mute_voices( int mask )
-{
- segapcm_set_mute_mask( chip, mask );
-}
-
-void SegaPcm_Emu::run( int pair_count, sample_t* out )
-{
- stream_sample_t bufL[ 1024 ];
- stream_sample_t bufR[ 1024 ];
- stream_sample_t * buffers[2] = { bufL, bufR };
-
- while (pair_count > 0)
- {
- int todo = pair_count;
- if (todo > 1024) todo = 1024;
- SEGAPCM_update( chip, buffers, todo );
-
- for (int i = 0; i < todo; i++)
- {
- int output_l = bufL [i];
- int output_r = bufR [i];
- output_l += out [0];
- output_r += out [1];
- if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
- if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
- out [0] = output_l;
- out [1] = output_r;
- out += 2;
- }
-
- pair_count -= todo;
- }
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "SegaPcm_Emu.h"
+#include "segapcm.h"
+
+SegaPcm_Emu::SegaPcm_Emu() { chip = 0; }
+
+SegaPcm_Emu::~SegaPcm_Emu()
+{
+ if ( chip ) device_stop_segapcm( chip );
+}
+
+int SegaPcm_Emu::set_rate( int intf_type )
+{
+ if ( chip )
+ {
+ device_stop_segapcm( chip );
+ chip = 0;
+ }
+
+ chip = device_start_segapcm( intf_type );
+ if ( !chip )
+ return 1;
+
+ reset();
+ return 0;
+}
+
+void SegaPcm_Emu::reset()
+{
+ device_reset_segapcm( chip );
+ segapcm_set_mute_mask( chip, 0 );
+}
+
+void SegaPcm_Emu::write( int addr, int data )
+{
+ sega_pcm_w( chip, addr, data );
+}
+
+void SegaPcm_Emu::write_rom( int size, int start, int length, void * data )
+{
+ sega_pcm_write_rom( chip, size, start, length, (const UINT8 *) data );
+}
+
+void SegaPcm_Emu::mute_voices( int mask )
+{
+ segapcm_set_mute_mask( chip, mask );
+}
+
+void SegaPcm_Emu::run( int pair_count, sample_t* out )
+{
+ stream_sample_t bufL[ 1024 ];
+ stream_sample_t bufR[ 1024 ];
+ stream_sample_t * buffers[2] = { bufL, bufR };
+
+ while (pair_count > 0)
+ {
+ int todo = pair_count;
+ if (todo > 1024) todo = 1024;
+ SEGAPCM_update( chip, buffers, todo );
+
+ for (int i = 0; i < todo; i++)
+ {
+ int output_l = bufL [i];
+ int output_r = bufR [i];
+ output_l += out [0];
+ output_r += out [1];
+ if ( (short)output_l != output_l ) output_l = 0x7FFF ^ ( output_l >> 31 );
+ if ( (short)output_r != output_r ) output_r = 0x7FFF ^ ( output_r >> 31 );
+ out [0] = output_l;
+ out [1] = output_r;
+ out += 2;
+ }
+
+ pair_count -= todo;
+ }
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/SegaPcm_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,36 +1,36 @@
-// Sega PCM sound chip emulator interface
-
-// Game_Music_Emu $vers
-#ifndef SEGAPCM_EMU_H
-#define SEGAPCM_EMU_H
-
-class SegaPcm_Emu {
- void* chip;
-public:
- SegaPcm_Emu();
- ~SegaPcm_Emu();
-
- // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( int intf_type );
-
- // Resets to power-up state
- void reset();
-
- // Mutes voice n if bit n (1 << n) of mask is set
- enum { channel_count = 16 };
- void mute_voices( int mask );
-
- // Writes data to addr
- void write( int addr, int data );
-
- // Scales ROM size, then writes length bytes from data at start offset
- void write_rom( int size, int start, int length, void * data );
-
- // Runs and writes pair_count*2 samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
+// Sega PCM sound chip emulator interface
+
+// Game_Music_Emu $vers
+#ifndef SEGAPCM_EMU_H
+#define SEGAPCM_EMU_H
+
+class SegaPcm_Emu {
+ void* chip;
+public:
+ SegaPcm_Emu();
+ ~SegaPcm_Emu();
+
+ // Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+ // if error.
+ int set_rate( int intf_type );
+
+ // Resets to power-up state
+ void reset();
+
+ // Mutes voice n if bit n (1 << n) of mask is set
+ enum { channel_count = 16 };
+ void mute_voices( int mask );
+
+ // Writes data to addr
+ void write( int addr, int data );
+
+ // Scales ROM size, then writes length bytes from data at start offset
+ void write_rom( int size, int start, int length, void * data );
+
+ // Runs and writes pair_count*2 samples to output
+ typedef short sample_t;
+ enum { out_chan_count = 2 }; // stereo
+ void run( int pair_count, sample_t* out );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/segapcm.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/segapcm.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/segapcm.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/segapcm.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,48 +1,48 @@
-/*********************************************************/
-/* SEGA 8bit PCM */
-/*********************************************************/
-
-#pragma once
-
-#include "mamedef.h"
-
-#define BANK_256 (11)
-#define BANK_512 (12)
-#define BANK_12M (13)
-#define BANK_MASK7 (0x70<<16)
-#define BANK_MASKF (0xf0<<16)
-#define BANK_MASKF8 (0xf8<<16)
-
-typedef struct _sega_pcm_interface sega_pcm_interface;
-struct _sega_pcm_interface
-{
- int bank;
-};
-
-/*WRITE8_DEVICE_HANDLER( sega_pcm_w );
-READ8_DEVICE_HANDLER( sega_pcm_r );
-
-DEVICE_GET_INFO( segapcm );
-#define SOUND_SEGAPCM DEVICE_GET_INFO_NAME( segapcm )*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void SEGAPCM_update(void *chip, stream_sample_t **outputs, int samples);
-
-void * device_start_segapcm(int intf_bank);
-void device_stop_segapcm(void *chip);
-void device_reset_segapcm(void *chip);
-
-void sega_pcm_w(void *chip, offs_t offset, UINT8 data);
-UINT8 sega_pcm_r(void *chip, offs_t offset);
-void sega_pcm_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
- const UINT8* ROMData);
-
-//void sega_pcm_fwrite_romusage(UINT8 ChipID);
-void segapcm_set_mute_mask(void *chip, UINT32 MuteMask);
-
-#ifdef __cplusplus
-}
-#endif
+/*********************************************************/
+/* SEGA 8bit PCM */
+/*********************************************************/
+
+#pragma once
+
+#include "mamedef.h"
+
+#define BANK_256 (11)
+#define BANK_512 (12)
+#define BANK_12M (13)
+#define BANK_MASK7 (0x70<<16)
+#define BANK_MASKF (0xf0<<16)
+#define BANK_MASKF8 (0xf8<<16)
+
+typedef struct _sega_pcm_interface sega_pcm_interface;
+struct _sega_pcm_interface
+{
+ int bank;
+};
+
+/*WRITE8_DEVICE_HANDLER( sega_pcm_w );
+READ8_DEVICE_HANDLER( sega_pcm_r );
+
+DEVICE_GET_INFO( segapcm );
+#define SOUND_SEGAPCM DEVICE_GET_INFO_NAME( segapcm )*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void SEGAPCM_update(void *chip, stream_sample_t **outputs, int samples);
+
+void * device_start_segapcm(int intf_bank);
+void device_stop_segapcm(void *chip);
+void device_reset_segapcm(void *chip);
+
+void sega_pcm_w(void *chip, offs_t offset, UINT8 data);
+UINT8 sega_pcm_r(void *chip, offs_t offset);
+void sega_pcm_write_rom(void *chip, offs_t ROMSize, offs_t DataStart, offs_t DataLength,
+ const UINT8* ROMData);
+
+//void sega_pcm_fwrite_romusage(UINT8 ChipID);
+void segapcm_set_mute_mask(void *chip, UINT32 MuteMask);
+
+#ifdef __cplusplus
+}
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Core.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Core.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Core.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Core.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,108 +1,108 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Sgc_Core.h"
-
-/* Copyright (C) 2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Sgc_Core::set_tempo( double t )
-{
- set_play_period( clock_rate() / (header().rate ? 50 : 60) / t );
-}
-
-blargg_err_t Sgc_Core::load_( Data_Reader& dr )
-{
- RETURN_ERR( Sgc_Impl::load_( dr ) );
-
- if ( sega_mapping() && fm_apu_.supported() )
- RETURN_ERR( fm_apu_.init( clock_rate(), clock_rate() / 72 ) );
-
- set_tempo( 1.0 );
- return blargg_ok;
-}
-
-blargg_err_t Sgc_Core::start_track( int t )
-{
- if ( sega_mapping() )
- {
- apu_.reset();
- fm_apu_.reset();
- fm_accessed = false;
- }
- else
- {
- apu_.reset( 0x0003, 15 );
- }
-
- return Sgc_Impl::start_track( t );
-}
-
-blargg_err_t Sgc_Core::end_frame( time_t t )
-{
- RETURN_ERR( Sgc_Impl::end_frame( t ) );
- apu_.end_frame( t );
- if ( sega_mapping() && fm_accessed )
- {
- if ( fm_apu_.supported() )
- fm_apu_.end_frame( t );
- else
- set_warning( "FM sound not supported" );
- }
-
- return blargg_ok;
-}
-
-Sgc_Core::Sgc_Core()
-{ }
-
-Sgc_Core::~Sgc_Core()
-{ }
-
-void Sgc_Core::cpu_out( time_t time, addr_t addr, int data )
-{
- int port = addr & 0xFF;
-
- if ( sega_mapping() )
- {
- switch ( port )
- {
- case 0x06:
- apu_.write_ggstereo( time, data );
- return;
-
- case 0x7E:
- case 0x7F:
- apu_.write_data( time, data ); dprintf( "$7E<-%02X\n", data );
- return;
-
- case 0xF0:
- fm_accessed = true;
- if ( fm_apu_.supported() )
- fm_apu_.write_addr( data );//, dprintf( "$F0<-%02X\n", data );
- return;
-
- case 0xF1:
- fm_accessed = true;
- if ( fm_apu_.supported() )
- fm_apu_.write_data( time, data );//, dprintf( "$F1<-%02X\n", data );
- return;
- }
- }
- else if ( port >= 0xE0 )
- {
- apu_.write_data( time, data );
- return;
- }
-
- Sgc_Impl::cpu_out( time, addr, data );
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Sgc_Core.h"
+
+/* Copyright (C) 2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Sgc_Core::set_tempo( double t )
+{
+ set_play_period( clock_rate() / (header().rate ? 50 : 60) / t );
+}
+
+blargg_err_t Sgc_Core::load_( Data_Reader& dr )
+{
+ RETURN_ERR( Sgc_Impl::load_( dr ) );
+
+ if ( sega_mapping() && fm_apu_.supported() )
+ RETURN_ERR( fm_apu_.init( clock_rate(), clock_rate() / 72 ) );
+
+ set_tempo( 1.0 );
+ return blargg_ok;
+}
+
+blargg_err_t Sgc_Core::start_track( int t )
+{
+ if ( sega_mapping() )
+ {
+ apu_.reset();
+ fm_apu_.reset();
+ fm_accessed = false;
+ }
+ else
+ {
+ apu_.reset( 0x0003, 15 );
+ }
+
+ return Sgc_Impl::start_track( t );
+}
+
+blargg_err_t Sgc_Core::end_frame( time_t t )
+{
+ RETURN_ERR( Sgc_Impl::end_frame( t ) );
+ apu_.end_frame( t );
+ if ( sega_mapping() && fm_accessed )
+ {
+ if ( fm_apu_.supported() )
+ fm_apu_.end_frame( t );
+ else
+ set_warning( "FM sound not supported" );
+ }
+
+ return blargg_ok;
+}
+
+Sgc_Core::Sgc_Core()
+{ }
+
+Sgc_Core::~Sgc_Core()
+{ }
+
+void Sgc_Core::cpu_out( time_t time, addr_t addr, int data )
+{
+ int port = addr & 0xFF;
+
+ if ( sega_mapping() )
+ {
+ switch ( port )
+ {
+ case 0x06:
+ apu_.write_ggstereo( time, data );
+ return;
+
+ case 0x7E:
+ case 0x7F:
+ apu_.write_data( time, data ); dprintf( "$7E<-%02X\n", data );
+ return;
+
+ case 0xF0:
+ fm_accessed = true;
+ if ( fm_apu_.supported() )
+ fm_apu_.write_addr( data );//, dprintf( "$F0<-%02X\n", data );
+ return;
+
+ case 0xF1:
+ fm_accessed = true;
+ if ( fm_apu_.supported() )
+ fm_apu_.write_data( time, data );//, dprintf( "$F1<-%02X\n", data );
+ return;
+ }
+ }
+ else if ( port >= 0xE0 )
+ {
+ apu_.write_data( time, data );
+ return;
+ }
+
+ Sgc_Impl::cpu_out( time, addr, data );
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Core.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Core.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Core.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Core.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,44 +1,44 @@
-// Sega/Game Gear/Coleco SGC music file emulator core
-
-// Game_Music_Emu $vers
-#ifndef SGC_CORE_H
-#define SGC_CORE_H
-
-#include "Sgc_Impl.h"
-#include "Sms_Fm_Apu.h"
-#include "Sms_Apu.h"
-
-class Sgc_Core : public Sgc_Impl {
-public:
-
- // Adjusts music tempo, where 1.0 is normal. Can be changed while playing.
- // Resets to 1.0 when loading file.
- void set_tempo( double );
-
- // Starts track, where 0 is the first.
- blargg_err_t start_track( int );
-
- // Ends time frame at time t
- blargg_err_t end_frame( time_t t );
-
- // SN76489 sound chip
- Sms_Apu& apu() { return apu_; }
- Sms_Fm_Apu& fm_apu() { return fm_apu_; }
-
-protected:
- // Overrides
- virtual void cpu_out( time_t, addr_t, int data );
- virtual blargg_err_t load_( Data_Reader& );
-
-// Implementation
-public:
- Sgc_Core();
- ~Sgc_Core();
-
-private:
- bool fm_accessed;
- Sms_Apu apu_;
- Sms_Fm_Apu fm_apu_;
-};
-
-#endif
+// Sega/Game Gear/Coleco SGC music file emulator core
+
+// Game_Music_Emu $vers
+#ifndef SGC_CORE_H
+#define SGC_CORE_H
+
+#include "Sgc_Impl.h"
+#include "Sms_Fm_Apu.h"
+#include "Sms_Apu.h"
+
+class Sgc_Core : public Sgc_Impl {
+public:
+
+ // Adjusts music tempo, where 1.0 is normal. Can be changed while playing.
+ // Resets to 1.0 when loading file.
+ void set_tempo( double );
+
+ // Starts track, where 0 is the first.
+ blargg_err_t start_track( int );
+
+ // Ends time frame at time t
+ blargg_err_t end_frame( time_t t );
+
+ // SN76489 sound chip
+ Sms_Apu& apu() { return apu_; }
+ Sms_Fm_Apu& fm_apu() { return fm_apu_; }
+
+protected:
+ // Overrides
+ virtual void cpu_out( time_t, addr_t, int data );
+ virtual blargg_err_t load_( Data_Reader& );
+
+// Implementation
+public:
+ Sgc_Core();
+ ~Sgc_Core();
+
+private:
+ bool fm_accessed;
+ Sms_Apu apu_;
+ Sms_Fm_Apu fm_apu_;
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Cpu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Cpu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Cpu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Cpu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,36 +1,36 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Sgc_Impl.h"
-
-#include "blargg_endian.h"
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#define OUT_PORT( addr, data ) cpu_out( TIME(), addr, data )
-#define IN_PORT( addr ) cpu_in( addr )
-#define WRITE_MEM( addr, data ) cpu_write( addr, data )
-#define IDLE_ADDR idle_addr
-#define CPU cpu
-#define RST_BASE vectors_addr
-
-#define CPU_BEGIN \
-bool Sgc_Impl::run_cpu( time_t end_time )\
-{\
- cpu.set_end_time( end_time );
-
- #include "Z80_Cpu_run.h"
-
- return warning;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Sgc_Impl.h"
+
+#include "blargg_endian.h"
+//#include "z80_cpu_log.h"
+
+/* Copyright (C) 2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#define OUT_PORT( addr, data ) cpu_out( TIME(), addr, data )
+#define IN_PORT( addr ) cpu_in( addr )
+#define WRITE_MEM( addr, data ) cpu_write( addr, data )
+#define IDLE_ADDR idle_addr
+#define CPU cpu
+#define RST_BASE vectors_addr
+
+#define CPU_BEGIN \
+bool Sgc_Impl::run_cpu( time_t end_time )\
+{\
+ cpu.set_end_time( end_time );
+
+ #include "Z80_Cpu_run.h"
+
+ return warning;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,167 +1,167 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Sgc_Emu.h"
-
-/* Copyright (C) 2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const osc_count = Sms_Apu::osc_count + Sms_Fm_Apu::osc_count;
-
-Sgc_Emu::Sgc_Emu()
-{
- set_type( gme_sgc_type );
- set_silence_lookahead( 6 );
- set_gain( 1.2 );
-}
-
-Sgc_Emu::~Sgc_Emu() { }
-
-void Sgc_Emu::unload()
-{
- core_.unload();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_sgc_fields( Sgc_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
-}
-
-static void hash_sgc_file( Sgc_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.vers, sizeof(h.vers) );
- out.hash_( &h.rate, sizeof(h.rate) );
- out.hash_( &h.reserved1[0], sizeof(h.reserved1) );
- out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
- out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
- out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
- out.hash_( &h.stack_ptr[0], sizeof(h.stack_ptr) );
- out.hash_( &h.reserved2[0], sizeof(h.reserved2) );
- out.hash_( &h.rst_addrs[0], sizeof(h.rst_addrs) );
- out.hash_( &h.mapping[0], sizeof(h.mapping) );
- out.hash_( &h.first_song, sizeof(h.first_song) );
- out.hash_( &h.song_count, sizeof(h.song_count) );
- out.hash_( &h.first_effect, sizeof(h.first_effect) );
- out.hash_( &h.last_effect, sizeof(h.last_effect) );
- out.hash_( &h.system, sizeof(h.system) );
- out.hash_( &h.reserved3[0], sizeof(h.reserved3) );
- out.hash_( data, data_size );
-}
-
-blargg_err_t Sgc_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_sgc_fields( header(), out );
- return blargg_ok;
-}
-
-struct Sgc_File : Gme_Info_
-{
- Sgc_Emu::header_t const* h;
-
- Sgc_File() { set_type( gme_sgc_type ); }
-
- blargg_err_t load_mem_( byte const begin [], int size )
- {
- h = ( Sgc_Emu::header_t const* ) begin;
-
- set_track_count( h->song_count );
- if ( !h->valid_tag() )
- return blargg_err_file_type;
-
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_sgc_fields( *h, out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_sgc_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_sgc_emu () { return BLARGG_NEW Sgc_Emu ; }
-static Music_Emu* new_sgc_file() { return BLARGG_NEW Sgc_File; }
-
-gme_type_t_ const gme_sgc_type [1] = {{ "Z80 PSG", 0, &new_sgc_emu, &new_sgc_file, "SGC", 1 }};
-
-// Setup
-
-blargg_err_t Sgc_Emu::load_( Data_Reader& in )
-{
- RETURN_ERR( core_.load( in ) );
- set_warning( core_.warning() );
- set_track_count( header().song_count );
- set_voice_count( core_.sega_mapping() ? osc_count : core_.apu().osc_count );
-
- core_.apu ().volume( gain() );
- core_.fm_apu().volume( gain() );
-
- static const char* const names [osc_count + 1] = {
- "Square 1", "Square 2", "Square 3", "Noise", "FM"
- };
- set_voice_names( names );
-
- static int const types [osc_count + 1] = {
- wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
- };
- set_voice_types( types );
-
- return setup_buffer( core_.clock_rate() );
-}
-
-void Sgc_Emu::update_eq( blip_eq_t const& eq )
-{
- core_.apu ().treble_eq( eq );
- core_.fm_apu().treble_eq( eq );
-}
-
-void Sgc_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- if ( i < core_.apu().osc_count )
- core_.apu().set_output( i, c, l, r );
- else
- core_.fm_apu().set_output( c, l, r );
-}
-
-void Sgc_Emu::set_tempo_( double t )
-{
- core_.set_tempo( t );
-}
-
-blargg_err_t Sgc_Emu::start_track_( int track )
-{
- RETURN_ERR( core_.start_track( track ) );
- return Classic_Emu::start_track_( track );
-}
-
-blargg_err_t Sgc_Emu::run_clocks( blip_time_t& duration, int )
-{
- RETURN_ERR( core_.end_frame( duration ) );
- set_warning( core_.warning() );
- return blargg_ok;
-}
-
-blargg_err_t Sgc_Emu::hash_( Hash_Function& out ) const
-{
- hash_sgc_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
- return blargg_ok;
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Sgc_Emu.h"
+
+/* Copyright (C) 2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const osc_count = Sms_Apu::osc_count + Sms_Fm_Apu::osc_count;
+
+Sgc_Emu::Sgc_Emu()
+{
+ set_type( gme_sgc_type );
+ set_silence_lookahead( 6 );
+ set_gain( 1.2 );
+}
+
+Sgc_Emu::~Sgc_Emu() { }
+
+void Sgc_Emu::unload()
+{
+ core_.unload();
+ Music_Emu::unload();
+}
+
+// Track info
+
+static void copy_sgc_fields( Sgc_Emu::header_t const& h, track_info_t* out )
+{
+ GME_COPY_FIELD( h, out, game );
+ GME_COPY_FIELD( h, out, author );
+ GME_COPY_FIELD( h, out, copyright );
+}
+
+static void hash_sgc_file( Sgc_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.vers, sizeof(h.vers) );
+ out.hash_( &h.rate, sizeof(h.rate) );
+ out.hash_( &h.reserved1[0], sizeof(h.reserved1) );
+ out.hash_( &h.load_addr[0], sizeof(h.load_addr) );
+ out.hash_( &h.init_addr[0], sizeof(h.init_addr) );
+ out.hash_( &h.play_addr[0], sizeof(h.play_addr) );
+ out.hash_( &h.stack_ptr[0], sizeof(h.stack_ptr) );
+ out.hash_( &h.reserved2[0], sizeof(h.reserved2) );
+ out.hash_( &h.rst_addrs[0], sizeof(h.rst_addrs) );
+ out.hash_( &h.mapping[0], sizeof(h.mapping) );
+ out.hash_( &h.first_song, sizeof(h.first_song) );
+ out.hash_( &h.song_count, sizeof(h.song_count) );
+ out.hash_( &h.first_effect, sizeof(h.first_effect) );
+ out.hash_( &h.last_effect, sizeof(h.last_effect) );
+ out.hash_( &h.system, sizeof(h.system) );
+ out.hash_( &h.reserved3[0], sizeof(h.reserved3) );
+ out.hash_( data, data_size );
+}
+
+blargg_err_t Sgc_Emu::track_info_( track_info_t* out, int ) const
+{
+ copy_sgc_fields( header(), out );
+ return blargg_ok;
+}
+
+struct Sgc_File : Gme_Info_
+{
+ Sgc_Emu::header_t const* h;
+
+ Sgc_File() { set_type( gme_sgc_type ); }
+
+ blargg_err_t load_mem_( byte const begin [], int size )
+ {
+ h = ( Sgc_Emu::header_t const* ) begin;
+
+ set_track_count( h->song_count );
+ if ( !h->valid_tag() )
+ return blargg_err_file_type;
+
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_sgc_fields( *h, out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_sgc_file( *h, file_begin() + h->size, file_end() - file_begin() - h->size, out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_sgc_emu () { return BLARGG_NEW Sgc_Emu ; }
+static Music_Emu* new_sgc_file() { return BLARGG_NEW Sgc_File; }
+
+gme_type_t_ const gme_sgc_type [1] = {{ "Z80 PSG", 0, &new_sgc_emu, &new_sgc_file, "SGC", 1 }};
+
+// Setup
+
+blargg_err_t Sgc_Emu::load_( Data_Reader& in )
+{
+ RETURN_ERR( core_.load( in ) );
+ set_warning( core_.warning() );
+ set_track_count( header().song_count );
+ set_voice_count( core_.sega_mapping() ? osc_count : core_.apu().osc_count );
+
+ core_.apu ().volume( gain() );
+ core_.fm_apu().volume( gain() );
+
+ static const char* const names [osc_count + 1] = {
+ "Square 1", "Square 2", "Square 3", "Noise", "FM"
+ };
+ set_voice_names( names );
+
+ static int const types [osc_count + 1] = {
+ wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
+ };
+ set_voice_types( types );
+
+ return setup_buffer( core_.clock_rate() );
+}
+
+void Sgc_Emu::update_eq( blip_eq_t const& eq )
+{
+ core_.apu ().treble_eq( eq );
+ core_.fm_apu().treble_eq( eq );
+}
+
+void Sgc_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
+{
+ if ( i < core_.apu().osc_count )
+ core_.apu().set_output( i, c, l, r );
+ else
+ core_.fm_apu().set_output( c, l, r );
+}
+
+void Sgc_Emu::set_tempo_( double t )
+{
+ core_.set_tempo( t );
+}
+
+blargg_err_t Sgc_Emu::start_track_( int track )
+{
+ RETURN_ERR( core_.start_track( track ) );
+ return Classic_Emu::start_track_( track );
+}
+
+blargg_err_t Sgc_Emu::run_clocks( blip_time_t& duration, int )
+{
+ RETURN_ERR( core_.end_frame( duration ) );
+ set_warning( core_.warning() );
+ return blargg_ok;
+}
+
+blargg_err_t Sgc_Emu::hash_( Hash_Function& out ) const
+{
+ hash_sgc_file( header(), core_.rom_().begin(), core_.rom_().file_size(), out );
+ return blargg_ok;
}
\ No newline at end of file
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Emu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,45 +1,45 @@
-// Sega/Game Gear/Coleco SGC music file emulator
-
-// Game_Music_Emu $vers
-#ifndef SGC_EMU_H
-#define SGC_EMU_H
-
-#include "Classic_Emu.h"
-#include "Sgc_Core.h"
-
-class Sgc_Emu : public Classic_Emu {
-public:
- // SGC file header (see Sgc_Impl.h)
- typedef Sgc_Core::header_t header_t;
-
- // Header for currently loaded file
- header_t const& header() const { return core_.header(); }
-
- blargg_err_t hash_( Hash_Function& ) const;
-
- // Sets 0x2000-byte Coleco BIOS. Necessary to play Coleco tracks.
- static void set_coleco_bios( void const* p ){ Sgc_Core::set_coleco_bios( p ); }
-
- static gme_type_t static_type() { return gme_sgc_type; }
-
-// Internal
-public:
- Sgc_Emu();
- ~Sgc_Emu();
-
-protected:
- // Classic_Emu overrides
- virtual blargg_err_t track_info_( track_info_t*, int track ) const;
- virtual blargg_err_t load_( Data_Reader& );
- virtual blargg_err_t start_track_( int );
- virtual blargg_err_t run_clocks( blip_time_t&, int );
- virtual void set_tempo_( double );
- virtual void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- virtual void update_eq( blip_eq_t const& );
- virtual void unload();
-
-private:
- Sgc_Core core_;
-};
-
-#endif
+// Sega/Game Gear/Coleco SGC music file emulator
+
+// Game_Music_Emu $vers
+#ifndef SGC_EMU_H
+#define SGC_EMU_H
+
+#include "Classic_Emu.h"
+#include "Sgc_Core.h"
+
+class Sgc_Emu : public Classic_Emu {
+public:
+ // SGC file header (see Sgc_Impl.h)
+ typedef Sgc_Core::header_t header_t;
+
+ // Header for currently loaded file
+ header_t const& header() const { return core_.header(); }
+
+ blargg_err_t hash_( Hash_Function& ) const;
+
+ // Sets 0x2000-byte Coleco BIOS. Necessary to play Coleco tracks.
+ static void set_coleco_bios( void const* p ){ Sgc_Core::set_coleco_bios( p ); }
+
+ static gme_type_t static_type() { return gme_sgc_type; }
+
+// Internal
+public:
+ Sgc_Emu();
+ ~Sgc_Emu();
+
+protected:
+ // Classic_Emu overrides
+ virtual blargg_err_t track_info_( track_info_t*, int track ) const;
+ virtual blargg_err_t load_( Data_Reader& );
+ virtual blargg_err_t start_track_( int );
+ virtual blargg_err_t run_clocks( blip_time_t&, int );
+ virtual void set_tempo_( double );
+ virtual void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
+ virtual void update_eq( blip_eq_t const& );
+ virtual void unload();
+
+private:
+ Sgc_Core core_;
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,225 +1,225 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Sgc_Impl.h"
-
-/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void const* Sgc_Impl::coleco_bios;
-
-Sgc_Impl::Sgc_Impl() :
- rom( bank_size )
-{
- assert( offsetof (header_t,copyright [32]) == header_t::size );
-}
-
-Sgc_Impl::~Sgc_Impl()
-{ }
-
-bool Sgc_Impl::header_t::valid_tag() const
-{
- return 0 == memcmp( tag, "SGC\x1A", 4 );
-}
-
-blargg_err_t Sgc_Impl::load_( Data_Reader& in )
-{
- RETURN_ERR( rom.load( in, header_.size, &header_, 0 ) );
-
- if ( !header_.valid_tag() )
- return blargg_err_file_type;
-
- if ( header_.vers != 1 )
- set_warning( "Unknown file version" );
-
- if ( header_.system > 2 )
- set_warning( "Unknown system" );
-
- addr_t load_addr = get_le16( header_.load_addr );
- if ( load_addr < 0x400 )
- set_warning( "Invalid load address" );
-
- rom.set_addr( load_addr );
- play_period = clock_rate() / 60;
-
- if ( sega_mapping() )
- {
- RETURN_ERR( ram.resize( 0x2000 + Sgc_Cpu::page_padding ) );
- RETURN_ERR( ram2.resize( bank_size + Sgc_Cpu::page_padding ) );
- }
- else
- {
- RETURN_ERR( ram.resize( 0x400 + Sgc_Cpu::page_padding ) );
- }
-
- RETURN_ERR( vectors.resize( Sgc_Cpu::page_size + Sgc_Cpu::page_padding ) );
-
- // TODO: doesn't need to be larger than page size, if we do mapping calls right
- RETURN_ERR( unmapped_write.resize( bank_size ) );
-
- return blargg_ok;
-}
-
-void Sgc_Impl::unload()
-{
- rom.clear();
- vectors.clear();
- ram.clear();
- ram2.clear();
- unmapped_write.clear();
- Gme_Loader::unload();
-}
-
-blargg_err_t Sgc_Impl::start_track( int track )
-{
- memset( ram .begin(), 0, ram .size() );
- memset( ram2.begin(), 0, ram2.size() );
- memset( vectors.begin(), 0xFF, vectors.size() );
- cpu.reset( unmapped_write.begin(), rom.unmapped() );
-
- if ( sega_mapping() )
- {
- vectors_addr = 0x10000 - Sgc_Cpu::page_size;
- idle_addr = vectors_addr;
- for ( int i = 1; i < 8; ++i )
- {
- vectors [i*8 + 0] = 0xC3; // JP addr
- vectors [i*8 + 1] = header_.rst_addrs [i*2 + 0];
- vectors [i*8 + 2] = header_.rst_addrs [i*2 + 1];
- }
-
- cpu.map_mem( 0xC000, 0x2000, ram.begin() );
- cpu.map_mem( vectors_addr, cpu.page_size, unmapped_write.begin(), vectors.begin() );
-
- bank2 = NULL;
- for ( int i = 0; i < 4; ++i )
- cpu_write( 0xFFFC + i, header_.mapping [i] );
- }
- else
- {
- if ( !coleco_bios )
- return BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" );
-
- vectors_addr = 0;
- cpu.map_mem( 0, 0x2000, unmapped_write.begin(), coleco_bios );
- for ( int i = 0; i < 8; ++i )
- cpu.map_mem( 0x6000 + i*0x400, 0x400, ram.begin() );
-
- idle_addr = 0x2000;
- cpu.map_mem( 0x2000, cpu.page_size, unmapped_write.begin(), vectors.begin() );
-
- for ( int i = 0; i < 0x8000 / bank_size; ++i )
- {
- int addr = 0x8000 + i*bank_size;
- cpu.map_mem( addr, bank_size, unmapped_write.begin(), rom.at_addr( addr ) );
- }
- }
-
- cpu.r.sp = get_le16( header_.stack_ptr );
- cpu.r.b.a = track;
- next_play = play_period;
-
- jsr( header_.init_addr );
-
- return blargg_ok;
-}
-
-// Emulation
-
-void Sgc_Impl::jsr( byte const (&addr) [2] )
-{
- *cpu.write( --cpu.r.sp ) = idle_addr >> 8;
- *cpu.write( --cpu.r.sp ) = idle_addr & 0xFF;
- cpu.r.pc = get_le16( addr );
-}
-
-void Sgc_Impl::set_bank( int bank, void const* data )
-{
- //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
- cpu.map_mem( bank * bank_size, bank_size, unmapped_write.begin(), data );
-}
-
-void Sgc_Impl::cpu_write( addr_t addr, int data )
-{
- if ( (addr ^ 0xFFFC) > 3 || !sega_mapping() )
- {
- *cpu.write( addr ) = data;
- return;
- }
-
- switch ( addr )
- {
- case 0xFFFC:
- cpu.map_mem( 2 * bank_size, bank_size, ram2.begin() );
- if ( data & 0x08 )
- break;
-
- bank2 = ram2.begin();
- // FALL THROUGH
-
- case 0xFFFF: {
- bool rom_mapped = (cpu.read( 2 * bank_size ) == bank2);
- bank2 = rom.at_addr( data * bank_size );
- if ( rom_mapped )
- set_bank( 2, bank2 );
- break;
- }
-
- case 0xFFFD:
- set_bank( 0, rom.at_addr( data * bank_size ) );
- break;
-
- case 0xFFFE:
- set_bank( 1, rom.at_addr( data * bank_size ) );
- break;
- }
-}
-
-int Sgc_Impl::cpu_in( addr_t addr )
-{
- dprintf( "in %02X\n", addr );
- return 0;
-}
-
-void Sgc_Impl::cpu_out( time_t, addr_t addr, int )
-{
- dprintf( "out %02X\n", addr & 0xFF );
-}
-
-blargg_err_t Sgc_Impl::end_frame( time_t end )
-{
- while ( cpu.time() < end )
- {
- time_t next = min( end, next_play );
- if ( run_cpu( next ) )
- {
- set_warning( "Unsupported CPU instruction" );
- cpu.set_time( next );
- }
-
- if ( cpu.r.pc == idle_addr )
- cpu.set_time( next );
-
- if ( cpu.time() >= next_play )
- {
- next_play += play_period;
- if ( cpu.r.pc == idle_addr )
- jsr( header_.play_addr );
- }
- }
-
- next_play -= end;
- check( next_play >= 0 );
- cpu.adjust_time( -end );
-
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Sgc_Impl.h"
+
+/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void const* Sgc_Impl::coleco_bios;
+
+Sgc_Impl::Sgc_Impl() :
+ rom( bank_size )
+{
+ assert( offsetof (header_t,copyright [32]) == header_t::size );
+}
+
+Sgc_Impl::~Sgc_Impl()
+{ }
+
+bool Sgc_Impl::header_t::valid_tag() const
+{
+ return 0 == memcmp( tag, "SGC\x1A", 4 );
+}
+
+blargg_err_t Sgc_Impl::load_( Data_Reader& in )
+{
+ RETURN_ERR( rom.load( in, header_.size, &header_, 0 ) );
+
+ if ( !header_.valid_tag() )
+ return blargg_err_file_type;
+
+ if ( header_.vers != 1 )
+ set_warning( "Unknown file version" );
+
+ if ( header_.system > 2 )
+ set_warning( "Unknown system" );
+
+ addr_t load_addr = get_le16( header_.load_addr );
+ if ( load_addr < 0x400 )
+ set_warning( "Invalid load address" );
+
+ rom.set_addr( load_addr );
+ play_period = clock_rate() / 60;
+
+ if ( sega_mapping() )
+ {
+ RETURN_ERR( ram.resize( 0x2000 + Sgc_Cpu::page_padding ) );
+ RETURN_ERR( ram2.resize( bank_size + Sgc_Cpu::page_padding ) );
+ }
+ else
+ {
+ RETURN_ERR( ram.resize( 0x400 + Sgc_Cpu::page_padding ) );
+ }
+
+ RETURN_ERR( vectors.resize( Sgc_Cpu::page_size + Sgc_Cpu::page_padding ) );
+
+ // TODO: doesn't need to be larger than page size, if we do mapping calls right
+ RETURN_ERR( unmapped_write.resize( bank_size ) );
+
+ return blargg_ok;
+}
+
+void Sgc_Impl::unload()
+{
+ rom.clear();
+ vectors.clear();
+ ram.clear();
+ ram2.clear();
+ unmapped_write.clear();
+ Gme_Loader::unload();
+}
+
+blargg_err_t Sgc_Impl::start_track( int track )
+{
+ memset( ram .begin(), 0, ram .size() );
+ memset( ram2.begin(), 0, ram2.size() );
+ memset( vectors.begin(), 0xFF, vectors.size() );
+ cpu.reset( unmapped_write.begin(), rom.unmapped() );
+
+ if ( sega_mapping() )
+ {
+ vectors_addr = 0x10000 - Sgc_Cpu::page_size;
+ idle_addr = vectors_addr;
+ for ( int i = 1; i < 8; ++i )
+ {
+ vectors [i*8 + 0] = 0xC3; // JP addr
+ vectors [i*8 + 1] = header_.rst_addrs [i*2 + 0];
+ vectors [i*8 + 2] = header_.rst_addrs [i*2 + 1];
+ }
+
+ cpu.map_mem( 0xC000, 0x2000, ram.begin() );
+ cpu.map_mem( vectors_addr, cpu.page_size, unmapped_write.begin(), vectors.begin() );
+
+ bank2 = NULL;
+ for ( int i = 0; i < 4; ++i )
+ cpu_write( 0xFFFC + i, header_.mapping [i] );
+ }
+ else
+ {
+ if ( !coleco_bios )
+ return BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" );
+
+ vectors_addr = 0;
+ cpu.map_mem( 0, 0x2000, unmapped_write.begin(), coleco_bios );
+ for ( int i = 0; i < 8; ++i )
+ cpu.map_mem( 0x6000 + i*0x400, 0x400, ram.begin() );
+
+ idle_addr = 0x2000;
+ cpu.map_mem( 0x2000, cpu.page_size, unmapped_write.begin(), vectors.begin() );
+
+ for ( int i = 0; i < 0x8000 / bank_size; ++i )
+ {
+ int addr = 0x8000 + i*bank_size;
+ cpu.map_mem( addr, bank_size, unmapped_write.begin(), rom.at_addr( addr ) );
+ }
+ }
+
+ cpu.r.sp = get_le16( header_.stack_ptr );
+ cpu.r.b.a = track;
+ next_play = play_period;
+
+ jsr( header_.init_addr );
+
+ return blargg_ok;
+}
+
+// Emulation
+
+void Sgc_Impl::jsr( byte const (&addr) [2] )
+{
+ *cpu.write( --cpu.r.sp ) = idle_addr >> 8;
+ *cpu.write( --cpu.r.sp ) = idle_addr & 0xFF;
+ cpu.r.pc = get_le16( addr );
+}
+
+void Sgc_Impl::set_bank( int bank, void const* data )
+{
+ //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
+ cpu.map_mem( bank * bank_size, bank_size, unmapped_write.begin(), data );
+}
+
+void Sgc_Impl::cpu_write( addr_t addr, int data )
+{
+ if ( (addr ^ 0xFFFC) > 3 || !sega_mapping() )
+ {
+ *cpu.write( addr ) = data;
+ return;
+ }
+
+ switch ( addr )
+ {
+ case 0xFFFC:
+ cpu.map_mem( 2 * bank_size, bank_size, ram2.begin() );
+ if ( data & 0x08 )
+ break;
+
+ bank2 = ram2.begin();
+ // FALL THROUGH
+
+ case 0xFFFF: {
+ bool rom_mapped = (cpu.read( 2 * bank_size ) == bank2);
+ bank2 = rom.at_addr( data * bank_size );
+ if ( rom_mapped )
+ set_bank( 2, bank2 );
+ break;
+ }
+
+ case 0xFFFD:
+ set_bank( 0, rom.at_addr( data * bank_size ) );
+ break;
+
+ case 0xFFFE:
+ set_bank( 1, rom.at_addr( data * bank_size ) );
+ break;
+ }
+}
+
+int Sgc_Impl::cpu_in( addr_t addr )
+{
+ dprintf( "in %02X\n", addr );
+ return 0;
+}
+
+void Sgc_Impl::cpu_out( time_t, addr_t addr, int )
+{
+ dprintf( "out %02X\n", addr & 0xFF );
+}
+
+blargg_err_t Sgc_Impl::end_frame( time_t end )
+{
+ while ( cpu.time() < end )
+ {
+ time_t next = min( end, next_play );
+ if ( run_cpu( next ) )
+ {
+ set_warning( "Unsupported CPU instruction" );
+ cpu.set_time( next );
+ }
+
+ if ( cpu.r.pc == idle_addr )
+ cpu.set_time( next );
+
+ if ( cpu.time() >= next_play )
+ {
+ next_play += play_period;
+ if ( cpu.r.pc == idle_addr )
+ jsr( header_.play_addr );
+ }
+ }
+
+ next_play -= end;
+ check( next_play >= 0 );
+ cpu.adjust_time( -end );
+
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sgc_Impl.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,116 +1,116 @@
-// Sega/Game Gear/Coleco SGC music file emulator implementation internals
-
-// Game_Music_Emu $vers
-#ifndef SGC_IMPL_H
-#define SGC_IMPL_H
-
-#include "Gme_Loader.h"
-#include "Rom_Data.h"
-#include "Z80_Cpu.h"
-
-class Sgc_Impl : public Gme_Loader {
-public:
-
- // SGC file header
- struct header_t
- {
- enum { size = 0xA0 };
-
- char tag [4]; // "SGC\x1A"
- byte vers; // 0x01
- byte rate; // 0=NTSC 1=PAL
- byte reserved1 [2];
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte stack_ptr [2];
- byte reserved2 [2];
- byte rst_addrs [7*2];
- byte mapping [4]; // Used by Sega only
- byte first_song; // Song to start playing first
- byte song_count;
- byte first_effect;
- byte last_effect;
- byte system; // 0=Master System 1=Game Gear 2=Colecovision
- byte reserved3 [23];
- char game [32]; // strings can be 32 chars, NOT terminated
- char author [32];
- char copyright [32];
-
- // True if header has valid file signature
- bool valid_tag() const;
-
- int effect_count() const { return last_effect ? last_effect - first_effect + 1 : 0; }
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- Rom_Data const& rom_() const { return rom; }
-
- int clock_rate() const { return header_.rate ? 3546893 : 3579545; }
-
- // 0x2000 bytes
- static void set_coleco_bios( void const* p ) { coleco_bios = p; }
-
- // Clocks between calls to play routine
- typedef int time_t;
- void set_play_period( time_t p ) { play_period = p; }
-
- // 0 = first track
- blargg_err_t start_track( int );
-
- // Runs for t clocks
- blargg_err_t end_frame( time_t t );
-
- // True if Master System or Game Gear
- bool sega_mapping() const;
-
-protected:
- typedef Z80_Cpu Sgc_Cpu;
- Sgc_Cpu cpu;
-
- typedef int addr_t;
- virtual void cpu_out( time_t, addr_t, int data ) BLARGG_PURE( ; )
-
-// Implementation
-public:
- Sgc_Impl();
- ~Sgc_Impl();
- virtual void unload();
-
-protected:
- virtual blargg_err_t load_( Data_Reader& );
-
-private:
- enum { bank_size = 0x4000 };
-
- Rom_Data rom;
- time_t play_period;
- time_t next_play;
- void const* bank2; // ROM selected for bank 2, in case RAM is currently hiding it
- addr_t vectors_addr; // RST vectors start here
- addr_t idle_addr; // return address for init/play routines
- static void const* coleco_bios;
-
- // large items
- header_t header_;
- blargg_vector vectors;
- blargg_vector ram;
- blargg_vector ram2;
- blargg_vector unmapped_write;
-
- bool run_cpu( time_t end );
- void jsr( byte const (&addr) [2] );
- void cpu_write( addr_t, int data );
- int cpu_in( addr_t );
-
- void set_bank( int bank, void const* data );
-};
-
-inline bool Sgc_Impl::sega_mapping() const
-{
- return header_.system <= 1;
-}
-
-#endif
+// Sega/Game Gear/Coleco SGC music file emulator implementation internals
+
+// Game_Music_Emu $vers
+#ifndef SGC_IMPL_H
+#define SGC_IMPL_H
+
+#include "Gme_Loader.h"
+#include "Rom_Data.h"
+#include "Z80_Cpu.h"
+
+class Sgc_Impl : public Gme_Loader {
+public:
+
+ // SGC file header
+ struct header_t
+ {
+ enum { size = 0xA0 };
+
+ char tag [4]; // "SGC\x1A"
+ byte vers; // 0x01
+ byte rate; // 0=NTSC 1=PAL
+ byte reserved1 [2];
+ byte load_addr [2];
+ byte init_addr [2];
+ byte play_addr [2];
+ byte stack_ptr [2];
+ byte reserved2 [2];
+ byte rst_addrs [7*2];
+ byte mapping [4]; // Used by Sega only
+ byte first_song; // Song to start playing first
+ byte song_count;
+ byte first_effect;
+ byte last_effect;
+ byte system; // 0=Master System 1=Game Gear 2=Colecovision
+ byte reserved3 [23];
+ char game [32]; // strings can be 32 chars, NOT terminated
+ char author [32];
+ char copyright [32];
+
+ // True if header has valid file signature
+ bool valid_tag() const;
+
+ int effect_count() const { return last_effect ? last_effect - first_effect + 1 : 0; }
+ };
+
+ // Header for currently loaded file
+ header_t const& header() const { return header_; }
+
+ Rom_Data const& rom_() const { return rom; }
+
+ int clock_rate() const { return header_.rate ? 3546893 : 3579545; }
+
+ // 0x2000 bytes
+ static void set_coleco_bios( void const* p ) { coleco_bios = p; }
+
+ // Clocks between calls to play routine
+ typedef int time_t;
+ void set_play_period( time_t p ) { play_period = p; }
+
+ // 0 = first track
+ blargg_err_t start_track( int );
+
+ // Runs for t clocks
+ blargg_err_t end_frame( time_t t );
+
+ // True if Master System or Game Gear
+ bool sega_mapping() const;
+
+protected:
+ typedef Z80_Cpu Sgc_Cpu;
+ Sgc_Cpu cpu;
+
+ typedef int addr_t;
+ virtual void cpu_out( time_t, addr_t, int data ) BLARGG_PURE( ; )
+
+// Implementation
+public:
+ Sgc_Impl();
+ ~Sgc_Impl();
+ virtual void unload();
+
+protected:
+ virtual blargg_err_t load_( Data_Reader& );
+
+private:
+ enum { bank_size = 0x4000 };
+
+ Rom_Data rom;
+ time_t play_period;
+ time_t next_play;
+ void const* bank2; // ROM selected for bank 2, in case RAM is currently hiding it
+ addr_t vectors_addr; // RST vectors start here
+ addr_t idle_addr; // return address for init/play routines
+ static void const* coleco_bios;
+
+ // large items
+ header_t header_;
+ blargg_vector vectors;
+ blargg_vector ram;
+ blargg_vector ram2;
+ blargg_vector unmapped_write;
+
+ bool run_cpu( time_t end );
+ void jsr( byte const (&addr) [2] );
+ void cpu_write( addr_t, int data );
+ int cpu_in( addr_t );
+
+ void set_bank( int bank, void const* data );
+};
+
+inline bool Sgc_Impl::sega_mapping() const
+{
+ return header_.system <= 1;
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/s_logtbl.c kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/s_logtbl.c
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/s_logtbl.c 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/s_logtbl.c 2013-05-31 22:59:22.000000000 +0000
@@ -1,88 +1,88 @@
-#include "nestypes.h"
-#include "s_logtbl.h"
-
-#if STATIC_TABLES
-
-static void LogTableRelease(void *ctx)
-{
-}
-
-static KMIF_LOGTABLE log_static_tables = {
- &log_static_tables;
- LogTableRelease,
-#include "s_logt.h"
-};
-
-
-KMIF_LOGTABLE *LogTableAddRef(void)
-{
- log_static_tables.release = LogTableRelease;
- return &log_static_tables;
-}
-
-#else
-
-#include
-
-static volatile Uint32 log_tables_mutex = 0;
-static Uint32 log_tables_refcount = 0;
-static KMIF_LOGTABLE *log_tables = 0;
-
-static void LogTableRelease(void *ctx)
-{
- ++log_tables_mutex;
- while (log_tables_mutex != 1)
- {
- XSLEEP(0);
- }
- log_tables_refcount--;
- if (!log_tables_refcount)
- {
- XFREE(ctx);
- log_tables = 0;
- }
- --log_tables_mutex;
-}
-
-static void LogTableCalc(KMIF_LOGTABLE *kmif_lt)
-{
- Uint32 i;
- double a;
- for (i = 0; i < (1 << LOG_BITS); i++)
- {
- a = (1 << LOG_LIN_BITS) / pow(2, i / (double)(1 << LOG_BITS));
- kmif_lt->logtbl[i] = (Uint32)a;
- }
- kmif_lt->lineartbl[0] = LOG_LIN_BITS << LOG_BITS;
- for (i = 1; i < (1 << LIN_BITS) + 1; i++)
- {
- Uint32 ua;
- a = i << (LOG_LIN_BITS - LIN_BITS);
- ua = (Uint32)((LOG_LIN_BITS - (log(a) / log(2))) * (1 << LOG_BITS));
- kmif_lt->lineartbl[i] = ua << 1;
- }
-}
-
-KMIF_LOGTABLE *LogTableAddRef(void)
-{
- ++log_tables_mutex;
- while (log_tables_mutex != 1)
- {
- XSLEEP(0);
- }
- if (!log_tables_refcount)
- {
- log_tables = (KMIF_LOGTABLE*) XMALLOC(sizeof(KMIF_LOGTABLE));
- if (log_tables)
- {
- log_tables->ctx = log_tables;
- log_tables->release = LogTableRelease;
- LogTableCalc(log_tables);
- }
- }
- if (log_tables) log_tables_refcount++;
- --log_tables_mutex;
- return log_tables;
-}
-
-#endif
+#include "nestypes.h"
+#include "s_logtbl.h"
+
+#if STATIC_TABLES
+
+static void LogTableRelease(void *ctx)
+{
+}
+
+static KMIF_LOGTABLE log_static_tables = {
+ &log_static_tables;
+ LogTableRelease,
+#include "s_logt.h"
+};
+
+
+KMIF_LOGTABLE *LogTableAddRef(void)
+{
+ log_static_tables.release = LogTableRelease;
+ return &log_static_tables;
+}
+
+#else
+
+#include
+
+static volatile Uint32 log_tables_mutex = 0;
+static Uint32 log_tables_refcount = 0;
+static KMIF_LOGTABLE *log_tables = 0;
+
+static void LogTableRelease(void *ctx)
+{
+ ++log_tables_mutex;
+ while (log_tables_mutex != 1)
+ {
+ XSLEEP(0);
+ }
+ log_tables_refcount--;
+ if (!log_tables_refcount)
+ {
+ XFREE(ctx);
+ log_tables = 0;
+ }
+ --log_tables_mutex;
+}
+
+static void LogTableCalc(KMIF_LOGTABLE *kmif_lt)
+{
+ Uint32 i;
+ double a;
+ for (i = 0; i < (1 << LOG_BITS); i++)
+ {
+ a = (1 << LOG_LIN_BITS) / pow(2, i / (double)(1 << LOG_BITS));
+ kmif_lt->logtbl[i] = (Uint32)a;
+ }
+ kmif_lt->lineartbl[0] = LOG_LIN_BITS << LOG_BITS;
+ for (i = 1; i < (1 << LIN_BITS) + 1; i++)
+ {
+ Uint32 ua;
+ a = i << (LOG_LIN_BITS - LIN_BITS);
+ ua = (Uint32)((LOG_LIN_BITS - (log(a) / log(2))) * (1 << LOG_BITS));
+ kmif_lt->lineartbl[i] = ua << 1;
+ }
+}
+
+KMIF_LOGTABLE *LogTableAddRef(void)
+{
+ ++log_tables_mutex;
+ while (log_tables_mutex != 1)
+ {
+ XSLEEP(0);
+ }
+ if (!log_tables_refcount)
+ {
+ log_tables = (KMIF_LOGTABLE*) XMALLOC(sizeof(KMIF_LOGTABLE));
+ if (log_tables)
+ {
+ log_tables->ctx = log_tables;
+ log_tables->release = LogTableRelease;
+ LogTableCalc(log_tables);
+ }
+ }
+ if (log_tables) log_tables_refcount++;
+ --log_tables_mutex;
+ return log_tables;
+}
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,80 +1,80 @@
-#include "Sms_Fm_Apu.h"
-
-#include "blargg_source.h"
-
-Sms_Fm_Apu::Sms_Fm_Apu()
-{ }
-
-Sms_Fm_Apu::~Sms_Fm_Apu()
-{ }
-
-blargg_err_t Sms_Fm_Apu::init( double clock_rate, double sample_rate )
-{
- period_ = clock_rate / sample_rate + 0.5;
- CHECK_ALLOC( !apu.set_rate( sample_rate, clock_rate ) );
-
- set_output( 0 );
- volume( 1.0 );
- reset();
- return blargg_ok;
-}
-
-void Sms_Fm_Apu::reset()
-{
- addr = 0;
- next_time = 0;
- last_amp = 0;
-
- apu.reset();
-}
-
-void Sms_Fm_Apu::write_data( blip_time_t time, int data )
-{
- if ( time > next_time )
- run_until( time );
-
- apu.write( addr, data );
-}
-
-void Sms_Fm_Apu::run_until( blip_time_t end_time )
-{
- assert( end_time > next_time );
-
- Blip_Buffer* const output = this->output_;
- if ( !output )
- {
- next_time = end_time;
- return;
- }
-
- blip_time_t time = next_time;
- do
- {
- Ym2413_Emu::sample_t samples [2] = {0};
- apu.run( 1, samples );
- int amp = (samples [0] + samples [1]) >> 1;
-
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth.offset_inline( time, delta, output );
- }
- time += period_;
- }
- while ( time < end_time );
-
- next_time = time;
-}
-
-void Sms_Fm_Apu::end_frame( blip_time_t time )
-{
- if ( time > next_time )
- run_until( time );
-
- next_time -= time;
- assert( next_time >= 0 );
-
- if ( output_ )
- output_->set_modified();
-}
+#include "Sms_Fm_Apu.h"
+
+#include "blargg_source.h"
+
+Sms_Fm_Apu::Sms_Fm_Apu()
+{ }
+
+Sms_Fm_Apu::~Sms_Fm_Apu()
+{ }
+
+blargg_err_t Sms_Fm_Apu::init( double clock_rate, double sample_rate )
+{
+ period_ = clock_rate / sample_rate + 0.5;
+ CHECK_ALLOC( !apu.set_rate( sample_rate, clock_rate ) );
+
+ set_output( 0 );
+ volume( 1.0 );
+ reset();
+ return blargg_ok;
+}
+
+void Sms_Fm_Apu::reset()
+{
+ addr = 0;
+ next_time = 0;
+ last_amp = 0;
+
+ apu.reset();
+}
+
+void Sms_Fm_Apu::write_data( blip_time_t time, int data )
+{
+ if ( time > next_time )
+ run_until( time );
+
+ apu.write( addr, data );
+}
+
+void Sms_Fm_Apu::run_until( blip_time_t end_time )
+{
+ assert( end_time > next_time );
+
+ Blip_Buffer* const output = this->output_;
+ if ( !output )
+ {
+ next_time = end_time;
+ return;
+ }
+
+ blip_time_t time = next_time;
+ do
+ {
+ Ym2413_Emu::sample_t samples [2] = {0};
+ apu.run( 1, samples );
+ int amp = (samples [0] + samples [1]) >> 1;
+
+ int delta = amp - last_amp;
+ if ( delta )
+ {
+ last_amp = amp;
+ synth.offset_inline( time, delta, output );
+ }
+ time += period_;
+ }
+ while ( time < end_time );
+
+ next_time = time;
+}
+
+void Sms_Fm_Apu::end_frame( blip_time_t time )
+{
+ if ( time > next_time )
+ run_until( time );
+
+ next_time -= time;
+ assert( next_time >= 0 );
+
+ if ( output_ )
+ output_->set_modified();
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Sms_Fm_Apu.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,47 +1,47 @@
-#ifndef SMS_FM_APU_H
-#define SMS_FM_APU_H
-
-#include "Blip_Buffer.h"
-#include "Ym2413_Emu.h"
-
-class Sms_Fm_Apu {
-public:
- static bool supported() { return Ym2413_Emu::supported(); }
- blargg_err_t init( double clock_rate, double sample_rate );
-
- void set_output( Blip_Buffer* b, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { output_ = b; }
- void volume( double v ) { synth.volume( 0.4 / 4096 * v ); }
- void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
-
- void reset();
-
- void write_addr( int data ) { addr = data; }
- void write_data( blip_time_t, int data );
-
- void end_frame( blip_time_t t );
-
-// Implementation
-public:
- Sms_Fm_Apu();
- ~Sms_Fm_Apu();
- BLARGG_DISABLE_NOTHROW
- enum { osc_count = 1 };
- void set_output( int i, Blip_Buffer* b, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { output_ = b; }
-
-private:
- Blip_Buffer* output_;
- blip_time_t next_time;
- int last_amp;
- int addr;
-
- int clock_;
- int rate_;
- blip_time_t period_;
-
- Blip_Synth_Norm synth;
- Ym2413_Emu apu;
-
- void run_until( blip_time_t );
-};
-
-#endif
+#ifndef SMS_FM_APU_H
+#define SMS_FM_APU_H
+
+#include "Blip_Buffer.h"
+#include "Ym2413_Emu.h"
+
+class Sms_Fm_Apu {
+public:
+ static bool supported() { return Ym2413_Emu::supported(); }
+ blargg_err_t init( double clock_rate, double sample_rate );
+
+ void set_output( Blip_Buffer* b, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { output_ = b; }
+ void volume( double v ) { synth.volume( 0.4 / 4096 * v ); }
+ void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
+
+ void reset();
+
+ void write_addr( int data ) { addr = data; }
+ void write_data( blip_time_t, int data );
+
+ void end_frame( blip_time_t t );
+
+// Implementation
+public:
+ Sms_Fm_Apu();
+ ~Sms_Fm_Apu();
+ BLARGG_DISABLE_NOTHROW
+ enum { osc_count = 1 };
+ void set_output( int i, Blip_Buffer* b, Blip_Buffer* = NULL, Blip_Buffer* = NULL ) { output_ = b; }
+
+private:
+ Blip_Buffer* output_;
+ blip_time_t next_time;
+ int last_amp;
+ int addr;
+
+ int clock_;
+ int rate_;
+ blip_time_t period_;
+
+ Blip_Synth_Norm synth;
+ Ym2413_Emu apu;
+
+ void run_until( blip_time_t );
+};
+
+#endif
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Emu.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Emu.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Emu.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Emu.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,462 +1,462 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Spc_Emu.h"
-
-#include "blargg_endian.h"
-
-/* Copyright (C) 2004-2009 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// TODO: support Spc_Filter's bass
-
-Spc_Emu::Spc_Emu()
-{
- set_type( gme_spc_type );
- set_gain( 1.4 );
-}
-
-Spc_Emu::~Spc_Emu() { }
-
-// Track info
-
-int const trailer_offset = 0x10200;
-
-inline byte const* Spc_Emu::trailer_() const { return &file_begin() [min( file_size(), trailer_offset )]; }
-
-inline int Spc_Emu::trailer_size_() const { return max( 0, file_size() - trailer_offset ); }
-
-static void get_spc_xid6( byte const begin [], int size, track_info_t* out )
-{
- // header
- byte const* end = begin + size;
- if ( size < 8 || memcmp( begin, "xid6", 4 ) )
- {
- check( false );
- return;
- }
- int info_size = get_le32( begin + 4 );
- byte const* in = begin + 8;
- if ( end - in > info_size )
- {
- dprintf( "SPC: Extra data after xid6\n" );
- end = in + info_size;
- }
-
- int year = 0;
- char copyright [256 + 5];
- int copyright_len = 0;
- int const year_len = 5;
- int disc = 0, track = 0;
-
- while ( end - in >= 4 )
- {
- // header
- int id = in [0];
- int data = in [3] * 0x100 + in [2];
- int type = in [1];
- int len = type ? data : 0;
- in += 4;
- if ( len > end - in )
- {
- dprintf( "SPC: xid6 goes past end" );
- break; // block goes past end of data
- }
-
- // handle specific block types
- char* field = NULL;
- switch ( id )
- {
- case 0x01: field = out->song; break;
- case 0x02: field = out->game; break;
- case 0x03: field = out->author; break;
- case 0x04: field = out->dumper; break;
- case 0x07: field = out->comment; break;
- case 0x10: field = out->ost; break;
- case 0x11: disc = data; break;
- case 0x12: track = data; break;
- case 0x14: year = data; break;
-
- //case 0x30: // intro length
- // Many SPCs have intro length set wrong for looped tracks, making it useless
- /*
- case 0x30:
- check( len == 4 );
- if ( len >= 4 )
- {
- out->intro_length = get_le32( in ) / 64;
- if ( out->length > 0 )
- {
- int loop = out->length - out->intro_length;
- if ( loop >= 2000 )
- out->loop_length = loop;
- }
- }
- break;
- */
-
- case 0x33:
- check( len == 4 );
- if ( len >= 4 )
- {
- out->fade_length = get_le32( in ) / 64;
- }
- break;
-
- case 0x13:
- copyright_len = min( len, (int) sizeof copyright - year_len );
- memcpy( ©right [year_len], in, copyright_len );
- break;
-
- default:
- if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
- (id > 0x14 && id < 0x30) || id > 0x36 )
- dprintf( "SPC: Unknown xid6 block: %X\n", (int) id );
- break;
- }
- if ( field )
- {
- check( type == 1 );
- Gme_File::copy_field_( field, (char const*) in, len );
- }
-
- // skip to next block
- in += len;
-
- // blocks are supposed to be 4-byte aligned with zero-padding...
- byte const* unaligned = in;
- while ( (in - begin) & 3 && in < end )
- {
- if ( *in++ != 0 )
- {
- // ...but some files have no padding
- in = unaligned;
- //dprintf( "SPC: xid6 info tag wasn't properly padded to align\n" );
- break;
- }
- }
- }
-
- char* p = ©right [year_len];
- if ( year )
- {
- *--p = ' ';
- // avoid using bloated printf
- for ( int n = 4; n--; )
- {
- *--p = char (year % 10 + '0');
- year /= 10;
- }
- copyright_len += year_len;
- }
- if ( copyright_len )
- Gme_File::copy_field_( out->copyright, p, copyright_len );
-
- if ( disc > 0 && disc <= 9 )
- {
- out->disc [0] = disc + '0';
- out->disc [1] = 0;
- }
-
- if ( track > 255 && track < ( ( 100 << 8 ) - 1 ) )
- {
- char* p = ©right [3];
- *p = 0;
- if ( track & 255 ) *--p = char (track & 255);
- track >>= 8;
- for ( int n = 2; n-- && track; )
- {
- *--p = char (track % 10 + '0');
- track /= 10;
- }
- memcpy( out->track, p, ©right [4] - p );
- }
-
- check( in == end );
-}
-
-static void get_spc_info( Spc_Emu::header_t const& h, byte const xid6 [], int xid6_size,
- track_info_t* out )
-{
- // decode length (can be in text or binary format, sometimes ambiguous ugh)
- int len_secs = 0;
- int i;
- for ( i = 0; i < 3; i++ )
- {
- unsigned n = h.len_secs [i] - '0';
- if ( n > 9 )
- {
- // ignore single-digit text lengths
- // (except if author field is present and begins at offset 1, ugh)
- if ( i == 1 && (h.author [0] || !h.author [1]) )
- len_secs = 0;
- break;
- }
- len_secs *= 10;
- len_secs += n;
- }
- if ( !len_secs || len_secs > 0x1FFF )
- len_secs = get_le16( h.len_secs );
- if ( len_secs < 0x1FFF )
- out->length = len_secs * 1000;
-
- long fade_msec = 0;
- for ( i = 0; i < 4; i++ )
- {
- unsigned n = h.fade_msec [i] - '0';
- if ( n > 9 )
- {
- if ( i == 1 && (h.author [0] || !h.author [1]) )
- fade_msec = -1;
- break;
- }
- fade_msec *= 10;
- fade_msec += n;
- }
- if ( i == 4 && unsigned( h.author [0] - '0' ) <= 9 )
- fade_msec = fade_msec * 10 + h.author [0] - '0';
- if ( fade_msec < 0 || fade_msec > 0x7FFF )
- fade_msec = get_le32( h.fade_msec );
- if ( fade_msec < 0x7FFF )
- out->fade_length = fade_msec;
-
- int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
- Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
-
- GME_COPY_FIELD( h, out, song );
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, dumper );
- GME_COPY_FIELD( h, out, comment );
-
- if ( xid6_size )
- get_spc_xid6( xid6, xid6_size, out );
-}
-
-static void hash_spc_file( Spc_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( &h.format, sizeof(h.format) );
- out.hash_( &h.version, sizeof(h.version) );
- out.hash_( &h.pc[0], sizeof(h.pc) );
- out.hash_( &h.a, sizeof(h.a) );
- out.hash_( &h.x, sizeof(h.x) );
- out.hash_( &h.y, sizeof(h.y) );
- out.hash_( &h.psw, sizeof(h.psw) );
- out.hash_( &h.sp, sizeof(h.sp) );
- out.hash_( &h.unused[0], sizeof(h.unused) );
- out.hash_( &h.emulator, sizeof(h.emulator) );
- out.hash_( &h.unused2[0], sizeof(h.unused2) );
- out.hash_( data, data_size );
-}
-
-blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
-{
- get_spc_info( header(), trailer_(), trailer_size_(), out );
- return blargg_ok;
-}
-
-static blargg_err_t check_spc_header( void const* header )
-{
- if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
- return blargg_err_file_type;
- return blargg_ok;
-}
-
-struct Spc_File : Gme_Info_
-{
- Spc_Emu::header_t header;
- blargg_vector data;
- blargg_vector xid6;
-
- Spc_File() { set_type( gme_spc_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- int file_size = in.remain();
- if ( file_size < 0x10180 )
- return blargg_err_file_type;
- RETURN_ERR( in.read( &header, header.size ) );
- RETURN_ERR( check_spc_header( header.tag ) );
- int const xid6_offset = 0x10200;
- RETURN_ERR( data.resize( blargg_min( xid6_offset - header.size, file_size - header.size ) ) );
- RETURN_ERR( in.read( data.begin(), data.end() - data.begin() ) );
- int xid6_size = file_size - xid6_offset;
- if ( xid6_size > 0 )
- {
- RETURN_ERR( xid6.resize( xid6_size ) );
- RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
- }
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- get_spc_info( header, xid6.begin(), xid6.size(), out );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_spc_file( header, data.begin(), data.end() - data.begin(), out );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
-static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
-
-gme_type_t_ const gme_spc_type [1] = {{ "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 }};
-
-// Setup
-
-blargg_err_t Spc_Emu::set_sample_rate_( int sample_rate )
-{
- smp.power();
- if ( sample_rate != native_sample_rate )
- {
- RETURN_ERR( resampler.resize_buffer( native_sample_rate / 20 * 2 ) );
- RETURN_ERR( resampler.set_rate( (double) native_sample_rate / sample_rate ) ); // 0.9965 rolloff
- }
- return blargg_ok;
-}
-
-void Spc_Emu::mute_voices_( int m )
-{
- Music_Emu::mute_voices_( m );
- for ( int i = 0, j = 1; i < SuperFamicom::SPC_DSP::voice_count; ++i, j <<= 1 )
- smp.dsp.channel_enable( i, !( m & j ) );
-}
-
-blargg_err_t Spc_Emu::load_mem_( byte const in [], int size )
-{
- assert( offsetof (header_t,unused2 [46]) == header_t::size );
- set_voice_count( SuperFamicom::SPC_DSP::voice_count );
- if ( size < 0x10180 )
- return blargg_err_file_type;
-
- static const char* const names [ SuperFamicom::SPC_DSP::voice_count ] = {
- "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
- };
- set_voice_names( names );
-
- return check_spc_header( in );
-}
-
-// Emulation
-
-void Spc_Emu::set_tempo_( double t )
-{
- smp.set_tempo( t );
-}
-
-blargg_err_t Spc_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- resampler.clear();
- filter.clear();
- smp.reset();
- const byte * ptr = file_begin();
-
- Spc_Emu::header_t & header = *(Spc_Emu::header_t*)ptr;
- ptr += sizeof(header);
-
- smp.regs.pc = header.pc[0] + header.pc[1] * 0x100;
- smp.regs.a = header.a;
- smp.regs.x = header.x;
- smp.regs.y = header.y;
- smp.regs.p = header.psw;
- smp.regs.s = header.sp;
-
- memcpy( smp.apuram, ptr, 0x10000 );
- memset( smp.apuram + 0xF4, 0, 4 );
- memcpy( smp.sfm_last, ptr + 0xF4, 4 );
-
- static const uint8_t regs_to_copy[][2] = { {0xFC,0xFF}, {0xFB,0xFF}, {0xFA,0xFF}, {0xF9,0xFF}, {0xF8,0xFF}, {0xF2,0xFF}, {0xF1,0x87} };
- for (auto n : regs_to_copy) smp.op_buswrite( n[0], ptr[ n[0] ] & n[1] );
- smp.timer0.stage3_ticks = ptr[ 0xFD ] & 0x0F;
- smp.timer1.stage3_ticks = ptr[ 0xFE ] & 0x0F;
- smp.timer2.stage3_ticks = ptr[ 0xFF ] & 0x0F;
- ptr += 0x10000;
-
- smp.dsp.spc_dsp.load( ptr );
-
- if ( !(smp.dsp.read( SuperFamicom::SPC_DSP::r_flg ) & 0x20) )
- {
- int addr = 0x100 * smp.dsp.read( SuperFamicom::SPC_DSP::r_esa );
- int end = addr + 0x800 * (smp.dsp.read( SuperFamicom::SPC_DSP::r_edl ) & 0x0F);
- if ( end > 0x10000 )
- end = 0x10000;
- memset( &smp.apuram [addr], 0xFF, end - addr );
- }
-
- filter.set_gain( (int) (gain() * Spc_Filter::gain_unit) );
- return blargg_ok;
-}
-
-blargg_err_t Spc_Emu::play_and_filter( int count, sample_t out [] )
-{
- smp.render( out, count );
- filter.run( out, count );
- return blargg_ok;
-}
-
-blargg_err_t Spc_Emu::skip_( int count )
-{
- if ( sample_rate() != native_sample_rate )
- {
- count = (int) (count * resampler.rate()) & ~1;
- count -= resampler.skip_input( count );
- }
-
- // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
-
- if ( count > 0 )
- {
- smp.skip( count );
- filter.clear();
- }
-
- // eliminate pop due to resampler
- if ( sample_rate() != native_sample_rate )
- {
- const int resampler_latency = 64;
- sample_t buf [resampler_latency];
- return play_( resampler_latency, buf );
- }
-
- return blargg_ok;
-}
-
-blargg_err_t Spc_Emu::play_( int count, sample_t out [] )
-{
- if ( sample_rate() == native_sample_rate )
- return play_and_filter( count, out );
-
- int remain = count;
- while ( remain > 0 )
- {
- remain -= resampler.read( &out [count - remain], remain );
- if ( remain > 0 )
- {
- int n = resampler.buffer_free();
- RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
- resampler.write( n );
- }
- }
- check( remain == 0 );
- return blargg_ok;
-}
-
-blargg_err_t Spc_Emu::hash_( Hash_Function& out ) const
-{
- hash_spc_file( header(), file_begin() + header_t::size, blargg_min( (size_t) ( 0x10200 - header_t::size ), (size_t) ( file_end() - file_begin() - header_t::size ) ), out );
- return blargg_ok;
-}
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Spc_Emu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2004-2009 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// TODO: support Spc_Filter's bass
+
+Spc_Emu::Spc_Emu()
+{
+ set_type( gme_spc_type );
+ set_gain( 1.4 );
+}
+
+Spc_Emu::~Spc_Emu() { }
+
+// Track info
+
+int const trailer_offset = 0x10200;
+
+inline byte const* Spc_Emu::trailer_() const { return &file_begin() [min( file_size(), trailer_offset )]; }
+
+inline int Spc_Emu::trailer_size_() const { return max( 0, file_size() - trailer_offset ); }
+
+static void get_spc_xid6( byte const begin [], int size, track_info_t* out )
+{
+ // header
+ byte const* end = begin + size;
+ if ( size < 8 || memcmp( begin, "xid6", 4 ) )
+ {
+ check( false );
+ return;
+ }
+ int info_size = get_le32( begin + 4 );
+ byte const* in = begin + 8;
+ if ( end - in > info_size )
+ {
+ dprintf( "SPC: Extra data after xid6\n" );
+ end = in + info_size;
+ }
+
+ int year = 0;
+ char copyright [256 + 5];
+ int copyright_len = 0;
+ int const year_len = 5;
+ int disc = 0, track = 0;
+
+ while ( end - in >= 4 )
+ {
+ // header
+ int id = in [0];
+ int data = in [3] * 0x100 + in [2];
+ int type = in [1];
+ int len = type ? data : 0;
+ in += 4;
+ if ( len > end - in )
+ {
+ dprintf( "SPC: xid6 goes past end" );
+ break; // block goes past end of data
+ }
+
+ // handle specific block types
+ char* field = NULL;
+ switch ( id )
+ {
+ case 0x01: field = out->song; break;
+ case 0x02: field = out->game; break;
+ case 0x03: field = out->author; break;
+ case 0x04: field = out->dumper; break;
+ case 0x07: field = out->comment; break;
+ case 0x10: field = out->ost; break;
+ case 0x11: disc = data; break;
+ case 0x12: track = data; break;
+ case 0x14: year = data; break;
+
+ //case 0x30: // intro length
+ // Many SPCs have intro length set wrong for looped tracks, making it useless
+ /*
+ case 0x30:
+ check( len == 4 );
+ if ( len >= 4 )
+ {
+ out->intro_length = get_le32( in ) / 64;
+ if ( out->length > 0 )
+ {
+ int loop = out->length - out->intro_length;
+ if ( loop >= 2000 )
+ out->loop_length = loop;
+ }
+ }
+ break;
+ */
+
+ case 0x33:
+ check( len == 4 );
+ if ( len >= 4 )
+ {
+ out->fade_length = get_le32( in ) / 64;
+ }
+ break;
+
+ case 0x13:
+ copyright_len = min( len, (int) sizeof copyright - year_len );
+ memcpy( ©right [year_len], in, copyright_len );
+ break;
+
+ default:
+ if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
+ (id > 0x14 && id < 0x30) || id > 0x36 )
+ dprintf( "SPC: Unknown xid6 block: %X\n", (int) id );
+ break;
+ }
+ if ( field )
+ {
+ check( type == 1 );
+ Gme_File::copy_field_( field, (char const*) in, len );
+ }
+
+ // skip to next block
+ in += len;
+
+ // blocks are supposed to be 4-byte aligned with zero-padding...
+ byte const* unaligned = in;
+ while ( (in - begin) & 3 && in < end )
+ {
+ if ( *in++ != 0 )
+ {
+ // ...but some files have no padding
+ in = unaligned;
+ //dprintf( "SPC: xid6 info tag wasn't properly padded to align\n" );
+ break;
+ }
+ }
+ }
+
+ char* p = ©right [year_len];
+ if ( year )
+ {
+ *--p = ' ';
+ // avoid using bloated printf
+ for ( int n = 4; n--; )
+ {
+ *--p = char (year % 10 + '0');
+ year /= 10;
+ }
+ copyright_len += year_len;
+ }
+ if ( copyright_len )
+ Gme_File::copy_field_( out->copyright, p, copyright_len );
+
+ if ( disc > 0 && disc <= 9 )
+ {
+ out->disc [0] = disc + '0';
+ out->disc [1] = 0;
+ }
+
+ if ( track > 255 && track < ( ( 100 << 8 ) - 1 ) )
+ {
+ char* p = ©right [3];
+ *p = 0;
+ if ( track & 255 ) *--p = char (track & 255);
+ track >>= 8;
+ for ( int n = 2; n-- && track; )
+ {
+ *--p = char (track % 10 + '0');
+ track /= 10;
+ }
+ memcpy( out->track, p, ©right [4] - p );
+ }
+
+ check( in == end );
+}
+
+static void get_spc_info( Spc_Emu::header_t const& h, byte const xid6 [], int xid6_size,
+ track_info_t* out )
+{
+ // decode length (can be in text or binary format, sometimes ambiguous ugh)
+ int len_secs = 0;
+ int i;
+ for ( i = 0; i < 3; i++ )
+ {
+ unsigned n = h.len_secs [i] - '0';
+ if ( n > 9 )
+ {
+ // ignore single-digit text lengths
+ // (except if author field is present and begins at offset 1, ugh)
+ if ( i == 1 && (h.author [0] || !h.author [1]) )
+ len_secs = 0;
+ break;
+ }
+ len_secs *= 10;
+ len_secs += n;
+ }
+ if ( !len_secs || len_secs > 0x1FFF )
+ len_secs = get_le16( h.len_secs );
+ if ( len_secs < 0x1FFF )
+ out->length = len_secs * 1000;
+
+ long fade_msec = 0;
+ for ( i = 0; i < 4; i++ )
+ {
+ unsigned n = h.fade_msec [i] - '0';
+ if ( n > 9 )
+ {
+ if ( i == 1 && (h.author [0] || !h.author [1]) )
+ fade_msec = -1;
+ break;
+ }
+ fade_msec *= 10;
+ fade_msec += n;
+ }
+ if ( i == 4 && unsigned( h.author [0] - '0' ) <= 9 )
+ fade_msec = fade_msec * 10 + h.author [0] - '0';
+ if ( fade_msec < 0 || fade_msec > 0x7FFF )
+ fade_msec = get_le32( h.fade_msec );
+ if ( fade_msec < 0x7FFF )
+ out->fade_length = fade_msec;
+
+ int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
+ Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
+
+ GME_COPY_FIELD( h, out, song );
+ GME_COPY_FIELD( h, out, game );
+ GME_COPY_FIELD( h, out, dumper );
+ GME_COPY_FIELD( h, out, comment );
+
+ if ( xid6_size )
+ get_spc_xid6( xid6, xid6_size, out );
+}
+
+static void hash_spc_file( Spc_Emu::header_t const& h, byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( &h.format, sizeof(h.format) );
+ out.hash_( &h.version, sizeof(h.version) );
+ out.hash_( &h.pc[0], sizeof(h.pc) );
+ out.hash_( &h.a, sizeof(h.a) );
+ out.hash_( &h.x, sizeof(h.x) );
+ out.hash_( &h.y, sizeof(h.y) );
+ out.hash_( &h.psw, sizeof(h.psw) );
+ out.hash_( &h.sp, sizeof(h.sp) );
+ out.hash_( &h.unused[0], sizeof(h.unused) );
+ out.hash_( &h.emulator, sizeof(h.emulator) );
+ out.hash_( &h.unused2[0], sizeof(h.unused2) );
+ out.hash_( data, data_size );
+}
+
+blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
+{
+ get_spc_info( header(), trailer_(), trailer_size_(), out );
+ return blargg_ok;
+}
+
+static blargg_err_t check_spc_header( void const* header )
+{
+ if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
+ return blargg_err_file_type;
+ return blargg_ok;
+}
+
+struct Spc_File : Gme_Info_
+{
+ Spc_Emu::header_t header;
+ blargg_vector data;
+ blargg_vector xid6;
+
+ Spc_File() { set_type( gme_spc_type ); }
+
+ blargg_err_t load_( Data_Reader& in )
+ {
+ int file_size = in.remain();
+ if ( file_size < 0x10180 )
+ return blargg_err_file_type;
+ RETURN_ERR( in.read( &header, header.size ) );
+ RETURN_ERR( check_spc_header( header.tag ) );
+ int const xid6_offset = 0x10200;
+ RETURN_ERR( data.resize( blargg_min( xid6_offset - header.size, file_size - header.size ) ) );
+ RETURN_ERR( in.read( data.begin(), data.end() - data.begin() ) );
+ int xid6_size = file_size - xid6_offset;
+ if ( xid6_size > 0 )
+ {
+ RETURN_ERR( xid6.resize( xid6_size ) );
+ RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
+ }
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ get_spc_info( header, xid6.begin(), xid6.size(), out );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_spc_file( header, data.begin(), data.end() - data.begin(), out );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
+static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
+
+gme_type_t_ const gme_spc_type [1] = {{ "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 }};
+
+// Setup
+
+blargg_err_t Spc_Emu::set_sample_rate_( int sample_rate )
+{
+ smp.power();
+ if ( sample_rate != native_sample_rate )
+ {
+ RETURN_ERR( resampler.resize_buffer( native_sample_rate / 20 * 2 ) );
+ RETURN_ERR( resampler.set_rate( (double) native_sample_rate / sample_rate ) ); // 0.9965 rolloff
+ }
+ return blargg_ok;
+}
+
+void Spc_Emu::mute_voices_( int m )
+{
+ Music_Emu::mute_voices_( m );
+ for ( int i = 0, j = 1; i < SuperFamicom::SPC_DSP::voice_count; ++i, j <<= 1 )
+ smp.dsp.channel_enable( i, !( m & j ) );
+}
+
+blargg_err_t Spc_Emu::load_mem_( byte const in [], int size )
+{
+ assert( offsetof (header_t,unused2 [46]) == header_t::size );
+ set_voice_count( SuperFamicom::SPC_DSP::voice_count );
+ if ( size < 0x10180 )
+ return blargg_err_file_type;
+
+ static const char* const names [ SuperFamicom::SPC_DSP::voice_count ] = {
+ "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
+ };
+ set_voice_names( names );
+
+ return check_spc_header( in );
+}
+
+// Emulation
+
+void Spc_Emu::set_tempo_( double t )
+{
+ smp.set_tempo( t );
+}
+
+blargg_err_t Spc_Emu::start_track_( int track )
+{
+ RETURN_ERR( Music_Emu::start_track_( track ) );
+ resampler.clear();
+ filter.clear();
+ smp.reset();
+ const byte * ptr = file_begin();
+
+ Spc_Emu::header_t & header = *(Spc_Emu::header_t*)ptr;
+ ptr += sizeof(header);
+
+ smp.regs.pc = header.pc[0] + header.pc[1] * 0x100;
+ smp.regs.a = header.a;
+ smp.regs.x = header.x;
+ smp.regs.y = header.y;
+ smp.regs.p = header.psw;
+ smp.regs.s = header.sp;
+
+ memcpy( smp.apuram, ptr, 0x10000 );
+ memset( smp.apuram + 0xF4, 0, 4 );
+ memcpy( smp.sfm_last, ptr + 0xF4, 4 );
+
+ static const uint8_t regs_to_copy[][2] = { {0xFC,0xFF}, {0xFB,0xFF}, {0xFA,0xFF}, {0xF9,0xFF}, {0xF8,0xFF}, {0xF2,0xFF}, {0xF1,0x87} };
+ for (auto n : regs_to_copy) smp.op_buswrite( n[0], ptr[ n[0] ] & n[1] );
+ smp.timer0.stage3_ticks = ptr[ 0xFD ] & 0x0F;
+ smp.timer1.stage3_ticks = ptr[ 0xFE ] & 0x0F;
+ smp.timer2.stage3_ticks = ptr[ 0xFF ] & 0x0F;
+ ptr += 0x10000;
+
+ smp.dsp.spc_dsp.load( ptr );
+
+ if ( !(smp.dsp.read( SuperFamicom::SPC_DSP::r_flg ) & 0x20) )
+ {
+ int addr = 0x100 * smp.dsp.read( SuperFamicom::SPC_DSP::r_esa );
+ int end = addr + 0x800 * (smp.dsp.read( SuperFamicom::SPC_DSP::r_edl ) & 0x0F);
+ if ( end > 0x10000 )
+ end = 0x10000;
+ memset( &smp.apuram [addr], 0xFF, end - addr );
+ }
+
+ filter.set_gain( (int) (gain() * Spc_Filter::gain_unit) );
+ return blargg_ok;
+}
+
+blargg_err_t Spc_Emu::play_and_filter( int count, sample_t out [] )
+{
+ smp.render( out, count );
+ filter.run( out, count );
+ return blargg_ok;
+}
+
+blargg_err_t Spc_Emu::skip_( int count )
+{
+ if ( sample_rate() != native_sample_rate )
+ {
+ count = (int) (count * resampler.rate()) & ~1;
+ count -= resampler.skip_input( count );
+ }
+
+ // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
+
+ if ( count > 0 )
+ {
+ smp.skip( count );
+ filter.clear();
+ }
+
+ // eliminate pop due to resampler
+ if ( sample_rate() != native_sample_rate )
+ {
+ const int resampler_latency = 64;
+ sample_t buf [resampler_latency];
+ return play_( resampler_latency, buf );
+ }
+
+ return blargg_ok;
+}
+
+blargg_err_t Spc_Emu::play_( int count, sample_t out [] )
+{
+ if ( sample_rate() == native_sample_rate )
+ return play_and_filter( count, out );
+
+ int remain = count;
+ while ( remain > 0 )
+ {
+ remain -= resampler.read( &out [count - remain], remain );
+ if ( remain > 0 )
+ {
+ int n = resampler.buffer_free();
+ RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
+ resampler.write( n );
+ }
+ }
+ check( remain == 0 );
+ return blargg_ok;
+}
+
+blargg_err_t Spc_Emu::hash_( Hash_Function& out ) const
+{
+ hash_spc_file( header(), file_begin() + header_t::size, blargg_min( (size_t) ( 0x10200 - header_t::size ), (size_t) ( file_end() - file_begin() - header_t::size ) ), out );
+ return blargg_ok;
+}
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.cpp kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.cpp
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.cpp 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.cpp 2013-05-31 22:59:22.000000000 +0000
@@ -1,680 +1,680 @@
-// Game_Music_Emu $vers. http://www.slack.net/~ant/
-
-#include "Spc_Sfm.h"
-
-#include "blargg_endian.h"
-
-#include
-
-/* Copyright (C) 2004-2013 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// TODO: support Spc_Filter's bass
-
-Sfm_Emu::Sfm_Emu()
-{
- set_type( gme_sfm_type );
- set_gain( 1.4 );
- set_max_initial_silence( 30 );
- set_silence_lookahead( 30 ); // Some SFMs may have a lot of initialization code
-}
-
-Sfm_Emu::~Sfm_Emu() { }
-
-// Track info
-
-static void hash_sfm_file( byte const* data, int data_size, Music_Emu::Hash_Function& out )
-{
- out.hash_( data, data_size );
-}
-
-static void copy_field( char* out, size_t size, const Bml_Parser& in, char const* in_path )
-{
- const char * value = in.enumValue( in_path );
- if ( value ) strncpy( out, value, size - 1 ), out[ size - 1 ] = 0;
- else out[ 0 ] = 0;
-}
-
-static void copy_info( track_info_t* out, const Bml_Parser& in )
-{
- copy_field( out->song, sizeof(out->song), in, "information:title" );
- copy_field( out->game, sizeof(out->game), in, "information:game" );
- copy_field( out->author, sizeof(out->author), in, "information:author" );
- copy_field( out->composer, sizeof(out->composer), in, "information:composer" );
- copy_field( out->copyright, sizeof(out->copyright), in, "information:copyright" );
- copy_field( out->date, sizeof(out->date), in, "information:date" );
- copy_field( out->track, sizeof(out->track), in, "information:track" );
- copy_field( out->disc, sizeof(out->disc), in, "information:disc" );
- copy_field( out->dumper, sizeof(out->dumper), in, "information:dumper" );
-
- char * end;
- const char * value = in.enumValue( "timing:length" );
- if ( value )
- out->length = strtoul( value, &end, 10 );
- else
- out->length = 0;
-
- value = in.enumValue( "timing:fade" );
- if ( value )
- out->fade_length = strtoul( value, &end, 10 );
- else
- out->fade_length = 0;
-}
-
-blargg_err_t Sfm_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_info( out, metadata );
- return blargg_ok;
-}
-
-static void set_track_info( const track_info_t* in, Bml_Parser& out )
-{
- out.setValue( "information:title", in->song );
- out.setValue( "information:game", in->game );
- out.setValue( "information:author", in->author );
- out.setValue( "information:composer", in->composer );
- out.setValue( "information:copyright", in->copyright );
- out.setValue( "information:date", in->date );
- out.setValue( "information:track", in->track );
- out.setValue( "information:disc", in->disc );
- out.setValue( "information:dumper", in->dumper );
-
- out.setValue( "timing:length", in->length );
- out.setValue( "timing:fade", in->fade_length );
-}
-
-blargg_err_t Sfm_Emu::set_track_info_( const track_info_t* in, int )
-{
- ::set_track_info(in, metadata);
-
- return blargg_ok;
-}
-
-static blargg_err_t check_sfm_header( void const* header )
-{
- if ( memcmp( header, "SFM1", 4 ) )
- return blargg_err_file_type;
- return blargg_ok;
-}
-
-struct Sfm_File : Gme_Info_
-{
- blargg_vector data;
- Bml_Parser metadata;
- unsigned long original_metadata_size;
-
- Sfm_File() { set_type( gme_sfm_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- int file_size = in.remain();
- if ( file_size < Sfm_Emu::sfm_min_file_size )
- return blargg_err_file_type;
- RETURN_ERR( data.resize( file_size ) );
- RETURN_ERR( in.read( data.begin(), data.end() - data.begin() ) );
- RETURN_ERR( check_sfm_header( data.begin() ) );
- if ( file_size < 8 )
- return "SFM file too small";
- int metadata_size = get_le32( data.begin() + 4 );
- metadata.parseDocument( (const char *)data.begin() + 8, metadata_size );
- original_metadata_size = metadata_size;
- return blargg_ok;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_info( out, metadata );
- return blargg_ok;
- }
-
- blargg_err_t set_track_info_( const track_info_t* in, int )
- {
- ::set_track_info( in, metadata );
- return blargg_ok;
- }
-
- blargg_err_t hash_( Hash_Function& out ) const
- {
- hash_sfm_file( data.begin(), data.end() - data.begin(), out );
- return blargg_ok;
- }
-
- blargg_err_t save_( gme_writer_t writer, void* your_data ) const
- {
- std::string metadata_serialized;
- metadata.serialize( metadata_serialized );
- uint8_t meta_length[4];
- set_le32( meta_length, (unsigned int) metadata_serialized.length() );
- writer( your_data, "SFM1", 4 );
- writer( your_data, meta_length, 4 );
- writer( your_data, metadata_serialized.c_str(), metadata_serialized.length() );
- writer( your_data, data.begin() + 4 + 4 + original_metadata_size, data.size() - (4 + 4 + original_metadata_size) );
- return blargg_ok;
- }
-};
-
-static Music_Emu* new_sfm_emu () { return BLARGG_NEW Sfm_Emu ; }
-static Music_Emu* new_sfm_file() { return BLARGG_NEW Sfm_File; }
-
-gme_type_t_ const gme_sfm_type [1] = {{ "Super Nintendo with log", 1, &new_sfm_emu, &new_sfm_file, "SFM", 0 }};
-
-// Setup
-
-blargg_err_t Sfm_Emu::set_sample_rate_( int sample_rate )
-{
- smp.power();
- if ( sample_rate != native_sample_rate )
- {
- RETURN_ERR( resampler.resize_buffer( native_sample_rate / 20 * 2 ) );
- RETURN_ERR( resampler.set_rate( (double) native_sample_rate / sample_rate ) ); // 0.9965 rolloff
- }
- return blargg_ok;
-}
-
-void Sfm_Emu::mute_voices_( int m )
-{
- Music_Emu::mute_voices_( m );
- for ( int i = 0, j = 1; i < 8; ++i, j <<= 1 )
- smp.dsp.channel_enable( i, !( m & j ) );
-}
-
-blargg_err_t Sfm_Emu::load_mem_( byte const in [], int size )
-{
- set_voice_count( 8 );
- if ( size < Sfm_Emu::sfm_min_file_size )
- return blargg_err_file_type;
-
- static const char* const names [ 8 ] = {
- "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
- };
- set_voice_names( names );
-
- RETURN_ERR( check_sfm_header( in ) );
-
- const byte * ptr = file_begin();
- int metadata_size = get_le32(ptr + 4);
- if ( file_size() < metadata_size + Sfm_Emu::sfm_min_file_size )
- return "SFM file too small";
- metadata.parseDocument((const char *) ptr + 8, metadata_size);
-
- return blargg_ok;
-}
-
-// Emulation
-
-void Sfm_Emu::set_tempo_( double t )
-{
- smp.set_tempo( t );
-}
-
-// (n ? n : 256)
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-
-#define META_ENUM_INT(n,d) (value = metadata.enumValue(n), value ? strtol(value, &end, 10) : (d))
-
-static const byte ipl_rom[0x40] =
-{
- 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
- 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
- 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
- 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
- 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB,
- 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
- 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD,
- 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
-};
-
-blargg_err_t Sfm_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- resampler.clear();
- filter.clear();
- const byte * ptr = file_begin();
- int metadata_size = get_le32(ptr + 4);
-
- memcpy( smp.iplrom, ipl_rom, 64 );
-
- smp.reset();
-
- memcpy( smp.apuram, ptr + 8 + metadata_size, 65536 );
-
- memcpy( smp.dsp.spc_dsp.m.regs, ptr + 8 + metadata_size + 65536, 128 );
-
- const uint8_t* log_begin = ptr + 8 + metadata_size + 65536 + 128;
- const uint8_t* log_end = ptr + file_size();
- size_t loop_begin = log_end - log_begin;
-
- char * end;
- const char * value;
-
- loop_begin = META_ENUM_INT("timing:loopstart", loop_begin);
-
- smp.set_sfm_queue( log_begin, log_end, log_begin + loop_begin );
-
- uint32_t test = META_ENUM_INT("smp:test", 0);
- smp.status.clock_speed = (test >> 6) & 3;
- smp.status.timer_speed = (test >> 4) & 3;
- smp.status.timers_enable = test & 0x08;
- smp.status.ram_disable = test & 0x04;
- smp.status.ram_writable = test & 0x02;
- smp.status.timers_disable = test & 0x01;
-
- smp.status.iplrom_enable = META_ENUM_INT("smp:iplrom",1);
- smp.status.dsp_addr = META_ENUM_INT("smp:dspaddr",0);
-
- value = metadata.enumValue("smp:ram");
- if (value)
- {
- smp.status.ram00f8 = strtol(value, &end, 10);
- if (*end)
- {
- value = end + 1;
- smp.status.ram00f9 = strtol(value, &end, 10);
- }
- }
-
- std::string name;
- std::ostringstream oss;
-
- name = "smp:regs:";
- smp.regs.pc = META_ENUM_INT(name + "pc", 0xffc0);
- smp.regs.a = META_ENUM_INT(name + "a", 0x00);
- smp.regs.x = META_ENUM_INT(name + "x", 0x00);
- smp.regs.y = META_ENUM_INT(name + "y", 0x00);
- smp.regs.s = META_ENUM_INT(name + "s", 0xef);
- smp.regs.p = META_ENUM_INT(name + "psw", 0x02);
-
- value = metadata.enumValue("smp:ports");
- if (value)
- {
- for (auto &n : smp.sfm_last)
- {
- n = strtol(value, &end, 10);
- if (*end == ',')
- value = end + 1;
- else
- break;
- }
- }
-
- for (int i = 0; i < 3; ++i)
- {
- SuperFamicom::SMP::Timer<192> &t = (i == 0 ? smp.timer0 : (i == 1 ? smp.timer1 : *(SuperFamicom::SMP::Timer<192>*)&smp.timer2));
- oss.str("");
- oss.clear();
- oss << "smp:timer[" << i << "]:";
- name = oss.str();
- value = metadata.enumValue(name + "enable");
- if (value)
- {
- t.enable = !!strtol(value, &end, 10);
- }
- value = metadata.enumValue(name + "target");
- if (value)
- {
- t.target = strtol(value, &end, 10);
- }
- value = metadata.enumValue(name + "stage");
- if (value)
- {
- t.stage0_ticks = strtol(value, &end, 10);
- if (*end != ',') break;
- value = end + 1;
- t.stage1_ticks = strtol(value, &end, 10);
- if (*end != ',') break;
- value = end + 1;
- t.stage2_ticks = strtol(value, &end, 10);
- if (*end != ',') break;
- value = end + 1;
- t.stage3_ticks = strtol(value, &end, 10);
- }
- value = metadata.enumValue(name + "line");
- if (value)
- {
- t.current_line = !!strtol(value, &end, 10);
- }
- }
-
- smp.dsp.clock = META_ENUM_INT("dsp:clock", 0) * 4096;
-
- smp.dsp.spc_dsp.m.echo_hist_pos = &smp.dsp.spc_dsp.m.echo_hist[META_ENUM_INT("dsp:echohistaddr", 0)];
-
- value = metadata.enumValue("dsp:echohistdata");
- if (value)
- {
- for (int i = 0; i < 8; ++i)
- {
- smp.dsp.spc_dsp.m.echo_hist[i][0] = strtol(value, &end, 10);
- value = strchr(value, ',');
- if (!value) break;
- ++value;
- smp.dsp.spc_dsp.m.echo_hist[i][1] = strtol(value, &end, 10);
- value = strchr(value, ',');
- if (!value) break;
- ++value;
- }
- }
-
- smp.dsp.spc_dsp.m.phase = META_ENUM_INT("dsp:sample", 0);
- smp.dsp.spc_dsp.m.kon = META_ENUM_INT("dsp:kon", 0);
- smp.dsp.spc_dsp.m.noise = META_ENUM_INT("dsp:noise", 0);
- smp.dsp.spc_dsp.m.counter = META_ENUM_INT("dsp:counter", 0);
- smp.dsp.spc_dsp.m.echo_offset = META_ENUM_INT("dsp:echooffset", 0);
- smp.dsp.spc_dsp.m.echo_length = META_ENUM_INT("dsp:echolength", 0);
- smp.dsp.spc_dsp.m.new_kon = META_ENUM_INT("dsp:koncache", 0);
- smp.dsp.spc_dsp.m.endx_buf = META_ENUM_INT("dsp:endx", 0);
- smp.dsp.spc_dsp.m.envx_buf = META_ENUM_INT("dsp:envx", 0);
- smp.dsp.spc_dsp.m.outx_buf = META_ENUM_INT("dsp:outx", 0);
- smp.dsp.spc_dsp.m.t_pmon = META_ENUM_INT("dsp:pmon", 0);
- smp.dsp.spc_dsp.m.t_non = META_ENUM_INT("dsp:non", 0);
- smp.dsp.spc_dsp.m.t_eon = META_ENUM_INT("dsp:eon", 0);
- smp.dsp.spc_dsp.m.t_dir = META_ENUM_INT("dsp:dir", 0);
- smp.dsp.spc_dsp.m.t_koff = META_ENUM_INT("dsp:koff", 0);
- smp.dsp.spc_dsp.m.t_brr_next_addr = META_ENUM_INT("dsp:brrnext", 0);
- smp.dsp.spc_dsp.m.t_adsr0 = META_ENUM_INT("dsp:adsr0", 0);
- smp.dsp.spc_dsp.m.t_brr_header = META_ENUM_INT("dsp:brrheader", 0);
- smp.dsp.spc_dsp.m.t_brr_byte = META_ENUM_INT("dsp:brrdata", 0);
- smp.dsp.spc_dsp.m.t_srcn = META_ENUM_INT("dsp:srcn", 0);
- smp.dsp.spc_dsp.m.t_esa = META_ENUM_INT("dsp:esa", 0);
- smp.dsp.spc_dsp.m.t_echo_enabled = !META_ENUM_INT("dsp:echodisable", 0);
- smp.dsp.spc_dsp.m.t_dir_addr = META_ENUM_INT("dsp:diraddr", 0);
- smp.dsp.spc_dsp.m.t_pitch = META_ENUM_INT("dsp:pitch", 0);
- smp.dsp.spc_dsp.m.t_output = META_ENUM_INT("dsp:output", 0);
- smp.dsp.spc_dsp.m.t_looped = META_ENUM_INT("dsp:looped", 0);
- smp.dsp.spc_dsp.m.t_echo_ptr = META_ENUM_INT("dsp:echoaddr", 0);
-
-
-#define META_ENUM_LEVELS(n, o) \
- value = metadata.enumValue(n); \
- if (value) \
- { \
- (o)[0] = strtol(value, &end, 10); \
- if (*end) \
- { \
- value = end + 1; \
- (o)[1] = strtol(value, &end, 10); \
- } \
- }
-
- META_ENUM_LEVELS("dsp:mainout", smp.dsp.spc_dsp.m.t_main_out);
- META_ENUM_LEVELS("dsp:echoout", smp.dsp.spc_dsp.m.t_echo_out);
- META_ENUM_LEVELS("dsp:echoin", smp.dsp.spc_dsp.m.t_echo_in);
-
-#undef META_ENUM_LEVELS
-
- for (int i = 0; i < 8; ++i)
- {
- oss.str("");
- oss.clear();
- oss << "dsp:voice[" << i << "]:";
- name = oss.str();
- SuperFamicom::SPC_DSP::voice_t & voice = smp.dsp.spc_dsp.m.voices[i];
- value = metadata.enumValue(name + "brrhistaddr");
- if (value)
- {
- voice.buf_pos = strtol(value, &end, 10);
- }
- value = metadata.enumValue(name + "brrhistdata");
- if (value)
- {
- for (int j = 0; j < SuperFamicom::SPC_DSP::brr_buf_size; ++j)
- {
- voice.buf[j] = voice.buf[j + SuperFamicom::SPC_DSP::brr_buf_size] = strtol(value, &end, 10);
- if (!*end) break;
- value = end + 1;
- }
- }
- voice.interp_pos = META_ENUM_INT(name + "interpaddr",0);
- voice.brr_addr = META_ENUM_INT(name + "brraddr",0);
- voice.brr_offset = META_ENUM_INT(name + "brroffset",0);
- voice.vbit = META_ENUM_INT(name + "vbit",0);
- voice.regs = &smp.dsp.spc_dsp.m.regs[META_ENUM_INT(name + "vidx",0)];
- voice.kon_delay = META_ENUM_INT(name + "kondelay", 0);
- voice.env_mode = (SuperFamicom::SPC_DSP::env_mode_t) META_ENUM_INT(name + "envmode", 0);
- voice.env = META_ENUM_INT(name + "env", 0);
- voice.t_envx_out = META_ENUM_INT(name + "envxout", 0);
- voice.hidden_env = META_ENUM_INT(name + "envcache", 0);
- }
-
- filter.set_gain( (int) (gain() * Spc_Filter::gain_unit) );
- return blargg_ok;
-}
-
-#undef META_ENUM_INT
-
-void Sfm_Emu::create_updated_metadata( Bml_Parser &out ) const
-{
- bool first;
- std::string name;
- std::ostringstream oss;
-
- metadata.serialize(name);
-
- out.parseDocument(name.c_str());
-
- out.setValue( "smp:test", (smp.status.clock_speed << 6) | (smp.status.timer_speed << 4) | (smp.status.timers_enable << 3) | (smp.status.ram_disable << 2) | (smp.status.ram_writable << 1) | (smp.status.timers_disable << 0) );
- out.setValue( "smp:iplrom", smp.status.iplrom_enable );
- out.setValue( "smp:dspaddr", smp.status.dsp_addr );
-
- oss.str("");
- oss.clear();
- oss << (unsigned long)smp.status.ram00f8 << "," << (unsigned long)smp.status.ram00f9;
- out.setValue( "smp:ram", oss.str().c_str() );
-
- name = "smp:regs:";
- out.setValue( name + "pc", smp.regs.pc );
- out.setValue( name + "a", smp.regs.a );
- out.setValue( name + "x", smp.regs.x );
- out.setValue( name + "y", smp.regs.y );
- out.setValue( name + "s", smp.regs.s );
- out.setValue( name + "psw", smp.regs.p );
-
- oss.str("");
- oss.clear();
- first = true;
- for (auto n : smp.sfm_last)
- {
- if (!first) oss << ",";
- oss << (unsigned long)n;
- first = false;
- }
- out.setValue("smp:ports", oss.str().c_str());
-
- for (int i = 0; i < 3; ++i)
- {
- SuperFamicom::SMP::Timer<192> const& t = (i == 0 ? smp.timer0 : (i == 1 ? smp.timer1 : *(SuperFamicom::SMP::Timer<192>*)&smp.timer2));
- oss.str("");
- oss.clear();
- oss << "smp:timer[" << i << "]:";
- name = oss.str();
- out.setValue( name + "enable", t.enable );
- out.setValue( name + "target", t.target );
- oss.str("");
- oss.clear();
- oss << (unsigned long)t.stage0_ticks << "," << (unsigned long)t.stage1_ticks << ","
- << (unsigned long)t.stage2_ticks << "," << (unsigned long)t.stage3_ticks;
- out.setValue( name + "stage", oss.str().c_str() );
- out.setValue( name + "line", t.current_line );
- }
-
- out.setValue( "dsp:clock", smp.dsp.clock / 4096 );
-
- out.setValue( "dsp:echohistaddr", smp.dsp.spc_dsp.m.echo_hist_pos - smp.dsp.spc_dsp.m.echo_hist );
-
- oss.str("");
- oss.clear();
- for (int i = 0; i < 8; ++i)
- {
- oss << smp.dsp.spc_dsp.m.echo_hist[i][0] << ","
- << smp.dsp.spc_dsp.m.echo_hist[i][1];
- if ( i != 7 ) oss << ",";
- }
- out.setValue( "dsp:echohistdata", oss.str().c_str() );
-
- out.setValue( "dsp:sample", smp.dsp.spc_dsp.m.phase );
- out.setValue( "dsp:kon", smp.dsp.spc_dsp.m.kon );
- out.setValue( "dsp:noise", smp.dsp.spc_dsp.m.noise );
- out.setValue( "dsp:counter", smp.dsp.spc_dsp.m.counter );
- out.setValue( "dsp:echooffset", smp.dsp.spc_dsp.m.echo_offset );
- out.setValue( "dsp:echolength", smp.dsp.spc_dsp.m.echo_length );
- out.setValue( "dsp:koncache", smp.dsp.spc_dsp.m.new_kon );
- out.setValue( "dsp:endx", smp.dsp.spc_dsp.m.endx_buf );
- out.setValue( "dsp:envx", smp.dsp.spc_dsp.m.envx_buf );
- out.setValue( "dsp:outx", smp.dsp.spc_dsp.m.outx_buf );
- out.setValue( "dsp:pmon", smp.dsp.spc_dsp.m.t_pmon );
- out.setValue( "dsp:non", smp.dsp.spc_dsp.m.t_non );
- out.setValue( "dsp:eon", smp.dsp.spc_dsp.m.t_eon );
- out.setValue( "dsp:dir", smp.dsp.spc_dsp.m.t_dir );
- out.setValue( "dsp:koff", smp.dsp.spc_dsp.m.t_koff );
- out.setValue( "dsp:brrnext", smp.dsp.spc_dsp.m.t_brr_next_addr );
- out.setValue( "dsp:adsr0", smp.dsp.spc_dsp.m.t_adsr0 );
- out.setValue( "dsp:brrheader", smp.dsp.spc_dsp.m.t_brr_header );
- out.setValue( "dsp:brrdata", smp.dsp.spc_dsp.m.t_brr_byte );
- out.setValue( "dsp:srcn", smp.dsp.spc_dsp.m.t_srcn );
- out.setValue( "dsp:esa", smp.dsp.spc_dsp.m.t_esa );
- out.setValue( "dsp:echodisable", !smp.dsp.spc_dsp.m.t_echo_enabled );
- out.setValue( "dsp:diraddr", smp.dsp.spc_dsp.m.t_dir_addr );
- out.setValue( "dsp:pitch", smp.dsp.spc_dsp.m.t_pitch );
- out.setValue( "dsp:output", smp.dsp.spc_dsp.m.t_output );
- out.setValue( "dsp:looped", smp.dsp.spc_dsp.m.t_looped );
- out.setValue( "dsp:echoaddr", smp.dsp.spc_dsp.m.t_echo_ptr );
-
-#define META_WRITE_LEVELS(n, o) \
- oss.str(""); \
- oss.clear(); \
- oss << (o)[0] << "," << (o)[1]; \
- out.setValue((n), oss.str().c_str());
-
- META_WRITE_LEVELS("dsp:mainout", smp.dsp.spc_dsp.m.t_main_out);
- META_WRITE_LEVELS("dsp:echoout", smp.dsp.spc_dsp.m.t_echo_out);
- META_WRITE_LEVELS("dsp:echoin", smp.dsp.spc_dsp.m.t_echo_in);
-
-#undef META_WRITE_LEVELS
-
- for (int i = 0; i < 8; ++i)
- {
- oss.str("");
- oss.clear();
- oss << "dsp:voice[" << i << "]:";
- name = oss.str();
- SuperFamicom::SPC_DSP::voice_t const& voice = smp.dsp.spc_dsp.m.voices[i];
- out.setValue( name + "brrhistaddr", voice.buf_pos );
- oss.str("");
- oss.clear();
- for (int j = 0; j < SuperFamicom::SPC_DSP::brr_buf_size; ++j)
- {
- oss << voice.buf[j];
- if ( j != SuperFamicom::SPC_DSP::brr_buf_size - 1 )
- oss << ",";
- }
- out.setValue( name + "brrhistdata", oss.str().c_str() );
- out.setValue( name + "interpaddr", voice.interp_pos );
- out.setValue( name + "brraddr", voice.brr_addr );
- out.setValue( name + "brroffset", voice.brr_offset );
- out.setValue( name + "vbit", voice.vbit );
- out.setValue( name + "vidx", voice.regs - smp.dsp.spc_dsp.m.regs);
- out.setValue( name + "kondelay", voice.kon_delay );
- out.setValue( name + "envmode", voice.env_mode );
- out.setValue( name + "env", voice.env );
- out.setValue( name + "envxout", voice.t_envx_out );
- out.setValue( name + "envcache", voice.hidden_env );
- }
-}
-
-blargg_err_t Sfm_Emu::save_( gme_writer_t writer, void* your_data ) const
-{
- std::string meta_serialized;
-
- Bml_Parser metadata;
- create_updated_metadata( metadata );
- metadata.serialize( meta_serialized );
-
- RETURN_ERR( writer( your_data, "SFM1", 4 ) );
-
- uint8_t temp[4];
- uint32_t meta_length = (uint32_t) meta_serialized.length();
- set_le32( temp, meta_length );
- RETURN_ERR( writer( your_data, temp, 4 ) );
-
- RETURN_ERR( writer( your_data, meta_serialized.c_str(), meta_length ) );
-
- RETURN_ERR( writer( your_data, smp.apuram, 65536 ) );
-
- RETURN_ERR( writer( your_data, smp.dsp.spc_dsp.m.regs, 128 ) );
-
- if ( smp.get_sfm_queue_remain() )
- RETURN_ERR( writer( your_data, smp.get_sfm_queue(), smp.get_sfm_queue_remain() ) );
-
- return blargg_ok;
-}
-
-blargg_err_t Sfm_Emu::play_and_filter( int count, sample_t out [] )
-{
- smp.render( out, count );
- filter.run( out, count );
- return blargg_ok;
-}
-
-blargg_err_t Sfm_Emu::skip_( int count )
-{
- if ( sample_rate() != native_sample_rate )
- {
- count = (int) (count * resampler.rate()) & ~1;
- count -= resampler.skip_input( count );
- }
-
- // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
-
- if ( count > 0 )
- {
- smp.skip( count );
- filter.clear();
- }
-
- if ( sample_rate() != native_sample_rate )
- {
- // eliminate pop due to resampler
- const int resampler_latency = 64;
- sample_t buf [resampler_latency];
- return play_( resampler_latency, buf );
- }
-
- return blargg_ok;
-}
-
-blargg_err_t Sfm_Emu::play_( int count, sample_t out [] )
-{
- if ( sample_rate() == native_sample_rate )
- return play_and_filter( count, out );
-
- int remain = count;
- while ( remain > 0 )
- {
- remain -= resampler.read( &out [count - remain], remain );
- if ( remain > 0 )
- {
- int n = resampler.buffer_free();
- RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
- resampler.write( n );
- }
- }
- check( remain == 0 );
- return blargg_ok;
-}
-
-blargg_err_t Sfm_Emu::hash_( Hash_Function& out ) const
-{
- hash_sfm_file( file_begin(), file_size(), out );
- return blargg_ok;
-}
-
+// Game_Music_Emu $vers. http://www.slack.net/~ant/
+
+#include "Spc_Sfm.h"
+
+#include "blargg_endian.h"
+
+#include
+
+/* Copyright (C) 2004-2013 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// TODO: support Spc_Filter's bass
+
+Sfm_Emu::Sfm_Emu()
+{
+ set_type( gme_sfm_type );
+ set_gain( 1.4 );
+ set_max_initial_silence( 30 );
+ set_silence_lookahead( 30 ); // Some SFMs may have a lot of initialization code
+}
+
+Sfm_Emu::~Sfm_Emu() { }
+
+// Track info
+
+static void hash_sfm_file( byte const* data, int data_size, Music_Emu::Hash_Function& out )
+{
+ out.hash_( data, data_size );
+}
+
+static void copy_field( char* out, size_t size, const Bml_Parser& in, char const* in_path )
+{
+ const char * value = in.enumValue( in_path );
+ if ( value ) strncpy( out, value, size - 1 ), out[ size - 1 ] = 0;
+ else out[ 0 ] = 0;
+}
+
+static void copy_info( track_info_t* out, const Bml_Parser& in )
+{
+ copy_field( out->song, sizeof(out->song), in, "information:title" );
+ copy_field( out->game, sizeof(out->game), in, "information:game" );
+ copy_field( out->author, sizeof(out->author), in, "information:author" );
+ copy_field( out->composer, sizeof(out->composer), in, "information:composer" );
+ copy_field( out->copyright, sizeof(out->copyright), in, "information:copyright" );
+ copy_field( out->date, sizeof(out->date), in, "information:date" );
+ copy_field( out->track, sizeof(out->track), in, "information:track" );
+ copy_field( out->disc, sizeof(out->disc), in, "information:disc" );
+ copy_field( out->dumper, sizeof(out->dumper), in, "information:dumper" );
+
+ char * end;
+ const char * value = in.enumValue( "timing:length" );
+ if ( value )
+ out->length = strtoul( value, &end, 10 );
+ else
+ out->length = 0;
+
+ value = in.enumValue( "timing:fade" );
+ if ( value )
+ out->fade_length = strtoul( value, &end, 10 );
+ else
+ out->fade_length = 0;
+}
+
+blargg_err_t Sfm_Emu::track_info_( track_info_t* out, int ) const
+{
+ copy_info( out, metadata );
+ return blargg_ok;
+}
+
+static void set_track_info( const track_info_t* in, Bml_Parser& out )
+{
+ out.setValue( "information:title", in->song );
+ out.setValue( "information:game", in->game );
+ out.setValue( "information:author", in->author );
+ out.setValue( "information:composer", in->composer );
+ out.setValue( "information:copyright", in->copyright );
+ out.setValue( "information:date", in->date );
+ out.setValue( "information:track", in->track );
+ out.setValue( "information:disc", in->disc );
+ out.setValue( "information:dumper", in->dumper );
+
+ out.setValue( "timing:length", in->length );
+ out.setValue( "timing:fade", in->fade_length );
+}
+
+blargg_err_t Sfm_Emu::set_track_info_( const track_info_t* in, int )
+{
+ ::set_track_info(in, metadata);
+
+ return blargg_ok;
+}
+
+static blargg_err_t check_sfm_header( void const* header )
+{
+ if ( memcmp( header, "SFM1", 4 ) )
+ return blargg_err_file_type;
+ return blargg_ok;
+}
+
+struct Sfm_File : Gme_Info_
+{
+ blargg_vector data;
+ Bml_Parser metadata;
+ unsigned long original_metadata_size;
+
+ Sfm_File() { set_type( gme_sfm_type ); }
+
+ blargg_err_t load_( Data_Reader& in )
+ {
+ int file_size = in.remain();
+ if ( file_size < Sfm_Emu::sfm_min_file_size )
+ return blargg_err_file_type;
+ RETURN_ERR( data.resize( file_size ) );
+ RETURN_ERR( in.read( data.begin(), data.end() - data.begin() ) );
+ RETURN_ERR( check_sfm_header( data.begin() ) );
+ if ( file_size < 8 )
+ return "SFM file too small";
+ int metadata_size = get_le32( data.begin() + 4 );
+ metadata.parseDocument( (const char *)data.begin() + 8, metadata_size );
+ original_metadata_size = metadata_size;
+ return blargg_ok;
+ }
+
+ blargg_err_t track_info_( track_info_t* out, int ) const
+ {
+ copy_info( out, metadata );
+ return blargg_ok;
+ }
+
+ blargg_err_t set_track_info_( const track_info_t* in, int )
+ {
+ ::set_track_info( in, metadata );
+ return blargg_ok;
+ }
+
+ blargg_err_t hash_( Hash_Function& out ) const
+ {
+ hash_sfm_file( data.begin(), data.end() - data.begin(), out );
+ return blargg_ok;
+ }
+
+ blargg_err_t save_( gme_writer_t writer, void* your_data ) const
+ {
+ std::string metadata_serialized;
+ metadata.serialize( metadata_serialized );
+ uint8_t meta_length[4];
+ set_le32( meta_length, (unsigned int) metadata_serialized.length() );
+ writer( your_data, "SFM1", 4 );
+ writer( your_data, meta_length, 4 );
+ writer( your_data, metadata_serialized.c_str(), metadata_serialized.length() );
+ writer( your_data, data.begin() + 4 + 4 + original_metadata_size, data.size() - (4 + 4 + original_metadata_size) );
+ return blargg_ok;
+ }
+};
+
+static Music_Emu* new_sfm_emu () { return BLARGG_NEW Sfm_Emu ; }
+static Music_Emu* new_sfm_file() { return BLARGG_NEW Sfm_File; }
+
+gme_type_t_ const gme_sfm_type [1] = {{ "Super Nintendo with log", 1, &new_sfm_emu, &new_sfm_file, "SFM", 0 }};
+
+// Setup
+
+blargg_err_t Sfm_Emu::set_sample_rate_( int sample_rate )
+{
+ smp.power();
+ if ( sample_rate != native_sample_rate )
+ {
+ RETURN_ERR( resampler.resize_buffer( native_sample_rate / 20 * 2 ) );
+ RETURN_ERR( resampler.set_rate( (double) native_sample_rate / sample_rate ) ); // 0.9965 rolloff
+ }
+ return blargg_ok;
+}
+
+void Sfm_Emu::mute_voices_( int m )
+{
+ Music_Emu::mute_voices_( m );
+ for ( int i = 0, j = 1; i < 8; ++i, j <<= 1 )
+ smp.dsp.channel_enable( i, !( m & j ) );
+}
+
+blargg_err_t Sfm_Emu::load_mem_( byte const in [], int size )
+{
+ set_voice_count( 8 );
+ if ( size < Sfm_Emu::sfm_min_file_size )
+ return blargg_err_file_type;
+
+ static const char* const names [ 8 ] = {
+ "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
+ };
+ set_voice_names( names );
+
+ RETURN_ERR( check_sfm_header( in ) );
+
+ const byte * ptr = file_begin();
+ int metadata_size = get_le32(ptr + 4);
+ if ( file_size() < metadata_size + Sfm_Emu::sfm_min_file_size )
+ return "SFM file too small";
+ metadata.parseDocument((const char *) ptr + 8, metadata_size);
+
+ return blargg_ok;
+}
+
+// Emulation
+
+void Sfm_Emu::set_tempo_( double t )
+{
+ smp.set_tempo( t );
+}
+
+// (n ? n : 256)
+#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
+
+#define META_ENUM_INT(n,d) (value = metadata.enumValue(n), value ? strtol(value, &end, 10) : (d))
+
+static const byte ipl_rom[0x40] =
+{
+ 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
+ 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
+ 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
+ 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
+ 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB,
+ 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
+ 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD,
+ 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
+};
+
+blargg_err_t Sfm_Emu::start_track_( int track )
+{
+ RETURN_ERR( Music_Emu::start_track_( track ) );
+ resampler.clear();
+ filter.clear();
+ const byte * ptr = file_begin();
+ int metadata_size = get_le32(ptr + 4);
+
+ memcpy( smp.iplrom, ipl_rom, 64 );
+
+ smp.reset();
+
+ memcpy( smp.apuram, ptr + 8 + metadata_size, 65536 );
+
+ memcpy( smp.dsp.spc_dsp.m.regs, ptr + 8 + metadata_size + 65536, 128 );
+
+ const uint8_t* log_begin = ptr + 8 + metadata_size + 65536 + 128;
+ const uint8_t* log_end = ptr + file_size();
+ size_t loop_begin = log_end - log_begin;
+
+ char * end;
+ const char * value;
+
+ loop_begin = META_ENUM_INT("timing:loopstart", loop_begin);
+
+ smp.set_sfm_queue( log_begin, log_end, log_begin + loop_begin );
+
+ uint32_t test = META_ENUM_INT("smp:test", 0);
+ smp.status.clock_speed = (test >> 6) & 3;
+ smp.status.timer_speed = (test >> 4) & 3;
+ smp.status.timers_enable = test & 0x08;
+ smp.status.ram_disable = test & 0x04;
+ smp.status.ram_writable = test & 0x02;
+ smp.status.timers_disable = test & 0x01;
+
+ smp.status.iplrom_enable = META_ENUM_INT("smp:iplrom",1);
+ smp.status.dsp_addr = META_ENUM_INT("smp:dspaddr",0);
+
+ value = metadata.enumValue("smp:ram");
+ if (value)
+ {
+ smp.status.ram00f8 = strtol(value, &end, 10);
+ if (*end)
+ {
+ value = end + 1;
+ smp.status.ram00f9 = strtol(value, &end, 10);
+ }
+ }
+
+ std::string name;
+ std::ostringstream oss;
+
+ name = "smp:regs:";
+ smp.regs.pc = META_ENUM_INT(name + "pc", 0xffc0);
+ smp.regs.a = META_ENUM_INT(name + "a", 0x00);
+ smp.regs.x = META_ENUM_INT(name + "x", 0x00);
+ smp.regs.y = META_ENUM_INT(name + "y", 0x00);
+ smp.regs.s = META_ENUM_INT(name + "s", 0xef);
+ smp.regs.p = META_ENUM_INT(name + "psw", 0x02);
+
+ value = metadata.enumValue("smp:ports");
+ if (value)
+ {
+ for (auto &n : smp.sfm_last)
+ {
+ n = strtol(value, &end, 10);
+ if (*end == ',')
+ value = end + 1;
+ else
+ break;
+ }
+ }
+
+ for (int i = 0; i < 3; ++i)
+ {
+ SuperFamicom::SMP::Timer<192> &t = (i == 0 ? smp.timer0 : (i == 1 ? smp.timer1 : *(SuperFamicom::SMP::Timer<192>*)&smp.timer2));
+ oss.str("");
+ oss.clear();
+ oss << "smp:timer[" << i << "]:";
+ name = oss.str();
+ value = metadata.enumValue(name + "enable");
+ if (value)
+ {
+ t.enable = !!strtol(value, &end, 10);
+ }
+ value = metadata.enumValue(name + "target");
+ if (value)
+ {
+ t.target = strtol(value, &end, 10);
+ }
+ value = metadata.enumValue(name + "stage");
+ if (value)
+ {
+ t.stage0_ticks = strtol(value, &end, 10);
+ if (*end != ',') break;
+ value = end + 1;
+ t.stage1_ticks = strtol(value, &end, 10);
+ if (*end != ',') break;
+ value = end + 1;
+ t.stage2_ticks = strtol(value, &end, 10);
+ if (*end != ',') break;
+ value = end + 1;
+ t.stage3_ticks = strtol(value, &end, 10);
+ }
+ value = metadata.enumValue(name + "line");
+ if (value)
+ {
+ t.current_line = !!strtol(value, &end, 10);
+ }
+ }
+
+ smp.dsp.clock = META_ENUM_INT("dsp:clock", 0) * 4096;
+
+ smp.dsp.spc_dsp.m.echo_hist_pos = &smp.dsp.spc_dsp.m.echo_hist[META_ENUM_INT("dsp:echohistaddr", 0)];
+
+ value = metadata.enumValue("dsp:echohistdata");
+ if (value)
+ {
+ for (int i = 0; i < 8; ++i)
+ {
+ smp.dsp.spc_dsp.m.echo_hist[i][0] = strtol(value, &end, 10);
+ value = strchr(value, ',');
+ if (!value) break;
+ ++value;
+ smp.dsp.spc_dsp.m.echo_hist[i][1] = strtol(value, &end, 10);
+ value = strchr(value, ',');
+ if (!value) break;
+ ++value;
+ }
+ }
+
+ smp.dsp.spc_dsp.m.phase = META_ENUM_INT("dsp:sample", 0);
+ smp.dsp.spc_dsp.m.kon = META_ENUM_INT("dsp:kon", 0);
+ smp.dsp.spc_dsp.m.noise = META_ENUM_INT("dsp:noise", 0);
+ smp.dsp.spc_dsp.m.counter = META_ENUM_INT("dsp:counter", 0);
+ smp.dsp.spc_dsp.m.echo_offset = META_ENUM_INT("dsp:echooffset", 0);
+ smp.dsp.spc_dsp.m.echo_length = META_ENUM_INT("dsp:echolength", 0);
+ smp.dsp.spc_dsp.m.new_kon = META_ENUM_INT("dsp:koncache", 0);
+ smp.dsp.spc_dsp.m.endx_buf = META_ENUM_INT("dsp:endx", 0);
+ smp.dsp.spc_dsp.m.envx_buf = META_ENUM_INT("dsp:envx", 0);
+ smp.dsp.spc_dsp.m.outx_buf = META_ENUM_INT("dsp:outx", 0);
+ smp.dsp.spc_dsp.m.t_pmon = META_ENUM_INT("dsp:pmon", 0);
+ smp.dsp.spc_dsp.m.t_non = META_ENUM_INT("dsp:non", 0);
+ smp.dsp.spc_dsp.m.t_eon = META_ENUM_INT("dsp:eon", 0);
+ smp.dsp.spc_dsp.m.t_dir = META_ENUM_INT("dsp:dir", 0);
+ smp.dsp.spc_dsp.m.t_koff = META_ENUM_INT("dsp:koff", 0);
+ smp.dsp.spc_dsp.m.t_brr_next_addr = META_ENUM_INT("dsp:brrnext", 0);
+ smp.dsp.spc_dsp.m.t_adsr0 = META_ENUM_INT("dsp:adsr0", 0);
+ smp.dsp.spc_dsp.m.t_brr_header = META_ENUM_INT("dsp:brrheader", 0);
+ smp.dsp.spc_dsp.m.t_brr_byte = META_ENUM_INT("dsp:brrdata", 0);
+ smp.dsp.spc_dsp.m.t_srcn = META_ENUM_INT("dsp:srcn", 0);
+ smp.dsp.spc_dsp.m.t_esa = META_ENUM_INT("dsp:esa", 0);
+ smp.dsp.spc_dsp.m.t_echo_enabled = !META_ENUM_INT("dsp:echodisable", 0);
+ smp.dsp.spc_dsp.m.t_dir_addr = META_ENUM_INT("dsp:diraddr", 0);
+ smp.dsp.spc_dsp.m.t_pitch = META_ENUM_INT("dsp:pitch", 0);
+ smp.dsp.spc_dsp.m.t_output = META_ENUM_INT("dsp:output", 0);
+ smp.dsp.spc_dsp.m.t_looped = META_ENUM_INT("dsp:looped", 0);
+ smp.dsp.spc_dsp.m.t_echo_ptr = META_ENUM_INT("dsp:echoaddr", 0);
+
+
+#define META_ENUM_LEVELS(n, o) \
+ value = metadata.enumValue(n); \
+ if (value) \
+ { \
+ (o)[0] = strtol(value, &end, 10); \
+ if (*end) \
+ { \
+ value = end + 1; \
+ (o)[1] = strtol(value, &end, 10); \
+ } \
+ }
+
+ META_ENUM_LEVELS("dsp:mainout", smp.dsp.spc_dsp.m.t_main_out);
+ META_ENUM_LEVELS("dsp:echoout", smp.dsp.spc_dsp.m.t_echo_out);
+ META_ENUM_LEVELS("dsp:echoin", smp.dsp.spc_dsp.m.t_echo_in);
+
+#undef META_ENUM_LEVELS
+
+ for (int i = 0; i < 8; ++i)
+ {
+ oss.str("");
+ oss.clear();
+ oss << "dsp:voice[" << i << "]:";
+ name = oss.str();
+ SuperFamicom::SPC_DSP::voice_t & voice = smp.dsp.spc_dsp.m.voices[i];
+ value = metadata.enumValue(name + "brrhistaddr");
+ if (value)
+ {
+ voice.buf_pos = strtol(value, &end, 10);
+ }
+ value = metadata.enumValue(name + "brrhistdata");
+ if (value)
+ {
+ for (int j = 0; j < SuperFamicom::SPC_DSP::brr_buf_size; ++j)
+ {
+ voice.buf[j] = voice.buf[j + SuperFamicom::SPC_DSP::brr_buf_size] = strtol(value, &end, 10);
+ if (!*end) break;
+ value = end + 1;
+ }
+ }
+ voice.interp_pos = META_ENUM_INT(name + "interpaddr",0);
+ voice.brr_addr = META_ENUM_INT(name + "brraddr",0);
+ voice.brr_offset = META_ENUM_INT(name + "brroffset",0);
+ voice.vbit = META_ENUM_INT(name + "vbit",0);
+ voice.regs = &smp.dsp.spc_dsp.m.regs[META_ENUM_INT(name + "vidx",0)];
+ voice.kon_delay = META_ENUM_INT(name + "kondelay", 0);
+ voice.env_mode = (SuperFamicom::SPC_DSP::env_mode_t) META_ENUM_INT(name + "envmode", 0);
+ voice.env = META_ENUM_INT(name + "env", 0);
+ voice.t_envx_out = META_ENUM_INT(name + "envxout", 0);
+ voice.hidden_env = META_ENUM_INT(name + "envcache", 0);
+ }
+
+ filter.set_gain( (int) (gain() * Spc_Filter::gain_unit) );
+ return blargg_ok;
+}
+
+#undef META_ENUM_INT
+
+void Sfm_Emu::create_updated_metadata( Bml_Parser &out ) const
+{
+ bool first;
+ std::string name;
+ std::ostringstream oss;
+
+ metadata.serialize(name);
+
+ out.parseDocument(name.c_str());
+
+ out.setValue( "smp:test", (smp.status.clock_speed << 6) | (smp.status.timer_speed << 4) | (smp.status.timers_enable << 3) | (smp.status.ram_disable << 2) | (smp.status.ram_writable << 1) | (smp.status.timers_disable << 0) );
+ out.setValue( "smp:iplrom", smp.status.iplrom_enable );
+ out.setValue( "smp:dspaddr", smp.status.dsp_addr );
+
+ oss.str("");
+ oss.clear();
+ oss << (unsigned long)smp.status.ram00f8 << "," << (unsigned long)smp.status.ram00f9;
+ out.setValue( "smp:ram", oss.str().c_str() );
+
+ name = "smp:regs:";
+ out.setValue( name + "pc", smp.regs.pc );
+ out.setValue( name + "a", smp.regs.a );
+ out.setValue( name + "x", smp.regs.x );
+ out.setValue( name + "y", smp.regs.y );
+ out.setValue( name + "s", smp.regs.s );
+ out.setValue( name + "psw", smp.regs.p );
+
+ oss.str("");
+ oss.clear();
+ first = true;
+ for (auto n : smp.sfm_last)
+ {
+ if (!first) oss << ",";
+ oss << (unsigned long)n;
+ first = false;
+ }
+ out.setValue("smp:ports", oss.str().c_str());
+
+ for (int i = 0; i < 3; ++i)
+ {
+ SuperFamicom::SMP::Timer<192> const& t = (i == 0 ? smp.timer0 : (i == 1 ? smp.timer1 : *(SuperFamicom::SMP::Timer<192>*)&smp.timer2));
+ oss.str("");
+ oss.clear();
+ oss << "smp:timer[" << i << "]:";
+ name = oss.str();
+ out.setValue( name + "enable", t.enable );
+ out.setValue( name + "target", t.target );
+ oss.str("");
+ oss.clear();
+ oss << (unsigned long)t.stage0_ticks << "," << (unsigned long)t.stage1_ticks << ","
+ << (unsigned long)t.stage2_ticks << "," << (unsigned long)t.stage3_ticks;
+ out.setValue( name + "stage", oss.str().c_str() );
+ out.setValue( name + "line", t.current_line );
+ }
+
+ out.setValue( "dsp:clock", smp.dsp.clock / 4096 );
+
+ out.setValue( "dsp:echohistaddr", smp.dsp.spc_dsp.m.echo_hist_pos - smp.dsp.spc_dsp.m.echo_hist );
+
+ oss.str("");
+ oss.clear();
+ for (int i = 0; i < 8; ++i)
+ {
+ oss << smp.dsp.spc_dsp.m.echo_hist[i][0] << ","
+ << smp.dsp.spc_dsp.m.echo_hist[i][1];
+ if ( i != 7 ) oss << ",";
+ }
+ out.setValue( "dsp:echohistdata", oss.str().c_str() );
+
+ out.setValue( "dsp:sample", smp.dsp.spc_dsp.m.phase );
+ out.setValue( "dsp:kon", smp.dsp.spc_dsp.m.kon );
+ out.setValue( "dsp:noise", smp.dsp.spc_dsp.m.noise );
+ out.setValue( "dsp:counter", smp.dsp.spc_dsp.m.counter );
+ out.setValue( "dsp:echooffset", smp.dsp.spc_dsp.m.echo_offset );
+ out.setValue( "dsp:echolength", smp.dsp.spc_dsp.m.echo_length );
+ out.setValue( "dsp:koncache", smp.dsp.spc_dsp.m.new_kon );
+ out.setValue( "dsp:endx", smp.dsp.spc_dsp.m.endx_buf );
+ out.setValue( "dsp:envx", smp.dsp.spc_dsp.m.envx_buf );
+ out.setValue( "dsp:outx", smp.dsp.spc_dsp.m.outx_buf );
+ out.setValue( "dsp:pmon", smp.dsp.spc_dsp.m.t_pmon );
+ out.setValue( "dsp:non", smp.dsp.spc_dsp.m.t_non );
+ out.setValue( "dsp:eon", smp.dsp.spc_dsp.m.t_eon );
+ out.setValue( "dsp:dir", smp.dsp.spc_dsp.m.t_dir );
+ out.setValue( "dsp:koff", smp.dsp.spc_dsp.m.t_koff );
+ out.setValue( "dsp:brrnext", smp.dsp.spc_dsp.m.t_brr_next_addr );
+ out.setValue( "dsp:adsr0", smp.dsp.spc_dsp.m.t_adsr0 );
+ out.setValue( "dsp:brrheader", smp.dsp.spc_dsp.m.t_brr_header );
+ out.setValue( "dsp:brrdata", smp.dsp.spc_dsp.m.t_brr_byte );
+ out.setValue( "dsp:srcn", smp.dsp.spc_dsp.m.t_srcn );
+ out.setValue( "dsp:esa", smp.dsp.spc_dsp.m.t_esa );
+ out.setValue( "dsp:echodisable", !smp.dsp.spc_dsp.m.t_echo_enabled );
+ out.setValue( "dsp:diraddr", smp.dsp.spc_dsp.m.t_dir_addr );
+ out.setValue( "dsp:pitch", smp.dsp.spc_dsp.m.t_pitch );
+ out.setValue( "dsp:output", smp.dsp.spc_dsp.m.t_output );
+ out.setValue( "dsp:looped", smp.dsp.spc_dsp.m.t_looped );
+ out.setValue( "dsp:echoaddr", smp.dsp.spc_dsp.m.t_echo_ptr );
+
+#define META_WRITE_LEVELS(n, o) \
+ oss.str(""); \
+ oss.clear(); \
+ oss << (o)[0] << "," << (o)[1]; \
+ out.setValue((n), oss.str().c_str());
+
+ META_WRITE_LEVELS("dsp:mainout", smp.dsp.spc_dsp.m.t_main_out);
+ META_WRITE_LEVELS("dsp:echoout", smp.dsp.spc_dsp.m.t_echo_out);
+ META_WRITE_LEVELS("dsp:echoin", smp.dsp.spc_dsp.m.t_echo_in);
+
+#undef META_WRITE_LEVELS
+
+ for (int i = 0; i < 8; ++i)
+ {
+ oss.str("");
+ oss.clear();
+ oss << "dsp:voice[" << i << "]:";
+ name = oss.str();
+ SuperFamicom::SPC_DSP::voice_t const& voice = smp.dsp.spc_dsp.m.voices[i];
+ out.setValue( name + "brrhistaddr", voice.buf_pos );
+ oss.str("");
+ oss.clear();
+ for (int j = 0; j < SuperFamicom::SPC_DSP::brr_buf_size; ++j)
+ {
+ oss << voice.buf[j];
+ if ( j != SuperFamicom::SPC_DSP::brr_buf_size - 1 )
+ oss << ",";
+ }
+ out.setValue( name + "brrhistdata", oss.str().c_str() );
+ out.setValue( name + "interpaddr", voice.interp_pos );
+ out.setValue( name + "brraddr", voice.brr_addr );
+ out.setValue( name + "brroffset", voice.brr_offset );
+ out.setValue( name + "vbit", voice.vbit );
+ out.setValue( name + "vidx", voice.regs - smp.dsp.spc_dsp.m.regs);
+ out.setValue( name + "kondelay", voice.kon_delay );
+ out.setValue( name + "envmode", voice.env_mode );
+ out.setValue( name + "env", voice.env );
+ out.setValue( name + "envxout", voice.t_envx_out );
+ out.setValue( name + "envcache", voice.hidden_env );
+ }
+}
+
+blargg_err_t Sfm_Emu::save_( gme_writer_t writer, void* your_data ) const
+{
+ std::string meta_serialized;
+
+ Bml_Parser metadata;
+ create_updated_metadata( metadata );
+ metadata.serialize( meta_serialized );
+
+ RETURN_ERR( writer( your_data, "SFM1", 4 ) );
+
+ uint8_t temp[4];
+ uint32_t meta_length = (uint32_t) meta_serialized.length();
+ set_le32( temp, meta_length );
+ RETURN_ERR( writer( your_data, temp, 4 ) );
+
+ RETURN_ERR( writer( your_data, meta_serialized.c_str(), meta_length ) );
+
+ RETURN_ERR( writer( your_data, smp.apuram, 65536 ) );
+
+ RETURN_ERR( writer( your_data, smp.dsp.spc_dsp.m.regs, 128 ) );
+
+ if ( smp.get_sfm_queue_remain() )
+ RETURN_ERR( writer( your_data, smp.get_sfm_queue(), smp.get_sfm_queue_remain() ) );
+
+ return blargg_ok;
+}
+
+blargg_err_t Sfm_Emu::play_and_filter( int count, sample_t out [] )
+{
+ smp.render( out, count );
+ filter.run( out, count );
+ return blargg_ok;
+}
+
+blargg_err_t Sfm_Emu::skip_( int count )
+{
+ if ( sample_rate() != native_sample_rate )
+ {
+ count = (int) (count * resampler.rate()) & ~1;
+ count -= resampler.skip_input( count );
+ }
+
+ // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
+
+ if ( count > 0 )
+ {
+ smp.skip( count );
+ filter.clear();
+ }
+
+ if ( sample_rate() != native_sample_rate )
+ {
+ // eliminate pop due to resampler
+ const int resampler_latency = 64;
+ sample_t buf [resampler_latency];
+ return play_( resampler_latency, buf );
+ }
+
+ return blargg_ok;
+}
+
+blargg_err_t Sfm_Emu::play_( int count, sample_t out [] )
+{
+ if ( sample_rate() == native_sample_rate )
+ return play_and_filter( count, out );
+
+ int remain = count;
+ while ( remain > 0 )
+ {
+ remain -= resampler.read( &out [count - remain], remain );
+ if ( remain > 0 )
+ {
+ int n = resampler.buffer_free();
+ RETURN_ERR( play_and_filter( n, resampler.buffer() ) );
+ resampler.write( n );
+ }
+ }
+ check( remain == 0 );
+ return blargg_ok;
+}
+
+blargg_err_t Sfm_Emu::hash_( Hash_Function& out ) const
+{
+ hash_sfm_file( file_begin(), file_size(), out );
+ return blargg_ok;
+}
+
diff -Nru kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.h kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.h
--- kodi-audiodecoder-gme-2.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.h 2020-02-05 18:17:13.000000000 +0000
+++ kodi-audiodecoder-gme-19.0.3/lib/Game_Music_Emu/gme/Spc_Sfm.h 2013-05-31 22:59:22.000000000 +0000
@@ -1,77 +1,77 @@
-// Super Nintendo SFM music file emulator
-
-// Game_Music_Emu $vers
-#ifndef SPC_SFM_H
-#define SPC_SFM_H
-
-#include "Music_Emu.h"
-#include "higan/smp/smp.hpp"
-#include "Spc_Filter.h"
-
-#include "Bml_Parser.h"
-
-#if GME_SPC_FAST_RESAMPLER
- #include "Upsampler.h"
- typedef Upsampler Spc_Emu_Resampler;
-#else
- #include "Fir_Resampler.h"
- typedef Fir_Resampler<24> Spc_Emu_Resampler;
-#endif
-
-class Sfm_Emu : public Music_Emu {
-public:
- // Minimum allowed file size
- enum { sfm_min_file_size = 8 + 65536 + 128 };
-
- // The Super Nintendo hardware samples at 32kHz. Other sample rates are
- // handled by resampling the 32kHz output; emulation accuracy is not affected.
- enum { native_sample_rate = 32000 };
-
- // This will serialize the current state of the emulator into a new SFM file
- blargg_err_t serialize( std::vector