summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/libgme/2413tone.h40
-rw-r--r--apps/codecs/libgme/281btone.h40
-rw-r--r--apps/codecs/libgme/ay_emu.c1198
-rw-r--r--apps/codecs/libgme/blargg_config.h84
-rw-r--r--apps/codecs/libgme/emu2413.c3962
-rw-r--r--apps/codecs/libgme/emu2413.h328
-rw-r--r--apps/codecs/libgme/emutables.h420
-rw-r--r--apps/codecs/libgme/emutypes.h82
-rw-r--r--apps/codecs/libgme/hes_apu_adpcm.c594
-rw-r--r--apps/codecs/libgme/inflate/mbreader.c32
-rw-r--r--apps/codecs/libgme/inflate/mbreader.h30
-rw-r--r--apps/codecs/libgme/kss_cpu.c70
-rw-r--r--apps/codecs/libgme/nes_cpu_run.h2244
-rw-r--r--apps/codecs/libgme/nes_vrc7_apu.c176
-rw-r--r--apps/codecs/libgme/opl_apu.c396
-rw-r--r--apps/codecs/libgme/opl_apu.h126
-rw-r--r--apps/codecs/libgme/opltables.h484
-rw-r--r--apps/codecs/libgme/sgc_cpu.c72
-rw-r--r--apps/codecs/libgme/sgc_emu.c960
-rw-r--r--apps/codecs/libgme/sgc_emu.h390
-rw-r--r--apps/codecs/libgme/sms_fm_apu.c164
-rw-r--r--apps/codecs/libgme/sms_fm_apu.h86
-rw-r--r--apps/codecs/libgme/track_filter.c588
-rw-r--r--apps/codecs/libgme/track_filter.h180
-rw-r--r--apps/codecs/libgme/vrc7tone.h40
-rw-r--r--apps/codecs/libgme/ym2413_emu.c90
-rw-r--r--apps/codecs/libgme/ym2413_emu.h122
-rw-r--r--apps/codecs/libgme/ymtables.h1118
-rw-r--r--apps/codecs/libgme/z80_cpu.h232
-rw-r--r--apps/codecs/libgme/z80_cpu_run.h3392
-rw-r--r--apps/lang/arabic.lang26
-rw-r--r--apps/lang/latviesu.lang25500
-rw-r--r--firmware/drivers/audio/cs42l55.c490
-rw-r--r--firmware/drivers/audio/dac3550a.c2
-rw-r--r--firmware/export/ata-defines.h116
-rw-r--r--firmware/export/config/rk27generic.h378
-rw-r--r--firmware/export/dac3550a.h2
-rw-r--r--firmware/export/mascodec.h2
-rw-r--r--firmware/export/s5l8702.h1660
-rw-r--r--firmware/target/arm/as3525/sansa-clipzip/lcd-clipzip.c2
-rw-r--r--firmware/target/arm/s5l8700/postmortemstub.S616
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c332
-rw-r--r--firmware/target/arm/s5l8702/debug-target.h66
-rw-r--r--firmware/target/arm/s5l8702/i2c-s5l8702.c392
-rw-r--r--firmware/target/arm/s5l8702/kernel-s5l8702.c112
-rw-r--r--firmware/target/arm/s5l8702/pcm-s5l8702.c456
-rw-r--r--firmware/target/arm/s5l8702/pcm-target.h80
-rw-r--r--firmware/target/arm/s5l8702/system-target.h94
-rw-r--r--firmware/target/arm/s5l8702/timer-s5l8702.c188
-rw-r--r--firmware/target/sh/archos/mascodec-archos.c2
-rw-r--r--rbutil/e200rpatcher/e200rpatcher.rc2
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.rc2
-rw-r--r--rbutil/sansapatcher/sansapatcher.rc2
-rw-r--r--utils/MTP/sendfirm.manifest16
-rw-r--r--utils/tcctool/tcctool-windows.txt62
-rw-r--r--utils/themeeditor/qtfindreplacedialog/findreplace_global.h42
-rw-r--r--utils/themeeditor/qtfindreplacedialog/findreplacedialog.ui64
-rw-r--r--utils/themeeditor/qtfindreplacedialog/findreplaceform.ui408
-rw-r--r--utils/themeeditor/themeeditor.rc2
59 files changed, 24428 insertions, 24428 deletions
diff --git a/apps/codecs/libgme/2413tone.h b/apps/codecs/libgme/2413tone.h
index e4366ab245..c0922c1225 100644
--- a/apps/codecs/libgme/2413tone.h
+++ b/apps/codecs/libgme/2413tone.h
@@ -1,20 +1,20 @@
-/* YM2413 tone by okazaki@angel.ne.jp */
-0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+/* YM2413 tone by okazaki@angel.ne.jp */
+0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/apps/codecs/libgme/281btone.h b/apps/codecs/libgme/281btone.h
index 1300523fbe..83f63bff00 100644
--- a/apps/codecs/libgme/281btone.h
+++ b/apps/codecs/libgme/281btone.h
@@ -1,20 +1,20 @@
-/* YMF281B tone by Chabin */
-0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x10,0x44,0x02,0xf6,0xf4,0x54,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x03,0x01,0x97,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x61,0x0a,0x0f,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x61,0x8a,0x0e,0xc0,0x61,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x61,0x1b,0x07,0x84,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x21,0x06,0x03,0xa5,0x71,0x51,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x06,0x11,0x5e,0x07,0xf3,0xf2,0xf6,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x20,0x18,0x06,0xf5,0xf3,0x20,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x97,0x41,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x65,0x61,0x15,0x00,0xf7,0xf3,0x16,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x31,0x0e,0x07,0xfa,0xf3,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x48,0x61,0x09,0x07,0xf1,0x94,0xf0,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+/* YMF281B tone by Chabin */
+0x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x10,0x44,0x02,0xf6,0xf4,0x54,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x03,0x01,0x97,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x61,0x0a,0x0f,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x61,0x8a,0x0e,0xc0,0x61,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x61,0x1b,0x07,0x84,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x21,0x06,0x03,0xa5,0x71,0x51,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x06,0x11,0x5e,0x07,0xf3,0xf2,0xf6,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x20,0x18,0x06,0xf5,0xf3,0x20,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x97,0x41,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x65,0x61,0x15,0x00,0xf7,0xf3,0x16,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x31,0x0e,0x07,0xfa,0xf3,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x48,0x61,0x09,0x07,0xf1,0x94,0xf0,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/apps/codecs/libgme/ay_emu.c b/apps/codecs/libgme/ay_emu.c
index 42e739f2df..92faba4929 100644
--- a/apps/codecs/libgme/ay_emu.c
+++ b/apps/codecs/libgme/ay_emu.c
@@ -1,599 +1,599 @@
-// Game_Music_Emu 0.6-pre. 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"
-
-const char* const gme_wrong_file_type = "Wrong file type for this emulator";
-
-// 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;
-
-static void clear_track_vars( struct Ay_Emu *this )
-{
- this->current_track = -1;
- track_stop( &this->track_filter );
-}
-
-void Ay_init( struct Ay_Emu *this )
-{
- this->sample_rate = 0;
- this->mute_mask_ = 0;
- this->tempo = (int)FP_ONE_TEMPO;
- this->gain = (int)FP_ONE_GAIN;
- this->track_count = 0;
-
- // defaults
- this->tfilter = *track_get_setup( &this->track_filter );
- this->tfilter.max_initial = 2;
- this->tfilter.lookahead = 6;
- this->track_filter.silence_ignored_ = false;
-
- this->beeper_output = NULL;
- disable_beeper( this );
-
- Ay_apu_init( &this->apu );
- Z80_init( &this->cpu );
-
- // clears fields
- this->voice_count = 0;
- this->voice_types = 0;
- clear_track_vars( this );
-}
-
-// 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( struct file_t const* file, byte const ptr [], int min_size )
-{
- int offset = (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, struct file_t* out )
-{
- if ( size < header_size )
- return gme_wrong_file_type;
-
- out->header = (struct header_t const*) in;
- out->end = in + size;
- struct header_t const* h = (struct header_t const*) in;
- if ( memcmp( h->tag, "ZXAYEMUL", 8 ) )
- return gme_wrong_file_type;
-
- out->tracks = get_data( out, h->track_info, (h->max_track + 1) * 4 );
- if ( !out->tracks )
- return "missing track data";
-
- return 0;
-}
-
-// Setup
-
-static void change_clock_rate( struct Ay_Emu *this, int rate )
-{
- this->clock_rate_ = rate;
- Buffer_clock_rate( &this->stereo_buf, rate );
-}
-
-blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], long size )
-{
- // Unload
- this->voice_count = 0;
- this->track_count = 0;
- this->m3u.size = 0;
- clear_track_vars( this );
-
- assert( offsetof (struct header_t,track_info [2]) == header_size );
-
- RETURN_ERR( parse_header( in, size, &this->file ) );
-
- /* if ( file.header->vers > 2 )
- warning( "Unknown file version" ); */
-
- this->voice_count = ay_osc_count + 1; // +1 for beeper
- static int const types [ay_osc_count + 1] = {
- wave_type+0, wave_type+1, wave_type+2, mixed_type+1
- };
- this->voice_types = types;
-
- Ay_apu_volume( &this->apu, this->gain);
-
- // Setup buffer
- change_clock_rate( this, spectrum_clock );
- RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
- this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
-
- Sound_set_tempo( this, this->tempo );
- Sound_mute_voices( this, this->mute_mask_ );
-
- this->track_count = this->file.header->max_track + 1;
- return 0;
-}
-
-static void set_beeper_output( struct Ay_Emu *this, struct Blip_Buffer* b )
-{
- this->beeper_output = b;
- if ( b && !this->cpc_mode )
- this->beeper_mask = 0x10;
- else
- disable_beeper( this );
-}
-
-static void set_voice( struct Ay_Emu *this, int i, struct Blip_Buffer* center )
-{
- if ( i >= ay_osc_count )
- set_beeper_output( this, center );
- else
- Ay_apu_set_output( &this->apu, i, center );
-}
-
-static blargg_err_t run_clocks( struct Ay_Emu *this, blip_time_t* duration, int msec )
-{
-#if defined(ROCKBOX)
- (void) msec;
-#endif
-
- cpu_time_t *end = duration;
- struct Z80_Cpu* cpu = &this->cpu;
- Z80_set_time( cpu, 0 );
-
- // Since detection of CPC mode will halve clock rate during the frame
- // and thus generate up to twice as much sound, we must generate half
- // as much until mode is known.
- if ( !(this->spectrum_mode | this->cpc_mode) )
- *end /= 2;
-
- while ( Z80_time( cpu ) < *end )
- {
- run_cpu( this, min( *end, this->next_play ) );
-
- if ( Z80_time( cpu ) >= this->next_play )
- {
- // next frame
- this->next_play += this->play_period;
-
- if ( cpu->r.iff1 )
- {
- // interrupt enabled
-
- if ( this->mem.ram [cpu->r.pc] == 0x76 )
- cpu->r.pc++; // advance past HALT instruction
-
- cpu->r.iff1 = 0;
- cpu->r.iff2 = 0;
-
- this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc >> 8);
- this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc);
-
- // fixed interrupt
- cpu->r.pc = 0x38;
- Z80_adjust_time( cpu, 12 );
-
- if ( cpu->r.im == 2 )
- {
- // vectored interrupt
- addr_t addr = cpu->r.i * 0x100 + 0xFF;
- cpu->r.pc = this->mem.ram [(addr + 1) & 0xFFFF] * 0x100 + this->mem.ram [addr];
- Z80_adjust_time( cpu, 6 );
- }
- }
- }
- }
-
- // End time frame
- *end = Z80_time( cpu );
- this->next_play -= *end;
- check( this->next_play >= 0 );
- Z80_adjust_time( cpu, -*end );
- Ay_apu_end_frame( &this->apu, *end );
- return 0;
-}
-
-// Emulation
-
-void cpu_out_( struct Ay_Emu *this, cpu_time_t time, addr_t addr, int data )
-{
- // Spectrum
- if ( !this->cpc_mode )
- {
- switch ( addr & 0xFEFF )
- {
- case 0xFEFD:
- this->spectrum_mode = true;
- Ay_apu_write_addr( &this->apu, data );
- return;
-
- case 0xBEFD:
- this->spectrum_mode = true;
- Ay_apu_write_data( &this->apu, time, data );
- return;
- }
- }
-
- // CPC
- if ( !this->spectrum_mode )
- {
- switch ( addr >> 8 )
- {
- case 0xF6:
- switch ( data & 0xC0 )
- {
- case 0xC0:
- Ay_apu_write_addr( &this->apu, this->cpc_latch );
- goto enable_cpc;
-
- case 0x80:
- Ay_apu_write_data( &this->apu, time, this->cpc_latch );
- goto enable_cpc;
- }
- break;
-
- case 0xF4:
- this->cpc_latch = data;
- goto enable_cpc;
- }
- }
-
- /* dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data ); */
- return;
-
-enable_cpc:
- if ( !this->cpc_mode )
- {
- this->cpc_mode = true;
- disable_beeper( this );
-
- change_clock_rate( this, cpc_clock );
- Sound_set_tempo( this, this->tempo );
- }
-}
-
-blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, int rate )
-{
- require( !this->sample_rate ); // sample rate can't be changed once set
- Buffer_init( &this->stereo_buf );
- RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
-
- // Set buffer bass
- Buffer_bass_freq( &this->stereo_buf, 160 );
-
- this->sample_rate = rate;
- RETURN_ERR( track_init( &this->track_filter, this ) );
- this->tfilter.max_silence = 6 * stereo * this->sample_rate;
- return 0;
-}
-
-void Sound_mute_voice( struct Ay_Emu *this, int index, bool mute )
-{
- require( (unsigned) index < (unsigned) this->voice_count );
- int bit = 1 << index;
- int mask = this->mute_mask_ | bit;
- if ( !mute )
- mask ^= bit;
- Sound_mute_voices( this, mask );
-}
-
-void Sound_mute_voices( struct Ay_Emu *this, int mask )
-{
- require( this->sample_rate ); // sample rate must be set first
- this->mute_mask_ = mask;
-
- int i;
- for ( i = this->voice_count; i--; )
- {
- if ( mask & (1 << i) )
- {
- set_voice( this, i, 0 );
- }
- else
- {
- struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
- assert( (ch.center && ch.left && ch.right) ||
- (!ch.center && !ch.left && !ch.right) ); // all or nothing
- set_voice( this, i, ch.center );
- }
- }
-}
-
-void Sound_set_tempo( struct Ay_Emu *this, int t )
-{
- require( this->sample_rate ); // sample rate must be set first
- int const min = (int)(FP_ONE_TEMPO*0.02);
- int const max = (int)(FP_ONE_TEMPO*4.00);
- if ( t < min ) t = min;
- if ( t > max ) t = max;
- this->tempo = t;
-
- int p = spectrum_period;
- if ( this->clock_rate_ != spectrum_clock )
- p = this->clock_rate_ / 50;
-
- this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t);
-}
-
-blargg_err_t Ay_start_track( struct Ay_Emu *this, int track )
-{
- clear_track_vars( this );
-
- // Remap track if playlist available
- if ( this->m3u.size > 0 ) {
- struct entry_t* e = &this->m3u.entries[track];
- track = e->track;
- }
-
- this->current_track = track;
- Buffer_clear( &this->stereo_buf );
-
- byte* const mem = this->mem.ram;
-
- memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
- memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
- memset( mem + ram_addr, 0x00, mem_size - ram_addr );
-
- // locate data blocks
- byte const* const data = get_data( &this->file, this->file.tracks + track * 4 + 2, 14 );
- if ( !data )
- return "file data missing";
-
- byte const* const more_data = get_data( &this->file, data + 10, 6 );
- if ( !more_data )
- return "file data missing";
-
- byte const* blocks = get_data( &this->file, data + 12, 8 );
- if ( !blocks )
- return "file data missing";
-
- // initial addresses
- unsigned addr = get_be16( blocks );
- if ( !addr )
- return "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 > mem_size )
- {
- /* warning( "Bad data block size" ); */
- len = mem_size - addr;
- }
- check( len );
- byte const* in = get_data( &this->file, blocks, 0 ); blocks += 2;
- if ( len > (unsigned) (this->file.end - in) )
- {
- /* warning( "File data missing" ); */
- len = this->file.end - in;
- }
-
- memcpy( mem + addr, in, len );
-
- if ( this->file.end - blocks < 8 )
- {
- /* 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( this, spectrum_clock );
- Sound_set_tempo( this, this->tempo );
-
- struct registers_t r;
- memset( &r, 0, sizeof(struct registers_t) );
-
- 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;
-
- memset( this->mem.padding1, 0xFF, sizeof this->mem.padding1 );
-
- int const mirrored = 0x80; // this much is mirrored after end of memory
- memset( this->mem.ram + mem_size + mirrored, 0xFF, sizeof this->mem.ram - mem_size - mirrored );
- memcpy( this->mem.ram + mem_size, this->mem.ram, mirrored ); // some code wraps around (ugh)
-
- Z80_reset( &this->cpu, this->mem.padding1, this->mem.padding1 );
- Z80_map_mem( &this->cpu, 0, mem_size, this->mem.ram, this->mem.ram );
- this->cpu.r = r;
-
- this->beeper_delta = (int) ((ay_amp_range*4)/5);
- this->last_beeper = 0;
- this->next_play = this->play_period;
- this->spectrum_mode = false;
- this->cpc_mode = false;
- this->cpc_latch = 0;
- set_beeper_output( this, this->beeper_output );
- Ay_apu_reset( &this->apu );
-
- // a few tunes rely on channels having tone enabled at the beginning
- Ay_apu_write_addr( &this->apu, 7 );
- Ay_apu_write_data( &this->apu, 0, 0x38 );
-
- // convert filter times to samples
- struct setup_t s = this->tfilter;
- s.max_initial *= this->sample_rate * stereo;
- #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
- s.lookahead = 1;
- #endif
- track_setup( &this->track_filter, &s );
-
- return track_start( &this->track_filter );
-}
-
-// Tell/Seek
-
-static int msec_to_samples( int msec, int sample_rate )
-{
- int sec = msec / 1000;
- msec -= sec * 1000;
- return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
-}
-
-int Track_tell( struct Ay_Emu *this )
-{
- int rate = this->sample_rate * stereo;
- int sec = track_sample_count( &this->track_filter ) / rate;
- return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Track_seek( struct Ay_Emu *this, int msec )
-{
- int time = msec_to_samples( msec, this->sample_rate );
- if ( time < track_sample_count( &this->track_filter ) )
- RETURN_ERR( Ay_start_track( this, this->current_track ) );
- return Track_skip( this, time - track_sample_count( &this->track_filter ) );
-}
-
-blargg_err_t skip_( void *emu, int count )
-{
- struct Ay_Emu* this = (struct Ay_Emu*) emu;
-
- // for long skip, mute sound
- const int threshold = 32768;
- if ( count > threshold )
- {
- int saved_mute = this->mute_mask_;
- Sound_mute_voices( this, ~0 );
-
- int n = count - threshold/2;
- n &= ~(2048-1); // round to multiple of 2048
- count -= n;
- RETURN_ERR( skippy_( &this->track_filter, n ) );
-
- Sound_mute_voices( this, saved_mute );
- }
-
- return skippy_( &this->track_filter, count );
-}
-
-blargg_err_t Track_skip( struct Ay_Emu *this, int count )
-{
- require( this->current_track >= 0 ); // start_track() must have been called already
- return track_skip( &this->track_filter, count );
-}
-
-int Track_get_length( struct Ay_Emu* this, int n )
-{
- int length = 0;
-
- byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 );
- if ( track_info )
- length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
-
- if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
- struct entry_t* entry = &this->m3u.entries [n];
- length = entry->length;
- }
-
- if ( length <= 0 )
- length = 120 * 1000; /* 2 minutes */
-
- return length;
-}
-
-void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec )
-{
- track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
- length_msec * this->sample_rate / (1000 / stereo) );
-}
-
-blargg_err_t Ay_play( struct Ay_Emu *this, int out_count, sample_t* out )
-{
- require( this->current_track >= 0 );
- require( out_count % stereo == 0 );
- return track_play( &this->track_filter, out_count, out );
-}
-
-blargg_err_t play_( void *emu, int count, sample_t* out )
-{
- struct Ay_Emu* this = (struct Ay_Emu*) emu;
-
- int remain = count;
- while ( remain )
- {
- Buffer_disable_immediate_removal( &this->stereo_buf );
- remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
- if ( remain )
- {
- if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
- {
- this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
-
- // Remute voices
- Sound_mute_voices( this, this->mute_mask_ );
- }
- int msec = Buffer_length( &this->stereo_buf );
- blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
- RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
- assert( clocks_emulated );
- Buffer_end_frame( &this->stereo_buf, clocks_emulated );
- }
- }
- return 0;
-}
+// Game_Music_Emu 0.6-pre. 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"
+
+const char* const gme_wrong_file_type = "Wrong file type for this emulator";
+
+// 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;
+
+static void clear_track_vars( struct Ay_Emu *this )
+{
+ this->current_track = -1;
+ track_stop( &this->track_filter );
+}
+
+void Ay_init( struct Ay_Emu *this )
+{
+ this->sample_rate = 0;
+ this->mute_mask_ = 0;
+ this->tempo = (int)FP_ONE_TEMPO;
+ this->gain = (int)FP_ONE_GAIN;
+ this->track_count = 0;
+
+ // defaults
+ this->tfilter = *track_get_setup( &this->track_filter );
+ this->tfilter.max_initial = 2;
+ this->tfilter.lookahead = 6;
+ this->track_filter.silence_ignored_ = false;
+
+ this->beeper_output = NULL;
+ disable_beeper( this );
+
+ Ay_apu_init( &this->apu );
+ Z80_init( &this->cpu );
+
+ // clears fields
+ this->voice_count = 0;
+ this->voice_types = 0;
+ clear_track_vars( this );
+}
+
+// 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( struct file_t const* file, byte const ptr [], int min_size )
+{
+ int offset = (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, struct file_t* out )
+{
+ if ( size < header_size )
+ return gme_wrong_file_type;
+
+ out->header = (struct header_t const*) in;
+ out->end = in + size;
+ struct header_t const* h = (struct header_t const*) in;
+ if ( memcmp( h->tag, "ZXAYEMUL", 8 ) )
+ return gme_wrong_file_type;
+
+ out->tracks = get_data( out, h->track_info, (h->max_track + 1) * 4 );
+ if ( !out->tracks )
+ return "missing track data";
+
+ return 0;
+}
+
+// Setup
+
+static void change_clock_rate( struct Ay_Emu *this, int rate )
+{
+ this->clock_rate_ = rate;
+ Buffer_clock_rate( &this->stereo_buf, rate );
+}
+
+blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], long size )
+{
+ // Unload
+ this->voice_count = 0;
+ this->track_count = 0;
+ this->m3u.size = 0;
+ clear_track_vars( this );
+
+ assert( offsetof (struct header_t,track_info [2]) == header_size );
+
+ RETURN_ERR( parse_header( in, size, &this->file ) );
+
+ /* if ( file.header->vers > 2 )
+ warning( "Unknown file version" ); */
+
+ this->voice_count = ay_osc_count + 1; // +1 for beeper
+ static int const types [ay_osc_count + 1] = {
+ wave_type+0, wave_type+1, wave_type+2, mixed_type+1
+ };
+ this->voice_types = types;
+
+ Ay_apu_volume( &this->apu, this->gain);
+
+ // Setup buffer
+ change_clock_rate( this, spectrum_clock );
+ RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
+ this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
+
+ Sound_set_tempo( this, this->tempo );
+ Sound_mute_voices( this, this->mute_mask_ );
+
+ this->track_count = this->file.header->max_track + 1;
+ return 0;
+}
+
+static void set_beeper_output( struct Ay_Emu *this, struct Blip_Buffer* b )
+{
+ this->beeper_output = b;
+ if ( b && !this->cpc_mode )
+ this->beeper_mask = 0x10;
+ else
+ disable_beeper( this );
+}
+
+static void set_voice( struct Ay_Emu *this, int i, struct Blip_Buffer* center )
+{
+ if ( i >= ay_osc_count )
+ set_beeper_output( this, center );
+ else
+ Ay_apu_set_output( &this->apu, i, center );
+}
+
+static blargg_err_t run_clocks( struct Ay_Emu *this, blip_time_t* duration, int msec )
+{
+#if defined(ROCKBOX)
+ (void) msec;
+#endif
+
+ cpu_time_t *end = duration;
+ struct Z80_Cpu* cpu = &this->cpu;
+ Z80_set_time( cpu, 0 );
+
+ // Since detection of CPC mode will halve clock rate during the frame
+ // and thus generate up to twice as much sound, we must generate half
+ // as much until mode is known.
+ if ( !(this->spectrum_mode | this->cpc_mode) )
+ *end /= 2;
+
+ while ( Z80_time( cpu ) < *end )
+ {
+ run_cpu( this, min( *end, this->next_play ) );
+
+ if ( Z80_time( cpu ) >= this->next_play )
+ {
+ // next frame
+ this->next_play += this->play_period;
+
+ if ( cpu->r.iff1 )
+ {
+ // interrupt enabled
+
+ if ( this->mem.ram [cpu->r.pc] == 0x76 )
+ cpu->r.pc++; // advance past HALT instruction
+
+ cpu->r.iff1 = 0;
+ cpu->r.iff2 = 0;
+
+ this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc >> 8);
+ this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc);
+
+ // fixed interrupt
+ cpu->r.pc = 0x38;
+ Z80_adjust_time( cpu, 12 );
+
+ if ( cpu->r.im == 2 )
+ {
+ // vectored interrupt
+ addr_t addr = cpu->r.i * 0x100 + 0xFF;
+ cpu->r.pc = this->mem.ram [(addr + 1) & 0xFFFF] * 0x100 + this->mem.ram [addr];
+ Z80_adjust_time( cpu, 6 );
+ }
+ }
+ }
+ }
+
+ // End time frame
+ *end = Z80_time( cpu );
+ this->next_play -= *end;
+ check( this->next_play >= 0 );
+ Z80_adjust_time( cpu, -*end );
+ Ay_apu_end_frame( &this->apu, *end );
+ return 0;
+}
+
+// Emulation
+
+void cpu_out_( struct Ay_Emu *this, cpu_time_t time, addr_t addr, int data )
+{
+ // Spectrum
+ if ( !this->cpc_mode )
+ {
+ switch ( addr & 0xFEFF )
+ {
+ case 0xFEFD:
+ this->spectrum_mode = true;
+ Ay_apu_write_addr( &this->apu, data );
+ return;
+
+ case 0xBEFD:
+ this->spectrum_mode = true;
+ Ay_apu_write_data( &this->apu, time, data );
+ return;
+ }
+ }
+
+ // CPC
+ if ( !this->spectrum_mode )
+ {
+ switch ( addr >> 8 )
+ {
+ case 0xF6:
+ switch ( data & 0xC0 )
+ {
+ case 0xC0:
+ Ay_apu_write_addr( &this->apu, this->cpc_latch );
+ goto enable_cpc;
+
+ case 0x80:
+ Ay_apu_write_data( &this->apu, time, this->cpc_latch );
+ goto enable_cpc;
+ }
+ break;
+
+ case 0xF4:
+ this->cpc_latch = data;
+ goto enable_cpc;
+ }
+ }
+
+ /* dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data ); */
+ return;
+
+enable_cpc:
+ if ( !this->cpc_mode )
+ {
+ this->cpc_mode = true;
+ disable_beeper( this );
+
+ change_clock_rate( this, cpc_clock );
+ Sound_set_tempo( this, this->tempo );
+ }
+}
+
+blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, int rate )
+{
+ require( !this->sample_rate ); // sample rate can't be changed once set
+ Buffer_init( &this->stereo_buf );
+ RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
+
+ // Set buffer bass
+ Buffer_bass_freq( &this->stereo_buf, 160 );
+
+ this->sample_rate = rate;
+ RETURN_ERR( track_init( &this->track_filter, this ) );
+ this->tfilter.max_silence = 6 * stereo * this->sample_rate;
+ return 0;
+}
+
+void Sound_mute_voice( struct Ay_Emu *this, int index, bool mute )
+{
+ require( (unsigned) index < (unsigned) this->voice_count );
+ int bit = 1 << index;
+ int mask = this->mute_mask_ | bit;
+ if ( !mute )
+ mask ^= bit;
+ Sound_mute_voices( this, mask );
+}
+
+void Sound_mute_voices( struct Ay_Emu *this, int mask )
+{
+ require( this->sample_rate ); // sample rate must be set first
+ this->mute_mask_ = mask;
+
+ int i;
+ for ( i = this->voice_count; i--; )
+ {
+ if ( mask & (1 << i) )
+ {
+ set_voice( this, i, 0 );
+ }
+ else
+ {
+ struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
+ assert( (ch.center && ch.left && ch.right) ||
+ (!ch.center && !ch.left && !ch.right) ); // all or nothing
+ set_voice( this, i, ch.center );
+ }
+ }
+}
+
+void Sound_set_tempo( struct Ay_Emu *this, int t )
+{
+ require( this->sample_rate ); // sample rate must be set first
+ int const min = (int)(FP_ONE_TEMPO*0.02);
+ int const max = (int)(FP_ONE_TEMPO*4.00);
+ if ( t < min ) t = min;
+ if ( t > max ) t = max;
+ this->tempo = t;
+
+ int p = spectrum_period;
+ if ( this->clock_rate_ != spectrum_clock )
+ p = this->clock_rate_ / 50;
+
+ this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t);
+}
+
+blargg_err_t Ay_start_track( struct Ay_Emu *this, int track )
+{
+ clear_track_vars( this );
+
+ // Remap track if playlist available
+ if ( this->m3u.size > 0 ) {
+ struct entry_t* e = &this->m3u.entries[track];
+ track = e->track;
+ }
+
+ this->current_track = track;
+ Buffer_clear( &this->stereo_buf );
+
+ byte* const mem = this->mem.ram;
+
+ memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
+ memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
+ memset( mem + ram_addr, 0x00, mem_size - ram_addr );
+
+ // locate data blocks
+ byte const* const data = get_data( &this->file, this->file.tracks + track * 4 + 2, 14 );
+ if ( !data )
+ return "file data missing";
+
+ byte const* const more_data = get_data( &this->file, data + 10, 6 );
+ if ( !more_data )
+ return "file data missing";
+
+ byte const* blocks = get_data( &this->file, data + 12, 8 );
+ if ( !blocks )
+ return "file data missing";
+
+ // initial addresses
+ unsigned addr = get_be16( blocks );
+ if ( !addr )
+ return "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 > mem_size )
+ {
+ /* warning( "Bad data block size" ); */
+ len = mem_size - addr;
+ }
+ check( len );
+ byte const* in = get_data( &this->file, blocks, 0 ); blocks += 2;
+ if ( len > (unsigned) (this->file.end - in) )
+ {
+ /* warning( "File data missing" ); */
+ len = this->file.end - in;
+ }
+
+ memcpy( mem + addr, in, len );
+
+ if ( this->file.end - blocks < 8 )
+ {
+ /* 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( this, spectrum_clock );
+ Sound_set_tempo( this, this->tempo );
+
+ struct registers_t r;
+ memset( &r, 0, sizeof(struct registers_t) );
+
+ 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;
+
+ memset( this->mem.padding1, 0xFF, sizeof this->mem.padding1 );
+
+ int const mirrored = 0x80; // this much is mirrored after end of memory
+ memset( this->mem.ram + mem_size + mirrored, 0xFF, sizeof this->mem.ram - mem_size - mirrored );
+ memcpy( this->mem.ram + mem_size, this->mem.ram, mirrored ); // some code wraps around (ugh)
+
+ Z80_reset( &this->cpu, this->mem.padding1, this->mem.padding1 );
+ Z80_map_mem( &this->cpu, 0, mem_size, this->mem.ram, this->mem.ram );
+ this->cpu.r = r;
+
+ this->beeper_delta = (int) ((ay_amp_range*4)/5);
+ this->last_beeper = 0;
+ this->next_play = this->play_period;
+ this->spectrum_mode = false;
+ this->cpc_mode = false;
+ this->cpc_latch = 0;
+ set_beeper_output( this, this->beeper_output );
+ Ay_apu_reset( &this->apu );
+
+ // a few tunes rely on channels having tone enabled at the beginning
+ Ay_apu_write_addr( &this->apu, 7 );
+ Ay_apu_write_data( &this->apu, 0, 0x38 );
+
+ // convert filter times to samples
+ struct setup_t s = this->tfilter;
+ s.max_initial *= this->sample_rate * stereo;
+ #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
+ s.lookahead = 1;
+ #endif
+ track_setup( &this->track_filter, &s );
+
+ return track_start( &this->track_filter );
+}
+
+// Tell/Seek
+
+static int msec_to_samples( int msec, int sample_rate )
+{
+ int sec = msec / 1000;
+ msec -= sec * 1000;
+ return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
+}
+
+int Track_tell( struct Ay_Emu *this )
+{
+ int rate = this->sample_rate * stereo;
+ int sec = track_sample_count( &this->track_filter ) / rate;
+ return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Track_seek( struct Ay_Emu *this, int msec )
+{
+ int time = msec_to_samples( msec, this->sample_rate );
+ if ( time < track_sample_count( &this->track_filter ) )
+ RETURN_ERR( Ay_start_track( this, this->current_track ) );
+ return Track_skip( this, time - track_sample_count( &this->track_filter ) );
+}
+
+blargg_err_t skip_( void *emu, int count )
+{
+ struct Ay_Emu* this = (struct Ay_Emu*) emu;
+
+ // for long skip, mute sound
+ const int threshold = 32768;
+ if ( count > threshold )
+ {
+ int saved_mute = this->mute_mask_;
+ Sound_mute_voices( this, ~0 );
+
+ int n = count - threshold/2;
+ n &= ~(2048-1); // round to multiple of 2048
+ count -= n;
+ RETURN_ERR( skippy_( &this->track_filter, n ) );
+
+ Sound_mute_voices( this, saved_mute );
+ }
+
+ return skippy_( &this->track_filter, count );
+}
+
+blargg_err_t Track_skip( struct Ay_Emu *this, int count )
+{
+ require( this->current_track >= 0 ); // start_track() must have been called already
+ return track_skip( &this->track_filter, count );
+}
+
+int Track_get_length( struct Ay_Emu* this, int n )
+{
+ int length = 0;
+
+ byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 );
+ if ( track_info )
+ length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
+
+ if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
+ struct entry_t* entry = &this->m3u.entries [n];
+ length = entry->length;
+ }
+
+ if ( length <= 0 )
+ length = 120 * 1000; /* 2 minutes */
+
+ return length;
+}
+
+void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec )
+{
+ track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
+ length_msec * this->sample_rate / (1000 / stereo) );
+}
+
+blargg_err_t Ay_play( struct Ay_Emu *this, int out_count, sample_t* out )
+{
+ require( this->current_track >= 0 );
+ require( out_count % stereo == 0 );
+ return track_play( &this->track_filter, out_count, out );
+}
+
+blargg_err_t play_( void *emu, int count, sample_t* out )
+{
+ struct Ay_Emu* this = (struct Ay_Emu*) emu;
+
+ int remain = count;
+ while ( remain )
+ {
+ Buffer_disable_immediate_removal( &this->stereo_buf );
+ remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
+ if ( remain )
+ {
+ if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
+ {
+ this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
+
+ // Remute voices
+ Sound_mute_voices( this, this->mute_mask_ );
+ }
+ int msec = Buffer_length( &this->stereo_buf );
+ blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
+ RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
+ assert( clocks_emulated );
+ Buffer_end_frame( &this->stereo_buf, clocks_emulated );
+ }
+ }
+ return 0;
+}
diff --git a/apps/codecs/libgme/blargg_config.h b/apps/codecs/libgme/blargg_config.h
index 6490c15cfb..398913d1fe 100644
--- a/apps/codecs/libgme/blargg_config.h
+++ b/apps/codecs/libgme/blargg_config.h
@@ -1,42 +1,42 @@
-// Library configuration. Modify this file as necessary.
-
-#ifndef BLARGG_CONFIG_H
-#define BLARGG_CONFIG_H
-
-// Uncomment to enable platform-specific optimizations
-//#define BLARGG_NONPORTABLE 1
-
-// Uncomment if automatic byte-order determination doesn't work
-#ifdef ROCKBOX_BIG_ENDIAN
- #define BLARGG_BIG_ENDIAN 1
-#endif
-
-// Uncomment if you get errors in the bool section of blargg_common.h
-#define BLARGG_COMPILER_HAS_BOOL 1
-
-// Uncomment to use fast gb apu implementation
-// #define GB_APU_FAST 1
-
-// Uncomment to remove agb emulation support
-// #define GB_APU_NO_AGB 1
-
-// Uncomment to emulate only nes apu
-// #define NSF_EMU_APU_ONLY 1
-
-// Uncomment to remove vrc7 apu support
-// #define NSF_EMU_NO_VRC7 1
-
-// Uncomment to remove fmopl apu support
-// #define KSS_EMU_NO_FMOPL 1
-
-// To handle undefined reference to assert
-#define NDEBUG 1
-
-// Use standard config.h if present
-#define HAVE_CONFIG_H 1
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#endif
+// Library configuration. Modify this file as necessary.
+
+#ifndef BLARGG_CONFIG_H
+#define BLARGG_CONFIG_H
+
+// Uncomment to enable platform-specific optimizations
+//#define BLARGG_NONPORTABLE 1
+
+// Uncomment if automatic byte-order determination doesn't work
+#ifdef ROCKBOX_BIG_ENDIAN
+ #define BLARGG_BIG_ENDIAN 1
+#endif
+
+// Uncomment if you get errors in the bool section of blargg_common.h
+#define BLARGG_COMPILER_HAS_BOOL 1
+
+// Uncomment to use fast gb apu implementation
+// #define GB_APU_FAST 1
+
+// Uncomment to remove agb emulation support
+// #define GB_APU_NO_AGB 1
+
+// Uncomment to emulate only nes apu
+// #define NSF_EMU_APU_ONLY 1
+
+// Uncomment to remove vrc7 apu support
+// #define NSF_EMU_NO_VRC7 1
+
+// Uncomment to remove fmopl apu support
+// #define KSS_EMU_NO_FMOPL 1
+
+// To handle undefined reference to assert
+#define NDEBUG 1
+
+// Use standard config.h if present
+#define HAVE_CONFIG_H 1
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#endif
diff --git a/apps/codecs/libgme/emu2413.c b/apps/codecs/libgme/emu2413.c
index a4637ce15b..01075821cb 100644
--- a/apps/codecs/libgme/emu2413.c
+++ b/apps/codecs/libgme/emu2413.c
@@ -1,1981 +1,1981 @@
-/***********************************************************************************
-
- emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
-
- 2001 01-08 : Version 0.10 -- 1st version.
- 2001 01-15 : Version 0.20 -- semi-public version.
- 2001 01-16 : Version 0.30 -- 1st public version.
- 2001 01-17 : Version 0.31 -- Fixed bassdrum problem.
- : Version 0.32 -- LPF implemented.
- 2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method.
- -- Fixed the LFO bug.
- 2001 01-24 : Version 0.35 -- Fixed the drum problem,
- support undocumented EG behavior.
- 2001 02-02 : Version 0.38 -- Improved the performance.
- Fixed the hi-hat and cymbal model.
- Fixed the default percussive datas.
- Noise reduction.
- Fixed the feedback problem.
- 2001 03-03 : Version 0.39 -- Fixed some drum bugs.
- Improved the performance.
- 2001 03-04 : Version 0.40 -- Improved the feedback.
- Change the default table size.
- Clock and Rate can be changed during play.
- 2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone.
- Added VRC7 patch (OPLL_reset_patch is changed).
- Fixed OPLL_reset() bug.
- Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask.
- Added OPLL_writeIO.
- 2001 09-28 : Version 0.51 -- Removed the noise table.
- 2002 01-28 : Version 0.52 -- Added Stereo mode.
- 2002 02-07 : Version 0.53 -- Fixed some drum bugs.
- 2002 02-20 : Version 0.54 -- Added the best quality mode.
- 2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close.
- 2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas.
- 2004 04-10 : Version 0.61 -- Added YMF281B tone (defined by Chabin).
-
- 2011 03-22 : --------------- Modified by gama to use precalculated tables.
-
- References:
- fmopl.c -- 1999,2000 written by Tatsuyuki Satoh (MAME development).
- fmopl.c(fixed) -- (C) 2002 Jarek Burczynski.
- s_opl.c -- 2001 written by Mamiya (NEZplug development).
- fmgen.cpp -- 1999,2000 written by cisc.
- fmpac.ill -- 2000 created by NARUTO.
- MSX-Datapack
- YMU757 data sheet
- YM2143 data sheet
-
-**************************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "emu2413.h"
-
-#include "emutables.h"
-#if !defined(ROCKBOX)
- #define EMU2413_CALCUL_TABLES
-#else
- #define EMU2413_COMPACTION
- #include "emutables.h"
-#endif
-
-#if defined(EMU2413_COMPACTION) && !defined(ROCKBOX)
-#define OPLL_TONE_NUM 1
-static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
- {
-#include "2413tone.h"
- }
-};
-#else
-#define OPLL_TONE_NUM 3
-static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
- {
-#include "2413tone.h"
- },
- {
-#include "vrc7tone.h"
- },
- {
-#include "281btone.h"
- }
-};
-#endif
-
-/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.) */
-#define PG_BITS 9
-#define PG_WIDTH (1<<PG_BITS)
-
-/* Phase increment counter */
-#define DP_BITS 18
-#define DP_WIDTH (1<<DP_BITS)
-#define DP_BASE_BITS (DP_BITS - PG_BITS)
-
-/* Dynamic range (Accuracy of sin table) */
-#define DB_PREC 48
-#define DB_BITS 8
-#define DB_STEP ((double)DB_PREC/(1<<DB_BITS))
-#define DB_MUTE (1<<DB_BITS)
-
-/* Dynamic range of envelope */
-#define EG_STEP 0.375
-#define EG_BITS 7
-#define EG_MUTE (1<<EG_BITS)
-
-/* Dynamic range of total level */
-#define TL_STEP 0.75
-#define TL_BITS 6
-#define TL_MUTE (1<<TL_BITS)
-
-/* Dynamic range of sustine level */
-#define SL_STEP 3.0
-#define SL_BITS 4
-#define SL_MUTE (1<<SL_BITS)
-
-#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
-#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
-#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
-
-#define DB_POS(x) (x*DB_MUTE/DB_PREC)
-#define DB_NEG(x) (DB_MUTE+DB_MUTE+x*DB_MUTE/DB_PREC)
-
-/* Bits for liner value */
-#define DB2LIN_AMP_BITS 8
-#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
-
-/* Bits for envelope phase incremental counter */
-#define EG_DP_BITS 22
-#define EG_DP_WIDTH (1<<EG_DP_BITS)
-
-/* Bits for Pitch and Amp modulator */
-#define PM_PG_BITS 8
-#define PM_PG_WIDTH (1<<PM_PG_BITS)
-#define PM_DP_BITS 16
-#define PM_DP_WIDTH (1<<PM_DP_BITS)
-#define AM_PG_BITS 8
-#define AM_PG_WIDTH (1<<AM_PG_BITS)
-#define AM_DP_BITS 16
-#define AM_DP_WIDTH (1<<AM_DP_BITS)
-
-/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
-#define PM_AMP_BITS 8
-#define PM_AMP (1<<PM_AMP_BITS)
-
-/* PM speed(Hz) and depth(cent) */
-#define PM_SPEED 6.4
-#define PM_DEPTH 13.75
-
-/* AM speed(Hz) and depth(dB) */
-#define AM_SPEED 3.6413
-#define AM_DEPTH 4.875
-
-/* Cut the lower b bit(s) off. */
-#define HIGHBITS(c,b) ((c)>>(b))
-
-/* Leave the lower b bit(s). */
-#define LOWBITS(c,b) ((c)&((1<<(b))-1))
-
-/* Expand x which is s bits to d bits. */
-#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s)))
-
-/* Expand x which is s bits to d bits and fill expanded bits '1' */
-#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
-
-/* Adjust envelope speed which depends on sampling rate. */
-#define RATE_ADJUST(x) (rate==49716?(e_uint32)x:(e_uint32)(((long long)(x)*clk/rate+36)/72))
-
-#define MOD(o,x) (&(o)->slot[(x)<<1])
-#define CAR(o,x) (&(o)->slot[((x)<<1)|1])
-
-#define BIT(s,b) (((s)>>(b))&1)
-
-/* Input clock */
-static e_uint32 clk = 844451141;
-/* Sampling rate */
-static e_uint32 rate = 3354932;
-
-/* WaveTable for each envelope amp */
-static e_uint16 fullsintable[PG_WIDTH];
-static e_uint16 halfsintable[PG_WIDTH];
-
-static e_uint16 *waveform[2] = { fullsintable, halfsintable };
-
-/* LFO Table */
-#ifdef EMU2413_CALCUL_TABLES
- static e_int32 pmtable[PM_PG_WIDTH];
- static e_int32 amtable[AM_PG_WIDTH];
- #define PMTABLE(x) pmtable[x]
- #define AMTABLE(x) amtable[x]
-#else
- #define PMTABLE(x) (e_int32)pm_coeff[x]
- #if (PM_PG_WIDTH != 256)
- #error PM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
- #endif
- #define AMTABLE(x) (e_int32)am_coeff[x]
- #if (AM_PG_WIDTH != 256)
- #error AM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
- #endif
-#endif
-
-/* Phase delta for LFO */
-static e_uint32 pm_dphase;
-static e_uint32 am_dphase;
-
-/* dB to Liner table */
-static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2];
-
-/* Liner to Log curve conversion table (for Attack rate). */
-#ifdef EMU2413_CALCUL_TABLES
- static e_uint16 ar_adjust_table[1 << EG_BITS];
- #define AR_ADJUST_TABLE(x) ar_adjust_table[x]
-#else
- #define AR_ADJUST_TABLE(x) ar_adjust_coeff[x]
- #if (EG_BITS != 7)
- #error EG_BITS must be set to 7 if EMU2413_CALCUL_TABLES is not defined
- #endif
-#endif
-
-/* Empty voice data */
-static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/* Basic voice Data */
-static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];
-
-/* Definition of envelope mode */
-enum OPLL_EG_STATE
-{ READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH };
-
-/* Phase incr table for Attack */
-static e_uint32 dphaseARTable[16][16];
-/* Phase incr table for Decay and Release */
-static e_uint32 dphaseDRTable[16][16];
-
-/* KSL + TL Table */
-e_uint8 tllTable[16][8][1 << TL_BITS][4];
-static e_int32 rksTable[2][8][2];
-
-/* We may not have too much SRAM in rockbox */
-#if !defined(ROCKBOX)
-/* Phase incr table for PG */
-static e_uint32 dphaseTable[512][8][16];
-#endif
-
-/***************************************************
-
- Create tables
-
-****************************************************/
-#ifdef EMU2413_CALCUL_TABLES
-INLINE static e_int32
-Min (e_int32 i, e_int32 j)
-{
- if (i < j)
- return i;
- else
- return j;
-}
-
-/* Table for AR to LogCurve. */
-static void
-makeAdjustTable (void)
-{
- e_int32 i;
-
- ar_adjust_table[0] = (1 << EG_BITS) - 1;
- for (i = 1; i < (1<<EG_BITS); i++)
- ar_adjust_table[i] = (e_uint16) ((double) (1<<EG_BITS)-1 - ((1<<EG_BITS)-1)*log(i)/log(127));
-}
-#endif
-
-/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
-static void
-makeDB2LinTable (void)
-{
- e_int32 i;
- for (i = 0; i < DB_MUTE + DB_MUTE; i++)
- {
- #ifdef EMU2413_CALCUL_TABLES
- DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
- #else
- DB2LIN_TABLE[i] = db2lin_coeff[i];
- #endif
- if (i >= DB_MUTE) DB2LIN_TABLE[i] = 0;
- DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]);
- }
-}
-
-#ifdef EMU2413_CALCUL_TABLES
-/* Liner(+0.0 - +1.0) to dB((1<<DB_BITS) - 1 -- 0) */
-static e_int32
-lin2db (double d)
-{
- if (d == 0)
- return (DB_MUTE - 1);
- else
- return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1); /* 0 -- 127 */
-}
-#endif
-
-/* Sin Table */
-static void
-makeSinTable (void)
-{
- e_int32 i;
-
- for (i = 0; i < PG_WIDTH / 4; i++)
- #ifdef EMU2413_CALCUL_TABLES
- fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
- #else
- fullsintable[i] = sin_coeff[i];
- #endif
-
- for (i = 0; i < PG_WIDTH / 4; i++)
- {
- fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
- }
-
- for (i = 0; i < PG_WIDTH / 2; i++)
- {
- fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
- }
-
- for (i = 0; i < PG_WIDTH / 2; i++)
- halfsintable[i] = fullsintable[i];
- for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
- halfsintable[i] = fullsintable[0];
-}
-
-#ifdef EMU2413_CALCUL_TABLES
-static double saw(double phase)
-{
- if(phase <= PI/2)
- return phase * 2 / PI ;
- else if(phase <= PI*3/2)
- return 2.0 - ( phase * 2 / PI );
- else
- return -4.0 + phase * 2 / PI;
-}
-
-/* Table for Pitch Modulator */
-static void
-makePmTable (void)
-{
- e_int32 i;
-
- for (i = 0; i < PM_PG_WIDTH; i++)
- /* pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200)); */
- pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * saw (2.0 * PI * i / PM_PG_WIDTH) / 1200));
-}
-
-/* Table for Amp Modulator */
-static void
-makeAmTable (void)
-{
- e_int32 i;
-
- for (i = 0; i < AM_PG_WIDTH; i++)
- /* amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH))); */
- amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + saw (2.0 * PI * i / PM_PG_WIDTH)));
-}
-#endif
-
-#if !defined(ROCKBOX)
-/* Phase increment counter table */
-static void
-makeDphaseTable (void)
-{
- e_uint32 fnum, block, ML;
- e_uint32 mltable[16] =
- { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
-
- for (fnum = 0; fnum < 512; fnum++)
- for (block = 0; block < 8; block++)
- for (ML = 0; ML < 16; ML++)
- dphaseTable[fnum][block][ML] = RATE_ADJUST (((fnum * mltable[ML]) << block) >> (20 - DP_BITS));
-}
-#endif
-
-static void
-makeTllTable (void)
-{
-/* Multiplication owith 8 to have an integer result. This allows to remove floating point operation. */
-#define dB2(x) (int)((x)*2*8)
-
- static int kltable[16] = {
- dB2 ( 0.000), dB2 ( 9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
- dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
- };
-
- e_int32 tmp;
- e_int32 fnum, block, TL, KL;
-
- for (fnum = 0; fnum < 16; fnum++)
- for (block = 0; block < 8; block++)
- for (TL = 0; TL < 64; TL++)
- for (KL = 0; KL < 4; KL++)
- {
- if (KL == 0)
- {
- tllTable[fnum][block][TL][KL] = TL2EG (TL);
- }
- else
- {
- tmp = (e_int32) ((kltable[fnum] - dB2 (3.000) * (7 - block))/8);
- if (tmp <= 0)
- tllTable[fnum][block][TL][KL] = TL2EG (TL);
- else
- /* tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL); */
- tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp << KL) / (int)(EG_STEP*8)) + TL2EG (TL);
- }
- }
-}
-
-#ifdef USE_SPEC_ENV_SPEED
-static double attacktime[16][4] = {
- {0, 0, 0, 0},
- {1730.15, 1400.60, 1153.43, 988.66},
- {865.08, 700.30, 576.72, 494.33},
- {432.54, 350.15, 288.36, 247.16},
- {216.27, 175.07, 144.18, 123.58},
- {108.13, 87.54, 72.09, 61.79},
- {54.07, 43.77, 36.04, 30.90},
- {27.03, 21.88, 18.02, 15.45},
- {13.52, 10.94, 9.01, 7.72},
- {6.76, 5.47, 4.51, 3.86},
- {3.38, 2.74, 2.25, 1.93},
- {1.69, 1.37, 1.13, 0.97},
- {0.84, 0.70, 0.60, 0.54},
- {0.50, 0.42, 0.34, 0.30},
- {0.28, 0.22, 0.18, 0.14},
- {0.00, 0.00, 0.00, 0.00}
-};
-
-static double decaytime[16][4] = {
- {0, 0, 0, 0},
- {20926.60, 16807.20, 14006.00, 12028.60},
- {10463.30, 8403.58, 7002.98, 6014.32},
- {5231.64, 4201.79, 3501.49, 3007.16},
- {2615.82, 2100.89, 1750.75, 1503.58},
- {1307.91, 1050.45, 875.37, 751.79},
- {653.95, 525.22, 437.69, 375.90},
- {326.98, 262.61, 218.84, 187.95},
- {163.49, 131.31, 109.42, 93.97},
- {81.74, 65.65, 54.71, 46.99},
- {40.87, 32.83, 27.36, 23.49},
- {20.44, 16.41, 13.68, 11.75},
- {10.22, 8.21, 6.84, 5.87},
- {5.11, 4.10, 3.42, 2.94},
- {2.55, 2.05, 1.71, 1.47},
- {1.27, 1.27, 1.27, 1.27}
-};
-#endif
-
-/* Rate Table for Attack */
-static void
-makeDphaseARTable (void)
-{
- e_int32 AR, Rks, RM, RL;
-
-#ifdef USE_SPEC_ENV_SPEED
- e_uint32 attacktable[16][4];
-
- for (RM = 0; RM < 16; RM++)
- for (RL = 0; RL < 4; RL++)
- {
- if (RM == 0)
- attacktable[RM][RL] = 0;
- else if (RM == 15)
- attacktable[RM][RL] = EG_DP_WIDTH;
- else
- attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
-
- }
-#endif
-
- for (AR = 0; AR < 16; AR++)
- for (Rks = 0; Rks < 16; Rks++)
- {
- RM = AR + (Rks >> 2);
- RL = Rks & 3;
- if (RM > 15)
- RM = 15;
- switch (AR)
- {
- case 0:
- dphaseARTable[AR][Rks] = 0;
- break;
- case 15:
- dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/
- break;
- default:
-#ifdef USE_SPEC_ENV_SPEED
- dphaseARTable[AR][Rks] = RATE_ADJUST (attacktable[RM][RL]);
-#else
- dphaseARTable[AR][Rks] = RATE_ADJUST ((3 * (RL + 4) << (RM + 1)));
-#endif
- break;
- }
- }
-}
-
-/* Rate Table for Decay and Release */
-static void
-makeDphaseDRTable (void)
-{
- e_int32 DR, Rks, RM, RL;
-
-#ifdef USE_SPEC_ENV_SPEED
- e_uint32 decaytable[16][4];
-
- for (RM = 0; RM < 16; RM++)
- for (RL = 0; RL < 4; RL++)
- if (RM == 0)
- decaytable[RM][RL] = 0;
- else
- decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000));
-#endif
-
- for (DR = 0; DR < 16; DR++)
- for (Rks = 0; Rks < 16; Rks++)
- {
- RM = DR + (Rks >> 2);
- RL = Rks & 3;
- if (RM > 15)
- RM = 15;
- switch (DR)
- {
- case 0:
- dphaseDRTable[DR][Rks] = 0;
- break;
- default:
-#ifdef USE_SPEC_ENV_SPEED
- dphaseDRTable[DR][Rks] = RATE_ADJUST (decaytable[RM][RL]);
-#else
- dphaseDRTable[DR][Rks] = RATE_ADJUST ((RL + 4) << (RM - 1));
-#endif
- break;
- }
- }
-}
-
-static void
-makeRksTable (void)
-{
-
- e_int32 fnum8, block, KR;
-
- for (fnum8 = 0; fnum8 < 2; fnum8++)
- for (block = 0; block < 8; block++)
- for (KR = 0; KR < 2; KR++)
- {
- if (KR != 0)
- rksTable[fnum8][block][KR] = (block << 1) + fnum8;
- else
- rksTable[fnum8][block][KR] = block >> 1;
- }
-}
-
-void
-OPLL_dump2patch (const e_uint8 * dump, OPLL_PATCH * patch)
-{
- patch[0].AM = (dump[0] >> 7) & 1;
- patch[1].AM = (dump[1] >> 7) & 1;
- patch[0].PM = (dump[0] >> 6) & 1;
- patch[1].PM = (dump[1] >> 6) & 1;
- patch[0].EG = (dump[0] >> 5) & 1;
- patch[1].EG = (dump[1] >> 5) & 1;
- patch[0].KR = (dump[0] >> 4) & 1;
- patch[1].KR = (dump[1] >> 4) & 1;
- patch[0].ML = (dump[0]) & 15;
- patch[1].ML = (dump[1]) & 15;
- patch[0].KL = (dump[2] >> 6) & 3;
- patch[1].KL = (dump[3] >> 6) & 3;
- patch[0].TL = (dump[2]) & 63;
- patch[0].FB = (dump[3]) & 7;
- patch[0].WF = (dump[3] >> 3) & 1;
- patch[1].WF = (dump[3] >> 4) & 1;
- patch[0].AR = (dump[4] >> 4) & 15;
- patch[1].AR = (dump[5] >> 4) & 15;
- patch[0].DR = (dump[4]) & 15;
- patch[1].DR = (dump[5]) & 15;
- patch[0].SL = (dump[6] >> 4) & 15;
- patch[1].SL = (dump[7] >> 4) & 15;
- patch[0].RR = (dump[6]) & 15;
- patch[1].RR = (dump[7]) & 15;
-}
-
-void
-OPLL_getDefaultPatch (e_int32 type, e_int32 num, OPLL_PATCH * patch)
-{
- OPLL_dump2patch (default_inst[type] + num * 16, patch);
-}
-
-static void
-makeDefaultPatch ( void )
-{
- e_int32 i, j;
-
- for (i = 0; i < OPLL_TONE_NUM; i++)
- for (j = 0; j < 19; j++)
- OPLL_getDefaultPatch (i, j, &default_patch[i][j * 2]);
-
-}
-
-void
-OPLL_setPatch (OPLL * opll, const e_uint8 * dump)
-{
- OPLL_PATCH patch[2];
- int i;
-
- for (i = 0; i < 19; i++)
- {
- OPLL_dump2patch (dump + i * 16, patch);
- memcpy (&opll->patch[i*2+0], &patch[0], sizeof (OPLL_PATCH));
- memcpy (&opll->patch[i*2+1], &patch[1], sizeof (OPLL_PATCH));
- }
-}
-
-void
-OPLL_patch2dump (const OPLL_PATCH * patch, e_uint8 * dump)
-{
- dump[0] = (e_uint8) ((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);
- dump[1] = (e_uint8) ((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);
- dump[2] = (e_uint8) ((patch[0].KL << 6) + patch[0].TL);
- dump[3] = (e_uint8) ((patch[1].KL << 6) + (patch[1].WF << 4) + (patch[0].WF << 3) + patch[0].FB);
- dump[4] = (e_uint8) ((patch[0].AR << 4) + patch[0].DR);
- dump[5] = (e_uint8) ((patch[1].AR << 4) + patch[1].DR);
- dump[6] = (e_uint8) ((patch[0].SL << 4) + patch[0].RR);
- dump[7] = (e_uint8) ((patch[1].SL << 4) + patch[1].RR);
- dump[8] = 0;
- dump[9] = 0;
- dump[10] = 0;
- dump[11] = 0;
- dump[12] = 0;
- dump[13] = 0;
- dump[14] = 0;
- dump[15] = 0;
-}
-
-/************************************************************
-
- Calc Parameters
-
-************************************************************/
-
-INLINE static e_uint32
-calc_eg_dphase (OPLL_SLOT * slot)
-{
-
- switch (slot->eg_mode)
- {
- case ATTACK:
- return dphaseARTable[slot->patch->AR][slot->rks];
-
- case DECAY:
- return dphaseDRTable[slot->patch->DR][slot->rks];
-
- case SUSHOLD:
- return 0;
-
- case SUSTINE:
- return dphaseDRTable[slot->patch->RR][slot->rks];
-
- case RELEASE:
- if (slot->sustine)
- return dphaseDRTable[5][slot->rks];
- else if (slot->patch->EG)
- return dphaseDRTable[slot->patch->RR][slot->rks];
- else
- return dphaseDRTable[7][slot->rks];
-
- case SETTLE:
- return dphaseDRTable[15][0];
-
- case FINISH:
- return 0;
-
- default:
- return 0;
- }
-}
-
-/*************************************************************
-
- OPLL internal interfaces
-
-*************************************************************/
-#define SLOT_BD1 12
-#define SLOT_BD2 13
-#define SLOT_HH 14
-#define SLOT_SD 15
-#define SLOT_TOM 16
-#define SLOT_CYM 17
-
-/* We will set this dinamically, but not sure if this affects playback */
-#if defined(ROCKBOX)
-INLINE static void
-UPDATE_PG(OPLL_SLOT * slot)
-{
- static const e_uint32 mltable[16] =
- { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
-
- slot->dphase = RATE_ADJUST (((slot->fnum * mltable[slot->patch->ML]) << slot->block) >> (20 - DP_BITS));
-}
-#else
-#define UPDATE_PG(S) (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch->ML]
-#endif
-
-#define UPDATE_TLL(S)\
-(((S)->type==0)?\
-((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch->TL][(S)->patch->KL]):\
-((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch->KL]))
-#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch->KR]
-#define UPDATE_WF(S) (S)->sintbl = waveform[(S)->patch->WF]
-#define UPDATE_EG(S) (S)->eg_dphase = calc_eg_dphase(S)
-#define UPDATE_ALL(S)\
- UPDATE_PG(S);\
- UPDATE_TLL(S);\
- UPDATE_RKS(S);\
- UPDATE_WF(S); \
- UPDATE_EG(S) /* EG should be updated last. */
-
-
-/* Slot key on */
-INLINE static void
-slotOn (OPLL_SLOT * slot)
-{
- slot->eg_mode = ATTACK;
- slot->eg_phase = 0;
- slot->phase = 0;
- UPDATE_EG(slot);
-}
-
-/* Slot key on without reseting the phase */
-INLINE static void
-slotOn2 (OPLL_SLOT * slot)
-{
- slot->eg_mode = ATTACK;
- slot->eg_phase = 0;
- UPDATE_EG(slot);
-}
-
-/* Slot key off */
-INLINE static void
-slotOff (OPLL_SLOT * slot)
-{
- if (slot->eg_mode == ATTACK)
- slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)), EG_BITS, EG_DP_BITS);
- slot->eg_mode = RELEASE;
- UPDATE_EG(slot);
-}
-
-/* Channel key on */
-INLINE static void
-keyOn (OPLL * opll, e_int32 i)
-{
- if (!opll->slot_on_flag[i * 2])
- slotOn (MOD(opll,i));
- if (!opll->slot_on_flag[i * 2 + 1])
- slotOn (CAR(opll,i));
- opll->key_status[i] = 1;
-}
-
-/* Channel key off */
-INLINE static void
-keyOff (OPLL * opll, e_int32 i)
-{
- if (opll->slot_on_flag[i * 2 + 1])
- slotOff (CAR(opll,i));
- opll->key_status[i] = 0;
-}
-
-INLINE static void
-keyOn_BD (OPLL * opll)
-{
- keyOn (opll, 6);
-}
-INLINE static void
-keyOn_SD (OPLL * opll)
-{
- if (!opll->slot_on_flag[SLOT_SD])
- slotOn (CAR(opll,7));
-}
-INLINE static void
-keyOn_TOM (OPLL * opll)
-{
- if (!opll->slot_on_flag[SLOT_TOM])
- slotOn (MOD(opll,8));
-}
-INLINE static void
-keyOn_HH (OPLL * opll)
-{
- if (!opll->slot_on_flag[SLOT_HH])
- slotOn2 (MOD(opll,7));
-}
-INLINE static void
-keyOn_CYM (OPLL * opll)
-{
- if (!opll->slot_on_flag[SLOT_CYM])
- slotOn2 (CAR(opll,8));
-}
-
-/* Drum key off */
-INLINE static void
-keyOff_BD (OPLL * opll)
-{
- keyOff (opll, 6);
-}
-INLINE static void
-keyOff_SD (OPLL * opll)
-{
- if (opll->slot_on_flag[SLOT_SD])
- slotOff (CAR(opll,7));
-}
-INLINE static void
-keyOff_TOM (OPLL * opll)
-{
- if (opll->slot_on_flag[SLOT_TOM])
- slotOff (MOD(opll,8));
-}
-INLINE static void
-keyOff_HH (OPLL * opll)
-{
- if (opll->slot_on_flag[SLOT_HH])
- slotOff (MOD(opll,7));
-}
-INLINE static void
-keyOff_CYM (OPLL * opll)
-{
- if (opll->slot_on_flag[SLOT_CYM])
- slotOff (CAR(opll,8));
-}
-
-/* Change a voice */
-INLINE static void
-setPatch (OPLL * opll, e_int32 i, e_int32 num)
-{
- opll->patch_number[i] = num;
- MOD(opll,i)->patch = &opll->patch[num * 2 + 0];
- CAR(opll,i)->patch = &opll->patch[num * 2 + 1];
-}
-
-/* Change a rhythm voice */
-INLINE static void
-setSlotPatch (OPLL_SLOT * slot, OPLL_PATCH * patch)
-{
- slot->patch = patch;
-}
-
-/* Set sustine parameter */
-INLINE static void
-setSustine (OPLL * opll, e_int32 c, e_int32 sustine)
-{
- CAR(opll,c)->sustine = sustine;
- if (MOD(opll,c)->type)
- MOD(opll,c)->sustine = sustine;
-}
-
-/* Volume : 6bit ( Volume register << 2 ) */
-INLINE static void
-setVolume (OPLL * opll, e_int32 c, e_int32 volume)
-{
- CAR(opll,c)->volume = volume;
-}
-
-INLINE static void
-setSlotVolume (OPLL_SLOT * slot, e_int32 volume)
-{
- slot->volume = volume;
-}
-
-/* Set F-Number ( fnum : 9bit ) */
-INLINE static void
-setFnumber (OPLL * opll, e_int32 c, e_int32 fnum)
-{
- CAR(opll,c)->fnum = fnum;
- MOD(opll,c)->fnum = fnum;
-}
-
-/* Set Block data (block : 3bit ) */
-INLINE static void
-setBlock (OPLL * opll, e_int32 c, e_int32 block)
-{
- CAR(opll,c)->block = block;
- MOD(opll,c)->block = block;
-}
-
-/* Change Rhythm Mode */
-INLINE static void
-update_rhythm_mode (OPLL * opll)
-{
- if (opll->patch_number[6] & 0x10)
- {
- if (!(opll->slot_on_flag[SLOT_BD2] | (opll->reg[0x0e] & 32)))
- {
- opll->slot[SLOT_BD1].eg_mode = FINISH;
- opll->slot[SLOT_BD2].eg_mode = FINISH;
- setPatch (opll, 6, opll->reg[0x36] >> 4);
- }
- }
- else if (opll->reg[0x0e] & 32)
- {
- opll->patch_number[6] = 16;
- opll->slot[SLOT_BD1].eg_mode = FINISH;
- opll->slot[SLOT_BD2].eg_mode = FINISH;
- setSlotPatch (&opll->slot[SLOT_BD1], &opll->patch[16 * 2 + 0]);
- setSlotPatch (&opll->slot[SLOT_BD2], &opll->patch[16 * 2 + 1]);
- }
-
- if (opll->patch_number[7] & 0x10)
- {
- if (!((opll->slot_on_flag[SLOT_HH] && opll->slot_on_flag[SLOT_SD]) | (opll->reg[0x0e] & 32)))
- {
- opll->slot[SLOT_HH].type = 0;
- opll->slot[SLOT_HH].eg_mode = FINISH;
- opll->slot[SLOT_SD].eg_mode = FINISH;
- setPatch (opll, 7, opll->reg[0x37] >> 4);
- }
- }
- else if (opll->reg[0x0e] & 32)
- {
- opll->patch_number[7] = 17;
- opll->slot[SLOT_HH].type = 1;
- opll->slot[SLOT_HH].eg_mode = FINISH;
- opll->slot[SLOT_SD].eg_mode = FINISH;
- setSlotPatch (&opll->slot[SLOT_HH], &opll->patch[17 * 2 + 0]);
- setSlotPatch (&opll->slot[SLOT_SD], &opll->patch[17 * 2 + 1]);
- }
-
- if (opll->patch_number[8] & 0x10)
- {
- if (!((opll->slot_on_flag[SLOT_CYM] && opll->slot_on_flag[SLOT_TOM]) | (opll->reg[0x0e] & 32)))
- {
- opll->slot[SLOT_TOM].type = 0;
- opll->slot[SLOT_TOM].eg_mode = FINISH;
- opll->slot[SLOT_CYM].eg_mode = FINISH;
- setPatch (opll, 8, opll->reg[0x38] >> 4);
- }
- }
- else if (opll->reg[0x0e] & 32)
- {
- opll->patch_number[8] = 18;
- opll->slot[SLOT_TOM].type = 1;
- opll->slot[SLOT_TOM].eg_mode = FINISH;
- opll->slot[SLOT_CYM].eg_mode = FINISH;
- setSlotPatch (&opll->slot[SLOT_TOM], &opll->patch[18 * 2 + 0]);
- setSlotPatch (&opll->slot[SLOT_CYM], &opll->patch[18 * 2 + 1]);
- }
-}
-
-INLINE static void
-update_key_status (OPLL * opll)
-{
- int ch;
-
- for (ch = 0; ch < 9; ch++)
- opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->reg[0x20 + ch]) & 0x10;
-
- if (opll->reg[0x0e] & 32)
- {
- opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e] & 0x10);
- opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e] & 0x10);
- opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e] & 0x08);
- opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e] & 0x01);
- opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e] & 0x04);
- opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e] & 0x02);
- }
-}
-
-void
-OPLL_copyPatch (OPLL * opll, e_int32 num, OPLL_PATCH * patch)
-{
- memcpy (&opll->patch[num], patch, sizeof (OPLL_PATCH));
-}
-
-/***********************************************************
-
- Initializing
-
-***********************************************************/
-
-static void
-OPLL_SLOT_reset (OPLL_SLOT * slot, int type)
-{
- slot->type = type;
- slot->sintbl = waveform[0];
- slot->phase = 0;
- slot->dphase = 0;
- slot->output[0] = 0;
- slot->output[1] = 0;
- slot->feedback = 0;
- slot->eg_mode = FINISH;
- slot->eg_phase = EG_DP_WIDTH;
- slot->eg_dphase = 0;
- slot->rks = 0;
- slot->tll = 0;
- slot->sustine = 0;
- slot->fnum = 0;
- slot->block = 0;
- slot->volume = 0;
- slot->pgout = 0;
- slot->egout = 0;
- slot->patch = &null_patch;
-}
-
-static void
-internal_refresh (void)
-{
-#if !defined(ROCKBOX)
- makeDphaseTable ();
-#endif
- makeDphaseARTable ();
- makeDphaseDRTable ();
- pm_dphase = (e_uint32) RATE_ADJUST ((int)(PM_SPEED * PM_DP_WIDTH) / (clk / 72));
- am_dphase = (e_uint32) RATE_ADJUST ((int)(AM_SPEED * AM_DP_WIDTH) / (clk / 72));
-}
-
-static void
-maketables (e_uint32 c, e_uint32 r)
-{
- if (c != clk)
- {
- clk = c;
-#ifdef EMU2413_CALCUL_TABLES
- makePmTable ();
- makeAmTable ();
- makeAdjustTable ();
-#endif
- makeDB2LinTable ();
- makeTllTable ();
- makeRksTable ();
- makeSinTable ();
- makeDefaultPatch ();
- }
-
- if (r != rate)
- {
- rate = r;
- internal_refresh ();
- }
-}
-
-void
-OPLL_new (OPLL *opll, e_uint32 clk, e_uint32 rate)
-{
- e_int32 i;
-
- maketables (clk, rate);
-
- memset(opll, 0, sizeof (OPLL));
- for (i = 0; i < 19 * 2; i++)
- memcpy(&opll->patch[i],&null_patch,sizeof(OPLL_PATCH));
-
- opll->mask = 0;
-
- OPLL_reset (opll);
- OPLL_reset_patch (opll, 0);
-}
-
-
-void
-OPLL_delete (OPLL * opll)
-{
- (void) opll;
-}
-
-
-/* Reset patch datas by system default. */
-void
-OPLL_reset_patch (OPLL * opll, e_int32 type)
-{
- e_int32 i;
-
- for (i = 0; i < 19 * 2; i++)
- OPLL_copyPatch (opll, i, &default_patch[type % OPLL_TONE_NUM][i]);
-}
-
-/* Reset whole of OPLL except patch datas. */
-void
-OPLL_reset (OPLL * opll)
-{
- e_int32 i;
-
- if (!opll)
- return;
-
- opll->adr = 0;
- opll->out = 0;
-
- opll->pm_phase = 0;
- opll->am_phase = 0;
-
- opll->noise_seed = 0xffff;
- opll->mask = 0;
-
- for (i = 0; i <18; i++)
- OPLL_SLOT_reset(&opll->slot[i], i%2);
-
- for (i = 0; i < 9; i++)
- {
- opll->key_status[i] = 0;
- setPatch (opll, i, 0);
- }
-
- for (i = 0; i < 0x40; i++)
- OPLL_writeReg (opll, i, 0);
-
-#ifndef EMU2413_COMPACTION
- opll->realstep = (e_uint32) ((1 << 31) / rate);
- opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72));
- opll->oplltime = 0;
- for (i = 0; i < 14; i++)
- opll->pan[i] = 2;
- opll->sprev[0] = opll->sprev[1] = 0;
- opll->snext[0] = opll->snext[1] = 0;
-#endif
-}
-
-/* Force Refresh (When external program changes some parameters). */
-void
-OPLL_forceRefresh (OPLL * opll)
-{
- e_int32 i;
-
- if (opll == NULL)
- return;
-
- for (i = 0; i < 9; i++)
- setPatch(opll,i,opll->patch_number[i]);
-
- for (i = 0; i < 18; i++)
- {
- UPDATE_PG (&opll->slot[i]);
- UPDATE_RKS (&opll->slot[i]);
- UPDATE_TLL (&opll->slot[i]);
- UPDATE_WF (&opll->slot[i]);
- UPDATE_EG (&opll->slot[i]);
- }
-}
-
-void
-OPLL_set_rate (OPLL * opll, e_uint32 r)
-{
- if (rate == r) return;
- if (opll->quality)
- rate = 49716;
- else
- rate = r;
- internal_refresh ();
- rate = r;
-}
-
-void
-OPLL_set_quality (OPLL * opll, e_uint32 q)
-{
- opll->quality = q;
- OPLL_set_rate (opll, rate);
-}
-
-/*********************************************************
-
- Generate wave data
-
-*********************************************************/
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
-#if ( SLOT_AMP_BITS - PG_BITS ) > 0
-#define wave2_2pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
-#else
-#define wave2_2pi(e) ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
-#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
-#define wave2_4pi(e) (e)
-#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
-#define wave2_4pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
-#else
-#define wave2_4pi(e) ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
-#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
-#define wave2_8pi(e) (e)
-#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
-#define wave2_8pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
-#else
-#define wave2_8pi(e) ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
-#endif
-
-/* Update AM, PM unit */
-INLINE static void
-update_ampm (OPLL * opll)
-{
- opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1);
- opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1);
- opll->lfo_am = AMTABLE(HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS));
- opll->lfo_pm = PMTABLE(HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS));
-}
-
-/* PG */
-INLINE static void
-calc_phase (OPLL_SLOT * slot, e_int32 lfo)
-{
- if (slot->patch->PM)
- slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS;
- else
- slot->phase += slot->dphase;
-
- slot->phase &= (DP_WIDTH - 1);
-
- slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS);
-}
-
-/* Update Noise unit */
-INLINE static void
-update_noise (OPLL * opll)
-{
- if(opll->noise_seed&1) opll->noise_seed ^= 0x8003020;
- opll->noise_seed >>= 1;
-}
-
-/* EG */
-INLINE static void
-calc_envelope (OPLL_SLOT * slot, e_int32 lfo)
-{
-#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
-
- static e_uint32 SL[16] = {
- S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
- S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
- };
-
- e_uint32 egout;
-
- switch (slot->eg_mode)
- {
- case ATTACK:
- egout = AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS));
- slot->eg_phase += slot->eg_dphase;
- if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch->AR==15))
- {
- egout = 0;
- slot->eg_phase = 0;
- slot->eg_mode = DECAY;
- UPDATE_EG (slot);
- }
- break;
-
- case DECAY:
- egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
- slot->eg_phase += slot->eg_dphase;
- if (slot->eg_phase >= SL[slot->patch->SL])
- {
- if (slot->patch->EG)
- {
- slot->eg_phase = SL[slot->patch->SL];
- slot->eg_mode = SUSHOLD;
- UPDATE_EG (slot);
- }
- else
- {
- slot->eg_phase = SL[slot->patch->SL];
- slot->eg_mode = SUSTINE;
- UPDATE_EG (slot);
- }
- }
- break;
-
- case SUSHOLD:
- egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
- if (slot->patch->EG == 0)
- {
- slot->eg_mode = SUSTINE;
- UPDATE_EG (slot);
- }
- break;
-
- case SUSTINE:
- case RELEASE:
- egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
- slot->eg_phase += slot->eg_dphase;
- if (egout >= (1 << EG_BITS))
- {
- slot->eg_mode = FINISH;
- egout = (1 << EG_BITS) - 1;
- }
- break;
-
- case SETTLE:
- egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
- slot->eg_phase += slot->eg_dphase;
- if (egout >= (1 << EG_BITS))
- {
- slot->eg_mode = ATTACK;
- egout = (1 << EG_BITS) - 1;
- UPDATE_EG(slot);
- }
- break;
-
- case FINISH:
- egout = (1 << EG_BITS) - 1;
- break;
-
- default:
- egout = (1 << EG_BITS) - 1;
- break;
- }
-
- if (slot->patch->AM)
- egout = EG2DB (egout + slot->tll) + lfo;
- else
- egout = EG2DB (egout + slot->tll);
-
- if (egout >= DB_MUTE)
- egout = DB_MUTE - 1;
-
- slot->egout = egout | 3;
-}
-
-/* CARRIOR */
-INLINE static e_int32
-calc_slot_car (OPLL_SLOT * slot, e_int32 fm)
-{
- if (slot->egout >= (DB_MUTE - 1))
- {
- slot->output[0] = 0;
- }
- else
- {
- slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
- }
-
- slot->output[1] = (slot->output[1] + slot->output[0]) >> 1;
- return slot->output[1];
-}
-
-/* MODULATOR */
-INLINE static e_int32
-calc_slot_mod (OPLL_SLOT * slot)
-{
- e_int32 fm;
-
- slot->output[1] = slot->output[0];
-
- if (slot->egout >= (DB_MUTE - 1))
- {
- slot->output[0] = 0;
- }
- else if (slot->patch->FB != 0)
- {
- fm = wave2_4pi (slot->feedback) >> (7 - slot->patch->FB);
- slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
- }
- else
- {
- slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
- }
-
- slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
-
- return slot->feedback;
-
-}
-
-/* TOM */
-INLINE static e_int32
-calc_slot_tom (OPLL_SLOT * slot)
-{
- if (slot->egout >= (DB_MUTE - 1))
- return 0;
-
- return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
-
-}
-
-/* SNARE */
-INLINE static e_int32
-calc_slot_snare (OPLL_SLOT * slot, e_uint32 noise)
-{
- if(slot->egout>=(DB_MUTE-1))
- return 0;
-
- if(BIT(slot->pgout,7))
- return DB2LIN_TABLE[(noise?DB_POS(0):DB_POS(15))+slot->egout];
- else
- return DB2LIN_TABLE[(noise?DB_NEG(0):DB_NEG(15))+slot->egout];
-}
-
-/*
- TOP-CYM
- */
-INLINE static e_int32
-calc_slot_cym (OPLL_SLOT * slot, e_uint32 pgout_hh)
-{
- e_uint32 dbout;
-
- if (slot->egout >= (DB_MUTE - 1))
- return 0;
- else if(
- /* the same as fmopl.c */
- ((BIT(pgout_hh,PG_BITS-8)^BIT(pgout_hh,PG_BITS-1))|BIT(pgout_hh,PG_BITS-7)) ^
- /* different from fmopl.c */
- (BIT(slot->pgout,PG_BITS-7)&!BIT(slot->pgout,PG_BITS-5))
- )
- dbout = DB_NEG(3);
- else
- dbout = DB_POS(3);
-
- return DB2LIN_TABLE[dbout + slot->egout];
-}
-
-/*
- HI-HAT
-*/
-INLINE static e_int32
-calc_slot_hat (OPLL_SLOT *slot, e_int32 pgout_cym, e_uint32 noise)
-{
- e_uint32 dbout;
-
- if (slot->egout >= (DB_MUTE - 1))
- return 0;
- else if(
- /* the same as fmopl.c */
- ((BIT(slot->pgout,PG_BITS-8)^BIT(slot->pgout,PG_BITS-1))|BIT(slot->pgout,PG_BITS-7)) ^
- /* different from fmopl.c */
- (BIT(pgout_cym,PG_BITS-7)&!BIT(pgout_cym,PG_BITS-5))
- )
- {
- if(noise)
- dbout = DB_NEG(12);
- else
- dbout = DB_NEG(24);
- }
- else
- {
- if(noise)
- dbout = DB_POS(12);
- else
- dbout = DB_POS(24);
- }
-
- return DB2LIN_TABLE[dbout + slot->egout];
-}
-
-static e_int16
-calc (OPLL * opll) EMU2413_CALC_ICODE;
-static e_int16
-calc (OPLL * opll)
-{
- e_int32 i;
-
- update_ampm (opll);
- update_noise (opll);
-
- for (i = 0; i < 18; i++)
- {
- calc_phase(&opll->slot[i],opll->lfo_pm);
- calc_envelope(&opll->slot[i],opll->lfo_am);
- }
-
- e_uint32 channel_mask = opll->mask;
- for (i = 0; i < 9; i++) {
- if (CAR(opll,i)->eg_mode != FINISH)
- channel_mask |= (1 << i);
- }
-
- e_int32 mix = 0;
-
- /* CH6 */
- if (opll->patch_number[6] & 0x10) {
- if (channel_mask & OPLL_MASK_CH (6)) {
- mix += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
- channel_mask &= ~(1 << 6);
- }
- }
-
- /* CH7 */
- if (opll->patch_number[7] & 0x10) {
- if (MOD(opll,7)->eg_mode != FINISH)
- mix += calc_slot_hat (MOD(opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
- if (channel_mask & OPLL_MASK_SD) {
- mix -= calc_slot_snare (CAR(opll,7), opll->noise_seed&1);
- channel_mask &= ~OPLL_MASK_SD;
- }
- }
-
- /* CH8 */
- if (opll->patch_number[8] & 0x10) {
- if (MOD(opll,8)->eg_mode != FINISH)
- mix += calc_slot_tom (MOD(opll,8));
- if (channel_mask & OPLL_MASK_CYM) {
- mix -= calc_slot_cym (CAR(opll,8), MOD(opll,7)->pgout);
- channel_mask &= ~OPLL_MASK_CYM;
- }
- }
-
- mix <<= 1;
-
- opll->current_mask = channel_mask;
- for (i = 0; channel_mask; channel_mask >>= 1, ++i) {
- if (channel_mask & 1) {
- mix += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i)));
- }
- }
-
- return (e_int16) mix << 3;
-}
-
-void
-OPLL_set_internal_mute(OPLL * opll, e_uint32 mute)
-{
- opll->internal_mute = mute;
-}
-
-e_uint32
-OPLL_is_internal_muted(OPLL * opll)
-{
- return opll->internal_mute;
-}
-
-static e_uint32
-check_mute_helper(OPLL * opll)
-{
- for (int i = 0; i < 6; i++) {
- /* if (ch[i].car.eg_mode != FINISH) return 0; */
- if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
- }
-
- if (!(opll->reg[0x0e] & 0x20)) {
- for(int i = 6; i < 9; i++) {
- /* if (ch[i].car.eg_mode != FINISH) return 0; */
- if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
- }
- } else {
- /* if (ch[6].car.eg_mode != FINISH) return false;
- if (ch[7].mod.eg_mode != FINISH) return false;
- if (ch[7].car.eg_mode != FINISH) return false;
- if (ch[8].mod.eg_mode != FINISH) return false;
- if (ch[8].car.eg_mode != FINISH) return false; */
- if (!(opll->current_mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH)) return 0;
- if (!(opll->current_mask & OPLL_MASK_CH (7)) && (MOD(opll,7)->eg_mode != FINISH)) return 0;
- if (!(opll->current_mask & OPLL_MASK_CH (7)) && (CAR(opll,7)->eg_mode != FINISH)) return 0;
- if (!(opll->current_mask & OPLL_MASK_CH (8)) && (MOD(opll,8)->eg_mode != FINISH)) return 0;
- if (!(opll->current_mask & OPLL_MASK_CH (8)) && (CAR(opll,8)->eg_mode != FINISH)) return 0;
- }
-
- return 1; /* nothing is playing, then mute */
-}
-
-static void
-check_mute(OPLL * opll)
-{
- OPLL_set_internal_mute (opll, check_mute_helper (opll));
-}
-
-EMU2413_API e_int16 *OPLL_update_buffer(OPLL * opll, e_uint32 length)
-{
- e_int16* buf = opll->buffer;
- while (length--) {
- *(buf++) = calc (opll);
- }
- check_mute (opll);
-
- return opll->buffer;
-}
-
-#ifdef EMU2413_COMPACTION
-e_int16
-OPLL_calc (OPLL * opll)
-{
- return calc (opll);
-}
-#else
-e_int16
-OPLL_calc (OPLL * opll)
-{
- if (!opll->quality)
- return calc (opll);
-
- while (opll->realstep > opll->oplltime)
- {
- opll->oplltime += opll->opllstep;
- opll->prev = opll->next;
- opll->next = calc (opll);
- }
-
- opll->oplltime -= opll->realstep;
- opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime)
- + (double) opll->prev * opll->oplltime) / opll->opllstep);
-
- return (e_int16) opll->out;
-}
-#endif
-
-e_uint32
-OPLL_setMask (OPLL * opll, e_uint32 mask)
-{
- e_uint32 ret;
-
- if (opll)
- {
- ret = opll->mask;
- opll->mask = mask;
- return ret;
- }
- else
- return 0;
-}
-
-e_uint32
-OPLL_toggleMask (OPLL * opll, e_uint32 mask)
-{
- e_uint32 ret;
-
- if (opll)
- {
- ret = opll->mask;
- opll->mask ^= mask;
- return ret;
- }
- else
- return 0;
-}
-
-/****************************************************
-
- I/O Ctrl
-
-*****************************************************/
-
-void
-OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
-{
- e_int32 i, v, ch;
-
- data = data & 0xff;
- reg = reg & 0x3f;
- opll->reg[reg] = (e_uint8) data;
-
- switch (reg)
- {
- case 0x00:
- opll->patch[0].AM = (data >> 7) & 1;
- opll->patch[0].PM = (data >> 6) & 1;
- opll->patch[0].EG = (data >> 5) & 1;
- opll->patch[0].KR = (data >> 4) & 1;
- opll->patch[0].ML = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_PG (MOD(opll,i));
- UPDATE_RKS (MOD(opll,i));
- UPDATE_EG (MOD(opll,i));
- }
- }
- break;
-
- case 0x01:
- opll->patch[1].AM = (data >> 7) & 1;
- opll->patch[1].PM = (data >> 6) & 1;
- opll->patch[1].EG = (data >> 5) & 1;
- opll->patch[1].KR = (data >> 4) & 1;
- opll->patch[1].ML = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_PG (CAR(opll,i));
- UPDATE_RKS (CAR(opll,i));
- UPDATE_EG (CAR(opll,i));
- }
- }
- break;
-
- case 0x02:
- opll->patch[0].KL = (data >> 6) & 3;
- opll->patch[0].TL = (data) & 63;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_TLL(MOD(opll,i));
- }
- }
- break;
-
- case 0x03:
- opll->patch[1].KL = (data >> 6) & 3;
- opll->patch[1].WF = (data >> 4) & 1;
- opll->patch[0].WF = (data >> 3) & 1;
- opll->patch[0].FB = (data) & 7;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_WF(MOD(opll,i));
- UPDATE_WF(CAR(opll,i));
- }
- }
- break;
-
- case 0x04:
- opll->patch[0].AR = (data >> 4) & 15;
- opll->patch[0].DR = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_EG (MOD(opll,i));
- }
- }
- break;
-
- case 0x05:
- opll->patch[1].AR = (data >> 4) & 15;
- opll->patch[1].DR = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_EG(CAR(opll,i));
- }
- }
- break;
-
- case 0x06:
- opll->patch[0].SL = (data >> 4) & 15;
- opll->patch[0].RR = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_EG (MOD(opll,i));
- }
- }
- break;
-
- case 0x07:
- opll->patch[1].SL = (data >> 4) & 15;
- opll->patch[1].RR = (data) & 15;
- for (i = 0; i < 9; i++)
- {
- if (opll->patch_number[i] == 0)
- {
- UPDATE_EG (CAR(opll,i));
- }
- }
- break;
-
- case 0x0e:
- update_rhythm_mode (opll);
- if (data & 32)
- {
- if (data & 0x10)
- keyOn_BD (opll);
- else
- keyOff_BD (opll);
- if (data & 0x8)
- keyOn_SD (opll);
- else
- keyOff_SD (opll);
- if (data & 0x4)
- keyOn_TOM (opll);
- else
- keyOff_TOM (opll);
- if (data & 0x2)
- keyOn_CYM (opll);
- else
- keyOff_CYM (opll);
- if (data & 0x1)
- keyOn_HH (opll);
- else
- keyOff_HH (opll);
- }
- update_key_status (opll);
-
- UPDATE_ALL (MOD(opll,6));
- UPDATE_ALL (CAR(opll,6));
- UPDATE_ALL (MOD(opll,7));
- UPDATE_ALL (CAR(opll,7));
- UPDATE_ALL (MOD(opll,8));
- UPDATE_ALL (CAR(opll,8));
-
- break;
-
- case 0x0f:
- break;
-
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- case 0x18:
- ch = reg - 0x10;
- setFnumber (opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));
- UPDATE_ALL (MOD(opll,ch));
- UPDATE_ALL (CAR(opll,ch));
- break;
-
- case 0x20:
- case 0x21:
- case 0x22:
- case 0x23:
- case 0x24:
- case 0x25:
- case 0x26:
- case 0x27:
- case 0x28:
- ch = reg - 0x20;
- setFnumber (opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);
- setBlock (opll, ch, (data >> 1) & 7);
- setSustine (opll, ch, (data >> 5) & 1);
- if (data & 0x10)
- keyOn (opll, ch);
- else
- keyOff (opll, ch);
- UPDATE_ALL (MOD(opll,ch));
- UPDATE_ALL (CAR(opll,ch));
- update_key_status (opll);
- update_rhythm_mode (opll);
- break;
-
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- i = (data >> 4) & 15;
- v = data & 15;
- if ((opll->reg[0x0e] & 32) && (reg >= 0x36))
- {
- switch (reg)
- {
- case 0x37:
- setSlotVolume (MOD(opll,7), i << 2);
- break;
- case 0x38:
- setSlotVolume (MOD(opll,8), i << 2);
- break;
- default:
- break;
- }
- }
- else
- {
- setPatch (opll, reg - 0x30, i);
- }
- setVolume (opll, reg - 0x30, v << 2);
- UPDATE_ALL (MOD(opll,reg - 0x30));
- UPDATE_ALL (CAR(opll,reg - 0x30));
- break;
-
- default:
- break;
-
- }
-}
-
-void
-OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val)
-{
- if (adr & 1)
- OPLL_writeReg (opll, opll->adr, val);
- else
- opll->adr = val;
-}
-
-e_uint32
-OPLL_read(OPLL * opll, e_uint32 a)
-{
- if( !(a&1) )
- {
- /* status port */
- return opll->status;
- }
- return 0xff;
-}
-
-#ifndef EMU2413_COMPACTION
-/* STEREO MODE (OPT) */
-void
-OPLL_set_pan (OPLL * opll, e_uint32 ch, e_uint32 pan)
-{
- opll->pan[ch & 15] = pan & 3;
-}
-
-static void
-calc_stereo (OPLL * opll, e_int32 out[2])
-{
- e_int32 b[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
- e_int32 r[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
- e_int32 i;
-
- update_ampm (opll);
- update_noise (opll);
-
- for(i=0;i<18;i++)
- {
- calc_phase(&opll->slot[i],opll->lfo_pm);
- calc_envelope(&opll->slot[i],opll->lfo_am);
- }
-
- for (i = 0; i < 6; i++)
- if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
- b[opll->pan[i]] += calc_slot_car (CAR(opll,i), calc_slot_mod (MOD(opll,i)));
-
-
- if (opll->patch_number[6] <= 15)
- {
- if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
- b[opll->pan[6]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
- }
- else
- {
- if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
- r[opll->pan[9]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
- }
-
- if (opll->patch_number[7] <= 15)
- {
- if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR (opll,7)->eg_mode != FINISH))
- b[opll->pan[7]] += calc_slot_car (CAR (opll,7), calc_slot_mod (MOD (opll,7)));
- }
- else
- {
- if (!(opll->mask & OPLL_MASK_HH) && (MOD (opll,7)->eg_mode != FINISH))
- r[opll->pan[10]] += calc_slot_hat (MOD (opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
- if (!(opll->mask & OPLL_MASK_SD) && (CAR (opll,7)->eg_mode != FINISH))
- r[opll->pan[11]] -= calc_slot_snare (CAR (opll,7), opll->noise_seed&1);
- }
-
- if (opll->patch_number[8] <= 15)
- {
- if (!(opll->mask & OPLL_MASK_CH (8)) && (CAR (opll,8)->eg_mode != FINISH))
- b[opll->pan[8]] += calc_slot_car (CAR (opll,8), calc_slot_mod (MOD (opll,8)));
- }
- else
- {
- if (!(opll->mask & OPLL_MASK_TOM) && (MOD (opll,8)->eg_mode != FINISH))
- r[opll->pan[12]] += calc_slot_tom (MOD (opll,8));
- if (!(opll->mask & OPLL_MASK_CYM) && (CAR (opll,8)->eg_mode != FINISH))
- r[opll->pan[13]] -= calc_slot_cym (CAR (opll,8), MOD(opll,7)->pgout);
- }
-
- out[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) <<3;
- out[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) <<3;
-}
-
-void
-OPLL_calc_stereo (OPLL * opll, e_int32 out[2])
-{
- if (!opll->quality)
- {
- calc_stereo (opll, out);
- return;
- }
-
- while (opll->realstep > opll->oplltime)
- {
- opll->oplltime += opll->opllstep;
- opll->sprev[0] = opll->snext[0];
- opll->sprev[1] = opll->snext[1];
- calc_stereo (opll, opll->snext);
- }
-
- opll->oplltime -= opll->realstep;
- out[0] = (e_int16) (((double) opll->snext[0] * (opll->opllstep - opll->oplltime)
- + (double) opll->sprev[0] * opll->oplltime) / opll->opllstep);
- out[1] = (e_int16) (((double) opll->snext[1] * (opll->opllstep - opll->oplltime)
- + (double) opll->sprev[1] * opll->oplltime) / opll->opllstep);
-}
-#endif /* EMU2413_COMPACTION */
+/***********************************************************************************
+
+ emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
+
+ 2001 01-08 : Version 0.10 -- 1st version.
+ 2001 01-15 : Version 0.20 -- semi-public version.
+ 2001 01-16 : Version 0.30 -- 1st public version.
+ 2001 01-17 : Version 0.31 -- Fixed bassdrum problem.
+ : Version 0.32 -- LPF implemented.
+ 2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method.
+ -- Fixed the LFO bug.
+ 2001 01-24 : Version 0.35 -- Fixed the drum problem,
+ support undocumented EG behavior.
+ 2001 02-02 : Version 0.38 -- Improved the performance.
+ Fixed the hi-hat and cymbal model.
+ Fixed the default percussive datas.
+ Noise reduction.
+ Fixed the feedback problem.
+ 2001 03-03 : Version 0.39 -- Fixed some drum bugs.
+ Improved the performance.
+ 2001 03-04 : Version 0.40 -- Improved the feedback.
+ Change the default table size.
+ Clock and Rate can be changed during play.
+ 2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone.
+ Added VRC7 patch (OPLL_reset_patch is changed).
+ Fixed OPLL_reset() bug.
+ Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask.
+ Added OPLL_writeIO.
+ 2001 09-28 : Version 0.51 -- Removed the noise table.
+ 2002 01-28 : Version 0.52 -- Added Stereo mode.
+ 2002 02-07 : Version 0.53 -- Fixed some drum bugs.
+ 2002 02-20 : Version 0.54 -- Added the best quality mode.
+ 2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close.
+ 2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas.
+ 2004 04-10 : Version 0.61 -- Added YMF281B tone (defined by Chabin).
+
+ 2011 03-22 : --------------- Modified by gama to use precalculated tables.
+
+ References:
+ fmopl.c -- 1999,2000 written by Tatsuyuki Satoh (MAME development).
+ fmopl.c(fixed) -- (C) 2002 Jarek Burczynski.
+ s_opl.c -- 2001 written by Mamiya (NEZplug development).
+ fmgen.cpp -- 1999,2000 written by cisc.
+ fmpac.ill -- 2000 created by NARUTO.
+ MSX-Datapack
+ YMU757 data sheet
+ YM2143 data sheet
+
+**************************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "emu2413.h"
+
+#include "emutables.h"
+#if !defined(ROCKBOX)
+ #define EMU2413_CALCUL_TABLES
+#else
+ #define EMU2413_COMPACTION
+ #include "emutables.h"
+#endif
+
+#if defined(EMU2413_COMPACTION) && !defined(ROCKBOX)
+#define OPLL_TONE_NUM 1
+static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
+ {
+#include "2413tone.h"
+ }
+};
+#else
+#define OPLL_TONE_NUM 3
+static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
+ {
+#include "2413tone.h"
+ },
+ {
+#include "vrc7tone.h"
+ },
+ {
+#include "281btone.h"
+ }
+};
+#endif
+
+/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.) */
+#define PG_BITS 9
+#define PG_WIDTH (1<<PG_BITS)
+
+/* Phase increment counter */
+#define DP_BITS 18
+#define DP_WIDTH (1<<DP_BITS)
+#define DP_BASE_BITS (DP_BITS - PG_BITS)
+
+/* Dynamic range (Accuracy of sin table) */
+#define DB_PREC 48
+#define DB_BITS 8
+#define DB_STEP ((double)DB_PREC/(1<<DB_BITS))
+#define DB_MUTE (1<<DB_BITS)
+
+/* Dynamic range of envelope */
+#define EG_STEP 0.375
+#define EG_BITS 7
+#define EG_MUTE (1<<EG_BITS)
+
+/* Dynamic range of total level */
+#define TL_STEP 0.75
+#define TL_BITS 6
+#define TL_MUTE (1<<TL_BITS)
+
+/* Dynamic range of sustine level */
+#define SL_STEP 3.0
+#define SL_BITS 4
+#define SL_MUTE (1<<SL_BITS)
+
+#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
+#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
+#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
+
+#define DB_POS(x) (x*DB_MUTE/DB_PREC)
+#define DB_NEG(x) (DB_MUTE+DB_MUTE+x*DB_MUTE/DB_PREC)
+
+/* Bits for liner value */
+#define DB2LIN_AMP_BITS 8
+#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
+
+/* Bits for envelope phase incremental counter */
+#define EG_DP_BITS 22
+#define EG_DP_WIDTH (1<<EG_DP_BITS)
+
+/* Bits for Pitch and Amp modulator */
+#define PM_PG_BITS 8
+#define PM_PG_WIDTH (1<<PM_PG_BITS)
+#define PM_DP_BITS 16
+#define PM_DP_WIDTH (1<<PM_DP_BITS)
+#define AM_PG_BITS 8
+#define AM_PG_WIDTH (1<<AM_PG_BITS)
+#define AM_DP_BITS 16
+#define AM_DP_WIDTH (1<<AM_DP_BITS)
+
+/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
+#define PM_AMP_BITS 8
+#define PM_AMP (1<<PM_AMP_BITS)
+
+/* PM speed(Hz) and depth(cent) */
+#define PM_SPEED 6.4
+#define PM_DEPTH 13.75
+
+/* AM speed(Hz) and depth(dB) */
+#define AM_SPEED 3.6413
+#define AM_DEPTH 4.875
+
+/* Cut the lower b bit(s) off. */
+#define HIGHBITS(c,b) ((c)>>(b))
+
+/* Leave the lower b bit(s). */
+#define LOWBITS(c,b) ((c)&((1<<(b))-1))
+
+/* Expand x which is s bits to d bits. */
+#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s)))
+
+/* Expand x which is s bits to d bits and fill expanded bits '1' */
+#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
+
+/* Adjust envelope speed which depends on sampling rate. */
+#define RATE_ADJUST(x) (rate==49716?(e_uint32)x:(e_uint32)(((long long)(x)*clk/rate+36)/72))
+
+#define MOD(o,x) (&(o)->slot[(x)<<1])
+#define CAR(o,x) (&(o)->slot[((x)<<1)|1])
+
+#define BIT(s,b) (((s)>>(b))&1)
+
+/* Input clock */
+static e_uint32 clk = 844451141;
+/* Sampling rate */
+static e_uint32 rate = 3354932;
+
+/* WaveTable for each envelope amp */
+static e_uint16 fullsintable[PG_WIDTH];
+static e_uint16 halfsintable[PG_WIDTH];
+
+static e_uint16 *waveform[2] = { fullsintable, halfsintable };
+
+/* LFO Table */
+#ifdef EMU2413_CALCUL_TABLES
+ static e_int32 pmtable[PM_PG_WIDTH];
+ static e_int32 amtable[AM_PG_WIDTH];
+ #define PMTABLE(x) pmtable[x]
+ #define AMTABLE(x) amtable[x]
+#else
+ #define PMTABLE(x) (e_int32)pm_coeff[x]
+ #if (PM_PG_WIDTH != 256)
+ #error PM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
+ #endif
+ #define AMTABLE(x) (e_int32)am_coeff[x]
+ #if (AM_PG_WIDTH != 256)
+ #error AM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
+ #endif
+#endif
+
+/* Phase delta for LFO */
+static e_uint32 pm_dphase;
+static e_uint32 am_dphase;
+
+/* dB to Liner table */
+static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2];
+
+/* Liner to Log curve conversion table (for Attack rate). */
+#ifdef EMU2413_CALCUL_TABLES
+ static e_uint16 ar_adjust_table[1 << EG_BITS];
+ #define AR_ADJUST_TABLE(x) ar_adjust_table[x]
+#else
+ #define AR_ADJUST_TABLE(x) ar_adjust_coeff[x]
+ #if (EG_BITS != 7)
+ #error EG_BITS must be set to 7 if EMU2413_CALCUL_TABLES is not defined
+ #endif
+#endif
+
+/* Empty voice data */
+static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/* Basic voice Data */
+static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];
+
+/* Definition of envelope mode */
+enum OPLL_EG_STATE
+{ READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH };
+
+/* Phase incr table for Attack */
+static e_uint32 dphaseARTable[16][16];
+/* Phase incr table for Decay and Release */
+static e_uint32 dphaseDRTable[16][16];
+
+/* KSL + TL Table */
+e_uint8 tllTable[16][8][1 << TL_BITS][4];
+static e_int32 rksTable[2][8][2];
+
+/* We may not have too much SRAM in rockbox */
+#if !defined(ROCKBOX)
+/* Phase incr table for PG */
+static e_uint32 dphaseTable[512][8][16];
+#endif
+
+/***************************************************
+
+ Create tables
+
+****************************************************/
+#ifdef EMU2413_CALCUL_TABLES
+INLINE static e_int32
+Min (e_int32 i, e_int32 j)
+{
+ if (i < j)
+ return i;
+ else
+ return j;
+}
+
+/* Table for AR to LogCurve. */
+static void
+makeAdjustTable (void)
+{
+ e_int32 i;
+
+ ar_adjust_table[0] = (1 << EG_BITS) - 1;
+ for (i = 1; i < (1<<EG_BITS); i++)
+ ar_adjust_table[i] = (e_uint16) ((double) (1<<EG_BITS)-1 - ((1<<EG_BITS)-1)*log(i)/log(127));
+}
+#endif
+
+/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
+static void
+makeDB2LinTable (void)
+{
+ e_int32 i;
+ for (i = 0; i < DB_MUTE + DB_MUTE; i++)
+ {
+ #ifdef EMU2413_CALCUL_TABLES
+ DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
+ #else
+ DB2LIN_TABLE[i] = db2lin_coeff[i];
+ #endif
+ if (i >= DB_MUTE) DB2LIN_TABLE[i] = 0;
+ DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]);
+ }
+}
+
+#ifdef EMU2413_CALCUL_TABLES
+/* Liner(+0.0 - +1.0) to dB((1<<DB_BITS) - 1 -- 0) */
+static e_int32
+lin2db (double d)
+{
+ if (d == 0)
+ return (DB_MUTE - 1);
+ else
+ return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1); /* 0 -- 127 */
+}
+#endif
+
+/* Sin Table */
+static void
+makeSinTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < PG_WIDTH / 4; i++)
+ #ifdef EMU2413_CALCUL_TABLES
+ fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
+ #else
+ fullsintable[i] = sin_coeff[i];
+ #endif
+
+ for (i = 0; i < PG_WIDTH / 4; i++)
+ {
+ fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
+ }
+
+ for (i = 0; i < PG_WIDTH / 2; i++)
+ {
+ fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
+ }
+
+ for (i = 0; i < PG_WIDTH / 2; i++)
+ halfsintable[i] = fullsintable[i];
+ for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
+ halfsintable[i] = fullsintable[0];
+}
+
+#ifdef EMU2413_CALCUL_TABLES
+static double saw(double phase)
+{
+ if(phase <= PI/2)
+ return phase * 2 / PI ;
+ else if(phase <= PI*3/2)
+ return 2.0 - ( phase * 2 / PI );
+ else
+ return -4.0 + phase * 2 / PI;
+}
+
+/* Table for Pitch Modulator */
+static void
+makePmTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < PM_PG_WIDTH; i++)
+ /* pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200)); */
+ pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * saw (2.0 * PI * i / PM_PG_WIDTH) / 1200));
+}
+
+/* Table for Amp Modulator */
+static void
+makeAmTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < AM_PG_WIDTH; i++)
+ /* amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH))); */
+ amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + saw (2.0 * PI * i / PM_PG_WIDTH)));
+}
+#endif
+
+#if !defined(ROCKBOX)
+/* Phase increment counter table */
+static void
+makeDphaseTable (void)
+{
+ e_uint32 fnum, block, ML;
+ e_uint32 mltable[16] =
+ { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
+
+ for (fnum = 0; fnum < 512; fnum++)
+ for (block = 0; block < 8; block++)
+ for (ML = 0; ML < 16; ML++)
+ dphaseTable[fnum][block][ML] = RATE_ADJUST (((fnum * mltable[ML]) << block) >> (20 - DP_BITS));
+}
+#endif
+
+static void
+makeTllTable (void)
+{
+/* Multiplication owith 8 to have an integer result. This allows to remove floating point operation. */
+#define dB2(x) (int)((x)*2*8)
+
+ static int kltable[16] = {
+ dB2 ( 0.000), dB2 ( 9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
+ dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
+ };
+
+ e_int32 tmp;
+ e_int32 fnum, block, TL, KL;
+
+ for (fnum = 0; fnum < 16; fnum++)
+ for (block = 0; block < 8; block++)
+ for (TL = 0; TL < 64; TL++)
+ for (KL = 0; KL < 4; KL++)
+ {
+ if (KL == 0)
+ {
+ tllTable[fnum][block][TL][KL] = TL2EG (TL);
+ }
+ else
+ {
+ tmp = (e_int32) ((kltable[fnum] - dB2 (3.000) * (7 - block))/8);
+ if (tmp <= 0)
+ tllTable[fnum][block][TL][KL] = TL2EG (TL);
+ else
+ /* tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL); */
+ tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp << KL) / (int)(EG_STEP*8)) + TL2EG (TL);
+ }
+ }
+}
+
+#ifdef USE_SPEC_ENV_SPEED
+static double attacktime[16][4] = {
+ {0, 0, 0, 0},
+ {1730.15, 1400.60, 1153.43, 988.66},
+ {865.08, 700.30, 576.72, 494.33},
+ {432.54, 350.15, 288.36, 247.16},
+ {216.27, 175.07, 144.18, 123.58},
+ {108.13, 87.54, 72.09, 61.79},
+ {54.07, 43.77, 36.04, 30.90},
+ {27.03, 21.88, 18.02, 15.45},
+ {13.52, 10.94, 9.01, 7.72},
+ {6.76, 5.47, 4.51, 3.86},
+ {3.38, 2.74, 2.25, 1.93},
+ {1.69, 1.37, 1.13, 0.97},
+ {0.84, 0.70, 0.60, 0.54},
+ {0.50, 0.42, 0.34, 0.30},
+ {0.28, 0.22, 0.18, 0.14},
+ {0.00, 0.00, 0.00, 0.00}
+};
+
+static double decaytime[16][4] = {
+ {0, 0, 0, 0},
+ {20926.60, 16807.20, 14006.00, 12028.60},
+ {10463.30, 8403.58, 7002.98, 6014.32},
+ {5231.64, 4201.79, 3501.49, 3007.16},
+ {2615.82, 2100.89, 1750.75, 1503.58},
+ {1307.91, 1050.45, 875.37, 751.79},
+ {653.95, 525.22, 437.69, 375.90},
+ {326.98, 262.61, 218.84, 187.95},
+ {163.49, 131.31, 109.42, 93.97},
+ {81.74, 65.65, 54.71, 46.99},
+ {40.87, 32.83, 27.36, 23.49},
+ {20.44, 16.41, 13.68, 11.75},
+ {10.22, 8.21, 6.84, 5.87},
+ {5.11, 4.10, 3.42, 2.94},
+ {2.55, 2.05, 1.71, 1.47},
+ {1.27, 1.27, 1.27, 1.27}
+};
+#endif
+
+/* Rate Table for Attack */
+static void
+makeDphaseARTable (void)
+{
+ e_int32 AR, Rks, RM, RL;
+
+#ifdef USE_SPEC_ENV_SPEED
+ e_uint32 attacktable[16][4];
+
+ for (RM = 0; RM < 16; RM++)
+ for (RL = 0; RL < 4; RL++)
+ {
+ if (RM == 0)
+ attacktable[RM][RL] = 0;
+ else if (RM == 15)
+ attacktable[RM][RL] = EG_DP_WIDTH;
+ else
+ attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
+
+ }
+#endif
+
+ for (AR = 0; AR < 16; AR++)
+ for (Rks = 0; Rks < 16; Rks++)
+ {
+ RM = AR + (Rks >> 2);
+ RL = Rks & 3;
+ if (RM > 15)
+ RM = 15;
+ switch (AR)
+ {
+ case 0:
+ dphaseARTable[AR][Rks] = 0;
+ break;
+ case 15:
+ dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/
+ break;
+ default:
+#ifdef USE_SPEC_ENV_SPEED
+ dphaseARTable[AR][Rks] = RATE_ADJUST (attacktable[RM][RL]);
+#else
+ dphaseARTable[AR][Rks] = RATE_ADJUST ((3 * (RL + 4) << (RM + 1)));
+#endif
+ break;
+ }
+ }
+}
+
+/* Rate Table for Decay and Release */
+static void
+makeDphaseDRTable (void)
+{
+ e_int32 DR, Rks, RM, RL;
+
+#ifdef USE_SPEC_ENV_SPEED
+ e_uint32 decaytable[16][4];
+
+ for (RM = 0; RM < 16; RM++)
+ for (RL = 0; RL < 4; RL++)
+ if (RM == 0)
+ decaytable[RM][RL] = 0;
+ else
+ decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000));
+#endif
+
+ for (DR = 0; DR < 16; DR++)
+ for (Rks = 0; Rks < 16; Rks++)
+ {
+ RM = DR + (Rks >> 2);
+ RL = Rks & 3;
+ if (RM > 15)
+ RM = 15;
+ switch (DR)
+ {
+ case 0:
+ dphaseDRTable[DR][Rks] = 0;
+ break;
+ default:
+#ifdef USE_SPEC_ENV_SPEED
+ dphaseDRTable[DR][Rks] = RATE_ADJUST (decaytable[RM][RL]);
+#else
+ dphaseDRTable[DR][Rks] = RATE_ADJUST ((RL + 4) << (RM - 1));
+#endif
+ break;
+ }
+ }
+}
+
+static void
+makeRksTable (void)
+{
+
+ e_int32 fnum8, block, KR;
+
+ for (fnum8 = 0; fnum8 < 2; fnum8++)
+ for (block = 0; block < 8; block++)
+ for (KR = 0; KR < 2; KR++)
+ {
+ if (KR != 0)
+ rksTable[fnum8][block][KR] = (block << 1) + fnum8;
+ else
+ rksTable[fnum8][block][KR] = block >> 1;
+ }
+}
+
+void
+OPLL_dump2patch (const e_uint8 * dump, OPLL_PATCH * patch)
+{
+ patch[0].AM = (dump[0] >> 7) & 1;
+ patch[1].AM = (dump[1] >> 7) & 1;
+ patch[0].PM = (dump[0] >> 6) & 1;
+ patch[1].PM = (dump[1] >> 6) & 1;
+ patch[0].EG = (dump[0] >> 5) & 1;
+ patch[1].EG = (dump[1] >> 5) & 1;
+ patch[0].KR = (dump[0] >> 4) & 1;
+ patch[1].KR = (dump[1] >> 4) & 1;
+ patch[0].ML = (dump[0]) & 15;
+ patch[1].ML = (dump[1]) & 15;
+ patch[0].KL = (dump[2] >> 6) & 3;
+ patch[1].KL = (dump[3] >> 6) & 3;
+ patch[0].TL = (dump[2]) & 63;
+ patch[0].FB = (dump[3]) & 7;
+ patch[0].WF = (dump[3] >> 3) & 1;
+ patch[1].WF = (dump[3] >> 4) & 1;
+ patch[0].AR = (dump[4] >> 4) & 15;
+ patch[1].AR = (dump[5] >> 4) & 15;
+ patch[0].DR = (dump[4]) & 15;
+ patch[1].DR = (dump[5]) & 15;
+ patch[0].SL = (dump[6] >> 4) & 15;
+ patch[1].SL = (dump[7] >> 4) & 15;
+ patch[0].RR = (dump[6]) & 15;
+ patch[1].RR = (dump[7]) & 15;
+}
+
+void
+OPLL_getDefaultPatch (e_int32 type, e_int32 num, OPLL_PATCH * patch)
+{
+ OPLL_dump2patch (default_inst[type] + num * 16, patch);
+}
+
+static void
+makeDefaultPatch ( void )
+{
+ e_int32 i, j;
+
+ for (i = 0; i < OPLL_TONE_NUM; i++)
+ for (j = 0; j < 19; j++)
+ OPLL_getDefaultPatch (i, j, &default_patch[i][j * 2]);
+
+}
+
+void
+OPLL_setPatch (OPLL * opll, const e_uint8 * dump)
+{
+ OPLL_PATCH patch[2];
+ int i;
+
+ for (i = 0; i < 19; i++)
+ {
+ OPLL_dump2patch (dump + i * 16, patch);
+ memcpy (&opll->patch[i*2+0], &patch[0], sizeof (OPLL_PATCH));
+ memcpy (&opll->patch[i*2+1], &patch[1], sizeof (OPLL_PATCH));
+ }
+}
+
+void
+OPLL_patch2dump (const OPLL_PATCH * patch, e_uint8 * dump)
+{
+ dump[0] = (e_uint8) ((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);
+ dump[1] = (e_uint8) ((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);
+ dump[2] = (e_uint8) ((patch[0].KL << 6) + patch[0].TL);
+ dump[3] = (e_uint8) ((patch[1].KL << 6) + (patch[1].WF << 4) + (patch[0].WF << 3) + patch[0].FB);
+ dump[4] = (e_uint8) ((patch[0].AR << 4) + patch[0].DR);
+ dump[5] = (e_uint8) ((patch[1].AR << 4) + patch[1].DR);
+ dump[6] = (e_uint8) ((patch[0].SL << 4) + patch[0].RR);
+ dump[7] = (e_uint8) ((patch[1].SL << 4) + patch[1].RR);
+ dump[8] = 0;
+ dump[9] = 0;
+ dump[10] = 0;
+ dump[11] = 0;
+ dump[12] = 0;
+ dump[13] = 0;
+ dump[14] = 0;
+ dump[15] = 0;
+}
+
+/************************************************************
+
+ Calc Parameters
+
+************************************************************/
+
+INLINE static e_uint32
+calc_eg_dphase (OPLL_SLOT * slot)
+{
+
+ switch (slot->eg_mode)
+ {
+ case ATTACK:
+ return dphaseARTable[slot->patch->AR][slot->rks];
+
+ case DECAY:
+ return dphaseDRTable[slot->patch->DR][slot->rks];
+
+ case SUSHOLD:
+ return 0;
+
+ case SUSTINE:
+ return dphaseDRTable[slot->patch->RR][slot->rks];
+
+ case RELEASE:
+ if (slot->sustine)
+ return dphaseDRTable[5][slot->rks];
+ else if (slot->patch->EG)
+ return dphaseDRTable[slot->patch->RR][slot->rks];
+ else
+ return dphaseDRTable[7][slot->rks];
+
+ case SETTLE:
+ return dphaseDRTable[15][0];
+
+ case FINISH:
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+/*************************************************************
+
+ OPLL internal interfaces
+
+*************************************************************/
+#define SLOT_BD1 12
+#define SLOT_BD2 13
+#define SLOT_HH 14
+#define SLOT_SD 15
+#define SLOT_TOM 16
+#define SLOT_CYM 17
+
+/* We will set this dinamically, but not sure if this affects playback */
+#if defined(ROCKBOX)
+INLINE static void
+UPDATE_PG(OPLL_SLOT * slot)
+{
+ static const e_uint32 mltable[16] =
+ { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
+
+ slot->dphase = RATE_ADJUST (((slot->fnum * mltable[slot->patch->ML]) << slot->block) >> (20 - DP_BITS));
+}
+#else
+#define UPDATE_PG(S) (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch->ML]
+#endif
+
+#define UPDATE_TLL(S)\
+(((S)->type==0)?\
+((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch->TL][(S)->patch->KL]):\
+((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch->KL]))
+#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch->KR]
+#define UPDATE_WF(S) (S)->sintbl = waveform[(S)->patch->WF]
+#define UPDATE_EG(S) (S)->eg_dphase = calc_eg_dphase(S)
+#define UPDATE_ALL(S)\
+ UPDATE_PG(S);\
+ UPDATE_TLL(S);\
+ UPDATE_RKS(S);\
+ UPDATE_WF(S); \
+ UPDATE_EG(S) /* EG should be updated last. */
+
+
+/* Slot key on */
+INLINE static void
+slotOn (OPLL_SLOT * slot)
+{
+ slot->eg_mode = ATTACK;
+ slot->eg_phase = 0;
+ slot->phase = 0;
+ UPDATE_EG(slot);
+}
+
+/* Slot key on without reseting the phase */
+INLINE static void
+slotOn2 (OPLL_SLOT * slot)
+{
+ slot->eg_mode = ATTACK;
+ slot->eg_phase = 0;
+ UPDATE_EG(slot);
+}
+
+/* Slot key off */
+INLINE static void
+slotOff (OPLL_SLOT * slot)
+{
+ if (slot->eg_mode == ATTACK)
+ slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)), EG_BITS, EG_DP_BITS);
+ slot->eg_mode = RELEASE;
+ UPDATE_EG(slot);
+}
+
+/* Channel key on */
+INLINE static void
+keyOn (OPLL * opll, e_int32 i)
+{
+ if (!opll->slot_on_flag[i * 2])
+ slotOn (MOD(opll,i));
+ if (!opll->slot_on_flag[i * 2 + 1])
+ slotOn (CAR(opll,i));
+ opll->key_status[i] = 1;
+}
+
+/* Channel key off */
+INLINE static void
+keyOff (OPLL * opll, e_int32 i)
+{
+ if (opll->slot_on_flag[i * 2 + 1])
+ slotOff (CAR(opll,i));
+ opll->key_status[i] = 0;
+}
+
+INLINE static void
+keyOn_BD (OPLL * opll)
+{
+ keyOn (opll, 6);
+}
+INLINE static void
+keyOn_SD (OPLL * opll)
+{
+ if (!opll->slot_on_flag[SLOT_SD])
+ slotOn (CAR(opll,7));
+}
+INLINE static void
+keyOn_TOM (OPLL * opll)
+{
+ if (!opll->slot_on_flag[SLOT_TOM])
+ slotOn (MOD(opll,8));
+}
+INLINE static void
+keyOn_HH (OPLL * opll)
+{
+ if (!opll->slot_on_flag[SLOT_HH])
+ slotOn2 (MOD(opll,7));
+}
+INLINE static void
+keyOn_CYM (OPLL * opll)
+{
+ if (!opll->slot_on_flag[SLOT_CYM])
+ slotOn2 (CAR(opll,8));
+}
+
+/* Drum key off */
+INLINE static void
+keyOff_BD (OPLL * opll)
+{
+ keyOff (opll, 6);
+}
+INLINE static void
+keyOff_SD (OPLL * opll)
+{
+ if (opll->slot_on_flag[SLOT_SD])
+ slotOff (CAR(opll,7));
+}
+INLINE static void
+keyOff_TOM (OPLL * opll)
+{
+ if (opll->slot_on_flag[SLOT_TOM])
+ slotOff (MOD(opll,8));
+}
+INLINE static void
+keyOff_HH (OPLL * opll)
+{
+ if (opll->slot_on_flag[SLOT_HH])
+ slotOff (MOD(opll,7));
+}
+INLINE static void
+keyOff_CYM (OPLL * opll)
+{
+ if (opll->slot_on_flag[SLOT_CYM])
+ slotOff (CAR(opll,8));
+}
+
+/* Change a voice */
+INLINE static void
+setPatch (OPLL * opll, e_int32 i, e_int32 num)
+{
+ opll->patch_number[i] = num;
+ MOD(opll,i)->patch = &opll->patch[num * 2 + 0];
+ CAR(opll,i)->patch = &opll->patch[num * 2 + 1];
+}
+
+/* Change a rhythm voice */
+INLINE static void
+setSlotPatch (OPLL_SLOT * slot, OPLL_PATCH * patch)
+{
+ slot->patch = patch;
+}
+
+/* Set sustine parameter */
+INLINE static void
+setSustine (OPLL * opll, e_int32 c, e_int32 sustine)
+{
+ CAR(opll,c)->sustine = sustine;
+ if (MOD(opll,c)->type)
+ MOD(opll,c)->sustine = sustine;
+}
+
+/* Volume : 6bit ( Volume register << 2 ) */
+INLINE static void
+setVolume (OPLL * opll, e_int32 c, e_int32 volume)
+{
+ CAR(opll,c)->volume = volume;
+}
+
+INLINE static void
+setSlotVolume (OPLL_SLOT * slot, e_int32 volume)
+{
+ slot->volume = volume;
+}
+
+/* Set F-Number ( fnum : 9bit ) */
+INLINE static void
+setFnumber (OPLL * opll, e_int32 c, e_int32 fnum)
+{
+ CAR(opll,c)->fnum = fnum;
+ MOD(opll,c)->fnum = fnum;
+}
+
+/* Set Block data (block : 3bit ) */
+INLINE static void
+setBlock (OPLL * opll, e_int32 c, e_int32 block)
+{
+ CAR(opll,c)->block = block;
+ MOD(opll,c)->block = block;
+}
+
+/* Change Rhythm Mode */
+INLINE static void
+update_rhythm_mode (OPLL * opll)
+{
+ if (opll->patch_number[6] & 0x10)
+ {
+ if (!(opll->slot_on_flag[SLOT_BD2] | (opll->reg[0x0e] & 32)))
+ {
+ opll->slot[SLOT_BD1].eg_mode = FINISH;
+ opll->slot[SLOT_BD2].eg_mode = FINISH;
+ setPatch (opll, 6, opll->reg[0x36] >> 4);
+ }
+ }
+ else if (opll->reg[0x0e] & 32)
+ {
+ opll->patch_number[6] = 16;
+ opll->slot[SLOT_BD1].eg_mode = FINISH;
+ opll->slot[SLOT_BD2].eg_mode = FINISH;
+ setSlotPatch (&opll->slot[SLOT_BD1], &opll->patch[16 * 2 + 0]);
+ setSlotPatch (&opll->slot[SLOT_BD2], &opll->patch[16 * 2 + 1]);
+ }
+
+ if (opll->patch_number[7] & 0x10)
+ {
+ if (!((opll->slot_on_flag[SLOT_HH] && opll->slot_on_flag[SLOT_SD]) | (opll->reg[0x0e] & 32)))
+ {
+ opll->slot[SLOT_HH].type = 0;
+ opll->slot[SLOT_HH].eg_mode = FINISH;
+ opll->slot[SLOT_SD].eg_mode = FINISH;
+ setPatch (opll, 7, opll->reg[0x37] >> 4);
+ }
+ }
+ else if (opll->reg[0x0e] & 32)
+ {
+ opll->patch_number[7] = 17;
+ opll->slot[SLOT_HH].type = 1;
+ opll->slot[SLOT_HH].eg_mode = FINISH;
+ opll->slot[SLOT_SD].eg_mode = FINISH;
+ setSlotPatch (&opll->slot[SLOT_HH], &opll->patch[17 * 2 + 0]);
+ setSlotPatch (&opll->slot[SLOT_SD], &opll->patch[17 * 2 + 1]);
+ }
+
+ if (opll->patch_number[8] & 0x10)
+ {
+ if (!((opll->slot_on_flag[SLOT_CYM] && opll->slot_on_flag[SLOT_TOM]) | (opll->reg[0x0e] & 32)))
+ {
+ opll->slot[SLOT_TOM].type = 0;
+ opll->slot[SLOT_TOM].eg_mode = FINISH;
+ opll->slot[SLOT_CYM].eg_mode = FINISH;
+ setPatch (opll, 8, opll->reg[0x38] >> 4);
+ }
+ }
+ else if (opll->reg[0x0e] & 32)
+ {
+ opll->patch_number[8] = 18;
+ opll->slot[SLOT_TOM].type = 1;
+ opll->slot[SLOT_TOM].eg_mode = FINISH;
+ opll->slot[SLOT_CYM].eg_mode = FINISH;
+ setSlotPatch (&opll->slot[SLOT_TOM], &opll->patch[18 * 2 + 0]);
+ setSlotPatch (&opll->slot[SLOT_CYM], &opll->patch[18 * 2 + 1]);
+ }
+}
+
+INLINE static void
+update_key_status (OPLL * opll)
+{
+ int ch;
+
+ for (ch = 0; ch < 9; ch++)
+ opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->reg[0x20 + ch]) & 0x10;
+
+ if (opll->reg[0x0e] & 32)
+ {
+ opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e] & 0x10);
+ opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e] & 0x10);
+ opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e] & 0x08);
+ opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e] & 0x01);
+ opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e] & 0x04);
+ opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e] & 0x02);
+ }
+}
+
+void
+OPLL_copyPatch (OPLL * opll, e_int32 num, OPLL_PATCH * patch)
+{
+ memcpy (&opll->patch[num], patch, sizeof (OPLL_PATCH));
+}
+
+/***********************************************************
+
+ Initializing
+
+***********************************************************/
+
+static void
+OPLL_SLOT_reset (OPLL_SLOT * slot, int type)
+{
+ slot->type = type;
+ slot->sintbl = waveform[0];
+ slot->phase = 0;
+ slot->dphase = 0;
+ slot->output[0] = 0;
+ slot->output[1] = 0;
+ slot->feedback = 0;
+ slot->eg_mode = FINISH;
+ slot->eg_phase = EG_DP_WIDTH;
+ slot->eg_dphase = 0;
+ slot->rks = 0;
+ slot->tll = 0;
+ slot->sustine = 0;
+ slot->fnum = 0;
+ slot->block = 0;
+ slot->volume = 0;
+ slot->pgout = 0;
+ slot->egout = 0;
+ slot->patch = &null_patch;
+}
+
+static void
+internal_refresh (void)
+{
+#if !defined(ROCKBOX)
+ makeDphaseTable ();
+#endif
+ makeDphaseARTable ();
+ makeDphaseDRTable ();
+ pm_dphase = (e_uint32) RATE_ADJUST ((int)(PM_SPEED * PM_DP_WIDTH) / (clk / 72));
+ am_dphase = (e_uint32) RATE_ADJUST ((int)(AM_SPEED * AM_DP_WIDTH) / (clk / 72));
+}
+
+static void
+maketables (e_uint32 c, e_uint32 r)
+{
+ if (c != clk)
+ {
+ clk = c;
+#ifdef EMU2413_CALCUL_TABLES
+ makePmTable ();
+ makeAmTable ();
+ makeAdjustTable ();
+#endif
+ makeDB2LinTable ();
+ makeTllTable ();
+ makeRksTable ();
+ makeSinTable ();
+ makeDefaultPatch ();
+ }
+
+ if (r != rate)
+ {
+ rate = r;
+ internal_refresh ();
+ }
+}
+
+void
+OPLL_new (OPLL *opll, e_uint32 clk, e_uint32 rate)
+{
+ e_int32 i;
+
+ maketables (clk, rate);
+
+ memset(opll, 0, sizeof (OPLL));
+ for (i = 0; i < 19 * 2; i++)
+ memcpy(&opll->patch[i],&null_patch,sizeof(OPLL_PATCH));
+
+ opll->mask = 0;
+
+ OPLL_reset (opll);
+ OPLL_reset_patch (opll, 0);
+}
+
+
+void
+OPLL_delete (OPLL * opll)
+{
+ (void) opll;
+}
+
+
+/* Reset patch datas by system default. */
+void
+OPLL_reset_patch (OPLL * opll, e_int32 type)
+{
+ e_int32 i;
+
+ for (i = 0; i < 19 * 2; i++)
+ OPLL_copyPatch (opll, i, &default_patch[type % OPLL_TONE_NUM][i]);
+}
+
+/* Reset whole of OPLL except patch datas. */
+void
+OPLL_reset (OPLL * opll)
+{
+ e_int32 i;
+
+ if (!opll)
+ return;
+
+ opll->adr = 0;
+ opll->out = 0;
+
+ opll->pm_phase = 0;
+ opll->am_phase = 0;
+
+ opll->noise_seed = 0xffff;
+ opll->mask = 0;
+
+ for (i = 0; i <18; i++)
+ OPLL_SLOT_reset(&opll->slot[i], i%2);
+
+ for (i = 0; i < 9; i++)
+ {
+ opll->key_status[i] = 0;
+ setPatch (opll, i, 0);
+ }
+
+ for (i = 0; i < 0x40; i++)
+ OPLL_writeReg (opll, i, 0);
+
+#ifndef EMU2413_COMPACTION
+ opll->realstep = (e_uint32) ((1 << 31) / rate);
+ opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72));
+ opll->oplltime = 0;
+ for (i = 0; i < 14; i++)
+ opll->pan[i] = 2;
+ opll->sprev[0] = opll->sprev[1] = 0;
+ opll->snext[0] = opll->snext[1] = 0;
+#endif
+}
+
+/* Force Refresh (When external program changes some parameters). */
+void
+OPLL_forceRefresh (OPLL * opll)
+{
+ e_int32 i;
+
+ if (opll == NULL)
+ return;
+
+ for (i = 0; i < 9; i++)
+ setPatch(opll,i,opll->patch_number[i]);
+
+ for (i = 0; i < 18; i++)
+ {
+ UPDATE_PG (&opll->slot[i]);
+ UPDATE_RKS (&opll->slot[i]);
+ UPDATE_TLL (&opll->slot[i]);
+ UPDATE_WF (&opll->slot[i]);
+ UPDATE_EG (&opll->slot[i]);
+ }
+}
+
+void
+OPLL_set_rate (OPLL * opll, e_uint32 r)
+{
+ if (rate == r) return;
+ if (opll->quality)
+ rate = 49716;
+ else
+ rate = r;
+ internal_refresh ();
+ rate = r;
+}
+
+void
+OPLL_set_quality (OPLL * opll, e_uint32 q)
+{
+ opll->quality = q;
+ OPLL_set_rate (opll, rate);
+}
+
+/*********************************************************
+
+ Generate wave data
+
+*********************************************************/
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
+#if ( SLOT_AMP_BITS - PG_BITS ) > 0
+#define wave2_2pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
+#else
+#define wave2_2pi(e) ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
+#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
+#define wave2_4pi(e) (e)
+#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
+#define wave2_4pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
+#else
+#define wave2_4pi(e) ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
+#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
+#define wave2_8pi(e) (e)
+#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
+#define wave2_8pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
+#else
+#define wave2_8pi(e) ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
+#endif
+
+/* Update AM, PM unit */
+INLINE static void
+update_ampm (OPLL * opll)
+{
+ opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1);
+ opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1);
+ opll->lfo_am = AMTABLE(HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS));
+ opll->lfo_pm = PMTABLE(HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS));
+}
+
+/* PG */
+INLINE static void
+calc_phase (OPLL_SLOT * slot, e_int32 lfo)
+{
+ if (slot->patch->PM)
+ slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS;
+ else
+ slot->phase += slot->dphase;
+
+ slot->phase &= (DP_WIDTH - 1);
+
+ slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS);
+}
+
+/* Update Noise unit */
+INLINE static void
+update_noise (OPLL * opll)
+{
+ if(opll->noise_seed&1) opll->noise_seed ^= 0x8003020;
+ opll->noise_seed >>= 1;
+}
+
+/* EG */
+INLINE static void
+calc_envelope (OPLL_SLOT * slot, e_int32 lfo)
+{
+#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
+
+ static e_uint32 SL[16] = {
+ S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
+ S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
+ };
+
+ e_uint32 egout;
+
+ switch (slot->eg_mode)
+ {
+ case ATTACK:
+ egout = AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS));
+ slot->eg_phase += slot->eg_dphase;
+ if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch->AR==15))
+ {
+ egout = 0;
+ slot->eg_phase = 0;
+ slot->eg_mode = DECAY;
+ UPDATE_EG (slot);
+ }
+ break;
+
+ case DECAY:
+ egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+ slot->eg_phase += slot->eg_dphase;
+ if (slot->eg_phase >= SL[slot->patch->SL])
+ {
+ if (slot->patch->EG)
+ {
+ slot->eg_phase = SL[slot->patch->SL];
+ slot->eg_mode = SUSHOLD;
+ UPDATE_EG (slot);
+ }
+ else
+ {
+ slot->eg_phase = SL[slot->patch->SL];
+ slot->eg_mode = SUSTINE;
+ UPDATE_EG (slot);
+ }
+ }
+ break;
+
+ case SUSHOLD:
+ egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+ if (slot->patch->EG == 0)
+ {
+ slot->eg_mode = SUSTINE;
+ UPDATE_EG (slot);
+ }
+ break;
+
+ case SUSTINE:
+ case RELEASE:
+ egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+ slot->eg_phase += slot->eg_dphase;
+ if (egout >= (1 << EG_BITS))
+ {
+ slot->eg_mode = FINISH;
+ egout = (1 << EG_BITS) - 1;
+ }
+ break;
+
+ case SETTLE:
+ egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
+ slot->eg_phase += slot->eg_dphase;
+ if (egout >= (1 << EG_BITS))
+ {
+ slot->eg_mode = ATTACK;
+ egout = (1 << EG_BITS) - 1;
+ UPDATE_EG(slot);
+ }
+ break;
+
+ case FINISH:
+ egout = (1 << EG_BITS) - 1;
+ break;
+
+ default:
+ egout = (1 << EG_BITS) - 1;
+ break;
+ }
+
+ if (slot->patch->AM)
+ egout = EG2DB (egout + slot->tll) + lfo;
+ else
+ egout = EG2DB (egout + slot->tll);
+
+ if (egout >= DB_MUTE)
+ egout = DB_MUTE - 1;
+
+ slot->egout = egout | 3;
+}
+
+/* CARRIOR */
+INLINE static e_int32
+calc_slot_car (OPLL_SLOT * slot, e_int32 fm)
+{
+ if (slot->egout >= (DB_MUTE - 1))
+ {
+ slot->output[0] = 0;
+ }
+ else
+ {
+ slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
+ }
+
+ slot->output[1] = (slot->output[1] + slot->output[0]) >> 1;
+ return slot->output[1];
+}
+
+/* MODULATOR */
+INLINE static e_int32
+calc_slot_mod (OPLL_SLOT * slot)
+{
+ e_int32 fm;
+
+ slot->output[1] = slot->output[0];
+
+ if (slot->egout >= (DB_MUTE - 1))
+ {
+ slot->output[0] = 0;
+ }
+ else if (slot->patch->FB != 0)
+ {
+ fm = wave2_4pi (slot->feedback) >> (7 - slot->patch->FB);
+ slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
+ }
+ else
+ {
+ slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
+ }
+
+ slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
+
+ return slot->feedback;
+
+}
+
+/* TOM */
+INLINE static e_int32
+calc_slot_tom (OPLL_SLOT * slot)
+{
+ if (slot->egout >= (DB_MUTE - 1))
+ return 0;
+
+ return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
+
+}
+
+/* SNARE */
+INLINE static e_int32
+calc_slot_snare (OPLL_SLOT * slot, e_uint32 noise)
+{
+ if(slot->egout>=(DB_MUTE-1))
+ return 0;
+
+ if(BIT(slot->pgout,7))
+ return DB2LIN_TABLE[(noise?DB_POS(0):DB_POS(15))+slot->egout];
+ else
+ return DB2LIN_TABLE[(noise?DB_NEG(0):DB_NEG(15))+slot->egout];
+}
+
+/*
+ TOP-CYM
+ */
+INLINE static e_int32
+calc_slot_cym (OPLL_SLOT * slot, e_uint32 pgout_hh)
+{
+ e_uint32 dbout;
+
+ if (slot->egout >= (DB_MUTE - 1))
+ return 0;
+ else if(
+ /* the same as fmopl.c */
+ ((BIT(pgout_hh,PG_BITS-8)^BIT(pgout_hh,PG_BITS-1))|BIT(pgout_hh,PG_BITS-7)) ^
+ /* different from fmopl.c */
+ (BIT(slot->pgout,PG_BITS-7)&!BIT(slot->pgout,PG_BITS-5))
+ )
+ dbout = DB_NEG(3);
+ else
+ dbout = DB_POS(3);
+
+ return DB2LIN_TABLE[dbout + slot->egout];
+}
+
+/*
+ HI-HAT
+*/
+INLINE static e_int32
+calc_slot_hat (OPLL_SLOT *slot, e_int32 pgout_cym, e_uint32 noise)
+{
+ e_uint32 dbout;
+
+ if (slot->egout >= (DB_MUTE - 1))
+ return 0;
+ else if(
+ /* the same as fmopl.c */
+ ((BIT(slot->pgout,PG_BITS-8)^BIT(slot->pgout,PG_BITS-1))|BIT(slot->pgout,PG_BITS-7)) ^
+ /* different from fmopl.c */
+ (BIT(pgout_cym,PG_BITS-7)&!BIT(pgout_cym,PG_BITS-5))
+ )
+ {
+ if(noise)
+ dbout = DB_NEG(12);
+ else
+ dbout = DB_NEG(24);
+ }
+ else
+ {
+ if(noise)
+ dbout = DB_POS(12);
+ else
+ dbout = DB_POS(24);
+ }
+
+ return DB2LIN_TABLE[dbout + slot->egout];
+}
+
+static e_int16
+calc (OPLL * opll) EMU2413_CALC_ICODE;
+static e_int16
+calc (OPLL * opll)
+{
+ e_int32 i;
+
+ update_ampm (opll);
+ update_noise (opll);
+
+ for (i = 0; i < 18; i++)
+ {
+ calc_phase(&opll->slot[i],opll->lfo_pm);
+ calc_envelope(&opll->slot[i],opll->lfo_am);
+ }
+
+ e_uint32 channel_mask = opll->mask;
+ for (i = 0; i < 9; i++) {
+ if (CAR(opll,i)->eg_mode != FINISH)
+ channel_mask |= (1 << i);
+ }
+
+ e_int32 mix = 0;
+
+ /* CH6 */
+ if (opll->patch_number[6] & 0x10) {
+ if (channel_mask & OPLL_MASK_CH (6)) {
+ mix += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
+ channel_mask &= ~(1 << 6);
+ }
+ }
+
+ /* CH7 */
+ if (opll->patch_number[7] & 0x10) {
+ if (MOD(opll,7)->eg_mode != FINISH)
+ mix += calc_slot_hat (MOD(opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
+ if (channel_mask & OPLL_MASK_SD) {
+ mix -= calc_slot_snare (CAR(opll,7), opll->noise_seed&1);
+ channel_mask &= ~OPLL_MASK_SD;
+ }
+ }
+
+ /* CH8 */
+ if (opll->patch_number[8] & 0x10) {
+ if (MOD(opll,8)->eg_mode != FINISH)
+ mix += calc_slot_tom (MOD(opll,8));
+ if (channel_mask & OPLL_MASK_CYM) {
+ mix -= calc_slot_cym (CAR(opll,8), MOD(opll,7)->pgout);
+ channel_mask &= ~OPLL_MASK_CYM;
+ }
+ }
+
+ mix <<= 1;
+
+ opll->current_mask = channel_mask;
+ for (i = 0; channel_mask; channel_mask >>= 1, ++i) {
+ if (channel_mask & 1) {
+ mix += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i)));
+ }
+ }
+
+ return (e_int16) mix << 3;
+}
+
+void
+OPLL_set_internal_mute(OPLL * opll, e_uint32 mute)
+{
+ opll->internal_mute = mute;
+}
+
+e_uint32
+OPLL_is_internal_muted(OPLL * opll)
+{
+ return opll->internal_mute;
+}
+
+static e_uint32
+check_mute_helper(OPLL * opll)
+{
+ for (int i = 0; i < 6; i++) {
+ /* if (ch[i].car.eg_mode != FINISH) return 0; */
+ if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
+ }
+
+ if (!(opll->reg[0x0e] & 0x20)) {
+ for(int i = 6; i < 9; i++) {
+ /* if (ch[i].car.eg_mode != FINISH) return 0; */
+ if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
+ }
+ } else {
+ /* if (ch[6].car.eg_mode != FINISH) return false;
+ if (ch[7].mod.eg_mode != FINISH) return false;
+ if (ch[7].car.eg_mode != FINISH) return false;
+ if (ch[8].mod.eg_mode != FINISH) return false;
+ if (ch[8].car.eg_mode != FINISH) return false; */
+ if (!(opll->current_mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH)) return 0;
+ if (!(opll->current_mask & OPLL_MASK_CH (7)) && (MOD(opll,7)->eg_mode != FINISH)) return 0;
+ if (!(opll->current_mask & OPLL_MASK_CH (7)) && (CAR(opll,7)->eg_mode != FINISH)) return 0;
+ if (!(opll->current_mask & OPLL_MASK_CH (8)) && (MOD(opll,8)->eg_mode != FINISH)) return 0;
+ if (!(opll->current_mask & OPLL_MASK_CH (8)) && (CAR(opll,8)->eg_mode != FINISH)) return 0;
+ }
+
+ return 1; /* nothing is playing, then mute */
+}
+
+static void
+check_mute(OPLL * opll)
+{
+ OPLL_set_internal_mute (opll, check_mute_helper (opll));
+}
+
+EMU2413_API e_int16 *OPLL_update_buffer(OPLL * opll, e_uint32 length)
+{
+ e_int16* buf = opll->buffer;
+ while (length--) {
+ *(buf++) = calc (opll);
+ }
+ check_mute (opll);
+
+ return opll->buffer;
+}
+
+#ifdef EMU2413_COMPACTION
+e_int16
+OPLL_calc (OPLL * opll)
+{
+ return calc (opll);
+}
+#else
+e_int16
+OPLL_calc (OPLL * opll)
+{
+ if (!opll->quality)
+ return calc (opll);
+
+ while (opll->realstep > opll->oplltime)
+ {
+ opll->oplltime += opll->opllstep;
+ opll->prev = opll->next;
+ opll->next = calc (opll);
+ }
+
+ opll->oplltime -= opll->realstep;
+ opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime)
+ + (double) opll->prev * opll->oplltime) / opll->opllstep);
+
+ return (e_int16) opll->out;
+}
+#endif
+
+e_uint32
+OPLL_setMask (OPLL * opll, e_uint32 mask)
+{
+ e_uint32 ret;
+
+ if (opll)
+ {
+ ret = opll->mask;
+ opll->mask = mask;
+ return ret;
+ }
+ else
+ return 0;
+}
+
+e_uint32
+OPLL_toggleMask (OPLL * opll, e_uint32 mask)
+{
+ e_uint32 ret;
+
+ if (opll)
+ {
+ ret = opll->mask;
+ opll->mask ^= mask;
+ return ret;
+ }
+ else
+ return 0;
+}
+
+/****************************************************
+
+ I/O Ctrl
+
+*****************************************************/
+
+void
+OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
+{
+ e_int32 i, v, ch;
+
+ data = data & 0xff;
+ reg = reg & 0x3f;
+ opll->reg[reg] = (e_uint8) data;
+
+ switch (reg)
+ {
+ case 0x00:
+ opll->patch[0].AM = (data >> 7) & 1;
+ opll->patch[0].PM = (data >> 6) & 1;
+ opll->patch[0].EG = (data >> 5) & 1;
+ opll->patch[0].KR = (data >> 4) & 1;
+ opll->patch[0].ML = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_PG (MOD(opll,i));
+ UPDATE_RKS (MOD(opll,i));
+ UPDATE_EG (MOD(opll,i));
+ }
+ }
+ break;
+
+ case 0x01:
+ opll->patch[1].AM = (data >> 7) & 1;
+ opll->patch[1].PM = (data >> 6) & 1;
+ opll->patch[1].EG = (data >> 5) & 1;
+ opll->patch[1].KR = (data >> 4) & 1;
+ opll->patch[1].ML = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_PG (CAR(opll,i));
+ UPDATE_RKS (CAR(opll,i));
+ UPDATE_EG (CAR(opll,i));
+ }
+ }
+ break;
+
+ case 0x02:
+ opll->patch[0].KL = (data >> 6) & 3;
+ opll->patch[0].TL = (data) & 63;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_TLL(MOD(opll,i));
+ }
+ }
+ break;
+
+ case 0x03:
+ opll->patch[1].KL = (data >> 6) & 3;
+ opll->patch[1].WF = (data >> 4) & 1;
+ opll->patch[0].WF = (data >> 3) & 1;
+ opll->patch[0].FB = (data) & 7;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_WF(MOD(opll,i));
+ UPDATE_WF(CAR(opll,i));
+ }
+ }
+ break;
+
+ case 0x04:
+ opll->patch[0].AR = (data >> 4) & 15;
+ opll->patch[0].DR = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_EG (MOD(opll,i));
+ }
+ }
+ break;
+
+ case 0x05:
+ opll->patch[1].AR = (data >> 4) & 15;
+ opll->patch[1].DR = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_EG(CAR(opll,i));
+ }
+ }
+ break;
+
+ case 0x06:
+ opll->patch[0].SL = (data >> 4) & 15;
+ opll->patch[0].RR = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_EG (MOD(opll,i));
+ }
+ }
+ break;
+
+ case 0x07:
+ opll->patch[1].SL = (data >> 4) & 15;
+ opll->patch[1].RR = (data) & 15;
+ for (i = 0; i < 9; i++)
+ {
+ if (opll->patch_number[i] == 0)
+ {
+ UPDATE_EG (CAR(opll,i));
+ }
+ }
+ break;
+
+ case 0x0e:
+ update_rhythm_mode (opll);
+ if (data & 32)
+ {
+ if (data & 0x10)
+ keyOn_BD (opll);
+ else
+ keyOff_BD (opll);
+ if (data & 0x8)
+ keyOn_SD (opll);
+ else
+ keyOff_SD (opll);
+ if (data & 0x4)
+ keyOn_TOM (opll);
+ else
+ keyOff_TOM (opll);
+ if (data & 0x2)
+ keyOn_CYM (opll);
+ else
+ keyOff_CYM (opll);
+ if (data & 0x1)
+ keyOn_HH (opll);
+ else
+ keyOff_HH (opll);
+ }
+ update_key_status (opll);
+
+ UPDATE_ALL (MOD(opll,6));
+ UPDATE_ALL (CAR(opll,6));
+ UPDATE_ALL (MOD(opll,7));
+ UPDATE_ALL (CAR(opll,7));
+ UPDATE_ALL (MOD(opll,8));
+ UPDATE_ALL (CAR(opll,8));
+
+ break;
+
+ case 0x0f:
+ break;
+
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ ch = reg - 0x10;
+ setFnumber (opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));
+ UPDATE_ALL (MOD(opll,ch));
+ UPDATE_ALL (CAR(opll,ch));
+ break;
+
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ ch = reg - 0x20;
+ setFnumber (opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);
+ setBlock (opll, ch, (data >> 1) & 7);
+ setSustine (opll, ch, (data >> 5) & 1);
+ if (data & 0x10)
+ keyOn (opll, ch);
+ else
+ keyOff (opll, ch);
+ UPDATE_ALL (MOD(opll,ch));
+ UPDATE_ALL (CAR(opll,ch));
+ update_key_status (opll);
+ update_rhythm_mode (opll);
+ break;
+
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ i = (data >> 4) & 15;
+ v = data & 15;
+ if ((opll->reg[0x0e] & 32) && (reg >= 0x36))
+ {
+ switch (reg)
+ {
+ case 0x37:
+ setSlotVolume (MOD(opll,7), i << 2);
+ break;
+ case 0x38:
+ setSlotVolume (MOD(opll,8), i << 2);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ setPatch (opll, reg - 0x30, i);
+ }
+ setVolume (opll, reg - 0x30, v << 2);
+ UPDATE_ALL (MOD(opll,reg - 0x30));
+ UPDATE_ALL (CAR(opll,reg - 0x30));
+ break;
+
+ default:
+ break;
+
+ }
+}
+
+void
+OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val)
+{
+ if (adr & 1)
+ OPLL_writeReg (opll, opll->adr, val);
+ else
+ opll->adr = val;
+}
+
+e_uint32
+OPLL_read(OPLL * opll, e_uint32 a)
+{
+ if( !(a&1) )
+ {
+ /* status port */
+ return opll->status;
+ }
+ return 0xff;
+}
+
+#ifndef EMU2413_COMPACTION
+/* STEREO MODE (OPT) */
+void
+OPLL_set_pan (OPLL * opll, e_uint32 ch, e_uint32 pan)
+{
+ opll->pan[ch & 15] = pan & 3;
+}
+
+static void
+calc_stereo (OPLL * opll, e_int32 out[2])
+{
+ e_int32 b[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
+ e_int32 r[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
+ e_int32 i;
+
+ update_ampm (opll);
+ update_noise (opll);
+
+ for(i=0;i<18;i++)
+ {
+ calc_phase(&opll->slot[i],opll->lfo_pm);
+ calc_envelope(&opll->slot[i],opll->lfo_am);
+ }
+
+ for (i = 0; i < 6; i++)
+ if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
+ b[opll->pan[i]] += calc_slot_car (CAR(opll,i), calc_slot_mod (MOD(opll,i)));
+
+
+ if (opll->patch_number[6] <= 15)
+ {
+ if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
+ b[opll->pan[6]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
+ }
+ else
+ {
+ if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
+ r[opll->pan[9]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
+ }
+
+ if (opll->patch_number[7] <= 15)
+ {
+ if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR (opll,7)->eg_mode != FINISH))
+ b[opll->pan[7]] += calc_slot_car (CAR (opll,7), calc_slot_mod (MOD (opll,7)));
+ }
+ else
+ {
+ if (!(opll->mask & OPLL_MASK_HH) && (MOD (opll,7)->eg_mode != FINISH))
+ r[opll->pan[10]] += calc_slot_hat (MOD (opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
+ if (!(opll->mask & OPLL_MASK_SD) && (CAR (opll,7)->eg_mode != FINISH))
+ r[opll->pan[11]] -= calc_slot_snare (CAR (opll,7), opll->noise_seed&1);
+ }
+
+ if (opll->patch_number[8] <= 15)
+ {
+ if (!(opll->mask & OPLL_MASK_CH (8)) && (CAR (opll,8)->eg_mode != FINISH))
+ b[opll->pan[8]] += calc_slot_car (CAR (opll,8), calc_slot_mod (MOD (opll,8)));
+ }
+ else
+ {
+ if (!(opll->mask & OPLL_MASK_TOM) && (MOD (opll,8)->eg_mode != FINISH))
+ r[opll->pan[12]] += calc_slot_tom (MOD (opll,8));
+ if (!(opll->mask & OPLL_MASK_CYM) && (CAR (opll,8)->eg_mode != FINISH))
+ r[opll->pan[13]] -= calc_slot_cym (CAR (opll,8), MOD(opll,7)->pgout);
+ }
+
+ out[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) <<3;
+ out[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) <<3;
+}
+
+void
+OPLL_calc_stereo (OPLL * opll, e_int32 out[2])
+{
+ if (!opll->quality)
+ {
+ calc_stereo (opll, out);
+ return;
+ }
+
+ while (opll->realstep > opll->oplltime)
+ {
+ opll->oplltime += opll->opllstep;
+ opll->sprev[0] = opll->snext[0];
+ opll->sprev[1] = opll->snext[1];
+ calc_stereo (opll, opll->snext);
+ }
+
+ opll->oplltime -= opll->realstep;
+ out[0] = (e_int16) (((double) opll->snext[0] * (opll->opllstep - opll->oplltime)
+ + (double) opll->sprev[0] * opll->oplltime) / opll->opllstep);
+ out[1] = (e_int16) (((double) opll->snext[1] * (opll->opllstep - opll->oplltime)
+ + (double) opll->sprev[1] * opll->oplltime) / opll->opllstep);
+}
+#endif /* EMU2413_COMPACTION */
diff --git a/apps/codecs/libgme/emu2413.h b/apps/codecs/libgme/emu2413.h
index 6a19b102a1..254f042957 100644
--- a/apps/codecs/libgme/emu2413.h
+++ b/apps/codecs/libgme/emu2413.h
@@ -1,164 +1,164 @@
-#ifndef _EMU2413_H_
-#define _EMU2413_H_
-
-#include "blargg_common.h"
-#include "emutypes.h"
-
-#ifdef EMU2413_DLL_EXPORTS
- #define EMU2413_API __declspec(dllexport)
-#elif defined(EMU2413_DLL_IMPORTS)
- #define EMU2413_API __declspec(dllimport)
-#else
- #define EMU2413_API
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AUDIO_MONO_BUFFER_SIZE 1024
-
-#define PI 3.14159265358979323846
-
-enum OPLL_TONE_ENUM {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1, OPLL_281B_TONE=2} ;
-
-/* voice data */
-typedef struct __OPLL_PATCH {
- e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ;
-} OPLL_PATCH ;
-
-/* slot */
-typedef struct __OPLL_SLOT {
-
- OPLL_PATCH *patch;
-
- e_int32 type ; /* 0 : modulator 1 : carrier */
-
- /* OUTPUT */
- e_int32 feedback ;
- e_int32 output[2] ; /* Output value of slot */
-
- /* for Phase Generator (PG) */
- e_uint16 *sintbl ; /* Wavetable */
- e_uint32 phase ; /* Phase */
- e_uint32 dphase ; /* Phase increment amount */
- e_uint32 pgout ; /* output */
-
- /* for Envelope Generator (EG) */
- e_int32 fnum ; /* F-Number */
- e_int32 block ; /* Block */
- e_int32 volume ; /* Current volume */
- e_int32 sustine ; /* Sustine 1 = ON, 0 = OFF */
- e_uint32 tll ; /* Total Level + Key scale level*/
- e_uint32 rks ; /* Key scale offset (Rks) */
- e_int32 eg_mode ; /* Current state */
- e_uint32 eg_phase ; /* Phase */
- e_uint32 eg_dphase ; /* Phase increment amount */
- e_uint32 egout ; /* output */
-
-} OPLL_SLOT ;
-
-/* Mask */
-#define OPLL_MASK_CH(x) (1<<(x))
-#define OPLL_MASK_HH (1<<(9))
-#define OPLL_MASK_CYM (1<<(10))
-#define OPLL_MASK_TOM (1<<(11))
-#define OPLL_MASK_SD (1<<(12))
-#define OPLL_MASK_BD (1<<(13))
-#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
-
-/* opll */
-typedef struct __OPLL {
-
- e_uint32 adr ;
- e_int32 out ;
-
-#ifndef EMU2413_COMPACTION
- e_uint32 realstep ;
- e_uint32 oplltime ;
- e_uint32 opllstep ;
- e_int32 prev, next ;
- e_int32 sprev[2],snext[2];
- e_uint32 pan[16];
-#endif
-
- /* Register */
- e_uint8 reg[0x40] ;
- e_int32 slot_on_flag[18] ;
-
- /* Pitch Modulator */
- e_uint32 pm_phase ;
- e_int32 lfo_pm ;
-
- /* Amp Modulator */
- e_int32 am_phase ;
- e_int32 lfo_am ;
-
- e_uint32 quality;
-
- /* Noise Generator */
- e_uint32 noise_seed ;
-
- /* Channel Data */
- e_int32 patch_number[9];
- e_int32 key_status[9] ;
-
- /* Slot */
- OPLL_SLOT slot[18] ;
-
- /* Voice Data */
- OPLL_PATCH patch[19*2] ;
- e_int32 patch_update[2] ; /* flag for check patch update */
-
- e_uint32 mask ;
- e_uint32 current_mask;
- e_uint32 status;
-
- e_uint32 internal_mute;
- e_int16 buffer[AUDIO_MONO_BUFFER_SIZE];
-} OPLL ;
-
-/* Create Object */
-EMU2413_API void OPLL_new(OPLL *, e_uint32 clk, e_uint32 rate) ;
-EMU2413_API void OPLL_delete(OPLL *) ;
-
-/* Setup */
-EMU2413_API void OPLL_reset(OPLL *) ;
-EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ;
-EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ;
-EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ;
-EMU2413_API void OPLL_set_pan(OPLL *, e_uint32 ch, e_uint32 pan);
-EMU2413_API void OPLL_set_internal_mute(OPLL *, e_uint32 mute);
-EMU2413_API e_uint32 OPLL_is_internal_muted(OPLL *);
-
-/* Port/Register access */
-EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val);
-EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val);
-EMU2413_API e_uint32 OPLL_read(OPLL *, e_uint32 port);
-
-/* Synthsize */
-EMU2413_API e_int16 OPLL_calc(OPLL *) EMU2413_CALC_ICODE;
-EMU2413_API void OPLL_calc_stereo(OPLL *, e_int32 out[2]) ;
-EMU2413_API e_int16 *OPLL_update_buffer(OPLL *, e_uint32 length) ;
-
-/* Misc */
-EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ;
-EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ;
-EMU2413_API void OPLL_forceRefresh(OPLL *) ;
-/* Utility */
-EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ;
-EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ;
-EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ;
-
-/* Channel Mask */
-EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ;
-EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
-
-#define dump2patch OPLL_dump2patch
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+#ifndef _EMU2413_H_
+#define _EMU2413_H_
+
+#include "blargg_common.h"
+#include "emutypes.h"
+
+#ifdef EMU2413_DLL_EXPORTS
+ #define EMU2413_API __declspec(dllexport)
+#elif defined(EMU2413_DLL_IMPORTS)
+ #define EMU2413_API __declspec(dllimport)
+#else
+ #define EMU2413_API
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AUDIO_MONO_BUFFER_SIZE 1024
+
+#define PI 3.14159265358979323846
+
+enum OPLL_TONE_ENUM {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1, OPLL_281B_TONE=2} ;
+
+/* voice data */
+typedef struct __OPLL_PATCH {
+ e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ;
+} OPLL_PATCH ;
+
+/* slot */
+typedef struct __OPLL_SLOT {
+
+ OPLL_PATCH *patch;
+
+ e_int32 type ; /* 0 : modulator 1 : carrier */
+
+ /* OUTPUT */
+ e_int32 feedback ;
+ e_int32 output[2] ; /* Output value of slot */
+
+ /* for Phase Generator (PG) */
+ e_uint16 *sintbl ; /* Wavetable */
+ e_uint32 phase ; /* Phase */
+ e_uint32 dphase ; /* Phase increment amount */
+ e_uint32 pgout ; /* output */
+
+ /* for Envelope Generator (EG) */
+ e_int32 fnum ; /* F-Number */
+ e_int32 block ; /* Block */
+ e_int32 volume ; /* Current volume */
+ e_int32 sustine ; /* Sustine 1 = ON, 0 = OFF */
+ e_uint32 tll ; /* Total Level + Key scale level*/
+ e_uint32 rks ; /* Key scale offset (Rks) */
+ e_int32 eg_mode ; /* Current state */
+ e_uint32 eg_phase ; /* Phase */
+ e_uint32 eg_dphase ; /* Phase increment amount */
+ e_uint32 egout ; /* output */
+
+} OPLL_SLOT ;
+
+/* Mask */
+#define OPLL_MASK_CH(x) (1<<(x))
+#define OPLL_MASK_HH (1<<(9))
+#define OPLL_MASK_CYM (1<<(10))
+#define OPLL_MASK_TOM (1<<(11))
+#define OPLL_MASK_SD (1<<(12))
+#define OPLL_MASK_BD (1<<(13))
+#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
+
+/* opll */
+typedef struct __OPLL {
+
+ e_uint32 adr ;
+ e_int32 out ;
+
+#ifndef EMU2413_COMPACTION
+ e_uint32 realstep ;
+ e_uint32 oplltime ;
+ e_uint32 opllstep ;
+ e_int32 prev, next ;
+ e_int32 sprev[2],snext[2];
+ e_uint32 pan[16];
+#endif
+
+ /* Register */
+ e_uint8 reg[0x40] ;
+ e_int32 slot_on_flag[18] ;
+
+ /* Pitch Modulator */
+ e_uint32 pm_phase ;
+ e_int32 lfo_pm ;
+
+ /* Amp Modulator */
+ e_int32 am_phase ;
+ e_int32 lfo_am ;
+
+ e_uint32 quality;
+
+ /* Noise Generator */
+ e_uint32 noise_seed ;
+
+ /* Channel Data */
+ e_int32 patch_number[9];
+ e_int32 key_status[9] ;
+
+ /* Slot */
+ OPLL_SLOT slot[18] ;
+
+ /* Voice Data */
+ OPLL_PATCH patch[19*2] ;
+ e_int32 patch_update[2] ; /* flag for check patch update */
+
+ e_uint32 mask ;
+ e_uint32 current_mask;
+ e_uint32 status;
+
+ e_uint32 internal_mute;
+ e_int16 buffer[AUDIO_MONO_BUFFER_SIZE];
+} OPLL ;
+
+/* Create Object */
+EMU2413_API void OPLL_new(OPLL *, e_uint32 clk, e_uint32 rate) ;
+EMU2413_API void OPLL_delete(OPLL *) ;
+
+/* Setup */
+EMU2413_API void OPLL_reset(OPLL *) ;
+EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ;
+EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ;
+EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ;
+EMU2413_API void OPLL_set_pan(OPLL *, e_uint32 ch, e_uint32 pan);
+EMU2413_API void OPLL_set_internal_mute(OPLL *, e_uint32 mute);
+EMU2413_API e_uint32 OPLL_is_internal_muted(OPLL *);
+
+/* Port/Register access */
+EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val);
+EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val);
+EMU2413_API e_uint32 OPLL_read(OPLL *, e_uint32 port);
+
+/* Synthsize */
+EMU2413_API e_int16 OPLL_calc(OPLL *) EMU2413_CALC_ICODE;
+EMU2413_API void OPLL_calc_stereo(OPLL *, e_int32 out[2]) ;
+EMU2413_API e_int16 *OPLL_update_buffer(OPLL *, e_uint32 length) ;
+
+/* Misc */
+EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ;
+EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ;
+EMU2413_API void OPLL_forceRefresh(OPLL *) ;
+/* Utility */
+EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ;
+EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ;
+EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ;
+
+/* Channel Mask */
+EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ;
+EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
+
+#define dump2patch OPLL_dump2patch
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/apps/codecs/libgme/emutables.h b/apps/codecs/libgme/emutables.h
index e34f100bc4..739c8c390a 100644
--- a/apps/codecs/libgme/emutables.h
+++ b/apps/codecs/libgme/emutables.h
@@ -1,210 +1,210 @@
-#ifndef _EMUTABLES_H_
-#define _EMUTABLES_H_
-
-/* Precalculated emu2413 tables for use in Rockbox,
- Calculated for 44Khz sampling rate */
-
-#include "emutypes.h"
-
-static const e_uint16 sin_coeff[] = {
- 255, 203, 171, 152, 139, 129, 120,
- 113, 107, 102, 97, 92, 88, 85,
- 81, 78, 75, 72, 70, 67, 65,
- 63, 61, 59, 57, 55, 53, 52,
- 50, 48, 47, 45, 44, 43, 41,
- 40, 39, 38, 37, 35, 34, 33,
- 32, 31, 30, 29, 28, 28, 27,
- 26, 25, 24, 23, 23, 22, 21,
- 21, 20, 19, 19, 18, 17, 17,
- 16, 16, 15, 14, 14, 13, 13,
- 12, 12, 11, 11, 11, 10, 10,
- 9, 9, 8, 8, 8, 7, 7,
- 7, 6, 6, 6, 5, 5, 5,
- 4, 4, 4, 4, 3, 3, 3,
- 3, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0,
-};
-
-static const e_int16 pm_coeff[] = {
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 258, 258, 258, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 253, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254,
- 254, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255,
-};
-
-static const e_int8 am_coeff[] = {
- 13, 13, 13, 13, 13, 14, 14,
- 14, 14, 14, 15, 15, 15, 15,
- 15, 16, 16, 16, 16, 16, 17,
- 17, 17, 17, 17, 18, 18, 18,
- 18, 18, 19, 19, 19, 19, 19,
- 20, 20, 20, 20, 20, 21, 21,
- 21, 21, 21, 22, 22, 22, 22,
- 22, 23, 23, 23, 23, 23, 24,
- 24, 24, 24, 24, 25, 25, 25,
- 25, 26, 25, 25, 25, 25, 24,
- 24, 24, 24, 24, 23, 23, 23,
- 23, 23, 22, 22, 22, 22, 22,
- 21, 21, 21, 21, 21, 20, 20,
- 20, 20, 20, 19, 19, 19, 19,
- 19, 18, 18, 18, 18, 18, 17,
- 17, 17, 17, 17, 16, 16, 16,
- 16, 16, 15, 15, 15, 15, 15,
- 14, 14, 14, 14, 14, 13, 13,
- 13, 13, 13, 12, 12, 12, 12,
- 11, 11, 11, 11, 11, 10, 10,
- 10, 10, 10, 9, 9, 9, 9,
- 9, 8, 8, 8, 8, 8, 7,
- 7, 7, 7, 7, 6, 6, 6,
- 6, 6, 5, 5, 5, 5, 5,
- 4, 4, 4, 4, 4, 3, 3,
- 3, 3, 3, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 2,
- 2, 2, 2, 2, 3, 3, 3,
- 3, 3, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 6, 6,
- 6, 6, 6, 7, 7, 7, 7,
- 7, 8, 8, 8, 8, 8, 9,
- 9, 9, 9, 9, 10, 10, 10,
- 10, 10, 11, 11, 11, 11, 11,
- 12, 12, 12, 12,
-};
-
-static const e_int16 db2lin_coeff[] = {
- 255, 249, 244, 239, 233, 228, 224,
- 219, 214, 209, 205, 201, 196, 192,
- 188, 184, 180, 176, 172, 169, 165,
- 162, 158, 155, 151, 148, 145, 142,
- 139, 136, 133, 130, 127, 125, 122,
- 119, 117, 114, 112, 109, 107, 105,
- 102, 100, 98, 96, 94, 92, 90,
- 88, 86, 84, 82, 81, 79, 77,
- 76, 74, 72, 71, 69, 68, 66,
- 65, 64, 62, 61, 60, 58, 57,
- 56, 55, 53, 52, 51, 50, 49,
- 48, 47, 46, 45, 44, 43, 42,
- 41, 40, 39, 38, 38, 37, 36,
- 35, 34, 34, 33, 32, 32, 31,
- 30, 30, 29, 28, 28, 27, 27,
- 26, 25, 25, 24, 24, 23, 23,
- 22, 22, 21, 21, 20, 20, 19,
- 19, 19, 18, 18, 17, 17, 17,
- 16, 16, 16, 15, 15, 15, 14,
- 14, 14, 13, 13, 13, 12, 12,
- 12, 12, 11, 11, 11, 11, 10,
- 10, 10, 10, 10, 9, 9, 9,
- 9, 8, 8, 8, 8, 8, 8,
- 7, 7, 7, 7, 7, 7, 6,
- 6, 6, 6, 6, 6, 6, 5,
- 5, 5, 5, 5, 5, 5, 5,
- 5, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,
- 0,
-};
-
-static const e_uint16 ar_adjust_coeff[] = {
- 127, 108, 98, 90, 84, 80, 75,
- 72, 69, 66, 64, 61, 59, 57,
- 56, 54, 52, 51, 49, 48, 47,
- 45, 44, 43, 42, 41, 40, 39,
- 38, 37, 36, 36, 35, 34, 33,
- 33, 32, 31, 30, 30, 29, 29,
- 28, 27, 27, 26, 26, 25, 24,
- 24, 23, 23, 22, 22, 21, 21,
- 21, 20, 20, 19, 19, 18, 18,
- 17, 17, 17, 16, 16, 15, 15,
- 15, 14, 14, 14, 13, 13, 13,
- 12, 12, 12, 11, 11, 11, 10,
- 10, 10, 9, 9, 9, 9, 8,
- 8, 8, 7, 7, 7, 7, 6,
- 6, 6, 6, 5, 5, 5, 4,
- 4, 4, 4, 4, 3, 3, 3,
- 3, 2, 2, 2, 2, 1, 1,
- 1, 1, 1, 0, 0, 0, 0,
- 0,
-};
-
-#endif
+#ifndef _EMUTABLES_H_
+#define _EMUTABLES_H_
+
+/* Precalculated emu2413 tables for use in Rockbox,
+ Calculated for 44Khz sampling rate */
+
+#include "emutypes.h"
+
+static const e_uint16 sin_coeff[] = {
+ 255, 203, 171, 152, 139, 129, 120,
+ 113, 107, 102, 97, 92, 88, 85,
+ 81, 78, 75, 72, 70, 67, 65,
+ 63, 61, 59, 57, 55, 53, 52,
+ 50, 48, 47, 45, 44, 43, 41,
+ 40, 39, 38, 37, 35, 34, 33,
+ 32, 31, 30, 29, 28, 28, 27,
+ 26, 25, 24, 23, 23, 22, 21,
+ 21, 20, 19, 19, 18, 17, 17,
+ 16, 16, 15, 14, 14, 13, 13,
+ 12, 12, 11, 11, 11, 10, 10,
+ 9, 9, 8, 8, 8, 7, 7,
+ 7, 6, 6, 6, 5, 5, 5,
+ 4, 4, 4, 4, 3, 3, 3,
+ 3, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+};
+
+static const e_int16 pm_coeff[] = {
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 258, 258, 258, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 253, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254,
+ 254, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255,
+};
+
+static const e_int8 am_coeff[] = {
+ 13, 13, 13, 13, 13, 14, 14,
+ 14, 14, 14, 15, 15, 15, 15,
+ 15, 16, 16, 16, 16, 16, 17,
+ 17, 17, 17, 17, 18, 18, 18,
+ 18, 18, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 21, 21,
+ 21, 21, 21, 22, 22, 22, 22,
+ 22, 23, 23, 23, 23, 23, 24,
+ 24, 24, 24, 24, 25, 25, 25,
+ 25, 26, 25, 25, 25, 25, 24,
+ 24, 24, 24, 24, 23, 23, 23,
+ 23, 23, 22, 22, 22, 22, 22,
+ 21, 21, 21, 21, 21, 20, 20,
+ 20, 20, 20, 19, 19, 19, 19,
+ 19, 18, 18, 18, 18, 18, 17,
+ 17, 17, 17, 17, 16, 16, 16,
+ 16, 16, 15, 15, 15, 15, 15,
+ 14, 14, 14, 14, 14, 13, 13,
+ 13, 13, 13, 12, 12, 12, 12,
+ 11, 11, 11, 11, 11, 10, 10,
+ 10, 10, 10, 9, 9, 9, 9,
+ 9, 8, 8, 8, 8, 8, 7,
+ 7, 7, 7, 7, 6, 6, 6,
+ 6, 6, 5, 5, 5, 5, 5,
+ 4, 4, 4, 4, 4, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 3, 3, 3,
+ 3, 3, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 6, 6,
+ 6, 6, 6, 7, 7, 7, 7,
+ 7, 8, 8, 8, 8, 8, 9,
+ 9, 9, 9, 9, 10, 10, 10,
+ 10, 10, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12,
+};
+
+static const e_int16 db2lin_coeff[] = {
+ 255, 249, 244, 239, 233, 228, 224,
+ 219, 214, 209, 205, 201, 196, 192,
+ 188, 184, 180, 176, 172, 169, 165,
+ 162, 158, 155, 151, 148, 145, 142,
+ 139, 136, 133, 130, 127, 125, 122,
+ 119, 117, 114, 112, 109, 107, 105,
+ 102, 100, 98, 96, 94, 92, 90,
+ 88, 86, 84, 82, 81, 79, 77,
+ 76, 74, 72, 71, 69, 68, 66,
+ 65, 64, 62, 61, 60, 58, 57,
+ 56, 55, 53, 52, 51, 50, 49,
+ 48, 47, 46, 45, 44, 43, 42,
+ 41, 40, 39, 38, 38, 37, 36,
+ 35, 34, 34, 33, 32, 32, 31,
+ 30, 30, 29, 28, 28, 27, 27,
+ 26, 25, 25, 24, 24, 23, 23,
+ 22, 22, 21, 21, 20, 20, 19,
+ 19, 19, 18, 18, 17, 17, 17,
+ 16, 16, 16, 15, 15, 15, 14,
+ 14, 14, 13, 13, 13, 12, 12,
+ 12, 12, 11, 11, 11, 11, 10,
+ 10, 10, 10, 10, 9, 9, 9,
+ 9, 8, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 6,
+ 6, 6, 6, 6, 6, 6, 5,
+ 5, 5, 5, 5, 5, 5, 5,
+ 5, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0,
+};
+
+static const e_uint16 ar_adjust_coeff[] = {
+ 127, 108, 98, 90, 84, 80, 75,
+ 72, 69, 66, 64, 61, 59, 57,
+ 56, 54, 52, 51, 49, 48, 47,
+ 45, 44, 43, 42, 41, 40, 39,
+ 38, 37, 36, 36, 35, 34, 33,
+ 33, 32, 31, 30, 30, 29, 29,
+ 28, 27, 27, 26, 26, 25, 24,
+ 24, 23, 23, 22, 22, 21, 21,
+ 21, 20, 20, 19, 19, 18, 18,
+ 17, 17, 17, 16, 16, 15, 15,
+ 15, 14, 14, 14, 13, 13, 13,
+ 12, 12, 12, 11, 11, 11, 10,
+ 10, 10, 9, 9, 9, 9, 8,
+ 8, 8, 7, 7, 7, 7, 6,
+ 6, 6, 6, 5, 5, 5, 4,
+ 4, 4, 4, 4, 3, 3, 3,
+ 3, 2, 2, 2, 2, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0,
+ 0,
+};
+
+#endif
diff --git a/apps/codecs/libgme/emutypes.h b/apps/codecs/libgme/emutypes.h
index bf5d7e1bf2..bc523db072 100644
--- a/apps/codecs/libgme/emutypes.h
+++ b/apps/codecs/libgme/emutypes.h
@@ -1,41 +1,41 @@
-#ifndef _EMUTYPES_H_
-#define _EMUTYPES_H_
-
-#if defined(_MSC_VER)
-#define INLINE __forceinline
-#elif defined(__GNUC__)
-#define INLINE __inline__
-#elif defined(_MWERKS_)
-#define INLINE inline
-#else
-#define INLINE
-#endif
-
-#if defined(EMU_DLL_IMPORTS)
-#define EMU2149_DLL_IMPORTS
-#define EMU2212_DLL_IMPORTS
-#define EMU2413_DLL_IMPORTS
-#define EMU8950_DLL_IMPORTS
-#define EMU76489_DLL_IMPORTS
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned int e_uint;
-typedef signed int e_int;
-
-typedef unsigned char e_uint8 ;
-typedef signed char e_int8 ;
-
-typedef unsigned short e_uint16 ;
-typedef signed short e_int16 ;
-
-typedef unsigned int e_uint32 ;
-typedef signed int e_int32 ;
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+#ifndef _EMUTYPES_H_
+#define _EMUTYPES_H_
+
+#if defined(_MSC_VER)
+#define INLINE __forceinline
+#elif defined(__GNUC__)
+#define INLINE __inline__
+#elif defined(_MWERKS_)
+#define INLINE inline
+#else
+#define INLINE
+#endif
+
+#if defined(EMU_DLL_IMPORTS)
+#define EMU2149_DLL_IMPORTS
+#define EMU2212_DLL_IMPORTS
+#define EMU2413_DLL_IMPORTS
+#define EMU8950_DLL_IMPORTS
+#define EMU76489_DLL_IMPORTS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int e_uint;
+typedef signed int e_int;
+
+typedef unsigned char e_uint8 ;
+typedef signed char e_int8 ;
+
+typedef unsigned short e_uint16 ;
+typedef signed short e_int16 ;
+
+typedef unsigned int e_uint32 ;
+typedef signed int e_int32 ;
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/apps/codecs/libgme/hes_apu_adpcm.c b/apps/codecs/libgme/hes_apu_adpcm.c
index 69ac7120d0..de9b894f5d 100644
--- a/apps/codecs/libgme/hes_apu_adpcm.c
+++ b/apps/codecs/libgme/hes_apu_adpcm.c
@@ -1,297 +1,297 @@
-// Game_Music_Emu 0.6-pre. 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 */
-
-
-void Adpcm_init( struct Hes_Apu_Adpcm* this )
-{
- this->output = NULL;
- memset( &this->state, 0, sizeof( this->state ) );
- Adpcm_reset( this );
-}
-
-void Adpcm_reset( struct Hes_Apu_Adpcm* this )
-{
- this->last_time = 0;
- this->next_timer = 0;
- this->last_amp = 0;
-
- memset( &this->state.pcmbuf, 0, sizeof(this->state.pcmbuf) );
- memset( &this->state.port, 0, sizeof(this->state.port) );
-
- this->state.ad_sample = 0;
- this->state.ad_ref_index = 0;
-
- this->state.addr = 0;
- this->state.freq = 0;
- this->state.writeptr = 0;
- this->state.readptr = 0;
- this->state.playflag = 0;
- this->state.repeatflag = 0;
- this->state.length = 0;
- this->state.volume = 0xFF;
- this->state.fadetimer = 0;
- this->state.fadecount = 0;
-}
-
-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
-};
-
-static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code );
-static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code )
-{
- struct State* state = &this->state;
- 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;
-}
-
-static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time );
-static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
-{
- struct State* state = &this->state;
- int volume = state->volume;
- int fadetimer = state->fadetimer;
- int fadecount = state->fadecount;
- int last_time = this->last_time;
- int next_timer = this->next_timer;
- int last_amp = this->last_amp;
-
- struct 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; // 7159091/1000;
- }
- int amp;
- if ( state->ad_low_nibble )
- {
- amp = Adpcm_decode( this, 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( this, 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( &this->synth, last_time, delta, output );
- }
- last_time += state->freq;
- }
-
- if ( !state->playflag )
- {
- while ( next_timer <= end_time ) next_timer += 7159; // 7159091/1000
- 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 Adpcm_write_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr, int data )
-{
- if ( time > this->last_time ) Adpcm_run_until( this, time );
- struct State* state = &this->state;
-
- 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 Adpcm_read_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr )
-{
- if ( time > this->last_time ) Adpcm_run_until( this, time );
-
- struct State* state = &this->state;
- 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 Adpcm_end_frame( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
-{
- Adpcm_run_until( this, end_time );
- this->last_time -= end_time;
- this->next_timer -= end_time;
- check( last_time >= 0 );
- if ( this->output )
- Blip_set_modified( this->output );
-}
+// Game_Music_Emu 0.6-pre. 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 */
+
+
+void Adpcm_init( struct Hes_Apu_Adpcm* this )
+{
+ this->output = NULL;
+ memset( &this->state, 0, sizeof( this->state ) );
+ Adpcm_reset( this );
+}
+
+void Adpcm_reset( struct Hes_Apu_Adpcm* this )
+{
+ this->last_time = 0;
+ this->next_timer = 0;
+ this->last_amp = 0;
+
+ memset( &this->state.pcmbuf, 0, sizeof(this->state.pcmbuf) );
+ memset( &this->state.port, 0, sizeof(this->state.port) );
+
+ this->state.ad_sample = 0;
+ this->state.ad_ref_index = 0;
+
+ this->state.addr = 0;
+ this->state.freq = 0;
+ this->state.writeptr = 0;
+ this->state.readptr = 0;
+ this->state.playflag = 0;
+ this->state.repeatflag = 0;
+ this->state.length = 0;
+ this->state.volume = 0xFF;
+ this->state.fadetimer = 0;
+ this->state.fadecount = 0;
+}
+
+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
+};
+
+static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code );
+static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code )
+{
+ struct State* state = &this->state;
+ 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;
+}
+
+static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time );
+static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
+{
+ struct State* state = &this->state;
+ int volume = state->volume;
+ int fadetimer = state->fadetimer;
+ int fadecount = state->fadecount;
+ int last_time = this->last_time;
+ int next_timer = this->next_timer;
+ int last_amp = this->last_amp;
+
+ struct 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; // 7159091/1000;
+ }
+ int amp;
+ if ( state->ad_low_nibble )
+ {
+ amp = Adpcm_decode( this, 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( this, 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( &this->synth, last_time, delta, output );
+ }
+ last_time += state->freq;
+ }
+
+ if ( !state->playflag )
+ {
+ while ( next_timer <= end_time ) next_timer += 7159; // 7159091/1000
+ 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 Adpcm_write_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr, int data )
+{
+ if ( time > this->last_time ) Adpcm_run_until( this, time );
+ struct State* state = &this->state;
+
+ 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 Adpcm_read_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr )
+{
+ if ( time > this->last_time ) Adpcm_run_until( this, time );
+
+ struct State* state = &this->state;
+ 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 Adpcm_end_frame( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
+{
+ Adpcm_run_until( this, end_time );
+ this->last_time -= end_time;
+ this->next_timer -= end_time;
+ check( last_time >= 0 );
+ if ( this->output )
+ Blip_set_modified( this->output );
+}
diff --git a/apps/codecs/libgme/inflate/mbreader.c b/apps/codecs/libgme/inflate/mbreader.c
index 96e45cd6c8..825787927c 100644
--- a/apps/codecs/libgme/inflate/mbreader.c
+++ b/apps/codecs/libgme/inflate/mbreader.c
@@ -1,16 +1,16 @@
-
-/* Memory buffer reader, simulates file read
- @ gama
-*/
-
-#include "mbreader.h"
-
-int mbread(struct mbreader_t *md, void *buf, size_t n)
-{
- if (!md) return -1;
- size_t read_bytes = (md->offset+n) > md->size ?
- md->size-md->offset : n;
- memcpy(buf,md->ptr + md->offset,read_bytes);
- md->offset += read_bytes;
- return read_bytes;
-}
+
+/* Memory buffer reader, simulates file read
+ @ gama
+*/
+
+#include "mbreader.h"
+
+int mbread(struct mbreader_t *md, void *buf, size_t n)
+{
+ if (!md) return -1;
+ size_t read_bytes = (md->offset+n) > md->size ?
+ md->size-md->offset : n;
+ memcpy(buf,md->ptr + md->offset,read_bytes);
+ md->offset += read_bytes;
+ return read_bytes;
+}
diff --git a/apps/codecs/libgme/inflate/mbreader.h b/apps/codecs/libgme/inflate/mbreader.h
index 6427f18231..d345c0c424 100644
--- a/apps/codecs/libgme/inflate/mbreader.h
+++ b/apps/codecs/libgme/inflate/mbreader.h
@@ -1,15 +1,15 @@
-
-#ifndef MBREADER_H
-#define MBREADER_H
-
-#include "codeclib.h"
-
-struct mbreader_t {
- const char *ptr;
- size_t size;
- size_t offset;
-};
-
-int mbread(struct mbreader_t *md, void *buf, size_t n);
-
-#endif
+
+#ifndef MBREADER_H
+#define MBREADER_H
+
+#include "codeclib.h"
+
+struct mbreader_t {
+ const char *ptr;
+ size_t size;
+ size_t offset;
+};
+
+int mbread(struct mbreader_t *md, void *buf, size_t n);
+
+#endif
diff --git a/apps/codecs/libgme/kss_cpu.c b/apps/codecs/libgme/kss_cpu.c
index 891a7df255..20601e608f 100644
--- a/apps/codecs/libgme/kss_cpu.c
+++ b/apps/codecs/libgme/kss_cpu.c
@@ -1,35 +1,35 @@
-// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
-
-#include "kss_emu.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( this, TIME(), addr, data )
-#define IN_PORT( addr ) cpu_in( this, TIME(), addr )
-#define WRITE_MEM( addr, data ) {FLUSH_TIME(); cpu_write( this, addr, data );}
-#define IDLE_ADDR idle_addr
-
-#define CPU_BEGIN \
-bool run_cpu( struct Kss_Emu* this, kss_time_t end_time )\
-{\
- struct Z80_Cpu *cpu = &this->cpu; \
- Z80_set_end_time( cpu, end_time );
-
- #include "z80_cpu_run.h"
-
- return warning;
-}
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "kss_emu.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( this, TIME(), addr, data )
+#define IN_PORT( addr ) cpu_in( this, TIME(), addr )
+#define WRITE_MEM( addr, data ) {FLUSH_TIME(); cpu_write( this, addr, data );}
+#define IDLE_ADDR idle_addr
+
+#define CPU_BEGIN \
+bool run_cpu( struct Kss_Emu* this, kss_time_t end_time )\
+{\
+ struct Z80_Cpu *cpu = &this->cpu; \
+ Z80_set_end_time( cpu, end_time );
+
+ #include "z80_cpu_run.h"
+
+ return warning;
+}
diff --git a/apps/codecs/libgme/nes_cpu_run.h b/apps/codecs/libgme/nes_cpu_run.h
index 5b964d5070..fd1fea9659 100644
--- a/apps/codecs/libgme/nes_cpu_run.h
+++ b/apps/codecs/libgme/nes_cpu_run.h
@@ -1,1122 +1,1122 @@
-// 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
-#ifdef 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 ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
-#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
-#define WORD( n ) ((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
- struct 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 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;
-
- // 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
+#ifdef 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 ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
+#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
+#define WORD( n ) ((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
+ struct 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 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;
+
+ // 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 --git a/apps/codecs/libgme/nes_vrc7_apu.c b/apps/codecs/libgme/nes_vrc7_apu.c
index 95bc676c26..8d3c2e88a6 100644
--- a/apps/codecs/libgme/nes_vrc7_apu.c
+++ b/apps/codecs/libgme/nes_vrc7_apu.c
@@ -1,88 +1,88 @@
-
-#include "nes_vrc7_apu.h"
-#include "blargg_source.h"
-
-int const period = 36; // NES CPU clocks per FM clock
-
-void Vrc7_init( struct Nes_Vrc7_Apu* this )
-{
- Synth_init( &this->synth );
-
- OPLL_new ( &this->opll, 3579545, 3579545 / 72 );
- OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
-
- this->osc.output = 0;
- this->osc.last_amp = 0;
- this->mask = 0;
-
- Vrc7_volume( this, (int)FP_ONE_VOLUME );
- Vrc7_reset( this );
-}
-
-void Vrc7_reset( struct Nes_Vrc7_Apu* this )
-{
- this->addr = 0;
- this->next_time = 0;
- this->osc.last_amp = 0;
-
- OPLL_reset (&this->opll);
- OPLL_setMask(&this->opll, this->mask);
-}
-
-void Vrc7_set_rate( struct Nes_Vrc7_Apu* this, int r )
-{
- OPLL_set_quality( &this->opll, r < 44100 ? 0 : 1 );
-}
-
-void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int data )
-{
- this->addr = data;
-}
-
-void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time );
-void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t time, int data )
-{
- if ( time > this->next_time )
- Vrc7_run_until( this, time );
-
- OPLL_writeIO( &this->opll, 0, this->addr );
- OPLL_writeIO( &this->opll, 1, data );
-}
-
-void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t time )
-{
- if ( time > this->next_time )
- Vrc7_run_until( this, time );
-
- this->next_time -= time;
- assert( this->next_time >= 0 );
-
- if ( this->osc.output )
- Blip_set_modified( this->osc.output );
-}
-
-void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time )
-{
- require( end_time > this->next_time );
-
- blip_time_t time = this->next_time;
- OPLL* opll = &this->opll; // cache
- struct Blip_Buffer* const output = this-> osc.output;
- if ( output )
- {
- do
- {
- int amp = OPLL_calc( opll ) << 1;
- int delta = amp - this->osc.last_amp;
- if ( delta )
- {
- this->osc.last_amp = amp;
- Synth_offset_inline( &this->synth, time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
- }
-
- this->next_time = time;
-}
+
+#include "nes_vrc7_apu.h"
+#include "blargg_source.h"
+
+int const period = 36; // NES CPU clocks per FM clock
+
+void Vrc7_init( struct Nes_Vrc7_Apu* this )
+{
+ Synth_init( &this->synth );
+
+ OPLL_new ( &this->opll, 3579545, 3579545 / 72 );
+ OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
+
+ this->osc.output = 0;
+ this->osc.last_amp = 0;
+ this->mask = 0;
+
+ Vrc7_volume( this, (int)FP_ONE_VOLUME );
+ Vrc7_reset( this );
+}
+
+void Vrc7_reset( struct Nes_Vrc7_Apu* this )
+{
+ this->addr = 0;
+ this->next_time = 0;
+ this->osc.last_amp = 0;
+
+ OPLL_reset (&this->opll);
+ OPLL_setMask(&this->opll, this->mask);
+}
+
+void Vrc7_set_rate( struct Nes_Vrc7_Apu* this, int r )
+{
+ OPLL_set_quality( &this->opll, r < 44100 ? 0 : 1 );
+}
+
+void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int data )
+{
+ this->addr = data;
+}
+
+void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time );
+void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t time, int data )
+{
+ if ( time > this->next_time )
+ Vrc7_run_until( this, time );
+
+ OPLL_writeIO( &this->opll, 0, this->addr );
+ OPLL_writeIO( &this->opll, 1, data );
+}
+
+void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t time )
+{
+ if ( time > this->next_time )
+ Vrc7_run_until( this, time );
+
+ this->next_time -= time;
+ assert( this->next_time >= 0 );
+
+ if ( this->osc.output )
+ Blip_set_modified( this->osc.output );
+}
+
+void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time )
+{
+ require( end_time > this->next_time );
+
+ blip_time_t time = this->next_time;
+ OPLL* opll = &this->opll; // cache
+ struct Blip_Buffer* const output = this-> osc.output;
+ if ( output )
+ {
+ do
+ {
+ int amp = OPLL_calc( opll ) << 1;
+ int delta = amp - this->osc.last_amp;
+ if ( delta )
+ {
+ this->osc.last_amp = amp;
+ Synth_offset_inline( &this->synth, time, delta, output );
+ }
+ time += period;
+ }
+ while ( time < end_time );
+ }
+
+ this->next_time = time;
+}
diff --git a/apps/codecs/libgme/opl_apu.c b/apps/codecs/libgme/opl_apu.c
index 64b2714b81..b573baef11 100644
--- a/apps/codecs/libgme/opl_apu.c
+++ b/apps/codecs/libgme/opl_apu.c
@@ -1,198 +1,198 @@
-#include "opl_apu.h"
-
-#include "blargg_source.h"
-
-/* NOTE: Removed unused chips ~ gama */
-
-blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type )
-{
- Synth_init( &this->synth );
-
- this->type_ = type;
- this->clock_ = clock;
- this->rate_ = rate;
- this->period_ = period;
- Opl_set_output( this, 0 );
- Opl_volume( this, (int)FP_ONE_VOLUME );
-
- switch (type)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- OPLL_new ( &this->opll, clock, rate );
- OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
- break;
- case type_vrc7:
- OPLL_new ( &this->opll, clock, rate );
- OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
- break;
- case type_msxaudio:
- OPL_init( &this->opl, this->opl_memory, sizeof this->opl_memory );
- OPL_setSampleRate( &this->opl, rate, clock );
- OPL_setInternalVolume(&this->opl, 1 << 13);
- break;
- }
-
- Opl_reset( this );
- return 0;
-}
-
-void Opl_shutdown( struct Opl_Apu* this )
-{
- switch (this->type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- OPLL_delete( &this->opll );
- break;
- case type_msxaudio: break;
- }
-}
-
-void Opl_reset( struct Opl_Apu* this )
-{
- this->addr = 0;
- this->next_time = 0;
- this->last_amp = 0;
-
- switch (this->type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- OPLL_reset( &this->opll );
- OPLL_setMask( &this->opll, 0 );
- break;
- case type_msxaudio:
- OPL_reset( &this->opl );
- break;
- }
-}
-
-static void run_until( struct Opl_Apu* this, blip_time_t end_time );
-void Opl_write_data( struct Opl_Apu* this, blip_time_t time, int data )
-{
- run_until( this, time );
- switch (this->type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- OPLL_writeIO( &this->opll, 0, this->addr );
- OPLL_writeIO( &this->opll, 1, data );
- break;
- case type_msxaudio:
- OPL_writeReg( &this->opl, this->addr, data );
- break;
- }
-}
-
-int Opl_read( struct Opl_Apu* this, blip_time_t time, int port )
-{
- run_until( this, time );
- switch (this->type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- return OPLL_read( &this->opll, port );
- case type_msxaudio:
- return OPL_readStatus( &this->opl );
- }
-
- return 0;
-}
-
-void Opl_end_frame( struct Opl_Apu* this, blip_time_t time )
-{
- run_until( this, time );
- this->next_time -= time;
-
- if ( this->output_ )
- Blip_set_modified( this->output_ );
-}
-
-static void run_until( struct Opl_Apu* this, blip_time_t end_time )
-{
- if ( end_time > this->next_time )
- {
- blip_time_t time_delta = end_time - this->next_time;
- blip_time_t time = this->next_time;
- unsigned count = time_delta / this->period_ + 1;
- switch (this->type_)
- {
- case type_opll:
- case type_msxmusic:
- case type_smsfmunit:
- case type_vrc7:
- {
- OPLL* opll = &this->opll; // cache
- struct Blip_Buffer* const output = this->output_;
- while ( count > 0 )
- {
- unsigned todo = count;
- if ( todo > 1024 ) todo = 1024;
- short *buffer = OPLL_update_buffer(opll, todo);
-
- if ( output && buffer )
- {
- int last_amp = this->last_amp;
- unsigned i;
- for ( i = 0; i < todo; i++ )
- {
- int amp = buffer [i];
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- Synth_offset_inline( &this->synth, time, delta, output );
- }
- time += this->period_;
- }
- this->last_amp = last_amp;
- }
- count -= todo;
- }
- }
- break;
- case type_msxaudio:
- {
- struct Y8950* opl = &this->opl;
- struct Blip_Buffer* const output = this->output_;
- while ( count > 0 )
- {
- unsigned todo = count;
- if ( todo > 1024 ) todo = 1024;
- int *buffer = OPL_updateBuffer(opl, todo);
-
- if ( output && buffer )
- {
- int last_amp = this->last_amp;
- unsigned i;
- for ( i = 0; i < todo; i++ )
- {
- int amp = buffer [i];
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- Synth_offset_inline( &this->synth, time, delta, output );
- }
- time += this->period_;
- }
- this->last_amp = last_amp;
- }
- count -= todo;
- }
- }
- break;
- }
- this->next_time = time;
- }
-}
+#include "opl_apu.h"
+
+#include "blargg_source.h"
+
+/* NOTE: Removed unused chips ~ gama */
+
+blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type )
+{
+ Synth_init( &this->synth );
+
+ this->type_ = type;
+ this->clock_ = clock;
+ this->rate_ = rate;
+ this->period_ = period;
+ Opl_set_output( this, 0 );
+ Opl_volume( this, (int)FP_ONE_VOLUME );
+
+ switch (type)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ OPLL_new ( &this->opll, clock, rate );
+ OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
+ break;
+ case type_vrc7:
+ OPLL_new ( &this->opll, clock, rate );
+ OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
+ break;
+ case type_msxaudio:
+ OPL_init( &this->opl, this->opl_memory, sizeof this->opl_memory );
+ OPL_setSampleRate( &this->opl, rate, clock );
+ OPL_setInternalVolume(&this->opl, 1 << 13);
+ break;
+ }
+
+ Opl_reset( this );
+ return 0;
+}
+
+void Opl_shutdown( struct Opl_Apu* this )
+{
+ switch (this->type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ OPLL_delete( &this->opll );
+ break;
+ case type_msxaudio: break;
+ }
+}
+
+void Opl_reset( struct Opl_Apu* this )
+{
+ this->addr = 0;
+ this->next_time = 0;
+ this->last_amp = 0;
+
+ switch (this->type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ OPLL_reset( &this->opll );
+ OPLL_setMask( &this->opll, 0 );
+ break;
+ case type_msxaudio:
+ OPL_reset( &this->opl );
+ break;
+ }
+}
+
+static void run_until( struct Opl_Apu* this, blip_time_t end_time );
+void Opl_write_data( struct Opl_Apu* this, blip_time_t time, int data )
+{
+ run_until( this, time );
+ switch (this->type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ OPLL_writeIO( &this->opll, 0, this->addr );
+ OPLL_writeIO( &this->opll, 1, data );
+ break;
+ case type_msxaudio:
+ OPL_writeReg( &this->opl, this->addr, data );
+ break;
+ }
+}
+
+int Opl_read( struct Opl_Apu* this, blip_time_t time, int port )
+{
+ run_until( this, time );
+ switch (this->type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ return OPLL_read( &this->opll, port );
+ case type_msxaudio:
+ return OPL_readStatus( &this->opl );
+ }
+
+ return 0;
+}
+
+void Opl_end_frame( struct Opl_Apu* this, blip_time_t time )
+{
+ run_until( this, time );
+ this->next_time -= time;
+
+ if ( this->output_ )
+ Blip_set_modified( this->output_ );
+}
+
+static void run_until( struct Opl_Apu* this, blip_time_t end_time )
+{
+ if ( end_time > this->next_time )
+ {
+ blip_time_t time_delta = end_time - this->next_time;
+ blip_time_t time = this->next_time;
+ unsigned count = time_delta / this->period_ + 1;
+ switch (this->type_)
+ {
+ case type_opll:
+ case type_msxmusic:
+ case type_smsfmunit:
+ case type_vrc7:
+ {
+ OPLL* opll = &this->opll; // cache
+ struct Blip_Buffer* const output = this->output_;
+ while ( count > 0 )
+ {
+ unsigned todo = count;
+ if ( todo > 1024 ) todo = 1024;
+ short *buffer = OPLL_update_buffer(opll, todo);
+
+ if ( output && buffer )
+ {
+ int last_amp = this->last_amp;
+ unsigned i;
+ for ( i = 0; i < todo; i++ )
+ {
+ int amp = buffer [i];
+ int delta = amp - last_amp;
+ if ( delta )
+ {
+ last_amp = amp;
+ Synth_offset_inline( &this->synth, time, delta, output );
+ }
+ time += this->period_;
+ }
+ this->last_amp = last_amp;
+ }
+ count -= todo;
+ }
+ }
+ break;
+ case type_msxaudio:
+ {
+ struct Y8950* opl = &this->opl;
+ struct Blip_Buffer* const output = this->output_;
+ while ( count > 0 )
+ {
+ unsigned todo = count;
+ if ( todo > 1024 ) todo = 1024;
+ int *buffer = OPL_updateBuffer(opl, todo);
+
+ if ( output && buffer )
+ {
+ int last_amp = this->last_amp;
+ unsigned i;
+ for ( i = 0; i < todo; i++ )
+ {
+ int amp = buffer [i];
+ int delta = amp - last_amp;
+ if ( delta )
+ {
+ last_amp = amp;
+ Synth_offset_inline( &this->synth, time, delta, output );
+ }
+ time += this->period_;
+ }
+ this->last_amp = last_amp;
+ }
+ count -= todo;
+ }
+ }
+ break;
+ }
+ this->next_time = time;
+ }
+}
diff --git a/apps/codecs/libgme/opl_apu.h b/apps/codecs/libgme/opl_apu.h
index f24a8d60c2..76fa766492 100644
--- a/apps/codecs/libgme/opl_apu.h
+++ b/apps/codecs/libgme/opl_apu.h
@@ -1,63 +1,63 @@
-#ifndef OPL_APU_H
-#define OPL_APU_H
-
-#include "blargg_common.h"
-#include "blargg_source.h"
-#include "blip_buffer.h"
-
-#include "emu8950.h"
-#include "emu2413.h"
-
-enum opl_type_t { type_opll = 0x10, type_msxmusic = 0x11, type_smsfmunit = 0x12,
- type_vrc7 = 0x13, type_msxaudio = 0x21 };
-
-enum { opl_osc_count = 1 };
-
-struct Opl_Apu {
- struct Blip_Buffer* output_;
- enum opl_type_t type_;
-
- blip_time_t next_time;
- int last_amp;
- int addr;
-
- long clock_;
- long rate_;
- blip_time_t period_;
-
- struct Blip_Synth synth;
-
- // OPL chips
- struct Y8950 opl;
- OPLL opll;
-
- unsigned char regs[ 0x100 ];
- unsigned char opl_memory[ 32768 ];
-};
-
-blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type );
-void Opl_shutdown( struct Opl_Apu* this );
-
-void Opl_reset( struct Opl_Apu* this );
-static inline void Opl_volume( struct Opl_Apu* this, int v ) { Synth_volume( &this->synth, v / (4096 * 6) ); }
-
-static inline void Opl_osc_output( struct Opl_Apu* this, int i, struct Blip_Buffer* buf )
-{
-#if defined(ROCKBOX)
- (void) i;
-#endif
- assert( (unsigned) i < opl_osc_count );
- this->output_ = buf;
-}
-
-static inline void Opl_set_output( struct Opl_Apu* this, struct Blip_Buffer* buf ) { Opl_osc_output( this, 0, buf ); }
-void Opl_end_frame( struct Opl_Apu* this, blip_time_t );
-
-static inline void Opl_write_addr( struct Opl_Apu* this, int data ) { this->addr = data; }
-void Opl_write_data( struct Opl_Apu* this, blip_time_t, int data );
-
-int Opl_read( struct Opl_Apu* this, blip_time_t, int port );
-
-static inline bool Opl_supported( void ) { return true; }
-
-#endif
+#ifndef OPL_APU_H
+#define OPL_APU_H
+
+#include "blargg_common.h"
+#include "blargg_source.h"
+#include "blip_buffer.h"
+
+#include "emu8950.h"
+#include "emu2413.h"
+
+enum opl_type_t { type_opll = 0x10, type_msxmusic = 0x11, type_smsfmunit = 0x12,
+ type_vrc7 = 0x13, type_msxaudio = 0x21 };
+
+enum { opl_osc_count = 1 };
+
+struct Opl_Apu {
+ struct Blip_Buffer* output_;
+ enum opl_type_t type_;
+
+ blip_time_t next_time;
+ int last_amp;
+ int addr;
+
+ long clock_;
+ long rate_;
+ blip_time_t period_;
+
+ struct Blip_Synth synth;
+
+ // OPL chips
+ struct Y8950 opl;
+ OPLL opll;
+
+ unsigned char regs[ 0x100 ];
+ unsigned char opl_memory[ 32768 ];
+};
+
+blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type );
+void Opl_shutdown( struct Opl_Apu* this );
+
+void Opl_reset( struct Opl_Apu* this );
+static inline void Opl_volume( struct Opl_Apu* this, int v ) { Synth_volume( &this->synth, v / (4096 * 6) ); }
+
+static inline void Opl_osc_output( struct Opl_Apu* this, int i, struct Blip_Buffer* buf )
+{
+#if defined(ROCKBOX)
+ (void) i;
+#endif
+ assert( (unsigned) i < opl_osc_count );
+ this->output_ = buf;
+}
+
+static inline void Opl_set_output( struct Opl_Apu* this, struct Blip_Buffer* buf ) { Opl_osc_output( this, 0, buf ); }
+void Opl_end_frame( struct Opl_Apu* this, blip_time_t );
+
+static inline void Opl_write_addr( struct Opl_Apu* this, int data ) { this->addr = data; }
+void Opl_write_data( struct Opl_Apu* this, blip_time_t, int data );
+
+int Opl_read( struct Opl_Apu* this, blip_time_t, int port );
+
+static inline bool Opl_supported( void ) { return true; }
+
+#endif
diff --git a/apps/codecs/libgme/opltables.h b/apps/codecs/libgme/opltables.h
index 6ec10eaa6e..50fc0a86c6 100644
--- a/apps/codecs/libgme/opltables.h
+++ b/apps/codecs/libgme/opltables.h
@@ -1,242 +1,242 @@
-#ifndef _OPLTABLES_H_
-#define _OPLTABLES_H_
-
-/* Precalculated emu8950 tables for use in Rockbox,
- Calculated for 44Khz sampling rate */
-
-static const short ar_adjust_coeff[] = {
- 255, 227, 210, 198, 189, 181, 175, 170, 165, 161, 157,
- 153, 150, 147, 144, 141, 139, 136, 134, 132, 130, 128,
- 126, 125, 123, 121, 120, 118, 117, 115, 114, 113, 112,
- 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100,
- 99, 98, 97, 96, 95, 94, 94, 93, 92, 91, 91,
- 90, 89, 88, 88, 87, 86, 86, 85, 84, 84, 83,
- 82, 82, 81, 81, 80, 79, 79, 78, 78, 77, 77,
- 76, 76, 75, 75, 74, 74, 73, 73, 72, 72, 71,
- 71, 70, 70, 69, 69, 69, 68, 68, 67, 67, 66,
- 66, 66, 65, 65, 64, 64, 64, 63, 63, 62, 62,
- 62, 61, 61, 61, 60, 60, 60, 59, 59, 59, 58,
- 58, 58, 57, 57, 57, 56, 56, 56, 55, 55, 55,
- 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 51,
- 51, 51, 50, 50, 50, 50, 49, 49, 49, 49, 48,
- 48, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45,
- 45, 45, 45, 44, 44, 44, 44, 44, 43, 43, 43,
- 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40,
- 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38,
- 38, 38, 37, 37, 37, 37, 37, 36, 36, 36, 36,
- 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34,
- 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32,
- 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30,
- 30, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28,
- 28, 28, 27, 27, 27, 27, 27, 27, 26, 26, 26,
- 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25,
- 24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23,
- 23, 23, 22, 22, 22, 22, 22, 22, 22, 21, 21,
- 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
- 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18,
- 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17,
- 17, 17, 17, 17, 16, 16, 16, 16, 16, 16, 16,
- 16, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const short db2lin_coeff[] = {
- 2047, 2003, 1960, 1918, 1877, 1837, 1798, 1759, 1722, 1685, 1649,
- 1614, 1579, 1546, 1513, 1480, 1449, 1418, 1387, 1358, 1329, 1300,
- 1273, 1245, 1219, 1193, 1167, 1142, 1118, 1094, 1071, 1048, 1025,
- 1004, 982, 961, 941, 920, 901, 882, 863, 844, 826, 809,
- 791, 774, 758, 742, 726, 710, 695, 680, 666, 651, 638,
- 624, 611, 598, 585, 572, 560, 548, 536, 525, 514, 503,
- 492, 481, 471, 461, 451, 442, 432, 423, 414, 405, 396,
- 388, 380, 371, 364, 356, 348, 341, 333, 326, 319, 312,
- 306, 299, 293, 287, 280, 274, 269, 263, 257, 252, 246,
- 241, 236, 231, 226, 221, 216, 212, 207, 203, 198, 194,
- 190, 186, 182, 178, 174, 170, 167, 163, 160, 156, 153,
- 150, 147, 143, 140, 137, 134, 131, 129, 126, 123, 121,
- 118, 115, 113, 111, 108, 106, 104, 101, 99, 97, 95,
- 93, 91, 89, 87, 85, 83, 82, 80, 78, 76, 75,
- 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 59,
- 58, 56, 55, 54, 53, 52, 51, 49, 48, 47, 46,
- 45, 44, 43, 42, 42, 41, 40, 39, 38, 37, 36,
- 36, 35, 34, 33, 33, 32, 31, 31, 30, 29, 29,
- 28, 27, 27, 26, 26, 25, 25, 24, 23, 23, 22,
- 22, 21, 21, 21, 20, 20, 19, 19, 18, 18, 18,
- 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14,
- 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11,
- 11, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8,
- 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7,
- 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
- 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0
-};
-
-static const short sin_coeff[] = {
- 511, 235, 203, 185, 171, 161, 152, 145, 139, 134, 129,
- 124, 120, 117, 113, 110, 107, 104, 102, 99, 97, 95,
- 92, 90, 88, 87, 85, 83, 81, 80, 78, 77, 75,
- 74, 72, 71, 70, 69, 67, 66, 65, 64, 63, 62,
- 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52,
- 51, 50, 49, 48, 48, 47, 46, 45, 45, 44, 43,
- 43, 42, 41, 41, 40, 39, 39, 38, 38, 37, 37,
- 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31,
- 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26,
- 25, 25, 25, 24, 24, 23, 23, 23, 22, 22, 22,
- 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18,
- 18, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15,
- 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12,
- 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9,
- 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7,
- 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5,
- 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4,
- 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,
-};
-
-static const short pm0_coeff[] = {
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255,
-};
-
-static const short pm1_coeff[] = {
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
- 258, 258, 258, 258, 258, 258, 258, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253,
- 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
- 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255,
-};
-
-static const short am0_coeff[] = {
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2,
-};
-
-static const short am1_coeff[] = {
- 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15,
- 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 19,
- 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
- 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23,
- 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 23,
- 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21,
- 21, 20, 20, 20, 20, 19, 19, 19, 19, 18, 18,
- 18, 17, 17, 17, 17, 16, 16, 16, 15, 15, 15,
- 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11,
- 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8,
- 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5,
- 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2,
- 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5,
- 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8,
- 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11,
- 11, 12, 12,
-};
-
-#endif
+#ifndef _OPLTABLES_H_
+#define _OPLTABLES_H_
+
+/* Precalculated emu8950 tables for use in Rockbox,
+ Calculated for 44Khz sampling rate */
+
+static const short ar_adjust_coeff[] = {
+ 255, 227, 210, 198, 189, 181, 175, 170, 165, 161, 157,
+ 153, 150, 147, 144, 141, 139, 136, 134, 132, 130, 128,
+ 126, 125, 123, 121, 120, 118, 117, 115, 114, 113, 112,
+ 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100,
+ 99, 98, 97, 96, 95, 94, 94, 93, 92, 91, 91,
+ 90, 89, 88, 88, 87, 86, 86, 85, 84, 84, 83,
+ 82, 82, 81, 81, 80, 79, 79, 78, 78, 77, 77,
+ 76, 76, 75, 75, 74, 74, 73, 73, 72, 72, 71,
+ 71, 70, 70, 69, 69, 69, 68, 68, 67, 67, 66,
+ 66, 66, 65, 65, 64, 64, 64, 63, 63, 62, 62,
+ 62, 61, 61, 61, 60, 60, 60, 59, 59, 59, 58,
+ 58, 58, 57, 57, 57, 56, 56, 56, 55, 55, 55,
+ 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 51,
+ 51, 51, 50, 50, 50, 50, 49, 49, 49, 49, 48,
+ 48, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45,
+ 45, 45, 45, 44, 44, 44, 44, 44, 43, 43, 43,
+ 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40,
+ 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38,
+ 38, 38, 37, 37, 37, 37, 37, 36, 36, 36, 36,
+ 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34,
+ 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32,
+ 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30,
+ 30, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28,
+ 28, 28, 27, 27, 27, 27, 27, 27, 26, 26, 26,
+ 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25,
+ 24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23,
+ 23, 23, 22, 22, 22, 22, 22, 22, 22, 21, 21,
+ 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
+ 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18,
+ 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17,
+ 17, 17, 17, 17, 16, 16, 16, 16, 16, 16, 16,
+ 16, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0
+};
+
+static const short db2lin_coeff[] = {
+ 2047, 2003, 1960, 1918, 1877, 1837, 1798, 1759, 1722, 1685, 1649,
+ 1614, 1579, 1546, 1513, 1480, 1449, 1418, 1387, 1358, 1329, 1300,
+ 1273, 1245, 1219, 1193, 1167, 1142, 1118, 1094, 1071, 1048, 1025,
+ 1004, 982, 961, 941, 920, 901, 882, 863, 844, 826, 809,
+ 791, 774, 758, 742, 726, 710, 695, 680, 666, 651, 638,
+ 624, 611, 598, 585, 572, 560, 548, 536, 525, 514, 503,
+ 492, 481, 471, 461, 451, 442, 432, 423, 414, 405, 396,
+ 388, 380, 371, 364, 356, 348, 341, 333, 326, 319, 312,
+ 306, 299, 293, 287, 280, 274, 269, 263, 257, 252, 246,
+ 241, 236, 231, 226, 221, 216, 212, 207, 203, 198, 194,
+ 190, 186, 182, 178, 174, 170, 167, 163, 160, 156, 153,
+ 150, 147, 143, 140, 137, 134, 131, 129, 126, 123, 121,
+ 118, 115, 113, 111, 108, 106, 104, 101, 99, 97, 95,
+ 93, 91, 89, 87, 85, 83, 82, 80, 78, 76, 75,
+ 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 59,
+ 58, 56, 55, 54, 53, 52, 51, 49, 48, 47, 46,
+ 45, 44, 43, 42, 42, 41, 40, 39, 38, 37, 36,
+ 36, 35, 34, 33, 33, 32, 31, 31, 30, 29, 29,
+ 28, 27, 27, 26, 26, 25, 25, 24, 23, 23, 22,
+ 22, 21, 21, 21, 20, 20, 19, 19, 18, 18, 18,
+ 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14,
+ 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11,
+ 11, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8,
+ 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7,
+ 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
+ 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+static const short sin_coeff[] = {
+ 511, 235, 203, 185, 171, 161, 152, 145, 139, 134, 129,
+ 124, 120, 117, 113, 110, 107, 104, 102, 99, 97, 95,
+ 92, 90, 88, 87, 85, 83, 81, 80, 78, 77, 75,
+ 74, 72, 71, 70, 69, 67, 66, 65, 64, 63, 62,
+ 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52,
+ 51, 50, 49, 48, 48, 47, 46, 45, 45, 44, 43,
+ 43, 42, 41, 41, 40, 39, 39, 38, 38, 37, 37,
+ 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31,
+ 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26,
+ 25, 25, 25, 24, 24, 23, 23, 23, 22, 22, 22,
+ 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18,
+ 18, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15,
+ 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12,
+ 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9,
+ 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7,
+ 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5,
+ 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4,
+ 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,
+};
+
+static const short pm0_coeff[] = {
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255,
+};
+
+static const short pm1_coeff[] = {
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
+ 258, 258, 258, 258, 258, 258, 258, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
+ 257, 257, 257, 257, 257, 257, 257, 257, 257, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253,
+ 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+ 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255,
+};
+
+static const short am0_coeff[] = {
+ 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2,
+};
+
+static const short am1_coeff[] = {
+ 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15,
+ 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 19,
+ 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23,
+ 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 23,
+ 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21,
+ 21, 20, 20, 20, 20, 19, 19, 19, 19, 18, 18,
+ 18, 17, 17, 17, 17, 16, 16, 16, 15, 15, 15,
+ 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11,
+ 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8,
+ 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5,
+ 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2,
+ 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5,
+ 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8,
+ 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11,
+ 11, 12, 12,
+};
+
+#endif
diff --git a/apps/codecs/libgme/sgc_cpu.c b/apps/codecs/libgme/sgc_cpu.c
index 3bd2d15df9..d23c01499b 100644
--- a/apps/codecs/libgme/sgc_cpu.c
+++ b/apps/codecs/libgme/sgc_cpu.c
@@ -1,36 +1,36 @@
-// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
-
-#include "sgc_emu.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( this, TIME(), addr, data )
-#define IN_PORT( addr ) 0 // cpu in
-#define WRITE_MEM( addr, data ) cpu_write( this, addr, data )
-#define IDLE_ADDR this->idle_addr
-#define RST_BASE this->vectors_addr
-
-#define CPU_BEGIN \
-bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time )\
-{\
- Sgc_Cpu* cpu = &this->cpu; \
- Z80_set_end_time( cpu, end_time );
-
- #include "z80_cpu_run.h"
-
- return warning;
-}
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "sgc_emu.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( this, TIME(), addr, data )
+#define IN_PORT( addr ) 0 // cpu in
+#define WRITE_MEM( addr, data ) cpu_write( this, addr, data )
+#define IDLE_ADDR this->idle_addr
+#define RST_BASE this->vectors_addr
+
+#define CPU_BEGIN \
+bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time )\
+{\
+ Sgc_Cpu* cpu = &this->cpu; \
+ Z80_set_end_time( cpu, end_time );
+
+ #include "z80_cpu_run.h"
+
+ return warning;
+}
diff --git a/apps/codecs/libgme/sgc_emu.c b/apps/codecs/libgme/sgc_emu.c
index e7253a8d5b..267f2c9271 100644
--- a/apps/codecs/libgme/sgc_emu.c
+++ b/apps/codecs/libgme/sgc_emu.c
@@ -1,480 +1,480 @@
-// Game_Music_Emu 0.6-pre. 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 aint 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_osc_count + fm_apu_osc_count;
-
-const char gme_wrong_file_type [] = "Wrong file type for this emulator";
-
-static void clear_track_vars( struct Sgc_Emu* this )
-{
- this->current_track = -1;
- track_stop( &this->track_filter );
-}
-
-void Sgc_init( struct Sgc_Emu* this )
-{
- assert( offsetof (struct header_t,copyright [32]) == header_size );
-
- this->sample_rate = 0;
- this->mute_mask_ = 0;
- this->tempo = (int)FP_ONE_TEMPO;
- this->gain = (int)FP_ONE_GAIN;
-
- // defaults
- this->tfilter = *track_get_setup( &this->track_filter );
- this->tfilter.max_initial = 2;
- this->tfilter.lookahead = 6;
- this->track_filter.silence_ignored_ = false;
-
- Sms_apu_init( &this->apu );
- Fm_apu_create( &this->fm_apu );
-
- Rom_init( &this->rom, 0x4000 );
- Z80_init( &this->cpu );
-
- Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
-
- // Unload
- this->voice_count = 0;
- this->voice_types = 0;
- clear_track_vars( this );
-}
-
-// Setup
-
-blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
-{
- RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
-
- if ( !valid_tag( &this->header ) )
- return gme_wrong_file_type;
-
- /* if ( header.vers != 1 )
- warning( "Unknown file version" ); */
-
- /* if ( header.system > 2 )
- warning( "Unknown system" ); */
-
- addr_t load_addr = get_le16( this->header.load_addr );
- /* if ( load_addr < 0x400 )
- set_warning( "Invalid load address" ); */
-
- Rom_set_addr( &this->rom, load_addr );
- this->play_period = clock_rate( this ) / 60;
-
- if ( sega_mapping( this ) && Fm_apu_supported() )
- RETURN_ERR( Fm_apu_init( &this->fm_apu, clock_rate( this ), clock_rate( this ) / 72 ) );
-
- this->m3u.size = 0;
- this->track_count = this->header.song_count;
- this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count;
- static int const types [sms_osc_count + fm_apu_osc_count] = {
- wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
- };
- this->voice_types = types;
-
- Sms_apu_volume( &this->apu, this->gain );
- Fm_apu_volume( &this->fm_apu, this->gain );
-
- // Setup buffer
- this->clock_rate_ = clock_rate( this );
- Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) );
- RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
- this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
-
- Sound_set_tempo( this, this->tempo );
- Sound_mute_voices( this, this->mute_mask_ );
- return 0;
-}
-
-static void Sound_set_voice( struct Sgc_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r )
-{
- if ( i < sms_osc_count )
- Sms_apu_set_output( &this->apu, i, c, l, r );
- else
- Fm_apu_set_output( &this->fm_apu, c );
-}
-
-static blargg_err_t run_clocks( struct Sgc_Emu* this, blip_time_t* duration, int msec )
-{
-#if defined(ROCKBOX)
- (void) msec;
-#endif
-
- cpu_time_t t = *duration;
- while ( Z80_time( &this->cpu ) < t )
- {
- cpu_time_t next = min( t, this->next_play );
- if ( run_cpu( this, next ) )
- {
- /* warning( "Unsupported CPU instruction" ); */
- Z80_set_time( &this->cpu, next );
- }
-
- if ( this->cpu.r.pc == this->idle_addr )
- Z80_set_time( &this->cpu, next );
-
- if ( Z80_time( &this->cpu ) >= this->next_play )
- {
- this->next_play += this->play_period;
- if ( this->cpu.r.pc == this->idle_addr )
- jsr( this, this->header.play_addr );
- }
- }
-
- this->next_play -= t;
- check( this->next_play >= 0 );
- Z80_adjust_time( &this->cpu, -t );
-
- Sms_apu_end_frame( &this->apu, t );
- if ( sega_mapping( this ) && this->fm_accessed )
- {
- if ( Fm_apu_supported() )
- Fm_apu_end_frame( &this->fm_apu, t );
- /* else
- warning( "FM sound not supported" ); */
- }
-
- return 0;
-}
-
-// Emulation
-
-void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data )
-{
- int port = addr & 0xFF;
-
- if ( sega_mapping( this ) )
- {
- switch ( port )
- {
- case 0x06:
- Sms_apu_write_ggstereo( &this->apu, time, data );
- return;
-
- case 0x7E:
- case 0x7F:
- Sms_apu_write_data( &this->apu, time, data ); /* dprintf( "$7E<-%02X\n", data ); */
- return;
-
- case 0xF0:
- this->fm_accessed = true;
- if ( Fm_apu_supported() )
- Fm_apu_write_addr( &this->fm_apu, data );//, dprintf( "$F0<-%02X\n", data );
- return;
-
- case 0xF1:
- this->fm_accessed = true;
- if ( Fm_apu_supported() )
- Fm_apu_write_data( &this->fm_apu, time, data );//, dprintf( "$F1<-%02X\n", data );
- return;
- }
- }
- else if ( port >= 0xE0 )
- {
- Sms_apu_write_data( &this->apu, time, data );
- return;
- }
-}
-
-void jsr( struct Sgc_Emu* this, byte addr [2] )
-{
- *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr >> 8;
- *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr & 0xFF;
- this->cpu.r.pc = get_le16( addr );
-}
-
-static void set_bank( struct Sgc_Emu* this, int bank, void const* data )
-{
- //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
- Z80_map_mem( &this->cpu, bank * this->rom.bank_size, this->rom.bank_size, this->unmapped_write, data );
-}
-
-void cpu_write( struct Sgc_Emu* this, addr_t addr, int data )
-{
- if ( (addr ^ 0xFFFC) > 3 || !sega_mapping( this ) )
- {
- *Z80_write( &this->cpu, addr ) = data;
- return;
- }
-
- switch ( addr )
- {
- case 0xFFFC:
- Z80_map_mem_rw( &this->cpu, 2 * this->rom.bank_size, this->rom.bank_size, this->ram2 );
- if ( data & 0x08 )
- break;
-
- this->bank2 = this->ram2;
- // FALL THROUGH
-
- case 0xFFFF: {
- bool rom_mapped = (Z80_read( &this->cpu, 2 * this->rom.bank_size ) == this->bank2);
- this->bank2 = Rom_at_addr( &this->rom, data * this->rom.bank_size );
- if ( rom_mapped )
- set_bank( this, 2, this->bank2 );
- break;
- }
-
- case 0xFFFD:
- set_bank( this, 0, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
- break;
-
- case 0xFFFE:
- set_bank( this, 1, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
- break;
- }
-}
-
-blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate )
-{
- require( !this->sample_rate ); // sample rate can't be changed once set
- Buffer_init( &this->stereo_buf );
- Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 );
-
- // Set buffer bass
- Buffer_bass_freq( &this->stereo_buf, 80 );
-
- this->sample_rate = rate;
- RETURN_ERR( track_init( &this->track_filter, this ) );
- this->tfilter.max_silence = 6 * stereo * this->sample_rate;
- return 0;
-}
-
-void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute )
-{
- require( (unsigned) index < (unsigned) this->voice_count );
- int bit = 1 << index;
- int mask = this->mute_mask_ | bit;
- if ( !mute )
- mask ^= bit;
- Sound_mute_voices( this, mask );
-}
-
-void Sound_mute_voices( struct Sgc_Emu* this, int mask )
-{
- require( this->sample_rate ); // sample rate must be set first
- this->mute_mask_ = mask;
-
- int i;
- for ( i = this->voice_count; i--; )
- {
- if ( mask & (1 << i) )
- {
- Sound_set_voice( this, i, 0, 0, 0 );
- }
- else
- {
- struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
- assert( (ch.center && ch.left && ch.right) ||
- (!ch.center && !ch.left && !ch.right) ); // all or nothing
- Sound_set_voice( this, i, ch.center, ch.left, ch.right );
- }
- }
-}
-
-void Sound_set_tempo( struct Sgc_Emu* this, int t )
-{
- require( this->sample_rate ); // sample rate must be set first
- int const min = (int)(FP_ONE_TEMPO*0.02);
- int const max = (int)(FP_ONE_TEMPO*4.00);
- if ( t < min ) t = min;
- if ( t > max ) t = max;
- this->tempo = t;
-
- this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t);
-}
-
-blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
-{
- clear_track_vars( this );
-
- // Remap track if playlist available
- if ( this->m3u.size > 0 ) {
- struct entry_t* e = &this->m3u.entries[track];
- track = e->track;
- }
-
- this->current_track = track;
-
- if ( sega_mapping( this ) )
- {
- Sms_apu_reset( &this->apu, 0, 0 );
- Fm_apu_reset( &this->fm_apu );
- this->fm_accessed = false;
- }
- else
- {
- Sms_apu_reset( &this->apu, 0x0003, 15 );
- }
-
- memset( this->ram , 0, sizeof this->ram );
- memset( this->ram2, 0, sizeof this->ram2 );
- memset( this->vectors, 0xFF, sizeof this->vectors );
- Z80_reset( &this->cpu, this->unmapped_write, this->rom.unmapped );
-
- if ( sega_mapping( this ) )
- {
- this->vectors_addr = 0x10000 - page_size;
- this->idle_addr = this->vectors_addr;
- int i;
- for ( i = 1; i < 8; ++i )
- {
- this->vectors [i*8 + 0] = 0xC3; // JP addr
- this->vectors [i*8 + 1] = this->header.rst_addrs [i - 1] & 0xff;
- this->vectors [i*8 + 2] = this->header.rst_addrs [i - 1] >> 8;
- }
-
- Z80_map_mem_rw( &this->cpu, 0xC000, 0x2000, this->ram );
- Z80_map_mem( &this->cpu, this->vectors_addr, page_size, this->unmapped_write, this->vectors );
-
- this->bank2 = NULL;
- for ( i = 0; i < 4; ++i )
- cpu_write( this, 0xFFFC + i, this->header.mapping [i] );
- }
- else
- {
- if ( !this->coleco_bios )
- return "Coleco BIOS not set"; /* BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); */
-
- this->vectors_addr = 0;
- Z80_map_mem( &this->cpu, 0, 0x2000, this->unmapped_write, this->coleco_bios );
- int i;
- for ( i = 0; i < 8; ++i )
- Z80_map_mem_rw( &this->cpu, 0x6000 + i*0x400, 0x400, this->ram );
-
- this->idle_addr = 0x2000;
- Z80_map_mem( &this->cpu, 0x2000, page_size, this->unmapped_write, this->vectors );
-
- for ( i = 0; i < 0x8000 / this->rom.bank_size; ++i )
- {
- int addr = 0x8000 + i*this->rom.bank_size;
- Z80_map_mem( &this->cpu, addr, this->rom.bank_size, this->unmapped_write, Rom_at_addr( &this->rom, addr ) );
- }
- }
-
- this->cpu.r.sp = get_le16( this->header.stack_ptr );
- this->cpu.r.b.a = track;
- this->next_play = this->play_period;
-
- jsr( this, this->header.init_addr );
-
- Buffer_clear( &this->stereo_buf );
-
- // convert filter times to samples
- struct setup_t s = this->tfilter;
- s.max_initial *= this->sample_rate * stereo;
- #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
- s.lookahead = 1;
- #endif
- track_setup( &this->track_filter, &s );
-
- return track_start( &this->track_filter );
-}
-
-// Tell/Seek
-
-static int msec_to_samples( int msec, int sample_rate )
-{
- int sec = msec / 1000;
- msec -= sec * 1000;
- return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
-}
-
-int Track_tell( struct Sgc_Emu* this )
-{
- int rate = this->sample_rate * stereo;
- int sec = track_sample_count( &this->track_filter ) / rate;
- return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Track_seek( struct Sgc_Emu* this, int msec )
-{
- int time = msec_to_samples( msec, this->sample_rate );
- if ( time < track_sample_count( &this->track_filter ) )
- RETURN_ERR( Sgc_start_track( this, this->current_track ) );
- return Track_skip( this, time - track_sample_count( &this->track_filter ) );
-}
-
-blargg_err_t Track_skip( struct Sgc_Emu* this, int count )
-{
- require( this->current_track >= 0 ); // start_track() must have been called already
- return track_skip( &this->track_filter, count );
-}
-
-blargg_err_t skip_( void* emu, int count )
-{
- struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
-
- // for long skip, mute sound
- const int threshold = 32768;
- if ( count > threshold )
- {
- int saved_mute = this->mute_mask_;
- Sound_mute_voices( this, ~0 );
-
- int n = count - threshold/2;
- n &= ~(2048-1); // round to multiple of 2048
- count -= n;
- RETURN_ERR( skippy_( &this->track_filter, n ) );
-
- Sound_mute_voices( this, saved_mute );
- }
-
- return skippy_( &this->track_filter, count );
-}
-
-void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec )
-{
- track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
- length_msec * this->sample_rate / (1000 / stereo) );
-}
-
-blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out )
-{
- require( this->current_track >= 0 );
- require( out_count % stereo == 0 );
- return track_play( &this->track_filter, out_count, out );
-}
-
-blargg_err_t play_( void* emu, int count, sample_t out [] )
-{
- struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
-
- int remain = count;
- while ( remain )
- {
- Buffer_disable_immediate_removal( &this->stereo_buf );
- remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
- if ( remain )
- {
- if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
- {
- this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
-
- // Remute voices
- Sound_mute_voices( this, this->mute_mask_ );
- }
- int msec = Buffer_length( &this->stereo_buf );
- blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
- RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
- assert( clocks_emulated );
- Buffer_end_frame( &this->stereo_buf, clocks_emulated );
- }
- }
- return 0;
-}
+// Game_Music_Emu 0.6-pre. 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 aint 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_osc_count + fm_apu_osc_count;
+
+const char gme_wrong_file_type [] = "Wrong file type for this emulator";
+
+static void clear_track_vars( struct Sgc_Emu* this )
+{
+ this->current_track = -1;
+ track_stop( &this->track_filter );
+}
+
+void Sgc_init( struct Sgc_Emu* this )
+{
+ assert( offsetof (struct header_t,copyright [32]) == header_size );
+
+ this->sample_rate = 0;
+ this->mute_mask_ = 0;
+ this->tempo = (int)FP_ONE_TEMPO;
+ this->gain = (int)FP_ONE_GAIN;
+
+ // defaults
+ this->tfilter = *track_get_setup( &this->track_filter );
+ this->tfilter.max_initial = 2;
+ this->tfilter.lookahead = 6;
+ this->track_filter.silence_ignored_ = false;
+
+ Sms_apu_init( &this->apu );
+ Fm_apu_create( &this->fm_apu );
+
+ Rom_init( &this->rom, 0x4000 );
+ Z80_init( &this->cpu );
+
+ Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
+
+ // Unload
+ this->voice_count = 0;
+ this->voice_types = 0;
+ clear_track_vars( this );
+}
+
+// Setup
+
+blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
+{
+ RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
+
+ if ( !valid_tag( &this->header ) )
+ return gme_wrong_file_type;
+
+ /* if ( header.vers != 1 )
+ warning( "Unknown file version" ); */
+
+ /* if ( header.system > 2 )
+ warning( "Unknown system" ); */
+
+ addr_t load_addr = get_le16( this->header.load_addr );
+ /* if ( load_addr < 0x400 )
+ set_warning( "Invalid load address" ); */
+
+ Rom_set_addr( &this->rom, load_addr );
+ this->play_period = clock_rate( this ) / 60;
+
+ if ( sega_mapping( this ) && Fm_apu_supported() )
+ RETURN_ERR( Fm_apu_init( &this->fm_apu, clock_rate( this ), clock_rate( this ) / 72 ) );
+
+ this->m3u.size = 0;
+ this->track_count = this->header.song_count;
+ this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count;
+ static int const types [sms_osc_count + fm_apu_osc_count] = {
+ wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
+ };
+ this->voice_types = types;
+
+ Sms_apu_volume( &this->apu, this->gain );
+ Fm_apu_volume( &this->fm_apu, this->gain );
+
+ // Setup buffer
+ this->clock_rate_ = clock_rate( this );
+ Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) );
+ RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
+ this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
+
+ Sound_set_tempo( this, this->tempo );
+ Sound_mute_voices( this, this->mute_mask_ );
+ return 0;
+}
+
+static void Sound_set_voice( struct Sgc_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r )
+{
+ if ( i < sms_osc_count )
+ Sms_apu_set_output( &this->apu, i, c, l, r );
+ else
+ Fm_apu_set_output( &this->fm_apu, c );
+}
+
+static blargg_err_t run_clocks( struct Sgc_Emu* this, blip_time_t* duration, int msec )
+{
+#if defined(ROCKBOX)
+ (void) msec;
+#endif
+
+ cpu_time_t t = *duration;
+ while ( Z80_time( &this->cpu ) < t )
+ {
+ cpu_time_t next = min( t, this->next_play );
+ if ( run_cpu( this, next ) )
+ {
+ /* warning( "Unsupported CPU instruction" ); */
+ Z80_set_time( &this->cpu, next );
+ }
+
+ if ( this->cpu.r.pc == this->idle_addr )
+ Z80_set_time( &this->cpu, next );
+
+ if ( Z80_time( &this->cpu ) >= this->next_play )
+ {
+ this->next_play += this->play_period;
+ if ( this->cpu.r.pc == this->idle_addr )
+ jsr( this, this->header.play_addr );
+ }
+ }
+
+ this->next_play -= t;
+ check( this->next_play >= 0 );
+ Z80_adjust_time( &this->cpu, -t );
+
+ Sms_apu_end_frame( &this->apu, t );
+ if ( sega_mapping( this ) && this->fm_accessed )
+ {
+ if ( Fm_apu_supported() )
+ Fm_apu_end_frame( &this->fm_apu, t );
+ /* else
+ warning( "FM sound not supported" ); */
+ }
+
+ return 0;
+}
+
+// Emulation
+
+void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data )
+{
+ int port = addr & 0xFF;
+
+ if ( sega_mapping( this ) )
+ {
+ switch ( port )
+ {
+ case 0x06:
+ Sms_apu_write_ggstereo( &this->apu, time, data );
+ return;
+
+ case 0x7E:
+ case 0x7F:
+ Sms_apu_write_data( &this->apu, time, data ); /* dprintf( "$7E<-%02X\n", data ); */
+ return;
+
+ case 0xF0:
+ this->fm_accessed = true;
+ if ( Fm_apu_supported() )
+ Fm_apu_write_addr( &this->fm_apu, data );//, dprintf( "$F0<-%02X\n", data );
+ return;
+
+ case 0xF1:
+ this->fm_accessed = true;
+ if ( Fm_apu_supported() )
+ Fm_apu_write_data( &this->fm_apu, time, data );//, dprintf( "$F1<-%02X\n", data );
+ return;
+ }
+ }
+ else if ( port >= 0xE0 )
+ {
+ Sms_apu_write_data( &this->apu, time, data );
+ return;
+ }
+}
+
+void jsr( struct Sgc_Emu* this, byte addr [2] )
+{
+ *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr >> 8;
+ *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr & 0xFF;
+ this->cpu.r.pc = get_le16( addr );
+}
+
+static void set_bank( struct Sgc_Emu* this, int bank, void const* data )
+{
+ //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
+ Z80_map_mem( &this->cpu, bank * this->rom.bank_size, this->rom.bank_size, this->unmapped_write, data );
+}
+
+void cpu_write( struct Sgc_Emu* this, addr_t addr, int data )
+{
+ if ( (addr ^ 0xFFFC) > 3 || !sega_mapping( this ) )
+ {
+ *Z80_write( &this->cpu, addr ) = data;
+ return;
+ }
+
+ switch ( addr )
+ {
+ case 0xFFFC:
+ Z80_map_mem_rw( &this->cpu, 2 * this->rom.bank_size, this->rom.bank_size, this->ram2 );
+ if ( data & 0x08 )
+ break;
+
+ this->bank2 = this->ram2;
+ // FALL THROUGH
+
+ case 0xFFFF: {
+ bool rom_mapped = (Z80_read( &this->cpu, 2 * this->rom.bank_size ) == this->bank2);
+ this->bank2 = Rom_at_addr( &this->rom, data * this->rom.bank_size );
+ if ( rom_mapped )
+ set_bank( this, 2, this->bank2 );
+ break;
+ }
+
+ case 0xFFFD:
+ set_bank( this, 0, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
+ break;
+
+ case 0xFFFE:
+ set_bank( this, 1, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
+ break;
+ }
+}
+
+blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate )
+{
+ require( !this->sample_rate ); // sample rate can't be changed once set
+ Buffer_init( &this->stereo_buf );
+ Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 );
+
+ // Set buffer bass
+ Buffer_bass_freq( &this->stereo_buf, 80 );
+
+ this->sample_rate = rate;
+ RETURN_ERR( track_init( &this->track_filter, this ) );
+ this->tfilter.max_silence = 6 * stereo * this->sample_rate;
+ return 0;
+}
+
+void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute )
+{
+ require( (unsigned) index < (unsigned) this->voice_count );
+ int bit = 1 << index;
+ int mask = this->mute_mask_ | bit;
+ if ( !mute )
+ mask ^= bit;
+ Sound_mute_voices( this, mask );
+}
+
+void Sound_mute_voices( struct Sgc_Emu* this, int mask )
+{
+ require( this->sample_rate ); // sample rate must be set first
+ this->mute_mask_ = mask;
+
+ int i;
+ for ( i = this->voice_count; i--; )
+ {
+ if ( mask & (1 << i) )
+ {
+ Sound_set_voice( this, i, 0, 0, 0 );
+ }
+ else
+ {
+ struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
+ assert( (ch.center && ch.left && ch.right) ||
+ (!ch.center && !ch.left && !ch.right) ); // all or nothing
+ Sound_set_voice( this, i, ch.center, ch.left, ch.right );
+ }
+ }
+}
+
+void Sound_set_tempo( struct Sgc_Emu* this, int t )
+{
+ require( this->sample_rate ); // sample rate must be set first
+ int const min = (int)(FP_ONE_TEMPO*0.02);
+ int const max = (int)(FP_ONE_TEMPO*4.00);
+ if ( t < min ) t = min;
+ if ( t > max ) t = max;
+ this->tempo = t;
+
+ this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t);
+}
+
+blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
+{
+ clear_track_vars( this );
+
+ // Remap track if playlist available
+ if ( this->m3u.size > 0 ) {
+ struct entry_t* e = &this->m3u.entries[track];
+ track = e->track;
+ }
+
+ this->current_track = track;
+
+ if ( sega_mapping( this ) )
+ {
+ Sms_apu_reset( &this->apu, 0, 0 );
+ Fm_apu_reset( &this->fm_apu );
+ this->fm_accessed = false;
+ }
+ else
+ {
+ Sms_apu_reset( &this->apu, 0x0003, 15 );
+ }
+
+ memset( this->ram , 0, sizeof this->ram );
+ memset( this->ram2, 0, sizeof this->ram2 );
+ memset( this->vectors, 0xFF, sizeof this->vectors );
+ Z80_reset( &this->cpu, this->unmapped_write, this->rom.unmapped );
+
+ if ( sega_mapping( this ) )
+ {
+ this->vectors_addr = 0x10000 - page_size;
+ this->idle_addr = this->vectors_addr;
+ int i;
+ for ( i = 1; i < 8; ++i )
+ {
+ this->vectors [i*8 + 0] = 0xC3; // JP addr
+ this->vectors [i*8 + 1] = this->header.rst_addrs [i - 1] & 0xff;
+ this->vectors [i*8 + 2] = this->header.rst_addrs [i - 1] >> 8;
+ }
+
+ Z80_map_mem_rw( &this->cpu, 0xC000, 0x2000, this->ram );
+ Z80_map_mem( &this->cpu, this->vectors_addr, page_size, this->unmapped_write, this->vectors );
+
+ this->bank2 = NULL;
+ for ( i = 0; i < 4; ++i )
+ cpu_write( this, 0xFFFC + i, this->header.mapping [i] );
+ }
+ else
+ {
+ if ( !this->coleco_bios )
+ return "Coleco BIOS not set"; /* BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); */
+
+ this->vectors_addr = 0;
+ Z80_map_mem( &this->cpu, 0, 0x2000, this->unmapped_write, this->coleco_bios );
+ int i;
+ for ( i = 0; i < 8; ++i )
+ Z80_map_mem_rw( &this->cpu, 0x6000 + i*0x400, 0x400, this->ram );
+
+ this->idle_addr = 0x2000;
+ Z80_map_mem( &this->cpu, 0x2000, page_size, this->unmapped_write, this->vectors );
+
+ for ( i = 0; i < 0x8000 / this->rom.bank_size; ++i )
+ {
+ int addr = 0x8000 + i*this->rom.bank_size;
+ Z80_map_mem( &this->cpu, addr, this->rom.bank_size, this->unmapped_write, Rom_at_addr( &this->rom, addr ) );
+ }
+ }
+
+ this->cpu.r.sp = get_le16( this->header.stack_ptr );
+ this->cpu.r.b.a = track;
+ this->next_play = this->play_period;
+
+ jsr( this, this->header.init_addr );
+
+ Buffer_clear( &this->stereo_buf );
+
+ // convert filter times to samples
+ struct setup_t s = this->tfilter;
+ s.max_initial *= this->sample_rate * stereo;
+ #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
+ s.lookahead = 1;
+ #endif
+ track_setup( &this->track_filter, &s );
+
+ return track_start( &this->track_filter );
+}
+
+// Tell/Seek
+
+static int msec_to_samples( int msec, int sample_rate )
+{
+ int sec = msec / 1000;
+ msec -= sec * 1000;
+ return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
+}
+
+int Track_tell( struct Sgc_Emu* this )
+{
+ int rate = this->sample_rate * stereo;
+ int sec = track_sample_count( &this->track_filter ) / rate;
+ return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Track_seek( struct Sgc_Emu* this, int msec )
+{
+ int time = msec_to_samples( msec, this->sample_rate );
+ if ( time < track_sample_count( &this->track_filter ) )
+ RETURN_ERR( Sgc_start_track( this, this->current_track ) );
+ return Track_skip( this, time - track_sample_count( &this->track_filter ) );
+}
+
+blargg_err_t Track_skip( struct Sgc_Emu* this, int count )
+{
+ require( this->current_track >= 0 ); // start_track() must have been called already
+ return track_skip( &this->track_filter, count );
+}
+
+blargg_err_t skip_( void* emu, int count )
+{
+ struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
+
+ // for long skip, mute sound
+ const int threshold = 32768;
+ if ( count > threshold )
+ {
+ int saved_mute = this->mute_mask_;
+ Sound_mute_voices( this, ~0 );
+
+ int n = count - threshold/2;
+ n &= ~(2048-1); // round to multiple of 2048
+ count -= n;
+ RETURN_ERR( skippy_( &this->track_filter, n ) );
+
+ Sound_mute_voices( this, saved_mute );
+ }
+
+ return skippy_( &this->track_filter, count );
+}
+
+void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec )
+{
+ track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
+ length_msec * this->sample_rate / (1000 / stereo) );
+}
+
+blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out )
+{
+ require( this->current_track >= 0 );
+ require( out_count % stereo == 0 );
+ return track_play( &this->track_filter, out_count, out );
+}
+
+blargg_err_t play_( void* emu, int count, sample_t out [] )
+{
+ struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
+
+ int remain = count;
+ while ( remain )
+ {
+ Buffer_disable_immediate_removal( &this->stereo_buf );
+ remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
+ if ( remain )
+ {
+ if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
+ {
+ this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
+
+ // Remute voices
+ Sound_mute_voices( this, this->mute_mask_ );
+ }
+ int msec = Buffer_length( &this->stereo_buf );
+ blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
+ RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
+ assert( clocks_emulated );
+ Buffer_end_frame( &this->stereo_buf, clocks_emulated );
+ }
+ }
+ return 0;
+}
diff --git a/apps/codecs/libgme/sgc_emu.h b/apps/codecs/libgme/sgc_emu.h
index 6595c02daf..83cde1e6ae 100644
--- a/apps/codecs/libgme/sgc_emu.h
+++ b/apps/codecs/libgme/sgc_emu.h
@@ -1,195 +1,195 @@
-// Sega/Game Gear/Coleco SGC music file emulator
-
-// Game_Music_Emu 0.6-pre
-#ifndef SGC_EMU_H
-#define SGC_EMU_H
-
-#include "blargg_common.h"
-#include "multi_buffer.h"
-
-#include "rom_data.h"
-#include "z80_cpu.h"
-#include "sms_fm_apu.h"
-#include "sms_apu.h"
-#include "m3u_playlist.h"
-#include "track_filter.h"
-
-typedef struct Z80_Cpu Sgc_Cpu;
-
-// SGC file header
-enum { header_size = 0xA0 };
-struct header_t
-{
- 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
-static inline bool valid_tag( struct header_t* h )
-{
- return 0 == memcmp( h->tag, "SGC\x1A", 4 );
-}
-
-static inline int effect_count( struct header_t* h ) { return h->last_effect ? h->last_effect - h->first_effect + 1 : 0; }
-
-struct Sgc_Emu {
- bool fm_accessed;
-
- cpu_time_t play_period;
- cpu_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
- void* coleco_bios;
-
- // general
- int voice_count;
- int const* voice_types;
- int mute_mask_;
- int tempo;
- int gain;
-
- int sample_rate;
-
- // track-specific
- int current_track;
- int track_count;
-
- int clock_rate_;
- unsigned buf_changed_count;
-
- // M3u Playlist
- struct M3u_Playlist m3u;
- struct header_t header;
-
- struct setup_t tfilter;
- struct Track_Filter track_filter;
-
- struct Multi_Buffer stereo_buf;
-
- struct Sms_Apu apu;
- struct Sms_Fm_Apu fm_apu;
-
- Sgc_Cpu cpu;
-
- // large items
- struct Rom_Data rom;
- byte vectors [page_size + page_padding];
- byte unmapped_write [0x4000];
- byte ram [0x2000 + page_padding];
- byte ram2 [0x4000 + page_padding];
-};
-
-// Basic functionality (see Gme_File.h for file loading/track info functions)
-
-void Sgc_init( struct Sgc_Emu* this );
-
-blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size );
-
-static inline int clock_rate( struct Sgc_Emu* this ) { return this->header.rate ? 3546893 : 3579545; }
-
-// 0x2000 bytes
-static inline void set_coleco_bios( struct Sgc_Emu* this, void* p ) { this->coleco_bios = p; }
-
-// Set output sample rate. Must be called only once before loading file.
-blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int sample_rate );
-
-// Start a track, where 0 is the first track. Also clears warning string.
-blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track );
-
-// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
-// errors set warning string, and major errors also end track.
-blargg_err_t Sgc_play( struct Sgc_Emu* this, int count, sample_t* buf );
-
-// Track status/control
-
-// Number of milliseconds (1000 msec = 1 second) played since beginning of track
-int Track_tell( struct Sgc_Emu* this );
-
-// Seek to new time in track. Seeking backwards or far forward can take a while.
-blargg_err_t Track_seek( struct Sgc_Emu* this, int msec );
-
-// Skip n samples
-blargg_err_t Track_skip( struct Sgc_Emu* this, int n );
-
-// Set start time and length of track fade out. Once fade ends track_ended() returns
-// true. Fade time can be changed while track is playing.
-void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec );
-
-// True if a track has reached its end
-static inline bool Track_ended( struct Sgc_Emu* this )
-{
- return track_ended( &this->track_filter );
-}
-
-// Disables automatic end-of-track detection and skipping of silence at beginning
-static inline void Track_ignore_silence( struct Sgc_Emu* this, bool disable )
-{
- this->track_filter.silence_ignored_ = disable;
-}
-
-// Get track length in milliseconds
-static inline int Track_get_length( struct Sgc_Emu* this, int n )
-{
- int length = 120 * 1000; /* 2 minutes */
- if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
- struct entry_t* entry = &this->m3u.entries [n];
- length = entry->length;
- }
-
- return length;
-}
-
-// Sound customization
-
-// Adjust 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 Sound_set_tempo( struct Sgc_Emu* this, int t );
-
-// Mute/unmute voice i, where voice 0 is first voice
-void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute );
-
-// Set 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 Sound_mute_voices( struct Sgc_Emu* this, int mask );
-
-// Change overall output amplitude, where 1.0 results in minimal clamping.
-// Must be called before set_sample_rate().
-static inline void Sound_set_gain( struct Sgc_Emu* this, int g )
-{
- assert( !this->sample_rate ); // you must set gain before setting sample rate
- this->gain = g;
-}
-
-// True if Master System or Game Gear
-static inline bool sega_mapping( struct Sgc_Emu* this )
-{
- return this->header.system <= 1;
-}
-
-// Emulation (You shouldn't touch these)
-
-bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time );
-void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data );
-void cpu_write( struct Sgc_Emu* this, addr_t addr, int data );
-void jsr( struct Sgc_Emu* this, byte addr [2] );
-
-#endif
+// Sega/Game Gear/Coleco SGC music file emulator
+
+// Game_Music_Emu 0.6-pre
+#ifndef SGC_EMU_H
+#define SGC_EMU_H
+
+#include "blargg_common.h"
+#include "multi_buffer.h"
+
+#include "rom_data.h"
+#include "z80_cpu.h"
+#include "sms_fm_apu.h"
+#include "sms_apu.h"
+#include "m3u_playlist.h"
+#include "track_filter.h"
+
+typedef struct Z80_Cpu Sgc_Cpu;
+
+// SGC file header
+enum { header_size = 0xA0 };
+struct header_t
+{
+ 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
+static inline bool valid_tag( struct header_t* h )
+{
+ return 0 == memcmp( h->tag, "SGC\x1A", 4 );
+}
+
+static inline int effect_count( struct header_t* h ) { return h->last_effect ? h->last_effect - h->first_effect + 1 : 0; }
+
+struct Sgc_Emu {
+ bool fm_accessed;
+
+ cpu_time_t play_period;
+ cpu_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
+ void* coleco_bios;
+
+ // general
+ int voice_count;
+ int const* voice_types;
+ int mute_mask_;
+ int tempo;
+ int gain;
+
+ int sample_rate;
+
+ // track-specific
+ int current_track;
+ int track_count;
+
+ int clock_rate_;
+ unsigned buf_changed_count;
+
+ // M3u Playlist
+ struct M3u_Playlist m3u;
+ struct header_t header;
+
+ struct setup_t tfilter;
+ struct Track_Filter track_filter;
+
+ struct Multi_Buffer stereo_buf;
+
+ struct Sms_Apu apu;
+ struct Sms_Fm_Apu fm_apu;
+
+ Sgc_Cpu cpu;
+
+ // large items
+ struct Rom_Data rom;
+ byte vectors [page_size + page_padding];
+ byte unmapped_write [0x4000];
+ byte ram [0x2000 + page_padding];
+ byte ram2 [0x4000 + page_padding];
+};
+
+// Basic functionality (see Gme_File.h for file loading/track info functions)
+
+void Sgc_init( struct Sgc_Emu* this );
+
+blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size );
+
+static inline int clock_rate( struct Sgc_Emu* this ) { return this->header.rate ? 3546893 : 3579545; }
+
+// 0x2000 bytes
+static inline void set_coleco_bios( struct Sgc_Emu* this, void* p ) { this->coleco_bios = p; }
+
+// Set output sample rate. Must be called only once before loading file.
+blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int sample_rate );
+
+// Start a track, where 0 is the first track. Also clears warning string.
+blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track );
+
+// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
+// errors set warning string, and major errors also end track.
+blargg_err_t Sgc_play( struct Sgc_Emu* this, int count, sample_t* buf );
+
+// Track status/control
+
+// Number of milliseconds (1000 msec = 1 second) played since beginning of track
+int Track_tell( struct Sgc_Emu* this );
+
+// Seek to new time in track. Seeking backwards or far forward can take a while.
+blargg_err_t Track_seek( struct Sgc_Emu* this, int msec );
+
+// Skip n samples
+blargg_err_t Track_skip( struct Sgc_Emu* this, int n );
+
+// Set start time and length of track fade out. Once fade ends track_ended() returns
+// true. Fade time can be changed while track is playing.
+void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec );
+
+// True if a track has reached its end
+static inline bool Track_ended( struct Sgc_Emu* this )
+{
+ return track_ended( &this->track_filter );
+}
+
+// Disables automatic end-of-track detection and skipping of silence at beginning
+static inline void Track_ignore_silence( struct Sgc_Emu* this, bool disable )
+{
+ this->track_filter.silence_ignored_ = disable;
+}
+
+// Get track length in milliseconds
+static inline int Track_get_length( struct Sgc_Emu* this, int n )
+{
+ int length = 120 * 1000; /* 2 minutes */
+ if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
+ struct entry_t* entry = &this->m3u.entries [n];
+ length = entry->length;
+ }
+
+ return length;
+}
+
+// Sound customization
+
+// Adjust 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 Sound_set_tempo( struct Sgc_Emu* this, int t );
+
+// Mute/unmute voice i, where voice 0 is first voice
+void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute );
+
+// Set 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 Sound_mute_voices( struct Sgc_Emu* this, int mask );
+
+// Change overall output amplitude, where 1.0 results in minimal clamping.
+// Must be called before set_sample_rate().
+static inline void Sound_set_gain( struct Sgc_Emu* this, int g )
+{
+ assert( !this->sample_rate ); // you must set gain before setting sample rate
+ this->gain = g;
+}
+
+// True if Master System or Game Gear
+static inline bool sega_mapping( struct Sgc_Emu* this )
+{
+ return this->header.system <= 1;
+}
+
+// Emulation (You shouldn't touch these)
+
+bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time );
+void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data );
+void cpu_write( struct Sgc_Emu* this, addr_t addr, int data );
+void jsr( struct Sgc_Emu* this, byte addr [2] );
+
+#endif
diff --git a/apps/codecs/libgme/sms_fm_apu.c b/apps/codecs/libgme/sms_fm_apu.c
index 6fd00545d6..ee5ce48932 100644
--- a/apps/codecs/libgme/sms_fm_apu.c
+++ b/apps/codecs/libgme/sms_fm_apu.c
@@ -1,82 +1,82 @@
-#include "sms_fm_apu.h"
-
-#include "blargg_source.h"
-
-void Fm_apu_create( struct Sms_Fm_Apu* this )
-{
- Synth_init( &this->synth );
- Ym2413_init( &this->apu );
-}
-
-blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate )
-{
- this->period_ = (blip_time_t) (clock_rate / sample_rate);
- CHECK_ALLOC( !Ym2413_set_rate( &this->apu, sample_rate, clock_rate ) );
-
- Fm_apu_set_output( this, 0 );
- Fm_apu_volume( this, (int)FP_ONE_VOLUME );
- Fm_apu_reset( this );
- return 0;
-}
-
-void Fm_apu_reset( struct Sms_Fm_Apu* this )
-{
- this->addr = 0;
- this->next_time = 0;
- this->last_amp = 0;
-
- Ym2413_reset( &this->apu );
-}
-
-void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time );
-void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t time, int data )
-{
- if ( time > this->next_time )
- fm_run_until( this, time );
-
- Ym2413_write( &this->apu, this->addr, data );
-}
-
-void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time )
-{
- assert( end_time > this->next_time );
-
- struct Blip_Buffer* const output = this->output_;
- if ( !output )
- {
- this->next_time = end_time;
- return;
- }
-
- blip_time_t time = this->next_time;
- struct Ym2413_Emu* emu = &this->apu;
- do
- {
- short samples [2];
- Ym2413_run( emu, 1, samples );
- int amp = (samples [0] + samples [1]) >> 1;
-
- int delta = amp - this->last_amp;
- if ( delta )
- {
- this->last_amp = amp;
- Synth_offset_inline( &this->synth, time, delta, output );
- }
- time += this->period_;
- }
- while ( time < end_time );
-
- this->next_time = time;
-}
-
-void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t time )
-{
- if ( time > this->next_time )
- fm_run_until( this, time );
-
- this->next_time -= time;
- assert( this->next_time >= 0 );
-
- if ( this->output_ )
- Blip_set_modified( this->output_ );
-}
+#include "sms_fm_apu.h"
+
+#include "blargg_source.h"
+
+void Fm_apu_create( struct Sms_Fm_Apu* this )
+{
+ Synth_init( &this->synth );
+ Ym2413_init( &this->apu );
+}
+
+blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate )
+{
+ this->period_ = (blip_time_t) (clock_rate / sample_rate);
+ CHECK_ALLOC( !Ym2413_set_rate( &this->apu, sample_rate, clock_rate ) );
+
+ Fm_apu_set_output( this, 0 );
+ Fm_apu_volume( this, (int)FP_ONE_VOLUME );
+ Fm_apu_reset( this );
+ return 0;
+}
+
+void Fm_apu_reset( struct Sms_Fm_Apu* this )
+{
+ this->addr = 0;
+ this->next_time = 0;
+ this->last_amp = 0;
+
+ Ym2413_reset( &this->apu );
+}
+
+void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time );
+void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t time, int data )
+{
+ if ( time > this->next_time )
+ fm_run_until( this, time );
+
+ Ym2413_write( &this->apu, this->addr, data );
+}
+
+void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time )
+{
+ assert( end_time > this->next_time );
+
+ struct Blip_Buffer* const output = this->output_;
+ if ( !output )
+ {
+ this->next_time = end_time;
+ return;
+ }
+
+ blip_time_t time = this->next_time;
+ struct Ym2413_Emu* emu = &this->apu;
+ do
+ {
+ short samples [2];
+ Ym2413_run( emu, 1, samples );
+ int amp = (samples [0] + samples [1]) >> 1;
+
+ int delta = amp - this->last_amp;
+ if ( delta )
+ {
+ this->last_amp = amp;
+ Synth_offset_inline( &this->synth, time, delta, output );
+ }
+ time += this->period_;
+ }
+ while ( time < end_time );
+
+ this->next_time = time;
+}
+
+void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t time )
+{
+ if ( time > this->next_time )
+ fm_run_until( this, time );
+
+ this->next_time -= time;
+ assert( this->next_time >= 0 );
+
+ if ( this->output_ )
+ Blip_set_modified( this->output_ );
+}
diff --git a/apps/codecs/libgme/sms_fm_apu.h b/apps/codecs/libgme/sms_fm_apu.h
index 00bc2b409c..921db6cef1 100644
--- a/apps/codecs/libgme/sms_fm_apu.h
+++ b/apps/codecs/libgme/sms_fm_apu.h
@@ -1,43 +1,43 @@
-#ifndef SMS_FM_APU_H
-#define SMS_FM_APU_H
-
-#include "blargg_common.h"
-#include "blip_buffer.h"
-#include "ym2413_emu.h"
-
-enum { fm_apu_osc_count = 1 };
-
-struct Sms_Fm_Apu {
- struct Blip_Buffer* output_;
- blip_time_t next_time;
- int last_amp;
- int addr;
-
- int clock_;
- int rate_;
- blip_time_t period_;
-
- struct Blip_Synth synth;
- struct Ym2413_Emu apu;
-};
-
-void Fm_apu_create( struct Sms_Fm_Apu* this );
-
-static inline bool Fm_apu_supported( void ) { return Ym2413_supported(); }
-blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate );
-
-static inline void Fm_apu_set_output( struct Sms_Fm_Apu* this, struct Blip_Buffer* b )
-{
- this->output_ = b;
-}
-
-static inline void Fm_apu_volume( struct Sms_Fm_Apu* this, int v ) { Synth_volume( &this->synth, (v*2) / 5 / 4096 ); }
-
-void Fm_apu_reset( struct Sms_Fm_Apu* this );
-
-static inline void Fm_apu_write_addr( struct Sms_Fm_Apu* this, int data ) { this->addr = data; }
-void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t, int data );
-
-void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t t );
-
-#endif
+#ifndef SMS_FM_APU_H
+#define SMS_FM_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+#include "ym2413_emu.h"
+
+enum { fm_apu_osc_count = 1 };
+
+struct Sms_Fm_Apu {
+ struct Blip_Buffer* output_;
+ blip_time_t next_time;
+ int last_amp;
+ int addr;
+
+ int clock_;
+ int rate_;
+ blip_time_t period_;
+
+ struct Blip_Synth synth;
+ struct Ym2413_Emu apu;
+};
+
+void Fm_apu_create( struct Sms_Fm_Apu* this );
+
+static inline bool Fm_apu_supported( void ) { return Ym2413_supported(); }
+blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate );
+
+static inline void Fm_apu_set_output( struct Sms_Fm_Apu* this, struct Blip_Buffer* b )
+{
+ this->output_ = b;
+}
+
+static inline void Fm_apu_volume( struct Sms_Fm_Apu* this, int v ) { Synth_volume( &this->synth, (v*2) / 5 / 4096 ); }
+
+void Fm_apu_reset( struct Sms_Fm_Apu* this );
+
+static inline void Fm_apu_write_addr( struct Sms_Fm_Apu* this, int data ) { this->addr = data; }
+void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t, int data );
+
+void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t t );
+
+#endif
diff --git a/apps/codecs/libgme/track_filter.c b/apps/codecs/libgme/track_filter.c
index 4776dcc7df..d0d75f2ded 100644
--- a/apps/codecs/libgme/track_filter.c
+++ b/apps/codecs/libgme/track_filter.c
@@ -1,294 +1,294 @@
-// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
-
-#include "track_filter.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 fade_block_size = 512;
-int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
-int const silence_threshold = 8;
-
-void track_create( struct Track_Filter* this )
-{
- this->emu_ = NULL;
- this->setup_.max_initial = 0;
- this->setup_.lookahead = 0;
- this->setup_.max_silence = indefinite_count;
- this->silence_ignored_ = false;
- track_stop( this );
-}
-
-blargg_err_t track_init( struct Track_Filter* this, void* emu )
-{
- this->emu_ = emu;
- return 0;
-}
-
-static void clear_time_vars( struct Track_Filter* this )
-{
- this->emu_time = this->buf_remain;
- this->out_time = 0;
- this->silence_time = 0;
- this->silence_count = 0;
-}
-
-void track_stop( struct Track_Filter* this )
-{
- this->emu_track_ended_ = true;
- this->track_ended_ = true;
- this->fade_start = indefinite_count;
- this->fade_step = 1;
- this->buf_remain = 0;
- this->emu_error = NULL;
- clear_time_vars( this );
-}
-
-blargg_err_t track_start( struct Track_Filter* this )
-{
- this->emu_error = NULL;
- track_stop( this );
-
- this->emu_track_ended_ = false;
- this->track_ended_ = false;
-
- if ( !this->silence_ignored_ )
- {
- // play until non-silence or end of track
- while ( this->emu_time < this->setup_.max_initial )
- {
- fill_buf( this );
- if ( this->buf_remain | this->emu_track_ended_ )
- break;
- }
- }
-
- clear_time_vars( this );
- return this->emu_error;
-}
-
-static void end_track_if_error( struct Track_Filter* this, blargg_err_t err )
-{
- if ( err )
- {
- this->emu_error = err;
- this->emu_track_ended_ = true;
- }
-}
-
-blargg_err_t track_skip( struct Track_Filter* this, int count )
-{
- this->emu_error = NULL;
- this->out_time += count;
-
- // remove from silence and buf first
- {
- int n = min( count, this->silence_count );
- this->silence_count -= n;
- count -= n;
-
- n = min( count, this->buf_remain );
- this->buf_remain -= n;
- count -= n;
- }
-
- if ( count && !this->emu_track_ended_ )
- {
- this->emu_time += count;
- this->silence_time = this->emu_time; // would otherwise be invalid
- end_track_if_error( this, skip_( this->emu_, count ) );
- }
-
- if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
- this->track_ended_ |= this->emu_track_ended_;
-
- return this->emu_error;
-}
-
-blargg_err_t skippy_( struct Track_Filter* this, int count )
-{
- while ( count && !this->emu_track_ended_ )
- {
- int n = buf_size;
- if ( n > count )
- n = count;
- count -= n;
- RETURN_ERR( play_( this->emu_, n, this->buf ) );
- }
- return 0;
-}
-
-// Fading
-
-void track_set_fade( struct Track_Filter* this, int start, int length )
-{
- this->fade_start = start;
- this->fade_step = length / (fade_block_size * fade_shift);
- if ( this->fade_step < 1 )
- this->fade_step = 1;
-}
-
-static bool is_fading( struct Track_Filter* this )
-{
- return this->out_time >= this->fade_start && this->fade_start != indefinite_count;
-}
-
-// unit / pow( 2.0, (double) x / step )
-static int int_log( int x, int step, int unit )
-{
- int shift = x / step;
- int fraction = (x - shift * step) * unit / step;
- return ((unit - fraction) + (fraction >> 1)) >> shift;
-}
-
-static void handle_fade( struct Track_Filter* this, sample_t out [], int out_count )
-{
- int i;
- for ( i = 0; i < out_count; i += fade_block_size )
- {
- int const shift = 14;
- int const unit = 1 << shift;
- int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
- this->fade_step, unit );
- if ( gain < (unit >> fade_shift) )
- this->track_ended_ = this->emu_track_ended_ = true;
-
- sample_t* io = &out [i];
- for ( int count = min( fade_block_size, out_count - i ); count; --count )
- {
- *io = (sample_t) ((*io * gain) >> shift);
- ++io;
- }
- }
-}
-
-// Silence detection
-
-static void emu_play( struct Track_Filter* this, sample_t out [], int count )
-{
- this->emu_time += count;
- if ( !this->emu_track_ended_ )
- end_track_if_error( this, play_( this->emu_, count, out ) );
- else
- memset( out, 0, count * sizeof *out );
-}
-
-// number of consecutive silent samples at end
-static int count_silence( sample_t begin [], int size )
-{
- sample_t first = *begin;
- *begin = silence_threshold * 2; // sentinel
- sample_t* p = begin + size;
- while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { }
- *begin = first;
- return size - (p - begin);
-}
-
-// fill internal buffer and check it for silence
-void fill_buf( struct Track_Filter* this )
-{
- assert( !this->buf_remain );
- if ( !this->emu_track_ended_ )
- {
- emu_play( this, this->buf, buf_size );
- int silence = count_silence( this->buf, buf_size );
- if ( silence < buf_size )
- {
- this->silence_time = this->emu_time - silence;
- this->buf_remain = buf_size;
- return;
- }
- }
- this->silence_count += buf_size;
-}
-
-blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] )
-{
- this->emu_error = NULL;
- if ( this->track_ended_ )
- {
- memset( out, 0, out_count * sizeof *out );
- }
- else
- {
- assert( this->emu_time >= this->out_time );
-
- // prints nifty graph of how far ahead we are when searching for silence
- //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" );
-
- // use any remaining silence samples
- int pos = 0;
- if ( this->silence_count )
- {
- if ( !this->silence_ignored_ )
- {
- // during a run of silence, run emulator at >=2x speed so it gets ahead
- int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) +
- this->silence_time;
- while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
- fill_buf( this );
-
- // end track if sufficient silence has been found
- if ( this->emu_time - this->silence_time > this->setup_.max_silence )
- {
- this->track_ended_ = this->emu_track_ended_ = true;
- this->silence_count = out_count;
- this->buf_remain = 0;
- }
- }
-
- // fill from remaining silence
- pos = min( this->silence_count, out_count );
- memset( out, 0, pos * sizeof *out );
- this->silence_count -= pos;
- }
-
- // use any remaining samples from buffer
- if ( this->buf_remain )
- {
- int n = min( this->buf_remain, (int) (out_count - pos) );
- memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out );
- this->buf_remain -= n;
- pos += n;
- }
-
- // generate remaining samples normally
- int remain = out_count - pos;
- if ( remain )
- {
- emu_play( this, out + pos, remain );
- this->track_ended_ |= this->emu_track_ended_;
-
- if ( this->silence_ignored_ && !is_fading( this ) )
- {
- // if left unupdated, ahead_time could become too large
- this->silence_time = this->emu_time;
- }
- else
- {
- // check end for a new run of silence
- int silence = count_silence( out + pos, remain );
- if ( silence < remain )
- this->silence_time = this->emu_time - silence;
-
- if ( this->emu_time - this->silence_time >= buf_size )
- fill_buf( this ); // cause silence detection on next play()
- }
- }
-
- if ( is_fading( this ) )
- handle_fade( this, out, out_count );
- }
- this->out_time += out_count;
- return this->emu_error;
-}
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "track_filter.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 fade_block_size = 512;
+int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
+int const silence_threshold = 8;
+
+void track_create( struct Track_Filter* this )
+{
+ this->emu_ = NULL;
+ this->setup_.max_initial = 0;
+ this->setup_.lookahead = 0;
+ this->setup_.max_silence = indefinite_count;
+ this->silence_ignored_ = false;
+ track_stop( this );
+}
+
+blargg_err_t track_init( struct Track_Filter* this, void* emu )
+{
+ this->emu_ = emu;
+ return 0;
+}
+
+static void clear_time_vars( struct Track_Filter* this )
+{
+ this->emu_time = this->buf_remain;
+ this->out_time = 0;
+ this->silence_time = 0;
+ this->silence_count = 0;
+}
+
+void track_stop( struct Track_Filter* this )
+{
+ this->emu_track_ended_ = true;
+ this->track_ended_ = true;
+ this->fade_start = indefinite_count;
+ this->fade_step = 1;
+ this->buf_remain = 0;
+ this->emu_error = NULL;
+ clear_time_vars( this );
+}
+
+blargg_err_t track_start( struct Track_Filter* this )
+{
+ this->emu_error = NULL;
+ track_stop( this );
+
+ this->emu_track_ended_ = false;
+ this->track_ended_ = false;
+
+ if ( !this->silence_ignored_ )
+ {
+ // play until non-silence or end of track
+ while ( this->emu_time < this->setup_.max_initial )
+ {
+ fill_buf( this );
+ if ( this->buf_remain | this->emu_track_ended_ )
+ break;
+ }
+ }
+
+ clear_time_vars( this );
+ return this->emu_error;
+}
+
+static void end_track_if_error( struct Track_Filter* this, blargg_err_t err )
+{
+ if ( err )
+ {
+ this->emu_error = err;
+ this->emu_track_ended_ = true;
+ }
+}
+
+blargg_err_t track_skip( struct Track_Filter* this, int count )
+{
+ this->emu_error = NULL;
+ this->out_time += count;
+
+ // remove from silence and buf first
+ {
+ int n = min( count, this->silence_count );
+ this->silence_count -= n;
+ count -= n;
+
+ n = min( count, this->buf_remain );
+ this->buf_remain -= n;
+ count -= n;
+ }
+
+ if ( count && !this->emu_track_ended_ )
+ {
+ this->emu_time += count;
+ this->silence_time = this->emu_time; // would otherwise be invalid
+ end_track_if_error( this, skip_( this->emu_, count ) );
+ }
+
+ if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
+ this->track_ended_ |= this->emu_track_ended_;
+
+ return this->emu_error;
+}
+
+blargg_err_t skippy_( struct Track_Filter* this, int count )
+{
+ while ( count && !this->emu_track_ended_ )
+ {
+ int n = buf_size;
+ if ( n > count )
+ n = count;
+ count -= n;
+ RETURN_ERR( play_( this->emu_, n, this->buf ) );
+ }
+ return 0;
+}
+
+// Fading
+
+void track_set_fade( struct Track_Filter* this, int start, int length )
+{
+ this->fade_start = start;
+ this->fade_step = length / (fade_block_size * fade_shift);
+ if ( this->fade_step < 1 )
+ this->fade_step = 1;
+}
+
+static bool is_fading( struct Track_Filter* this )
+{
+ return this->out_time >= this->fade_start && this->fade_start != indefinite_count;
+}
+
+// unit / pow( 2.0, (double) x / step )
+static int int_log( int x, int step, int unit )
+{
+ int shift = x / step;
+ int fraction = (x - shift * step) * unit / step;
+ return ((unit - fraction) + (fraction >> 1)) >> shift;
+}
+
+static void handle_fade( struct Track_Filter* this, sample_t out [], int out_count )
+{
+ int i;
+ for ( i = 0; i < out_count; i += fade_block_size )
+ {
+ int const shift = 14;
+ int const unit = 1 << shift;
+ int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
+ this->fade_step, unit );
+ if ( gain < (unit >> fade_shift) )
+ this->track_ended_ = this->emu_track_ended_ = true;
+
+ sample_t* io = &out [i];
+ for ( int count = min( fade_block_size, out_count - i ); count; --count )
+ {
+ *io = (sample_t) ((*io * gain) >> shift);
+ ++io;
+ }
+ }
+}
+
+// Silence detection
+
+static void emu_play( struct Track_Filter* this, sample_t out [], int count )
+{
+ this->emu_time += count;
+ if ( !this->emu_track_ended_ )
+ end_track_if_error( this, play_( this->emu_, count, out ) );
+ else
+ memset( out, 0, count * sizeof *out );
+}
+
+// number of consecutive silent samples at end
+static int count_silence( sample_t begin [], int size )
+{
+ sample_t first = *begin;
+ *begin = silence_threshold * 2; // sentinel
+ sample_t* p = begin + size;
+ while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { }
+ *begin = first;
+ return size - (p - begin);
+}
+
+// fill internal buffer and check it for silence
+void fill_buf( struct Track_Filter* this )
+{
+ assert( !this->buf_remain );
+ if ( !this->emu_track_ended_ )
+ {
+ emu_play( this, this->buf, buf_size );
+ int silence = count_silence( this->buf, buf_size );
+ if ( silence < buf_size )
+ {
+ this->silence_time = this->emu_time - silence;
+ this->buf_remain = buf_size;
+ return;
+ }
+ }
+ this->silence_count += buf_size;
+}
+
+blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] )
+{
+ this->emu_error = NULL;
+ if ( this->track_ended_ )
+ {
+ memset( out, 0, out_count * sizeof *out );
+ }
+ else
+ {
+ assert( this->emu_time >= this->out_time );
+
+ // prints nifty graph of how far ahead we are when searching for silence
+ //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" );
+
+ // use any remaining silence samples
+ int pos = 0;
+ if ( this->silence_count )
+ {
+ if ( !this->silence_ignored_ )
+ {
+ // during a run of silence, run emulator at >=2x speed so it gets ahead
+ int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) +
+ this->silence_time;
+ while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
+ fill_buf( this );
+
+ // end track if sufficient silence has been found
+ if ( this->emu_time - this->silence_time > this->setup_.max_silence )
+ {
+ this->track_ended_ = this->emu_track_ended_ = true;
+ this->silence_count = out_count;
+ this->buf_remain = 0;
+ }
+ }
+
+ // fill from remaining silence
+ pos = min( this->silence_count, out_count );
+ memset( out, 0, pos * sizeof *out );
+ this->silence_count -= pos;
+ }
+
+ // use any remaining samples from buffer
+ if ( this->buf_remain )
+ {
+ int n = min( this->buf_remain, (int) (out_count - pos) );
+ memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out );
+ this->buf_remain -= n;
+ pos += n;
+ }
+
+ // generate remaining samples normally
+ int remain = out_count - pos;
+ if ( remain )
+ {
+ emu_play( this, out + pos, remain );
+ this->track_ended_ |= this->emu_track_ended_;
+
+ if ( this->silence_ignored_ && !is_fading( this ) )
+ {
+ // if left unupdated, ahead_time could become too large
+ this->silence_time = this->emu_time;
+ }
+ else
+ {
+ // check end for a new run of silence
+ int silence = count_silence( out + pos, remain );
+ if ( silence < remain )
+ this->silence_time = this->emu_time - silence;
+
+ if ( this->emu_time - this->silence_time >= buf_size )
+ fill_buf( this ); // cause silence detection on next play()
+ }
+ }
+
+ if ( is_fading( this ) )
+ handle_fade( this, out, out_count );
+ }
+ this->out_time += out_count;
+ return this->emu_error;
+}
diff --git a/apps/codecs/libgme/track_filter.h b/apps/codecs/libgme/track_filter.h
index 35049b91bb..3689be9620 100644
--- a/apps/codecs/libgme/track_filter.h
+++ b/apps/codecs/libgme/track_filter.h
@@ -1,90 +1,90 @@
-// Removes silence from beginning of track, fades end of track. Also looks ahead
-// for excessive silence, and if found, ends track.
-
-// Game_Music_Emu 0.6-pre
-#ifndef TRACK_FILTER_H
-#define TRACK_FILTER_H
-
-#include "blargg_common.h"
-
-typedef short sample_t;
-typedef int sample_count_t;
-
-enum { indefinite_count = INT_MAX/2 + 1 };
-enum { buf_size = 2048 };
-
-struct setup_t {
- sample_count_t max_initial; // maximum silence to strip from beginning of track
- sample_count_t max_silence; // maximum silence in middle of track without it ending
- int lookahead; // internal speed when looking ahead for silence (2=200% etc.)
-};
-
-struct Track_Filter {
- void* emu_;
- struct setup_t setup_;
- const char* emu_error;
- bool silence_ignored_;
-
- // Timing
- int out_time; // number of samples played since start of track
- int emu_time; // number of samples emulator has generated since start of track
- int emu_track_ended_; // emulator has reached end of track
- volatile int track_ended_;
-
- // Fading
- int fade_start;
- int fade_step;
-
- // Silence detection
- int silence_time; // absolute number of samples where most recent silence began
- int silence_count; // number of samples of silence to play before using buf
- int buf_remain; // number of samples left in silence buffer
- sample_t buf [buf_size];
-};
-
-// Initializes filter. Must be done once before using object.
-blargg_err_t track_init( struct Track_Filter* this, void* );
-void track_create( struct Track_Filter* this );
-
-// Gets/sets setup
-static inline struct setup_t const* track_get_setup( struct Track_Filter* this ) { return &this->setup_; }
-static inline void track_setup( struct Track_Filter* this, struct setup_t const* s ) { this->setup_ = *s; }
-
-// Disables automatic end-of-track detection and skipping of silence at beginning
-static inline void track_ignore_silence( struct Track_Filter* this, bool disable ) { this->silence_ignored_ = disable; }
-
-// Clears state and skips initial silence in track
-blargg_err_t track_start( struct Track_Filter* this );
-
-// Sets time that fade starts, and how long until track ends.
-void track_set_fade( struct Track_Filter* this, sample_count_t start, sample_count_t length );
-
-// Generates n samples into buf
-blargg_err_t track_play( struct Track_Filter* this, int n, sample_t buf [] );
-
-// Skips n samples
-blargg_err_t track_skip( struct Track_Filter* this, int n );
-
-// Number of samples played/skipped since start_track()
-static inline int track_sample_count( struct Track_Filter* this ) { return this->out_time; }
-
-// True if track ended. Causes are end of source samples, end of fade,
-// or excessive silence.
-static inline bool track_ended( struct Track_Filter* this ) { return this->track_ended_; }
-
-// Clears state
-void track_stop( struct Track_Filter* this );
-
-// For use by callbacks
-
-// Sets internal "track ended" flag and stops generation of further source samples
-static inline void track_set_end( struct Track_Filter* this ) { this->emu_track_ended_ = true; }
-
-// For use by skip_() callback
-blargg_err_t skippy_( struct Track_Filter* this, int count );
-void fill_buf( struct Track_Filter* this );
-
-// Skip and play callbacks
-blargg_err_t skip_( void* emu, int count );
-blargg_err_t play_( void* emu, int count, sample_t out [] );
-#endif
+// Removes silence from beginning of track, fades end of track. Also looks ahead
+// for excessive silence, and if found, ends track.
+
+// Game_Music_Emu 0.6-pre
+#ifndef TRACK_FILTER_H
+#define TRACK_FILTER_H
+
+#include "blargg_common.h"
+
+typedef short sample_t;
+typedef int sample_count_t;
+
+enum { indefinite_count = INT_MAX/2 + 1 };
+enum { buf_size = 2048 };
+
+struct setup_t {
+ sample_count_t max_initial; // maximum silence to strip from beginning of track
+ sample_count_t max_silence; // maximum silence in middle of track without it ending
+ int lookahead; // internal speed when looking ahead for silence (2=200% etc.)
+};
+
+struct Track_Filter {
+ void* emu_;
+ struct setup_t setup_;
+ const char* emu_error;
+ bool silence_ignored_;
+
+ // Timing
+ int out_time; // number of samples played since start of track
+ int emu_time; // number of samples emulator has generated since start of track
+ int emu_track_ended_; // emulator has reached end of track
+ volatile int track_ended_;
+
+ // Fading
+ int fade_start;
+ int fade_step;
+
+ // Silence detection
+ int silence_time; // absolute number of samples where most recent silence began
+ int silence_count; // number of samples of silence to play before using buf
+ int buf_remain; // number of samples left in silence buffer
+ sample_t buf [buf_size];
+};
+
+// Initializes filter. Must be done once before using object.
+blargg_err_t track_init( struct Track_Filter* this, void* );
+void track_create( struct Track_Filter* this );
+
+// Gets/sets setup
+static inline struct setup_t const* track_get_setup( struct Track_Filter* this ) { return &this->setup_; }
+static inline void track_setup( struct Track_Filter* this, struct setup_t const* s ) { this->setup_ = *s; }
+
+// Disables automatic end-of-track detection and skipping of silence at beginning
+static inline void track_ignore_silence( struct Track_Filter* this, bool disable ) { this->silence_ignored_ = disable; }
+
+// Clears state and skips initial silence in track
+blargg_err_t track_start( struct Track_Filter* this );
+
+// Sets time that fade starts, and how long until track ends.
+void track_set_fade( struct Track_Filter* this, sample_count_t start, sample_count_t length );
+
+// Generates n samples into buf
+blargg_err_t track_play( struct Track_Filter* this, int n, sample_t buf [] );
+
+// Skips n samples
+blargg_err_t track_skip( struct Track_Filter* this, int n );
+
+// Number of samples played/skipped since start_track()
+static inline int track_sample_count( struct Track_Filter* this ) { return this->out_time; }
+
+// True if track ended. Causes are end of source samples, end of fade,
+// or excessive silence.
+static inline bool track_ended( struct Track_Filter* this ) { return this->track_ended_; }
+
+// Clears state
+void track_stop( struct Track_Filter* this );
+
+// For use by callbacks
+
+// Sets internal "track ended" flag and stops generation of further source samples
+static inline void track_set_end( struct Track_Filter* this ) { this->emu_track_ended_ = true; }
+
+// For use by skip_() callback
+blargg_err_t skippy_( struct Track_Filter* this, int count );
+void fill_buf( struct Track_Filter* this );
+
+// Skip and play callbacks
+blargg_err_t skip_( void* emu, int count );
+blargg_err_t play_( void* emu, int count, sample_t out [] );
+#endif
diff --git a/apps/codecs/libgme/vrc7tone.h b/apps/codecs/libgme/vrc7tone.h
index a256c80ba6..c589335c3c 100644
--- a/apps/codecs/libgme/vrc7tone.h
+++ b/apps/codecs/libgme/vrc7tone.h
@@ -1,20 +1,20 @@
-/* VRC7 TONES by okazaki@angel.ne.jp */
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x33,0x01,0x09,0x0e,0x94,0x90,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x13,0x41,0x0f,0x0d,0xce,0xd3,0x43,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x12,0x1b,0x06,0xff,0xd2,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x61,0x61,0x1b,0x07,0xaf,0x63,0x20,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x22,0x21,0x1e,0x06,0xf0,0x76,0x08,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x66,0x21,0x15,0x00,0x93,0x94,0x20,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x61,0x1c,0x07,0x82,0x81,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x23,0x21,0x20,0x1f,0xc0,0x71,0x07,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0x31,0x26,0x05,0x64,0x41,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x17,0x21,0x28,0x07,0xff,0x83,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x97,0x81,0x25,0x07,0xcf,0xc8,0x02,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x21,0x54,0x0f,0x80,0x7f,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x01,0x56,0x03,0xd3,0xb2,0x43,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x31,0x21,0x0c,0x03,0x82,0xc0,0x40,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x21,0x01,0x0c,0x03,0xd4,0xd3,0x40,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+/* VRC7 TONES by okazaki@angel.ne.jp */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x33,0x01,0x09,0x0e,0x94,0x90,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x13,0x41,0x0f,0x0d,0xce,0xd3,0x43,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x12,0x1b,0x06,0xff,0xd2,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x61,0x61,0x1b,0x07,0xaf,0x63,0x20,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x22,0x21,0x1e,0x06,0xf0,0x76,0x08,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x66,0x21,0x15,0x00,0x93,0x94,0x20,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x61,0x1c,0x07,0x82,0x81,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x23,0x21,0x20,0x1f,0xc0,0x71,0x07,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0x31,0x26,0x05,0x64,0x41,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x17,0x21,0x28,0x07,0xff,0x83,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x97,0x81,0x25,0x07,0xcf,0xc8,0x02,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x21,0x54,0x0f,0x80,0x7f,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x56,0x03,0xd3,0xb2,0x43,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x31,0x21,0x0c,0x03,0x82,0xc0,0x40,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x21,0x01,0x0c,0x03,0xd4,0xd3,0x40,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/apps/codecs/libgme/ym2413_emu.c b/apps/codecs/libgme/ym2413_emu.c
index 9efd3dcc3d..d9ada431ca 100644
--- a/apps/codecs/libgme/ym2413_emu.c
+++ b/apps/codecs/libgme/ym2413_emu.c
@@ -1,45 +1,45 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "ym2413_emu.h"
-
-void Ym2413_init( struct Ym2413_Emu* this )
-{
- this->last_time = disabled_time; this->out = 0;
-}
-
-int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate )
-{
- OPLL_new ( &this->opll, clock_rate, sample_rate );
- OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
-
- Ym2413_reset( this );
- return 0;
-}
-
-void Ym2413_reset( struct Ym2413_Emu* this )
-{
- OPLL_reset( &this->opll );
- OPLL_setMask( &this->opll, 0 );
-}
-
-void Ym2413_write( struct Ym2413_Emu* this, int addr, int data )
-{
- OPLL_writeIO( &this->opll, 0, addr );
- OPLL_writeIO( &this->opll, 1, data );
-}
-
-void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask )
-{
- OPLL_setMask( &this->opll, mask );
-}
-
-void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out )
-{
- while ( pair_count-- )
- {
- int s = OPLL_calc( &this->opll ) << 1;
- out [0] = s;
- out [1] = s;
- out += 2;
- }
-}
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "ym2413_emu.h"
+
+void Ym2413_init( struct Ym2413_Emu* this )
+{
+ this->last_time = disabled_time; this->out = 0;
+}
+
+int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate )
+{
+ OPLL_new ( &this->opll, clock_rate, sample_rate );
+ OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
+
+ Ym2413_reset( this );
+ return 0;
+}
+
+void Ym2413_reset( struct Ym2413_Emu* this )
+{
+ OPLL_reset( &this->opll );
+ OPLL_setMask( &this->opll, 0 );
+}
+
+void Ym2413_write( struct Ym2413_Emu* this, int addr, int data )
+{
+ OPLL_writeIO( &this->opll, 0, addr );
+ OPLL_writeIO( &this->opll, 1, data );
+}
+
+void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask )
+{
+ OPLL_setMask( &this->opll, mask );
+}
+
+void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out )
+{
+ while ( pair_count-- )
+ {
+ int s = OPLL_calc( &this->opll ) << 1;
+ out [0] = s;
+ out [1] = s;
+ out += 2;
+ }
+}
diff --git a/apps/codecs/libgme/ym2413_emu.h b/apps/codecs/libgme/ym2413_emu.h
index 68d8fe3d8f..8f52b04fbd 100644
--- a/apps/codecs/libgme/ym2413_emu.h
+++ b/apps/codecs/libgme/ym2413_emu.h
@@ -1,61 +1,61 @@
-// YM2413 FM sound chip emulator interface
-
-// Game_Music_Emu 0.6-pre
-#ifndef YM2413_EMU_H
-#define YM2413_EMU_H
-
-#include "blargg_common.h"
-#include "emu2413.h"
-
-enum { out_chan_count = 2 }; // stereo
-enum { channel_count = 14 };
-enum { disabled_time = -1 };
-
-struct Ym2413_Emu {
- OPLL opll;
-
- // Impl
- int last_time;
- short* out;
-};
-
-void Ym2413_init( struct Ym2413_Emu* this );
-
-static inline bool Ym2413_supported( void ) { return true; }
-
-// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
-// if error.
-int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate );
-
-// Resets to power-up state
-void Ym2413_reset( struct Ym2413_Emu* this );
-
-// Mutes voice n if bit n (1 << n) of mask is set
-void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask );
-
-// Writes data to addr
-void Ym2413_write( struct Ym2413_Emu* this, int addr, int data );
-
-// Runs and writes pair_count*2 samples to output
-void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out );
-
-static inline void Ym2413_enable( struct Ym2413_Emu* this, bool b ) { this->last_time = b ? 0 : disabled_time; }
-static inline bool Ym2413_enabled( struct Ym2413_Emu* this ) { return this->last_time != disabled_time; }
-static inline void Ym2413_begin_frame( struct Ym2413_Emu* this, short* buf ) { this->out = buf; this->last_time = 0; }
-
-static inline int Ym2413_run_until( struct Ym2413_Emu* this, int time )
-{
- int count = time - this->last_time;
- if ( count > 0 )
- {
- if ( this->last_time < 0 )
- return false;
- this->last_time = time;
- short* p = this->out;
- this->out += count * out_chan_count;
- Ym2413_run( this, count, p );
- }
- return true;
-}
-
-#endif
+// YM2413 FM sound chip emulator interface
+
+// Game_Music_Emu 0.6-pre
+#ifndef YM2413_EMU_H
+#define YM2413_EMU_H
+
+#include "blargg_common.h"
+#include "emu2413.h"
+
+enum { out_chan_count = 2 }; // stereo
+enum { channel_count = 14 };
+enum { disabled_time = -1 };
+
+struct Ym2413_Emu {
+ OPLL opll;
+
+ // Impl
+ int last_time;
+ short* out;
+};
+
+void Ym2413_init( struct Ym2413_Emu* this );
+
+static inline bool Ym2413_supported( void ) { return true; }
+
+// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
+// if error.
+int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate );
+
+// Resets to power-up state
+void Ym2413_reset( struct Ym2413_Emu* this );
+
+// Mutes voice n if bit n (1 << n) of mask is set
+void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask );
+
+// Writes data to addr
+void Ym2413_write( struct Ym2413_Emu* this, int addr, int data );
+
+// Runs and writes pair_count*2 samples to output
+void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out );
+
+static inline void Ym2413_enable( struct Ym2413_Emu* this, bool b ) { this->last_time = b ? 0 : disabled_time; }
+static inline bool Ym2413_enabled( struct Ym2413_Emu* this ) { return this->last_time != disabled_time; }
+static inline void Ym2413_begin_frame( struct Ym2413_Emu* this, short* buf ) { this->out = buf; this->last_time = 0; }
+
+static inline int Ym2413_run_until( struct Ym2413_Emu* this, int time )
+{
+ int count = time - this->last_time;
+ if ( count > 0 )
+ {
+ if ( this->last_time < 0 )
+ return false;
+ this->last_time = time;
+ short* p = this->out;
+ this->out += count * out_chan_count;
+ Ym2413_run( this, count, p );
+ }
+ return true;
+}
+
+#endif
diff --git a/apps/codecs/libgme/ymtables.h b/apps/codecs/libgme/ymtables.h
index 51812c1b57..c1619026b2 100644
--- a/apps/codecs/libgme/ymtables.h
+++ b/apps/codecs/libgme/ymtables.h
@@ -1,559 +1,559 @@
-#ifndef _EMUTABLES_H_
-#define _EMUTABLES_H_
-
-/* Precompiled ym2612 tables for use in Rockbox */
-
-static const int tl_coeff[] = {
- 268435455, 267712100, 266990695, 266271234, 265553712, 264838123, 264124462, 263412725, 262702906, 261994999, 261289000,
- 260584903, 259882704, 259182396, 258483976, 257787438, 257092777, 256399988, 255709066, 255020006, 254332802, 253647450,
- 252963945, 252282282, 251602456, 250924462, 250248294, 249573949, 248901421, 248230705, 247561797, 246894691, 246229383,
- 245565867, 244904140, 244244195, 243586029, 242929637, 242275013, 241622154, 240971053, 240321708, 239674112, 239028261,
- 238384150, 237741775, 237101131, 236462214, 235825018, 235189539, 234555773, 233923714, 233293359, 232664702, 232037740,
- 231412466, 230788878, 230166970, 229546738, 228928178, 228311284, 227696052, 227082479, 226470558, 225860287, 225251660,
- 224644674, 224039323, 223435603, 222833510, 222233039, 221634187, 221036948, 220441319, 219847295, 219254871, 218664044,
- 218074809, 217487162, 216901098, 216316614, 215733704, 215152366, 214572594, 213994384, 213417732, 212842635, 212269087,
- 211697084, 211126623, 210557699, 209990308, 209424446, 208860109, 208297293, 207735993, 207176206, 206617927, 206061153,
- 205505879, 204952102, 204399816, 203849019, 203299706, 202751873, 202205517, 201660633, 201117217, 200575266, 200034774,
- 199495740, 198958158, 198422024, 197887335, 197354088, 196822277, 196291899, 195762950, 195235427, 194709325, 194184641,
- 193661370, 193139510, 192619056, 192100005, 191582352, 191066094, 190551228, 190037748, 189525653, 189014937, 188505598,
- 187997631, 187491033, 186985800, 186481928, 185979414, 185478255, 184978446, 184479983, 183982864, 183487085, 182992641,
- 182499530, 182007748, 181517291, 181028155, 180540338, 180053835, 179568643, 179084759, 178602178, 178120898, 177640915,
- 177162225, 176684825, 176208712, 175733881, 175260330, 174788055, 174317053, 173847320, 173378853, 172911648, 172445702,
- 171981012, 171517574, 171055385, 170594441, 170134740, 169676277, 169219049, 168763054, 168308287, 167854746, 167402427,
- 166951327, 166501443, 166052770, 165605307, 165159050, 164713995, 164270139, 163827480, 163386013, 162945736, 162506646,
- 162068738, 161632011, 161196460, 160762083, 160328877, 159896838, 159465963, 159036250, 158607694, 158180293, 157754044,
- 157328943, 156904988, 156482176, 156060502, 155639965, 155220562, 154802288, 154385142, 153969119, 153554218, 153140435,
- 152727766, 152316210, 151905763, 151496422, 151088184, 150681046, 150275005, 149870058, 149466203, 149063435, 148661753,
- 148261154, 147861634, 147463190, 147065821, 146669522, 146274291, 145880125, 145487021, 145094976, 144703988, 144314054,
- 143925170, 143537334, 143150543, 142764795, 142380086, 141996414, 141613775, 141232168, 140851589, 140472035, 140093505,
- 139715994, 139339501, 138964022, 138589555, 138216097, 137843646, 137472198, 137101751, 136732302, 136363849, 135996388,
- 135629918, 135264436, 134899938, 134536423, 134173887, 133812328, 133451743, 133092130, 132733486, 132375808, 132019095,
- 131663342, 131308548, 130954711, 130601826, 130249893, 129898908, 129548869, 129199773, 128851618, 128504401, 128158119,
- 127812771, 127468353, 127124864, 126782300, 126440659, 126099939, 125760137, 125421250, 125083277, 124746214, 124410060,
- 124074812, 123740467, 123407023, 123074477, 122742828, 122412072, 122082208, 121753232, 121425143, 121097939, 120771615,
- 120446172, 120121605, 119797912, 119475092, 119153142, 118832060, 118511843, 118192488, 117873994, 117556359, 117239579,
- 116923653, 116608578, 116294353, 115980974, 115668439, 115356747, 115045894, 114735880, 114426700, 114118354, 113810839,
- 113504152, 113198292, 112893256, 112589042, 112285648, 111983071, 111681310, 111380362, 111080225, 110780896, 110482375,
- 110184657, 109887742, 109591627, 109296310, 109001789, 108708061, 108415125, 108122978, 107831619, 107541044, 107251253,
- 106962243, 106674011, 106386556, 106099876, 105813968, 105528830, 105244461, 104960859, 104678020, 104395944, 104114628,
- 103834069, 103554267, 103275219, 102996923, 102719377, 102442578, 102166526, 101891217, 101616650, 101342823, 101069734,
- 100797381, 100525762, 100254875, 99984718, 99715288, 99446585, 99178606, 98911349, 98644812, 98378993, 98113891,
- 97849503, 97585828, 97322863, 97060606, 96799057, 96538212, 96278070, 96018629, 95759887, 95501842, 95244493,
- 94987837, 94731873, 94476599, 94222012, 93968112, 93714895, 93462361, 93210508, 92959333, 92708835, 92459012,
- 92209863, 91961384, 91713575, 91466434, 91219959, 90974149, 90729000, 90484512, 90240683, 89997511, 89754994,
- 89513131, 89271920, 89031358, 88791445, 88552178, 88313556, 88075578, 87838240, 87601542, 87365481, 87130057,
- 86895267, 86661110, 86427584, 86194687, 85962418, 85730775, 85499756, 85269359, 85039583, 84810427, 84581888,
- 84353965, 84126656, 83899959, 83673874, 83448397, 83223528, 82999266, 82775607, 82552551, 82330096, 82108241,
- 81886984, 81666322, 81446256, 81226782, 81007900, 80789608, 80571904, 80354786, 80138254, 79922305, 79706938,
- 79492151, 79277943, 79064313, 78851258, 78638777, 78426868, 78215531, 78004763, 77794564, 77584930, 77375862,
- 77167357, 76959413, 76752031, 76545207, 76338940, 76133229, 75928072, 75723469, 75519416, 75315914, 75112960,
- 74910552, 74708690, 74507373, 74306597, 74106363, 73906668, 73707512, 73508892, 73310807, 73113256, 72916237,
- 72719749, 72523791, 72328361, 72133457, 71939079, 71745225, 71551892, 71359081, 71166789, 70975016, 70783759,
- 70593018, 70402791, 70213076, 70023872, 69835179, 69646994, 69459315, 69272143, 69085475, 68899310, 68713647,
- 68528484, 68343820, 68159653, 67975983, 67792808, 67610127, 67427937, 67246239, 67065030, 66884310, 66704076,
- 66524328, 66345065, 66166285, 65987986, 65810168, 65632829, 65455968, 65279583, 65103674, 64928239, 64753277,
- 64578786, 64404765, 64231213, 64058129, 63885511, 63713359, 63541670, 63370444, 63199679, 63029375, 62859529,
- 62690141, 62521210, 62352734, 62184711, 62017142, 61850024, 61683357, 61517138, 61351368, 61186044, 61021166,
- 60856731, 60692741, 60529192, 60366083, 60203414, 60041184, 59879391, 59718034, 59557111, 59396622, 59236566,
- 59076941, 58917746, 58758980, 58600642, 58442730, 58285245, 58128183, 57971545, 57815329, 57659533, 57504158,
- 57349201, 57194662, 57040539, 56886832, 56733539, 56580659, 56428190, 56276133, 56124486, 55973247, 55822415,
- 55671990, 55521971, 55372355, 55223143, 55074333, 54925924, 54777915, 54630305, 54483092, 54336276, 54189856,
- 54043830, 53898198, 53752959, 53608110, 53463652, 53319583, 53175903, 53032610, 52889702, 52747180, 52605042,
- 52463287, 52321914, 52180922, 52040310, 51900076, 51760221, 51620743, 51481640, 51342912, 51204558, 51066577,
- 50928968, 50791729, 50654860, 50518360, 50382228, 50246463, 50111064, 49976029, 49841359, 49707051, 49573105,
- 49439520, 49306295, 49173429, 49040922, 48908771, 48776976, 48645537, 48514451, 48383719, 48253339, 48123311,
- 47993633, 47864304, 47735324, 47606691, 47478405, 47350465, 47222869, 47095618, 46968709, 46842142, 46715916,
- 46590031, 46464484, 46339276, 46214406, 46089871, 45965673, 45841809, 45718279, 45595082, 45472216, 45349682,
- 45227478, 45105603, 44984057, 44862838, 44741946, 44621380, 44501139, 44381221, 44261627, 44142355, 44023404,
- 43904774, 43786464, 43668472, 43550798, 43433442, 43316402, 43199677, 43083266, 42967170, 42851386, 42735914,
- 42620753, 42505903, 42391362, 42277130, 42163206, 42049588, 41936277, 41823271, 41710570, 41598172, 41486077,
- 41374285, 41262793, 41151602, 41040711, 40930118, 40819823, 40709826, 40600125, 40490720, 40381609, 40272793,
- 40164269, 40056039, 39948099, 39840451, 39733093, 39626024, 39519243, 39412751, 39306545, 39200625, 39094991,
- 38989642, 38884576, 38779794, 38675294, 38571075, 38467138, 38363480, 38260102, 38157002, 38054180, 37951635,
- 37849367, 37747374, 37645656, 37544212, 37443042, 37342144, 37241518, 37141163, 37041078, 36941264, 36841718,
- 36742440, 36643430, 36544687, 36446210, 36347998, 36250051, 36152368, 36054948, 35957790, 35860895, 35764260,
- 35667886, 35571772, 35475916, 35380319, 35284980, 35189897, 35095071, 35000500, 34906184, 34812122, 34718314,
- 34624758, 34531454, 34438402, 34345601, 34253050, 34160748, 34068695, 33976890, 33885332, 33794021, 33702956,
- 33612137, 33521562, 33431231, 33341144, 33251299, 33161697, 33072336, 32983216, 32894336, 32805695, 32717294,
- 32629130, 32541204, 32453515, 32366063, 32278846, 32191864, 32105116, 32018602, 31932322, 31846273, 31760457,
- 31674872, 31589518, 31504393, 31419498, 31334832, 31250394, 31166183, 31082200, 30998442, 30914911, 30831604,
- 30748522, 30665664, 30583029, 30500617, 30418426, 30336458, 30254710, 30173183, 30091875, 30010786, 29929916,
- 29849263, 29768829, 29688610, 29608608, 29528822, 29449250, 29369893, 29290750, 29211820, 29133103, 29054598,
- 28976304, 28898222, 28820350, 28742687, 28665234, 28587990, 28510954, 28434125, 28357503, 28281088, 28204879,
- 28128875, 28053076, 27977482, 27902091, 27826903, 27751917, 27677134, 27602552, 27528172, 27453991, 27380011,
- 27306230, 27232648, 27159264, 27086078, 27013089, 26940296, 26867700, 26795300, 26723094, 26651083, 26579267,
- 26507643, 26436213, 26364975, 26293929, 26223075, 26152412, 26081939, 26011656, 25941562, 25871657, 25801940,
- 25732412, 25663071, 25593916, 25524948, 25456166, 25387569, 25319157, 25250929, 25182886, 25115025, 25047348,
- 24979852, 24912539, 24845407, 24778456, 24711686, 24645095, 24578684, 24512451, 24446397, 24380522, 24314823,
- 24249302, 24183957, 24118789, 24053796, 23988978, 23924335, 23859866, 23795570, 23731448, 23667499, 23603722,
- 23540117, 23476683, 23413421, 23350328, 23287406, 23224653, 23162070, 23099655, 23037408, 22975329, 22913417,
- 22851673, 22790094, 22728681, 22667434, 22606352, 22545435, 22484682, 22424092, 22363666, 22303402, 22243301,
- 22183362, 22123584, 22063968, 22004512, 21945216, 21886080, 21827104, 21768286, 21709627, 21651126, 21592783,
- 21534597, 21476567, 21418694, 21360977, 21303416, 21246009, 21188758, 21131660, 21074717, 21017926, 20961289,
- 20904805, 20848473, 20792292, 20736263, 20680385, 20624657, 20569080, 20513652, 20458374, 20403245, 20348264,
- 20293432, 20238747, 20184209, 20129819, 20075575, 20021477, 19967525, 19913719, 19860057, 19806540, 19753167,
- 19699938, 19646853, 19593910, 19541111, 19488453, 19435937, 19383563, 19331330, 19279238, 19227286, 19175474,
- 19123802, 19072269, 19020875, 18969619, 18918502, 18867522, 18816680, 18765974, 18715405, 18664973, 18614676,
- 18564515, 18514489, 18464598, 18414842, 18365219, 18315730, 18266375, 18217152, 18168062, 18119105, 18070279,
- 18021585, 17973022, 17924590, 17876289, 17828118, 17780076, 17732164, 17684381, 17636727, 17589201, 17541803,
- 17494533, 17447391, 17400375, 17353486, 17306724, 17260087, 17213577, 17167191, 17120930, 17074795, 17028783,
- 16982896, 16937132, 16891491, 16845974, 16800579, 16755306, 16710155, 16665126, 16620219, 16575432, 16530766,
- 16486221, 16441795, 16397490, 16353303, 16309236, 16265287, 16221457, 16177745, 16134151, 16090674, 16047314,
- 16004072, 15960945, 15917935, 15875041, 15832263, 15789599, 15747051, 15704617, 15662298, 15620093, 15578001,
- 15536023, 15494158, 15452406, 15410766, 15369239, 15327823, 15286519, 15245327, 15204245, 15163274, 15122414,
- 15081663, 15041023, 15000491, 14960070, 14919757, 14879552, 14839456, 14799468, 14759588, 14719815, 14680150,
- 14640591, 14601139, 14561793, 14522554, 14483420, 14444391, 14405468, 14366649, 14327935, 14289326, 14250820,
- 14212418, 14174120, 14135925, 14097833, 14059843, 14021956, 13984171, 13946488, 13908906, 13871426, 13834047,
- 13796768, 13759590, 13722512, 13685534, 13648655, 13611876, 13575196, 13538615, 13502132, 13465748, 13429462,
- 13393273, 13357183, 13321189, 13285292, 13249492, 13213789, 13178182, 13142670, 13107255, 13071934, 13036709,
- 13001579, 12966544, 12931603, 12896756, 12862003, 12827344, 12792778, 12758305, 12723925, 12689638, 12655443,
- 12621341, 12587330, 12553411, 12519583, 12485846, 12452201, 12418646, 12385181, 12351807, 12318522, 12285327,
- 12252222, 12219206, 12186279, 12153440, 12120690, 12088029, 12055455, 12022969, 11990571, 11958260, 11926036,
- 11893899, 11861848, 11829884, 11798006, 11766214, 11734507, 11702886, 11671350, 11639900, 11608533, 11577252,
- 11546055, 11514941, 11483912, 11452966, 11422104, 11391325, 11360628, 11330015, 11299484, 11269035, 11238668,
- 11208384, 11178180, 11148058, 11118018, 11088058, 11058179, 11028380, 10998662, 10969024, 10939466, 10909987,
- 10880588, 10851268, 10822027, 10792865, 10763781, 10734776, 10705849, 10677000, 10648228, 10619535, 10590918,
- 10562379, 10533916, 10505530, 10477221, 10448988, 10420831, 10392750, 10364745, 10336815, 10308960, 10281180,
- 10253476, 10225846, 10198290, 10170809, 10143401, 10116068, 10088808, 10061622, 10034509, 10007468, 9980501,
- 9953607, 9926785, 9900035, 9873357, 9846752, 9820217, 9793755, 9767364, 9741043, 9714794, 9688616,
- 9662508, 9636470, 9610503, 9584605, 9558778, 9533019, 9507331, 9481711, 9456161, 9430679, 9405266,
- 9379922, 9354646, 9329438, 9304298, 9279225, 9254221, 9229283, 9204413, 9179610, 9154874, 9130204,
- 9105601, 9081064, 9056593, 9032188, 9007849, 8983576, 8959368, 8935225, 8911147, 8887134, 8863186,
- 8839302, 8815483, 8791728, 8768037, 8744409, 8720846, 8697346, 8673909, 8650535, 8627225, 8603977,
- 8580792, 8557669, 8534608, 8511610, 8488674, 8465799, 8442987, 8420235, 8397545, 8374916, 8352348,
- 8329841, 8307395, 8285009, 8262683, 8240418, 8218212, 8196067, 8173981, 8151954, 8129987, 8108079,
- 8086230, 8064440, 8042709, 8021036, 7999422, 7977866, 7956368, 7934928, 7913545, 7892221, 7870954,
- 7849744, 7828591, 7807495, 7786456, 7765474, 7744548, 7723679, 7702866, 7682109, 7661408, 7640763,
- 7620173, 7599639, 7579160, 7558737, 7538368, 7518055, 7497796, 7477591, 7457441, 7437346, 7417304,
- 7397317, 7377383, 7357503, 7337677, 7317904, 7298185, 7278518, 7258905, 7239344, 7219836, 7200381,
- 7180978, 7161627, 7142329, 7123082, 7103888, 7084745, 7065654, 7046614, 7027625, 7008688, 6989802,
- 6970966, 6952181, 6933447, 6914764, 6896130, 6877547, 6859014, 6840531, 6822098, 6803715, 6785381,
- 6767096, 6748861, 6730675, 6712537, 6694449, 6676410, 6658419, 6640476, 6622582, 6604736, 6586938,
- 6569188, 6551486, 6533832, 6516225, 6498666, 6481154, 6463689, 6446272, 6428901, 6411577, 6394299,
- 6377069, 6359884, 6342746, 6325655, 6308609, 6291609, 6274655, 6257747, 6240884, 6224066, 6207294,
- 6190568, 6173886, 6157249, 6140657, 6124110, 6107607, 6091149, 6074735, 6058365, 6042040, 6025758,
- 6009521, 5993327, 5977177, 5961070, 5945007, 5928987, 5913010, 5897076, 5881185, 5865337, 5849532,
- 5833769, 5818049, 5802371, 5786735, 5771141, 5755590, 5740080, 5724612, 5709186, 5693802, 5678459,
- 5663157, 5647896, 5632677, 5617498, 5602361, 5587264, 5572208, 5557193, 5542218, 5527283, 5512389,
- 5497534, 5482720, 5467946, 5453211, 5438517, 5423861, 5409246, 5394669, 5380132, 5365635, 5351176,
- 5336756, 5322375, 5308033, 5293729, 5279464, 5265237, 5251049, 5236899, 5222787, 5208713, 5194677,
- 5180679, 5166719, 5152796, 5138911, 5125063, 5111252, 5097479, 5083743, 5070044, 5056382, 5042756,
- 5029167, 5015615, 5002100, 4988620, 4975178, 4961771, 4948400, 4935066, 4921767, 4908505, 4895278,
- 4882086, 4868931, 4855810, 4842725, 4829676, 4816661, 4803682, 4790737, 4777827, 4764953, 4752112,
- 4739307, 4726536, 4713799, 4701097, 4688429, 4675795, 4663195, 4650629, 4638097, 4625599, 4613134,
- 4600703, 4588306, 4575941, 4563611, 4551313, 4539049, 4526817, 4514619, 4502453, 4490320, 4478220,
- 4466153, 4454118, 4442115, 4430145, 4418207, 4406301, 4394428, 4382586, 4370776, 4358998, 4347252,
- 4335538, 4323855, 4312203, 4300583, 4288994, 4277437, 4265910, 4254415, 4242950, 4231517, 4220114,
- 4208742, 4197401, 4186090, 4174810, 4163560, 4152340, 4141151, 4129992, 4118863, 4107764, 4096694,
- 4085655, 4074645, 4063665, 4052715, 4041794, 4030903, 4020041, 4009208, 3998404, 3987630, 3976884,
- 3966168, 3955480, 3944821, 3934191, 3923590, 3913017, 3902472, 3891956, 3881469, 3871009, 3860578,
- 3850175, 3839800, 3829453, 3819133, 3808842, 3798578, 3788342, 3778134, 3767953, 3757799, 3747673,
- 3737574, 3727503, 3717458, 3707441, 3697450, 3687487, 3677550, 3667640, 3657757, 3647900, 3638070,
- 3628267, 3618490, 3608739, 3599014, 3589316, 3579644, 3569998, 3560378, 3550783, 3541215, 3531673,
- 3522156, 3512665, 3503199, 3493759, 3484344, 3474955, 3465591, 3456252, 3446939, 3437650, 3428387,
- 3419148, 3409935, 3400746, 3391582, 3382443, 3373328, 3364238, 3355172, 3346131, 3337114, 3328122,
- 3319153, 3310209, 3301289, 3292393, 3283521, 3274673, 3265849, 3257048, 3248271, 3239518, 3230789,
- 3222083, 3213400, 3204741, 3196105, 3187493, 3178903, 3170337, 3161794, 3153274, 3144777, 3136302,
- 3127851, 3119422, 3111016, 3102633, 3094272, 3085934, 3077619, 3069325, 3061054, 3052806, 3044579,
- 3036375, 3028193, 3020033, 3011895, 3003779, 2995684, 2987612, 2979561, 2971532, 2963525, 2955539,
- 2947575, 2939632, 2931710, 2923810, 2915931, 2908074, 2900237, 2892422, 2884628, 2876855, 2869102,
- 2861371, 2853660, 2845971, 2838302, 2830653, 2823025, 2815418, 2807832, 2800265, 2792719, 2785194,
- 2777689, 2770203, 2762739, 2755294, 2747869, 2740464, 2733080, 2725715, 2718370, 2711045, 2703739,
- 2696453, 2689187, 2681941, 2674714, 2667506, 2660318, 2653149, 2646000, 2638870, 2631759, 2624667,
- 2617594, 2610540, 2603506, 2596490, 2589493, 2582515, 2575556, 2568616, 2561694, 2554791, 2547907,
- 2541041, 2534194, 2527365, 2520554, 2513762, 2506988, 2500233, 2493495, 2486776, 2480075, 2473392,
- 2466727, 2460080, 2453450, 2446839, 2440246, 2433670, 2427112, 2420571, 2414049, 2407544, 2401056,
- 2394586, 2388133, 2381698, 2375280, 2368879, 2362496, 2356130, 2349780, 2343448, 2337134, 2330836,
- 2324555, 2318291, 2312044, 2305813, 2299600, 2293403, 2287223, 2281060, 2274913, 2268783, 2262669,
- 2256572, 2250491, 2244427, 2238379, 2232347, 2226331, 2220332, 2214349, 2208382, 2202431, 2196496,
- 2190577, 2184674, 2178787, 2172916, 2167060, 2161221, 2155397, 2149589, 2143796, 2138019, 2132258,
- 2126512, 2120782, 2115067, 2109368, 2103683, 2098015, 2092361, 2086723, 2081100, 2075492, 2069899,
- 2064321, 2058758, 2053211, 2047678, 2042160, 2036657, 2031169, 2025695, 2020237, 2014793, 2009364,
- 2003949, 1998549, 1993163, 1987792, 1982436, 1977094, 1971766, 1966453, 1961154, 1955869, 1950599,
- 1945342, 1940100, 1934872, 1929658, 1924458, 1919272, 1914101, 1908943, 1903799, 1898668, 1893552,
- 1888450, 1883361, 1878286, 1873224, 1868176, 1863142, 1858122, 1853115, 1848121, 1843141, 1838174,
- 1833221, 1828281, 1823354, 1818441, 1813540, 1808654, 1803780, 1798919, 1794072, 1789237, 1784416,
- 1779607, 1774812, 1770029, 1765259, 1760502, 1755758, 1751027, 1746309, 1741603, 1736910, 1732229,
- 1727561, 1722906, 1718263, 1713633, 1709015, 1704410, 1699817, 1695237, 1690669, 1686113, 1681569,
- 1677038, 1672519, 1668012, 1663517, 1659034, 1654564, 1650105, 1645659, 1641224, 1636801, 1632391,
- 1627992, 1623605, 1619230, 1614866, 1610515, 1606175, 1601847, 1597530, 1593225, 1588932, 1584650,
- 1580380, 1576122, 1571874, 1567639, 1563414, 1559201, 1555000, 1550810, 1546631, 1542463, 1538306,
- 1534161, 1530027, 1525904, 1521792, 1517691, 1513602, 1509523, 1505455, 1501399, 1497353, 1493318,
- 1489294, 1485281, 1481278, 1477287, 1473306, 1469336, 1465376, 1461427, 1457489, 1453562, 1449645,
- 1445738, 1441843, 1437957, 1434082, 1430218, 1426364, 1422520, 1418687, 1414864, 1411051, 1407249,
- 1403457, 1399675, 1395903, 1392142, 1388390, 1384649, 1380918, 1377197, 1373486, 1369784, 1366093,
- 1362412, 1358741, 1355079, 1351428, 1347786, 1344154, 1340532, 1336920, 1333317, 1329724, 1326141,
- 1322567, 1319004, 1315449, 1311904, 1308369, 1304844, 1301327, 1297821, 1294323, 1290836, 1287357,
- 1283888, 1280429, 1276978, 1273537, 1270105, 1266683, 1263269, 1259865, 1256470, 1253084, 1249708,
- 1246340, 1242982, 1239632, 1236292, 1232960, 1229638, 1226324, 1223020, 1219724, 1216437, 1213159,
- 1209890, 1206630, 1203378, 1200136, 1196902, 1193676, 1190460, 1187252, 1184052, 1180862, 1177680,
- 1174506, 1171341, 1168185, 1165037, 1161897, 1158767, 1155644, 1152530, 1149424, 1146327, 1143238,
- 1140157, 1137085, 1134021, 1130965, 1127917, 1124878, 1121846, 1118823, 1115809, 1112802, 1109803,
- 1106813, 1103830, 1100855, 1097889, 1094931, 1091980, 1089037, 1086103, 1083176, 1080257, 1077346,
- 1074443, 1071548, 1068660, 1065781, 1062909, 1060044, 1057188, 1054339, 1051498, 1048664, 1045839,
- 1043020, 1040210, 1037407, 1034611, 1031823, 1029043, 1026270, 1023504, 1020746, 1017996, 1015252,
- 1012517, 1009788, 1007067, 1004353, 1001647, 998948, 996256, 993571, 990894, 988224, 985561,
- 982905, 980256, 977615, 974980, 972353, 969733, 967120, 964514, 961915, 959323, 956737,
- 954159, 951588, 949024, 946467, 943916, 941373, 938836, 936306, 933783, 931267, 928757,
- 926254, 923758, 921269, 918787, 916311, 913842, 911379, 908923, 906474, 904031, 901595,
- 899166, 896743, 894326, 891916, 889513, 887116, 884725, 882341, 879963, 877592, 875227,
- 872869, 870517, 868171, 865831, 863498, 861171, 858851, 856536, 854228, 851926, 849631,
- 847341, 845058, 842781, 840510, 838245, 835986, 833733, 831487, 829246, 827011, 824783,
- 822560, 820344, 818133, 815929, 813730, 811537, 809350, 807169, 804994, 802825, 800662,
- 798504, 796352, 794206, 792066, 789932, 787803, 785680, 783563, 781452, 779346, 777246,
- 775151, 773062, 770979, 768902, 766830, 764763, 762703, 760647, 758598, 756553, 754515,
- 752482, 750454, 748432, 746415, 744403, 742397, 740397, 738402, 736412, 734428, 732448,
- 730475, 728506, 726543, 724585, 722633, 720686, 718744, 716807, 714875, 712949, 711028,
- 709112, 707201, 705295, 703394, 701499, 699609, 697723, 695843, 693968, 692098, 690233,
- 688373, 686518, 684668, 682823, 680983, 679148, 677318, 675493, 673673, 671857, 670047,
- 668241, 666441, 664645, 662854, 661067, 659286, 657510, 655738, 653971, 652208, 650451,
- 648698, 646950, 645207, 643468, 641734, 640005, 638280, 636560, 634845, 633134, 631428,
- 629727, 628030, 626337, 624650, 622966, 621288, 619613, 617944, 616279, 614618, 612962,
- 611310, 609663, 608020, 606381, 604747, 603118, 601492, 599872, 598255, 596643, 595035,
- 593432, 591833, 590238, 588647, 587061, 585479, 583901, 582328, 580759, 579194, 577633,
- 576076, 574524, 572976, 571432, 569892, 568356, 566825, 565297, 563774, 562255, 560740,
- 559229, 557722, 556219, 554720, 553225, 551734, 550248, 548765, 547286, 545811, 544341,
- 542874, 541411, 539952, 538497, 537046, 535599, 534155, 532716, 531280, 529849, 528421,
- 526997, 525577, 524161, 522748, 521340, 519935, 518534, 517136, 515743, 514353, 512967,
- 511585, 510206, 508831, 507460, 506093, 504729, 503369, 502012, 500660, 499310, 497965,
- 496623, 495285, 493950, 492619, 491292, 489968, 488648, 487331, 486018, 484708, 483402,
- 482099, 480800, 479504, 478212, 476924, 475638, 474357, 473078, 471804, 470532, 469264,
- 468000, 466739, 465481, 464227, 462976, 461728, 460484, 459243, 458005, 456771, 455540,
- 454313, 453089, 451868, 450650, 449436, 448225, 447017, 445812, 444611, 443413, 442218,
- 441026, 439838, 438653, 437470, 436292, 435116, 433943, 432774, 431608, 430445, 429285,
- 428128, 426974, 425824, 424676, 423532, 422391, 421252, 420117, 418985, 417856, 416730,
- 415607, 414487, 413370, 412256, 411146, 410038, 408933, 407831, 406732, 405636, 404543,
- 403453, 402365, 401281, 400200, 399121, 398046, 396973, 395903, 394837, 393773, 392712,
- 391653, 390598, 389545, 388496, 387449, 386405, 385363, 384325, 383289, 382257, 381226,
- 380199, 379175, 378153, 377134, 376118, 375104, 374093, 373085, 372080, 371077, 370077,
- 369080, 368085, 367094, 366104, 365118, 364134, 363153, 362174, 361198, 360225, 359254,
- 358286, 357321, 356358, 355397, 354440, 353485, 352532, 351582, 350635, 349690, 348748,
- 347808, 346871, 345936, 345004, 344074, 343147, 342222, 341300, 340380, 339463, 338548,
- 337636, 336726, 335819, 334914, 334011, 333111, 332214, 331318, 330426, 329535, 328647,
- 327762, 326878, 325997, 325119, 324243, 323369, 322498, 321629, 320762, 319898, 319036,
- 318176, 317319, 316463, 315611, 314760, 313912, 313066, 312222, 311381, 310542, 309705,
- 308871, 308038, 307208, 306380, 305555, 304731, 303910, 303091, 302275, 301460, 300648,
- 299838, 299030, 298224, 297420, 296619, 295819, 295022, 294227, 293434, 292644, 291855,
- 291069, 290284, 289502, 288722, 287944, 287168, 286394, 285622, 284853, 284085, 283320,
- 282556, 281795, 281035, 280278, 279523, 278770, 278018, 277269, 276522, 275777, 275034,
- 274293, 273553, 272816, 272081, 271348, 270617, 269888, 269160, 268435, 267712, 266990,
- 266271, 265553, 264838, 264124, 263412, 262702, 261994, 261289, 260584, 259882, 259182,
- 258483, 257787, 257092, 256399, 255709, 255020, 254332, 253647, 252963, 252282, 251602,
- 250924, 250248, 249573, 248901, 248230, 247561, 246894, 246229, 245565, 244904, 244244,
- 243586, 242929, 242275, 241622, 240971, 240321, 239674, 239028, 238384, 237741, 237101,
- 236462, 235825, 235189, 234555, 233923, 233293, 232664, 232037, 231412, 230788, 230166,
- 229546, 228928, 228311, 227696, 227082, 226470, 225860, 225251, 224644, 224039, 223435,
- 222833, 222233, 221634, 221036, 220441, 219847, 219254, 218664, 218074, 217487, 216901,
- 216316, 215733, 215152, 214572, 213994, 213417, 212842, 212269, 211697, 211126, 210557,
- 209990, 209424, 208860, 208297, 207735, 207176, 206617, 206061, 205505, 204952, 204399,
- 203849, 203299, 202751, 202205, 201660, 201117, 200575, 200034, 199495, 198958, 198422,
- 197887, 197354, 196822, 196291, 195762, 195235, 194709, 194184, 193661, 193139, 192619,
- 192100, 191582, 191066, 190551, 190037, 189525, 189014, 188505, 187997, 187491, 186985,
- 186481, 185979, 185478, 184978, 184479, 183982, 183487, 182992, 182499, 182007, 181517,
- 181028, 180540, 180053, 179568, 179084, 178602, 178120, 177640, 177162, 176684, 176208,
- 175733, 175260, 174788, 174317, 173847, 173378, 172911, 172445, 171981, 171517, 171055,
- 170594, 170134, 169676, 169219, 168763, 168308, 167854, 167402, 166951, 166501, 166052,
- 165605, 165159, 164713, 164270, 163827, 163386, 162945, 162506, 162068, 161632, 161196,
- 160762, 160328, 159896, 159465, 159036, 158607, 158180, 157754, 157328, 156904, 156482,
- 156060, 155639, 155220, 154802, 154385, 153969, 153554, 153140, 152727, 152316, 151905,
- 151496, 151088, 150681, 150275, 149870, 149466, 149063, 148661, 148261, 147861, 147463,
- 147065, 146669, 146274, 145880, 145487, 145094, 144703, 144314, 143925, 143537, 143150,
- 142764, 142380, 141996, 141613, 141232, 140851, 140472, 140093, 139715, 139339, 138964,
- 138589, 138216, 137843, 137472, 137101, 136732, 136363, 135996, 135629, 135264, 134899,
- 134536, 134173, 133812, 133451, 133092, 132733, 132375, 132019, 131663, 131308, 130954,
- 130601, 130249, 129898, 129548, 129199, 128851, 128504, 128158, 127812, 127468, 127124,
- 126782, 126440, 126099, 125760, 125421, 125083, 124746, 124410, 124074, 123740, 123407,
- 123074, 122742, 122412, 122082, 121753, 121425, 121097, 120771, 120446, 120121, 119797,
- 119475, 119153, 118832, 118511, 118192, 117873, 117556, 117239, 116923, 116608, 116294,
- 115980, 115668, 115356, 115045, 114735, 114426, 114118, 113810, 113504, 113198, 112893,
- 112589, 112285, 111983, 111681, 111380, 111080, 110780, 110482, 110184, 109887, 109591,
- 109296, 109001, 108708, 108415, 108122, 107831, 107541, 107251, 106962, 106674, 106386,
- 106099, 105813, 105528, 105244, 104960, 104678, 104395, 104114, 103834, 103554, 103275,
- 102996, 102719, 102442, 102166, 101891, 101616, 101342, 101069, 100797, 100525, 100254,
- 99984, 99715, 99446, 99178, 98911, 98644, 98378, 98113, 97849, 97585, 97322,
- 97060, 96799, 96538, 96278, 96018, 95759, 95501, 95244, 94987, 94731, 94476,
- 94222, 93968, 93714, 93462, 93210, 92959, 92708, 92459, 92209, 91961, 91713,
- 91466, 91219, 90974, 90729, 90484, 90240, 89997, 89754, 89513, 89271, 89031,
- 88791, 88552, 88313, 88075, 87838, 87601, 87365, 87130, 86895, 86661, 86427,
- 86194, 85962, 85730, 85499, 85269, 85039, 84810, 84581, 84353, 84126, 83899,
- 83673, 83448, 83223, 82999, 82775, 82552, 82330, 82108, 81886, 81666, 81446,
- 81226, 81007, 80789, 80571, 80354, 80138, 79922, 79706, 79492, 79277, 79064,
- 78851, 78638, 78426, 78215, 78004, 77794, 77584, 77375, 77167, 76959, 76752,
- 76545, 76338, 76133, 75928, 75723, 75519, 75315, 75112, 74910, 74708, 74507,
- 74306, 74106, 73906, 73707, 73508, 73310, 73113, 72916, 72719, 72523, 72328,
- 72133, 71939, 71745, 71551, 71359, 71166, 70975, 70783, 70593, 70402, 70213,
- 70023, 69835, 69646, 69459, 69272, 69085, 68899, 68713, 68528, 68343, 68159,
- 67975, 67792, 67610, 67427, 67246, 67065, 66884, 66704, 66524, 66345, 66166,
- 65987, 65810, 65632, 65455, 65279, 65103, 64928, 64753, 64578, 64404, 64231,
- 64058, 63885, 63713, 63541, 63370, 63199, 63029, 62859, 62690, 62521, 62352,
- 62184, 62017, 61850, 61683, 61517, 61351, 61186, 61021, 60856, 60692, 60529,
- 60366, 60203, 60041, 59879, 59718, 59557, 59396, 59236, 59076, 58917, 58758,
- 58600, 58442, 58285, 58128, 57971, 57815, 57659, 57504, 57349, 57194, 57040,
- 56886, 56733, 56580, 56428, 56276, 56124, 55973, 55822, 55671, 55521, 55372,
- 55223, 55074, 54925, 54777, 54630, 54483, 54336, 54189, 54043, 53898, 53752,
- 53608, 53463, 53319, 53175, 53032, 52889, 52747, 52605, 52463, 52321, 52180,
- 52040, 51900, 51760, 51620, 51481, 51342, 51204, 51066, 50928, 50791, 50654,
- 50518, 50382, 50246, 50111, 49976, 49841, 49707, 49573, 49439, 49306, 49173,
- 49040, 48908, 48776, 48645, 48514, 48383, 48253, 48123, 47993, 47864, 47735,
- 47606, 47478, 47350, 47222, 47095, 46968, 46842, 46715, 46590, 46464, 46339,
- 46214, 46089, 45965, 45841, 45718, 45595, 45472, 45349, 45227, 45105, 44984,
- 44862, 44741, 44621, 44501, 44381, 44261, 44142, 44023, 43904, 43786, 43668,
- 43550, 43433, 43316, 43199, 43083, 42967, 42851, 42735, 42620, 42505, 42391,
- 42277, 42163, 42049, 41936, 41823, 41710, 41598, 41486, 41374, 41262, 41151,
- 41040, 40930, 40819, 40709, 40600, 40490, 40381, 40272, 40164, 40056, 39948,
- 39840, 39733, 39626, 39519, 39412, 39306, 39200, 39094, 38989, 38884, 38779,
- 38675, 38571, 38467, 38363, 38260, 38157, 38054, 37951, 37849, 37747, 37645,
- 37544, 37443, 37342, 37241, 37141, 37041, 36941, 36841, 36742, 36643, 36544,
- 36446, 36347, 36250, 36152, 36054, 35957, 35860, 35764, 35667, 35571, 35475,
- 35380, 35284, 35189, 35095, 35000, 34906, 34812, 34718, 34624, 34531, 34438,
- 34345, 34253, 34160, 34068, 33976, 33885
-};
-
-static const short sindb_coeff[] = {
- 2401, 2144, 1994, 1887, 1804, 1737, 1680, 1630, 1587, 1548, 1512, 1480, 1450,
- 1423, 1397, 1373, 1351, 1330, 1310, 1291, 1273, 1255, 1239, 1223, 1208, 1194,
- 1180, 1166, 1153, 1141, 1128, 1117, 1105, 1094, 1084, 1073, 1063, 1053, 1043,
- 1034, 1025, 1016, 1007, 999, 990, 982, 974, 967, 959, 952, 944, 937,
- 930, 923, 916, 910, 903, 897, 890, 884, 878, 872, 866, 860, 855,
- 849, 843, 838, 832, 827, 822, 817, 812, 807, 802, 797, 792, 787,
- 783, 778, 773, 769, 764, 760, 756, 751, 747, 743, 739, 734, 730,
- 726, 722, 718, 715, 711, 707, 703, 699, 696, 692, 688, 685, 681,
- 678, 674, 671, 667, 664, 661, 657, 654, 651, 648, 644, 641, 638,
- 635, 632, 629, 626, 623, 620, 617, 614, 611, 608, 605, 602, 599,
- 597, 594, 591, 588, 586, 583, 580, 578, 575, 572, 570, 567, 565,
- 562, 560, 557, 555, 552, 550, 547, 545, 542, 540, 538, 535, 533,
- 531, 528, 526, 524, 522, 519, 517, 515, 513, 510, 508, 506, 504,
- 502, 500, 498, 495, 493, 491, 489, 487, 485, 483, 481, 479, 477,
- 475, 473, 471, 469, 467, 465, 464, 462, 460, 458, 456, 454, 452,
- 450, 449, 447, 445, 443, 441, 440, 438, 436, 434, 433, 431, 429,
- 427, 426, 424, 422, 421, 419, 417, 416, 414, 412, 411, 409, 408,
- 406, 404, 403, 401, 400, 398, 396, 395, 393, 392, 390, 389, 387,
- 386, 384, 383, 381, 380, 378, 377, 375, 374, 372, 371, 370, 368,
- 367, 365, 364, 362, 361, 360, 358, 357, 355, 354, 353, 351, 350,
- 349, 347, 346, 345, 343, 342, 341, 339, 338, 337, 336, 334, 333,
- 332, 330, 329, 328, 327, 325, 324, 323, 322, 320, 319, 318, 317,
- 316, 314, 313, 312, 311, 310, 308, 307, 306, 305, 304, 303, 301,
- 300, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287,
- 286, 285, 284, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273,
- 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
- 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247,
- 246, 245, 244, 243, 242, 241, 240, 240, 239, 238, 237, 236, 235,
- 234, 233, 232, 231, 230, 230, 229, 228, 227, 226, 225, 224, 223,
- 222, 222, 221, 220, 219, 218, 217, 216, 216, 215, 214, 213, 212,
- 211, 211, 210, 209, 208, 207, 206, 206, 205, 204, 203, 202, 202,
- 201, 200, 199, 198, 198, 197, 196, 195, 195, 194, 193, 192, 191,
- 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182,
- 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172,
- 172, 171, 170, 170, 169, 168, 167, 167, 166, 165, 165, 164, 163,
- 163, 162, 161, 161, 160, 159, 159, 158, 157, 157, 156, 155, 155,
- 154, 153, 153, 152, 151, 151, 150, 150, 149, 148, 148, 147, 146,
- 146, 145, 145, 144, 143, 143, 142, 141, 141, 140, 140, 139, 138,
- 138, 137, 137, 136, 135, 135, 134, 134, 133, 133, 132, 131, 131,
- 130, 130, 129, 129, 128, 127, 127, 126, 126, 125, 125, 124, 123,
- 123, 122, 122, 121, 121, 120, 120, 119, 119, 118, 117, 117, 116,
- 116, 115, 115, 114, 114, 113, 113, 112, 112, 111, 111, 110, 110,
- 109, 109, 108, 108, 107, 107, 106, 106, 105, 105, 104, 104, 103,
- 103, 102, 102, 101, 101, 100, 100, 99, 99, 98, 98, 97, 97,
- 96, 96, 95, 95, 94, 94, 94, 93, 93, 92, 92, 91, 91,
- 90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85,
- 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79,
- 79, 79, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74,
- 74, 73, 73, 73, 72, 72, 71, 71, 71, 70, 70, 69, 69,
- 69, 68, 68, 68, 67, 67, 66, 66, 66, 65, 65, 65, 64,
- 64, 63, 63, 63, 62, 62, 62, 61, 61, 61, 60, 60, 59,
- 59, 59, 58, 58, 58, 57, 57, 57, 56, 56, 56, 55, 55,
- 55, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51,
- 50, 50, 50, 49, 49, 49, 49, 48, 48, 48, 47, 47, 47,
- 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 43, 43, 43,
- 43, 42, 42, 42, 41, 41, 41, 40, 40, 40, 40, 39, 39,
- 39, 39, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 36,
- 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32,
- 32, 32, 31, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29,
- 29, 29, 28, 28, 28, 28, 27, 27, 27, 27, 27, 26, 26,
- 26, 26, 25, 25, 25, 25, 25, 24, 24, 24, 24, 23, 23,
- 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21,
- 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 18, 18,
- 18, 18, 18, 17, 17, 17, 17, 17, 17, 16, 16, 16, 16,
- 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14,
- 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
- 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,
- 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-static const short lfo_freq_coeff[] = {
- 0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37,
- 40, 43, 46, 50, 53, 56, 59, 62, 65, 68, 71, 74, 78,
- 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118,
- 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157,
- 160, 163, 166, 169, 172, 175, 178, 180, 183, 186, 189, 192, 195,
- 198, 201, 204, 207, 209, 212, 215, 218, 221, 224, 226, 229, 232,
- 235, 238, 240, 243, 246, 249, 251, 254, 257, 260, 262, 265, 268,
- 270, 273, 276, 278, 281, 283, 286, 289, 291, 294, 296, 299, 301,
- 304, 306, 309, 311, 314, 316, 319, 321, 324, 326, 328, 331, 333,
- 336, 338, 340, 343, 345, 347, 350, 352, 354, 356, 359, 361, 363,
- 365, 367, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 391,
- 393, 395, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 415,
- 417, 419, 421, 423, 424, 426, 428, 430, 431, 433, 435, 436, 438,
- 439, 441, 443, 444, 446, 447, 449, 450, 452, 453, 455, 456, 457,
- 459, 460, 461, 463, 464, 465, 467, 468, 469, 470, 472, 473, 474,
- 475, 476, 477, 478, 480, 481, 482, 483, 484, 485, 486, 487, 488,
- 488, 489, 490, 491, 492, 493, 494, 494, 495, 496, 497, 497, 498,
- 499, 499, 500, 501, 501, 502, 502, 503, 504, 504, 504, 505, 505,
- 506, 506, 507, 507, 507, 508, 508, 508, 509, 509, 509, 509, 510,
- 510, 510, 510, 510, 510, 510, 510, 510, 510, 511, 510, 510, 510,
- 510, 510, 510, 510, 510, 510, 510, 509, 509, 509, 509, 508, 508,
- 508, 507, 507, 507, 506, 506, 505, 505, 504, 504, 504, 503, 502,
- 502, 501, 501, 500, 499, 499, 498, 497, 497, 496, 495, 494, 494,
- 493, 492, 491, 490, 489, 488, 488, 487, 486, 485, 484, 483, 482,
- 481, 480, 478, 477, 476, 475, 474, 473, 472, 470, 469, 468, 467,
- 465, 464, 463, 461, 460, 459, 457, 456, 455, 453, 452, 450, 449,
- 447, 446, 444, 443, 441, 439, 438, 436, 435, 433, 431, 430, 428,
- 426, 424, 423, 421, 419, 417, 415, 414, 412, 410, 408, 406, 404,
- 402, 400, 398, 396, 395, 393, 391, 388, 386, 384, 382, 380, 378,
- 376, 374, 372, 370, 367, 365, 363, 361, 359, 356, 354, 352, 350,
- 347, 345, 343, 340, 338, 336, 333, 331, 328, 326, 324, 321, 319,
- 316, 314, 311, 309, 306, 304, 301, 299, 296, 294, 291, 289, 286,
- 283, 281, 278, 276, 273, 270, 268, 265, 262, 260, 257, 254, 251,
- 249, 246, 243, 240, 238, 235, 232, 229, 226, 224, 221, 218, 215,
- 212, 209, 207, 204, 201, 198, 195, 192, 189, 186, 183, 180, 178,
- 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139,
- 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99,
- 96, 93, 90, 87, 84, 81, 78, 74, 71, 68, 65, 62, 59,
- 56, 53, 50, 46, 43, 40, 37, 34, 31, 28, 25, 21, 18,
- 15, 12, 9, 6, 3, 0, -3, -6, -9, -12, -15, -18, -21,
- -25, -28, -31, -34, -37, -40, -43, -46, -50, -53, -56, -59, -62,
- -65, -68, -71, -74, -78, -81, -84, -87, -90, -93, -96, -99, -102,
- -105, -108, -111, -115, -118, -121, -124, -127, -130, -133, -136, -139, -142,
- -145, -148, -151, -154, -157, -160, -163, -166, -169, -172, -175, -178, -180,
- -183, -186, -189, -192, -195, -198, -201, -204, -207, -209, -212, -215, -218,
- -221, -224, -226, -229, -232, -235, -238, -240, -243, -246, -249, -251, -254,
- -257, -260, -262, -265, -268, -270, -273, -276, -278, -281, -283, -286, -289,
- -291, -294, -296, -299, -301, -304, -306, -309, -311, -314, -316, -319, -321,
- -324, -326, -328, -331, -333, -336, -338, -340, -343, -345, -347, -350, -352,
- -354, -356, -359, -361, -363, -365, -367, -370, -372, -374, -376, -378, -380,
- -382, -384, -386, -388, -391, -393, -395, -396, -398, -400, -402, -404, -406,
- -408, -410, -412, -414, -415, -417, -419, -421, -423, -424, -426, -428, -430,
- -431, -433, -435, -436, -438, -439, -441, -443, -444, -446, -447, -449, -450,
- -452, -453, -455, -456, -457, -459, -460, -461, -463, -464, -465, -467, -468,
- -469, -470, -472, -473, -474, -475, -476, -477, -478, -480, -481, -482, -483,
- -484, -485, -486, -487, -488, -488, -489, -490, -491, -492, -493, -494, -494,
- -495, -496, -497, -497, -498, -499, -499, -500, -501, -501, -502, -502, -503,
- -504, -504, -504, -505, -505, -506, -506, -507, -507, -507, -508, -508, -508,
- -509, -509, -509, -509, -510, -510, -510, -510, -510, -510, -510, -510, -510,
- -510, -511, -510, -510, -510, -510, -510, -510, -510, -510, -510, -510, -509,
- -509, -509, -509, -508, -508, -508, -507, -507, -507, -506, -506, -505, -505,
- -504, -504, -504, -503, -502, -502, -501, -501, -500, -499, -499, -498, -497,
- -497, -496, -495, -494, -494, -493, -492, -491, -490, -489, -488, -488, -487,
- -486, -485, -484, -483, -482, -481, -480, -478, -477, -476, -475, -474, -473,
- -472, -470, -469, -468, -467, -465, -464, -463, -461, -460, -459, -457, -456,
- -455, -453, -452, -450, -449, -447, -446, -444, -443, -441, -439, -438, -436,
- -435, -433, -431, -430, -428, -426, -424, -423, -421, -419, -417, -415, -414,
- -412, -410, -408, -406, -404, -402, -400, -398, -396, -395, -393, -391, -388,
- -386, -384, -382, -380, -378, -376, -374, -372, -370, -367, -365, -363, -361,
- -359, -356, -354, -352, -350, -347, -345, -343, -340, -338, -336, -333, -331,
- -328, -326, -324, -321, -319, -316, -314, -311, -309, -306, -304, -301, -299,
- -296, -294, -291, -289, -286, -283, -281, -278, -276, -273, -270, -268, -265,
- -262, -260, -257, -254, -251, -249, -246, -243, -240, -238, -235, -232, -229,
- -226, -224, -221, -218, -215, -212, -209, -207, -204, -201, -198, -195, -192,
- -189, -186, -183, -180, -178, -175, -172, -169, -166, -163, -160, -157, -154,
- -151, -148, -145, -142, -139, -136, -133, -130, -127, -124, -121, -118, -115,
- -111, -108, -105, -102, -99, -96, -93, -90, -87, -84, -81, -78, -74,
- -71, -68, -65, -62, -59, -56, -53, -50, -46, -43, -40, -37, -34,
- -31, -28, -25, -21, -18, -15, -12, -9, -6, -3
-};
-
-static const short lfo_env_coeff[] = {
- 251, 253, 254, 256, 257, 259, 260, 262, 264, 265, 267, 268, 270,
- 271, 273, 274, 276, 277, 279, 281, 282, 284, 285, 287, 288, 290,
- 291, 293, 294, 296, 297, 299, 300, 302, 303, 305, 306, 308, 309,
- 311, 312, 314, 315, 317, 318, 320, 321, 323, 324, 326, 327, 329,
- 330, 332, 333, 335, 336, 337, 339, 340, 342, 343, 345, 346, 348,
- 349, 350, 352, 353, 355, 356, 357, 359, 360, 362, 363, 364, 366,
- 367, 369, 370, 371, 373, 374, 375, 377, 378, 379, 381, 382, 383,
- 385, 386, 387, 389, 390, 391, 392, 394, 395, 396, 397, 399, 400,
- 401, 402, 404, 405, 406, 407, 409, 410, 411, 412, 413, 414, 416,
- 417, 418, 419, 420, 421, 423, 424, 425, 426, 427, 428, 429, 430,
- 431, 432, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
- 445, 446, 447, 448, 449, 450, 451, 452, 453, 453, 454, 455, 456,
- 457, 458, 459, 460, 461, 461, 462, 463, 464, 465, 466, 466, 467,
- 468, 469, 469, 470, 471, 472, 473, 473, 474, 475, 475, 476, 477,
- 477, 478, 479, 479, 480, 481, 481, 482, 483, 483, 484, 484, 485,
- 486, 486, 487, 487, 488, 488, 489, 489, 490, 490, 491, 491, 492,
- 492, 493, 493, 493, 494, 494, 495, 495, 495, 496, 496, 497, 497,
- 497, 498, 498, 498, 498, 499, 499, 499, 500, 500, 500, 500, 500,
- 501, 501, 501, 501, 501, 502, 502, 502, 502, 502, 502, 502, 502,
- 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503,
- 503, 503, 503, 503, 503, 503, 502, 502, 502, 502, 502, 502, 502,
- 502, 501, 501, 501, 501, 501, 500, 500, 500, 500, 500, 499, 499,
- 499, 498, 498, 498, 498, 497, 497, 497, 496, 496, 495, 495, 495,
- 494, 494, 493, 493, 493, 492, 492, 491, 491, 490, 490, 489, 489,
- 488, 488, 487, 487, 486, 486, 485, 484, 484, 483, 483, 482, 481,
- 481, 480, 479, 479, 478, 477, 477, 476, 475, 475, 474, 473, 473,
- 472, 471, 470, 469, 469, 468, 467, 466, 466, 465, 464, 463, 462,
- 461, 461, 460, 459, 458, 457, 456, 455, 454, 453, 453, 452, 451,
- 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438,
- 437, 436, 435, 434, 432, 431, 430, 429, 428, 427, 426, 425, 424,
- 423, 421, 420, 419, 418, 417, 416, 414, 413, 412, 411, 410, 409,
- 407, 406, 405, 404, 402, 401, 400, 399, 397, 396, 395, 394, 392,
- 391, 390, 389, 387, 386, 385, 383, 382, 381, 379, 378, 377, 375,
- 374, 373, 371, 370, 369, 367, 366, 364, 363, 362, 360, 359, 357,
- 356, 355, 353, 352, 350, 349, 348, 346, 345, 343, 342, 340, 339,
- 337, 336, 335, 333, 332, 330, 329, 327, 326, 324, 323, 321, 320,
- 318, 317, 315, 314, 312, 311, 309, 308, 306, 305, 303, 302, 300,
- 299, 297, 296, 294, 293, 291, 290, 288, 287, 285, 284, 282, 281,
- 279, 277, 276, 274, 273, 271, 270, 268, 267, 265, 264, 262, 260,
- 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 240,
- 239, 237, 236, 234, 233, 231, 230, 228, 227, 225, 223, 222, 220,
- 219, 217, 216, 214, 213, 211, 210, 208, 207, 205, 204, 202, 201,
- 199, 198, 196, 195, 193, 192, 190, 189, 187, 186, 184, 183, 181,
- 180, 178, 177, 175, 174, 172, 171, 169, 168, 166, 165, 164, 162,
- 161, 159, 158, 156, 155, 153, 152, 151, 149, 148, 146, 145, 144,
- 142, 141, 139, 138, 137, 135, 134, 133, 131, 130, 129, 127, 126,
- 124, 123, 122, 120, 119, 118, 117, 115, 114, 113, 111, 110, 109,
- 108, 106, 105, 104, 103, 101, 100, 99, 98, 96, 95, 94, 93,
- 92, 90, 89, 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
- 77, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64,
- 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
- 50, 49, 48, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39,
- 39, 38, 37, 36, 35, 35, 34, 33, 32, 31, 31, 30, 29,
- 29, 28, 27, 26, 26, 25, 24, 24, 23, 22, 22, 21, 20,
- 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13,
- 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7,
- 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3,
- 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
- 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
- 19, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26,
- 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 35, 35, 36,
- 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
- 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
- 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88,
- 89, 90, 92, 93, 94, 95, 96, 98, 99, 100, 101, 103, 104,
- 105, 106, 108, 109, 110, 111, 113, 114, 115, 117, 118, 119, 120,
- 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 135, 137, 138,
- 139, 141, 142, 144, 145, 146, 148, 149, 151, 152, 153, 155, 156,
- 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 174, 175,
- 177, 178, 180, 181, 183, 184, 186, 187, 189, 190, 192, 193, 195,
- 196, 198, 199, 201, 202, 204, 205, 207, 208, 210, 211, 213, 214,
- 216, 217, 219, 220, 222, 223, 225, 227, 228, 230, 231, 233, 234,
- 236, 237, 239, 240, 242, 244, 245, 247, 248, 250
-};
-
-#endif
+#ifndef _EMUTABLES_H_
+#define _EMUTABLES_H_
+
+/* Precompiled ym2612 tables for use in Rockbox */
+
+static const int tl_coeff[] = {
+ 268435455, 267712100, 266990695, 266271234, 265553712, 264838123, 264124462, 263412725, 262702906, 261994999, 261289000,
+ 260584903, 259882704, 259182396, 258483976, 257787438, 257092777, 256399988, 255709066, 255020006, 254332802, 253647450,
+ 252963945, 252282282, 251602456, 250924462, 250248294, 249573949, 248901421, 248230705, 247561797, 246894691, 246229383,
+ 245565867, 244904140, 244244195, 243586029, 242929637, 242275013, 241622154, 240971053, 240321708, 239674112, 239028261,
+ 238384150, 237741775, 237101131, 236462214, 235825018, 235189539, 234555773, 233923714, 233293359, 232664702, 232037740,
+ 231412466, 230788878, 230166970, 229546738, 228928178, 228311284, 227696052, 227082479, 226470558, 225860287, 225251660,
+ 224644674, 224039323, 223435603, 222833510, 222233039, 221634187, 221036948, 220441319, 219847295, 219254871, 218664044,
+ 218074809, 217487162, 216901098, 216316614, 215733704, 215152366, 214572594, 213994384, 213417732, 212842635, 212269087,
+ 211697084, 211126623, 210557699, 209990308, 209424446, 208860109, 208297293, 207735993, 207176206, 206617927, 206061153,
+ 205505879, 204952102, 204399816, 203849019, 203299706, 202751873, 202205517, 201660633, 201117217, 200575266, 200034774,
+ 199495740, 198958158, 198422024, 197887335, 197354088, 196822277, 196291899, 195762950, 195235427, 194709325, 194184641,
+ 193661370, 193139510, 192619056, 192100005, 191582352, 191066094, 190551228, 190037748, 189525653, 189014937, 188505598,
+ 187997631, 187491033, 186985800, 186481928, 185979414, 185478255, 184978446, 184479983, 183982864, 183487085, 182992641,
+ 182499530, 182007748, 181517291, 181028155, 180540338, 180053835, 179568643, 179084759, 178602178, 178120898, 177640915,
+ 177162225, 176684825, 176208712, 175733881, 175260330, 174788055, 174317053, 173847320, 173378853, 172911648, 172445702,
+ 171981012, 171517574, 171055385, 170594441, 170134740, 169676277, 169219049, 168763054, 168308287, 167854746, 167402427,
+ 166951327, 166501443, 166052770, 165605307, 165159050, 164713995, 164270139, 163827480, 163386013, 162945736, 162506646,
+ 162068738, 161632011, 161196460, 160762083, 160328877, 159896838, 159465963, 159036250, 158607694, 158180293, 157754044,
+ 157328943, 156904988, 156482176, 156060502, 155639965, 155220562, 154802288, 154385142, 153969119, 153554218, 153140435,
+ 152727766, 152316210, 151905763, 151496422, 151088184, 150681046, 150275005, 149870058, 149466203, 149063435, 148661753,
+ 148261154, 147861634, 147463190, 147065821, 146669522, 146274291, 145880125, 145487021, 145094976, 144703988, 144314054,
+ 143925170, 143537334, 143150543, 142764795, 142380086, 141996414, 141613775, 141232168, 140851589, 140472035, 140093505,
+ 139715994, 139339501, 138964022, 138589555, 138216097, 137843646, 137472198, 137101751, 136732302, 136363849, 135996388,
+ 135629918, 135264436, 134899938, 134536423, 134173887, 133812328, 133451743, 133092130, 132733486, 132375808, 132019095,
+ 131663342, 131308548, 130954711, 130601826, 130249893, 129898908, 129548869, 129199773, 128851618, 128504401, 128158119,
+ 127812771, 127468353, 127124864, 126782300, 126440659, 126099939, 125760137, 125421250, 125083277, 124746214, 124410060,
+ 124074812, 123740467, 123407023, 123074477, 122742828, 122412072, 122082208, 121753232, 121425143, 121097939, 120771615,
+ 120446172, 120121605, 119797912, 119475092, 119153142, 118832060, 118511843, 118192488, 117873994, 117556359, 117239579,
+ 116923653, 116608578, 116294353, 115980974, 115668439, 115356747, 115045894, 114735880, 114426700, 114118354, 113810839,
+ 113504152, 113198292, 112893256, 112589042, 112285648, 111983071, 111681310, 111380362, 111080225, 110780896, 110482375,
+ 110184657, 109887742, 109591627, 109296310, 109001789, 108708061, 108415125, 108122978, 107831619, 107541044, 107251253,
+ 106962243, 106674011, 106386556, 106099876, 105813968, 105528830, 105244461, 104960859, 104678020, 104395944, 104114628,
+ 103834069, 103554267, 103275219, 102996923, 102719377, 102442578, 102166526, 101891217, 101616650, 101342823, 101069734,
+ 100797381, 100525762, 100254875, 99984718, 99715288, 99446585, 99178606, 98911349, 98644812, 98378993, 98113891,
+ 97849503, 97585828, 97322863, 97060606, 96799057, 96538212, 96278070, 96018629, 95759887, 95501842, 95244493,
+ 94987837, 94731873, 94476599, 94222012, 93968112, 93714895, 93462361, 93210508, 92959333, 92708835, 92459012,
+ 92209863, 91961384, 91713575, 91466434, 91219959, 90974149, 90729000, 90484512, 90240683, 89997511, 89754994,
+ 89513131, 89271920, 89031358, 88791445, 88552178, 88313556, 88075578, 87838240, 87601542, 87365481, 87130057,
+ 86895267, 86661110, 86427584, 86194687, 85962418, 85730775, 85499756, 85269359, 85039583, 84810427, 84581888,
+ 84353965, 84126656, 83899959, 83673874, 83448397, 83223528, 82999266, 82775607, 82552551, 82330096, 82108241,
+ 81886984, 81666322, 81446256, 81226782, 81007900, 80789608, 80571904, 80354786, 80138254, 79922305, 79706938,
+ 79492151, 79277943, 79064313, 78851258, 78638777, 78426868, 78215531, 78004763, 77794564, 77584930, 77375862,
+ 77167357, 76959413, 76752031, 76545207, 76338940, 76133229, 75928072, 75723469, 75519416, 75315914, 75112960,
+ 74910552, 74708690, 74507373, 74306597, 74106363, 73906668, 73707512, 73508892, 73310807, 73113256, 72916237,
+ 72719749, 72523791, 72328361, 72133457, 71939079, 71745225, 71551892, 71359081, 71166789, 70975016, 70783759,
+ 70593018, 70402791, 70213076, 70023872, 69835179, 69646994, 69459315, 69272143, 69085475, 68899310, 68713647,
+ 68528484, 68343820, 68159653, 67975983, 67792808, 67610127, 67427937, 67246239, 67065030, 66884310, 66704076,
+ 66524328, 66345065, 66166285, 65987986, 65810168, 65632829, 65455968, 65279583, 65103674, 64928239, 64753277,
+ 64578786, 64404765, 64231213, 64058129, 63885511, 63713359, 63541670, 63370444, 63199679, 63029375, 62859529,
+ 62690141, 62521210, 62352734, 62184711, 62017142, 61850024, 61683357, 61517138, 61351368, 61186044, 61021166,
+ 60856731, 60692741, 60529192, 60366083, 60203414, 60041184, 59879391, 59718034, 59557111, 59396622, 59236566,
+ 59076941, 58917746, 58758980, 58600642, 58442730, 58285245, 58128183, 57971545, 57815329, 57659533, 57504158,
+ 57349201, 57194662, 57040539, 56886832, 56733539, 56580659, 56428190, 56276133, 56124486, 55973247, 55822415,
+ 55671990, 55521971, 55372355, 55223143, 55074333, 54925924, 54777915, 54630305, 54483092, 54336276, 54189856,
+ 54043830, 53898198, 53752959, 53608110, 53463652, 53319583, 53175903, 53032610, 52889702, 52747180, 52605042,
+ 52463287, 52321914, 52180922, 52040310, 51900076, 51760221, 51620743, 51481640, 51342912, 51204558, 51066577,
+ 50928968, 50791729, 50654860, 50518360, 50382228, 50246463, 50111064, 49976029, 49841359, 49707051, 49573105,
+ 49439520, 49306295, 49173429, 49040922, 48908771, 48776976, 48645537, 48514451, 48383719, 48253339, 48123311,
+ 47993633, 47864304, 47735324, 47606691, 47478405, 47350465, 47222869, 47095618, 46968709, 46842142, 46715916,
+ 46590031, 46464484, 46339276, 46214406, 46089871, 45965673, 45841809, 45718279, 45595082, 45472216, 45349682,
+ 45227478, 45105603, 44984057, 44862838, 44741946, 44621380, 44501139, 44381221, 44261627, 44142355, 44023404,
+ 43904774, 43786464, 43668472, 43550798, 43433442, 43316402, 43199677, 43083266, 42967170, 42851386, 42735914,
+ 42620753, 42505903, 42391362, 42277130, 42163206, 42049588, 41936277, 41823271, 41710570, 41598172, 41486077,
+ 41374285, 41262793, 41151602, 41040711, 40930118, 40819823, 40709826, 40600125, 40490720, 40381609, 40272793,
+ 40164269, 40056039, 39948099, 39840451, 39733093, 39626024, 39519243, 39412751, 39306545, 39200625, 39094991,
+ 38989642, 38884576, 38779794, 38675294, 38571075, 38467138, 38363480, 38260102, 38157002, 38054180, 37951635,
+ 37849367, 37747374, 37645656, 37544212, 37443042, 37342144, 37241518, 37141163, 37041078, 36941264, 36841718,
+ 36742440, 36643430, 36544687, 36446210, 36347998, 36250051, 36152368, 36054948, 35957790, 35860895, 35764260,
+ 35667886, 35571772, 35475916, 35380319, 35284980, 35189897, 35095071, 35000500, 34906184, 34812122, 34718314,
+ 34624758, 34531454, 34438402, 34345601, 34253050, 34160748, 34068695, 33976890, 33885332, 33794021, 33702956,
+ 33612137, 33521562, 33431231, 33341144, 33251299, 33161697, 33072336, 32983216, 32894336, 32805695, 32717294,
+ 32629130, 32541204, 32453515, 32366063, 32278846, 32191864, 32105116, 32018602, 31932322, 31846273, 31760457,
+ 31674872, 31589518, 31504393, 31419498, 31334832, 31250394, 31166183, 31082200, 30998442, 30914911, 30831604,
+ 30748522, 30665664, 30583029, 30500617, 30418426, 30336458, 30254710, 30173183, 30091875, 30010786, 29929916,
+ 29849263, 29768829, 29688610, 29608608, 29528822, 29449250, 29369893, 29290750, 29211820, 29133103, 29054598,
+ 28976304, 28898222, 28820350, 28742687, 28665234, 28587990, 28510954, 28434125, 28357503, 28281088, 28204879,
+ 28128875, 28053076, 27977482, 27902091, 27826903, 27751917, 27677134, 27602552, 27528172, 27453991, 27380011,
+ 27306230, 27232648, 27159264, 27086078, 27013089, 26940296, 26867700, 26795300, 26723094, 26651083, 26579267,
+ 26507643, 26436213, 26364975, 26293929, 26223075, 26152412, 26081939, 26011656, 25941562, 25871657, 25801940,
+ 25732412, 25663071, 25593916, 25524948, 25456166, 25387569, 25319157, 25250929, 25182886, 25115025, 25047348,
+ 24979852, 24912539, 24845407, 24778456, 24711686, 24645095, 24578684, 24512451, 24446397, 24380522, 24314823,
+ 24249302, 24183957, 24118789, 24053796, 23988978, 23924335, 23859866, 23795570, 23731448, 23667499, 23603722,
+ 23540117, 23476683, 23413421, 23350328, 23287406, 23224653, 23162070, 23099655, 23037408, 22975329, 22913417,
+ 22851673, 22790094, 22728681, 22667434, 22606352, 22545435, 22484682, 22424092, 22363666, 22303402, 22243301,
+ 22183362, 22123584, 22063968, 22004512, 21945216, 21886080, 21827104, 21768286, 21709627, 21651126, 21592783,
+ 21534597, 21476567, 21418694, 21360977, 21303416, 21246009, 21188758, 21131660, 21074717, 21017926, 20961289,
+ 20904805, 20848473, 20792292, 20736263, 20680385, 20624657, 20569080, 20513652, 20458374, 20403245, 20348264,
+ 20293432, 20238747, 20184209, 20129819, 20075575, 20021477, 19967525, 19913719, 19860057, 19806540, 19753167,
+ 19699938, 19646853, 19593910, 19541111, 19488453, 19435937, 19383563, 19331330, 19279238, 19227286, 19175474,
+ 19123802, 19072269, 19020875, 18969619, 18918502, 18867522, 18816680, 18765974, 18715405, 18664973, 18614676,
+ 18564515, 18514489, 18464598, 18414842, 18365219, 18315730, 18266375, 18217152, 18168062, 18119105, 18070279,
+ 18021585, 17973022, 17924590, 17876289, 17828118, 17780076, 17732164, 17684381, 17636727, 17589201, 17541803,
+ 17494533, 17447391, 17400375, 17353486, 17306724, 17260087, 17213577, 17167191, 17120930, 17074795, 17028783,
+ 16982896, 16937132, 16891491, 16845974, 16800579, 16755306, 16710155, 16665126, 16620219, 16575432, 16530766,
+ 16486221, 16441795, 16397490, 16353303, 16309236, 16265287, 16221457, 16177745, 16134151, 16090674, 16047314,
+ 16004072, 15960945, 15917935, 15875041, 15832263, 15789599, 15747051, 15704617, 15662298, 15620093, 15578001,
+ 15536023, 15494158, 15452406, 15410766, 15369239, 15327823, 15286519, 15245327, 15204245, 15163274, 15122414,
+ 15081663, 15041023, 15000491, 14960070, 14919757, 14879552, 14839456, 14799468, 14759588, 14719815, 14680150,
+ 14640591, 14601139, 14561793, 14522554, 14483420, 14444391, 14405468, 14366649, 14327935, 14289326, 14250820,
+ 14212418, 14174120, 14135925, 14097833, 14059843, 14021956, 13984171, 13946488, 13908906, 13871426, 13834047,
+ 13796768, 13759590, 13722512, 13685534, 13648655, 13611876, 13575196, 13538615, 13502132, 13465748, 13429462,
+ 13393273, 13357183, 13321189, 13285292, 13249492, 13213789, 13178182, 13142670, 13107255, 13071934, 13036709,
+ 13001579, 12966544, 12931603, 12896756, 12862003, 12827344, 12792778, 12758305, 12723925, 12689638, 12655443,
+ 12621341, 12587330, 12553411, 12519583, 12485846, 12452201, 12418646, 12385181, 12351807, 12318522, 12285327,
+ 12252222, 12219206, 12186279, 12153440, 12120690, 12088029, 12055455, 12022969, 11990571, 11958260, 11926036,
+ 11893899, 11861848, 11829884, 11798006, 11766214, 11734507, 11702886, 11671350, 11639900, 11608533, 11577252,
+ 11546055, 11514941, 11483912, 11452966, 11422104, 11391325, 11360628, 11330015, 11299484, 11269035, 11238668,
+ 11208384, 11178180, 11148058, 11118018, 11088058, 11058179, 11028380, 10998662, 10969024, 10939466, 10909987,
+ 10880588, 10851268, 10822027, 10792865, 10763781, 10734776, 10705849, 10677000, 10648228, 10619535, 10590918,
+ 10562379, 10533916, 10505530, 10477221, 10448988, 10420831, 10392750, 10364745, 10336815, 10308960, 10281180,
+ 10253476, 10225846, 10198290, 10170809, 10143401, 10116068, 10088808, 10061622, 10034509, 10007468, 9980501,
+ 9953607, 9926785, 9900035, 9873357, 9846752, 9820217, 9793755, 9767364, 9741043, 9714794, 9688616,
+ 9662508, 9636470, 9610503, 9584605, 9558778, 9533019, 9507331, 9481711, 9456161, 9430679, 9405266,
+ 9379922, 9354646, 9329438, 9304298, 9279225, 9254221, 9229283, 9204413, 9179610, 9154874, 9130204,
+ 9105601, 9081064, 9056593, 9032188, 9007849, 8983576, 8959368, 8935225, 8911147, 8887134, 8863186,
+ 8839302, 8815483, 8791728, 8768037, 8744409, 8720846, 8697346, 8673909, 8650535, 8627225, 8603977,
+ 8580792, 8557669, 8534608, 8511610, 8488674, 8465799, 8442987, 8420235, 8397545, 8374916, 8352348,
+ 8329841, 8307395, 8285009, 8262683, 8240418, 8218212, 8196067, 8173981, 8151954, 8129987, 8108079,
+ 8086230, 8064440, 8042709, 8021036, 7999422, 7977866, 7956368, 7934928, 7913545, 7892221, 7870954,
+ 7849744, 7828591, 7807495, 7786456, 7765474, 7744548, 7723679, 7702866, 7682109, 7661408, 7640763,
+ 7620173, 7599639, 7579160, 7558737, 7538368, 7518055, 7497796, 7477591, 7457441, 7437346, 7417304,
+ 7397317, 7377383, 7357503, 7337677, 7317904, 7298185, 7278518, 7258905, 7239344, 7219836, 7200381,
+ 7180978, 7161627, 7142329, 7123082, 7103888, 7084745, 7065654, 7046614, 7027625, 7008688, 6989802,
+ 6970966, 6952181, 6933447, 6914764, 6896130, 6877547, 6859014, 6840531, 6822098, 6803715, 6785381,
+ 6767096, 6748861, 6730675, 6712537, 6694449, 6676410, 6658419, 6640476, 6622582, 6604736, 6586938,
+ 6569188, 6551486, 6533832, 6516225, 6498666, 6481154, 6463689, 6446272, 6428901, 6411577, 6394299,
+ 6377069, 6359884, 6342746, 6325655, 6308609, 6291609, 6274655, 6257747, 6240884, 6224066, 6207294,
+ 6190568, 6173886, 6157249, 6140657, 6124110, 6107607, 6091149, 6074735, 6058365, 6042040, 6025758,
+ 6009521, 5993327, 5977177, 5961070, 5945007, 5928987, 5913010, 5897076, 5881185, 5865337, 5849532,
+ 5833769, 5818049, 5802371, 5786735, 5771141, 5755590, 5740080, 5724612, 5709186, 5693802, 5678459,
+ 5663157, 5647896, 5632677, 5617498, 5602361, 5587264, 5572208, 5557193, 5542218, 5527283, 5512389,
+ 5497534, 5482720, 5467946, 5453211, 5438517, 5423861, 5409246, 5394669, 5380132, 5365635, 5351176,
+ 5336756, 5322375, 5308033, 5293729, 5279464, 5265237, 5251049, 5236899, 5222787, 5208713, 5194677,
+ 5180679, 5166719, 5152796, 5138911, 5125063, 5111252, 5097479, 5083743, 5070044, 5056382, 5042756,
+ 5029167, 5015615, 5002100, 4988620, 4975178, 4961771, 4948400, 4935066, 4921767, 4908505, 4895278,
+ 4882086, 4868931, 4855810, 4842725, 4829676, 4816661, 4803682, 4790737, 4777827, 4764953, 4752112,
+ 4739307, 4726536, 4713799, 4701097, 4688429, 4675795, 4663195, 4650629, 4638097, 4625599, 4613134,
+ 4600703, 4588306, 4575941, 4563611, 4551313, 4539049, 4526817, 4514619, 4502453, 4490320, 4478220,
+ 4466153, 4454118, 4442115, 4430145, 4418207, 4406301, 4394428, 4382586, 4370776, 4358998, 4347252,
+ 4335538, 4323855, 4312203, 4300583, 4288994, 4277437, 4265910, 4254415, 4242950, 4231517, 4220114,
+ 4208742, 4197401, 4186090, 4174810, 4163560, 4152340, 4141151, 4129992, 4118863, 4107764, 4096694,
+ 4085655, 4074645, 4063665, 4052715, 4041794, 4030903, 4020041, 4009208, 3998404, 3987630, 3976884,
+ 3966168, 3955480, 3944821, 3934191, 3923590, 3913017, 3902472, 3891956, 3881469, 3871009, 3860578,
+ 3850175, 3839800, 3829453, 3819133, 3808842, 3798578, 3788342, 3778134, 3767953, 3757799, 3747673,
+ 3737574, 3727503, 3717458, 3707441, 3697450, 3687487, 3677550, 3667640, 3657757, 3647900, 3638070,
+ 3628267, 3618490, 3608739, 3599014, 3589316, 3579644, 3569998, 3560378, 3550783, 3541215, 3531673,
+ 3522156, 3512665, 3503199, 3493759, 3484344, 3474955, 3465591, 3456252, 3446939, 3437650, 3428387,
+ 3419148, 3409935, 3400746, 3391582, 3382443, 3373328, 3364238, 3355172, 3346131, 3337114, 3328122,
+ 3319153, 3310209, 3301289, 3292393, 3283521, 3274673, 3265849, 3257048, 3248271, 3239518, 3230789,
+ 3222083, 3213400, 3204741, 3196105, 3187493, 3178903, 3170337, 3161794, 3153274, 3144777, 3136302,
+ 3127851, 3119422, 3111016, 3102633, 3094272, 3085934, 3077619, 3069325, 3061054, 3052806, 3044579,
+ 3036375, 3028193, 3020033, 3011895, 3003779, 2995684, 2987612, 2979561, 2971532, 2963525, 2955539,
+ 2947575, 2939632, 2931710, 2923810, 2915931, 2908074, 2900237, 2892422, 2884628, 2876855, 2869102,
+ 2861371, 2853660, 2845971, 2838302, 2830653, 2823025, 2815418, 2807832, 2800265, 2792719, 2785194,
+ 2777689, 2770203, 2762739, 2755294, 2747869, 2740464, 2733080, 2725715, 2718370, 2711045, 2703739,
+ 2696453, 2689187, 2681941, 2674714, 2667506, 2660318, 2653149, 2646000, 2638870, 2631759, 2624667,
+ 2617594, 2610540, 2603506, 2596490, 2589493, 2582515, 2575556, 2568616, 2561694, 2554791, 2547907,
+ 2541041, 2534194, 2527365, 2520554, 2513762, 2506988, 2500233, 2493495, 2486776, 2480075, 2473392,
+ 2466727, 2460080, 2453450, 2446839, 2440246, 2433670, 2427112, 2420571, 2414049, 2407544, 2401056,
+ 2394586, 2388133, 2381698, 2375280, 2368879, 2362496, 2356130, 2349780, 2343448, 2337134, 2330836,
+ 2324555, 2318291, 2312044, 2305813, 2299600, 2293403, 2287223, 2281060, 2274913, 2268783, 2262669,
+ 2256572, 2250491, 2244427, 2238379, 2232347, 2226331, 2220332, 2214349, 2208382, 2202431, 2196496,
+ 2190577, 2184674, 2178787, 2172916, 2167060, 2161221, 2155397, 2149589, 2143796, 2138019, 2132258,
+ 2126512, 2120782, 2115067, 2109368, 2103683, 2098015, 2092361, 2086723, 2081100, 2075492, 2069899,
+ 2064321, 2058758, 2053211, 2047678, 2042160, 2036657, 2031169, 2025695, 2020237, 2014793, 2009364,
+ 2003949, 1998549, 1993163, 1987792, 1982436, 1977094, 1971766, 1966453, 1961154, 1955869, 1950599,
+ 1945342, 1940100, 1934872, 1929658, 1924458, 1919272, 1914101, 1908943, 1903799, 1898668, 1893552,
+ 1888450, 1883361, 1878286, 1873224, 1868176, 1863142, 1858122, 1853115, 1848121, 1843141, 1838174,
+ 1833221, 1828281, 1823354, 1818441, 1813540, 1808654, 1803780, 1798919, 1794072, 1789237, 1784416,
+ 1779607, 1774812, 1770029, 1765259, 1760502, 1755758, 1751027, 1746309, 1741603, 1736910, 1732229,
+ 1727561, 1722906, 1718263, 1713633, 1709015, 1704410, 1699817, 1695237, 1690669, 1686113, 1681569,
+ 1677038, 1672519, 1668012, 1663517, 1659034, 1654564, 1650105, 1645659, 1641224, 1636801, 1632391,
+ 1627992, 1623605, 1619230, 1614866, 1610515, 1606175, 1601847, 1597530, 1593225, 1588932, 1584650,
+ 1580380, 1576122, 1571874, 1567639, 1563414, 1559201, 1555000, 1550810, 1546631, 1542463, 1538306,
+ 1534161, 1530027, 1525904, 1521792, 1517691, 1513602, 1509523, 1505455, 1501399, 1497353, 1493318,
+ 1489294, 1485281, 1481278, 1477287, 1473306, 1469336, 1465376, 1461427, 1457489, 1453562, 1449645,
+ 1445738, 1441843, 1437957, 1434082, 1430218, 1426364, 1422520, 1418687, 1414864, 1411051, 1407249,
+ 1403457, 1399675, 1395903, 1392142, 1388390, 1384649, 1380918, 1377197, 1373486, 1369784, 1366093,
+ 1362412, 1358741, 1355079, 1351428, 1347786, 1344154, 1340532, 1336920, 1333317, 1329724, 1326141,
+ 1322567, 1319004, 1315449, 1311904, 1308369, 1304844, 1301327, 1297821, 1294323, 1290836, 1287357,
+ 1283888, 1280429, 1276978, 1273537, 1270105, 1266683, 1263269, 1259865, 1256470, 1253084, 1249708,
+ 1246340, 1242982, 1239632, 1236292, 1232960, 1229638, 1226324, 1223020, 1219724, 1216437, 1213159,
+ 1209890, 1206630, 1203378, 1200136, 1196902, 1193676, 1190460, 1187252, 1184052, 1180862, 1177680,
+ 1174506, 1171341, 1168185, 1165037, 1161897, 1158767, 1155644, 1152530, 1149424, 1146327, 1143238,
+ 1140157, 1137085, 1134021, 1130965, 1127917, 1124878, 1121846, 1118823, 1115809, 1112802, 1109803,
+ 1106813, 1103830, 1100855, 1097889, 1094931, 1091980, 1089037, 1086103, 1083176, 1080257, 1077346,
+ 1074443, 1071548, 1068660, 1065781, 1062909, 1060044, 1057188, 1054339, 1051498, 1048664, 1045839,
+ 1043020, 1040210, 1037407, 1034611, 1031823, 1029043, 1026270, 1023504, 1020746, 1017996, 1015252,
+ 1012517, 1009788, 1007067, 1004353, 1001647, 998948, 996256, 993571, 990894, 988224, 985561,
+ 982905, 980256, 977615, 974980, 972353, 969733, 967120, 964514, 961915, 959323, 956737,
+ 954159, 951588, 949024, 946467, 943916, 941373, 938836, 936306, 933783, 931267, 928757,
+ 926254, 923758, 921269, 918787, 916311, 913842, 911379, 908923, 906474, 904031, 901595,
+ 899166, 896743, 894326, 891916, 889513, 887116, 884725, 882341, 879963, 877592, 875227,
+ 872869, 870517, 868171, 865831, 863498, 861171, 858851, 856536, 854228, 851926, 849631,
+ 847341, 845058, 842781, 840510, 838245, 835986, 833733, 831487, 829246, 827011, 824783,
+ 822560, 820344, 818133, 815929, 813730, 811537, 809350, 807169, 804994, 802825, 800662,
+ 798504, 796352, 794206, 792066, 789932, 787803, 785680, 783563, 781452, 779346, 777246,
+ 775151, 773062, 770979, 768902, 766830, 764763, 762703, 760647, 758598, 756553, 754515,
+ 752482, 750454, 748432, 746415, 744403, 742397, 740397, 738402, 736412, 734428, 732448,
+ 730475, 728506, 726543, 724585, 722633, 720686, 718744, 716807, 714875, 712949, 711028,
+ 709112, 707201, 705295, 703394, 701499, 699609, 697723, 695843, 693968, 692098, 690233,
+ 688373, 686518, 684668, 682823, 680983, 679148, 677318, 675493, 673673, 671857, 670047,
+ 668241, 666441, 664645, 662854, 661067, 659286, 657510, 655738, 653971, 652208, 650451,
+ 648698, 646950, 645207, 643468, 641734, 640005, 638280, 636560, 634845, 633134, 631428,
+ 629727, 628030, 626337, 624650, 622966, 621288, 619613, 617944, 616279, 614618, 612962,
+ 611310, 609663, 608020, 606381, 604747, 603118, 601492, 599872, 598255, 596643, 595035,
+ 593432, 591833, 590238, 588647, 587061, 585479, 583901, 582328, 580759, 579194, 577633,
+ 576076, 574524, 572976, 571432, 569892, 568356, 566825, 565297, 563774, 562255, 560740,
+ 559229, 557722, 556219, 554720, 553225, 551734, 550248, 548765, 547286, 545811, 544341,
+ 542874, 541411, 539952, 538497, 537046, 535599, 534155, 532716, 531280, 529849, 528421,
+ 526997, 525577, 524161, 522748, 521340, 519935, 518534, 517136, 515743, 514353, 512967,
+ 511585, 510206, 508831, 507460, 506093, 504729, 503369, 502012, 500660, 499310, 497965,
+ 496623, 495285, 493950, 492619, 491292, 489968, 488648, 487331, 486018, 484708, 483402,
+ 482099, 480800, 479504, 478212, 476924, 475638, 474357, 473078, 471804, 470532, 469264,
+ 468000, 466739, 465481, 464227, 462976, 461728, 460484, 459243, 458005, 456771, 455540,
+ 454313, 453089, 451868, 450650, 449436, 448225, 447017, 445812, 444611, 443413, 442218,
+ 441026, 439838, 438653, 437470, 436292, 435116, 433943, 432774, 431608, 430445, 429285,
+ 428128, 426974, 425824, 424676, 423532, 422391, 421252, 420117, 418985, 417856, 416730,
+ 415607, 414487, 413370, 412256, 411146, 410038, 408933, 407831, 406732, 405636, 404543,
+ 403453, 402365, 401281, 400200, 399121, 398046, 396973, 395903, 394837, 393773, 392712,
+ 391653, 390598, 389545, 388496, 387449, 386405, 385363, 384325, 383289, 382257, 381226,
+ 380199, 379175, 378153, 377134, 376118, 375104, 374093, 373085, 372080, 371077, 370077,
+ 369080, 368085, 367094, 366104, 365118, 364134, 363153, 362174, 361198, 360225, 359254,
+ 358286, 357321, 356358, 355397, 354440, 353485, 352532, 351582, 350635, 349690, 348748,
+ 347808, 346871, 345936, 345004, 344074, 343147, 342222, 341300, 340380, 339463, 338548,
+ 337636, 336726, 335819, 334914, 334011, 333111, 332214, 331318, 330426, 329535, 328647,
+ 327762, 326878, 325997, 325119, 324243, 323369, 322498, 321629, 320762, 319898, 319036,
+ 318176, 317319, 316463, 315611, 314760, 313912, 313066, 312222, 311381, 310542, 309705,
+ 308871, 308038, 307208, 306380, 305555, 304731, 303910, 303091, 302275, 301460, 300648,
+ 299838, 299030, 298224, 297420, 296619, 295819, 295022, 294227, 293434, 292644, 291855,
+ 291069, 290284, 289502, 288722, 287944, 287168, 286394, 285622, 284853, 284085, 283320,
+ 282556, 281795, 281035, 280278, 279523, 278770, 278018, 277269, 276522, 275777, 275034,
+ 274293, 273553, 272816, 272081, 271348, 270617, 269888, 269160, 268435, 267712, 266990,
+ 266271, 265553, 264838, 264124, 263412, 262702, 261994, 261289, 260584, 259882, 259182,
+ 258483, 257787, 257092, 256399, 255709, 255020, 254332, 253647, 252963, 252282, 251602,
+ 250924, 250248, 249573, 248901, 248230, 247561, 246894, 246229, 245565, 244904, 244244,
+ 243586, 242929, 242275, 241622, 240971, 240321, 239674, 239028, 238384, 237741, 237101,
+ 236462, 235825, 235189, 234555, 233923, 233293, 232664, 232037, 231412, 230788, 230166,
+ 229546, 228928, 228311, 227696, 227082, 226470, 225860, 225251, 224644, 224039, 223435,
+ 222833, 222233, 221634, 221036, 220441, 219847, 219254, 218664, 218074, 217487, 216901,
+ 216316, 215733, 215152, 214572, 213994, 213417, 212842, 212269, 211697, 211126, 210557,
+ 209990, 209424, 208860, 208297, 207735, 207176, 206617, 206061, 205505, 204952, 204399,
+ 203849, 203299, 202751, 202205, 201660, 201117, 200575, 200034, 199495, 198958, 198422,
+ 197887, 197354, 196822, 196291, 195762, 195235, 194709, 194184, 193661, 193139, 192619,
+ 192100, 191582, 191066, 190551, 190037, 189525, 189014, 188505, 187997, 187491, 186985,
+ 186481, 185979, 185478, 184978, 184479, 183982, 183487, 182992, 182499, 182007, 181517,
+ 181028, 180540, 180053, 179568, 179084, 178602, 178120, 177640, 177162, 176684, 176208,
+ 175733, 175260, 174788, 174317, 173847, 173378, 172911, 172445, 171981, 171517, 171055,
+ 170594, 170134, 169676, 169219, 168763, 168308, 167854, 167402, 166951, 166501, 166052,
+ 165605, 165159, 164713, 164270, 163827, 163386, 162945, 162506, 162068, 161632, 161196,
+ 160762, 160328, 159896, 159465, 159036, 158607, 158180, 157754, 157328, 156904, 156482,
+ 156060, 155639, 155220, 154802, 154385, 153969, 153554, 153140, 152727, 152316, 151905,
+ 151496, 151088, 150681, 150275, 149870, 149466, 149063, 148661, 148261, 147861, 147463,
+ 147065, 146669, 146274, 145880, 145487, 145094, 144703, 144314, 143925, 143537, 143150,
+ 142764, 142380, 141996, 141613, 141232, 140851, 140472, 140093, 139715, 139339, 138964,
+ 138589, 138216, 137843, 137472, 137101, 136732, 136363, 135996, 135629, 135264, 134899,
+ 134536, 134173, 133812, 133451, 133092, 132733, 132375, 132019, 131663, 131308, 130954,
+ 130601, 130249, 129898, 129548, 129199, 128851, 128504, 128158, 127812, 127468, 127124,
+ 126782, 126440, 126099, 125760, 125421, 125083, 124746, 124410, 124074, 123740, 123407,
+ 123074, 122742, 122412, 122082, 121753, 121425, 121097, 120771, 120446, 120121, 119797,
+ 119475, 119153, 118832, 118511, 118192, 117873, 117556, 117239, 116923, 116608, 116294,
+ 115980, 115668, 115356, 115045, 114735, 114426, 114118, 113810, 113504, 113198, 112893,
+ 112589, 112285, 111983, 111681, 111380, 111080, 110780, 110482, 110184, 109887, 109591,
+ 109296, 109001, 108708, 108415, 108122, 107831, 107541, 107251, 106962, 106674, 106386,
+ 106099, 105813, 105528, 105244, 104960, 104678, 104395, 104114, 103834, 103554, 103275,
+ 102996, 102719, 102442, 102166, 101891, 101616, 101342, 101069, 100797, 100525, 100254,
+ 99984, 99715, 99446, 99178, 98911, 98644, 98378, 98113, 97849, 97585, 97322,
+ 97060, 96799, 96538, 96278, 96018, 95759, 95501, 95244, 94987, 94731, 94476,
+ 94222, 93968, 93714, 93462, 93210, 92959, 92708, 92459, 92209, 91961, 91713,
+ 91466, 91219, 90974, 90729, 90484, 90240, 89997, 89754, 89513, 89271, 89031,
+ 88791, 88552, 88313, 88075, 87838, 87601, 87365, 87130, 86895, 86661, 86427,
+ 86194, 85962, 85730, 85499, 85269, 85039, 84810, 84581, 84353, 84126, 83899,
+ 83673, 83448, 83223, 82999, 82775, 82552, 82330, 82108, 81886, 81666, 81446,
+ 81226, 81007, 80789, 80571, 80354, 80138, 79922, 79706, 79492, 79277, 79064,
+ 78851, 78638, 78426, 78215, 78004, 77794, 77584, 77375, 77167, 76959, 76752,
+ 76545, 76338, 76133, 75928, 75723, 75519, 75315, 75112, 74910, 74708, 74507,
+ 74306, 74106, 73906, 73707, 73508, 73310, 73113, 72916, 72719, 72523, 72328,
+ 72133, 71939, 71745, 71551, 71359, 71166, 70975, 70783, 70593, 70402, 70213,
+ 70023, 69835, 69646, 69459, 69272, 69085, 68899, 68713, 68528, 68343, 68159,
+ 67975, 67792, 67610, 67427, 67246, 67065, 66884, 66704, 66524, 66345, 66166,
+ 65987, 65810, 65632, 65455, 65279, 65103, 64928, 64753, 64578, 64404, 64231,
+ 64058, 63885, 63713, 63541, 63370, 63199, 63029, 62859, 62690, 62521, 62352,
+ 62184, 62017, 61850, 61683, 61517, 61351, 61186, 61021, 60856, 60692, 60529,
+ 60366, 60203, 60041, 59879, 59718, 59557, 59396, 59236, 59076, 58917, 58758,
+ 58600, 58442, 58285, 58128, 57971, 57815, 57659, 57504, 57349, 57194, 57040,
+ 56886, 56733, 56580, 56428, 56276, 56124, 55973, 55822, 55671, 55521, 55372,
+ 55223, 55074, 54925, 54777, 54630, 54483, 54336, 54189, 54043, 53898, 53752,
+ 53608, 53463, 53319, 53175, 53032, 52889, 52747, 52605, 52463, 52321, 52180,
+ 52040, 51900, 51760, 51620, 51481, 51342, 51204, 51066, 50928, 50791, 50654,
+ 50518, 50382, 50246, 50111, 49976, 49841, 49707, 49573, 49439, 49306, 49173,
+ 49040, 48908, 48776, 48645, 48514, 48383, 48253, 48123, 47993, 47864, 47735,
+ 47606, 47478, 47350, 47222, 47095, 46968, 46842, 46715, 46590, 46464, 46339,
+ 46214, 46089, 45965, 45841, 45718, 45595, 45472, 45349, 45227, 45105, 44984,
+ 44862, 44741, 44621, 44501, 44381, 44261, 44142, 44023, 43904, 43786, 43668,
+ 43550, 43433, 43316, 43199, 43083, 42967, 42851, 42735, 42620, 42505, 42391,
+ 42277, 42163, 42049, 41936, 41823, 41710, 41598, 41486, 41374, 41262, 41151,
+ 41040, 40930, 40819, 40709, 40600, 40490, 40381, 40272, 40164, 40056, 39948,
+ 39840, 39733, 39626, 39519, 39412, 39306, 39200, 39094, 38989, 38884, 38779,
+ 38675, 38571, 38467, 38363, 38260, 38157, 38054, 37951, 37849, 37747, 37645,
+ 37544, 37443, 37342, 37241, 37141, 37041, 36941, 36841, 36742, 36643, 36544,
+ 36446, 36347, 36250, 36152, 36054, 35957, 35860, 35764, 35667, 35571, 35475,
+ 35380, 35284, 35189, 35095, 35000, 34906, 34812, 34718, 34624, 34531, 34438,
+ 34345, 34253, 34160, 34068, 33976, 33885
+};
+
+static const short sindb_coeff[] = {
+ 2401, 2144, 1994, 1887, 1804, 1737, 1680, 1630, 1587, 1548, 1512, 1480, 1450,
+ 1423, 1397, 1373, 1351, 1330, 1310, 1291, 1273, 1255, 1239, 1223, 1208, 1194,
+ 1180, 1166, 1153, 1141, 1128, 1117, 1105, 1094, 1084, 1073, 1063, 1053, 1043,
+ 1034, 1025, 1016, 1007, 999, 990, 982, 974, 967, 959, 952, 944, 937,
+ 930, 923, 916, 910, 903, 897, 890, 884, 878, 872, 866, 860, 855,
+ 849, 843, 838, 832, 827, 822, 817, 812, 807, 802, 797, 792, 787,
+ 783, 778, 773, 769, 764, 760, 756, 751, 747, 743, 739, 734, 730,
+ 726, 722, 718, 715, 711, 707, 703, 699, 696, 692, 688, 685, 681,
+ 678, 674, 671, 667, 664, 661, 657, 654, 651, 648, 644, 641, 638,
+ 635, 632, 629, 626, 623, 620, 617, 614, 611, 608, 605, 602, 599,
+ 597, 594, 591, 588, 586, 583, 580, 578, 575, 572, 570, 567, 565,
+ 562, 560, 557, 555, 552, 550, 547, 545, 542, 540, 538, 535, 533,
+ 531, 528, 526, 524, 522, 519, 517, 515, 513, 510, 508, 506, 504,
+ 502, 500, 498, 495, 493, 491, 489, 487, 485, 483, 481, 479, 477,
+ 475, 473, 471, 469, 467, 465, 464, 462, 460, 458, 456, 454, 452,
+ 450, 449, 447, 445, 443, 441, 440, 438, 436, 434, 433, 431, 429,
+ 427, 426, 424, 422, 421, 419, 417, 416, 414, 412, 411, 409, 408,
+ 406, 404, 403, 401, 400, 398, 396, 395, 393, 392, 390, 389, 387,
+ 386, 384, 383, 381, 380, 378, 377, 375, 374, 372, 371, 370, 368,
+ 367, 365, 364, 362, 361, 360, 358, 357, 355, 354, 353, 351, 350,
+ 349, 347, 346, 345, 343, 342, 341, 339, 338, 337, 336, 334, 333,
+ 332, 330, 329, 328, 327, 325, 324, 323, 322, 320, 319, 318, 317,
+ 316, 314, 313, 312, 311, 310, 308, 307, 306, 305, 304, 303, 301,
+ 300, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287,
+ 286, 285, 284, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273,
+ 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
+ 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247,
+ 246, 245, 244, 243, 242, 241, 240, 240, 239, 238, 237, 236, 235,
+ 234, 233, 232, 231, 230, 230, 229, 228, 227, 226, 225, 224, 223,
+ 222, 222, 221, 220, 219, 218, 217, 216, 216, 215, 214, 213, 212,
+ 211, 211, 210, 209, 208, 207, 206, 206, 205, 204, 203, 202, 202,
+ 201, 200, 199, 198, 198, 197, 196, 195, 195, 194, 193, 192, 191,
+ 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182,
+ 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172,
+ 172, 171, 170, 170, 169, 168, 167, 167, 166, 165, 165, 164, 163,
+ 163, 162, 161, 161, 160, 159, 159, 158, 157, 157, 156, 155, 155,
+ 154, 153, 153, 152, 151, 151, 150, 150, 149, 148, 148, 147, 146,
+ 146, 145, 145, 144, 143, 143, 142, 141, 141, 140, 140, 139, 138,
+ 138, 137, 137, 136, 135, 135, 134, 134, 133, 133, 132, 131, 131,
+ 130, 130, 129, 129, 128, 127, 127, 126, 126, 125, 125, 124, 123,
+ 123, 122, 122, 121, 121, 120, 120, 119, 119, 118, 117, 117, 116,
+ 116, 115, 115, 114, 114, 113, 113, 112, 112, 111, 111, 110, 110,
+ 109, 109, 108, 108, 107, 107, 106, 106, 105, 105, 104, 104, 103,
+ 103, 102, 102, 101, 101, 100, 100, 99, 99, 98, 98, 97, 97,
+ 96, 96, 95, 95, 94, 94, 94, 93, 93, 92, 92, 91, 91,
+ 90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85,
+ 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79,
+ 79, 79, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74,
+ 74, 73, 73, 73, 72, 72, 71, 71, 71, 70, 70, 69, 69,
+ 69, 68, 68, 68, 67, 67, 66, 66, 66, 65, 65, 65, 64,
+ 64, 63, 63, 63, 62, 62, 62, 61, 61, 61, 60, 60, 59,
+ 59, 59, 58, 58, 58, 57, 57, 57, 56, 56, 56, 55, 55,
+ 55, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51,
+ 50, 50, 50, 49, 49, 49, 49, 48, 48, 48, 47, 47, 47,
+ 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 43, 43, 43,
+ 43, 42, 42, 42, 41, 41, 41, 40, 40, 40, 40, 39, 39,
+ 39, 39, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 36,
+ 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32,
+ 32, 32, 31, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29,
+ 29, 29, 28, 28, 28, 28, 27, 27, 27, 27, 27, 26, 26,
+ 26, 26, 25, 25, 25, 25, 25, 24, 24, 24, 24, 23, 23,
+ 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21,
+ 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 18, 18,
+ 18, 18, 18, 17, 17, 17, 17, 17, 17, 16, 16, 16, 16,
+ 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14,
+ 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
+ 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,
+ 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
+static const short lfo_freq_coeff[] = {
+ 0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37,
+ 40, 43, 46, 50, 53, 56, 59, 62, 65, 68, 71, 74, 78,
+ 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118,
+ 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157,
+ 160, 163, 166, 169, 172, 175, 178, 180, 183, 186, 189, 192, 195,
+ 198, 201, 204, 207, 209, 212, 215, 218, 221, 224, 226, 229, 232,
+ 235, 238, 240, 243, 246, 249, 251, 254, 257, 260, 262, 265, 268,
+ 270, 273, 276, 278, 281, 283, 286, 289, 291, 294, 296, 299, 301,
+ 304, 306, 309, 311, 314, 316, 319, 321, 324, 326, 328, 331, 333,
+ 336, 338, 340, 343, 345, 347, 350, 352, 354, 356, 359, 361, 363,
+ 365, 367, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 391,
+ 393, 395, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 415,
+ 417, 419, 421, 423, 424, 426, 428, 430, 431, 433, 435, 436, 438,
+ 439, 441, 443, 444, 446, 447, 449, 450, 452, 453, 455, 456, 457,
+ 459, 460, 461, 463, 464, 465, 467, 468, 469, 470, 472, 473, 474,
+ 475, 476, 477, 478, 480, 481, 482, 483, 484, 485, 486, 487, 488,
+ 488, 489, 490, 491, 492, 493, 494, 494, 495, 496, 497, 497, 498,
+ 499, 499, 500, 501, 501, 502, 502, 503, 504, 504, 504, 505, 505,
+ 506, 506, 507, 507, 507, 508, 508, 508, 509, 509, 509, 509, 510,
+ 510, 510, 510, 510, 510, 510, 510, 510, 510, 511, 510, 510, 510,
+ 510, 510, 510, 510, 510, 510, 510, 509, 509, 509, 509, 508, 508,
+ 508, 507, 507, 507, 506, 506, 505, 505, 504, 504, 504, 503, 502,
+ 502, 501, 501, 500, 499, 499, 498, 497, 497, 496, 495, 494, 494,
+ 493, 492, 491, 490, 489, 488, 488, 487, 486, 485, 484, 483, 482,
+ 481, 480, 478, 477, 476, 475, 474, 473, 472, 470, 469, 468, 467,
+ 465, 464, 463, 461, 460, 459, 457, 456, 455, 453, 452, 450, 449,
+ 447, 446, 444, 443, 441, 439, 438, 436, 435, 433, 431, 430, 428,
+ 426, 424, 423, 421, 419, 417, 415, 414, 412, 410, 408, 406, 404,
+ 402, 400, 398, 396, 395, 393, 391, 388, 386, 384, 382, 380, 378,
+ 376, 374, 372, 370, 367, 365, 363, 361, 359, 356, 354, 352, 350,
+ 347, 345, 343, 340, 338, 336, 333, 331, 328, 326, 324, 321, 319,
+ 316, 314, 311, 309, 306, 304, 301, 299, 296, 294, 291, 289, 286,
+ 283, 281, 278, 276, 273, 270, 268, 265, 262, 260, 257, 254, 251,
+ 249, 246, 243, 240, 238, 235, 232, 229, 226, 224, 221, 218, 215,
+ 212, 209, 207, 204, 201, 198, 195, 192, 189, 186, 183, 180, 178,
+ 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139,
+ 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99,
+ 96, 93, 90, 87, 84, 81, 78, 74, 71, 68, 65, 62, 59,
+ 56, 53, 50, 46, 43, 40, 37, 34, 31, 28, 25, 21, 18,
+ 15, 12, 9, 6, 3, 0, -3, -6, -9, -12, -15, -18, -21,
+ -25, -28, -31, -34, -37, -40, -43, -46, -50, -53, -56, -59, -62,
+ -65, -68, -71, -74, -78, -81, -84, -87, -90, -93, -96, -99, -102,
+ -105, -108, -111, -115, -118, -121, -124, -127, -130, -133, -136, -139, -142,
+ -145, -148, -151, -154, -157, -160, -163, -166, -169, -172, -175, -178, -180,
+ -183, -186, -189, -192, -195, -198, -201, -204, -207, -209, -212, -215, -218,
+ -221, -224, -226, -229, -232, -235, -238, -240, -243, -246, -249, -251, -254,
+ -257, -260, -262, -265, -268, -270, -273, -276, -278, -281, -283, -286, -289,
+ -291, -294, -296, -299, -301, -304, -306, -309, -311, -314, -316, -319, -321,
+ -324, -326, -328, -331, -333, -336, -338, -340, -343, -345, -347, -350, -352,
+ -354, -356, -359, -361, -363, -365, -367, -370, -372, -374, -376, -378, -380,
+ -382, -384, -386, -388, -391, -393, -395, -396, -398, -400, -402, -404, -406,
+ -408, -410, -412, -414, -415, -417, -419, -421, -423, -424, -426, -428, -430,
+ -431, -433, -435, -436, -438, -439, -441, -443, -444, -446, -447, -449, -450,
+ -452, -453, -455, -456, -457, -459, -460, -461, -463, -464, -465, -467, -468,
+ -469, -470, -472, -473, -474, -475, -476, -477, -478, -480, -481, -482, -483,
+ -484, -485, -486, -487, -488, -488, -489, -490, -491, -492, -493, -494, -494,
+ -495, -496, -497, -497, -498, -499, -499, -500, -501, -501, -502, -502, -503,
+ -504, -504, -504, -505, -505, -506, -506, -507, -507, -507, -508, -508, -508,
+ -509, -509, -509, -509, -510, -510, -510, -510, -510, -510, -510, -510, -510,
+ -510, -511, -510, -510, -510, -510, -510, -510, -510, -510, -510, -510, -509,
+ -509, -509, -509, -508, -508, -508, -507, -507, -507, -506, -506, -505, -505,
+ -504, -504, -504, -503, -502, -502, -501, -501, -500, -499, -499, -498, -497,
+ -497, -496, -495, -494, -494, -493, -492, -491, -490, -489, -488, -488, -487,
+ -486, -485, -484, -483, -482, -481, -480, -478, -477, -476, -475, -474, -473,
+ -472, -470, -469, -468, -467, -465, -464, -463, -461, -460, -459, -457, -456,
+ -455, -453, -452, -450, -449, -447, -446, -444, -443, -441, -439, -438, -436,
+ -435, -433, -431, -430, -428, -426, -424, -423, -421, -419, -417, -415, -414,
+ -412, -410, -408, -406, -404, -402, -400, -398, -396, -395, -393, -391, -388,
+ -386, -384, -382, -380, -378, -376, -374, -372, -370, -367, -365, -363, -361,
+ -359, -356, -354, -352, -350, -347, -345, -343, -340, -338, -336, -333, -331,
+ -328, -326, -324, -321, -319, -316, -314, -311, -309, -306, -304, -301, -299,
+ -296, -294, -291, -289, -286, -283, -281, -278, -276, -273, -270, -268, -265,
+ -262, -260, -257, -254, -251, -249, -246, -243, -240, -238, -235, -232, -229,
+ -226, -224, -221, -218, -215, -212, -209, -207, -204, -201, -198, -195, -192,
+ -189, -186, -183, -180, -178, -175, -172, -169, -166, -163, -160, -157, -154,
+ -151, -148, -145, -142, -139, -136, -133, -130, -127, -124, -121, -118, -115,
+ -111, -108, -105, -102, -99, -96, -93, -90, -87, -84, -81, -78, -74,
+ -71, -68, -65, -62, -59, -56, -53, -50, -46, -43, -40, -37, -34,
+ -31, -28, -25, -21, -18, -15, -12, -9, -6, -3
+};
+
+static const short lfo_env_coeff[] = {
+ 251, 253, 254, 256, 257, 259, 260, 262, 264, 265, 267, 268, 270,
+ 271, 273, 274, 276, 277, 279, 281, 282, 284, 285, 287, 288, 290,
+ 291, 293, 294, 296, 297, 299, 300, 302, 303, 305, 306, 308, 309,
+ 311, 312, 314, 315, 317, 318, 320, 321, 323, 324, 326, 327, 329,
+ 330, 332, 333, 335, 336, 337, 339, 340, 342, 343, 345, 346, 348,
+ 349, 350, 352, 353, 355, 356, 357, 359, 360, 362, 363, 364, 366,
+ 367, 369, 370, 371, 373, 374, 375, 377, 378, 379, 381, 382, 383,
+ 385, 386, 387, 389, 390, 391, 392, 394, 395, 396, 397, 399, 400,
+ 401, 402, 404, 405, 406, 407, 409, 410, 411, 412, 413, 414, 416,
+ 417, 418, 419, 420, 421, 423, 424, 425, 426, 427, 428, 429, 430,
+ 431, 432, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
+ 445, 446, 447, 448, 449, 450, 451, 452, 453, 453, 454, 455, 456,
+ 457, 458, 459, 460, 461, 461, 462, 463, 464, 465, 466, 466, 467,
+ 468, 469, 469, 470, 471, 472, 473, 473, 474, 475, 475, 476, 477,
+ 477, 478, 479, 479, 480, 481, 481, 482, 483, 483, 484, 484, 485,
+ 486, 486, 487, 487, 488, 488, 489, 489, 490, 490, 491, 491, 492,
+ 492, 493, 493, 493, 494, 494, 495, 495, 495, 496, 496, 497, 497,
+ 497, 498, 498, 498, 498, 499, 499, 499, 500, 500, 500, 500, 500,
+ 501, 501, 501, 501, 501, 502, 502, 502, 502, 502, 502, 502, 502,
+ 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503,
+ 503, 503, 503, 503, 503, 503, 502, 502, 502, 502, 502, 502, 502,
+ 502, 501, 501, 501, 501, 501, 500, 500, 500, 500, 500, 499, 499,
+ 499, 498, 498, 498, 498, 497, 497, 497, 496, 496, 495, 495, 495,
+ 494, 494, 493, 493, 493, 492, 492, 491, 491, 490, 490, 489, 489,
+ 488, 488, 487, 487, 486, 486, 485, 484, 484, 483, 483, 482, 481,
+ 481, 480, 479, 479, 478, 477, 477, 476, 475, 475, 474, 473, 473,
+ 472, 471, 470, 469, 469, 468, 467, 466, 466, 465, 464, 463, 462,
+ 461, 461, 460, 459, 458, 457, 456, 455, 454, 453, 453, 452, 451,
+ 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438,
+ 437, 436, 435, 434, 432, 431, 430, 429, 428, 427, 426, 425, 424,
+ 423, 421, 420, 419, 418, 417, 416, 414, 413, 412, 411, 410, 409,
+ 407, 406, 405, 404, 402, 401, 400, 399, 397, 396, 395, 394, 392,
+ 391, 390, 389, 387, 386, 385, 383, 382, 381, 379, 378, 377, 375,
+ 374, 373, 371, 370, 369, 367, 366, 364, 363, 362, 360, 359, 357,
+ 356, 355, 353, 352, 350, 349, 348, 346, 345, 343, 342, 340, 339,
+ 337, 336, 335, 333, 332, 330, 329, 327, 326, 324, 323, 321, 320,
+ 318, 317, 315, 314, 312, 311, 309, 308, 306, 305, 303, 302, 300,
+ 299, 297, 296, 294, 293, 291, 290, 288, 287, 285, 284, 282, 281,
+ 279, 277, 276, 274, 273, 271, 270, 268, 267, 265, 264, 262, 260,
+ 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 240,
+ 239, 237, 236, 234, 233, 231, 230, 228, 227, 225, 223, 222, 220,
+ 219, 217, 216, 214, 213, 211, 210, 208, 207, 205, 204, 202, 201,
+ 199, 198, 196, 195, 193, 192, 190, 189, 187, 186, 184, 183, 181,
+ 180, 178, 177, 175, 174, 172, 171, 169, 168, 166, 165, 164, 162,
+ 161, 159, 158, 156, 155, 153, 152, 151, 149, 148, 146, 145, 144,
+ 142, 141, 139, 138, 137, 135, 134, 133, 131, 130, 129, 127, 126,
+ 124, 123, 122, 120, 119, 118, 117, 115, 114, 113, 111, 110, 109,
+ 108, 106, 105, 104, 103, 101, 100, 99, 98, 96, 95, 94, 93,
+ 92, 90, 89, 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
+ 77, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64,
+ 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
+ 50, 49, 48, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39,
+ 39, 38, 37, 36, 35, 35, 34, 33, 32, 31, 31, 30, 29,
+ 29, 28, 27, 26, 26, 25, 24, 24, 23, 22, 22, 21, 20,
+ 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13,
+ 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7,
+ 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3,
+ 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
+ 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
+ 19, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26,
+ 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 35, 35, 36,
+ 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88,
+ 89, 90, 92, 93, 94, 95, 96, 98, 99, 100, 101, 103, 104,
+ 105, 106, 108, 109, 110, 111, 113, 114, 115, 117, 118, 119, 120,
+ 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 135, 137, 138,
+ 139, 141, 142, 144, 145, 146, 148, 149, 151, 152, 153, 155, 156,
+ 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 174, 175,
+ 177, 178, 180, 181, 183, 184, 186, 187, 189, 190, 192, 193, 195,
+ 196, 198, 199, 201, 202, 204, 205, 207, 208, 210, 211, 213, 214,
+ 216, 217, 219, 220, 222, 223, 225, 227, 228, 230, 231, 233, 234,
+ 236, 237, 239, 240, 242, 244, 245, 247, 248, 250
+};
+
+#endif
diff --git a/apps/codecs/libgme/z80_cpu.h b/apps/codecs/libgme/z80_cpu.h
index 15115b7e53..341119b6b1 100644
--- a/apps/codecs/libgme/z80_cpu.h
+++ b/apps/codecs/libgme/z80_cpu.h
@@ -1,116 +1,116 @@
-// Z80 CPU emulator
-
-// Game_Music_Emu 0.6-pre
-#ifndef Z80_CPU_H
-#define Z80_CPU_H
-
-#include "blargg_source.h"
-#include "blargg_endian.h"
-
-typedef int cpu_time_t;
-typedef int addr_t;
-
-enum { page_bits = 10 };
-enum { page_size = 1 << page_bits };
-enum { page_count = 0x10000 / page_size };
-
-// Can read this far past end of memory
-enum { cpu_padding = 0x100 };
-
-// Can read this many bytes past end of a page
-enum { page_padding = 4 };
-
-#ifdef BLARGG_BIG_ENDIAN
- struct regs_t { byte b,c, d,e, h,l, flags,a; };
-#else
- struct regs_t { byte c,b, e,d, l,h, a,flags; };
-#endif
-// BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
-
-struct pairs_t { uint16_t bc, de, hl, fa; };
-
-// Registers are not updated until run() returns
-struct registers_t {
- uint16_t pc;
- uint16_t sp;
- uint16_t ix;
- uint16_t iy;
- union {
- struct regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
- struct pairs_t w; // w.bc, w.de, w.hl. w.fa
- };
- union {
- struct regs_t b;
- struct pairs_t w;
- } alt;
- byte iff1;
- byte iff2;
- byte r;
- byte i;
- byte im;
-};
-
-struct cpu_state_t {
- byte const* read [page_count + 1];
- byte * write [page_count + 1];
- cpu_time_t base;
- cpu_time_t time;
-};
-
-struct Z80_Cpu {
- byte szpc [0x200];
- cpu_time_t end_time_;
-
- struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy within run()
- struct cpu_state_t cpu_state_;
-
- struct registers_t r;
-};
-
-void Z80_init( struct Z80_Cpu* this );
-
-// Clears registers and maps all pages to unmapped
-void Z80_reset( struct Z80_Cpu* this, void* unmapped_write, void const* unmapped_read );
-
-// TODO: split mapping out of CPU
-
-// Maps memory. Start and size must be multiple of page_size.
-void Z80_map_mem( struct Z80_Cpu* this, addr_t addr, int size, void* write, void const* read );
-
-// Time of beginning of next instruction
-static inline cpu_time_t Z80_time( struct Z80_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; }
-
-// Alter current time
-static inline void Z80_set_time( struct Z80_Cpu* this, cpu_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
-static inline void Z80_adjust_time( struct Z80_Cpu* this, int delta ) { this->cpu_state->time += delta; }
-
-#ifdef BLARGG_NONPORTABLE
- #define Z80_CPU_OFFSET( addr ) (addr)
-#else
- #define Z80_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-// Maps address to pointer to that byte
-static inline byte* Z80_write( struct Z80_Cpu* this, addr_t addr )
-{
- return this->cpu_state->write [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
-}
-
-static inline byte const* Z80_read( struct Z80_Cpu* this, addr_t addr )
-{
- return this->cpu_state->read [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
-}
-
-static inline void Z80_map_mem_rw( struct Z80_Cpu* this, addr_t addr, int size, void* p )
-{
- Z80_map_mem( this, addr, size, p, p );
-}
-
-static inline void Z80_set_end_time( struct Z80_Cpu* this, cpu_time_t t )
-{
- cpu_time_t delta = this->cpu_state->base - t;
- this->cpu_state->base = t;
- this->cpu_state->time += delta;
-}
-
-#endif
+// Z80 CPU emulator
+
+// Game_Music_Emu 0.6-pre
+#ifndef Z80_CPU_H
+#define Z80_CPU_H
+
+#include "blargg_source.h"
+#include "blargg_endian.h"
+
+typedef int cpu_time_t;
+typedef int addr_t;
+
+enum { page_bits = 10 };
+enum { page_size = 1 << page_bits };
+enum { page_count = 0x10000 / page_size };
+
+// Can read this far past end of memory
+enum { cpu_padding = 0x100 };
+
+// Can read this many bytes past end of a page
+enum { page_padding = 4 };
+
+#ifdef BLARGG_BIG_ENDIAN
+ struct regs_t { byte b,c, d,e, h,l, flags,a; };
+#else
+ struct regs_t { byte c,b, e,d, l,h, a,flags; };
+#endif
+// BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
+
+struct pairs_t { uint16_t bc, de, hl, fa; };
+
+// Registers are not updated until run() returns
+struct registers_t {
+ uint16_t pc;
+ uint16_t sp;
+ uint16_t ix;
+ uint16_t iy;
+ union {
+ struct regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
+ struct pairs_t w; // w.bc, w.de, w.hl. w.fa
+ };
+ union {
+ struct regs_t b;
+ struct pairs_t w;
+ } alt;
+ byte iff1;
+ byte iff2;
+ byte r;
+ byte i;
+ byte im;
+};
+
+struct cpu_state_t {
+ byte const* read [page_count + 1];
+ byte * write [page_count + 1];
+ cpu_time_t base;
+ cpu_time_t time;
+};
+
+struct Z80_Cpu {
+ byte szpc [0x200];
+ cpu_time_t end_time_;
+
+ struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy within run()
+ struct cpu_state_t cpu_state_;
+
+ struct registers_t r;
+};
+
+void Z80_init( struct Z80_Cpu* this );
+
+// Clears registers and maps all pages to unmapped
+void Z80_reset( struct Z80_Cpu* this, void* unmapped_write, void const* unmapped_read );
+
+// TODO: split mapping out of CPU
+
+// Maps memory. Start and size must be multiple of page_size.
+void Z80_map_mem( struct Z80_Cpu* this, addr_t addr, int size, void* write, void const* read );
+
+// Time of beginning of next instruction
+static inline cpu_time_t Z80_time( struct Z80_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; }
+
+// Alter current time
+static inline void Z80_set_time( struct Z80_Cpu* this, cpu_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
+static inline void Z80_adjust_time( struct Z80_Cpu* this, int delta ) { this->cpu_state->time += delta; }
+
+#ifdef BLARGG_NONPORTABLE
+ #define Z80_CPU_OFFSET( addr ) (addr)
+#else
+ #define Z80_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
+#endif
+
+// Maps address to pointer to that byte
+static inline byte* Z80_write( struct Z80_Cpu* this, addr_t addr )
+{
+ return this->cpu_state->write [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
+}
+
+static inline byte const* Z80_read( struct Z80_Cpu* this, addr_t addr )
+{
+ return this->cpu_state->read [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
+}
+
+static inline void Z80_map_mem_rw( struct Z80_Cpu* this, addr_t addr, int size, void* p )
+{
+ Z80_map_mem( this, addr, size, p, p );
+}
+
+static inline void Z80_set_end_time( struct Z80_Cpu* this, cpu_time_t t )
+{
+ cpu_time_t delta = this->cpu_state->base - t;
+ this->cpu_state->base = t;
+ this->cpu_state->time += delta;
+}
+
+#endif
diff --git a/apps/codecs/libgme/z80_cpu_run.h b/apps/codecs/libgme/z80_cpu_run.h
index 18195ac92b..a453487bb0 100644
--- a/apps/codecs/libgme/z80_cpu_run.h
+++ b/apps/codecs/libgme/z80_cpu_run.h
@@ -1,1696 +1,1696 @@
-// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
-
-// Last validated with zexall 2009.12.05.
-// Doesn't implement the R register or immediate interrupt after EI.
-// Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-// 16-bit memory accesses are made directly to mapped memory, instead of using macro.
-
-#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 between FLUSH_TIME() and
-CACHE_TIME() the normal time changing functions can be used.
-- Macros "returning" void may use a {} statement block. */
-
- // 0 <= addr <= 0xFFFF + 0x100
- // Optional; default uses whatever was set with map_mem()
- int READ_MEM( addr_t );
- void WRITE_MEM( addr_t, int data );
-
- // 0 <= port <= 0xFFFF (apparently upper 8 bits are output by hardware)
- void OUT_PORT( int port, int data );
- int IN_PORT int port );
-
- // Reference to Z80_Cpu object used for emulation
- #define CPU cpu
-
-// 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)
-
- // Optimizes as if map_mem( 0, 0x10000, FLAT_MEM, FLAT_MEM ) is always in effect
- #define FLAT_MEM my_mem_array
-
- // If RST 7 ($FF) is encountered and PC = IDLE_ADDR, stops execution
- #define IDLE_ADDR 0x1234
-
- // Expanded just before beginning of code, to help debugger
- #define CPU_BEGIN void my_run_cpu() {
-
-#endif
-
-/* 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 */
-
-#ifdef CPU_BEGIN
- CPU_BEGIN
-#endif
-
-#define R cpu->r
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n ) cpu->szpc [n]
-#define SZ28PC( n ) cpu->szpc [n]
-#define SZ28C( n ) (cpu->szpc [n] & ~P04)
-#define SZ28( n ) SZ28C( n )
-
-#define SET_R( n ) (void) (R.r = n)
-#define GET_R() (R.r)
-
-// Time
-#define TIME() (s_time + s.base)
-#define FLUSH_TIME() {s.time = s_time;}
-#define CACHE_TIME() {s_time = s.time;}
-
-// Memory
-#define RW_MEM( addr, rw ) RW_PAGE( addr, rw ) [RW_OFFSET( addr )]
-#define READ_CODE( addr ) RW_MEM( addr, read )
-
-#ifdef FLAT_MEM
- #define RW_PAGE( addr, rw ) FLAT_MEM
- #define RW_OFFSET( addr ) (addr)
- #define INSTR( off, addr ) READ_CODE( addr )
-#else
- #define RW_PAGE( addr, rw ) s.rw [(unsigned) (addr) >> page_bits]
- #define RW_OFFSET( addr ) Z80_CPU_OFFSET( addr )
- #define INSTR( off, addr ) instr [off]
-#endif
-
-#ifndef READ_MEM
- #define READ_MEM( addr ) RW_MEM( addr, read )
-#endif
-
-#ifndef WRITE_MEM
- #define WRITE_MEM( addr, data ) (RW_MEM( addr, write ) = data)
-#endif
-
-#define READ_WORD( addr ) GET_LE16( &RW_MEM( addr, read ) )
-#define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data )
-
-// Truncation
-#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
-#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
-#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
-
-// Misc
-#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-#ifdef BLARGG_BIG_ENDIAN
- #define R8( n, offset ) ((r.r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n, offset ) ((r.r8_ - offset) [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
-#define R16( n, shift, offset ) (r.r16_ [((unsigned) (n) >> shift) - (offset >> shift)])
-
-#define EX( x, y ) \
- {\
- int temp = x;\
- x = y;\
- y = temp;\
- }
-
-#define EXX( name ) \
- EX( R.alt.name, r.name )
-
-bool warning = false;
-{
- struct cpu_state_t s;
- #ifdef FLAT_MEM
- s.base = cpu->cpu_state_.base;
- #else
- s = cpu->cpu_state_;
- #endif
- cpu->cpu_state = &s;
-
-
- union r_t {
- struct regs_t b;
- struct pairs_t w;
- byte r8_ [8]; // indexed
- uint16_t r16_ [4];
- } r;
- r.b = R.b;
-
- cpu_time_t s_time = cpu->cpu_state_.time;
- int pc = R.pc;
- int sp = R.sp;
- int ix = R.ix; // TODO: keep in memory for direct access?
- int iy = R.iy;
- int flags = R.b.flags;
-
- //goto loop; // confuses optimizer
- s_time += 7;
- pc -= 2;
-
-call_not_taken:
- s_time -= 7;
-jp_not_taken:
- pc += 2;
-loop:
-
- check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around
- check( (unsigned) sp < 0x10000 );
- check( (unsigned) flags < 0x100 );
- check( (unsigned) ix < 0x10000 );
- check( (unsigned) iy < 0x10000 );
-
- byte const* instr = RW_PAGE( pc, read );
-
- int opcode;
-
- if ( RW_OFFSET( ~0 ) == ~0 )
- {
- opcode = instr [RW_OFFSET( pc )];
- pc++;
- instr += RW_OFFSET( pc );
- }
- else
- {
- instr += RW_OFFSET( pc );
- opcode = *instr++;
- pc++;
- }
-
- static byte const clock_table [256 * 2] = {
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
- 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
- 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, // 2
- 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, // 3
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
- 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
- 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
- 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
- 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
- 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
-
- // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
- //0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
- 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
- 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
- 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
- 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
- 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
- 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
- };
-
- if ( s_time >= 0 )
- goto out_of_time;
- s_time += clock_table [opcode];
-
- #ifdef Z80_CPU_LOG_H
- //log_opcode( opcode, READ_CODE( pc ) );
- z80_cpu_log( "log.txt", pc - 1, opcode, READ_CODE( pc ),
- READ_CODE( pc + 1 ), READ_CODE( pc + 2 ) );
- z80_log_regs( r.b.a, r.w.bc, r.w.de, r.w.hl, sp, ix, iy );
- #endif
-
-#define GET_ADDR() GET_LE16( &INSTR( 0, pc ) )
-
- int data;
- data = INSTR( 0, pc );
-
- switch ( opcode )
- {
-// Common
-
- case 0x00: // NOP
- CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
- goto loop;
-
- case 0x08:{// EX AF,AF'
- EXX( b.a );
- EX( R.alt.b.flags, flags );
- goto loop;
- }
-
- case 0xD3: // OUT (imm),A
- pc++;
- OUT_PORT( (data + r.b.a * 0x100), r.b.a );
- goto loop;
-
- case 0x2E: // LD L,imm
- pc++;
- r.b.l = data;
- goto loop;
-
- case 0x3E: // LD A,imm
- pc++;
- r.b.a = data;
- goto loop;
-
- case 0x3A:{// LD A,(addr)
- int addr = GET_ADDR();
- pc += 2;
- r.b.a = READ_MEM( addr );
- goto loop;
- }
-
-// Conditional
-
-#define ZERO (flags & Z40)
-#define CARRY (flags & C01)
-#define EVEN (flags & P04)
-#define MINUS (flags & S80)
-
-// JR
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define JR_( cond, clocks ) {\
- pc++;\
- if ( !(cond) )\
- goto loop;\
- int offset = SBYTE( data );\
- pc = WORD( pc + offset );\
- s_time += clocks;\
- goto loop;\
-}
-
-#define JR( cond ) JR_( cond, 5 )
-
- case 0x20: JR( !ZERO ) // JR NZ,disp
- case 0x28: JR( ZERO ) // JR Z,disp
- case 0x30: JR( !CARRY ) // JR NC,disp
- case 0x38: JR( CARRY ) // JR C,disp
- case 0x18: JR_( true,0) // JR disp
-
- case 0x10:{// DJNZ disp
- int temp = r.b.b - 1;
- r.b.b = temp;
- JR( temp )
- }
-
-// JP
-#define JP( cond ) \
- if ( !(cond) )\
- goto jp_not_taken;\
- pc = GET_ADDR();\
- goto loop;
-
- case 0xC2: JP( !ZERO ) // JP NZ,addr
- case 0xCA: JP( ZERO ) // JP Z,addr
- case 0xD2: JP( !CARRY ) // JP NC,addr
- case 0xDA: JP( CARRY ) // JP C,addr
- case 0xE2: JP( !EVEN ) // JP PO,addr
- case 0xEA: JP( EVEN ) // JP PE,addr
- case 0xF2: JP( !MINUS ) // JP P,addr
- case 0xFA: JP( MINUS ) // JP M,addr
-
- case 0xC3: // JP addr
- pc = GET_ADDR();
- goto loop;
-
- case 0xE9: // JP HL
- pc = r.w.hl;
- goto loop;
-
-// RET
-#define RET( cond ) \
- if ( cond )\
- goto ret_taken;\
- s_time -= 6;\
- goto loop;
-
- case 0xC0: RET( !ZERO ) // RET NZ
- case 0xC8: RET( ZERO ) // RET Z
- case 0xD0: RET( !CARRY ) // RET NC
- case 0xD8: RET( CARRY ) // RET C
- case 0xE0: RET( !EVEN ) // RET PO
- case 0xE8: RET( EVEN ) // RET PE
- case 0xF0: RET( !MINUS ) // RET P
- case 0xF8: RET( MINUS ) // RET M
-
- case 0xC9: // RET
- ret_taken:
- pc = READ_WORD( sp );
- sp = WORD( sp + 2 );
- goto loop;
-
-// CALL
-#define CALL( cond ) \
- if ( cond )\
- goto call_taken;\
- goto call_not_taken;
-
- case 0xC4: CALL( !ZERO ) // CALL NZ,addr
- case 0xCC: CALL( ZERO ) // CALL Z,addr
- case 0xD4: CALL( !CARRY ) // CALL NC,addr
- case 0xDC: CALL( CARRY ) // CALL C,addr
- case 0xE4: CALL( !EVEN ) // CALL PO,addr
- case 0xEC: CALL( EVEN ) // CALL PE,addr
- case 0xF4: CALL( !MINUS ) // CALL P,addr
- case 0xFC: CALL( MINUS ) // CALL M,addr
-
- case 0xCD:{// CALL addr
- call_taken: {
- int addr = pc + 2;
- pc = GET_ADDR();
- sp = WORD( sp - 2 );
- WRITE_WORD( sp, addr );
- goto loop;
- }
- }
-
- case 0xFF: // RST
- #ifdef IDLE_ADDR
- if ( pc == IDLE_ADDR + 1 )
- goto hit_idle_addr;
- #else
- if ( pc > 0x10000 )
- {
- pc = WORD( pc - 1 );
- s_time -= 11;
- goto loop;
- }
- #endif
- CASE7( C7, CF, D7, DF, E7, EF, F7 ):
- data = pc;
- pc = opcode & 0x38;
- #ifdef RST_BASE
- pc += RST_BASE;
- #endif
- goto push_data;
-
-// PUSH/POP
- case 0xF5: // PUSH AF
- data = r.b.a * 0x100u + flags;
- goto push_data;
-
- case 0xC5: // PUSH BC
- case 0xD5: // PUSH DE
- case 0xE5: // PUSH HL
- data = R16( opcode, 4, 0xC5 );
- push_data:
- sp = WORD( sp - 2 );
- WRITE_WORD( sp, data );
- goto loop;
-
- case 0xF1: // POP AF
- flags = READ_MEM( sp );
- r.b.a = READ_MEM( (sp + 1) );
- sp = WORD( sp + 2 );
- goto loop;
-
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL
- R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
- sp = WORD( sp + 2 );
- goto loop;
-
-// ADC/ADD/SBC/SUB
- case 0x96: // SUB (HL)
- case 0x86: // ADD (HL)
- flags &= ~C01;
- case 0x9E: // SBC (HL)
- case 0x8E: // ADC (HL)
- data = READ_MEM( r.w.hl );
- goto adc_data;
-
- case 0xD6: // SUB A,imm
- case 0xC6: // ADD imm
- flags &= ~C01;
- case 0xDE: // SBC A,imm
- case 0xCE: // ADC imm
- pc++;
- goto adc_data;
-
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
- flags &= ~C01;
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
- data = R8( opcode & 7, 0 );
- adc_data: {
- int result = data + (flags & C01);
- data ^= r.b.a;
- flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
- if ( flags )
- result = -result;
- result += r.b.a;
- data ^= result;
- flags +=(data & H10) +
- ((data + 0x80) >> 6 & V04) +
- SZ28C( result & 0x1FF );
- r.b.a = result;
- goto loop;
- }
-
-// CP
- case 0xBE: // CP (HL)
- data = READ_MEM( r.w.hl );
- goto cp_data;
-
- case 0xFE: // CP imm
- pc++;
- goto cp_data;
-
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
- data = R8( opcode, 0xB8 );
- cp_data: {
- int result = r.b.a - data;
- flags = N02 + (data & (F20 | F08)) + (result >> 8 & C01);
- data ^= r.b.a;
- flags +=(((result ^ r.b.a) & data) >> 5 & V04) +
- (((data & H10) ^ result) & (S80 | H10));
- if ( BYTE( result ) )
- goto loop;
- flags += Z40;
- goto loop;
- }
-
-// ADD HL,r.w
-
- case 0x39: // ADD HL,SP
- data = sp;
- goto add_hl_data;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- data = R16( opcode, 4, 0x09 );
- add_hl_data: {
- int sum = r.w.hl + data;
- data ^= r.w.hl;
- r.w.hl = sum;
- flags = (flags & (S80 | Z40 | V04)) +
- (sum >> 16) +
- (sum >> 8 & (F20 | F08)) +
- ((data ^ sum) >> 8 & H10);
- goto loop;
- }
-
- case 0x27:{// DAA
- int a = r.b.a;
- if ( a > 0x99 )
- flags |= C01;
-
- int adjust = 0x60 * (flags & C01);
-
- if ( flags & H10 || (a & 0x0F) > 9 )
- adjust += 0x06;
-
- if ( flags & N02 )
- adjust = -adjust;
- a += adjust;
-
- flags = (flags & (C01 | N02)) +
- ((r.b.a ^ a) & H10) +
- SZ28P( BYTE( a ) );
- r.b.a = a;
- goto loop;
- }
-
-// INC/DEC
- case 0x34: // INC (HL)
- data = READ_MEM( r.w.hl ) + 1;
- WRITE_MEM( r.w.hl, data );
- goto inc_set_flags;
-
- CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
- data = ++R8( opcode >> 3, 0 );
- inc_set_flags:
- flags = (flags & C01) +
- (((data & 0x0F) - 1) & H10) +
- SZ28( BYTE( data ) );
- if ( data != 0x80 )
- goto loop;
- flags += V04;
- goto loop;
-
- case 0x35: // DEC (HL)
- data = READ_MEM( r.w.hl ) - 1;
- WRITE_MEM( r.w.hl, data );
- goto dec_set_flags;
-
- CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
- data = --R8( opcode >> 3, 0 );
- dec_set_flags:
- flags = (flags & C01) + N02 +
- (((data & 0x0F) + 1) & H10) +
- SZ28( BYTE( data ) );
- if ( data != 0x7F )
- goto loop;
- flags += V04;
- goto loop;
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- R16( opcode, 4, 0x03 )++;
- goto loop;
-
- case 0x33: // INC SP
- sp = WORD( sp + 1 );
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- R16( opcode, 4, 0x0B )--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = WORD( sp - 1 );
- goto loop;
-
-// AND
- case 0xA6: // AND (HL)
- data = READ_MEM( r.w.hl );
- goto and_data;
-
- case 0xE6: // AND imm
- pc++;
- goto and_data;
-
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
- data = R8( opcode, 0xA0 );
- and_data:
- r.b.a &= data;
- flags = SZ28P( r.b.a ) + H10;
- goto loop;
-
-// OR
- case 0xB6: // OR (HL)
- data = READ_MEM( r.w.hl );
- goto or_data;
-
- case 0xF6: // OR imm
- pc++;
- goto or_data;
-
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
- data = R8( opcode, 0xB0 );
- or_data:
- r.b.a |= data;
- flags = SZ28P( r.b.a );
- goto loop;
-
-// XOR
- case 0xAE: // XOR (HL)
- data = READ_MEM( r.w.hl );
- goto xor_data;
-
- case 0xEE: // XOR imm
- pc++;
- goto xor_data;
-
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
- data = R8( opcode, 0xA8 );
- xor_data:
- r.b.a ^= data;
- flags = SZ28P( r.b.a );
- goto loop;
-
-// LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
- WRITE_MEM( r.w.hl, R8( opcode, 0x70 ) );
- goto loop;
-
- CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
- CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
- CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
- CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
- CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
- CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
- CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
- R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
- goto loop;
-
- CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
- R8( opcode >> 3, 0 ) = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),imm
- pc++;
- WRITE_MEM( r.w.hl, data );
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
- R8( opcode >> 3, 8 ) = READ_MEM( r.w.hl );
- goto loop;
-
- case 0x01: // LD r.w,imm
- case 0x11:
- case 0x21:
- R16( opcode, 4, 0x01 ) = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x31: // LD sp,imm
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x2A:{// LD HL,(addr)
- int addr = GET_ADDR();
- pc += 2;
- r.w.hl = READ_WORD( addr );
- goto loop;
- }
-
- case 0x32:{// LD (addr),A
- int addr = GET_ADDR();
- pc += 2;
- WRITE_MEM( addr, r.b.a );
- goto loop;
- }
-
- case 0x22:{// LD (addr),HL
- int addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, r.w.hl );
- goto loop;
- }
-
- case 0x02: // LD (BC),A
- case 0x12: // LD (DE),A
- WRITE_MEM( R16( opcode, 4, 0x02 ), r.b.a );
- goto loop;
-
- case 0x0A: // LD A,(BC)
- case 0x1A: // LD A,(DE)
- r.b.a = READ_MEM( R16( opcode, 4, 0x0A ) );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = r.w.hl;
- goto loop;
-
-// Rotate
-
- case 0x07:{// RLCA
- int temp = r.b.a;
- temp = (temp << 1) + (temp >> 7);
- flags = (flags & (S80 | Z40 | P04)) +
- (temp & (F20 | F08 | C01));
- r.b.a = temp;
- goto loop;
- }
-
- case 0x0F:{// RRCA
- int temp = r.b.a;
- flags = (flags & (S80 | Z40 | P04)) +
- (temp & C01);
- temp = (temp << 7) + (temp >> 1);
- flags += temp & (F20 | F08);
- r.b.a = temp;
- goto loop;
- }
-
- case 0x17:{// RLA
- int temp = (r.b.a << 1) + (flags & C01);
- flags = (flags & (S80 | Z40 | P04)) +
- (temp & (F20 | F08)) +
- (temp >> 8);
- r.b.a = temp;
- goto loop;
- }
-
- case 0x1F:{// RRA
- int temp = (flags << 7) + (r.b.a >> 1);
- flags = (flags & (S80 | Z40 | P04)) +
- (temp & (F20 | F08)) +
- (r.b.a & C01);
- r.b.a = temp;
- goto loop;
- }
-
-// Misc
- case 0x2F:{// CPL
- int temp = ~r.b.a;
- flags = (flags & (S80 | Z40 | P04 | C01)) +
- (temp & (F20 | F08)) +
- (H10 | N02);
- r.b.a = temp;
- goto loop;
- }
-
- case 0x3F:{// CCF
- flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) +
- (flags << 4 & H10) +
- (r.b.a & (F20 | F08));
- goto loop;
- }
-
- case 0x37: // SCF
- flags = ((flags & (S80 | Z40 | P04)) | C01) +
- (r.b.a & (F20 | F08));
- goto loop;
-
- case 0xDB: // IN A,(imm)
- pc++;
- r.b.a = IN_PORT( (data + r.b.a * 0x100) );
- goto loop;
-
- case 0xE3:{// EX (SP),HL
- int temp = READ_WORD( sp );
- WRITE_WORD( sp, r.w.hl );
- r.w.hl = temp;
- goto loop;
- }
-
- case 0xEB: // EX DE,HL
- EX( r.w.hl, r.w.de );
- goto loop;
-
- case 0xD9: // EXX DE,HL
- EXX( w.bc );
- EXX( w.de );
- EXX( w.hl );
- goto loop;
-
- case 0xF3: // DI
- R.iff1 = 0;
- R.iff2 = 0;
- goto loop;
-
- case 0xFB: // EI
- R.iff1 = 1;
- R.iff2 = 1;
- // TODO: delayed effect
- goto loop;
-
- case 0x76: // HALT
- goto halt;
-
-//////////////////////////////////////// CB prefix
- {
- case 0xCB:
- pc++;
- switch ( data )
- {
-
- // Rotate left
-
- #define RLC( read, write ) {\
- int result = read;\
- result = BYTE( result << 1 ) + (result >> 7);\
- flags = SZ28P( result ) + (result & C01);\
- write;\
- goto loop;\
- }
-
- case 0x06: // RLC (HL)
- s_time += 7;
- data = r.w.hl;
- rlc_data_addr:
- RLC( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
- byte* reg = &R8( data, 0 );
- RLC( *reg, *reg = result )
- }
-
- #define RL( read, write ) {\
- int result = (read << 1) + (flags & C01);\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x16: // RL (HL)
- s_time += 7;
- data = r.w.hl;
- rl_data_addr:
- RL( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
- byte* reg = &R8( data, 0x10 );
- RL( *reg, *reg = result )
- }
-
- #define SLA( read, low_bit, write ) {\
- int result = (read << 1) + low_bit;\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x26: // SLA (HL)
- s_time += 7;
- data = r.w.hl;
- sla_data_addr:
- SLA( READ_MEM( data ), 0, WRITE_MEM( data, result ) )
-
- CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
- byte* reg = &R8( data, 0x20 );
- SLA( *reg, 0, *reg = result )
- }
-
- case 0x36: // SLL (HL)
- s_time += 7;
- data = r.w.hl;
- sll_data_addr:
- SLA( READ_MEM( data ), 1, WRITE_MEM( data, result ) )
-
- CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
- byte* reg = &R8( data, 0x30 );
- SLA( *reg, 1, *reg = result )
- }
-
- // Rotate right
-
- #define RRC( read, write ) {\
- int result = read;\
- flags = result & C01;\
- result = BYTE( result << 7 ) + (result >> 1);\
- flags += SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x0E: // RRC (HL)
- s_time += 7;
- data = r.w.hl;
- rrc_data_addr:
- RRC( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
- byte* reg = &R8( data, 0x08 );
- RRC( *reg, *reg = result )
- }
-
- #define RR( read, write ) {\
- int result = read;\
- int temp = result & C01;\
- result = BYTE( flags << 7 ) + (result >> 1);\
- flags = SZ28P( result ) + temp;\
- write;\
- goto loop;\
- }
-
- case 0x1E: // RR (HL)
- s_time += 7;
- data = r.w.hl;
- rr_data_addr:
- RR( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
- byte* reg = &R8( data, 0x18 );
- RR( *reg, *reg = result )
- }
-
- #define SRA( read, write ) {\
- int result = read;\
- flags = result & C01;\
- result = (result & 0x80) + (result >> 1);\
- flags += SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x2E: // SRA (HL)
- data = r.w.hl;
- s_time += 7;
- sra_data_addr:
- SRA( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
- byte* reg = &R8( data, 0x28 );
- SRA( *reg, *reg = result )
- }
-
- #define SRL( read, write ) {\
- int result = read;\
- flags = result & C01;\
- result >>= 1;\
- flags += SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x3E: // SRL (HL)
- s_time += 7;
- data = r.w.hl;
- srl_data_addr:
- SRL( READ_MEM( data ), WRITE_MEM( data, result ) )
-
- CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
- byte* reg = &R8( data, 0x38 );
- SRL( *reg, *reg = result )
- }
-
- // BIT
- {
- int temp;
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
- s_time += 4;
- temp = READ_MEM( r.w.hl );
- flags &= C01;
- goto bit_temp;
- CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
- CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
- CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
- CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
- CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
- CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
- CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
- temp = R8( data & 7, 0 );
- flags = (flags & C01) + (temp & (F20 | F08));
- bit_temp:
- temp = temp & (1 << (data >> 3 & 7));
- flags += (temp & S80) + H10;
- flags += (unsigned) --temp >> 8 & (Z40 | P04);
- goto loop;
- }
-
- // SET/RES
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
- s_time += 7;
- int temp = READ_MEM( r.w.hl );
- int bit = 1 << (data >> 3 & 7);
- temp |= bit; // SET
- if ( !(data & 0x40) )
- temp ^= bit; // RES
- WRITE_MEM( r.w.hl, temp );
- goto loop;
- }
-
- CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
- CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
- CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
- CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
- CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
- CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
- CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
- CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
- R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
- goto loop;
-
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
- R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
- goto loop;
- }
- assert( false );
- }
-
-#undef GET_ADDR
-#define GET_ADDR() GET_LE16( &INSTR( 1, pc ) )
-
-//////////////////////////////////////// ED prefix
- {
- case 0xED:
- pc++;
- s_time += (clock_table + 256) [data] >> 4;
- switch ( data )
- {
- {
- int temp;
- case 0x72: // SBC HL,SP
- case 0x7A: // ADC HL,SP
- temp = sp;
- if ( 0 )
- case 0x42: // SBC HL,BC
- case 0x52: // SBC HL,DE
- case 0x62: // SBC HL,HL
- case 0x4A: // ADC HL,BC
- case 0x5A: // ADC HL,DE
- case 0x6A: // ADC HL,HL
- temp = R16( data >> 3 & 6, 1, 0 );
- int sum = temp + (flags & C01);
- flags = ~data >> 2 & N02;
- if ( flags )
- sum = -sum;
- sum += r.w.hl;
- temp ^= r.w.hl;
- temp ^= sum;
- flags +=(sum >> 16 & C01) +
- (temp >> 8 & H10) +
- (sum >> 8 & (S80 | F20 | F08)) +
- ((temp + 0x8000) >> 14 & V04);
- r.w.hl = sum;
- if ( WORD( sum ) )
- goto loop;
- flags += Z40;
- goto loop;
- }
-
- CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
- int temp = IN_PORT( r.w.bc );
- R8( data >> 3, 8 ) = temp;
- flags = (flags & C01) + SZ28P( temp );
- goto loop;
- }
-
- case 0x71: // OUT (C),0
- r.b.flags = 0;
- CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
- OUT_PORT( r.w.bc, R8( data >> 3, 8 ) );
- goto loop;
-
- {
- int temp;
- case 0x73: // LD (ADDR),SP
- temp = sp;
- if ( 0 )
- case 0x43: // LD (ADDR),BC
- case 0x53: // LD (ADDR),DE
- temp = R16( data, 4, 0x43 );
- int addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, temp );
- goto loop;
- }
-
- case 0x4B: // LD BC,(ADDR)
- case 0x5B:{// LD DE,(ADDR)
- int addr = GET_ADDR();
- pc += 2;
- R16( data, 4, 0x4B ) = READ_WORD( addr );
- goto loop;
- }
-
- case 0x7B:{// LD SP,(ADDR)
- int addr = GET_ADDR();
- pc += 2;
- sp = READ_WORD( addr );
- goto loop;
- }
-
- case 0x67:{// RRD
- int temp = READ_MEM( r.w.hl );
- WRITE_MEM( r.w.hl, ((r.b.a << 4) + (temp >> 4)) );
- temp = (r.b.a & 0xF0) + (temp & 0x0F);
- flags = (flags & C01) + SZ28P( temp );
- r.b.a = temp;
- goto loop;
- }
-
- case 0x6F:{// RLD
- int temp = READ_MEM( r.w.hl );
- WRITE_MEM( r.w.hl, ((temp << 4) + (r.b.a & 0x0F)) );
- temp = (r.b.a & 0xF0) + (temp >> 4);
- flags = (flags & C01) + SZ28P( temp );
- r.b.a = temp;
- goto loop;
- }
-
- CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
- opcode = 0x10; // flag to do SBC instead of ADC
- flags &= ~C01;
- data = r.b.a;
- r.b.a = 0;
- goto adc_data;
-
- {
- int inc;
- case 0xA9: // CPD
- case 0xB9: // CPDR
- inc = -1;
- if ( 0 )
- case 0xA1: // CPI
- case 0xB1: // CPIR
- inc = +1;
- int addr = r.w.hl;
- r.w.hl = addr + inc;
- int temp = READ_MEM( addr );
-
- int result = r.b.a - temp;
- flags = (flags & C01) + N02 +
- ((((temp ^ r.b.a) & H10) ^ result) & (S80 | H10));
-
- if ( !BYTE( result ) )
- flags += Z40;
- result -= (flags & H10) >> 4;
- flags += result & F08;
- flags += result << 4 & F20;
- if ( !--r.w.bc )
- goto loop;
-
- flags += V04;
- if ( flags & Z40 || data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xA8: // LDD
- case 0xB8: // LDDR
- inc = -1;
- if ( 0 )
- case 0xA0: // LDI
- case 0xB0: // LDIR
- inc = +1;
- int addr = r.w.hl;
- r.w.hl = addr + inc;
- int temp = READ_MEM( addr );
-
- addr = r.w.de;
- r.w.de = addr + inc;
- WRITE_MEM( addr, temp );
-
- temp += r.b.a;
- flags = (flags & (S80 | Z40 | C01)) +
- (temp & F08) + (temp << 4 & F20);
- if ( !--r.w.bc )
- goto loop;
-
- flags += V04;
- if ( data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xAB: // OUTD
- case 0xBB: // OTDR
- inc = -1;
- if ( 0 )
- case 0xA3: // OUTI
- case 0xB3: // OTIR
- inc = +1;
- int addr = r.w.hl;
- r.w.hl = addr + inc;
- int temp = READ_MEM( addr );
-
- int b = --r.b.b;
- flags = (temp >> 6 & N02) + SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- OUT_PORT( r.w.bc, temp );
- goto loop;
- }
-
- {
- int inc;
- case 0xAA: // IND
- case 0xBA: // INDR
- inc = -1;
- if ( 0 )
- case 0xA2: // INI
- case 0xB2: // INIR
- inc = +1;
-
- int addr = r.w.hl;
- r.w.hl = addr + inc;
-
- int temp = IN_PORT( r.w.bc );
-
- int b = --r.b.b;
- flags = (temp >> 6 & N02) + SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- WRITE_MEM( addr, temp );
- goto loop;
- }
-
- case 0x47: // LD I,A
- R.i = r.b.a;
- goto loop;
-
- case 0x4F: // LD R,A
- SET_R( r.b.a );
- dprintf( "LD R,A not supported\n" );
- warning = true;
- goto loop;
-
- case 0x57: // LD A,I
- r.b.a = R.i;
- goto ld_ai_common;
-
- case 0x5F: // LD A,R
- r.b.a = GET_R();
- dprintf( "LD A,R not supported\n" );
- warning = true;
- ld_ai_common:
- flags = (flags & C01) + SZ28( r.b.a ) + (R.iff2 << 2 & V04);
- goto loop;
-
- CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
- R.iff1 = R.iff2;
- goto ret_taken;
-
- case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
- R.im = 0;
- goto loop;
-
- case 0x56: case 0x76: // IM 1
- R.im = 1;
- goto loop;
-
- case 0x5E: case 0x7E: // IM 2
- R.im = 2;
- goto loop;
-
- default:
- dprintf( "Opcode $ED $%02X not supported\n", data );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// DD/FD prefix
- {
- int ixy;
- case 0xDD:
- ixy = ix;
- goto ix_prefix;
- case 0xFD:
- ixy = iy;
- ix_prefix:
- pc++;
- int data2 = READ_CODE( pc );
- s_time += (clock_table + 256) [data] & 0x0F;
- switch ( data )
- {
- // TODO: more efficient way of avoid negative address
- // TODO: avoid using this as argument to READ_MEM() since it is evaluated twice
- #define IXY_DISP( ixy, disp ) WORD( (ixy ) + (disp))
-
- #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
- // ADD/ADC/SUB/SBC
-
- case 0x96: // SUB (IXY+disp)
- case 0x86: // ADD (IXY+disp)
- flags &= ~C01;
- case 0x9E: // SBC (IXY+disp)
- case 0x8E: // ADC (IXY+disp)
- pc++;
- opcode = data;
- data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto adc_data;
-
- case 0x94: // SUB HXY
- case 0x84: // ADD HXY
- flags &= ~C01;
- case 0x9C: // SBC HXY
- case 0x8C: // ADC HXY
- opcode = data;
- data = ixy >> 8;
- goto adc_data;
-
- case 0x95: // SUB LXY
- case 0x85: // ADD LXY
- flags &= ~C01;
- case 0x9D: // SBC LXY
- case 0x8D: // ADC LXY
- opcode = data;
- data = BYTE( ixy );
- goto adc_data;
-
- {
- int temp;
- case 0x39: // ADD IXY,SP
- temp = sp;
- goto add_ixy_data;
-
- case 0x29: // ADD IXY,HL
- temp = ixy;
- goto add_ixy_data;
-
- case 0x09: // ADD IXY,BC
- case 0x19: // ADD IXY,DE
- temp = R16( data, 4, 0x09 );
- add_ixy_data: {
- int sum = ixy + temp;
- temp ^= ixy;
- ixy = WORD( sum );
- flags = (flags & (S80 | Z40 | V04)) +
- (sum >> 16) +
- (sum >> 8 & (F20 | F08)) +
- ((temp ^ sum) >> 8 & H10);
- goto set_ixy;
- }
- }
-
- // AND
- case 0xA6: // AND (IXY+disp)
- pc++;
- data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto and_data;
-
- case 0xA4: // AND HXY
- data = ixy >> 8;
- goto and_data;
-
- case 0xA5: // AND LXY
- data = BYTE( ixy );
- goto and_data;
-
- // OR
- case 0xB6: // OR (IXY+disp)
- pc++;
- data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto or_data;
-
- case 0xB4: // OR HXY
- data = ixy >> 8;
- goto or_data;
-
- case 0xB5: // OR LXY
- data = BYTE( ixy );
- goto or_data;
-
- // XOR
- case 0xAE: // XOR (IXY+disp)
- pc++;
- data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto xor_data;
-
- case 0xAC: // XOR HXY
- data = ixy >> 8;
- goto xor_data;
-
- case 0xAD: // XOR LXY
- data = BYTE( ixy );
- goto xor_data;
-
- // CP
- case 0xBE: // CP (IXY+disp)
- pc++;
- data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto cp_data;
-
- case 0xBC: // CP HXY
- data = ixy >> 8;
- goto cp_data;
-
- case 0xBD: // CP LXY
- data = BYTE( ixy );
- goto cp_data;
-
- // LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
- data = R8( data, 0x70 );
- if ( 0 )
- case 0x36: // LD (IXY+disp),imm
- pc++, data = READ_CODE( pc );
- pc++;
- WRITE_MEM( IXY_DISP( ixy, SBYTE( data2 ) ), data );
- goto loop;
-
- CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
- R8( data >> 3, 8 ) = ixy >> 8;
- goto loop;
-
- case 0x64: // LD HXY,HXY
- case 0x6D: // LD LXY,LXY
- goto loop;
-
- CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
- R8( data >> 3, 8 ) = ixy;
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
- pc++;
- R8( data >> 3, 8 ) = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
- goto loop;
-
- case 0x26: // LD HXY,imm
- pc++;
- goto ld_hxy_data;
-
- case 0x65: // LD HXY,LXY
- data2 = BYTE( ixy );
- goto ld_hxy_data;
-
- CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
- data2 = R8( data, 0x60 );
- ld_hxy_data:
- ixy = BYTE( ixy ) + (data2 << 8);
- goto set_ixy;
-
- case 0x2E: // LD LXY,imm
- pc++;
- goto ld_lxy_data;
-
- case 0x6C: // LD LXY,HXY
- data2 = ixy >> 8;
- goto ld_lxy_data;
-
- CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
- data2 = R8( data, 0x68 );
- ld_lxy_data:
- ixy = (ixy & 0xFF00) + data2;
- set_ixy:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto loop;
- }
- iy = ixy;
- goto loop;
-
- case 0xF9: // LD SP,IXY
- sp = ixy;
- goto loop;
-
- case 0x22:{// LD (ADDR),IXY
- int addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, ixy );
- goto loop;
- }
-
- case 0x21: // LD IXY,imm
- ixy = GET_ADDR();
- pc += 2;
- goto set_ixy;
-
- case 0x2A:{// LD IXY,(addr)
- int addr = GET_ADDR();
- ixy = READ_WORD( addr );
- pc += 2;
- goto set_ixy;
- }
-
- // DD/FD CB prefix
- case 0xCB: {
- data = IXY_DISP( ixy, SBYTE( data2 ) );
- pc++;
- data2 = READ_CODE( pc );
- pc++;
- switch ( data2 )
- {
- case 0x06: goto rlc_data_addr; // RLC (IXY)
- case 0x16: goto rl_data_addr; // RL (IXY)
- case 0x26: goto sla_data_addr; // SLA (IXY)
- case 0x36: goto sll_data_addr; // SLL (IXY)
- case 0x0E: goto rrc_data_addr; // RRC (IXY)
- case 0x1E: goto rr_data_addr; // RR (IXY)
- case 0x2E: goto sra_data_addr; // SRA (IXY)
- case 0x3E: goto srl_data_addr; // SRL (IXY)
-
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
- int temp = READ_MEM( data );
- temp = temp & (1 << (data2 >> 3 & 7));
- flags = (flags & C01) + H10 + (temp & S80);
- flags += (unsigned) --temp >> 8 & (Z40 | P04);
- goto loop;
- }
-
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
- int temp = READ_MEM( data );
- int bit = 1 << (data2 >> 3 & 7);
- temp |= bit; // SET
- if ( !(data2 & 0x40) )
- temp ^= bit; // RES
- WRITE_MEM( data, temp );
- goto loop;
- }
-
- default:
- dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
- // INC/DEC
- case 0x23: // INC IXY
- ixy = WORD( ixy + 1 );
- goto set_ixy;
-
- case 0x2B: // DEC IXY
- ixy = WORD( ixy - 1 );
- goto set_ixy;
-
- case 0x34: // INC (IXY+disp)
- ixy = IXY_DISP( ixy, SBYTE( data2 ) );
- pc++;
- data = READ_MEM( ixy ) + 1;
- WRITE_MEM( ixy, data );
- goto inc_set_flags;
-
- case 0x35: // DEC (IXY+disp)
- ixy = IXY_DISP( ixy, SBYTE( data2 ) );
- pc++;
- data = READ_MEM( ixy ) - 1;
- WRITE_MEM( ixy, data );
- goto dec_set_flags;
-
- case 0x24: // INC HXY
- ixy = WORD( ixy + 0x100 );
- data = ixy >> 8;
- goto inc_xy_common;
-
- case 0x2C: // INC LXY
- data = BYTE( ixy + 1 );
- ixy = (ixy & 0xFF00) + data;
- inc_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto inc_set_flags;
- }
- iy = ixy;
- goto inc_set_flags;
-
- case 0x25: // DEC HXY
- ixy = WORD( ixy - 0x100 );
- data = ixy >> 8;
- goto dec_xy_common;
-
- case 0x2D: // DEC LXY
- data = BYTE( ixy - 1 );
- ixy = (ixy & 0xFF00) + data;
- dec_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto dec_set_flags;
- }
- iy = ixy;
- goto dec_set_flags;
-
- // PUSH/POP
- case 0xE5: // PUSH IXY
- data = ixy;
- goto push_data;
-
- case 0xE1:{// POP IXY
- ixy = READ_WORD( sp );
- sp = WORD( sp + 2 );
- goto set_ixy;
- }
-
- // Misc
-
- case 0xE9: // JP (IXY)
- pc = ixy;
- goto loop;
-
- case 0xE3:{// EX (SP),IXY
- int temp = READ_WORD( sp );
- WRITE_WORD( sp, ixy );
- ixy = temp;
- goto set_ixy;
- }
-
- default:
- dprintf( "Unnecessary DD/FD prefix encountered\n" );
- warning = true;
- pc--;
- goto loop;
- }
- assert( false );
- }
-
- }
- dprintf( "Unhandled main opcode: $%02X\n", opcode );
- assert( false );
-
-#ifdef IDLE_ADDR
-hit_idle_addr:
- s_time -= 11;
- goto out_of_time;
-#endif
-halt:
- s_time &= 3; // increment by multiple of 4
-out_of_time:
- pc--;
-
- r.b.flags = flags;
- R.ix = ix;
- R.iy = iy;
- R.sp = sp;
- R.pc = pc;
- R.b = r.b;
-
- cpu->cpu_state_.base = s.base;
- cpu->cpu_state_.time = s_time;
- cpu->cpu_state = &cpu->cpu_state_;
-}
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+// Last validated with zexall 2009.12.05.
+// Doesn't implement the R register or immediate interrupt after EI.
+// Address wrap-around isn't completely correct, but is prevented from crashing emulator.
+// 16-bit memory accesses are made directly to mapped memory, instead of using macro.
+
+#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 between FLUSH_TIME() and
+CACHE_TIME() the normal time changing functions can be used.
+- Macros "returning" void may use a {} statement block. */
+
+ // 0 <= addr <= 0xFFFF + 0x100
+ // Optional; default uses whatever was set with map_mem()
+ int READ_MEM( addr_t );
+ void WRITE_MEM( addr_t, int data );
+
+ // 0 <= port <= 0xFFFF (apparently upper 8 bits are output by hardware)
+ void OUT_PORT( int port, int data );
+ int IN_PORT int port );
+
+ // Reference to Z80_Cpu object used for emulation
+ #define CPU cpu
+
+// 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)
+
+ // Optimizes as if map_mem( 0, 0x10000, FLAT_MEM, FLAT_MEM ) is always in effect
+ #define FLAT_MEM my_mem_array
+
+ // If RST 7 ($FF) is encountered and PC = IDLE_ADDR, stops execution
+ #define IDLE_ADDR 0x1234
+
+ // Expanded just before beginning of code, to help debugger
+ #define CPU_BEGIN void my_run_cpu() {
+
+#endif
+
+/* 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 */
+
+#ifdef CPU_BEGIN
+ CPU_BEGIN
+#endif
+
+#define R cpu->r
+
+// flags, named with hex value for clarity
+int const S80 = 0x80;
+int const Z40 = 0x40;
+int const F20 = 0x20;
+int const H10 = 0x10;
+int const F08 = 0x08;
+int const V04 = 0x04;
+int const P04 = 0x04;
+int const N02 = 0x02;
+int const C01 = 0x01;
+
+#define SZ28P( n ) cpu->szpc [n]
+#define SZ28PC( n ) cpu->szpc [n]
+#define SZ28C( n ) (cpu->szpc [n] & ~P04)
+#define SZ28( n ) SZ28C( n )
+
+#define SET_R( n ) (void) (R.r = n)
+#define GET_R() (R.r)
+
+// Time
+#define TIME() (s_time + s.base)
+#define FLUSH_TIME() {s.time = s_time;}
+#define CACHE_TIME() {s_time = s.time;}
+
+// Memory
+#define RW_MEM( addr, rw ) RW_PAGE( addr, rw ) [RW_OFFSET( addr )]
+#define READ_CODE( addr ) RW_MEM( addr, read )
+
+#ifdef FLAT_MEM
+ #define RW_PAGE( addr, rw ) FLAT_MEM
+ #define RW_OFFSET( addr ) (addr)
+ #define INSTR( off, addr ) READ_CODE( addr )
+#else
+ #define RW_PAGE( addr, rw ) s.rw [(unsigned) (addr) >> page_bits]
+ #define RW_OFFSET( addr ) Z80_CPU_OFFSET( addr )
+ #define INSTR( off, addr ) instr [off]
+#endif
+
+#ifndef READ_MEM
+ #define READ_MEM( addr ) RW_MEM( addr, read )
+#endif
+
+#ifndef WRITE_MEM
+ #define WRITE_MEM( addr, data ) (RW_MEM( addr, write ) = data)
+#endif
+
+#define READ_WORD( addr ) GET_LE16( &RW_MEM( addr, read ) )
+#define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data )
+
+// Truncation
+#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
+#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
+#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
+
+// Misc
+#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
+#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
+#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
+#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
+
+#ifdef BLARGG_BIG_ENDIAN
+ #define R8( n, offset ) ((r.r8_ - offset) [n])
+#elif BLARGG_LITTLE_ENDIAN
+ #define R8( n, offset ) ((r.r8_ - offset) [(n) ^ 1])
+#else
+ #error "Byte order of CPU must be known"
+#endif
+
+#define R16( n, shift, offset ) (r.r16_ [((unsigned) (n) >> shift) - (offset >> shift)])
+
+#define EX( x, y ) \
+ {\
+ int temp = x;\
+ x = y;\
+ y = temp;\
+ }
+
+#define EXX( name ) \
+ EX( R.alt.name, r.name )
+
+bool warning = false;
+{
+ struct cpu_state_t s;
+ #ifdef FLAT_MEM
+ s.base = cpu->cpu_state_.base;
+ #else
+ s = cpu->cpu_state_;
+ #endif
+ cpu->cpu_state = &s;
+
+
+ union r_t {
+ struct regs_t b;
+ struct pairs_t w;
+ byte r8_ [8]; // indexed
+ uint16_t r16_ [4];
+ } r;
+ r.b = R.b;
+
+ cpu_time_t s_time = cpu->cpu_state_.time;
+ int pc = R.pc;
+ int sp = R.sp;
+ int ix = R.ix; // TODO: keep in memory for direct access?
+ int iy = R.iy;
+ int flags = R.b.flags;
+
+ //goto loop; // confuses optimizer
+ s_time += 7;
+ pc -= 2;
+
+call_not_taken:
+ s_time -= 7;
+jp_not_taken:
+ pc += 2;
+loop:
+
+ check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around
+ check( (unsigned) sp < 0x10000 );
+ check( (unsigned) flags < 0x100 );
+ check( (unsigned) ix < 0x10000 );
+ check( (unsigned) iy < 0x10000 );
+
+ byte const* instr = RW_PAGE( pc, read );
+
+ int opcode;
+
+ if ( RW_OFFSET( ~0 ) == ~0 )
+ {
+ opcode = instr [RW_OFFSET( pc )];
+ pc++;
+ instr += RW_OFFSET( pc );
+ }
+ else
+ {
+ instr += RW_OFFSET( pc );
+ opcode = *instr++;
+ pc++;
+ }
+
+ static byte const clock_table [256 * 2] = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
+ 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
+ 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, // 2
+ 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, // 3
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
+ 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
+ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
+ 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
+ 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
+ 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
+ 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
+
+ // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
+ //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+ 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
+ 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
+ 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
+ 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
+ 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ };
+
+ if ( s_time >= 0 )
+ goto out_of_time;
+ s_time += clock_table [opcode];
+
+ #ifdef Z80_CPU_LOG_H
+ //log_opcode( opcode, READ_CODE( pc ) );
+ z80_cpu_log( "log.txt", pc - 1, opcode, READ_CODE( pc ),
+ READ_CODE( pc + 1 ), READ_CODE( pc + 2 ) );
+ z80_log_regs( r.b.a, r.w.bc, r.w.de, r.w.hl, sp, ix, iy );
+ #endif
+
+#define GET_ADDR() GET_LE16( &INSTR( 0, pc ) )
+
+ int data;
+ data = INSTR( 0, pc );
+
+ switch ( opcode )
+ {
+// Common
+
+ case 0x00: // NOP
+ CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
+ goto loop;
+
+ case 0x08:{// EX AF,AF'
+ EXX( b.a );
+ EX( R.alt.b.flags, flags );
+ goto loop;
+ }
+
+ case 0xD3: // OUT (imm),A
+ pc++;
+ OUT_PORT( (data + r.b.a * 0x100), r.b.a );
+ goto loop;
+
+ case 0x2E: // LD L,imm
+ pc++;
+ r.b.l = data;
+ goto loop;
+
+ case 0x3E: // LD A,imm
+ pc++;
+ r.b.a = data;
+ goto loop;
+
+ case 0x3A:{// LD A,(addr)
+ int addr = GET_ADDR();
+ pc += 2;
+ r.b.a = READ_MEM( addr );
+ goto loop;
+ }
+
+// Conditional
+
+#define ZERO (flags & Z40)
+#define CARRY (flags & C01)
+#define EVEN (flags & P04)
+#define MINUS (flags & S80)
+
+// JR
+// TODO: more efficient way to handle negative branch that wraps PC around
+#define JR_( cond, clocks ) {\
+ pc++;\
+ if ( !(cond) )\
+ goto loop;\
+ int offset = SBYTE( data );\
+ pc = WORD( pc + offset );\
+ s_time += clocks;\
+ goto loop;\
+}
+
+#define JR( cond ) JR_( cond, 5 )
+
+ case 0x20: JR( !ZERO ) // JR NZ,disp
+ case 0x28: JR( ZERO ) // JR Z,disp
+ case 0x30: JR( !CARRY ) // JR NC,disp
+ case 0x38: JR( CARRY ) // JR C,disp
+ case 0x18: JR_( true,0) // JR disp
+
+ case 0x10:{// DJNZ disp
+ int temp = r.b.b - 1;
+ r.b.b = temp;
+ JR( temp )
+ }
+
+// JP
+#define JP( cond ) \
+ if ( !(cond) )\
+ goto jp_not_taken;\
+ pc = GET_ADDR();\
+ goto loop;
+
+ case 0xC2: JP( !ZERO ) // JP NZ,addr
+ case 0xCA: JP( ZERO ) // JP Z,addr
+ case 0xD2: JP( !CARRY ) // JP NC,addr
+ case 0xDA: JP( CARRY ) // JP C,addr
+ case 0xE2: JP( !EVEN ) // JP PO,addr
+ case 0xEA: JP( EVEN ) // JP PE,addr
+ case 0xF2: JP( !MINUS ) // JP P,addr
+ case 0xFA: JP( MINUS ) // JP M,addr
+
+ case 0xC3: // JP addr
+ pc = GET_ADDR();
+ goto loop;
+
+ case 0xE9: // JP HL
+ pc = r.w.hl;
+ goto loop;
+
+// RET
+#define RET( cond ) \
+ if ( cond )\
+ goto ret_taken;\
+ s_time -= 6;\
+ goto loop;
+
+ case 0xC0: RET( !ZERO ) // RET NZ
+ case 0xC8: RET( ZERO ) // RET Z
+ case 0xD0: RET( !CARRY ) // RET NC
+ case 0xD8: RET( CARRY ) // RET C
+ case 0xE0: RET( !EVEN ) // RET PO
+ case 0xE8: RET( EVEN ) // RET PE
+ case 0xF0: RET( !MINUS ) // RET P
+ case 0xF8: RET( MINUS ) // RET M
+
+ case 0xC9: // RET
+ ret_taken:
+ pc = READ_WORD( sp );
+ sp = WORD( sp + 2 );
+ goto loop;
+
+// CALL
+#define CALL( cond ) \
+ if ( cond )\
+ goto call_taken;\
+ goto call_not_taken;
+
+ case 0xC4: CALL( !ZERO ) // CALL NZ,addr
+ case 0xCC: CALL( ZERO ) // CALL Z,addr
+ case 0xD4: CALL( !CARRY ) // CALL NC,addr
+ case 0xDC: CALL( CARRY ) // CALL C,addr
+ case 0xE4: CALL( !EVEN ) // CALL PO,addr
+ case 0xEC: CALL( EVEN ) // CALL PE,addr
+ case 0xF4: CALL( !MINUS ) // CALL P,addr
+ case 0xFC: CALL( MINUS ) // CALL M,addr
+
+ case 0xCD:{// CALL addr
+ call_taken: {
+ int addr = pc + 2;
+ pc = GET_ADDR();
+ sp = WORD( sp - 2 );
+ WRITE_WORD( sp, addr );
+ goto loop;
+ }
+ }
+
+ case 0xFF: // RST
+ #ifdef IDLE_ADDR
+ if ( pc == IDLE_ADDR + 1 )
+ goto hit_idle_addr;
+ #else
+ if ( pc > 0x10000 )
+ {
+ pc = WORD( pc - 1 );
+ s_time -= 11;
+ goto loop;
+ }
+ #endif
+ CASE7( C7, CF, D7, DF, E7, EF, F7 ):
+ data = pc;
+ pc = opcode & 0x38;
+ #ifdef RST_BASE
+ pc += RST_BASE;
+ #endif
+ goto push_data;
+
+// PUSH/POP
+ case 0xF5: // PUSH AF
+ data = r.b.a * 0x100u + flags;
+ goto push_data;
+
+ case 0xC5: // PUSH BC
+ case 0xD5: // PUSH DE
+ case 0xE5: // PUSH HL
+ data = R16( opcode, 4, 0xC5 );
+ push_data:
+ sp = WORD( sp - 2 );
+ WRITE_WORD( sp, data );
+ goto loop;
+
+ case 0xF1: // POP AF
+ flags = READ_MEM( sp );
+ r.b.a = READ_MEM( (sp + 1) );
+ sp = WORD( sp + 2 );
+ goto loop;
+
+ case 0xC1: // POP BC
+ case 0xD1: // POP DE
+ case 0xE1: // POP HL
+ R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
+ sp = WORD( sp + 2 );
+ goto loop;
+
+// ADC/ADD/SBC/SUB
+ case 0x96: // SUB (HL)
+ case 0x86: // ADD (HL)
+ flags &= ~C01;
+ case 0x9E: // SBC (HL)
+ case 0x8E: // ADC (HL)
+ data = READ_MEM( r.w.hl );
+ goto adc_data;
+
+ case 0xD6: // SUB A,imm
+ case 0xC6: // ADD imm
+ flags &= ~C01;
+ case 0xDE: // SBC A,imm
+ case 0xCE: // ADC imm
+ pc++;
+ goto adc_data;
+
+ CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
+ CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
+ flags &= ~C01;
+ CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
+ CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
+ data = R8( opcode & 7, 0 );
+ adc_data: {
+ int result = data + (flags & C01);
+ data ^= r.b.a;
+ flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
+ if ( flags )
+ result = -result;
+ result += r.b.a;
+ data ^= result;
+ flags +=(data & H10) +
+ ((data + 0x80) >> 6 & V04) +
+ SZ28C( result & 0x1FF );
+ r.b.a = result;
+ goto loop;
+ }
+
+// CP
+ case 0xBE: // CP (HL)
+ data = READ_MEM( r.w.hl );
+ goto cp_data;
+
+ case 0xFE: // CP imm
+ pc++;
+ goto cp_data;
+
+ CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
+ data = R8( opcode, 0xB8 );
+ cp_data: {
+ int result = r.b.a - data;
+ flags = N02 + (data & (F20 | F08)) + (result >> 8 & C01);
+ data ^= r.b.a;
+ flags +=(((result ^ r.b.a) & data) >> 5 & V04) +
+ (((data & H10) ^ result) & (S80 | H10));
+ if ( BYTE( result ) )
+ goto loop;
+ flags += Z40;
+ goto loop;
+ }
+
+// ADD HL,r.w
+
+ case 0x39: // ADD HL,SP
+ data = sp;
+ goto add_hl_data;
+
+ case 0x09: // ADD HL,BC
+ case 0x19: // ADD HL,DE
+ case 0x29: // ADD HL,HL
+ data = R16( opcode, 4, 0x09 );
+ add_hl_data: {
+ int sum = r.w.hl + data;
+ data ^= r.w.hl;
+ r.w.hl = sum;
+ flags = (flags & (S80 | Z40 | V04)) +
+ (sum >> 16) +
+ (sum >> 8 & (F20 | F08)) +
+ ((data ^ sum) >> 8 & H10);
+ goto loop;
+ }
+
+ case 0x27:{// DAA
+ int a = r.b.a;
+ if ( a > 0x99 )
+ flags |= C01;
+
+ int adjust = 0x60 * (flags & C01);
+
+ if ( flags & H10 || (a & 0x0F) > 9 )
+ adjust += 0x06;
+
+ if ( flags & N02 )
+ adjust = -adjust;
+ a += adjust;
+
+ flags = (flags & (C01 | N02)) +
+ ((r.b.a ^ a) & H10) +
+ SZ28P( BYTE( a ) );
+ r.b.a = a;
+ goto loop;
+ }
+
+// INC/DEC
+ case 0x34: // INC (HL)
+ data = READ_MEM( r.w.hl ) + 1;
+ WRITE_MEM( r.w.hl, data );
+ goto inc_set_flags;
+
+ CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
+ data = ++R8( opcode >> 3, 0 );
+ inc_set_flags:
+ flags = (flags & C01) +
+ (((data & 0x0F) - 1) & H10) +
+ SZ28( BYTE( data ) );
+ if ( data != 0x80 )
+ goto loop;
+ flags += V04;
+ goto loop;
+
+ case 0x35: // DEC (HL)
+ data = READ_MEM( r.w.hl ) - 1;
+ WRITE_MEM( r.w.hl, data );
+ goto dec_set_flags;
+
+ CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
+ data = --R8( opcode >> 3, 0 );
+ dec_set_flags:
+ flags = (flags & C01) + N02 +
+ (((data & 0x0F) + 1) & H10) +
+ SZ28( BYTE( data ) );
+ if ( data != 0x7F )
+ goto loop;
+ flags += V04;
+ goto loop;
+
+ case 0x03: // INC BC
+ case 0x13: // INC DE
+ case 0x23: // INC HL
+ R16( opcode, 4, 0x03 )++;
+ goto loop;
+
+ case 0x33: // INC SP
+ sp = WORD( sp + 1 );
+ goto loop;
+
+ case 0x0B: // DEC BC
+ case 0x1B: // DEC DE
+ case 0x2B: // DEC HL
+ R16( opcode, 4, 0x0B )--;
+ goto loop;
+
+ case 0x3B: // DEC SP
+ sp = WORD( sp - 1 );
+ goto loop;
+
+// AND
+ case 0xA6: // AND (HL)
+ data = READ_MEM( r.w.hl );
+ goto and_data;
+
+ case 0xE6: // AND imm
+ pc++;
+ goto and_data;
+
+ CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
+ data = R8( opcode, 0xA0 );
+ and_data:
+ r.b.a &= data;
+ flags = SZ28P( r.b.a ) + H10;
+ goto loop;
+
+// OR
+ case 0xB6: // OR (HL)
+ data = READ_MEM( r.w.hl );
+ goto or_data;
+
+ case 0xF6: // OR imm
+ pc++;
+ goto or_data;
+
+ CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
+ data = R8( opcode, 0xB0 );
+ or_data:
+ r.b.a |= data;
+ flags = SZ28P( r.b.a );
+ goto loop;
+
+// XOR
+ case 0xAE: // XOR (HL)
+ data = READ_MEM( r.w.hl );
+ goto xor_data;
+
+ case 0xEE: // XOR imm
+ pc++;
+ goto xor_data;
+
+ CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
+ data = R8( opcode, 0xA8 );
+ xor_data:
+ r.b.a ^= data;
+ flags = SZ28P( r.b.a );
+ goto loop;
+
+// LD
+ CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
+ WRITE_MEM( r.w.hl, R8( opcode, 0x70 ) );
+ goto loop;
+
+ CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
+ CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
+ CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
+ CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
+ CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
+ CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
+ CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
+ R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
+ goto loop;
+
+ CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
+ R8( opcode >> 3, 0 ) = data;
+ pc++;
+ goto loop;
+
+ case 0x36: // LD (HL),imm
+ pc++;
+ WRITE_MEM( r.w.hl, data );
+ goto loop;
+
+ CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
+ R8( opcode >> 3, 8 ) = READ_MEM( r.w.hl );
+ goto loop;
+
+ case 0x01: // LD r.w,imm
+ case 0x11:
+ case 0x21:
+ R16( opcode, 4, 0x01 ) = GET_ADDR();
+ pc += 2;
+ goto loop;
+
+ case 0x31: // LD sp,imm
+ sp = GET_ADDR();
+ pc += 2;
+ goto loop;
+
+ case 0x2A:{// LD HL,(addr)
+ int addr = GET_ADDR();
+ pc += 2;
+ r.w.hl = READ_WORD( addr );
+ goto loop;
+ }
+
+ case 0x32:{// LD (addr),A
+ int addr = GET_ADDR();
+ pc += 2;
+ WRITE_MEM( addr, r.b.a );
+ goto loop;
+ }
+
+ case 0x22:{// LD (addr),HL
+ int addr = GET_ADDR();
+ pc += 2;
+ WRITE_WORD( addr, r.w.hl );
+ goto loop;
+ }
+
+ case 0x02: // LD (BC),A
+ case 0x12: // LD (DE),A
+ WRITE_MEM( R16( opcode, 4, 0x02 ), r.b.a );
+ goto loop;
+
+ case 0x0A: // LD A,(BC)
+ case 0x1A: // LD A,(DE)
+ r.b.a = READ_MEM( R16( opcode, 4, 0x0A ) );
+ goto loop;
+
+ case 0xF9: // LD SP,HL
+ sp = r.w.hl;
+ goto loop;
+
+// Rotate
+
+ case 0x07:{// RLCA
+ int temp = r.b.a;
+ temp = (temp << 1) + (temp >> 7);
+ flags = (flags & (S80 | Z40 | P04)) +
+ (temp & (F20 | F08 | C01));
+ r.b.a = temp;
+ goto loop;
+ }
+
+ case 0x0F:{// RRCA
+ int temp = r.b.a;
+ flags = (flags & (S80 | Z40 | P04)) +
+ (temp & C01);
+ temp = (temp << 7) + (temp >> 1);
+ flags += temp & (F20 | F08);
+ r.b.a = temp;
+ goto loop;
+ }
+
+ case 0x17:{// RLA
+ int temp = (r.b.a << 1) + (flags & C01);
+ flags = (flags & (S80 | Z40 | P04)) +
+ (temp & (F20 | F08)) +
+ (temp >> 8);
+ r.b.a = temp;
+ goto loop;
+ }
+
+ case 0x1F:{// RRA
+ int temp = (flags << 7) + (r.b.a >> 1);
+ flags = (flags & (S80 | Z40 | P04)) +
+ (temp & (F20 | F08)) +
+ (r.b.a & C01);
+ r.b.a = temp;
+ goto loop;
+ }
+
+// Misc
+ case 0x2F:{// CPL
+ int temp = ~r.b.a;
+ flags = (flags & (S80 | Z40 | P04 | C01)) +
+ (temp & (F20 | F08)) +
+ (H10 | N02);
+ r.b.a = temp;
+ goto loop;
+ }
+
+ case 0x3F:{// CCF
+ flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) +
+ (flags << 4 & H10) +
+ (r.b.a & (F20 | F08));
+ goto loop;
+ }
+
+ case 0x37: // SCF
+ flags = ((flags & (S80 | Z40 | P04)) | C01) +
+ (r.b.a & (F20 | F08));
+ goto loop;
+
+ case 0xDB: // IN A,(imm)
+ pc++;
+ r.b.a = IN_PORT( (data + r.b.a * 0x100) );
+ goto loop;
+
+ case 0xE3:{// EX (SP),HL
+ int temp = READ_WORD( sp );
+ WRITE_WORD( sp, r.w.hl );
+ r.w.hl = temp;
+ goto loop;
+ }
+
+ case 0xEB: // EX DE,HL
+ EX( r.w.hl, r.w.de );
+ goto loop;
+
+ case 0xD9: // EXX DE,HL
+ EXX( w.bc );
+ EXX( w.de );
+ EXX( w.hl );
+ goto loop;
+
+ case 0xF3: // DI
+ R.iff1 = 0;
+ R.iff2 = 0;
+ goto loop;
+
+ case 0xFB: // EI
+ R.iff1 = 1;
+ R.iff2 = 1;
+ // TODO: delayed effect
+ goto loop;
+
+ case 0x76: // HALT
+ goto halt;
+
+//////////////////////////////////////// CB prefix
+ {
+ case 0xCB:
+ pc++;
+ switch ( data )
+ {
+
+ // Rotate left
+
+ #define RLC( read, write ) {\
+ int result = read;\
+ result = BYTE( result << 1 ) + (result >> 7);\
+ flags = SZ28P( result ) + (result & C01);\
+ write;\
+ goto loop;\
+ }
+
+ case 0x06: // RLC (HL)
+ s_time += 7;
+ data = r.w.hl;
+ rlc_data_addr:
+ RLC( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
+ byte* reg = &R8( data, 0 );
+ RLC( *reg, *reg = result )
+ }
+
+ #define RL( read, write ) {\
+ int result = (read << 1) + (flags & C01);\
+ flags = SZ28PC( result );\
+ write;\
+ goto loop;\
+ }
+
+ case 0x16: // RL (HL)
+ s_time += 7;
+ data = r.w.hl;
+ rl_data_addr:
+ RL( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
+ byte* reg = &R8( data, 0x10 );
+ RL( *reg, *reg = result )
+ }
+
+ #define SLA( read, low_bit, write ) {\
+ int result = (read << 1) + low_bit;\
+ flags = SZ28PC( result );\
+ write;\
+ goto loop;\
+ }
+
+ case 0x26: // SLA (HL)
+ s_time += 7;
+ data = r.w.hl;
+ sla_data_addr:
+ SLA( READ_MEM( data ), 0, WRITE_MEM( data, result ) )
+
+ CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
+ byte* reg = &R8( data, 0x20 );
+ SLA( *reg, 0, *reg = result )
+ }
+
+ case 0x36: // SLL (HL)
+ s_time += 7;
+ data = r.w.hl;
+ sll_data_addr:
+ SLA( READ_MEM( data ), 1, WRITE_MEM( data, result ) )
+
+ CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
+ byte* reg = &R8( data, 0x30 );
+ SLA( *reg, 1, *reg = result )
+ }
+
+ // Rotate right
+
+ #define RRC( read, write ) {\
+ int result = read;\
+ flags = result & C01;\
+ result = BYTE( result << 7 ) + (result >> 1);\
+ flags += SZ28P( result );\
+ write;\
+ goto loop;\
+ }
+
+ case 0x0E: // RRC (HL)
+ s_time += 7;
+ data = r.w.hl;
+ rrc_data_addr:
+ RRC( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
+ byte* reg = &R8( data, 0x08 );
+ RRC( *reg, *reg = result )
+ }
+
+ #define RR( read, write ) {\
+ int result = read;\
+ int temp = result & C01;\
+ result = BYTE( flags << 7 ) + (result >> 1);\
+ flags = SZ28P( result ) + temp;\
+ write;\
+ goto loop;\
+ }
+
+ case 0x1E: // RR (HL)
+ s_time += 7;
+ data = r.w.hl;
+ rr_data_addr:
+ RR( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
+ byte* reg = &R8( data, 0x18 );
+ RR( *reg, *reg = result )
+ }
+
+ #define SRA( read, write ) {\
+ int result = read;\
+ flags = result & C01;\
+ result = (result & 0x80) + (result >> 1);\
+ flags += SZ28P( result );\
+ write;\
+ goto loop;\
+ }
+
+ case 0x2E: // SRA (HL)
+ data = r.w.hl;
+ s_time += 7;
+ sra_data_addr:
+ SRA( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
+ byte* reg = &R8( data, 0x28 );
+ SRA( *reg, *reg = result )
+ }
+
+ #define SRL( read, write ) {\
+ int result = read;\
+ flags = result & C01;\
+ result >>= 1;\
+ flags += SZ28P( result );\
+ write;\
+ goto loop;\
+ }
+
+ case 0x3E: // SRL (HL)
+ s_time += 7;
+ data = r.w.hl;
+ srl_data_addr:
+ SRL( READ_MEM( data ), WRITE_MEM( data, result ) )
+
+ CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
+ byte* reg = &R8( data, 0x38 );
+ SRL( *reg, *reg = result )
+ }
+
+ // BIT
+ {
+ int temp;
+ CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
+ s_time += 4;
+ temp = READ_MEM( r.w.hl );
+ flags &= C01;
+ goto bit_temp;
+ CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
+ CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
+ CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
+ CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
+ CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
+ CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
+ CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
+ CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
+ temp = R8( data & 7, 0 );
+ flags = (flags & C01) + (temp & (F20 | F08));
+ bit_temp:
+ temp = temp & (1 << (data >> 3 & 7));
+ flags += (temp & S80) + H10;
+ flags += (unsigned) --temp >> 8 & (Z40 | P04);
+ goto loop;
+ }
+
+ // SET/RES
+ CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
+ CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
+ s_time += 7;
+ int temp = READ_MEM( r.w.hl );
+ int bit = 1 << (data >> 3 & 7);
+ temp |= bit; // SET
+ if ( !(data & 0x40) )
+ temp ^= bit; // RES
+ WRITE_MEM( r.w.hl, temp );
+ goto loop;
+ }
+
+ CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
+ CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
+ CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
+ CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
+ CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
+ CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
+ CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
+ CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
+ R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
+ goto loop;
+
+ CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
+ CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
+ CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
+ CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
+ CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
+ CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
+ CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
+ CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
+ R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
+ goto loop;
+ }
+ assert( false );
+ }
+
+#undef GET_ADDR
+#define GET_ADDR() GET_LE16( &INSTR( 1, pc ) )
+
+//////////////////////////////////////// ED prefix
+ {
+ case 0xED:
+ pc++;
+ s_time += (clock_table + 256) [data] >> 4;
+ switch ( data )
+ {
+ {
+ int temp;
+ case 0x72: // SBC HL,SP
+ case 0x7A: // ADC HL,SP
+ temp = sp;
+ if ( 0 )
+ case 0x42: // SBC HL,BC
+ case 0x52: // SBC HL,DE
+ case 0x62: // SBC HL,HL
+ case 0x4A: // ADC HL,BC
+ case 0x5A: // ADC HL,DE
+ case 0x6A: // ADC HL,HL
+ temp = R16( data >> 3 & 6, 1, 0 );
+ int sum = temp + (flags & C01);
+ flags = ~data >> 2 & N02;
+ if ( flags )
+ sum = -sum;
+ sum += r.w.hl;
+ temp ^= r.w.hl;
+ temp ^= sum;
+ flags +=(sum >> 16 & C01) +
+ (temp >> 8 & H10) +
+ (sum >> 8 & (S80 | F20 | F08)) +
+ ((temp + 0x8000) >> 14 & V04);
+ r.w.hl = sum;
+ if ( WORD( sum ) )
+ goto loop;
+ flags += Z40;
+ goto loop;
+ }
+
+ CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
+ int temp = IN_PORT( r.w.bc );
+ R8( data >> 3, 8 ) = temp;
+ flags = (flags & C01) + SZ28P( temp );
+ goto loop;
+ }
+
+ case 0x71: // OUT (C),0
+ r.b.flags = 0;
+ CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
+ OUT_PORT( r.w.bc, R8( data >> 3, 8 ) );
+ goto loop;
+
+ {
+ int temp;
+ case 0x73: // LD (ADDR),SP
+ temp = sp;
+ if ( 0 )
+ case 0x43: // LD (ADDR),BC
+ case 0x53: // LD (ADDR),DE
+ temp = R16( data, 4, 0x43 );
+ int addr = GET_ADDR();
+ pc += 2;
+ WRITE_WORD( addr, temp );
+ goto loop;
+ }
+
+ case 0x4B: // LD BC,(ADDR)
+ case 0x5B:{// LD DE,(ADDR)
+ int addr = GET_ADDR();
+ pc += 2;
+ R16( data, 4, 0x4B ) = READ_WORD( addr );
+ goto loop;
+ }
+
+ case 0x7B:{// LD SP,(ADDR)
+ int addr = GET_ADDR();
+ pc += 2;
+ sp = READ_WORD( addr );
+ goto loop;
+ }
+
+ case 0x67:{// RRD
+ int temp = READ_MEM( r.w.hl );
+ WRITE_MEM( r.w.hl, ((r.b.a << 4) + (temp >> 4)) );
+ temp = (r.b.a & 0xF0) + (temp & 0x0F);
+ flags = (flags & C01) + SZ28P( temp );
+ r.b.a = temp;
+ goto loop;
+ }
+
+ case 0x6F:{// RLD
+ int temp = READ_MEM( r.w.hl );
+ WRITE_MEM( r.w.hl, ((temp << 4) + (r.b.a & 0x0F)) );
+ temp = (r.b.a & 0xF0) + (temp >> 4);
+ flags = (flags & C01) + SZ28P( temp );
+ r.b.a = temp;
+ goto loop;
+ }
+
+ CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
+ opcode = 0x10; // flag to do SBC instead of ADC
+ flags &= ~C01;
+ data = r.b.a;
+ r.b.a = 0;
+ goto adc_data;
+
+ {
+ int inc;
+ case 0xA9: // CPD
+ case 0xB9: // CPDR
+ inc = -1;
+ if ( 0 )
+ case 0xA1: // CPI
+ case 0xB1: // CPIR
+ inc = +1;
+ int addr = r.w.hl;
+ r.w.hl = addr + inc;
+ int temp = READ_MEM( addr );
+
+ int result = r.b.a - temp;
+ flags = (flags & C01) + N02 +
+ ((((temp ^ r.b.a) & H10) ^ result) & (S80 | H10));
+
+ if ( !BYTE( result ) )
+ flags += Z40;
+ result -= (flags & H10) >> 4;
+ flags += result & F08;
+ flags += result << 4 & F20;
+ if ( !--r.w.bc )
+ goto loop;
+
+ flags += V04;
+ if ( flags & Z40 || data < 0xB0 )
+ goto loop;
+
+ pc -= 2;
+ s_time += 5;
+ goto loop;
+ }
+
+ {
+ int inc;
+ case 0xA8: // LDD
+ case 0xB8: // LDDR
+ inc = -1;
+ if ( 0 )
+ case 0xA0: // LDI
+ case 0xB0: // LDIR
+ inc = +1;
+ int addr = r.w.hl;
+ r.w.hl = addr + inc;
+ int temp = READ_MEM( addr );
+
+ addr = r.w.de;
+ r.w.de = addr + inc;
+ WRITE_MEM( addr, temp );
+
+ temp += r.b.a;
+ flags = (flags & (S80 | Z40 | C01)) +
+ (temp & F08) + (temp << 4 & F20);
+ if ( !--r.w.bc )
+ goto loop;
+
+ flags += V04;
+ if ( data < 0xB0 )
+ goto loop;
+
+ pc -= 2;
+ s_time += 5;
+ goto loop;
+ }
+
+ {
+ int inc;
+ case 0xAB: // OUTD
+ case 0xBB: // OTDR
+ inc = -1;
+ if ( 0 )
+ case 0xA3: // OUTI
+ case 0xB3: // OTIR
+ inc = +1;
+ int addr = r.w.hl;
+ r.w.hl = addr + inc;
+ int temp = READ_MEM( addr );
+
+ int b = --r.b.b;
+ flags = (temp >> 6 & N02) + SZ28( b );
+ if ( b && data >= 0xB0 )
+ {
+ pc -= 2;
+ s_time += 5;
+ }
+
+ OUT_PORT( r.w.bc, temp );
+ goto loop;
+ }
+
+ {
+ int inc;
+ case 0xAA: // IND
+ case 0xBA: // INDR
+ inc = -1;
+ if ( 0 )
+ case 0xA2: // INI
+ case 0xB2: // INIR
+ inc = +1;
+
+ int addr = r.w.hl;
+ r.w.hl = addr + inc;
+
+ int temp = IN_PORT( r.w.bc );
+
+ int b = --r.b.b;
+ flags = (temp >> 6 & N02) + SZ28( b );
+ if ( b && data >= 0xB0 )
+ {
+ pc -= 2;
+ s_time += 5;
+ }
+
+ WRITE_MEM( addr, temp );
+ goto loop;
+ }
+
+ case 0x47: // LD I,A
+ R.i = r.b.a;
+ goto loop;
+
+ case 0x4F: // LD R,A
+ SET_R( r.b.a );
+ dprintf( "LD R,A not supported\n" );
+ warning = true;
+ goto loop;
+
+ case 0x57: // LD A,I
+ r.b.a = R.i;
+ goto ld_ai_common;
+
+ case 0x5F: // LD A,R
+ r.b.a = GET_R();
+ dprintf( "LD A,R not supported\n" );
+ warning = true;
+ ld_ai_common:
+ flags = (flags & C01) + SZ28( r.b.a ) + (R.iff2 << 2 & V04);
+ goto loop;
+
+ CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
+ R.iff1 = R.iff2;
+ goto ret_taken;
+
+ case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
+ R.im = 0;
+ goto loop;
+
+ case 0x56: case 0x76: // IM 1
+ R.im = 1;
+ goto loop;
+
+ case 0x5E: case 0x7E: // IM 2
+ R.im = 2;
+ goto loop;
+
+ default:
+ dprintf( "Opcode $ED $%02X not supported\n", data );
+ warning = true;
+ goto loop;
+ }
+ assert( false );
+ }
+
+//////////////////////////////////////// DD/FD prefix
+ {
+ int ixy;
+ case 0xDD:
+ ixy = ix;
+ goto ix_prefix;
+ case 0xFD:
+ ixy = iy;
+ ix_prefix:
+ pc++;
+ int data2 = READ_CODE( pc );
+ s_time += (clock_table + 256) [data] & 0x0F;
+ switch ( data )
+ {
+ // TODO: more efficient way of avoid negative address
+ // TODO: avoid using this as argument to READ_MEM() since it is evaluated twice
+ #define IXY_DISP( ixy, disp ) WORD( (ixy ) + (disp))
+
+ #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
+
+ // ADD/ADC/SUB/SBC
+
+ case 0x96: // SUB (IXY+disp)
+ case 0x86: // ADD (IXY+disp)
+ flags &= ~C01;
+ case 0x9E: // SBC (IXY+disp)
+ case 0x8E: // ADC (IXY+disp)
+ pc++;
+ opcode = data;
+ data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto adc_data;
+
+ case 0x94: // SUB HXY
+ case 0x84: // ADD HXY
+ flags &= ~C01;
+ case 0x9C: // SBC HXY
+ case 0x8C: // ADC HXY
+ opcode = data;
+ data = ixy >> 8;
+ goto adc_data;
+
+ case 0x95: // SUB LXY
+ case 0x85: // ADD LXY
+ flags &= ~C01;
+ case 0x9D: // SBC LXY
+ case 0x8D: // ADC LXY
+ opcode = data;
+ data = BYTE( ixy );
+ goto adc_data;
+
+ {
+ int temp;
+ case 0x39: // ADD IXY,SP
+ temp = sp;
+ goto add_ixy_data;
+
+ case 0x29: // ADD IXY,HL
+ temp = ixy;
+ goto add_ixy_data;
+
+ case 0x09: // ADD IXY,BC
+ case 0x19: // ADD IXY,DE
+ temp = R16( data, 4, 0x09 );
+ add_ixy_data: {
+ int sum = ixy + temp;
+ temp ^= ixy;
+ ixy = WORD( sum );
+ flags = (flags & (S80 | Z40 | V04)) +
+ (sum >> 16) +
+ (sum >> 8 & (F20 | F08)) +
+ ((temp ^ sum) >> 8 & H10);
+ goto set_ixy;
+ }
+ }
+
+ // AND
+ case 0xA6: // AND (IXY+disp)
+ pc++;
+ data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto and_data;
+
+ case 0xA4: // AND HXY
+ data = ixy >> 8;
+ goto and_data;
+
+ case 0xA5: // AND LXY
+ data = BYTE( ixy );
+ goto and_data;
+
+ // OR
+ case 0xB6: // OR (IXY+disp)
+ pc++;
+ data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto or_data;
+
+ case 0xB4: // OR HXY
+ data = ixy >> 8;
+ goto or_data;
+
+ case 0xB5: // OR LXY
+ data = BYTE( ixy );
+ goto or_data;
+
+ // XOR
+ case 0xAE: // XOR (IXY+disp)
+ pc++;
+ data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto xor_data;
+
+ case 0xAC: // XOR HXY
+ data = ixy >> 8;
+ goto xor_data;
+
+ case 0xAD: // XOR LXY
+ data = BYTE( ixy );
+ goto xor_data;
+
+ // CP
+ case 0xBE: // CP (IXY+disp)
+ pc++;
+ data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto cp_data;
+
+ case 0xBC: // CP HXY
+ data = ixy >> 8;
+ goto cp_data;
+
+ case 0xBD: // CP LXY
+ data = BYTE( ixy );
+ goto cp_data;
+
+ // LD
+ CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
+ data = R8( data, 0x70 );
+ if ( 0 )
+ case 0x36: // LD (IXY+disp),imm
+ pc++, data = READ_CODE( pc );
+ pc++;
+ WRITE_MEM( IXY_DISP( ixy, SBYTE( data2 ) ), data );
+ goto loop;
+
+ CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
+ R8( data >> 3, 8 ) = ixy >> 8;
+ goto loop;
+
+ case 0x64: // LD HXY,HXY
+ case 0x6D: // LD LXY,LXY
+ goto loop;
+
+ CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
+ R8( data >> 3, 8 ) = ixy;
+ goto loop;
+
+ CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
+ pc++;
+ R8( data >> 3, 8 ) = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
+ goto loop;
+
+ case 0x26: // LD HXY,imm
+ pc++;
+ goto ld_hxy_data;
+
+ case 0x65: // LD HXY,LXY
+ data2 = BYTE( ixy );
+ goto ld_hxy_data;
+
+ CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
+ data2 = R8( data, 0x60 );
+ ld_hxy_data:
+ ixy = BYTE( ixy ) + (data2 << 8);
+ goto set_ixy;
+
+ case 0x2E: // LD LXY,imm
+ pc++;
+ goto ld_lxy_data;
+
+ case 0x6C: // LD LXY,HXY
+ data2 = ixy >> 8;
+ goto ld_lxy_data;
+
+ CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
+ data2 = R8( data, 0x68 );
+ ld_lxy_data:
+ ixy = (ixy & 0xFF00) + data2;
+ set_ixy:
+ if ( opcode == 0xDD )
+ {
+ ix = ixy;
+ goto loop;
+ }
+ iy = ixy;
+ goto loop;
+
+ case 0xF9: // LD SP,IXY
+ sp = ixy;
+ goto loop;
+
+ case 0x22:{// LD (ADDR),IXY
+ int addr = GET_ADDR();
+ pc += 2;
+ WRITE_WORD( addr, ixy );
+ goto loop;
+ }
+
+ case 0x21: // LD IXY,imm
+ ixy = GET_ADDR();
+ pc += 2;
+ goto set_ixy;
+
+ case 0x2A:{// LD IXY,(addr)
+ int addr = GET_ADDR();
+ ixy = READ_WORD( addr );
+ pc += 2;
+ goto set_ixy;
+ }
+
+ // DD/FD CB prefix
+ case 0xCB: {
+ data = IXY_DISP( ixy, SBYTE( data2 ) );
+ pc++;
+ data2 = READ_CODE( pc );
+ pc++;
+ switch ( data2 )
+ {
+ case 0x06: goto rlc_data_addr; // RLC (IXY)
+ case 0x16: goto rl_data_addr; // RL (IXY)
+ case 0x26: goto sla_data_addr; // SLA (IXY)
+ case 0x36: goto sll_data_addr; // SLL (IXY)
+ case 0x0E: goto rrc_data_addr; // RRC (IXY)
+ case 0x1E: goto rr_data_addr; // RR (IXY)
+ case 0x2E: goto sra_data_addr; // SRA (IXY)
+ case 0x3E: goto srl_data_addr; // SRL (IXY)
+
+ CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
+ int temp = READ_MEM( data );
+ temp = temp & (1 << (data2 >> 3 & 7));
+ flags = (flags & C01) + H10 + (temp & S80);
+ flags += (unsigned) --temp >> 8 & (Z40 | P04);
+ goto loop;
+ }
+
+ CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
+ CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
+ int temp = READ_MEM( data );
+ int bit = 1 << (data2 >> 3 & 7);
+ temp |= bit; // SET
+ if ( !(data2 & 0x40) )
+ temp ^= bit; // RES
+ WRITE_MEM( data, temp );
+ goto loop;
+ }
+
+ default:
+ dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
+ warning = true;
+ goto loop;
+ }
+ assert( false );
+ }
+
+ // INC/DEC
+ case 0x23: // INC IXY
+ ixy = WORD( ixy + 1 );
+ goto set_ixy;
+
+ case 0x2B: // DEC IXY
+ ixy = WORD( ixy - 1 );
+ goto set_ixy;
+
+ case 0x34: // INC (IXY+disp)
+ ixy = IXY_DISP( ixy, SBYTE( data2 ) );
+ pc++;
+ data = READ_MEM( ixy ) + 1;
+ WRITE_MEM( ixy, data );
+ goto inc_set_flags;
+
+ case 0x35: // DEC (IXY+disp)
+ ixy = IXY_DISP( ixy, SBYTE( data2 ) );
+ pc++;
+ data = READ_MEM( ixy ) - 1;
+ WRITE_MEM( ixy, data );
+ goto dec_set_flags;
+
+ case 0x24: // INC HXY
+ ixy = WORD( ixy + 0x100 );
+ data = ixy >> 8;
+ goto inc_xy_common;
+
+ case 0x2C: // INC LXY
+ data = BYTE( ixy + 1 );
+ ixy = (ixy & 0xFF00) + data;
+ inc_xy_common:
+ if ( opcode == 0xDD )
+ {
+ ix = ixy;
+ goto inc_set_flags;
+ }
+ iy = ixy;
+ goto inc_set_flags;
+
+ case 0x25: // DEC HXY
+ ixy = WORD( ixy - 0x100 );
+ data = ixy >> 8;
+ goto dec_xy_common;
+
+ case 0x2D: // DEC LXY
+ data = BYTE( ixy - 1 );
+ ixy = (ixy & 0xFF00) + data;
+ dec_xy_common:
+ if ( opcode == 0xDD )
+ {
+ ix = ixy;
+ goto dec_set_flags;
+ }
+ iy = ixy;
+ goto dec_set_flags;
+
+ // PUSH/POP
+ case 0xE5: // PUSH IXY
+ data = ixy;
+ goto push_data;
+
+ case 0xE1:{// POP IXY
+ ixy = READ_WORD( sp );
+ sp = WORD( sp + 2 );
+ goto set_ixy;
+ }
+
+ // Misc
+
+ case 0xE9: // JP (IXY)
+ pc = ixy;
+ goto loop;
+
+ case 0xE3:{// EX (SP),IXY
+ int temp = READ_WORD( sp );
+ WRITE_WORD( sp, ixy );
+ ixy = temp;
+ goto set_ixy;
+ }
+
+ default:
+ dprintf( "Unnecessary DD/FD prefix encountered\n" );
+ warning = true;
+ pc--;
+ goto loop;
+ }
+ assert( false );
+ }
+
+ }
+ dprintf( "Unhandled main opcode: $%02X\n", opcode );
+ assert( false );
+
+#ifdef IDLE_ADDR
+hit_idle_addr:
+ s_time -= 11;
+ goto out_of_time;
+#endif
+halt:
+ s_time &= 3; // increment by multiple of 4
+out_of_time:
+ pc--;
+
+ r.b.flags = flags;
+ R.ix = ix;
+ R.iy = iy;
+ R.sp = sp;
+ R.pc = pc;
+ R.b = r.b;
+
+ cpu->cpu_state_.base = s.base;
+ cpu->cpu_state_.time = s_time;
+ cpu->cpu_state = &cpu->cpu_state_;
+}
diff --git a/apps/lang/arabic.lang b/apps/lang/arabic.lang
index 12e84c819b..b9450c1710 100644
--- a/apps/lang/arabic.lang
+++ b/apps/lang/arabic.lang
@@ -7010,17 +7010,17 @@
radio: "قائمة اذاعة اف ام"
</voice>
</phrase>
-<phrase>
- id: LANG_FILESIZE
- desc: in record timesplit options and in track information viewer
- user: core
- <source>
- *: "Filesize"
- </source>
- <dest>
- *: "حجم الملف"
- </dest>
- <voice>
- *: "حجم الملف"
- </voice>
+<phrase>
+ id: LANG_FILESIZE
+ desc: in record timesplit options and in track information viewer
+ user: core
+ <source>
+ *: "Filesize"
+ </source>
+ <dest>
+ *: "حجم الملف"
+ </dest>
+ <voice>
+ *: "حجم الملف"
+ </voice>
</phrase>
diff --git a/apps/lang/latviesu.lang b/apps/lang/latviesu.lang
index 0fb0afa417..866820d4f3 100644
--- a/apps/lang/latviesu.lang
+++ b/apps/lang/latviesu.lang
@@ -1,12750 +1,12750 @@
-# __________ __ ___.
-# Open \______ \ ____ ____ | | _\_ |__ _______ ___
-# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
-# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
-# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
-# \/ \/ \/ \/ \/
-# $Id$
-#
-# 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-#
-# Latvian language file, translated by Mārtiņš Šimis jeb msh
-
-<phrase>
- id: LANG_SET_BOOL_YES
- desc: bool true representation
- user: core
- <source>
- *: "Yes"
- </source>
- <dest>
- *: "Jā"
- </dest>
- <voice>
- *: "jaa"
- </voice>
-</phrase>
-<phrase>
- id: LANG_SET_BOOL_NO
- desc: bool false representation
- user: core
- <source>
- *: "No"
- </source>
- <dest>
- *: "Nē"
- </dest>
- <voice>
- *: "nee"
- </voice>
-</phrase>
-<phrase>
- id: LANG_ON
- desc: Used in a lot of places
- user: core
- <source>
- *: "On"
- </source>
- <dest>
- *: "Ieslēgts"
- </dest>
- <voice>
- *: "iesleegts"
- </voice>
-</phrase>
-<phrase>
- id: LANG_OFF
- desc: Used in a lot of places
- user: core
- <source>
- *: "Off"
- </source>
- <dest>
- *: "Izslēgts"
- </dest>
- <voice>
- *: "izsleegts"
- </voice>
-</phrase>
-<phrase>
- id: LANG_ASK
- desc: in settings_menu
- user: core
- <source>
- *: "Ask"
- </source>
- <dest>
- *: "Prasīt"
- </dest>
- <voice>
- *: "prasiit"
- </voice>
-</phrase>
-<phrase>
- id: LANG_ALWAYS
- desc: used in various places
- user: core
- <source>
- *: "Always"
- </source>
- <dest>
- *: "Vienmēr"
- </dest>
- <voice>
- *: "vienmeer"
- </voice>
-</phrase>
-<phrase>
- id: LANG_NORMAL
- desc: in settings_menu
- user: core
- <source>
- *: "Normal"
- </source>
- <dest>
- *: "Normāls"
- </dest>
- <voice>
- *: "normaals"
- </voice>
-</phrase>
-<phrase>
- id: LANG_GAIN
- desc: Generic string for gain used in EQ menu and recording screen
- user: core
- <source>
- *: "Gain"
- </source>
- <dest>
- *: "Pastiprinājums"
- </dest>
- <voice>
- *: "pastiprinaajums"
- </voice>
-</phrase>
-<phrase>
- id: LANG_WAIT
- desc: general please wait splash
- user: core
- <source>
- *: "Loading..."
- </source>
- <dest>
- *: "Ielādē..."
- </dest>
- <voice>
- *: "notiek ielaade"
- </voice>
-</phrase>
-<phrase>
- id: LANG_LOADING_PERCENT
- desc: splash number of percents loaded
- user: core
- <source>
- *: "Loading... %d%% done (%s)"
- </source>
- <dest>
- *: "ielaade... %d%% gatavs (%s)"
- </dest>
- <voice>
- *: ""
- </voice>
-</phrase>
-<phrase>
- id: LANG_SCANNING_DISK
- desc: when booting up and rebuilding the cache and calculating free space
- user: core
- <source>
- *: "Scanning disk..."
- </source>
- <dest>
- *: "Skanē atmiņu..."
- </dest>
- <voice>
- *: "skanee atminju"
- </voice>
-</phrase>
-<phrase>
- id: LANG_SHUTTINGDOWN
- desc: in main menu
- user: core
- <source>
- *: "Shutting down..."
- </source>
- <dest>
- *: "Izslēdzas..."
- </dest>
- <voice>
- *: "izsleedzas"
- </voice>
-</phrase>
-<phrase>
- id: LANG_CANCEL
- desc: Visual confirmation of canceling a changed setting
- user: core
- <source>
- *: "Cancelled"
- </source>
- <dest>
- *: "Atcelts"
- </dest>
- <voice>
- *: "atcelts"
- </voice>
-</phrase>
-<phrase>
- id: LANG_FAILED
- desc: Something failed. To be appended after actions
- user: core
- <source>
- *: "Failed"
- </source>
- <dest>
- *: "Neizdevās"
- </dest>
- <voice>
- *: "neizdevaas"
- </voice>
-</phrase>
-<phrase>
- id: LANG_CHANNELS
- desc: in sound_settings
- user: core
- <source>
- *: "Channels"
- </source>
- <dest>
- *: "Kanāli"
- </dest>
- <voice>
- *: "kanaali"
- </voice