summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libgme
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libgme')
-rw-r--r--lib/rbcodec/codecs/libgme/2413tone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/281btone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/AYSOURCES7
-rw-r--r--lib/rbcodec/codecs/libgme/EMU2413SOURCES4
-rw-r--r--lib/rbcodec/codecs/libgme/GBSSOURCES9
-rw-r--r--lib/rbcodec/codecs/libgme/HESSOURCES8
-rw-r--r--lib/rbcodec/codecs/libgme/KSSSOURCES12
-rw-r--r--lib/rbcodec/codecs/libgme/NSFSOURCES15
-rw-r--r--lib/rbcodec/codecs/libgme/SGCSOURCES7
-rw-r--r--lib/rbcodec/codecs/libgme/VGMSOURCES10
-rw-r--r--lib/rbcodec/codecs/libgme/ay_apu.c413
-rw-r--r--lib/rbcodec/codecs/libgme/ay_apu.h79
-rw-r--r--lib/rbcodec/codecs/libgme/ay_cpu.c59
-rw-r--r--lib/rbcodec/codecs/libgme/ay_emu.c599
-rw-r--r--lib/rbcodec/codecs/libgme/ay_emu.h169
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_common.h160
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_config.h42
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_endian.h168
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_source.h76
-rw-r--r--lib/rbcodec/codecs/libgme/blip_buffer.c225
-rw-r--r--lib/rbcodec/codecs/libgme/blip_buffer.h335
-rw-r--r--lib/rbcodec/codecs/libgme/emu2413.c1981
-rw-r--r--lib/rbcodec/codecs/libgme/emu2413.h164
-rw-r--r--lib/rbcodec/codecs/libgme/emu8950.c1206
-rw-r--r--lib/rbcodec/codecs/libgme/emu8950.h248
-rw-r--r--lib/rbcodec/codecs/libgme/emuadpcm.c297
-rw-r--r--lib/rbcodec/codecs/libgme/emuadpcm.h52
-rw-r--r--lib/rbcodec/codecs/libgme/emutables.h210
-rw-r--r--lib/rbcodec/codecs/libgme/emutypes.h41
-rw-r--r--lib/rbcodec/codecs/libgme/gb_apu.c410
-rw-r--r--lib/rbcodec/codecs/libgme/gb_apu.h85
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu.c53
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu.h80
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu_run.h1187
-rw-r--r--lib/rbcodec/codecs/libgme/gb_oscs.c787
-rw-r--r--lib/rbcodec/codecs/libgme/gb_oscs.h187
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_cpu.c120
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_emu.c452
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_emu.h192
-rw-r--r--lib/rbcodec/codecs/libgme/gme.h18
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu.c371
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu.h66
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu_adpcm.c297
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu_adpcm.h89
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu.c121
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu.h132
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu_run.h1344
-rw-r--r--lib/rbcodec/codecs/libgme/hes_emu.c644
-rw-r--r--lib/rbcodec/codecs/libgme/hes_emu.h195
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/bbfuncs.c147
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/bbfuncs.h33
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/inflate.c1156
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/inflate.h30
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mallocer.c86
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mallocer.h16
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mbreader.c16
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mbreader.h15
-rw-r--r--lib/rbcodec/codecs/libgme/kss_cpu.c35
-rw-r--r--lib/rbcodec/codecs/libgme/kss_emu.c714
-rw-r--r--lib/rbcodec/codecs/libgme/kss_emu.h223
-rw-r--r--lib/rbcodec/codecs/libgme/kss_scc_apu.c166
-rw-r--r--lib/rbcodec/codecs/libgme/kss_scc_apu.h51
-rw-r--r--lib/rbcodec/codecs/libgme/libay.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libemu2413.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libgbs.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libhes.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libkss.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libnsf.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libsgc.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libvgm.make10
-rw-r--r--lib/rbcodec/codecs/libgme/m3u_playlist.h31
-rw-r--r--lib/rbcodec/codecs/libgme/msxtypes.h36
-rw-r--r--lib/rbcodec/codecs/libgme/multi_buffer.c286
-rw-r--r--lib/rbcodec/codecs/libgme/multi_buffer.h114
-rw-r--r--lib/rbcodec/codecs/libgme/nes_apu.c397
-rw-r--r--lib/rbcodec/codecs/libgme/nes_apu.h137
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu.c62
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu.h109
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu_run.h1122
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fds_apu.c291
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fds_apu.h116
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fme7_apu.c136
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fme7_apu.h90
-rw-r--r--lib/rbcodec/codecs/libgme/nes_mmc5_apu.h61
-rw-r--r--lib/rbcodec/codecs/libgme/nes_namco_apu.c138
-rw-r--r--lib/rbcodec/codecs/libgme/nes_namco_apu.h71
-rw-r--r--lib/rbcodec/codecs/libgme/nes_oscs.c592
-rw-r--r--lib/rbcodec/codecs/libgme/nes_oscs.h164
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc6_apu.c192
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc6_apu.h62
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc7_apu.c88
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc7_apu.h52
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_cpu.c115
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_emu.c921
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_emu.h261
-rw-r--r--lib/rbcodec/codecs/libgme/nsfe_info.c272
-rw-r--r--lib/rbcodec/codecs/libgme/nsfe_info.h30
-rw-r--r--lib/rbcodec/codecs/libgme/opl_apu.c198
-rw-r--r--lib/rbcodec/codecs/libgme/opl_apu.h63
-rw-r--r--lib/rbcodec/codecs/libgme/opltables.h242
-rw-r--r--lib/rbcodec/codecs/libgme/resampler.c218
-rw-r--r--lib/rbcodec/codecs/libgme/resampler.h75
-rw-r--r--lib/rbcodec/codecs/libgme/rom_data.c68
-rw-r--r--lib/rbcodec/codecs/libgme/rom_data.h83
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_cpu.c36
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_emu.c480
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_emu.h195
-rw-r--r--lib/rbcodec/codecs/libgme/sms_apu.c306
-rw-r--r--lib/rbcodec/codecs/libgme/sms_apu.h63
-rw-r--r--lib/rbcodec/codecs/libgme/sms_fm_apu.c82
-rw-r--r--lib/rbcodec/codecs/libgme/sms_fm_apu.h43
-rw-r--r--lib/rbcodec/codecs/libgme/track_filter.c294
-rw-r--r--lib/rbcodec/codecs/libgme/track_filter.h90
-rw-r--r--lib/rbcodec/codecs/libgme/vgm_emu.c858
-rw-r--r--lib/rbcodec/codecs/libgme/vgm_emu.h206
-rw-r--r--lib/rbcodec/codecs/libgme/vrc7tone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/ym2413_emu.c45
-rw-r--r--lib/rbcodec/codecs/libgme/ym2413_emu.h61
-rw-r--r--lib/rbcodec/codecs/libgme/ym2612_emu.c1374
-rw-r--r--lib/rbcodec/codecs/libgme/ym2612_emu.h248
-rw-r--r--lib/rbcodec/codecs/libgme/ymtables.h559
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu.c85
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu.h116
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu_run.h1696
124 files changed, 29984 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libgme/2413tone.h b/lib/rbcodec/codecs/libgme/2413tone.h
new file mode 100644
index 0000000000..c0922c1225
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/2413tone.h
@@ -0,0 +1,20 @@
1/* YM2413 tone by okazaki@angel.ne.jp */
20x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
30x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
170x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
180x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
190x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
200x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/lib/rbcodec/codecs/libgme/281btone.h b/lib/rbcodec/codecs/libgme/281btone.h
new file mode 100644
index 0000000000..83f63bff00
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/281btone.h
@@ -0,0 +1,20 @@
1/* YMF281B tone by Chabin */
20x49,0x4c,0x4c,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
30x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40x00,0x10,0x44,0x02,0xf6,0xf4,0x54,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50x03,0x01,0x97,0x04,0xf3,0xf3,0x13,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60x01,0x61,0x0a,0x0f,0xfa,0x64,0x70,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80x00,0x61,0x8a,0x0e,0xc0,0x61,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90x21,0x61,0x1b,0x07,0x84,0x80,0x17,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110x01,0x21,0x06,0x03,0xa5,0x71,0x51,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120x06,0x11,0x5e,0x07,0xf3,0xf2,0xf6,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130x00,0x20,0x18,0x06,0xf5,0xf3,0x20,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140x97,0x41,0x20,0x07,0xff,0xf4,0x22,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150x65,0x61,0x15,0x00,0xf7,0xf3,0x16,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160x01,0x31,0x0e,0x07,0xfa,0xf3,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
170x48,0x61,0x09,0x07,0xf1,0x94,0xf0,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
180x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
190x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
200x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/lib/rbcodec/codecs/libgme/AYSOURCES b/lib/rbcodec/codecs/libgme/AYSOURCES
new file mode 100644
index 0000000000..f2b52a51d9
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/AYSOURCES
@@ -0,0 +1,7 @@
1ay_apu.c
2ay_cpu.c
3ay_emu.c
4blip_buffer.c
5multi_buffer.c
6track_filter.c
7z80_cpu.c
diff --git a/lib/rbcodec/codecs/libgme/EMU2413SOURCES b/lib/rbcodec/codecs/libgme/EMU2413SOURCES
new file mode 100644
index 0000000000..901c49eccf
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/EMU2413SOURCES
@@ -0,0 +1,4 @@
1sms_apu.c
2sms_fm_apu.c
3emu2413.c
4ym2413_emu.c
diff --git a/lib/rbcodec/codecs/libgme/GBSSOURCES b/lib/rbcodec/codecs/libgme/GBSSOURCES
new file mode 100644
index 0000000000..a839a2156e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/GBSSOURCES
@@ -0,0 +1,9 @@
1gb_apu.c
2gb_cpu.c
3gbs_cpu.c
4gb_oscs.c
5gbs_emu.c
6blip_buffer.c
7multi_buffer.c
8rom_data.c
9track_filter.c
diff --git a/lib/rbcodec/codecs/libgme/HESSOURCES b/lib/rbcodec/codecs/libgme/HESSOURCES
new file mode 100644
index 0000000000..d529388978
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/HESSOURCES
@@ -0,0 +1,8 @@
1hes_apu.c
2hes_apu_adpcm.c
3hes_cpu.c
4hes_emu.c
5blip_buffer.c
6multi_buffer.c
7rom_data.c
8track_filter.c
diff --git a/lib/rbcodec/codecs/libgme/KSSSOURCES b/lib/rbcodec/codecs/libgme/KSSSOURCES
new file mode 100644
index 0000000000..bde213364b
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/KSSSOURCES
@@ -0,0 +1,12 @@
1ay_apu.c
2kss_cpu.c
3kss_emu.c
4kss_scc_apu.c
5opl_apu.c
6z80_cpu.c
7blip_buffer.c
8multi_buffer.c
9rom_data.c
10emu8950.c
11emuadpcm.c
12track_filter.c
diff --git a/lib/rbcodec/codecs/libgme/NSFSOURCES b/lib/rbcodec/codecs/libgme/NSFSOURCES
new file mode 100644
index 0000000000..60537ff8e4
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/NSFSOURCES
@@ -0,0 +1,15 @@
1nes_apu.c
2nes_cpu.c
3nes_fds_apu.c
4nes_fme7_apu.c
5nes_namco_apu.c
6nes_oscs.c
7nes_vrc6_apu.c
8nes_vrc7_apu.c
9nsf_cpu.c
10nsf_emu.c
11nsfe_info.c
12blip_buffer.c
13multi_buffer.c
14rom_data.c
15track_filter.c
diff --git a/lib/rbcodec/codecs/libgme/SGCSOURCES b/lib/rbcodec/codecs/libgme/SGCSOURCES
new file mode 100644
index 0000000000..d0e8abc2b7
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/SGCSOURCES
@@ -0,0 +1,7 @@
1sgc_cpu.c
2sgc_emu.c
3z80_cpu.c
4blip_buffer.c
5multi_buffer.c
6rom_data.c
7track_filter.c
diff --git a/lib/rbcodec/codecs/libgme/VGMSOURCES b/lib/rbcodec/codecs/libgme/VGMSOURCES
new file mode 100644
index 0000000000..bb57e16e82
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/VGMSOURCES
@@ -0,0 +1,10 @@
1blip_buffer.c
2multi_buffer.c
3resampler.c
4vgm_emu.c
5ym2612_emu.c
6track_filter.c
7inflate/bbfuncs.c
8inflate/inflate.c
9inflate/mallocer.c
10inflate/mbreader.c
diff --git a/lib/rbcodec/codecs/libgme/ay_apu.c b/lib/rbcodec/codecs/libgme/ay_apu.c
new file mode 100644
index 0000000000..c84e92d43d
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ay_apu.c
@@ -0,0 +1,413 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "ay_apu.h"
4
5/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18// Emulation inaccuracies:
19// * Noise isn't run when not in use
20// * Changes to envelope and noise periods are delayed until next reload
21// * Super-sonic tone should attenuate output to about 60%, not 50%
22
23// Tones above this frequency are treated as disabled tone at half volume.
24// Power of two is more efficient (avoids division).
25int const inaudible_freq = 16384;
26
27int const period_factor = 16;
28
29static byte const amp_table [16] =
30{
31#define ENTRY( n ) (byte) (n * ay_amp_range + 0.5)
32 // With channels tied together and 1K resistor to ground (as datasheet recommends),
33 // output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
34 ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
35 ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
36 ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
37 ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
38
39 /*
40 // Measured from an AY-3-8910A chip with date code 8611.
41
42 // Direct voltages without any load (very linear)
43 ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
44 ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
45 ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
46 ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
47 // With only some load
48 ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
49 ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
50 ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
51 ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
52 */
53#undef ENTRY
54};
55
56static byte const modes [8] =
57{
58#define MODE( a0,a1, b0,b1, c0,c1 ) \
59 (a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
60 MODE( 1,0, 1,0, 1,0 ),
61 MODE( 1,0, 0,0, 0,0 ),
62 MODE( 1,0, 0,1, 1,0 ),
63 MODE( 1,0, 1,1, 1,1 ),
64 MODE( 0,1, 0,1, 0,1 ),
65 MODE( 0,1, 1,1, 1,1 ),
66 MODE( 0,1, 1,0, 0,1 ),
67 MODE( 0,1, 0,0, 0,0 ),
68};
69
70static void set_output( struct Ay_Apu* this, struct Blip_Buffer* b )
71{
72 int i;
73 for ( i = 0; i < ay_osc_count; ++i )
74 Ay_apu_set_output( this, i, b );
75}
76
77void Ay_apu_init( struct Ay_Apu* this )
78{
79 Synth_init( &this->synth_ );
80
81 // build full table of the upper 8 envelope waveforms
82 int m;
83 for ( m = 8; m--; )
84 {
85 byte* out = this->env_modes [m];
86 int x, y, flags = modes [m];
87 for ( x = 3; --x >= 0; )
88 {
89 int amp = flags & 1;
90 int end = flags >> 1 & 1;
91 int step = end - amp;
92 amp *= 15;
93 for ( y = 16; --y >= 0; )
94 {
95 *out++ = amp_table [amp];
96 amp += step;
97 }
98 flags >>= 2;
99 }
100 }
101
102 set_output( this, NULL );
103 Ay_apu_volume( this, (int)FP_ONE_VOLUME );
104 Ay_apu_reset( this );
105}
106
107void Ay_apu_reset( struct Ay_Apu* this )
108{
109 this->addr_ = 0;
110 this->last_time = 0;
111 this->noise_delay = 0;
112 this->noise_lfsr = 1;
113
114 struct osc_t* osc;
115 for ( osc = &this->oscs [ay_osc_count]; osc != this->oscs; )
116 {
117 osc--;
118 osc->period = period_factor;
119 osc->delay = 0;
120 osc->last_amp = 0;
121 osc->phase = 0;
122 }
123
124 int i;
125 for ( i = sizeof this->regs; --i >= 0; )
126 this->regs [i] = 0;
127 this->regs [7] = 0xFF;
128 write_data_( this, 13, 0 );
129}
130
131int Ay_apu_read( struct Ay_Apu* this )
132{
133 static byte const masks [ay_reg_count] = {
134 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x1F, 0x3F,
135 0x1F, 0x1F, 0x1F, 0xFF, 0xFF, 0x0F, 0x00, 0x00
136 };
137 return this->regs [this->addr_] & masks [this->addr_];
138}
139
140void write_data_( struct Ay_Apu* this, int addr, int data )
141{
142 assert( (unsigned) addr < ay_reg_count );
143
144 /* if ( (unsigned) addr >= 14 )
145 dprintf( "Wrote to I/O port %02X\n", (int) addr ); */
146
147 // envelope mode
148 if ( addr == 13 )
149 {
150 if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
151 data = (data & 4) ? 15 : 9;
152 this->env_wave = this->env_modes [data - 7];
153 this->env_pos = -48;
154 this->env_delay = 0; // will get set to envelope period in run_until()
155 }
156 this->regs [addr] = data;
157
158 // handle period changes accurately
159 int i = addr >> 1;
160 if ( i < ay_osc_count )
161 {
162 blip_time_t period = (this->regs [i * 2 + 1] & 0x0F) * (0x100 * period_factor) +
163 this->regs [i * 2] * period_factor;
164 if ( !period )
165 period = period_factor;
166
167 // adjust time of next timer expiration based on change in period
168 struct osc_t* osc = &this->oscs [i];
169 if ( (osc->delay += period - osc->period) < 0 )
170 osc->delay = 0;
171 osc->period = period;
172 }
173
174 // TODO: same as above for envelope timer, and it also has a divide by two after it
175}
176
177int const noise_off = 0x08;
178int const tone_off = 0x01;
179
180void run_until( struct Ay_Apu* this, blip_time_t final_end_time )
181{
182 require( final_end_time >= this->last_time );
183
184 // noise period and initial values
185 blip_time_t const noise_period_factor = period_factor * 2; // verified
186 blip_time_t noise_period = (this->regs [6] & 0x1F) * noise_period_factor;
187 if ( !noise_period )
188 noise_period = noise_period_factor;
189 blip_time_t const old_noise_delay = this->noise_delay;
190 unsigned const old_noise_lfsr = this->noise_lfsr;
191
192 // envelope period
193 blip_time_t const env_period_factor = period_factor * 2; // verified
194 blip_time_t env_period = (this->regs [12] * 0x100 + this->regs [11]) * env_period_factor;
195 if ( !env_period )
196 env_period = env_period_factor; // same as period 1 on my AY chip
197 if ( !this->env_delay )
198 this->env_delay = env_period;
199
200 // run each osc separately
201 int index;
202 for ( index = 0; index < ay_osc_count; index++ )
203 {
204 struct osc_t* const osc = &this->oscs [index];
205 int osc_mode = this->regs [7] >> index;
206
207 // output
208 struct Blip_Buffer* const osc_output = osc->output;
209 if ( !osc_output )
210 continue;
211 Blip_set_modified( osc_output );
212
213 // period
214 int half_vol = 0;
215 blip_time_t inaudible_period = (unsigned) (Blip_clock_rate( osc_output ) +
216 inaudible_freq) / (unsigned) (inaudible_freq * 2);
217 if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
218 {
219 half_vol = 1; // Actually around 60%, but 50% is close enough
220 osc_mode |= tone_off;
221 }
222
223 // envelope
224 blip_time_t start_time = this->last_time;
225 blip_time_t end_time = final_end_time;
226 int const vol_mode = this->regs [0x08 + index];
227 int volume = amp_table [vol_mode & 0x0F] >> half_vol;
228 int osc_env_pos = this->env_pos;
229 if ( vol_mode & 0x10 )
230 {
231 volume = this->env_wave [osc_env_pos] >> half_vol;
232 // use envelope only if it's a repeating wave or a ramp that hasn't finished
233 if ( !(this->regs [13] & 1) || osc_env_pos < -32 )
234 {
235 end_time = start_time + this->env_delay;
236 if ( end_time >= final_end_time )
237 end_time = final_end_time;
238
239 //if ( !(regs [12] | regs [11]) )
240 // dprintf( "Used envelope period 0\n" );
241 }
242 else if ( !volume )
243 {
244 osc_mode = noise_off | tone_off;
245 }
246 }
247 else if ( !volume )
248 {
249 osc_mode = noise_off | tone_off;
250 }
251
252 // tone time
253 blip_time_t const period = osc->period;
254 blip_time_t time = start_time + osc->delay;
255 if ( osc_mode & tone_off ) // maintain tone's phase when off
256 {
257 int count = (final_end_time - time + period - 1) / period;
258 time += count * period;
259 osc->phase ^= count & 1;
260 }
261
262 // noise time
263 blip_time_t ntime = final_end_time;
264 unsigned noise_lfsr = 1;
265 if ( !(osc_mode & noise_off) )
266 {
267 ntime = start_time + old_noise_delay;
268 noise_lfsr = old_noise_lfsr;
269 //if ( (regs [6] & 0x1F) == 0 )
270 // dprintf( "Used noise period 0\n" );
271 }
272
273 // The following efficiently handles several cases (least demanding first):
274 // * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
275 // * Just tone or just noise, envelope disabled
276 // * Envelope controlling tone and/or noise
277 // * Tone and noise disabled, envelope enabled with high frequency
278 // * Tone and noise together
279 // * Tone and noise together with envelope
280
281 // this loop only runs one iteration if envelope is disabled. If envelope
282 // is being used as a waveform (tone and noise disabled), this loop will
283 // still be reasonably efficient since the bulk of it will be skipped.
284 while ( 1 )
285 {
286 // current amplitude
287 int amp = 0;
288 if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
289 amp = volume;
290 {
291 int delta = amp - osc->last_amp;
292 if ( delta )
293 {
294 osc->last_amp = amp;
295 Synth_offset( &this->synth_, start_time, delta, osc_output );
296 }
297 }
298
299 // Run wave and noise interleved with each catching up to the other.
300 // If one or both are disabled, their "current time" will be past end time,
301 // so there will be no significant performance hit.
302 if ( ntime < end_time || time < end_time )
303 {
304 // Since amplitude was updated above, delta will always be +/- volume,
305 // so we can avoid using last_amp every time to calculate the delta.
306 int delta = amp * 2 - volume;
307 int delta_non_zero = delta != 0;
308 int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
309 do
310 {
311 // run noise
312 blip_time_t end = end_time;
313 if ( end_time > time ) end = time;
314 if ( phase & delta_non_zero )
315 {
316 while ( ntime <= end ) // must advance *past* time to avoid hang
317 {
318 int changed = noise_lfsr + 1;
319 noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
320 if ( changed & 2 )
321 {
322 delta = -delta;
323 Synth_offset( &this->synth_, ntime, delta, osc_output );
324 }
325 ntime += noise_period;
326 }
327 }
328 else
329 {
330 // 20 or more noise periods on average for some music
331 int remain = end - ntime;
332 int count = remain / noise_period;
333 if ( remain >= 0 )
334 ntime += noise_period + count * noise_period;
335 }
336
337 // run tone
338 end = end_time;
339 if ( end_time > ntime ) end = ntime;
340 if ( noise_lfsr & delta_non_zero )
341 {
342 while ( time < end )
343 {
344 delta = -delta;
345 Synth_offset( &this->synth_, time, delta, osc_output );
346 time += period;
347
348 // alternate (less-efficient) implementation
349 //phase ^= 1;
350 }
351 phase = (unsigned) (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
352 check( phase == (delta > 0) );
353 }
354 else
355 {
356 // loop usually runs less than once
357 //SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
358
359 while ( time < end )
360 {
361 time += period;
362 phase ^= 1;
363 }
364 }
365 }
366 while ( time < end_time || ntime < end_time );
367
368 osc->last_amp = (delta + volume) >> 1;
369 if ( !(osc_mode & tone_off) )
370 osc->phase = phase;
371 }
372
373 if ( end_time >= final_end_time )
374 break; // breaks first time when envelope is disabled
375
376 // next envelope step
377 if ( ++osc_env_pos >= 0 )
378 osc_env_pos -= 32;
379 volume = this->env_wave [osc_env_pos] >> half_vol;
380
381 start_time = end_time;
382 end_time += env_period;
383 if ( end_time > final_end_time )
384 end_time = final_end_time;
385 }
386 osc->delay = time - final_end_time;
387
388 if ( !(osc_mode & noise_off) )
389 {
390 this->noise_delay = ntime - final_end_time;
391 this->noise_lfsr = noise_lfsr;
392 }
393 }
394
395 // TODO: optimized saw wave envelope?
396
397 // maintain envelope phase
398 blip_time_t remain = final_end_time - this->last_time - this->env_delay;
399 if ( remain >= 0 )
400 {
401 int count = (remain + env_period) / env_period;
402 this->env_pos += count;
403 if ( this->env_pos >= 0 )
404 this->env_pos = (this->env_pos & 31) - 32;
405 remain -= count * env_period;
406 assert( -remain <= env_period );
407 }
408 this->env_delay = -remain;
409 assert( this->env_delay > 0 );
410 assert( this->env_pos < 0 );
411
412 this->last_time = final_end_time;
413}
diff --git a/lib/rbcodec/codecs/libgme/ay_apu.h b/lib/rbcodec/codecs/libgme/ay_apu.h
new file mode 100644
index 0000000000..3df6ba1118
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ay_apu.h
@@ -0,0 +1,79 @@
1// AY-3-8910 sound chip ulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef AY_APU_H
5#define AY_APU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9#include "blip_buffer.h"
10
11// Number of registers
12enum { ay_reg_count = 16 };
13enum { ay_osc_count = 3 };
14enum { ay_amp_range = 255 };
15
16struct osc_t
17{
18 blip_time_t period;
19 blip_time_t delay;
20 short last_amp;
21 short phase;
22 struct Blip_Buffer* output;
23};
24
25struct Ay_Apu {
26 struct osc_t oscs [ay_osc_count];
27
28 blip_time_t last_time;
29 byte addr_;
30 byte regs [ay_reg_count];
31
32 blip_time_t noise_delay;
33 unsigned noise_lfsr;
34
35 blip_time_t env_delay;
36 byte const* env_wave;
37 int env_pos;
38 byte env_modes [8] [48]; // values already passed through volume table
39
40 struct Blip_Synth synth_; // used by Ay_Core for beeper sound
41};
42
43void Ay_apu_init( struct Ay_Apu* this );
44
45// Writes to address register
46static inline void Ay_apu_write_addr( struct Ay_Apu* this, int data ) { this->addr_ = data & 0x0F; }
47
48// Emulates to time t, then writes to current data register
49void run_until( struct Ay_Apu* this, blip_time_t final_end_time );;
50void write_data_( struct Ay_Apu* this, int addr, int data );
51static inline void Ay_apu_write_data( struct Ay_Apu* this, blip_time_t t, int data ) { run_until( this, t ); write_data_( this, this->addr_, data ); }
52
53// Reads from current data register
54int Ay_apu_read( struct Ay_Apu* this );
55
56// Resets sound chip
57void Ay_apu_reset( struct Ay_Apu* this );
58
59// Sets overall volume, where 1.0 is normal
60static inline void Ay_apu_volume( struct Ay_Apu* this, int v ) { Synth_volume( &this->synth_, (v*7)/10 /ay_osc_count/ay_amp_range ); }
61
62static inline void Ay_apu_set_output( struct Ay_Apu* this, int i, struct Blip_Buffer* out )
63{
64 assert( (unsigned) i < ay_osc_count );
65 this->oscs [i].output = out;
66}
67
68// Emulates to time t, then subtracts t from the current time.
69// OK if previous write call had time slightly after t.
70static inline void Ay_apu_end_frame( struct Ay_Apu* this, blip_time_t time )
71{
72 if ( time > this->last_time )
73 run_until( this, time );
74
75 this->last_time -= time;
76 assert( this->last_time >= 0 );
77}
78
79#endif
diff --git a/lib/rbcodec/codecs/libgme/ay_cpu.c b/lib/rbcodec/codecs/libgme/ay_cpu.c
new file mode 100644
index 0000000000..5fbfe7c1ea
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ay_cpu.c
@@ -0,0 +1,59 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "ay_emu.h"
4
5#include "blargg_endian.h"
6//#include "z80_cpu_log.h"
7
8/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21void cpu_out( struct Ay_Emu* this, cpu_time_t time, addr_t addr, int data )
22{
23 if ( (addr & 0xFF) == 0xFE )
24 {
25 check( !cpc_mode );
26 this->spectrum_mode = !this->cpc_mode;
27
28 // beeper_mask and last_beeper are 0 if (cpc_mode || !beeper_output)
29 if ( (data &= this->beeper_mask) != this->last_beeper )
30 {
31 this->last_beeper = data;
32 int delta = -this->beeper_delta;
33 this->beeper_delta = delta;
34 struct Blip_Buffer* bb = this->beeper_output;
35 Blip_set_modified( bb );
36 Synth_offset( &this->apu.synth_, time, delta, bb );
37 }
38 }
39 else
40 {
41 cpu_out_( this, time, addr, data );
42 }
43}
44
45#define OUT_PORT( addr, data ) cpu_out( this, TIME(), addr, data )
46#define IN_PORT( addr ) 0xFF // cpu in
47#define FLAT_MEM mem
48
49#define CPU_BEGIN \
50bool run_cpu( struct Ay_Emu* this, cpu_time_t end_time ) \
51{\
52 struct Z80_Cpu* cpu = &this->cpu; \
53 Z80_set_end_time( cpu, end_time ); \
54 byte* const mem = this->mem.ram; // cache
55
56 #include "z80_cpu_run.h"
57
58 return warning;
59}
diff --git a/lib/rbcodec/codecs/libgme/ay_emu.c b/lib/rbcodec/codecs/libgme/ay_emu.c
new file mode 100644
index 0000000000..92faba4929
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ay_emu.c
@@ -0,0 +1,599 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "ay_emu.h"
4
5#include "blargg_endian.h"
6
7/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20const char* const gme_wrong_file_type = "Wrong file type for this emulator";
21
22// TODO: probably don't need detailed errors as to why file is corrupt
23
24int const spectrum_clock = 3546900; // 128K Spectrum
25int const spectrum_period = 70908;
26
27//int const spectrum_clock = 3500000; // 48K Spectrum
28//int const spectrum_period = 69888;
29
30int const cpc_clock = 2000000;
31
32static void clear_track_vars( struct Ay_Emu *this )
33{
34 this->current_track = -1;
35 track_stop( &this->track_filter );
36}
37
38void Ay_init( struct Ay_Emu *this )
39{
40 this->sample_rate = 0;
41 this->mute_mask_ = 0;
42 this->tempo = (int)FP_ONE_TEMPO;
43 this->gain = (int)FP_ONE_GAIN;
44 this->track_count = 0;
45
46 // defaults
47 this->tfilter = *track_get_setup( &this->track_filter );
48 this->tfilter.max_initial = 2;
49 this->tfilter.lookahead = 6;
50 this->track_filter.silence_ignored_ = false;
51
52 this->beeper_output = NULL;
53 disable_beeper( this );
54
55 Ay_apu_init( &this->apu );
56 Z80_init( &this->cpu );
57
58 // clears fields
59 this->voice_count = 0;
60 this->voice_types = 0;
61 clear_track_vars( this );
62}
63
64// Track info
65
66// Given pointer to 2-byte offset of data, returns pointer to data, or NULL if
67// offset is 0 or there is less than min_size bytes of data available.
68static byte const* get_data( struct file_t const* file, byte const ptr [], int min_size )
69{
70 int offset = (int16_t) get_be16( ptr );
71 int pos = ptr - (byte const*) file->header;
72 int size = file->end - (byte const*) file->header;
73 assert( (unsigned) pos <= (unsigned) size - 2 );
74 int limit = size - min_size;
75 if ( limit < 0 || !offset || (unsigned) (pos + offset) > (unsigned) limit )
76 return NULL;
77 return ptr + offset;
78}
79
80static blargg_err_t parse_header( byte const in [], int size, struct file_t* out )
81{
82 if ( size < header_size )
83 return gme_wrong_file_type;
84
85 out->header = (struct header_t const*) in;
86 out->end = in + size;
87 struct header_t const* h = (struct header_t const*) in;
88 if ( memcmp( h->tag, "ZXAYEMUL", 8 ) )
89 return gme_wrong_file_type;
90
91 out->tracks = get_data( out, h->track_info, (h->max_track + 1) * 4 );
92 if ( !out->tracks )
93 return "missing track data";
94
95 return 0;
96}
97
98// Setup
99
100static void change_clock_rate( struct Ay_Emu *this, int rate )
101{
102 this->clock_rate_ = rate;
103 Buffer_clock_rate( &this->stereo_buf, rate );
104}
105
106blargg_err_t Ay_load_mem( struct Ay_Emu *this, byte const in [], long size )
107{
108 // Unload
109 this->voice_count = 0;
110 this->track_count = 0;
111 this->m3u.size = 0;
112 clear_track_vars( this );
113
114 assert( offsetof (struct header_t,track_info [2]) == header_size );
115
116 RETURN_ERR( parse_header( in, size, &this->file ) );
117
118 /* if ( file.header->vers > 2 )
119 warning( "Unknown file version" ); */
120
121 this->voice_count = ay_osc_count + 1; // +1 for beeper
122 static int const types [ay_osc_count + 1] = {
123 wave_type+0, wave_type+1, wave_type+2, mixed_type+1
124 };
125 this->voice_types = types;
126
127 Ay_apu_volume( &this->apu, this->gain);
128
129 // Setup buffer
130 change_clock_rate( this, spectrum_clock );
131 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
132 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
133
134 Sound_set_tempo( this, this->tempo );
135 Sound_mute_voices( this, this->mute_mask_ );
136
137 this->track_count = this->file.header->max_track + 1;
138 return 0;
139}
140
141static void set_beeper_output( struct Ay_Emu *this, struct Blip_Buffer* b )
142{
143 this->beeper_output = b;
144 if ( b && !this->cpc_mode )
145 this->beeper_mask = 0x10;
146 else
147 disable_beeper( this );
148}
149
150static void set_voice( struct Ay_Emu *this, int i, struct Blip_Buffer* center )
151{
152 if ( i >= ay_osc_count )
153 set_beeper_output( this, center );
154 else
155 Ay_apu_set_output( &this->apu, i, center );
156}
157
158static blargg_err_t run_clocks( struct Ay_Emu *this, blip_time_t* duration, int msec )
159{
160#if defined(ROCKBOX)
161 (void) msec;
162#endif
163
164 cpu_time_t *end = duration;
165 struct Z80_Cpu* cpu = &this->cpu;
166 Z80_set_time( cpu, 0 );
167
168 // Since detection of CPC mode will halve clock rate during the frame
169 // and thus generate up to twice as much sound, we must generate half
170 // as much until mode is known.
171 if ( !(this->spectrum_mode | this->cpc_mode) )
172 *end /= 2;
173
174 while ( Z80_time( cpu ) < *end )
175 {
176 run_cpu( this, min( *end, this->next_play ) );
177
178 if ( Z80_time( cpu ) >= this->next_play )
179 {
180 // next frame
181 this->next_play += this->play_period;
182
183 if ( cpu->r.iff1 )
184 {
185 // interrupt enabled
186
187 if ( this->mem.ram [cpu->r.pc] == 0x76 )
188 cpu->r.pc++; // advance past HALT instruction
189
190 cpu->r.iff1 = 0;
191 cpu->r.iff2 = 0;
192
193 this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc >> 8);
194 this->mem.ram [--cpu->r.sp] = (byte) (cpu->r.pc);
195
196 // fixed interrupt
197 cpu->r.pc = 0x38;
198 Z80_adjust_time( cpu, 12 );
199
200 if ( cpu->r.im == 2 )
201 {
202 // vectored interrupt
203 addr_t addr = cpu->r.i * 0x100 + 0xFF;
204 cpu->r.pc = this->mem.ram [(addr + 1) & 0xFFFF] * 0x100 + this->mem.ram [addr];
205 Z80_adjust_time( cpu, 6 );
206 }
207 }
208 }
209 }
210
211 // End time frame
212 *end = Z80_time( cpu );
213 this->next_play -= *end;
214 check( this->next_play >= 0 );
215 Z80_adjust_time( cpu, -*end );
216 Ay_apu_end_frame( &this->apu, *end );
217 return 0;
218}
219
220// Emulation
221
222void cpu_out_( struct Ay_Emu *this, cpu_time_t time, addr_t addr, int data )
223{
224 // Spectrum
225 if ( !this->cpc_mode )
226 {
227 switch ( addr & 0xFEFF )
228 {
229 case 0xFEFD:
230 this->spectrum_mode = true;
231 Ay_apu_write_addr( &this->apu, data );
232 return;
233
234 case 0xBEFD:
235 this->spectrum_mode = true;
236 Ay_apu_write_data( &this->apu, time, data );
237 return;
238 }
239 }
240
241 // CPC
242 if ( !this->spectrum_mode )
243 {
244 switch ( addr >> 8 )
245 {
246 case 0xF6:
247 switch ( data & 0xC0 )
248 {
249 case 0xC0:
250 Ay_apu_write_addr( &this->apu, this->cpc_latch );
251 goto enable_cpc;
252
253 case 0x80:
254 Ay_apu_write_data( &this->apu, time, this->cpc_latch );
255 goto enable_cpc;
256 }
257 break;
258
259 case 0xF4:
260 this->cpc_latch = data;
261 goto enable_cpc;
262 }
263 }
264
265 /* dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data ); */
266 return;
267
268enable_cpc:
269 if ( !this->cpc_mode )
270 {
271 this->cpc_mode = true;
272 disable_beeper( this );
273
274 change_clock_rate( this, cpc_clock );
275 Sound_set_tempo( this, this->tempo );
276 }
277}
278
279blargg_err_t Ay_set_sample_rate( struct Ay_Emu *this, int rate )
280{
281 require( !this->sample_rate ); // sample rate can't be changed once set
282 Buffer_init( &this->stereo_buf );
283 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
284
285 // Set buffer bass
286 Buffer_bass_freq( &this->stereo_buf, 160 );
287
288 this->sample_rate = rate;
289 RETURN_ERR( track_init( &this->track_filter, this ) );
290 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
291 return 0;
292}
293
294void Sound_mute_voice( struct Ay_Emu *this, int index, bool mute )
295{
296 require( (unsigned) index < (unsigned) this->voice_count );
297 int bit = 1 << index;
298 int mask = this->mute_mask_ | bit;
299 if ( !mute )
300 mask ^= bit;
301 Sound_mute_voices( this, mask );
302}
303
304void Sound_mute_voices( struct Ay_Emu *this, int mask )
305{
306 require( this->sample_rate ); // sample rate must be set first
307 this->mute_mask_ = mask;
308
309 int i;
310 for ( i = this->voice_count; i--; )
311 {
312 if ( mask & (1 << i) )
313 {
314 set_voice( this, i, 0 );
315 }
316 else
317 {
318 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
319 assert( (ch.center && ch.left && ch.right) ||
320 (!ch.center && !ch.left && !ch.right) ); // all or nothing
321 set_voice( this, i, ch.center );
322 }
323 }
324}
325
326void Sound_set_tempo( struct Ay_Emu *this, int t )
327{
328 require( this->sample_rate ); // sample rate must be set first
329 int const min = (int)(FP_ONE_TEMPO*0.02);
330 int const max = (int)(FP_ONE_TEMPO*4.00);
331 if ( t < min ) t = min;
332 if ( t > max ) t = max;
333 this->tempo = t;
334
335 int p = spectrum_period;
336 if ( this->clock_rate_ != spectrum_clock )
337 p = this->clock_rate_ / 50;
338
339 this->play_period = (blip_time_t) ((p * FP_ONE_TEMPO) / t);
340}
341
342blargg_err_t Ay_start_track( struct Ay_Emu *this, int track )
343{
344 clear_track_vars( this );
345
346 // Remap track if playlist available
347 if ( this->m3u.size > 0 ) {
348 struct entry_t* e = &this->m3u.entries[track];
349 track = e->track;
350 }
351
352 this->current_track = track;
353 Buffer_clear( &this->stereo_buf );
354
355 byte* const mem = this->mem.ram;
356
357 memset( mem + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
358 memset( mem + 0x0100, 0xFF, 0x4000 - 0x100 );
359 memset( mem + ram_addr, 0x00, mem_size - ram_addr );
360
361 // locate data blocks
362 byte const* const data = get_data( &this->file, this->file.tracks + track * 4 + 2, 14 );
363 if ( !data )
364 return "file data missing";
365
366 byte const* const more_data = get_data( &this->file, data + 10, 6 );
367 if ( !more_data )
368 return "file data missing";
369
370 byte const* blocks = get_data( &this->file, data + 12, 8 );
371 if ( !blocks )
372 return "file data missing";
373
374 // initial addresses
375 unsigned addr = get_be16( blocks );
376 if ( !addr )
377 return "file data missing";
378
379 unsigned init = get_be16( more_data + 2 );
380 if ( !init )
381 init = addr;
382
383 // copy blocks into memory
384 do
385 {
386 blocks += 2;
387 unsigned len = get_be16( blocks ); blocks += 2;
388 if ( addr + len > mem_size )
389 {
390 /* warning( "Bad data block size" ); */
391 len = mem_size - addr;
392 }
393 check( len );
394 byte const* in = get_data( &this->file, blocks, 0 ); blocks += 2;
395 if ( len > (unsigned) (this->file.end - in) )
396 {
397 /* warning( "File data missing" ); */
398 len = this->file.end - in;
399 }
400
401 memcpy( mem + addr, in, len );
402
403 if ( this->file.end - blocks < 8 )
404 {
405 /* warning( "File data missing" ); */
406 break;
407 }
408 }
409 while ( (addr = get_be16( blocks )) != 0 );
410
411 // copy and configure driver
412 static byte const passive [] = {
413 0xF3, // DI
414 0xCD, 0, 0, // CALL init
415 0xED, 0x5E, // LOOP: IM 2
416 0xFB, // EI
417 0x76, // HALT
418 0x18, 0xFA // JR LOOP
419 };
420 static byte const active [] = {
421 0xF3, // DI
422 0xCD, 0, 0, // CALL init
423 0xED, 0x56, // LOOP: IM 1
424 0xFB, // EI
425 0x76, // HALT
426 0xCD, 0, 0, // CALL play
427 0x18, 0xF7 // JR LOOP
428 };
429 memcpy( mem, passive, sizeof passive );
430 int const play_addr = get_be16( more_data + 4 );
431 if ( play_addr )
432 {
433 memcpy( mem, active, sizeof active );
434 mem [ 9] = play_addr;
435 mem [10] = play_addr >> 8;
436 }
437 mem [2] = init;
438 mem [3] = init >> 8;
439
440 mem [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
441
442 // start at spectrum speed
443 change_clock_rate( this, spectrum_clock );
444 Sound_set_tempo( this, this->tempo );
445
446 struct registers_t r;
447 memset( &r, 0, sizeof(struct registers_t) );
448
449 r.sp = get_be16( more_data );
450 r.b.a = r.b.b = r.b.d = r.b.h = data [8];
451 r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
452 r.alt.w = r.w;
453 r.ix = r.iy = r.w.hl;
454
455 memset( this->mem.padding1, 0xFF, sizeof this->mem.padding1 );
456
457 int const mirrored = 0x80; // this much is mirrored after end of memory
458 memset( this->mem.ram + mem_size + mirrored, 0xFF, sizeof this->mem.ram - mem_size - mirrored );
459 memcpy( this->mem.ram + mem_size, this->mem.ram, mirrored ); // some code wraps around (ugh)
460
461 Z80_reset( &this->cpu, this->mem.padding1, this->mem.padding1 );
462 Z80_map_mem( &this->cpu, 0, mem_size, this->mem.ram, this->mem.ram );
463 this->cpu.r = r;
464
465 this->beeper_delta = (int) ((ay_amp_range*4)/5);
466 this->last_beeper = 0;
467 this->next_play = this->play_period;
468 this->spectrum_mode = false;
469 this->cpc_mode = false;
470 this->cpc_latch = 0;
471 set_beeper_output( this, this->beeper_output );
472 Ay_apu_reset( &this->apu );
473
474 // a few tunes rely on channels having tone enabled at the beginning
475 Ay_apu_write_addr( &this->apu, 7 );
476 Ay_apu_write_data( &this->apu, 0, 0x38 );
477
478 // convert filter times to samples
479 struct setup_t s = this->tfilter;
480 s.max_initial *= this->sample_rate * stereo;
481 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
482 s.lookahead = 1;
483 #endif
484 track_setup( &this->track_filter, &s );
485
486 return track_start( &this->track_filter );
487}
488
489// Tell/Seek
490
491static int msec_to_samples( int msec, int sample_rate )
492{
493 int sec = msec / 1000;
494 msec -= sec * 1000;
495 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
496}
497
498int Track_tell( struct Ay_Emu *this )
499{
500 int rate = this->sample_rate * stereo;
501 int sec = track_sample_count( &this->track_filter ) / rate;
502 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
503}
504
505blargg_err_t Track_seek( struct Ay_Emu *this, int msec )
506{
507 int time = msec_to_samples( msec, this->sample_rate );
508 if ( time < track_sample_count( &this->track_filter ) )
509 RETURN_ERR( Ay_start_track( this, this->current_track ) );
510 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
511}
512
513blargg_err_t skip_( void *emu, int count )
514{
515 struct Ay_Emu* this = (struct Ay_Emu*) emu;
516
517 // for long skip, mute sound
518 const int threshold = 32768;
519 if ( count > threshold )
520 {
521 int saved_mute = this->mute_mask_;
522 Sound_mute_voices( this, ~0 );
523
524 int n = count - threshold/2;
525 n &= ~(2048-1); // round to multiple of 2048
526 count -= n;
527 RETURN_ERR( skippy_( &this->track_filter, n ) );
528
529 Sound_mute_voices( this, saved_mute );
530 }
531
532 return skippy_( &this->track_filter, count );
533}
534
535blargg_err_t Track_skip( struct Ay_Emu *this, int count )
536{
537 require( this->current_track >= 0 ); // start_track() must have been called already
538 return track_skip( &this->track_filter, count );
539}
540
541int Track_get_length( struct Ay_Emu* this, int n )
542{
543 int length = 0;
544
545 byte const* track_info = get_data( &this->file, this->file.tracks + n * 4 + 2, 6 );
546 if ( track_info )
547 length = get_be16( track_info + 4 ) * (1000 / 50); // frames to msec
548
549 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
550 struct entry_t* entry = &this->m3u.entries [n];
551 length = entry->length;
552 }
553
554 if ( length <= 0 )
555 length = 120 * 1000; /* 2 minutes */
556
557 return length;
558}
559
560void Track_set_fade( struct Ay_Emu *this, int start_msec, int length_msec )
561{
562 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
563 length_msec * this->sample_rate / (1000 / stereo) );
564}
565
566blargg_err_t Ay_play( struct Ay_Emu *this, int out_count, sample_t* out )
567{
568 require( this->current_track >= 0 );
569 require( out_count % stereo == 0 );
570 return track_play( &this->track_filter, out_count, out );
571}
572
573blargg_err_t play_( void *emu, int count, sample_t* out )
574{
575 struct Ay_Emu* this = (struct Ay_Emu*) emu;
576
577 int remain = count;
578 while ( remain )
579 {
580 Buffer_disable_immediate_removal( &this->stereo_buf );
581 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
582 if ( remain )
583 {
584 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
585 {
586 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
587
588 // Remute voices
589 Sound_mute_voices( this, this->mute_mask_ );
590 }
591 int msec = Buffer_length( &this->stereo_buf );
592 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
593 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
594 assert( clocks_emulated );
595 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
596 }
597 }
598 return 0;
599}
diff --git a/lib/rbcodec/codecs/libgme/ay_emu.h b/lib/rbcodec/codecs/libgme/ay_emu.h
new file mode 100644
index 0000000000..7334167876
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ay_emu.h
@@ -0,0 +1,169 @@
1// Sinclair Spectrum AY music file emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef AY_EMU_H
5#define AY_EMU_H
6
7#include "blargg_source.h"
8
9#include "multi_buffer.h"
10#include "z80_cpu.h"
11#include "ay_apu.h"
12#include "m3u_playlist.h"
13#include "track_filter.h"
14
15// 64K memory to load code and data into before starting track. Caller
16// must parse the AY file.
17enum { mem_size = 0x10000 };
18enum { ram_addr = 0x4000 }; // where official RAM starts
19
20// AY file header
21enum { header_size = 0x14 };
22struct header_t
23{
24 byte tag [8];
25 byte vers;
26 byte player;
27 byte unused [2];
28 byte author [2];
29 byte comment [2];
30 byte max_track;
31 byte first_track;
32 byte track_info [2];
33};
34
35struct file_t {
36 struct header_t const* header;
37 byte const* tracks;
38 byte const* end; // end of file data
39};
40
41struct mem_t {
42 uint8_t padding1 [0x100];
43 uint8_t ram [mem_size + 0x100];
44};
45
46struct Ay_Emu {
47 struct file_t file;
48
49 struct Blip_Buffer* beeper_output;
50 int beeper_delta;
51 int last_beeper;
52 int beeper_mask;
53
54 addr_t play_addr;
55 cpu_time_t play_period;
56 cpu_time_t next_play;
57
58 int cpc_latch;
59 bool spectrum_mode;
60 bool cpc_mode;
61
62 // general
63 int voice_count;
64 int const* voice_types;
65 int mute_mask_;
66 int tempo;
67 int gain;
68
69 int sample_rate;
70
71 // track-specific
72 int current_track;
73 int track_count;
74
75 int clock_rate_;
76 unsigned buf_changed_count;
77
78 // M3u Playlist
79 struct M3u_Playlist m3u;
80
81 // large items
82 struct setup_t tfilter;
83 struct Track_Filter track_filter;
84
85 struct Ay_Apu apu;
86 struct Multi_Buffer stereo_buf; // NULL if using custom buffer
87 struct Z80_Cpu cpu;
88 struct mem_t mem;
89};
90
91// Basic functionality (see Gme_File.h for file loading/track info functions)
92void Ay_init( struct Ay_Emu* this );
93
94blargg_err_t Ay_load_mem( struct Ay_Emu* this, byte const in [], long size );
95
96// Set output sample rate. Must be called only once before loading file.
97blargg_err_t Ay_set_sample_rate( struct Ay_Emu* this, int sample_rate );
98
99// Start a track, where 0 is the first track. Also clears warning string.
100blargg_err_t Ay_start_track( struct Ay_Emu* this, int track );
101
102// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
103// errors set warning string, and major errors also end track.
104blargg_err_t Ay_play( struct Ay_Emu* this, int count, sample_t* buf );
105
106
107// Track status/control
108
109// Number of milliseconds (1000 msec = 1 second) played since beginning of track
110int Track_tell( struct Ay_Emu* this );
111
112// Seek to new time in track. Seeking backwards or far forward can take a while.
113blargg_err_t Track_seek( struct Ay_Emu* this, int msec );
114
115// Skip n samples
116blargg_err_t Track_skip( struct Ay_Emu* this, int n );
117
118// Set start time and length of track fade out. Once fade ends track_ended() returns
119// true. Fade time can be changed while track is playing.
120void Track_set_fade( struct Ay_Emu* this, int start_msec, int length_msec );
121
122// True if a track has reached its end
123static inline bool Track_ended( struct Ay_Emu* this )
124{
125 return track_ended( &this->track_filter );
126}
127
128// Disables automatic end-of-track detection and skipping of silence at beginning
129static inline void Track_ignore_silence( struct Ay_Emu* this, bool disable )
130{
131 this->track_filter.silence_ignored_ = disable;
132}
133
134// Get track length in milliseconds
135int Track_get_length( struct Ay_Emu* this, int n );
136
137// Sound customization
138
139// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
140// Track length as returned by track_info() assumes a tempo of 1.0.
141void Sound_set_tempo( struct Ay_Emu* this, int t );
142
143// Mute/unmute voice i, where voice 0 is first voice
144void Sound_mute_voice( struct Ay_Emu* this, int index, bool mute );
145
146// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
147// 0 unmutes them all, 0x01 mutes just the first voice, etc.
148void Sound_mute_voices( struct Ay_Emu* this, int mask );
149
150// Change overall output amplitude, where 1.0 results in minimal clamping.
151// Must be called before set_sample_rate().
152static inline void Sound_set_gain( struct Ay_Emu* this, int g )
153{
154 assert( !this->sample_rate ); // you must set gain before setting sample rate
155 this->gain = g;
156}
157
158// Emulation (You shouldn't touch these)
159void cpu_out( struct Ay_Emu* this, cpu_time_t, addr_t, int data );
160void cpu_out_( struct Ay_Emu* this, cpu_time_t, addr_t, int data );
161bool run_cpu( struct Ay_Emu* this, cpu_time_t end );
162
163static inline void disable_beeper( struct Ay_Emu *this )
164{
165 this->beeper_mask = 0;
166 this->last_beeper = 0;
167}
168
169#endif
diff --git a/lib/rbcodec/codecs/libgme/blargg_common.h b/lib/rbcodec/codecs/libgme/blargg_common.h
new file mode 100644
index 0000000000..74cc227eed
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blargg_common.h
@@ -0,0 +1,160 @@
1// Sets up common environment for Shay Green's libraries.
2// To change configuration options, modify blargg_config.h, not this file.
3
4#ifndef BLARGG_COMMON_H
5#define BLARGG_COMMON_H
6
7#include <stddef.h>
8#include <stdlib.h>
9#include <string.h>
10#include <limits.h>
11
12#undef BLARGG_COMMON_H
13// allow blargg_config.h to #include blargg_common.h
14#include "blargg_config.h"
15#include "blargg_source.h"
16#ifndef BLARGG_COMMON_H
17#define BLARGG_COMMON_H
18
19#if defined(ROCKBOX)
20#include "codeclib.h"
21#endif
22
23// common defines
24#define FP_ONE_CLOCK (1LL << 12)
25#define FP_ONE_TEMPO (1LL << 24)
26#define FP_ONE_GAIN (1LL << 24)
27#define FP_ONE_VOLUME FP_ONE_GAIN
28
29// IRAM configuration
30#if (CONFIG_CPU == MCF5250)
31#define EMU2413_CALC_ICODE
32
33#elif (CONFIG_CPU == PP5022) || (CONFIG_CPU == PP5024)
34#define EMU2413_CALC_ICODE ICODE_ATTR
35
36#elif defined(CPU_S5L870X)
37#define EMU2413_CALC_ICODE
38
39#else
40#define EMU2413_CALC_ICODE
41
42#endif
43
44// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
45#if __GNUC__ >= 3 || _MSC_VER >= 1100
46 #define BLARGG_RESTRICT __restrict
47#else
48 #define BLARGG_RESTRICT
49#endif
50
51// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
52#ifndef STATIC_CAST
53 #define STATIC_CAST(T,expr) ((T) (expr))
54#endif
55
56// blargg_err_t (0 on success, otherwise error string)
57#ifndef blargg_err_t
58 typedef const char* blargg_err_t;
59#endif
60
61#define BLARGG_4CHAR( a, b, c, d ) \
62 ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
63
64// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
65#ifndef BOOST_STATIC_ASSERT
66 #ifdef _MSC_VER
67 // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
68 #define BOOST_STATIC_ASSERT( expr ) \
69 void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
70 #else
71 // Some other compilers fail when declaring same function multiple times in class,
72 // so differentiate them by line
73 #define BOOST_STATIC_ASSERT( expr ) \
74 void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
75 #endif
76#endif
77
78// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
79// compiler is assumed to support bool. If undefined, availability is determined.
80#ifndef BLARGG_COMPILER_HAS_BOOL
81 #if defined (__MWERKS__)
82 #if !__option(bool)
83 #define BLARGG_COMPILER_HAS_BOOL 0
84 #endif
85 #elif defined (_MSC_VER)
86 #if _MSC_VER < 1100
87 #define BLARGG_COMPILER_HAS_BOOL 0
88 #endif
89 #elif defined (__GNUC__)
90 // supports bool
91 #elif __cplusplus < 199711
92 #define BLARGG_COMPILER_HAS_BOOL 0
93 #endif
94#endif
95#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
96 // If you get errors here, modify your blargg_config.h file
97 typedef int bool;
98 static bool true = 1;
99 static bool false = 0;
100#endif
101
102/* My code depends on int being at least 32 bits. Almost everything these days
103uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
104to test with. The issue can't be gotten around by using a suitable blargg_int
105everywhere either, because int is often converted to implicitly when doing
106arithmetic on smaller types. */
107#if UINT_MAX < 0xFFFFFFFF
108 #error "int must be at least 32 bits"
109#endif
110
111// int8_t etc.
112
113
114// ROCKBOX: If defined, use <codeclib.h> for int_8_t etc
115#if defined (ROCKBOX)
116 #include <codecs/lib/codeclib.h>
117// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
118#elif defined (HAVE_STDINT_H)
119 #include <stdint.h>
120 #define BOOST
121
122// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
123#elif defined (HAVE_INTTYPES_H)
124 #include <inttypes.h>
125 #define BOOST
126
127#else
128 #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
129 typedef signed char int8_t;
130 typedef unsigned char uint8_t;
131 #else
132 // No suitable 8-bit type available
133 typedef struct see_blargg_common_h int8_t;
134 typedef struct see_blargg_common_h uint8_t;
135 #endif
136
137 #if USHRT_MAX == 0xFFFF
138 typedef short int16_t;
139 typedef unsigned short uint16_t;
140 #else
141 // No suitable 16-bit type available
142 typedef struct see_blargg_common_h int16_t;
143 typedef struct see_blargg_common_h uint16_t;
144 #endif
145
146 #if ULONG_MAX == 0xFFFFFFFF
147 typedef long int32_t;
148 typedef unsigned long uint32_t;
149 #elif UINT_MAX == 0xFFFFFFFF
150 typedef int int32_t;
151 typedef unsigned int uint32_t;
152 #else
153 // No suitable 32-bit type available
154 typedef struct see_blargg_common_h int32_t;
155 typedef struct see_blargg_common_h uint32_t;
156 #endif
157#endif
158
159#endif
160#endif
diff --git a/lib/rbcodec/codecs/libgme/blargg_config.h b/lib/rbcodec/codecs/libgme/blargg_config.h
new file mode 100644
index 0000000000..398913d1fe
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blargg_config.h
@@ -0,0 +1,42 @@
1// Library configuration. Modify this file as necessary.
2
3#ifndef BLARGG_CONFIG_H
4#define BLARGG_CONFIG_H
5
6// Uncomment to enable platform-specific optimizations
7//#define BLARGG_NONPORTABLE 1
8
9// Uncomment if automatic byte-order determination doesn't work
10#ifdef ROCKBOX_BIG_ENDIAN
11 #define BLARGG_BIG_ENDIAN 1
12#endif
13
14// Uncomment if you get errors in the bool section of blargg_common.h
15#define BLARGG_COMPILER_HAS_BOOL 1
16
17// Uncomment to use fast gb apu implementation
18// #define GB_APU_FAST 1
19
20// Uncomment to remove agb emulation support
21// #define GB_APU_NO_AGB 1
22
23// Uncomment to emulate only nes apu
24// #define NSF_EMU_APU_ONLY 1
25
26// Uncomment to remove vrc7 apu support
27// #define NSF_EMU_NO_VRC7 1
28
29// Uncomment to remove fmopl apu support
30// #define KSS_EMU_NO_FMOPL 1
31
32// To handle undefined reference to assert
33#define NDEBUG 1
34
35// Use standard config.h if present
36#define HAVE_CONFIG_H 1
37
38#ifdef HAVE_CONFIG_H
39 #include "config.h"
40#endif
41
42#endif
diff --git a/lib/rbcodec/codecs/libgme/blargg_endian.h b/lib/rbcodec/codecs/libgme/blargg_endian.h
new file mode 100644
index 0000000000..dce5cb2048
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blargg_endian.h
@@ -0,0 +1,168 @@
1// CPU Byte Order Utilities
2
3// Game_Music_Emu 0.5.2
4#ifndef BLARGG_ENDIAN
5#define BLARGG_ENDIAN
6
7#include "blargg_common.h"
8
9// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
10#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
11 defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
12 #define BLARGG_CPU_X86 1
13 #define BLARGG_CPU_CISC 1
14#endif
15
16#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
17 #define BLARGG_CPU_POWERPC 1
18#endif
19
20// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
21// one may be #defined to 1. Only needed if something actually depends on byte order.
22#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
23#ifdef __GLIBC__
24 // GCC handles this for us
25 #include <endian.h>
26 #if __BYTE_ORDER == __LITTLE_ENDIAN
27 #define BLARGG_LITTLE_ENDIAN 1
28 #elif __BYTE_ORDER == __BIG_ENDIAN
29 #define BLARGG_BIG_ENDIAN 1
30 #endif
31#else
32
33#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || defined (BLARGG_CPU_X86) || \
34 (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
35 #define BLARGG_LITTLE_ENDIAN 1
36#endif
37
38#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
39 defined (__mips__) || defined (__sparc__) || defined (BLARGG_CPU_POWERPC) || \
40 (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
41 #define BLARGG_BIG_ENDIAN 1
42#else
43 // No endian specified; assume little-endian, since it's most common
44 #define BLARGG_LITTLE_ENDIAN 1
45#endif
46#endif
47#endif
48
49#if defined (BLARGG_LITTLE_ENDIAN) && defined(BLARGG_BIG_ENDIAN)
50 #undef BLARGG_LITTLE_ENDIAN
51 #undef BLARGG_BIG_ENDIAN
52#endif
53
54static inline void blargg_verify_byte_order( void )
55{
56 #ifndef NDEBUG
57 #if BLARGG_BIG_ENDIAN
58 volatile int i = 1;
59 assert( *(volatile char*) &i == 0 );
60 #elif BLARGG_LITTLE_ENDIAN
61 volatile int i = 1;
62 assert( *(volatile char*) &i != 0 );
63 #endif
64 #endif
65}
66
67static inline unsigned get_le16( void const* p )
68{
69 return (unsigned) ((unsigned char const*) p) [1] << 8 |
70 (unsigned) ((unsigned char const*) p) [0];
71}
72
73static inline unsigned get_be16( void const* p )
74{
75 return (unsigned) ((unsigned char const*) p) [0] << 8 |
76 (unsigned) ((unsigned char const*) p) [1];
77}
78
79static inline unsigned get_le32( void const* p )
80{
81 return (unsigned) ((unsigned char const*) p) [3] << 24 |
82 (unsigned) ((unsigned char const*) p) [2] << 16 |
83 (unsigned) ((unsigned char const*) p) [1] << 8 |
84 (unsigned) ((unsigned char const*) p) [0];
85}
86
87static inline unsigned get_be32( void const* p )
88{
89 return (unsigned) ((unsigned char const*) p) [0] << 24 |
90 (unsigned) ((unsigned char const*) p) [1] << 16 |
91 (unsigned) ((unsigned char const*) p) [2] << 8 |
92 (unsigned) ((unsigned char const*) p) [3];
93}
94
95static inline void set_le16( void* p, unsigned n )
96{
97 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
98 ((unsigned char*) p) [0] = (unsigned char) n;
99}
100
101static inline void set_be16( void* p, unsigned n )
102{
103 ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
104 ((unsigned char*) p) [1] = (unsigned char) n;
105}
106
107static inline void set_le32( void* p, unsigned n )
108{
109 ((unsigned char*) p) [0] = (unsigned char) n;
110 ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
111 ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
112 ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
113}
114
115static inline void set_be32( void* p, unsigned n )
116{
117 ((unsigned char*) p) [3] = (unsigned char) n;
118 ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
119 ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
120 ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
121}
122
123#if defined(BLARGG_NONPORTABLE)
124 // Optimized implementation if byte order is known
125 #if defined(BLARGG_LITTLE_ENDIAN)
126 #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr))
127 #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr))
128 #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
129 #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
130 #elif defined(BLARGG_BIG_ENDIAN)
131 #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr))
132 #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
133 #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
134 #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
135 #endif
136
137 #if defined(BLARGG_CPU_POWERPC) && defined (__MWERKS__)
138 // PowerPC has special byte-reversed instructions
139 // to do: assumes that PowerPC is running in big-endian mode
140 // to do: implement for other compilers which don't support these macros
141 #define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
142 #define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
143 #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
144 #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
145 #endif
146#endif
147
148#ifndef GET_LE16
149 #define GET_LE16( addr ) get_le16( addr )
150 #define SET_LE16( addr, data ) set_le16( addr, data )
151#endif
152
153#ifndef GET_LE32
154 #define GET_LE32( addr ) get_le32( addr )
155 #define SET_LE32( addr, data ) set_le32( addr, data )
156#endif
157
158#ifndef GET_BE16
159 #define GET_BE16( addr ) get_be16( addr )
160 #define SET_BE16( addr, data ) set_be16( addr, data )
161#endif
162
163#ifndef GET_BE32
164 #define GET_BE32( addr ) get_be32( addr )
165 #define SET_BE32( addr, data ) set_be32( addr, data )
166#endif
167
168#endif
diff --git a/lib/rbcodec/codecs/libgme/blargg_source.h b/lib/rbcodec/codecs/libgme/blargg_source.h
new file mode 100644
index 0000000000..ab8e1b072b
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blargg_source.h
@@ -0,0 +1,76 @@
1// Included at the beginning of library source files, after all other #include lines
2#ifndef BLARGG_SOURCE_H
3#define BLARGG_SOURCE_H
4
5// If debugging is enabled and expr is false, abort program. Meant for checking
6// caller-supplied parameters and operations that are outside the control of the
7// module. A failed requirement indicates a bug outside the module.
8// void require( bool expr );
9#if defined(ROCKBOX)
10#undef assert
11#define assert( expr )
12#undef require
13#define require( expr )
14#else
15#undef require
16#define require( expr ) assert( expr )
17#endif
18
19// Like printf() except output goes to debug log file. Might be defined to do
20// nothing (not even evaluate its arguments).
21// void dprintf( const char* format, ... );
22#if defined(ROCKBOX)
23#define dprintf DEBUGF
24#else
25static inline void blargg_dprintf_( const char* fmt, ... ) { }
26#undef dprintf
27#define dprintf (1) ? (void) 0 : blargg_dprintf_
28#endif
29
30// If enabled, evaluate expr and if false, make debug log entry with source file
31// and line. Meant for finding situations that should be examined further, but that
32// don't indicate a problem. In all cases, execution continues normally.
33#undef check
34#define check( expr ) ((void) 0)
35
36/* If expr yields non-NULL error string, returns it from current function,
37otherwise continues normally. */
38#undef RETURN_ERR
39#define RETURN_ERR( expr ) \
40 do {\
41 blargg_err_t blargg_return_err_ = (expr);\
42 if ( blargg_return_err_ )\
43 return blargg_return_err_;\
44 } while ( 0 )
45
46/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
47#undef CHECK_ALLOC
48#define CHECK_ALLOC( ptr ) \
49 do {\
50 if ( !(ptr) )\
51 return "Out of memory";\
52 } while ( 0 )
53
54#ifndef max
55 #define max(a,b) (((a) > (b)) ? (a) : (b))
56#endif
57
58#ifndef min
59 #define min(a,b) (((a) < (b)) ? (a) : (b))
60#endif
61
62// typedef unsigned char byte;
63typedef unsigned char blargg_byte;
64#undef byte
65#define byte blargg_byte
66
67// deprecated
68#define BLARGG_CHECK_ALLOC CHECK_ALLOC
69#define BLARGG_RETURN_ERR RETURN_ERR
70
71// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
72#ifdef BLARGG_SOURCE_BEGIN
73 #include BLARGG_SOURCE_BEGIN
74#endif
75
76#endif
diff --git a/lib/rbcodec/codecs/libgme/blip_buffer.c b/lib/rbcodec/codecs/libgme/blip_buffer.c
new file mode 100644
index 0000000000..ba0a6558d2
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blip_buffer.c
@@ -0,0 +1,225 @@
1// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
2
3#include "blip_buffer.h"
4
5#include <limits.h>
6#include <string.h>
7#include <stdlib.h>
8#include <math.h>
9
10/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
11can redistribute it and/or modify it under the terms of the GNU Lesser
12General Public License as published by the Free Software Foundation; either
13version 2.1 of the License, or (at your option) any later version. This
14module is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
17details. You should have received a copy of the GNU Lesser General Public
18License along with this module; if not, write to the Free Software Foundation,
19Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
20
21#include "blargg_source.h"
22
23void Blip_init( struct Blip_Buffer* this )
24{
25 this->factor_ = UINT_MAX/2 + 1;;
26 this->buffer_center_ = NULL;
27 this->buffer_size_ = 0;
28 this->sample_rate_ = 0;
29 this->bass_shift_ = 0;
30 this->clock_rate_ = 0;
31 this->bass_freq_ = 16;
32 this->length_ = 0;
33
34 // assumptions code makes about implementation-defined features
35 #ifndef NDEBUG
36 // right shift of negative value preserves sign
37 buf_t_ i = -0x7FFFFFFE;
38 assert( (i >> 1) == -0x3FFFFFFF );
39
40 // casting to short truncates to 16 bits and sign-extends
41 i = 0x18000;
42 assert( (short) i == -0x8000 );
43 #endif
44
45 Blip_clear( this );
46}
47
48void Blip_clear( struct Blip_Buffer* this )
49{
50 bool const entire_buffer = true;
51
52 this->offset_ = 0;
53 this->reader_accum_ = 0;
54 this->modified = false;
55
56 if ( this->buffer_ )
57 {
58 int count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this ));
59 memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (delta_t) );
60 }
61}
62
63blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, int new_rate, int msec )
64{
65 // Limit to maximum size that resampled time can represent
66 int max_size = (((blip_resampled_time_t) -1) >> BLIP_BUFFER_ACCURACY) -
67 blip_buffer_extra_ - 64; // TODO: -64 isn't needed
68 int new_size = (new_rate * (msec + 1) + 999) / 1000;
69 if ( new_size > max_size )
70 new_size = max_size;
71
72 // Resize buffer
73 if ( this->buffer_size_ != new_size ) {
74 this->buffer_center_ = this->buffer_ + BLIP_MAX_QUALITY/2;
75 this->buffer_size_ = new_size;
76 }
77
78 // update things based on the sample rate
79 this->sample_rate_ = new_rate;
80 this->length_ = new_size * 1000 / new_rate - 1;
81 if ( this->clock_rate_ )
82 Blip_set_clock_rate( this, this->clock_rate_ );
83 Blip_bass_freq( this, this->bass_freq_ );
84
85 Blip_clear( this );
86
87 return 0; // success
88}
89
90blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, int rate )
91{
92 int factor = (int) ( this->sample_rate_ * (1LL << BLIP_BUFFER_ACCURACY) / rate);
93 assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large
94 return (blip_resampled_time_t) factor;
95}
96
97void Blip_bass_freq( struct Blip_Buffer* this, int freq )
98{
99 this->bass_freq_ = freq;
100 int shift = 31;
101 if ( freq > 0 && this->sample_rate_ )
102 {
103 shift = 13;
104 int f = (freq << 16) / this->sample_rate_;
105 while ( (f >>= 1) && --shift ) { }
106 }
107 this->bass_shift_ = shift;
108}
109
110void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t )
111{
112 this->offset_ += t * this->factor_;
113 assert( Blip_samples_avail( this ) <= (int) this->buffer_size_ ); // time outside buffer length
114}
115
116int Blip_count_samples( struct Blip_Buffer* this, blip_time_t t )
117{
118 blip_resampled_time_t last_sample = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY;
119 blip_resampled_time_t first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
120 return (int) (last_sample - first_sample);
121}
122
123blip_time_t Blip_count_clocks( struct Blip_Buffer* this, int count )
124{
125 if ( count > this->buffer_size_ )
126 count = this->buffer_size_;
127 blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
128 return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_);
129}
130
131void Blip_remove_samples( struct Blip_Buffer* this, int count )
132{
133 if ( count )
134 {
135 Blip_remove_silence( this, count );
136
137 // copy remaining samples to beginning and clear old samples
138 int remain = Blip_samples_avail( this ) + blip_buffer_extra_;
139 memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ );
140 memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ );
141 }
142}
143
144int Blip_read_samples( struct Blip_Buffer* this, blip_sample_t out_ [], int max_samples, bool stereo )
145{
146 int count = Blip_samples_avail( this );
147 if ( count > max_samples )
148 count = max_samples;
149
150 if ( count )
151 {
152 int const bass = this->bass_shift_;
153 delta_t const* reader = this->buffer_ + count;
154 int reader_sum = this->reader_accum_;
155
156 blip_sample_t* BLARGG_RESTRICT out = out_ + count;
157 if ( stereo )
158 out += count;
159 int offset = -count;
160
161 if ( !stereo )
162 {
163 do
164 {
165 int s = reader_sum >> delta_bits;
166
167 reader_sum -= reader_sum >> bass;
168 reader_sum += reader [offset];
169
170 BLIP_CLAMP( s, s );
171 out [offset] = (blip_sample_t) s;
172 }
173 while ( ++offset );
174 }
175 else
176 {
177 do
178 {
179 int s = reader_sum >> delta_bits;
180
181 reader_sum -= reader_sum >> bass;
182 reader_sum += reader [offset];
183
184 BLIP_CLAMP( s, s );
185 out [offset * 2] = (blip_sample_t) s;
186 }
187 while ( ++offset );
188 }
189
190 this->reader_accum_ = reader_sum;
191
192 Blip_remove_samples( this, count );
193 }
194 return count;
195}
196
197void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const in [], int count )
198{
199 delta_t* out = this->buffer_center_ + (this->offset_ >> BLIP_BUFFER_ACCURACY);
200
201 int const sample_shift = blip_sample_bits - 16;
202 int prev = 0;
203 while ( --count >= 0 )
204 {
205 int s = *in++ << sample_shift;
206 *out += s - prev;
207 prev = s;
208 ++out;
209 }
210 *out -= prev;
211}
212
213// Blip_Synth
214
215void volume_unit( struct Blip_Synth* this, int new_unit )
216{
217 this->delta_factor = (int) (new_unit * (1LL << blip_sample_bits) / FP_ONE_VOLUME);
218}
219
220void Synth_init( struct Blip_Synth* this )
221{
222 this->buf = 0;
223 this->last_amp = 0;
224 this->delta_factor = 0;
225}
diff --git a/lib/rbcodec/codecs/libgme/blip_buffer.h b/lib/rbcodec/codecs/libgme/blip_buffer.h
new file mode 100644
index 0000000000..5fe1f4b9c6
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/blip_buffer.h
@@ -0,0 +1,335 @@
1// Band-limited sound synthesis buffer
2
3// Blip_Buffer 0.4.1
4#ifndef BLIP_BUFFER_H
5#define BLIP_BUFFER_H
6
7#include "blargg_common.h"
8
9typedef unsigned blip_resampled_time_t;
10typedef int blip_time_t;
11typedef int clocks_t;
12
13// Output samples are 16-bit signed, with a range of -32768 to 32767
14typedef short blip_sample_t;
15
16static int const blip_default_length = 1000 / 4; // Default Blip_Buffer length (1/4 second)
17
18#ifndef BLIP_MAX_QUALITY
19 #define BLIP_MAX_QUALITY 2
20#endif
21
22#ifndef BLIP_BUFFER_ACCURACY
23 #define BLIP_BUFFER_ACCURACY 16
24#endif
25
26// linear interpolation needs 8 bits
27#ifndef BLIP_PHASE_BITS
28 #define BLIP_PHASE_BITS 8
29#endif
30
31static int const blip_res = 1 << BLIP_PHASE_BITS;
32static int const blip_buffer_extra_ = BLIP_MAX_QUALITY + 2;
33
34// Properties of fixed-point sample position
35typedef unsigned ufixed_t; // unsigned for more range, optimized shifts
36enum { fixed_bits = BLIP_BUFFER_ACCURACY }; // bits in fraction
37enum { fixed_unit = 1 << fixed_bits }; // 1.0 samples
38
39// Deltas in buffer are fixed-point with this many fraction bits.
40// Less than 16 for extra range.
41enum { delta_bits = 14 };
42
43// Pointer to first committed delta sample
44typedef int delta_t;
45
46// Maximun buffer size (48Khz, 50 ms)
47enum { blip_buffer_max = 2466 };
48
49struct Blip_Buffer {
50 unsigned factor_;
51 ufixed_t offset_;
52 delta_t* buffer_center_;
53 int buffer_size_;
54 int reader_accum_;
55 int bass_shift_;
56 int bass_freq_;
57 int sample_rate_;
58 int clock_rate_;
59 int length_;
60 bool modified;
61
62 delta_t buffer_ [blip_buffer_max];
63};
64
65// Blip_Buffer_ implementation
66static inline ufixed_t to_fixed( struct Blip_Buffer *this, clocks_t t )
67{
68 return t * this->factor_ + this->offset_;
69}
70
71static inline delta_t* delta_at( struct Blip_Buffer *this, ufixed_t f )
72{
73 assert( (f >> fixed_bits) < (unsigned) this->buffer_size_ );
74 return this->buffer_center_ + (f >> fixed_bits);
75}
76
77// Number of samples available for reading with read_samples()
78static inline int Blip_samples_avail( struct Blip_Buffer* this )
79{
80 return (int) (this->offset_ >> BLIP_BUFFER_ACCURACY);
81}
82
83static inline void Blip_remove_silence( struct Blip_Buffer* this, int count )
84{
85 assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available
86 this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
87}
88
89// Initializes Blip_Buffer structure
90void Blip_init( struct Blip_Buffer* this );
91
92// Sets output sample rate and resizes and clears sample buffer
93blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, int samples_per_sec, int msec_length );
94
95// Current output sample rate
96static inline int Blip_sample_rate( struct Blip_Buffer* this )
97{
98 return this->sample_rate_;
99}
100
101// Sets number of source time units per second
102blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, int clock_rate );
103static inline void Blip_set_clock_rate( struct Blip_Buffer* this, int clocks_per_sec )
104{
105 this->factor_ = Blip_clock_rate_factor( this, this->clock_rate_ = clocks_per_sec );
106}
107
108// Number of source time units per second
109static inline int Blip_clock_rate( struct Blip_Buffer* this )
110{
111 return this->clock_rate_;
112}
113
114static inline int Blip_length( struct Blip_Buffer* this )
115{
116 return this->length_;
117}
118
119// Clears buffer and removes all samples
120void Blip_clear( struct Blip_Buffer* this );
121
122// Use Blip_Synth to add waveform to buffer
123
124// Resamples to time t, then subtracts t from current time. Appends result of resampling
125// to buffer for reading.
126void Blip_end_frame( struct Blip_Buffer* this, blip_time_t time ) ICODE_ATTR;
127
128
129// Reads at most n samples to out [0 to n-1] and returns number actually read. If stereo
130// is true, writes to out [0], out [2], out [4] etc. instead.
131int Blip_read_samples( struct Blip_Buffer* this, blip_sample_t out [], int n, bool stereo ) ICODE_ATTR;
132
133
134// More features
135
136// Sets flag that tells some Multi_Buffer types that sound was added to buffer,
137// so they know that it needs to be mixed in. Only needs to be called once
138// per time frame that sound was added. Not needed if not using Multi_Buffer.
139static inline void Blip_set_modified( struct Blip_Buffer* this ) { this->modified = true; }
140
141// Set frequency high-pass filter frequency, where higher values reduce bass more
142void Blip_bass_freq( struct Blip_Buffer* this, int frequency );
143
144
145// Low-level features
146
147// Removes the first n samples
148void Blip_remove_samples( struct Blip_Buffer* this, int n ) ICODE_ATTR;
149
150// Returns number of clocks needed until n samples will be available.
151// If buffer cannot even hold n samples, returns number of clocks
152// until buffer becomes full.
153blip_time_t Blip_count_clocks( struct Blip_Buffer* this, int count ) ICODE_ATTR;
154
155// Number of samples that should be mixed before calling Blip_end_frame( t )
156int Blip_count_samples( struct Blip_Buffer* this, blip_time_t t ) ICODE_ATTR;
157
158// Mixes n samples into buffer
159void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const in [], int n ) ICODE_ATTR;
160
161
162// Resampled time (sorry, poor documentation right now)
163
164// Resampled time is fixed-point, in terms of output samples.
165
166// Converts clock count to resampled time
167static inline blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t )
168{
169 return t * this->factor_;
170}
171
172// Converts clock time since beginning of current time frame to resampled time
173static inline blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t )
174{
175 return t * this->factor_ + this->offset_;
176}
177
178
179// Range specifies the greatest expected change in amplitude. Calculate it
180// by finding the difference between the maximum and minimum expected
181// amplitudes (max - min).
182
183typedef char coeff_t;
184
185struct Blip_Synth {
186 int delta_factor;
187 int last_amp;
188 struct Blip_Buffer* buf;
189};
190
191// Blip_Synth_
192void volume_unit( struct Blip_Synth* this, int new_unit );
193
194// Initializes Blip_Synth structure
195void Synth_init( struct Blip_Synth* this );
196
197// Sets volume of amplitude delta unit
198static inline void Synth_volume( struct Blip_Synth* this, int v )
199{
200 volume_unit( this, v ); // new_unit = 1 / range * v
201}
202
203
204// Low-level interface
205
206// (in >> sh & mask) * mul
207#define BLIP_SH_AND_MUL( in, sh, mask, mul ) \
208((int) (in) / ((1U << (sh)) / (mul)) & (unsigned) ((mask) * (mul)))
209
210// (T*) ptr + (off >> sh)
211#define BLIP_PTR_OFF_SH( T, ptr, off, sh ) \
212 ((T*) (BLIP_SH_AND_MUL( off, sh, -1, sizeof (T) ) + (char*) (ptr)))
213
214// Works directly in terms of fractional output samples. Use resampled time functions in Blip_Buffer
215// to convert clock counts to resampled time.
216static inline void Synth_offset_resampled( struct Blip_Synth* this, blip_resampled_time_t time,
217 int delta, struct Blip_Buffer* blip_buf )
218{
219 int const half_width = 1;
220
221 delta_t* BLARGG_RESTRICT buf = delta_at( blip_buf, time );
222 delta *= this->delta_factor;
223
224 int const phase_shift = BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS;
225 int const phase = (half_width & (half_width - 1)) ?
226 (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) ) * half_width :
227 (int) BLIP_SH_AND_MUL( time, phase_shift, blip_res - 1, sizeof (coeff_t) * half_width );
228
229 int left = buf [0] + delta;
230
231 // Kind of crappy, but doing shift after multiply results in overflow.
232 // Alternate way of delaying multiply by delta_factor results in worse
233 // sub-sample resolution.
234 int right = (delta >> BLIP_PHASE_BITS) * phase;
235 #ifdef BLIP_BUFFER_NOINTERP
236 // TODO: remove? (just a hack to see how it sounds)
237 right = 0;
238 #endif
239 left -= right;
240 right += buf [1];
241
242 buf [0] = left;
243 buf [1] = right;
244}
245
246// Update amplitude of waveform at given time. Using this requires a separate
247// Blip_Synth for each waveform.
248static inline void Synth_update( struct Blip_Synth* this, blip_time_t t, int amp )
249{
250 int delta = amp - this->last_amp;
251 this->last_amp = amp;
252 Synth_offset_resampled( this, to_fixed(this->buf, t), delta, this->buf );
253}
254
255// Adds amplitude transition at time t. Delta can be positive or negative.
256// The actual change in amplitude is delta * volume.
257static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf )
258{
259 Synth_offset_resampled( this, to_fixed(buf, t), delta, buf );
260}
261
262#define Synth_offset( synth, time, delta, buf ) Synth_offset_inline( synth, time, delta, buf )
263
264// Number of bits in raw sample that covers normal output range. Less than 32 bits to give
265// extra amplitude range. That is,
266// +1 << (blip_sample_bits-1) = +1.0
267// -1 << (blip_sample_bits-1) = -1.0
268static int const blip_sample_bits = 30;
269
270// Optimized reading from Blip_Buffer, for use in custom sample output
271
272// Begin reading from buffer. Name should be unique to the current block.
273#define BLIP_READER_BEGIN( name, blip_buffer ) \
274 const delta_t* BLARGG_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
275 int name##_reader_accum = (blip_buffer).reader_accum_
276
277// Get value to pass to BLIP_READER_NEXT()
278#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
279
280// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
281// code at the cost of having no bass_freq() functionality
282static int const blip_reader_default_bass = 9;
283
284// Current sample
285#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
286
287// Current raw sample in full internal resolution
288#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
289
290// Advance to next sample
291#define BLIP_READER_NEXT( name, bass ) \
292 (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
293
294// End reading samples from buffer. The number of samples read must now be removed
295// using Blip_remove_samples().
296#define BLIP_READER_END( name, blip_buffer ) \
297 (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
298
299#define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset)
300
301#define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\
302 name##_reader_accum -= name##_reader_accum >> (bass);\
303 name##_reader_accum += name##_reader_buf [(idx)];\
304}
305
306#define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\
307 name##_reader_accum -= name##_reader_accum >> (bass);\
308 name##_reader_accum +=\
309 *(delta_t const*) ((char const*) name##_reader_buf + (idx));\
310}
311
312//// BLIP_CLAMP
313
314#if defined(CPU_ARM) && (ARM_ARCH >= 6)
315 #define BLIP_CLAMP( sample, out ) \
316 ({ \
317 asm ("ssat %0, #16, %1" \
318 : "=r" ( out ) : "r"( sample ) ); \
319 out; \
320 })
321#else
322 #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
323 defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
324 #define BLIP_X86 1
325 #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in
326 #else
327 #define BLIP_CLAMP_( in ) (blip_sample_t) in != in
328 #endif
329
330 // Clamp sample to blip_sample_t range
331 #define BLIP_CLAMP( sample, out )\
332 { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 31) ^ 0x7FFF; }
333#endif
334
335#endif
diff --git a/lib/rbcodec/codecs/libgme/emu2413.c b/lib/rbcodec/codecs/libgme/emu2413.c
new file mode 100644
index 0000000000..01075821cb
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emu2413.c
@@ -0,0 +1,1981 @@
1/***********************************************************************************
2
3 emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
4
5 2001 01-08 : Version 0.10 -- 1st version.
6 2001 01-15 : Version 0.20 -- semi-public version.
7 2001 01-16 : Version 0.30 -- 1st public version.
8 2001 01-17 : Version 0.31 -- Fixed bassdrum problem.
9 : Version 0.32 -- LPF implemented.
10 2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method.
11 -- Fixed the LFO bug.
12 2001 01-24 : Version 0.35 -- Fixed the drum problem,
13 support undocumented EG behavior.
14 2001 02-02 : Version 0.38 -- Improved the performance.
15 Fixed the hi-hat and cymbal model.
16 Fixed the default percussive datas.
17 Noise reduction.
18 Fixed the feedback problem.
19 2001 03-03 : Version 0.39 -- Fixed some drum bugs.
20 Improved the performance.
21 2001 03-04 : Version 0.40 -- Improved the feedback.
22 Change the default table size.
23 Clock and Rate can be changed during play.
24 2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone.
25 Added VRC7 patch (OPLL_reset_patch is changed).
26 Fixed OPLL_reset() bug.
27 Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask.
28 Added OPLL_writeIO.
29 2001 09-28 : Version 0.51 -- Removed the noise table.
30 2002 01-28 : Version 0.52 -- Added Stereo mode.
31 2002 02-07 : Version 0.53 -- Fixed some drum bugs.
32 2002 02-20 : Version 0.54 -- Added the best quality mode.
33 2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close.
34 2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas.
35 2004 04-10 : Version 0.61 -- Added YMF281B tone (defined by Chabin).
36
37 2011 03-22 : --------------- Modified by gama to use precalculated tables.
38
39 References:
40 fmopl.c -- 1999,2000 written by Tatsuyuki Satoh (MAME development).
41 fmopl.c(fixed) -- (C) 2002 Jarek Burczynski.
42 s_opl.c -- 2001 written by Mamiya (NEZplug development).
43 fmgen.cpp -- 1999,2000 written by cisc.
44 fmpac.ill -- 2000 created by NARUTO.
45 MSX-Datapack
46 YMU757 data sheet
47 YM2143 data sheet
48
49**************************************************************************************/
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <math.h>
54#include "emu2413.h"
55
56#include "emutables.h"
57#if !defined(ROCKBOX)
58 #define EMU2413_CALCUL_TABLES
59#else
60 #define EMU2413_COMPACTION
61 #include "emutables.h"
62#endif
63
64#if defined(EMU2413_COMPACTION) && !defined(ROCKBOX)
65#define OPLL_TONE_NUM 1
66static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
67 {
68#include "2413tone.h"
69 }
70};
71#else
72#define OPLL_TONE_NUM 3
73static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 16] = {
74 {
75#include "2413tone.h"
76 },
77 {
78#include "vrc7tone.h"
79 },
80 {
81#include "281btone.h"
82 }
83};
84#endif
85
86/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.) */
87#define PG_BITS 9
88#define PG_WIDTH (1<<PG_BITS)
89
90/* Phase increment counter */
91#define DP_BITS 18
92#define DP_WIDTH (1<<DP_BITS)
93#define DP_BASE_BITS (DP_BITS - PG_BITS)
94
95/* Dynamic range (Accuracy of sin table) */
96#define DB_PREC 48
97#define DB_BITS 8
98#define DB_STEP ((double)DB_PREC/(1<<DB_BITS))
99#define DB_MUTE (1<<DB_BITS)
100
101/* Dynamic range of envelope */
102#define EG_STEP 0.375
103#define EG_BITS 7
104#define EG_MUTE (1<<EG_BITS)
105
106/* Dynamic range of total level */
107#define TL_STEP 0.75
108#define TL_BITS 6
109#define TL_MUTE (1<<TL_BITS)
110
111/* Dynamic range of sustine level */
112#define SL_STEP 3.0
113#define SL_BITS 4
114#define SL_MUTE (1<<SL_BITS)
115
116#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
117#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
118#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
119
120#define DB_POS(x) (x*DB_MUTE/DB_PREC)
121#define DB_NEG(x) (DB_MUTE+DB_MUTE+x*DB_MUTE/DB_PREC)
122
123/* Bits for liner value */
124#define DB2LIN_AMP_BITS 8
125#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
126
127/* Bits for envelope phase incremental counter */
128#define EG_DP_BITS 22
129#define EG_DP_WIDTH (1<<EG_DP_BITS)
130
131/* Bits for Pitch and Amp modulator */
132#define PM_PG_BITS 8
133#define PM_PG_WIDTH (1<<PM_PG_BITS)
134#define PM_DP_BITS 16
135#define PM_DP_WIDTH (1<<PM_DP_BITS)
136#define AM_PG_BITS 8
137#define AM_PG_WIDTH (1<<AM_PG_BITS)
138#define AM_DP_BITS 16
139#define AM_DP_WIDTH (1<<AM_DP_BITS)
140
141/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
142#define PM_AMP_BITS 8
143#define PM_AMP (1<<PM_AMP_BITS)
144
145/* PM speed(Hz) and depth(cent) */
146#define PM_SPEED 6.4
147#define PM_DEPTH 13.75
148
149/* AM speed(Hz) and depth(dB) */
150#define AM_SPEED 3.6413
151#define AM_DEPTH 4.875
152
153/* Cut the lower b bit(s) off. */
154#define HIGHBITS(c,b) ((c)>>(b))
155
156/* Leave the lower b bit(s). */
157#define LOWBITS(c,b) ((c)&((1<<(b))-1))
158
159/* Expand x which is s bits to d bits. */
160#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s)))
161
162/* Expand x which is s bits to d bits and fill expanded bits '1' */
163#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
164
165/* Adjust envelope speed which depends on sampling rate. */
166#define RATE_ADJUST(x) (rate==49716?(e_uint32)x:(e_uint32)(((long long)(x)*clk/rate+36)/72))
167
168#define MOD(o,x) (&(o)->slot[(x)<<1])
169#define CAR(o,x) (&(o)->slot[((x)<<1)|1])
170
171#define BIT(s,b) (((s)>>(b))&1)
172
173/* Input clock */
174static e_uint32 clk = 844451141;
175/* Sampling rate */
176static e_uint32 rate = 3354932;
177
178/* WaveTable for each envelope amp */
179static e_uint16 fullsintable[PG_WIDTH];
180static e_uint16 halfsintable[PG_WIDTH];
181
182static e_uint16 *waveform[2] = { fullsintable, halfsintable };
183
184/* LFO Table */
185#ifdef EMU2413_CALCUL_TABLES
186 static e_int32 pmtable[PM_PG_WIDTH];
187 static e_int32 amtable[AM_PG_WIDTH];
188 #define PMTABLE(x) pmtable[x]
189 #define AMTABLE(x) amtable[x]
190#else
191 #define PMTABLE(x) (e_int32)pm_coeff[x]
192 #if (PM_PG_WIDTH != 256)
193 #error PM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
194 #endif
195 #define AMTABLE(x) (e_int32)am_coeff[x]
196 #if (AM_PG_WIDTH != 256)
197 #error AM_PG_WIDTH must be set to 256 if EMU2413_CALCUL_TABLES is not defined
198 #endif
199#endif
200
201/* Phase delta for LFO */
202static e_uint32 pm_dphase;
203static e_uint32 am_dphase;
204
205/* dB to Liner table */
206static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2];
207
208/* Liner to Log curve conversion table (for Attack rate). */
209#ifdef EMU2413_CALCUL_TABLES
210 static e_uint16 ar_adjust_table[1 << EG_BITS];
211 #define AR_ADJUST_TABLE(x) ar_adjust_table[x]
212#else
213 #define AR_ADJUST_TABLE(x) ar_adjust_coeff[x]
214 #if (EG_BITS != 7)
215 #error EG_BITS must be set to 7 if EMU2413_CALCUL_TABLES is not defined
216 #endif
217#endif
218
219/* Empty voice data */
220static OPLL_PATCH null_patch = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
221
222/* Basic voice Data */
223static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2];
224
225/* Definition of envelope mode */
226enum OPLL_EG_STATE
227{ READY, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, SETTLE, FINISH };
228
229/* Phase incr table for Attack */
230static e_uint32 dphaseARTable[16][16];
231/* Phase incr table for Decay and Release */
232static e_uint32 dphaseDRTable[16][16];
233
234/* KSL + TL Table */
235e_uint8 tllTable[16][8][1 << TL_BITS][4];
236static e_int32 rksTable[2][8][2];
237
238/* We may not have too much SRAM in rockbox */
239#if !defined(ROCKBOX)
240/* Phase incr table for PG */
241static e_uint32 dphaseTable[512][8][16];
242#endif
243
244/***************************************************
245
246 Create tables
247
248****************************************************/
249#ifdef EMU2413_CALCUL_TABLES
250INLINE static e_int32
251Min (e_int32 i, e_int32 j)
252{
253 if (i < j)
254 return i;
255 else
256 return j;
257}
258
259/* Table for AR to LogCurve. */
260static void
261makeAdjustTable (void)
262{
263 e_int32 i;
264
265 ar_adjust_table[0] = (1 << EG_BITS) - 1;
266 for (i = 1; i < (1<<EG_BITS); i++)
267 ar_adjust_table[i] = (e_uint16) ((double) (1<<EG_BITS)-1 - ((1<<EG_BITS)-1)*log(i)/log(127));
268}
269#endif
270
271/* Table for dB(0 -- (1<<DB_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
272static void
273makeDB2LinTable (void)
274{
275 e_int32 i;
276 for (i = 0; i < DB_MUTE + DB_MUTE; i++)
277 {
278 #ifdef EMU2413_CALCUL_TABLES
279 DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
280 #else
281 DB2LIN_TABLE[i] = db2lin_coeff[i];
282 #endif
283 if (i >= DB_MUTE) DB2LIN_TABLE[i] = 0;
284 DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]);
285 }
286}
287
288#ifdef EMU2413_CALCUL_TABLES
289/* Liner(+0.0 - +1.0) to dB((1<<DB_BITS) - 1 -- 0) */
290static e_int32
291lin2db (double d)
292{
293 if (d == 0)
294 return (DB_MUTE - 1);
295 else
296 return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1); /* 0 -- 127 */
297}
298#endif
299
300/* Sin Table */
301static void
302makeSinTable (void)
303{
304 e_int32 i;
305
306 for (i = 0; i < PG_WIDTH / 4; i++)
307 #ifdef EMU2413_CALCUL_TABLES
308 fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
309 #else
310 fullsintable[i] = sin_coeff[i];
311 #endif
312
313 for (i = 0; i < PG_WIDTH / 4; i++)
314 {
315 fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
316 }
317
318 for (i = 0; i < PG_WIDTH / 2; i++)
319 {
320 fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
321 }
322
323 for (i = 0; i < PG_WIDTH / 2; i++)
324 halfsintable[i] = fullsintable[i];
325 for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
326 halfsintable[i] = fullsintable[0];
327}
328
329#ifdef EMU2413_CALCUL_TABLES
330static double saw(double phase)
331{
332 if(phase <= PI/2)
333 return phase * 2 / PI ;
334 else if(phase <= PI*3/2)
335 return 2.0 - ( phase * 2 / PI );
336 else
337 return -4.0 + phase * 2 / PI;
338}
339
340/* Table for Pitch Modulator */
341static void
342makePmTable (void)
343{
344 e_int32 i;
345
346 for (i = 0; i < PM_PG_WIDTH; i++)
347 /* pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200)); */
348 pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * saw (2.0 * PI * i / PM_PG_WIDTH) / 1200));
349}
350
351/* Table for Amp Modulator */
352static void
353makeAmTable (void)
354{
355 e_int32 i;
356
357 for (i = 0; i < AM_PG_WIDTH; i++)
358 /* amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH))); */
359 amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + saw (2.0 * PI * i / PM_PG_WIDTH)));
360}
361#endif
362
363#if !defined(ROCKBOX)
364/* Phase increment counter table */
365static void
366makeDphaseTable (void)
367{
368 e_uint32 fnum, block, ML;
369 e_uint32 mltable[16] =
370 { 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 };
371
372 for (fnum = 0; fnum < 512; fnum++)
373 for (block = 0; block < 8; block++)
374 for (ML = 0; ML < 16; ML++)
375 dphaseTable[fnum][block][ML] = RATE_ADJUST (((fnum * mltable[ML]) << block) >> (20 - DP_BITS));
376}
377#endif
378
379static void
380makeTllTable (void)
381{
382/* Multiplication owith 8 to have an integer result. This allows to remove floating point operation. */
383#define dB2(x) (int)((x)*2*8)
384
385 static int kltable[16] = {
386 dB2 ( 0.000), dB2 ( 9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625),
387 dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000)
388 };
389
390 e_int32 tmp;
391 e_int32 fnum, block, TL, KL;
392
393 for (fnum = 0; fnum < 16; fnum++)
394 for (block = 0; block < 8; block++)
395 for (TL = 0; TL < 64; TL++)
396 for (KL = 0; KL < 4; KL++)
397 {
398 if (KL == 0)
399 {
400 tllTable[fnum][block][TL][KL] = TL2EG (TL);
401 }
402 else
403 {
404 tmp = (e_int32) ((kltable[fnum] - dB2 (3.000) * (7 - block))/8);
405 if (tmp <= 0)
406 tllTable[fnum][block][TL][KL] = TL2EG (TL);
407 else
408 /* tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL); */
409 tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp << KL) / (int)(EG_STEP*8)) + TL2EG (TL);
410 }
411 }
412}
413
414#ifdef USE_SPEC_ENV_SPEED
415static double attacktime[16][4] = {
416 {0, 0, 0, 0},
417 {1730.15, 1400.60, 1153.43, 988.66},
418 {865.08, 700.30, 576.72, 494.33},
419 {432.54, 350.15, 288.36, 247.16},
420 {216.27, 175.07, 144.18, 123.58},
421 {108.13, 87.54, 72.09, 61.79},
422 {54.07, 43.77, 36.04, 30.90},
423 {27.03, 21.88, 18.02, 15.45},
424 {13.52, 10.94, 9.01, 7.72},
425 {6.76, 5.47, 4.51, 3.86},
426 {3.38, 2.74, 2.25, 1.93},
427 {1.69, 1.37, 1.13, 0.97},
428 {0.84, 0.70, 0.60, 0.54},
429 {0.50, 0.42, 0.34, 0.30},
430 {0.28, 0.22, 0.18, 0.14},
431 {0.00, 0.00, 0.00, 0.00}
432};
433
434static double decaytime[16][4] = {
435 {0, 0, 0, 0},
436 {20926.60, 16807.20, 14006.00, 12028.60},
437 {10463.30, 8403.58, 7002.98, 6014.32},
438 {5231.64, 4201.79, 3501.49, 3007.16},
439 {2615.82, 2100.89, 1750.75, 1503.58},
440 {1307.91, 1050.45, 875.37, 751.79},
441 {653.95, 525.22, 437.69, 375.90},
442 {326.98, 262.61, 218.84, 187.95},
443 {163.49, 131.31, 109.42, 93.97},
444 {81.74, 65.65, 54.71, 46.99},
445 {40.87, 32.83, 27.36, 23.49},
446 {20.44, 16.41, 13.68, 11.75},
447 {10.22, 8.21, 6.84, 5.87},
448 {5.11, 4.10, 3.42, 2.94},
449 {2.55, 2.05, 1.71, 1.47},
450 {1.27, 1.27, 1.27, 1.27}
451};
452#endif
453
454/* Rate Table for Attack */
455static void
456makeDphaseARTable (void)
457{
458 e_int32 AR, Rks, RM, RL;
459
460#ifdef USE_SPEC_ENV_SPEED
461 e_uint32 attacktable[16][4];
462
463 for (RM = 0; RM < 16; RM++)
464 for (RL = 0; RL < 4; RL++)
465 {
466 if (RM == 0)
467 attacktable[RM][RL] = 0;
468 else if (RM == 15)
469 attacktable[RM][RL] = EG_DP_WIDTH;
470 else
471 attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000));
472
473 }
474#endif
475
476 for (AR = 0; AR < 16; AR++)
477 for (Rks = 0; Rks < 16; Rks++)
478 {
479 RM = AR + (Rks >> 2);
480 RL = Rks & 3;
481 if (RM > 15)
482 RM = 15;
483 switch (AR)
484 {
485 case 0:
486 dphaseARTable[AR][Rks] = 0;
487 break;
488 case 15:
489 dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/
490 break;
491 default:
492#ifdef USE_SPEC_ENV_SPEED
493 dphaseARTable[AR][Rks] = RATE_ADJUST (attacktable[RM][RL]);
494#else
495 dphaseARTable[AR][Rks] = RATE_ADJUST ((3 * (RL + 4) << (RM + 1)));
496#endif
497 break;
498 }
499 }
500}
501
502/* Rate Table for Decay and Release */
503static void
504makeDphaseDRTable (void)
505{
506 e_int32 DR, Rks, RM, RL;
507
508#ifdef USE_SPEC_ENV_SPEED
509 e_uint32 decaytable[16][4];
510
511 for (RM = 0; RM < 16; RM++)
512 for (RL = 0; RL < 4; RL++)
513 if (RM == 0)
514 decaytable[RM][RL] = 0;
515 else
516 decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000));
517#endif
518
519 for (DR = 0; DR < 16; DR++)
520 for (Rks = 0; Rks < 16; Rks++)
521 {
522 RM = DR + (Rks >> 2);
523 RL = Rks & 3;
524 if (RM > 15)
525 RM = 15;
526 switch (DR)
527 {
528 case 0:
529 dphaseDRTable[DR][Rks] = 0;
530 break;
531 default:
532#ifdef USE_SPEC_ENV_SPEED
533 dphaseDRTable[DR][Rks] = RATE_ADJUST (decaytable[RM][RL]);
534#else
535 dphaseDRTable[DR][Rks] = RATE_ADJUST ((RL + 4) << (RM - 1));
536#endif
537 break;
538 }
539 }
540}
541
542static void
543makeRksTable (void)
544{
545
546 e_int32 fnum8, block, KR;
547
548 for (fnum8 = 0; fnum8 < 2; fnum8++)
549 for (block = 0; block < 8; block++)
550 for (KR = 0; KR < 2; KR++)
551 {
552 if (KR != 0)
553 rksTable[fnum8][block][KR] = (block << 1) + fnum8;
554 else
555 rksTable[fnum8][block][KR] = block >> 1;
556 }
557}
558
559void
560OPLL_dump2patch (const e_uint8 * dump, OPLL_PATCH * patch)
561{
562 patch[0].AM = (dump[0] >> 7) & 1;
563 patch[1].AM = (dump[1] >> 7) & 1;
564 patch[0].PM = (dump[0] >> 6) & 1;
565 patch[1].PM = (dump[1] >> 6) & 1;
566 patch[0].EG = (dump[0] >> 5) & 1;
567 patch[1].EG = (dump[1] >> 5) & 1;
568 patch[0].KR = (dump[0] >> 4) & 1;
569 patch[1].KR = (dump[1] >> 4) & 1;
570 patch[0].ML = (dump[0]) & 15;
571 patch[1].ML = (dump[1]) & 15;
572 patch[0].KL = (dump[2] >> 6) & 3;
573 patch[1].KL = (dump[3] >> 6) & 3;
574 patch[0].TL = (dump[2]) & 63;
575 patch[0].FB = (dump[3]) & 7;
576 patch[0].WF = (dump[3] >> 3) & 1;
577 patch[1].WF = (dump[3] >> 4) & 1;
578 patch[0].AR = (dump[4] >> 4) & 15;
579 patch[1].AR = (dump[5] >> 4) & 15;
580 patch[0].DR = (dump[4]) & 15;
581 patch[1].DR = (dump[5]) & 15;
582 patch[0].SL = (dump[6] >> 4) & 15;
583 patch[1].SL = (dump[7] >> 4) & 15;
584 patch[0].RR = (dump[6]) & 15;
585 patch[1].RR = (dump[7]) & 15;
586}
587
588void
589OPLL_getDefaultPatch (e_int32 type, e_int32 num, OPLL_PATCH * patch)
590{
591 OPLL_dump2patch (default_inst[type] + num * 16, patch);
592}
593
594static void
595makeDefaultPatch ( void )
596{
597 e_int32 i, j;
598
599 for (i = 0; i < OPLL_TONE_NUM; i++)
600 for (j = 0; j < 19; j++)
601 OPLL_getDefaultPatch (i, j, &default_patch[i][j * 2]);
602
603}
604
605void
606OPLL_setPatch (OPLL * opll, const e_uint8 * dump)
607{
608 OPLL_PATCH patch[2];
609 int i;
610
611 for (i = 0; i < 19; i++)
612 {
613 OPLL_dump2patch (dump + i * 16, patch);
614 memcpy (&opll->patch[i*2+0], &patch[0], sizeof (OPLL_PATCH));
615 memcpy (&opll->patch[i*2+1], &patch[1], sizeof (OPLL_PATCH));
616 }
617}
618
619void
620OPLL_patch2dump (const OPLL_PATCH * patch, e_uint8 * dump)
621{
622 dump[0] = (e_uint8) ((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML);
623 dump[1] = (e_uint8) ((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML);
624 dump[2] = (e_uint8) ((patch[0].KL << 6) + patch[0].TL);
625 dump[3] = (e_uint8) ((patch[1].KL << 6) + (patch[1].WF << 4) + (patch[0].WF << 3) + patch[0].FB);
626 dump[4] = (e_uint8) ((patch[0].AR << 4) + patch[0].DR);
627 dump[5] = (e_uint8) ((patch[1].AR << 4) + patch[1].DR);
628 dump[6] = (e_uint8) ((patch[0].SL << 4) + patch[0].RR);
629 dump[7] = (e_uint8) ((patch[1].SL << 4) + patch[1].RR);
630 dump[8] = 0;
631 dump[9] = 0;
632 dump[10] = 0;
633 dump[11] = 0;
634 dump[12] = 0;
635 dump[13] = 0;
636 dump[14] = 0;
637 dump[15] = 0;
638}
639
640/************************************************************
641
642 Calc Parameters
643
644************************************************************/
645
646INLINE static e_uint32
647calc_eg_dphase (OPLL_SLOT * slot)
648{
649
650 switch (slot->eg_mode)
651 {
652 case ATTACK:
653 return dphaseARTable[slot->patch->AR][slot->rks];
654
655 case DECAY:
656 return dphaseDRTable[slot->patch->DR][slot->rks];
657
658 case SUSHOLD:
659 return 0;
660
661 case SUSTINE:
662 return dphaseDRTable[slot->patch->RR][slot->rks];
663
664 case RELEASE:
665 if (slot->sustine)
666 return dphaseDRTable[5][slot->rks];
667 else if (slot->patch->EG)
668 return dphaseDRTable[slot->patch->RR][slot->rks];
669 else
670 return dphaseDRTable[7][slot->rks];
671
672 case SETTLE:
673 return dphaseDRTable[15][0];
674
675 case FINISH:
676 return 0;
677
678 default:
679 return 0;
680 }
681}
682
683/*************************************************************
684
685 OPLL internal interfaces
686
687*************************************************************/
688#define SLOT_BD1 12
689#define SLOT_BD2 13
690#define SLOT_HH 14
691#define SLOT_SD 15
692#define SLOT_TOM 16
693#define SLOT_CYM 17
694
695/* We will set this dinamically, but not sure if this affects playback */
696#if defined(ROCKBOX)
697INLINE static void
698UPDATE_PG(OPLL_SLOT * slot)
699{
700 static const e_uint32 mltable[16] =
701 { 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 };
702
703 slot->dphase = RATE_ADJUST (((slot->fnum * mltable[slot->patch->ML]) << slot->block) >> (20 - DP_BITS));
704}
705#else
706#define UPDATE_PG(S) (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch->ML]
707#endif
708
709#define UPDATE_TLL(S)\
710(((S)->type==0)?\
711((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch->TL][(S)->patch->KL]):\
712((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch->KL]))
713#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch->KR]
714#define UPDATE_WF(S) (S)->sintbl = waveform[(S)->patch->WF]
715#define UPDATE_EG(S) (S)->eg_dphase = calc_eg_dphase(S)
716#define UPDATE_ALL(S)\
717 UPDATE_PG(S);\
718 UPDATE_TLL(S);\
719 UPDATE_RKS(S);\
720 UPDATE_WF(S); \
721 UPDATE_EG(S) /* EG should be updated last. */
722
723
724/* Slot key on */
725INLINE static void
726slotOn (OPLL_SLOT * slot)
727{
728 slot->eg_mode = ATTACK;
729 slot->eg_phase = 0;
730 slot->phase = 0;
731 UPDATE_EG(slot);
732}
733
734/* Slot key on without reseting the phase */
735INLINE static void
736slotOn2 (OPLL_SLOT * slot)
737{
738 slot->eg_mode = ATTACK;
739 slot->eg_phase = 0;
740 UPDATE_EG(slot);
741}
742
743/* Slot key off */
744INLINE static void
745slotOff (OPLL_SLOT * slot)
746{
747 if (slot->eg_mode == ATTACK)
748 slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)), EG_BITS, EG_DP_BITS);
749 slot->eg_mode = RELEASE;
750 UPDATE_EG(slot);
751}
752
753/* Channel key on */
754INLINE static void
755keyOn (OPLL * opll, e_int32 i)
756{
757 if (!opll->slot_on_flag[i * 2])
758 slotOn (MOD(opll,i));
759 if (!opll->slot_on_flag[i * 2 + 1])
760 slotOn (CAR(opll,i));
761 opll->key_status[i] = 1;
762}
763
764/* Channel key off */
765INLINE static void
766keyOff (OPLL * opll, e_int32 i)
767{
768 if (opll->slot_on_flag[i * 2 + 1])
769 slotOff (CAR(opll,i));
770 opll->key_status[i] = 0;
771}
772
773INLINE static void
774keyOn_BD (OPLL * opll)
775{
776 keyOn (opll, 6);
777}
778INLINE static void
779keyOn_SD (OPLL * opll)
780{
781 if (!opll->slot_on_flag[SLOT_SD])
782 slotOn (CAR(opll,7));
783}
784INLINE static void
785keyOn_TOM (OPLL * opll)
786{
787 if (!opll->slot_on_flag[SLOT_TOM])
788 slotOn (MOD(opll,8));
789}
790INLINE static void
791keyOn_HH (OPLL * opll)
792{
793 if (!opll->slot_on_flag[SLOT_HH])
794 slotOn2 (MOD(opll,7));
795}
796INLINE static void
797keyOn_CYM (OPLL * opll)
798{
799 if (!opll->slot_on_flag[SLOT_CYM])
800 slotOn2 (CAR(opll,8));
801}
802
803/* Drum key off */
804INLINE static void
805keyOff_BD (OPLL * opll)
806{
807 keyOff (opll, 6);
808}
809INLINE static void
810keyOff_SD (OPLL * opll)
811{
812 if (opll->slot_on_flag[SLOT_SD])
813 slotOff (CAR(opll,7));
814}
815INLINE static void
816keyOff_TOM (OPLL * opll)
817{
818 if (opll->slot_on_flag[SLOT_TOM])
819 slotOff (MOD(opll,8));
820}
821INLINE static void
822keyOff_HH (OPLL * opll)
823{
824 if (opll->slot_on_flag[SLOT_HH])
825 slotOff (MOD(opll,7));
826}
827INLINE static void
828keyOff_CYM (OPLL * opll)
829{
830 if (opll->slot_on_flag[SLOT_CYM])
831 slotOff (CAR(opll,8));
832}
833
834/* Change a voice */
835INLINE static void
836setPatch (OPLL * opll, e_int32 i, e_int32 num)
837{
838 opll->patch_number[i] = num;
839 MOD(opll,i)->patch = &opll->patch[num * 2 + 0];
840 CAR(opll,i)->patch = &opll->patch[num * 2 + 1];
841}
842
843/* Change a rhythm voice */
844INLINE static void
845setSlotPatch (OPLL_SLOT * slot, OPLL_PATCH * patch)
846{
847 slot->patch = patch;
848}
849
850/* Set sustine parameter */
851INLINE static void
852setSustine (OPLL * opll, e_int32 c, e_int32 sustine)
853{
854 CAR(opll,c)->sustine = sustine;
855 if (MOD(opll,c)->type)
856 MOD(opll,c)->sustine = sustine;
857}
858
859/* Volume : 6bit ( Volume register << 2 ) */
860INLINE static void
861setVolume (OPLL * opll, e_int32 c, e_int32 volume)
862{
863 CAR(opll,c)->volume = volume;
864}
865
866INLINE static void
867setSlotVolume (OPLL_SLOT * slot, e_int32 volume)
868{
869 slot->volume = volume;
870}
871
872/* Set F-Number ( fnum : 9bit ) */
873INLINE static void
874setFnumber (OPLL * opll, e_int32 c, e_int32 fnum)
875{
876 CAR(opll,c)->fnum = fnum;
877 MOD(opll,c)->fnum = fnum;
878}
879
880/* Set Block data (block : 3bit ) */
881INLINE static void
882setBlock (OPLL * opll, e_int32 c, e_int32 block)
883{
884 CAR(opll,c)->block = block;
885 MOD(opll,c)->block = block;
886}
887
888/* Change Rhythm Mode */
889INLINE static void
890update_rhythm_mode (OPLL * opll)
891{
892 if (opll->patch_number[6] & 0x10)
893 {
894 if (!(opll->slot_on_flag[SLOT_BD2] | (opll->reg[0x0e] & 32)))
895 {
896 opll->slot[SLOT_BD1].eg_mode = FINISH;
897 opll->slot[SLOT_BD2].eg_mode = FINISH;
898 setPatch (opll, 6, opll->reg[0x36] >> 4);
899 }
900 }
901 else if (opll->reg[0x0e] & 32)
902 {
903 opll->patch_number[6] = 16;
904 opll->slot[SLOT_BD1].eg_mode = FINISH;
905 opll->slot[SLOT_BD2].eg_mode = FINISH;
906 setSlotPatch (&opll->slot[SLOT_BD1], &opll->patch[16 * 2 + 0]);
907 setSlotPatch (&opll->slot[SLOT_BD2], &opll->patch[16 * 2 + 1]);
908 }
909
910 if (opll->patch_number[7] & 0x10)
911 {
912 if (!((opll->slot_on_flag[SLOT_HH] && opll->slot_on_flag[SLOT_SD]) | (opll->reg[0x0e] & 32)))
913 {
914 opll->slot[SLOT_HH].type = 0;
915 opll->slot[SLOT_HH].eg_mode = FINISH;
916 opll->slot[SLOT_SD].eg_mode = FINISH;
917 setPatch (opll, 7, opll->reg[0x37] >> 4);
918 }
919 }
920 else if (opll->reg[0x0e] & 32)
921 {
922 opll->patch_number[7] = 17;
923 opll->slot[SLOT_HH].type = 1;
924 opll->slot[SLOT_HH].eg_mode = FINISH;
925 opll->slot[SLOT_SD].eg_mode = FINISH;
926 setSlotPatch (&opll->slot[SLOT_HH], &opll->patch[17 * 2 + 0]);
927 setSlotPatch (&opll->slot[SLOT_SD], &opll->patch[17 * 2 + 1]);
928 }
929
930 if (opll->patch_number[8] & 0x10)
931 {
932 if (!((opll->slot_on_flag[SLOT_CYM] && opll->slot_on_flag[SLOT_TOM]) | (opll->reg[0x0e] & 32)))
933 {
934 opll->slot[SLOT_TOM].type = 0;
935 opll->slot[SLOT_TOM].eg_mode = FINISH;
936 opll->slot[SLOT_CYM].eg_mode = FINISH;
937 setPatch (opll, 8, opll->reg[0x38] >> 4);
938 }
939 }
940 else if (opll->reg[0x0e] & 32)
941 {
942 opll->patch_number[8] = 18;
943 opll->slot[SLOT_TOM].type = 1;
944 opll->slot[SLOT_TOM].eg_mode = FINISH;
945 opll->slot[SLOT_CYM].eg_mode = FINISH;
946 setSlotPatch (&opll->slot[SLOT_TOM], &opll->patch[18 * 2 + 0]);
947 setSlotPatch (&opll->slot[SLOT_CYM], &opll->patch[18 * 2 + 1]);
948 }
949}
950
951INLINE static void
952update_key_status (OPLL * opll)
953{
954 int ch;
955
956 for (ch = 0; ch < 9; ch++)
957 opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->reg[0x20 + ch]) & 0x10;
958
959 if (opll->reg[0x0e] & 32)
960 {
961 opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e] & 0x10);
962 opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e] & 0x10);
963 opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e] & 0x08);
964 opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e] & 0x01);
965 opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e] & 0x04);
966 opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e] & 0x02);
967 }
968}
969
970void
971OPLL_copyPatch (OPLL * opll, e_int32 num, OPLL_PATCH * patch)
972{
973 memcpy (&opll->patch[num], patch, sizeof (OPLL_PATCH));
974}
975
976/***********************************************************
977
978 Initializing
979
980***********************************************************/
981
982static void
983OPLL_SLOT_reset (OPLL_SLOT * slot, int type)
984{
985 slot->type = type;
986 slot->sintbl = waveform[0];
987 slot->phase = 0;
988 slot->dphase = 0;
989 slot->output[0] = 0;
990 slot->output[1] = 0;
991 slot->feedback = 0;
992 slot->eg_mode = FINISH;
993 slot->eg_phase = EG_DP_WIDTH;
994 slot->eg_dphase = 0;
995 slot->rks = 0;
996 slot->tll = 0;
997 slot->sustine = 0;
998 slot->fnum = 0;
999 slot->block = 0;
1000 slot->volume = 0;
1001 slot->pgout = 0;
1002 slot->egout = 0;
1003 slot->patch = &null_patch;
1004}
1005
1006static void
1007internal_refresh (void)
1008{
1009#if !defined(ROCKBOX)
1010 makeDphaseTable ();
1011#endif
1012 makeDphaseARTable ();
1013 makeDphaseDRTable ();
1014 pm_dphase = (e_uint32) RATE_ADJUST ((int)(PM_SPEED * PM_DP_WIDTH) / (clk / 72));
1015 am_dphase = (e_uint32) RATE_ADJUST ((int)(AM_SPEED * AM_DP_WIDTH) / (clk / 72));
1016}
1017
1018static void
1019maketables (e_uint32 c, e_uint32 r)
1020{
1021 if (c != clk)
1022 {
1023 clk = c;
1024#ifdef EMU2413_CALCUL_TABLES
1025 makePmTable ();
1026 makeAmTable ();
1027 makeAdjustTable ();
1028#endif
1029 makeDB2LinTable ();
1030 makeTllTable ();
1031 makeRksTable ();
1032 makeSinTable ();
1033 makeDefaultPatch ();
1034 }
1035
1036 if (r != rate)
1037 {
1038 rate = r;
1039 internal_refresh ();
1040 }
1041}
1042
1043void
1044OPLL_new (OPLL *opll, e_uint32 clk, e_uint32 rate)
1045{
1046 e_int32 i;
1047
1048 maketables (clk, rate);
1049
1050 memset(opll, 0, sizeof (OPLL));
1051 for (i = 0; i < 19 * 2; i++)
1052 memcpy(&opll->patch[i],&null_patch,sizeof(OPLL_PATCH));
1053
1054 opll->mask = 0;
1055
1056 OPLL_reset (opll);
1057 OPLL_reset_patch (opll, 0);
1058}
1059
1060
1061void
1062OPLL_delete (OPLL * opll)
1063{
1064 (void) opll;
1065}
1066
1067
1068/* Reset patch datas by system default. */
1069void
1070OPLL_reset_patch (OPLL * opll, e_int32 type)
1071{
1072 e_int32 i;
1073
1074 for (i = 0; i < 19 * 2; i++)
1075 OPLL_copyPatch (opll, i, &default_patch[type % OPLL_TONE_NUM][i]);
1076}
1077
1078/* Reset whole of OPLL except patch datas. */
1079void
1080OPLL_reset (OPLL * opll)
1081{
1082 e_int32 i;
1083
1084 if (!opll)
1085 return;
1086
1087 opll->adr = 0;
1088 opll->out = 0;
1089
1090 opll->pm_phase = 0;
1091 opll->am_phase = 0;
1092
1093 opll->noise_seed = 0xffff;
1094 opll->mask = 0;
1095
1096 for (i = 0; i <18; i++)
1097 OPLL_SLOT_reset(&opll->slot[i], i%2);
1098
1099 for (i = 0; i < 9; i++)
1100 {
1101 opll->key_status[i] = 0;
1102 setPatch (opll, i, 0);
1103 }
1104
1105 for (i = 0; i < 0x40; i++)
1106 OPLL_writeReg (opll, i, 0);
1107
1108#ifndef EMU2413_COMPACTION
1109 opll->realstep = (e_uint32) ((1 << 31) / rate);
1110 opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72));
1111 opll->oplltime = 0;
1112 for (i = 0; i < 14; i++)
1113 opll->pan[i] = 2;
1114 opll->sprev[0] = opll->sprev[1] = 0;
1115 opll->snext[0] = opll->snext[1] = 0;
1116#endif
1117}
1118
1119/* Force Refresh (When external program changes some parameters). */
1120void
1121OPLL_forceRefresh (OPLL * opll)
1122{
1123 e_int32 i;
1124
1125 if (opll == NULL)
1126 return;
1127
1128 for (i = 0; i < 9; i++)
1129 setPatch(opll,i,opll->patch_number[i]);
1130
1131 for (i = 0; i < 18; i++)
1132 {
1133 UPDATE_PG (&opll->slot[i]);
1134 UPDATE_RKS (&opll->slot[i]);
1135 UPDATE_TLL (&opll->slot[i]);
1136 UPDATE_WF (&opll->slot[i]);
1137 UPDATE_EG (&opll->slot[i]);
1138 }
1139}
1140
1141void
1142OPLL_set_rate (OPLL * opll, e_uint32 r)
1143{
1144 if (rate == r) return;
1145 if (opll->quality)
1146 rate = 49716;
1147 else
1148 rate = r;
1149 internal_refresh ();
1150 rate = r;
1151}
1152
1153void
1154OPLL_set_quality (OPLL * opll, e_uint32 q)
1155{
1156 opll->quality = q;
1157 OPLL_set_rate (opll, rate);
1158}
1159
1160/*********************************************************
1161
1162 Generate wave data
1163
1164*********************************************************/
1165/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
1166#if ( SLOT_AMP_BITS - PG_BITS ) > 0
1167#define wave2_2pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
1168#else
1169#define wave2_2pi(e) ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
1170#endif
1171
1172/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
1173#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
1174#define wave2_4pi(e) (e)
1175#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
1176#define wave2_4pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
1177#else
1178#define wave2_4pi(e) ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
1179#endif
1180
1181/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
1182#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
1183#define wave2_8pi(e) (e)
1184#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
1185#define wave2_8pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
1186#else
1187#define wave2_8pi(e) ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
1188#endif
1189
1190/* Update AM, PM unit */
1191INLINE static void
1192update_ampm (OPLL * opll)
1193{
1194 opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1);
1195 opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1);
1196 opll->lfo_am = AMTABLE(HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS));
1197 opll->lfo_pm = PMTABLE(HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS));
1198}
1199
1200/* PG */
1201INLINE static void
1202calc_phase (OPLL_SLOT * slot, e_int32 lfo)
1203{
1204 if (slot->patch->PM)
1205 slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS;
1206 else
1207 slot->phase += slot->dphase;
1208
1209 slot->phase &= (DP_WIDTH - 1);
1210
1211 slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS);
1212}
1213
1214/* Update Noise unit */
1215INLINE static void
1216update_noise (OPLL * opll)
1217{
1218 if(opll->noise_seed&1) opll->noise_seed ^= 0x8003020;
1219 opll->noise_seed >>= 1;
1220}
1221
1222/* EG */
1223INLINE static void
1224calc_envelope (OPLL_SLOT * slot, e_int32 lfo)
1225{
1226#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
1227
1228 static e_uint32 SL[16] = {
1229 S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0),
1230 S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0)
1231 };
1232
1233 e_uint32 egout;
1234
1235 switch (slot->eg_mode)
1236 {
1237 case ATTACK:
1238 egout = AR_ADJUST_TABLE(HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS));
1239 slot->eg_phase += slot->eg_dphase;
1240 if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch->AR==15))
1241 {
1242 egout = 0;
1243 slot->eg_phase = 0;
1244 slot->eg_mode = DECAY;
1245 UPDATE_EG (slot);
1246 }
1247 break;
1248
1249 case DECAY:
1250 egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
1251 slot->eg_phase += slot->eg_dphase;
1252 if (slot->eg_phase >= SL[slot->patch->SL])
1253 {
1254 if (slot->patch->EG)
1255 {
1256 slot->eg_phase = SL[slot->patch->SL];
1257 slot->eg_mode = SUSHOLD;
1258 UPDATE_EG (slot);
1259 }
1260 else
1261 {
1262 slot->eg_phase = SL[slot->patch->SL];
1263 slot->eg_mode = SUSTINE;
1264 UPDATE_EG (slot);
1265 }
1266 }
1267 break;
1268
1269 case SUSHOLD:
1270 egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
1271 if (slot->patch->EG == 0)
1272 {
1273 slot->eg_mode = SUSTINE;
1274 UPDATE_EG (slot);
1275 }
1276 break;
1277
1278 case SUSTINE:
1279 case RELEASE:
1280 egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
1281 slot->eg_phase += slot->eg_dphase;
1282 if (egout >= (1 << EG_BITS))
1283 {
1284 slot->eg_mode = FINISH;
1285 egout = (1 << EG_BITS) - 1;
1286 }
1287 break;
1288
1289 case SETTLE:
1290 egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS);
1291 slot->eg_phase += slot->eg_dphase;
1292 if (egout >= (1 << EG_BITS))
1293 {
1294 slot->eg_mode = ATTACK;
1295 egout = (1 << EG_BITS) - 1;
1296 UPDATE_EG(slot);
1297 }
1298 break;
1299
1300 case FINISH:
1301 egout = (1 << EG_BITS) - 1;
1302 break;
1303
1304 default:
1305 egout = (1 << EG_BITS) - 1;
1306 break;
1307 }
1308
1309 if (slot->patch->AM)
1310 egout = EG2DB (egout + slot->tll) + lfo;
1311 else
1312 egout = EG2DB (egout + slot->tll);
1313
1314 if (egout >= DB_MUTE)
1315 egout = DB_MUTE - 1;
1316
1317 slot->egout = egout | 3;
1318}
1319
1320/* CARRIOR */
1321INLINE static e_int32
1322calc_slot_car (OPLL_SLOT * slot, e_int32 fm)
1323{
1324 if (slot->egout >= (DB_MUTE - 1))
1325 {
1326 slot->output[0] = 0;
1327 }
1328 else
1329 {
1330 slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
1331 }
1332
1333 slot->output[1] = (slot->output[1] + slot->output[0]) >> 1;
1334 return slot->output[1];
1335}
1336
1337/* MODULATOR */
1338INLINE static e_int32
1339calc_slot_mod (OPLL_SLOT * slot)
1340{
1341 e_int32 fm;
1342
1343 slot->output[1] = slot->output[0];
1344
1345 if (slot->egout >= (DB_MUTE - 1))
1346 {
1347 slot->output[0] = 0;
1348 }
1349 else if (slot->patch->FB != 0)
1350 {
1351 fm = wave2_4pi (slot->feedback) >> (7 - slot->patch->FB);
1352 slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
1353 }
1354 else
1355 {
1356 slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
1357 }
1358
1359 slot->feedback = (slot->output[1] + slot->output[0]) >> 1;
1360
1361 return slot->feedback;
1362
1363}
1364
1365/* TOM */
1366INLINE static e_int32
1367calc_slot_tom (OPLL_SLOT * slot)
1368{
1369 if (slot->egout >= (DB_MUTE - 1))
1370 return 0;
1371
1372 return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout];
1373
1374}
1375
1376/* SNARE */
1377INLINE static e_int32
1378calc_slot_snare (OPLL_SLOT * slot, e_uint32 noise)
1379{
1380 if(slot->egout>=(DB_MUTE-1))
1381 return 0;
1382
1383 if(BIT(slot->pgout,7))
1384 return DB2LIN_TABLE[(noise?DB_POS(0):DB_POS(15))+slot->egout];
1385 else
1386 return DB2LIN_TABLE[(noise?DB_NEG(0):DB_NEG(15))+slot->egout];
1387}
1388
1389/*
1390 TOP-CYM
1391 */
1392INLINE static e_int32
1393calc_slot_cym (OPLL_SLOT * slot, e_uint32 pgout_hh)
1394{
1395 e_uint32 dbout;
1396
1397 if (slot->egout >= (DB_MUTE - 1))
1398 return 0;
1399 else if(
1400 /* the same as fmopl.c */
1401 ((BIT(pgout_hh,PG_BITS-8)^BIT(pgout_hh,PG_BITS-1))|BIT(pgout_hh,PG_BITS-7)) ^
1402 /* different from fmopl.c */
1403 (BIT(slot->pgout,PG_BITS-7)&!BIT(slot->pgout,PG_BITS-5))
1404 )
1405 dbout = DB_NEG(3);
1406 else
1407 dbout = DB_POS(3);
1408
1409 return DB2LIN_TABLE[dbout + slot->egout];
1410}
1411
1412/*
1413 HI-HAT
1414*/
1415INLINE static e_int32
1416calc_slot_hat (OPLL_SLOT *slot, e_int32 pgout_cym, e_uint32 noise)
1417{
1418 e_uint32 dbout;
1419
1420 if (slot->egout >= (DB_MUTE - 1))
1421 return 0;
1422 else if(
1423 /* the same as fmopl.c */
1424 ((BIT(slot->pgout,PG_BITS-8)^BIT(slot->pgout,PG_BITS-1))|BIT(slot->pgout,PG_BITS-7)) ^
1425 /* different from fmopl.c */
1426 (BIT(pgout_cym,PG_BITS-7)&!BIT(pgout_cym,PG_BITS-5))
1427 )
1428 {
1429 if(noise)
1430 dbout = DB_NEG(12);
1431 else
1432 dbout = DB_NEG(24);
1433 }
1434 else
1435 {
1436 if(noise)
1437 dbout = DB_POS(12);
1438 else
1439 dbout = DB_POS(24);
1440 }
1441
1442 return DB2LIN_TABLE[dbout + slot->egout];
1443}
1444
1445static e_int16
1446calc (OPLL * opll) EMU2413_CALC_ICODE;
1447static e_int16
1448calc (OPLL * opll)
1449{
1450 e_int32 i;
1451
1452 update_ampm (opll);
1453 update_noise (opll);
1454
1455 for (i = 0; i < 18; i++)
1456 {
1457 calc_phase(&opll->slot[i],opll->lfo_pm);
1458 calc_envelope(&opll->slot[i],opll->lfo_am);
1459 }
1460
1461 e_uint32 channel_mask = opll->mask;
1462 for (i = 0; i < 9; i++) {
1463 if (CAR(opll,i)->eg_mode != FINISH)
1464 channel_mask |= (1 << i);
1465 }
1466
1467 e_int32 mix = 0;
1468
1469 /* CH6 */
1470 if (opll->patch_number[6] & 0x10) {
1471 if (channel_mask & OPLL_MASK_CH (6)) {
1472 mix += calc_slot_car (CAR(opll,6), calc_slot_mod(MOD(opll,6)));
1473 channel_mask &= ~(1 << 6);
1474 }
1475 }
1476
1477 /* CH7 */
1478 if (opll->patch_number[7] & 0x10) {
1479 if (MOD(opll,7)->eg_mode != FINISH)
1480 mix += calc_slot_hat (MOD(opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
1481 if (channel_mask & OPLL_MASK_SD) {
1482 mix -= calc_slot_snare (CAR(opll,7), opll->noise_seed&1);
1483 channel_mask &= ~OPLL_MASK_SD;
1484 }
1485 }
1486
1487 /* CH8 */
1488 if (opll->patch_number[8] & 0x10) {
1489 if (MOD(opll,8)->eg_mode != FINISH)
1490 mix += calc_slot_tom (MOD(opll,8));
1491 if (channel_mask & OPLL_MASK_CYM) {
1492 mix -= calc_slot_cym (CAR(opll,8), MOD(opll,7)->pgout);
1493 channel_mask &= ~OPLL_MASK_CYM;
1494 }
1495 }
1496
1497 mix <<= 1;
1498
1499 opll->current_mask = channel_mask;
1500 for (i = 0; channel_mask; channel_mask >>= 1, ++i) {
1501 if (channel_mask & 1) {
1502 mix += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i)));
1503 }
1504 }
1505
1506 return (e_int16) mix << 3;
1507}
1508
1509void
1510OPLL_set_internal_mute(OPLL * opll, e_uint32 mute)
1511{
1512 opll->internal_mute = mute;
1513}
1514
1515e_uint32
1516OPLL_is_internal_muted(OPLL * opll)
1517{
1518 return opll->internal_mute;
1519}
1520
1521static e_uint32
1522check_mute_helper(OPLL * opll)
1523{
1524 for (int i = 0; i < 6; i++) {
1525 /* if (ch[i].car.eg_mode != FINISH) return 0; */
1526 if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
1527 }
1528
1529 if (!(opll->reg[0x0e] & 0x20)) {
1530 for(int i = 6; i < 9; i++) {
1531 /* if (ch[i].car.eg_mode != FINISH) return 0; */
1532 if (!(opll->current_mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) return 0;
1533 }
1534 } else {
1535 /* if (ch[6].car.eg_mode != FINISH) return false;
1536 if (ch[7].mod.eg_mode != FINISH) return false;
1537 if (ch[7].car.eg_mode != FINISH) return false;
1538 if (ch[8].mod.eg_mode != FINISH) return false;
1539 if (ch[8].car.eg_mode != FINISH) return false; */
1540 if (!(opll->current_mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH)) return 0;
1541 if (!(opll->current_mask & OPLL_MASK_CH (7)) && (MOD(opll,7)->eg_mode != FINISH)) return 0;
1542 if (!(opll->current_mask & OPLL_MASK_CH (7)) && (CAR(opll,7)->eg_mode != FINISH)) return 0;
1543 if (!(opll->current_mask & OPLL_MASK_CH (8)) && (MOD(opll,8)->eg_mode != FINISH)) return 0;
1544 if (!(opll->current_mask & OPLL_MASK_CH (8)) && (CAR(opll,8)->eg_mode != FINISH)) return 0;
1545 }
1546
1547 return 1; /* nothing is playing, then mute */
1548}
1549
1550static void
1551check_mute(OPLL * opll)
1552{
1553 OPLL_set_internal_mute (opll, check_mute_helper (opll));
1554}
1555
1556EMU2413_API e_int16 *OPLL_update_buffer(OPLL * opll, e_uint32 length)
1557{
1558 e_int16* buf = opll->buffer;
1559 while (length--) {
1560 *(buf++) = calc (opll);
1561 }
1562 check_mute (opll);
1563
1564 return opll->buffer;
1565}
1566
1567#ifdef EMU2413_COMPACTION
1568e_int16
1569OPLL_calc (OPLL * opll)
1570{
1571 return calc (opll);
1572}
1573#else
1574e_int16
1575OPLL_calc (OPLL * opll)
1576{
1577 if (!opll->quality)
1578 return calc (opll);
1579
1580 while (opll->realstep > opll->oplltime)
1581 {
1582 opll->oplltime += opll->opllstep;
1583 opll->prev = opll->next;
1584 opll->next = calc (opll);
1585 }
1586
1587 opll->oplltime -= opll->realstep;
1588 opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime)
1589 + (double) opll->prev * opll->oplltime) / opll->opllstep);
1590
1591 return (e_int16) opll->out;
1592}
1593#endif
1594
1595e_uint32
1596OPLL_setMask (OPLL * opll, e_uint32 mask)
1597{
1598 e_uint32 ret;
1599
1600 if (opll)
1601 {
1602 ret = opll->mask;
1603 opll->mask = mask;
1604 return ret;
1605 }
1606 else
1607 return 0;
1608}
1609
1610e_uint32
1611OPLL_toggleMask (OPLL * opll, e_uint32 mask)
1612{
1613 e_uint32 ret;
1614
1615 if (opll)
1616 {
1617 ret = opll->mask;
1618 opll->mask ^= mask;
1619 return ret;
1620 }
1621 else
1622 return 0;
1623}
1624
1625/****************************************************
1626
1627 I/O Ctrl
1628
1629*****************************************************/
1630
1631void
1632OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data)
1633{
1634 e_int32 i, v, ch;
1635
1636 data = data & 0xff;
1637 reg = reg & 0x3f;
1638 opll->reg[reg] = (e_uint8) data;
1639
1640 switch (reg)
1641 {
1642 case 0x00:
1643 opll->patch[0].AM = (data >> 7) & 1;
1644 opll->patch[0].PM = (data >> 6) & 1;
1645 opll->patch[0].EG = (data >> 5) & 1;
1646 opll->patch[0].KR = (data >> 4) & 1;
1647 opll->patch[0].ML = (data) & 15;
1648 for (i = 0; i < 9; i++)
1649 {
1650 if (opll->patch_number[i] == 0)
1651 {
1652 UPDATE_PG (MOD(opll,i));
1653 UPDATE_RKS (MOD(opll,i));
1654 UPDATE_EG (MOD(opll,i));
1655 }
1656 }
1657 break;
1658
1659 case 0x01:
1660 opll->patch[1].AM = (data >> 7) & 1;
1661 opll->patch[1].PM = (data >> 6) & 1;
1662 opll->patch[1].EG = (data >> 5) & 1;
1663 opll->patch[1].KR = (data >> 4) & 1;
1664 opll->patch[1].ML = (data) & 15;
1665 for (i = 0; i < 9; i++)
1666 {
1667 if (opll->patch_number[i] == 0)
1668 {
1669 UPDATE_PG (CAR(opll,i));
1670 UPDATE_RKS (CAR(opll,i));
1671 UPDATE_EG (CAR(opll,i));
1672 }
1673 }
1674 break;
1675
1676 case 0x02:
1677 opll->patch[0].KL = (data >> 6) & 3;
1678 opll->patch[0].TL = (data) & 63;
1679 for (i = 0; i < 9; i++)
1680 {
1681 if (opll->patch_number[i] == 0)
1682 {
1683 UPDATE_TLL(MOD(opll,i));
1684 }
1685 }
1686 break;
1687
1688 case 0x03:
1689 opll->patch[1].KL = (data >> 6) & 3;
1690 opll->patch[1].WF = (data >> 4) & 1;
1691 opll->patch[0].WF = (data >> 3) & 1;
1692 opll->patch[0].FB = (data) & 7;
1693 for (i = 0; i < 9; i++)
1694 {
1695 if (opll->patch_number[i] == 0)
1696 {
1697 UPDATE_WF(MOD(opll,i));
1698 UPDATE_WF(CAR(opll,i));
1699 }
1700 }
1701 break;
1702
1703 case 0x04:
1704 opll->patch[0].AR = (data >> 4) & 15;
1705 opll->patch[0].DR = (data) & 15;
1706 for (i = 0; i < 9; i++)
1707 {
1708 if (opll->patch_number[i] == 0)
1709 {
1710 UPDATE_EG (MOD(opll,i));
1711 }
1712 }
1713 break;
1714
1715 case 0x05:
1716 opll->patch[1].AR = (data >> 4) & 15;
1717 opll->patch[1].DR = (data) & 15;
1718 for (i = 0; i < 9; i++)
1719 {
1720 if (opll->patch_number[i] == 0)
1721 {
1722 UPDATE_EG(CAR(opll,i));
1723 }
1724 }
1725 break;
1726
1727 case 0x06:
1728 opll->patch[0].SL = (data >> 4) & 15;
1729 opll->patch[0].RR = (data) & 15;
1730 for (i = 0; i < 9; i++)
1731 {
1732 if (opll->patch_number[i] == 0)
1733 {
1734 UPDATE_EG (MOD(opll,i));
1735 }
1736 }
1737 break;
1738
1739 case 0x07:
1740 opll->patch[1].SL = (data >> 4) & 15;
1741 opll->patch[1].RR = (data) & 15;
1742 for (i = 0; i < 9; i++)
1743 {
1744 if (opll->patch_number[i] == 0)
1745 {
1746 UPDATE_EG (CAR(opll,i));
1747 }
1748 }
1749 break;
1750
1751 case 0x0e:
1752 update_rhythm_mode (opll);
1753 if (data & 32)
1754 {
1755 if (data & 0x10)
1756 keyOn_BD (opll);
1757 else
1758 keyOff_BD (opll);
1759 if (data & 0x8)
1760 keyOn_SD (opll);
1761 else
1762 keyOff_SD (opll);
1763 if (data & 0x4)
1764 keyOn_TOM (opll);
1765 else
1766 keyOff_TOM (opll);
1767 if (data & 0x2)
1768 keyOn_CYM (opll);
1769 else
1770 keyOff_CYM (opll);
1771 if (data & 0x1)
1772 keyOn_HH (opll);
1773 else
1774 keyOff_HH (opll);
1775 }
1776 update_key_status (opll);
1777
1778 UPDATE_ALL (MOD(opll,6));
1779 UPDATE_ALL (CAR(opll,6));
1780 UPDATE_ALL (MOD(opll,7));
1781 UPDATE_ALL (CAR(opll,7));
1782 UPDATE_ALL (MOD(opll,8));
1783 UPDATE_ALL (CAR(opll,8));
1784
1785 break;
1786
1787 case 0x0f:
1788 break;
1789
1790 case 0x10:
1791 case 0x11:
1792 case 0x12:
1793 case 0x13:
1794 case 0x14:
1795 case 0x15:
1796 case 0x16:
1797 case 0x17:
1798 case 0x18:
1799 ch = reg - 0x10;
1800 setFnumber (opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8));
1801 UPDATE_ALL (MOD(opll,ch));
1802 UPDATE_ALL (CAR(opll,ch));
1803 break;
1804
1805 case 0x20:
1806 case 0x21:
1807 case 0x22:
1808 case 0x23:
1809 case 0x24:
1810 case 0x25:
1811 case 0x26:
1812 case 0x27:
1813 case 0x28:
1814 ch = reg - 0x20;
1815 setFnumber (opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]);
1816 setBlock (opll, ch, (data >> 1) & 7);
1817 setSustine (opll, ch, (data >> 5) & 1);
1818 if (data & 0x10)
1819 keyOn (opll, ch);
1820 else
1821 keyOff (opll, ch);
1822 UPDATE_ALL (MOD(opll,ch));
1823 UPDATE_ALL (CAR(opll,ch));
1824 update_key_status (opll);
1825 update_rhythm_mode (opll);
1826 break;
1827
1828 case 0x30:
1829 case 0x31:
1830 case 0x32:
1831 case 0x33:
1832 case 0x34:
1833 case 0x35:
1834 case 0x36:
1835 case 0x37:
1836 case 0x38:
1837 i = (data >> 4) & 15;
1838 v = data & 15;
1839 if ((opll->reg[0x0e] & 32) && (reg >= 0x36))
1840 {
1841 switch (reg)
1842 {
1843 case 0x37:
1844 setSlotVolume (MOD(opll,7), i << 2);
1845 break;
1846 case 0x38:
1847 setSlotVolume (MOD(opll,8), i << 2);
1848 break;
1849 default:
1850 break;
1851 }
1852 }
1853 else
1854 {
1855 setPatch (opll, reg - 0x30, i);
1856 }
1857 setVolume (opll, reg - 0x30, v << 2);
1858 UPDATE_ALL (MOD(opll,reg - 0x30));
1859 UPDATE_ALL (CAR(opll,reg - 0x30));
1860 break;
1861
1862 default:
1863 break;
1864
1865 }
1866}
1867
1868void
1869OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val)
1870{
1871 if (adr & 1)
1872 OPLL_writeReg (opll, opll->adr, val);
1873 else
1874 opll->adr = val;
1875}
1876
1877e_uint32
1878OPLL_read(OPLL * opll, e_uint32 a)
1879{
1880 if( !(a&1) )
1881 {
1882 /* status port */
1883 return opll->status;
1884 }
1885 return 0xff;
1886}
1887
1888#ifndef EMU2413_COMPACTION
1889/* STEREO MODE (OPT) */
1890void
1891OPLL_set_pan (OPLL * opll, e_uint32 ch, e_uint32 pan)
1892{
1893 opll->pan[ch & 15] = pan & 3;
1894}
1895
1896static void
1897calc_stereo (OPLL * opll, e_int32 out[2])
1898{
1899 e_int32 b[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
1900 e_int32 r[4] = { 0, 0, 0, 0 }; /* Ignore, Right, Left, Center */
1901 e_int32 i;
1902
1903 update_ampm (opll);
1904 update_noise (opll);
1905
1906 for(i=0;i<18;i++)
1907 {
1908 calc_phase(&opll->slot[i],opll->lfo_pm);
1909 calc_envelope(&opll->slot[i],opll->lfo_am);
1910 }
1911
1912 for (i = 0; i < 6; i++)
1913 if (!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH))
1914 b[opll->pan[i]] += calc_slot_car (CAR(opll,i), calc_slot_mod (MOD(opll,i)));
1915
1916
1917 if (opll->patch_number[6] <= 15)
1918 {
1919 if (!(opll->mask & OPLL_MASK_CH (6)) && (CAR(opll,6)->eg_mode != FINISH))
1920 b[opll->pan[6]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
1921 }
1922 else
1923 {
1924 if (!(opll->mask & OPLL_MASK_BD) && (CAR(opll,6)->eg_mode != FINISH))
1925 r[opll->pan[9]] += calc_slot_car (CAR(opll,6), calc_slot_mod (MOD(opll,6)));
1926 }
1927
1928 if (opll->patch_number[7] <= 15)
1929 {
1930 if (!(opll->mask & OPLL_MASK_CH (7)) && (CAR (opll,7)->eg_mode != FINISH))
1931 b[opll->pan[7]] += calc_slot_car (CAR (opll,7), calc_slot_mod (MOD (opll,7)));
1932 }
1933 else
1934 {
1935 if (!(opll->mask & OPLL_MASK_HH) && (MOD (opll,7)->eg_mode != FINISH))
1936 r[opll->pan[10]] += calc_slot_hat (MOD (opll,7), CAR(opll,8)->pgout, opll->noise_seed&1);
1937 if (!(opll->mask & OPLL_MASK_SD) && (CAR (opll,7)->eg_mode != FINISH))
1938 r[opll->pan[11]] -= calc_slot_snare (CAR (opll,7), opll->noise_seed&1);
1939 }
1940
1941 if (opll->patch_number[8] <= 15)
1942 {
1943 if (!(opll->mask & OPLL_MASK_CH (8)) && (CAR (opll,8)->eg_mode != FINISH))
1944 b[opll->pan[8]] += calc_slot_car (CAR (opll,8), calc_slot_mod (MOD (opll,8)));
1945 }
1946 else
1947 {
1948 if (!(opll->mask & OPLL_MASK_TOM) && (MOD (opll,8)->eg_mode != FINISH))
1949 r[opll->pan[12]] += calc_slot_tom (MOD (opll,8));
1950 if (!(opll->mask & OPLL_MASK_CYM) && (CAR (opll,8)->eg_mode != FINISH))
1951 r[opll->pan[13]] -= calc_slot_cym (CAR (opll,8), MOD(opll,7)->pgout);
1952 }
1953
1954 out[1] = (b[1] + b[3] + ((r[1] + r[3]) << 1)) <<3;
1955 out[0] = (b[2] + b[3] + ((r[2] + r[3]) << 1)) <<3;
1956}
1957
1958void
1959OPLL_calc_stereo (OPLL * opll, e_int32 out[2])
1960{
1961 if (!opll->quality)
1962 {
1963 calc_stereo (opll, out);
1964 return;
1965 }
1966
1967 while (opll->realstep > opll->oplltime)
1968 {
1969 opll->oplltime += opll->opllstep;
1970 opll->sprev[0] = opll->snext[0];
1971 opll->sprev[1] = opll->snext[1];
1972 calc_stereo (opll, opll->snext);
1973 }
1974
1975 opll->oplltime -= opll->realstep;
1976 out[0] = (e_int16) (((double) opll->snext[0] * (opll->opllstep - opll->oplltime)
1977 + (double) opll->sprev[0] * opll->oplltime) / opll->opllstep);
1978 out[1] = (e_int16) (((double) opll->snext[1] * (opll->opllstep - opll->oplltime)
1979 + (double) opll->sprev[1] * opll->oplltime) / opll->opllstep);
1980}
1981#endif /* EMU2413_COMPACTION */
diff --git a/lib/rbcodec/codecs/libgme/emu2413.h b/lib/rbcodec/codecs/libgme/emu2413.h
new file mode 100644
index 0000000000..254f042957
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emu2413.h
@@ -0,0 +1,164 @@
1#ifndef _EMU2413_H_
2#define _EMU2413_H_
3
4#include "blargg_common.h"
5#include "emutypes.h"
6
7#ifdef EMU2413_DLL_EXPORTS
8 #define EMU2413_API __declspec(dllexport)
9#elif defined(EMU2413_DLL_IMPORTS)
10 #define EMU2413_API __declspec(dllimport)
11#else
12 #define EMU2413_API
13#endif
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
19#define AUDIO_MONO_BUFFER_SIZE 1024
20
21#define PI 3.14159265358979323846
22
23enum OPLL_TONE_ENUM {OPLL_2413_TONE=0, OPLL_VRC7_TONE=1, OPLL_281B_TONE=2} ;
24
25/* voice data */
26typedef struct __OPLL_PATCH {
27 e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ;
28} OPLL_PATCH ;
29
30/* slot */
31typedef struct __OPLL_SLOT {
32
33 OPLL_PATCH *patch;
34
35 e_int32 type ; /* 0 : modulator 1 : carrier */
36
37 /* OUTPUT */
38 e_int32 feedback ;
39 e_int32 output[2] ; /* Output value of slot */
40
41 /* for Phase Generator (PG) */
42 e_uint16 *sintbl ; /* Wavetable */
43 e_uint32 phase ; /* Phase */
44 e_uint32 dphase ; /* Phase increment amount */
45 e_uint32 pgout ; /* output */
46
47 /* for Envelope Generator (EG) */
48 e_int32 fnum ; /* F-Number */
49 e_int32 block ; /* Block */
50 e_int32 volume ; /* Current volume */
51 e_int32 sustine ; /* Sustine 1 = ON, 0 = OFF */
52 e_uint32 tll ; /* Total Level + Key scale level*/
53 e_uint32 rks ; /* Key scale offset (Rks) */
54 e_int32 eg_mode ; /* Current state */
55 e_uint32 eg_phase ; /* Phase */
56 e_uint32 eg_dphase ; /* Phase increment amount */
57 e_uint32 egout ; /* output */
58
59} OPLL_SLOT ;
60
61/* Mask */
62#define OPLL_MASK_CH(x) (1<<(x))
63#define OPLL_MASK_HH (1<<(9))
64#define OPLL_MASK_CYM (1<<(10))
65#define OPLL_MASK_TOM (1<<(11))
66#define OPLL_MASK_SD (1<<(12))
67#define OPLL_MASK_BD (1<<(13))
68#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
69
70/* opll */
71typedef struct __OPLL {
72
73 e_uint32 adr ;
74 e_int32 out ;
75
76#ifndef EMU2413_COMPACTION
77 e_uint32 realstep ;
78 e_uint32 oplltime ;
79 e_uint32 opllstep ;
80 e_int32 prev, next ;
81 e_int32 sprev[2],snext[2];
82 e_uint32 pan[16];
83#endif
84
85 /* Register */
86 e_uint8 reg[0x40] ;
87 e_int32 slot_on_flag[18] ;
88
89 /* Pitch Modulator */
90 e_uint32 pm_phase ;
91 e_int32 lfo_pm ;
92
93 /* Amp Modulator */
94 e_int32 am_phase ;
95 e_int32 lfo_am ;
96
97 e_uint32 quality;
98
99 /* Noise Generator */
100 e_uint32 noise_seed ;
101
102 /* Channel Data */
103 e_int32 patch_number[9];
104 e_int32 key_status[9] ;
105
106 /* Slot */
107 OPLL_SLOT slot[18] ;
108
109 /* Voice Data */
110 OPLL_PATCH patch[19*2] ;
111 e_int32 patch_update[2] ; /* flag for check patch update */
112
113 e_uint32 mask ;
114 e_uint32 current_mask;
115 e_uint32 status;
116
117 e_uint32 internal_mute;
118 e_int16 buffer[AUDIO_MONO_BUFFER_SIZE];
119} OPLL ;
120
121/* Create Object */
122EMU2413_API void OPLL_new(OPLL *, e_uint32 clk, e_uint32 rate) ;
123EMU2413_API void OPLL_delete(OPLL *) ;
124
125/* Setup */
126EMU2413_API void OPLL_reset(OPLL *) ;
127EMU2413_API void OPLL_reset_patch(OPLL *, e_int32) ;
128EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ;
129EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ;
130EMU2413_API void OPLL_set_pan(OPLL *, e_uint32 ch, e_uint32 pan);
131EMU2413_API void OPLL_set_internal_mute(OPLL *, e_uint32 mute);
132EMU2413_API e_uint32 OPLL_is_internal_muted(OPLL *);
133
134/* Port/Register access */
135EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val);
136EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val);
137EMU2413_API e_uint32 OPLL_read(OPLL *, e_uint32 port);
138
139/* Synthsize */
140EMU2413_API e_int16 OPLL_calc(OPLL *) EMU2413_CALC_ICODE;
141EMU2413_API void OPLL_calc_stereo(OPLL *, e_int32 out[2]) ;
142EMU2413_API e_int16 *OPLL_update_buffer(OPLL *, e_uint32 length) ;
143
144/* Misc */
145EMU2413_API void OPLL_setPatch(OPLL *, const e_uint8 *dump) ;
146EMU2413_API void OPLL_copyPatch(OPLL *, e_int32, OPLL_PATCH *) ;
147EMU2413_API void OPLL_forceRefresh(OPLL *) ;
148/* Utility */
149EMU2413_API void OPLL_dump2patch(const e_uint8 *dump, OPLL_PATCH *patch) ;
150EMU2413_API void OPLL_patch2dump(const OPLL_PATCH *patch, e_uint8 *dump) ;
151EMU2413_API void OPLL_getDefaultPatch(e_int32 type, e_int32 num, OPLL_PATCH *) ;
152
153/* Channel Mask */
154EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ;
155EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ;
156
157#define dump2patch OPLL_dump2patch
158
159#ifdef __cplusplus
160}
161#endif
162
163#endif
164
diff --git a/lib/rbcodec/codecs/libgme/emu8950.c b/lib/rbcodec/codecs/libgme/emu8950.c
new file mode 100644
index 0000000000..2f8a32044f
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emu8950.c
@@ -0,0 +1,1206 @@
1/*
2 * This file is based on:
3 * Y8950.cc -- Y8950 emulator from the openMSX team
4 * ported to c by gama
5 *
6 * The openMSX version is based on:
7 * emu8950.c -- Y8950 emulator written by Mitsutaka Okazaki 2001
8 * heavily rewritten to fit openMSX structure
9 */
10
11#include <math.h>
12#include "emu8950.h"
13
14#ifdef _MSC_VER
15#pragma warning( disable : 4355 )
16#endif
17
18#if !defined(ROCKBOX)
19 #define EMU8950_CALCUL_TABLES
20#else
21 #include "opltables.h"
22#endif
23
24// dB to Liner table
25static short dB2LinTab[(2*DB_MUTE)*2];
26// Dynamic range
27static unsigned int dphaseNoiseTable[1024][8];
28// LFO Table
29int pmtable[2][PM_PG_WIDTH];
30int amtable[2][AM_PG_WIDTH];
31
32/** WaveTable for each envelope amp. */
33static int sintable[PG_WIDTH];
34 /** Phase incr table for Attack. */
35static unsigned int dphaseARTable[16][16];
36/** Phase incr table for Decay and Release. */
37static unsigned int dphaseDRTable[16][16];
38/** KSL + TL Table. */
39#if !defined(ROCKBOX)
40static unsigned char tllTable[16][8][1<<TL_BITS][4];
41#else
42/* Use the table calculated in emu2413 which is identical. */
43extern unsigned char tllTable[16][8][1<<TL_BITS][4];
44#endif
45static int rksTable[2][8][2];
46/** Since we wont change clock rate in rockbox we can
47 skip this table */
48#if !defined(ROCKBOX)
49/** Phase incr table for PG. */
50static unsigned int dphaseTable[1024][8][16];
51#endif
52
53/** Liner to Log curve conversion table (for Attack rate). */
54static int AR_ADJUST_TABLE[1<<EG_BITS];
55
56//**************************************************//
57// //
58// Helper functions //
59// //
60//**************************************************//
61
62#define ALIGN(d, SS, SD) (d*(int)(SS/SD))
63
64inline static int DB_POS(int x)
65{
66 return (int)(x/DB_STEP);
67}
68
69inline static int DB_NEG(int x)
70{
71 return (int)(2*DB_MUTE+x/DB_STEP);
72}
73
74// Cut the lower b bits off
75inline static int HIGHBITS(int c, int b)
76{
77 return c >> b;
78}
79// Leave the lower b bits
80inline static int LOWBITS(int c, int b)
81{
82 return c & ((1<<b)-1);
83}
84// Expand x which is s bits to d bits
85inline static int EXPAND_BITS(int x, int s, int d)
86{
87 return x << (d-s);
88}
89
90//**************************************************//
91// //
92// Create tables //
93// //
94//**************************************************//
95
96// Table for AR to LogCurve.
97static void makeAdjustTable(void)
98{
99 AR_ADJUST_TABLE[0] = 1 << EG_BITS;
100 for (int i = 1; i < (1 << EG_BITS); i++)
101 #ifdef EMU8950_CALCUL_TABLES
102 AR_ADJUST_TABLE[i] = (int)((double)(1 << EG_BITS) - 1 -
103 (1 << EG_BITS) * log((double)i) / log((double)(1 << EG_BITS))) >> 1;
104 #else
105 AR_ADJUST_TABLE[i] = ar_adjust_coeff[i-1];
106 #endif
107}
108
109// Table for dB(0 -- (1<<DB_BITS)) to Liner(0 -- DB2LIN_AMP_WIDTH)
110static void makeDB2LinTable(void)
111{
112 int i;
113 for (i=0; i < 2*DB_MUTE; i++) {
114 dB2LinTab[i] = (i<DB_MUTE) ?
115 #ifdef EMU8950_CALCUL_TABLES
116 (int)((double)((1<<DB2LIN_AMP_BITS)-1)*pow((double)10,-(double)i*DB_STEP/20)) :
117 #else
118 db2lin_coeff[i] :
119 #endif
120 0;
121 dB2LinTab[i + 2*DB_MUTE] = -dB2LinTab[i];
122 }
123}
124
125// Sin Table
126static void makeSinTable(void)
127{
128 int i;
129 for (i=0; i < PG_WIDTH/4; i++)
130 #ifdef EMU8950_CALCUL_TABLES
131 sintable[i] = lin2db(sin(2.0*MPI*i/PG_WIDTH));
132 #else
133 sintable[i] = sin_coeff[i];
134 #endif
135 for (int i=0; i < PG_WIDTH/4; i++)
136 sintable[PG_WIDTH/2 - 1 - i] = sintable[i];
137 for (int i=0; i < PG_WIDTH/2; i++)
138 sintable[PG_WIDTH/2 + i] = 2*DB_MUTE + sintable[i];
139}
140
141static void makeDphaseNoiseTable(int sampleRate, int clockRate)
142{
143 for (int i=0; i<1024; i++)
144 for (int j=0; j<8; j++)
145 dphaseNoiseTable[i][j] = rate_adjust(i<<j, sampleRate, clockRate);
146}
147
148// Table for Pitch Modulator
149static void makePmTable(void)
150{
151 int i;
152 for (i=0; i < PM_PG_WIDTH; i++)
153 #ifdef EMU8950_CALCUL_TABLES
154 pmtable[0][i] = (int)((double)PM_AMP * pow(2.,(double)PM_DEPTH*sin(2.0*MPI*i/PM_PG_WIDTH)/1200));
155 #else
156 pmtable[0][i] = pm0_coeff[i];
157 #endif
158 for (i=0; i < PM_PG_WIDTH; i++)
159 #ifdef EMU8950_CALCUL_TABLES
160 pmtable[1][i] = (int)((double)PM_AMP * pow(2.,(double)PM_DEPTH2*sin(2.0*MPI*i/PM_PG_WIDTH)/1200));
161 #else
162 pmtable[1][i] = pm1_coeff[i];
163 #endif
164}
165
166// Table for Amp Modulator
167static void makeAmTable(void)
168{
169 int i;
170 for (i=0; i<AM_PG_WIDTH; i++)
171 #ifdef EMU8950_CALCUL_TABLES
172 amtable[0][i] = (int)((double)AM_DEPTH/2/DB_STEP * (1.0 + sin(2.0*MPI*i/PM_PG_WIDTH)));
173 #else
174 amtable[0][i] = am0_coeff[i];
175 #endif
176 for (i=0; i<AM_PG_WIDTH; i++)
177 #ifdef EMU8950_CALCUL_TABLES
178 amtable[1][i] = (int)((double)AM_DEPTH2/2/DB_STEP * (1.0 + sin(2.0*MPI*i/PM_PG_WIDTH)));
179 #else
180 amtable[1][i] = am1_coeff[i];
181 #endif
182}
183
184#if !defined(ROCKBOX)
185// Phase increment counter table
186static void makeDphaseTable(int sampleRate, int clockRate)
187{
188 int mltable[16] = {
189 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
190 };
191
192 int fnum, block, ML;
193 for (fnum=0; fnum<1024; fnum++)
194 for (block=0; block<8; block++)
195 for (ML=0; ML<16; ML++)
196 dphaseTable[fnum][block][ML] =
197 rate_adjust((((fnum * mltable[ML]) << block) >> (21 - DP_BITS)), sampleRate, clockRate);
198}
199#endif
200
201#if !defined(ROCKBOX)
202static void makeTllTable(void)
203{
204 #define dB2(x) (int)((x)*2)
205 static int kltable[16] = {
206 dB2( 0.000),dB2( 9.000),dB2(12.000),dB2(13.875),
207 dB2(15.000),dB2(16.125),dB2(16.875),dB2(17.625),
208 dB2(18.000),dB2(18.750),dB2(19.125),dB2(19.500),
209 dB2(19.875),dB2(20.250),dB2(20.625),dB2(21.000)
210 };
211
212 int fnum, block, TL, KL;
213 for (fnum=0; fnum<16; fnum++)
214 for (block=0; block<8; block++)
215 for (TL=0; TL<64; TL++)
216 for (KL=0; KL<4; KL++) {
217 if (KL==0) {
218 tllTable[fnum][block][TL][KL] = (ALIGN(TL, TL_STEP, EG_STEP) ) >> 1;
219 } else {
220 int tmp = kltable[fnum] - dB2(3.000) * (7 - block);
221 if (tmp <= 0)
222 tllTable[fnum][block][TL][KL] = (ALIGN(TL, TL_STEP, EG_STEP) ) >> 1;
223 else
224 tllTable[fnum][block][TL][KL] = ((int)((tmp>>(3-KL))/EG_STEP) + ALIGN(TL, TL_STEP, EG_STEP) ) >> 1;
225 }
226 }
227}
228#endif
229
230// Rate Table for Attack
231static void makeDphaseARTable(int sampleRate, int clockRate)
232{
233 int AR, Rks;
234 for (AR=0; AR<16; AR++)
235 for (Rks=0; Rks<16; Rks++) {
236 int RM = AR + (Rks>>2);
237 int RL = Rks&3;
238 if (RM>15) RM=15;
239 switch (AR) {
240 case 0:
241 dphaseARTable[AR][Rks] = 0;
242 break;
243 case 15:
244 dphaseARTable[AR][Rks] = EG_DP_WIDTH;
245 break;
246 default:
247 dphaseARTable[AR][Rks] = rate_adjust((3*(RL+4) << (RM+1)), sampleRate, clockRate);
248 break;
249 }
250 }
251}
252
253// Rate Table for Decay
254static void makeDphaseDRTable(int sampleRate, int clockRate)
255{
256 int DR, Rks;
257 for (DR=0; DR<16; DR++)
258 for (Rks=0; Rks<16; Rks++) {
259 int RM = DR + (Rks>>2);
260 int RL = Rks&3;
261 if (RM>15) RM=15;
262 switch (DR) {
263 case 0:
264 dphaseDRTable[DR][Rks] = 0;
265 break;
266 default:
267 dphaseDRTable[DR][Rks] = rate_adjust((RL+4) << (RM-1), sampleRate, clockRate);
268 break;
269 }
270 }
271}
272
273static void makeRksTable(void)
274{
275 int fnum9, block, KR;
276 for (fnum9=0; fnum9<2; fnum9++)
277 for (block=0; block<8; block++)
278 for (KR=0; KR<2; KR++) {
279 rksTable[fnum9][block][KR] = (KR != 0) ?
280 (block<<1) + fnum9:
281 block>>1;
282 }
283}
284
285//**********************************************************//
286// //
287// Patch //
288// //
289//**********************************************************//
290
291
292void patchReset(struct Patch* patch)
293{
294 patch->AM = patch->PM = patch->EG = false;
295 patch->KR = patch->ML = patch->KL = patch->TL =
296 patch->FB = patch->AR = patch->DR = patch->SL = patch->RR = 0;
297}
298
299
300//**********************************************************//
301// //
302// Slot //
303// //
304//**********************************************************//
305
306
307static inline void slotUpdatePG(struct Slot* slot)
308{
309#if defined(ROCKBOX)
310 static const int mltable[16] = {
311 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
312 };
313
314 slot->dphase = ((slot->fnum * mltable[slot->patch.ML]) << slot->block) >> (21 - DP_BITS);
315#else
316 slot->dphase = dphaseTable[slot->fnum][slot->block][slot->patch.ML];
317#endif
318}
319
320static inline void slotUpdateTLL(struct Slot* slot)
321{
322 slot->tll = (int)(tllTable[slot->fnum>>6][slot->block][slot->patch.TL][slot->patch.KL]) << 1;
323}
324
325static inline void slotUpdateRKS(struct Slot* slot)
326{
327 slot->rks = rksTable[slot->fnum>>9][slot->block][slot->patch.KR];
328}
329
330static inline void slotUpdateEG(struct Slot* slot)
331{
332 switch (slot->eg_mode) {
333 case ATTACK:
334 slot->eg_dphase = dphaseARTable[slot->patch.AR][slot->rks];
335 break;
336 case DECAY:
337 slot->eg_dphase = dphaseDRTable[slot->patch.DR][slot->rks];
338 break;
339 case SUSTINE:
340 slot->eg_dphase = dphaseDRTable[slot->patch.RR][slot->rks];
341 break;
342 case RELEASE:
343 slot->eg_dphase = slot->patch.EG ?
344 dphaseDRTable[slot->patch.RR][slot->rks]:
345 dphaseDRTable[7] [slot->rks];
346 break;
347 case SUSHOLD:
348 case FINISH:
349 slot->eg_dphase = 0;
350 break;
351 }
352}
353
354static inline void slotUpdateAll(struct Slot* slot)
355{
356 slotUpdatePG(slot);
357 slotUpdateTLL(slot);
358 slotUpdateRKS(slot);
359 slotUpdateEG(slot); // EG should be last
360}
361
362void slotReset(struct Slot* slot)
363{
364 slot->phase = 0;
365 slot->dphase = 0;
366 slot->output[0] = 0;
367 slot->output[1] = 0;
368 slot->feedback = 0;
369 slot->eg_mode = FINISH;
370 slot->eg_phase = EG_DP_WIDTH;
371 slot->eg_dphase = 0;
372 slot->rks = 0;
373 slot->tll = 0;
374 slot->fnum = 0;
375 slot->block = 0;
376 slot->pgout = 0;
377 slot->egout = 0;
378 slot->slotStatus = false;
379 patchReset(&slot->patch);
380 slotUpdateAll(slot);
381}
382
383// Slot key on
384static inline void slotOn(struct Slot* slot)
385{
386 if (!slot->slotStatus) {
387 slot->slotStatus = true;
388 slot->eg_mode = ATTACK;
389 slot->phase = 0;
390 slot->eg_phase = 0;
391 }
392}
393
394// Slot key off
395static inline void slotOff(struct Slot* slot)
396{
397 if (slot->slotStatus) {
398 slot->slotStatus = false;
399 if (slot->eg_mode == ATTACK)
400 slot->eg_phase = EXPAND_BITS(AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase, EG_DP_BITS-EG_BITS)], EG_BITS, EG_DP_BITS);
401 slot->eg_mode = RELEASE;
402 }
403}
404
405
406//**********************************************************//
407// //
408// OPLChannel //
409// //
410//**********************************************************//
411
412
413void channelReset(struct OPLChannel* ch)
414{
415 slotReset(&ch->mod);
416 slotReset(&ch->car);
417 ch->alg = false;
418}
419
420// Set F-Number ( fnum : 10bit )
421static void channelSetFnumber(struct OPLChannel* ch, int fnum)
422{
423 ch->car.fnum = fnum;
424 ch->mod.fnum = fnum;
425}
426
427// Set Block data (block : 3bit )
428static void channelSetBlock(struct OPLChannel* ch, int block)
429{
430 ch->car.block = block;
431 ch->mod.block = block;
432}
433
434// OPLChannel key on
435static void keyOn(struct OPLChannel* ch)
436{
437 slotOn(&ch->mod);
438 slotOn(&ch->car);
439}
440
441// OPLChannel key off
442static void keyOff(struct OPLChannel* ch)
443{
444 slotOff(&ch->mod);
445 slotOff(&ch->car);
446}
447
448
449//**********************************************************//
450// //
451// Y8950 //
452// //
453//**********************************************************//
454
455void OPL_init(struct Y8950* this, byte* ramBank, int sampleRam)
456{
457 this->clockRate = CLK_FREQ;
458
459 ADPCM_init(&this->adpcm, this, ramBank, sampleRam);
460
461 makePmTable();
462 makeAmTable();
463
464 makeAdjustTable();
465 makeDB2LinTable();
466#if !defined(ROCKBOX)
467 makeTllTable();
468#endif
469 makeRksTable();
470 makeSinTable();
471
472 int i;
473 for (i=0; i<9; i++) {
474 // TODO cleanup
475 this->slot[i*2+0] = &(this->ch[i].mod);
476 this->slot[i*2+1] = &(this->ch[i].car);
477 this->ch[i].mod.plfo_am = &this->lfo_am;
478 this->ch[i].mod.plfo_pm = &this->lfo_pm;
479 this->ch[i].car.plfo_am = &this->lfo_am;
480 this->ch[i].car.plfo_pm = &this->lfo_pm;
481 }
482
483 OPL_reset(this);
484}
485
486void OPL_setSampleRate(struct Y8950* this, int sampleRate, int clockRate)
487{
488 this->clockRate = clockRate;
489 ADPCM_setSampleRate(&this->adpcm, sampleRate, clockRate);
490
491#if !defined(ROCKBOX)
492 makeDphaseTable(sampleRate, clockRate);
493#endif
494 makeDphaseARTable(sampleRate, clockRate);
495 makeDphaseDRTable(sampleRate, clockRate);
496 makeDphaseNoiseTable(sampleRate, clockRate);
497 this->pm_dphase = rate_adjust( (int)(PM_SPEED * PM_DP_WIDTH) / (clockRate/72), sampleRate, clockRate);
498 this->am_dphase = rate_adjust( (int)(AM_SPEED * AM_DP_WIDTH) / (clockRate/72), sampleRate, clockRate);
499}
500
501// Reset whole of opl except patch datas.
502void OPL_reset(struct Y8950* this)
503{
504 int i;
505 for (i=0; i<9; i++)
506 channelReset(&this->ch[i]);
507 this->output[0] = 0;
508 this->output[1] = 0;
509
510
511 this->dacSampleVolume = 0;
512 this->dacOldSampleVolume = 0;
513 this->dacSampleVolumeSum = 0;
514 this->dacCtrlVolume = 0;
515 this->dacDaVolume = 0;
516 this->dacEnabled = 0;
517
518 this->rythm_mode = false;
519 this->am_mode = 0;
520 this->pm_mode = 0;
521 this->pm_phase = 0;
522 this->am_phase = 0;
523 this->noise_seed = 0xffff;
524 this->noiseA = 0;
525 this->noiseB = 0;
526 this->noiseA_phase = 0;
527 this->noiseB_phase = 0;
528 this->noiseA_dphase = 0;
529 this->noiseB_dphase = 0;
530
531 for (i = 0; i < 0x100; ++i)
532 this->reg[i] = 0x00;
533
534 this->reg[0x04] = 0x18;
535 this->reg[0x19] = 0x0F; // fixes 'Thunderbirds are Go'
536 this->status = 0x00;
537 this->statusMask = 0;
538 /* irq.reset(); */
539
540 ADPCM_reset(&this->adpcm);
541 OPL_setInternalMute(this, true); // muted
542}
543
544
545// Drum key on
546static inline void keyOn_BD(struct Y8950* this) { keyOn(&this->ch[6]); }
547static inline void keyOn_HH(struct Y8950* this) { slotOn(&this->ch[7].mod); }
548static inline void keyOn_SD(struct Y8950* this) { slotOn(&this->ch[7].car); }
549static inline void keyOn_TOM(struct Y8950* this) { slotOn(&this->ch[8].mod); }
550static inline void keyOn_CYM(struct Y8950* this) { slotOn(&this->ch[8].car); }
551
552// Drum key off
553static inline void keyOff_BD(struct Y8950* this) { keyOff(&this->ch[6]); }
554static inline void keyOff_HH(struct Y8950* this) { slotOff(&this->ch[7].mod); }
555static inline void keyOff_SD(struct Y8950* this) { slotOff(&this->ch[7].car); }
556static inline void keyOff_TOM(struct Y8950* this){ slotOff(&this->ch[8].mod); }
557static inline void keyOff_CYM(struct Y8950* this){ slotOff(&this->ch[8].car); }
558
559// Change Rhythm Mode
560static inline void setRythmMode(struct Y8950* this, int data)
561{
562 bool newMode = (data & 32) != 0;
563 if (this->rythm_mode != newMode) {
564 this->rythm_mode = newMode;
565 if (!this->rythm_mode) {
566 // ON->OFF
567 this->ch[6].mod.eg_mode = FINISH; // BD1
568 this->ch[6].mod.slotStatus = false;
569 this->ch[6].car.eg_mode = FINISH; // BD2
570 this->ch[6].car.slotStatus = false;
571 this->ch[7].mod.eg_mode = FINISH; // HH
572 this->ch[7].mod.slotStatus = false;
573 this->ch[7].car.eg_mode = FINISH; // SD
574 this->ch[7].car.slotStatus = false;
575 this->ch[8].mod.eg_mode = FINISH; // TOM
576 this->ch[8].mod.slotStatus = false;
577 this->ch[8].car.eg_mode = FINISH; // CYM
578 this->ch[8].car.slotStatus = false;
579 }
580 }
581}
582
583//********************************************************//
584// //
585// Generate wave data //
586// //
587//********************************************************//
588
589// Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI).
590inline static int wave2_4pi(int e)
591{
592 int shift = SLOT_AMP_BITS - PG_BITS - 1;
593 if (shift > 0)
594 return e >> shift;
595 else
596 return e << -shift;
597}
598
599// Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI).
600inline static int wave2_8pi(int e)
601{
602 int shift = SLOT_AMP_BITS - PG_BITS - 2;
603 if (shift > 0)
604 return e >> shift;
605 else
606 return e << -shift;
607}
608
609static inline void update_noise(struct Y8950* this)
610{
611 if (this->noise_seed & 1)
612 this->noise_seed ^= 0x24000;
613 this->noise_seed >>= 1;
614 this->whitenoise = this->noise_seed&1 ? DB_POS(6) : DB_NEG(6);
615
616 this->noiseA_phase += this->noiseA_dphase;
617 this->noiseB_phase += this->noiseB_dphase;
618
619 this->noiseA_phase &= (0x40<<11) - 1;
620 if ((this->noiseA_phase>>11)==0x3f)
621 this->noiseA_phase = 0;
622 this->noiseA = this->noiseA_phase&(0x03<<11)?DB_POS(6):DB_NEG(6);
623
624 this->noiseB_phase &= (0x10<<11) - 1;
625 this->noiseB = this->noiseB_phase&(0x0A<<11)?DB_POS(6):DB_NEG(6);
626}
627
628static inline void update_ampm(struct Y8950* this)
629{
630 this->pm_phase = (this->pm_phase + this->pm_dphase)&(PM_DP_WIDTH - 1);
631 this->am_phase = (this->am_phase + this->am_dphase)&(AM_DP_WIDTH - 1);
632 this->lfo_am = amtable[this->am_mode][HIGHBITS(this->am_phase, AM_DP_BITS - AM_PG_BITS)];
633 this->lfo_pm = pmtable[this->pm_mode][HIGHBITS(this->pm_phase, PM_DP_BITS - PM_PG_BITS)];
634}
635
636static inline void calc_phase(struct Slot* slot)
637{
638 if (slot->patch.PM)
639 slot->phase += (slot->dphase * (*slot->plfo_pm)) >> PM_AMP_BITS;
640 else
641 slot->phase += slot->dphase;
642 slot->phase &= (DP_WIDTH - 1);
643 slot->pgout = HIGHBITS(slot->phase, DP_BASE_BITS);
644}
645
646static inline void calc_envelope(struct Slot* slot)
647{
648 #define S2E(x) (ALIGN((unsigned int)(x/SL_STEP),SL_STEP,EG_STEP)<<(EG_DP_BITS-EG_BITS))
649 static unsigned int SL[16] = {
650 S2E( 0), S2E( 3), S2E( 6), S2E( 9), S2E(12), S2E(15), S2E(18), S2E(21),
651 S2E(24), S2E(27), S2E(30), S2E(33), S2E(36), S2E(39), S2E(42), S2E(93)
652 };
653
654 switch (slot->eg_mode) {
655 case ATTACK:
656 slot->eg_phase += slot->eg_dphase;
657 if (EG_DP_WIDTH & slot->eg_phase) {
658 slot->egout = 0;
659 slot->eg_phase= 0;
660 slot->eg_mode = DECAY;
661 slotUpdateEG(slot);
662 } else {
663 slot->egout = AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS)];
664 }
665 break;
666
667 case DECAY:
668 slot->eg_phase += slot->eg_dphase;
669 slot->egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS);
670 if (slot->eg_phase >= SL[slot->patch.SL]) {
671 if (slot->patch.EG) {
672 slot->eg_phase = SL[slot->patch.SL];
673 slot->eg_mode = SUSHOLD;
674 slotUpdateEG(slot);
675 } else {
676 slot->eg_phase = SL[slot->patch.SL];
677 slot->eg_mode = SUSTINE;
678 slotUpdateEG(slot);
679 }
680 slot->egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS);
681 }
682 break;
683
684 case SUSHOLD:
685 slot->egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS);
686 if (!slot->patch.EG) {
687 slot->eg_mode = SUSTINE;
688 slotUpdateEG(slot);
689 }
690 break;
691
692 case SUSTINE:
693 case RELEASE:
694 slot->eg_phase += slot->eg_dphase;
695 slot->egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS);
696 if (slot->egout >= (1<<EG_BITS)) {
697 slot->eg_mode = FINISH;
698 slot->egout = (1<<EG_BITS) - 1;
699 }
700 break;
701
702 case FINISH:
703 slot->egout = (1<<EG_BITS) - 1;
704 break;
705 }
706
707 if (slot->patch.AM)
708 slot->egout = ALIGN(slot->egout+slot->tll,EG_STEP,DB_STEP) + (*slot->plfo_am);
709 else
710 slot->egout = ALIGN(slot->egout+slot->tll,EG_STEP,DB_STEP);
711 if (slot->egout >= DB_MUTE)
712 slot->egout = DB_MUTE-1;
713}
714
715inline static int calc_slot_car(struct Slot* slot, int fm)
716{
717 calc_envelope(slot);
718 calc_phase(slot);
719 if (slot->egout>=(DB_MUTE-1))
720 return 0;
721 return dB2LinTab[sintable[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout];
722}
723
724inline static int calc_slot_mod(struct Slot* slot)
725{
726 slot->output[1] = slot->output[0];
727 calc_envelope(slot);
728 calc_phase(slot);
729
730 if (slot->egout>=(DB_MUTE-1)) {
731 slot->output[0] = 0;
732 } else if (slot->patch.FB!=0) {
733 int fm = wave2_4pi(slot->feedback) >> (7-slot->patch.FB);
734 slot->output[0] = dB2LinTab[sintable[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout];
735 } else
736 slot->output[0] = dB2LinTab[sintable[slot->pgout] + slot->egout];
737
738 slot->feedback = (slot->output[1] + slot->output[0])>>1;
739 return slot->feedback;
740}
741
742// TOM
743inline static int calc_slot_tom(struct Slot* slot)
744{
745 calc_envelope(slot);
746 calc_phase(slot);
747 if (slot->egout>=(DB_MUTE-1))
748 return 0;
749 return dB2LinTab[sintable[slot->pgout] + slot->egout];
750}
751
752// SNARE
753inline static int calc_slot_snare(struct Slot* slot, int whitenoise)
754{
755 calc_envelope(slot);
756 calc_phase(slot);
757 if (slot->egout>=(DB_MUTE-1))
758 return 0;
759 if (slot->pgout & (1<<(PG_BITS-1))) {
760 return (dB2LinTab[slot->egout] + dB2LinTab[slot->egout+whitenoise]) >> 1;
761 } else {
762 return (dB2LinTab[2*DB_MUTE + slot->egout] + dB2LinTab[slot->egout+whitenoise]) >> 1;
763 }
764}
765
766// TOP-CYM
767inline static int calc_slot_cym(struct Slot* slot, int a, int b)
768{
769 calc_envelope(slot);
770 if (slot->egout>=(DB_MUTE-1)) {
771 return 0;
772 } else {
773 return (dB2LinTab[slot->egout+a] + dB2LinTab[slot->egout+b]) >> 1;
774 }
775}
776
777// HI-HAT
778inline static int calc_slot_hat(struct Slot* slot, int a, int b, int whitenoise)
779{
780 calc_envelope(slot);
781 if (slot->egout>=(DB_MUTE-1)) {
782 return 0;
783 } else {
784 return (dB2LinTab[slot->egout+whitenoise] + dB2LinTab[slot->egout+a] + dB2LinTab[slot->egout+b]) >>2;
785 }
786}
787
788
789static inline int calcSample(struct Y8950* this, int channelMask)
790{
791 // while muted update_ampm() and update_noise() aren't called, probably ok
792 update_ampm(this);
793 update_noise(this);
794
795 int mix = 0;
796
797 if (this->rythm_mode) {
798 // TODO wasn't in original source either
799 calc_phase(&this->ch[7].mod);
800 calc_phase(&this->ch[8].car);
801
802 if (channelMask & (1 << 6))
803 mix += calc_slot_car(&this->ch[6].car, calc_slot_mod(&this->ch[6].mod));
804 if (this->ch[7].mod.eg_mode != FINISH)
805 mix += calc_slot_hat(&this->ch[7].mod, this->noiseA, this->noiseB, this->whitenoise);
806 if (channelMask & (1 << 7))
807 mix += calc_slot_snare(&this->ch[7].car, this->whitenoise);
808 if (this->ch[8].mod.eg_mode != FINISH)
809 mix += calc_slot_tom(&this->ch[8].mod);
810 if (channelMask & (1 << 8))
811 mix += calc_slot_cym(&this->ch[8].car, this->noiseA, this->noiseB);
812
813 channelMask &= (1<< 6) - 1;
814 mix *= 2;
815 }
816 struct OPLChannel *cp;
817 for (cp = this->ch; channelMask; channelMask >>=1, cp++) {
818 if (channelMask & 1) {
819 if (cp->alg)
820 mix += calc_slot_car(&cp->car, 0) +
821 calc_slot_mod(&cp->mod);
822 else
823 mix += calc_slot_car(&cp->car,
824 calc_slot_mod(&cp->mod));
825 }
826 }
827
828 mix += ADPCM_calcSample(&this->adpcm);
829
830 return (mix*this->maxVolume) >> (DB2LIN_AMP_BITS - 1);
831}
832
833static bool checkMuteHelper(struct Y8950* this)
834{
835 int i;
836 struct OPLChannel *ch = this->ch;
837 for (i = 0; i < 6; i++) {
838 if (ch[i].car.eg_mode != FINISH) return false;
839 }
840 if (!this->rythm_mode) {
841 for(i = 6; i < 9; i++) {
842 if (ch[i].car.eg_mode != FINISH) return false;
843 }
844 } else {
845 if (ch[6].car.eg_mode != FINISH) return false;
846 if (ch[7].mod.eg_mode != FINISH) return false;
847 if (ch[7].car.eg_mode != FINISH) return false;
848 if (ch[8].mod.eg_mode != FINISH) return false;
849 if (ch[8].car.eg_mode != FINISH) return false;
850 }
851
852 return ADPCM_muted(&this->adpcm);
853}
854
855static void checkMute(struct Y8950* this)
856{
857 bool mute = checkMuteHelper(this);
858 //PRT_DEBUG("Y8950: muted " << mute);
859 OPL_setInternalMute(this, mute);
860}
861
862int* OPL_updateBuffer(struct Y8950* this, int length)
863{
864 //PRT_DEBUG("Y8950: update buffer");
865
866 if (OPL_isInternalMuted(this) && !this->dacEnabled) {
867 return 0;
868 }
869
870 this->dacCtrlVolume = this->dacSampleVolume - this->dacOldSampleVolume + 0x3fe7 * this->dacCtrlVolume / 0x4000;
871 this->dacOldSampleVolume = this->dacSampleVolume;
872
873 int channelMask = 0, i;
874 struct OPLChannel *ch = this->ch;
875 for (i = 9; i--; ) {
876 channelMask <<= 1;
877 if (ch[i].car.eg_mode != FINISH) channelMask |= 1;
878 }
879
880 int* buf = this->buffer;
881 while (length--) {
882 int sample = calcSample(this, channelMask);
883
884 this->dacCtrlVolume = 0x3fe7 * this->dacCtrlVolume / 0x4000;
885 this->dacDaVolume += 2 * (this->dacCtrlVolume - this->dacDaVolume) / 3;
886 sample += 48 * this->dacDaVolume;
887 *(buf++) = sample;
888 }
889
890 this->dacEnabled = this->dacDaVolume;
891
892 checkMute(this);
893 return this->buffer;
894}
895
896void OPL_setInternalVolume(struct Y8950* this, short newVolume)
897{
898 this->maxVolume = newVolume;
899}
900
901//**************************************************//
902// //
903// I/O Ctrl //
904// //
905//**************************************************//
906
907void OPL_writeReg(struct Y8950* this, byte rg, byte data)
908{
909 //PRT_DEBUG("Y8950 write " << (int)rg << " " << (int)data);
910 int stbl[32] = {
911 0, 2, 4, 1, 3, 5,-1,-1,
912 6, 8,10, 7, 9,11,-1,-1,
913 12,14,16,13,15,17,-1,-1,
914 -1,-1,-1,-1,-1,-1,-1,-1
915 };
916
917 //TODO only for registers that influence sound
918 //TODO also ADPCM
919
920 switch (rg & 0xe0) {
921 case 0x00: {
922 switch (rg) {
923 case 0x01: // TEST
924 // TODO
925 // Y8950 MSX-AUDIO Test register $01 (write only)
926 //
927 // Bit Description
928 //
929 // 7 Reset LFOs - seems to force the LFOs to their initial values (eg.
930 // maximum amplitude, zero phase deviation)
931 //
932 // 6 something to do with ADPCM - bit 0 of the status register is
933 // affected by setting this bit (PCM BSY)
934 //
935 // 5 No effect? - Waveform select enable in YM3812 OPL2 so seems
936 // reasonable that this bit wouldn't have been used in OPL
937 //
938 // 4 No effect?
939 //
940 // 3 Faster LFOs - increases the frequencies of the LFOs and (maybe)
941 // the timers (cf. YM2151 test register)
942 //
943 // 2 Reset phase generators - No phase generator output, but envelope
944 // generators still work (can hear a transient when they are gated)
945 //
946 // 1 No effect?
947 //
948 // 0 Reset envelopes - Envelope generator outputs forced to maximum,
949 // so all enabled voices sound at maximum
950 this->reg[rg] = data;
951 break;
952
953 case 0x02: // TIMER1 (reso. 80us)
954 this->reg[rg] = data;
955 break;
956
957 case 0x03: // TIMER2 (reso. 320us)
958 this->reg[rg] = data;
959 break;
960
961 case 0x04: // FLAG CONTROL
962 if (data & R04_IRQ_RESET) {
963 OPL_resetStatus(this, 0x78); // reset all flags
964 } else {
965 OPL_changeStatusMask(this, (~data) & 0x78);
966 this->reg[rg] = data;
967 }
968 break;
969
970 case 0x06: // (KEYBOARD OUT)
971 this->reg[rg] = data;
972 break;
973
974 case 0x07: // START/REC/MEM DATA/REPEAT/SP-OFF/-/-/RESET
975 case 0x08: // CSM/KEY BOARD SPLIT/-/-/SAMPLE/DA AD/64K/ROM
976 case 0x09: // START ADDRESS (L)
977 case 0x0A: // START ADDRESS (H)
978 case 0x0B: // STOP ADDRESS (L)
979 case 0x0C: // STOP ADDRESS (H)
980 case 0x0D: // PRESCALE (L)
981 case 0x0E: // PRESCALE (H)
982 case 0x0F: // ADPCM-DATA
983 case 0x10: // DELTA-N (L)
984 case 0x11: // DELTA-N (H)
985 case 0x12: // ENVELOP CONTROL
986 case 0x1A: // PCM-DATA
987 this->reg[rg] = data;
988 ADPCM_writeReg(&this->adpcm, rg, data);
989 break;
990
991 case 0x15: // DAC-DATA (bit9-2)
992 this->reg[rg] = data;
993 if (this->reg[0x08] & 0x04) {
994 static int damp[] = { 256, 279, 304, 332, 362, 395, 431, 470 };
995 int sample = (short)(256 * this->reg[0x15] + this->reg[0x16]) * 128 / damp[this->reg[0x17]];
996 this->dacSampleVolume = sample;
997 this->dacEnabled = 1;
998 }
999 break;
1000 case 0x16: // (bit1-0)
1001 this->reg[rg] = data & 0xC0;
1002 break;
1003 case 0x17: // (exponent)
1004 this->reg[rg] = data & 0x07;
1005 break;
1006
1007 case 0x18: // I/O-CONTROL (bit3-0)
1008 // TODO
1009 // 0 -> input
1010 // 1 -> output
1011 this->reg[rg] = data;
1012 break;
1013
1014 case 0x19: // I/O-DATA (bit3-0)
1015 // TODO
1016 this->reg[rg] = data;
1017 break;
1018 }
1019
1020 break;
1021 }
1022 case 0x20: {
1023 int s = stbl[rg&0x1f];
1024 if (s >= 0) {
1025 this->slot[s]->patch.AM = (data>>7)&1;
1026 this->slot[s]->patch.PM = (data>>6)&1;
1027 this->slot[s]->patch.EG = (data>>5)&1;
1028 this->slot[s]->patch.KR = (data>>4)&1;
1029 this->slot[s]->patch.ML = (data)&15;
1030 slotUpdateAll(this->slot[s]);
1031 }
1032 this->reg[rg] = data;
1033 break;
1034 }
1035 case 0x40: {
1036 int s = stbl[rg&0x1f];
1037 if (s >= 0) {
1038 this->slot[s]->patch.KL = (data>>6)&3;
1039 this->slot[s]->patch.TL = (data)&63;
1040 slotUpdateAll(this->slot[s]);
1041 }
1042 this->reg[rg] = data;
1043 break;
1044 }
1045 case 0x60: {
1046 int s = stbl[rg&0x1f];
1047 if (s >= 0) {
1048 this->slot[s]->patch.AR = (data>>4)&15;
1049 this->slot[s]->patch.DR = (data)&15;
1050 slotUpdateEG(this->slot[s]);
1051 }
1052 this->reg[rg] = data;
1053 break;
1054 }
1055 case 0x80: {
1056 int s = stbl[rg&0x1f];
1057 if (s >= 0) {
1058 this->slot[s]->patch.SL = (data>>4)&15;
1059 this->slot[s]->patch.RR = (data)&15;
1060 slotUpdateEG(this->slot[s]);
1061 }
1062 this->reg[rg] = data;
1063 break;
1064 }
1065 case 0xa0: {
1066 if (rg==0xbd) {
1067 this->am_mode = (data>>7)&1;
1068 this->pm_mode = (data>>6)&1;
1069
1070 setRythmMode(this, data);
1071 if (this->rythm_mode) {
1072 if (data&0x10) keyOn_BD(this); else keyOff_BD(this);
1073 if (data&0x08) keyOn_SD(this); else keyOff_SD(this);
1074 if (data&0x04) keyOn_TOM(this); else keyOff_TOM(this);
1075 if (data&0x02) keyOn_CYM(this); else keyOff_CYM(this);
1076 if (data&0x01) keyOn_HH(this); else keyOff_HH(this);
1077 }
1078 slotUpdateAll(&this->ch[6].mod);
1079 slotUpdateAll(&this->ch[6].car);
1080 slotUpdateAll(&this->ch[7].mod);
1081 slotUpdateAll(&this->ch[7].car);
1082 slotUpdateAll(&this->ch[8].mod);
1083 slotUpdateAll(&this->ch[8].car);
1084
1085 this->reg[rg] = data;
1086 break;
1087 }
1088 if ((rg&0xf) > 8) {
1089 // 0xa9-0xaf 0xb9-0xbf
1090 break;
1091 }
1092 if (!(rg&0x10)) {
1093 // 0xa0-0xa8
1094 int c = rg-0xa0;
1095 int fNum = data + ((this->reg[rg+0x10]&3)<<8);
1096 int block = (this->reg[rg+0x10]>>2)&7;
1097 channelSetFnumber(&this->ch[c], fNum);
1098 switch (c) {
1099 case 7: this->noiseA_dphase = dphaseNoiseTable[fNum][block];
1100 break;
1101 case 8: this->noiseB_dphase = dphaseNoiseTable[fNum][block];
1102 break;
1103 }
1104 slotUpdateAll(&this->ch[c].car);
1105 slotUpdateAll(&this->ch[c].mod);
1106 this->reg[rg] = data;
1107 } else {
1108 // 0xb0-0xb8
1109 int c = rg-0xb0;
1110 int fNum = ((data&3)<<8) + this->reg[rg-0x10];
1111 int block = (data>>2)&7;
1112 channelSetFnumber(&this->ch[c], fNum);
1113 channelSetBlock(&this->ch[c], block);
1114 switch (c) {
1115 case 7: this->noiseA_dphase = dphaseNoiseTable[fNum][block];
1116 break;
1117 case 8: this->noiseB_dphase = dphaseNoiseTable[fNum][block];
1118 break;
1119 }
1120 if (data&0x20)
1121 keyOn(&this->ch[c]);
1122 else
1123 keyOff(&this->ch[c]);
1124 slotUpdateAll(&this->ch[c].mod);
1125 slotUpdateAll(&this->ch[c].car);
1126 this->reg[rg] = data;
1127 }
1128 break;
1129 }
1130 case 0xc0: {
1131 if (rg > 0xc8)
1132 break;
1133 int c = rg-0xC0;
1134 this->slot[c*2]->patch.FB = (data>>1)&7;
1135 this->ch[c].alg = data&1;
1136 this->reg[rg] = data;
1137 }
1138 }
1139
1140 //TODO only for registers that influence sound
1141 checkMute(this);
1142}
1143
1144byte OPL_readReg(struct Y8950* this, byte rg)
1145{
1146 byte result;
1147 switch (rg) {
1148 case 0x05: // (KEYBOARD IN)
1149 result = 0xff;
1150 break;
1151
1152 case 0x0f: // ADPCM-DATA
1153 case 0x13: // ???
1154 case 0x14: // ???
1155 case 0x1a: // PCM-DATA
1156 result = ADPCM_readReg(&this->adpcm, rg);
1157 break;
1158
1159 case 0x19: // I/O DATA TODO
1160 /* result = ~(switchGetAudio() ? 0 : 0x04); */
1161 result = 0;
1162 break;
1163 default:
1164 result = 255;
1165 }
1166 //PRT_DEBUG("Y8950 read " << (int)rg<<" "<<(int)result);
1167 return result;
1168}
1169
1170byte OPL_readStatus(struct Y8950* this)
1171{
1172 OPL_setStatus(this, STATUS_BUF_RDY); // temp hack
1173 byte tmp = this->status & (0x80 | this->statusMask);
1174 //PRT_DEBUG("Y8950 read status " << (int)tmp);
1175 return tmp | 0x06; // bit 1 and 2 are always 1
1176}
1177
1178
1179void OPL_setStatus(struct Y8950* this, byte flags)
1180{
1181 this->status |= flags;
1182 if (this->status & this->statusMask) {
1183 this->status |= 0x80;
1184 /* irq.set(); */
1185 }
1186}
1187void OPL_resetStatus(struct Y8950* this, byte flags)
1188{
1189 this->status &= ~flags;
1190 if (!(this->status & this->statusMask)) {
1191 this->status &= 0x7f;
1192 /* irq.reset(); */
1193 }
1194}
1195void OPL_changeStatusMask(struct Y8950* this, byte newMask)
1196{
1197 this->statusMask = newMask;
1198 this->status &= this->statusMask;
1199 if (this->status) {
1200 this->status |= 0x80;
1201 /* irq.set(); */
1202 } else {
1203 this->status &= 0x7f;
1204 /* irq.reset(); */
1205 }
1206}
diff --git a/lib/rbcodec/codecs/libgme/emu8950.h b/lib/rbcodec/codecs/libgme/emu8950.h
new file mode 100644
index 0000000000..02169050d2
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emu8950.h
@@ -0,0 +1,248 @@
1#ifndef __Y8950_HH__
2#define __Y8950_HH__
3
4#include "blargg_common.h"
5#include "emuadpcm.h"
6
7#define AUDIO_MONO_BUFFER_SIZE 1024
8
9// Dynamic range of envelope
10static const double EG_STEP = 0.1875;
11#define EG_BITS 9
12#define EG_MUTE (1<<EG_BITS)
13// Dynamic range of sustine level
14static const double SL_STEP = 3.0;
15static const int SL_BITS = 4;
16#define SL_MUTE (1<<SL_BITS)
17// Size of Sintable ( 1 -- 18 can be used, but 7 -- 14 recommended.)
18#define PG_BITS 10
19#define PG_WIDTH (1<<PG_BITS)
20// Phase increment counter
21static const int DP_BITS = 19;
22#define DP_WIDTH (1<<DP_BITS)
23#define DP_BASE_BITS (DP_BITS - PG_BITS)
24// Bits for envelope phase incremental counter
25static const int EG_DP_BITS = 23;
26#define EG_DP_WIDTH (1<<EG_DP_BITS)
27// Dynamic range of total level
28static const double TL_STEP = 0.75;
29#define TL_BITS 6
30#define TL_MUTE (1<<TL_BITS)
31
32static const double DB_STEP = 0.1875;
33#define DB_BITS 9
34#define DB_MUTE (1<<DB_BITS)
35// PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200)
36static const int PM_AMP_BITS = 8;
37#define PM_AMP (1<<PM_AMP_BITS)
38
39
40
41static const int CLK_FREQ = 3579545;
42static const double MPI = 3.14159265358979;
43// PM speed(Hz) and depth(cent)
44static const double PM_SPEED = 6.4;
45static const double PM_DEPTH = (13.75/2);
46static const double PM_DEPTH2 = 13.75;
47// AM speed(Hz) and depth(dB)
48static const double AM_SPEED = 3.7;
49static const double AM_DEPTH = 1.0;
50static const double AM_DEPTH2 = 4.8;
51// Bits for liner value
52static const int DB2LIN_AMP_BITS = 11;
53#define SLOT_AMP_BITS DB2LIN_AMP_BITS
54
55// Bits for Pitch and Amp modulator
56#define PM_PG_BITS 8
57#define PM_PG_WIDTH (1<<PM_PG_BITS)
58static const int PM_DP_BITS = 16;
59#define PM_DP_WIDTH (1<<PM_DP_BITS)
60#define AM_PG_BITS 8
61#define AM_PG_WIDTH (1<<AM_PG_BITS)
62static const int AM_DP_BITS = 16;
63#define AM_DP_WIDTH (1<<AM_DP_BITS)
64
65// Bitmask for register 0x04
66/** Timer1 Start. */
67static const int R04_ST1 = 0x01;
68/** Timer2 Start. */
69static const int R04_ST2 = 0x02;
70// not used
71//static const int R04 = 0x04;
72/** Mask 'Buffer Ready'. */
73static const int R04_MASK_BUF_RDY = 0x08;
74/** Mask 'End of sequence'. */
75static const int R04_MASK_EOS = 0x10;
76/** Mask Timer2 flag. */
77static const int R04_MASK_T2 = 0x20;
78/** Mask Timer1 flag. */
79static const int R04_MASK_T1 = 0x40;
80/** IRQ RESET. */
81static const int R04_IRQ_RESET = 0x80;
82
83// Bitmask for status register
84#define STATUS_EOS (R04_MASK_EOS)
85#define STATUS_BUF_RDY (R04_MASK_BUF_RDY)
86#define STATUS_T2 (R04_MASK_T2)
87#define STATUS_T1 (R04_MASK_T1)
88
89// Definition of envelope mode
90enum { ATTACK,DECAY,SUSHOLD,SUSTINE,RELEASE,FINISH };
91
92struct Patch {
93 bool AM, PM, EG;
94 byte KR; // 0-1
95 byte ML; // 0-15
96 byte KL; // 0-3
97 byte TL; // 0-63
98 byte FB; // 0-7
99 byte AR; // 0-15
100 byte DR; // 0-15
101 byte SL; // 0-15
102 byte RR; // 0-15
103};
104
105void patchReset(struct Patch* p);
106
107struct Slot {
108 // OUTPUT
109 int feedback;
110 /** Output value of slot. */
111 int output[5];
112
113 // for Phase Generator (PG)
114 /** Phase. */
115 unsigned int phase;
116 /** Phase increment amount. */
117 unsigned int dphase;
118 /** Output. */
119 int pgout;
120
121 // for Envelope Generator (EG)
122 /** F-Number. */
123 int fnum;
124 /** Block. */
125 int block;
126 /** Total Level + Key scale level. */
127 int tll;
128 /** Key scale offset (Rks). */
129 int rks;
130 /** Current state. */
131 int eg_mode;
132 /** Phase. */
133 unsigned int eg_phase;
134 /** Phase increment amount. */
135 unsigned int eg_dphase;
136 /** Output. */
137 int egout;
138
139 bool slotStatus;
140 struct Patch patch;
141
142 // refer to Y8950->
143 int *plfo_pm;
144 int *plfo_am;
145};
146
147void slotReset(struct Slot* slot);
148
149
150struct OPLChannel {
151 bool alg;
152 struct Slot mod, car;
153};
154
155void channelReset(struct OPLChannel* ch);
156
157
158struct Y8950
159{
160 int adr;
161 int output[2];
162 // Register
163 byte reg[0x100];
164 bool rythm_mode;
165 // Pitch Modulator
166 int pm_mode;
167 unsigned int pm_phase;
168 // Amp Modulator
169 int am_mode;
170 unsigned int am_phase;
171
172 // Noise Generator
173 int noise_seed;
174 int whitenoise;
175 int noiseA;
176 int noiseB;
177 unsigned int noiseA_phase;
178 unsigned int noiseB_phase;
179 unsigned int noiseA_dphase;
180 unsigned int noiseB_dphase;
181
182 // Channel & Slot
183 struct OPLChannel ch[9];
184 struct Slot *slot[18];
185
186 unsigned int pm_dphase;
187 int lfo_pm;
188 unsigned int am_dphase;
189 int lfo_am;
190
191 int maxVolume;
192 bool internalMuted;
193
194 int clockRate;
195
196 /** STATUS Register. */
197 byte status;
198 /** bit=0 -> masked. */
199 byte statusMask;
200 /* MsxAudioIRQHelper irq; */
201
202 // ADPCM
203 struct Y8950Adpcm adpcm;
204
205 /** 13-bit (exponential) DAC. */
206 /* DACSound16S dac13; */
207
208 // DAC stuff
209 int dacSampleVolume;
210 int dacOldSampleVolume;
211 int dacSampleVolumeSum;
212 int dacCtrlVolume;
213 int dacDaVolume;
214 int dacEnabled;
215
216 // Internal buffer
217 int buffer[AUDIO_MONO_BUFFER_SIZE];
218};
219
220void OPL_init(struct Y8950* this_, byte* ramBank, int sampleRam);
221
222void OPL_reset(struct Y8950* this_);
223void OPL_writeReg(struct Y8950* this_, byte reg, byte data);
224byte OPL_readReg(struct Y8950* this_, byte reg);
225byte OPL_readStatus(struct Y8950* this_);
226static inline void OPL_setInternalMute(struct Y8950* this_, bool muted) { this_->internalMuted = muted; }
227static inline bool OPL_isInternalMuted(struct Y8950* this_) { return this_->internalMuted; }
228
229void OPL_setSampleRate(struct Y8950* this_, int sampleRate, int clockRate);
230int* OPL_updateBuffer(struct Y8950* this_, int length);
231
232// SoundDevice
233void OPL_setInternalVolume(struct Y8950* this_, short maxVolume);
234
235void OPL_setStatus(struct Y8950* this_, byte flags);
236void OPL_resetStatus(struct Y8950* this_, byte flags);
237void OPL_changeStatusMask(struct Y8950* this_, byte newMask);
238
239
240// Adjust envelope speed which depends on sampling rate
241static inline unsigned int rate_adjust(int x, int rate, int clk)
242{
243 unsigned int tmp = (long long)x * clk / 72 / rate;
244// assert (tmp <= 4294967295U);
245 return tmp;
246}
247
248#endif
diff --git a/lib/rbcodec/codecs/libgme/emuadpcm.c b/lib/rbcodec/codecs/libgme/emuadpcm.c
new file mode 100644
index 0000000000..b426a74de5
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emuadpcm.c
@@ -0,0 +1,297 @@
1/*
2 * This file is based on:
3 * Y8950Adpcm.cc -- Y8950 ADPCM emulator from the openMSX team
4 * ported to c by gama
5 *
6 * The openMSX version is based on:
7 * emuadpcm.c -- Y8950 ADPCM emulator written by Mitsutaka Okazaki 2001
8 * heavily rewritten to fit openMSX structure
9 */
10
11#include <string.h>
12
13#include "emuadpcm.h"
14#include "emu8950.h"
15
16// Relative volume between ADPCM part and FM part,
17// value experimentally found by Manuel Bilderbeek
18const int ADPCM_VOLUME = 356;
19
20// Bitmask for register 0x07
21static const int R07_RESET = 0x01;
22//static const int R07 = 0x02;. // not used
23//static const int R07 = 0x04;. // not used
24const int R07_SP_OFF = 0x08;
25const int R07_REPEAT = 0x10;
26const int R07_MEMORY_DATA = 0x20;
27const int R07_REC = 0x40;
28const int R07_START = 0x80;
29
30//Bitmask for register 0x08
31const int R08_ROM = 0x01;
32const int R08_64K = 0x02;
33const int R08_DA_AD = 0x04;
34const int R08_SAMPL = 0x08;
35//const int R08 = 0x10;. // not used
36//const int R08 = 0x20;. // not used
37const int R08_NOTE_SET = 0x40;
38const int R08_CSM = 0x80;
39
40const int DMAX = 0x6000;
41const int DMIN = 0x7F;
42const int DDEF = 0x7F;
43
44const int DECODE_MAX = 32767;
45const int DECODE_MIN = -32768;
46
47#define GETA_BITS 14
48#define MAX_STEP (1<<(16+GETA_BITS))
49
50
51//**************************************************//
52// //
53// Helper functions //
54// //
55//**************************************************//
56
57static int CLAP(int min, int x, int max)
58{
59 return (x < min) ? min : ((max < x) ? max : x);
60}
61
62//**********************************************************//
63// //
64// Y8950Adpcm //
65// //
66//**********************************************************//
67
68
69void ADPCM_init(struct Y8950Adpcm* this_, struct Y8950* y8950_, byte* ramBank, int sampleRam)
70
71{
72 this_->y8950 = y8950_;
73 this_->ramBank = ramBank;
74 this_->ramSize = sampleRam;
75 memset(this_->ramBank, 0xFF, this_->ramSize);
76 this_->volume = 0;
77}
78
79void restart(struct Y8950Adpcm* this_);
80void ADPCM_reset(struct Y8950Adpcm* this_)
81{
82 this_->playing = false;
83 this_->startAddr = 0;
84 this_->stopAddr = 7;
85 this_->memPntr = 0;
86 this_->delta = 0;
87 this_->step = 0;
88 this_->addrMask = (1 << 19) - 1;
89 this_->reg7 = 0;
90 this_->reg15 = 0;
91 ADPCM_writeReg(this_, 0x12, 255); // volume
92 restart(this_);
93}
94
95void ADPCM_setSampleRate(struct Y8950Adpcm* this_, int sr, int clk)
96{
97 this_->sampleRate = sr;
98 this_->clockRate = clk;
99}
100
101bool ADPCM_muted(struct Y8950Adpcm* this_)
102{
103 return (!this_->playing) || (this_->reg7 & R07_SP_OFF);
104}
105
106//**************************************************//
107// //
108// I/O Ctrl //
109// //
110//**************************************************//
111
112void restart(struct Y8950Adpcm* this_)
113{
114 this_->playAddr = this_->startAddr & this_->addrMask;
115 this_->nowStep = MAX_STEP - this_->step;
116 this_->out = this_->output = 0;
117 this_->diff = DDEF;
118 this_->nextLeveling = 0;
119 this_->sampleStep = 0;
120 this_->volumeWStep = (int)((long long)this_->volume * this_->step / MAX_STEP);
121}
122
123void ADPCM_writeReg(struct Y8950Adpcm* this_, byte rg, byte data)
124{
125 switch (rg) {
126 case 0x07: // START/REC/MEM DATA/REPEAT/SP-OFF/-/-/RESET
127 this_->reg7 = data;
128 if (this_->reg7 & R07_RESET) {
129 this_->playing = false;
130 } else if (data & R07_START) {
131 this_->playing = true;
132 restart(this_);
133 }
134 break;
135
136 case 0x08: // CSM/KEY BOARD SPLIT/-/-/SAMPLE/DA AD/64K/ROM
137 this_->romBank = data & R08_ROM;
138 this_->addrMask = data & R08_64K ? (1<<17)-1 : (1<<19)-1;
139 break;
140
141 case 0x09: // START ADDRESS (L)
142 this_->startAddr = (this_->startAddr & 0x7F800) | (data << 3);
143 this_->memPntr = 0;
144 break;
145 case 0x0A: // START ADDRESS (H)
146 this_->startAddr = (this_->startAddr & 0x007F8) | (data << 11);
147 this_->memPntr = 0;
148 break;
149
150 case 0x0B: // STOP ADDRESS (L)
151 this_->stopAddr = (this_->stopAddr & 0x7F807) | (data << 3);
152 break;
153 case 0x0C: // STOP ADDRESS (H)
154 this_->stopAddr = (this_->stopAddr & 0x007FF) | (data << 11);
155 break;
156
157
158 case 0x0F: // ADPCM-DATA
159 // TODO check this
160 //if ((reg7 & R07_REC) && (reg7 & R07_MEMORY_DATA)) {
161 {
162 int tmp = ((this_->startAddr + this_->memPntr) & this_->addrMask) / 2;
163 tmp = (tmp < this_->ramSize) ? tmp : (tmp & (this_->ramSize - 1));
164 if (!this_->romBank) {
165 this_->ramBank[tmp] = data;
166 }
167 //PRT_DEBUG("Y8950Adpcm: mem " << tmp << " " << (int)data);
168 this_->memPntr += 2;
169 if ((this_->startAddr + this_->memPntr) > this_->stopAddr) {
170 OPL_setStatus(this_->y8950, STATUS_EOS);
171 }
172 }
173 OPL_setStatus(this_->y8950, STATUS_BUF_RDY);
174 break;
175
176 case 0x10: // DELTA-N (L)
177 this_->delta = (this_->delta & 0xFF00) | data;
178 this_->step = rate_adjust(this_->delta<<GETA_BITS, this_->sampleRate, this_->clockRate);
179 this_->volumeWStep = (int)((long long)this_->volume * this_->step / MAX_STEP);
180 break;
181 case 0x11: // DELTA-N (H)
182 this_->delta = (this_->delta & 0x00FF) | (data << 8);
183 this_->step = rate_adjust(this_->delta<<GETA_BITS, this_->sampleRate, this_->clockRate);
184 this_->volumeWStep = (int)((long long)this_->volume * this_->step / MAX_STEP);
185 break;
186
187 case 0x12: { // ENVELOP CONTROL
188 int oldVol = this_->volume;
189 this_->volume = (data * ADPCM_VOLUME) >> 8;
190 if (oldVol != 0) {
191 this_->output = (int)(((long long)this_->output * this_->volume) / oldVol);
192 this_->sampleStep = (int)(((long long)this_->sampleStep * this_->volume) / oldVol);
193 }
194 this_->volumeWStep = (int)((long long)this_->volume * this_->step / MAX_STEP);
195 break;
196 }
197 case 0x0D: // PRESCALE (L)
198 case 0x0E: // PRESCALE (H)
199 case 0x15: // DAC-DATA (bit9-2)
200 case 0x16: // (bit1-0)
201 case 0x17: // (exponent)
202 case 0x1A: // PCM-DATA
203 // not implemented
204 break;
205 }
206}
207
208byte ADPCM_readReg(struct Y8950Adpcm* this_, byte rg)
209{
210 byte result;
211 switch (rg) {
212 case 0x0F: { // ADPCM-DATA
213 // TODO don't advance pointer when playing???
214 int adr = ((this_->startAddr + this_->memPntr) & this_->addrMask) / 2;
215 if (this_->romBank || (adr >= this_->ramSize)) {
216 result = 0xFF;
217 } else {
218 result = this_->ramBank[adr];
219 }
220 this_->memPntr += 2;
221 if ((this_->startAddr + this_->memPntr) > this_->stopAddr) {
222 OPL_setStatus(this_->y8950, STATUS_EOS);
223 }
224 break;
225 }
226 case 0x13: // TODO check
227 result = this_->out & 0xFF;
228 break;
229 case 0x14: // TODO check
230 result = this_->out / 256;
231 break;
232 default:
233 result = 255;
234 }
235 //PRT_DEBUG("Y8950Adpcm: read "<<(int)rg<<" "<<(int)result);
236 return result;
237}
238
239int ADPCM_calcSample(struct Y8950Adpcm* this_)
240{
241 // This table values are from ymdelta.c by Tatsuyuki Satoh.
242 static const int F1[16] = { 1, 3, 5, 7, 9, 11, 13, 15,
243 -1, -3, -5, -7, -9, -11, -13, -15};
244 static const int F2[16] = {57, 57, 57, 57, 77, 102, 128, 153,
245 57, 57, 57, 57, 77, 102, 128, 153};
246
247 if (ADPCM_muted(this_)) {
248 return 0;
249 }
250 this_->nowStep += this_->step;
251 if (this_->nowStep >= MAX_STEP) {
252 int nowLeveling;
253 do {
254 this_->nowStep -= MAX_STEP;
255 unsigned long val;
256 if (!(this_->playAddr & 1)) {
257 // n-th nibble
258 int tmp = this_->playAddr / 2;
259 if (this_->romBank || (tmp >= this_->ramSize)) {
260 this_->reg15 = 0xFF;
261 } else {
262 this_->reg15 = this_->ramBank[tmp];
263 }
264 val = this_->reg15 >> 4;
265 } else {
266 // (n+1)-th nibble
267 val = this_->reg15 & 0x0F;
268 }
269 int prevOut = this_->out;
270 this_->out = CLAP(DECODE_MIN, this_->out + (this_->diff * F1[val]) / 8,
271 DECODE_MAX);
272 this_->diff = CLAP(DMIN, (this_->diff * F2[val]) / 64, DMAX);
273 int deltaNext = this_->out - prevOut;
274 nowLeveling = this_->nextLeveling;
275 this_->nextLeveling = prevOut + deltaNext / 2;
276
277 this_->playAddr++;
278 if (this_->playAddr > this_->stopAddr) {
279 if (this_->reg7 & R07_REPEAT) {
280 restart(this_);
281 } else {
282 this_->playing = false;
283 //y8950.setStatus(Y8950::STATUS_EOS);
284 }
285 }
286 } while (this_->nowStep >= MAX_STEP);
287 this_->sampleStep = (this_->nextLeveling - nowLeveling) * this_->volumeWStep;
288 this_->output = nowLeveling * this_->volume;
289
290 /* TODO: Used fixed point math here */
291 #if !defined(ROCKBOX)
292 this_->output += (int)(((long long)this_->sampleStep * this_->nowStep) / this_->step);
293 #endif
294 }
295 this_->output += this_->sampleStep;
296 return this_->output >> 12;
297}
diff --git a/lib/rbcodec/codecs/libgme/emuadpcm.h b/lib/rbcodec/codecs/libgme/emuadpcm.h
new file mode 100644
index 0000000000..0fc39a1709
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emuadpcm.h
@@ -0,0 +1,52 @@
1#ifndef __Y8950ADPCM_HH__
2#define __Y8950ADPCM_HH__
3
4#include "blargg_common.h"
5#include "blargg_source.h"
6#include "msxtypes.h"
7
8typedef unsigned short word;
9typedef unsigned __int64 uint64;
10struct Y8950;
11
12struct Y8950Adpcm
13{
14 struct Y8950* y8950;
15
16 int sampleRate;
17 int clockRate;
18
19 int ramSize;
20 int startAddr;
21 int stopAddr;
22 int playAddr;
23 int addrMask;
24 int memPntr;
25 bool romBank;
26 byte* ramBank;
27
28 bool playing;
29 int volume;
30 word delta;
31 unsigned int nowStep, step;
32 int out, output;
33 int diff;
34 int nextLeveling;
35 int sampleStep;
36 int volumeWStep;
37
38 byte reg7;
39 byte reg15;
40};
41
42
43void ADPCM_init(struct Y8950Adpcm* this_, struct Y8950* y8950, byte* ramBank, int sampleRam);
44void ADPCM_reset(struct Y8950Adpcm* this_);
45void ADPCM_setSampleRate(struct Y8950Adpcm* this_, int sr, int clk);
46bool ADPCM_muted(struct Y8950Adpcm* this_);
47void ADPCM_writeReg(struct Y8950Adpcm* this_, byte rg, byte data);
48byte ADPCM_readReg(struct Y8950Adpcm* this_, byte rg);
49int ADPCM_calcSample(struct Y8950Adpcm* this_);
50
51
52#endif
diff --git a/lib/rbcodec/codecs/libgme/emutables.h b/lib/rbcodec/codecs/libgme/emutables.h
new file mode 100644
index 0000000000..739c8c390a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emutables.h
@@ -0,0 +1,210 @@
1#ifndef _EMUTABLES_H_
2#define _EMUTABLES_H_
3
4/* Precalculated emu2413 tables for use in Rockbox,
5 Calculated for 44Khz sampling rate */
6
7#include "emutypes.h"
8
9static const e_uint16 sin_coeff[] = {
10 255, 203, 171, 152, 139, 129, 120,
11 113, 107, 102, 97, 92, 88, 85,
12 81, 78, 75, 72, 70, 67, 65,
13 63, 61, 59, 57, 55, 53, 52,
14 50, 48, 47, 45, 44, 43, 41,
15 40, 39, 38, 37, 35, 34, 33,
16 32, 31, 30, 29, 28, 28, 27,
17 26, 25, 24, 23, 23, 22, 21,
18 21, 20, 19, 19, 18, 17, 17,
19 16, 16, 15, 14, 14, 13, 13,
20 12, 12, 11, 11, 11, 10, 10,
21 9, 9, 8, 8, 8, 7, 7,
22 7, 6, 6, 6, 5, 5, 5,
23 4, 4, 4, 4, 3, 3, 3,
24 3, 2, 2, 2, 2, 2, 2,
25 1, 1, 1, 1, 1, 1, 1,
26 0, 0, 0, 0, 0, 0, 0,
27 0, 0, 0, 0, 0, 0, 0,
28 0, 0,
29};
30
31static const e_int16 pm_coeff[] = {
32 256, 256, 256, 256, 256, 256, 256,
33 256, 256, 256, 256, 256, 256, 256,
34 256, 256, 256, 256, 256, 256, 256,
35 256, 256, 256, 256, 256, 256, 256,
36 256, 256, 256, 256, 257, 257, 257,
37 257, 257, 257, 257, 257, 257, 257,
38 257, 257, 257, 257, 257, 257, 257,
39 257, 257, 257, 257, 257, 257, 257,
40 257, 257, 257, 257, 257, 257, 257,
41 258, 258, 258, 257, 257, 257, 257,
42 257, 257, 257, 257, 257, 257, 257,
43 257, 257, 257, 257, 257, 257, 257,
44 257, 257, 257, 257, 257, 257, 257,
45 257, 257, 257, 257, 257, 257, 256,
46 256, 256, 256, 256, 256, 256, 256,
47 256, 256, 256, 256, 256, 256, 256,
48 256, 256, 256, 256, 256, 256, 256,
49 256, 256, 256, 256, 256, 256, 256,
50 256, 256, 256, 255, 255, 255, 255,
51 255, 255, 255, 255, 255, 255, 255,
52 255, 255, 255, 255, 255, 255, 255,
53 255, 255, 255, 255, 255, 255, 255,
54 255, 255, 255, 255, 255, 255, 254,
55 254, 254, 254, 254, 254, 254, 254,
56 254, 254, 254, 254, 254, 254, 254,
57 254, 254, 254, 254, 254, 254, 254,
58 254, 254, 254, 254, 254, 254, 254,
59 254, 254, 254, 253, 254, 254, 254,
60 254, 254, 254, 254, 254, 254, 254,
61 254, 254, 254, 254, 254, 254, 254,
62 254, 254, 254, 254, 254, 254, 254,
63 254, 254, 254, 254, 254, 254, 254,
64 254, 255, 255, 255, 255, 255, 255,
65 255, 255, 255, 255, 255, 255, 255,
66 255, 255, 255, 255, 255, 255, 255,
67 255, 255, 255, 255, 255, 255, 255,
68 255, 255, 255, 255,
69};
70
71static const e_int8 am_coeff[] = {
72 13, 13, 13, 13, 13, 14, 14,
73 14, 14, 14, 15, 15, 15, 15,
74 15, 16, 16, 16, 16, 16, 17,
75 17, 17, 17, 17, 18, 18, 18,
76 18, 18, 19, 19, 19, 19, 19,
77 20, 20, 20, 20, 20, 21, 21,
78 21, 21, 21, 22, 22, 22, 22,
79 22, 23, 23, 23, 23, 23, 24,
80 24, 24, 24, 24, 25, 25, 25,
81 25, 26, 25, 25, 25, 25, 24,
82 24, 24, 24, 24, 23, 23, 23,
83 23, 23, 22, 22, 22, 22, 22,
84 21, 21, 21, 21, 21, 20, 20,
85 20, 20, 20, 19, 19, 19, 19,
86 19, 18, 18, 18, 18, 18, 17,
87 17, 17, 17, 17, 16, 16, 16,
88 16, 16, 15, 15, 15, 15, 15,
89 14, 14, 14, 14, 14, 13, 13,
90 13, 13, 13, 12, 12, 12, 12,
91 11, 11, 11, 11, 11, 10, 10,
92 10, 10, 10, 9, 9, 9, 9,
93 9, 8, 8, 8, 8, 8, 7,
94 7, 7, 7, 7, 6, 6, 6,
95 6, 6, 5, 5, 5, 5, 5,
96 4, 4, 4, 4, 4, 3, 3,
97 3, 3, 3, 2, 2, 2, 2,
98 2, 1, 1, 1, 1, 1, 0,
99 0, 0, 0, 0, 0, 0, 0,
100 0, 1, 1, 1, 1, 1, 2,
101 2, 2, 2, 2, 3, 3, 3,
102 3, 3, 4, 4, 4, 4, 4,
103 5, 5, 5, 5, 5, 6, 6,
104 6, 6, 6, 7, 7, 7, 7,
105 7, 8, 8, 8, 8, 8, 9,
106 9, 9, 9, 9, 10, 10, 10,
107 10, 10, 11, 11, 11, 11, 11,
108 12, 12, 12, 12,
109};
110
111static const e_int16 db2lin_coeff[] = {
112 255, 249, 244, 239, 233, 228, 224,
113 219, 214, 209, 205, 201, 196, 192,
114 188, 184, 180, 176, 172, 169, 165,
115 162, 158, 155, 151, 148, 145, 142,
116 139, 136, 133, 130, 127, 125, 122,
117 119, 117, 114, 112, 109, 107, 105,
118 102, 100, 98, 96, 94, 92, 90,
119 88, 86, 84, 82, 81, 79, 77,
120 76, 74, 72, 71, 69, 68, 66,
121 65, 64, 62, 61, 60, 58, 57,
122 56, 55, 53, 52, 51, 50, 49,
123 48, 47, 46, 45, 44, 43, 42,
124 41, 40, 39, 38, 38, 37, 36,
125 35, 34, 34, 33, 32, 32, 31,
126 30, 30, 29, 28, 28, 27, 27,
127 26, 25, 25, 24, 24, 23, 23,
128 22, 22, 21, 21, 20, 20, 19,
129 19, 19, 18, 18, 17, 17, 17,
130 16, 16, 16, 15, 15, 15, 14,
131 14, 14, 13, 13, 13, 12, 12,
132 12, 12, 11, 11, 11, 11, 10,
133 10, 10, 10, 10, 9, 9, 9,
134 9, 8, 8, 8, 8, 8, 8,
135 7, 7, 7, 7, 7, 7, 6,
136 6, 6, 6, 6, 6, 6, 5,
137 5, 5, 5, 5, 5, 5, 5,
138 5, 4, 4, 4, 4, 4, 4,
139 4, 4, 4, 4, 3, 3, 3,
140 3, 3, 3, 3, 3, 3, 3,
141 3, 3, 3, 2, 2, 2, 2,
142 2, 2, 2, 2, 2, 2, 2,
143 2, 2, 2, 2, 2, 2, 2,
144 2, 1, 1, 1, 1, 1, 1,
145 1, 1, 1, 1, 1, 1, 1,
146 1, 1, 1, 1, 1, 1, 1,
147 1, 1, 1, 1, 1, 1, 1,
148 1, 1, 1, 1, 1, 0, 0,
149 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, 0,
152 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 0, 0, 0, 0,
156 0, 0, 0, 0, 0, 0, 0,
157 0, 0, 0, 0, 0, 0, 0,
158 0, 0, 0, 0, 0, 0, 0,
159 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0,
161 0, 0, 0, 0, 0, 0, 0,
162 0, 0, 0, 0, 0, 0, 0,
163 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0,
173 0, 0, 0, 0, 0, 0, 0,
174 0, 0, 0, 0, 0, 0, 0,
175 0, 0, 0, 0, 0, 0, 0,
176 0, 0, 0, 0, 0, 0, 0,
177 0, 0, 0, 0, 0, 0, 0,
178 0, 0, 0, 0, 0, 0, 0,
179 0, 0, 0, 0, 0, 0, 0,
180 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0, 0, 0,
183 0, 0, 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0, 0, 0,
185 0,
186};
187
188static const e_uint16 ar_adjust_coeff[] = {
189 127, 108, 98, 90, 84, 80, 75,
190 72, 69, 66, 64, 61, 59, 57,
191 56, 54, 52, 51, 49, 48, 47,
192 45, 44, 43, 42, 41, 40, 39,
193 38, 37, 36, 36, 35, 34, 33,
194 33, 32, 31, 30, 30, 29, 29,
195 28, 27, 27, 26, 26, 25, 24,
196 24, 23, 23, 22, 22, 21, 21,
197 21, 20, 20, 19, 19, 18, 18,
198 17, 17, 17, 16, 16, 15, 15,
199 15, 14, 14, 14, 13, 13, 13,
200 12, 12, 12, 11, 11, 11, 10,
201 10, 10, 9, 9, 9, 9, 8,
202 8, 8, 7, 7, 7, 7, 6,
203 6, 6, 6, 5, 5, 5, 4,
204 4, 4, 4, 4, 3, 3, 3,
205 3, 2, 2, 2, 2, 1, 1,
206 1, 1, 1, 0, 0, 0, 0,
207 0,
208};
209
210#endif
diff --git a/lib/rbcodec/codecs/libgme/emutypes.h b/lib/rbcodec/codecs/libgme/emutypes.h
new file mode 100644
index 0000000000..bc523db072
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/emutypes.h
@@ -0,0 +1,41 @@
1#ifndef _EMUTYPES_H_
2#define _EMUTYPES_H_
3
4#if defined(_MSC_VER)
5#define INLINE __forceinline
6#elif defined(__GNUC__)
7#define INLINE __inline__
8#elif defined(_MWERKS_)
9#define INLINE inline
10#else
11#define INLINE
12#endif
13
14#if defined(EMU_DLL_IMPORTS)
15#define EMU2149_DLL_IMPORTS
16#define EMU2212_DLL_IMPORTS
17#define EMU2413_DLL_IMPORTS
18#define EMU8950_DLL_IMPORTS
19#define EMU76489_DLL_IMPORTS
20#endif
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26typedef unsigned int e_uint;
27typedef signed int e_int;
28
29typedef unsigned char e_uint8 ;
30typedef signed char e_int8 ;
31
32typedef unsigned short e_uint16 ;
33typedef signed short e_int16 ;
34
35typedef unsigned int e_uint32 ;
36typedef signed int e_int32 ;
37
38#ifdef __cplusplus
39}
40#endif
41#endif
diff --git a/lib/rbcodec/codecs/libgme/gb_apu.c b/lib/rbcodec/codecs/libgme/gb_apu.c
new file mode 100644
index 0000000000..e8bf3afcf5
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_apu.c
@@ -0,0 +1,410 @@
1// Gb_Snd_Emu 0.1.4. http://www.slack.net/~ant/
2
3#include "gb_apu.h"
4
5//#include "gb_apu_logger.h"
6
7/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20int const vol_reg = 0xFF24;
21int const stereo_reg = 0xFF25;
22int const status_reg = 0xFF26;
23int const wave_ram = 0xFF30;
24
25int const power_mask = 0x80;
26
27static inline int calc_output( struct Gb_Apu* this, int osc )
28{
29 int bits = this->regs [stereo_reg - io_addr] >> osc;
30 return (bits >> 3 & 2) | (bits & 1);
31}
32
33void Apu_set_output( struct Gb_Apu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
34{
35 // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
36 require( !center || (center && !left && !right) || (center && left && right) );
37 require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
38
39 if ( !center || !left || !right )
40 {
41 left = center;
42 right = center;
43 }
44
45 struct Gb_Osc* o = this->oscs [i];
46 o->outputs [1] = right;
47 o->outputs [2] = left;
48 o->outputs [3] = center;
49 o->output = o->outputs [calc_output( this, i )];
50}
51
52static void synth_volume( struct Gb_Apu* this, int iv )
53{
54 int v = (this->volume_ * 6) / 10 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
55 Synth_volume( &this->synth, v );
56}
57
58static void apply_volume( struct Gb_Apu* this )
59{
60 // TODO: Doesn't handle differing left and right volumes (panning).
61 // Not worth the complexity.
62 int data = this->regs [vol_reg - io_addr];
63 int left = data >> 4 & 7;
64 int right = data & 7;
65 //if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
66 //if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
67 synth_volume( this, max( left, right ) + 1 );
68}
69
70void Apu_volume( struct Gb_Apu* this, int v )
71{
72 if ( this->volume_ != v )
73 {
74 this->volume_ = v;
75 apply_volume( this );
76 }
77}
78
79static void reset_regs( struct Gb_Apu* this )
80{
81 int i;
82 for ( i = 0; i < 0x20; i++ )
83 this->regs [i] = 0;
84
85 Sweep_reset ( &this->square1 );
86 Square_reset( &this->square2 );
87 Wave_reset ( &this->wave );
88 Noise_reset ( &this->noise );
89
90 apply_volume( this );
91}
92
93static void reset_lengths( struct Gb_Apu* this )
94{
95 this->square1.osc.length_ctr = 64;
96 this->square2.osc.length_ctr = 64;
97 this->wave .osc.length_ctr = 256;
98 this->noise .osc.length_ctr = 64;
99}
100
101void Apu_reduce_clicks( struct Gb_Apu* this, bool reduce )
102{
103 this->reduce_clicks_ = reduce;
104
105 // Click reduction makes DAC off generate same output as volume 0
106 int dac_off_amp = 0;
107 if ( reduce && this->wave.osc.mode != mode_agb ) // AGB already eliminates clicks
108 dac_off_amp = -dac_bias;
109
110 int i;
111 for ( i = 0; i < osc_count; i++ )
112 this->oscs [i]->dac_off_amp = dac_off_amp;
113
114 // AGB always eliminates clicks on wave channel using same method
115 if ( this->wave.osc.mode == mode_agb )
116 this->wave.osc.dac_off_amp = -dac_bias;
117}
118
119void Apu_reset( struct Gb_Apu* this, enum gb_mode_t mode, bool agb_wave )
120{
121 // Hardware mode
122 if ( agb_wave )
123 mode = mode_agb; // using AGB wave features implies AGB hardware
124 this->wave.agb_mask = agb_wave ? 0xFF : 0;
125 int i;
126 for ( i = 0; i < osc_count; i++ )
127 this->oscs [i]->mode = mode;
128 Apu_reduce_clicks( this, this->reduce_clicks_ );
129
130 // Reset state
131 this->frame_time = 0;
132 this->last_time = 0;
133 this->frame_phase = 0;
134
135 reset_regs( this );
136 reset_lengths( this );
137
138 // Load initial wave RAM
139 static byte const initial_wave [2] [16] = {
140 {0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
141 {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
142 };
143 int b;
144 for ( b = 2; --b >= 0; )
145 {
146 // Init both banks (does nothing if not in AGB mode)
147 // TODO: verify that this works
148 Apu_write_register( this, 0, 0xFF1A, b * 0x40 );
149 unsigned i;
150 for ( i = 0; i < sizeof initial_wave [0]; i++ )
151 Apu_write_register( this, 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
152 }
153}
154
155void Apu_set_tempo( struct Gb_Apu* this, int t )
156{
157 this->frame_period = 4194304 / 512; // 512 Hz
158 if ( t != (int)FP_ONE_TEMPO )
159 this->frame_period = t ? (blip_time_t) ((this->frame_period * FP_ONE_TEMPO) / t) : (blip_time_t) (0);
160}
161
162void Apu_init( struct Gb_Apu* this )
163{
164 this->wave.wave_ram = &this->regs [wave_ram - io_addr];
165
166 Synth_init( &this->synth );
167
168 this->oscs [0] = &this->square1.osc;
169 this->oscs [1] = &this->square2.osc;
170 this->oscs [2] = &this->wave.osc;
171 this->oscs [3] = &this->noise.osc;
172
173 int i;
174 for ( i = osc_count; --i >= 0; )
175 {
176 struct Gb_Osc* o = this->oscs [i];
177 o->regs = &this->regs [i * 5];
178 o->output = NULL;
179 o->outputs [0] = NULL;
180 o->outputs [1] = NULL;
181 o->outputs [2] = NULL;
182 o->outputs [3] = NULL;
183 o->synth = &this->synth;
184 }
185
186 this->reduce_clicks_ = false;
187 Apu_set_tempo( this, (int)FP_ONE_TEMPO );
188 this->volume_ = (int)FP_ONE_VOLUME;
189 Apu_reset( this, mode_cgb, false );
190}
191
192static void run_until_( struct Gb_Apu* this, blip_time_t end_time )
193{
194 if ( !this->frame_period )
195 this->frame_time += end_time - this->last_time;
196
197 while ( true )
198 {
199 // run oscillators
200 blip_time_t time = end_time;
201 if ( time > this->frame_time )
202 time = this->frame_time;
203
204 Square_run( &this->square1, this->last_time, time );
205 Square_run( &this->square2, this->last_time, time );
206 Wave_run ( &this->wave, this->last_time, time );
207 Noise_run ( &this->noise, this->last_time, time );
208 this->last_time = time;
209
210 if ( time == end_time )
211 break;
212
213 // run frame sequencer
214 assert( this->frame_period );
215 this->frame_time += this->frame_period * clk_mul;
216 switch ( this->frame_phase++ )
217 {
218 case 2:
219 case 6:
220 // 128 Hz
221 clock_sweep( &this->square1 );
222 case 0:
223 case 4:
224 // 256 Hz
225 Osc_clock_length( &this->square1.osc );
226 Osc_clock_length( &this->square2.osc);
227 Osc_clock_length( &this->wave.osc);
228 Osc_clock_length( &this->noise.osc);
229 break;
230
231 case 7:
232 // 64 Hz
233 this->frame_phase = 0;
234 Square_clock_envelope( &this->square1 );
235 Square_clock_envelope( &this->square2 );
236 Noise_clock_envelope( &this->noise );
237 }
238 }
239}
240
241static inline void run_until( struct Gb_Apu* this, blip_time_t time )
242{
243 require( time >= this->last_time ); // end_time must not be before previous time
244 if ( time > this->last_time )
245 run_until_( this, time );
246}
247
248void Apu_end_frame( struct Gb_Apu* this, blip_time_t end_time )
249{
250 #ifdef LOG_FRAME
251 LOG_FRAME( end_time );
252 #endif
253
254 if ( end_time > this->last_time )
255 run_until( this, end_time );
256
257 this->frame_time -= end_time;
258 assert( this->frame_time >= 0 );
259
260 this->last_time -= end_time;
261 assert( this->last_time >= 0 );
262}
263
264static void silence_osc( struct Gb_Apu* this, struct Gb_Osc* o )
265{
266 int delta = -o->last_amp;
267 if ( this->reduce_clicks_ )
268 delta += o->dac_off_amp;
269
270 if ( delta )
271 {
272 o->last_amp = o->dac_off_amp;
273 if ( o->output )
274 {
275 Blip_set_modified( o->output );
276 Synth_offset( &this->synth, this->last_time, delta, o->output );
277 }
278 }
279}
280
281static void apply_stereo( struct Gb_Apu* this )
282{
283 int i;
284 for ( i = osc_count; --i >= 0; )
285 {
286 struct Gb_Osc* o = this->oscs [i];
287 struct Blip_Buffer* out = o->outputs [calc_output( this, i )];
288 if ( o->output != out )
289 {
290 silence_osc( this, o );
291 o->output = out;
292 }
293 }
294}
295
296void Apu_write_register( struct Gb_Apu* this, blip_time_t time, int addr, int data )
297{
298 require( (unsigned) data < 0x100 );
299
300 int reg = addr - io_addr;
301 if ( (unsigned) reg >= io_size )
302 {
303 require( false );
304 return;
305 }
306
307 #ifdef LOG_WRITE
308 LOG_WRITE( time, addr, data );
309 #endif
310
311 if ( addr < status_reg && !(this->regs [status_reg - io_addr] & power_mask) )
312 {
313 // Power is off
314
315 // length counters can only be written in DMG mode
316 if ( this->wave.osc.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
317 return;
318
319 if ( reg < 10 )
320 data &= 0x3F; // clear square duty
321 }
322
323 run_until( this, time );
324
325 if ( addr >= wave_ram )
326 {
327 Wave_write( &this->wave, addr, data );
328 }
329 else
330 {
331 int old_data = this->regs [reg];
332 this->regs [reg] = data;
333
334 if ( addr < vol_reg )
335 {
336 // Oscillator
337 write_osc( this, reg, old_data, data );
338 }
339 else if ( addr == vol_reg && data != old_data )
340 {
341 // Master volume
342 int i;
343 for ( i = osc_count; --i >= 0; )
344 silence_osc( this, this->oscs [i] );
345
346 apply_volume( this );
347 }
348 else if ( addr == stereo_reg )
349 {
350 // Stereo panning
351 apply_stereo( this );
352 }
353 else if ( addr == status_reg && (data ^ old_data) & power_mask )
354 {
355 // Power control
356 this->frame_phase = 0;
357 int i;
358 for ( i = osc_count; --i >= 0; )
359 silence_osc( this, this->oscs [i] );
360
361 reset_regs( this );
362 if ( this->wave.osc.mode != mode_dmg )
363 reset_lengths( this );
364
365 this->regs [status_reg - io_addr] = data;
366 }
367 }
368}
369
370int Apu_read_register( struct Gb_Apu* this, blip_time_t time, int addr )
371{
372 if ( addr >= status_reg )
373 run_until( this, time );
374
375 int reg = addr - io_addr;
376 if ( (unsigned) reg >= io_size )
377 {
378 require( false );
379 return 0;
380 }
381
382 if ( addr >= wave_ram )
383 return Wave_read( &this->wave, addr );
384
385 // Value read back has some bits always set
386 static byte const masks [] = {
387 0x80,0x3F,0x00,0xFF,0xBF,
388 0xFF,0x3F,0x00,0xFF,0xBF,
389 0x7F,0xFF,0x9F,0xFF,0xBF,
390 0xFF,0xFF,0x00,0x00,0xBF,
391 0x00,0x00,0x70,
392 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
393 };
394 int mask = masks [reg];
395 if ( this->wave.agb_mask && (reg == 10 || reg == 12) )
396 mask = 0x1F; // extra implemented bits in wave regs on AGB
397 int data = this->regs [reg] | mask;
398
399 // Status register
400 if ( addr == status_reg )
401 {
402 data &= 0xF0;
403 data |= (int) this->square1.osc.enabled << 0;
404 data |= (int) this->square2.osc.enabled << 1;
405 data |= (int) this->wave .osc.enabled << 2;
406 data |= (int) this->noise .osc.enabled << 3;
407 }
408
409 return data;
410}
diff --git a/lib/rbcodec/codecs/libgme/gb_apu.h b/lib/rbcodec/codecs/libgme/gb_apu.h
new file mode 100644
index 0000000000..69307b9840
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_apu.h
@@ -0,0 +1,85 @@
1// Nintendo Game Boy sound hardware emulator with save state support
2
3// Gb_Snd_Emu 0.1.4
4#ifndef GB_APU_H
5#define GB_APU_H
6
7#include "gb_oscs.h"
8
9// Clock rate sound hardware runs at
10enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
11
12// Registers are at io_addr to io_addr+io_size-1
13enum { io_addr = 0xFF10 };
14enum { io_size = 0x30 };
15enum { regs_size = io_size + 0x10 };
16
17enum gb_mode_t {
18 mode_dmg, // Game Boy monochrome
19 mode_cgb, // Game Boy Color
20 mode_agb // Game Boy Advance
21};
22
23// 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
24enum { osc_count = 4 }; // 0 <= chan < osc_count
25
26struct Gb_Apu {
27 struct Gb_Osc* oscs [osc_count];
28 blip_time_t last_time; // time sound emulator has been run to
29 blip_time_t frame_period; // clocks between each frame sequencer step
30 int volume_;
31 bool reduce_clicks_;
32
33 struct Gb_Square square1;
34 struct Gb_Square square2;
35 struct Gb_Wave wave;
36 struct Gb_Noise noise;
37 blip_time_t frame_time; // time of next frame sequencer action
38 int frame_phase; // phase of next frame sequencer step
39
40 uint8_t regs [regs_size];// last values written to registers
41
42 // large objects after everything else
43 struct Blip_Synth synth;
44};
45
46// Basics
47
48// Initializes apu
49void Apu_init( struct Gb_Apu* this );
50
51// Emulates to time t, then writes data to addr
52void Apu_write_register( struct Gb_Apu* this, blip_time_t t, int addr, int data );
53
54// Emulates to time t, then subtracts t from the current time.
55// OK if previous write call had time slightly after t.
56void Apu_end_frame( struct Gb_Apu* this,blip_time_t t );
57
58// More features
59
60// Emulates to time t, then reads from addr
61int Apu_read_register( struct Gb_Apu* this, blip_time_t t, int addr );
62
63// Resets hardware to state after power, BEFORE boot ROM runs. Mode selects
64// sound hardware. If agb_wave is true, enables AGB's extra wave features.
65void Apu_reset( struct Gb_Apu* this, enum gb_mode_t mode, bool agb_wave );
66
67// Same as set_output(), but for a particular channel
68void Apu_set_output( struct Gb_Apu* this, int chan, struct Blip_Buffer* center,
69 struct Blip_Buffer* left, struct Blip_Buffer* right );
70
71// Sets overall volume, where 1.0 is normal
72void Apu_volume( struct Gb_Apu* this, int v );
73
74// If true, reduces clicking by disabling DAC biasing. Note that this reduces
75// emulation accuracy, since the clicks are authentic.
76void Apu_reduce_clicks( struct Gb_Apu* this, bool reduce );
77
78// Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the
79// tempo in a music player.
80void Apu_set_tempo( struct Gb_Apu* this, int t );
81
82
83void write_osc( struct Gb_Apu* this, int reg, int old_data, int data );
84
85#endif
diff --git a/lib/rbcodec/codecs/libgme/gb_cpu.c b/lib/rbcodec/codecs/libgme/gb_cpu.c
new file mode 100644
index 0000000000..4b2df63a17
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_cpu.c
@@ -0,0 +1,53 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "gb_cpu.h"
4
5#include "blargg_endian.h"
6
7/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20static inline void set_code_page( struct Gb_Cpu* this, int i, void* p )
21{
22 byte* p2 = STATIC_CAST(byte*,p) - GB_CPU_OFFSET( i * page_size );
23 this->cpu_state_.code_map [i] = p2;
24 this->cpu_state->code_map [i] = p2;
25}
26
27void Cpu_reset( struct Gb_Cpu* this, void* unmapped )
28{
29 check( this->cpu_state == &this->cpu_state_ );
30 this->cpu_state = &this->cpu_state_;
31
32 this->cpu_state_.time = 0;
33
34 int i;
35 for ( i = 0; i < page_count + 1; ++i )
36 set_code_page( this, i, unmapped );
37
38 memset( &this->r, 0, sizeof this->r );
39
40 blargg_verify_byte_order();
41}
42
43void Cpu_map_code( struct Gb_Cpu* this, addr_t start, int size, void* data )
44{
45 // address range must begin and end on page boundaries
46 require( start % page_size == 0 );
47 require( size % page_size == 0 );
48 require( start + size <= mem_size );
49
50 int offset;
51 for ( offset = 0; offset < size; offset += page_size )
52 set_code_page( this, (start + offset) >> page_bits, STATIC_CAST(char*,data) + offset );
53}
diff --git a/lib/rbcodec/codecs/libgme/gb_cpu.h b/lib/rbcodec/codecs/libgme/gb_cpu.h
new file mode 100644
index 0000000000..37b22141d7
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_cpu.h
@@ -0,0 +1,80 @@
1// Nintendo Game Boy CPU emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef GB_CPU_H
5#define GB_CPU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9
10typedef int addr_t;
11
12// Emulator reads this many bytes past end of a page
13enum { cpu_padding = 8 };
14enum { mem_size = 0x10000 };
15enum { page_bits = 13 };
16enum { page_size = 1 << page_bits };
17enum { page_count = mem_size >> page_bits };
18
19// Game Boy Z-80 registers. NOT kept updated during emulation.
20struct core_regs_t {
21 uint16_t bc, de, hl, fa;
22};
23
24struct registers_t {
25 int pc; // more than 16 bits to allow overflow detection
26 uint16_t sp;
27
28 struct core_regs_t rp;
29};
30
31struct cpu_state_t {
32 byte* code_map [page_count + 1];
33 int time;
34};
35
36struct Gb_Cpu {
37 // Base address for RST vectors, to simplify GBS player (normally 0)
38 addr_t rst_base;
39
40 struct registers_t r;
41 struct cpu_state_t* cpu_state; // points to state_ or a local copy within run()
42 struct cpu_state_t cpu_state_;
43};
44
45// Initializes Gb cpu
46static inline void Cpu_init( struct Gb_Cpu* this )
47{
48 this->rst_base = 0;
49 this->cpu_state = &this->cpu_state_;
50}
51
52// Clears registers and map all pages to unmapped
53void Cpu_reset( struct Gb_Cpu* this, void* unmapped );
54
55// Maps code memory (memory accessed via the program counter). Start and size
56// must be multiple of page_size.
57void Cpu_map_code( struct Gb_Cpu* this, addr_t start, int size, void* code );
58
59// Current time.
60static inline int Cpu_time( struct Gb_Cpu* this ) { return this->cpu_state->time; }
61
62// Changes time. Must not be called during emulation.
63// Should be negative, because emulation stops once it becomes >= 0.
64static inline void Cpu_set_time( struct Gb_Cpu* this, int t ) { this->cpu_state->time = t; }
65
66#define GB_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
67
68#ifdef BLARGG_NONPORTABLE
69 #define GB_CPU_OFFSET( addr ) (addr)
70#else
71 #define GB_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
72#endif
73
74// Accesses emulated memory as CPU does
75static inline uint8_t* Cpu_get_code( struct Gb_Cpu* this, addr_t addr )
76{
77 return this->cpu_state_.code_map [GB_CPU_PAGE( addr )] + GB_CPU_OFFSET( addr );
78}
79
80#endif
diff --git a/lib/rbcodec/codecs/libgme/gb_cpu_run.h b/lib/rbcodec/codecs/libgme/gb_cpu_run.h
new file mode 100644
index 0000000000..1ea8b59249
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_cpu_run.h
@@ -0,0 +1,1187 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#if 0
4/* Define these macros in the source file before #including this file.
5- Parameters might be expressions, so they are best evaluated only once,
6though they NEVER have side-effects, so multiple evaluation is OK.
7- Output parameters might be a multiple-assignment expression like "a=x",
8so they must NOT be parenthesized.
9- Macros "returning" void may use a {} statement block. */
10
11 // 0 <= addr <= 0xFFFF + page_size
12 // time functions can be used
13 int READ_MEM( addr_t );
14 void WRITE_MEM( addr_t, int data );
15
16 // Access of 0xFF00 + offset
17 // 0 <= offset <= 0xFF
18 int READ_IO( int offset );
19 void WRITE_IO( int offset, int data );
20
21 // Often-used instructions use this instead of READ_MEM
22 void READ_FAST( addr_t, int& out );
23
24// The following can be used within macros:
25
26 // Current time
27 cpu_time_t TIME();
28#endif
29
30/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
31can redistribute it and/or modify it under the terms of the GNU Lesser
32General Public License as published by the Free Software Foundation; either
33version 2.1 of the License, or (at your option) any later version. This
34module is distributed in the hope that it will be useful, but WITHOUT ANY
35WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
36FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
37details. You should have received a copy of the GNU Lesser General Public
38License along with this module; if not, write to the Free Software Foundation,
39Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
40
41// Common instructions:
42//
43// 365880 FA LD A,(nn)
44// 355863 20 JR NZ
45// 313655 21 LD HL,nn
46// 274580 28 JR Z
47// 252878 FE CP n
48// 230541 7E LD A,(HL)
49// 226209 2A LD A,(HL+)
50// 217467 CD CALL
51// 212034 C9 RET
52// 208376 CB CB prefix
53//
54// 27486 CB 7E BIT 7,(HL)
55// 15925 CB 76 BIT 6,(HL)
56// 13035 CB 19 RR C
57// 11557 CB 7F BIT 7,A
58// 10898 CB 37 SWAP A
59// 10208 CB 66 BIT 4,(HL)
60
61// Allows MWCW debugger to step through code properly
62#ifdef CPU_BEGIN
63 CPU_BEGIN
64#endif
65
66#define TIME() s.time
67
68#define CODE_PAGE( addr ) s.code_map [GB_CPU_PAGE( addr )]
69#define READ_CODE( addr ) (CODE_PAGE( addr ) [GB_CPU_OFFSET( addr )])
70
71// Flags with hex value for clarity when used as mask.
72// Stored in indicated variable during emulation.
73int const z80 = 0x80; // cz
74int const n40 = 0x40; // ph
75int const h20 = 0x20; // ph
76int const c10 = 0x10; // cz
77
78#define SET_FLAGS( in )\
79{\
80 cz = ((in) << 4 & 0x100) + (~(in) >> 7 & 1);\
81 ph = (~(in) << 2 & 0x100) + ((in) >> 1 & 0x10);\
82}
83
84// random bits in cz to catch misuse of them
85#define SET_FLAGS_DEBUG( in )\
86{\
87 cz = ((in) << 4 & 0x100) | (rand() & ~0x1FF) | ((in) & 0x80 ? 0 : (rand() & 0xFF) | 1);\
88 ph = (~(in) << 2 & 0x100) | (((in) >> 1 & 0x10) ^ BYTE( cz ));\
89}
90
91#define GET_FLAGS( out )\
92{\
93 out = (cz >> 4 & c10);\
94 out += ~ph >> 2 & n40;\
95 out += (ph ^ cz) << 1 & h20;\
96 if ( !BYTE( cz ) )\
97 out += z80;\
98}
99
100#define CC_NZ() ( BYTE( cz ))
101#define CC_Z() (!BYTE( cz ))
102#define CC_NC() (!(cz & 0x100))
103#define CC_C() ( cz & 0x100 )
104
105// Truncation
106#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
107#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
108#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
109
110{
111 struct cpu_state_t s;
112 cpu->cpu_state = &s;
113 memcpy( &s, &cpu->cpu_state_, sizeof s );
114
115 union {
116 struct {
117 #ifdef BLARGG_BIG_ENDIAN
118 byte b, c, d, e, h, l, flags, a;
119 #else
120 byte c, b, e, d, l, h, a, flags;
121 #endif
122 } rg; // individual registers
123 struct core_regs_t rp; // pairs
124
125 byte r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
126 uint16_t r16 [4]; // indexed pairs
127 } reg;
128 BOOST_STATIC_ASSERT( sizeof reg.rg == 8 && sizeof reg.rp == 8 );
129
130 #ifdef BLARGG_BIG_ENDIAN
131 #define R8( n ) (reg.r8_ [n])
132 #elif BLARGG_LITTLE_ENDIAN
133 #define R8( n ) (reg.r8_ [(n) ^ 1])
134 #else
135 // Be sure "blargg_endian.h" has been #included in the file that #includes this
136 #error "Byte order of CPU must be known"
137 #endif
138
139 #define R16( n ) (reg.r16 [n])
140 #define RG (reg.rg)
141 #define RP (reg.rp)
142
143 RP = cpu->r.rp;
144 int pc = cpu->r.pc;
145 int sp = cpu->r.sp;
146 int ph;
147 int cz;
148 SET_FLAGS( RG.flags );
149
150 int time = s.time;
151
152loop:
153
154 check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around
155 check( (unsigned) sp < 0x10000 );
156
157 byte const* instr = CODE_PAGE( pc );
158 int op;
159
160 if ( GB_CPU_OFFSET(~0) == ~0 )
161 {
162 op = instr [pc];
163 pc++;
164 instr += pc;
165 }
166 else
167 {
168 instr += GB_CPU_OFFSET( pc );
169 op = *instr++;
170 pc++;
171 }
172
173#define GET_ADDR() GET_LE16( instr )
174
175 static byte const instr_times [256*2] = {
176 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
177 4,12, 8, 8, 4, 4, 8, 4,20, 8, 8, 8, 4, 4, 8, 4,// 0
178 4,12, 8, 8, 4, 4, 8, 4,12, 8, 8, 8, 4, 4, 8, 4,// 1
179 8,12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4,// 2
180 8,12, 8, 8,12,12,12, 4, 8, 8, 8, 8, 4, 4, 8, 4,// 3
181 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// 4
182 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// 5
183 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// 6
184 8, 8, 8, 8, 8, 8, 0, 8, 4, 4, 4, 4, 4, 4, 8, 4,// 7
185 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// 8
186 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// 9
187 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// A
188 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,// B
189 8,12,16,16,12,16, 8,16, 8,16,16, 0,12,24, 8,16,// C
190 8,12,16, 0,12,16, 8,16, 8,16,16, 0,12, 0, 8,16,// D
191 12,12, 8, 0, 0,16, 8,16,16, 4,16, 0, 0, 0, 8,16,// E
192 12,12, 8, 4, 0,16, 8,16,12, 8,16, 4, 0, 0, 8,16,// F
193
194 // CB prefixed
195 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
196 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 0
197 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 1
198 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 2
199 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 3
200 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,// 4
201 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,// 5
202 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,// 6
203 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,// 7
204 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 8
205 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// 9
206 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// A
207 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// B
208 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// C
209 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// D
210 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// E
211 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,// F
212 };
213
214 if ( time >= 0 )
215 goto stop;
216
217 time += instr_times [op];
218
219 int data;
220 data = *instr;
221 s.time = time;
222
223 #ifdef CPU_INSTR_HOOK
224 { CPU_INSTR_HOOK( (pc-1), (instr-1), rg.a, rp.bc, rp.de, rp.hl, sp ); }
225 #endif
226
227 switch ( op )
228 {
229
230// TODO: more efficient way to handle negative branch that wraps PC around
231#define BRANCH_( cond, clocks )\
232{\
233 pc++;\
234 if ( !(cond) )\
235 goto loop;\
236 pc = WORD( pc + SBYTE( data ) );\
237 time += clocks;\
238 goto loop;\
239}
240
241#define BRANCH( cond ) BRANCH_( cond, 4 )
242
243// Most Common
244
245 case 0x20: // JR NZ
246 BRANCH( CC_NZ() )
247
248 case 0x21: // LD HL,IMM (common)
249 RP.hl = GET_ADDR();
250 pc += 2;
251 goto loop;
252
253 case 0x28: // JR Z
254 BRANCH( CC_Z() )
255
256 case 0xF2: // LD A,(0xFF00+C)
257 READ_IO( this, RG.c, RG.a );
258 goto loop;
259
260 case 0xF0: // LD A,(0xFF00+imm)
261 pc++;
262 READ_IO( this, data, RG.a );
263 goto loop;
264
265 {
266 int temp;
267 case 0x0A: // LD A,(BC)
268 temp = RP.bc;
269 goto ld_a_ind_comm;
270
271 case 0x3A: // LD A,(HL-)
272 temp = RP.hl;
273 RP.hl = temp - 1;
274 goto ld_a_ind_comm;
275
276 case 0x1A: // LD A,(DE)
277 temp = RP.de;
278 goto ld_a_ind_comm;
279
280 case 0x2A: // LD A,(HL+) (common)
281 temp = RP.hl;
282 RP.hl = temp + 1;
283 goto ld_a_ind_comm;
284
285 case 0xFA: // LD A,IND16 (common)
286 temp = GET_ADDR();
287 pc += 2;
288 ld_a_ind_comm:
289 READ_FAST( this, temp, RG.a );
290 goto loop;
291 }
292
293 {
294 int temp;
295 case 0xBE: // CP (HL)
296 temp = READ_MEM( this, RP.hl );
297 goto cmp_comm;
298
299 case 0xB8: // CP B
300 case 0xB9: // CP C
301 case 0xBA: // CP D
302 case 0xBB: // CP E
303 case 0xBC: // CP H
304 case 0xBD: // CP L
305 case 0xBF: // CP A
306 temp = R8( op & 7 );
307 cmp_comm:
308 ph = RG.a ^ temp; // N=1 H=*
309 cz = RG.a - temp; // C=* Z=*
310 goto loop;
311 }
312
313 case 0xFE: // CP IMM
314 pc++;
315 ph = RG.a ^ data; // N=1 H=*
316 cz = RG.a - data; // C=* Z=*
317 goto loop;
318
319 case 0x46: // LD B,(HL)
320 case 0x4E: // LD C,(HL)
321 case 0x56: // LD D,(HL)
322 case 0x5E: // LD E,(HL)
323 case 0x66: // LD H,(HL)
324 case 0x6E: // LD L,(HL)
325 case 0x7E:{// LD A,(HL)
326 int addr = RP.hl;
327 READ_FAST( this, addr, R8( op >> 3 & 7 ) );
328 goto loop;
329 }
330
331 case 0xC4: // CNZ (next-most-common)
332 pc += 2;
333 if ( CC_Z() )
334 goto loop;
335 call:
336 time += 12;
337 pc -= 2;
338 case 0xCD: // CALL (most-common)
339 data = pc + 2;
340 pc = GET_ADDR();
341 push: {
342 int addr = WORD( sp - 1 );
343 WRITE_MEM( this, addr, (data >> 8) );
344 sp = WORD( sp - 2 );
345 WRITE_MEM( this, sp, data );
346 goto loop;
347 }
348
349 case 0xC8: // RET Z (next-most-common)
350 if ( CC_NZ() )
351 goto loop;
352 ret:
353 time += 12;
354 case 0xD9: // RETI
355 case 0xC9:{// RET (most common)
356 pc = READ_MEM( this, sp );
357 int addr = sp + 1;
358 sp = WORD( sp + 2 );
359 pc += 0x100 * READ_MEM( this, addr );
360 goto loop;
361 }
362
363 case 0x00: // NOP
364 case 0x40: // LD B,B
365 case 0x49: // LD C,C
366 case 0x52: // LD D,D
367 case 0x5B: // LD E,E
368 case 0x64: // LD H,H
369 case 0x6D: // LD L,L
370 case 0x7F: // LD A,A
371 goto loop;
372
373// CB Instructions
374
375 case 0xCB:
376 time += (instr_times + 256) [data];
377 pc++;
378 // now data is the opcode
379 switch ( data ) {
380
381 case 0x46: // BIT b,(HL)
382 case 0x4E:
383 case 0x56:
384 case 0x5E:
385 case 0x66:
386 case 0x6E:
387 case 0x76:
388 case 0x7E: {
389 int addr = RP.hl;
390 READ_FAST( this, addr, op );
391 goto bit_comm;
392 }
393
394 case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
395 case 0x44: case 0x45: case 0x47: case 0x48:
396 case 0x49: case 0x4A: case 0x4B: case 0x4C:
397 case 0x4D: case 0x4F: case 0x50: case 0x51:
398 case 0x52: case 0x53: case 0x54: case 0x55:
399 case 0x57: case 0x58: case 0x59: case 0x5A:
400 case 0x5B: case 0x5C: case 0x5D: case 0x5F:
401 case 0x60: case 0x61: case 0x62: case 0x63:
402 case 0x64: case 0x65: case 0x67: case 0x68:
403 case 0x69: case 0x6A: case 0x6B: case 0x6C:
404 case 0x6D: case 0x6F: case 0x70: case 0x71:
405 case 0x72: case 0x73: case 0x74: case 0x75:
406 case 0x77: case 0x78: case 0x79: case 0x7A:
407 case 0x7B: case 0x7C: case 0x7D: case 0x7F:
408 op = R8( data & 7 );
409 bit_comm:
410 ph = op >> (data >> 3 & 7) & 1;
411 cz = (cz & 0x100) + ph;
412 ph ^= 0x110; // N=0 H=1
413 goto loop;
414
415 case 0x86: // RES b,(HL)
416 case 0x8E:
417 case 0x96:
418 case 0x9E:
419 case 0xA6:
420 case 0xAE:
421 case 0xB6:
422 case 0xBE: {
423 int temp = READ_MEM( this, RP.hl );
424 temp &= ~(1 << (data >> 3 & 7));
425 WRITE_MEM( this, RP.hl, temp );
426 goto loop;
427 }
428
429 case 0xC6: // SET b,(HL)
430 case 0xCE:
431 case 0xD6:
432 case 0xDE:
433 case 0xE6:
434 case 0xEE:
435 case 0xF6:
436 case 0xFE: {
437 int temp = READ_MEM( this, RP.hl );
438 temp |= 1 << (data >> 3 & 7);
439 WRITE_MEM( this, RP.hl, temp );
440 goto loop;
441 }
442
443 case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
444 case 0xC4: case 0xC5: case 0xC7: case 0xC8:
445 case 0xC9: case 0xCA: case 0xCB: case 0xCC:
446 case 0xCD: case 0xCF: case 0xD0: case 0xD1:
447 case 0xD2: case 0xD3: case 0xD4: case 0xD5:
448 case 0xD7: case 0xD8: case 0xD9: case 0xDA:
449 case 0xDB: case 0xDC: case 0xDD: case 0xDF:
450 case 0xE0: case 0xE1: case 0xE2: case 0xE3:
451 case 0xE4: case 0xE5: case 0xE7: case 0xE8:
452 case 0xE9: case 0xEA: case 0xEB: case 0xEC:
453 case 0xED: case 0xEF: case 0xF0: case 0xF1:
454 case 0xF2: case 0xF3: case 0xF4: case 0xF5:
455 case 0xF7: case 0xF8: case 0xF9: case 0xFA:
456 case 0xFB: case 0xFC: case 0xFD: case 0xFF:
457 R8( data & 7 ) |= 1 << (data >> 3 & 7);
458 goto loop;
459
460 case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
461 case 0x84: case 0x85: case 0x87: case 0x88:
462 case 0x89: case 0x8A: case 0x8B: case 0x8C:
463 case 0x8D: case 0x8F: case 0x90: case 0x91:
464 case 0x92: case 0x93: case 0x94: case 0x95:
465 case 0x97: case 0x98: case 0x99: case 0x9A:
466 case 0x9B: case 0x9C: case 0x9D: case 0x9F:
467 case 0xA0: case 0xA1: case 0xA2: case 0xA3:
468 case 0xA4: case 0xA5: case 0xA7: case 0xA8:
469 case 0xA9: case 0xAA: case 0xAB: case 0xAC:
470 case 0xAD: case 0xAF: case 0xB0: case 0xB1:
471 case 0xB2: case 0xB3: case 0xB4: case 0xB5:
472 case 0xB7: case 0xB8: case 0xB9: case 0xBA:
473 case 0xBB: case 0xBC: case 0xBD: case 0xBF:
474 R8( data & 7 ) &= ~(1 << (data >> 3 & 7));
475 goto loop;
476
477 case 0x36: // SWAP (HL)
478 op = READ_MEM( this, RP.hl );
479 goto swap_comm;
480
481 case 0x30: // SWAP B
482 case 0x31: // SWAP C
483 case 0x32: // SWAP D
484 case 0x33: // SWAP E
485 case 0x34: // SWAP H
486 case 0x35: // SWAP L
487 case 0x37: // SWAP A
488 op = R8( data & 7 );
489 swap_comm:
490 op = (op >> 4) + (op << 4);
491 cz = BYTE( op );
492 ph = cz + 0x100;
493 if ( data == 0x36 )
494 goto write_hl_op_ff;
495 R8( data & 7 ) = op;
496 goto loop;
497
498// Shift/Rotate
499
500 case 0x26: // SLA (HL)
501 cz = 0;
502 case 0x16: // RL (HL)
503 cz = (cz >> 8 & 1) + (READ_MEM( this, RP.hl ) << 1);
504 goto rl_hl_common;
505
506 case 0x06: // RLC (HL)
507 cz = READ_MEM( this, RP.hl );
508 cz = (cz << 1) + (cz >> 7 & 1);
509 rl_hl_common:
510 // Z=* C=*
511 ph = cz | 0x100; // N=0 H=0
512 WRITE_MEM( this, RP.hl, cz );
513 goto loop;
514
515 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA r
516 cz = 0;
517 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL r
518 cz = (cz >> 8 & 1) + (R8( data & 7 ) << 1);
519 goto rl_common;
520
521 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC r
522 cz = R8( data & 7 );
523 cz = (cz << 1) + (cz >> 7 & 1);
524 rl_common:
525 // Z=* C=*
526 ph = cz | 0x100; // N=0 H=0
527 R8( data & 7 ) = cz;
528 goto loop;
529
530 case 0x0E: // RRC (HL)
531 cz = READ_MEM( this, RP.hl );
532 cz += cz << 8 & 0x100;
533 goto rr_hl_common;
534
535 case 0x2E: // SRA (HL)
536 cz = READ_MEM( this, RP.hl );
537 cz += cz << 1 & 0x100;
538 goto rr_hl_common;
539
540 case 0x3E: // SRL (HL)
541 cz = 0;
542 case 0x1E: // RR (HL)
543 cz = (cz & 0x100) + READ_MEM( this, RP.hl );
544 rr_hl_common:
545 cz = (cz << 8) + (cz >> 1); // Z=* C=*
546 ph = cz | 0x100; // N=0 H=0
547 WRITE_MEM( this, RP.hl, cz );
548 goto loop;
549
550 case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC r
551 cz = R8( data & 7 );
552 cz += cz << 8 & 0x100;
553 goto rr_common;
554
555 case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA r
556 cz = R8( data & 7 );
557 cz += cz << 1 & 0x100;
558 goto rr_common;
559
560 case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL r
561 cz = 0;
562 case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR r
563 cz = (cz & 0x100) + R8( data & 7 );
564 rr_common:
565 cz = (cz << 8) + (cz >> 1); // Z=* C=*
566 ph = cz | 0x100; // N=0 H=0
567 R8( data & 7 ) = cz;
568 goto loop;
569
570 } // CB op
571 assert( false ); // unhandled CB op
572
573 case 0x07: // RLCA
574 cz = RG.a >> 7;
575 goto rlc_common;
576 case 0x17: // RLA
577 cz = cz >> 8 & 1;
578 rlc_common:
579 cz += RG.a << 1;
580 ph = cz | 0x100;
581 RG.a = BYTE( cz );
582 cz |= 1;
583 goto loop;
584
585 case 0x0F: // RRCA
586 ph = RG.a << 8;
587 goto rrc_common;
588 case 0x1F: // RRA
589 ph = cz;
590 rrc_common:
591 cz = (RG.a << 8) + 1; // Z=0 C=*
592 RG.a = ((ph & 0x100) + RG.a) >> 1;
593 ph = 0x100; // N=0 H=0
594 goto loop;
595
596// Load
597
598 case 0x70: // LD (HL),B
599 case 0x71: // LD (HL),C
600 case 0x72: // LD (HL),D
601 case 0x73: // LD (HL),E
602 case 0x74: // LD (HL),H
603 case 0x75: // LD (HL),L
604 case 0x77: // LD (HL),A
605 op = R8( op & 7 );
606 write_hl_op_ff:
607 WRITE_MEM( this, RP.hl, op );
608 goto loop;
609
610 case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
611 case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
612 case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
613 case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
614 case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
615 case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
616 case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
617 R8( op >> 3 & 7 ) = R8( op & 7 );
618 goto loop;
619
620 case 0x08: // LD IND16,SP
621 data = GET_ADDR();
622 pc += 2;
623 WRITE_MEM( this, data, sp );
624 data++;
625 WRITE_MEM( this, data, (sp >> 8) );
626 goto loop;
627
628 case 0xF9: // LD SP,HL
629 sp = RP.hl;
630 goto loop;
631
632 case 0x31: // LD SP,IMM
633 sp = GET_ADDR();
634 pc += 2;
635 goto loop;
636
637 case 0x01: // LD BC,IMM
638 case 0x11: // LD DE,IMM
639 R16( (unsigned) op >> 4 ) = GET_ADDR();
640 pc += 2;
641 goto loop;
642
643 case 0xE2: // LD (0xFF00+C),A
644 WRITE_IO( this, RG.c, RG.a );
645 goto loop;
646
647 case 0xE0: // LD (0xFF00+imm),A
648 pc++;
649 WRITE_IO( this, data, RG.a );
650 goto loop;
651
652 {
653 int temp;
654 case 0x32: // LD (HL-),A
655 temp = RP.hl;
656 RP.hl = temp - 1;
657 goto write_data_rg_a;
658
659 case 0x02: // LD (BC),A
660 temp = RP.bc;
661 goto write_data_rg_a;
662
663 case 0x12: // LD (DE),A
664 temp = RP.de;
665 goto write_data_rg_a;
666
667 case 0x22: // LD (HL+),A
668 temp = RP.hl;
669 RP.hl = temp + 1;
670 goto write_data_rg_a;
671
672 case 0xEA: // LD IND16,A (common)
673 temp = GET_ADDR();
674 pc += 2;
675 write_data_rg_a:
676 WRITE_MEM( this, temp, RG.a );
677 goto loop;
678 }
679
680 case 0x06: // LD B,IMM
681 RG.b = data;
682 pc++;
683 goto loop;
684
685 case 0x0E: // LD C,IMM
686 RG.c = data;
687 pc++;
688 goto loop;
689
690 case 0x16: // LD D,IMM
691 RG.d = data;
692 pc++;
693 goto loop;
694
695 case 0x1E: // LD E,IMM
696 RG.e = data;
697 pc++;
698 goto loop;
699
700 case 0x26: // LD H,IMM
701 RG.h = data;
702 pc++;
703 goto loop;
704
705 case 0x2E: // LD L,IMM
706 RG.l = data;
707 pc++;
708 goto loop;
709
710 case 0x36: // LD (HL),IMM
711 WRITE_MEM( this, RP.hl, data );
712 pc++;
713 goto loop;
714
715 case 0x3E: // LD A,IMM
716 RG.a = data;
717 pc++;
718 goto loop;
719
720// Increment/decrement
721
722 case 0x03: // INC BC
723 case 0x13: // INC DE
724 case 0x23: // INC HL
725 R16( (unsigned) op >> 4 )++;
726 goto loop;
727
728 case 0x33: // INC SP
729 sp = WORD( sp + 1 );
730 goto loop;
731
732 case 0x0B: // DEC BC
733 case 0x1B: // DEC DE
734 case 0x2B: // DEC HL
735 R16( (unsigned) op >> 4 )--;
736 goto loop;
737
738 case 0x3B: // DEC SP
739 sp = WORD( sp - 1 );
740 goto loop;
741
742 case 0x34: // INC (HL)
743 op = RP.hl;
744 data = READ_MEM( this, op );
745 data++;
746 WRITE_MEM( this, op, data );
747 goto inc_comm;
748
749 case 0x04: // INC B
750 case 0x0C: // INC C (common)
751 case 0x14: // INC D
752 case 0x1C: // INC E
753 case 0x24: // INC H
754 case 0x2C: // INC L
755 case 0x3C: // INC A
756 op = op >> 3 & 7;
757 data = R8( op ) + 1;
758 R8( op ) = data;
759 inc_comm:
760 ph = data - 0x101; // N=0 H=*
761 cz = (cz & 0x100) + BYTE( data ); // C=- Z=*
762 goto loop;
763
764 case 0x35: // DEC (HL)
765 op = RP.hl;
766 data = READ_MEM( this, op );
767 data--;
768 WRITE_MEM( this, op, data );
769 goto dec_comm;
770
771 case 0x05: // DEC B
772 case 0x0D: // DEC C
773 case 0x15: // DEC D
774 case 0x1D: // DEC E
775 case 0x25: // DEC H
776 case 0x2D: // DEC L
777 case 0x3D: // DEC A
778 op = op >> 3 & 7;
779 data = R8( op ) - 1;
780 R8( op ) = data;
781 dec_comm:
782 ph = data + 1; // N=1 H=*
783 cz = (cz & 0x100) + BYTE( data ); // C=- Z=*
784 goto loop;
785
786// Add 16-bit
787
788 case 0xF8: // LD HL,SP+n
789 case 0xE8:{// ADD SP,n
790 pc++;
791 int t = WORD( sp + SBYTE( data ) );
792 cz = ((BYTE( sp ) + data) & 0x100) + 1; // Z=0 C=*
793 ph = (sp ^ data ^ t) | 0x100; // N=0 H=*
794 if ( op == 0xF8 )
795 {
796 RP.hl = t;
797 goto loop;
798 }
799 sp = t;
800 goto loop;
801 }
802
803 case 0x39: // ADD HL,SP
804 data = sp;
805 goto add_hl_comm;
806
807 case 0x09: // ADD HL,BC
808 case 0x19: // ADD HL,DE
809 case 0x29: // ADD HL,HL
810 data = R16( (unsigned) op >> 4 );
811 add_hl_comm:
812 ph = RP.hl ^ data;
813 data += RP.hl;
814 RP.hl = WORD( data );
815 ph ^= data;
816 cz = BYTE( cz ) + (data >> 8 & 0x100); // C=* Z=-
817 ph = ((ph >> 8) ^ cz) | 0x100; // N=0 H=*
818 goto loop;
819
820 case 0x86: // ADD (HL)
821 data = READ_MEM( this, RP.hl );
822 goto add_comm;
823
824 case 0x80: // ADD B
825 case 0x81: // ADD C
826 case 0x82: // ADD D
827 case 0x83: // ADD E
828 case 0x84: // ADD H
829 case 0x85: // ADD L
830 case 0x87: // ADD A
831 data = R8( op & 7 );
832 goto add_comm;
833
834 case 0xC6: // ADD IMM
835 pc++;
836 add_comm:
837 ph = (RG.a ^ data) | 0x100; // N=1 H=*
838 cz = RG.a + data; // C=* Z=*
839 RG.a = cz;
840 goto loop;
841
842// Add/Subtract
843
844 case 0x8E: // ADC (HL)
845 data = READ_MEM( this, RP.hl );
846 goto adc_comm;
847
848 case 0x88: // ADC B
849 case 0x89: // ADC C
850 case 0x8A: // ADC D
851 case 0x8B: // ADC E
852 case 0x8C: // ADC H
853 case 0x8D: // ADC L
854 case 0x8F: // ADC A
855 data = R8( op & 7 );
856 goto adc_comm;
857
858 case 0xCE: // ADC IMM
859 pc++;
860 adc_comm:
861 ph = (RG.a ^ data) | 0x100; // N=1 H=*
862 cz = RG.a + data + (cz >> 8 & 1); // C=* Z=*
863 RG.a = cz;
864 goto loop;
865
866 case 0x96: // SUB (HL)
867 data = READ_MEM( this, RP.hl );
868 goto sub_comm;
869
870 case 0x90: // SUB B
871 case 0x91: // SUB C
872 case 0x92: // SUB D
873 case 0x93: // SUB E
874 case 0x94: // SUB H
875 case 0x95: // SUB L
876 case 0x97: // SUB A
877 data = R8( op & 7 );
878 goto sub_comm;
879
880 case 0xD6: // SUB IMM
881 pc++;
882 sub_comm:
883 ph = RG.a ^ data; // N=1 H=*
884 cz = RG.a - data; // C=* Z=*
885 RG.a = cz;
886 goto loop;
887
888 case 0x9E: // SBC (HL)
889 data = READ_MEM( this, RP.hl );
890 goto sbc_comm;
891
892 case 0x98: // SBC B
893 case 0x99: // SBC C
894 case 0x9A: // SBC D
895 case 0x9B: // SBC E
896 case 0x9C: // SBC H
897 case 0x9D: // SBC L
898 case 0x9F: // SBC A
899 data = R8( op & 7 );
900 goto sbc_comm;
901
902 case 0xDE: // SBC IMM
903 pc++;
904 sbc_comm:
905 ph = RG.a ^ data; // N=1 H=*
906 cz = RG.a - data - (cz >> 8 & 1); // C=* Z=*
907 RG.a = cz;
908 goto loop;
909
910// Logical
911
912 case 0xA0: // AND B
913 case 0xA1: // AND C
914 case 0xA2: // AND D
915 case 0xA3: // AND E
916 case 0xA4: // AND H
917 case 0xA5: // AND L
918 data = R8( op & 7 );
919 goto and_comm;
920
921 case 0xA6: // AND (HL)
922 data = READ_MEM( this, RP.hl );
923 goto and_comm;
924 case 0xE6: // AND IMM
925 pc++;
926 and_comm:
927 cz = RG.a & data; // C=0 Z=*
928 ph = ~cz; // N=0 H=1
929 RG.a = cz;
930 goto loop;
931
932 case 0xA7: // AND A
933 cz = RG.a; // C=0 Z=*
934 ph = ~RG.a; // N=0 H=1
935 goto loop;
936
937 case 0xB0: // OR B
938 case 0xB1: // OR C
939 case 0xB2: // OR D
940 case 0xB3: // OR E
941 case 0xB4: // OR H
942 case 0xB5: // OR L
943 data = R8( op & 7 );
944 goto or_comm;
945
946 case 0xB6: // OR (HL)
947 data = READ_MEM( this, RP.hl );
948 goto or_comm;
949 case 0xF6: // OR IMM
950 pc++;
951 or_comm:
952 cz = RG.a | data; // C=0 Z=*
953 ph = cz | 0x100; // N=0 H=0
954 RG.a = cz;
955 goto loop;
956
957 case 0xB7: // OR A
958 cz = RG.a; // C=0 Z=*
959 ph = RG.a + 0x100; // N=0 H=0
960 goto loop;
961
962 case 0xA8: // XOR B
963 case 0xA9: // XOR C
964 case 0xAA: // XOR D
965 case 0xAB: // XOR E
966 case 0xAC: // XOR H
967 case 0xAD: // XOR L
968 data = R8( op & 7 );
969 goto xor_comm;
970
971 case 0xAE: // XOR (HL)
972 data = READ_MEM( this, RP.hl );
973 pc--;
974 case 0xEE: // XOR IMM
975 pc++;
976 xor_comm:
977 cz = RG.a ^ data; // C=0 Z=*
978 ph = cz + 0x100; // N=0 H=0
979 RG.a = cz;
980 goto loop;
981
982 case 0xAF: // XOR A
983 RG.a = 0;
984 cz = 0; // C=0 Z=*
985 ph = 0x100; // N=0 H=0
986 goto loop;
987
988// Stack
989
990 case 0xF1: // POP AF
991 case 0xC1: // POP BC
992 case 0xD1: // POP DE
993 case 0xE1: // POP HL (common)
994 data = READ_MEM( this, sp );
995 R16( op >> 4 & 3 ) = data + 0x100 * READ_MEM( this, (sp + 1) );
996 sp = WORD( sp + 2 );
997 if ( op != 0xF1 )
998 goto loop;
999
1000 SET_FLAGS( RG.a );
1001 RG.a = RG.flags;
1002 goto loop;
1003
1004 case 0xC5: // PUSH BC
1005 data = RP.bc;
1006 goto push;
1007
1008 case 0xD5: // PUSH DE
1009 data = RP.de;
1010 goto push;
1011
1012 case 0xE5: // PUSH HL
1013 data = RP.hl;
1014 goto push;
1015
1016 case 0xF5: // PUSH AF
1017 GET_FLAGS( data );
1018 data += RG.a << 8;
1019 goto push;
1020
1021// Flow control
1022
1023 case 0xFF: case 0xC7: case 0xCF: case 0xD7: // RST
1024 case 0xDF: case 0xE7: case 0xEF: case 0xF7:
1025 data = pc;
1026 pc = (op & 0x38) + cpu->rst_base;
1027 goto push;
1028
1029 case 0xCC: // CALL Z
1030 pc += 2;
1031 if ( CC_Z() )
1032 goto call;
1033 goto loop;
1034
1035 case 0xD4: // CALL NC
1036 pc += 2;
1037 if ( CC_NC() )
1038 goto call;
1039 goto loop;
1040
1041 case 0xDC: // CALL C
1042 pc += 2;
1043 if ( CC_C() )
1044 goto call;
1045 goto loop;
1046
1047 case 0xC0: // RET NZ
1048 if ( CC_NZ() )
1049 goto ret;
1050 goto loop;
1051
1052 case 0xD0: // RET NC
1053 if ( CC_NC() )
1054 goto ret;
1055 goto loop;
1056
1057 case 0xD8: // RET C
1058 if ( CC_C() )
1059 goto ret;
1060 goto loop;
1061
1062 case 0x18: // JR
1063 BRANCH_( true, 0 )
1064
1065 case 0x30: // JR NC
1066 BRANCH( CC_NC() )
1067
1068 case 0x38: // JR C
1069 BRANCH( CC_C() )
1070
1071 case 0xE9: // LD PC,HL
1072 pc = RP.hl;
1073 goto loop;
1074
1075 case 0xC3: // JP (next-most-common)
1076 pc = GET_ADDR();
1077 goto loop;
1078
1079 case 0xC2: // JP NZ
1080 pc += 2;
1081 if ( CC_NZ() )
1082 goto jp_taken;
1083 time -= 4;
1084 goto loop;
1085
1086 case 0xCA: // JP Z (most common)
1087 pc += 2;
1088 if ( CC_Z() )
1089 goto jp_taken;
1090 time -= 4;
1091 goto loop;
1092
1093 jp_taken:
1094 pc -= 2;
1095 pc = GET_ADDR();
1096 goto loop;
1097
1098 case 0xD2: // JP NC
1099 pc += 2;
1100 if ( CC_NC() )
1101 goto jp_taken;
1102 time -= 4;
1103 goto loop;
1104
1105 case 0xDA: // JP C
1106 pc += 2;
1107 if ( CC_C() )
1108 goto jp_taken;
1109 time -= 4;
1110 goto loop;
1111
1112// Flags
1113
1114 case 0x2F: // CPL
1115 RG.a = ~RG.a;
1116 ph = BYTE( ~cz ); // N=1 H=1
1117 goto loop;
1118
1119 case 0x3F: // CCF
1120 ph = cz | 0x100; // N=0 H=0
1121 cz ^= 0x100; // C=* Z=-
1122 goto loop;
1123
1124 case 0x37: // SCF
1125 ph = cz | 0x100; // N=0 H=0
1126 cz |= 0x100; // C=1 Z=-
1127 goto loop;
1128
1129 case 0xF3: // DI
1130 goto loop;
1131
1132 case 0xFB: // EI
1133 goto loop;
1134
1135 case 0x27:{// DAA
1136 unsigned a = RG.a;
1137 int h = ph ^ cz;
1138 if ( ph & 0x100 )
1139 {
1140 if ( (h & 0x10) || (a & 0x0F) > 9 )
1141 a += 6;
1142
1143 if ( (cz & 0x100) || a > 0x9F )
1144 a += 0x60;
1145 }
1146 else
1147 {
1148 if ( h & 0x10 )
1149 a = (a - 6) & 0xFF;
1150
1151 if ( cz & 0x100 )
1152 a -= 0x60;
1153 }
1154 cz = (cz & 0x100) | a; // C=- Z=*
1155 RG.a = a;
1156 ph = (ph & 0x100) + BYTE( a ); // N=- H=0
1157 goto loop;
1158 }
1159
1160// Special
1161
1162 case 0x76: // HALT
1163 case 0x10: // STOP
1164 case 0xD3: case 0xDB: case 0xDD: // Illegal
1165 case 0xE3: case 0xE4: case 0xEB: case 0xEC: case 0xED: // (all freeze cpu)
1166 case 0xF4: case 0xFC: case 0xFD:
1167 goto stop;
1168 }
1169
1170 // If this fails then an opcode isn't handled above
1171 assert( false );
1172
1173stop:
1174 pc--;
1175
1176 // copy state back
1177 cpu->cpu_state_.time = time;
1178 cpu->r.pc = pc;
1179 cpu->r.sp = sp;
1180 {
1181 int t;
1182 GET_FLAGS( t );
1183 RG.flags = t;
1184 }
1185 cpu->cpu_state = &cpu->cpu_state_;
1186 cpu->r.rp = RP;
1187}
diff --git a/lib/rbcodec/codecs/libgme/gb_oscs.c b/lib/rbcodec/codecs/libgme/gb_oscs.c
new file mode 100644
index 0000000000..09bb98238e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_oscs.c
@@ -0,0 +1,787 @@
1// Gb_Snd_Emu 0.1.4. http://www.slack.net/~ant/
2
3#include "gb_apu.h"
4
5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const cgb_02 = 0; // enables bug in early CGB units that causes problems in some games
19int const cgb_05 = 0; // enables CGB-05 zombie behavior
20
21int const trigger_mask = 0x80;
22int const length_enabled = 0x40;
23
24void Osc_reset( struct Gb_Osc* this )
25{
26 this->output = NULL;
27 this->last_amp = 0;
28 this->delay = 0;
29 this->phase = 0;
30 this->enabled = false;
31}
32
33static inline void Osc_update_amp( struct Gb_Osc* this, blip_time_t time, int new_amp )
34{
35 Blip_set_modified( this->output );
36 int delta = new_amp - this->last_amp;
37 if ( delta )
38 {
39 this->last_amp = new_amp;
40 Synth_offset( this->synth, time, delta, this->output );
41 }
42}
43
44// Units
45
46void Osc_clock_length( struct Gb_Osc* this )
47{
48 if ( (this->regs [4] & length_enabled) && this->length_ctr )
49 {
50 if ( --this->length_ctr <= 0 )
51 this->enabled = false;
52 }
53}
54
55void Noise_clock_envelope( struct Gb_Noise* this )
56{
57 if ( this->env_enabled && --this->env_delay <= 0 && Noise_reload_env_timer( this ) )
58 {
59 int v = this->volume + (this->osc.regs [2] & 0x08 ? +1 : -1);
60 if ( 0 <= v && v <= 15 )
61 this->volume = v;
62 else
63 this->env_enabled = false;
64 }
65}
66
67void Square_clock_envelope( struct Gb_Square* this )
68{
69 if ( this->env_enabled && --this->env_delay <= 0 && Square_reload_env_timer( this ) )
70 {
71 int v = this->volume + (this->osc.regs [2] & 0x08 ? +1 : -1);
72 if ( 0 <= v && v <= 15 )
73 this->volume = v;
74 else
75 this->env_enabled = false;
76 }
77}
78
79static inline void reload_sweep_timer( struct Gb_Square* this )
80{
81 this->sweep_delay = (this->osc.regs [0] & period_mask) >> 4;
82 if ( !this->sweep_delay )
83 this->sweep_delay = 8;
84}
85
86static void calc_sweep( struct Gb_Square* this, bool update )
87{
88 struct Gb_Osc* osc = &this->osc;
89 int const shift = osc->regs [0] & shift_mask;
90 int const delta = this->sweep_freq >> shift;
91 this->sweep_neg = (osc->regs [0] & 0x08) != 0;
92 int const freq = this->sweep_freq + (this->sweep_neg ? -delta : delta);
93
94 if ( freq > 0x7FF )
95 {
96 osc->enabled = false;
97 }
98 else if ( shift && update )
99 {
100 this->sweep_freq = freq;
101
102 osc->regs [3] = freq & 0xFF;
103 osc->regs [4] = (osc->regs [4] & ~0x07) | (freq >> 8 & 0x07);
104 }
105}
106
107void clock_sweep( struct Gb_Square* this )
108{
109 if ( --this->sweep_delay <= 0 )
110 {
111 reload_sweep_timer( this );
112 if ( this->sweep_enabled && (this->osc.regs [0] & period_mask) )
113 {
114 calc_sweep( this, true );
115 calc_sweep( this, false );
116 }
117 }
118}
119
120int wave_access( struct Gb_Wave* this, int addr )
121{
122 if ( this->osc.enabled )
123 {
124 addr = this->osc.phase & (wave_bank_size - 1);
125 if ( this->osc.mode == mode_dmg )
126 {
127 addr++;
128 if ( this->osc.delay > clk_mul )
129 return -1; // can only access within narrow time window while playing
130 }
131 addr >>= 1;
132 }
133 return addr & 0x0F;
134}
135
136// write_register
137
138static int write_trig( struct Gb_Osc* this, int frame_phase, int max_len, int old_data )
139{
140 int data = this->regs [4];
141
142 if ( (frame_phase & 1) && !(old_data & length_enabled) && this->length_ctr )
143 {
144 if ( (data & length_enabled) || cgb_02 )
145 this->length_ctr--;
146 }
147
148 if ( data & trigger_mask )
149 {
150 this->enabled = true;
151 if ( !this->length_ctr )
152 {
153 this->length_ctr = max_len;
154 if ( (frame_phase & 1) && (data & length_enabled) )
155 this->length_ctr--;
156 }
157 }
158
159 if ( !this->length_ctr )
160 this->enabled = false;
161
162 return data & trigger_mask;
163}
164
165static inline void Noise_zombie_volume( struct Gb_Noise* this, int old, int data )
166{
167 int v = this->volume;
168 if ( this->osc.mode == mode_agb || cgb_05 )
169 {
170 // CGB-05 behavior, very close to AGB behavior as well
171 if ( (old ^ data) & 8 )
172 {
173 if ( !(old & 8) )
174 {
175 v++;
176 if ( old & 7 )
177 v++;
178 }
179
180 v = 16 - v;
181 }
182 else if ( (old & 0x0F) == 8 )
183 {
184 v++;
185 }
186 }
187 else
188 {
189 // CGB-04&02 behavior, very close to MGB behavior as well
190 if ( !(old & 7) && this->env_enabled )
191 v++;
192 else if ( !(old & 8) )
193 v += 2;
194
195 if ( (old ^ data) & 8 )
196 v = 16 - v;
197 }
198 this->volume = v & 0x0F;
199}
200
201static inline void Square_zombie_volume( struct Gb_Square* this, int old, int data )
202{
203 int v = this->volume;
204 if ( this->osc.mode == mode_agb || cgb_05 )
205 {
206 // CGB-05 behavior, very close to AGB behavior as well
207 if ( (old ^ data) & 8 )
208 {
209 if ( !(old & 8) )
210 {
211 v++;
212 if ( old & 7 )
213 v++;
214 }
215
216 v = 16 - v;
217 }
218 else if ( (old & 0x0F) == 8 )
219 {
220 v++;
221 }
222 }
223 else
224 {
225 // CGB-04&02 behavior, very close to MGB behavior as well
226 if ( !(old & 7) && this->env_enabled )
227 v++;
228 else if ( !(old & 8) )
229 v += 2;
230
231 if ( (old ^ data) & 8 )
232 v = 16 - v;
233 }
234 this->volume = v & 0x0F;
235}
236
237static bool Square_write_register( struct Gb_Square* this, int frame_phase, int reg, int old_data, int data )
238{
239 int const max_len = 64;
240
241 switch ( reg )
242 {
243 case 1:
244 this->osc.length_ctr = max_len - (data & (max_len - 1));
245 break;
246
247 case 2:
248 if ( !Square_dac_enabled( this ) )
249 this->osc.enabled = false;
250
251 Square_zombie_volume( this, old_data, data );
252
253 if ( (data & 7) && this->env_delay == 8 )
254 {
255 this->env_delay = 1;
256 Square_clock_envelope( this ); // TODO: really happens at next length clock
257 }
258 break;
259
260 case 4:
261 if ( write_trig( &this->osc, frame_phase, max_len, old_data ) )
262 {
263 this->volume = this->osc.regs [2] >> 4;
264 Square_reload_env_timer( this );
265 this->env_enabled = true;
266 if ( frame_phase == 7 )
267 this->env_delay++;
268 if ( !Square_dac_enabled( this ) )
269 this->osc.enabled = false;
270 this->osc.delay = (this->osc.delay & (4 * clk_mul - 1)) + Square_period( this );
271 return true;
272 }
273 }
274
275 return false;
276}
277
278static inline void Noise_write_register( struct Gb_Noise* this, int frame_phase, int reg, int old_data, int data )
279{
280 int const max_len = 64;
281
282 switch ( reg )
283 {
284 case 1:
285 this->osc.length_ctr = max_len - (data & (max_len - 1));
286 break;
287
288 case 2:
289 if ( !Noise_dac_enabled( this ) )
290 this->osc.enabled = false;
291
292 Noise_zombie_volume( this, old_data, data );
293
294 if ( (data & 7) && this->env_delay == 8 )
295 {
296 this->env_delay = 1;
297 Noise_clock_envelope( this ); // TODO: really happens at next length clock
298 }
299 break;
300
301 case 4:
302 if ( write_trig( &this->osc, frame_phase, max_len, old_data ) )
303 {
304 this->volume = this->osc.regs [2] >> 4;
305 Noise_reload_env_timer( this );
306 this->env_enabled = true;
307 if ( frame_phase == 7 )
308 this->env_delay++;
309 if ( !Noise_dac_enabled( this ) )
310 this->osc.enabled = false;
311
312 this->osc.phase = 0x7FFF;
313 this->osc.delay += 8 * clk_mul;
314 }
315 }
316}
317
318static inline void Sweep_write_register( struct Gb_Square* this, int frame_phase, int reg, int old_data, int data )
319{
320 if ( reg == 0 && this->sweep_enabled && this->sweep_neg && !(data & 0x08) )
321 this->osc.enabled = false; // sweep negate disabled after used
322
323 if ( Square_write_register( this, frame_phase, reg, old_data, data ) )
324 {
325 this->sweep_freq = Osc_frequency( &this->osc );
326 this->sweep_neg = false;
327 reload_sweep_timer( this );
328 this->sweep_enabled = (this->osc.regs [0] & (period_mask | shift_mask)) != 0;
329 if ( this->osc.regs [0] & shift_mask )
330 calc_sweep( this, false );
331 }
332}
333
334static void corrupt_wave( struct Gb_Wave* this )
335{
336 int pos = ((this->osc.phase + 1) & (wave_bank_size - 1)) >> 1;
337 if ( pos < 4 )
338 this->wave_ram [0] = this->wave_ram [pos];
339 else {
340 int i;
341 for ( i = 4; --i >= 0; )
342 this->wave_ram [i] = this->wave_ram [(pos & ~3) + i];
343 }
344}
345
346static inline void Wave_write_register( struct Gb_Wave* this, int frame_phase, int reg, int old_data, int data )
347{
348 int const max_len = 256;
349
350 switch ( reg )
351 {
352 case 0:
353 if ( !Wave_dac_enabled( this ) )
354 this->osc.enabled = false;
355 break;
356
357 case 1:
358 this->osc.length_ctr = max_len - data;
359 break;
360
361 case 4:
362 {
363 bool was_enabled = this->osc.enabled;
364 if ( write_trig( &this->osc, frame_phase, max_len, old_data ) )
365 {
366 if ( !Wave_dac_enabled( this ) )
367 this->osc.enabled = false;
368 else if ( this->osc.mode == mode_dmg && was_enabled &&
369 (unsigned) (this->osc.delay - 2 * clk_mul) < 2 * clk_mul )
370 corrupt_wave( this );
371
372 this->osc.phase = 0;
373 this->osc.delay = Wave_period( this ) + 6 * clk_mul;
374 }
375 }
376 }
377}
378
379void write_osc( struct Gb_Apu* this, int reg, int old_data, int data )
380{
381 int index = (reg * 3 + 3) >> 4; // avoids divide
382 assert( index == reg / 5 );
383 reg -= index * 5;
384 switch ( index )
385 {
386 case 0: Sweep_write_register ( &this->square1, this->frame_phase, reg, old_data, data ); break;
387 case 1: Square_write_register( &this->square2, this->frame_phase, reg, old_data, data ); break;
388 case 2: Wave_write_register ( &this->wave, this->frame_phase, reg, old_data, data ); break;
389 case 3: Noise_write_register ( &this->noise, this->frame_phase, reg, old_data, data ); break;
390 }
391}
392
393// Synthesis
394
395void Square_run( struct Gb_Square* this, blip_time_t time, blip_time_t end_time )
396{
397 // Calc duty and phase
398 static byte const duty_offsets [4] = { 1, 1, 3, 7 };
399 static byte const duties [4] = { 1, 2, 4, 6 };
400
401 struct Gb_Osc* osc = &this->osc;
402 int const duty_code = osc->regs [1] >> 6;
403 int duty_offset = duty_offsets [duty_code];
404 int duty = duties [duty_code];
405 if ( osc->mode == mode_agb )
406 {
407 // AGB uses inverted duty
408 duty_offset -= duty;
409 duty = 8 - duty;
410 }
411 int ph = (osc->phase + duty_offset) & 7;
412
413 // Determine what will be generated
414 int vol = 0;
415 struct Blip_Buffer* const out = osc->output;
416 if ( out )
417 {
418 int amp = osc->dac_off_amp;
419 if ( Square_dac_enabled( this ) )
420 {
421 if ( osc->enabled )
422 vol = this->volume;
423
424 amp = -dac_bias;
425 if ( osc->mode == mode_agb )
426 amp = -(vol >> 1);
427
428 // Play inaudible frequencies as constant amplitude
429 if ( Osc_frequency( osc ) >= 0x7FA && osc->delay < 32 * clk_mul )
430 {
431 amp += (vol * duty) >> 3;
432 vol = 0;
433 }
434
435 if ( ph < duty )
436 {
437 amp += vol;
438 vol = -vol;
439 }
440 }
441 Osc_update_amp( osc, time, amp );
442 }
443
444 // Generate wave
445 time += osc->delay;
446 if ( time < end_time )
447 {
448 int const per = Square_period( this );
449 if ( !vol )
450 {
451 #ifdef GB_APU_FAST
452 time = end_time;
453 #else
454 // Maintain phase when not playing
455 int count = (end_time - time + per - 1) / per;
456 ph += count; // will be masked below
457 time += (blip_time_t) count * per;
458 #endif
459 }
460 else
461 {
462 // Output amplitude transitions
463 int delta = vol;
464 do
465 {
466 ph = (ph + 1) & 7;
467 if ( ph == 0 || ph == duty )
468 {
469 Synth_offset_inline( osc->synth, time, delta, out );
470 delta = -delta;
471 }
472 time += per;
473 }
474 while ( time < end_time );
475
476 if ( delta != vol )
477 osc->last_amp -= delta;
478 }
479 osc->phase = (ph - duty_offset) & 7;
480 }
481 osc->delay = time - end_time;
482}
483
484#ifndef GB_APU_FAST
485// Quickly runs LFSR for a large number of clocks. For use when noise is generating
486// no sound.
487static unsigned run_lfsr( unsigned s, unsigned mask, int count )
488{
489 bool const optimized = true; // set to false to use only unoptimized loop in middle
490
491 // optimization used in several places:
492 // ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)
493
494 if ( mask == 0x4000 && optimized )
495 {
496 if ( count >= 32767 )
497 count %= 32767;
498
499 // Convert from Fibonacci to Galois configuration,
500 // shifted left 1 bit
501 s ^= (s & 1) * 0x8000;
502
503 // Each iteration is equivalent to clocking LFSR 255 times
504 while ( (count -= 255) > 0 )
505 s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
506 count += 255;
507
508 // Each iteration is equivalent to clocking LFSR 15 times
509 // (interesting similarity to single clocking below)
510 while ( (count -= 15) > 0 )
511 s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
512 count += 15;
513
514 // Remaining singles
515 while ( --count >= 0 )
516 s = ((s & 2) * (3 << 13)) ^ (s >> 1);
517
518 // Convert back to Fibonacci configuration
519 s &= 0x7FFF;
520 }
521 else if ( count < 8 || !optimized )
522 {
523 // won't fully replace upper 8 bits, so have to do the unoptimized way
524 while ( --count >= 0 )
525 s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2));
526 }
527 else
528 {
529 if ( count > 127 )
530 {
531 count %= 127;
532 if ( !count )
533 count = 127; // must run at least once
534 }
535
536 // Need to keep one extra bit of history
537 s = s << 1 & 0xFF;
538
539 // Convert from Fibonacci to Galois configuration,
540 // shifted left 2 bits
541 s ^= (s & 2) * 0x80;
542
543 // Each iteration is equivalent to clocking LFSR 7 times
544 // (interesting similarity to single clocking below)
545 while ( (count -= 7) > 0 )
546 s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
547 count += 7;
548
549 // Remaining singles
550 while ( --count >= 0 )
551 s = ((s & 4) * (3 << 5)) ^ (s >> 1);
552
553 // Convert back to Fibonacci configuration and
554 // repeat last 8 bits above significant 7
555 s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
556 }
557
558 return s;
559}
560#endif
561
562void Noise_run( struct Gb_Noise* this, blip_time_t time, blip_time_t end_time )
563{
564 // Determine what will be generated
565 int vol = 0;
566 struct Gb_Osc* osc = &this->osc;
567 struct Blip_Buffer* const out = osc->output;
568 if ( out )
569 {
570 int amp = osc->dac_off_amp;
571 if ( Noise_dac_enabled( this ) )
572 {
573 if ( osc->enabled )
574 vol = this->volume;
575
576 amp = -dac_bias;
577 if ( osc->mode == mode_agb )
578 amp = -(vol >> 1);
579
580 if ( !(osc->phase & 1) )
581 {
582 amp += vol;
583 vol = -vol;
584 }
585 }
586
587 // AGB negates final output
588 if ( osc->mode == mode_agb )
589 {
590 vol = -vol;
591 amp = -amp;
592 }
593
594 Osc_update_amp( osc, time, amp );
595 }
596
597 // Run timer and calculate time of next LFSR clock
598 static byte const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
599 int const period1 = period1s [osc->regs [3] & 7] * clk_mul;
600
601 #ifdef GB_APU_FAST
602 time += delay;
603 #else
604 {
605 int extra = (end_time - time) - osc->delay;
606 int const per2 = period2( this, 8 );
607 time += osc->delay + ((this->divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
608
609 int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
610 this->divider = (this->divider - count) & period2_mask;
611 osc->delay = count * period1 - extra;
612 }
613 #endif
614
615 // Generate wave
616 if ( time < end_time )
617 {
618 unsigned const mask = lfsr_mask( this );
619 unsigned bits = osc->phase;
620
621 int per = period2( this, period1 * 8 );
622 #ifdef GB_APU_FAST
623 // Noise can be THE biggest time hog; adjust as necessary
624 int const min_period = 24;
625 if ( per < min_period )
626 per = min_period;
627 #endif
628 if ( period2_index( this ) >= 0xE )
629 {
630 time = end_time;
631 }
632 else if ( !vol )
633 {
634 #ifdef GB_APU_FAST
635 time = end_time;
636 #else
637 // Maintain phase when not playing
638 int count = (end_time - time + per - 1) / per;
639 time += (blip_time_t) count * per;
640 bits = run_lfsr( bits, ~mask, count );
641 #endif
642 }
643 else
644 {
645 struct Blip_Synth* synth = osc->synth; // cache
646
647 // Output amplitude transitions
648 int delta = -vol;
649 do
650 {
651 unsigned changed = bits + 1;
652 bits = bits >> 1 & mask;
653 if ( changed & 2 )
654 {
655 bits |= ~mask;
656 delta = -delta;
657 Synth_offset_inline( synth, time, delta, out );
658 }
659 time += per;
660 }
661 while ( time < end_time );
662
663 if ( delta == vol )
664 osc->last_amp += delta;
665 }
666 osc->phase = bits;
667 }
668
669 #ifdef GB_APU_FAST
670 osc->delay = time - end_time;
671 #endif
672}
673
674void Wave_run( struct Gb_Wave* this, blip_time_t time, blip_time_t end_time )
675{
676 // Calc volume
677#ifdef GB_APU_NO_AGB
678 static byte const shifts [4] = { 4+4, 0+4, 1+4, 2+4 };
679 int const volume_idx = this->regs [2] >> 5 & 3;
680 int const volume_shift = shifts [volume_idx];
681 int const volume_mul = 1;
682#else
683 static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
684 int const volume_shift = 2 + 4;
685 int const volume_idx = this->osc.regs [2] >> 5 & (this->agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
686 int const volume_mul = volumes [volume_idx];
687#endif
688
689 // Determine what will be generated
690 int playing = false;
691 struct Gb_Osc* osc = &this->osc;
692 struct Blip_Buffer* out = osc->output;
693 if ( out )
694 {
695 int amp = osc->dac_off_amp;
696 if ( Wave_dac_enabled( this ) )
697 {
698 // Play inaudible frequencies as constant amplitude
699 amp = 8 << 4; // really depends on average of all samples in wave
700
701 // if delay is larger, constant amplitude won't start yet
702 if ( Osc_frequency( osc ) <= 0x7FB || osc->delay > 15 * clk_mul )
703 {
704 if ( volume_mul && volume_shift != 4+4 )
705 playing = (int) osc->enabled;
706
707 amp = (this->sample_buf << (osc->phase << 2 & 4) & 0xF0) * playing;
708 }
709
710 amp = ((amp * volume_mul) >> volume_shift) - dac_bias;
711 }
712 Osc_update_amp( osc, time, amp );
713 }
714
715 // Generate wave
716 time += osc->delay;
717 if ( time < end_time )
718 {
719 byte const* wave = this->wave_ram;
720
721 // wave size and bank
722 #ifdef GB_APU_NO_AGB
723 int const wave_mask = 0x1F;
724 int const swap_banks = 0;
725 #else
726 int const size20_mask = 0x20;
727 int const flags = osc->regs [0] & this->agb_mask;
728 int const wave_mask = (flags & size20_mask) | 0x1F;
729 int swap_banks = 0;
730 if ( flags & bank40_mask )
731 {
732 swap_banks = flags & size20_mask;
733 wave += wave_bank_size/2 - (swap_banks >> 1);
734 }
735 #endif
736
737 int ph = osc->phase ^ swap_banks;
738 ph = (ph + 1) & wave_mask; // pre-advance
739
740 int const per = Wave_period( this );
741 if ( !playing )
742 {
743 #ifdef GB_APU_FAST
744 time = end_time;
745 #else
746 // Maintain phase when not playing
747 int count = (end_time - time + per - 1) / per;
748 ph += count; // will be masked below
749 time += (blip_time_t) count * per;
750 #endif
751 }
752 else
753 {
754 struct Blip_Synth* synth = osc->synth; // cache
755
756 // Output amplitude transitions
757 int lamp = osc->last_amp + dac_bias;
758 do
759 {
760 // Extract nibble
761 int nibble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
762 ph = (ph + 1) & wave_mask;
763
764 // Scale by volume
765 int amp = (nibble * volume_mul) >> volume_shift;
766
767 int delta = amp - lamp;
768 if ( delta )
769 {
770 lamp = amp;
771 Synth_offset_inline( synth, time, delta, out );
772 }
773 time += per;
774 }
775 while ( time < end_time );
776 osc->last_amp = lamp - dac_bias;
777 }
778 ph = (ph - 1) & wave_mask; // undo pre-advance and mask position
779
780 // Keep track of last byte read
781 if ( osc->enabled )
782 this->sample_buf = wave [ph >> 1];
783
784 osc->phase = ph ^ swap_banks; // undo swapped banks
785 }
786 osc->delay = time - end_time;
787}
diff --git a/lib/rbcodec/codecs/libgme/gb_oscs.h b/lib/rbcodec/codecs/libgme/gb_oscs.h
new file mode 100644
index 0000000000..3c8dfef51f
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gb_oscs.h
@@ -0,0 +1,187 @@
1// Private oscillators used by Gb_Apu
2
3// Gb_Snd_Emu 0.1.4
4#ifndef GB_OSCS_H
5#define GB_OSCS_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10#ifndef GB_APU_OVERCLOCK
11 #define GB_APU_OVERCLOCK 1
12#endif
13
14#if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1)
15 #error "GB_APU_OVERCLOCK must be a power of 2"
16#endif
17
18enum { clk_mul = GB_APU_OVERCLOCK };
19enum { dac_bias = 7 };
20
21struct Gb_Osc {
22 struct Blip_Buffer* outputs [4];// NULL, right, left, center
23 struct Blip_Buffer* output; // where to output sound
24 uint8_t* regs; // osc's 5 registers
25 int mode; // mode_dmg, mode_cgb, mode_agb
26 int dac_off_amp;// amplitude when DAC is off
27 int last_amp; // current amplitude in Blip_Buffer
28
29 struct Blip_Synth* synth;
30
31 int delay; // clocks until frequency timer expires
32 int length_ctr; // length counter
33 unsigned phase; // waveform phase (or equivalent)
34 bool enabled; // internal enabled flag
35};
36
37// 11-bit frequency in NRx3 and NRx4
38static inline int Osc_frequency( struct Gb_Osc* this ) { return (this->regs [4] & 7) * 0x100 + this->regs [3]; }
39
40void Osc_clock_length( struct Gb_Osc* this );
41void Osc_reset( struct Gb_Osc* this );
42
43// Square
44
45enum { period_mask = 0x70 };
46enum { shift_mask = 0x07 };
47
48struct Gb_Square {
49 struct Gb_Osc osc;
50
51 int env_delay;
52 int volume;
53 bool env_enabled;
54
55 // Sweep square
56 int sweep_freq;
57 int sweep_delay;
58 bool sweep_enabled;
59 bool sweep_neg;
60};
61
62void Square_run( struct Gb_Square* this, blip_time_t, blip_time_t );
63void Square_clock_envelope( struct Gb_Square* this );
64
65static inline void Square_reset( struct Gb_Square* this )
66{
67 this->env_delay = 0;
68 this->volume = 0;
69 Osc_reset( &this->osc );
70 this->osc.delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
71}
72// Frequency timer period
73static inline int Square_period( struct Gb_Square* this ) { return (2048 - Osc_frequency( &this->osc )) * (4 * clk_mul); }
74static inline int Square_dac_enabled( struct Gb_Square* this) { return this->osc.regs [2] & 0xF8; }
75static inline int Square_reload_env_timer( struct Gb_Square* this )
76{
77 int raw = this->osc.regs [2] & 7;
78 this->env_delay = (raw ? raw : 8);
79 return raw;
80}
81
82// Sweep square
83
84void clock_sweep( struct Gb_Square* this );
85
86static inline void Sweep_reset( struct Gb_Square* this )
87{
88 this->sweep_freq = 0;
89 this->sweep_delay = 0;
90 this->sweep_enabled = false;
91 this->sweep_neg = false;
92
93 this->env_delay = 0;
94 this->volume = 0;
95 Osc_reset( &this->osc );
96 this->osc.delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
97}
98
99// Noise
100
101enum { period2_mask = 0x1FFFF };
102
103struct Gb_Noise {
104 struct Gb_Osc osc;
105
106 int env_delay;
107 int volume;
108 bool env_enabled;
109
110 int divider; // noise has more complex frequency divider setup
111};
112
113void Noise_run( struct Gb_Noise* this, blip_time_t, blip_time_t );
114
115static inline void Noise_reset( struct Gb_Noise* this )
116{
117 this->divider = 0;
118
119 this->env_delay = 0;
120 this->volume = 0;
121 Osc_reset( &this->osc );
122 this->osc.delay = 4 * clk_mul; // TODO: remove?
123}
124
125void Noise_clock_envelope( struct Gb_Noise* this );
126
127// Non-zero if DAC is enabled
128static inline int Noise_dac_enabled( struct Gb_Noise* this) { return this->osc.regs [2] & 0xF8; }
129static inline int Noise_reload_env_timer( struct Gb_Noise* this )
130{
131 int raw = this->osc.regs [2] & 7;
132 this->env_delay = (raw ? raw : 8);
133 return raw;
134}
135
136static inline int period2_index( struct Gb_Noise* this ) { return this->osc.regs [3] >> 4; }
137static inline int period2( struct Gb_Noise* this, int base ) { return base << period2_index( this ); }
138static inline unsigned lfsr_mask( struct Gb_Noise* this ) { return (this->osc.regs [3] & 0x08) ? ~0x4040 : ~0x4000; }
139
140// Wave
141
142enum { bank40_mask = 0x40 };
143enum { wave_bank_size = 32 };
144
145struct Gb_Wave {
146 struct Gb_Osc osc;
147
148 int sample_buf; // last wave RAM byte read (hardware has this as well)
149
150 int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
151 uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU
152};
153
154void Wave_run( struct Gb_Wave* this, blip_time_t, blip_time_t );
155
156static inline void Wave_reset( struct Gb_Wave* this )
157{
158 this->sample_buf = 0;
159 Osc_reset( &this->osc );
160}
161
162// Frequency timer period
163static inline int Wave_period( struct Gb_Wave* this ) { return (2048 - Osc_frequency( &this->osc )) * (2 * clk_mul); }
164
165// Non-zero if DAC is enabled
166static inline int Wave_dac_enabled( struct Gb_Wave* this ) { return this->osc.regs [0] & 0x80; }
167
168static inline uint8_t* wave_bank( struct Gb_Wave* this ) { return &this->wave_ram [(~this->osc.regs [0] & bank40_mask) >> 2 & this->agb_mask]; }
169
170// Wave index that would be accessed, or -1 if no access would occur
171int wave_access( struct Gb_Wave* this, int addr );
172
173// Reads/writes wave RAM
174static inline int Wave_read( struct Gb_Wave* this, int addr )
175{
176 int index = wave_access( this, addr );
177 return (index < 0 ? 0xFF : wave_bank( this ) [index]);
178}
179
180static inline void Wave_write( struct Gb_Wave* this, int addr, int data )
181{
182 int index = wave_access( this, addr );
183 if ( index >= 0 )
184 wave_bank( this ) [index] = data;;
185}
186
187#endif
diff --git a/lib/rbcodec/codecs/libgme/gbs_cpu.c b/lib/rbcodec/codecs/libgme/gbs_cpu.c
new file mode 100644
index 0000000000..1015dd5358
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gbs_cpu.c
@@ -0,0 +1,120 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "gbs_emu.h"
4#include "blargg_endian.h"
5
6/* Copyright (C) 2003-2009 Shay Green. This module is free software; you
7can redistribute it and/or modify it under the terms of the GNU Lesser
8General Public License as published by the Free Software Foundation; either
9version 2.1 of the License, or (at your option) any later version. This
10module is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13details. You should have received a copy of the GNU Lesser General Public
14License along with this module; if not, write to the Free Software Foundation,
15Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
16
17#include "blargg_source.h"
18
19#ifndef LOG_MEM
20 #define LOG_MEM( addr, str, data ) data
21#endif
22
23int read_mem( struct Gbs_Emu* this, addr_t addr )
24{
25 int result = *Cpu_get_code( &this->cpu, addr );
26 if ( (unsigned) (addr - io_addr) < io_size )
27 result = Apu_read_register( &this->apu, Time( this ), addr );
28
29 return LOG_MEM( addr, ">", result );
30}
31
32static inline void write_io_inline( struct Gbs_Emu* this, int offset, int data, int base )
33{
34 if ( (unsigned) (offset - (io_addr - base)) < io_size )
35 Apu_write_register( &this->apu, Time( this ), offset + base, data & 0xFF );
36 else if ( (unsigned) (offset - (0xFF06 - base)) < 2 )
37 update_timer( this );
38 else if ( offset == io_base - base )
39 this->ram [base - ram_addr + offset] = 0; // keep joypad return value 0
40 else
41 this->ram [base - ram_addr + offset] = 0xFF;
42}
43
44void write_mem( struct Gbs_Emu* this, addr_t addr, int data )
45{
46 (void) LOG_MEM( addr, "<", data );
47
48 int offset = addr - ram_addr;
49 if ( (unsigned) offset < 0x10000 - ram_addr )
50 {
51 this->ram [offset] = data;
52
53 offset -= 0xE000 - ram_addr;
54 if ( (unsigned) offset < 0x1F80 )
55 write_io_inline( this, offset, data, 0xE000 );
56 }
57 else if ( (unsigned) (offset - (0x2000 - ram_addr)) < 0x2000 )
58 {
59 set_bank( this, data & 0xFF );
60 }
61#ifndef NDEBUG
62 else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
63 {
64 /* dprintf( "Unmapped write $%04X\n", (unsigned) addr ); */
65 }
66#endif
67}
68
69static void write_io_( struct Gbs_Emu* this, int offset, int data )
70{
71 write_io_inline( this, offset, data, io_base );
72}
73
74static inline void write_io( struct Gbs_Emu* this, int offset, int data )
75{
76 (void) LOG_MEM( offset + io_base, "<", data );
77
78 this->ram [io_base - ram_addr + offset] = data;
79 if ( (unsigned) offset < 0x80 )
80 write_io_( this, offset, data );
81}
82
83static int read_io( struct Gbs_Emu* this, int offset )
84{
85 int const io_base = 0xFF00;
86 int result = this->ram [io_base - ram_addr + offset];
87
88 if ( (unsigned) (offset - (io_addr - io_base)) < io_size )
89 {
90 result = Apu_read_register( &this->apu, Time( this ), offset + io_base );
91 (void) LOG_MEM( offset + io_base, ">", result );
92 }
93 else
94 {
95 check( result == read_mem( offset + io_base ) );
96 }
97 return result;
98}
99
100#define READ_FAST( emu, addr, out ) \
101{\
102 out = READ_CODE( addr );\
103 if ( (unsigned) (addr - io_addr) < io_size )\
104 out = LOG_MEM( addr, ">", Apu_read_register( &emu->apu, TIME() + emu->end_time, addr ) );\
105 else\
106 check( out == Read_mem( emu, addr ) );\
107}
108
109#define READ_MEM( emu, addr ) read_mem( emu, addr )
110#define WRITE_MEM( emu, addr, data ) write_mem( emu, addr, data )
111
112#define WRITE_IO( emu, addr, data ) write_io( emu, addr, data )
113#define READ_IO( emu, addr, out ) out = read_io( emu, addr )
114
115#define CPU_BEGIN \
116void run_cpu( struct Gbs_Emu* this )\
117{ \
118 struct Gb_Cpu* cpu = &this->cpu;
119 #include "gb_cpu_run.h"
120}
diff --git a/lib/rbcodec/codecs/libgme/gbs_emu.c b/lib/rbcodec/codecs/libgme/gbs_emu.c
new file mode 100644
index 0000000000..7a6d484673
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gbs_emu.c
@@ -0,0 +1,452 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2
3#include "gbs_emu.h"
4
5#include "blargg_endian.h"
6
7/* Copyright (C) 2003-2006 Shay Green. this module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. this
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20const char gme_wrong_file_type [] = "Wrong file type for this emulator";
21
22int const idle_addr = 0xF00D;
23int const tempo_unit = 16;
24
25static void clear_track_vars( struct Gbs_Emu* this )
26{
27 this->current_track_ = -1;
28 track_stop( &this->track_filter );
29}
30
31void Gbs_init( struct Gbs_Emu* this )
32{
33 this->sample_rate_ = 0;
34 this->mute_mask_ = 0;
35 this->tempo_ = (int)(FP_ONE_TEMPO);
36
37 // Unload
38 this->header.timer_mode = 0;
39
40 // defaults
41 this->tfilter = *track_get_setup( &this->track_filter );
42 this->tfilter.max_initial = 21;
43 this->tfilter.lookahead = 6;
44 this->track_filter.silence_ignored_ = false;
45
46 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
47
48 Rom_init( &this->rom, 0x4000 );
49
50 Apu_init( &this->apu );
51 Cpu_init( &this->cpu );
52
53 this->tempo = tempo_unit;
54 this->sound_hardware = sound_gbs;
55
56 // Reduce apu sound clicks?
57 Apu_reduce_clicks( &this->apu, true );
58
59 // clears fields
60 this->voice_count_ = 0;
61 this->voice_types_ = 0;
62 clear_track_vars( this );
63}
64
65static blargg_err_t check_gbs_header( void const* header )
66{
67 if ( memcmp( header, "GBS", 3 ) )
68 return gme_wrong_file_type;
69 return 0;
70}
71
72// Setup
73
74blargg_err_t Gbs_load_mem( struct Gbs_Emu* this, void* data, long size )
75{
76 // Unload
77 this->header.timer_mode = 0;
78 this->voice_count_ = 0;
79 this->track_count = 0;
80 this->m3u.size = 0;
81 clear_track_vars( this );
82
83 assert( offsetof (struct header_t,copyright [32]) == header_size );
84 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
85
86 RETURN_ERR( check_gbs_header( &this->header ) );
87
88 /* Ignore warnings? */
89 /*if ( header_.vers != 1 )
90 warning( "Unknown file version" );
91
92 if ( header_.timer_mode & 0x78 )
93 warning( "Invalid timer mode" ); */
94
95 /* unsigned load_addr = get_le16( this->header.load_addr ); */
96 /* if ( (header_.load_addr [1] | header_.init_addr [1] | header_.play_addr [1]) > 0x7F ||
97 load_addr < 0x400 )
98 warning( "Invalid load/init/play address" ); */
99
100 unsigned load_addr = get_le16( this->header.load_addr );
101 /* if ( (this->header.load_addr [1] | this->header.init_addr [1] | this->header.play_addr [1]) > 0x7F ||
102 load_addr < 0x400 )
103 warning( "Invalid load/init/play address" ); */
104
105 this->cpu.rst_base = load_addr;
106 Rom_set_addr( &this->rom, load_addr );
107
108 this->voice_count_ = osc_count;
109 static int const types [osc_count] = {
110 wave_type+1, wave_type+2, wave_type+3, mixed_type+1
111 };
112 this->voice_types_ = types;
113
114 Apu_volume( &this->apu, this->gain_ );
115
116 // Change clock rate & setup buffer
117 this->clock_rate_ = 4194304;
118 Buffer_clock_rate( &this->stereo_buf, 4194304 );
119 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count_, this->voice_types_ ) );
120 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
121
122 // Post load
123 Sound_set_tempo( this, this->tempo_ );
124 Sound_mute_voices( this, this->mute_mask_ );
125
126 // Set track count
127 this->track_count = this->header.track_count;
128 return 0;
129}
130
131// Emulation
132
133// see gb_cpu_io.h for read/write functions
134
135void set_bank( struct Gbs_Emu* this, int n )
136{
137 addr_t addr = mask_addr( n * this->rom.bank_size, this->rom.mask );
138 if ( addr == 0 && this->rom.size > this->rom.bank_size )
139 addr = this->rom.bank_size; // MBC1&2 behavior, bank 0 acts like bank 1
140 Cpu_map_code( &this->cpu, this->rom.bank_size, this->rom.bank_size, Rom_at_addr( &this->rom, addr ) );
141}
142
143void update_timer( struct Gbs_Emu* this )
144{
145 this->play_period = 70224 / tempo_unit; /// 59.73 Hz
146
147 if ( this->header.timer_mode & 0x04 )
148 {
149 // Using custom rate
150 static byte const rates [4] = { 6, 0, 2, 4 };
151 // TODO: emulate double speed CPU mode rather than halving timer rate
152 int double_speed = this->header.timer_mode >> 7;
153 int shift = rates [this->ram [hi_page + 7] & 3] - double_speed;
154 this->play_period = (256 - this->ram [hi_page + 6]) << shift;
155 }
156
157 this->play_period *= this->tempo;
158}
159
160// Jumps to routine, given pointer to address in file header. Pushes idle_addr
161// as return address, NOT old PC.
162void jsr_then_stop( struct Gbs_Emu* this, byte const addr [] )
163{
164 check( this->cpu.r.sp == get_le16( this->header.stack_ptr ) );
165 this->cpu.r.pc = get_le16( addr );
166 write_mem( this, --this->cpu.r.sp, idle_addr >> 8 );
167 write_mem( this, --this->cpu.r.sp, idle_addr );
168}
169
170static blargg_err_t run_until( struct Gbs_Emu* this, int end )
171{
172 this->end_time = end;
173 Cpu_set_time( &this->cpu, Cpu_time( &this->cpu ) - end );
174 while ( true )
175 {
176 run_cpu( this );
177 if ( Cpu_time( &this->cpu ) >= 0 )
178 break;
179
180 if ( this->cpu.r.pc == idle_addr )
181 {
182 if ( this->next_play > this->end_time )
183 {
184 Cpu_set_time( &this->cpu, 0 );
185 break;
186 }
187
188 if ( Cpu_time( &this->cpu ) < this->next_play - this->end_time )
189 Cpu_set_time( &this->cpu, this->next_play - this->end_time );
190 this->next_play += this->play_period;
191 jsr_then_stop( this, this->header.play_addr );
192 }
193 else if ( this->cpu.r.pc > 0xFFFF )
194 {
195 /* warning( "PC wrapped around\n" ); */
196 this->cpu.r.pc &= 0xFFFF;
197 }
198 else
199 {
200 /* warning( "Emulation error (illegal/unsupported instruction)" ); */
201 this->cpu.r.pc = (this->cpu.r.pc + 1) & 0xFFFF;
202 Cpu_set_time( &this->cpu, Cpu_time( &this->cpu ) + 6 );
203 }
204 }
205
206 return 0;
207}
208
209static blargg_err_t end_frame( struct Gbs_Emu* this, int end )
210{
211 RETURN_ERR( run_until( this, end ) );
212
213 this->next_play -= end;
214 if ( this->next_play < 0 ) // happens when play routine takes too long
215 {
216 #if !defined(GBS_IGNORE_STARVED_PLAY)
217 check( false );
218 #endif
219 this->next_play = 0;
220 }
221
222 Apu_end_frame( &this->apu, end );
223
224 return 0;
225}
226
227blargg_err_t run_clocks( struct Gbs_Emu* this, blip_time_t duration )
228{
229 return end_frame( this, duration );
230}
231
232blargg_err_t play_( void* emu, int count, sample_t* out )
233{
234 struct Gbs_Emu* this = (struct Gbs_Emu*) emu;
235
236 int remain = count;
237 while ( remain )
238 {
239 Buffer_disable_immediate_removal( &this->stereo_buf );
240 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
241 if ( remain )
242 {
243 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
244 {
245 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
246
247 // Remute voices
248 Sound_mute_voices( this, this->mute_mask_ );
249 }
250 int msec = Buffer_length( &this->stereo_buf );
251 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
252 RETURN_ERR( run_clocks( this, clocks_emulated ) );
253 assert( clocks_emulated );
254 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
255 }
256 }
257 return 0;
258}
259
260blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, int rate )
261{
262 require( !this->sample_rate_ ); // sample rate can't be changed once set
263 Buffer_init( &this->stereo_buf );
264 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
265
266 // Set bass frequency
267 Buffer_bass_freq( &this->stereo_buf, 300 );
268
269 this->sample_rate_ = rate;
270 RETURN_ERR( track_init( &this->track_filter, this ) );
271 this->tfilter.max_silence = 6 * stereo * this->sample_rate_;
272 return 0;
273}
274
275
276// Sound
277
278void Sound_mute_voice( struct Gbs_Emu* this, int index, bool mute )
279{
280 require( (unsigned) index < (unsigned) this->voice_count_ );
281 int bit = 1 << index;
282 int mask = this->mute_mask_ | bit;
283 if ( !mute )
284 mask ^= bit;
285 Sound_mute_voices( this, mask );
286}
287
288void Sound_mute_voices( struct Gbs_Emu* this, int mask )
289{
290 require( this->sample_rate_ ); // sample rate must be set first
291 this->mute_mask_ = mask;
292
293 int i;
294 for ( i = this->voice_count_; i--; )
295 {
296 if ( mask & (1 << i) )
297 {
298 Apu_set_output( &this->apu, i, 0, 0, 0 );
299 }
300 else
301 {
302 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
303 assert( (ch.center && ch.left && ch.right) ||
304 (!ch.center && !ch.left && !ch.right) ); // all or nothing
305 Apu_set_output( &this->apu, i, ch.center, ch.left, ch.right );
306 }
307 }
308}
309
310void Sound_set_tempo( struct Gbs_Emu* this, int t )
311{
312 require( this->sample_rate_ ); // sample rate must be set first
313 int const min = (int)(FP_ONE_TEMPO*0.02);
314 int const max = (int)(FP_ONE_TEMPO*4.00);
315 if ( t < min ) t = min;
316 if ( t > max ) t = max;
317 this->tempo_ = t;
318
319 this->tempo = (int) ((tempo_unit * FP_ONE_TEMPO) / t);
320 Apu_set_tempo( &this->apu, t );
321 update_timer( this );
322}
323
324blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int track )
325{
326 clear_track_vars( this );
327
328 // Remap track if playlist available
329 if ( this->m3u.size > 0 ) {
330 struct entry_t* e = &this->m3u.entries[track];
331 track = e->track;
332 }
333
334 this->current_track_ = track;
335 Buffer_clear( &this->stereo_buf );
336
337 // Reset APU to state expected by most rips
338 static byte const sound_data [] = {
339 0x80, 0xBF, 0x00, 0x00, 0xB8, // square 1 DAC disabled
340 0x00, 0x3F, 0x00, 0x00, 0xB8, // square 2 DAC disabled
341 0x7F, 0xFF, 0x9F, 0x00, 0xB8, // wave DAC disabled
342 0x00, 0xFF, 0x00, 0x00, 0xB8, // noise DAC disabled
343 0x77, 0xFF, 0x80, // max volume, all chans in center, power on
344 };
345
346 enum sound_t mode = this->sound_hardware;
347 if ( mode == sound_gbs )
348 mode = (this->header.timer_mode & 0x80) ? sound_cgb : sound_dmg;
349
350 Apu_reset( &this->apu, (enum gb_mode_t) mode, false );
351 Apu_write_register( &this->apu, 0, 0xFF26, 0x80 ); // power on
352 int i;
353 for ( i = 0; i < (int) sizeof sound_data; i++ )
354 Apu_write_register( &this->apu, 0, i + io_addr, sound_data [i] );
355 Apu_end_frame( &this->apu, 1 ); // necessary to get click out of the way */
356
357 memset( this->ram, 0, 0x4000 );
358 memset( this->ram + 0x4000, 0xFF, 0x1F80 );
359 memset( this->ram + 0x5F80, 0, sizeof this->ram - 0x5F80 );
360 this->ram [hi_page] = 0; // joypad reads back as 0
361 this->ram [idle_addr - ram_addr] = 0xED; // illegal instruction
362 this->ram [hi_page + 6] = this->header.timer_modulo;
363 this->ram [hi_page + 7] = this->header.timer_mode;
364
365 Cpu_reset( &this->cpu, this->rom.unmapped );
366 Cpu_map_code( &this->cpu, ram_addr, 0x10000 - ram_addr, this->ram );
367 Cpu_map_code( &this->cpu, 0, this->rom.bank_size, Rom_at_addr( &this->rom, 0 ) );
368 set_bank( this, this->rom.size > this->rom.bank_size );
369
370 update_timer( this );
371 this->next_play = this->play_period;
372 this->cpu.r.rp.fa = track;
373 this->cpu.r.sp = get_le16( this->header.stack_ptr );
374 this->cpu_time = 0;
375 jsr_then_stop( this, this->header.init_addr );
376
377 // convert filter times to samples
378 struct setup_t s = this->tfilter;
379 s.max_initial *= this->sample_rate_ * stereo;
380 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
381 s.lookahead = 1;
382 #endif
383 track_setup( &this->track_filter, &s );
384
385 return track_start( &this->track_filter );
386}
387
388
389// Track
390
391static int msec_to_samples( int msec, int sample_rate )
392{
393 int sec = msec / 1000;
394 msec -= sec * 1000;
395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
396}
397
398int Track_tell( struct Gbs_Emu* this )
399{
400 int rate = this->sample_rate_ * stereo;
401 int sec = track_sample_count( &this->track_filter ) / rate;
402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
403}
404
405blargg_err_t Track_seek( struct Gbs_Emu* this, int msec )
406{
407 int time = msec_to_samples( msec, this->sample_rate_ );
408 if ( time < track_sample_count( &this->track_filter ) )
409 RETURN_ERR( Gbs_start_track( this, this->current_track_ ) );
410 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
411}
412
413blargg_err_t skip_( void* emu, int count )
414{
415 struct Gbs_Emu* this = (struct Gbs_Emu*) emu;
416
417 // for long skip, mute sound
418 const int threshold = 32768;
419 if ( count > threshold )
420 {
421 int saved_mute = this->mute_mask_;
422 Sound_mute_voices( this, ~0 );
423
424 int n = count - threshold/2;
425 n &= ~(2048-1); // round to multiple of 2048
426 count -= n;
427 RETURN_ERR( skippy_( &this->track_filter, n ) );
428
429 Sound_mute_voices( this, saved_mute );
430 }
431
432 return skippy_( &this->track_filter, count );
433}
434
435blargg_err_t Track_skip( struct Gbs_Emu* this, int count )
436{
437 require( this->current_track_ >= 0 ); // start_track() must have been called already
438 return track_skip( &this->track_filter, count );
439}
440
441void Track_set_fade( struct Gbs_Emu* this, int start_msec, int length_msec )
442{
443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate_ ),
444 length_msec * this->sample_rate_ / (1000 / stereo) );
445}
446
447blargg_err_t Gbs_play( struct Gbs_Emu* this, int out_count, sample_t* out )
448{
449 require( this->current_track_ >= 0 );
450 require( out_count % stereo == 0 );
451 return track_play( &this->track_filter, out_count, out );
452}
diff --git a/lib/rbcodec/codecs/libgme/gbs_emu.h b/lib/rbcodec/codecs/libgme/gbs_emu.h
new file mode 100644
index 0000000000..72671b4658
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gbs_emu.h
@@ -0,0 +1,192 @@
1// Nintendo Game Boy GBS music file emulator
2
3// Game_Music_Emu 0.5.2
4#ifndef GBS_EMU_H
5#define GBS_EMU_H
6
7#include "rom_data.h"
8#include "multi_buffer.h"
9#include "gb_apu.h"
10#include "gb_cpu.h"
11#include "m3u_playlist.h"
12#include "track_filter.h"
13
14enum { joypad_addr = 0xFF00 };
15enum { ram_addr = 0xA000 };
16enum { hi_page = 0xFF00 - ram_addr };
17enum { io_base = 0xFF00 };
18
19// Selects which sound hardware to use. AGB hardware is cleaner than the
20// others. Doesn't take effect until next start_track().
21enum sound_t {
22 sound_dmg = mode_dmg, // Game Boy monochrome
23 sound_cgb = mode_cgb, // Game Boy Color
24 sound_agb = mode_agb, // Game Boy Advance
25 sound_gbs // Use DMG/CGB based on GBS (default)
26};
27
28// GBS file header
29enum { header_size = 112 };
30struct header_t
31{
32 char tag [3];
33 byte vers;
34 byte track_count;
35 byte first_track;
36 byte load_addr [2];
37 byte init_addr [2];
38 byte play_addr [2];
39 byte stack_ptr [2];
40 byte timer_modulo;
41 byte timer_mode;
42 char game [32];
43 char author [32];
44 char copyright [32];
45};
46
47struct Gbs_Emu {
48 enum sound_t sound_hardware;
49
50 int tempo;
51
52 // timer
53 blip_time_t cpu_time;
54 blip_time_t end_time;
55 blip_time_t play_period;
56 blip_time_t next_play;
57
58 // Sound
59 int clock_rate_;
60 int sample_rate_;
61 unsigned buf_changed_count;
62 int voice_count_;
63 int const* voice_types_;
64 int mute_mask_;
65 int gain_;
66 int tempo_;
67
68 // track-specific
69 byte track_count;
70 int current_track_;
71
72 // Larger items at the end
73 // Header for currently loaded file
74 struct header_t header;
75
76 // M3u Playlist
77 struct M3u_Playlist m3u;
78
79 struct setup_t tfilter;
80 struct Track_Filter track_filter;
81
82 struct Gb_Apu apu;
83 struct Gb_Cpu cpu;
84 struct Multi_Buffer stereo_buf;
85
86 // rom & ram
87 struct Rom_Data rom;
88 byte ram [0x4000 + 0x2000 + cpu_padding];
89};
90
91
92// Basic functionality
93// Initializes Gbs_Emu structure
94void Gbs_init( struct Gbs_Emu* this );
95
96// Stops (clear) Gbs_Emu structure
97void Gbs_stop( struct Gbs_Emu* this );
98
99// Loads a file from memory
100blargg_err_t Gbs_load_mem( struct Gbs_Emu* this, void* data, long size );
101
102// Set output sample rate. Must be called only once before loading file.
103blargg_err_t Gbs_set_sample_rate( struct Gbs_Emu* this, int sample_rate );
104
105// Start a track, where 0 is the first track. Also clears warning string.
106blargg_err_t Gbs_start_track( struct Gbs_Emu* this, int );
107
108// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
109// errors set warning string, and major errors also end track.
110blargg_err_t Gbs_play( struct Gbs_Emu* this, int count, sample_t* buf );
111
112// Track status/control
113// Number of milliseconds (1000 msec = 1 second) played since beginning of track
114int Track_tell( struct Gbs_Emu* this );
115
116// Seek to new time in track. Seeking backwards or far forward can take a while.
117blargg_err_t Track_seek( struct Gbs_Emu* this, int msec );
118
119// Skip n samples
120blargg_err_t Track_skip( struct Gbs_Emu* this, int n );
121
122// Set start time and length of track fade out. Once fade ends track_ended() returns
123// true. Fade time can be changed while track is playing.
124void Track_set_fade( struct Gbs_Emu* this, int start_msec, int length_msec );
125
126// True if a track has reached its end
127static inline bool Track_ended( struct Gbs_Emu* this )
128{
129 return track_ended( &this->track_filter );
130}
131
132// Disables automatic end-of-track detection and skipping of silence at beginning
133static inline void Track_ignore_silence( struct Gbs_Emu* this, bool disable )
134{
135 this->track_filter.silence_ignored_ = disable;
136}
137
138// Get track length in milliseconds
139static inline int Track_get_length( struct Gbs_Emu* this, int n )
140{
141 int length = 120 * 1000; /* 2 minutes */
142 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
143 struct entry_t* entry = &this->m3u.entries [n];
144 length = entry->length;
145 }
146
147 return length;
148}
149
150
151// Sound customization
152// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
153// Track length as returned by track_info() assumes a tempo of 1.0.
154void Sound_set_tempo( struct Gbs_Emu* this, int );
155
156// Mute/unmute voice i, where voice 0 is first voice
157void Sound_mute_voice( struct Gbs_Emu* this, int index, bool mute );
158
159// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
160// 0 unmutes them all, 0x01 mutes just the first voice, etc.
161void Sound_mute_voices( struct Gbs_Emu* this, int mask );
162
163// Change overall output amplitude, where 1.0 results in minimal clamping.
164// Must be called before set_sample_rate().
165static inline void Sound_set_gain( struct Gbs_Emu* this, int g )
166{
167 assert( !this->sample_rate_ ); // you must set gain before setting sample rate
168 this->gain_ = g;
169}
170
171// Emulation (You shouldn't touch these)
172
173blargg_err_t run_clocks( struct Gbs_Emu* this, blip_time_t duration );
174void set_bank( struct Gbs_Emu* this, int );
175void update_timer( struct Gbs_Emu* this );
176
177// Runs CPU until time becomes >= 0
178void run_cpu( struct Gbs_Emu* this );
179
180// Reads/writes memory and I/O
181int read_mem( struct Gbs_Emu* this, addr_t addr );
182void write_mem( struct Gbs_Emu* this, addr_t addr, int data );
183
184// Current time
185static inline blip_time_t Time( struct Gbs_Emu* this )
186{
187 return Cpu_time( &this->cpu ) + this->end_time;
188}
189
190void jsr_then_stop( struct Gbs_Emu* this, byte const [] );
191
192#endif
diff --git a/lib/rbcodec/codecs/libgme/gme.h b/lib/rbcodec/codecs/libgme/gme.h
new file mode 100644
index 0000000000..d6803704ce
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/gme.h
@@ -0,0 +1,18 @@
1/* Game music emulator library C interface (also usable from C++) */
2
3/* Game_Music_Emu 0.5.2 */
4#ifndef GME_H
5#define GME_H
6
7#ifdef __cplusplus
8 extern "C" {
9#endif
10
11/* Error string returned by library functions, or NULL if no error (success) */
12typedef const char* gme_err_t;
13
14#ifdef __cplusplus
15 }
16#endif
17
18#endif
diff --git a/lib/rbcodec/codecs/libgme/hes_apu.c b/lib/rbcodec/codecs/libgme/hes_apu.c
new file mode 100644
index 0000000000..a9cd32c8aa
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_apu.c
@@ -0,0 +1,371 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2
3#include "hes_apu.h"
4#include <string.h>
5
6/* Copyright (C) 2006 Shay Green. This module is free software; you
7can redistribute it and/or modify it under the terms of the GNU Lesser
8General Public License as published by the Free Software Foundation; either
9version 2.1 of the License, or (at your option) any later version. This
10module is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13details. You should have received a copy of the GNU Lesser General Public
14License along with this module; if not, write to the Free Software Foundation,
15Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
16
17#include "blargg_source.h"
18
19enum { center_waves = 1 }; // reduces asymmetry and clamping when starting notes
20
21static void balance_changed( struct Hes_Apu* this, struct Hes_Osc* osc )
22{
23 static short const log_table [32] = { // ~1.5 db per step
24 #define ENTRY( factor ) (short) (factor * amp_range / 31.0 + 0.5)
25 ENTRY( 0.000000 ),ENTRY( 0.005524 ),ENTRY( 0.006570 ),ENTRY( 0.007813 ),
26 ENTRY( 0.009291 ),ENTRY( 0.011049 ),ENTRY( 0.013139 ),ENTRY( 0.015625 ),
27 ENTRY( 0.018581 ),ENTRY( 0.022097 ),ENTRY( 0.026278 ),ENTRY( 0.031250 ),
28 ENTRY( 0.037163 ),ENTRY( 0.044194 ),ENTRY( 0.052556 ),ENTRY( 0.062500 ),
29 ENTRY( 0.074325 ),ENTRY( 0.088388 ),ENTRY( 0.105112 ),ENTRY( 0.125000 ),
30 ENTRY( 0.148651 ),ENTRY( 0.176777 ),ENTRY( 0.210224 ),ENTRY( 0.250000 ),
31 ENTRY( 0.297302 ),ENTRY( 0.353553 ),ENTRY( 0.420448 ),ENTRY( 0.500000 ),
32 ENTRY( 0.594604 ),ENTRY( 0.707107 ),ENTRY( 0.840896 ),ENTRY( 1.000000 ),
33 #undef ENTRY
34 };
35
36 int vol = (osc->control & 0x1F) - 0x1E * 2;
37
38 int left = vol + (osc->balance >> 3 & 0x1E) + (this->balance >> 3 & 0x1E);
39 if ( left < 0 ) left = 0;
40
41 int right = vol + (osc->balance << 1 & 0x1E) + (this->balance << 1 & 0x1E);
42 if ( right < 0 ) right = 0;
43
44 // optimizing for the common case of being centered also allows easy
45 // panning using Effects_Buffer
46
47 // Separate balance into center volume and additional on either left or right
48 osc->output [0] = osc->outputs [0]; // center
49 osc->output [1] = osc->outputs [2]; // right
50 int base = log_table [left ];
51 int side = log_table [right] - base;
52 if ( side < 0 )
53 {
54 base += side;
55 side = -side;
56 osc->output [1] = osc->outputs [1]; // left
57 }
58
59 // Optimize when output is far left, center, or far right
60 if ( !base || osc->output [0] == osc->output [1] )
61 {
62 base += side;
63 side = 0;
64 osc->output [0] = osc->output [1];
65 osc->output [1] = NULL;
66 osc->last_amp [1] = 0;
67 }
68
69 if ( center_waves )
70 {
71 // TODO: this can leave a non-zero level in a buffer (minor)
72 osc->last_amp [0] += (base - osc->volume [0]) * 16;
73 osc->last_amp [1] += (side - osc->volume [1]) * 16;
74 }
75
76 osc->volume [0] = base;
77 osc->volume [1] = side;
78}
79
80void Apu_init( struct Hes_Apu* this )
81{
82 struct Hes_Osc* osc = &this->oscs [osc_count];
83 do
84 {
85 osc--;
86 osc->output [0] = NULL;
87 osc->output [1] = NULL;
88 osc->outputs [0] = NULL;
89 osc->outputs [1] = NULL;
90 osc->outputs [2] = NULL;
91 }
92 while ( osc != this->oscs );
93
94 Apu_reset( this );
95}
96
97void Apu_reset( struct Hes_Apu* this )
98{
99 this->latch = 0;
100 this->balance = 0xFF;
101
102 struct Hes_Osc* osc = &this->oscs [osc_count];
103 do
104 {
105 osc--;
106 memset( osc, 0, offsetof (struct Hes_Osc,outputs) );
107 osc->lfsr = 1;
108 osc->control = 0x40;
109 osc->balance = 0xFF;
110 }
111 while ( osc != this->oscs );
112
113 // Only last two oscs support noise
114 this->oscs [osc_count - 2].lfsr = 0x200C3; // equivalent to 1 in Fibonacci LFSR
115 this->oscs [osc_count - 1].lfsr = 0x200C3;
116}
117
118void Apu_osc_output( struct Hes_Apu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
119{
120 // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
121 require( !center || (center && !left && !right) || (center && left && right) );
122 require( (unsigned) i < osc_count ); // fails if you pass invalid osc index
123
124 if ( !center || !left || !right )
125 {
126 left = center;
127 right = center;
128 }
129
130 struct Hes_Osc* o = &this->oscs [i];
131 o->outputs [0] = center;
132 o->outputs [1] = right;
133 o->outputs [2] = left;
134 balance_changed( this, o );
135}
136
137static void run_osc( struct Hes_Osc* o, struct Blip_Synth* syn, blip_time_t end_time )
138{
139 int vol0 = o->volume [0];
140 int vol1 = o->volume [1];
141 int dac = o->dac;
142
143 struct Blip_Buffer* out0 = o->output [0]; // cache often-used values
144 struct Blip_Buffer* out1 = o->output [1];
145 if ( !(o->control & 0x80) )
146 out0 = NULL;
147
148 if ( out0 )
149 {
150 // Update amplitudes
151 if ( out1 )
152 {
153 int delta = dac * vol1 - o->last_amp [1];
154 if ( delta )
155 {
156 Synth_offset( syn, o->last_time, delta, out1 );
157 Blip_set_modified( out1 );
158 }
159 }
160 int delta = dac * vol0 - o->last_amp [0];
161 if ( delta )
162 {
163 Synth_offset( syn, o->last_time, delta, out0 );
164 Blip_set_modified( out0 );
165 }
166
167 // Don't generate if silent
168 if ( !(vol0 | vol1) )
169 out0 = NULL;
170 }
171
172 // Generate noise
173 int noise = 0;
174 if ( o->lfsr )
175 {
176 noise = o->noise & 0x80;
177
178 blip_time_t time = o->last_time + o->noise_delay;
179 if ( time < end_time )
180 {
181 int period = (~o->noise & 0x1F) * 128;
182 if ( !period )
183 period = 64;
184
185 if ( noise && out0 )
186 {
187 unsigned lfsr = o->lfsr;
188 do
189 {
190 int new_dac = -(lfsr & 1);
191 lfsr = (lfsr >> 1) ^ (0x30061 & new_dac);
192
193 int delta = (new_dac &= 0x1F) - dac;
194 if ( delta )
195 {
196 dac = new_dac;
197 Synth_offset( syn, time, delta * vol0, out0 );
198 if ( out1 )
199 Synth_offset( syn, time, delta * vol1, out1 );
200 }
201 time += period;
202 }
203 while ( time < end_time );
204
205 if ( !lfsr )
206 {
207 lfsr = 1;
208 check( false );
209 }
210 o->lfsr = lfsr;
211
212 Blip_set_modified( out0 );
213 if ( out1 )
214 Blip_set_modified( out1 );
215 }
216 else
217 {
218 // Maintain phase when silent
219 int count = (end_time - time + period - 1) / period;
220 time += count * period;
221
222 // not worth it
223 //while ( count-- )
224 // o->lfsr = (o->lfsr >> 1) ^ (0x30061 * (o->lfsr & 1));
225 }
226 }
227 o->noise_delay = time - end_time;
228 }
229
230 // Generate wave
231 blip_time_t time = o->last_time + o->delay;
232 if ( time < end_time )
233 {
234 int phase = (o->phase + 1) & 0x1F; // pre-advance for optimal inner loop
235 int period = o->period * 2;
236
237 if ( period >= 14 && out0 && !((o->control & 0x40) | noise) )
238 {
239 do
240 {
241 int new_dac = o->wave [phase];
242 phase = (phase + 1) & 0x1F;
243 int delta = new_dac - dac;
244 if ( delta )
245 {
246 dac = new_dac;
247 Synth_offset( syn, time, delta * vol0, out0 );
248 if ( out1 )
249 Synth_offset( syn, time, delta * vol1, out1 );
250 }
251 time += period;
252 }
253 while ( time < end_time );
254 Blip_set_modified( out0 );
255 if ( out1 )
256 Blip_set_modified( out1 );
257 }
258 else
259 {
260 // Maintain phase when silent
261 int count = end_time - time;
262 if ( !period )
263 period = 1;
264 count = (count + period - 1) / period;
265
266 phase += count; // phase will be masked below
267 time += count * period;
268 }
269
270 // TODO: Find whether phase increments even when both volumes are zero.
271 // CAN'T simply check for out0 being non-NULL, since it could be NULL
272 // if channel is muted in player, but still has non-zero volume.
273 // City Hunter breaks when this check is removed.
274 if ( !(o->control & 0x40) && (vol0 | vol1) )
275 o->phase = (phase - 1) & 0x1F; // undo pre-advance
276 }
277 o->delay = time - end_time;
278 check( o->delay >= 0 );
279
280 o->last_time = end_time;
281 o->dac = dac;
282 o->last_amp [0] = dac * vol0;
283 o->last_amp [1] = dac * vol1;
284}
285
286void Apu_write_data( struct Hes_Apu* this, blip_time_t time, int addr, int data )
287{
288 if ( addr == 0x800 )
289 {
290 this->latch = data & 7;
291 }
292 else if ( addr == 0x801 )
293 {
294 if ( this->balance != data )
295 {
296 this->balance = data;
297
298 struct Hes_Osc* osc = &this->oscs [osc_count];
299 do
300 {
301 osc--;
302 run_osc( osc, &this->synth, time );
303 balance_changed( this, this->oscs );
304 }
305 while ( osc != this->oscs );
306 }
307 }
308 else if ( this->latch < osc_count )
309 {
310 struct Hes_Osc* osc = &this->oscs [this->latch];
311 run_osc( osc, &this->synth, time );
312 switch ( addr )
313 {
314 case 0x802:
315 osc->period = (osc->period & 0xF00) | data;
316 break;
317
318 case 0x803:
319 osc->period = (osc->period & 0x0FF) | ((data & 0x0F) << 8);
320 break;
321
322 case 0x804:
323 if ( osc->control & 0x40 & ~data )
324 osc->phase = 0;
325 osc->control = data;
326 balance_changed( this, osc );
327 break;
328
329 case 0x805:
330 osc->balance = data;
331 balance_changed( this, osc );
332 break;
333
334 case 0x806:
335 data &= 0x1F;
336 if ( !(osc->control & 0x40) )
337 {
338 osc->wave [osc->phase] = data;
339 osc->phase = (osc->phase + 1) & 0x1F;
340 }
341 else if ( osc->control & 0x80 )
342 {
343 osc->dac = data;
344 }
345 break;
346
347 case 0x807:
348 osc->noise = data;
349 break;
350
351 case 0x809:
352 if ( !(data & 0x80) && (data & 0x03) != 0 ) {
353 dprintf( "HES LFO not supported\n" );
354 }
355 }
356 }
357}
358
359void Apu_end_frame( struct Hes_Apu* this, blip_time_t end_time )
360{
361 struct Hes_Osc* osc = &this->oscs [osc_count];
362 do
363 {
364 osc--;
365 if ( end_time > osc->last_time )
366 run_osc( osc, &this->synth, end_time );
367 assert( osc->last_time >= end_time );
368 osc->last_time -= end_time;
369 }
370 while ( osc != this->oscs );
371}
diff --git a/lib/rbcodec/codecs/libgme/hes_apu.h b/lib/rbcodec/codecs/libgme/hes_apu.h
new file mode 100644
index 0000000000..0265e6a3ad
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_apu.h
@@ -0,0 +1,66 @@
1// Turbo Grafx 16 (PC Engine) PSG sound chip emulator
2
3// Game_Music_Emu 0.5.2
4#ifndef HES_APU_H
5#define HES_APU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9#include "blip_buffer.h"
10
11enum { amp_range = 0x8000 };
12enum { osc_count = 6 }; // 0 <= chan < osc_count
13
14// Registers are at io_addr to io_addr+io_size-1
15enum { apu_io_addr = 0x0800 };
16enum { apu_io_size = 10 };
17
18struct Hes_Osc
19{
20 byte wave [32];
21 int delay;
22 int period;
23 int phase;
24
25 int noise_delay;
26 byte noise;
27 unsigned lfsr;
28
29 byte control;
30 byte balance;
31 byte dac;
32 short volume [2];
33 int last_amp [2];
34
35 blip_time_t last_time;
36 struct Blip_Buffer* output [2];
37 struct Blip_Buffer* outputs [3];
38};
39
40void Osc_run_until( struct Hes_Osc* this, struct Blip_Synth* synth, blip_time_t );
41
42struct Hes_Apu {
43
44 int latch;
45 int balance;
46 struct Blip_Synth synth;
47 struct Hes_Osc oscs [osc_count];
48};
49
50// Init HES apu sound chip
51void Apu_init( struct Hes_Apu* this );
52
53// Reset HES apu couns chip
54void Apu_reset( struct Hes_Apu* this );
55
56void Apu_osc_output( struct Hes_Apu* this, int index, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right );
57
58// Emulates to time t, then writes data to addr
59void Apu_write_data( struct Hes_Apu* this, blip_time_t, int addr, int data );
60
61// Emulates to time t, then subtracts t from the current time.
62// OK if previous write call had time slightly after t.
63void Apu_end_frame( struct Hes_Apu* this, blip_time_t );
64
65static inline void Apu_volume( struct Hes_Apu* this, int v ) { Synth_volume( &this->synth, (v*9)/5 / osc_count / amp_range ); }
66#endif
diff --git a/lib/rbcodec/codecs/libgme/hes_apu_adpcm.c b/lib/rbcodec/codecs/libgme/hes_apu_adpcm.c
new file mode 100644
index 0000000000..de9b894f5d
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_apu_adpcm.c
@@ -0,0 +1,297 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "hes_apu_adpcm.h"
4
5/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16
17void Adpcm_init( struct Hes_Apu_Adpcm* this )
18{
19 this->output = NULL;
20 memset( &this->state, 0, sizeof( this->state ) );
21 Adpcm_reset( this );
22}
23
24void Adpcm_reset( struct Hes_Apu_Adpcm* this )
25{
26 this->last_time = 0;
27 this->next_timer = 0;
28 this->last_amp = 0;
29
30 memset( &this->state.pcmbuf, 0, sizeof(this->state.pcmbuf) );
31 memset( &this->state.port, 0, sizeof(this->state.port) );
32
33 this->state.ad_sample = 0;
34 this->state.ad_ref_index = 0;
35
36 this->state.addr = 0;
37 this->state.freq = 0;
38 this->state.writeptr = 0;
39 this->state.readptr = 0;
40 this->state.playflag = 0;
41 this->state.repeatflag = 0;
42 this->state.length = 0;
43 this->state.volume = 0xFF;
44 this->state.fadetimer = 0;
45 this->state.fadecount = 0;
46}
47
48static short stepsize[49] = {
49 16, 17, 19, 21, 23, 25, 28,
50 31, 34, 37, 41, 45, 50, 55,
51 60, 66, 73, 80, 88, 97, 107,
52 118, 130, 143, 157, 173, 190, 209,
53 230, 253, 279, 307, 337, 371, 408,
54 449, 494, 544, 598, 658, 724, 796,
55 876, 963,1060,1166,1282,1411,1552
56};
57
58static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code );
59static int Adpcm_decode( struct Hes_Apu_Adpcm* this,int code )
60{
61 struct State* state = &this->state;
62 int step = stepsize[state->ad_ref_index];
63 int delta;
64 int c = code & 7;
65#if 1
66 delta = 0;
67 if ( c & 4 ) delta += step;
68 step >>= 1;
69 if ( c & 2 ) delta += step;
70 step >>= 1;
71 if ( c & 1 ) delta += step;
72 step >>= 1;
73 delta += step;
74#else
75 delta = ( ( c + c + 1 ) * step ) / 8; // maybe faster, but introduces rounding
76#endif
77 if ( c != code )
78 {
79 state->ad_sample -= delta;
80 if ( state->ad_sample < -2048 )
81 state->ad_sample = -2048;
82 }
83 else
84 {
85 state->ad_sample += delta;
86 if ( state->ad_sample > 2047 )
87 state->ad_sample = 2047;
88 }
89
90 static int const steps [8] = {
91 -1, -1, -1, -1, 2, 4, 6, 8
92 };
93 state->ad_ref_index += steps [c];
94 if ( state->ad_ref_index < 0 )
95 state->ad_ref_index = 0;
96 else if ( state->ad_ref_index > 48 )
97 state->ad_ref_index = 48;
98
99 return state->ad_sample;
100}
101
102static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time );
103static void Adpcm_run_until( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
104{
105 struct State* state = &this->state;
106 int volume = state->volume;
107 int fadetimer = state->fadetimer;
108 int fadecount = state->fadecount;
109 int last_time = this->last_time;
110 int next_timer = this->next_timer;
111 int last_amp = this->last_amp;
112
113 struct Blip_Buffer* output = this->output; // cache often-used values
114
115 while ( state->playflag && last_time < end_time )
116 {
117 while ( last_time >= next_timer )
118 {
119 if ( fadetimer )
120 {
121 if ( fadecount > 0 )
122 {
123 fadecount--;
124 volume = 0xFF * fadecount / fadetimer;
125 }
126 else if ( fadecount < 0 )
127 {
128 fadecount++;
129 volume = 0xFF - ( 0xFF * fadecount / fadetimer );
130 }
131 }
132 next_timer += 7159; // 7159091/1000;
133 }
134 int amp;
135 if ( state->ad_low_nibble )
136 {
137 amp = Adpcm_decode( this, state->pcmbuf[ state->playptr ] & 0x0F );
138 state->ad_low_nibble = false;
139 state->playptr++;
140 state->playedsamplecount++;
141 if ( state->playedsamplecount == state->playlength )
142 {
143 state->playflag = 0;
144 }
145 }
146 else
147 {
148 amp = Adpcm_decode( this, state->pcmbuf[ state->playptr ] >> 4 );
149 state->ad_low_nibble = true;
150 }
151 amp = amp * volume / 0xFF;
152 int delta = amp - last_amp;
153 if ( output && delta )
154 {
155 last_amp = amp;
156 Synth_offset_inline( &this->synth, last_time, delta, output );
157 }
158 last_time += state->freq;
159 }
160
161 if ( !state->playflag )
162 {
163 while ( next_timer <= end_time ) next_timer += 7159; // 7159091/1000
164 last_time = end_time;
165 }
166
167 this->last_time = last_time;
168 this->next_timer = next_timer;
169 this->last_amp = last_amp;
170 state->volume = volume;
171 state->fadetimer = fadetimer;
172 state->fadecount = fadecount;
173}
174
175void Adpcm_write_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr, int data )
176{
177 if ( time > this->last_time ) Adpcm_run_until( this, time );
178 struct State* state = &this->state;
179
180 data &= 0xFF;
181 state->port[ addr & 15 ] = data;
182 switch ( addr & 15 )
183 {
184 case 8:
185 state->addr &= 0xFF00;
186 state->addr |= data;
187 break;
188 case 9:
189 state->addr &= 0xFF;
190 state->addr |= data << 8;
191 break;
192 case 10:
193 state->pcmbuf[ state->writeptr++ ] = data;
194 state->playlength ++;
195 break;
196 case 11:
197 dprintf("ADPCM DMA 0x%02X", data);
198 break;
199 case 13:
200 if ( data & 0x80 )
201 {
202 state->addr = 0;
203 state->freq = 0;
204 state->writeptr = 0;
205 state->readptr = 0;
206 state->playflag = 0;
207 state->repeatflag = 0;
208 state->length = 0;
209 state->volume = 0xFF;
210 }
211 if ( ( data & 3 ) == 3 )
212 {
213 state->writeptr = state->addr;
214 }
215 if ( data & 8 )
216 {
217 state->readptr = state->addr ? state->addr - 1 : state->addr;
218 }
219 if ( data & 0x10 )
220 {
221 state->length = state->addr;
222 }
223 state->repeatflag = data & 0x20;
224 state->playflag = data & 0x40;
225 if ( state->playflag )
226 {
227 state->playptr = state->readptr;
228 state->playlength = state->length + 1;
229 state->playedsamplecount = 0;
230 state->ad_sample = 0;
231 state->ad_low_nibble = false;
232 }
233 break;
234 case 14:
235 state->freq = 7159091 / ( 32000 / ( 16 - ( data & 15 ) ) );
236 break;
237 case 15:
238 switch ( data & 15 )
239 {
240 case 0:
241 case 8:
242 case 12:
243 state->fadetimer = -100;
244 state->fadecount = state->fadetimer;
245 break;
246 case 10:
247 state->fadetimer = 5000;
248 state->fadecount = state->fadetimer;
249 break;
250 case 14:
251 state->fadetimer = 1500;
252 state->fadecount = state->fadetimer;
253 break;
254 }
255 break;
256 }
257}
258
259int Adpcm_read_data( struct Hes_Apu_Adpcm* this, blip_time_t time, int addr )
260{
261 if ( time > this->last_time ) Adpcm_run_until( this, time );
262
263 struct State* state = &this->state;
264 switch ( addr & 15 )
265 {
266 case 10:
267 return state->pcmbuf [state->readptr++];
268 case 11:
269 return state->port [11] & ~1;
270 case 12:
271 if (!state->playflag)
272 {
273 state->port [12] |= 1;
274 state->port [12] &= ~8;
275 }
276 else
277 {
278 state->port [12] &= ~1;
279 state->port [12] |= 8;
280 }
281 return state->port [12];
282 case 13:
283 return state->port [13];
284 }
285
286 return 0xFF;
287}
288
289void Adpcm_end_frame( struct Hes_Apu_Adpcm* this, blip_time_t end_time )
290{
291 Adpcm_run_until( this, end_time );
292 this->last_time -= end_time;
293 this->next_timer -= end_time;
294 check( last_time >= 0 );
295 if ( this->output )
296 Blip_set_modified( this->output );
297}
diff --git a/lib/rbcodec/codecs/libgme/hes_apu_adpcm.h b/lib/rbcodec/codecs/libgme/hes_apu_adpcm.h
new file mode 100644
index 0000000000..afe160bb9c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_apu_adpcm.h
@@ -0,0 +1,89 @@
1// Turbo Grafx 16 (PC Engine) ADPCM sound chip emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef HES_APU_ADPCM_H
5#define HES_APU_ADPCM_H
6
7#include "blargg_source.h"
8#include "blargg_common.h"
9#include "blip_buffer.h"
10
11enum { adpcm_amp_range = 2048 };
12enum { adpcm_osc_count = 1 }; // 0 <= chan < osc_count
13
14// Registers are at io_addr to io_addr+io_size-1
15enum { adpcm_io_addr = 0x1800 };
16enum { adpcm_io_size = 0x400 };
17
18struct State
19{
20 byte pcmbuf [0x10000];
21 byte port [0x10];
22 int ad_sample;
23 int ad_ref_index;
24 bool ad_low_nibble;
25 int freq;
26 unsigned short addr;
27 unsigned short writeptr;
28 unsigned short readptr;
29 unsigned short playptr;
30 byte playflag;
31 byte repeatflag;
32 int length;
33 int playlength;
34 int playedsamplecount;
35 int volume;
36 int fadetimer;
37 int fadecount;
38};
39
40struct Hes_Apu_Adpcm {
41 struct State state;
42 struct Blip_Synth synth;
43
44 struct Blip_Buffer* output;
45 blip_time_t last_time;
46 int next_timer;
47 int last_amp;
48};
49
50// Init HES adpcm sound chip
51void Adpcm_init( struct Hes_Apu_Adpcm* this );
52
53// Rest HES adpcm sound chip
54void Adpcm_reset( struct Hes_Apu_Adpcm* this );
55
56// Sets buffer(s) to generate sound into, or 0 to mute. If only center is not 0,
57// output is mono.
58static inline void Adpcm_set_output( struct Hes_Apu_Adpcm* this, int chan, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
59{
60 // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
61 require( !center || (center && !left && !right) || (center && left && right) );
62 require( (unsigned) chan < adpcm_osc_count ); // fails if you pass invalid osc index
63
64#if defined(ROCKBOX)
65 (void) chan;
66#endif
67
68 if ( !center || !left || !right )
69 {
70 left = center;
71 right = center;
72 }
73
74 this->output = center;
75}
76
77// Emulates to time t, then writes data to addr
78void Adpcm_write_data( struct Hes_Apu_Adpcm* this, blip_time_t t, int addr, int data );
79
80// Emulates to time t, then reads from addr
81int Adpcm_read_data( struct Hes_Apu_Adpcm* this, blip_time_t t, int addr );
82
83// Emulates to time t, then subtracts t from the current time.
84// OK if previous write call had time slightly after t.
85void Adpcm_end_frame( struct Hes_Apu_Adpcm* this,blip_time_t t );
86
87// Sets overall volume, where 1.0 is normal
88static inline void Adpcm_volume( struct Hes_Apu_Adpcm* this, int v ) { Synth_volume( &this->synth, (v*3)/5 / adpcm_osc_count / adpcm_amp_range ); }
89#endif
diff --git a/lib/rbcodec/codecs/libgme/hes_cpu.c b/lib/rbcodec/codecs/libgme/hes_cpu.c
new file mode 100644
index 0000000000..6b833b3b98
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_cpu.c
@@ -0,0 +1,121 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2
3#include "hes_emu.h"
4
5#include "blargg_endian.h"
6
7//#include "hes_cpu_log.h"
8
9/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
10can redistribute it and/or modify it under the terms of the GNU Lesser
11General Public License as published by the Free Software Foundation; either
12version 2.1 of the License, or (at your option) any later version. This
13module is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16details. You should have received a copy of the GNU Lesser General Public
17License along with this module; if not, write to the Free Software Foundation,
18Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
20#include "blargg_source.h"
21#define PAGE HES_CPU_PAGE
22
23int read_mem( struct Hes_Emu* this, hes_addr_t addr )
24{
25 check( addr < 0x10000 );
26 int result = *Cpu_get_code( &this->cpu, addr );
27 if ( this->cpu.mmr [PAGE( addr )] == 0xFF )
28 result = read_mem_( this, addr );
29 return result;
30}
31
32void write_mem( struct Hes_Emu* this, hes_addr_t addr, int data )
33{
34 check( addr < 0x10000 );
35 byte* out = this->write_pages [PAGE( addr )];
36 if ( out )
37 out [addr & (page_size - 1)] = data;
38 else if ( this->cpu.mmr [PAGE( addr )] == 0xFF )
39 write_mem_( this, addr, data );
40}
41
42void set_mmr( struct Hes_Emu* this, int page, int bank )
43{
44 this->write_pages [page] = 0;
45 byte* data = Rom_at_addr( &this->rom, bank * page_size );
46 if ( bank >= 0x80 )
47 {
48 data = 0;
49 switch ( bank )
50 {
51 case 0xF8:
52 data = this->ram;
53 break;
54
55 case 0xF9:
56 case 0xFA:
57 case 0xFB:
58 data = &this->sgx [(bank - 0xF9) * page_size];
59 break;
60
61 default:
62 /* if ( bank != 0xFF )
63 dprintf( "Unmapped bank $%02X\n", bank ); */
64 data = this->rom.unmapped;
65 goto end;
66 }
67
68 this->write_pages [page] = data;
69 }
70end:
71 Cpu_set_mmr( &this->cpu, page, bank, data );
72}
73
74#define READ_FAST( addr, out ) \
75{\
76 out = READ_CODE( addr );\
77 if ( cpu->mmr [PAGE( addr )] == 0xFF )\
78 {\
79 FLUSH_TIME();\
80 out = read_mem_( this, addr );\
81 CACHE_TIME();\
82 }\
83}
84
85#define WRITE_FAST( addr, data ) \
86{\
87 int page = PAGE( addr );\
88 byte* out = this->write_pages [page];\
89 addr &= page_size - 1;\
90 if ( out )\
91 {\
92 out [addr] = data;\
93 }\
94 else if ( cpu->mmr [page] == 0xFF )\
95 {\
96 FLUSH_TIME();\
97 write_mem_( this, addr, data );\
98 CACHE_TIME();\
99 }\
100}
101
102#define READ_LOW( addr ) (this->ram [addr])
103#define WRITE_LOW( addr, data ) (this->ram [addr] = data)
104#define READ_MEM( addr ) read_mem( this, addr )
105#define WRITE_MEM( addr, data ) write_mem( this, addr, data )
106#define WRITE_VDP( addr, data ) write_vdp( this, addr, data )
107#define CPU_DONE( result_out ) { FLUSH_TIME(); result_out = cpu_done( this ); CACHE_TIME(); }
108#define SET_MMR( reg, bank ) set_mmr( this, reg, bank )
109
110#define IDLE_ADDR idle_addr
111
112#define CPU_BEGIN \
113bool run_cpu( struct Hes_Emu* this, hes_time_t end_time )\
114{\
115 struct Hes_Cpu* cpu = &this->cpu;\
116 Cpu_set_end_time( cpu, end_time );
117
118 #include "hes_cpu_run.h"
119
120 return illegal_encountered;
121}
diff --git a/lib/rbcodec/codecs/libgme/hes_cpu.h b/lib/rbcodec/codecs/libgme/hes_cpu.h
new file mode 100644
index 0000000000..0429eeaba0
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_cpu.h
@@ -0,0 +1,132 @@
1// PC Engine CPU emulator for use with HES music files
2
3// Game_Music_Emu 0.6-pre
4#ifndef HES_CPU_H
5#define HES_CPU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9
10typedef int hes_time_t; // clock cycle count
11typedef int hes_addr_t; // 16-bit address
12
13struct Hes_Emu;
14
15enum { future_time = INT_MAX/2 + 1 };
16enum { page_bits = 13 };
17enum { page_size = 1 << page_bits };
18enum { page_count = 0x10000 / page_size };
19
20// Can read this many bytes past end of a page
21enum { cpu_padding = 8 };
22enum { irq_inhibit_mask = 0x04 };
23enum { idle_addr = 0x1FFF };
24
25// Cpu state
26struct cpu_state_t {
27 byte const* code_map [page_count + 1];
28 hes_time_t base;
29 int time;
30};
31
32// NOT kept updated during emulation.
33struct registers_t {
34 uint16_t pc;
35 byte a;
36 byte x;
37 byte y;
38 byte flags;
39 byte sp;
40};
41
42struct Hes_Cpu {
43 struct registers_t r;
44
45 hes_time_t irq_time_;
46 hes_time_t end_time_;
47
48 struct cpu_state_t* cpu_state; // points to state_ or a local copy within run()
49 struct cpu_state_t cpu_state_;
50
51 // page mapping registers
52 uint8_t mmr [page_count + 1];
53 uint8_t ram [page_size];
54};
55
56// Init cpu state
57static inline void Cpu_init( struct Hes_Cpu* this )
58{
59 this->cpu_state = &this->cpu_state_;
60}
61
62// Reset hes cpu
63void Cpu_reset( struct Hes_Cpu* this );
64
65// Set end_time and run CPU from current time. Returns true if any illegal
66// instructions were encountered.
67bool Cpu_run( struct Hes_Emu* this, hes_time_t end_time );
68
69// Time of ning of next instruction to be executed
70static inline hes_time_t Cpu_time( struct Hes_Cpu* this )
71{
72 return this->cpu_state->time + this->cpu_state->base;
73}
74
75static inline void Cpu_set_time( struct Hes_Cpu* this, hes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
76static inline void Cpu_adjust_time( struct Hes_Cpu* this, int delta ) { this->cpu_state->time += delta; }
77
78#define HES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
79
80#ifdef BLARGG_NONPORTABLE
81 #define HES_CPU_OFFSET( addr ) (addr)
82#else
83 #define HES_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
84#endif
85
86static inline uint8_t const* Cpu_get_code( struct Hes_Cpu* this, hes_addr_t addr )
87{
88 return this->cpu_state_.code_map [HES_CPU_PAGE( addr )] + HES_CPU_OFFSET( addr );
89}
90
91static inline void update_end_time( struct Hes_Cpu* this, hes_time_t end, hes_time_t irq )
92{
93 if ( end > irq && !(this->r.flags & irq_inhibit_mask) )
94 end = irq;
95
96 this->cpu_state->time += this->cpu_state->base - end;
97 this->cpu_state->base = end;
98}
99
100static inline hes_time_t Cpu_end_time( struct Hes_Cpu* this ) { return this->end_time_; }
101
102static inline void Cpu_set_irq_time( struct Hes_Cpu* this, hes_time_t t )
103{
104 this->irq_time_ = t;
105 update_end_time( this, this->end_time_, t );
106}
107
108static inline void Cpu_set_end_time( struct Hes_Cpu* this, hes_time_t t )
109{
110 this->end_time_ = t;
111 update_end_time( this, t, this->irq_time_ );
112}
113
114static inline void Cpu_end_frame( struct Hes_Cpu* this, hes_time_t t )
115{
116 assert( this->cpu_state == &this->cpu_state_ );
117 this->cpu_state_.base -= t;
118 if ( this->irq_time_ < future_time ) this->irq_time_ -= t;
119 if ( this->end_time_ < future_time ) this->end_time_ -= t;
120}
121
122static inline void Cpu_set_mmr( struct Hes_Cpu* this, int reg, int bank, void const* code )
123{
124 assert( (unsigned) reg <= page_count ); // allow page past end to be set
125 assert( (unsigned) bank < 0x100 );
126 this->mmr [reg] = bank;
127 byte const* p = STATIC_CAST(byte const*,code) - HES_CPU_OFFSET( reg << page_bits );
128 this->cpu_state->code_map [reg] = p;
129 this->cpu_state_.code_map [reg] = p;
130}
131
132#endif
diff --git a/lib/rbcodec/codecs/libgme/hes_cpu_run.h b/lib/rbcodec/codecs/libgme/hes_cpu_run.h
new file mode 100644
index 0000000000..bfba2b6109
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_cpu_run.h
@@ -0,0 +1,1344 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#if 0
4/* Define these macros in the source file before #including this file.
5- Parameters might be expressions, so they are best evaluated only once,
6though they NEVER have side-effects, so multiple evaluation is OK.
7- Output parameters might be a multiple-assignment expression like "a=x",
8so they must NOT be parenthesized.
9- Except where noted, time() and related functions will NOT work
10correctly inside a macro. TIME() is always correct, and FLUSH_TIME() and
11CACHE_TIME() allow the time changing functions to work.
12- Macros "returning" void may use a {} statement block. */
13
14 // 0 <= addr <= 0xFFFF + page_size
15 // time functions can be used
16 int READ_MEM( addr_t );
17 void WRITE_MEM( addr_t, int data );
18
19 // 0 <= addr <= 0x1FF
20 int READ_LOW( addr_t );
21 void WRITE_LOW( addr_t, int data );
22
23 // 0 <= addr <= 0xFFFF + page_size
24 // Used by common instructions.
25 int READ_FAST( addr_t, int& out );
26 void WRITE_FAST( addr_t, int data );
27
28 // 0 <= addr <= 2
29 // ST0, ST1, ST2 instructions
30 void WRITE_VDP( int addr, int data );
31
32// The following can be used within macros:
33
34 // Current time
35 hes_time_t TIME();
36
37 // Allows use of time functions
38 void FLUSH_TIME();
39
40 // Must be used before end of macro if FLUSH_TIME() was used earlier
41 void CACHE_TIME();
42
43// Configuration (optional; commented behavior if defined)
44
45 // Expanded just before beginning of code, to help debugger
46 #define CPU_BEGIN void my_run_cpu() {
47#endif
48
49/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
50can redistribute it and/or modify it under the terms of the GNU Lesser
51General Public License as published by the Free Software Foundation; either
52version 2.1 of the License, or (at your option) any later version. This
53module is distributed in the hope that it will be useful, but WITHOUT ANY
54WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
55FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
56details. You should have received a copy of the GNU Lesser General Public
57License along with this module; if not, write to the Free Software Foundation,
58Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
59
60// TODO: support T flag, including clearing it at appropriate times?
61
62// all zero-page should really use whatever is at page 1, but that would
63// reduce efficiency quite a bit
64int const ram_addr = 0x2000;
65
66void Cpu_reset( struct Hes_Cpu* this )
67{
68 check( this->cpu_state == &this->cpu_state_ );
69 this->cpu_state = &this->cpu_state_;
70
71 this->cpu_state_.time = 0;
72 this->cpu_state_.base = 0;
73 this->irq_time_ = future_time;
74 this->end_time_ = future_time;
75
76 this->r.flags = 0x04;
77 this->r.sp = 0;
78 this->r.pc = 0;
79 this->r.a = 0;
80 this->r.x = 0;
81 this->r.y = 0;
82
83 // Be sure "blargg_endian.h" has been #included
84 blargg_verify_byte_order();
85}
86
87// Allows MWCW debugger to step through code properly
88#ifdef CPU_BEGIN
89 CPU_BEGIN
90#endif
91
92// Time
93#define TIME() (s_time + s.base)
94#define FLUSH_TIME() {s.time = s_time;}
95#define CACHE_TIME() {s_time = s.time;}
96
97// Memory
98#define READ_STACK READ_LOW
99#define WRITE_STACK WRITE_LOW
100
101#define CODE_PAGE( addr ) s.code_map [HES_CPU_PAGE( addr )]
102#define CODE_OFFSET( addr ) HES_CPU_OFFSET( addr )
103#define READ_CODE( addr ) CODE_PAGE( addr ) [CODE_OFFSET( addr )]
104
105// Stack
106#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
107#define GET_SP() ((sp - 1) & 0xFF)
108#define SP( o ) ((sp + (o - (o>0)*0x100)) | 0x100)
109
110// Truncation
111#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
112#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
113#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
114
115// Flags with hex value for clarity when used as mask.
116// Stored in indicated variable during emulation.
117int const n80 = 0x80; // nz
118int const v40 = 0x40; // flags
119//int const t20 = 0x20;
120int const b10 = 0x10;
121int const d08 = 0x08; // flags
122int const i04 = 0x04; // flags
123int const z02 = 0x02; // nz
124int const c01 = 0x01; // c
125
126#define IS_NEG (nz & 0x8080)
127
128#define GET_FLAGS( out ) \
129{\
130 out = flags & (v40 | d08 | i04);\
131 out += ((nz >> 8) | nz) & n80;\
132 out += c >> 8 & c01;\
133 if ( !BYTE( nz ) )\
134 out += z02;\
135}
136
137#define SET_FLAGS( in ) \
138{\
139 flags = in & (v40 | d08 | i04);\
140 c = nz = in << 8;\
141 nz += ~in & z02;\
142}
143
144bool illegal_encountered = false;
145{
146 struct cpu_state_t s = cpu->cpu_state_;
147 cpu->cpu_state = &s;
148 // even on x86, using s.time in place of s_time was slower
149 int s_time = s.time;
150
151 // registers
152 int pc = cpu->r.pc;
153 int a = cpu->r.a;
154 int x = cpu->r.x;
155 int y = cpu->r.y;
156 int sp;
157 SET_SP( cpu->r.sp );
158
159 // Flags
160 int flags;
161 int c; // carry set if (c & 0x100) != 0
162 int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
163 {
164 int temp = cpu->r.flags;
165 SET_FLAGS( temp );
166 }
167
168loop:
169
170 #ifndef NDEBUG
171 {
172 hes_time_t correct = cpu->end_time_;
173 if ( !(flags & i04) && correct > cpu->irq_time_ )
174 correct = cpu->irq_time_;
175 check( s.base == correct );
176 /*
177 static int count;
178 if ( count == 1844 ) Debugger();
179 if ( s.base != correct ) dprintf( "%ld\n", count );
180 count++;
181 */
182 }
183 #endif
184
185 // Check all values
186 check( (unsigned) sp - 0x100 < 0x100 );
187 check( (unsigned) pc < 0x10000 + 0x100 ); // +0x100 so emulator can catch wrap-around
188 check( (unsigned) a < 0x100 );
189 check( (unsigned) x < 0x100 );
190 check( (unsigned) y < 0x100 );
191
192 // Read instruction
193 byte const* instr = CODE_PAGE( pc );
194 int opcode;
195
196 if ( CODE_OFFSET(~0) == ~0 )
197 {
198 opcode = instr [pc];
199 pc++;
200 instr += pc;
201 }
202 else
203 {
204 instr += CODE_OFFSET( pc );
205 opcode = *instr++;
206 pc++;
207 }
208
209 // TODO: each reference lists slightly different timing values, ugh
210 static byte const clock_table [256] =
211 {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
212 1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,4,// 0
213 2,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,4,// 1
214 7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,4,// 2
215 2,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,4,// 3
216 7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,4,// 4
217 2,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,4,// 5
218 7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,4,// 6
219 2,7,7,17,4,4,6,7,2,5,4,2,7,5,7,4,// 7
220 4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,4,// 8
221 2,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,4,// 9
222 2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,4,// A
223 2,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,4,// B
224 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,4,// C
225 2,7,7,17,2,4,6,7,2,5,3,2,2,5,7,4,// D
226 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,4,// E
227 2,7,7,17,2,4,6,7,2,5,4,2,2,5,7,4 // F
228 }; // 0x00 was 8
229
230 // Update time
231 if ( s_time >= 0 )
232 goto out_of_time;
233
234 #ifdef HES_CPU_LOG_H
235 log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
236 instr [3], instr [4], instr [5], a, x, y );
237 //log_opcode( opcode );
238 #endif
239
240 s_time += clock_table [opcode];
241
242 int data;
243 data = *instr;
244
245 switch ( opcode )
246 {
247// Macros
248
249#define GET_MSB() (instr [1])
250#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB());
251#define GET_ADDR() GET_LE16( instr )
252
253// TODO: is the penalty really always added? the original 6502 was much better
254//#define PAGE_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
255#define PAGE_PENALTY( lsb )
256
257// Branch
258
259// TODO: more efficient way to handle negative branch that wraps PC around
260#define BRANCH_( cond, adj )\
261{\
262 pc++;\
263 if ( !(cond) ) goto loop;\
264 pc = (uint16_t) (pc + SBYTE( data ));\
265 s_time += adj;\
266 goto loop;\
267}
268
269#define BRANCH( cond ) BRANCH_( cond, 2 )
270
271 case 0xF0: // BEQ
272 BRANCH( !BYTE( nz ) );
273
274 case 0xD0: // BNE
275 BRANCH( BYTE( nz ) );
276
277 case 0x10: // BPL
278 BRANCH( !IS_NEG );
279
280 case 0x90: // BCC
281 BRANCH( !(c & 0x100) )
282
283 case 0x30: // BMI
284 BRANCH( IS_NEG )
285
286 case 0x50: // BVC
287 BRANCH( !(flags & v40) )
288
289 case 0x70: // BVS
290 BRANCH( flags & v40 )
291
292 case 0xB0: // BCS
293 BRANCH( c & 0x100 )
294
295 case 0x80: // BRA
296 branch_taken:
297 BRANCH_( true, 0 );
298
299 case 0xFF:
300 #ifdef IDLE_ADDR
301 if ( pc == IDLE_ADDR + 1 )
302 goto idle_done;
303 #endif
304
305 pc = (uint16_t) pc;
306
307 case 0x0F: // BBRn
308 case 0x1F:
309 case 0x2F:
310 case 0x3F:
311 case 0x4F:
312 case 0x5F:
313 case 0x6F:
314 case 0x7F:
315 case 0x8F: // BBSn
316 case 0x9F:
317 case 0xAF:
318 case 0xBF:
319 case 0xCF:
320 case 0xDF:
321 case 0xEF: {
322 // Make two copies of bits, one negated
323 int t = 0x101 * READ_LOW( data );
324 t ^= 0xFF;
325 pc++;
326 data = GET_MSB();
327 BRANCH( t & (1 << (opcode >> 4)) )
328 }
329
330 case 0x4C: // JMP abs
331 pc = GET_ADDR();
332 goto loop;
333
334 case 0x7C: // JMP (ind+X)
335 data += x;
336 case 0x6C:{// JMP (ind)
337 data += 0x100 * GET_MSB();
338 pc = GET_LE16( &READ_CODE( data ) );
339 goto loop;
340 }
341
342// Subroutine
343
344 case 0x44: // BSR
345 WRITE_STACK( SP( -1 ), pc >> 8 );
346 sp = SP( -2 );
347 WRITE_STACK( sp, pc );
348 goto branch_taken;
349
350 case 0x20: { // JSR
351 int temp = pc + 1;
352 pc = GET_ADDR();
353 WRITE_STACK( SP( -1 ), temp >> 8 );
354 sp = SP( -2 );
355 WRITE_STACK( sp, temp );
356 goto loop;
357 }
358
359 case 0x60: // RTS
360 pc = 1 + READ_STACK( sp );
361 pc += 0x100 * READ_STACK( SP( 1 ) );
362 sp = SP( 2 );
363 goto loop;
364
365 case 0x00: // BRK
366 goto handle_brk;
367
368// Common
369
370 case 0xBD:{// LDA abs,X
371 PAGE_PENALTY( data + x );
372 int addr = GET_ADDR() + x;
373 pc += 2;
374 READ_FAST( addr, nz );
375 a = nz;
376 goto loop;
377 }
378
379 case 0x9D:{// STA abs,X
380 int addr = GET_ADDR() + x;
381 pc += 2;
382 WRITE_FAST( addr, a );
383 goto loop;
384 }
385
386 case 0x95: // STA zp,x
387 data = BYTE( data + x );
388 case 0x85: // STA zp
389 pc++;
390 WRITE_LOW( data, a );
391 goto loop;
392
393 case 0xAE:{// LDX abs
394 int addr = GET_ADDR();
395 pc += 2;
396 READ_FAST( addr, nz );
397 x = nz;
398 goto loop;
399 }
400
401 case 0xA5: // LDA zp
402 a = nz = READ_LOW( data );
403 pc++;
404 goto loop;
405
406// Load/store
407
408 {
409 int addr;
410 case 0x91: // STA (ind),Y
411 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
412 addr += READ_LOW( data ) + y;
413 pc++;
414 goto sta_ptr;
415
416 case 0x81: // STA (ind,X)
417 data = BYTE( data + x );
418 case 0x92: // STA (ind)
419 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
420 addr += READ_LOW( data );
421 pc++;
422 goto sta_ptr;
423
424 case 0x99: // STA abs,Y
425 data += y;
426 case 0x8D: // STA abs
427 addr = data + 0x100 * GET_MSB();
428 pc += 2;
429 sta_ptr:
430 WRITE_FAST( addr, a );
431 goto loop;
432 }
433
434 {
435 int addr;
436 case 0xA1: // LDA (ind,X)
437 data = BYTE( data + x );
438 case 0xB2: // LDA (ind)
439 addr = 0x100 * READ_LOW( BYTE( data + 1 ) );
440 addr += READ_LOW( data );
441 pc++;
442 goto a_nz_read_addr;
443
444 case 0xB1:// LDA (ind),Y
445 addr = READ_LOW( data ) + y;
446 PAGE_PENALTY( addr );
447 addr += 0x100 * READ_LOW( BYTE( data + 1 ) );
448 pc++;
449 goto a_nz_read_addr;
450
451 case 0xB9: // LDA abs,Y
452 data += y;
453 PAGE_PENALTY( data );
454 case 0xAD: // LDA abs
455 addr = data + 0x100 * GET_MSB();
456 pc += 2;
457 a_nz_read_addr:
458 READ_FAST( addr, nz );
459 a = nz;
460 goto loop;
461 }
462
463 case 0xBE:{// LDX abs,y
464 PAGE_PENALTY( data + y );
465 int addr = GET_ADDR() + y;
466 pc += 2;
467 FLUSH_TIME();
468 x = nz = READ_MEM( addr );
469 CACHE_TIME();
470 goto loop;
471 }
472
473 case 0xB5: // LDA zp,x
474 a = nz = READ_LOW( BYTE( data + x ) );
475 pc++;
476 goto loop;
477
478 case 0xA9: // LDA #imm
479 pc++;
480 a = data;
481 nz = data;
482 goto loop;
483
484// Bit operations
485
486 case 0x3C: // BIT abs,x
487 data += x;
488 case 0x2C:{// BIT abs
489 int addr;
490 ADD_PAGE( addr );
491 FLUSH_TIME();
492 nz = READ_MEM( addr );
493 CACHE_TIME();
494 goto bit_common;
495 }
496 case 0x34: // BIT zp,x
497 data = BYTE( data + x );
498 case 0x24: // BIT zp
499 data = READ_LOW( data );
500 case 0x89: // BIT imm
501 nz = data;
502 bit_common:
503 pc++;
504 flags = (flags & ~v40) + (nz & v40);
505 if ( nz & a )
506 goto loop; // Z should be clear, and nz must be non-zero if nz & a is
507 nz <<= 8; // set Z flag without affecting N flag
508 goto loop;
509
510 {
511 int addr;
512
513 case 0xB3: // TST abs,x
514 addr = GET_MSB() + x;
515 goto tst_abs;
516
517 case 0x93: // TST abs
518 addr = GET_MSB();
519 tst_abs:
520 addr += 0x100 * instr [2];
521 pc++;
522 FLUSH_TIME();
523 nz = READ_MEM( addr );
524 CACHE_TIME();
525 goto tst_common;
526 }
527
528 case 0xA3: // TST zp,x
529 nz = READ_LOW( BYTE( GET_MSB() + x ) );
530 goto tst_common;
531
532 case 0x83: // TST zp
533 nz = READ_LOW( GET_MSB() );
534 tst_common:
535 pc += 2;
536 flags = (flags & ~v40) + (nz & v40);
537 if ( nz & data )
538 goto loop; // Z should be clear, and nz must be non-zero if nz & data is
539 nz <<= 8; // set Z flag without affecting N flag
540 goto loop;
541
542 {
543 int addr;
544 case 0x0C: // TSB abs
545 case 0x1C: // TRB abs
546 addr = GET_ADDR();
547 pc++;
548 goto txb_addr;
549
550 // TODO: everyone lists different behaviors for the flags flags, ugh
551 case 0x04: // TSB zp
552 case 0x14: // TRB zp
553 addr = data + ram_addr;
554 txb_addr:
555 FLUSH_TIME();
556 nz = a | READ_MEM( addr );
557 if ( opcode & 0x10 )
558 nz ^= a; // bits from a will already be set, so this clears them
559 flags = (flags & ~v40) + (nz & v40);
560 pc++;
561 WRITE_MEM( addr, nz );
562 CACHE_TIME();
563 goto loop;
564 }
565
566 case 0x07: // RMBn
567 case 0x17:
568 case 0x27:
569 case 0x37:
570 case 0x47:
571 case 0x57:
572 case 0x67:
573 case 0x77:
574 pc++;
575 READ_LOW( data ) &= ~(1 << (opcode >> 4));
576 goto loop;
577
578 case 0x87: // SMBn
579 case 0x97:
580 case 0xA7:
581 case 0xB7:
582 case 0xC7:
583 case 0xD7:
584 case 0xE7:
585 case 0xF7:
586 pc++;
587 READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
588 goto loop;
589
590// Load/store
591
592 case 0x9E: // STZ abs,x
593 data += x;
594 case 0x9C: // STZ abs
595 ADD_PAGE( data );
596 pc++;
597 FLUSH_TIME();
598 WRITE_MEM( data, 0 );
599 CACHE_TIME();
600 goto loop;
601
602 case 0x74: // STZ zp,x
603 data = BYTE( data + x );
604 case 0x64: // STZ zp
605 pc++;
606 WRITE_LOW( data, 0 );
607 goto loop;
608
609 case 0x94: // STY zp,x
610 data = BYTE( data + x );
611 case 0x84: // STY zp
612 pc++;
613 WRITE_LOW( data, y );
614 goto loop;
615
616 case 0x96: // STX zp,y
617 data = BYTE( data + y );
618 case 0x86: // STX zp
619 pc++;
620 WRITE_LOW( data, x );
621 goto loop;
622
623 case 0xB6: // LDX zp,y
624 data = BYTE( data + y );
625 case 0xA6: // LDX zp
626 data = READ_LOW( data );
627 case 0xA2: // LDX #imm
628 pc++;
629 x = data;
630 nz = data;
631 goto loop;
632
633 case 0xB4: // LDY zp,x
634 data = BYTE( data + x );
635 case 0xA4: // LDY zp
636 data = READ_LOW( data );
637 case 0xA0: // LDY #imm
638 pc++;
639 y = data;
640 nz = data;
641 goto loop;
642
643 case 0xBC: // LDY abs,X
644 data += x;
645 PAGE_PENALTY( data );
646 case 0xAC:{// LDY abs
647 int addr = data + 0x100 * GET_MSB();
648 pc += 2;
649 FLUSH_TIME();
650 y = nz = READ_MEM( addr );
651 CACHE_TIME();
652 goto loop;
653 }
654
655 {
656 int temp;
657 case 0x8C: // STY abs
658 temp = y;
659 if ( 0 )
660 case 0x8E: // STX abs
661 temp = x;
662 int addr = GET_ADDR();
663 pc += 2;
664 FLUSH_TIME();
665 WRITE_MEM( addr, temp );
666 CACHE_TIME();
667 goto loop;
668 }
669
670// Compare
671
672 case 0xEC:{// CPX abs
673 int addr = GET_ADDR();
674 pc++;
675 FLUSH_TIME();
676 data = READ_MEM( addr );
677 CACHE_TIME();
678 goto cpx_data;
679 }
680
681 case 0xE4: // CPX zp
682 data = READ_LOW( data );
683 case 0xE0: // CPX #imm
684 cpx_data:
685 nz = x - data;
686 pc++;
687 c = ~nz;
688 nz = BYTE( nz );
689 goto loop;
690
691 case 0xCC:{// CPY abs
692 int addr = GET_ADDR();
693 pc++;
694 FLUSH_TIME();
695 data = READ_MEM( addr );
696 CACHE_TIME();
697 goto cpy_data;
698 }
699
700 case 0xC4: // CPY zp
701 data = READ_LOW( data );
702 case 0xC0: // CPY #imm
703 cpy_data:
704 nz = y - data;
705 pc++;
706 c = ~nz;
707 nz = BYTE( nz );
708 goto loop;
709
710// Logical
711
712#define ARITH_ADDR_MODES( op )\
713 case op - 0x04: /* (ind,x) */\
714 data = BYTE( data + x );\
715 case op + 0x0D: /* (ind) */\
716 data = 0x100 * READ_LOW( BYTE( data + 1 ) ) + READ_LOW( data );\
717 goto ptr##op;\
718 case op + 0x0C:{/* (ind),y */\
719 int temp = READ_LOW( data ) + y;\
720 PAGE_PENALTY( temp );\
721 data = temp + 0x100 * READ_LOW( BYTE( data + 1 ) );\
722 goto ptr##op;\
723 }\
724 case op + 0x10: /* zp,X */\
725 data = BYTE( data + x );\
726 case op + 0x00: /* zp */\
727 data = READ_LOW( data );\
728 goto imm##op;\
729 case op + 0x14: /* abs,Y */\
730 data += y;\
731 goto ind##op;\
732 case op + 0x18: /* abs,X */\
733 data += x;\
734 ind##op:\
735 PAGE_PENALTY( data );\
736 case op + 0x08: /* abs */\
737 ADD_PAGE( data );\
738 ptr##op:\
739 FLUSH_TIME();\
740 data = READ_MEM( data );\
741 CACHE_TIME();\
742 case op + 0x04: /* imm */\
743 imm##op:
744
745 ARITH_ADDR_MODES( 0xC5 ) // CMP
746 nz = a - data;
747 pc++;
748 c = ~nz;
749 nz = BYTE( nz );
750 goto loop;
751
752 ARITH_ADDR_MODES( 0x25 ) // AND
753 nz = (a &= data);
754 pc++;
755 goto loop;
756
757 ARITH_ADDR_MODES( 0x45 ) // EOR
758 nz = (a ^= data);
759 pc++;
760 goto loop;
761
762 ARITH_ADDR_MODES( 0x05 ) // ORA
763 nz = (a |= data);
764 pc++;
765 goto loop;
766
767// Add/subtract
768
769 ARITH_ADDR_MODES( 0xE5 ) // SBC
770 data ^= 0xFF;
771 goto adc_imm;
772
773 ARITH_ADDR_MODES( 0x65 ) // ADC
774 adc_imm: {
775 /* if ( flags & d08 )
776 dprintf( "Decimal mode not supported\n" ); */
777 int carry = c >> 8 & 1;
778 int ov = (a ^ 0x80) + carry + SBYTE( data );
779 flags = (flags & ~v40) + (ov >> 2 & v40);
780 c = nz = a + data + carry;
781 pc++;
782 a = BYTE( nz );
783 goto loop;
784 }
785
786// Shift/rotate
787
788 case 0x4A: // LSR A
789 c = 0;
790 case 0x6A: // ROR A
791 nz = c >> 1 & 0x80;
792 c = a << 8;
793 nz += a >> 1;
794 a = nz;
795 goto loop;
796
797 case 0x0A: // ASL A
798 nz = a << 1;
799 c = nz;
800 a = BYTE( nz );
801 goto loop;
802
803 case 0x2A: { // ROL A
804 nz = a << 1;
805 int temp = c >> 8 & 1;
806 c = nz;
807 nz += temp;
808 a = BYTE( nz );
809 goto loop;
810 }
811
812 case 0x5E: // LSR abs,X
813 data += x;
814 case 0x4E: // LSR abs
815 c = 0;
816 case 0x6E: // ROR abs
817 ror_abs: {
818 ADD_PAGE( data );
819 FLUSH_TIME();
820 int temp = READ_MEM( data );
821 nz = (c >> 1 & 0x80) + (temp >> 1);
822 c = temp << 8;
823 goto rotate_common;
824 }
825
826 case 0x3E: // ROL abs,X
827 data += x;
828 goto rol_abs;
829
830 case 0x1E: // ASL abs,X
831 data += x;
832 case 0x0E: // ASL abs
833 c = 0;
834 case 0x2E: // ROL abs
835 rol_abs:
836 ADD_PAGE( data );
837 nz = c >> 8 & 1;
838 FLUSH_TIME();
839 nz += (c = READ_MEM( data ) << 1);
840 rotate_common:
841 pc++;
842 WRITE_MEM( data, BYTE( nz ) );
843 CACHE_TIME();
844 goto loop;
845
846 case 0x7E: // ROR abs,X
847 data += x;
848 goto ror_abs;
849
850 case 0x76: // ROR zp,x
851 data = BYTE( data + x );
852 goto ror_zp;
853
854 case 0x56: // LSR zp,x
855 data = BYTE( data + x );
856 case 0x46: // LSR zp
857 c = 0;
858 case 0x66: // ROR zp
859 ror_zp: {
860 int temp = READ_LOW( data );
861 nz = (c >> 1 & 0x80) + (temp >> 1);
862 c = temp << 8;
863 goto write_nz_zp;
864 }
865
866 case 0x36: // ROL zp,x
867 data = BYTE( data + x );
868 goto rol_zp;
869
870 case 0x16: // ASL zp,x
871 data = BYTE( data + x );
872 case 0x06: // ASL zp
873 c = 0;
874 case 0x26: // ROL zp
875 rol_zp:
876 nz = c >> 8 & 1;
877 nz += (c = READ_LOW( data ) << 1);
878 goto write_nz_zp;
879
880// Increment/decrement
881
882#define INC_DEC( reg, n ) reg = BYTE( nz = reg + n ); goto loop;
883
884 case 0x1A: // INA
885 INC_DEC( a, +1 )
886
887 case 0xE8: // INX
888 INC_DEC( x, +1 )
889
890 case 0xC8: // INY
891 INC_DEC( y, +1 )
892
893 case 0x3A: // DEA
894 INC_DEC( a, -1 )
895
896 case 0xCA: // DEX
897 INC_DEC( x, -1 )
898
899 case 0x88: // DEY
900 INC_DEC( y, -1 )
901
902 case 0xF6: // INC zp,x
903 data = BYTE( data + x );
904 case 0xE6: // INC zp
905 nz = 1;
906 goto add_nz_zp;
907
908 case 0xD6: // DEC zp,x
909 data = BYTE( data + x );
910 case 0xC6: // DEC zp
911 nz = -1;
912 add_nz_zp:
913 nz += READ_LOW( data );
914 write_nz_zp:
915 pc++;
916 WRITE_LOW( data, nz );
917 goto loop;
918
919 case 0xFE: // INC abs,x
920 data = x + GET_ADDR();
921 goto inc_ptr;
922
923 case 0xEE: // INC abs
924 data = GET_ADDR();
925 inc_ptr:
926 nz = 1;
927 goto inc_common;
928
929 case 0xDE: // DEC abs,x
930 data = x + GET_ADDR();
931 goto dec_ptr;
932
933 case 0xCE: // DEC abs
934 data = GET_ADDR();
935 dec_ptr:
936 nz = -1;
937 inc_common:
938 FLUSH_TIME();
939 pc += 2;
940 nz += READ_MEM( data );
941 WRITE_MEM( data, BYTE( nz ) );
942 CACHE_TIME();
943 goto loop;
944
945// Transfer
946
947 case 0xA8: // TAY
948 y = nz = a;
949 goto loop;
950
951 case 0x98: // TYA
952 a = nz = y;
953 goto loop;
954
955 case 0xAA: // TAX
956 x = nz = a;
957 goto loop;
958
959 case 0x8A: // TXA
960 a = nz = x;
961 goto loop;
962
963 case 0x9A: // TXS
964 SET_SP( x ); // verified (no flag change)
965 goto loop;
966
967 case 0xBA: // TSX
968 x = nz = GET_SP();
969 goto loop;
970
971 #define SWAP_REGS( r1, r2 ) {\
972 int t = r1;\
973 r1 = r2;\
974 r2 = t;\
975 goto loop;\
976 }
977
978 case 0x02: // SXY
979 SWAP_REGS( x, y );
980
981 case 0x22: // SAX
982 SWAP_REGS( a, x );
983
984 case 0x42: // SAY
985 SWAP_REGS( a, y );
986
987 case 0x62: // CLA
988 a = 0;
989 goto loop;
990
991 case 0x82: // CLX
992 x = 0;
993 goto loop;
994
995 case 0xC2: // CLY
996 y = 0;
997 goto loop;
998
999// Stack
1000
1001 case 0x48: // PHA
1002 sp = SP( -1 );
1003 WRITE_STACK( sp, a );
1004 goto loop;
1005
1006 case 0x68: // PLA
1007 a = nz = READ_STACK( sp );
1008 sp = SP( 1 );
1009 goto loop;
1010
1011 case 0xDA: // PHX
1012 sp = SP( -1 );
1013 WRITE_STACK( sp, x );
1014 goto loop;
1015
1016 case 0x5A: // PHY
1017 sp = SP( -1 );
1018 WRITE_STACK( sp, y );
1019 goto loop;
1020
1021 case 0x40:{// RTI
1022 pc = READ_STACK( SP( 1 ) );
1023 pc += READ_STACK( SP( 2 ) ) * 0x100;
1024 int temp = READ_STACK( sp );
1025 sp = SP( 3 );
1026 data = flags;
1027 SET_FLAGS( temp );
1028 cpu->r.flags = flags; // update externally-visible I flag
1029 if ( (data ^ flags) & i04 )
1030 {
1031 hes_time_t new_time = cpu->end_time_;
1032 if ( !(flags & i04) && new_time > cpu->irq_time_ )
1033 new_time = cpu->irq_time_;
1034 int delta = s.base - new_time;
1035 s.base = new_time;
1036 s_time += delta;
1037 }
1038 goto loop;
1039 }
1040
1041 case 0xFA: // PLX
1042 x = nz = READ_STACK( sp );
1043 sp = SP( 1 );
1044 goto loop;
1045
1046 case 0x7A: // PLY
1047 y = nz = READ_STACK( sp );
1048 sp = SP( 1 );
1049 goto loop;
1050
1051 case 0x28:{// PLP
1052 int temp = READ_STACK( sp );
1053 sp = SP( 1 );
1054 int changed = flags ^ temp;
1055 SET_FLAGS( temp );
1056 if ( !(changed & i04) )
1057 goto loop; // I flag didn't change
1058 if ( flags & i04 )
1059 goto handle_sei;
1060 goto handle_cli;
1061 }
1062
1063 case 0x08:{// PHP
1064 int temp;
1065 GET_FLAGS( temp );
1066 sp = SP( -1 );
1067 WRITE_STACK( sp, temp | b10 );
1068 goto loop;
1069 }
1070
1071// Flags
1072
1073 case 0x38: // SEC
1074 c = 0x100;
1075 goto loop;
1076
1077 case 0x18: // CLC
1078 c = 0;
1079 goto loop;
1080
1081 case 0xB8: // CLV
1082 flags &= ~v40;
1083 goto loop;
1084
1085 case 0xD8: // CLD
1086 flags &= ~d08;
1087 goto loop;
1088
1089 case 0xF8: // SED
1090 flags |= d08;
1091 goto loop;
1092
1093 case 0x58: // CLI
1094 if ( !(flags & i04) )
1095 goto loop;
1096 flags &= ~i04;
1097 handle_cli: {
1098 //dprintf( "CLI at %d\n", TIME );
1099 cpu->r.flags = flags; // update externally-visible I flag
1100 int delta = s.base - cpu->irq_time_;
1101 if ( delta <= 0 )
1102 {
1103 if ( TIME() < cpu->irq_time_ )
1104 goto loop;
1105 goto delayed_cli;
1106 }
1107 s.base = cpu->irq_time_;
1108 s_time += delta;
1109 if ( s_time < 0 )
1110 goto loop;
1111
1112 if ( delta >= s_time + 1 )
1113 {
1114 // delayed irq until after next instruction
1115 s.base += s_time + 1;
1116 s_time = -1;
1117 cpu->irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
1118 goto loop;
1119 }
1120
1121 // TODO: implement
1122 delayed_cli:
1123 dprintf( "Delayed CLI not supported\n" );
1124 goto loop;
1125 }
1126
1127 case 0x78: // SEI
1128 if ( flags & i04 )
1129 goto loop;
1130 flags |= i04;
1131 handle_sei: {
1132 cpu->r.flags = flags; // update externally-visible I flag
1133 int delta = s.base - cpu->end_time_;
1134 s.base = cpu->end_time_;
1135 s_time += delta;
1136 if ( s_time < 0 )
1137 goto loop;
1138
1139 dprintf( "Delayed SEI not supported\n" );
1140 goto loop;
1141 }
1142
1143// Special
1144
1145 case 0x53:{// TAM
1146 int bits = data; // avoid using data across function call
1147 pc++;
1148 for ( int i = 0; i < 8; i++ )
1149 if ( bits & (1 << i) )
1150 SET_MMR( i, a );
1151 goto loop;
1152 }
1153
1154 case 0x43:{// TMA
1155 pc++;
1156 byte const* in = cpu->mmr;
1157 do
1158 {
1159 if ( data & 1 )
1160 a = *in;
1161 in++;
1162 }
1163 while ( (data >>= 1) != 0 );
1164 goto loop;
1165 }
1166
1167 case 0x03: // ST0
1168 case 0x13: // ST1
1169 case 0x23:{// ST2
1170 int addr = opcode >> 4;
1171 if ( addr )
1172 addr++;
1173 pc++;
1174 FLUSH_TIME();
1175 WRITE_VDP( addr, data );
1176 CACHE_TIME();
1177 goto loop;
1178 }
1179
1180 case 0xEA: // NOP
1181 goto loop;
1182
1183 case 0x54: // CSL
1184 dprintf( "CSL not supported\n" );
1185 illegal_encountered = true;
1186 goto loop;
1187
1188 case 0xD4: // CSH
1189 goto loop;
1190
1191 case 0xF4: { // SET
1192 //int operand = GET_MSB();
1193 dprintf( "SET not handled\n" );
1194 //switch ( data )
1195 //{
1196 //}
1197 illegal_encountered = true;
1198 goto loop;
1199 }
1200
1201// Block transfer
1202
1203 {
1204 int in_alt;
1205 int in_inc;
1206 int out_alt;
1207 int out_inc;
1208
1209 case 0xE3: // TIA
1210 in_alt = 0;
1211 goto bxfer_alt;
1212
1213 case 0xF3: // TAI
1214 in_alt = 1;
1215 bxfer_alt:
1216 in_inc = in_alt ^ 1;
1217 out_alt = in_inc;
1218 out_inc = in_alt;
1219 goto bxfer;
1220
1221 case 0xD3: // TIN
1222 in_inc = 1;
1223 out_inc = 0;
1224 goto bxfer_no_alt;
1225
1226 case 0xC3: // TDD
1227 in_inc = -1;
1228 out_inc = -1;
1229 goto bxfer_no_alt;
1230
1231 case 0x73: // TII
1232 in_inc = 1;
1233 out_inc = 1;
1234 bxfer_no_alt:
1235 in_alt = 0;
1236 out_alt = 0;
1237 bxfer:
1238 {
1239 int in = GET_LE16( instr + 0 );
1240 int out = GET_LE16( instr + 2 );
1241 int count = GET_LE16( instr + 4 );
1242 if ( !count )
1243 count = 0x10000;
1244 pc += 6;
1245 WRITE_STACK( SP( -1 ), y );
1246 WRITE_STACK( SP( -2 ), a );
1247 WRITE_STACK( SP( -3 ), x );
1248 FLUSH_TIME();
1249 do
1250 {
1251 // TODO: reads from $0800-$1400 in I/O page should do I/O
1252 int t = READ_MEM( in );
1253 in = WORD( in + in_inc );
1254 s.time += 6;
1255 if ( in_alt )
1256 in_inc = -in_inc;
1257 WRITE_MEM( out, t );
1258 out = WORD( out + out_inc );
1259 if ( out_alt )
1260 out_inc = -out_inc;
1261 }
1262 while ( --count );
1263 CACHE_TIME();
1264 goto loop;
1265 }
1266 }
1267
1268// Illegal
1269
1270 default:
1271 check( (unsigned) opcode <= 0xFF );
1272 dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
1273 illegal_encountered = true;
1274 goto loop;
1275 }
1276 assert( false ); // catch missing 'goto loop' or accidental 'break'
1277
1278 int result_;
1279handle_brk:
1280 pc++;
1281 result_ = 6;
1282
1283interrupt:
1284 {
1285 s_time += 7;
1286
1287 // Save PC and read vector
1288 WRITE_STACK( SP( -1 ), pc >> 8 );
1289 WRITE_STACK( SP( -2 ), pc );
1290 pc = GET_LE16( &READ_CODE( 0xFFF0 ) + result_ );
1291
1292 // Save flags
1293 int temp;
1294 GET_FLAGS( temp );
1295 if ( result_ == 6 )
1296 temp |= b10; // BRK sets B bit
1297 sp = SP( -3 );
1298 WRITE_STACK( sp, temp );
1299
1300 // Update I flag in externally-visible flags
1301 flags &= ~d08;
1302 cpu->r.flags = (flags |= i04);
1303
1304 // Update time
1305 int delta = s.base - cpu->end_time_;
1306 if ( delta >= 0 )
1307 goto loop;
1308 s_time += delta;
1309 s.base = cpu->end_time_;
1310 goto loop;
1311 }
1312
1313idle_done:
1314 s_time = 0;
1315
1316out_of_time:
1317 pc--;
1318
1319 // Optional action that triggers interrupt or changes irq/end time
1320 #ifdef CPU_DONE
1321 {
1322 CPU_DONE( result_ );
1323 if ( result_ >= 0 )
1324 goto interrupt;
1325 if ( s_time < 0 )
1326 goto loop;
1327 }
1328 #endif
1329
1330 // Flush cached state
1331 cpu->r.pc = pc;
1332 cpu->r.sp = GET_SP();
1333 cpu->r.a = a;
1334 cpu->r.x = x;
1335 cpu->r.y = y;
1336
1337 int temp;
1338 GET_FLAGS( temp );
1339 cpu->r.flags = temp;
1340
1341 cpu->cpu_state_.base = s.base;
1342 cpu->cpu_state_.time = s_time;
1343 cpu->cpu_state = &cpu->cpu_state_;
1344}
diff --git a/lib/rbcodec/codecs/libgme/hes_emu.c b/lib/rbcodec/codecs/libgme/hes_emu.c
new file mode 100644
index 0000000000..d6bafea334
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_emu.c
@@ -0,0 +1,644 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2
3#include "hes_emu.h"
4
5#include "blargg_endian.h"
6#include "blargg_source.h"
7
8/* Copyright (C) 2006 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19int const timer_mask = 0x04;
20int const vdp_mask = 0x02;
21int const i_flag_mask = 0x04;
22int const unmapped = 0xFF;
23
24int const period_60hz = 262 * 455; // scanlines * clocks per scanline
25
26const char gme_wrong_file_type [] = "Wrong file type for this emulator";
27
28static void clear_track_vars( struct Hes_Emu* this )
29{
30 this->current_track_ = -1;
31 track_stop( &this->track_filter );
32}
33
34void Hes_init( struct Hes_Emu* this )
35{
36 this->sample_rate_ = 0;
37 this->mute_mask_ = 0;
38 this->tempo_ = (int)(FP_ONE_TEMPO);
39
40 // defaults
41 this->tfilter = *track_get_setup( &this->track_filter );
42 this->tfilter.max_initial = 2;
43 this->tfilter.lookahead = 6;
44 this->track_filter.silence_ignored_ = false;
45
46 this->timer.raw_load = 0;
47 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.11) );
48
49 Rom_init( &this->rom, 0x2000 );
50
51 Apu_init( &this->apu );
52 Adpcm_init( &this->adpcm );
53 Cpu_init( &this->cpu );
54
55 /* Set default track count */
56 this->track_count = 255;
57
58 // clears fields
59 this->voice_count_ = 0;
60 this->voice_types_ = 0;
61 clear_track_vars( this );
62}
63
64static blargg_err_t check_hes_header( void const* header )
65{
66 if ( memcmp( header, "HESM", 4 ) )
67 return gme_wrong_file_type;
68 return 0;
69}
70
71// Setup
72
73blargg_err_t Hes_load_mem( struct Hes_Emu* this, void* data, long size )
74{
75 // Unload
76 this->voice_count_ = 0;
77 this->track_count = 255;
78 this->m3u.size = 0;
79 clear_track_vars( this );
80
81 assert( offsetof (struct header_t,unused [4]) == header_size );
82 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, unmapped ) );
83
84 RETURN_ERR( check_hes_header( this->header.tag ) );
85
86 /* if ( header_.vers != 0 )
87 warning( "Unknown file version" );
88
89 if ( memcmp( header_.data_tag, "DATA", 4 ) )
90 warning( "Data header missing" );
91
92 if ( memcmp( header_.unused, "\0\0\0\0", 4 ) )
93 warning( "Unknown header data" ); */
94
95 // File spec supports multiple blocks, but I haven't found any, and
96 // many files have bad sizes in the only block, so it's simpler to
97 // just try to load the damn data as best as possible.
98
99 int addr = get_le32( this->header.addr );
100 /* int rom_size = get_le32( this->header.size ); */
101 int const rom_max = 0x100000;
102 if ( (unsigned) addr >= (unsigned) rom_max )
103 {
104 /* warning( "Invalid address" ); */
105 addr &= rom_max - 1;
106 }
107 /* if ( (unsigned) (addr + size) > (unsigned) rom_max )
108 warning( "Invalid size" );
109
110 if ( rom_size != rom.file_size() )
111 {
112 if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) )
113 warning( "Multiple DATA not supported" );
114 else if ( size < rom.file_size() )
115 warning( "Extra file data" );
116 else
117 warning( "Missing file data" );
118 } */
119
120 Rom_set_addr( &this->rom, addr );
121
122 this->voice_count_ = osc_count + adpcm_osc_count;
123 static int const types [osc_count + adpcm_osc_count] = {
124 wave_type+0, wave_type+1, wave_type+2, wave_type+3, mixed_type+0, mixed_type+1, mixed_type+2
125 };
126 this->voice_types_ = types;
127
128 Apu_volume( &this->apu, this->gain_ );
129 Adpcm_volume( &this->adpcm, this->gain_ );
130
131 // Setup buffer
132 this->clock_rate_ = 7159091;
133 Buffer_clock_rate( &this->stereo_buf, 7159091 );
134 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count_, this->voice_types_ ) );
135 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
136
137 Sound_set_tempo( this, this->tempo_ );
138 Sound_mute_voices( this, this->mute_mask_ );
139
140 return 0;
141}
142
143// Emulation
144
145static void recalc_timer_load( struct Hes_Emu* this )
146{
147 this->timer.load = this->timer.raw_load * this->timer_base + 1;
148}
149
150// Hardware
151
152void run_until( struct Hes_Emu* this, hes_time_t present )
153{
154 while ( this->vdp.next_vbl < present )
155 this->vdp.next_vbl += this->play_period;
156
157 hes_time_t elapsed = present - this->timer.last_time;
158 if ( elapsed > 0 )
159 {
160 if ( this->timer.enabled )
161 {
162 this->timer.count -= elapsed;
163 if ( this->timer.count <= 0 )
164 this->timer.count += this->timer.load;
165 }
166 this->timer.last_time = present;
167 }
168}
169
170void write_vdp( struct Hes_Emu* this, int addr, int data )
171{
172 switch ( addr )
173 {
174 case 0:
175 this->vdp.latch = data & 0x1F;
176 break;
177
178 case 2:
179 if ( this->vdp.latch == 5 )
180 {
181 /* if ( data & 0x04 )
182 warning( "Scanline interrupt unsupported" ); */
183 run_until( this, Cpu_time( &this->cpu ) );
184 this->vdp.control = data;
185 irq_changed( this );
186 }
187 /* else
188 {
189 dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
190 } */
191 break;
192
193 case 3:
194 /* dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data ); */
195 break;
196 }
197}
198
199void write_mem_( struct Hes_Emu* this, hes_addr_t addr, int data )
200{
201 hes_time_t time = Cpu_time( &this->cpu );
202 if ( (unsigned) (addr - apu_io_addr) < apu_io_size )
203 {
204 // Avoid going way past end when a long block xfer is writing to I/O space.
205 // Not a problem for other registers below because they don't write to
206 // Blip_Buffer.
207 hes_time_t t = min( time, Cpu_end_time( &this->cpu ) + 8 );
208 Apu_write_data( &this->apu, t, addr, data );
209 return;
210 }
211 if ( (unsigned) (addr - adpcm_io_addr) < adpcm_io_size )
212 {
213 hes_time_t t = min( time, Cpu_end_time( &this->cpu ) + 6 );
214 Adpcm_write_data( &this->adpcm, t, addr, data );
215 return;
216 }
217
218 switch ( addr )
219 {
220 case 0x0000:
221 case 0x0002:
222 case 0x0003:
223 write_vdp( this, addr, data );
224 return;
225
226 case 0x0C00: {
227 run_until( this, time );
228 this->timer.raw_load = (data & 0x7F) + 1;
229 recalc_timer_load( this );
230 this->timer.count = this->timer.load;
231 break;
232 }
233
234 case 0x0C01:
235 data &= 1;
236 if ( this->timer.enabled == data )
237 return;
238 run_until( this, time );
239 this->timer.enabled = data;
240 if ( data )
241 this->timer.count = this->timer.load;
242 break;
243
244 case 0x1402:
245 run_until( this, time );
246 this->irq.disables = data;
247 /* if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
248 dprintf( "Int mask: $%02X\n", data ); */
249 break;
250
251 case 0x1403:
252 run_until( this, time );
253 if ( this->timer.enabled )
254 this->timer.count = this->timer.load;
255 this->timer.fired = false;
256 break;
257
258#ifndef NDEBUG
259 case 0x1000: // I/O port
260 case 0x0402: // palette
261 case 0x0403:
262 case 0x0404:
263 case 0x0405:
264 return;
265
266 default:
267 /* dprintf( "unmapped write $%04X <- $%02X\n", addr, data ); */
268 return;
269#endif
270 }
271
272 irq_changed( this );
273}
274
275int read_mem_( struct Hes_Emu* this, hes_addr_t addr )
276{
277 hes_time_t time = Cpu_time( &this->cpu );
278 addr &= page_size - 1;
279 switch ( addr )
280 {
281 case 0x0000:
282 if ( this->irq.vdp > time )
283 return 0;
284 this->irq.vdp = future_time;
285 run_until( this, time );
286 irq_changed( this );
287 return 0x20;
288
289 /* case 0x0002:
290 case 0x0003:
291 dprintf( "VDP read not supported: %d\n", addr );
292 return 0; */
293
294 case 0x0C01:
295 //return timer.enabled; // TODO: remove?
296 case 0x0C00:
297 run_until( this, time );
298 /* dprintf( "Timer count read\n" ); */
299 return (unsigned) (this->timer.count - 1) / this->timer_base;
300
301 case 0x1402:
302 return this->irq.disables;
303
304 case 0x1403:
305 {
306 int status = 0;
307 if ( this->irq.timer <= time ) status |= timer_mask;
308 if ( this->irq.vdp <= time ) status |= vdp_mask;
309 return status;
310 }
311
312 case 0x180A:
313 case 0x180B:
314 case 0x180C:
315 case 0x180D:
316 return Adpcm_read_data( &this->adpcm, time, addr );
317
318 #ifndef NDEBUG
319 case 0x1000: // I/O port
320 //case 0x180C: // CD-ROM
321 //case 0x180D:
322 break;
323
324 /* default:
325 dprintf( "unmapped read $%04X\n", addr ); */
326 #endif
327 }
328
329 return unmapped;
330}
331
332void irq_changed( struct Hes_Emu* this )
333{
334 hes_time_t present = Cpu_time( &this->cpu );
335
336 if ( this->irq.timer > present )
337 {
338 this->irq.timer = future_time;
339 if ( this->timer.enabled && !this->timer.fired )
340 this->irq.timer = present + this->timer.count;
341 }
342
343 if ( this->irq.vdp > present )
344 {
345 this->irq.vdp = future_time;
346 if ( this->vdp.control & 0x08 )
347 this->irq.vdp = this->vdp.next_vbl;
348 }
349
350 hes_time_t time = future_time;
351 if ( !(this->irq.disables & timer_mask) ) time = this->irq.timer;
352 if ( !(this->irq.disables & vdp_mask) ) time = min( time, this->irq.vdp );
353
354 Cpu_set_irq_time( &this->cpu, time );
355}
356
357int cpu_done( struct Hes_Emu* this )
358{
359 check( Cpu_time( &this->cpu ) >= Cpu_end_time( &this->cpu ) ||
360 (!(this->cpu.r.flags & i_flag_mask) && Cpu_time( &this->cpu ) >= Cpu_irq_time( &this->cpu )) );
361
362 if ( !(this->cpu.r.flags & i_flag_mask) )
363 {
364 hes_time_t present = Cpu_time( &this->cpu );
365
366 if ( this->irq.timer <= present && !(this->irq.disables & timer_mask) )
367 {
368 this->timer.fired = true;
369 this->irq.timer = future_time;
370 irq_changed( this ); // overkill, but not worth writing custom code
371 return 0x0A;
372 }
373
374 if ( this->irq.vdp <= present && !(this->irq.disables & vdp_mask) )
375 {
376 // work around for bugs with music not acknowledging VDP
377 //run_until( present );
378 //irq.vdp = cpu.future_time;
379 //irq_changed();
380 return 0x08;
381 }
382 }
383 return -1;
384}
385
386static void adjust_time( hes_time_t* time, hes_time_t delta )
387{
388 if ( *time < future_time )
389 {
390 *time -= delta;
391 if ( *time < 0 )
392 *time = 0;
393 }
394}
395
396static blargg_err_t end_frame( struct Hes_Emu* this, hes_time_t duration )
397{
398 /* if ( run_cpu( this, duration ) )
399 warning( "Emulation error (illegal instruction)" ); */
400 run_cpu( this, duration );
401
402 check( Cpu_time( &this->cpu ) >= duration );
403 //check( time() - duration < 20 ); // Txx instruction could cause going way over
404
405 run_until( this, duration );
406
407 // end time frame
408 this->timer.last_time -= duration;
409 this->vdp.next_vbl -= duration;
410 Cpu_end_frame( &this->cpu, duration );
411 adjust_time( &this->irq.timer, duration );
412 adjust_time( &this->irq.vdp, duration );
413 Apu_end_frame( &this->apu, duration );
414 Adpcm_end_frame( &this->adpcm, duration );
415
416 return 0;
417}
418
419static blargg_err_t run_clocks( struct Hes_Emu* this, blip_time_t* duration_ )
420{
421 return end_frame( this, *duration_ );
422}
423
424blargg_err_t play_( void *emu, int count, sample_t out [] )
425{
426 struct Hes_Emu* this = (struct Hes_Emu*) emu;
427
428 int remain = count;
429 while ( remain )
430 {
431 Buffer_disable_immediate_removal( &this->stereo_buf );
432 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
433 if ( remain )
434 {
435 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
436 {
437 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
438
439 // Remute voices
440 Sound_mute_voices( this, this->mute_mask_ );
441 }
442 int msec = Buffer_length( &this->stereo_buf );
443 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
444 RETURN_ERR( run_clocks( this, &clocks_emulated ) );
445 assert( clocks_emulated );
446 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
447 }
448 }
449 return 0;
450}
451
452// Music emu
453
454blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, int rate )
455{
456 require( !this->sample_rate_ ); // sample rate can't be changed once set
457 Buffer_init( &this->stereo_buf );
458 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
459
460 // Set bass frequency
461 Buffer_bass_freq( &this->stereo_buf, 60 );
462
463 this->sample_rate_ = rate;
464 RETURN_ERR( track_init( &this->track_filter, this ) );
465 this->tfilter.max_silence = 6 * stereo * this->sample_rate_;
466 return 0;
467}
468
469void Sound_mute_voice( struct Hes_Emu* this, int index, bool mute )
470{
471 require( (unsigned) index < (unsigned) this->voice_count_ );
472 int bit = 1 << index;
473 int mask = this->mute_mask_ | bit;
474 if ( !mute )
475 mask ^= bit;
476 Sound_mute_voices( this, mask );
477}
478
479void Sound_mute_voices( struct Hes_Emu* this, int mask )
480{
481 require( this->sample_rate_ ); // sample rate must be set first
482 this->mute_mask_ = mask;
483
484 // Set adpcm voice
485 struct channel_t ch = Buffer_channel( &this->stereo_buf, this->voice_count_ );
486 if ( mask & (1 << this->voice_count_ ) )
487 Adpcm_set_output( &this->adpcm, 0, 0, 0, 0 );
488 else
489 Adpcm_set_output( &this->adpcm, 0, ch.center, ch.left, ch.right );
490
491 // Set apu voices
492 int i = this->voice_count_ - 1;
493 for ( ; i--; )
494 {
495 if ( mask & (1 << i) )
496 {
497 Apu_osc_output( &this->apu, i, 0, 0, 0 );
498 }
499 else
500 {
501 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
502 assert( (ch.center && ch.left && ch.right) ||
503 (!ch.center && !ch.left && !ch.right) ); // all or nothing
504 Apu_osc_output( &this->apu, i, ch.center, ch.left, ch.right );
505 }
506 }
507}
508
509void Sound_set_tempo( struct Hes_Emu* this, int t )
510{
511 require( this->sample_rate_ ); // sample rate must be set first
512 int const min = (int)(FP_ONE_TEMPO*0.02);
513 int const max = (int)(FP_ONE_TEMPO*4.00);
514 if ( t < min ) t = min;
515 if ( t > max ) t = max;
516 this->play_period = (hes_time_t) ((period_60hz*FP_ONE_TEMPO) / t);
517 this->timer_base = (int) ((1024*FP_ONE_TEMPO) / t);
518 recalc_timer_load( this );
519 this->tempo_ = t;
520}
521
522blargg_err_t Hes_start_track( struct Hes_Emu* this, int track )
523{
524 clear_track_vars( this );
525
526 // Remap track if playlist available
527 if ( this->m3u.size > 0 ) {
528 struct entry_t* e = &this->m3u.entries[track];
529 track = e->track;
530 }
531
532 this->current_track_ = track;
533
534 Buffer_clear( &this->stereo_buf );
535
536 memset( this->ram, 0, sizeof this->ram ); // some HES music relies on zero fill
537 memset( this->sgx, 0, sizeof this->sgx );
538
539 Apu_reset( &this->apu );
540 Adpcm_reset( &this->adpcm );
541 Cpu_reset( &this->cpu );
542
543 unsigned i;
544 for ( i = 0; i < sizeof this->header.banks; i++ )
545 set_mmr( this, i, this->header.banks [i] );
546 set_mmr( this, page_count, 0xFF ); // unmapped beyond end of address space
547
548 this->irq.disables = timer_mask | vdp_mask;
549 this->irq.timer = future_time;
550 this->irq.vdp = future_time;
551
552 this->timer.enabled = false;
553 this->timer.raw_load= 0x80;
554 this->timer.count = this->timer.load;
555 this->timer.fired = false;
556 this->timer.last_time = 0;
557
558 this->vdp.latch = 0;
559 this->vdp.control = 0;
560 this->vdp.next_vbl = 0;
561
562 this->ram [0x1FF] = (idle_addr - 1) >> 8;
563 this->ram [0x1FE] = (idle_addr - 1) & 0xFF;
564 this->cpu.r.sp = 0xFD;
565 this->cpu.r.pc = get_le16( this->header.init_addr );
566 this->cpu.r.a = track;
567
568 recalc_timer_load( this );
569
570 // convert filter times to samples
571 struct setup_t s = this->tfilter;
572 s.max_initial *= this->sample_rate_ * stereo;
573 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
574 s.lookahead = 1;
575 #endif
576 track_setup( &this->track_filter, &s );
577
578 return track_start( &this->track_filter );
579}
580
581// Tell/Seek
582
583static int msec_to_samples( int msec, int sample_rate )
584{
585 int sec = msec / 1000;
586 msec -= sec * 1000;
587 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
588}
589
590int Track_tell( struct Hes_Emu* this )
591{
592 int rate = this->sample_rate_ * stereo;
593 int sec = track_sample_count( &this->track_filter ) / rate;
594 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
595}
596
597blargg_err_t Track_seek( struct Hes_Emu* this, int msec )
598{
599 int time = msec_to_samples( msec, this->sample_rate_ );
600 if ( time < track_sample_count( &this->track_filter ) )
601 RETURN_ERR( Hes_start_track( this, this->current_track_ ) );
602 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
603}
604
605blargg_err_t skip_( void* emu, int count )
606{
607 struct Hes_Emu* this = (struct Hes_Emu*) emu;
608
609 // for long skip, mute sound
610 const int threshold = 32768;
611 if ( count > threshold )
612 {
613 int saved_mute = this->mute_mask_;
614 Sound_mute_voices( this, ~0 );
615
616 int n = count - threshold/2;
617 n &= ~(2048-1); // round to multiple of 2048
618 count -= n;
619 RETURN_ERR( skippy_( &this->track_filter, n ) );
620
621 Sound_mute_voices( this, saved_mute );
622 }
623
624 return skippy_( &this->track_filter, count );
625}
626
627blargg_err_t Track_skip( struct Hes_Emu* this, int count )
628{
629 require( this->current_track_ >= 0 ); // start_track() must have been called already
630 return track_skip( &this->track_filter, count );
631}
632
633void Track_set_fade( struct Hes_Emu* this, int start_msec, int length_msec )
634{
635 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate_ ),
636 length_msec * this->sample_rate_ / (1000 / stereo) );
637}
638
639blargg_err_t Hes_play( struct Hes_Emu* this, int out_count, sample_t* out )
640{
641 require( this->current_track_ >= 0 );
642 require( out_count % stereo == 0 );
643 return track_play( &this->track_filter, out_count, out );
644}
diff --git a/lib/rbcodec/codecs/libgme/hes_emu.h b/lib/rbcodec/codecs/libgme/hes_emu.h
new file mode 100644
index 0000000000..a1dd048498
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/hes_emu.h
@@ -0,0 +1,195 @@
1// TurboGrafx-16/PC Engine HES music file emulator
2
3// Game_Music_Emu 0.5.2
4#ifndef HES_EMU_H
5#define HES_EMU_H
6
7#include "blargg_source.h"
8
9#include "multi_buffer.h"
10#include "rom_data.h"
11#include "hes_apu.h"
12#include "hes_apu_adpcm.h"
13#include "hes_cpu.h"
14#include "m3u_playlist.h"
15#include "track_filter.h"
16
17// HES file header
18enum { info_offset = 0x20 };
19enum { header_size = 0x20 };
20struct header_t
21{
22 byte tag [4];
23 byte vers;
24 byte first_track;
25 byte init_addr [2];
26 byte banks [8];
27 byte data_tag [4];
28 byte size [4];
29 byte addr [4];
30 byte unused [4];
31};
32
33
34struct timer_t {
35 hes_time_t last_time;
36 int count;
37 int load;
38 int raw_load;
39 byte enabled;
40 byte fired;
41};
42
43struct vdp_t {
44 hes_time_t next_vbl;
45 byte latch;
46 byte control;
47};
48
49struct irq_t {
50 hes_time_t timer;
51 hes_time_t vdp;
52 byte disables;
53};
54
55struct Hes_Emu {
56 hes_time_t play_period;
57 int timer_base;
58
59 struct timer_t timer;
60 struct vdp_t vdp;
61 struct irq_t irq;
62
63 // Sound
64 int clock_rate_;
65 int sample_rate_;
66 unsigned buf_changed_count;
67 int voice_count_;
68 int const* voice_types_;
69 int mute_mask_;
70 int tempo_;
71 int gain_;
72
73 // track-specific
74 byte track_count;
75 int current_track_;
76
77 // Larger files at the end
78 // Header for currently loaded file
79 struct header_t header;
80
81 // M3u Playlist
82 struct M3u_Playlist m3u;
83
84 struct setup_t tfilter;
85 struct Track_Filter track_filter;
86
87 // Hes Cpu
88 struct Hes_Cpu cpu;
89 struct Rom_Data rom;
90
91 struct Hes_Apu apu;
92 struct Hes_Apu_Adpcm adpcm;
93
94 struct Multi_Buffer stereo_buf;
95
96 // rom & ram
97 byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space
98 byte ram [page_size];
99 byte sgx [3 * page_size + cpu_padding];
100};
101
102
103// Basic functionality
104// Initializes Hes_Emu structure
105void Hes_init( struct Hes_Emu* this );
106
107// Stops (clear) Hes_Emu structure
108void Hes_stop( struct Hes_Emu* this );
109
110// Loads a file from memory
111blargg_err_t Hes_load_mem( struct Hes_Emu* this, void* data, long size );
112
113// Set output sample rate. Must be called only once before loading file.
114blargg_err_t Hes_set_sample_rate( struct Hes_Emu* this, int sample_rate );
115
116// Start a track, where 0 is the first track. Also clears warning string.
117blargg_err_t Hes_start_track( struct Hes_Emu* this, int );
118
119// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
120// errors set warning string, and major errors also end track.
121blargg_err_t Hes_play( struct Hes_Emu* this, int count, sample_t* buf );
122
123// Track status/control
124// Number of milliseconds (1000 msec = 1 second) played since ning of track
125int Track_tell( struct Hes_Emu* this );
126
127// Seek to new time in track. Seeking backwards or far forward can take a while.
128blargg_err_t Track_seek( struct Hes_Emu* this, int msec );
129
130// Skip n samples
131blargg_err_t Track_skip( struct Hes_Emu* this, int n );
132
133// Set start time and length of track fade out. Once fade ends track_ended() returns
134// true. Fade time can be changed while track is playing.
135void Track_set_fade( struct Hes_Emu* this, int start_msec, int length_msec );
136
137// True if a track has reached its end
138static inline bool Track_ended( struct Hes_Emu* this )
139{
140 return track_ended( &this->track_filter );
141}
142
143// Disables automatic end-of-track detection and skipping of silence at beginning
144static inline void Track_ignore_silence( struct Hes_Emu* this, bool disable )
145{
146 this->track_filter.silence_ignored_ = disable;
147}
148
149// Get track length in milliseconds
150static inline int Track_get_length( struct Hes_Emu* this, int n )
151{
152 int length = 120 * 1000; /* 2 minutes */
153 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
154 struct entry_t* entry = &this->m3u.entries [n];
155 length = entry->length;
156 }
157
158 return length;
159}
160
161
162// Sound customization
163// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
164// Track length as returned by track_info() assumes a tempo of 1.0.
165void Sound_set_tempo( struct Hes_Emu* this, int );
166
167// Mute/unmute voice i, where voice 0 is first voice
168void Sound_mute_voice( struct Hes_Emu* this, int index, bool mute );
169
170// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
171// 0 unmutes them all, 0x01 mutes just the first voice, etc.
172void Sound_mute_voices( struct Hes_Emu* this, int mask );
173
174// Change overall output amplitude, where 1.0 results in minimal clamping.
175// Must be called before set_sample_rate().
176static inline void Sound_set_gain( struct Hes_Emu* this, int g )
177{
178 assert( !this->sample_rate_ ); // you must set gain before setting sample rate
179 this->gain_ = g;
180}
181
182// Emulation (You shouldn't touch these)
183
184void irq_changed( struct Hes_Emu* this );
185void run_until( struct Hes_Emu* this, hes_time_t );
186bool run_cpu( struct Hes_Emu* this, hes_time_t end );
187int read_mem_( struct Hes_Emu* this, hes_addr_t );
188int read_mem( struct Hes_Emu* this, hes_addr_t );
189void write_mem_( struct Hes_Emu* this, hes_addr_t, int data );
190void write_mem( struct Hes_Emu* this, hes_addr_t, int );
191void write_vdp( struct Hes_Emu* this, int addr, int data );
192void set_mmr( struct Hes_Emu* this, int reg, int bank );
193int cpu_done( struct Hes_Emu* this );
194
195#endif
diff --git a/lib/rbcodec/codecs/libgme/inflate/bbfuncs.c b/lib/rbcodec/codecs/libgme/inflate/bbfuncs.c
new file mode 100644
index 0000000000..3b23c3b6db
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/bbfuncs.c
@@ -0,0 +1,147 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "bbfuncs.h"
21
22#if defined(ROCKBOX)
23#include "codeclib.h"
24#endif
25
26void error_die(const char* msg)
27{
28 (void)msg;
29}
30
31void error_msg(const char* msg)
32{
33 (void)msg;
34}
35
36size_t safe_read(struct mbreader_t *md, void *buf, size_t count)
37{
38 ssize_t n;
39
40 do {
41 n = mbread(md, buf, count);
42 } while (n < 0&&n!=-1);
43
44 return n;
45}
46
47/*
48 * Read all of the supplied buffer from a file This does multiple reads as
49 *necessary. Returns the amount read, or -1 on an error. A short read is
50 *returned on an end of file.
51 */
52ssize_t full_read(struct mbreader_t *md, void *buf, size_t len)
53{
54 ssize_t cc;
55 ssize_t total;
56
57 total = 0;
58
59 while (len)
60 {
61 cc = safe_read(md, buf, len);
62
63 if (cc < 0)
64 return cc; /* read() returns -1 on failure. */
65
66 if (cc == 0)
67 break;
68
69 buf = ((char *)buf) + cc;
70 total += cc;
71 len -= cc;
72 }
73
74 return total;
75}
76
77/* Die with an error message if we can't read the entire buffer. */
78void xread(struct mbreader_t *md, void *buf, ssize_t count)
79{
80 if (count)
81 {
82 ssize_t size = full_read(md, buf, count);
83 if (size != count)
84 error_die("short read");
85 }
86}
87
88/* Die with an error message if we can't read one character. */
89unsigned char xread_char(struct mbreader_t *md)
90{
91 unsigned char tmp;
92
93 xread(md, &tmp, 1);
94
95 return tmp;
96}
97
98void check_header_gzip(struct mbreader_t *src_md)
99{
100 union {
101 unsigned char raw[8];
102 struct {
103 unsigned char method;
104 unsigned char flags;
105 unsigned int mtime;
106 unsigned char xtra_flags;
107 unsigned char os_flags;
108 } formatted;
109 } header;
110
111 xread(src_md, header.raw, 8);
112
113 /* Check the compression method */
114 if (header.formatted.method != 8)
115 error_die("Unknown compression method");
116
117 if (header.formatted.flags & 0x04)
118 {
119 /* bit 2 set: extra field present */
120 unsigned char extra_short;
121
122 extra_short = xread_char(src_md) + (xread_char(src_md) << 8);
123 while (extra_short > 0)
124 {
125 /* Ignore extra field */
126 xread_char(src_md);
127 extra_short--;
128 }
129 }
130
131 /* Discard original name if any */
132 if (header.formatted.flags & 0x08)
133 /* bit 3 set: original file name present */
134 while(xread_char(src_md) != 0) ;
135
136 /* Discard file comment if any */
137 if (header.formatted.flags & 0x10)
138 /* bit 4 set: file comment present */
139 while(xread_char(src_md) != 0) ;
140
141 /* Read the header checksum */
142 if (header.formatted.flags & 0x02)
143 {
144 xread_char(src_md);
145 xread_char(src_md);
146 }
147}
diff --git a/lib/rbcodec/codecs/libgme/inflate/bbfuncs.h b/lib/rbcodec/codecs/libgme/inflate/bbfuncs.h
new file mode 100644
index 0000000000..fe03ec1a3c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/bbfuncs.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef BBFUNCS_H
21#define BBFUNCS_H
22
23#include "mbreader.h"
24
25void error_die(const char* msg);
26void error_msg(const char* msg);
27size_t safe_read(struct mbreader_t *md, void *buf, size_t count);
28ssize_t full_read(struct mbreader_t *md, void *buf, size_t len);
29void xread(struct mbreader_t *md, void *buf, ssize_t count);
30unsigned char xread_char(struct mbreader_t *md);
31void check_header_gzip(struct mbreader_t *md);
32
33#endif
diff --git a/lib/rbcodec/codecs/libgme/inflate/inflate.c b/lib/rbcodec/codecs/libgme/inflate/inflate.c
new file mode 100644
index 0000000000..130abe89be
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/inflate.c
@@ -0,0 +1,1156 @@
1/*
2 * gunzip implementation for wikiviewer (c) Frederik M.J.V., 2006.
3 * some bug fixes by Adam Gashlin gunzip implementation for busybox
4 *
5 * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
6 *
7 * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
8 * based on gzip sources
9 *
10 * Adjusted further by Erik Andersen <andersen@codepoet.org> to support files as
11 *well as stdin/stdout, and to generally behave itself wrt command line
12 *handling.
13 *
14 * General cleanup to better adhere to the style guide and make use of standard
15 *busybox functions by Glenn McGrath <bug1@iinet.net.au>
16 *
17 * read_gz interface + associated hacking by Laurence Anderson
18 *
19 * Fixed huft_build() so decoding end-of-block code does not grab more bits than
20 *necessary (this is required by unzip applet), added inflate_cleanup() to free
21 *leaked bytebuffer memory (used in unzip.c), and some minor style guide
22 *cleanups by Ed Clark
23 *
24 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
25 *Copyright (C) 1992-1993 Jean-loup Gailly The unzip code was written and put in
26 *the public domain by Mark Adler. Portions of the lzw code are derived from the
27 *public domain 'compress'
28 * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
29 *Ken Turkowski, Dave Mack and Peter Jannesen.
30 *
31 *
32 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
33 */
34
35#include <inttypes.h>
36#ifndef NULL
37#define NULL 0
38#endif
39#define ENABLE_DESKTOP 0
40#define USE_DESKTOP(...)
41#include "mallocer.h"
42#include "bbfuncs.h"
43#include "inflate.h"
44
45#define TRIM_FILE_ON_ERROR 1
46
47typedef struct huft_s {
48 unsigned char e; /* number of extra bits or operation */
49 unsigned char b; /* number of bits in this code or subcode */
50 union {
51 unsigned short n; /* literal, length base, or distance base */
52 struct huft_s *t; /* pointer to next level of table */
53 } v;
54} huft_t;
55
56/*static void *mainmembuf;*/
57static void *huftbuffer1;
58static void *huftbuffer2;
59
60#define HUFT_MMP1 8
61#define HUFT_MMP2 9
62
63static struct mbreader_t *gunzip_src_md;
64static unsigned int gunzip_bytes_out; /* number of output bytes */
65static unsigned int gunzip_outbuf_count; /* bytes in output buffer */
66
67/* gunzip_window size--must be a power of two, and at least 32K for zip's
68 deflate method */
69enum {
70 gunzip_wsize = 0x8000
71};
72
73static unsigned char *gunzip_window;
74static uint32_t ifl_total;
75
76static uint32_t gunzip_crc;
77
78/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
79#define BMAX 16 /* maximum bit length of any code (16 for explode) */
80#define N_MAX 288 /* maximum number of codes in any set */
81
82/* bitbuffer */
83static unsigned int gunzip_bb; /* bit buffer */
84static unsigned char gunzip_bk; /* bits in bit buffer */
85
86/* These control the size of the bytebuffer */
87static unsigned int bytebuffer_max = 0x8000;
88static unsigned char *bytebuffer = NULL;
89static unsigned int bytebuffer_offset = 0;
90static unsigned int bytebuffer_size = 0;
91
92static const unsigned short mask_bits[] = {
93 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
94 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
95};
96
97/* Copy lengths for literal codes 257..285 */
98static const unsigned short cplens[] = {
99 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
100 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
101};
102
103/* note: see note #13 above about the 258 in this list. */
104/* Extra bits for literal codes 257..285 */
105static const unsigned char cplext[] = {
106 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5,
107 5, 5, 5, 0, 99, 99
108}; /* 99==invalid */
109
110/* Copy offsets for distance codes 0..29 */
111static const unsigned short cpdist[] = {
112 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
113 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
114};
115
116/* Extra bits for distance codes */
117static const unsigned char cpdext[] = {
118 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
119 11, 11, 12, 12, 13, 13
120};
121
122/* Tables for deflate from PKZIP's appnote.txt. */
123/* Order of the bit length code lengths */
124static const unsigned char border[] = {
125 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
126};
127
128static const uint32_t crc_table[256]= {
129 0,1996959894,-301047508,-1727442502,124634137,1886057615,
130 -379345611,-1637575261,249268274,2044508324,-522852066,
131 -1747789432,162941995,2125561021,-407360249,-1866523247,
132 498536548,1789927666,-205950648,-2067906082,450548861,
133 1843258603,-187386543,-2083289657,325883990,1684777152,
134 -43845254,-1973040660,335633487,1661365465,-99664541,
135 -1928851979,997073096,1281953886,-715111964,-1570279054,
136 1006888145,1258607687,-770865667,-1526024853,901097722,
137 1119000684,-608450090,-1396901568,853044451,1172266101,
138 -589951537,-1412350631,651767980,1373503546,-925412992,
139 -1076862698,565507253,1454621731,-809855591,-1195530993,
140 671266974,1594198024,-972236366,-1324619484,795835527,
141 1483230225,-1050600021,-1234817731,1994146192,31158534,
142 -1731059524,-271249366,1907459465,112637215,-1614814043,
143 -390540237,2013776290,251722036,-1777751922,-519137256,
144 2137656763,141376813,-1855689577,-429695999,1802195444,
145 476864866,-2056965928,-228458418,1812370925,453092731,
146 -2113342271,-183516073,1706088902,314042704,-1950435094,
147 -54949764,1658658271,366619977,-1932296973,-69972891,
148 1303535960,984961486,-1547960204,-725929758,1256170817,
149 1037604311,-1529756563,-740887301,1131014506,879679996,
150 -1385723834,-631195440,1141124467,855842277,-1442165665,
151 -586318647,1342533948,654459306,-1106571248,-921952122,
152 1466479909,544179635,-1184443383,-832445281,1591671054,
153 702138776,-1328506846,-942167884,1504918807,783551873,
154 -1212326853,-1061524307,-306674912,-1698712650,62317068,
155 1957810842,-355121351,-1647151185,81470997,1943803523,
156 -480048366,-1805370492,225274430,2053790376,-468791541,
157 -1828061283,167816743,2097651377,-267414716,-2029476910,
158 503444072,1762050814,-144550051,-2140837941,426522225,
159 1852507879,-19653770,-1982649376,282753626,1742555852,
160 -105259153,-1900089351,397917763,1622183637,-690576408,
161 -1580100738,953729732,1340076626,-776247311,-1497606297,
162 1068828381,1219638859,-670225446,-1358292148,906185462,
163 1090812512,-547295293,-1469587627,829329135,1181335161,
164 -882789492,-1134132454,628085408,1382605366,-871598187,
165 -1156888829,570562233,1426400815,-977650754,-1296233688,
166 733239954,1555261956,-1026031705,-1244606671,752459403,
167 1541320221,-1687895376,-328994266,1969922972,40735498,
168 -1677130071,-351390145,1913087877,83908371,-1782625662,
169 -491226604,2075208622,213261112,-1831694693,-438977011,
170 2094854071,198958881,-2032938284,-237706686,1759359992,
171 534414190,-2118248755,-155638181,1873836001,414664567,
172 -2012718362,-15766928,1711684554,285281116,-1889165569,
173 -127750551,1634467795,376229701,-1609899400,-686959890,
174 1308918612,956543938,-1486412191,-799009033,1231636301,
175 1047427035,-1362007478,-640263460,1088359270,936918000,
176 -1447252397,-558129467,1202900863,817233897,-1111625188,
177 -893730166,1404277552,615818150,-1160759803,-841546093,
178 1423857449,601450431,-1285129682,-1000256840,1567103746,
179 711928724,-1274298825,-1022587231,1510334235,755167117
180};
181
182static unsigned int fill_bitbuffer(unsigned int bitbuffer, unsigned int *current,
183 const unsigned int required)
184{
185 while (*current < required)
186 {
187 if (bytebuffer_offset >= bytebuffer_size)
188 {
189 /* Leave the first 4 bytes empty so we can always unwind the
190 bitbuffer to the front of the bytebuffer, leave 4 bytes free at
191 end of tail so we can easily top up buffer in
192 check_trailer_gzip() */
193 if (1 > (bytebuffer_size = safe_read(gunzip_src_md, &bytebuffer[4],
194 bytebuffer_max - 8)))
195 error_die("unexpected end of file");
196
197 bytebuffer_size += 4;
198 bytebuffer_offset = 4;
199 }
200
201 bitbuffer |= ((unsigned int) bytebuffer[bytebuffer_offset]) << *current;
202 bytebuffer_offset++;
203 *current += 8;
204 }
205 return(bitbuffer);
206}
207
208/*
209 * Free the malloc'ed tables built by huft_build(), which makes a linked list of
210 *the tables it made, with the links in a dummy first entry of each table.
211 * t: table to free
212 */
213static int huft_free(huft_t * t,unsigned char bufnum)
214{
215 wpw_reset_mempool(bufnum);
216 if(t==0)
217 {
218 }
219
220 return 0;
221}
222
223/* Given a list of code lengths and a maximum table size, make a set of tables
224 to decode that set of codes. Return zero on success, one if the given code
225 set is incomplete (the tables are still built in this case), two if the input
226 is invalid (all zero length codes or an oversubscribed set of lengths), and
227 three if not enough memory.
228 *
229 * b: code lengths in bits (all assumed <= BMAX) n: number of codes
230 *(assumed <= N_MAX) s: number of simple-valued codes (0..s-1) d: list of
231 *base values for non-simple codes e: list of extra bits for non-simple codes
232 *t: result: starting table m: maximum lookup bits, returns actual bufnum:
233 *the number of the memory pool to fetch memory from
234 */
235static
236int huft_build(unsigned int *b, const unsigned int n,
237 const unsigned int s, const unsigned short *d,
238 const unsigned char *e, huft_t ** t, unsigned int *m,
239 unsigned char bufnum)
240{
241 unsigned a=0; /* counter for codes of length k */
242 unsigned c[BMAX + 1]; /* bit length count table */
243 unsigned eob_len=0; /* length of end-of-block code (value 256) */
244 unsigned f=0; /* i repeats in table every f entries */
245 int g=0; /* maximum code length */
246 int htl=0; /* table level */
247 unsigned i=0; /* counter, current code */
248 unsigned j=0; /* counter */
249 int k=0; /* number of bits in current code */
250 unsigned *p; /* pointer into c[], b[], or v[] */
251 huft_t *q; /* points to current table */
252 huft_t r; /* table entry for structure assignment */
253 huft_t *u[BMAX]; /* table stack */
254 unsigned v[N_MAX]; /* values in order of bit length */
255 int ws[BMAX+1]; /* bits decoded stack */
256 int w=0; /* bits decoded */
257 unsigned x[BMAX + 1]; /* bit offsets, then code stack */
258 unsigned *xp; /* pointer into x */
259 int y=0; /* number of dummy codes added */
260 unsigned z=0; /* number of entries in current table */
261
262 /* Length of EOB code, if any */
263 eob_len = n > 256 ? b[256] : BMAX;
264
265 /* Generate counts for each bit length */
266 memset((void *)c, 0, sizeof(c));
267 p = b;
268 i = n;
269 do {
270 c[*p]++; /* assume all entries <= BMAX */
271 p++; /* Can't combine with above line (Solaris bug) */
272 } while (--i);
273 if (c[0] == n) /* null input--all zero length codes */
274 {
275 *t = (huft_t *) NULL;
276 *m = 0;
277 return 2;
278 }
279
280 /* Find minimum and maximum length, bound *m by those */
281 for (j = 1; (c[j] == 0) && (j <= BMAX); j++) ;
282
283 k = j; /* minimum code length */
284 for (i = BMAX; (c[i] == 0) && i; i--) ;
285
286 g = i; /* maximum code length */
287 *m = (*m < j) ? j : ((*m > i) ? i : *m);
288
289 /* Adjust last length count to fill out codes, if needed */
290 for (y = 1 << j; j < i; j++, y <<= 1)
291 {
292 if ((y -= c[j]) < 0)
293 return 2; /* bad input: more codes than bits */
294 }
295
296 if ((y -= c[i]) < 0)
297 return 2;
298
299 c[i] += y;
300
301 /* Generate starting offsets into the value table for each length */
302 x[1] = j = 0;
303 p = c + 1;
304 xp = x + 2;
305 while (--i) /* note that i == g from above */
306 {
307 *xp++ = (j += *p++);
308 }
309
310 /* Make a table of values in order of bit lengths */
311 p = b;
312 i = 0;
313 do {
314 if ((j = *p++) != 0)
315 v[x[j]++] = i;
316 } while (++i < n);
317
318 /* Generate the Huffman codes and for each, make the table entries */
319 x[0] = i = 0; /* first Huffman code is zero */
320 p = v; /* grab values in bit order */
321 htl = -1; /* no tables yet--level -1 */
322 w = ws[0] = 0; /* bits decoded */
323 u[0] = (huft_t *) NULL; /* just to keep compilers happy */
324 q = (huft_t *) NULL; /* ditto */
325 z = 0; /* ditto */
326
327 /* go through the bit lengths (k already is bits in shortest code) */
328 for (; k <= g; k++)
329 {
330 a = c[k];
331 while (a--)
332 {
333 /* here i is the Huffman code of length k bits for value *p */
334 /* make tables up to required level */
335 while (k > ws[htl + 1])
336 {
337 w = ws[++htl];
338
339 /* compute minimum size table less than or equal to *m bits */
340 z = (z = g - w) > *m ? *m : z; /* upper limit on table size */
341 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
342 { /* too few codes for k-w bit table */
343 f -= a + 1; /* deduct codes from patterns left */
344 xp = c + k;
345 while (++j < z) /* try smaller tables up to z bits */
346 {
347 if ((f <<= 1) <= *++xp)
348 break; /* enough codes to use up j bits */
349
350 f -= *xp; /* else deduct codes from patterns */
351 }
352 }
353
354 j = ((unsigned)(w + j) > eob_len && (unsigned)w < eob_len)
355 ? eob_len - w : j; /* make EOB code end at table */
356 z = 1 << j; /* table entries for j-bit table */
357 ws[htl+1] = w + j; /* set bits decoded in stack */
358
359 /* allocate and link in new table */
360 q = (huft_t *) wpw_malloc(bufnum,(z + 1) * sizeof(huft_t));
361 if(q==0)
362 return 3;
363
364 *t = q + 1; /* link to list for huft_free() */
365 t = &(q->v.t);
366 u[htl] = ++q; /* table starts after link */
367
368 /* connect to last table, if there is one */
369 if (htl)
370 {
371 x[htl] = i; /* save pattern for backing up */
372
373 /* bits to dump before this table */
374 r.b = (unsigned char) (w - ws[htl - 1]);
375 r.e = (unsigned char) (16 + j); /* bits in this table */
376 r.v.t = q; /* pointer to this table */
377 j = (i & ((1 << w) - 1)) >> ws[htl - 1];
378 u[htl - 1][j] = r; /* connect to last table */
379 }
380 }
381
382 /* set up table entry in r */
383 r.b = (unsigned char) (k - w);
384 if (p >= v + n)
385 r.e = 99; /* out of values--invalid code */
386 else if (*p < s)
387 {
388 r.e = (unsigned char) (*p < 256 ? 16 : 15); /* 256 is EOB
389 code */
390 r.v.n = (unsigned short) (*p++); /* simple code is just the
391 value */
392 }
393 else
394 {
395 r.e = (unsigned char) e[*p - s]; /* non-simple--look up in lists
396 */
397 r.v.n = d[*p++ - s];
398 }
399
400 /* fill code-like entries with r */
401 f = 1 << (k - w);
402 for (j = i >> w; j < z; j += f)
403 {
404 q[j] = r;
405 }
406
407 /* backwards increment the k-bit code i */
408 for (j = 1 << (k - 1); i &j; j >>= 1)
409 {
410 i ^= j;
411 }
412 i ^= j;
413
414 /* backup over finished tables */
415 while ((i & ((1 << w) - 1)) != x[htl])
416 {
417 w = ws[--htl];
418 }
419 }
420 }
421
422 /* return actual size of base table */
423 *m = ws[1];
424
425 /* Return true (1) if we were given an incomplete table */
426 return y != 0 && g != 1;
427}
428
429/*
430 * inflate (decompress) the codes in a deflated (compressed) block. Return an
431 *error code or zero if it all goes ok.
432 *
433 * tl, td: literal/length and distance decoder tables bl, bd: number of bits
434 *decoded by tl[] and td[]
435 */
436static int inflate_codes_resumeCopy = 0;
437static int inflate_codes(huft_t * my_tl, huft_t * my_td,
438 const unsigned int my_bl, const unsigned int my_bd,
439 int setup)
440{
441 static unsigned int e; /* table entry flag/number of extra bits */
442 static unsigned int n, d; /* length and index for copy */
443 static unsigned int w; /* current gunzip_window position */
444 static huft_t *t; /* pointer to table entry */
445 static unsigned int ml, md; /* masks for bl and bd bits */
446 static unsigned int b; /* bit buffer */
447 static unsigned int k; /* number of bits in bit buffer */
448 static huft_t *tl, *td;
449 static unsigned int bl, bd;
450
451 if (setup) /* 1st time we are called, copy in variables */
452 {
453 tl = my_tl;
454 td = my_td;
455 bl = my_bl;
456 bd = my_bd;
457 /* make local copies of globals */
458 b = gunzip_bb; /* initialize bit buffer */
459 k = gunzip_bk;
460 w = gunzip_outbuf_count; /* initialize gunzip_window position
461 */
462
463 /* inflate the coded data */
464 ml = mask_bits[bl]; /* precompute masks for speed */
465 md = mask_bits[bd];
466 return 0; /* Don't actually do anything the first time */
467 }
468
469 if (inflate_codes_resumeCopy) goto do_copy;
470
471 while (1) /* do until end of block */
472 {
473 b = fill_bitbuffer(b, &k, bl);
474 if ((e = (t = tl + ((unsigned) b & ml))->e) > 16)
475 do {
476 if (e == 99)
477 error_die("inflate_codes error 1");
478
479 b >>= t->b;
480 k -= t->b;
481 e -= 16;
482 b = fill_bitbuffer(b, &k, e);
483 } while ((e =
484 (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
485
486 b >>= t->b;
487 k -= t->b;
488 if (e == 16) /* then it's a literal */
489 {
490 gunzip_window[w++] = (unsigned char) t->v.n;
491 if (w == gunzip_wsize)
492 {
493 gunzip_outbuf_count = (w);
494 w = 0;
495 return 1; /* We have a block to read */
496 }
497 }
498 else /* it's an EOB or a length */
499 { /* exit if end of block */
500 if (e == 15)
501 break;
502
503 /* get length of block to copy */
504 b = fill_bitbuffer(b, &k, e);
505 n = t->v.n + ((unsigned) b & mask_bits[e]);
506 b >>= e;
507 k -= e;
508
509 /* decode distance of block to copy */
510 b = fill_bitbuffer(b, &k, bd);
511 if ((e = (t = td + ((unsigned) b & md))->e) > 16)
512 do {
513 if (e == 99)
514 error_die("inflate_codes error 2");
515
516 b >>= t->b;
517 k -= t->b;
518 e -= 16;
519 b = fill_bitbuffer(b, &k, e);
520 } while ((e =
521 (t =
522 t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16);
523
524 b >>= t->b;
525 k -= t->b;
526 b = fill_bitbuffer(b, &k, e);
527 d = w - t->v.n - ((unsigned) b & mask_bits[e]);
528 b >>= e;
529 k -= e;
530
531 /* do the copy */
532do_copy: do {
533 n -= (e =
534 (e =
535 gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e);
536 /* copy to new buffer to prevent possible overwrite */
537 if (w - d >= e) /* (this test assumes unsigned comparison)
538 */
539 {
540 memcpy(gunzip_window + w, gunzip_window + d, e);
541 w += e;
542 d += e;
543 }
544 else
545 {
546 /* do it slow to avoid memcpy() overlap */
547 /* !NOMEMCPY */
548 do {
549 gunzip_window[w++] = gunzip_window[d++];
550 } while (--e);
551 }
552
553 if (w == gunzip_wsize)
554 {
555 gunzip_outbuf_count = (w);
556 if (n) inflate_codes_resumeCopy = 1;
557 else inflate_codes_resumeCopy = 0;
558
559 w = 0;
560 return 1;
561 }
562 } while (n);
563 inflate_codes_resumeCopy = 0;
564 }
565 }
566
567 /* restore the globals from the locals */
568 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
569 gunzip_bb = b; /* restore global bit buffer */
570 gunzip_bk = k;
571
572 /* normally just after call to inflate_codes, but save code by putting it
573 here */
574 /* free the decoding tables, return */
575 huft_free(tl,HUFT_MMP1);
576 huft_free(td,HUFT_MMP2);
577
578 /* done */
579 return 0;
580}
581
582static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
583{
584 static unsigned int n, b_stored, k_stored, w;
585 if (setup)
586 {
587 n = my_n;
588 b_stored = my_b_stored;
589 k_stored = my_k_stored;
590 w = gunzip_outbuf_count; /* initialize gunzip_window position */
591 return 0; /* Don't do anything first time */
592 }
593
594 /* read and output the compressed data */
595 while (n--)
596 {
597 b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
598 gunzip_window[w++] = (unsigned char) b_stored;
599 if (w == gunzip_wsize)
600 {
601 gunzip_outbuf_count = (w);
602 w = 0;
603 b_stored >>= 8;
604 k_stored -= 8;
605 return 1; /* We have a block */
606 }
607
608 b_stored >>= 8;
609 k_stored -= 8;
610 }
611
612 /* restore the globals from the locals */
613 gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
614 gunzip_bb = b_stored; /* restore global bit buffer */
615 gunzip_bk = k_stored;
616 return 0; /* Finished */
617}
618
619/*
620 * decompress an inflated block e: last block flag
621 *
622 * GLOBAL VARIABLES: bb, kk,
623 */
624/* Return values: -1 = inflate_stored, -2 = inflate_codes */
625static int inflate_block(int *e)
626{
627 unsigned t; /* block type */
628 unsigned int b; /* bit buffer */
629 unsigned int k; /* number of bits in bit buffer */
630
631 /* make local bit buffer */
632
633 b = gunzip_bb;
634 k = gunzip_bk;
635
636 /* read in last block bit */
637 b = fill_bitbuffer(b, &k, 1);
638 *e = (int) b & 1;
639 b >>= 1;
640 k -= 1;
641
642 /* read in block type */
643 b = fill_bitbuffer(b, &k, 2);
644 t = (unsigned) b & 3;
645 b >>= 2;
646 k -= 2;
647
648 /* restore the global bit buffer */
649 gunzip_bb = b;
650 gunzip_bk = k;
651
652 /* inflate that block type */
653 switch (t)
654 {
655 case 0: /* Inflate stored */
656 {
657 unsigned int n=0; /* number of bytes in block */
658
659 /* make local copies of globals */
660 unsigned int b_stored=gunzip_bb; /* bit buffer */
661 unsigned int k_stored=gunzip_bk; /* number of bits in bit buffer */
662
663 /* go to byte boundary */
664 n = k_stored & 7;
665 b_stored >>= n;
666 k_stored -= n;
667
668 /* get the length and its complement */
669 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
670 n = ((unsigned) b_stored & 0xffff);
671 b_stored >>= 16;
672 k_stored -= 16;
673
674 b_stored = fill_bitbuffer(b_stored, &k_stored, 16);
675 if (n != (unsigned) ((~b_stored) & 0xffff))
676 return 1; /* error in compressed data */
677
678 b_stored >>= 16;
679 k_stored -= 16;
680
681 inflate_stored(n, b_stored, k_stored, 1); /* Setup inflate_stored */
682 return -1;
683 }
684 case 1: /* Inflate fixed decompress an inflated type 1 (fixed
685 Huffman codes) block. We should either replace this
686 with a custom decoder, or at least precompute the
687 Huffman tables.
688 */
689 {
690 int i; /* temporary variable */
691 huft_t *tl; /* literal/length code table */
692 huft_t *td; /* distance code table */
693 unsigned int bl; /* lookup bits for tl */
694 unsigned int bd; /* lookup bits for td */
695 unsigned int l[288]; /* length list for huft_build */
696
697 /* set up literal table */
698 for (i = 0; i < 144; i++)
699 {
700 l[i] = 8;
701 }
702 for (; i < 256; i++)
703 {
704 l[i] = 9;
705 }
706 for (; i < 280; i++)
707 {
708 l[i] = 7;
709 }
710 for (; i < 288; i++) /* make a complete, but wrong code set */
711 {
712 l[i] = 8;
713 }
714 bl = 7;
715 if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl,HUFT_MMP1)) != 0)
716 return i;
717
718 /* set up distance table */
719 for (i = 0; i < 30; i++) /* make an incomplete code set */
720 {
721 l[i] = 5;
722 }
723 bd = 5;
724 if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd,HUFT_MMP2)) > 1)
725 {
726 huft_free(tl,HUFT_MMP1);
727 return i;
728 }
729
730 /* decompress until an end-of-block code */
731 inflate_codes(tl, td, bl, bd, 1); /* Setup inflate_codes */
732
733 /* huft_free code moved into inflate_codes */
734
735 return -2;
736 }
737 case 2: /* Inflate dynamic */
738 {
739 const int dbits = 6; /* bits in base distance lookup table */
740 const int lbits = 9; /* bits in base literal/length lookup table */
741
742 huft_t *tl; /* literal/length code table */
743 huft_t *td; /* distance code table */
744 unsigned int i; /* temporary variables */
745 unsigned int j;
746 unsigned int l; /* last length */
747 unsigned int m; /* mask for bit lengths table */
748 unsigned int n; /* number of lengths to get */
749 unsigned int bl; /* lookup bits for tl */
750 unsigned int bd; /* lookup bits for td */
751 unsigned int nb; /* number of bit length codes */
752 unsigned int nl; /* number of literal/length codes */
753 unsigned int nd; /* number of distance codes */
754
755 unsigned int ll[286 + 30]; /* literal/length and distance code
756 lengths */
757 unsigned int b_dynamic; /* bit buffer */
758 unsigned int k_dynamic; /* number of bits in bit buffer */
759
760 /* make local bit buffer */
761 b_dynamic = gunzip_bb;
762 k_dynamic = gunzip_bk;
763
764 /* read in table lengths */
765 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
766 nl = 257 + ((unsigned int) b_dynamic & 0x1f); /* number of
767 literal/length codes
768 */
769
770 b_dynamic >>= 5;
771 k_dynamic -= 5;
772 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 5);
773 nd = 1 + ((unsigned int) b_dynamic & 0x1f); /* number of distance
774 codes */
775
776 b_dynamic >>= 5;
777 k_dynamic -= 5;
778 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 4);
779 nb = 4 + ((unsigned int) b_dynamic & 0xf); /* number of bit length
780 codes */
781
782 b_dynamic >>= 4;
783 k_dynamic -= 4;
784 if (nl > 286 || nd > 30)
785 return 1; /* bad lengths */
786
787 /* read in bit-length-code lengths */
788 for (j = 0; j < nb; j++)
789 {
790 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
791 ll[border[j]] = (unsigned int) b_dynamic & 7;
792 b_dynamic >>= 3;
793 k_dynamic -= 3;
794 }
795 for (; j < 19; j++)
796 {
797 ll[border[j]] = 0;
798 }
799
800 /* build decoding table for trees--single level, 7 bit lookup */
801 bl = 7;
802 i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl,HUFT_MMP1);
803 if (i != 0)
804 {
805 if (i == 1)
806 huft_free(tl,HUFT_MMP1);
807
808 return i; /* incomplete code set */
809 }
810
811 /* read in literal and distance code lengths */
812 n = nl + nd;
813 m = mask_bits[bl];
814 i = l = 0;
815 while ((unsigned int) i < n)
816 {
817 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, (unsigned int)bl);
818 j = (td = tl + ((unsigned int) b_dynamic & m))->b;
819 b_dynamic >>= j;
820 k_dynamic -= j;
821 j = td->v.n;
822 if (j < 16) /* length of code in bits (0..15) */
823 ll[i++] = l = j; /* save last length in l */
824 else if (j == 16) /* repeat last length 3 to 6 times */
825 {
826 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 2);
827 j = 3 + ((unsigned int) b_dynamic & 3);
828 b_dynamic >>= 2;
829 k_dynamic -= 2;
830 if ((unsigned int) i + j > n)
831 return 1;
832
833 while (j--)
834 {
835 ll[i++] = l;
836 }
837 }
838 else if (j == 17) /* 3 to 10 zero length codes */
839 {
840 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 3);
841 j = 3 + ((unsigned int) b_dynamic & 7);
842 b_dynamic >>= 3;
843 k_dynamic -= 3;
844 if ((unsigned int) i + j > n)
845 return 1;
846
847 while (j--)
848 {
849 ll[i++] = 0;
850 }
851 l = 0;
852 }
853 else /* j == 18: 11 to 138 zero length codes */
854 {
855 b_dynamic = fill_bitbuffer(b_dynamic, &k_dynamic, 7);
856 j = 11 + ((unsigned int) b_dynamic & 0x7f);
857 b_dynamic >>= 7;
858 k_dynamic -= 7;
859 if ((unsigned int) i + j > n)
860 return 1;
861
862 while (j--)
863 {
864 ll[i++] = 0;
865 }
866 l = 0;
867 }
868 }
869
870 /* free decoding table for trees */
871 huft_free(tl,HUFT_MMP1);
872
873 /* restore the global bit buffer */
874 gunzip_bb = b_dynamic;
875 gunzip_bk = k_dynamic;
876
877 /* build the decoding tables for literal/length and distance codes */
878 bl = lbits;
879
880 if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl,HUFT_MMP1)) != 0)
881 {
882 if (i == 1)
883 {
884 error_die("Incomplete literal tree");
885 huft_free(tl,HUFT_MMP1);
886 }
887
888 return i; /* incomplete code set */
889 }
890
891 bd = dbits;
892 if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd,HUFT_MMP2)) != 0)
893 {
894 if (i == 1)
895 {
896 error_die("incomplete distance tree");
897 huft_free(td,HUFT_MMP2);
898 }
899
900 huft_free(tl,HUFT_MMP1);
901 return i; /* incomplete code set */
902 }
903
904 /* decompress until an end-of-block code */
905 inflate_codes(tl, td, bl, bd, 1); /* Setup inflate_codes */
906
907 /* huft_free code moved into inflate_codes */
908
909 return -2;
910 }
911 default:
912 /* bad block type */
913 error_die("bad block type");
914 }
915 return 0;
916}
917
918static void calculate_gunzip_crc(void)
919{
920 unsigned int n;
921 for (n = 0; n < gunzip_outbuf_count; n++)
922 {
923 gunzip_crc = crc_table[((int) gunzip_crc ^ (gunzip_window[n])) & 0xff]
924 ^ (gunzip_crc >> 8);
925 }
926 gunzip_bytes_out += gunzip_outbuf_count;
927}
928
929static int inflate_get_next_window_method = -1; /* Method == -1 for stored, -2
930 for codes */
931static int inflate_get_next_window_e = 0;
932static int inflate_get_next_window_needAnotherBlock = 1;
933
934static int inflate_get_next_window(void)
935{
936 gunzip_outbuf_count = 0;
937
938 while(1)
939 {
940 int ret=0;
941 if (inflate_get_next_window_needAnotherBlock)
942 {
943 if(inflate_get_next_window_e)
944 {
945 calculate_gunzip_crc();
946 inflate_get_next_window_e = 0;
947 inflate_get_next_window_needAnotherBlock = 1;
948 return 0;
949 } /* Last block */
950
951 inflate_get_next_window_method = inflate_block(&inflate_get_next_window_e);
952 inflate_get_next_window_needAnotherBlock = 0;
953 }
954
955 switch (inflate_get_next_window_method)
956 {
957 case -1: ret = inflate_stored(0,0,0,0);
958 break;
959 case -2: ret = inflate_codes(0,0,0,0,0);
960 break;
961 default:
962 error_die("inflate error");
963 }
964
965 if (ret == 1)
966 {
967 calculate_gunzip_crc();
968 return 1; /* More data left */
969 }
970 else inflate_get_next_window_needAnotherBlock = 1; /* End of that
971 block */
972 }
973 /* Doesnt get here */
974}
975
976/* Initialise bytebuffer, be careful not to overfill the buffer */
977static void inflate_init(unsigned int bufsize)
978{
979 /* Set the bytebuffer size, default is same as gunzip_wsize */
980 bytebuffer_max = bufsize + 8;
981 bytebuffer_offset = 4;
982 bytebuffer_size = 0;
983}
984
985static void inflate_cleanup(void)
986{
987 /* free(bytebuffer); */
988}
989
990USE_DESKTOP(long long) static int
991inflate_unzip(struct mbreader_t *in,char* outbuffer,uint32_t outbuflen)
992{
993 USE_DESKTOP(long long total = 0; )
994 typedef void (*sig_type)(int);
995
996 /* Allocate all global buffers (for DYN_ALLOC option) */
997 gunzip_outbuf_count = 0;
998 gunzip_bytes_out = 0;
999 gunzip_src_md = in;
1000
1001 /* initialize gunzip_window, bit buffer */
1002 gunzip_bk = 0;
1003 gunzip_bb = 0;
1004
1005 /* Create the crc table */
1006 gunzip_crc = ~0;
1007
1008 /* Allocate space for buffer */
1009 while(1)
1010 {
1011 int ret = inflate_get_next_window();
1012 if((signed int)outbuflen-(signed int)gunzip_outbuf_count<0)
1013 {
1014 error_msg("write_error");
1015 #ifdef TRIM_FILE_ON_ERROR
1016 return USE_DESKTOP(total) + 0;
1017 #else
1018 return -1;
1019 #endif
1020 }
1021
1022 memcpy(outbuffer,gunzip_window,gunzip_outbuf_count);
1023 outbuffer+=sizeof(char)*gunzip_outbuf_count;
1024 ifl_total+=sizeof(char)*gunzip_outbuf_count;
1025 outbuflen-=gunzip_outbuf_count;
1026 USE_DESKTOP(total += gunzip_outbuf_count; )
1027 if (ret == 0) break;
1028 }
1029
1030 /* Store unused bytes in a global buffer so calling applets can access it */
1031 if (gunzip_bk >= 8)
1032 {
1033 /* Undo too much lookahead. The next read will be byte aligned so we can
1034 discard unused bits in the last meaningful byte. */
1035 bytebuffer_offset--;
1036 bytebuffer[bytebuffer_offset] = gunzip_bb & 0xff;
1037 gunzip_bb >>= 8;
1038 gunzip_bk -= 8;
1039 }
1040
1041 return USE_DESKTOP(total) + 0;
1042}
1043
1044USE_DESKTOP(long long) static int
1045inflate_gunzip(struct mbreader_t *in,char* outbuffer,uint32_t outbuflen)
1046{
1047 uint32_t stored_crc = 0;
1048 unsigned int count;
1049 USE_DESKTOP(long long total = ) inflate_unzip(in, outbuffer,outbuflen);
1050
1051 USE_DESKTOP(if (total < 0) return total;
1052
1053 )
1054
1055 /* top up the input buffer with the rest of the trailer */
1056 count = bytebuffer_size - bytebuffer_offset;
1057 if (count < 8)
1058 {
1059 xread(in, &bytebuffer[bytebuffer_size], 8 - count);
1060 bytebuffer_size += 8 - count;
1061 }
1062
1063 for (count = 0; count != 4; count++)
1064 {
1065 stored_crc |= (bytebuffer[bytebuffer_offset] << (count * 8));
1066 bytebuffer_offset++;
1067 }
1068
1069 /* Validate decompression - crc */
1070 if (stored_crc != (~gunzip_crc))
1071 {
1072 error_msg("crc error");
1073
1074 #ifdef TRIM_FILE_ON_ERROR
1075 return USE_DESKTOP(total) + 0;
1076 #else
1077 return -1;
1078 #endif
1079 }
1080
1081 /* Validate decompression - size */
1082 if ((signed int)gunzip_bytes_out !=
1083 (bytebuffer[bytebuffer_offset] | (bytebuffer[bytebuffer_offset+1] << 8) |
1084 (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24)))
1085 {
1086 error_msg("incorrect length");
1087 return -1;
1088 }
1089
1090 return USE_DESKTOP(total) + 0;
1091}
1092
1093/*An allocated memory buffer at least 0x13100 (72448) bytes long*/
1094uint32_t decompress(const char *inbuffer,uint32_t inbuflen,char* outbuffer,uint32_t outbuflen,uint32_t offset,char* membuf)
1095{
1096 signed char status=0;
1097 int exitcode=0;
1098 struct mbreader_t src_md;
1099 ifl_total=0;
1100 /* reset statics */
1101 inflate_codes_resumeCopy = 0;
1102 inflate_get_next_window_method = -1; /* Method == -1 for stored, -2 for
1103 codes */
1104 inflate_get_next_window_e = 0;
1105 inflate_get_next_window_needAnotherBlock = 1;
1106 /* init */
1107 inflate_init(0x8000-8);
1108 /*Memory init*/
1109 huftbuffer1=membuf;
1110 huftbuffer2=membuf+0x2A00;
1111 gunzip_window=membuf+0x2A00+0xA00;
1112 bytebuffer=membuf+0x2A00+0xA00+0x8000;
1113 wpw_init_mempool_pdm(HUFT_MMP1,(unsigned char*)huftbuffer1,0x2A00);
1114 wpw_init_mempool_pdm(HUFT_MMP2,(unsigned char*)huftbuffer2,0xA00);
1115
1116 /* Initialize memory buffer reader */
1117 src_md.ptr = inbuffer;
1118 src_md.size = inbuflen;
1119 src_md.offset = offset;
1120
1121 if ((exitcode=xread_char(&src_md)) == 0x1f)
1122 {
1123 unsigned char magic2;
1124 magic2 = xread_char(&src_md);
1125 if (magic2 == 0x8b)
1126 {
1127 check_header_gzip(&src_md); /* FIXME: xfunc? _or_die? */
1128 status = inflate_gunzip(&src_md, outbuffer,outbuflen);
1129 }
1130 else
1131 {
1132 error_msg("invalid magic");
1133 exitcode = -1;
1134 }
1135
1136 if (status < 0)
1137 {
1138 error_msg("error inflating");
1139 exitcode = -1;
1140 }
1141 }
1142 else
1143 {
1144 error_msg("invalid magic");
1145 exitcode = -1;
1146 }
1147
1148 inflate_cleanup();
1149 wpw_destroy_mempool(HUFT_MMP1);
1150 wpw_destroy_mempool(HUFT_MMP2);
1151
1152 if(exitcode==-1)
1153 return 0;
1154
1155 return ifl_total;
1156}
diff --git a/lib/rbcodec/codecs/libgme/inflate/inflate.h b/lib/rbcodec/codecs/libgme/inflate/inflate.h
new file mode 100644
index 0000000000..05164621b9
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/inflate.h
@@ -0,0 +1,30 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef INFLATE_H
21#define INFLATE_H
22#include <inttypes.h>
23
24#if defined(ROCKBOX)
25#include "codeclib.h"
26#endif
27
28uint32_t decompress(const char *inbuffer,uint32_t inbuflen,char* outbuffer,uint32_t outbuflen,
29 uint32_t offset,char* membuf);
30#endif
diff --git a/lib/rbcodec/codecs/libgme/inflate/mallocer.c b/lib/rbcodec/codecs/libgme/inflate/mallocer.c
new file mode 100644
index 0000000000..41abedd09f
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/mallocer.c
@@ -0,0 +1,86 @@
1
2/*
3 Based on the wiki viewer mallocer
4 Copyright (C) 2005 Dave Chapman
5
6 @ Modified to decompress memory buffer by gama
7 */
8
9#include "mallocer.h"
10#include "codeclib.h"
11
12unsigned char* mallocbuffer[MEMPOOL_MAX];
13long memory_ptr[MEMPOOL_MAX];
14size_t buffersize[MEMPOOL_MAX];
15
16int wpw_init_mempool(unsigned char mempool)
17{
18 memory_ptr[mempool] = 0;
19 mallocbuffer[mempool] = (unsigned char *)ci->codec_get_buffer(&buffersize[mempool]);
20 // memset(mallocbuf[mempool], 0, bufsize[mempool]);
21 return 0;
22}
23
24int wpw_init_mempool_pdm(unsigned char mempool,
25 unsigned char* mem,long memsize)
26{
27 memory_ptr[mempool] = 0;
28 mallocbuffer[mempool] = mem;
29 buffersize[mempool]=memsize;
30 return 0;
31}
32
33void wpw_reset_mempool(unsigned char mempool)
34{
35 memory_ptr[mempool]=0;
36}
37
38void wpw_destroy_mempool(unsigned char mempool)
39{
40 memory_ptr[mempool] = 0;
41 mallocbuffer[mempool] =0;
42 buffersize[mempool]=0;
43}
44
45long wpw_available(unsigned char mempool)
46{
47 return buffersize[mempool]-memory_ptr[mempool];
48}
49
50void* wpw_malloc(unsigned char mempool,size_t size)
51{
52 void* x;
53
54 if (memory_ptr[mempool] + size > buffersize[mempool] )
55 return NULL;
56
57 x=&mallocbuffer[mempool][memory_ptr[mempool]];
58 memory_ptr[mempool]+=(size+3)&~3; /* Keep memory 32-bit aligned */
59
60 return(x);
61}
62
63void* wpw_calloc(unsigned char mempool,size_t nmemb, size_t size)
64{
65 void* x;
66 x = wpw_malloc(mempool,nmemb*size);
67 if (x == NULL)
68 return NULL;
69
70 memset(x,0,nmemb*size);
71 return(x);
72}
73
74void wpw_free(unsigned char mempool,void* ptr)
75{
76 (void)ptr;
77 (void)mempool;
78}
79
80void* wpw_realloc(unsigned char mempool,void* ptr, size_t size)
81{
82 void* x;
83 (void)ptr;
84 x = wpw_malloc(mempool,size);
85 return(x);
86}
diff --git a/lib/rbcodec/codecs/libgme/inflate/mallocer.h b/lib/rbcodec/codecs/libgme/inflate/mallocer.h
new file mode 100644
index 0000000000..091643443c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/mallocer.h
@@ -0,0 +1,16 @@
1
2#define MEMPOOL_MAX 10
3#include <inttypes.h>
4#include <stdlib.h>
5
6int wpw_init_mempool(unsigned char mempool);
7int wpw_init_mempool_pdm(unsigned char mempool,
8 unsigned char* mem,long memsize);
9
10void wpw_reset_mempool(unsigned char mempool);
11void wpw_destroy_mempool(unsigned char mempool);
12void* wpw_malloc(unsigned char mempool,size_t size);
13void* wpw_calloc(unsigned char mempool,size_t nmemb, size_t size);
14void wpw_free(unsigned char mempool,void* ptr);
15void* wpw_realloc(unsigned char mempool,void* ptr, size_t size);
16long wpw_available(unsigned char mempool);
diff --git a/lib/rbcodec/codecs/libgme/inflate/mbreader.c b/lib/rbcodec/codecs/libgme/inflate/mbreader.c
new file mode 100644
index 0000000000..825787927c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/mbreader.c
@@ -0,0 +1,16 @@
1
2/* Memory buffer reader, simulates file read
3 @ gama
4*/
5
6#include "mbreader.h"
7
8int mbread(struct mbreader_t *md, void *buf, size_t n)
9{
10 if (!md) return -1;
11 size_t read_bytes = (md->offset+n) > md->size ?
12 md->size-md->offset : n;
13 memcpy(buf,md->ptr + md->offset,read_bytes);
14 md->offset += read_bytes;
15 return read_bytes;
16}
diff --git a/lib/rbcodec/codecs/libgme/inflate/mbreader.h b/lib/rbcodec/codecs/libgme/inflate/mbreader.h
new file mode 100644
index 0000000000..d345c0c424
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/inflate/mbreader.h
@@ -0,0 +1,15 @@
1
2#ifndef MBREADER_H
3#define MBREADER_H
4
5#include "codeclib.h"
6
7struct mbreader_t {
8 const char *ptr;
9 size_t size;
10 size_t offset;
11};
12
13int mbread(struct mbreader_t *md, void *buf, size_t n);
14
15#endif
diff --git a/lib/rbcodec/codecs/libgme/kss_cpu.c b/lib/rbcodec/codecs/libgme/kss_cpu.c
new file mode 100644
index 0000000000..20601e608f
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/kss_cpu.c
@@ -0,0 +1,35 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "kss_emu.h"
4
5#include "blargg_endian.h"
6//#include "z80_cpu_log.h"
7
8/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21#define OUT_PORT( addr, data ) cpu_out( this, TIME(), addr, data )
22#define IN_PORT( addr ) cpu_in( this, TIME(), addr )
23#define WRITE_MEM( addr, data ) {FLUSH_TIME(); cpu_write( this, addr, data );}
24#define IDLE_ADDR idle_addr
25
26#define CPU_BEGIN \
27bool run_cpu( struct Kss_Emu* this, kss_time_t end_time )\
28{\
29 struct Z80_Cpu *cpu = &this->cpu; \
30 Z80_set_end_time( cpu, end_time );
31
32 #include "z80_cpu_run.h"
33
34 return warning;
35}
diff --git a/lib/rbcodec/codecs/libgme/kss_emu.c b/lib/rbcodec/codecs/libgme/kss_emu.c
new file mode 100644
index 0000000000..ba80ef613e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/kss_emu.c
@@ -0,0 +1,714 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "kss_emu.h"
4
5#include "blargg_endian.h"
6
7/* Copyright (C) 2006 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20int const clock_rate = 3579545;
21
22const char gme_wrong_file_type [] = "Wrong file type for this emulator";
23
24static void clear_track_vars( struct Kss_Emu* this )
25{
26 this->current_track = -1;
27 track_stop( &this->track_filter );
28}
29
30static blargg_err_t init_opl_apu( enum opl_type_t type, struct Opl_Apu* out )
31{
32 blip_time_t const period = 72;
33 int const rate = clock_rate / period;
34 return Opl_init( out, rate * period, rate, period, type );
35}
36
37void Kss_init( struct Kss_Emu* this )
38{
39 this->sample_rate = 0;
40 this->mute_mask_ = 0;
41 this->tempo = (int)(FP_ONE_TEMPO);
42 this->gain = (int)FP_ONE_GAIN;
43 this->chip_flags = 0;
44
45 // defaults
46 this->tfilter = *track_get_setup( &this->track_filter );
47 this->tfilter.max_initial = 2;
48 this->tfilter.lookahead = 6;
49 this->track_filter.silence_ignored_ = false;
50
51 memset( this->unmapped_read, 0xFF, sizeof this->unmapped_read );
52
53 // Init all stuff
54 Buffer_init( &this->stereo_buf );
55
56 Z80_init( &this->cpu );
57 Rom_init( &this->rom, page_size );
58
59 // Initialize all apus just once (?)
60 Sms_apu_init( &this->sms.psg);
61 Ay_apu_init( &this->msx.psg );
62 Scc_init( &this->msx.scc );
63
64#ifndef KSS_EMU_NO_FMOPL
65 init_opl_apu( type_smsfmunit, &this->sms.fm );
66 init_opl_apu( type_msxmusic, &this->msx.music );
67 init_opl_apu( type_msxaudio, &this->msx.audio );
68#endif
69
70 this->voice_count = 0;
71 this->voice_types = 0;
72 clear_track_vars( this );
73}
74
75// Track info
76
77static blargg_err_t check_kss_header( void const* header )
78{
79 if ( memcmp( header, "KSCC", 4 ) && memcmp( header, "KSSX", 4 ) )
80 return gme_wrong_file_type;
81 return 0;
82}
83
84// Setup
85
86static void update_gain_( struct Kss_Emu* this )
87{
88 int g = this->gain;
89 if ( msx_music_enabled( this ) || msx_audio_enabled( this )
90 || sms_fm_enabled( this ) )
91 {
92 g = (g*3) / 4; //g *= 0.75;
93 }
94 else
95 {
96 if ( this->scc_accessed )
97 g = (g*6) / 5; //g *= 1.2;
98 }
99
100 if ( sms_psg_enabled( this ) ) Sms_apu_volume( &this->sms.psg, g );
101 if ( sms_fm_enabled( this ) ) Opl_volume( &this->sms.fm, g );
102 if ( msx_psg_enabled( this ) ) Ay_apu_volume( &this->msx.psg, g );
103 if ( msx_scc_enabled( this ) ) Scc_volume( &this->msx.scc, g );
104 if ( msx_music_enabled( this ) ) Opl_volume( &this->msx.music, g );
105 if ( msx_audio_enabled( this ) ) Opl_volume( &this->msx.audio, g );
106}
107
108static void update_gain( struct Kss_Emu* this )
109{
110 if ( this->scc_accessed )
111 {
112 /* dprintf( "SCC accessed\n" ); */
113 update_gain_( this );
114 }
115}
116
117blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size )
118{
119 /* warning( core.warning() ); */
120 memset( &this->header, 0, sizeof this->header );
121 assert( offsetof (header_t,msx_audio_vol) == header_size - 1 );
122 RETURN_ERR( Rom_load( &this->rom, data, size, header_base_size, &this->header, 0 ) );
123
124 RETURN_ERR( check_kss_header( this->header.tag ) );
125
126 this->chip_flags = 0;
127 this->header.last_track [0] = 255;
128 if ( this->header.tag [3] == 'C' )
129 {
130 if ( this->header.extra_header )
131 {
132 this->header.extra_header = 0;
133 /* warning( "Unknown data in header" ); */
134 }
135 if ( this->header.device_flags & ~0x0F )
136 {
137 this->header.device_flags &= 0x0F;
138 /* warning( "Unknown data in header" ); */
139 }
140 }
141 else if ( this->header.extra_header )
142 {
143 if ( this->header.extra_header != header_ext_size )
144 {
145 this->header.extra_header = 0;
146 /* warning( "Invalid extra_header_size" ); */
147 }
148 else
149 {
150 memcpy( this->header.data_size, this->rom.file_data, header_ext_size );
151 }
152 }
153
154 #ifndef NDEBUG
155 {
156 int ram_mode = this->header.device_flags & 0x84; // MSX
157 if ( this->header.device_flags & 0x02 ) // SMS
158 ram_mode = (this->header.device_flags & 0x88);
159
160 if ( ram_mode )
161 blargg_dprintf_( "RAM not supported\n" ); // TODO: support
162 }
163 #endif
164
165 this->track_count = get_le16( this->header.last_track ) + 1;
166 this->m3u.size = 0;
167
168 this->scc_enabled = false;
169 if ( this->header.device_flags & 0x02 ) // Sega Master System
170 {
171 int const osc_count = sms_osc_count + opl_osc_count;
172
173 // sms.psg
174 this->voice_count = sms_osc_count;
175 static int const types [sms_osc_count + opl_osc_count] = {
176 wave_type+1, wave_type+3, wave_type+2, mixed_type+1, wave_type+0
177 };
178 this->voice_types = types;
179 this->chip_flags |= sms_psg_flag;
180
181 // sms.fm
182 if ( this->header.device_flags & 0x01 )
183 {
184 this->voice_count = osc_count;
185 this->chip_flags |= sms_fm_flag;
186 }
187 }
188 else // MSX
189 {
190 int const osc_count = ay_osc_count + opl_osc_count;
191
192 // msx.psg
193 this->voice_count = ay_osc_count;
194 static int const types [ay_osc_count + opl_osc_count] = {
195 wave_type+1, wave_type+3, wave_type+2, wave_type+0
196 };
197 this->voice_types = types;
198 this->chip_flags |= msx_psg_flag;
199
200 /* if ( this->header.device_flags & 0x10 )
201 warning( "MSX stereo not supported" ); */
202
203 // msx.music
204 if ( this->header.device_flags & 0x01 )
205 {
206 this->voice_count = osc_count;
207 this->chip_flags |= msx_music_flag;
208 }
209
210 #ifndef KSS_EMU_NO_FMOPL
211 // msx.audio
212 if ( this->header.device_flags & 0x08 )
213 {
214 this->voice_count = osc_count;
215 this->chip_flags |= msx_audio_flag;
216 }
217 #endif
218
219 if ( !(this->header.device_flags & 0x80) )
220 {
221 if ( !(this->header.device_flags & 0x84) )
222 this->scc_enabled = scc_enabled_true;
223
224 // msx.scc
225 this->chip_flags |= msx_scc_flag;
226 this->voice_count = ay_osc_count + scc_osc_count;
227 static int const types [ay_osc_count + scc_osc_count] = {
228 wave_type+1, wave_type+3, wave_type+2,
229 wave_type+0, wave_type+4, wave_type+5, wave_type+6, wave_type+7,
230 };
231 this->voice_types = types;
232 }
233 }
234
235 this->tfilter.lookahead = 6;
236 if ( sms_fm_enabled( this ) || msx_music_enabled( this ) || msx_audio_enabled( this ) )
237 {
238 if ( !Opl_supported() )
239 ; /* warning( "FM sound not supported" ); */
240 else
241 this->tfilter.lookahead = 3; // Opl_Apu is really slow
242 }
243
244 this->clock_rate_ = clock_rate;
245 Buffer_clock_rate( &this->stereo_buf, clock_rate );
246 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
247 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
248
249 Sound_set_tempo( this, this->tempo );
250 Sound_mute_voices( this, this->mute_mask_ );
251 return 0;
252}
253
254static void set_voice( struct Kss_Emu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
255{
256 if ( sms_psg_enabled( this ) ) // Sega Master System
257 {
258 i -= sms_osc_count;
259 if ( i < 0 )
260 {
261 Sms_apu_set_output( &this->sms.psg, i + sms_osc_count, center, left, right );
262 return;
263 }
264
265 if ( sms_fm_enabled( this ) && i < opl_osc_count )
266 Opl_set_output( &this->sms.fm, center );
267 }
268 else if ( msx_psg_enabled( this ) ) // MSX
269 {
270 i -= ay_osc_count;
271 if ( i < 0 )
272 {
273 Ay_apu_set_output( &this->msx.psg, i + ay_osc_count, center );
274 return;
275 }
276
277 if ( msx_scc_enabled( this ) && i < scc_osc_count ) Scc_set_output( &this->msx.scc, i, center );
278 if ( msx_music_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.music, center );
279 if ( msx_audio_enabled( this ) && i < opl_osc_count ) Opl_set_output( &this->msx.audio, center );
280 }
281}
282
283// Emulation
284
285void jsr( struct Kss_Emu* this, byte const addr [] )
286{
287 this->ram [--this->cpu.r.sp] = idle_addr >> 8;
288 this->ram [--this->cpu.r.sp] = idle_addr & 0xFF;
289 this->cpu.r.pc = get_le16( addr );
290}
291
292static void set_bank( struct Kss_Emu* this, int logical, int physical )
293{
294 int const bank_size = (16 * 1024L) >> (this->header.bank_mode >> 7 & 1);
295
296 int addr = 0x8000;
297 if ( logical && bank_size == 8 * 1024 )
298 addr = 0xA000;
299
300 physical -= this->header.first_bank;
301 if ( (unsigned) physical >= (unsigned) this->bank_count )
302 {
303 byte* data = this->ram + addr;
304 Z80_map_mem( &this->cpu, addr, bank_size, data, data );
305 }
306 else
307 {
308 int offset, phys = physical * bank_size;
309 for ( offset = 0; offset < bank_size; offset += page_size )
310 Z80_map_mem( &this->cpu, addr + offset, page_size,
311 this->unmapped_write, Rom_at_addr( &this->rom, phys + offset ) );
312
313 }
314}
315
316void cpu_write( struct Kss_Emu* this, addr_t addr, int data )
317{
318 *Z80_write( &this->cpu, addr ) = data;
319 if ( (addr & this->scc_enabled) == 0x8000 ) {
320 // TODO: SCC+ support
321
322 data &= 0xFF;
323 switch ( addr )
324 {
325 case 0x9000:
326 set_bank( this, 0, data );
327 return;
328
329 case 0xB000:
330 set_bank( this, 1, data );
331 return;
332
333 case 0xBFFE: // selects between mapping areas (we just always enable both)
334 if ( data == 0 || data == 0x20 )
335 return;
336 }
337
338 int scc_addr = (addr & 0xDFFF) - 0x9800;
339 if ( msx_scc_enabled( this ) && (unsigned) scc_addr < 0xB0 )
340 {
341 this->scc_accessed = true;
342 //if ( (unsigned) (scc_addr - 0x90) < 0x10 )
343 // scc_addr -= 0x10; // 0x90-0x9F mirrors to 0x80-0x8F
344 if ( scc_addr < scc_reg_count )
345 Scc_write( &this->msx.scc, Z80_time( &this->cpu ), addr, data );
346 return;
347 }
348 }
349}
350
351void cpu_out( struct Kss_Emu* this, kss_time_t time, kss_addr_t addr, int data )
352{
353 data &= 0xFF;
354 switch ( addr & 0xFF )
355 {
356 case 0xA0:
357 if ( msx_psg_enabled( this ) )
358 Ay_apu_write_addr( &this->msx.psg, data );
359 return;
360
361 case 0xA1:
362 if ( msx_psg_enabled( this ) )
363 Ay_apu_write_data( &this->msx.psg, time, data );
364 return;
365
366 case 0x06:
367 if ( sms_psg_enabled( this ) && (this->header.device_flags & 0x04) )
368 {
369 Sms_apu_write_ggstereo( &this->sms.psg, time, data );
370 return;
371 }
372 break;
373
374 case 0x7E:
375 case 0x7F:
376 if ( sms_psg_enabled( this ) )
377 {
378 Sms_apu_write_data( &this->sms.psg, time, data );
379 return;
380 }
381 break;
382
383 #define OPL_WRITE_HANDLER( base, name, opl )\
384 case base : if ( name##_enabled( this ) ) { Opl_write_addr( opl, data ); return; } break;\
385 case base+1: if ( name##_enabled( this ) ) { Opl_write_data( opl, time, data ); return; } break;
386
387 OPL_WRITE_HANDLER( 0x7C, msx_music, &this->msx.music )
388 OPL_WRITE_HANDLER( 0xC0, msx_audio, &this->msx.audio )
389 OPL_WRITE_HANDLER( 0xF0, sms_fm, &this->sms.fm )
390
391 case 0xFE:
392 set_bank( this, 0, data );
393 return;
394
395 #ifndef NDEBUG
396 case 0xA8: // PPI
397 return;
398 #endif
399 }
400
401 /* cpu_out( time, addr, data ); */
402}
403
404int cpu_in( struct Kss_Emu* this, kss_time_t time, kss_addr_t addr )
405{
406 switch ( addr & 0xFF )
407 {
408 case 0xC0:
409 case 0xC1:
410 if ( msx_audio_enabled( this ) )
411 return Opl_read( &this->msx.audio, time, addr & 1 );
412 break;
413
414 case 0xA2:
415 if ( msx_psg_enabled( this ) )
416 return Ay_apu_read( &this->msx.psg );
417 break;
418
419 #ifndef NDEBUG
420 case 0xA8: // PPI
421 return 0;
422 #endif
423 }
424
425 /* return cpu_in( time, addr ); */
426 return 0xFF;
427}
428
429static blargg_err_t run_clocks( struct Kss_Emu* this, blip_time_t* duration_ )
430{
431 blip_time_t duration = *duration_;
432 RETURN_ERR( end_frame( this, duration ) );
433
434 if ( sms_psg_enabled( this ) ) Sms_apu_end_frame( &this->sms.psg, duration );
435 if ( sms_fm_enabled( this ) ) Opl_end_frame( &this->sms.fm, duration );
436 if ( msx_psg_enabled( this ) ) Ay_apu_end_frame( &this->msx.psg, duration );
437 if ( msx_scc_enabled( this ) ) Scc_end_frame( &this->msx.scc, duration );
438 if ( msx_music_enabled( this ) ) Opl_end_frame( &this->msx.music, duration );
439 if ( msx_audio_enabled( this ) ) Opl_end_frame( &this->msx.audio, duration );
440
441 return 0;
442}
443
444blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t end )
445{
446 while ( Z80_time( &this->cpu ) < end )
447 {
448 kss_time_t next = min( end, this->next_play );
449 run_cpu( this, next );
450 if ( this->cpu.r.pc == idle_addr )
451 Z80_set_time( &this->cpu, next );
452
453 if ( Z80_time( &this->cpu ) >= this->next_play )
454 {
455 this->next_play += this->play_period;
456 if ( this->cpu.r.pc == idle_addr )
457 {
458 if ( !this->gain_updated )
459 {
460 this->gain_updated = true;
461 update_gain( this );
462 }
463
464 jsr( this, this->header.play_addr );
465 }
466 }
467 }
468
469 this->next_play -= end;
470 check( this->next_play >= 0 );
471 Z80_adjust_time( &this->cpu, -end );
472
473 return 0;
474}
475
476// MUSIC
477
478blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, int rate )
479{
480 require( !this->sample_rate ); // sample rate can't be changed once set
481 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
482
483 // Set bass frequency
484 Buffer_bass_freq( &this->stereo_buf, 180 );
485
486 this->sample_rate = rate;
487 RETURN_ERR( track_init( &this->track_filter, this ) );
488 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
489 return 0;
490}
491
492void Sound_mute_voice( struct Kss_Emu* this, int index, bool mute )
493{
494 require( (unsigned) index < (unsigned) this->voice_count );
495 int bit = 1 << index;
496 int mask = this->mute_mask_ | bit;
497 if ( !mute )
498 mask ^= bit;
499 Sound_mute_voices( this, mask );
500}
501
502void Sound_mute_voices( struct Kss_Emu* this, int mask )
503{
504 require( this->sample_rate ); // sample rate must be set first
505 this->mute_mask_ = mask;
506
507 int i;
508 for ( i = this->voice_count; i--; )
509 {
510 if ( mask & (1 << i) )
511 {
512 set_voice( this, i, 0, 0, 0 );
513 }
514 else
515 {
516 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
517 assert( (ch.center && ch.left && ch.right) ||
518 (!ch.center && !ch.left && !ch.right) ); // all or nothing
519 set_voice( this, i, ch.center, ch.left, ch.right );
520 }
521 }
522}
523
524void Sound_set_tempo( struct Kss_Emu* this, int t )
525{
526 require( this->sample_rate ); // sample rate must be set first
527 int const min = (int)(FP_ONE_TEMPO*0.02);
528 int const max = (int)(FP_ONE_TEMPO*4.00);
529 if ( t < min ) t = min;
530 if ( t > max ) t = max;
531 this->tempo = t;
532
533 blip_time_t period =
534 (this->header.device_flags & 0x40 ? clock_rate / 50 : clock_rate / 60);
535 this->play_period = (blip_time_t) ((period * FP_ONE_TEMPO) / t);
536}
537
538blargg_err_t Kss_start_track( struct Kss_Emu* this, int track )
539{
540 clear_track_vars( this );
541
542 // Remap track if playlist available
543 if ( this->m3u.size > 0 ) {
544 struct entry_t* e = &this->m3u.entries[track];
545 track = e->track;
546 }
547
548 this->current_track = track;
549
550 Buffer_clear( &this->stereo_buf );
551
552 if ( sms_psg_enabled( this ) ) Sms_apu_reset( &this->sms.psg, 0, 0 );
553 if ( sms_fm_enabled( this ) ) Opl_reset( &this->sms.fm );
554 if ( msx_psg_enabled( this ) ) Ay_apu_reset( &this->msx.psg );
555 if ( msx_scc_enabled( this ) ) Scc_reset( &this->msx.scc );
556 if ( msx_music_enabled( this ) ) Opl_reset( &this->msx.music );
557 if ( msx_audio_enabled( this ) ) Opl_reset( &this->msx.audio );
558
559 this->scc_accessed = false;
560 update_gain_( this );
561
562 memset( this->ram, 0xC9, 0x4000 );
563 memset( this->ram + 0x4000, 0, sizeof this->ram - 0x4000 );
564
565 // copy driver code to lo RAM
566 static byte const bios [] = {
567 0xD3, 0xA0, 0xF5, 0x7B, 0xD3, 0xA1, 0xF1, 0xC9, // $0001: WRTPSG
568 0xD3, 0xA0, 0xDB, 0xA2, 0xC9 // $0009: RDPSG
569 };
570 static byte const vectors [] = {
571 0xC3, 0x01, 0x00, // $0093: WRTPSG vector
572 0xC3, 0x09, 0x00, // $0096: RDPSG vector
573 };
574 memcpy( this->ram + 0x01, bios, sizeof bios );
575 memcpy( this->ram + 0x93, vectors, sizeof vectors );
576
577 // copy non-banked data into RAM
578 int load_addr = get_le16( this->header.load_addr );
579 int orig_load_size = get_le16( this->header.load_size );
580 int load_size = min( orig_load_size, (int) this->rom.file_size );
581 load_size = min( load_size, (int) mem_size - load_addr );
582 /* if ( load_size != orig_load_size )
583 warning( "Excessive data size" ); */
584 memcpy( this->ram + load_addr, this->rom.file_data + this->header.extra_header, load_size );
585
586 Rom_set_addr( &this->rom, -load_size - this->header.extra_header );
587
588 // check available bank data
589 int const bank_size = (16 * 1024L) >> (this->header.bank_mode >> 7 & 1);
590 int max_banks = (this->rom.file_size - load_size + bank_size - 1) / bank_size;
591 this->bank_count = this->header.bank_mode & 0x7F;
592 if ( this->bank_count > max_banks )
593 {
594 this->bank_count = max_banks;
595 /* warning( "Bank data missing" ); */
596 }
597 //dprintf( "load_size : $%X\n", load_size );
598 //dprintf( "bank_size : $%X\n", bank_size );
599 //dprintf( "bank_count: %d (%d claimed)\n", bank_count, this->header.bank_mode & 0x7F );
600
601 this->ram [idle_addr] = 0xFF;
602 Z80_reset( &this->cpu, this->unmapped_write, this->unmapped_read );
603 Z80_map_mem( &this->cpu, 0, mem_size, this->ram, this->ram );
604
605 this->cpu.r.sp = 0xF380;
606 this->cpu.r.b.a = track;
607 this->cpu.r.b.h = 0;
608 this->next_play = this->play_period;
609 this->gain_updated = false;
610 jsr( this, this->header.init_addr );
611
612 // convert filter times to samples
613 struct setup_t s = this->tfilter;
614 s.max_initial *= this->sample_rate * stereo;
615 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
616 s.lookahead = 1;
617 #endif
618 track_setup( &this->track_filter, &s );
619
620 return track_start( &this->track_filter );
621}
622
623// Tell/Seek
624
625static int msec_to_samples( int msec, int sample_rate )
626{
627 int sec = msec / 1000;
628 msec -= sec * 1000;
629 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
630}
631
632int Track_tell( struct Kss_Emu* this )
633{
634 int rate = this->sample_rate * stereo;
635 int sec = track_sample_count( &this->track_filter ) / rate;
636 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
637}
638
639blargg_err_t Track_seek( struct Kss_Emu* this, int msec )
640{
641 int time = msec_to_samples( msec, this->sample_rate );
642 if ( time < track_sample_count( &this->track_filter ) )
643 RETURN_ERR( Kss_start_track( this, this->current_track ) );
644 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
645}
646
647blargg_err_t skip_( void *emu, int count )
648{
649 struct Kss_Emu* this = (struct Kss_Emu*) emu;
650
651 // for long skip, mute sound
652 const int threshold = 32768;
653 if ( count > threshold )
654 {
655 int saved_mute = this->mute_mask_;
656 Sound_mute_voices( this, ~0 );
657
658 int n = count - threshold/2;
659 n &= ~(2048-1); // round to multiple of 2048
660 count -= n;
661 RETURN_ERR( skippy_( &this->track_filter, n ) );
662
663 Sound_mute_voices( this, saved_mute );
664 }
665
666 return skippy_( &this->track_filter, count );
667}
668
669blargg_err_t Track_skip( struct Kss_Emu* this, int count )
670{
671 require( this->current_track >= 0 ); // start_track() must have been called already
672 return track_skip( &this->track_filter, count );
673}
674
675void Track_set_fade( struct Kss_Emu* this, int start_msec, int length_msec )
676{
677 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
678 length_msec * this->sample_rate / (1000 / stereo) );
679}
680
681blargg_err_t Kss_play( struct Kss_Emu* this, int out_count, sample_t* out )
682{
683 require( this->current_track >= 0 );
684 require( out_count % stereo == 0 );
685 return track_play( &this->track_filter, out_count, out );
686}
687
688blargg_err_t play_( void *emu, int count, sample_t* out )
689{
690 struct Kss_Emu* this = (struct Kss_Emu*) emu;
691
692 int remain = count;
693 while ( remain )
694 {
695 Buffer_disable_immediate_removal( &this->stereo_buf );
696 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
697 if ( remain )
698 {
699 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
700 {
701 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
702
703 // Remute voices
704 Sound_mute_voices( this, this->mute_mask_ );
705 }
706 int msec = Buffer_length( &this->stereo_buf );
707 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
708 RETURN_ERR( run_clocks( this, &clocks_emulated ) );
709 assert( clocks_emulated );
710 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
711 }
712 }
713 return 0;
714}
diff --git a/lib/rbcodec/codecs/libgme/kss_emu.h b/lib/rbcodec/codecs/libgme/kss_emu.h
new file mode 100644
index 0000000000..382e4b807b
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/kss_emu.h
@@ -0,0 +1,223 @@
1// MSX computer KSS music file emulator
2
3// Game_Music_Emu 0.5.5
4#ifndef KSS_EMU_H
5#define KSS_EMU_H
6
7#include "gme.h"
8#include "blargg_common.h"
9
10#include "rom_data.h"
11#include "multi_buffer.h"
12
13#include "kss_scc_apu.h"
14#include "z80_cpu.h"
15#include "sms_apu.h"
16#include "ay_apu.h"
17#include "opl_apu.h"
18#include "m3u_playlist.h"
19#include "track_filter.h"
20
21typedef int kss_time_t;
22typedef int kss_addr_t;
23typedef struct Z80_Cpu Kss_Cpu;
24
25// Sound chip flags
26enum {
27 sms_psg_flag = 1 << 0,
28 sms_fm_flag = 1 << 1,
29 msx_psg_flag = 1 << 2,
30 msx_scc_flag = 1 << 3,
31 msx_music_flag = 1 << 4,
32 msx_audio_flag = 1 << 5
33};
34
35enum { idle_addr = 0xFFFF };
36enum { scc_enabled_true = 0xC000 };
37enum { mem_size = 0x10000 };
38
39// KSS file header
40enum { header_size = 0x20 };
41enum { header_base_size = 0x10 };
42enum { header_ext_size = header_size - header_base_size };
43
44struct header_t
45{
46 byte tag [4];
47 byte load_addr [2];
48 byte load_size [2];
49 byte init_addr [2];
50 byte play_addr [2];
51 byte first_bank;
52 byte bank_mode;
53 byte extra_header;
54 byte device_flags;
55
56 // KSSX extended data, if extra_header==0x10
57 byte data_size [4];
58 byte unused [4];
59 byte first_track [2];
60 byte last_track [2]; // if no extended data, we set this to 0xFF
61 byte psg_vol;
62 byte scc_vol;
63 byte msx_music_vol;
64 byte msx_audio_vol;
65};
66
67struct sms_t {
68 struct Sms_Apu psg;
69 struct Opl_Apu fm;
70};
71
72struct msx_t {
73 struct Ay_Apu psg;
74 struct Scc_Apu scc;
75 struct Opl_Apu music;
76 struct Opl_Apu audio;
77};
78
79struct Kss_Emu {
80 struct header_t header;
81
82 int chip_flags;
83 bool scc_accessed;
84 bool gain_updated;
85
86 unsigned scc_enabled; // 0 or 0xC000
87 int bank_count;
88
89 blip_time_t play_period;
90 blip_time_t next_play;
91 int ay_latch;
92
93 // general
94 int voice_count;
95 int const* voice_types;
96 int mute_mask_;
97 int tempo;
98 int gain;
99
100 int sample_rate;
101
102 // track-specific
103 int track_count;
104 int current_track;
105
106 int clock_rate_;
107 unsigned buf_changed_count;
108
109 // M3u Playlist
110 struct M3u_Playlist m3u;
111
112 struct setup_t tfilter;
113 struct Track_Filter track_filter;
114
115 struct sms_t sms;
116 struct msx_t msx;
117
118 Kss_Cpu cpu;
119 struct Multi_Buffer stereo_buf; // NULL if using custom buffer
120 struct Rom_Data rom;
121
122 byte unmapped_read [0x100];
123 byte unmapped_write [page_size];
124 byte ram [mem_size + cpu_padding];
125};
126
127// Basic functionality (see Gme_File.h for file loading/track info functions)
128
129void Kss_init( struct Kss_Emu* this );
130blargg_err_t Kss_load_mem( struct Kss_Emu* this, const void* data, long size );
131blargg_err_t end_frame( struct Kss_Emu* this, kss_time_t );
132
133// Set output sample rate. Must be called only once before loading file.
134blargg_err_t Kss_set_sample_rate( struct Kss_Emu* this, int sample_rate );
135
136// Start a track, where 0 is the first track. Also clears warning string.
137blargg_err_t Kss_start_track( struct Kss_Emu* this, int track );
138
139// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
140// errors set warning string, and major errors also end track.
141blargg_err_t Kss_play( struct Kss_Emu* this, int count, sample_t* buf );
142
143// Track status/control
144
145// Number of milliseconds (1000 msec = 1 second) played since beginning of track
146int Track_tell( struct Kss_Emu* this );
147
148// Seek to new time in track. Seeking backwards or far forward can take a while.
149blargg_err_t Track_seek( struct Kss_Emu* this, int msec );
150
151// Skip n samples
152blargg_err_t Track_skip( struct Kss_Emu* this, int n );
153
154// Set start time and length of track fade out. Once fade ends track_ended() returns
155// true. Fade time can be changed while track is playing.
156void Track_set_fade( struct Kss_Emu* this, int start_msec, int length_msec );
157
158// True if a track has reached its end
159static inline bool Track_ended( struct Kss_Emu* this )
160{
161 return track_ended( &this->track_filter );
162}
163
164// Disables automatic end-of-track detection and skipping of silence at beginning
165static inline void Track_ignore_silence( struct Kss_Emu* this, bool disable )
166{
167 this->track_filter.silence_ignored_ = disable;
168}
169
170// Get track length in milliseconds
171static inline int Track_get_length( struct Kss_Emu* this, int n )
172{
173 int length = 0;
174
175 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
176 struct entry_t* entry = &this->m3u.entries [n];
177 length = entry->length;
178 }
179
180 if ( length <= 0 )
181 length = 120 * 1000; /* 2 minutes */
182
183 return length;
184}
185
186// Sound customization
187
188// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
189// Track length as returned by track_info() assumes a tempo of 1.0.
190void Sound_set_tempo( struct Kss_Emu* this, int t );
191
192// Mute/unmute voice i, where voice 0 is first voice
193void Sound_mute_voice( struct Kss_Emu* this, int index, bool mute );
194
195// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
196// 0 unmutes them all, 0x01 mutes just the first voice, etc.
197void Sound_mute_voices( struct Kss_Emu* this, int mask );
198
199// Change overall output amplitude, where 1.0 results in minimal clamping.
200// Must be called before set_sample_rate().
201static inline void Sound_set_gain( struct Kss_Emu* this, int g )
202{
203 assert( !this->sample_rate ); // you must set gain before setting sample rate
204 this->gain = g;
205}
206
207// Emulation (You shouldn't touch these
208void cpu_write( struct Kss_Emu* this, kss_addr_t, int );
209int cpu_in( struct Kss_Emu* this, kss_time_t, kss_addr_t );
210void cpu_out( struct Kss_Emu* this, kss_time_t, kss_addr_t, int );
211
212void cpu_write_( struct Kss_Emu* this, kss_addr_t addr, int data );
213bool run_cpu( struct Kss_Emu* this, kss_time_t end );
214void jsr( struct Kss_Emu* this, byte const addr [] );
215
216static inline int sms_psg_enabled( struct Kss_Emu* this ) { return this->chip_flags & sms_psg_flag; }
217static inline int sms_fm_enabled( struct Kss_Emu* this ) { return this->chip_flags & sms_fm_flag; }
218static inline int msx_psg_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_psg_flag; }
219static inline int msx_scc_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_scc_flag; }
220static inline int msx_music_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_music_flag;}
221static inline int msx_audio_enabled( struct Kss_Emu* this ) { return this->chip_flags & msx_audio_flag;}
222
223#endif
diff --git a/lib/rbcodec/codecs/libgme/kss_scc_apu.c b/lib/rbcodec/codecs/libgme/kss_scc_apu.c
new file mode 100644
index 0000000000..1bec9b7f0e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/kss_scc_apu.c
@@ -0,0 +1,166 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "kss_scc_apu.h"
4
5/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18// Tones above this frequency are treated as disabled tone at half volume.
19// Power of two is more efficient (avoids division).
20extern int const inaudible_freq;
21
22int const wave_size = 0x20;
23
24static void set_output( struct Scc_Apu* this, struct Blip_Buffer* buf )
25{
26 int i;
27 for ( i = 0; i < scc_osc_count; ++i )
28 Scc_set_output( this, i, buf );
29}
30
31void Scc_volume( struct Scc_Apu* this, int v )
32{
33 Synth_volume( &this->synth, (v/2 - (v*7)/100) / scc_osc_count / scc_amp_range );
34}
35
36void Scc_reset( struct Scc_Apu* this )
37{
38 this->last_time = 0;
39
40 int i;
41 for ( i = scc_osc_count; --i >= 0; )
42 memset( &this->oscs [i], 0, offsetof (struct scc_osc_t,output) );
43
44 memset( this->regs, 0, sizeof this->regs );
45}
46
47void Scc_init( struct Scc_Apu* this )
48{
49 Synth_init( &this->synth);
50
51 set_output( this, NULL );
52 Scc_volume( this, (int)FP_ONE_VOLUME );
53 Scc_reset( this );
54}
55
56static void run_until( struct Scc_Apu* this, blip_time_t end_time )
57{
58 int index;
59 for ( index = 0; index < scc_osc_count; index++ )
60 {
61 struct scc_osc_t* osc = &this->oscs [index];
62
63 struct Blip_Buffer* const output = osc->output;
64 if ( !output )
65 continue;
66
67 blip_time_t period = (this->regs [0xA0 + index * 2 + 1] & 0x0F) * 0x100 +
68 this->regs [0xA0 + index * 2] + 1;
69 int volume = 0;
70 if ( this->regs [0xAF] & (1 << index) )
71 {
72 blip_time_t inaudible_period = (unsigned) (Blip_clock_rate( output ) +
73 inaudible_freq * 32) / (unsigned) (inaudible_freq * 16);
74 if ( period > inaudible_period )
75 volume = (this->regs [0xAA + index] & 0x0F) * (scc_amp_range / 256 / 15);
76 }
77
78 int8_t const* wave = (int8_t*) this->regs + index * wave_size;
79 /*if ( index == osc_count - 1 )
80 wave -= wave_size; // last two oscs share same wave RAM*/
81
82 {
83 int delta = wave [osc->phase] * volume - osc->last_amp;
84 if ( delta )
85 {
86 osc->last_amp += delta;
87 Blip_set_modified( output );
88 Synth_offset( &this->synth, this->last_time, delta, output );
89 }
90 }
91
92 blip_time_t time = this->last_time + osc->delay;
93 if ( time < end_time )
94 {
95 int phase = osc->phase;
96 if ( !volume )
97 {
98 // maintain phase
99 int count = (end_time - time + period - 1) / period;
100 phase += count; // will be masked below
101 time += count * period;
102 }
103 else
104 {
105 int last_wave = wave [phase];
106 phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop
107 do
108 {
109 int delta = wave [phase] - last_wave;
110 phase = (phase + 1) & (wave_size - 1);
111 if ( delta )
112 {
113 last_wave += delta;
114 Synth_offset_inline( &this->synth, time, delta * volume, output );
115 }
116 time += period;
117 }
118 while ( time < end_time );
119
120 osc->last_amp = last_wave * volume;
121 Blip_set_modified( output );
122 phase--; // undo pre-advance
123 }
124 osc->phase = phase & (wave_size - 1);
125 }
126 osc->delay = time - end_time;
127 }
128 this->last_time = end_time;
129}
130
131void Scc_write( struct Scc_Apu* this, blip_time_t time, int addr, int data )
132{
133 //assert( (unsigned) addr < reg_count );
134 assert( ( addr >= 0x9800 && addr <= 0x988F ) || ( addr >= 0xB800 && addr <= 0xB8AF ) );
135 run_until( this, time );
136
137 addr -= 0x9800;
138 if ( ( unsigned ) addr < 0x90 )
139 {
140 if ( ( unsigned ) addr < 0x60 )
141 this->regs [addr] = data;
142 else if ( ( unsigned ) addr < 0x80 )
143 {
144 this->regs [addr] = this->regs[addr + 0x20] = data;
145 }
146 else if ( ( unsigned ) addr < 0x90 )
147 {
148 this->regs [addr + 0x20] = data;
149 }
150 }
151 else
152 {
153 addr -= 0xB800 - 0x9800;
154 if ( ( unsigned ) addr < 0xB0 )
155 this->regs [addr] = data;
156 }
157}
158
159void Scc_end_frame( struct Scc_Apu* this, blip_time_t end_time )
160{
161 if ( end_time > this->last_time )
162 run_until( this, end_time );
163
164 this->last_time -= end_time;
165 assert( this->last_time >= 0 );
166}
diff --git a/lib/rbcodec/codecs/libgme/kss_scc_apu.h b/lib/rbcodec/codecs/libgme/kss_scc_apu.h
new file mode 100644
index 0000000000..a6962469ac
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/kss_scc_apu.h
@@ -0,0 +1,51 @@
1// Konami SCC sound chip emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef KSS_SCC_APU_H
5#define KSS_SCC_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10enum { scc_reg_count = 0xB0 }; // 0 <= reg < reg_count
11enum { scc_osc_count = 5 };
12enum { scc_amp_range = 0x8000 };
13
14struct scc_osc_t
15{
16 int delay;
17 int phase;
18 int last_amp;
19 struct Blip_Buffer* output;
20};
21
22struct Scc_Apu {
23 struct scc_osc_t oscs [scc_osc_count];
24 blip_time_t last_time;
25 unsigned char regs [scc_reg_count];
26
27 struct Blip_Synth synth;
28};
29
30void Scc_init( struct Scc_Apu* this );
31
32// Resets sound chip
33void Scc_reset( struct Scc_Apu* this );
34
35// Set overall volume, where 1.0 is normal
36void Scc_volume( struct Scc_Apu* this, int v );
37
38static inline void Scc_set_output( struct Scc_Apu* this, int index, struct Blip_Buffer* b )
39{
40 assert( (unsigned) index < scc_osc_count );
41 this->oscs [index].output = b;
42}
43
44// Emulates to time t, then writes data to reg
45void Scc_write( struct Scc_Apu* this, blip_time_t time, int addr, int data );
46
47// Emulates to time t, then subtracts t from the current time.
48// OK if previous write call had time slightly after t.
49void Scc_end_frame( struct Scc_Apu* this, blip_time_t end_time );
50
51#endif
diff --git a/lib/rbcodec/codecs/libgme/libay.make b/lib/rbcodec/codecs/libgme/libay.make
new file mode 100644
index 0000000000..135ad041d3
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libay.make
@@ -0,0 +1,10 @@
1
2# libay
3AYLIB := $(CODECDIR)/libay.a
4AYLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/AYSOURCES)
5AYLIB_OBJ := $(call c2obj, $(AYLIB_SRC))
6OTHER_SRC += $(AYLIB_SRC)
7
8$(AYLIB): $(AYLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libemu2413.make b/lib/rbcodec/codecs/libgme/libemu2413.make
new file mode 100644
index 0000000000..4d596dd93e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libemu2413.make
@@ -0,0 +1,10 @@
1
2# libemu2413
3EMU2413LIB := $(CODECDIR)/libemu2413.a
4EMU2413LIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/EMU2413SOURCES)
5EMU2413LIB_OBJ := $(call c2obj, $(EMU2413LIB_SRC))
6OTHER_SRC += $(EMU2413LIB_SRC)
7
8$(EMU2413LIB): $(EMU2413LIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libgbs.make b/lib/rbcodec/codecs/libgme/libgbs.make
new file mode 100644
index 0000000000..c6f872d6be
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libgbs.make
@@ -0,0 +1,10 @@
1
2# libgbs
3GBSLIB := $(CODECDIR)/libgbs.a
4GBSLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/GBSSOURCES)
5GBSLIB_OBJ := $(call c2obj, $(GBSLIB_SRC))
6OTHER_SRC += $(GBSLIB_SRC)
7
8$(GBSLIB): $(GBSLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libhes.make b/lib/rbcodec/codecs/libgme/libhes.make
new file mode 100644
index 0000000000..1d99f6a192
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libhes.make
@@ -0,0 +1,10 @@
1
2# libhes
3HESLIB := $(CODECDIR)/libhes.a
4HESLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/HESSOURCES)
5HESLIB_OBJ := $(call c2obj, $(HESLIB_SRC))
6OTHER_SRC += $(HESLIB_SRC)
7
8$(HESLIB): $(HESLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libkss.make b/lib/rbcodec/codecs/libgme/libkss.make
new file mode 100644
index 0000000000..fc12bc22b4
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libkss.make
@@ -0,0 +1,10 @@
1
2# libkss
3KSSLIB := $(CODECDIR)/libkss.a
4KSSLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/KSSSOURCES)
5KSSLIB_OBJ := $(call c2obj, $(KSSLIB_SRC))
6OTHER_SRC += $(KSSLIB_SRC)
7
8$(KSSLIB): $(KSSLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libnsf.make b/lib/rbcodec/codecs/libgme/libnsf.make
new file mode 100644
index 0000000000..1e7d56b88a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libnsf.make
@@ -0,0 +1,10 @@
1
2# libnsf
3NSFLIB := $(CODECDIR)/libnsf.a
4NSFLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/NSFSOURCES)
5NSFLIB_OBJ := $(call c2obj, $(NSFLIB_SRC))
6OTHER_SRC += $(NSFLIB_SRC)
7
8$(NSFLIB): $(NSFLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libsgc.make b/lib/rbcodec/codecs/libgme/libsgc.make
new file mode 100644
index 0000000000..3caa3abd05
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libsgc.make
@@ -0,0 +1,10 @@
1
2# libsgc
3SGCLIB := $(CODECDIR)/libsgc.a
4SGCLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/SGCSOURCES)
5SGCLIB_OBJ := $(call c2obj, $(SGCLIB_SRC))
6OTHER_SRC += $(SGCLIB_SRC)
7
8$(SGCLIB): $(SGCLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/libvgm.make b/lib/rbcodec/codecs/libgme/libvgm.make
new file mode 100644
index 0000000000..24efc6ae3d
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/libvgm.make
@@ -0,0 +1,10 @@
1
2# libvgm
3VGMLIB := $(CODECDIR)/libvgm.a
4VGMLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libgme/VGMSOURCES)
5VGMLIB_OBJ := $(call c2obj, $(VGMLIB_SRC))
6OTHER_SRC += $(VGMLIB_SRC)
7
8$(VGMLIB): $(VGMLIB_OBJ)
9 $(SILENT)$(shell rm -f $@)
10 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
diff --git a/lib/rbcodec/codecs/libgme/m3u_playlist.h b/lib/rbcodec/codecs/libgme/m3u_playlist.h
new file mode 100644
index 0000000000..06a5d3024b
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/m3u_playlist.h
@@ -0,0 +1,31 @@
1// M3U entries parser, with support for subtrack information
2
3// Game_Music_Emu 0.5.2
4#ifndef M3U_PLAYLIST_H
5#define M3U_PLAYILST_H
6
7#include "blargg_common.h"
8
9struct entry_t
10{
11 unsigned char track; // 1-based
12 int length; // milliseconds
13};
14
15/* Short version of the m3u playlist */
16struct M3u_Playlist
17{
18 unsigned char size;
19 struct entry_t *entries;
20};
21
22static inline void M3u_load_data(struct M3u_Playlist* this, void *addr)
23{
24 if( addr == NULL ) return;
25 /* m3u entries data must be at offset 100,
26 the first 99 bytes are used by metadata info */
27 this->size = *(unsigned char *)(addr + 99);
28 this->entries = (struct entry_t *)(addr+100);
29}
30
31#endif
diff --git a/lib/rbcodec/codecs/libgme/msxtypes.h b/lib/rbcodec/codecs/libgme/msxtypes.h
new file mode 100644
index 0000000000..6224e0760c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/msxtypes.h
@@ -0,0 +1,36 @@
1#ifndef MSX_TYPES
2#define MSX_TYPES
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8
9#ifdef __GNUC__
10#define __int64 long long
11#endif
12
13#ifdef _WIN32
14#define DIR_SEPARATOR "\\"
15#else
16#define DIR_SEPARATOR "/"
17#endif
18
19/* So far, only support for MSVC types
20 */
21typedef unsigned char UInt8;
22#ifndef __CARBON__
23typedef unsigned short UInt16;
24typedef unsigned int UInt32;
25typedef unsigned __int64 UInt64;
26#endif
27typedef signed char Int8;
28typedef signed short Int16;
29typedef signed int Int32;
30
31#ifdef __cplusplus
32}
33#endif
34
35
36#endif
diff --git a/lib/rbcodec/codecs/libgme/multi_buffer.c b/lib/rbcodec/codecs/libgme/multi_buffer.c
new file mode 100644
index 0000000000..554778c3de
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/multi_buffer.c
@@ -0,0 +1,286 @@
1// Multi_Buffer 0.4.1. http://www.slack.net/~ant/
2
3#include "multi_buffer.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18// Tracked_Blip_Buffer
19
20int const blip_buffer_extra = 32; // TODO: explain why this value
21
22void Tracked_init( struct Tracked_Blip_Buffer* this )
23{
24 Blip_init( &this->blip );
25 this->last_non_silence = 0;
26}
27
28void Tracked_clear( struct Tracked_Blip_Buffer* this )
29{
30 this->last_non_silence = 0;
31 Blip_clear( &this->blip );
32}
33
34void Tracked_end_frame( struct Tracked_Blip_Buffer* this, blip_time_t t )
35{
36 Blip_end_frame( &this->blip, t );
37 if ( this->blip.modified )
38 {
39 this->blip.modified = false;
40 this->last_non_silence = Blip_samples_avail( &this->blip ) + blip_buffer_extra;
41 }
42}
43
44unsigned Tracked_non_silent( struct Tracked_Blip_Buffer* this )
45{
46 return this->last_non_silence | unsettled( &this->blip );
47}
48
49static inline void remove_( struct Tracked_Blip_Buffer* this, int n )
50{
51 if ( (this->last_non_silence -= n) < 0 )
52 this->last_non_silence = 0;
53}
54
55void Tracked_remove_silence( struct Tracked_Blip_Buffer* this, int n )
56{
57 remove_( this, n );
58 Blip_remove_silence( &this->blip, n );
59}
60
61void Tracked_remove_samples( struct Tracked_Blip_Buffer* this, int n )
62{
63 remove_( this, n );
64 Blip_remove_samples( &this->blip, n );
65}
66
67void Tracked_remove_all_samples( struct Tracked_Blip_Buffer* this )
68{
69 int avail = Blip_samples_avail( &this->blip );
70 if ( !Tracked_non_silent( this ) )
71 Tracked_remove_silence( this, avail );
72 else
73 Tracked_remove_samples( this, avail );
74}
75
76int Tracked_read_samples( struct Tracked_Blip_Buffer* this, blip_sample_t out [], int count )
77{
78 count = Blip_read_samples( &this->blip, out, count, false );
79 remove_( this, count );
80 return count;
81}
82
83// Stereo_Mixer
84
85// mixers use a single index value to improve performance on register-challenged processors
86// offset goes from negative to zero
87
88void Mixer_init( struct Stereo_Mixer* this )
89{
90 this->samples_read = 0;
91}
92
93static void mix_mono( struct Stereo_Mixer* this, blip_sample_t out_ [], int count )
94{
95 int const bass = this->bufs [2]->blip.bass_shift_;
96 delta_t const* center = this->bufs [2]->blip.buffer_ + this->samples_read;
97 int center_sum = this->bufs [2]->blip.reader_accum_;
98
99 typedef blip_sample_t stereo_blip_sample_t [stereo];
100 stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
101 int offset = -count;
102 do
103 {
104 int s = center_sum >> delta_bits;
105
106 center_sum -= center_sum >> bass;
107 center_sum += center [offset];
108
109 BLIP_CLAMP( s, s );
110
111 out [offset] [0] = (blip_sample_t) s;
112 out [offset] [1] = (blip_sample_t) s;
113 }
114 while ( ++offset );
115
116 this->bufs [2]->blip.reader_accum_ = center_sum;
117}
118
119static void mix_stereo( struct Stereo_Mixer* this, blip_sample_t out_ [], int count )
120{
121 blip_sample_t* BLARGG_RESTRICT out = out_ + count * stereo;
122 // do left + center and right + center separately to reduce register load
123 struct Tracked_Blip_Buffer* const* buf = &this->bufs [2];
124 while ( true ) // loop runs twice
125 {
126 --buf;
127 --out;
128
129 int const bass = this->bufs [2]->blip.bass_shift_;
130 delta_t const* side = (*buf)->blip.buffer_ + this->samples_read;
131 delta_t const* center = this->bufs [2]->blip.buffer_ + this->samples_read;
132
133 int side_sum = (*buf)->blip.reader_accum_;
134 int center_sum = this->bufs [2]->blip.reader_accum_;
135
136 int offset = -count;
137 do
138 {
139 int s = (center_sum + side_sum) >> delta_bits;
140
141 side_sum -= side_sum >> bass;
142 center_sum -= center_sum >> bass;
143
144 side_sum += side [offset];
145 center_sum += center [offset];
146
147 BLIP_CLAMP( s, s );
148
149 ++offset; // before write since out is decremented to slightly before end
150 out [offset * stereo] = (blip_sample_t) s;
151 }
152 while ( offset );
153
154 (*buf)->blip.reader_accum_ = side_sum;
155
156 if ( buf != this->bufs )
157 continue;
158
159 // only end center once
160 this->bufs [2]->blip.reader_accum_ = center_sum;
161 break;
162 }
163}
164
165void Mixer_read_pairs( struct Stereo_Mixer* this, blip_sample_t out [], int count )
166{
167 // TODO: if caller never marks buffers as modified, uses mono
168 // except that buffer isn't cleared, so caller can encounter
169 // subtle problems and not realize the cause.
170 this->samples_read += count;
171 if ( Tracked_non_silent( this->bufs [0] ) | Tracked_non_silent( this->bufs [1] ) )
172 mix_stereo( this, out, count );
173 else
174 mix_mono( this, out, count );
175}
176
177// Multi_Buffer
178
179void Buffer_init( struct Multi_Buffer* this )
180{
181 int const spf = 2;
182
183 Tracked_init( &this->bufs [0] );
184 Tracked_init( &this->bufs [1] );
185 Tracked_init( &this->bufs [2] );
186
187 Mixer_init( &this->mixer );
188
189 this->length_ = 0;
190 this->sample_rate_ = 0;
191 this->channels_changed_count_ = 1;
192 this->channel_types_ = NULL;
193 this->channel_count_ = 0;
194 this->samples_per_frame_ = spf;
195 this->immediate_removal_ = true;
196
197 this->mixer.bufs [2] = &this->bufs [2];
198 this->mixer.bufs [0] = &this->bufs [0];
199 this->mixer.bufs [1] = &this->bufs [1];
200
201 this->chan.center = &this->bufs [2].blip;
202 this->chan.left = &this->bufs [0].blip;
203 this->chan.right = &this->bufs [1].blip;
204}
205
206blargg_err_t Buffer_set_sample_rate( struct Multi_Buffer* this, int rate, int msec )
207{
208 int i;
209 for ( i = bufs_size; --i >= 0; )
210 RETURN_ERR( Blip_set_sample_rate( &this->bufs [i].blip, rate, msec ) );
211
212 this->sample_rate_ = Blip_sample_rate( &this->bufs [0].blip );
213 this->length_ = Blip_length( &this->bufs [0].blip );
214 return 0;
215}
216
217void Buffer_clock_rate( struct Multi_Buffer* this, int rate )
218{
219 int i;
220 for ( i = bufs_size; --i >= 0; )
221 Blip_set_clock_rate( &this->bufs [i].blip, rate );
222}
223
224void Buffer_bass_freq( struct Multi_Buffer* this, int bass )
225{
226 int i;
227 for ( i = bufs_size; --i >= 0; )
228 Blip_bass_freq( &this->bufs [i].blip, bass );
229}
230
231blargg_err_t Buffer_set_channel_count( struct Multi_Buffer* this, int n, int const* types )
232{
233 this->channel_count_ = n;
234 this->channel_types_ = types;
235 return 0;
236}
237
238struct channel_t Buffer_channel( struct Multi_Buffer* this, int i )
239{
240 (void) i;
241 return this->chan;
242}
243
244void Buffer_clear( struct Multi_Buffer* this )
245{
246 int i;
247 this->mixer.samples_read = 0;
248 for ( i = bufs_size; --i >= 0; )
249 Tracked_clear( &this->bufs [i] );
250}
251
252void Buffer_end_frame( struct Multi_Buffer* this, blip_time_t clock_count )
253{
254 int i;
255 for ( i = bufs_size; --i >= 0; )
256 Tracked_end_frame( &this->bufs [i], clock_count );
257}
258
259int Buffer_read_samples( struct Multi_Buffer* this, blip_sample_t out [], int out_size )
260{
261 require( (out_size & 1) == 0 ); // must read an even number of samples
262 out_size = min( out_size, Buffer_samples_avail( this ) );
263
264 int pair_count = (int) (out_size >> 1);
265 if ( pair_count )
266 {
267 Mixer_read_pairs( &this->mixer, out, pair_count );
268
269 if ( Buffer_samples_avail( this ) <= 0 || this->immediate_removal_ )
270 {
271 int i;
272 for ( i = bufs_size; --i >= 0; )
273 {
274 buf_t* b = &this->bufs [i];
275 // TODO: might miss non-silence settling since it checks END of last read
276 if ( !Tracked_non_silent( b ) )
277 Tracked_remove_silence( b, this->mixer.samples_read );
278 else
279 Tracked_remove_samples( b, this->mixer.samples_read );
280 }
281 this->mixer.samples_read = 0;
282 }
283 }
284
285 return out_size;
286}
diff --git a/lib/rbcodec/codecs/libgme/multi_buffer.h b/lib/rbcodec/codecs/libgme/multi_buffer.h
new file mode 100644
index 0000000000..e5efa5a230
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/multi_buffer.h
@@ -0,0 +1,114 @@
1// Multi-channel sound buffer interface, stereo and effects buffers
2
3// Blip_Buffer 0.4.1
4#ifndef MULTI_BUFFER_H
5#define MULTI_BUFFER_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10// Get indexed channel, from 0 to channel count - 1
11struct channel_t {
12 struct Blip_Buffer* center;
13 struct Blip_Buffer* left;
14 struct Blip_Buffer* right;
15};
16
17enum { type_index_mask = 0xFF };
18enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
19enum { stereo = 2 };
20enum { bufs_size = 3 };
21
22// Tracked_Blip_Buffer
23struct Tracked_Blip_Buffer {
24 struct Blip_Buffer blip;
25 int last_non_silence;
26};
27
28void Tracked_init( struct Tracked_Blip_Buffer* this );
29unsigned Tracked_non_silent( struct Tracked_Blip_Buffer* this );
30void Tracked_remove_all_samples( struct Tracked_Blip_Buffer * this );
31int Tracked_read_samples( struct Tracked_Blip_Buffer* this, blip_sample_t [], int );
32void Tracked_remove_silence( struct Tracked_Blip_Buffer* this, int );
33void Tracked_remove_samples( struct Tracked_Blip_Buffer* this, int );
34void Tracked_clear( struct Tracked_Blip_Buffer* this );
35void Tracked_end_frame( struct Tracked_Blip_Buffer* this, blip_time_t );
36
37static inline delta_t unsettled( struct Blip_Buffer* this )
38{
39 return this->reader_accum_ >> delta_bits;
40}
41
42// Stereo Mixer
43struct Stereo_Mixer {
44 struct Tracked_Blip_Buffer* bufs [3];
45 int samples_read;
46};
47
48void Mixer_init( struct Stereo_Mixer* this );
49void Mixer_read_pairs( struct Stereo_Mixer* this, blip_sample_t out [], int count );
50
51typedef struct Tracked_Blip_Buffer buf_t;
52
53// Multi_Buffer
54struct Multi_Buffer {
55 unsigned channels_changed_count_;
56 int sample_rate_;
57 int length_;
58 int channel_count_;
59 int samples_per_frame_;
60 int const *channel_types_;
61 bool immediate_removal_;
62
63 buf_t bufs [bufs_size];
64 struct Stereo_Mixer mixer;
65 struct channel_t chan;
66};
67
68blargg_err_t Buffer_set_channel_count( struct Multi_Buffer* this, int n, int const* types );
69
70// Buffers used for all channels
71static inline struct Blip_Buffer* center( struct Multi_Buffer* this ) { return &this->bufs [2].blip; }
72static inline struct Blip_Buffer* left( struct Multi_Buffer* this ) { return &this->bufs [0].blip; }
73static inline struct Blip_Buffer* right( struct Multi_Buffer* this ) { return &this->bufs [1].blip; }
74
75// Initializes Multi_Buffer structure
76void Buffer_init( struct Multi_Buffer* this );
77
78blargg_err_t Buffer_set_sample_rate( struct Multi_Buffer* this, int, int msec );
79void Buffer_clock_rate( struct Multi_Buffer* this, int );
80void Buffer_bass_freq( struct Multi_Buffer* this, int );
81void Buffer_clear( struct Multi_Buffer* this );
82void Buffer_end_frame( struct Multi_Buffer* this, blip_time_t ) ICODE_ATTR;
83
84static inline int Buffer_length( struct Multi_Buffer* this )
85{
86 return this->length_;
87}
88
89// Count of changes to channel configuration. Incremented whenever
90// a change is made to any of the Blip_Buffers for any channel.
91static inline unsigned Buffer_channels_changed_count( struct Multi_Buffer* this )
92{
93 return this->channels_changed_count_;
94}
95
96static inline void Buffer_disable_immediate_removal( struct Multi_Buffer* this )
97{
98 this->immediate_removal_ = false;
99}
100
101static inline int Buffer_sample_rate( struct Multi_Buffer* this )
102{
103 return this->sample_rate_;
104}
105
106static inline int Buffer_samples_avail( struct Multi_Buffer* this )
107{
108 return (Blip_samples_avail(&this->bufs [0].blip) - this->mixer.samples_read) * 2;
109}
110
111int Buffer_read_samples( struct Multi_Buffer* this, blip_sample_t*, int ) ICODE_ATTR;
112struct channel_t Buffer_channel( struct Multi_Buffer* this, int i );
113
114#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_apu.c b/lib/rbcodec/codecs/libgme/nes_apu.c
new file mode 100644
index 0000000000..b6c88bc7e7
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_apu.c
@@ -0,0 +1,397 @@
1// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
2
3#include "nes_apu.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const amp_range = 15;
19
20void Apu_init( struct Nes_Apu* this )
21{
22 this->tempo_ = (int)(FP_ONE_TEMPO);
23 this->dmc.apu = this;
24 this->dmc.prg_reader = NULL;
25 this->irq_notifier_ = NULL;
26
27 Synth_init( &this->square_synth );
28 Synth_init( &this->triangle.synth );
29 Synth_init( &this->noise.synth );
30 Synth_init( &this->dmc.synth );
31
32 Square_set_synth( &this->square1, &this->square_synth );
33 Square_set_synth( &this->square2, &this->square_synth );
34
35 this->oscs [0] = &this->square1.osc;
36 this->oscs [1] = &this->square2.osc;
37 this->oscs [2] = &this->triangle.osc;
38 this->oscs [3] = &this->noise.osc;
39 this->oscs [4] = &this->dmc.osc;
40
41 Apu_output( this, NULL );
42 this->dmc.nonlinear = false;
43 Apu_volume( this, (int)FP_ONE_VOLUME );
44 Apu_reset( this, false, 0 );
45}
46
47#if 0
48// sq and tnd must use a fixed point frac where 1.0 = FP_ONE_VOLUME
49void Apu_enable_nonlinear_( struct Nes_Apu* this, int sq, int tnd )
50{
51 this->dmc.nonlinear = true;
52 Synth_volume( &this->square_synth, sq );
53
54 Synth_volume( &this->triangle.synth, (int)((long long)(FP_ONE_VOLUME * 2.752) * tnd / FP_ONE_VOLUME) );
55 Synth_volume( &this->noise.synth , (int)((long long)(FP_ONE_VOLUME * 1.849) * tnd / FP_ONE_VOLUME) );
56 Synth_volume( &this->dmc.synth , tnd );
57
58 this->square1 .osc.last_amp = 0;
59 this->square2 .osc.last_amp = 0;
60 this->triangle.osc.last_amp = 0;
61 this->noise .osc.last_amp = 0;
62 this->dmc .osc.last_amp = 0;
63}
64#endif
65
66void Apu_volume( struct Nes_Apu* this, int v )
67{
68 if ( !this->dmc.nonlinear )
69 {
70 Synth_volume( &this->square_synth, (int)((long long)((0.125 / 1.11) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.1128 1.108
71 Synth_volume( &this->triangle.synth,(int)((long long)((0.150 / 1.11) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.12765 1.175
72 Synth_volume( &this->noise.synth, (int)((long long)((0.095 / 1.11) * FP_ONE_VOLUME) * v / amp_range / FP_ONE_VOLUME) ); // was 0.0741 1.282
73 Synth_volume( &this->dmc.synth, (int)((long long)((0.450 / 1.11) * FP_ONE_VOLUME) * v / 2048 / FP_ONE_VOLUME) ); // was 0.42545 1.058
74 }
75}
76
77void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* buffer )
78{
79 int i;
80 for ( i = 0; i < apu_osc_count; i++ )
81 Apu_osc_output( this, i, buffer );
82}
83
84void Apu_set_tempo( struct Nes_Apu* this, int t )
85{
86 this->tempo_ = t;
87 this->frame_period = (this->dmc.pal_mode ? 8314 : 7458);
88 if ( t != (int)FP_ONE_TEMPO )
89 this->frame_period = (int) ((this->frame_period * FP_ONE_TEMPO) / t) & ~1; // must be even
90}
91
92void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac )
93{
94 this->dmc.pal_mode = pal_mode;
95 Apu_set_tempo( this, this->tempo_ );
96
97 Square_reset( &this->square1 );
98 Square_reset( &this->square2 );
99 Triangle_reset( &this->triangle );
100 Noise_reset( &this->noise );
101 Dmc_reset( &this->dmc );
102
103 this->last_time = 0;
104 this->last_dmc_time = 0;
105 this->osc_enables = 0;
106 this->irq_flag = false;
107 this->earliest_irq_ = apu_no_irq;
108 this->frame_delay = 1;
109 Apu_write_register( this, 0, 0x4017, 0x00 );
110 Apu_write_register( this, 0, 0x4015, 0x00 );
111
112 addr_t addr;
113 for ( addr = apu_io_addr; addr <= 0x4013; addr++ )
114 Apu_write_register( this, 0, addr, (addr & 3) ? 0x00 : 0x10 );
115
116 this->dmc.dac = initial_dmc_dac;
117 if ( !this->dmc.nonlinear )
118 this->triangle.osc.last_amp = 15;
119 if ( !this->dmc.nonlinear ) // TODO: remove?
120 this->dmc.osc.last_amp = initial_dmc_dac; // prevent output transition
121}
122
123void Apu_irq_changed( struct Nes_Apu* this )
124{
125 nes_time_t new_irq = this->dmc.next_irq;
126 if ( this->dmc.irq_flag | this->irq_flag ) {
127 new_irq = 0;
128 }
129 else if ( new_irq > this->next_irq ) {
130 new_irq = this->next_irq;
131 }
132
133 if ( new_irq != this->earliest_irq_ ) {
134 this->earliest_irq_ = new_irq;
135 if ( this->irq_notifier_ )
136 this->irq_notifier_( this->irq_data );
137 }
138}
139
140// frames
141
142void Apu_run_until( struct Nes_Apu* this, nes_time_t end_time )
143{
144 require( end_time >= this->last_dmc_time );
145 if ( end_time > Apu_next_dmc_read_time( this ) )
146 {
147 nes_time_t start = this->last_dmc_time;
148 this->last_dmc_time = end_time;
149 Dmc_run( &this->dmc, start, end_time );
150 }
151}
152
153static void run_until_( struct Nes_Apu* this, nes_time_t end_time )
154{
155 require( end_time >= this->last_time );
156
157 if ( end_time == this->last_time )
158 return;
159
160 if ( this->last_dmc_time < end_time )
161 {
162 nes_time_t start = this->last_dmc_time;
163 this->last_dmc_time = end_time;
164 Dmc_run( &this->dmc, start, end_time );
165 }
166
167 while ( true )
168 {
169 // earlier of next frame time or end time
170 nes_time_t time = this->last_time + this->frame_delay;
171 if ( time > end_time )
172 time = end_time;
173 this->frame_delay -= time - this->last_time;
174
175 // run oscs to present
176 Square_run( &this->square1, this->last_time, time );
177 Square_run( &this->square2, this->last_time, time );
178 Triangle_run( &this->triangle, this->last_time, time );
179 Noise_run( &this->noise, this->last_time, time );
180 this->last_time = time;
181
182 if ( time == end_time )
183 break; // no more frames to run
184
185 // take frame-specific actions
186 this->frame_delay = this->frame_period;
187 switch ( this->frame++ )
188 {
189 case 0:
190 if ( !(this->frame_mode & 0xC0) ) {
191 this->next_irq = time + this->frame_period * 4 + 2;
192 this->irq_flag = true;
193 }
194 // fall through
195 case 2:
196 // clock length and sweep on frames 0 and 2
197 Osc_clock_length( &this->square1.osc, 0x20 );
198 Osc_clock_length( &this->square2.osc, 0x20 );
199 Osc_clock_length( &this->noise.osc, 0x20 );
200 Osc_clock_length( &this->triangle.osc, 0x80 ); // different bit for halt flag on triangle
201
202 Square_clock_sweep( &this->square1, -1 );
203 Square_clock_sweep( &this->square2, 0 );
204
205 // frame 2 is slightly shorter in mode 1
206 if ( this->dmc.pal_mode && this->frame == 3 )
207 this->frame_delay -= 2;
208 break;
209
210 case 1:
211 // frame 1 is slightly shorter in mode 0
212 if ( !this->dmc.pal_mode )
213 this->frame_delay -= 2;
214 break;
215
216 case 3:
217 this->frame = 0;
218
219 // frame 3 is almost twice as long in mode 1
220 if ( this->frame_mode & 0x80 )
221 this->frame_delay += this->frame_period - (this->dmc.pal_mode ? 2 : 6);
222 break;
223 }
224
225 // clock envelopes and linear counter every frame
226 Triangle_clock_linear_counter( &this->triangle );
227 Square_clock_envelope( &this->square1 );
228 Square_clock_envelope( &this->square2 );
229 Noise_clock_envelope( &this->noise );
230 }
231}
232
233static inline void zero_apu_osc( struct Nes_Osc* osc, struct Blip_Synth* synth, nes_time_t time )
234{
235 struct Blip_Buffer* output = osc->output;
236 int last_amp = osc->last_amp;
237 osc->last_amp = 0;
238 if ( output && last_amp )
239 Synth_offset( synth, time, -osc->last_amp, output );
240}
241
242void Apu_end_frame( struct Nes_Apu* this, nes_time_t end_time )
243{
244 if ( end_time > this->last_time )
245 run_until_( this, end_time );
246
247 if ( this->dmc.nonlinear )
248 {
249 zero_apu_osc( &this->square1.osc, this->square1.synth, this->last_time );
250 zero_apu_osc( &this->square2.osc, this->square2.synth, this->last_time );
251 zero_apu_osc( &this->triangle.osc, &this->triangle.synth, this->last_time );
252 zero_apu_osc( &this->noise.osc, &this->noise.synth, this->last_time );
253 zero_apu_osc( &this->dmc.osc, &this->dmc.synth, this->last_time );
254 }
255
256 // make times relative to new frame
257 this->last_time -= end_time;
258 require( this->last_time >= 0 );
259
260 this->last_dmc_time -= end_time;
261 require( this->last_dmc_time >= 0 );
262
263 if ( this->next_irq != apu_no_irq ) {
264 this->next_irq -= end_time;
265 check( this->next_irq >= 0 );
266 }
267 if ( this->dmc.next_irq != apu_no_irq ) {
268 this->dmc.next_irq -= end_time;
269 check( this->dmc.next_irq >= 0 );
270 }
271 if ( this->earliest_irq_ != apu_no_irq ) {
272 this->earliest_irq_ -= end_time;
273 if ( this->earliest_irq_ < 0 )
274 this->earliest_irq_ = 0;
275 }
276}
277
278// registers
279
280static const unsigned char length_table [0x20] = {
281 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
282 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
283 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
284 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
285};
286
287void Apu_write_register( struct Nes_Apu* this, nes_time_t time, addr_t addr, int data )
288{
289 require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
290 require( (unsigned) data <= 0xFF );
291
292 // Ignore addresses outside range
293 if ( (unsigned) (addr - apu_io_addr) >= apu_io_size )
294 return;
295
296 run_until_( this, time );
297
298 if ( addr < 0x4014 )
299 {
300 // Write to channel
301 int osc_index = (addr - apu_io_addr) >> 2;
302 struct Nes_Osc* osc = this->oscs [osc_index];
303
304 int reg = addr & 3;
305 osc->regs [reg] = data;
306 osc->reg_written [reg] = true;
307
308 if ( osc_index == 4 )
309 {
310 // handle DMC specially
311 Dmc_write_register( &this->dmc, reg, data );
312 }
313 else if ( reg == 3 )
314 {
315 // load length counter
316 if ( (this->osc_enables >> osc_index) & 1 )
317 osc->length_counter = length_table [(data >> 3) & 0x1F];
318
319 // reset square phase
320 if ( osc_index == 0 ) this->square1.phase = square_phase_range - 1;
321 else if ( osc_index == 1 ) this->square2.phase = square_phase_range - 1;
322 }
323 }
324 else if ( addr == 0x4015 )
325 {
326 // Channel enables
327 int i;
328 for ( i = apu_osc_count; i--; )
329 if ( !((data >> i) & 1) )
330 this->oscs [i]->length_counter = 0;
331
332 bool recalc_irq = this->dmc.irq_flag;
333 this->dmc.irq_flag = false;
334
335 int old_enables = this->osc_enables;
336 this->osc_enables = data;
337 if ( !(data & 0x10) ) {
338 this->dmc.next_irq = apu_no_irq;
339 recalc_irq = true;
340 }
341 else if ( !(old_enables & 0x10) ) {
342 Dmc_start( &this->dmc ); // dmc just enabled
343 }
344
345 if ( recalc_irq )
346 Apu_irq_changed( this );
347 }
348 else if ( addr == 0x4017 )
349 {
350 // Frame mode
351 this->frame_mode = data;
352
353 bool irq_enabled = !(data & 0x40);
354 this->irq_flag &= irq_enabled;
355 this->next_irq = apu_no_irq;
356
357 // mode 1
358 this->frame_delay = (this->frame_delay & 1);
359 this->frame = 0;
360
361 if ( !(data & 0x80) )
362 {
363 // mode 0
364 this->frame = 1;
365 this->frame_delay += this->frame_period;
366 if ( irq_enabled )
367 this->next_irq = time + this->frame_delay + this->frame_period * 3 + 1;
368 }
369
370 Apu_irq_changed( this );
371 }
372}
373
374int Apu_read_status( struct Nes_Apu* this, nes_time_t time )
375{
376 run_until_( this, time - 1 );
377
378 int result = (this->dmc.irq_flag << 7) | (this->irq_flag << 6);
379
380 int i;
381 for ( i = 0; i < apu_osc_count; i++ )
382 if ( this->oscs [i]->length_counter )
383 result |= 1 << i;
384
385 run_until_( this, time );
386
387 if ( this->irq_flag )
388 {
389 result |= 0x40;
390 this->irq_flag = false;
391 Apu_irq_changed( this );
392 }
393
394 //debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
395
396 return result;
397}
diff --git a/lib/rbcodec/codecs/libgme/nes_apu.h b/lib/rbcodec/codecs/libgme/nes_apu.h
new file mode 100644
index 0000000000..152ec94a17
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_apu.h
@@ -0,0 +1,137 @@
1// NES 2A03 APU sound chip emulator
2
3// Nes_Snd_Emu 0.2.0-pre
4#ifndef NES_APU_H
5#define NES_APU_H
6
7#include "blargg_common.h"
8#include "nes_oscs.h"
9
10enum { apu_status_addr = 0x4015 };
11enum { apu_osc_count = 5 };
12enum { apu_no_irq = INT_MAX/2 + 1 };
13enum { apu_irq_waiting = 0 };
14
15enum { apu_io_addr = 0x4000 };
16enum { apu_io_size = 0x18 };
17
18struct apu_state_t;
19
20struct Nes_Apu {
21 int tempo_;
22 nes_time_t last_time; // has been run until this time in current frame
23 nes_time_t last_dmc_time;
24 nes_time_t earliest_irq_;
25 nes_time_t next_irq;
26 int frame_period;
27 int frame_delay; // cycles until frame counter runs next
28 int frame; // current frame (0-3)
29 int osc_enables;
30 int frame_mode;
31 bool irq_flag;
32
33 void (*irq_notifier_)( void* user_data );
34 void* irq_data;
35
36 Synth square_synth; // shared by squares
37
38 struct Nes_Osc* oscs [apu_osc_count];
39 struct Nes_Square square1;
40 struct Nes_Square square2;
41 struct Nes_Noise noise;
42 struct Nes_Triangle triangle;
43 struct Nes_Dmc dmc;
44};
45
46// Init Nes apu
47void Apu_init( struct Nes_Apu* this );
48
49// Set buffer to generate all sound into, or disable sound if NULL
50void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* );
51
52// All time values are the number of cpu clock cycles relative to the
53// beginning of the current time frame. Before resetting the cpu clock
54// count, call end_frame( last_cpu_time ).
55
56// Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
57void Apu_write_register( struct Nes_Apu* this, nes_time_t, addr_t, int data );
58
59// Read from status register at 0x4015
60int Apu_read_status( struct Nes_Apu* this, nes_time_t );
61
62// Run all oscillators up to specified time, end current time frame, then
63// start a new time frame at time 0. Time frames have no effect on emulation
64// and each can be whatever length is convenient.
65void Apu_end_frame( struct Nes_Apu* this, nes_time_t );
66
67// Additional optional features (can be ignored without any problem)
68
69// Reset internal frame counter, registers, and all oscillators.
70// Use PAL timing if pal_timing is true, otherwise use NTSC timing.
71// Set the DMC oscillator's initial DAC value to initial_dmc_dac without
72// any audible click.
73void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac );
74
75// Adjust frame period
76void Apu_set_tempo( struct Nes_Apu* this, int );
77
78// Set overall volume (default is 1.0)
79void Apu_volume( struct Nes_Apu* this, int );
80
81// Run DMC until specified time, so that any DMC memory reads can be
82// accounted for (i.e. inserting cpu wait states).
83void Apu_run_until( struct Nes_Apu* this, nes_time_t );
84
85// Set sound output of specific oscillator to buffer. If buffer is NULL,
86// the specified oscillator is muted and emulation accuracy is reduced.
87// The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
88// 2) Triangle, 3) Noise, 4) DMC.
89static inline void Apu_osc_output( struct Nes_Apu* this, int osc, struct Blip_Buffer* buf )
90{
91 assert( (unsigned) osc < apu_osc_count );
92 this->oscs [osc]->output = buf;
93}
94
95// Set memory reader callback used by DMC oscillator to fetch samples.
96// When callback is invoked, 'user_data' is passed unchanged as the
97// first parameter.
98static inline void Apu_dmc_reader( struct Nes_Apu* this, int (*func)( void*, addr_t ), void* user_data )
99{
100 this->dmc.prg_reader_data = user_data;
101 this->dmc.prg_reader = func;
102}
103
104// Set IRQ time callback that is invoked when the time of earliest IRQ
105// may have changed, or NULL to disable. When callback is invoked,
106// 'user_data' is passed unchanged as the first parameter.
107static inline void Apu_irq_notifier( struct Nes_Apu* this, void (*func)( void* user_data ), void* user_data )
108{
109 this->irq_notifier_ = func;
110 this->irq_data = user_data;
111}
112
113// Count number of DMC reads that would occur if 'run_until( t )' were executed.
114// If last_read is not NULL, set *last_read to the earliest time that
115// 'count_dmc_reads( time )' would result in the same result.
116static inline int Apu_count_dmc_reads( struct Nes_Apu* this, nes_time_t time, nes_time_t* last_read )
117{
118 return Dmc_count_reads( &this->dmc, time, last_read );
119}
120
121static inline nes_time_t Dmc_next_read_time( struct Nes_Dmc* this )
122{
123 if ( this->osc.length_counter == 0 )
124 return apu_no_irq; // not reading
125
126 return this->apu->last_dmc_time + this->osc.delay + (this->bits_remain - 1) * this->period;
127}
128
129// Time when next DMC memory read will occur
130static inline nes_time_t Apu_next_dmc_read_time( struct Nes_Apu* this ) { return Dmc_next_read_time( &this->dmc ); }
131void Apu_irq_changed( struct Nes_Apu* this );
132
133#if 0
134// Experimental
135void Apu_enable_nonlinear_( struct Nes_Apu* this, int sq, int tnd );
136#endif
137#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_cpu.c b/lib/rbcodec/codecs/libgme/nes_cpu.c
new file mode 100644
index 0000000000..20925918c2
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_cpu.c
@@ -0,0 +1,62 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "nes_cpu.h"
4
5#include "blargg_endian.h"
6
7/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20static inline void set_code_page( struct Nes_Cpu* this, int i, void const* p )
21{
22 byte const* p2 = STATIC_CAST(byte const*,p) - NES_CPU_OFFSET( i * page_size );
23 this->cpu_state->code_map [i] = p2;
24 this->cpu_state_.code_map [i] = p2;
25}
26
27void Cpu_map_code( struct Nes_Cpu* this, addr_t start, int size, void const* data, int mirror_size )
28{
29 // address range must begin and end on page boundaries
30 require( start % page_size == 0 );
31 require( size % page_size == 0 );
32 require( start + size <= 0x10000 );
33 require( mirror_size % page_size == 0 );
34
35 int offset;
36 for ( offset = 0; offset < size; offset += page_size )
37 set_code_page( this, NES_CPU_PAGE( start + offset ),
38 STATIC_CAST(char const*,data) + (offset & ((unsigned) mirror_size - 1)) );
39}
40
41void Cpu_reset( struct Nes_Cpu* this, void const* unmapped_page )
42{
43 check( this->cpu_state == &this->cpu_state_ );
44 this->cpu_state = &this->cpu_state_;
45
46 this->r.flags = irq_inhibit_mask;
47 this->r.sp = 0xFF;
48 this->r.pc = 0;
49 this->r.a = 0;
50 this->r.x = 0;
51 this->r.y = 0;
52
53 this->cpu_state_.time = 0;
54 this->cpu_state_.base = 0;
55 this->irq_time = future_time;
56 this->end_time = future_time;
57
58 set_code_page( this, page_count, unmapped_page );
59 Cpu_map_code( this, 0, 0x10000, unmapped_page, page_size );
60
61 blargg_verify_byte_order();
62}
diff --git a/lib/rbcodec/codecs/libgme/nes_cpu.h b/lib/rbcodec/codecs/libgme/nes_cpu.h
new file mode 100644
index 0000000000..e4538cd00c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_cpu.h
@@ -0,0 +1,109 @@
1// NES cpu emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef NES_CPU_H
5#define NES_CPU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9
10typedef int nes_time_t;
11typedef int addr_t;
12
13enum { page_bits = 11 };
14enum { page_size = 1 << page_bits };
15enum { page_count = 0x10000 >> page_bits };
16
17// Unmapped page should be filled with this
18enum { halt_opcode = 0x22 };
19
20enum { future_time = INT_MAX/2 + 1 };
21enum { irq_inhibit_mask = 0x04 };
22
23// Can read this many bytes past end of a page
24enum { cpu_padding = 8 };
25
26struct registers_t {
27 uint16_t pc;
28 uint8_t a;
29 uint8_t x;
30 uint8_t y;
31 uint8_t flags;
32 uint8_t sp;
33};
34
35struct cpu_state_t {
36 uint8_t const* code_map [page_count + 1];
37 nes_time_t base;
38 int time;
39};
40
41struct Nes_Cpu {
42 // NES 6502 registers. NOT kept updated during emulation.
43 struct registers_t r;
44 nes_time_t irq_time;
45 nes_time_t end_time;
46
47 struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy
48 struct cpu_state_t cpu_state_;
49};
50
51static inline void Cpu_init( struct Nes_Cpu* this )
52{
53 this->cpu_state = &this->cpu_state_;
54}
55
56// Clears registers and maps all pages to unmapped_page
57void Cpu_reset( struct Nes_Cpu* this, void const* unmapped_page );
58
59// Maps code memory (memory accessed via the program counter). Start and size
60// must be multiple of page_size. If mirror_size is non-zero, the first
61// mirror_size bytes are repeated over the range. mirror_size must be a
62// multiple of page_size.
63void Cpu_map_code( struct Nes_Cpu* this, addr_t start, int size, void const* code, int mirror_size );
64
65// Time of beginning of next instruction to be executed
66static inline nes_time_t Cpu_time( struct Nes_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; }
67static inline void Cpu_set_time( struct Nes_Cpu* this, nes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
68static inline void Cpu_adjust_time( struct Nes_Cpu* this, int delta ) { this->cpu_state->time += delta; }
69
70// Clocks past end (negative if before)
71static inline int Cpu_time_past_end( struct Nes_Cpu* this ) { return this->cpu_state->time; }
72
73#define NES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
74
75#ifdef BLARGG_NONPORTABLE
76 #define NES_CPU_OFFSET( addr ) (addr)
77#else
78 #define NES_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
79#endif
80
81// Accesses emulated memory as cpu does
82static inline uint8_t const* Cpu_get_code( struct Nes_Cpu* this, addr_t addr )
83{
84 return this->cpu_state_.code_map [NES_CPU_PAGE( addr )] + NES_CPU_OFFSET( addr );
85}
86
87static inline void Cpu_update_end_time( struct Nes_Cpu* this, nes_time_t end, nes_time_t irq )
88{
89 if ( end > irq && !(this->r.flags & irq_inhibit_mask) )
90 end = irq;
91
92 this->cpu_state->time += this->cpu_state->base - end;
93 this->cpu_state->base = end;
94}
95
96// Time of next IRQ
97static inline void Cpu_set_irq_time( struct Nes_Cpu* this, nes_time_t t )
98{
99 this->irq_time = t;
100 Cpu_update_end_time( this, this->end_time, t );
101}
102
103static inline void Cpu_set_end_time( struct Nes_Cpu* this, nes_time_t t )
104{
105 this->end_time = t;
106 Cpu_update_end_time( this, t, this->irq_time );
107}
108
109#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_cpu_run.h b/lib/rbcodec/codecs/libgme/nes_cpu_run.h
new file mode 100644
index 0000000000..fd1fea9659
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_cpu_run.h
@@ -0,0 +1,1122 @@
1// NES 6502 cpu emulator run function
2
3#if 0
4/* Define these macros in the source file before #including this file.
5- Parameters might be expressions, so they are best evaluated only once,
6though they NEVER have side-effects, so multiple evaluation is OK.
7- Output parameters might be a multiple-assignment expression like "a=x",
8so they must NOT be parenthesized.
9- Except where noted, time() and related functions will NOT work
10correctly inside a macro. TIME() is always correct, and FLUSH_TIME() and
11CACHE_TIME() allow the time changing functions to work.
12- Macros "returning" void may use a {} statement block. */
13
14 // 0 <= addr <= 0xFFFF + page_size
15 // time functions can be used
16 int READ_MEM( addr_t );
17 void WRITE_MEM( addr_t, int data );
18 // 0 <= READ_MEM() <= 0xFF
19
20 // 0 <= addr <= 0x1FF
21 int READ_LOW( addr_t );
22 void WRITE_LOW( addr_t, int data );
23 // 0 <= READ_LOW() <= 0xFF
24
25 // Often-used instructions attempt these before using a normal memory access.
26 // Optional; defaults to READ_MEM() and WRITE_MEM()
27 bool CAN_READ_FAST( addr_t ); // if true, uses result of READ_FAST
28 void READ_FAST( addr_t, int& out ); // ALWAYS called BEFORE CAN_READ_FAST
29 bool CAN_WRITE_FAST( addr_t ); // if true, uses WRITE_FAST instead of WRITE_MEM
30 void WRITE_FAST( addr_t, int data );
31
32 // Used by instructions most often used to access the NES PPU (LDA abs and BIT abs).
33 // Optional; defaults to READ_MEM.
34 void READ_PPU( addr_t, int& out );
35 // 0 <= out <= 0xFF
36
37// The following can be used within macros:
38
39 // Current time
40 time_t TIME();
41
42 // Allows use of time functions
43 void FLUSH_TIME();
44
45 // Must be used before end of macro if FLUSH_TIME() was used earlier
46 void CACHE_TIME();
47
48// Configuration (optional; commented behavior if defined)
49
50 // Emulates dummy reads for indexed instructions
51 #define NES_CPU_DUMMY_READS 1
52
53 // Optimizes as if map_code( 0, 0x10000 + cpu_padding, FLAT_MEM ) is always in effect
54 #define FLAT_MEM my_mem_array
55
56 // Expanded just before beginning of code, to help debugger
57 #define CPU_BEGIN void my_run_cpu() {
58
59#endif
60
61/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
62can redistribute it and/or modify it under the terms of the GNU Lesser
63General Public License as published by the Free Software Foundation; either
64version 2.1 of the License, or (at your option) any later version. This
65module is distributed in the hope that it will be useful, but WITHOUT ANY
66WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
67FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
68details. You should have received a copy of the GNU Lesser General Public
69License along with this module; if not, write to the Free Software Foundation,
70Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
71
72// Allows MWCW debugger to step through code properly
73#ifdef CPU_BEGIN
74 CPU_BEGIN
75#endif
76
77// Time
78#define TIME() (s_time + s.base)
79#define FLUSH_TIME() {s.time = s_time - time_offset;}
80#define CACHE_TIME() {s_time = s.time + time_offset;}
81
82// Defaults
83#ifndef CAN_WRITE_FAST
84 #define CAN_WRITE_FAST( addr ) 0
85 #define WRITE_FAST( addr, data )
86#endif
87
88#ifndef CAN_READ_FAST
89 #define CAN_READ_FAST( addr ) 0
90 #define READ_FAST( addr, out )
91#endif
92
93#ifndef READ_PPU
94 #define READ_PPU( addr, out )\
95 {\
96 FLUSH_TIME();\
97 out = READ_MEM( addr );\
98 CACHE_TIME();\
99 }
100#endif
101
102#define READ_STACK READ_LOW
103#define WRITE_STACK WRITE_LOW
104
105// Dummy reads
106#ifdef NES_CPU_DUMMY_READS
107 // TODO: optimize time handling
108 #define DUMMY_READ( addr, idx ) \
109 if ( (addr & 0xFF) < idx )\
110 {\
111 int const time_offset = 1;\
112 FLUSH_TIME();\
113 READ_MEM( (addr - 0x100) );\
114 CACHE_TIME();\
115 }
116#else
117 #define DUMMY_READ( addr, idx )
118#endif
119
120// Code
121#ifdef FLAT_MEM
122 #define CODE_PAGE( addr ) (FLAT_MEM)
123 #define CODE_OFFSET( addr ) (addr)
124#else
125 #define CODE_PAGE( addr ) (s.code_map [NES_CPU_PAGE( addr )])
126 #define CODE_OFFSET( addr ) NES_CPU_OFFSET( addr )
127#endif
128#define READ_CODE( addr ) (CODE_PAGE( addr ) [CODE_OFFSET( addr )])
129
130// Stack
131#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
132#define GET_SP() ((sp - 1) & 0xFF)
133#define SP( o ) ((sp + (o - (o>0)*0x100)) | 0x100)
134
135// Truncation
136#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
137#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
138#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
139
140// Flags with hex value for clarity when used as mask.
141// Stored in indicated variable during emulation.
142int const n80 = 0x80; // nz
143int const v40 = 0x40; // flags
144int const r20 = 0x20;
145int const b10 = 0x10;
146int const d08 = 0x08; // flags
147int const i04 = 0x04; // flags
148int const z02 = 0x02; // nz
149int const c01 = 0x01; // c
150
151#define IS_NEG (nz & 0x8080)
152
153#define GET_FLAGS( out ) \
154{\
155 out = flags & (v40 | d08 | i04);\
156 out += ((nz >> 8) | nz) & n80;\
157 out += c >> 8 & c01;\
158 if ( !BYTE( nz ) )\
159 out += z02;\
160}
161
162#define SET_FLAGS( in ) \
163{\
164 flags = in & (v40 | d08 | i04);\
165 c = nz = in << 8;\
166 nz += ~in & z02;\
167}
168
169{
170 int const time_offset = 0;
171
172 // Local state
173 struct cpu_state_t s;
174 #ifdef FLAT_MEM
175 s.base = cpu->cpu_state_.base;
176 #else
177 s = cpu->cpu_state_;
178 #endif
179 cpu->cpu_state = &s;
180 int s_time = cpu->cpu_state_.time; // helps even on x86
181
182 // Registers
183 int pc = cpu->r.pc;
184 int a = cpu->r.a;
185 int x = cpu->r.x;
186 int y = cpu->r.y;
187 int sp;
188 SET_SP( cpu->r.sp );
189
190 // Flags
191 int flags;
192 int c; // carry set if (c & 0x100) != 0
193 int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
194 {
195 int temp = cpu->r.flags;
196 SET_FLAGS( temp );
197 }
198
199loop:
200
201 // Check all values
202 check( (unsigned) sp - 0x100 < 0x100 );
203 check( (unsigned) pc < 0x10000 );
204 check( (unsigned) a < 0x100 );
205 check( (unsigned) x < 0x100 );
206 check( (unsigned) y < 0x100 );
207
208 // Read instruction
209 byte const* instr = CODE_PAGE( pc );
210 int opcode;
211
212 if ( CODE_OFFSET(~0) == ~0 )
213 {
214 opcode = instr [pc];
215 pc++;
216 instr += pc;
217 }
218 else
219 {
220 instr += CODE_OFFSET( pc );
221 opcode = *instr++;
222 pc++;
223 }
224
225 // local to function in case it helps optimizer
226 static byte const clock_table [256] =
227 {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
228 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
229 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
230 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
231 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
232 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
233 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
234 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
235 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
236 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
237 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
238 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
239 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
240 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
241 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
242 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
243 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
244 }; // 0x00 was 7 and 0x22 was 2
245
246 // Update time
247 if ( s_time >= 0 )
248 goto out_of_time;
249
250 #ifdef CPU_INSTR_HOOK
251 { CPU_INSTR_HOOK( (pc-1), (&instr [-1]), a, x, y, GET_SP(), TIME() ); }
252 #endif
253
254 s_time += clock_table [opcode];
255
256 int data;
257 data = *instr;
258
259 switch ( opcode )
260 {
261
262// Macros
263
264#define GET_MSB() (instr [1])
265#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB())
266#define GET_ADDR() GET_LE16( instr )
267
268#define PAGE_PENALTY( lsb ) s_time += (lsb) >> 8;
269
270#define INC_DEC( reg, n ) reg = BYTE( nz = reg + n ); goto loop;
271
272#define IND_Y( cross, out ) {\
273 int temp = READ_LOW( data ) + y;\
274 out = temp + 0x100 * READ_LOW( BYTE( data + 1 ) );\
275 cross( temp );\
276 }
277
278#define IND_X( out ) {\
279 int temp = data + x;\
280 out = 0x100 * READ_LOW( BYTE( temp + 1 ) ) + READ_LOW( BYTE( temp ) );\
281 }
282
283#define ARITH_ADDR_MODES( op )\
284case op - 0x04: /* (ind,x) */\
285 IND_X( data )\
286 goto ptr##op;\
287case op + 0x0C: /* (ind),y */\
288 IND_Y( PAGE_PENALTY, data )\
289 goto ptr##op;\
290case op + 0x10: /* zp,X */\
291 data = BYTE( data + x );\
292case op + 0x00: /* zp */\
293 data = READ_LOW( data );\
294 goto imm##op;\
295case op + 0x14: /* abs,Y */\
296 data += y;\
297 goto ind##op;\
298case op + 0x18: /* abs,X */\
299 data += x;\
300ind##op:\
301 PAGE_PENALTY( data );\
302case op + 0x08: /* abs */\
303 ADD_PAGE( data );\
304ptr##op:\
305 FLUSH_TIME();\
306 data = READ_MEM( data );\
307 CACHE_TIME();\
308case op + 0x04: /* imm */\
309imm##op:
310
311// TODO: more efficient way to handle negative branch that wraps PC around
312#define BRANCH( cond )\
313{\
314 ++pc;\
315 if ( !(cond) ) goto loop;\
316 s_time++;\
317 int offset = SBYTE( data );\
318 s_time += (BYTE(pc) + offset) >> 8 & 1;\
319 pc = WORD( pc + offset );\
320 goto loop;\
321}
322
323// Often-Used
324
325 case 0xB5: // LDA zp,x
326 a = nz = READ_LOW( BYTE( data + x ) );
327 pc++;
328 goto loop;
329
330 case 0xA5: // LDA zp
331 a = nz = READ_LOW( data );
332 pc++;
333 goto loop;
334
335 case 0xD0: // BNE
336 BRANCH( BYTE( nz ) );
337
338 case 0x20: { // JSR
339 int temp = pc + 1;
340 pc = GET_ADDR();
341 WRITE_STACK( SP( -1 ), temp >> 8 );
342 sp = SP( -2 );
343 WRITE_STACK( sp, temp );
344 goto loop;
345 }
346
347 case 0x4C: // JMP abs
348 pc = GET_ADDR();
349 goto loop;
350
351 case 0xE8: // INX
352 INC_DEC( x, 1 )
353
354 case 0x10: // BPL
355 BRANCH( !IS_NEG )
356
357 ARITH_ADDR_MODES( 0xC5 ) // CMP
358 nz = a - data;
359 pc++;
360 c = ~nz;
361 nz &= 0xFF;
362 goto loop;
363
364 case 0x30: // BMI
365 BRANCH( IS_NEG )
366
367 case 0xF0: // BEQ
368 BRANCH( !BYTE( nz ) );
369
370 case 0x95: // STA zp,x
371 data = BYTE( data + x );
372 case 0x85: // STA zp
373 pc++;
374 WRITE_LOW( data, a );
375 goto loop;
376
377 case 0xC8: // INY
378 INC_DEC( y, 1 )
379
380 case 0xA8: // TAY
381 y = a;
382 nz = a;
383 goto loop;
384
385 case 0x98: // TYA
386 a = y;
387 nz = y;
388 goto loop;
389
390 case 0xAD:{// LDA abs
391 int addr = GET_ADDR();
392 pc += 2;
393 READ_PPU( addr, a = nz );
394 goto loop;
395 }
396
397 case 0x60: // RTS
398 pc = 1 + READ_STACK( sp );
399 pc += 0x100 * READ_STACK( SP( 1 ) );
400 sp = SP( 2 );
401 goto loop;
402
403 {
404 int addr;
405
406 case 0x8D: // STA abs
407 addr = GET_ADDR();
408 pc += 2;
409 if ( CAN_WRITE_FAST( addr ) )
410 {
411 WRITE_FAST( addr, a );
412 goto loop;
413 }
414 sta_ptr:
415 FLUSH_TIME();
416 WRITE_MEM( addr, a );
417 CACHE_TIME();
418 goto loop;
419
420 case 0x99: // STA abs,Y
421 addr = y + GET_ADDR();
422 pc += 2;
423 if ( CAN_WRITE_FAST( addr ) )
424 {
425 WRITE_FAST( addr, a );
426 goto loop;
427 }
428 goto sta_abs_x;
429
430 case 0x9D: // STA abs,X (slightly more common than STA abs)
431 addr = x + GET_ADDR();
432 pc += 2;
433 if ( CAN_WRITE_FAST( addr ) )
434 {
435 WRITE_FAST( addr, a );
436 goto loop;
437 }
438 DUMMY_READ( addr, x );
439 sta_abs_x:
440 FLUSH_TIME();
441 WRITE_MEM( addr, a );
442 CACHE_TIME();
443 goto loop;
444
445 case 0x91: // STA (ind),Y
446 #define NO_PAGE_PENALTY( lsb )
447 IND_Y( NO_PAGE_PENALTY, addr )
448 pc++;
449 DUMMY_READ( addr, y );
450 goto sta_ptr;
451
452 case 0x81: // STA (ind,X)
453 IND_X( addr )
454 pc++;
455 goto sta_ptr;
456
457 }
458
459 case 0xA9: // LDA #imm
460 pc++;
461 a = data;
462 nz = data;
463 goto loop;
464
465 // common read instructions
466 {
467 int addr;
468
469 case 0xA1: // LDA (ind,X)
470 IND_X( addr )
471 pc++;
472 goto a_nz_read_addr;
473
474 case 0xB1:// LDA (ind),Y
475 addr = READ_LOW( data ) + y;
476 PAGE_PENALTY( addr );
477 addr += 0x100 * READ_LOW( BYTE( data + 1 ) );
478 pc++;
479 READ_FAST( addr, a = nz );
480 if ( CAN_READ_FAST( addr ) )
481 goto loop;
482 DUMMY_READ( addr, y );
483 goto a_nz_read_addr;
484
485 case 0xB9: // LDA abs,Y
486 PAGE_PENALTY( data + y );
487 addr = GET_ADDR() + y;
488 pc += 2;
489 READ_FAST( addr, a = nz );
490 if ( CAN_READ_FAST( addr ) )
491 goto loop;
492 goto a_nz_read_addr;
493
494 case 0xBD: // LDA abs,X
495 PAGE_PENALTY( data + x );
496 addr = GET_ADDR() + x;
497 pc += 2;
498 READ_FAST( addr, a = nz );
499 if ( CAN_READ_FAST( addr ) )
500 goto loop;
501 DUMMY_READ( addr, x );
502 a_nz_read_addr:
503 FLUSH_TIME();
504 a = nz = READ_MEM( addr );
505 CACHE_TIME();
506 goto loop;
507
508 }
509
510// Branch
511
512 case 0x50: // BVC
513 BRANCH( !(flags & v40) )
514
515 case 0x70: // BVS
516 BRANCH( flags & v40 )
517
518 case 0xB0: // BCS
519 BRANCH( c & 0x100 )
520
521 case 0x90: // BCC
522 BRANCH( !(c & 0x100) )
523
524// Load/store
525
526 case 0x94: // STY zp,x
527 data = BYTE( data + x );
528 case 0x84: // STY zp
529 pc++;
530 WRITE_LOW( data, y );
531 goto loop;
532
533 case 0x96: // STX zp,y
534 data = BYTE( data + y );
535 case 0x86: // STX zp
536 pc++;
537 WRITE_LOW( data, x );
538 goto loop;
539
540 case 0xB6: // LDX zp,y
541 data = BYTE( data + y );
542 case 0xA6: // LDX zp
543 data = READ_LOW( data );
544 case 0xA2: // LDX #imm
545 pc++;
546 x = data;
547 nz = data;
548 goto loop;
549
550 case 0xB4: // LDY zp,x
551 data = BYTE( data + x );
552 case 0xA4: // LDY zp
553 data = READ_LOW( data );
554 case 0xA0: // LDY #imm
555 pc++;
556 y = data;
557 nz = data;
558 goto loop;
559
560 case 0xBC: // LDY abs,X
561 data += x;
562 PAGE_PENALTY( data );
563 case 0xAC:{// LDY abs
564 int addr = data + 0x100 * GET_MSB();
565 pc += 2;
566 FLUSH_TIME();
567 y = nz = READ_MEM( addr );
568 CACHE_TIME();
569 goto loop;
570 }
571
572 case 0xBE: // LDX abs,y
573 data += y;
574 PAGE_PENALTY( data );
575 case 0xAE:{// LDX abs
576 int addr = data + 0x100 * GET_MSB();
577 pc += 2;
578 FLUSH_TIME();
579 x = nz = READ_MEM( addr );
580 CACHE_TIME();
581 goto loop;
582 }
583
584 {
585 int temp;
586 case 0x8C: // STY abs
587 temp = y;
588 goto store_abs;
589
590 case 0x8E: // STX abs
591 temp = x;
592 store_abs:
593 {
594 int addr = GET_ADDR();
595 pc += 2;
596 if ( CAN_WRITE_FAST( addr ) )
597 {
598 WRITE_FAST( addr, temp );
599 goto loop;
600 }
601 FLUSH_TIME();
602 WRITE_MEM( addr, temp );
603 CACHE_TIME();
604 goto loop;
605 }
606 }
607
608// Compare
609
610 case 0xEC: {// CPX abs
611 int addr = GET_ADDR();
612 pc++;
613 FLUSH_TIME();
614 data = READ_MEM( addr );
615 CACHE_TIME();
616 goto cpx_data;
617 }
618
619 case 0xE4: // CPX zp
620 data = READ_LOW( data );
621 case 0xE0: // CPX #imm
622 cpx_data:
623 nz = x - data;
624 pc++;
625 c = ~nz;
626 nz &= 0xFF;
627 goto loop;
628
629 case 0xCC:{// CPY abs
630 int addr = GET_ADDR();
631 pc++;
632 FLUSH_TIME();
633 data = READ_MEM( addr );
634 CACHE_TIME();
635 goto cpy_data;
636 }
637
638 case 0xC4: // CPY zp
639 data = READ_LOW( data );
640 case 0xC0: // CPY #imm
641 cpy_data:
642 nz = y - data;
643 pc++;
644 c = ~nz;
645 nz &= 0xFF;
646 goto loop;
647
648// Logical
649
650 ARITH_ADDR_MODES( 0x25 ) // AND
651 nz = (a &= data);
652 pc++;
653 goto loop;
654
655 ARITH_ADDR_MODES( 0x45 ) // EOR
656 nz = (a ^= data);
657 pc++;
658 goto loop;
659
660 ARITH_ADDR_MODES( 0x05 ) // ORA
661 nz = (a |= data);
662 pc++;
663 goto loop;
664
665 case 0x2C:{// BIT abs
666 int addr = GET_ADDR();
667 pc += 2;
668 READ_PPU( addr, nz );
669 flags = (flags & ~v40) + (nz & v40);
670 if ( a & nz )
671 goto loop;
672 nz <<= 8; // result must be zero, even if N bit is set
673 goto loop;
674 }
675
676 case 0x24: // BIT zp
677 nz = READ_LOW( data );
678 pc++;
679 flags = (flags & ~v40) + (nz & v40);
680 if ( a & nz )
681 goto loop; // Z should be clear, and nz must be non-zero if nz & a is
682 nz <<= 8; // set Z flag without affecting N flag
683 goto loop;
684
685// Add/subtract
686
687 ARITH_ADDR_MODES( 0xE5 ) // SBC
688 case 0xEB: // unofficial equivalent
689 data ^= 0xFF;
690 goto adc_imm;
691
692 ARITH_ADDR_MODES( 0x65 ) // ADC
693 adc_imm: {
694 int carry = c >> 8 & 1;
695 int ov = (a ^ 0x80) + carry + SBYTE( data );
696 flags = (flags & ~v40) + (ov >> 2 & v40);
697 c = nz = a + data + carry;
698 pc++;
699 a = BYTE( nz );
700 goto loop;
701 }
702
703// Shift/rotate
704
705 case 0x4A: // LSR A
706 c = 0;
707 case 0x6A: // ROR A
708 nz = c >> 1 & 0x80;
709 c = a << 8;
710 nz += a >> 1;
711 a = nz;
712 goto loop;
713
714 case 0x0A: // ASL A
715 nz = a << 1;
716 c = nz;
717 a = BYTE( nz );
718 goto loop;
719
720 case 0x2A: { // ROL A
721 nz = a << 1;
722 int temp = c >> 8 & 1;
723 c = nz;
724 nz += temp;
725 a = BYTE( nz );
726 goto loop;
727 }
728
729 case 0x5E: // LSR abs,X
730 data += x;
731 case 0x4E: // LSR abs
732 c = 0;
733 case 0x6E: // ROR abs
734 ror_abs: {
735 ADD_PAGE( data );
736 FLUSH_TIME();
737 int temp = READ_MEM( data );
738 nz = (c >> 1 & 0x80) + (temp >> 1);
739 c = temp << 8;
740 goto rotate_common;
741 }
742
743 case 0x3E: // ROL abs,X
744 data += x;
745 goto rol_abs;
746
747 case 0x1E: // ASL abs,X
748 data += x;
749 case 0x0E: // ASL abs
750 c = 0;
751 case 0x2E: // ROL abs
752 rol_abs:
753 ADD_PAGE( data );
754 nz = c >> 8 & 1;
755 FLUSH_TIME();
756 nz += (c = READ_MEM( data ) << 1);
757 rotate_common:
758 pc++;
759 WRITE_MEM( data, BYTE( nz ) );
760 CACHE_TIME();
761 goto loop;
762
763 case 0x7E: // ROR abs,X
764 data += x;
765 goto ror_abs;
766
767 case 0x76: // ROR zp,x
768 data = BYTE( data + x );
769 goto ror_zp;
770
771 case 0x56: // LSR zp,x
772 data = BYTE( data + x );
773 case 0x46: // LSR zp
774 c = 0;
775 case 0x66: // ROR zp
776 ror_zp: {
777 int temp = READ_LOW( data );
778 nz = (c >> 1 & 0x80) + (temp >> 1);
779 c = temp << 8;
780 goto write_nz_zp;
781 }
782
783 case 0x36: // ROL zp,x
784 data = BYTE( data + x );
785 goto rol_zp;
786
787 case 0x16: // ASL zp,x
788 data = BYTE( data + x );
789 case 0x06: // ASL zp
790 c = 0;
791 case 0x26: // ROL zp
792 rol_zp:
793 nz = c >> 8 & 1;
794 nz += (c = READ_LOW( data ) << 1);
795 goto write_nz_zp;
796
797// Increment/decrement
798
799 case 0xCA: // DEX
800 INC_DEC( x, -1 )
801
802 case 0x88: // DEY
803 INC_DEC( y, -1 )
804
805 case 0xF6: // INC zp,x
806 data = BYTE( data + x );
807 case 0xE6: // INC zp
808 nz = 1;
809 goto add_nz_zp;
810
811 case 0xD6: // DEC zp,x
812 data = BYTE( data + x );
813 case 0xC6: // DEC zp
814 nz = -1;
815 add_nz_zp:
816 nz += READ_LOW( data );
817 write_nz_zp:
818 pc++;
819 WRITE_LOW( data, nz );
820 goto loop;
821
822 case 0xFE: // INC abs,x
823 data = x + GET_ADDR();
824 goto inc_ptr;
825
826 case 0xEE: // INC abs
827 data = GET_ADDR();
828 inc_ptr:
829 nz = 1;
830 goto inc_common;
831
832 case 0xDE: // DEC abs,x
833 data = x + GET_ADDR();
834 goto dec_ptr;
835
836 case 0xCE: // DEC abs
837 data = GET_ADDR();
838 dec_ptr:
839 nz = -1;
840 inc_common:
841 FLUSH_TIME();
842 pc += 2;
843 nz += READ_MEM( data );
844 WRITE_MEM( data, BYTE( nz ) );
845 CACHE_TIME();
846 goto loop;
847
848// Transfer
849
850 case 0xAA: // TAX
851 x = nz = a;
852 goto loop;
853
854 case 0x8A: // TXA
855 a = nz = x;
856 goto loop;
857
858 case 0x9A: // TXS
859 SET_SP( x ); // verified (no flag change)
860 goto loop;
861
862 case 0xBA: // TSX
863 x = nz = GET_SP();
864 goto loop;
865
866// Stack
867
868 case 0x48: // PHA
869 sp = SP( -1 );
870 WRITE_STACK( sp, a );
871 goto loop;
872
873 case 0x68: // PLA
874 a = nz = READ_STACK( sp );
875 sp = SP( 1 );
876 goto loop;
877
878 case 0x40:{// RTI
879 pc = READ_STACK( SP( 1 ) );
880 pc += READ_STACK( SP( 2 ) ) * 0x100;
881 int temp = READ_STACK( sp );
882 sp = SP( 3 );
883 data = flags;
884 SET_FLAGS( temp );
885 cpu->r.flags = flags; // update externally-visible I flag
886 int delta = s.base - cpu->irq_time;
887 if ( delta <= 0 ) goto loop; // end_time < irq_time
888 if ( flags & i04 ) goto loop;
889 s_time += delta;
890 s.base = cpu->irq_time;
891 goto loop;
892 }
893
894 case 0x28:{// PLP
895 int temp = READ_STACK( sp );
896 sp = SP( 1 );
897 int changed = flags ^ temp;
898 SET_FLAGS( temp );
899 if ( !(changed & i04) )
900 goto loop; // I flag didn't change
901 if ( flags & i04 )
902 goto handle_sei;
903 goto handle_cli;
904 }
905
906 case 0x08:{// PHP
907 int temp;
908 GET_FLAGS( temp );
909 sp = SP( -1 );
910 WRITE_STACK( sp, temp | (b10 | r20) );
911 goto loop;
912 }
913
914 case 0x6C:{// JMP (ind)
915 data = GET_ADDR();
916 byte const* page = CODE_PAGE( data );
917 pc = page [CODE_OFFSET( data )];
918 data = (data & 0xFF00) + ((data + 1) & 0xFF);
919 pc += page [CODE_OFFSET( data )] * 0x100;
920 goto loop;
921 }
922
923 case 0x00: // BRK
924 goto handle_brk;
925
926// Flags
927
928 case 0x38: // SEC
929 c = 0x100;
930 goto loop;
931
932 case 0x18: // CLC
933 c = 0;
934 goto loop;
935
936 case 0xB8: // CLV
937 flags &= ~v40;
938 goto loop;
939
940 case 0xD8: // CLD
941 flags &= ~d08;
942 goto loop;
943
944 case 0xF8: // SED
945 flags |= d08;
946 goto loop;
947
948 case 0x58: // CLI
949 if ( !(flags & i04) )
950 goto loop;
951 flags &= ~i04;
952 handle_cli: {
953 //dprintf( "CLI at %d\n", TIME );
954 cpu->r.flags = flags; // update externally-visible I flag
955 int delta = s.base - cpu->irq_time;
956 if ( delta <= 0 )
957 {
958 if ( TIME() < cpu->irq_time )
959 goto loop;
960 goto delayed_cli;
961 }
962 s.base = cpu->irq_time;
963 s_time += delta;
964 if ( s_time < 0 )
965 goto loop;
966
967 if ( delta >= s_time + 1 )
968 {
969 // delayed irq until after next instruction
970 s.base += s_time + 1;
971 s_time = -1;
972 goto loop;
973 }
974
975 // TODO: implement
976 delayed_cli:
977 dprintf( "Delayed CLI not emulated\n" );
978 goto loop;
979 }
980
981 case 0x78: // SEI
982 if ( flags & i04 )
983 goto loop;
984 flags |= i04;
985 handle_sei: {
986 cpu->r.flags = flags; // update externally-visible I flag
987 int delta = s.base - cpu->end_time;
988 s.base = cpu->end_time;
989 s_time += delta;
990 if ( s_time < 0 )
991 goto loop;
992
993 dprintf( "Delayed SEI not emulated\n" );
994 goto loop;
995 }
996
997// Unofficial
998
999 // SKW - skip word
1000 case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
1001 PAGE_PENALTY( data + x );
1002 case 0x0C:
1003 pc++;
1004 // SKB - skip byte
1005 case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
1006 case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
1007 pc++;
1008 goto loop;
1009
1010 // NOP
1011 case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
1012 goto loop;
1013
1014 case halt_opcode: // HLT - halt processor
1015 if ( pc-- > 0x10000 )
1016 {
1017 // handle wrap-around (assumes caller has put page of HLT at 0x10000)
1018 pc = WORD( pc );
1019 goto loop;
1020 }
1021 case 0x02: case 0x12: case 0x32: case 0x42: case 0x52:
1022 case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
1023 goto stop;
1024
1025// Unimplemented
1026
1027 case 0xFF: // force 256-entry jump table for optimization purposes
1028 c |= 1; // compiler doesn't know that this won't affect anything
1029 default:
1030 check( (unsigned) opcode < 0x100 );
1031
1032 #ifdef UNIMPL_INSTR
1033 UNIMPL_INSTR();
1034 #endif
1035
1036 // At least skip over proper number of bytes instruction uses
1037 static unsigned char const illop_lens [8] = {
1038 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
1039 };
1040 int opcode = instr [-1];
1041 int len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
1042 if ( opcode == 0x9C )
1043 len = 2;
1044 pc += len;
1045
1046 // Account for extra clock
1047 if ( (opcode >> 4) == 0x0B )
1048 {
1049 if ( opcode == 0xB3 )
1050 data = READ_LOW( data );
1051 if ( opcode != 0xB7 )
1052 PAGE_PENALTY( data + y );
1053 }
1054 goto loop;
1055 }
1056 assert( false ); // catch missing 'goto loop' or accidental 'break'
1057
1058 int result_;
1059handle_brk:
1060 pc++;
1061 result_ = b10 | 4;
1062
1063#ifdef CPU_DONE
1064interrupt:
1065#endif
1066 {
1067 s_time += 7;
1068
1069 // Save PC and read vector
1070 WRITE_STACK( SP( -1 ), pc >> 8 );
1071 WRITE_STACK( SP( -2 ), pc );
1072 pc = GET_LE16( &READ_CODE( 0xFFFA ) + (result_ & 4) );
1073
1074 // Save flags
1075 int temp;
1076 GET_FLAGS( temp );
1077 temp |= r20 + (result_ & b10); // B flag set for BRK
1078 sp = SP( -3 );
1079 WRITE_STACK( sp, temp );
1080
1081 // Update I flag in externally-visible flags
1082 cpu->r.flags = (flags |= i04);
1083
1084 // Update time
1085 int delta = s.base - cpu->end_time;
1086 if ( delta >= 0 )
1087 goto loop;
1088 s_time += delta;
1089 s.base = cpu->end_time;
1090 goto loop;
1091 }
1092
1093out_of_time:
1094 pc--;
1095
1096 // Optional action that triggers interrupt or changes irq/end time
1097 #ifdef CPU_DONE
1098 {
1099 CPU_DONE( result_ );
1100 if ( result_ >= 0 )
1101 goto interrupt;
1102 if ( s_time < 0 )
1103 goto loop;
1104 }
1105 #endif
1106stop:
1107
1108 // Flush cached state
1109 cpu->r.pc = pc;
1110 cpu->r.sp = GET_SP();
1111 cpu->r.a = a;
1112 cpu->r.x = x;
1113 cpu->r.y = y;
1114
1115 int temp;
1116 GET_FLAGS( temp );
1117 cpu->r.flags = temp;
1118
1119 cpu->cpu_state_.base = s.base;
1120 cpu->cpu_state_.time = s_time;
1121 cpu->cpu_state = &cpu->cpu_state_;
1122}
diff --git a/lib/rbcodec/codecs/libgme/nes_fds_apu.c b/lib/rbcodec/codecs/libgme/nes_fds_apu.c
new file mode 100644
index 0000000000..dc0775d5d3
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_fds_apu.c
@@ -0,0 +1,291 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "nes_fds_apu.h"
4
5/* Copyright (C) 2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const fract_range = 65536;
19
20void Fds_init( struct Nes_Fds_Apu* this )
21{
22 Synth_init( &this->synth );
23
24 this->lfo_tempo = lfo_base_tempo;
25 Fds_set_output( this, 0, NULL );
26 Fds_volume( this, (int)FP_ONE_VOLUME );
27 Fds_reset( this );
28}
29
30void Fds_reset( struct Nes_Fds_Apu* this )
31{
32 memset( this->regs_, 0, sizeof this->regs_ );
33 memset( this->mod_wave, 0, sizeof this->mod_wave );
34
35 this->last_time = 0;
36 this->env_delay = 0;
37 this->sweep_delay = 0;
38 this->wave_pos = 0;
39 this->last_amp = 0;
40 this->wave_fract = fract_range;
41 this->mod_fract = fract_range;
42 this->mod_pos = 0;
43 this->mod_write_pos = 0;
44
45 static byte const initial_regs [0x0B] = {
46 0x80, // disable envelope
47 0, 0, 0xC0, // disable wave and lfo
48 0x80, // disable sweep
49 0, 0, 0x80, // disable modulation
50 0, 0, 0xFF // LFO period // TODO: use 0xE8 as FDS ROM does?
51 };
52 int i;
53 for ( i = 0; i < (int) sizeof initial_regs; i++ )
54 {
55 // two writes to set both gain and period for envelope registers
56 Fds_write_( this, fds_io_addr + fds_wave_size + i, 0 );
57 Fds_write_( this, fds_io_addr + fds_wave_size + i, initial_regs [i] );
58 }
59}
60
61void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data )
62{
63 unsigned reg = addr - fds_io_addr;
64 if ( reg < fds_io_size )
65 {
66 if ( reg < fds_wave_size )
67 {
68 if ( *regs_nes (this, 0x4089) & 0x80 )
69 this->regs_ [reg] = data & fds_wave_sample_max;
70 }
71 else
72 {
73 this->regs_ [reg] = data;
74 switch ( addr )
75 {
76 case 0x4080:
77 if ( data & 0x80 )
78 this->env_gain = data & 0x3F;
79 else
80 this->env_speed = (data & 0x3F) + 1;
81 break;
82
83 case 0x4084:
84 if ( data & 0x80 )
85 this->sweep_gain = data & 0x3F;
86 else
87 this->sweep_speed = (data & 0x3F) + 1;
88 break;
89
90 case 0x4085:
91 this->mod_pos = this->mod_write_pos;
92 *regs_nes (this, 0x4085) = data & 0x7F;
93 break;
94
95 case 0x4088:
96 if ( *regs_nes (this, 0x4087) & 0x80 )
97 {
98 int pos = this->mod_write_pos;
99 data &= 0x07;
100 this->mod_wave [pos ] = data;
101 this->mod_wave [pos + 1] = data;
102 this->mod_write_pos = (pos + 2) & (fds_wave_size - 1);
103 this->mod_pos = (this->mod_pos + 2) & (fds_wave_size - 1);
104 }
105 break;
106 }
107 }
108 }
109}
110
111void Fds_set_tempo( struct Nes_Fds_Apu* this, int t )
112{
113 this->lfo_tempo = lfo_base_tempo;
114 if ( t != (int)FP_ONE_TEMPO )
115 {
116 this->lfo_tempo = (int) ((lfo_base_tempo * FP_ONE_TEMPO) / t);
117 if ( this->lfo_tempo <= 0 )
118 this->lfo_tempo = 1;
119 }
120}
121
122void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t final_end_time )
123{
124 int const wave_freq = (*regs_nes (this, 0x4083) & 0x0F) * 0x100 + *regs_nes (this, 0x4082);
125 struct Blip_Buffer* const output_ = this->output_;
126 if ( wave_freq && output_ && !((*regs_nes (this, 0x4089) | *regs_nes (this, 0x4083)) & 0x80) )
127 {
128 Blip_set_modified( output_ );
129
130 // master_volume
131 #define MVOL_ENTRY( percent ) (fds_master_vol_max * percent + 50) / 100
132 static unsigned char const master_volumes [4] = {
133 MVOL_ENTRY( 100 ), MVOL_ENTRY( 67 ), MVOL_ENTRY( 50 ), MVOL_ENTRY( 40 )
134 };
135 int const master_volume = master_volumes [*regs_nes (this, 0x4089) & 0x03];
136
137 // lfo_period
138 blip_time_t lfo_period = *regs_nes (this, 0x408A) * this->lfo_tempo;
139 if ( *regs_nes (this, 0x4083) & 0x40 )
140 lfo_period = 0;
141
142 // sweep setup
143 blip_time_t sweep_time = this->last_time + this->sweep_delay;
144 blip_time_t const sweep_period = lfo_period * this->sweep_speed;
145 if ( !sweep_period || *regs_nes (this, 0x4084) & 0x80 )
146 sweep_time = final_end_time;
147
148 // envelope setup
149 blip_time_t env_time = this->last_time + this->env_delay;
150 blip_time_t const env_period = lfo_period * this->env_speed;
151 if ( !env_period || *regs_nes (this, 0x4080) & 0x80 )
152 env_time = final_end_time;
153
154 // modulation
155 int mod_freq = 0;
156 if ( !(*regs_nes (this, 0x4087) & 0x80) )
157 mod_freq = (*regs_nes (this, 0x4087) & 0x0F) * 0x100 + *regs_nes (this, 0x4086);
158
159 blip_time_t end_time = this->last_time;
160 do
161 {
162 // sweep
163 if ( sweep_time <= end_time )
164 {
165 sweep_time += sweep_period;
166 int mode = *regs_nes (this, 0x4084) >> 5 & 2;
167 int new_sweep_gain = this->sweep_gain + mode - 1;
168 if ( (unsigned) new_sweep_gain <= (unsigned) 0x80 >> mode )
169 this->sweep_gain = new_sweep_gain;
170 else
171 *regs_nes (this, 0x4084) |= 0x80; // optimization only
172 }
173
174 // envelope
175 if ( env_time <= end_time )
176 {
177 env_time += env_period;
178 int mode = *regs_nes (this, 0x4080) >> 5 & 2;
179 int new_env_gain = this->env_gain + mode - 1;
180 if ( (unsigned) new_env_gain <= (unsigned) 0x80 >> mode )
181 this->env_gain = new_env_gain;
182 else
183 *regs_nes (this, 0x4080) |= 0x80; // optimization only
184 }
185
186 // new end_time
187 blip_time_t const start_time = end_time;
188 end_time = final_end_time;
189 if ( end_time > env_time ) end_time = env_time;
190 if ( end_time > sweep_time ) end_time = sweep_time;
191
192 // frequency modulation
193 int freq = wave_freq;
194 if ( mod_freq )
195 {
196 // time of next modulation clock
197 blip_time_t mod_time = start_time + (this->mod_fract + mod_freq - 1) / mod_freq;
198 if ( end_time > mod_time )
199 end_time = mod_time;
200
201 // run modulator up to next clock and save old sweep_bias
202 int sweep_bias = *regs_nes (this, 0x4085);
203 this->mod_fract -= (end_time - start_time) * mod_freq;
204 if ( this->mod_fract <= 0 )
205 {
206 this->mod_fract += fract_range;
207 check( (unsigned) this->mod_fract <= fract_range );
208
209 static short const mod_table [8] = { 0, +1, +2, +4, 0, -4, -2, -1 };
210 int mod = this->mod_wave [this->mod_pos];
211 this->mod_pos = (this->mod_pos + 1) & (fds_wave_size - 1);
212 int new_sweep_bias = (sweep_bias + mod_table [mod]) & 0x7F;
213 if ( mod == 4 )
214 new_sweep_bias = 0;
215 *regs_nes (this, 0x4085) = new_sweep_bias;
216 }
217
218 // apply frequency modulation
219 sweep_bias = (sweep_bias ^ 0x40) - 0x40;
220 int factor = sweep_bias * this->sweep_gain;
221 int extra = factor & 0x0F;
222 factor >>= 4;
223 if ( extra )
224 {
225 factor--;
226 if ( sweep_bias >= 0 )
227 factor += 3;
228 }
229 if ( factor > 193 ) factor -= 258;
230 if ( factor < -64 ) factor += 256;
231 freq += (freq * factor) >> 6;
232 if ( freq <= 0 )
233 continue;
234 }
235
236 // wave
237 int wave_fract = this->wave_fract;
238 blip_time_t delay = (wave_fract + freq - 1) / freq;
239 blip_time_t time = start_time + delay;
240
241 if ( time <= end_time )
242 {
243 // at least one wave clock within start_time...end_time
244
245 blip_time_t const min_delay = fract_range / freq;
246 int wave_pos = this->wave_pos;
247
248 int volume = this->env_gain;
249 if ( volume > fds_vol_max )
250 volume = fds_vol_max;
251 volume *= master_volume;
252
253 int const min_fract = min_delay * freq;
254
255 do
256 {
257 // clock wave
258 int amp = this->regs_ [wave_pos] * volume;
259 wave_pos = (wave_pos + 1) & (fds_wave_size - 1);
260 int delta = amp - this->last_amp;
261 if ( delta )
262 {
263 this->last_amp = amp;
264 Synth_offset_inline( &this->synth, time, delta, output_ );
265 }
266
267 wave_fract += fract_range - delay * freq;
268 check( unsigned (fract_range - wave_fract) < freq );
269
270 // delay until next clock
271 delay = min_delay;
272 if ( wave_fract > min_fract )
273 delay++;
274 check( delay && delay == (wave_fract + freq - 1) / freq );
275
276 time += delay;
277 }
278 while ( time <= end_time ); // TODO: using < breaks things, but <= is wrong
279
280 this->wave_pos = wave_pos;
281 }
282 this->wave_fract = wave_fract - (end_time - (time - delay)) * freq;
283 check( this->wave_fract > 0 );
284 }
285 while ( end_time < final_end_time );
286
287 this->env_delay = env_time - final_end_time; check( env_delay >= 0 );
288 this->sweep_delay = sweep_time - final_end_time; check( sweep_delay >= 0 );
289 }
290 this->last_time = final_end_time;
291}
diff --git a/lib/rbcodec/codecs/libgme/nes_fds_apu.h b/lib/rbcodec/codecs/libgme/nes_fds_apu.h
new file mode 100644
index 0000000000..8dac3b721a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_fds_apu.h
@@ -0,0 +1,116 @@
1// NES FDS sound chip emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef NES_FDS_APU_H
5#define NES_FDS_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10enum { lfo_base_tempo = 8 };
11enum { fds_osc_count = 1 };
12
13enum { fds_io_addr = 0x4040 };
14enum { fds_io_size = 0x53 };
15
16enum { fds_wave_size = 0x40 };
17enum { fds_master_vol_max = 10 };
18enum { fds_vol_max = 0x20 };
19enum { fds_wave_sample_max = 0x3F };
20
21struct Nes_Fds_Apu {
22 unsigned char regs_ [fds_io_size];// last written value to registers
23 int lfo_tempo; // normally 8; adjusted by set_tempo()
24
25 int env_delay;
26 int env_speed;
27 int env_gain;
28
29 int sweep_delay;
30 int sweep_speed;
31 int sweep_gain;
32
33 int wave_pos;
34 int last_amp;
35 blip_time_t wave_fract;
36
37 int mod_fract;
38 int mod_pos;
39 int mod_write_pos;
40 unsigned char mod_wave [fds_wave_size];
41
42 // synthesis
43 blip_time_t last_time;
44 struct Blip_Buffer* output_;
45 struct Blip_Synth synth;
46};
47
48// init
49void Fds_init( struct Nes_Fds_Apu* this );
50// setup
51void Fds_set_tempo( struct Nes_Fds_Apu* this, int t );
52
53// emulation
54void Fds_reset( struct Nes_Fds_Apu* this );
55
56static inline void Fds_volume( struct Nes_Fds_Apu* this, int v )
57{
58 Synth_volume( &this->synth, (v*14) / 100 / fds_master_vol_max / fds_vol_max / fds_wave_sample_max );
59}
60
61static inline void Fds_set_output( struct Nes_Fds_Apu* this, int i, struct Blip_Buffer* b )
62{
63#if defined(ROCKBOX)
64 (void) i;
65#endif
66
67 assert( (unsigned) i < fds_osc_count );
68 this->output_ = b;
69}
70
71void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t );
72static inline void Fds_end_frame( struct Nes_Fds_Apu* this, blip_time_t end_time )
73{
74 if ( end_time > this->last_time )
75 Fds_run_until( this, end_time );
76 this->last_time -= end_time;
77 assert( this->last_time >= 0 );
78}
79
80void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data );
81static inline void Fds_write( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr, int data )
82{
83 Fds_run_until( this, time );
84 Fds_write_( this, addr, data );
85}
86
87static inline int Fds_read( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr )
88{
89 Fds_run_until( this, time );
90
91 int result = 0xFF;
92 switch ( addr )
93 {
94 case 0x4090:
95 result = this->env_gain;
96 break;
97
98 case 0x4092:
99 result = this->sweep_gain;
100 break;
101
102 default:
103 {
104 unsigned i = addr - fds_io_addr;
105 if ( i < fds_wave_size )
106 result = this->regs_ [i];
107 }
108 }
109
110 return result | 0x40;
111}
112
113// allow access to registers by absolute address (i.e. 0x4080)
114static inline unsigned char* regs_nes( struct Nes_Fds_Apu* this, unsigned addr ) { return &this->regs_ [addr - fds_io_addr]; }
115
116#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_fme7_apu.c b/lib/rbcodec/codecs/libgme/nes_fme7_apu.c
new file mode 100644
index 0000000000..3e47e0b17c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_fme7_apu.c
@@ -0,0 +1,136 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
2
3#include "nes_fme7_apu.h"
4
5#include <string.h>
6
7/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
8can redistribute it and/or modify it under the terms of the GNU Lesser
9General Public License as published by the Free Software Foundation; either
10version 2.1 of the License, or (at your option) any later version. This
11module is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14details. You should have received a copy of the GNU Lesser General Public
15License along with this module; if not, write to the Free Software Foundation,
16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
17
18#include "blargg_source.h"
19
20void Fme7_init( struct Nes_Fme7_Apu* this )
21{
22 Synth_init( &this->synth );
23
24 Fme7_output( this, NULL );
25 Fme7_volume( this, (int)FP_ONE_VOLUME );
26 Fme7_reset( this );
27}
28
29void Fme7_reset( struct Nes_Fme7_Apu* this )
30{
31 this->last_time = 0;
32
33 int i;
34 for ( i = 0; i < fme7_osc_count; i++ )
35 this->oscs [i].last_amp = 0;
36
37 this->latch = 0;
38 memset( this->regs, 0, sizeof this->regs);
39 memset( this->phases, 0, sizeof this->phases );
40 memset( this->delays, 0, sizeof this->delays );
41}
42
43static unsigned char const amp_table [16] =
44{
45 #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
46 ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
47 ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
48 ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
49 ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
50 #undef ENTRY
51};
52
53void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
54{
55 require( end_time >= this->last_time );
56
57 int index;
58 for ( index = 0; index < fme7_osc_count; index++ )
59 {
60 int mode = this->regs [7] >> index;
61 int vol_mode = this->regs [010 + index];
62 int volume = amp_table [vol_mode & 0x0F];
63
64 struct Blip_Buffer* const osc_output = this->oscs [index].output;
65 if ( !osc_output )
66 continue;
67
68 // check for unsupported mode
69 #ifndef NDEBUG
70 if ( (mode & 011) <= 001 && vol_mode & 0x1F )
71 debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
72 mode, vol_mode & 0x1F );
73 #endif
74
75 if ( (mode & 001) | (vol_mode & 0x10) )
76 volume = 0; // noise and envelope aren't supported
77
78 // period
79 int const period_factor = 16;
80 unsigned period = (this->regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
81 this->regs [index * 2] * period_factor;
82 if ( period < 50 ) // around 22 kHz
83 {
84 volume = 0;
85 if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
86 period = period_factor;
87 }
88
89 // current amplitude
90 int amp = volume;
91 if ( !this->phases [index] )
92 amp = 0;
93
94 {
95 int delta = amp - this->oscs [index].last_amp;
96 if ( delta )
97 {
98 this->oscs [index].last_amp = amp;
99 Blip_set_modified( osc_output );
100 Synth_offset( &this->synth, this->last_time, delta, osc_output );
101 }
102 }
103
104 blip_time_t time = this->last_time + this->delays [index];
105 if ( time < end_time )
106 {
107 int delta = amp * 2 - volume;
108 Blip_set_modified( osc_output );
109 if ( volume )
110 {
111 do
112 {
113 delta = -delta;
114 Synth_offset_inline( &this->synth, time, delta, osc_output );
115 time += period;
116 }
117 while ( time < end_time );
118
119 this->oscs [index].last_amp = (delta + volume) >> 1;
120 this->phases [index] = (delta > 0);
121 }
122 else
123 {
124 // maintain phase when silent
125 int count = (end_time - time + period - 1) / period;
126 this->phases [index] ^= count & 1;
127 time += count * period;
128 }
129 }
130
131 this->delays [index] = time - end_time;
132 }
133
134 this->last_time = end_time;
135}
136
diff --git a/lib/rbcodec/codecs/libgme/nes_fme7_apu.h b/lib/rbcodec/codecs/libgme/nes_fme7_apu.h
new file mode 100644
index 0000000000..c0eac4c765
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_fme7_apu.h
@@ -0,0 +1,90 @@
1// Sunsoft FME-7 sound emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef NES_FME7_APU_H
5#define NES_FME7_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10enum { fme7_reg_count = 14 };
11
12// Mask and addresses of registers
13enum { fme7_addr_mask = 0xE000 };
14enum { fme7_data_addr = 0xE000 };
15enum { fme7_latch_addr = 0xC000 };
16enum { fme7_osc_count = 3 };
17
18enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff
19
20struct osc_t {
21 struct Blip_Buffer* output;
22 int last_amp;
23};
24
25// static unsigned char const amp_table [16];
26
27struct Nes_Fme7_Apu {
28 // fme7 apu state
29 uint8_t regs [fme7_reg_count];
30 uint8_t phases [3]; // 0 or 1
31 uint8_t latch;
32 uint16_t delays [3]; // a, b, c
33
34 struct osc_t oscs [fme7_osc_count];
35 blip_time_t last_time;
36
37 struct Blip_Synth synth;
38};
39
40// See Nes_Apu.h for reference
41void Fme7_init( struct Nes_Fme7_Apu* this );
42void Fme7_reset( struct Nes_Fme7_Apu* this );
43
44static inline void Fme7_volume( struct Nes_Fme7_Apu* this, int v )
45{
46 Synth_volume( &this->synth, (v/2 - (v*3)/25) / amp_range ); // to do: fine-tune
47}
48
49static inline void Fme7_osc_output( struct Nes_Fme7_Apu* this, int i, struct Blip_Buffer* buf )
50{
51 assert( (unsigned) i < fme7_osc_count );
52 this->oscs [i].output = buf;
53}
54
55static inline void Fme7_output( struct Nes_Fme7_Apu* this, struct Blip_Buffer* buf )
56{
57 int i;
58 for ( i = 0; i < fme7_osc_count; i++ )
59 Fme7_osc_output( this, i, buf );
60}
61
62// (addr & addr_mask) == latch_addr
63static inline void Fme7_write_latch( struct Nes_Fme7_Apu* this, int data ) { this->latch = data; }
64
65// (addr & addr_mask) == data_addr
66void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time );
67static inline void Fme7_write_data( struct Nes_Fme7_Apu* this, blip_time_t time, int data )
68{
69 if ( (unsigned) this->latch >= fme7_reg_count )
70 {
71 #ifdef debug_printf
72 debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
73 #endif
74 return;
75 }
76
77 Fme7_run_until( this, time );
78 this->regs [this->latch] = data;
79}
80
81static inline void Fme7_end_frame( struct Nes_Fme7_Apu* this, blip_time_t time )
82{
83 if ( time > this->last_time )
84 Fme7_run_until( this, time );
85
86 assert( this->last_time >= time );
87 this->last_time -= time;
88}
89
90#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_mmc5_apu.h b/lib/rbcodec/codecs/libgme/nes_mmc5_apu.h
new file mode 100644
index 0000000000..b696b49e97
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_mmc5_apu.h
@@ -0,0 +1,61 @@
1// NES MMC5 sound chip emulator
2
3// Nes_Snd_Emu 0.2.0-pre
4#ifndef NES_MMC5_APU_H
5#define NES_MMC5_APU_H
6
7#include "blargg_common.h"
8#include "nes_apu.h"
9
10enum { mmc5_regs_addr = 0x5000 };
11enum { mmc5_regs_size = 0x16 };
12enum { mmc5_osc_count = 3 };
13enum { mmc5_exram_size = 1024 };
14
15struct Nes_Mmc5_Apu {
16 struct Nes_Apu apu;
17 unsigned char exram [mmc5_exram_size];
18};
19
20static inline void Mmc5_init( struct Nes_Mmc5_Apu* this )
21{
22 Apu_init( &this->apu );
23}
24
25static inline void Mmc5_set_output( struct Nes_Mmc5_Apu* this, int i, struct Blip_Buffer* b )
26{
27 // in: square 1, square 2, PCM
28 // out: square 1, square 2, skipped, skipped, PCM
29 if ( i > 1 )
30 i += 2;
31 Apu_osc_output( &this->apu, i, b );
32}
33
34static inline void Mmc5_write_register( struct Nes_Mmc5_Apu* this, blip_time_t time, unsigned addr, int data )
35{
36 switch ( addr )
37 {
38 case 0x5015: // channel enables
39 data &= 0x03; // enable the square waves only
40 // fall through
41 case 0x5000: // Square 1
42 case 0x5002:
43 case 0x5003:
44 case 0x5004: // Square 2
45 case 0x5006:
46 case 0x5007:
47 case 0x5011: // DAC
48 Apu_write_register( &this->apu, time, addr - 0x1000, data );
49 break;
50
51 case 0x5010: // some things write to this for some reason
52 break;
53
54#ifdef BLARGG_DEBUG_H
55 default:
56 dprintf( "Unmapped MMC5 APU write: $%04X <- $%02X\n", addr, data );
57#endif
58 }
59}
60
61#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_namco_apu.c b/lib/rbcodec/codecs/libgme/nes_namco_apu.c
new file mode 100644
index 0000000000..34df200bb6
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_namco_apu.c
@@ -0,0 +1,138 @@
1// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
2
3#include "nes_namco_apu.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18void Namco_init( struct Nes_Namco_Apu* this )
19{
20 Synth_init( &this->synth );
21
22 Namco_output( this, NULL );
23 Namco_volume( this, (int)FP_ONE_VOLUME );
24 Namco_reset( this );
25}
26
27void Namco_reset( struct Nes_Namco_Apu* this )
28{
29 this->last_time = 0;
30 this->addr_reg = 0;
31
32 int i;
33 for ( i = 0; i < namco_reg_count; i++ )
34 this->reg [i] = 0;
35
36 for ( i = 0; i < namco_osc_count; i++ )
37 {
38 struct Namco_Osc* osc = &this->oscs [i];
39 osc->delay = 0;
40 osc->last_amp = 0;
41 osc->wave_pos = 0;
42 }
43}
44
45void Namco_output( struct Nes_Namco_Apu* this, struct Blip_Buffer* buf )
46{
47 int i;
48 for ( i = 0; i < namco_osc_count; i++ )
49 Namco_osc_output( this, i, buf );
50}
51
52void Namco_end_frame( struct Nes_Namco_Apu* this, blip_time_t time )
53{
54 if ( time > this->last_time )
55 Namco_run_until( this, time );
56
57 assert( this->last_time >= time );
58 this->last_time -= time;
59}
60
61void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t nes_end_time )
62{
63 int active_oscs = (this->reg [0x7F] >> 4 & 7) + 1;
64 int i;
65 for ( i = namco_osc_count - active_oscs; i < namco_osc_count; i++ )
66 {
67 struct Namco_Osc* osc = &this->oscs [i];
68 struct Blip_Buffer* output = osc->output;
69 if ( !output )
70 continue;
71
72 blip_resampled_time_t time =
73 Blip_resampled_time( output, this->last_time ) + osc->delay;
74 blip_resampled_time_t end_time = Blip_resampled_time( output, nes_end_time );
75 osc->delay = 0;
76 if ( time < end_time )
77 {
78 const uint8_t* osc_reg = &this->reg [i * 8 + 0x40];
79 if ( !(osc_reg [4] & 0xE0) )
80 continue;
81
82 int volume = osc_reg [7] & 15;
83 if ( !volume )
84 continue;
85
86 int freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
87 if ( freq < 64 * active_oscs )
88 continue; // prevent low frequencies from excessively delaying freq changes
89
90 int const master_clock_divider = 12; // NES time derived via divider of master clock
91 int const n106_divider = 45; // N106 then divides master clock by this
92 int const max_freq = 0x3FFFF;
93 int const lowest_freq_period = (max_freq + 1) * n106_divider / master_clock_divider;
94 // divide by 8 to avoid overflow
95 blip_resampled_time_t period =
96 Blip_resampled_duration( output, lowest_freq_period / 8 ) / freq * 8 * active_oscs;
97
98 int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
99 if ( !wave_size )
100 continue;
101
102 int last_amp = osc->last_amp;
103 int wave_pos = osc->wave_pos;
104
105 Blip_set_modified( output );
106
107 do
108 {
109 // read wave sample
110 int addr = wave_pos + osc_reg [6];
111 int sample = this->reg [addr >> 1] >> (addr << 2 & 4);
112 wave_pos++;
113 sample = (sample & 15) * volume;
114
115 // output impulse if amplitude changed
116 int delta = sample - last_amp;
117 if ( delta )
118 {
119 last_amp = sample;
120 Synth_offset_resampled( &this->synth, time, delta, output );
121 }
122
123 // next sample
124 time += period;
125 if ( wave_pos >= wave_size )
126 wave_pos = 0;
127 }
128 while ( time < end_time );
129
130 osc->wave_pos = wave_pos;
131 osc->last_amp = last_amp;
132 }
133 osc->delay = time - end_time;
134 }
135
136 this->last_time = nes_end_time;
137}
138
diff --git a/lib/rbcodec/codecs/libgme/nes_namco_apu.h b/lib/rbcodec/codecs/libgme/nes_namco_apu.h
new file mode 100644
index 0000000000..c428c894c3
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_namco_apu.h
@@ -0,0 +1,71 @@
1// Namco 106 sound chip emulator
2
3// Nes_Snd_Emu 0.1.8
4#ifndef NES_NAMCO_APU_H
5#define NES_NAMCO_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10struct namco_state_t;
11
12enum { namco_osc_count = 8 };
13enum { namco_addr_reg_addr = 0xF800 };
14enum { namco_data_reg_addr = 0x4800 };
15enum { namco_reg_count = 0x80 };
16
17struct Namco_Osc {
18 int delay;
19 struct Blip_Buffer* output;
20 short last_amp;
21 short wave_pos;
22};
23
24struct Nes_Namco_Apu {
25 struct Namco_Osc oscs [namco_osc_count];
26
27 blip_time_t last_time;
28 int addr_reg;
29
30 uint8_t reg [namco_reg_count];
31
32 struct Blip_Synth synth;
33};
34
35// See Nes_Apu.h for reference.
36void Namco_init( struct Nes_Namco_Apu* this );
37void Namco_output( struct Nes_Namco_Apu* this, struct Blip_Buffer* );
38
39void Namco_reset( struct Nes_Namco_Apu* this );
40void Namco_end_frame( struct Nes_Namco_Apu* this, blip_time_t );
41
42static inline uint8_t* namco_access( struct Nes_Namco_Apu* this )
43{
44 int addr = this->addr_reg & 0x7F;
45 if ( this->addr_reg & 0x80 )
46 this->addr_reg = (addr + 1) | 0x80;
47 return &this->reg [addr];
48}
49
50static inline void Namco_volume( struct Nes_Namco_Apu* this, int v ) { Synth_volume( &this->synth, v / 10 / namco_osc_count / 15 ); }
51
52// Write-only address register is at 0xF800
53static inline void Namco_write_addr( struct Nes_Namco_Apu* this, int v ) { this->addr_reg = v; }
54
55static inline int Namco_read_data( struct Nes_Namco_Apu* this ) { return *namco_access( this ); }
56
57static inline void Namco_osc_output( struct Nes_Namco_Apu* this, int i, struct Blip_Buffer* buf )
58{
59 assert( (unsigned) i < namco_osc_count );
60 this->oscs [i].output = buf;
61}
62
63// Read/write data register is at 0x4800
64void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t );
65static inline void Namco_write_data( struct Nes_Namco_Apu* this, blip_time_t time, int data )
66{
67 Namco_run_until( this, time );
68 *namco_access( this ) = data;
69}
70
71#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_oscs.c b/lib/rbcodec/codecs/libgme/nes_oscs.c
new file mode 100644
index 0000000000..ac6e5759da
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_oscs.c
@@ -0,0 +1,592 @@
1// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
2
3#include "nes_apu.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18// Nes_Osc
19
20void Osc_clock_length( struct Nes_Osc* this, int halt_mask )
21{
22 if ( this->length_counter && !(this->regs [0] & halt_mask) )
23 this->length_counter--;
24}
25
26// Nes_Square
27
28void Square_clock_envelope( struct Nes_Square* this )
29{
30 struct Nes_Osc* osc = &this->osc;
31 int period = osc->regs [0] & 15;
32 if ( osc->reg_written [3] ) {
33 osc->reg_written [3] = false;
34 this->env_delay = period;
35 this->envelope = 15;
36 }
37 else if ( --this->env_delay < 0 ) {
38 this->env_delay = period;
39 if ( this->envelope | (osc->regs [0] & 0x20) )
40 this->envelope = (this->envelope - 1) & 15;
41 }
42}
43
44int Square_volume( struct Nes_Square* this )
45{
46 struct Nes_Osc* osc = &this->osc;
47 return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
48}
49
50void Square_clock_sweep( struct Nes_Square* this, int negative_adjust )
51{
52 struct Nes_Osc* osc = &this->osc;
53 int sweep = osc->regs [1];
54
55 if ( --this->sweep_delay < 0 )
56 {
57 osc->reg_written [1] = true;
58
59 int period = Osc_period( osc );
60 int shift = sweep & shift_mask;
61 if ( shift && (sweep & 0x80) && period >= 8 )
62 {
63 int offset = period >> shift;
64
65 if ( sweep & negate_flag )
66 offset = negative_adjust - offset;
67
68 if ( period + offset < 0x800 )
69 {
70 period += offset;
71 // rewrite period
72 osc->regs [2] = period & 0xFF;
73 osc->regs [3] = (osc->regs [3] & ~7) | ((period >> 8) & 7);
74 }
75 }
76 }
77
78 if ( osc->reg_written [1] ) {
79 osc->reg_written [1] = false;
80 this->sweep_delay = (sweep >> 4) & 7;
81 }
82}
83
84// TODO: clean up
85static inline nes_time_t Square_maintain_phase( struct Nes_Square* this, nes_time_t time, nes_time_t end_time,
86 nes_time_t timer_period )
87{
88 nes_time_t remain = end_time - time;
89 if ( remain > 0 )
90 {
91 int count = (remain + timer_period - 1) / timer_period;
92 this->phase = (this->phase + count) & (square_phase_range - 1);
93 time += count * timer_period;
94 }
95 return time;
96}
97
98void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
99{
100 struct Nes_Osc* osc = &this->osc;
101 const int period = Osc_period( osc );
102 const int timer_period = (period + 1) * 2;
103
104 if ( !osc->output )
105 {
106 osc->delay = Square_maintain_phase( this, time + osc->delay, end_time, timer_period ) - end_time;
107 return;
108 }
109
110 int offset = period >> (osc->regs [1] & shift_mask);
111 if ( osc->regs [1] & negate_flag )
112 offset = 0;
113
114 const int volume = Square_volume( this );
115 if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
116 {
117 if ( osc->last_amp ) {
118 Blip_set_modified( osc->output );
119 Synth_offset( this->synth, time, -osc->last_amp, osc->output );
120 osc->last_amp = 0;
121 }
122
123 time += osc->delay;
124 time = Square_maintain_phase( this, time, end_time, timer_period );
125 }
126 else
127 {
128 // handle duty select
129 int duty_select = (osc->regs [0] >> 6) & 3;
130 int duty = 1 << duty_select; // 1, 2, 4, 2
131 int amp = 0;
132 if ( duty_select == 3 ) {
133 duty = 2; // negated 25%
134 amp = volume;
135 }
136 if ( this->phase < duty )
137 amp ^= volume;
138
139 Blip_set_modified( osc->output );
140 {
141 int delta = Osc_update_amp( osc, amp );
142 if ( delta )
143 Synth_offset( this->synth, time, delta, osc->output );
144 }
145
146 time += osc->delay;
147 if ( time < end_time )
148 {
149 struct Blip_Buffer* const output = osc->output;
150 Synth* synth = this->synth;
151 int delta = amp * 2 - volume;
152 int phase = this->phase;
153
154 do {
155 phase = (phase + 1) & (square_phase_range - 1);
156 if ( phase == 0 || phase == duty ) {
157 delta = -delta;
158 Synth_offset_inline( synth, time, delta, output );
159 }
160 time += timer_period;
161 }
162 while ( time < end_time );
163
164 osc->last_amp = (delta + volume) >> 1;
165 this->phase = phase;
166 }
167 }
168
169 osc->delay = time - end_time;
170}
171
172// Nes_Triangle
173
174void Triangle_clock_linear_counter( struct Nes_Triangle* this )
175{
176 struct Nes_Osc* osc = &this->osc;
177 if ( osc->reg_written [3] )
178 this->linear_counter = osc->regs [0] & 0x7F;
179 else if ( this->linear_counter )
180 this->linear_counter--;
181
182 if ( !(osc->regs [0] & 0x80) )
183 osc->reg_written [3] = false;
184}
185
186static inline int Triangle_calc_amp( struct Nes_Triangle* this )
187{
188 int amp = Triangle_phase_range - this->phase;
189 if ( amp < 0 )
190 amp = this->phase - (Triangle_phase_range + 1);
191 return amp;
192}
193
194// TODO: clean up
195static inline nes_time_t Triangle_maintain_phase( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time,
196 nes_time_t timer_period )
197{
198 nes_time_t remain = end_time - time;
199 if ( remain > 0 )
200 {
201 int count = (remain + timer_period - 1) / timer_period;
202 this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1);
203 this->phase++;
204 time += count * timer_period;
205 }
206 return time;
207}
208
209void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time )
210{
211 struct Nes_Osc* osc = &this->osc;
212 const int timer_period = Osc_period( osc ) + 1;
213 if ( !osc->output )
214 {
215 time += osc->delay;
216 osc->delay = 0;
217 if ( osc->length_counter && this->linear_counter && timer_period >= 3 )
218 osc->delay = Triangle_maintain_phase( this, time, end_time, timer_period ) - end_time;
219 return;
220 }
221
222 // to do: track phase when period < 3
223 // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
224
225 int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) );
226 if ( delta )
227 {
228 Blip_set_modified( osc->output );
229 Synth_offset( &this->synth, time, delta, osc->output );
230 }
231
232 time += osc->delay;
233 if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 )
234 {
235 time = end_time;
236 }
237 else if ( time < end_time )
238 {
239 struct Blip_Buffer* const output = osc->output;
240
241 int phase = this->phase;
242 int volume = 1;
243 if ( phase > Triangle_phase_range ) {
244 phase -= Triangle_phase_range;
245 volume = -volume;
246 }
247 Blip_set_modified( osc->output );
248
249 do {
250 if ( --phase == 0 ) {
251 phase = Triangle_phase_range;
252 volume = -volume;
253 }
254 else
255 {
256 Synth_offset_inline( &this->synth, time, volume, output );
257 }
258
259 time += timer_period;
260 }
261 while ( time < end_time );
262
263 if ( volume < 0 )
264 phase += Triangle_phase_range;
265 this->phase = phase;
266 osc->last_amp = Triangle_calc_amp( this );
267 }
268 osc->delay = time - end_time;
269}
270
271// Nes_Dmc
272
273void Dmc_reset( struct Nes_Dmc* this )
274{
275 this->address = 0;
276 this->dac = 0;
277 this->buf = 0;
278 this->bits_remain = 1;
279 this->bits = 0;
280 this->buf_full = false;
281 this->silence = true;
282 this->next_irq = apu_no_irq;
283 this->irq_flag = false;
284 this->irq_enabled = false;
285
286 Osc_reset( &this->osc );
287 this->period = 0x1AC;
288}
289
290void Dmc_recalc_irq( struct Nes_Dmc* this )
291{
292 struct Nes_Osc* osc = &this->osc;
293 nes_time_t irq = apu_no_irq;
294 if ( this->irq_enabled && osc->length_counter )
295 irq = this->apu->last_dmc_time + osc->delay +
296 ((osc->length_counter - 1) * 8 + this->bits_remain - 1) * (nes_time_t) (this->period) + 1;
297 if ( irq != this->next_irq ) {
298 this->next_irq = irq;
299 Apu_irq_changed( this->apu );
300 }
301}
302
303int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t time, nes_time_t* last_read )
304{
305 struct Nes_Osc* osc = &this->osc;
306 if ( last_read )
307 *last_read = time;
308
309 if ( osc->length_counter == 0 )
310 return 0; // not reading
311
312 nes_time_t first_read = Dmc_next_read_time( this );
313 nes_time_t avail = time - first_read;
314 if ( avail <= 0 )
315 return 0;
316
317 int count = (avail - 1) / (this->period * 8) + 1;
318 if ( !(osc->regs [0] & loop_flag) && count > osc->length_counter )
319 count = osc->length_counter;
320
321 if ( last_read )
322 {
323 *last_read = first_read + (count - 1) * (this->period * 8) + 1;
324 check( *last_read <= time );
325 check( count == count_reads( *last_read, NULL ) );
326 check( count - 1 == count_reads( *last_read - 1, NULL ) );
327 }
328
329 return count;
330}
331
332static short const dmc_period_table [2] [16] = {
333 {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
334 190, 160, 142, 128, 106, 84, 72, 54},
335
336 {398, 354, 316, 298, 276, 236, 210, 198, // PAL
337 176, 148, 132, 118, 98, 78, 66, 50}
338};
339
340static inline void Dmc_reload_sample( struct Nes_Dmc* this )
341{
342 this->address = 0x4000 + this->osc.regs [2] * 0x40;
343 this->osc.length_counter = this->osc.regs [3] * 0x10 + 1;
344}
345
346static int const dmc_table [128] =
347{
348 0, 24, 48, 71, 94, 118, 141, 163, 186, 209, 231, 253, 275, 297, 319, 340,
349 361, 383, 404, 425, 445, 466, 486, 507, 527, 547, 567, 587, 606, 626, 645, 664,
350 683, 702, 721, 740, 758, 777, 795, 813, 832, 850, 867, 885, 903, 920, 938, 955,
351 972, 989,1006,1023,1040,1056,1073,1089,1105,1122,1138,1154,1170,1185,1201,1217,
3521232,1248,1263,1278,1293,1308,1323,1338,1353,1368,1382,1397,1411,1425,1440,1454,
3531468,1482,1496,1510,1523,1537,1551,1564,1578,1591,1604,1618,1631,1644,1657,1670,
3541683,1695,1708,1721,1733,1746,1758,1771,1783,1795,1807,1819,1831,1843,1855,1867,
3551879,1890,1902,1914,1925,1937,1948,1959,1971,1982,1993,2004,2015,2026,2037,2048,
356};
357
358static inline int update_amp_nonlinear( struct Nes_Dmc* this, int in )
359{
360 if ( !this->nonlinear )
361 in = dmc_table [in];
362 int delta = in - this->osc.last_amp;
363 this->osc.last_amp = in;
364 return delta;
365}
366
367void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
368{
369 if ( addr == 0 )
370 {
371 this->period = dmc_period_table [this->pal_mode] [data & 15];
372 this->irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
373 this->irq_flag &= this->irq_enabled;
374 Dmc_recalc_irq( this );
375 }
376 else if ( addr == 1 )
377 {
378 this->dac = data & 0x7F;
379 }
380}
381
382void Dmc_start( struct Nes_Dmc* this )
383{
384 Dmc_reload_sample( this );
385 Dmc_fill_buffer( this );
386 Dmc_recalc_irq( this );
387}
388
389void Dmc_fill_buffer( struct Nes_Dmc* this )
390{
391 if ( !this->buf_full && this->osc.length_counter )
392 {
393 require( this->prg_reader ); // prg_reader must be set
394 this->buf = this->prg_reader( this->prg_reader_data, 0x8000u + this->address );
395 this->address = (this->address + 1) & 0x7FFF;
396 this->buf_full = true;
397 if ( --this->osc.length_counter == 0 )
398 {
399 if ( this->osc.regs [0] & loop_flag ) {
400 Dmc_reload_sample( this );
401 }
402 else {
403 this->apu->osc_enables &= ~0x10;
404 this->irq_flag = this->irq_enabled;
405 this->next_irq = apu_no_irq;
406 Apu_irq_changed( this->apu );
407 }
408 }
409 }
410}
411
412void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
413{
414 struct Nes_Osc* osc = &this->osc;
415 int delta = update_amp_nonlinear( this, this->dac );
416 if ( !osc->output )
417 {
418 this->silence = true;
419 }
420 else if ( delta )
421 {
422 Blip_set_modified( osc->output );
423 Synth_offset( &this->synth, time, delta, osc->output );
424 }
425
426 time += osc->delay;
427 if ( time < end_time )
428 {
429 int bits_remain = this->bits_remain;
430 if ( this->silence && !this->buf_full )
431 {
432 int count = (end_time - time + this->period - 1) / this->period;
433 bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
434 time += count * this->period;
435 }
436 else
437 {
438 struct Blip_Buffer* const output = osc->output;
439 const int period = this->period;
440 int bits = this->bits;
441 int dac = this->dac;
442 if ( output )
443 Blip_set_modified( output );
444
445 do
446 {
447 if ( !this->silence )
448 {
449 int step = (bits & 1) * 4 - 2;
450 bits >>= 1;
451 if ( (unsigned) (dac + step) <= 0x7F ) {
452 dac += step;
453 Synth_offset_inline( &this->synth, time, update_amp_nonlinear( this, dac ), output );
454 }
455 }
456
457 time += period;
458
459 if ( --bits_remain == 0 )
460 {
461 bits_remain = 8;
462 if ( !this->buf_full ) {
463 this->silence = true;
464 }
465 else
466 {
467 this->silence = false;
468 bits = this->buf;
469 this->buf_full = false;
470 if ( !output )
471 this->silence = true;
472 Dmc_fill_buffer( this );
473 }
474 }
475 }
476 while ( time < end_time );
477
478 this->dac = dac;
479 //osc->last_amp = dac;
480 this->bits = bits;
481 }
482 this->bits_remain = bits_remain;
483 }
484 osc->delay = time - end_time;
485}
486
487// Nes_Noise
488
489static short const noise_period_table [16] = {
490 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
491 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
492};
493
494void Noise_clock_envelope( struct Nes_Noise* this )
495{
496 struct Nes_Osc* osc = &this->osc;
497 int period = osc->regs [0] & 15;
498 if ( osc->reg_written [3] ) {
499 osc->reg_written [3] = false;
500 this->env_delay = period;
501 this->envelope = 15;
502 }
503 else if ( --this->env_delay < 0 ) {
504 this->env_delay = period;
505 if ( this->envelope | (osc->regs [0] & 0x20) )
506 this->envelope = (this->envelope - 1) & 15;
507 }
508}
509
510int Noise_volume( struct Nes_Noise* this )
511{
512 struct Nes_Osc* osc = &this->osc;
513 return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
514}
515
516void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
517{
518 struct Nes_Osc* osc = &this->osc;
519 int period = noise_period_table [osc->regs [2] & 15];
520
521 if ( !osc->output )
522 {
523 // TODO: clean up
524 time += osc->delay;
525 osc->delay = time + (end_time - time + period - 1) / period * period - end_time;
526 return;
527 }
528
529 const int volume = Noise_volume( this );
530 int amp = (this->noise & 1) ? volume : 0;
531 {
532 int delta = Osc_update_amp( osc, amp );
533 if ( delta )
534 {
535 Blip_set_modified( osc->output );
536 Synth_offset( &this->synth, time, delta, osc->output );
537 }
538 }
539
540 time += osc->delay;
541 if ( time < end_time )
542 {
543 const int mode_flag = 0x80;
544
545 if ( !volume )
546 {
547 // round to next multiple of period
548 time += (end_time - time + period - 1) / period * period;
549
550 // approximate noise cycling while muted, by shuffling up noise register
551 // to do: precise muted noise cycling?
552 if ( !(osc->regs [2] & mode_flag) ) {
553 int feedback = (this->noise << 13) ^ (this->noise << 14);
554 this->noise = (feedback & 0x4000) | (this->noise >> 1);
555 }
556 }
557 else
558 {
559 struct Blip_Buffer* const output = osc->output;
560
561 // using resampled time avoids conversion in synth.offset()
562 blip_resampled_time_t rperiod = Blip_resampled_duration( output, period );
563 blip_resampled_time_t rtime = Blip_resampled_time( output, time );
564
565 int noise = this->noise;
566 int delta = amp * 2 - volume;
567 const int tap = (osc->regs [2] & mode_flag ? 8 : 13);
568 Blip_set_modified( output );
569
570 do {
571 int feedback = (noise << tap) ^ (noise << 14);
572 time += period;
573
574 if ( (noise + 1) & 2 ) {
575 // bits 0 and 1 of noise differ
576 delta = -delta;
577 Synth_offset_resampled( &this->synth, rtime, delta, output );
578 }
579
580 rtime += rperiod;
581 noise = (feedback & 0x4000) | (noise >> 1);
582 }
583 while ( time < end_time );
584
585 osc->last_amp = (delta + volume) >> 1;
586 this->noise = noise;
587 }
588 }
589
590 osc->delay = time - end_time;
591}
592
diff --git a/lib/rbcodec/codecs/libgme/nes_oscs.h b/lib/rbcodec/codecs/libgme/nes_oscs.h
new file mode 100644
index 0000000000..1eeb302e6c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_oscs.h
@@ -0,0 +1,164 @@
1// Private oscillators used by Nes_Apu
2
3// Nes_Snd_Emu 0.1.8
4#ifndef NES_OSCS_H
5#define NES_OSCS_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9#include "nes_cpu.h"
10
11struct Nes_Apu;
12
13struct Nes_Osc
14{
15 unsigned char regs [4];
16 bool reg_written [4];
17 struct Blip_Buffer* output;
18 int length_counter;// length counter (0 if unused by oscillator)
19 int delay; // delay until next (potential) transition
20 int last_amp; // last amplitude oscillator was outputting
21};
22
23void Osc_clock_length( struct Nes_Osc* this, int halt_mask );
24static inline int Osc_period( struct Nes_Osc* this )
25{
26 return (this->regs [3] & 7) * 0x100 + (this->regs [2] & 0xFF);
27}
28
29static inline void Osc_reset( struct Nes_Osc* this )
30{
31 this->delay = 0;
32 this->last_amp = 0;
33}
34
35static inline int Osc_update_amp( struct Nes_Osc* this, int amp )
36{
37 int delta = amp - this->last_amp;
38 this->last_amp = amp;
39 return delta;
40}
41
42// Nes_Square
43
44enum { negate_flag = 0x08 };
45enum { shift_mask = 0x07 };
46enum { square_phase_range = 8 };
47
48typedef struct Blip_Synth Synth;
49
50struct Nes_Square
51{
52 struct Nes_Osc osc;
53 int envelope;
54 int env_delay;
55 int phase;
56 int sweep_delay;
57
58 Synth* synth; // shared between squares
59};
60
61static inline void Square_set_synth( struct Nes_Square* this, Synth* s ) { this->synth = s; }
62
63void Square_clock_sweep( struct Nes_Square* this, int adjust );
64void Square_run( struct Nes_Square* this, nes_time_t, nes_time_t );
65
66static inline void Square_reset( struct Nes_Square* this )
67{
68 this->sweep_delay = 0;
69 this->envelope = 0;
70 this->env_delay = 0;
71 Osc_reset( &this->osc );
72}
73
74void Square_clock_envelope( struct Nes_Square* this );
75int Square_volume( struct Nes_Square* this );
76
77// Nes_Triangle
78
79enum { Triangle_phase_range = 16 };
80
81struct Nes_Triangle
82{
83 struct Nes_Osc osc;
84
85 int phase;
86 int linear_counter;
87 struct Blip_Synth synth;
88};
89
90void Triangle_run( struct Nes_Triangle* this, nes_time_t, nes_time_t );
91void Triangle_clock_linear_counter( struct Nes_Triangle* this );
92
93static inline void Triangle_reset( struct Nes_Triangle* this )
94{
95 this->linear_counter = 0;
96 this->phase = 1;
97 Osc_reset( &this->osc );
98}
99
100// Nes_Noise
101struct Nes_Noise
102{
103 struct Nes_Osc osc;
104
105 int envelope;
106 int env_delay;
107 int noise;
108 struct Blip_Synth synth;
109};
110
111void Noise_clock_envelope( struct Nes_Noise* this );
112int Noise_volume( struct Nes_Noise* this );
113void Noise_run( struct Nes_Noise* this, nes_time_t, nes_time_t );
114
115static inline void Noise_reset( struct Nes_Noise* this )
116{
117 this->noise = 1 << 14;
118 this->envelope = 0;
119 this->env_delay = 0;
120 Osc_reset( &this->osc );
121}
122
123// Nes_Dmc
124
125enum { loop_flag = 0x40 };
126
127struct Nes_Dmc
128{
129 struct Nes_Osc osc;
130
131 int address; // address of next byte to read
132 int period;
133 int buf;
134 int bits_remain;
135 int bits;
136 bool buf_full;
137 bool silence;
138
139 int dac;
140
141 nes_time_t next_irq;
142 bool irq_enabled;
143 bool irq_flag;
144 bool pal_mode;
145 bool nonlinear;
146
147 int (*prg_reader)( void*, int ); // needs to be initialized to prg read function
148 void* prg_reader_data;
149
150 struct Nes_Apu* apu;
151
152 struct Blip_Synth synth;
153};
154
155void Dmc_start( struct Nes_Dmc* this );
156void Dmc_write_register( struct Nes_Dmc* this, int, int );
157void Dmc_run( struct Nes_Dmc* this, nes_time_t, nes_time_t );
158void Dmc_recalc_irq( struct Nes_Dmc* this );
159void Dmc_fill_buffer( struct Nes_Dmc* this );
160void Dmc_reset( struct Nes_Dmc* this );
161
162int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t, nes_time_t* );
163
164#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_vrc6_apu.c b/lib/rbcodec/codecs/libgme/nes_vrc6_apu.c
new file mode 100644
index 0000000000..99a9ae3fed
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_vrc6_apu.c
@@ -0,0 +1,192 @@
1 // Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
2
3#include "nes_vrc6_apu.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18void Vrc6_init( struct Nes_Vrc6_Apu* this )
19{
20 Synth_init( &this->saw_synth );
21 Synth_init( &this->square_synth );
22
23 Vrc6_output( this, NULL );
24 Vrc6_volume( this, (int)FP_ONE_VOLUME );
25 Vrc6_reset( this );
26}
27
28void Vrc6_reset( struct Nes_Vrc6_Apu* this )
29{
30 this->last_time = 0;
31 int i;
32 for ( i = 0; i < vrc6_osc_count; i++ )
33 {
34 struct Vrc6_Osc* osc = &this->oscs [i];
35 int j;
36 for ( j = 0; j < vrc6_reg_count; j++ )
37 osc->regs [j] = 0;
38 osc->delay = 0;
39 osc->last_amp = 0;
40 osc->phase = 1;
41 osc->amp = 0;
42 }
43}
44
45void Vrc6_output( struct Nes_Vrc6_Apu* this, struct Blip_Buffer* buf )
46{
47 int i;
48 for ( i = 0; i < vrc6_osc_count; i++ )
49 Vrc6_osc_output( this, i, buf );
50}
51
52void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t end_time );
53void run_saw( struct Nes_Vrc6_Apu* this, blip_time_t end_time );
54static void Vrc6_run_until( struct Nes_Vrc6_Apu* this, blip_time_t time )
55{
56 require( time >= this->last_time );
57 run_square( this, &this->oscs [0], time );
58 run_square( this, &this->oscs [1], time );
59 run_saw( this, time );
60 this->last_time = time;
61}
62
63void Vrc6_write_osc( struct Nes_Vrc6_Apu* this, blip_time_t time, int osc_index, int reg, int data )
64{
65 require( (unsigned) osc_index < vrc6_osc_count );
66 require( (unsigned) reg < vrc6_reg_count );
67
68 Vrc6_run_until( this, time );
69 this->oscs [osc_index].regs [reg] = data;
70}
71
72void Vrc6_end_frame( struct Nes_Vrc6_Apu* this, blip_time_t time )
73{
74 if ( time > this->last_time )
75 Vrc6_run_until( this, time );
76
77 assert( this->last_time >= time );
78 this->last_time -= time;
79}
80
81void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t end_time )
82{
83 struct Blip_Buffer* output = osc->output;
84 if ( !output )
85 return;
86
87 int volume = osc->regs [0] & 15;
88 if ( !(osc->regs [2] & 0x80) )
89 volume = 0;
90
91 int gate = osc->regs [0] & 0x80;
92 int duty = ((osc->regs [0] >> 4) & 7) + 1;
93 int delta = ((gate || osc->phase < duty) ? volume : 0) - osc->last_amp;
94 blip_time_t time = this->last_time;
95 if ( delta )
96 {
97 osc->last_amp += delta;
98 Blip_set_modified( output );
99 Synth_offset( &this->square_synth, time, delta, output );
100 }
101
102 time += osc->delay;
103 osc->delay = 0;
104 int period = Vrc6_osc_period( osc );
105 if ( volume && !gate && period > 4 )
106 {
107 if ( time < end_time )
108 {
109 int phase = osc->phase;
110 Blip_set_modified( output );
111
112 do
113 {
114 phase++;
115 if ( phase == 16 )
116 {
117 phase = 0;
118 osc->last_amp = volume;
119 Synth_offset( &this->square_synth, time, volume, output );
120 }
121 if ( phase == duty )
122 {
123 osc->last_amp = 0;
124 Synth_offset( &this->square_synth, time, -volume, output );
125 }
126 time += period;
127 }
128 while ( time < end_time );
129
130 osc->phase = phase;
131 }
132 osc->delay = time - end_time;
133 }
134}
135
136void run_saw( struct Nes_Vrc6_Apu* this, blip_time_t end_time )
137{
138 struct Vrc6_Osc* osc = &this->oscs [2];
139 struct Blip_Buffer* output = osc->output;
140 if ( !output )
141 return;
142 Blip_set_modified( output );
143
144 int amp = osc->amp;
145 int amp_step = osc->regs [0] & 0x3F;
146 blip_time_t time = this->last_time;
147 int last_amp = osc->last_amp;
148 if ( !(osc->regs [2] & 0x80) || !(amp_step | amp) )
149 {
150 osc->delay = 0;
151 int delta = (amp >> 3) - last_amp;
152 last_amp = amp >> 3;
153 Synth_offset( &this->saw_synth, time, delta, output );
154 }
155 else
156 {
157 time += osc->delay;
158 if ( time < end_time )
159 {
160 int period = Vrc6_osc_period( osc ) * 2;
161 int phase = osc->phase;
162
163 do
164 {
165 if ( --phase == 0 )
166 {
167 phase = 7;
168 amp = 0;
169 }
170
171 int delta = (amp >> 3) - last_amp;
172 if ( delta )
173 {
174 last_amp = amp >> 3;
175 Synth_offset( &this->saw_synth, time, delta, output );
176 }
177
178 time += period;
179 amp = (amp + amp_step) & 0xFF;
180 }
181 while ( time < end_time );
182
183 osc->phase = phase;
184 osc->amp = amp;
185 }
186
187 osc->delay = time - end_time;
188 }
189
190 osc->last_amp = last_amp;
191}
192
diff --git a/lib/rbcodec/codecs/libgme/nes_vrc6_apu.h b/lib/rbcodec/codecs/libgme/nes_vrc6_apu.h
new file mode 100644
index 0000000000..57b8a42a79
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_vrc6_apu.h
@@ -0,0 +1,62 @@
1// Konami VRC6 sound chip emulator
2
3// Nes_Snd_Emu 0.2.0-pre
4#ifndef NES_VRC6_APU_H
5#define NES_VRC6_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10enum { vrc6_osc_count = 3 };
11enum { vrc6_reg_count = 3 };
12enum { vrc6_base_addr = 0x9000 };
13enum { vrc6_addr_step = 0x1000 };
14
15struct Vrc6_Osc
16{
17 uint8_t regs [3];
18 struct Blip_Buffer* output;
19 int delay;
20 int last_amp;
21 int phase;
22 int amp; // only used by saw
23};
24
25static inline int Vrc6_osc_period( struct Vrc6_Osc* this )
26{
27 return (this->regs [2] & 0x0F) * 0x100 + this->regs [1] + 1;
28}
29
30struct Nes_Vrc6_Apu {
31 struct Vrc6_Osc oscs [vrc6_osc_count];
32 blip_time_t last_time;
33
34 struct Blip_Synth saw_synth;
35 struct Blip_Synth square_synth;
36};
37
38// See Nes_Apu.h for reference
39void Vrc6_init( struct Nes_Vrc6_Apu* this );
40void Vrc6_reset( struct Nes_Vrc6_Apu* this );
41void Vrc6_output( struct Nes_Vrc6_Apu* this, struct Blip_Buffer* );
42void Vrc6_end_frame( struct Nes_Vrc6_Apu* this, blip_time_t );
43
44// Oscillator 0 write-only registers are at $9000-$9002
45// Oscillator 1 write-only registers are at $A000-$A002
46// Oscillator 2 write-only registers are at $B000-$B002
47void Vrc6_write_osc( struct Nes_Vrc6_Apu* this, blip_time_t, int osc, int reg, int data );
48
49static inline void Vrc6_osc_output( struct Nes_Vrc6_Apu* this, int i, struct Blip_Buffer* buf )
50{
51 assert( (unsigned) i < vrc6_osc_count );
52 this->oscs [i].output = buf;
53}
54
55static inline void Vrc6_volume( struct Nes_Vrc6_Apu* this, int v )
56{
57 long long const factor = (long long)(FP_ONE_VOLUME * 0.0967 * 2);
58 Synth_volume( &this->saw_synth, (int)(v * factor / 31 / FP_ONE_VOLUME) );
59 Synth_volume( &this->square_synth, (int)(v * factor / 2 / 15 / FP_ONE_VOLUME) );
60}
61
62#endif
diff --git a/lib/rbcodec/codecs/libgme/nes_vrc7_apu.c b/lib/rbcodec/codecs/libgme/nes_vrc7_apu.c
new file mode 100644
index 0000000000..8d3c2e88a6
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_vrc7_apu.c
@@ -0,0 +1,88 @@
1
2#include "nes_vrc7_apu.h"
3#include "blargg_source.h"
4
5int const period = 36; // NES CPU clocks per FM clock
6
7void Vrc7_init( struct Nes_Vrc7_Apu* this )
8{
9 Synth_init( &this->synth );
10
11 OPLL_new ( &this->opll, 3579545, 3579545 / 72 );
12 OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
13
14 this->osc.output = 0;
15 this->osc.last_amp = 0;
16 this->mask = 0;
17
18 Vrc7_volume( this, (int)FP_ONE_VOLUME );
19 Vrc7_reset( this );
20}
21
22void Vrc7_reset( struct Nes_Vrc7_Apu* this )
23{
24 this->addr = 0;
25 this->next_time = 0;
26 this->osc.last_amp = 0;
27
28 OPLL_reset (&this->opll);
29 OPLL_setMask(&this->opll, this->mask);
30}
31
32void Vrc7_set_rate( struct Nes_Vrc7_Apu* this, int r )
33{
34 OPLL_set_quality( &this->opll, r < 44100 ? 0 : 1 );
35}
36
37void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int data )
38{
39 this->addr = data;
40}
41
42void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time );
43void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t time, int data )
44{
45 if ( time > this->next_time )
46 Vrc7_run_until( this, time );
47
48 OPLL_writeIO( &this->opll, 0, this->addr );
49 OPLL_writeIO( &this->opll, 1, data );
50}
51
52void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t time )
53{
54 if ( time > this->next_time )
55 Vrc7_run_until( this, time );
56
57 this->next_time -= time;
58 assert( this->next_time >= 0 );
59
60 if ( this->osc.output )
61 Blip_set_modified( this->osc.output );
62}
63
64void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time )
65{
66 require( end_time > this->next_time );
67
68 blip_time_t time = this->next_time;
69 OPLL* opll = &this->opll; // cache
70 struct Blip_Buffer* const output = this-> osc.output;
71 if ( output )
72 {
73 do
74 {
75 int amp = OPLL_calc( opll ) << 1;
76 int delta = amp - this->osc.last_amp;
77 if ( delta )
78 {
79 this->osc.last_amp = amp;
80 Synth_offset_inline( &this->synth, time, delta, output );
81 }
82 time += period;
83 }
84 while ( time < end_time );
85 }
86
87 this->next_time = time;
88}
diff --git a/lib/rbcodec/codecs/libgme/nes_vrc7_apu.h b/lib/rbcodec/codecs/libgme/nes_vrc7_apu.h
new file mode 100644
index 0000000000..1f45a435db
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nes_vrc7_apu.h
@@ -0,0 +1,52 @@
1// Konami VRC7 sound chip emulator
2
3#ifndef NES_VRC7_APU_H
4#define NES_VRC7_APU_H
5
6#include "blargg_common.h"
7#include "blip_buffer.h"
8
9#include "emu2413.h"
10
11enum { vrc7_osc_count = 6 };
12
13struct vrc7_osc_t {
14 struct Blip_Buffer* output;
15 int last_amp;
16};
17
18struct Nes_Vrc7_Apu {
19 OPLL opll;
20 int addr;
21 blip_time_t next_time;
22 struct vrc7_osc_t osc;
23 struct Blip_Synth synth;
24 e_uint32 mask;
25};
26
27// See Nes_Apu.h for reference
28void Vrc7_init( struct Nes_Vrc7_Apu* this );
29void Vrc7_reset( struct Nes_Vrc7_Apu* this );
30void Vrc7_set_rate( struct Nes_Vrc7_Apu* this, int r );
31void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t );
32
33void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int reg );
34void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t, int data );
35
36void output_changed( struct Nes_Vrc7_Apu* this );
37static inline void Vrc7_set_output( struct Nes_Vrc7_Apu* this, int i, struct Blip_Buffer* buf )
38{
39 assert( (unsigned) i < vrc7_osc_count );
40 this->mask |= 1 << i;
41
42 // Will use OPLL_setMask to mute voices
43 if ( buf ) {
44 this->mask ^= 1 << i;
45 this->osc.output = buf;
46 }
47}
48
49// DB2LIN_AMP_BITS == 11, * 2
50static inline void Vrc7_volume( struct Nes_Vrc7_Apu* this, int v ) { Synth_volume( &this->synth, v / 3 / 4096 ); }
51
52#endif
diff --git a/lib/rbcodec/codecs/libgme/nsf_cpu.c b/lib/rbcodec/codecs/libgme/nsf_cpu.c
new file mode 100644
index 0000000000..1f44bd3c3c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nsf_cpu.c
@@ -0,0 +1,115 @@
1// Normal cpu for NSF emulator
2
3// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
4
5#include "nsf_emu.h"
6
7#include "blargg_endian.h"
8
9#ifdef BLARGG_DEBUG_H
10 //#define CPU_LOG_START 1000000
11 //#include "nes_cpu_log.h"
12 #undef LOG_MEM
13#endif
14
15/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
16can redistribute it and/or modify it under the terms of the GNU Lesser
17General Public License as published by the Free Software Foundation; either
18version 2.1 of the License, or (at your option) any later version. This
19module is distributed in the hope that it will be useful, but WITHOUT ANY
20WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
22details. You should have received a copy of the GNU Lesser General Public
23License along with this module; if not, write to the Free Software Foundation,
24Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
25
26#include "blargg_source.h"
27
28#ifndef LOG_MEM
29 #define LOG_MEM( addr, str, data ) data
30#endif
31
32int read_mem( struct Nsf_Emu* this, addr_t addr )
33{
34 int result = this->low_ram [addr & (low_ram_size-1)]; // also handles wrap-around
35 if ( addr & 0xE000 )
36 {
37 result = *Cpu_get_code( &this->cpu, addr );
38 if ( addr < sram_addr )
39 {
40 if ( addr == apu_status_addr )
41 result = Apu_read_status( &this->apu, Cpu_time( &this->cpu ) );
42 else
43 result = cpu_read( this, addr );
44 }
45 }
46 return LOG_MEM( addr, ">", result );
47}
48
49void write_mem( struct Nsf_Emu* this, addr_t addr, int data )
50{
51 (void) LOG_MEM( addr, "<", data );
52
53 int offset = addr - sram_addr;
54 if ( (unsigned) offset < sram_size )
55 {
56 sram( this ) [offset] = data;
57 }
58 else
59 {
60 // after sram because cpu handles most low_ram accesses internally already
61 int temp = addr & (low_ram_size-1); // also handles wrap-around
62 if ( !(addr & 0xE000) )
63 {
64 this->low_ram [temp] = data;
65 }
66 else
67 {
68 int bank = addr - banks_addr;
69 if ( (unsigned) bank < bank_count )
70 {
71 write_bank( this, bank, data );
72 }
73 else if ( (unsigned) (addr - apu_io_addr) < apu_io_size )
74 {
75 Apu_write_register( &this->apu, Cpu_time( &this->cpu ), addr, data );
76 }
77 else
78 {
79 #ifndef NSF_EMU_APU_ONLY
80 // 0x8000-0xDFFF is writable
81 int i = addr - 0x8000;
82 if ( fds_enabled( this ) && (unsigned) i < fdsram_size )
83 fdsram( this ) [i] = data;
84 else
85 #endif
86 cpu_write( this, addr, data );
87 }
88 }
89 }
90}
91
92#define READ_LOW( addr ) (LOG_MEM( addr, ">", this->low_ram [addr] ))
93#define WRITE_LOW( addr, data ) (LOG_MEM( addr, "<", this->low_ram [addr] = data ))
94
95#define CAN_WRITE_FAST( addr ) (addr < low_ram_size)
96#define WRITE_FAST WRITE_LOW
97
98// addr < 0x2000 || addr >= 0x8000
99#define CAN_READ_FAST( addr ) ((addr ^ 0x8000) < 0xA000)
100#define READ_FAST( addr, out ) (LOG_MEM( addr, ">", out = READ_CODE( addr ) ))
101
102#define READ_MEM( addr ) read_mem( this, addr )
103#define WRITE_MEM( addr, data ) write_mem( this, addr, data )
104
105#define CPU_BEGIN \
106bool run_cpu_until( struct Nsf_Emu* this, nes_time_t end ) \
107{ \
108 struct Nes_Cpu* cpu = &this->cpu; \
109 Cpu_set_end_time( cpu, end ); \
110 if ( *Cpu_get_code( cpu, cpu->r.pc ) != halt_opcode ) \
111 {
112 #include "nes_cpu_run.h"
113 }
114 return Cpu_time_past_end( cpu ) < 0;
115}
diff --git a/lib/rbcodec/codecs/libgme/nsf_emu.c b/lib/rbcodec/codecs/libgme/nsf_emu.c
new file mode 100644
index 0000000000..d9fc4e031d
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nsf_emu.c
@@ -0,0 +1,921 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "nsf_emu.h"
4#include "multi_buffer.h"
5
6#include "blargg_endian.h"
7
8/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21const char gme_wrong_file_type [] = "Wrong file type for this emulator";
22
23// number of frames until play interrupts init
24int const initial_play_delay = 7; // KikiKaikai needed this to work
25int const bank_size = 0x1000;
26int const rom_addr = 0x8000;
27
28static void clear_track_vars( struct Nsf_Emu* this )
29{
30 this->current_track = -1;
31 track_stop( &this->track_filter );
32}
33
34static int pcm_read( void* emu, int addr )
35{
36 return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr );
37}
38
39void Nsf_init( struct Nsf_Emu* this )
40{
41 this->sample_rate = 0;
42 this->mute_mask_ = 0;
43 this->tempo = (int)(FP_ONE_TEMPO);
44 this->gain = (int)(FP_ONE_GAIN);
45
46 // defaults
47 this->tfilter = *track_get_setup( &this->track_filter );
48 this->tfilter.max_initial = 2;
49 this->tfilter.lookahead = 6;
50 this->track_filter.silence_ignored_ = false;
51
52 // Set sound gain
53 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
54
55 // Init rom
56 Rom_init( &this->rom, bank_size );
57
58 // Init & clear nsfe info
59 Info_init( &this->info );
60 Info_unload( &this->info ); // TODO: extremely hacky!
61
62 Cpu_init( &this->cpu );
63 Apu_init( &this->apu );
64 Apu_dmc_reader( &this->apu, pcm_read, this );
65
66 // Unload
67 this->voice_count = 0;
68 memset( this->voice_types, 0, sizeof this->voice_types );
69 clear_track_vars( this );
70}
71
72// Setup
73
74static void append_voices( struct Nsf_Emu* this, int const types [], int count )
75{
76 assert( this->voice_count + count < max_voices );
77 int i;
78 for ( i = 0; i < count; i++ ) {
79 this->voice_types [this->voice_count + i] = types [i];
80 }
81 this->voice_count += count;
82}
83
84static blargg_err_t init_sound( struct Nsf_Emu* this )
85{
86/* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) )
87 warning( "Uses unsupported audio expansion hardware" ); **/
88
89 {
90 static int const types [apu_osc_count] = {
91 wave_type+1, wave_type+2, mixed_type+1, noise_type+0, mixed_type+1
92 };
93 append_voices( this, types, apu_osc_count );
94 }
95
96 int adjusted_gain = (this->gain * 4) / 3;
97
98 #ifdef NSF_EMU_APU_ONLY
99 {
100 if ( this->header_.chip_flags )
101 set_warning( "Uses unsupported audio expansion hardware" );
102 }
103 #else
104 {
105 if ( vrc6_enabled( this ) )
106 {
107 Vrc6_init( &this->vrc6 );
108 adjusted_gain = (adjusted_gain*3) / 4;
109
110 static int const types [vrc6_osc_count] = {
111 wave_type+3, wave_type+4, wave_type+5,
112 };
113 append_voices( this, types, vrc6_osc_count );
114 }
115
116 if ( fme7_enabled( this ) )
117 {
118 Fme7_init( &this->fme7 );
119 adjusted_gain = (adjusted_gain*3) / 4;
120
121 static int const types [fme7_osc_count] = {
122 wave_type+3, wave_type+4, wave_type+5,
123 };
124 append_voices( this, types, fme7_osc_count );
125 }
126
127 if ( mmc5_enabled( this ) )
128 {
129 Mmc5_init( &this->mmc5 );
130 adjusted_gain = (adjusted_gain*3) / 4;
131
132
133 static int const types [mmc5_osc_count] = {
134 wave_type+3, wave_type+4, mixed_type+2
135 };
136 append_voices( this, types, mmc5_osc_count );
137 }
138
139 if ( fds_enabled( this ) )
140 {
141 Fds_init( &this->fds );
142 adjusted_gain = (adjusted_gain*3) / 4;
143
144 static int const types [fds_osc_count] = {
145 wave_type+0
146 };
147 append_voices( this, types, fds_osc_count );
148 }
149
150 if ( namco_enabled( this ) )
151 {
152 Namco_init( &this->namco );
153 adjusted_gain = (adjusted_gain*3) / 4;
154
155 static int const types [namco_osc_count] = {
156 wave_type+3, wave_type+4, wave_type+5, wave_type+ 6,
157 wave_type+7, wave_type+8, wave_type+9, wave_type+10,
158 };
159 append_voices( this, types, namco_osc_count );
160 }
161
162 #ifndef NSF_EMU_NO_VRC7
163 if ( vrc7_enabled( this ) )
164 {
165
166 Vrc7_init( &this->vrc7 );
167 Vrc7_set_rate( &this->vrc7, this->sample_rate );
168
169 adjusted_gain = (adjusted_gain*3) / 4;
170
171 static int const types [vrc7_osc_count] = {
172 wave_type+3, wave_type+4, wave_type+5, wave_type+6,
173 wave_type+7, wave_type+8
174 };
175 append_voices( this, types, vrc7_osc_count );
176 }
177
178 if ( vrc7_enabled( this ) ) Vrc7_volume( &this->vrc7, adjusted_gain );
179 #endif
180 if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain );
181 if ( vrc6_enabled( this ) ) Vrc6_volume( &this->vrc6, adjusted_gain );
182 if ( fme7_enabled( this ) ) Fme7_volume( &this->fme7, adjusted_gain );
183 if ( mmc5_enabled( this ) ) Apu_volume( &this->mmc5.apu, adjusted_gain );
184 if ( fds_enabled( this ) ) Fds_volume( &this->fds, adjusted_gain );
185 }
186 #endif
187
188 if ( adjusted_gain > this->gain )
189 adjusted_gain = this->gain;
190
191 Apu_volume( &this->apu, adjusted_gain );
192
193 return 0;
194}
195
196// Header stuff
197static bool valid_tag( struct header_t* this )
198{
199 return 0 == memcmp( this->tag, "NESM\x1A", 5 );
200}
201
202// True if file supports only PAL speed
203static bool pal_only( struct header_t* this )
204{
205 return (this->speed_flags & 3) == 1;
206}
207
208static int clock_rate( struct header_t* this )
209{
210 return pal_only( this ) ? (int)1662607.125 : (int)1789772.727272727;
211}
212
213static int play_period( struct header_t* this )
214{
215 // NTSC
216 int clocks = 29780;
217 int value = 0x411A;
218 byte const* rate_ptr = this->ntsc_speed;
219
220 // PAL
221 if ( pal_only( this ) )
222 {
223 clocks = 33247;
224 value = 0x4E20;
225 rate_ptr = this->pal_speed;
226 }
227
228 // Default rate
229 int rate = get_le16( rate_ptr );
230 if ( rate == 0 )
231 rate = value;
232
233 // Custom rate
234 if ( rate != value )
235 clocks = (int) ((1LL * rate * clock_rate( this )) / 1000000);
236
237 return clocks;
238}
239
240// Gets address, given pointer to it in file header. If zero, returns rom_addr.
241addr_t get_addr( byte const in [] )
242{
243 addr_t addr = get_le16( in );
244 if ( addr == 0 )
245 addr = rom_addr;
246 return addr;
247}
248
249static blargg_err_t check_nsf_header( struct header_t* h )
250{
251 if ( !valid_tag( h ) )
252 return gme_wrong_file_type;
253 return 0;
254}
255
256blargg_err_t Nsf_load_mem( struct Nsf_Emu* this, void* data, long size )
257{
258 // Unload
259 Info_unload( &this->info ); // TODO: extremely hacky!
260 this->m3u.size = 0;
261
262 this->voice_count = 0;
263 clear_track_vars( this );
264
265 assert( offsetof (struct header_t,unused [4]) == header_size );
266
267 if ( !memcmp( data, "NESM\x1A", 5 ) ) {
268 Nsf_disable_playlist( this, true );
269
270 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
271 return Nsf_post_load( this );
272 }
273
274 blargg_err_t err = Info_load( &this->info, data, size, this );
275 Nsf_disable_playlist( this, false );
276 return err;
277}
278
279blargg_err_t Nsf_post_load( struct Nsf_Emu* this )
280{
281 RETURN_ERR( check_nsf_header( &this->header ) );
282
283 /* if ( header_.vers != 1 )
284 warning( "Unknown file version" ); */
285
286 // set up data
287 addr_t load_addr = get_addr( this->header.load_addr );
288 /* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) )
289 warning( "Load address is too low" ); */
290
291 Rom_set_addr( &this->rom, load_addr % this->rom.bank_size );
292
293 /* if ( header_.vers != 1 )
294 warning( "Unknown file version" ); */
295
296 set_play_period( this, play_period( &this->header ) );
297
298 // sound and memory
299 blargg_err_t err = init_sound( this );
300 if ( err )
301 return err;
302
303 // Set track_count
304 this->track_count = this->header.track_count;
305
306 // Change clock rate & setup buffer
307 this->clock_rate__ = clock_rate( &this->header );
308 Buffer_clock_rate( &this->stereo_buf, this->clock_rate__ );
309 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
310 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
311
312 // Post load
313 Sound_set_tempo( this, this->tempo );
314 Sound_mute_voices( this, this->mute_mask_ );
315 return 0;
316}
317
318void Nsf_disable_playlist( struct Nsf_Emu* this, bool b )
319{
320 Info_disable_playlist( &this->info, b );
321 this->track_count = this->info.track_count;
322}
323
324void Nsf_clear_playlist( struct Nsf_Emu* this )
325{
326 Nsf_disable_playlist( this, true );
327}
328
329void write_bank( struct Nsf_Emu* this, int bank, int data )
330{
331 // Find bank in ROM
332 int offset = mask_addr( data * this->rom.bank_size, this->rom.mask );
333 /* if ( offset >= rom.size() )
334 warning( "invalid bank" ); */
335 void const* rom_data = Rom_at_addr( &this->rom, offset );
336
337 #ifndef NSF_EMU_APU_ONLY
338 if ( bank < bank_count - fds_banks && fds_enabled( this ) )
339 {
340 // TODO: FDS bank switching is kind of hacky, might need to
341 // treat ROM as RAM so changes won't get lost when switching.
342 byte* out = sram( this );
343 if ( bank >= fds_banks )
344 {
345 out = fdsram( this );
346 bank -= fds_banks;
347 }
348 memcpy( &out [bank * this->rom.bank_size], rom_data, this->rom.bank_size );
349 return;
350 }
351 #endif
352
353 if ( bank >= fds_banks )
354 Cpu_map_code( &this->cpu, (bank + 6) * this->rom.bank_size, this->rom.bank_size, rom_data, false );
355}
356
357static void map_memory( struct Nsf_Emu* this )
358{
359 // Map standard things
360 Cpu_reset( &this->cpu, unmapped_code( this ) );
361 Cpu_map_code( &this->cpu, 0, 0x2000, this->low_ram, low_ram_size ); // mirrored four times
362 Cpu_map_code( &this->cpu, sram_addr, sram_size, sram( this ), 0 );
363
364 // Determine initial banks
365 byte banks [bank_count];
366 static byte const zero_banks [sizeof this->header.banks] = { 0 };
367 if ( memcmp( this->header.banks, zero_banks, sizeof zero_banks ) )
368 {
369 banks [0] = this->header.banks [6];
370 banks [1] = this->header.banks [7];
371 memcpy( banks + fds_banks, this->header.banks, sizeof this->header.banks );
372 }
373 else
374 {
375 // No initial banks, so assign them based on load_addr
376 int i, first_bank = (get_addr( this->header.load_addr ) - sram_addr) / this->rom.bank_size;
377 unsigned total_banks = this->rom.size / this->rom.bank_size;
378 for ( i = bank_count; --i >= 0; )
379 {
380 int bank = i - first_bank;
381 if ( (unsigned) bank >= total_banks )
382 bank = 0;
383 banks [i] = bank;
384 }
385 }
386
387 // Map banks
388 int i;
389 for ( i = (fds_enabled( this ) ? 0 : fds_banks); i < bank_count; ++i )
390 write_bank( this, i, banks [i] );
391
392 // Map FDS RAM
393 if ( fds_enabled( this ) )
394 Cpu_map_code( &this->cpu, rom_addr, fdsram_size, fdsram( this ), 0 );
395}
396
397static void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, struct Blip_Buffer* left, struct Blip_Buffer* right)
398{
399#if defined(ROCKBOX)
400 (void) left;
401 (void) right;
402#endif
403
404 if ( i < apu_osc_count )
405 {
406 Apu_osc_output( &this->apu, i, buf );
407 return;
408 }
409 i -= apu_osc_count;
410
411 #ifndef NSF_EMU_APU_ONLY
412 {
413 if ( vrc6_enabled( this ) && (i -= vrc6_osc_count) < 0 )
414 {
415 Vrc6_osc_output( &this->vrc6, i + vrc6_osc_count, buf );
416 return;
417 }
418
419 if ( fme7_enabled( this ) && (i -= fme7_osc_count) < 0 )
420 {
421 Fme7_osc_output( &this->fme7, i + fme7_osc_count, buf );
422 return;
423 }
424
425 if ( mmc5_enabled( this ) && (i -= mmc5_osc_count) < 0 )
426 {
427 Mmc5_set_output( &this->mmc5, i + mmc5_osc_count, buf );
428 return;
429 }
430
431 if ( fds_enabled( this ) && (i -= fds_osc_count) < 0 )
432 {
433 Fds_set_output( &this->fds, i + fds_osc_count, buf );
434 return;
435 }
436
437 if ( namco_enabled( this ) && (i -= namco_osc_count) < 0 )
438 {
439 Namco_osc_output( &this->namco, i + namco_osc_count, buf );
440 return;
441 }
442
443 #ifndef NSF_EMU_NO_VRC7
444 if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 )
445 {
446 Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf );
447 return;
448 }
449 #endif
450 }
451 #endif
452}
453
454// Emulation
455
456// Music Emu
457
458blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, int rate )
459{
460 require( !this->sample_rate ); // sample rate can't be changed once set
461 Buffer_init( &this->stereo_buf );
462 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
463
464 // Set bass frequency
465 Buffer_bass_freq( &this->stereo_buf, 80 );
466
467 this->sample_rate = rate;
468 RETURN_ERR( track_init( &this->track_filter, this ) );
469 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
470 return 0;
471}
472
473void Sound_mute_voice( struct Nsf_Emu* this, int index, bool mute )
474{
475 require( (unsigned) index < (unsigned) this->voice_count );
476 int bit = 1 << index;
477 int mask = this->mute_mask_ | bit;
478 if ( !mute )
479 mask ^= bit;
480 Sound_mute_voices( this, mask );
481}
482
483void Sound_mute_voices( struct Nsf_Emu* this, int mask )
484{
485 require( this->sample_rate ); // sample rate must be set first
486 this->mute_mask_ = mask;
487
488 int i;
489 for ( i = this->voice_count; i--; )
490 {
491 if ( mask & (1 << i) )
492 {
493 set_voice( this, i, 0, 0, 0 );
494 }
495 else
496 {
497 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
498 assert( (ch.center && ch.left && ch.right) ||
499 (!ch.center && !ch.left && !ch.right) ); // all or nothing
500 set_voice( this, i, ch.center, ch.left, ch.right );
501 }
502 }
503}
504
505void Sound_set_tempo( struct Nsf_Emu* this, int t )
506{
507 require( this->sample_rate ); // sample rate must be set first
508 int const min = (int)(FP_ONE_TEMPO*0.02);
509 int const max = (int)(FP_ONE_TEMPO*4.00);
510 if ( t < min ) t = min;
511 if ( t > max ) t = max;
512 this->tempo = t;
513
514 set_play_period( this, (int) ((play_period( &this->header ) * FP_ONE_TEMPO) / t) );
515
516 Apu_set_tempo( &this->apu, t );
517
518#ifndef NSF_EMU_APU_ONLY
519 if ( fds_enabled( this ) )
520 Fds_set_tempo( &this->fds, t );
521#endif
522}
523
524static inline void push_byte( struct Nsf_Emu* this, int b )
525{
526 this->low_ram [0x100 + this->cpu.r.sp--] = b;
527}
528
529// Jumps to routine, given pointer to address in file header. Pushes idle_addr
530// as return address, NOT old PC.
531static void jsr_then_stop( struct Nsf_Emu* this, byte const addr [] )
532{
533 this->cpu.r.pc = get_addr( addr );
534 push_byte( this, (idle_addr - 1) >> 8 );
535 push_byte( this, (idle_addr - 1) );
536}
537
538int cpu_read( struct Nsf_Emu* this, addr_t addr )
539{
540 #ifndef NSF_EMU_APU_ONLY
541 {
542 if ( namco_enabled( this ) && addr == namco_data_reg_addr )
543 return Namco_read_data( &this->namco );
544
545 if ( fds_enabled( this ) && (unsigned) (addr - fds_io_addr) < fds_io_size )
546 return Fds_read( &this->fds, Cpu_time( &this->cpu ), addr );
547
548 if ( mmc5_enabled( this ) ) {
549 int i = addr - 0x5C00;
550 if ( (unsigned) i < mmc5_exram_size )
551 return this->mmc5.exram [i];
552
553 int m = addr - 0x5205;
554 if ( (unsigned) m < 2 )
555 return (this->mmc5_mul [0] * this->mmc5_mul [1]) >> (m * 8) & 0xFF;
556 }
557 }
558 #endif
559
560 /* Unmapped read */
561 return addr >> 8;
562}
563
564void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
565{
566 #ifndef NSF_EMU_APU_ONLY
567 {
568 if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size )
569 {
570 Fds_write( &this->fds, Cpu_time( &this->cpu ), addr, data );
571 return;
572 }
573
574 if ( namco_enabled( this) )
575 {
576 if ( addr == namco_addr_reg_addr )
577 {
578 Namco_write_addr( &this->namco, data );
579 return;
580 }
581
582 if ( addr == namco_data_reg_addr )
583 {
584 Namco_write_data( &this->namco, Cpu_time( &this->cpu ), data );
585 return;
586 }
587 }
588
589 if ( vrc6_enabled( this) )
590 {
591 int reg = addr & (vrc6_addr_step - 1);
592 int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step;
593 if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count )
594 {
595 Vrc6_write_osc( &this->vrc6, Cpu_time( &this->cpu ), osc, reg, data );
596 return;
597 }
598 }
599
600 if ( fme7_enabled( this) && addr >= fme7_latch_addr )
601 {
602 switch ( addr & fme7_addr_mask )
603 {
604 case fme7_latch_addr:
605 Fme7_write_latch( &this->fme7, data );
606 return;
607
608 case fme7_data_addr:
609 Fme7_write_data( &this->fme7, Cpu_time( &this->cpu ), data );
610 return;
611 }
612 }
613
614 if ( mmc5_enabled( this) )
615 {
616 if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size )
617 {
618 Mmc5_write_register( &this->mmc5, Cpu_time( &this->cpu ), addr, data );
619 return;
620 }
621
622 int m = addr - 0x5205;
623 if ( (unsigned) m < 2 )
624 {
625 this->mmc5_mul [m] = data;
626 return;
627 }
628
629 int i = addr - 0x5C00;
630 if ( (unsigned) i < mmc5_exram_size )
631 {
632 this->mmc5.exram [i] = data;
633 return;
634 }
635 }
636
637 #ifndef NSF_EMU_NO_VRC7
638 if ( vrc7_enabled( this) )
639 {
640 if ( addr == 0x9010 )
641 {
642 Vrc7_write_reg( &this->vrc7, data );
643 return;
644 }
645
646 if ( (unsigned) (addr - 0x9028) <= 0x08 )
647 {
648 Vrc7_write_data( &this->vrc7, Cpu_time( &this->cpu ), data );
649 return;
650 }
651 }
652 #endif
653 }
654 #endif
655
656 // Unmapped_write
657}
658
659blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
660{
661 clear_track_vars( this );
662
663 // Remap track if playlist available
664 if ( this->m3u.size > 0 ) {
665 struct entry_t* e = &this->m3u.entries[track];
666 track = e->track;
667 }
668 else track = Info_remap_track( &this->info, track );
669
670 this->current_track = track;
671 Buffer_clear( &this->stereo_buf );
672
673 #ifndef NSF_EMU_APU_ONLY
674 if ( mmc5_enabled( this ) )
675 {
676 this->mmc5_mul [0] = 0;
677 this->mmc5_mul [1] = 0;
678 memset( this->mmc5.exram, 0, mmc5_exram_size );
679 }
680
681 if ( fds_enabled( this ) ) Fds_reset( &this->fds );
682 if ( namco_enabled( this ) ) Namco_reset( &this->namco );
683 if ( vrc6_enabled( this ) ) Vrc6_reset( &this->vrc6 );
684 if ( fme7_enabled( this ) ) Fme7_reset( &this->fme7 );
685 if ( mmc5_enabled( this ) ) Apu_reset( &this->mmc5.apu, false, 0 );
686 #ifndef NSF_EMU_NO_VRC7
687 if ( vrc7_enabled( this ) ) Vrc7_reset( &this->vrc7 );
688 #endif
689 #endif
690
691 int speed_flags = 0;
692 #ifdef NSF_EMU_EXTRA_FLAGS
693 speed_flags = this->header.speed_flags;
694 #endif
695
696 Apu_reset( &this->apu, pal_only( &this->header ), (speed_flags & 0x20) ? 0x3F : 0 );
697 Apu_write_register( &this->apu, 0, 0x4015, 0x0F );
698 Apu_write_register( &this->apu, 0, 0x4017, (speed_flags & 0x10) ? 0x80 : 0 );
699
700 memset( unmapped_code( this ), halt_opcode, unmapped_size );
701 memset( this->low_ram, 0, low_ram_size );
702 memset( sram( this ), 0, sram_size );
703
704 map_memory( this );
705
706 // Arrange time of first call to play routine
707 this->play_extra = 0;
708 this->next_play = this->play_period;
709
710 this->play_delay = initial_play_delay;
711 this->saved_state.pc = idle_addr;
712
713 // Setup for call to init routine
714 this->cpu.r.a = track;
715 this->cpu.r.x = pal_only( &this->header );
716 this->cpu.r.sp = 0xFF;
717 jsr_then_stop( this, this->header.init_addr );
718 /* if ( this->cpu.r.pc < get_addr( header.load_addr ) )
719 warning( "Init address < load address" ); */
720
721 // convert filter times to samples
722 struct setup_t s = this->tfilter;
723 s.max_initial *= this->sample_rate * stereo;
724 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
725 s.lookahead = 1;
726 #endif
727 track_setup( &this->track_filter, &s );
728
729 return track_start( &this->track_filter );
730}
731
732void run_once( struct Nsf_Emu* this, nes_time_t end )
733{
734 // Emulate until next play call if possible
735 if ( run_cpu_until( this, min( this->next_play, end ) ) )
736 {
737 // Halt instruction encountered
738
739 if ( this->cpu.r.pc != idle_addr )
740 {
741 // special_event( "illegal instruction" );
742 Cpu_set_time( &this->cpu, this->cpu.end_time );
743 return;
744 }
745
746 // Init/play routine returned
747 this->play_delay = 1; // play can now be called regularly
748
749 if ( this->saved_state.pc == idle_addr )
750 {
751 // nothing to run
752 nes_time_t t = this->cpu.end_time;
753 if ( Cpu_time( &this->cpu ) < t )
754 Cpu_set_time( &this->cpu, t );
755 }
756 else
757 {
758 // continue init routine that was interrupted by play routine
759 this->cpu.r = this->saved_state;
760 this->saved_state.pc = idle_addr;
761 }
762 }
763
764 if ( Cpu_time( &this->cpu ) >= this->next_play )
765 {
766 // Calculate time of next call to play routine
767 this->play_extra ^= 1; // extra clock every other call
768 this->next_play += this->play_period + this->play_extra;
769
770 // Call routine if ready
771 if ( this->play_delay && !--this->play_delay )
772 {
773 // Save state if init routine is still running
774 if ( this->cpu.r.pc != idle_addr )
775 {
776 check( this->saved_state.pc == idle_addr );
777 this->saved_state = this->cpu.r;
778 // special_event( "play called during init" );
779 }
780
781 jsr_then_stop( this, this->header.play_addr );
782 }
783 }
784}
785
786void run_until( struct Nsf_Emu* this, nes_time_t end )
787{
788 while ( Cpu_time( &this->cpu ) < end )
789 run_once( this, end );
790}
791
792static void end_frame( struct Nsf_Emu* this, nes_time_t end )
793{
794 if ( Cpu_time( &this->cpu ) < end )
795 run_until( this, end );
796 Cpu_adjust_time( &this->cpu, -end );
797
798 // Localize to new time frame
799 this->next_play -= end;
800 check( this->next_play >= 0 );
801 if ( this->next_play < 0 )
802 this->next_play = 0;
803
804 Apu_end_frame( &this->apu, end );
805
806 #ifndef NSF_EMU_APU_ONLY
807 if ( fds_enabled( this ) ) Fds_end_frame( &this->fds, end );
808 if ( fme7_enabled( this ) ) Fme7_end_frame( &this->fme7, end );
809 if ( mmc5_enabled( this ) ) Apu_end_frame( &this->mmc5.apu, end );
810 if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end );
811 if ( vrc6_enabled( this ) ) Vrc6_end_frame( &this->vrc6, end );
812 #ifndef NSF_EMU_NO_VRC7
813 if ( vrc7_enabled( this ) ) Vrc7_end_frame( &this->vrc7, end );
814 #endif
815 #endif
816}
817
818// Tell/Seek
819
820static int msec_to_samples( int msec, int sample_rate )
821{
822 int sec = msec / 1000;
823 msec -= sec * 1000;
824 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
825}
826
827int Track_tell( struct Nsf_Emu* this )
828{
829 int rate = this->sample_rate * stereo;
830 int sec = track_sample_count( &this->track_filter ) / rate;
831 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
832}
833
834blargg_err_t Track_seek( struct Nsf_Emu* this, int msec )
835{
836 int time = msec_to_samples( msec, this->sample_rate );
837 if ( time < track_sample_count( &this->track_filter ) )
838 RETURN_ERR( Nsf_start_track( this, this->current_track ) );
839 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
840}
841
842blargg_err_t Track_skip( struct Nsf_Emu* this, int count )
843{
844 require( this->current_track >= 0 ); // start_track() must have been called already
845 return track_skip( &this->track_filter, count );
846}
847
848blargg_err_t skip_( void *emu, int count )
849{
850 struct Nsf_Emu* this = (struct Nsf_Emu*) emu;
851
852 // for long skip, mute sound
853 const int threshold = 32768;
854 if ( count > threshold )
855 {
856 int saved_mute = this->mute_mask_;
857 Sound_mute_voices( this, ~0 );
858
859 int n = count - threshold/2;
860 n &= ~(2048-1); // round to multiple of 2048
861 count -= n;
862 RETURN_ERR( skippy_( &this->track_filter, n ) );
863
864 Sound_mute_voices( this, saved_mute );
865 }
866
867 return skippy_( &this->track_filter, count );
868}
869
870// Fading
871
872void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec )
873{
874 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
875 length_msec * this->sample_rate / (1000 / stereo) );
876}
877
878blargg_err_t Nsf_play( struct Nsf_Emu* this, int out_count, sample_t* out )
879{
880 require( this->current_track >= 0 );
881 require( out_count % stereo == 0 );
882 return track_play( &this->track_filter, out_count, out );
883}
884
885blargg_err_t play_( void* emu, int count, sample_t* out )
886{
887 struct Nsf_Emu* this = (struct Nsf_Emu*) emu;
888
889 int remain = count;
890 while ( remain )
891 {
892 Buffer_disable_immediate_removal( &this->stereo_buf );
893 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
894 if ( remain )
895 {
896 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
897 {
898 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
899
900 // Remute voices
901 Sound_mute_voices( this, this->mute_mask_ );
902 }
903 int msec = Buffer_length( &this->stereo_buf );
904 blip_time_t clocks_emulated = msec * this->clock_rate__ / 1000 - 100;
905 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
906 assert( clocks_emulated );
907 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
908 }
909 }
910 return 0;
911}
912
913blargg_err_t run_clocks( struct Nsf_Emu* this, blip_time_t* duration, int msec )
914{
915#if defined(ROCKBOX)
916 (void) msec;
917#endif
918
919 end_frame( this, *duration );
920 return 0;
921}
diff --git a/lib/rbcodec/codecs/libgme/nsf_emu.h b/lib/rbcodec/codecs/libgme/nsf_emu.h
new file mode 100644
index 0000000000..00bdad4a4e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nsf_emu.h
@@ -0,0 +1,261 @@
1// Nintendo NES/Famicom NSF music file emulator
2
3// Game_Music_Emu 0.5.5
4#ifndef NSF_EMU_H
5#define NSF_EMU_H
6
7#include "rom_data.h"
8#include "multi_buffer.h"
9#include "nes_apu.h"
10#include "nes_cpu.h"
11#include "nsfe_info.h"
12#include "m3u_playlist.h"
13#include "track_filter.h"
14
15#ifndef NSF_EMU_APU_ONLY
16 #include "nes_namco_apu.h"
17 #include "nes_vrc6_apu.h"
18 #include "nes_fme7_apu.h"
19 #include "nes_fds_apu.h"
20 #include "nes_mmc5_apu.h"
21 #ifndef NSF_EMU_NO_VRC7
22 #include "nes_vrc7_apu.h"
23 #endif
24#endif
25
26// Sound chip flags
27enum {
28 vrc6_flag = 1 << 0,
29 vrc7_flag = 1 << 1,
30 fds_flag = 1 << 2,
31 mmc5_flag = 1 << 3,
32 namco_flag = 1 << 4,
33 fme7_flag = 1 << 5
34};
35
36enum { fds_banks = 2 };
37enum { bank_count = fds_banks + 8 };
38
39enum { rom_begin = 0x8000 };
40enum { bank_select_addr = 0x5FF8 };
41enum { mem_size = 0x10000 };
42
43// cpu sits here when waiting for next call to play routine
44enum { idle_addr = 0x5FF6 };
45enum { banks_addr = idle_addr };
46enum { badop_addr = bank_select_addr };
47
48enum { low_ram_size = 0x800 };
49enum { sram_size = 0x2000 };
50enum { fdsram_size = 0x6000 };
51enum { fdsram_offset = 0x2000 + page_size + 8 };
52enum { sram_addr = 0x6000 };
53enum { unmapped_size= page_size + 8 };
54enum { max_voices = 32 };
55
56// NSF file header
57enum { header_size = 0x80 };
58struct header_t
59{
60 char tag [5];
61 byte vers;
62 byte track_count;
63 byte first_track;
64 byte load_addr [2];
65 byte init_addr [2];
66 byte play_addr [2];
67 char game [32];
68 char author [32];
69 char copyright [32];
70 byte ntsc_speed [2];
71 byte banks [8];
72 byte pal_speed [2];
73 byte speed_flags;
74 byte chip_flags;
75 byte unused [4];
76};
77
78struct Nsf_Emu {
79 // Play routine timing
80 nes_time_t next_play;
81 nes_time_t play_period;
82 int play_extra;
83 int play_delay;
84 struct registers_t saved_state; // of interrupted init routine
85
86 // general
87 int voice_count;
88 int voice_types [32];
89 int mute_mask_;
90 int tempo;
91 int gain;
92
93 int sample_rate;
94
95 // track-specific
96 int track_count;
97 int current_track;
98
99 int clock_rate__;
100 unsigned buf_changed_count;
101
102 // M3u Playlist
103 struct M3u_Playlist m3u;
104
105 // Larger items at the end
106 #ifndef NSF_EMU_APU_ONLY
107 byte mmc5_mul [2];
108
109 struct Nes_Fds_Apu fds;
110 struct Nes_Mmc5_Apu mmc5;
111 struct Nes_Namco_Apu namco;
112 struct Nes_Vrc6_Apu vrc6;
113 struct Nes_Fme7_Apu fme7;
114 #ifndef NSF_EMU_NO_VRC7
115 struct Nes_Vrc7_Apu vrc7;
116 #endif
117 #endif
118
119 struct Nes_Cpu cpu;
120 struct Nes_Apu apu;
121
122 // Header for currently loaded file
123 struct header_t header;
124
125 struct setup_t tfilter;
126 struct Track_Filter track_filter;
127
128 struct Multi_Buffer stereo_buf;
129 struct Rom_Data rom;
130
131 // Extended nsf info
132 struct Nsfe_Info info;
133
134 byte high_ram[fdsram_size + fdsram_offset];
135 byte low_ram [low_ram_size];
136};
137
138// Basic functionality (see Gme_File.h for file loading/track info functions)
139
140void Nsf_init( struct Nsf_Emu* this );
141blargg_err_t Nsf_load_mem( struct Nsf_Emu* this, void* data, long size );
142blargg_err_t Nsf_post_load( struct Nsf_Emu* this );
143
144// Set output sample rate. Must be called only once before loading file.
145blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, int sample_rate );
146
147// Start a track, where 0 is the first track. Also clears warning string.
148blargg_err_t Nsf_start_track( struct Nsf_Emu* this , int );
149
150// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
151// errors set warning string, and major errors also end track.
152blargg_err_t Nsf_play( struct Nsf_Emu* this, int count, sample_t* buf );
153
154void Nsf_clear_playlist( struct Nsf_Emu* this );
155void Nsf_disable_playlist( struct Nsf_Emu* this, bool b ); // use clear_playlist()
156
157// Track status/control
158
159// Number of milliseconds (1000 msec = 1 second) played since beginning of track
160int Track_tell( struct Nsf_Emu* this );
161
162// Seek to new time in track. Seeking backwards or far forward can take a while.
163blargg_err_t Track_seek( struct Nsf_Emu* this, int msec );
164
165// Skip n samples
166blargg_err_t Track_skip( struct Nsf_Emu* this, int n );
167
168// Set start time and length of track fade out. Once fade ends track_ended() returns
169// true. Fade time can be changed while track is playing.
170void Track_set_fade( struct Nsf_Emu* this, int start_msec, int length_msec );
171
172// True if a track has reached its end
173static inline bool Track_ended( struct Nsf_Emu* this )
174{
175 return track_ended( &this->track_filter );
176}
177
178// Disables automatic end-of-track detection and skipping of silence at beginning
179static inline void Track_ignore_silence( struct Nsf_Emu* this, bool disable )
180{
181 this->track_filter.silence_ignored_ = disable;
182}
183
184// Get track length in milliseconds
185int Track_length( struct Nsf_Emu* this, int n );
186
187// Sound customization
188
189// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
190// Track length as returned by track_info() assumes a tempo of 1.0.
191void Sound_set_tempo( struct Nsf_Emu* this, int t );
192
193// Mute/unmute voice i, where voice 0 is first voice
194void Sound_mute_voice( struct Nsf_Emu* this, int index, bool mute );
195
196// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
197// 0 unmutes them all, 0x01 mutes just the first voice, etc.
198void Sound_mute_voices( struct Nsf_Emu* this, int mask );
199
200// Change overall output amplitude, where 1.0 results in minimal clamping.
201// Must be called before set_sample_rate().
202static inline void Sound_set_gain( struct Nsf_Emu* this, int g )
203{
204 assert( !this->sample_rate ); // you must set gain before setting sample rate
205 this->gain = g;
206}
207
208// Emulation (You shouldn't touch these)
209
210blargg_err_t run_clocks( struct Nsf_Emu* this, blip_time_t* duration, int );
211
212void write_bank( struct Nsf_Emu* this, int index, int data );
213int cpu_read( struct Nsf_Emu* this, addr_t );
214void cpu_write( struct Nsf_Emu* this, addr_t, int );
215addr_t get_addr( byte const [] );
216bool run_cpu_until( struct Nsf_Emu* this, nes_time_t end );
217
218// Sets clocks between calls to play routine to p + 1/2 clock
219static inline void set_play_period( struct Nsf_Emu* this, int p ) { this->play_period = p; }
220
221// Time play routine will next be called
222static inline nes_time_t play_time( struct Nsf_Emu* this ) { return this->next_play; }
223
224// Emulates to at least time t. Might emulate a few clocks extra.
225void run_until( struct Nsf_Emu* this, nes_time_t t );
226
227// Runs cpu to at least time t and returns false, or returns true
228// if it encounters illegal instruction (halt).
229bool run_cpu_until( struct Nsf_Emu* this, nes_time_t t );
230
231// cpu calls through to these to access memory (except instructions)
232int read_mem( struct Nsf_Emu* this, addr_t );
233void write_mem( struct Nsf_Emu* this, addr_t, int );
234
235// Address of play routine
236static inline addr_t play_addr( struct Nsf_Emu* this ) { return get_addr( this->header.play_addr ); }
237
238// Same as run_until, except emulation stops for any event (routine returned,
239// play routine called, illegal instruction).
240void run_once( struct Nsf_Emu* this, nes_time_t );
241
242// Reads byte as cpu would when executing code. Only works for RAM/ROM,
243// NOT I/O like sound chips.
244int read_code( struct Nsf_Emu* this, addr_t addr );
245
246static inline byte* fdsram( struct Nsf_Emu* this ) { return &this->high_ram [fdsram_offset]; }
247static inline byte* sram( struct Nsf_Emu* this ) { return this->high_ram; }
248static inline byte* unmapped_code( struct Nsf_Emu* this ) { return &this->high_ram [sram_size]; }
249
250#ifndef NSF_EMU_APU_ONLY
251 static inline int fds_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fds_flag; }
252 static inline int vrc6_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc6_flag; }
253 #ifndef NSF_EMU_NO_VRC7
254 static inline int vrc7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & vrc7_flag; }
255 #endif
256 static inline int mmc5_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & mmc5_flag; }
257 static inline int namco_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & namco_flag; }
258 static inline int fme7_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & fme7_flag; }
259#endif
260
261#endif
diff --git a/lib/rbcodec/codecs/libgme/nsfe_info.c b/lib/rbcodec/codecs/libgme/nsfe_info.c
new file mode 100644
index 0000000000..337b1e580a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nsfe_info.c
@@ -0,0 +1,272 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
2
3#include "nsf_emu.h"
4
5#include "blargg_endian.h"
6#include <string.h>
7
8/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21void Info_init( struct Nsfe_Info* this )
22{
23 this->playlist_disabled = false;
24}
25
26void Info_unload( struct Nsfe_Info* this )
27{
28 memset(this->playlist, 0, 256);
29 memset(this->track_times, 0, 256 * sizeof(int32_t));
30
31 this->playlist_size = 0;
32 this->track_times_size = 0;
33}
34
35// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
36void Info_disable_playlist( struct Nsfe_Info* this, bool b )
37{
38 this->playlist_disabled = b;
39 this->track_count = this->playlist_size;
40 if ( !this->track_count || this->playlist_disabled )
41 this->track_count = this->actual_track_count_;
42}
43
44int Info_remap_track( struct Nsfe_Info* this, int track )
45{
46 if ( !this->playlist_disabled && (unsigned) track < (unsigned) this->playlist_size )
47 track = this->playlist [track];
48 return track;
49}
50
51const char eof_error [] = "Unexpected end of file";
52
53// Read n bytes from memory buffer
54static blargg_err_t in_read( void* dst, long bytes, void* data, long* offset, long size )
55{
56 if ((*offset + bytes) > size) return eof_error;
57
58 memcpy(dst, (char*) data + *offset, bytes);
59 *offset += bytes;
60 return 0;
61}
62
63static blargg_err_t in_skip( long bytes, long *offset, long size )
64{
65 if ((*offset + bytes) > size) return eof_error;
66
67 *offset += bytes;
68 return 0;
69}
70
71// Skip n bytes from memory buffer
72
73// Read multiple strings and separate into individual strings
74static int read_strs( void* data, long bytes, long* offset, long size,
75 const char* strs [4] )
76{
77 char* chars = (char*) data + *offset;
78 chars [bytes - 1] = 0; // in case last string doesn't have terminator
79
80 if ( in_skip( bytes, offset, size) )
81 return -1;
82
83 int count = 0, i;
84 for ( i = 0; i < bytes; i++ )
85 {
86 strs [count] = &chars [i];
87 while ( i < bytes && chars [i] )
88 i++;
89
90 count++;
91 if (count >= 4)
92 break;
93 }
94
95 return count;
96}
97
98struct nsfe_info_t
99{
100 byte load_addr [2];
101 byte init_addr [2];
102 byte play_addr [2];
103 byte speed_flags;
104 byte chip_flags;
105 byte track_count;
106 byte first_track;
107 byte unused [6];
108};
109
110blargg_err_t Info_load( struct Nsfe_Info* this, void* data, long size, struct Nsf_Emu* nsf_emu )
111{
112 long offset = 0;
113 int const nsfe_info_size = 16;
114 assert( offsetof (struct nsfe_info_t,unused [6]) == nsfe_info_size );
115
116 // check header
117 byte signature [4];
118 blargg_err_t err = in_read( signature, sizeof signature, data, &offset, size );
119 if ( err )
120 return (err == eof_error ? gme_wrong_file_type : err);
121 if ( memcmp( signature, "NSFE", 4 ) ) {
122 }
123
124 // free previous info
125 /* TODO: clear track_names */
126 memset(this->playlist, 0, 256);
127 memset(this->track_times, 0, 256 * sizeof(int32_t));
128
129 this->playlist_size = 0;
130 this->track_times_size = 0;
131
132 // default nsf header
133 static const struct header_t base_header =
134 {
135 {'N','E','S','M','\x1A'},// tag
136 1, // version
137 1, 1, // track count, first track
138 {0,0},{0,0},{0,0}, // addresses
139 "","","", // strings
140 {0x1A, 0x41}, // NTSC rate
141 {0,0,0,0,0,0,0,0}, // banks
142 {0x20, 0x4E}, // PAL rate
143 0, 0, // flags
144 {0,0,0,0} // unused
145 };
146
147 memcpy( &nsf_emu->header, &base_header, sizeof base_header );
148
149 // parse tags
150 int phase = 0;
151 while ( phase != 3 )
152 {
153 // read size and tag
154 byte block_header [2] [4];
155 RETURN_ERR( in_read( block_header, sizeof block_header, data, &offset, size ) );
156
157 int chunk_size = get_le32( block_header [0] );
158 int tag = get_le32( block_header [1] );
159
160 switch ( tag )
161 {
162 case BLARGG_4CHAR('O','F','N','I'): {
163 check( phase == 0 );
164 if ( chunk_size < 8 )
165 return "Corrupt file";
166
167 struct nsfe_info_t finfo;
168 finfo.track_count = 1;
169 finfo.first_track = 0;
170
171 RETURN_ERR( in_read( &finfo, min( chunk_size, nsfe_info_size ),
172 (char*) data, &offset, size ) );
173
174 if ( chunk_size > nsfe_info_size )
175 RETURN_ERR( in_skip( chunk_size - nsfe_info_size, &offset, size ) );
176
177 phase = 1;
178 nsf_emu->header.speed_flags = finfo.speed_flags;
179 nsf_emu->header.chip_flags = finfo.chip_flags;
180 nsf_emu->header.track_count = finfo.track_count;
181 this->actual_track_count_ = finfo.track_count;
182 nsf_emu->header.first_track = finfo.first_track;
183 memcpy( nsf_emu->header.load_addr, finfo.load_addr, 2 * 3 );
184 break;
185 }
186
187 case BLARGG_4CHAR('K','N','A','B'):
188 if ( chunk_size > (int) sizeof nsf_emu->header.banks )
189 return "Corrupt file";
190 RETURN_ERR( in_read( nsf_emu->header.banks, chunk_size, data, &offset, size ) );
191 break;
192
193 case BLARGG_4CHAR('h','t','u','a'): {
194 const char* strs [4];
195 int n = read_strs( data, chunk_size, &offset, size, strs );
196 if ( n < 0 )
197 return eof_error;
198 break;
199 }
200
201 case BLARGG_4CHAR('e','m','i','t'):
202 this->track_times_size = chunk_size / 4;
203 RETURN_ERR( in_read( this->track_times, this->track_times_size * 4, data, &offset, size ) );
204 break;
205
206 case BLARGG_4CHAR('l','b','l','t'):
207 RETURN_ERR( in_skip( chunk_size, &offset, size ) );
208 break;
209
210 case BLARGG_4CHAR('t','s','l','p'):
211 this->playlist_size = chunk_size;
212 RETURN_ERR( in_read( &this->playlist [0], chunk_size, data, &offset, size ) );
213 break;
214
215 case BLARGG_4CHAR('A','T','A','D'): {
216 check( phase == 1 );
217 phase = 2;
218 if ( !nsf_emu )
219 {
220 RETURN_ERR( in_skip( chunk_size, &offset, size ) );
221 }
222 else
223 {
224 // Avoid unexpected end of file
225 if ( (offset + chunk_size) > size )
226 return eof_error;
227
228 RETURN_ERR( Rom_load( &nsf_emu->rom, (char*) data + offset, chunk_size, 0, 0, 0 ) );
229 RETURN_ERR( Nsf_post_load( nsf_emu ) );
230 offset += chunk_size;
231 }
232 break;
233 }
234
235 case BLARGG_4CHAR('D','N','E','N'):
236 check( phase == 2 );
237 phase = 3;
238 break;
239
240 default:
241 // tags that can be skipped start with a lowercase character
242 check( islower( (tag >> 24) & 0xFF ) );
243 RETURN_ERR( in_skip( chunk_size, &offset, size ) );
244 break;
245 }
246 }
247
248 return 0;
249}
250
251int Track_length( struct Nsf_Emu* this, int n )
252{
253 int length = 0;
254 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
255 struct entry_t* entry = &this->m3u.entries [n];
256 length = entry->length;
257 }
258 else if ( (this->info.playlist_size > 0) && (n < this->info.playlist_size) ) {
259 int remapped = Info_remap_track( &this->info, n );
260 if ( (unsigned) remapped < (unsigned) this->info.track_times_size )
261 length = (int32_t) get_le32( &this->info.track_times [remapped] );
262 }
263 else if( (unsigned) n < (unsigned) this->info.track_times_size )
264 length = (int32_t) get_le32( &this->info.track_times [n] );
265
266 /* Length will be 2,30 minutes for one track songs,
267 and 1,45 minutes for multitrack songs */
268 if ( length <= 0 )
269 length = (this->track_count > 1 ? 105 : 150) * 1000;
270
271 return length;
272}
diff --git a/lib/rbcodec/codecs/libgme/nsfe_info.h b/lib/rbcodec/codecs/libgme/nsfe_info.h
new file mode 100644
index 0000000000..9dcde7b68a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/nsfe_info.h
@@ -0,0 +1,30 @@
1// Nintendo NES/Famicom NSFE file info parser
2
3// Game_Music_Emu 0.5.5
4#ifndef NSFE_INFO_H
5#define NSFE_INFO_H
6
7#include "blargg_common.h"
8
9struct Nsf_Emu;
10
11// Allows reading info from NSFE file without creating emulator
12struct Nsfe_Info {
13 int playlist_size;
14 int track_times_size;
15 int track_count;
16 int actual_track_count_;
17 bool playlist_disabled;
18
19 unsigned char playlist [256];
20 int32_t track_times [256];
21};
22
23void Info_init( struct Nsfe_Info* this );
24blargg_err_t Info_load( struct Nsfe_Info* this, void *data, long size, struct Nsf_Emu* );
25void Info_disable_playlist( struct Nsfe_Info* this, bool b );
26int Info_remap_track( struct Nsfe_Info* this, int i );
27void Info_unload( struct Nsfe_Info* this );
28
29
30#endif
diff --git a/lib/rbcodec/codecs/libgme/opl_apu.c b/lib/rbcodec/codecs/libgme/opl_apu.c
new file mode 100644
index 0000000000..b573baef11
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/opl_apu.c
@@ -0,0 +1,198 @@
1#include "opl_apu.h"
2
3#include "blargg_source.h"
4
5/* NOTE: Removed unused chips ~ gama */
6
7blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type )
8{
9 Synth_init( &this->synth );
10
11 this->type_ = type;
12 this->clock_ = clock;
13 this->rate_ = rate;
14 this->period_ = period;
15 Opl_set_output( this, 0 );
16 Opl_volume( this, (int)FP_ONE_VOLUME );
17
18 switch (type)
19 {
20 case type_opll:
21 case type_msxmusic:
22 case type_smsfmunit:
23 OPLL_new ( &this->opll, clock, rate );
24 OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
25 break;
26 case type_vrc7:
27 OPLL_new ( &this->opll, clock, rate );
28 OPLL_reset_patch( &this->opll, OPLL_VRC7_TONE );
29 break;
30 case type_msxaudio:
31 OPL_init( &this->opl, this->opl_memory, sizeof this->opl_memory );
32 OPL_setSampleRate( &this->opl, rate, clock );
33 OPL_setInternalVolume(&this->opl, 1 << 13);
34 break;
35 }
36
37 Opl_reset( this );
38 return 0;
39}
40
41void Opl_shutdown( struct Opl_Apu* this )
42{
43 switch (this->type_)
44 {
45 case type_opll:
46 case type_msxmusic:
47 case type_smsfmunit:
48 case type_vrc7:
49 OPLL_delete( &this->opll );
50 break;
51 case type_msxaudio: break;
52 }
53}
54
55void Opl_reset( struct Opl_Apu* this )
56{
57 this->addr = 0;
58 this->next_time = 0;
59 this->last_amp = 0;
60
61 switch (this->type_)
62 {
63 case type_opll:
64 case type_msxmusic:
65 case type_smsfmunit:
66 case type_vrc7:
67 OPLL_reset( &this->opll );
68 OPLL_setMask( &this->opll, 0 );
69 break;
70 case type_msxaudio:
71 OPL_reset( &this->opl );
72 break;
73 }
74}
75
76static void run_until( struct Opl_Apu* this, blip_time_t end_time );
77void Opl_write_data( struct Opl_Apu* this, blip_time_t time, int data )
78{
79 run_until( this, time );
80 switch (this->type_)
81 {
82 case type_opll:
83 case type_msxmusic:
84 case type_smsfmunit:
85 case type_vrc7:
86 OPLL_writeIO( &this->opll, 0, this->addr );
87 OPLL_writeIO( &this->opll, 1, data );
88 break;
89 case type_msxaudio:
90 OPL_writeReg( &this->opl, this->addr, data );
91 break;
92 }
93}
94
95int Opl_read( struct Opl_Apu* this, blip_time_t time, int port )
96{
97 run_until( this, time );
98 switch (this->type_)
99 {
100 case type_opll:
101 case type_msxmusic:
102 case type_smsfmunit:
103 case type_vrc7:
104 return OPLL_read( &this->opll, port );
105 case type_msxaudio:
106 return OPL_readStatus( &this->opl );
107 }
108
109 return 0;
110}
111
112void Opl_end_frame( struct Opl_Apu* this, blip_time_t time )
113{
114 run_until( this, time );
115 this->next_time -= time;
116
117 if ( this->output_ )
118 Blip_set_modified( this->output_ );
119}
120
121static void run_until( struct Opl_Apu* this, blip_time_t end_time )
122{
123 if ( end_time > this->next_time )
124 {
125 blip_time_t time_delta = end_time - this->next_time;
126 blip_time_t time = this->next_time;
127 unsigned count = time_delta / this->period_ + 1;
128 switch (this->type_)
129 {
130 case type_opll:
131 case type_msxmusic:
132 case type_smsfmunit:
133 case type_vrc7:
134 {
135 OPLL* opll = &this->opll; // cache
136 struct Blip_Buffer* const output = this->output_;
137 while ( count > 0 )
138 {
139 unsigned todo = count;
140 if ( todo > 1024 ) todo = 1024;
141 short *buffer = OPLL_update_buffer(opll, todo);
142
143 if ( output && buffer )
144 {
145 int last_amp = this->last_amp;
146 unsigned i;
147 for ( i = 0; i < todo; i++ )
148 {
149 int amp = buffer [i];
150 int delta = amp - last_amp;
151 if ( delta )
152 {
153 last_amp = amp;
154 Synth_offset_inline( &this->synth, time, delta, output );
155 }
156 time += this->period_;
157 }
158 this->last_amp = last_amp;
159 }
160 count -= todo;
161 }
162 }
163 break;
164 case type_msxaudio:
165 {
166 struct Y8950* opl = &this->opl;
167 struct Blip_Buffer* const output = this->output_;
168 while ( count > 0 )
169 {
170 unsigned todo = count;
171 if ( todo > 1024 ) todo = 1024;
172 int *buffer = OPL_updateBuffer(opl, todo);
173
174 if ( output && buffer )
175 {
176 int last_amp = this->last_amp;
177 unsigned i;
178 for ( i = 0; i < todo; i++ )
179 {
180 int amp = buffer [i];
181 int delta = amp - last_amp;
182 if ( delta )
183 {
184 last_amp = amp;
185 Synth_offset_inline( &this->synth, time, delta, output );
186 }
187 time += this->period_;
188 }
189 this->last_amp = last_amp;
190 }
191 count -= todo;
192 }
193 }
194 break;
195 }
196 this->next_time = time;
197 }
198}
diff --git a/lib/rbcodec/codecs/libgme/opl_apu.h b/lib/rbcodec/codecs/libgme/opl_apu.h
new file mode 100644
index 0000000000..76fa766492
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/opl_apu.h
@@ -0,0 +1,63 @@
1#ifndef OPL_APU_H
2#define OPL_APU_H
3
4#include "blargg_common.h"
5#include "blargg_source.h"
6#include "blip_buffer.h"
7
8#include "emu8950.h"
9#include "emu2413.h"
10
11enum opl_type_t { type_opll = 0x10, type_msxmusic = 0x11, type_smsfmunit = 0x12,
12 type_vrc7 = 0x13, type_msxaudio = 0x21 };
13
14enum { opl_osc_count = 1 };
15
16struct Opl_Apu {
17 struct Blip_Buffer* output_;
18 enum opl_type_t type_;
19
20 blip_time_t next_time;
21 int last_amp;
22 int addr;
23
24 long clock_;
25 long rate_;
26 blip_time_t period_;
27
28 struct Blip_Synth synth;
29
30 // OPL chips
31 struct Y8950 opl;
32 OPLL opll;
33
34 unsigned char regs[ 0x100 ];
35 unsigned char opl_memory[ 32768 ];
36};
37
38blargg_err_t Opl_init( struct Opl_Apu* this, long clock, long rate, blip_time_t period, enum opl_type_t type );
39void Opl_shutdown( struct Opl_Apu* this );
40
41void Opl_reset( struct Opl_Apu* this );
42static inline void Opl_volume( struct Opl_Apu* this, int v ) { Synth_volume( &this->synth, v / (4096 * 6) ); }
43
44static inline void Opl_osc_output( struct Opl_Apu* this, int i, struct Blip_Buffer* buf )
45{
46#if defined(ROCKBOX)
47 (void) i;
48#endif
49 assert( (unsigned) i < opl_osc_count );
50 this->output_ = buf;
51}
52
53static inline void Opl_set_output( struct Opl_Apu* this, struct Blip_Buffer* buf ) { Opl_osc_output( this, 0, buf ); }
54void Opl_end_frame( struct Opl_Apu* this, blip_time_t );
55
56static inline void Opl_write_addr( struct Opl_Apu* this, int data ) { this->addr = data; }
57void Opl_write_data( struct Opl_Apu* this, blip_time_t, int data );
58
59int Opl_read( struct Opl_Apu* this, blip_time_t, int port );
60
61static inline bool Opl_supported( void ) { return true; }
62
63#endif
diff --git a/lib/rbcodec/codecs/libgme/opltables.h b/lib/rbcodec/codecs/libgme/opltables.h
new file mode 100644
index 0000000000..50fc0a86c6
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/opltables.h
@@ -0,0 +1,242 @@
1#ifndef _OPLTABLES_H_
2#define _OPLTABLES_H_
3
4/* Precalculated emu8950 tables for use in Rockbox,
5 Calculated for 44Khz sampling rate */
6
7static const short ar_adjust_coeff[] = {
8 255, 227, 210, 198, 189, 181, 175, 170, 165, 161, 157,
9 153, 150, 147, 144, 141, 139, 136, 134, 132, 130, 128,
10 126, 125, 123, 121, 120, 118, 117, 115, 114, 113, 112,
11 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100,
12 99, 98, 97, 96, 95, 94, 94, 93, 92, 91, 91,
13 90, 89, 88, 88, 87, 86, 86, 85, 84, 84, 83,
14 82, 82, 81, 81, 80, 79, 79, 78, 78, 77, 77,
15 76, 76, 75, 75, 74, 74, 73, 73, 72, 72, 71,
16 71, 70, 70, 69, 69, 69, 68, 68, 67, 67, 66,
17 66, 66, 65, 65, 64, 64, 64, 63, 63, 62, 62,
18 62, 61, 61, 61, 60, 60, 60, 59, 59, 59, 58,
19 58, 58, 57, 57, 57, 56, 56, 56, 55, 55, 55,
20 54, 54, 54, 53, 53, 53, 53, 52, 52, 52, 51,
21 51, 51, 50, 50, 50, 50, 49, 49, 49, 49, 48,
22 48, 48, 48, 47, 47, 47, 46, 46, 46, 46, 45,
23 45, 45, 45, 44, 44, 44, 44, 44, 43, 43, 43,
24 43, 42, 42, 42, 42, 41, 41, 41, 41, 41, 40,
25 40, 40, 40, 39, 39, 39, 39, 39, 38, 38, 38,
26 38, 38, 37, 37, 37, 37, 37, 36, 36, 36, 36,
27 36, 35, 35, 35, 35, 35, 34, 34, 34, 34, 34,
28 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, 32,
29 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30,
30 30, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28,
31 28, 28, 27, 27, 27, 27, 27, 27, 26, 26, 26,
32 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25,
33 24, 24, 24, 24, 24, 24, 23, 23, 23, 23, 23,
34 23, 23, 22, 22, 22, 22, 22, 22, 22, 21, 21,
35 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
36 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18,
37 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17,
38 17, 17, 17, 17, 16, 16, 16, 16, 16, 16, 16,
39 16, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14,
40 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13,
41 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
42 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
43 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
44 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8,
45 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7,
46 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
47 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
48 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
49 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3,
50 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2,
51 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
52 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0
55};
56
57static const short db2lin_coeff[] = {
58 2047, 2003, 1960, 1918, 1877, 1837, 1798, 1759, 1722, 1685, 1649,
59 1614, 1579, 1546, 1513, 1480, 1449, 1418, 1387, 1358, 1329, 1300,
60 1273, 1245, 1219, 1193, 1167, 1142, 1118, 1094, 1071, 1048, 1025,
61 1004, 982, 961, 941, 920, 901, 882, 863, 844, 826, 809,
62 791, 774, 758, 742, 726, 710, 695, 680, 666, 651, 638,
63 624, 611, 598, 585, 572, 560, 548, 536, 525, 514, 503,
64 492, 481, 471, 461, 451, 442, 432, 423, 414, 405, 396,
65 388, 380, 371, 364, 356, 348, 341, 333, 326, 319, 312,
66 306, 299, 293, 287, 280, 274, 269, 263, 257, 252, 246,
67 241, 236, 231, 226, 221, 216, 212, 207, 203, 198, 194,
68 190, 186, 182, 178, 174, 170, 167, 163, 160, 156, 153,
69 150, 147, 143, 140, 137, 134, 131, 129, 126, 123, 121,
70 118, 115, 113, 111, 108, 106, 104, 101, 99, 97, 95,
71 93, 91, 89, 87, 85, 83, 82, 80, 78, 76, 75,
72 73, 72, 70, 69, 67, 66, 64, 63, 61, 60, 59,
73 58, 56, 55, 54, 53, 52, 51, 49, 48, 47, 46,
74 45, 44, 43, 42, 42, 41, 40, 39, 38, 37, 36,
75 36, 35, 34, 33, 33, 32, 31, 31, 30, 29, 29,
76 28, 27, 27, 26, 26, 25, 25, 24, 23, 23, 22,
77 22, 21, 21, 21, 20, 20, 19, 19, 18, 18, 18,
78 17, 17, 16, 16, 16, 15, 15, 15, 14, 14, 14,
79 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11,
80 11, 10, 10, 10, 10, 9, 9, 9, 9, 9, 8,
81 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7,
82 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5,
83 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4,
84 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
85 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
86 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
87 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
88 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
90 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0
105};
106
107static const short sin_coeff[] = {
108 511, 235, 203, 185, 171, 161, 152, 145, 139, 134, 129,
109 124, 120, 117, 113, 110, 107, 104, 102, 99, 97, 95,
110 92, 90, 88, 87, 85, 83, 81, 80, 78, 77, 75,
111 74, 72, 71, 70, 69, 67, 66, 65, 64, 63, 62,
112 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 52,
113 51, 50, 49, 48, 48, 47, 46, 45, 45, 44, 43,
114 43, 42, 41, 41, 40, 39, 39, 38, 38, 37, 37,
115 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31,
116 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26,
117 25, 25, 25, 24, 24, 23, 23, 23, 22, 22, 22,
118 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18,
119 18, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15,
120 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12,
121 12, 11, 11, 11, 11, 11, 10, 10, 10, 10, 9,
122 9, 9, 9, 9, 8, 8, 8, 8, 8, 7, 7,
123 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 5,
124 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4,
125 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
126 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
128 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0,
132};
133
134static const short pm0_coeff[] = {
135 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
136 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
137 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
138 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
139 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
140 256, 256, 257, 257, 257, 257, 257, 257, 257, 257, 257,
141 257, 257, 257, 257, 257, 257, 256, 256, 256, 256, 256,
142 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
143 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
144 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
145 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
146 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
147 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
148 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
149 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
150 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
151 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254,
152 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
153 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
154 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
155 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
156 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
157 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
158 255, 255, 255,
159};
160
161static const short pm1_coeff[] = {
162 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
163 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 257,
164 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
165 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
166 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
167 257, 258, 258, 258, 258, 258, 258, 258, 258, 258, 258,
168 258, 258, 258, 258, 258, 258, 258, 257, 257, 257, 257,
169 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
170 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
171 257, 257, 257, 257, 257, 257, 257, 257, 257, 256, 256,
172 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
173 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255,
174 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
175 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254,
176 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
177 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
178 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253,
179 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
180 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
181 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
182 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
183 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255,
184 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
185 255, 255, 255,
186};
187
188static const short am0_coeff[] = {
189 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
190 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
191 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
192 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
193 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
194 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
195 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
196 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4,
197 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
198 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3,
199 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
200 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
201 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
202 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
203 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
209 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
210 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
211 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
212 2, 2, 2,
213};
214
215static const short am1_coeff[] = {
216 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15,
217 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 19,
218 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
219 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23,
220 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25,
221 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
222 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
223 24, 24, 24, 24, 24, 24, 24, 24, 23, 23, 23,
224 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21,
225 21, 20, 20, 20, 20, 19, 19, 19, 19, 18, 18,
226 18, 17, 17, 17, 17, 16, 16, 16, 15, 15, 15,
227 14, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11,
228 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8,
229 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5,
230 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2,
231 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
235 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
236 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5,
237 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8,
238 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11,
239 11, 12, 12,
240};
241
242#endif
diff --git a/lib/rbcodec/codecs/libgme/resampler.c b/lib/rbcodec/codecs/libgme/resampler.c
new file mode 100644
index 0000000000..c4f42a9794
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/resampler.c
@@ -0,0 +1,218 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
2
3#include "resampler.h"
4
5#include <stdlib.h>
6#include <string.h>
7
8/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21// TODO: fix this. hack since resampler holds back some output.
22unsigned const resampler_extra = 34;
23
24enum { shift = 14 };
25int const unit = 1 << shift;
26
27blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain )
28{
29 this->gain_ = (int)( ((1LL << gain_bits) * fm_gain * gain) / FP_ONE_GAIN );
30 this->step = (int)( ((1LL << shift) * fm_rate) / rate + 1);
31 this->rate_ = this->step;
32 return 0;
33}
34
35blargg_err_t Resampler_reset( struct Resampler* this, int pairs )
36{
37 // expand allocations a bit
38 this->sample_buffer_size = (pairs + (pairs >> 2)) * 2;
39 Resampler_resize( this, pairs );
40 this->resampler_size = this->oversamples_per_frame + (this->oversamples_per_frame >> 2);
41
42 this->buffer_size = this->resampler_size;
43 this->pos = 0;
44 this->write_pos = 0;
45
46 Resampler_clear( this );
47 return 0;
48}
49
50void Resampler_resize( struct Resampler* this, int pairs )
51{
52 int new_sample_buf_size = pairs * 2;
53 if ( this->sample_buf_size != new_sample_buf_size )
54 {
55 if ( new_sample_buf_size > this->sample_buffer_size )
56 {
57 check(false);
58 return;
59 }
60
61 this->sample_buf_size = new_sample_buf_size;
62 this->oversamples_per_frame = (int) ((pairs * this->rate_ * 2LL) / unit) + 2;
63 Resampler_clear( this );
64 }
65}
66
67static void mix_samples( struct Resampler* this, struct Blip_Buffer* blip_buf, dsample_t out_ [] )
68{
69 int const bass = BLIP_READER_BASS( *blip_buf );
70 BLIP_READER_BEGIN( sn, *blip_buf );
71
72 int count = this->sample_buf_size >> 1;
73 BLIP_READER_ADJ_( sn, count );
74
75 typedef dsample_t stereo_dsample_t [2];
76 stereo_dsample_t* BLARGG_RESTRICT out = (stereo_dsample_t*) out_ + count;
77 stereo_dsample_t const* BLARGG_RESTRICT in =
78 (stereo_dsample_t const*) this->sample_buf + count;
79 int offset = -count;
80 int const gain = this->gain_;
81 do
82 {
83 int s = BLIP_READER_READ_RAW( sn ) >> (blip_sample_bits - 16);
84 BLIP_READER_NEXT_IDX_( sn, bass, offset );
85
86 int l = (in [offset] [0] * gain >> gain_bits) + s;
87 int r = (in [offset] [1] * gain >> gain_bits) + s;
88
89 BLIP_CLAMP( l, l );
90 out [offset] [0] = (blip_sample_t) l;
91
92 BLIP_CLAMP( r, r );
93 out [offset] [1] = (blip_sample_t) r;
94 }
95 while ( ++offset );
96
97 BLIP_READER_END( sn, *blip_buf );
98}
99
100static dsample_t const* resample_( struct Resampler* this, dsample_t** out_,
101 dsample_t const* out_end, dsample_t const in [], int in_size )
102{
103 in_size -= write_offset;
104 if ( in_size > 0 )
105 {
106 dsample_t* BLARGG_RESTRICT out = *out_;
107 dsample_t const* const in_end = in + in_size;
108
109 int const step = this->step;
110 int pos = this->pos;
111
112 // TODO: IIR filter, then linear resample
113 // TODO: detect skipped sample, allowing merging of IIR and resample?
114
115 do
116 {
117 #define INTERP( i, out )\
118 out = (in [0 + i] * (unit - pos) + ((in [2 + i] + in [4 + i] + in [6 + i]) << shift) +\
119 in [8 + i] * pos) >> (shift + 2);
120
121 int out_0;
122 INTERP( 0, out_0 )
123 INTERP( 1, out [0] = out_0; out [1] )
124 out += stereo;
125
126 pos += step;
127 in += ((unsigned) pos >> shift) * stereo;
128 pos &= unit - 1;
129 }
130 while ( in < in_end && out < out_end );
131
132 this->pos = pos;
133 *out_ = out;
134 }
135 return in;
136}
137
138static inline int resample_wrapper( struct Resampler* this, dsample_t out [], int* out_size,
139 dsample_t const in [], int in_size )
140{
141 assert( Resampler_rate( this ) );
142
143 dsample_t* out_ = out;
144 int result = resample_( this, &out_, out + *out_size, in, in_size ) - in;
145 assert( out_ <= out + *out_size );
146 assert( result <= in_size );
147
148 *out_size = out_ - out;
149 return result;
150}
151
152static int skip_input( struct Resampler* this, int count )
153{
154 this->write_pos -= count;
155 if ( this->write_pos < 0 ) // occurs when downsampling
156 {
157 count += this->write_pos;
158 this->write_pos = 0;
159 }
160 memmove( this->buf, &this->buf [count], this->write_pos * sizeof this->buf [0] );
161 return count;
162}
163
164static void play_frame_( struct Resampler* this, struct Blip_Buffer* blip_buf, dsample_t* out )
165{
166 int pair_count = this->sample_buf_size >> 1;
167 blip_time_t blip_time = Blip_count_clocks( blip_buf, pair_count );
168 int sample_count = this->oversamples_per_frame - this->write_pos + resampler_extra;
169
170 int new_count = this->callback( this->callback_data, blip_time, sample_count, &this->buf [this->write_pos] );
171 assert( new_count < this->resampler_size );
172
173 Blip_end_frame( blip_buf, blip_time );
174 assert( Blip_samples_avail( blip_buf ) == pair_count );
175
176 this->write_pos += new_count;
177 assert( (unsigned) this->write_pos <= this->buffer_size );
178
179 int count = this->sample_buf_size;
180 if ( count )
181 skip_input( this, resample_wrapper( this, this->sample_buf, &count, this->buf, this->write_pos ) );
182 assert( count == this->sample_buf_size );
183
184 mix_samples( this, blip_buf, out );
185 Blip_remove_samples( blip_buf, pair_count );
186}
187
188void Resampler_play( struct Resampler* this, int count, dsample_t* out, struct Blip_Buffer* blip_buf )
189{
190 // empty extra buffer
191 int remain = this->sample_buf_size - this->buf_pos;
192 if ( remain )
193 {
194 if ( remain > count )
195 remain = count;
196 count -= remain;
197 memcpy( out, &this->sample_buf [this->buf_pos], remain * sizeof *out );
198 out += remain;
199 this->buf_pos += remain;
200 }
201
202 // entire frames
203 while ( count >= this->sample_buf_size )
204 {
205 play_frame_( this, blip_buf, out );
206 out += this->sample_buf_size;
207 count -= this->sample_buf_size;
208 }
209
210 // extra
211 if ( count )
212 {
213 play_frame_( this, blip_buf, this->sample_buf );
214 this->buf_pos = count;
215 memcpy( out, this->sample_buf, count * sizeof *out );
216 out += count;
217 }
218}
diff --git a/lib/rbcodec/codecs/libgme/resampler.h b/lib/rbcodec/codecs/libgme/resampler.h
new file mode 100644
index 0000000000..3f3710a54a
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/resampler.h
@@ -0,0 +1,75 @@
1// Combination of Downsampler and Blip_Buffer mixing. Used by Sega FM emulators.
2
3// Game_Music_Emu 0.5.5
4#ifndef RESAMPLER_H
5#define RESAMPLER_H
6
7#include "blargg_common.h"
8#include "multi_buffer.h"
9
10typedef short dsample_t;
11
12enum { max_buf_size = 3960 };
13enum { max_resampler_size = 5942 };
14enum { write_offset = 8 * stereo };
15enum { gain_bits = 14 };
16
17struct Resampler {
18 int (*callback)( void*, blip_time_t, int, dsample_t* );
19 void* callback_data;
20
21 int sample_buffer_size;
22 int sample_buf_size;
23 int oversamples_per_frame;
24 int buf_pos;
25 int resampler_size;
26 int gain_;
27
28 int buffer_size;
29 int write_pos;
30
31 int pos;
32 int step;
33
34 int rate_;
35
36 dsample_t sample_buf [max_buf_size];
37 dsample_t buf [max_resampler_size]; // Internal resampler
38};
39
40static inline void Resampler_init( struct Resampler* this )
41{
42 this->pos = 0;
43 this->write_pos = 0;
44 this->rate_ = 0;
45 this->sample_buf_size = 0;
46 this->sample_buffer_size = 0;
47 this->oversamples_per_frame = 0;
48}
49
50blargg_err_t Resampler_reset( struct Resampler* this, int max_pairs );
51void Resampler_resize( struct Resampler* this, int pairs_per_frame );
52void Resampler_play( struct Resampler* this, int count, dsample_t* out, struct Blip_Buffer* );
53
54static inline void Resampler_set_callback(struct Resampler* this, int (*func)( void*, blip_time_t, int, dsample_t* ), void* user_data )
55{
56 this->callback = func;
57 this->callback_data = user_data;
58}
59
60blargg_err_t Resampler_setup( struct Resampler* this, int fm_rate, int fm_gain, int rate, int gain );
61
62static inline void Resampler_clear( struct Resampler* this )
63{
64 this->buf_pos = this->sample_buf_size;
65
66 this->pos = 0;
67 this->write_pos = 0;
68}
69
70static inline int Resampler_rate( struct Resampler* this )
71{
72 return this->rate_;
73}
74
75#endif
diff --git a/lib/rbcodec/codecs/libgme/rom_data.c b/lib/rbcodec/codecs/libgme/rom_data.c
new file mode 100644
index 0000000000..9c36a99d2d
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/rom_data.c
@@ -0,0 +1,68 @@
1// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
2
3#include "rom_data.h"
4
5/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include <string.h>
17#include "blargg_source.h"
18
19// Rom_Data
20
21blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size,
22 int header_size, void* header_out, int fill )
23{
24 int file_offset = this->pad_size;
25
26 this->rom_addr = 0;
27 this->mask = 0;
28 this->size = 0;
29
30 if ( size <= header_size ) // <= because there must be data after header
31 return gme_wrong_file_type;
32
33 // Read header
34 memcpy( header_out, data, header_size );
35
36 this->file_size = size - header_size;
37 this->file_data = (byte*) data + header_size;
38
39 memset( this->unmapped, fill, this->rom_size );
40 memcpy( &this->unmapped [file_offset], this->file_data,
41 this->file_size < this->pad_size ? this->file_size : this->pad_size );
42
43 return 0;
44}
45
46void Rom_set_addr( struct Rom_Data* this, int addr )
47{
48 this->rom_addr = addr - this->bank_size - pad_extra;
49
50 int rounded = (addr + this->file_size + this->bank_size - 1) / this->bank_size * this->bank_size;
51 if ( rounded <= 0 )
52 {
53 rounded = 0;
54 }
55 else
56 {
57 int shift = 0;
58 unsigned int max_addr = (unsigned int) (rounded - 1);
59 while ( max_addr >> shift )
60 shift++;
61 this->mask = (1L << shift) - 1;
62 }
63
64 if ( addr < 0 )
65 addr = 0;
66 this->size = rounded;
67 this->rsize_ = rounded - this->rom_addr + pad_extra;
68}
diff --git a/lib/rbcodec/codecs/libgme/rom_data.h b/lib/rbcodec/codecs/libgme/rom_data.h
new file mode 100644
index 0000000000..b8bc54cd3f
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/rom_data.h
@@ -0,0 +1,83 @@
1// Common aspects of emulators which use rom data
2
3// Game_Music_Emu 0.5.2
4#ifndef ROM_DATA_H
5#define ROM_DATA_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9
10// ROM data handler, used by several Classic_Emu derivitives. Loads file data
11// with padding on both sides, allowing direct use in bank mapping. The main purpose
12// is to allow all file data to be loaded with only one read() call (for efficiency).
13
14extern const char gme_wrong_file_type []; // declared in gme.h
15
16enum { pad_extra = 8 };
17enum { max_bank_size = 0x4000 };
18enum { max_pad_size = max_bank_size + pad_extra };
19enum { max_rom_size = 2 * max_pad_size };
20
21struct Rom_Data {
22 byte* file_data;
23 unsigned file_size;
24
25 int rom_addr;
26 int bank_size;
27 int rom_size;
28 unsigned pad_size;
29 int mask;
30 int size; // TODO: eliminate
31 int rsize_;
32
33 // Unmapped space
34 byte unmapped [max_rom_size];
35};
36
37// Initialize rom
38static inline void Rom_init( struct Rom_Data* this, int bank_size )
39{
40 this->bank_size = bank_size;
41 this->pad_size = this->bank_size + pad_extra;
42 this->rom_size = 2 * this->pad_size;
43}
44
45// Load file data, using already-loaded header 'h' if not NULL. Copy header
46// from loaded file data into *out and fill unmapped bytes with 'fill'.
47blargg_err_t Rom_load( struct Rom_Data* this, const void* data, long size, int header_size, void* header_out, int fill );
48
49// Set address that file data should start at
50void Rom_set_addr( struct Rom_Data* this, int addr );
51
52// Mask address to nearest power of two greater than size()
53static inline int mask_addr( int addr, int mask )
54{
55 #ifdef check
56 check( addr <= mask );
57 #endif
58 return addr & mask;
59}
60
61// Pointer to page starting at addr. Returns unmapped() if outside data.
62static inline byte* Rom_at_addr( struct Rom_Data* this, int addr )
63{
64 unsigned offset = mask_addr( addr, this->mask ) - this->rom_addr;
65 if ( offset > (unsigned) (this->rsize_ - this->pad_size) )
66 offset = 0; // unmapped
67
68 if ( offset < this->pad_size ) return &this->unmapped [offset];
69 else return &this->file_data [offset - this->pad_size];
70}
71
72
73#ifndef GME_APU_HOOK
74 #define GME_APU_HOOK( emu, addr, data ) ((void) 0)
75#endif
76
77#ifndef GME_FRAME_HOOK
78 #define GME_FRAME_HOOK( emu ) ((void) 0)
79#else
80 #define GME_FRAME_HOOK_DEFINED 1
81#endif
82
83#endif
diff --git a/lib/rbcodec/codecs/libgme/sgc_cpu.c b/lib/rbcodec/codecs/libgme/sgc_cpu.c
new file mode 100644
index 0000000000..d23c01499b
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sgc_cpu.c
@@ -0,0 +1,36 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "sgc_emu.h"
4
5#include "blargg_endian.h"
6//#include "z80_cpu_log.h"
7
8/* Copyright (C) 2009 Shay Green. This module is free software; you
9can redistribute it and/or modify it under the terms of the GNU Lesser
10General Public License as published by the Free Software Foundation; either
11version 2.1 of the License, or (at your option) any later version. This
12module is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15details. You should have received a copy of the GNU Lesser General Public
16License along with this module; if not, write to the Free Software Foundation,
17Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19#include "blargg_source.h"
20
21#define OUT_PORT( addr, data ) cpu_out( this, TIME(), addr, data )
22#define IN_PORT( addr ) 0 // cpu in
23#define WRITE_MEM( addr, data ) cpu_write( this, addr, data )
24#define IDLE_ADDR this->idle_addr
25#define RST_BASE this->vectors_addr
26
27#define CPU_BEGIN \
28bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time )\
29{\
30 Sgc_Cpu* cpu = &this->cpu; \
31 Z80_set_end_time( cpu, end_time );
32
33 #include "z80_cpu_run.h"
34
35 return warning;
36}
diff --git a/lib/rbcodec/codecs/libgme/sgc_emu.c b/lib/rbcodec/codecs/libgme/sgc_emu.c
new file mode 100644
index 0000000000..267f2c9271
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sgc_emu.c
@@ -0,0 +1,480 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "sgc_emu.h"
4
5/* Copyright (C) 2009 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License aint with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const osc_count = sms_osc_count + fm_apu_osc_count;
19
20const char gme_wrong_file_type [] = "Wrong file type for this emulator";
21
22static void clear_track_vars( struct Sgc_Emu* this )
23{
24 this->current_track = -1;
25 track_stop( &this->track_filter );
26}
27
28void Sgc_init( struct Sgc_Emu* this )
29{
30 assert( offsetof (struct header_t,copyright [32]) == header_size );
31
32 this->sample_rate = 0;
33 this->mute_mask_ = 0;
34 this->tempo = (int)FP_ONE_TEMPO;
35 this->gain = (int)FP_ONE_GAIN;
36
37 // defaults
38 this->tfilter = *track_get_setup( &this->track_filter );
39 this->tfilter.max_initial = 2;
40 this->tfilter.lookahead = 6;
41 this->track_filter.silence_ignored_ = false;
42
43 Sms_apu_init( &this->apu );
44 Fm_apu_create( &this->fm_apu );
45
46 Rom_init( &this->rom, 0x4000 );
47 Z80_init( &this->cpu );
48
49 Sound_set_gain( this, (int)(FP_ONE_GAIN*1.2) );
50
51 // Unload
52 this->voice_count = 0;
53 this->voice_types = 0;
54 clear_track_vars( this );
55}
56
57// Setup
58
59blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size )
60{
61 RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
62
63 if ( !valid_tag( &this->header ) )
64 return gme_wrong_file_type;
65
66 /* if ( header.vers != 1 )
67 warning( "Unknown file version" ); */
68
69 /* if ( header.system > 2 )
70 warning( "Unknown system" ); */
71
72 addr_t load_addr = get_le16( this->header.load_addr );
73 /* if ( load_addr < 0x400 )
74 set_warning( "Invalid load address" ); */
75
76 Rom_set_addr( &this->rom, load_addr );
77 this->play_period = clock_rate( this ) / 60;
78
79 if ( sega_mapping( this ) && Fm_apu_supported() )
80 RETURN_ERR( Fm_apu_init( &this->fm_apu, clock_rate( this ), clock_rate( this ) / 72 ) );
81
82 this->m3u.size = 0;
83 this->track_count = this->header.song_count;
84 this->voice_count = sega_mapping( this ) ? osc_count : sms_osc_count;
85 static int const types [sms_osc_count + fm_apu_osc_count] = {
86 wave_type+1, wave_type+2, wave_type+3, mixed_type+1, mixed_type+2
87 };
88 this->voice_types = types;
89
90 Sms_apu_volume( &this->apu, this->gain );
91 Fm_apu_volume( &this->fm_apu, this->gain );
92
93 // Setup buffer
94 this->clock_rate_ = clock_rate( this );
95 Buffer_clock_rate( &this->stereo_buf, clock_rate( this ) );
96 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
97 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
98
99 Sound_set_tempo( this, this->tempo );
100 Sound_mute_voices( this, this->mute_mask_ );
101 return 0;
102}
103
104static void Sound_set_voice( struct Sgc_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r )
105{
106 if ( i < sms_osc_count )
107 Sms_apu_set_output( &this->apu, i, c, l, r );
108 else
109 Fm_apu_set_output( &this->fm_apu, c );
110}
111
112static blargg_err_t run_clocks( struct Sgc_Emu* this, blip_time_t* duration, int msec )
113{
114#if defined(ROCKBOX)
115 (void) msec;
116#endif
117
118 cpu_time_t t = *duration;
119 while ( Z80_time( &this->cpu ) < t )
120 {
121 cpu_time_t next = min( t, this->next_play );
122 if ( run_cpu( this, next ) )
123 {
124 /* warning( "Unsupported CPU instruction" ); */
125 Z80_set_time( &this->cpu, next );
126 }
127
128 if ( this->cpu.r.pc == this->idle_addr )
129 Z80_set_time( &this->cpu, next );
130
131 if ( Z80_time( &this->cpu ) >= this->next_play )
132 {
133 this->next_play += this->play_period;
134 if ( this->cpu.r.pc == this->idle_addr )
135 jsr( this, this->header.play_addr );
136 }
137 }
138
139 this->next_play -= t;
140 check( this->next_play >= 0 );
141 Z80_adjust_time( &this->cpu, -t );
142
143 Sms_apu_end_frame( &this->apu, t );
144 if ( sega_mapping( this ) && this->fm_accessed )
145 {
146 if ( Fm_apu_supported() )
147 Fm_apu_end_frame( &this->fm_apu, t );
148 /* else
149 warning( "FM sound not supported" ); */
150 }
151
152 return 0;
153}
154
155// Emulation
156
157void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data )
158{
159 int port = addr & 0xFF;
160
161 if ( sega_mapping( this ) )
162 {
163 switch ( port )
164 {
165 case 0x06:
166 Sms_apu_write_ggstereo( &this->apu, time, data );
167 return;
168
169 case 0x7E:
170 case 0x7F:
171 Sms_apu_write_data( &this->apu, time, data ); /* dprintf( "$7E<-%02X\n", data ); */
172 return;
173
174 case 0xF0:
175 this->fm_accessed = true;
176 if ( Fm_apu_supported() )
177 Fm_apu_write_addr( &this->fm_apu, data );//, dprintf( "$F0<-%02X\n", data );
178 return;
179
180 case 0xF1:
181 this->fm_accessed = true;
182 if ( Fm_apu_supported() )
183 Fm_apu_write_data( &this->fm_apu, time, data );//, dprintf( "$F1<-%02X\n", data );
184 return;
185 }
186 }
187 else if ( port >= 0xE0 )
188 {
189 Sms_apu_write_data( &this->apu, time, data );
190 return;
191 }
192}
193
194void jsr( struct Sgc_Emu* this, byte addr [2] )
195{
196 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr >> 8;
197 *Z80_write( &this->cpu, --this->cpu.r.sp ) = this->idle_addr & 0xFF;
198 this->cpu.r.pc = get_le16( addr );
199}
200
201static void set_bank( struct Sgc_Emu* this, int bank, void const* data )
202{
203 //dprintf( "map bank %d to %p\n", bank, (byte*) data - rom.at_addr( 0 ) );
204 Z80_map_mem( &this->cpu, bank * this->rom.bank_size, this->rom.bank_size, this->unmapped_write, data );
205}
206
207void cpu_write( struct Sgc_Emu* this, addr_t addr, int data )
208{
209 if ( (addr ^ 0xFFFC) > 3 || !sega_mapping( this ) )
210 {
211 *Z80_write( &this->cpu, addr ) = data;
212 return;
213 }
214
215 switch ( addr )
216 {
217 case 0xFFFC:
218 Z80_map_mem_rw( &this->cpu, 2 * this->rom.bank_size, this->rom.bank_size, this->ram2 );
219 if ( data & 0x08 )
220 break;
221
222 this->bank2 = this->ram2;
223 // FALL THROUGH
224
225 case 0xFFFF: {
226 bool rom_mapped = (Z80_read( &this->cpu, 2 * this->rom.bank_size ) == this->bank2);
227 this->bank2 = Rom_at_addr( &this->rom, data * this->rom.bank_size );
228 if ( rom_mapped )
229 set_bank( this, 2, this->bank2 );
230 break;
231 }
232
233 case 0xFFFD:
234 set_bank( this, 0, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
235 break;
236
237 case 0xFFFE:
238 set_bank( this, 1, Rom_at_addr( &this->rom, data * this->rom.bank_size ) );
239 break;
240 }
241}
242
243blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int rate )
244{
245 require( !this->sample_rate ); // sample rate can't be changed once set
246 Buffer_init( &this->stereo_buf );
247 Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 );
248
249 // Set buffer bass
250 Buffer_bass_freq( &this->stereo_buf, 80 );
251
252 this->sample_rate = rate;
253 RETURN_ERR( track_init( &this->track_filter, this ) );
254 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
255 return 0;
256}
257
258void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute )
259{
260 require( (unsigned) index < (unsigned) this->voice_count );
261 int bit = 1 << index;
262 int mask = this->mute_mask_ | bit;
263 if ( !mute )
264 mask ^= bit;
265 Sound_mute_voices( this, mask );
266}
267
268void Sound_mute_voices( struct Sgc_Emu* this, int mask )
269{
270 require( this->sample_rate ); // sample rate must be set first
271 this->mute_mask_ = mask;
272
273 int i;
274 for ( i = this->voice_count; i--; )
275 {
276 if ( mask & (1 << i) )
277 {
278 Sound_set_voice( this, i, 0, 0, 0 );
279 }
280 else
281 {
282 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
283 assert( (ch.center && ch.left && ch.right) ||
284 (!ch.center && !ch.left && !ch.right) ); // all or nothing
285 Sound_set_voice( this, i, ch.center, ch.left, ch.right );
286 }
287 }
288}
289
290void Sound_set_tempo( struct Sgc_Emu* this, int t )
291{
292 require( this->sample_rate ); // sample rate must be set first
293 int const min = (int)(FP_ONE_TEMPO*0.02);
294 int const max = (int)(FP_ONE_TEMPO*4.00);
295 if ( t < min ) t = min;
296 if ( t > max ) t = max;
297 this->tempo = t;
298
299 this->play_period = (int) ((clock_rate( this ) * FP_ONE_TEMPO) / (this->header.rate ? 50 : 60) / t);
300}
301
302blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track )
303{
304 clear_track_vars( this );
305
306 // Remap track if playlist available
307 if ( this->m3u.size > 0 ) {
308 struct entry_t* e = &this->m3u.entries[track];
309 track = e->track;
310 }
311
312 this->current_track = track;
313
314 if ( sega_mapping( this ) )
315 {
316 Sms_apu_reset( &this->apu, 0, 0 );
317 Fm_apu_reset( &this->fm_apu );
318 this->fm_accessed = false;
319 }
320 else
321 {
322 Sms_apu_reset( &this->apu, 0x0003, 15 );
323 }
324
325 memset( this->ram , 0, sizeof this->ram );
326 memset( this->ram2, 0, sizeof this->ram2 );
327 memset( this->vectors, 0xFF, sizeof this->vectors );
328 Z80_reset( &this->cpu, this->unmapped_write, this->rom.unmapped );
329
330 if ( sega_mapping( this ) )
331 {
332 this->vectors_addr = 0x10000 - page_size;
333 this->idle_addr = this->vectors_addr;
334 int i;
335 for ( i = 1; i < 8; ++i )
336 {
337 this->vectors [i*8 + 0] = 0xC3; // JP addr
338 this->vectors [i*8 + 1] = this->header.rst_addrs [i - 1] & 0xff;
339 this->vectors [i*8 + 2] = this->header.rst_addrs [i - 1] >> 8;
340 }
341
342 Z80_map_mem_rw( &this->cpu, 0xC000, 0x2000, this->ram );
343 Z80_map_mem( &this->cpu, this->vectors_addr, page_size, this->unmapped_write, this->vectors );
344
345 this->bank2 = NULL;
346 for ( i = 0; i < 4; ++i )
347 cpu_write( this, 0xFFFC + i, this->header.mapping [i] );
348 }
349 else
350 {
351 if ( !this->coleco_bios )
352 return "Coleco BIOS not set"; /* BLARGG_ERR( BLARGG_ERR_CALLER, "Coleco BIOS not set" ); */
353
354 this->vectors_addr = 0;
355 Z80_map_mem( &this->cpu, 0, 0x2000, this->unmapped_write, this->coleco_bios );
356 int i;
357 for ( i = 0; i < 8; ++i )
358 Z80_map_mem_rw( &this->cpu, 0x6000 + i*0x400, 0x400, this->ram );
359
360 this->idle_addr = 0x2000;
361 Z80_map_mem( &this->cpu, 0x2000, page_size, this->unmapped_write, this->vectors );
362
363 for ( i = 0; i < 0x8000 / this->rom.bank_size; ++i )
364 {
365 int addr = 0x8000 + i*this->rom.bank_size;
366 Z80_map_mem( &this->cpu, addr, this->rom.bank_size, this->unmapped_write, Rom_at_addr( &this->rom, addr ) );
367 }
368 }
369
370 this->cpu.r.sp = get_le16( this->header.stack_ptr );
371 this->cpu.r.b.a = track;
372 this->next_play = this->play_period;
373
374 jsr( this, this->header.init_addr );
375
376 Buffer_clear( &this->stereo_buf );
377
378 // convert filter times to samples
379 struct setup_t s = this->tfilter;
380 s.max_initial *= this->sample_rate * stereo;
381 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
382 s.lookahead = 1;
383 #endif
384 track_setup( &this->track_filter, &s );
385
386 return track_start( &this->track_filter );
387}
388
389// Tell/Seek
390
391static int msec_to_samples( int msec, int sample_rate )
392{
393 int sec = msec / 1000;
394 msec -= sec * 1000;
395 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
396}
397
398int Track_tell( struct Sgc_Emu* this )
399{
400 int rate = this->sample_rate * stereo;
401 int sec = track_sample_count( &this->track_filter ) / rate;
402 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
403}
404
405blargg_err_t Track_seek( struct Sgc_Emu* this, int msec )
406{
407 int time = msec_to_samples( msec, this->sample_rate );
408 if ( time < track_sample_count( &this->track_filter ) )
409 RETURN_ERR( Sgc_start_track( this, this->current_track ) );
410 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
411}
412
413blargg_err_t Track_skip( struct Sgc_Emu* this, int count )
414{
415 require( this->current_track >= 0 ); // start_track() must have been called already
416 return track_skip( &this->track_filter, count );
417}
418
419blargg_err_t skip_( void* emu, int count )
420{
421 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
422
423 // for long skip, mute sound
424 const int threshold = 32768;
425 if ( count > threshold )
426 {
427 int saved_mute = this->mute_mask_;
428 Sound_mute_voices( this, ~0 );
429
430 int n = count - threshold/2;
431 n &= ~(2048-1); // round to multiple of 2048
432 count -= n;
433 RETURN_ERR( skippy_( &this->track_filter, n ) );
434
435 Sound_mute_voices( this, saved_mute );
436 }
437
438 return skippy_( &this->track_filter, count );
439}
440
441void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec )
442{
443 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
444 length_msec * this->sample_rate / (1000 / stereo) );
445}
446
447blargg_err_t Sgc_play( struct Sgc_Emu* this, int out_count, sample_t* out )
448{
449 require( this->current_track >= 0 );
450 require( out_count % stereo == 0 );
451 return track_play( &this->track_filter, out_count, out );
452}
453
454blargg_err_t play_( void* emu, int count, sample_t out [] )
455{
456 struct Sgc_Emu* this = (struct Sgc_Emu*) emu;
457
458 int remain = count;
459 while ( remain )
460 {
461 Buffer_disable_immediate_removal( &this->stereo_buf );
462 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
463 if ( remain )
464 {
465 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
466 {
467 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
468
469 // Remute voices
470 Sound_mute_voices( this, this->mute_mask_ );
471 }
472 int msec = Buffer_length( &this->stereo_buf );
473 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
474 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
475 assert( clocks_emulated );
476 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
477 }
478 }
479 return 0;
480}
diff --git a/lib/rbcodec/codecs/libgme/sgc_emu.h b/lib/rbcodec/codecs/libgme/sgc_emu.h
new file mode 100644
index 0000000000..83cde1e6ae
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sgc_emu.h
@@ -0,0 +1,195 @@
1// Sega/Game Gear/Coleco SGC music file emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef SGC_EMU_H
5#define SGC_EMU_H
6
7#include "blargg_common.h"
8#include "multi_buffer.h"
9
10#include "rom_data.h"
11#include "z80_cpu.h"
12#include "sms_fm_apu.h"
13#include "sms_apu.h"
14#include "m3u_playlist.h"
15#include "track_filter.h"
16
17typedef struct Z80_Cpu Sgc_Cpu;
18
19// SGC file header
20enum { header_size = 0xA0 };
21struct header_t
22{
23 char tag [4]; // "SGC\x1A"
24 byte vers; // 0x01
25 byte rate; // 0=NTSC 1=PAL
26 byte reserved1 [2];
27 byte load_addr [2];
28 byte init_addr [2];
29 byte play_addr [2];
30 byte stack_ptr [2];
31 byte reserved2 [2];
32 byte rst_addrs [7*2];
33 byte mapping [4]; // Used by Sega only
34 byte first_song; // Song to start playing first
35 byte song_count;
36 byte first_effect;
37 byte last_effect;
38 byte system; // 0=Master System 1=Game Gear 2=Colecovision
39 byte reserved3 [23];
40 char game [32]; // strings can be 32 chars, NOT terminated
41 char author [32];
42 char copyright [32];
43};
44
45// True if header has valid file signature
46static inline bool valid_tag( struct header_t* h )
47{
48 return 0 == memcmp( h->tag, "SGC\x1A", 4 );
49}
50
51static inline int effect_count( struct header_t* h ) { return h->last_effect ? h->last_effect - h->first_effect + 1 : 0; }
52
53struct Sgc_Emu {
54 bool fm_accessed;
55
56 cpu_time_t play_period;
57 cpu_time_t next_play;
58 void const* bank2; // ROM selected for bank 2, in case RAM is currently hiding it
59 addr_t vectors_addr; // RST vectors start here
60 addr_t idle_addr; // return address for init/play routines
61 void* coleco_bios;
62
63 // general
64 int voice_count;
65 int const* voice_types;
66 int mute_mask_;
67 int tempo;
68 int gain;
69
70 int sample_rate;
71
72 // track-specific
73 int current_track;
74 int track_count;
75
76 int clock_rate_;
77 unsigned buf_changed_count;
78
79 // M3u Playlist
80 struct M3u_Playlist m3u;
81 struct header_t header;
82
83 struct setup_t tfilter;
84 struct Track_Filter track_filter;
85
86 struct Multi_Buffer stereo_buf;
87
88 struct Sms_Apu apu;
89 struct Sms_Fm_Apu fm_apu;
90
91 Sgc_Cpu cpu;
92
93 // large items
94 struct Rom_Data rom;
95 byte vectors [page_size + page_padding];
96 byte unmapped_write [0x4000];
97 byte ram [0x2000 + page_padding];
98 byte ram2 [0x4000 + page_padding];
99};
100
101// Basic functionality (see Gme_File.h for file loading/track info functions)
102
103void Sgc_init( struct Sgc_Emu* this );
104
105blargg_err_t Sgc_load_mem( struct Sgc_Emu* this, const void* data, long size );
106
107static inline int clock_rate( struct Sgc_Emu* this ) { return this->header.rate ? 3546893 : 3579545; }
108
109// 0x2000 bytes
110static inline void set_coleco_bios( struct Sgc_Emu* this, void* p ) { this->coleco_bios = p; }
111
112// Set output sample rate. Must be called only once before loading file.
113blargg_err_t Sgc_set_sample_rate( struct Sgc_Emu* this, int sample_rate );
114
115// Start a track, where 0 is the first track. Also clears warning string.
116blargg_err_t Sgc_start_track( struct Sgc_Emu* this, int track );
117
118// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
119// errors set warning string, and major errors also end track.
120blargg_err_t Sgc_play( struct Sgc_Emu* this, int count, sample_t* buf );
121
122// Track status/control
123
124// Number of milliseconds (1000 msec = 1 second) played since beginning of track
125int Track_tell( struct Sgc_Emu* this );
126
127// Seek to new time in track. Seeking backwards or far forward can take a while.
128blargg_err_t Track_seek( struct Sgc_Emu* this, int msec );
129
130// Skip n samples
131blargg_err_t Track_skip( struct Sgc_Emu* this, int n );
132
133// Set start time and length of track fade out. Once fade ends track_ended() returns
134// true. Fade time can be changed while track is playing.
135void Track_set_fade( struct Sgc_Emu* this, int start_msec, int length_msec );
136
137// True if a track has reached its end
138static inline bool Track_ended( struct Sgc_Emu* this )
139{
140 return track_ended( &this->track_filter );
141}
142
143// Disables automatic end-of-track detection and skipping of silence at beginning
144static inline void Track_ignore_silence( struct Sgc_Emu* this, bool disable )
145{
146 this->track_filter.silence_ignored_ = disable;
147}
148
149// Get track length in milliseconds
150static inline int Track_get_length( struct Sgc_Emu* this, int n )
151{
152 int length = 120 * 1000; /* 2 minutes */
153 if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
154 struct entry_t* entry = &this->m3u.entries [n];
155 length = entry->length;
156 }
157
158 return length;
159}
160
161// Sound customization
162
163// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
164// Track length as returned by track_info() assumes a tempo of 1.0.
165void Sound_set_tempo( struct Sgc_Emu* this, int t );
166
167// Mute/unmute voice i, where voice 0 is first voice
168void Sound_mute_voice( struct Sgc_Emu* this, int index, bool mute );
169
170// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
171// 0 unmutes them all, 0x01 mutes just the first voice, etc.
172void Sound_mute_voices( struct Sgc_Emu* this, int mask );
173
174// Change overall output amplitude, where 1.0 results in minimal clamping.
175// Must be called before set_sample_rate().
176static inline void Sound_set_gain( struct Sgc_Emu* this, int g )
177{
178 assert( !this->sample_rate ); // you must set gain before setting sample rate
179 this->gain = g;
180}
181
182// True if Master System or Game Gear
183static inline bool sega_mapping( struct Sgc_Emu* this )
184{
185 return this->header.system <= 1;
186}
187
188// Emulation (You shouldn't touch these)
189
190bool run_cpu( struct Sgc_Emu* this, cpu_time_t end_time );
191void cpu_out( struct Sgc_Emu* this, cpu_time_t time, addr_t addr, int data );
192void cpu_write( struct Sgc_Emu* this, addr_t addr, int data );
193void jsr( struct Sgc_Emu* this, byte addr [2] );
194
195#endif
diff --git a/lib/rbcodec/codecs/libgme/sms_apu.c b/lib/rbcodec/codecs/libgme/sms_apu.c
new file mode 100644
index 0000000000..379fcf1cbf
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sms_apu.c
@@ -0,0 +1,306 @@
1// Sms_Snd_Emu 0.1.1. http://www.slack.net/~ant/
2
3#include "sms_apu.h"
4
5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const noise_osc = 3;
19
20void Sms_apu_volume( struct Sms_Apu* this, int vol )
21{
22 vol = (vol - (vol*3)/20) / sms_osc_count / 64;
23 Synth_volume( &this->synth, vol );
24}
25
26static inline int calc_output( struct Sms_Apu* this, int i )
27{
28 int flags = this->ggstereo >> i;
29 return (flags >> 3 & 2) | (flags & 1);
30}
31
32void Sms_apu_set_output( struct Sms_Apu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right )
33{
34#if defined(ROCKBOX)
35 (void) left;
36 (void) right;
37#endif
38
39 // Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
40 require( !center || (center && !left && !right) || (center && left && right) );
41 require( (unsigned) i < sms_osc_count ); // fails if you pass invalid osc index
42
43 if ( center )
44 {
45 unsigned const divisor = 16384 * 16 * 2;
46 this->min_tone_period = ((unsigned) Blip_clock_rate( center ) + divisor/2) / divisor;
47 }
48
49 if ( !center || !left || !right )
50 {
51 left = center;
52 right = center;
53 }
54
55 struct Osc* o = &this->oscs [i];
56 o->outputs [0] = NULL;
57 o->outputs [1] = right;
58 o->outputs [2] = left;
59 o->outputs [3] = center;
60 o->output = o->outputs [calc_output( this, i )];
61}
62
63static inline unsigned fibonacci_to_galois_lfsr( unsigned fibonacci, int width )
64{
65 unsigned galois = 0;
66 while ( --width >= 0 )
67 {
68 galois = (galois << 1) | (fibonacci & 1);
69 fibonacci >>= 1;
70 }
71 return galois;
72}
73
74void Sms_apu_reset( struct Sms_Apu* this, unsigned feedback, int noise_width )
75{
76 this->last_time = 0;
77 this->latch = 0;
78 this->ggstereo = 0;
79
80 // Calculate noise feedback values
81 if ( !feedback || !noise_width )
82 {
83 feedback = 0x0009;
84 noise_width = 16;
85 }
86 this->looped_feedback = 1 << (noise_width - 1);
87 this->noise_feedback = fibonacci_to_galois_lfsr( feedback, noise_width );
88
89 // Reset oscs
90 int i;
91 for ( i = sms_osc_count; --i >= 0; )
92 {
93 struct Osc* o = &this->oscs [i];
94 o->output = NULL;
95 o->last_amp = 0;
96 o->delay = 0;
97 o->phase = 0;
98 o->period = 0;
99 o->volume = 15; // silent
100 }
101
102 this->oscs [noise_osc].phase = 0x8000;
103 Sms_apu_write_ggstereo( this, 0, 0xFF );
104}
105
106void Sms_apu_init( struct Sms_Apu* this )
107{
108 this->min_tone_period = 7;
109
110 Synth_init( &this->synth );
111
112 // Clear outputs to NULL FIRST
113 this->ggstereo = 0;
114
115 int i;
116 for ( i = sms_osc_count; --i >= 0; )
117 Sms_apu_set_output( this, i, NULL, NULL, NULL );
118
119 Sms_apu_volume( this, (int)FP_ONE_VOLUME );
120 Sms_apu_reset( this, 0, 0 );
121}
122
123static void run_until( struct Sms_Apu* this, blip_time_t end_time )
124{
125 require( end_time >= this->last_time );
126 if ( end_time <= this->last_time )
127 return;
128
129 // Synthesize each oscillator
130 int idx;
131 for ( idx = sms_osc_count; --idx >= 0; )
132 {
133 struct Osc* osc = &this->oscs [idx];
134 int vol = 0;
135 int amp = 0;
136
137 // Determine what will be generated
138 struct Blip_Buffer* const out = osc->output;
139 if ( out )
140 {
141 // volumes [i] ~= 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
142 static unsigned char const volumes [16] = {
143 64, 50, 40, 32, 25, 20, 16, 13, 10, 8, 6, 5, 4, 3, 2, 0
144 };
145
146 vol = volumes [osc->volume];
147 amp = (osc->phase & 1) * vol;
148
149 // Square freq above 16 kHz yields constant amplitude at half volume
150 if ( idx != noise_osc && osc->period < this->min_tone_period )
151 {
152 amp = vol >> 1;
153 vol = 0;
154 }
155
156 // Update amplitude
157 int delta = amp - osc->last_amp;
158 if ( delta )
159 {
160 osc->last_amp = amp;
161 Synth_offset( &this->synth, this->last_time, delta, out );
162 Blip_set_modified( out );
163 }
164 }
165
166 // Generate wave
167 blip_time_t time = this->last_time + osc->delay;
168 if ( time < end_time )
169 {
170 // Calculate actual period
171 int period = osc->period;
172 if ( idx == noise_osc )
173 {
174 period = 0x20 << (period & 3);
175 if ( period == 0x100 )
176 period = this->oscs [2].period * 2;
177 }
178 period *= 0x10;
179 if ( !period )
180 period = 0x10;
181
182 // Maintain phase when silent
183 int phase = osc->phase;
184 if ( !vol )
185 {
186 int count = (end_time - time + period - 1) / period;
187 time += count * period;
188 if ( idx != noise_osc ) // TODO: maintain noise LFSR phase?
189 phase ^= count & 1;
190 }
191 else
192 {
193 int delta = amp * 2 - vol;
194
195 if ( idx != noise_osc )
196 {
197 // Square
198 do
199 {
200 delta = -delta;
201 Synth_offset( &this->synth, time, delta, out );
202 time += period;
203 }
204 while ( time < end_time );
205 phase = (delta >= 0);
206 }
207 else
208 {
209 // Noise
210 unsigned const feedback = (osc->period & 4 ? this->noise_feedback : this->looped_feedback);
211 do
212 {
213 unsigned changed = phase + 1;
214 phase = ((phase & 1) * feedback) ^ (phase >> 1);
215 if ( changed & 2 ) // true if bits 0 and 1 differ
216 {
217 delta = -delta;
218 Synth_offset_inline( &this->synth, time, delta, out );
219 }
220 time += period;
221 }
222 while ( time < end_time );
223 check( phase );
224 }
225 osc->last_amp = (phase & 1) * vol;
226 Blip_set_modified( out );
227 }
228 osc->phase = phase;
229 }
230 osc->delay = time - end_time;
231 }
232 this->last_time = end_time;
233}
234
235void Sms_apu_write_ggstereo( struct Sms_Apu* this, blip_time_t time, int data )
236{
237 require( (unsigned) data <= 0xFF );
238
239 run_until( this, time );
240 this->ggstereo = data;
241
242 int i;
243 for ( i = sms_osc_count; --i >= 0; )
244 {
245 struct Osc* osc = &this->oscs [i];
246
247 struct Blip_Buffer* old = osc->output;
248 osc->output = osc->outputs [calc_output( this, i )];
249 if ( osc->output != old )
250 {
251 int delta = -osc->last_amp;
252 if ( delta )
253 {
254 osc->last_amp = 0;
255 if ( old )
256 {
257 Blip_set_modified( old );
258 Synth_offset( &this->synth, this->last_time, delta, old );
259 }
260 }
261 }
262 }
263}
264
265void Sms_apu_write_data( struct Sms_Apu* this, blip_time_t time, int data )
266{
267 require( (unsigned) data <= 0xFF );
268
269 run_until( this, time );
270
271 if ( data & 0x80 )
272 this->latch = data;
273
274 // We want the raw values written so our save state format can be
275 // as close to hardware as possible and unspecific to any emulator.
276 int idx = this->latch >> 5 & 3;
277 struct Osc* osc = &this->oscs [idx];
278 if ( this->latch & 0x10 )
279 {
280 osc->volume = data & 0x0F;
281 }
282 else
283 {
284 if ( idx == noise_osc )
285 osc->phase = 0x8000; // reset noise LFSR
286
287 // Replace high 6 bits/low 4 bits of register with data
288 int lo = osc->period;
289 int hi = data << 4;
290 if ( idx == noise_osc || (data & 0x80) )
291 {
292 hi = lo;
293 lo = data;
294 }
295 osc->period = (hi & 0x3F0) | (lo & 0x00F);
296 }
297}
298
299void Sms_apu_end_frame( struct Sms_Apu* this, blip_time_t end_time )
300{
301 if ( end_time > this->last_time )
302 run_until( this, end_time );
303
304 this->last_time -= end_time;
305 assert( this->last_time >= 0 );
306}
diff --git a/lib/rbcodec/codecs/libgme/sms_apu.h b/lib/rbcodec/codecs/libgme/sms_apu.h
new file mode 100644
index 0000000000..6dd65591ce
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sms_apu.h
@@ -0,0 +1,63 @@
1// Sega Master System SN76489 PSG sound chip emulator
2
3// Sms_Snd_Emu 0.1.2
4#ifndef SMS_APU_H
5#define SMS_APU_H
6
7#include "blargg_common.h"
8#include "blip_buffer.h"
9
10// 0: Square 1, 1: Square 2, 2: Square 3, 3: Noise
11enum { sms_osc_count = 4 }; // 0 <= chan < osc_count
12
13struct Osc
14{
15 struct Blip_Buffer* outputs [4]; // NULL, right, left, center
16 struct Blip_Buffer* output;
17 int last_amp;
18
19 int volume;
20 int period;
21 int delay;
22 unsigned phase;
23};
24
25struct Sms_Apu {
26 struct Osc oscs [sms_osc_count];
27 int ggstereo;
28 int latch;
29
30 blip_time_t last_time;
31 int min_tone_period;
32 unsigned noise_feedback;
33 unsigned looped_feedback;
34 struct Blip_Synth synth;
35};
36
37// Basics
38
39void Sms_apu_init( struct Sms_Apu* this );
40
41// Sets buffer(s) to generate sound into, or 0 to mute. If only center is not 0,
42// output is mono.
43void Sms_apu_set_output( struct Sms_Apu* this, int i, struct Blip_Buffer* center, struct Blip_Buffer* left, struct Blip_Buffer* right);
44
45// Emulates to time t, then writes data to Game Gear left/right assignment byte
46void Sms_apu_write_ggstereo( struct Sms_Apu* this, blip_time_t t, int data );
47
48// Emulates to time t, then writes data
49void Sms_apu_write_data( struct Sms_Apu* this, blip_time_t t, int data );
50
51// Emulates to time t, then subtracts t from the current time.
52// OK if previous write call had time slightly after t.
53void Sms_apu_end_frame( struct Sms_Apu* this, blip_time_t t );
54
55// More features
56
57// Resets sound chip and sets noise feedback bits and width
58void Sms_apu_reset( struct Sms_Apu* this, unsigned noise_feedback, int noise_width );
59
60// Sets overall volume, where 1.0 is normal
61void Sms_apu_volume( struct Sms_Apu* this, int vol );
62
63#endif
diff --git a/lib/rbcodec/codecs/libgme/sms_fm_apu.c b/lib/rbcodec/codecs/libgme/sms_fm_apu.c
new file mode 100644
index 0000000000..ee5ce48932
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sms_fm_apu.c
@@ -0,0 +1,82 @@
1#include "sms_fm_apu.h"
2
3#include "blargg_source.h"
4
5void Fm_apu_create( struct Sms_Fm_Apu* this )
6{
7 Synth_init( &this->synth );
8 Ym2413_init( &this->apu );
9}
10
11blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate )
12{
13 this->period_ = (blip_time_t) (clock_rate / sample_rate);
14 CHECK_ALLOC( !Ym2413_set_rate( &this->apu, sample_rate, clock_rate ) );
15
16 Fm_apu_set_output( this, 0 );
17 Fm_apu_volume( this, (int)FP_ONE_VOLUME );
18 Fm_apu_reset( this );
19 return 0;
20}
21
22void Fm_apu_reset( struct Sms_Fm_Apu* this )
23{
24 this->addr = 0;
25 this->next_time = 0;
26 this->last_amp = 0;
27
28 Ym2413_reset( &this->apu );
29}
30
31void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time );
32void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t time, int data )
33{
34 if ( time > this->next_time )
35 fm_run_until( this, time );
36
37 Ym2413_write( &this->apu, this->addr, data );
38}
39
40void fm_run_until( struct Sms_Fm_Apu* this, blip_time_t end_time )
41{
42 assert( end_time > this->next_time );
43
44 struct Blip_Buffer* const output = this->output_;
45 if ( !output )
46 {
47 this->next_time = end_time;
48 return;
49 }
50
51 blip_time_t time = this->next_time;
52 struct Ym2413_Emu* emu = &this->apu;
53 do
54 {
55 short samples [2];
56 Ym2413_run( emu, 1, samples );
57 int amp = (samples [0] + samples [1]) >> 1;
58
59 int delta = amp - this->last_amp;
60 if ( delta )
61 {
62 this->last_amp = amp;
63 Synth_offset_inline( &this->synth, time, delta, output );
64 }
65 time += this->period_;
66 }
67 while ( time < end_time );
68
69 this->next_time = time;
70}
71
72void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t time )
73{
74 if ( time > this->next_time )
75 fm_run_until( this, time );
76
77 this->next_time -= time;
78 assert( this->next_time >= 0 );
79
80 if ( this->output_ )
81 Blip_set_modified( this->output_ );
82}
diff --git a/lib/rbcodec/codecs/libgme/sms_fm_apu.h b/lib/rbcodec/codecs/libgme/sms_fm_apu.h
new file mode 100644
index 0000000000..921db6cef1
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/sms_fm_apu.h
@@ -0,0 +1,43 @@
1#ifndef SMS_FM_APU_H
2#define SMS_FM_APU_H
3
4#include "blargg_common.h"
5#include "blip_buffer.h"
6#include "ym2413_emu.h"
7
8enum { fm_apu_osc_count = 1 };
9
10struct Sms_Fm_Apu {
11 struct Blip_Buffer* output_;
12 blip_time_t next_time;
13 int last_amp;
14 int addr;
15
16 int clock_;
17 int rate_;
18 blip_time_t period_;
19
20 struct Blip_Synth synth;
21 struct Ym2413_Emu apu;
22};
23
24void Fm_apu_create( struct Sms_Fm_Apu* this );
25
26static inline bool Fm_apu_supported( void ) { return Ym2413_supported(); }
27blargg_err_t Fm_apu_init( struct Sms_Fm_Apu* this, int clock_rate, int sample_rate );
28
29static inline void Fm_apu_set_output( struct Sms_Fm_Apu* this, struct Blip_Buffer* b )
30{
31 this->output_ = b;
32}
33
34static inline void Fm_apu_volume( struct Sms_Fm_Apu* this, int v ) { Synth_volume( &this->synth, (v*2) / 5 / 4096 ); }
35
36void Fm_apu_reset( struct Sms_Fm_Apu* this );
37
38static inline void Fm_apu_write_addr( struct Sms_Fm_Apu* this, int data ) { this->addr = data; }
39void Fm_apu_write_data( struct Sms_Fm_Apu* this, blip_time_t, int data );
40
41void Fm_apu_end_frame( struct Sms_Fm_Apu* this, blip_time_t t );
42
43#endif
diff --git a/lib/rbcodec/codecs/libgme/track_filter.c b/lib/rbcodec/codecs/libgme/track_filter.c
new file mode 100644
index 0000000000..d0d75f2ded
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/track_filter.c
@@ -0,0 +1,294 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "track_filter.h"
4
5/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18int const fade_block_size = 512;
19int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
20int const silence_threshold = 8;
21
22void track_create( struct Track_Filter* this )
23{
24 this->emu_ = NULL;
25 this->setup_.max_initial = 0;
26 this->setup_.lookahead = 0;
27 this->setup_.max_silence = indefinite_count;
28 this->silence_ignored_ = false;
29 track_stop( this );
30}
31
32blargg_err_t track_init( struct Track_Filter* this, void* emu )
33{
34 this->emu_ = emu;
35 return 0;
36}
37
38static void clear_time_vars( struct Track_Filter* this )
39{
40 this->emu_time = this->buf_remain;
41 this->out_time = 0;
42 this->silence_time = 0;
43 this->silence_count = 0;
44}
45
46void track_stop( struct Track_Filter* this )
47{
48 this->emu_track_ended_ = true;
49 this->track_ended_ = true;
50 this->fade_start = indefinite_count;
51 this->fade_step = 1;
52 this->buf_remain = 0;
53 this->emu_error = NULL;
54 clear_time_vars( this );
55}
56
57blargg_err_t track_start( struct Track_Filter* this )
58{
59 this->emu_error = NULL;
60 track_stop( this );
61
62 this->emu_track_ended_ = false;
63 this->track_ended_ = false;
64
65 if ( !this->silence_ignored_ )
66 {
67 // play until non-silence or end of track
68 while ( this->emu_time < this->setup_.max_initial )
69 {
70 fill_buf( this );
71 if ( this->buf_remain | this->emu_track_ended_ )
72 break;
73 }
74 }
75
76 clear_time_vars( this );
77 return this->emu_error;
78}
79
80static void end_track_if_error( struct Track_Filter* this, blargg_err_t err )
81{
82 if ( err )
83 {
84 this->emu_error = err;
85 this->emu_track_ended_ = true;
86 }
87}
88
89blargg_err_t track_skip( struct Track_Filter* this, int count )
90{
91 this->emu_error = NULL;
92 this->out_time += count;
93
94 // remove from silence and buf first
95 {
96 int n = min( count, this->silence_count );
97 this->silence_count -= n;
98 count -= n;
99
100 n = min( count, this->buf_remain );
101 this->buf_remain -= n;
102 count -= n;
103 }
104
105 if ( count && !this->emu_track_ended_ )
106 {
107 this->emu_time += count;
108 this->silence_time = this->emu_time; // would otherwise be invalid
109 end_track_if_error( this, skip_( this->emu_, count ) );
110 }
111
112 if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
113 this->track_ended_ |= this->emu_track_ended_;
114
115 return this->emu_error;
116}
117
118blargg_err_t skippy_( struct Track_Filter* this, int count )
119{
120 while ( count && !this->emu_track_ended_ )
121 {
122 int n = buf_size;
123 if ( n > count )
124 n = count;
125 count -= n;
126 RETURN_ERR( play_( this->emu_, n, this->buf ) );
127 }
128 return 0;
129}
130
131// Fading
132
133void track_set_fade( struct Track_Filter* this, int start, int length )
134{
135 this->fade_start = start;
136 this->fade_step = length / (fade_block_size * fade_shift);
137 if ( this->fade_step < 1 )
138 this->fade_step = 1;
139}
140
141static bool is_fading( struct Track_Filter* this )
142{
143 return this->out_time >= this->fade_start && this->fade_start != indefinite_count;
144}
145
146// unit / pow( 2.0, (double) x / step )
147static int int_log( int x, int step, int unit )
148{
149 int shift = x / step;
150 int fraction = (x - shift * step) * unit / step;
151 return ((unit - fraction) + (fraction >> 1)) >> shift;
152}
153
154static void handle_fade( struct Track_Filter* this, sample_t out [], int out_count )
155{
156 int i;
157 for ( i = 0; i < out_count; i += fade_block_size )
158 {
159 int const shift = 14;
160 int const unit = 1 << shift;
161 int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
162 this->fade_step, unit );
163 if ( gain < (unit >> fade_shift) )
164 this->track_ended_ = this->emu_track_ended_ = true;
165
166 sample_t* io = &out [i];
167 for ( int count = min( fade_block_size, out_count - i ); count; --count )
168 {
169 *io = (sample_t) ((*io * gain) >> shift);
170 ++io;
171 }
172 }
173}
174
175// Silence detection
176
177static void emu_play( struct Track_Filter* this, sample_t out [], int count )
178{
179 this->emu_time += count;
180 if ( !this->emu_track_ended_ )
181 end_track_if_error( this, play_( this->emu_, count, out ) );
182 else
183 memset( out, 0, count * sizeof *out );
184}
185
186// number of consecutive silent samples at end
187static int count_silence( sample_t begin [], int size )
188{
189 sample_t first = *begin;
190 *begin = silence_threshold * 2; // sentinel
191 sample_t* p = begin + size;
192 while ( (unsigned) (*--p + silence_threshold) <= (unsigned) silence_threshold * 2 ) { }
193 *begin = first;
194 return size - (p - begin);
195}
196
197// fill internal buffer and check it for silence
198void fill_buf( struct Track_Filter* this )
199{
200 assert( !this->buf_remain );
201 if ( !this->emu_track_ended_ )
202 {
203 emu_play( this, this->buf, buf_size );
204 int silence = count_silence( this->buf, buf_size );
205 if ( silence < buf_size )
206 {
207 this->silence_time = this->emu_time - silence;
208 this->buf_remain = buf_size;
209 return;
210 }
211 }
212 this->silence_count += buf_size;
213}
214
215blargg_err_t track_play( struct Track_Filter* this, int out_count, sample_t out [] )
216{
217 this->emu_error = NULL;
218 if ( this->track_ended_ )
219 {
220 memset( out, 0, out_count * sizeof *out );
221 }
222 else
223 {
224 assert( this->emu_time >= this->out_time );
225
226 // prints nifty graph of how far ahead we are when searching for silence
227 //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / 44100), "*" );
228
229 // use any remaining silence samples
230 int pos = 0;
231 if ( this->silence_count )
232 {
233 if ( !this->silence_ignored_ )
234 {
235 // during a run of silence, run emulator at >=2x speed so it gets ahead
236 int ahead_time = this->setup_.lookahead * (this->out_time + out_count - this->silence_time) +
237 this->silence_time;
238 while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
239 fill_buf( this );
240
241 // end track if sufficient silence has been found
242 if ( this->emu_time - this->silence_time > this->setup_.max_silence )
243 {
244 this->track_ended_ = this->emu_track_ended_ = true;
245 this->silence_count = out_count;
246 this->buf_remain = 0;
247 }
248 }
249
250 // fill from remaining silence
251 pos = min( this->silence_count, out_count );
252 memset( out, 0, pos * sizeof *out );
253 this->silence_count -= pos;
254 }
255
256 // use any remaining samples from buffer
257 if ( this->buf_remain )
258 {
259 int n = min( this->buf_remain, (int) (out_count - pos) );
260 memcpy( out + pos, this->buf + (buf_size - this->buf_remain), n * sizeof *out );
261 this->buf_remain -= n;
262 pos += n;
263 }
264
265 // generate remaining samples normally
266 int remain = out_count - pos;
267 if ( remain )
268 {
269 emu_play( this, out + pos, remain );
270 this->track_ended_ |= this->emu_track_ended_;
271
272 if ( this->silence_ignored_ && !is_fading( this ) )
273 {
274 // if left unupdated, ahead_time could become too large
275 this->silence_time = this->emu_time;
276 }
277 else
278 {
279 // check end for a new run of silence
280 int silence = count_silence( out + pos, remain );
281 if ( silence < remain )
282 this->silence_time = this->emu_time - silence;
283
284 if ( this->emu_time - this->silence_time >= buf_size )
285 fill_buf( this ); // cause silence detection on next play()
286 }
287 }
288
289 if ( is_fading( this ) )
290 handle_fade( this, out, out_count );
291 }
292 this->out_time += out_count;
293 return this->emu_error;
294}
diff --git a/lib/rbcodec/codecs/libgme/track_filter.h b/lib/rbcodec/codecs/libgme/track_filter.h
new file mode 100644
index 0000000000..3689be9620
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/track_filter.h
@@ -0,0 +1,90 @@
1// Removes silence from beginning of track, fades end of track. Also looks ahead
2// for excessive silence, and if found, ends track.
3
4// Game_Music_Emu 0.6-pre
5#ifndef TRACK_FILTER_H
6#define TRACK_FILTER_H
7
8#include "blargg_common.h"
9
10typedef short sample_t;
11typedef int sample_count_t;
12
13enum { indefinite_count = INT_MAX/2 + 1 };
14enum { buf_size = 2048 };
15
16struct setup_t {
17 sample_count_t max_initial; // maximum silence to strip from beginning of track
18 sample_count_t max_silence; // maximum silence in middle of track without it ending
19 int lookahead; // internal speed when looking ahead for silence (2=200% etc.)
20};
21
22struct Track_Filter {
23 void* emu_;
24 struct setup_t setup_;
25 const char* emu_error;
26 bool silence_ignored_;
27
28 // Timing
29 int out_time; // number of samples played since start of track
30 int emu_time; // number of samples emulator has generated since start of track
31 int emu_track_ended_; // emulator has reached end of track
32 volatile int track_ended_;
33
34 // Fading
35 int fade_start;
36 int fade_step;
37
38 // Silence detection
39 int silence_time; // absolute number of samples where most recent silence began
40 int silence_count; // number of samples of silence to play before using buf
41 int buf_remain; // number of samples left in silence buffer
42 sample_t buf [buf_size];
43};
44
45// Initializes filter. Must be done once before using object.
46blargg_err_t track_init( struct Track_Filter* this, void* );
47void track_create( struct Track_Filter* this );
48
49// Gets/sets setup
50static inline struct setup_t const* track_get_setup( struct Track_Filter* this ) { return &this->setup_; }
51static inline void track_setup( struct Track_Filter* this, struct setup_t const* s ) { this->setup_ = *s; }
52
53// Disables automatic end-of-track detection and skipping of silence at beginning
54static inline void track_ignore_silence( struct Track_Filter* this, bool disable ) { this->silence_ignored_ = disable; }
55
56// Clears state and skips initial silence in track
57blargg_err_t track_start( struct Track_Filter* this );
58
59// Sets time that fade starts, and how long until track ends.
60void track_set_fade( struct Track_Filter* this, sample_count_t start, sample_count_t length );
61
62// Generates n samples into buf
63blargg_err_t track_play( struct Track_Filter* this, int n, sample_t buf [] );
64
65// Skips n samples
66blargg_err_t track_skip( struct Track_Filter* this, int n );
67
68// Number of samples played/skipped since start_track()
69static inline int track_sample_count( struct Track_Filter* this ) { return this->out_time; }
70
71// True if track ended. Causes are end of source samples, end of fade,
72// or excessive silence.
73static inline bool track_ended( struct Track_Filter* this ) { return this->track_ended_; }
74
75// Clears state
76void track_stop( struct Track_Filter* this );
77
78// For use by callbacks
79
80// Sets internal "track ended" flag and stops generation of further source samples
81static inline void track_set_end( struct Track_Filter* this ) { this->emu_track_ended_ = true; }
82
83// For use by skip_() callback
84blargg_err_t skippy_( struct Track_Filter* this, int count );
85void fill_buf( struct Track_Filter* this );
86
87// Skip and play callbacks
88blargg_err_t skip_( void* emu, int count );
89blargg_err_t play_( void* emu, int count, sample_t out [] );
90#endif
diff --git a/lib/rbcodec/codecs/libgme/vgm_emu.c b/lib/rbcodec/codecs/libgme/vgm_emu.c
new file mode 100644
index 0000000000..4b8953ccf4
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/vgm_emu.c
@@ -0,0 +1,858 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
2
3#include "vgm_emu.h"
4
5#include "blargg_endian.h"
6#include <string.h>
7#include <math.h>
8
9/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
10can redistribute it and/or modify it under the terms of the GNU Lesser
11General Public License as published by the Free Software Foundation; either
12version 2.1 of the License, or (at your option) any later version. This
13module is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16details. You should have received a copy of the GNU Lesser General Public
17License along with this module; if not, write to the Free Software Foundation,
18Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
19
20#include "blargg_source.h"
21
22const char* const gme_wrong_file_type = "Wrong file type for this emulator";
23
24int const fm_gain = 3; // FM emulators are internally quieter to avoid 16-bit overflow
25
26// VGM commands (Spec v1.50)
27enum {
28 cmd_gg_stereo = 0x4F,
29 cmd_psg = 0x50,
30 cmd_ym2413 = 0x51,
31 cmd_ym2612_port0 = 0x52,
32 cmd_ym2612_port1 = 0x53,
33 cmd_ym2151 = 0x54,
34 cmd_delay = 0x61,
35 cmd_delay_735 = 0x62,
36 cmd_delay_882 = 0x63,
37 cmd_byte_delay = 0x64,
38 cmd_end = 0x66,
39 cmd_data_block = 0x67,
40 cmd_short_delay = 0x70,
41 cmd_pcm_delay = 0x80,
42 cmd_pcm_seek = 0xE0,
43
44 pcm_block_type = 0x00,
45 ym2612_dac_port = 0x2A,
46 ym2612_dac_pan_port = 0xB6
47};
48
49static void clear_track_vars( struct Vgm_Emu* this )
50{
51 this->current_track = -1;
52 track_stop( &this->track_filter );
53}
54
55int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, sample_t* buf );
56static int play_frame_( void* data, blip_time_t blip_time, int sample_count, short int* buf )
57{
58 return play_frame( (struct Vgm_Emu*) data, blip_time, sample_count, buf );
59}
60
61void Vgm_init( struct Vgm_Emu* this )
62{
63 this->sample_rate = 0;
64 this->mute_mask_ = 0;
65 this->tempo = (int)(FP_ONE_TEMPO);
66
67 // defaults
68 this->tfilter = *track_get_setup( &this->track_filter );
69 this->tfilter.max_initial = 2;
70 this->tfilter.lookahead = 1;
71 this->track_filter.silence_ignored_ = false;
72
73 // Disable oversampling by default
74 this->disable_oversampling = true;
75 this->psg_rate = 0;
76
77 Sms_apu_init( &this->psg );
78 Synth_init( &this->pcm );
79
80 Buffer_init( &this->stereo_buf );
81 Blip_init( &this->blip_buf );
82
83 // Init fm chips
84 Ym2413_init( &this->ym2413 );
85 Ym2612_init( &this->ym2612 );
86
87 // Init resampler
88 Resampler_init( &this->resampler );
89 Resampler_set_callback( &this->resampler, play_frame_, this );
90
91 // Set sound gain, a value too high
92 // will cause saturation
93 Sound_set_gain(this, (int)(FP_ONE_GAIN*0.7));
94
95 // Unload
96 this->voice_count = 0;
97 this->voice_types = 0;
98 clear_track_vars( this );
99}
100
101// Track info
102
103static byte const* skip_gd3_str( byte const* in, byte const* end )
104{
105 while ( end - in >= 2 )
106 {
107 in += 2;
108 if ( !(in [-2] | in [-1]) )
109 break;
110 }
111 return in;
112}
113
114static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
115{
116 byte const* mid = skip_gd3_str( in, end );
117 int i, len = (mid - in) / 2 - 1;
118 if ( field && len > 0 )
119 {
120 len = min( len, (int) gme_max_field );
121 field [len] = 0;
122 for ( i = 0; i < len; i++ )
123 field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
124 }
125 return mid;
126}
127
128static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
129{
130 return skip_gd3_str( get_gd3_str( in, end, field ), end );
131}
132
133static void parse_gd3( byte const* in, byte const* end, struct track_info_t* out )
134{
135 in = get_gd3_pair( in, end, out->song );
136 in = get_gd3_pair( in, end, out->game );
137 in = get_gd3_pair( in, end, NULL ); // Skip system
138 in = get_gd3_pair( in, end, out->author );
139}
140
141int const gd3_header_size = 12;
142
143static int check_gd3_header( byte const* h, int remain )
144{
145 if ( remain < gd3_header_size ) return 0;
146 if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
147 if ( get_le32( h + 4 ) >= 0x200 ) return 0;
148
149 int gd3_size = get_le32( h + 8 );
150 if ( gd3_size > remain - gd3_header_size )
151 gd3_size = remain - gd3_header_size;
152 return gd3_size;
153}
154
155static byte const* gd3_data( struct Vgm_Emu* this, int* size )
156{
157 if ( size )
158 *size = 0;
159
160 int gd3_offset = get_le32( header( this )->gd3_offset ) - 0x2C;
161 if ( gd3_offset < 0 )
162 return 0;
163
164 byte const* gd3 = this->file_begin + header_size + gd3_offset;
165 int gd3_size = check_gd3_header( gd3, this->file_end - gd3 );
166 if ( !gd3_size )
167 return 0;
168
169 if ( size )
170 *size = gd3_size + gd3_header_size;
171
172 return gd3;
173}
174
175static void get_vgm_length( struct header_t const* h, struct track_info_t* out )
176{
177 int length = get_le32( h->track_duration ) * 10 / 441;
178 if ( length > 0 )
179 {
180 int loop = get_le32( h->loop_duration );
181 if ( loop > 0 && get_le32( h->loop_offset ) )
182 {
183 out->loop_length = loop * 10 / 441;
184 out->intro_length = length - out->loop_length;
185 }
186 else
187 {
188 out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
189 out->intro_length = length; // make it clear that track is no longer than length
190 out->loop_length = 0;
191 }
192 }
193}
194
195static blargg_err_t track_info( struct Vgm_Emu* this, struct track_info_t* out )
196{
197 memset(out, 0, sizeof *out);
198 get_vgm_length( header( this ), out );
199
200 int size;
201 byte const* gd3 = gd3_data( this, &size );
202 if ( gd3 )
203 parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
204
205 return 0;
206}
207
208static blargg_err_t check_vgm_header( struct header_t* h )
209{
210 if ( memcmp( h->tag, "Vgm ", 4 ) )
211 return gme_wrong_file_type;
212 return 0;
213}
214
215static void set_voice( struct Vgm_Emu* this, int i, struct Blip_Buffer* c, struct Blip_Buffer* l, struct Blip_Buffer* r )
216{
217 if ( i < sms_osc_count ) {
218 Sms_apu_set_output( &this->psg, i, c, l, r );
219 }
220}
221
222blargg_err_t setup_fm( struct Vgm_Emu* this );
223blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_size, bool parse_info )
224{
225 // Unload
226 this->voice_count = 0;
227 clear_track_vars( this );
228
229 // Clear info
230 memset( &this->info, 0, sizeof this->info );
231
232 assert( offsetof (struct header_t,unused2 [8]) == header_size );
233
234 if ( new_size <= header_size )
235 return gme_wrong_file_type;
236
237 // Reset data pointers
238 this->file_begin = new_data;
239 this->file_end = new_data + new_size;
240
241 struct header_t* h = (struct header_t*) new_data;
242 RETURN_ERR( check_vgm_header( h ) );
243 check( get_le32( h.version ) <= 0x150 );
244
245 // If this was VGZ file gd3 parse info
246 if ( parse_info ) {
247 track_info( this, &this->info );
248
249 // If file was trimmed add an
250 // incomplete token to the game tag
251 if ( get_le32( h->data_size ) > (unsigned) new_size ) {
252 *((char *) this->file_end) = cmd_end;
253 strcat(this->info.game, "(Trimmed VGZ file)" );
254 }
255 }
256
257 // Get loop
258 this->loop_begin = this->file_end;
259
260 // If file was trimmed don't loop
261 if ( get_le32( h->loop_offset ) && get_le32( h->data_size ) <= (unsigned) new_size )
262 this->loop_begin = &new_data [get_le32( h->loop_offset ) + offsetof (struct header_t,loop_offset)];
263
264 // PSG rate
265 this->psg_rate = get_le32( h->psg_rate );
266 if ( !this->psg_rate )
267 this->psg_rate = 3579545;
268
269 Blip_set_clock_rate( &this->blip_buf, this->psg_rate );
270
271 // Disable FM
272 this->fm_rate = 0;
273 Ym2612_enable( &this->ym2612, false );
274 Ym2413_enable( &this->ym2413, false );
275
276 this->voice_count = sms_osc_count;
277 static int const types [8] = {
278 wave_type+1, wave_type+2, wave_type+3, noise_type+1,
279 0, 0, 0, 0
280 };
281 this->voice_types = types;
282
283 RETURN_ERR( setup_fm( this ) );
284
285 // do after FM in case output buffer is changed
286 // setup buffer
287 this->clock_rate_ = this->psg_rate;
288 Buffer_clock_rate( &this->stereo_buf, this->psg_rate );
289 RETURN_ERR( Buffer_set_channel_count( &this->stereo_buf, this->voice_count, this->voice_types ) );
290 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
291
292 // Post load
293 Sound_set_tempo( this, this->tempo );
294 Sound_mute_voices( this, this->mute_mask_ );
295
296 // so we can start playback
297 this->current_track = 0;
298 return 0;
299}
300
301void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate );
302static blargg_err_t init_fm( struct Vgm_Emu* this, int* rate )
303{
304 int ym2612_rate = get_le32( header( this )->ym2612_rate );
305 int ym2413_rate = get_le32( header( this )->ym2413_rate );
306 if ( ym2413_rate && get_le32( header( this )->version ) < 0x110 )
307 update_fm_rates( this, &ym2413_rate, &ym2612_rate );
308
309 if ( ym2612_rate )
310 {
311 if ( !*rate )
312 *rate = ym2612_rate / 144;
313 RETURN_ERR( Ym2612_set_rate( &this->ym2612, *rate, ym2612_rate ) );
314 Ym2612_enable( &this->ym2612, true );
315 }
316 else if ( ym2413_rate )
317 {
318 if ( !*rate )
319 *rate = ym2413_rate / 72;
320 int result = Ym2413_set_rate( &this->ym2413, *rate, ym2413_rate );
321 if ( result == 2 )
322 return "YM2413 FM sound not supported";
323 CHECK_ALLOC( !result );
324 Ym2413_enable( &this->ym2413, true );
325 }
326
327 this->fm_rate = *rate;
328
329 return 0;
330}
331
332blargg_err_t setup_fm( struct Vgm_Emu* this )
333{
334 int fm_rate = 0;
335 if ( !this->disable_oversampling )
336 fm_rate = (this->sample_rate * 3) / 2; // oversample factor = 1.5
337 RETURN_ERR( init_fm( this, &fm_rate ) );
338
339 if ( uses_fm( this ) )
340 {
341 this->voice_count = 8;
342 RETURN_ERR( Resampler_setup( &this->resampler, fm_rate, fm_gain, this->sample_rate, this->gain ) );
343 RETURN_ERR( Resampler_reset( &this->resampler, Blip_length( &this->blip_buf ) * this->sample_rate / 1000 ) );
344 Sms_apu_volume( &this->psg, ((this->gain/5)-(this->gain*5)/1000) * fm_gain );
345 }
346 else
347 {
348 Sms_apu_volume( &this->psg, this->gain );
349 }
350
351 return 0;
352}
353
354// Emulation
355
356blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time );
357static blip_time_t run_psg( struct Vgm_Emu* this, int msec )
358{
359 blip_time_t t = run( this, msec * this->vgm_rate / 1000 );
360 Sms_apu_end_frame( &this->psg, t );
361 return t;
362}
363
364static void check_end( struct Vgm_Emu* this )
365{
366 if( this->pos >= this->file_end )
367 track_set_end( &this->track_filter );
368}
369
370static blargg_err_t run_clocks( struct Vgm_Emu* this, blip_time_t* time_io, int msec )
371{
372 check_end( this );
373 *time_io = run_psg( this, msec );
374 return 0;
375}
376
377blargg_err_t play_( void *emu, int count, sample_t out [] )
378{
379 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
380
381 if ( !uses_fm( this ) ) {
382 int remain = count;
383 while ( remain )
384 {
385 Buffer_disable_immediate_removal( &this->stereo_buf );
386 remain -= Buffer_read_samples( &this->stereo_buf, &out [count - remain], remain );
387 if ( remain )
388 {
389 if ( this->buf_changed_count != Buffer_channels_changed_count( &this->stereo_buf ) )
390 {
391 this->buf_changed_count = Buffer_channels_changed_count( &this->stereo_buf );
392
393 // Remute voices
394 Sound_mute_voices( this, this->mute_mask_ );
395 }
396 int msec = Buffer_length( &this->stereo_buf );
397 blip_time_t clocks_emulated = msec * this->clock_rate_ / 1000 - 100;
398 RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
399 assert( clocks_emulated );
400 Buffer_end_frame( &this->stereo_buf, clocks_emulated );
401 }
402 }
403
404 return 0;
405 }
406
407 Resampler_play( &this->resampler, count, out, &this->blip_buf );
408 return 0;
409}
410
411// Vgm_Emu_impl
412
413static inline int command_len( int command )
414{
415 static byte const lens [0x10] = {
416 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
417 1,1,1,2,2,3,1,1,1,1,3,3,4,4,5,5
418 };
419 int len = lens [command >> 4];
420 check( len != 1 );
421 return len;
422}
423
424static inline fm_time_t to_fm_time( struct Vgm_Emu* this, vgm_time_t t )
425{
426 return (t * this->fm_time_factor + this->fm_time_offset) >> fm_time_bits;
427}
428
429static inline blip_time_t to_psg_time( struct Vgm_Emu* this, vgm_time_t t )
430{
431 return (t * this->blip_time_factor) >> blip_time_bits;
432}
433
434static void write_pcm( struct Vgm_Emu* this, vgm_time_t vgm_time, int amp )
435{
436 check( amp >= 0 );
437 blip_time_t blip_time = to_psg_time( this, vgm_time );
438 int old = this->dac_amp;
439 int delta = amp - old;
440 this->dac_amp = amp;
441 Blip_set_modified( &this->blip_buf );
442 if ( old >= 0 ) // first write is ignored, to avoid click
443 Synth_offset_inline( &this->pcm, blip_time, delta, &this->blip_buf );
444 else
445 this->dac_amp |= this->dac_disabled;
446}
447
448blip_time_t run( struct Vgm_Emu* this, vgm_time_t end_time )
449{
450 vgm_time_t vgm_time = this->vgm_time;
451 byte const* pos = this->pos;
452 /* if ( pos > this->file_end )
453 {
454 warning( "Stream lacked end event" );
455 } */
456
457 while ( vgm_time < end_time && pos < this->file_end )
458 {
459 // TODO: be sure there are enough bytes left in stream for particular command
460 // so we don't read past end
461 switch ( *pos++ )
462 {
463 case cmd_end:
464 pos = this->loop_begin; // if not looped, loop_begin == data_end
465 break;
466
467 case cmd_delay_735:
468 vgm_time += 735;
469 break;
470
471 case cmd_delay_882:
472 vgm_time += 882;
473 break;
474
475 case cmd_gg_stereo:
476 Sms_apu_write_ggstereo( &this->psg, to_psg_time( this, vgm_time ), *pos++ );
477 break;
478
479 case cmd_psg:
480 Sms_apu_write_data( &this->psg, to_psg_time( this, vgm_time ), *pos++ );
481 break;
482
483 case cmd_delay:
484 vgm_time += pos [1] * 0x100 + pos [0];
485 pos += 2;
486 break;
487
488 case cmd_byte_delay:
489 vgm_time += *pos++;
490 break;
491
492 case cmd_ym2413:
493 if ( Ym2413_run_until( &this->ym2413, to_fm_time( this, vgm_time ) ) )
494 Ym2413_write( &this->ym2413, pos [0], pos [1] );
495 pos += 2;
496 break;
497
498 case cmd_ym2612_port0:
499 if ( pos [0] == ym2612_dac_port )
500 {
501 write_pcm( this, vgm_time, pos [1] );
502 }
503 else if ( Ym2612_run_until( &this->ym2612, to_fm_time( this, vgm_time ) ) )
504 {
505 if ( pos [0] == 0x2B )
506 {
507 this->dac_disabled = (pos [1] >> 7 & 1) - 1;
508 this->dac_amp |= this->dac_disabled;
509 }
510 Ym2612_write0( &this->ym2612, pos [0], pos [1] );
511 }
512 pos += 2;
513 break;
514
515 case cmd_ym2612_port1:
516 if ( Ym2612_run_until( &this->ym2612, to_fm_time( this, vgm_time ) ) )
517 Ym2612_write1( &this->ym2612, pos [0], pos [1] );
518 pos += 2;
519 break;
520
521 case cmd_data_block: {
522 check( *pos == cmd_end );
523 int type = pos [1];
524 int size = get_le32( pos + 2 );
525 pos += 6;
526 if ( type == pcm_block_type )
527 this->pcm_data = pos;
528 pos += size;
529 break;
530 }
531
532 case cmd_pcm_seek:
533 this->pcm_pos = this->pcm_data + pos [3] * 0x1000000 + pos [2] * 0x10000 +
534 pos [1] * 0x100 + pos [0];
535 pos += 4;
536 break;
537
538 default: {
539 int cmd = pos [-1];
540 switch ( cmd & 0xF0 )
541 {
542 case cmd_pcm_delay:
543 write_pcm( this, vgm_time, *this->pcm_pos++ );
544 vgm_time += cmd & 0x0F;
545 break;
546
547 case cmd_short_delay:
548 vgm_time += (cmd & 0x0F) + 1;
549 break;
550
551 case 0x50:
552 pos += 2;
553 break;
554
555 default:
556 pos += command_len( cmd ) - 1;
557 /* warning( "Unknown stream event" ); */
558 }
559 }
560 }
561 }
562 vgm_time -= end_time;
563 this->pos = pos;
564 this->vgm_time = vgm_time;
565
566 return to_psg_time( this, end_time );
567}
568
569int play_frame( struct Vgm_Emu* this, blip_time_t blip_time, int sample_count, blip_sample_t out [] )
570{
571 check_end( this);
572
573 // to do: timing is working mostly by luck
574 int min_pairs = (unsigned) sample_count / 2;
575 int vgm_time = (min_pairs << fm_time_bits) / this->fm_time_factor - 1;
576 assert( to_fm_time( this, vgm_time ) <= min_pairs );
577 int pairs;
578 while ( (pairs = to_fm_time( this, vgm_time )) < min_pairs )
579 vgm_time++;
580 //debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
581
582 if ( Ym2612_enabled( &this->ym2612 ) )
583 {
584 Ym2612_begin_frame( &this->ym2612, out );
585 memset( out, 0, pairs * stereo * sizeof *out );
586 }
587 else if ( Ym2413_enabled( &this->ym2413 ) )
588 {
589 Ym2413_begin_frame( &this->ym2413, out );
590 }
591
592 run( this, vgm_time );
593 Ym2612_run_until( &this->ym2612, pairs );
594 Ym2413_run_until( &this->ym2413, pairs );
595
596 this->fm_time_offset = (vgm_time * this->fm_time_factor + this->fm_time_offset) - (pairs << fm_time_bits);
597
598 Sms_apu_end_frame( &this->psg, blip_time );
599
600 return pairs * stereo;
601}
602
603// Update pre-1.10 header FM rates by scanning commands
604void update_fm_rates( struct Vgm_Emu* this, int* ym2413_rate, int* ym2612_rate )
605{
606 byte const* p = this->file_begin + 0x40;
607 while ( p < this->file_end )
608 {
609 switch ( *p )
610 {
611 case cmd_end:
612 return;
613
614 case cmd_psg:
615 case cmd_byte_delay:
616 p += 2;
617 break;
618
619 case cmd_delay:
620 p += 3;
621 break;
622
623 case cmd_data_block:
624 p += 7 + get_le32( p + 3 );
625 break;
626
627 case cmd_ym2413:
628 *ym2612_rate = 0;
629 return;
630
631 case cmd_ym2612_port0:
632 case cmd_ym2612_port1:
633 *ym2612_rate = *ym2413_rate;
634 *ym2413_rate = 0;
635 return;
636
637 case cmd_ym2151:
638 *ym2413_rate = 0;
639 *ym2612_rate = 0;
640 return;
641
642 default:
643 p += command_len( *p );
644 }
645 }
646}
647
648
649// Music Emu
650
651blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, int rate )
652{
653 require( !this->sample_rate ); // sample rate can't be changed once set
654 RETURN_ERR( Blip_set_sample_rate( &this->blip_buf, rate, 1000 / 30 ) );
655 RETURN_ERR( Buffer_set_sample_rate( &this->stereo_buf, rate, 1000 / 20 ) );
656
657 // Set bass frequency
658 Buffer_bass_freq( &this->stereo_buf, 80 );
659
660 this->sample_rate = rate;
661 RETURN_ERR( track_init( &this->track_filter, this ) );
662 this->tfilter.max_silence = 6 * stereo * this->sample_rate;
663 return 0;
664}
665
666void Sound_mute_voice( struct Vgm_Emu* this, int index, bool mute )
667{
668 require( (unsigned) index < (unsigned) this->voice_count );
669 int bit = 1 << index;
670 int mask = this->mute_mask_ | bit;
671 if ( !mute )
672 mask ^= bit;
673 Sound_mute_voices( this, mask );
674}
675
676void Sound_mute_voices( struct Vgm_Emu* this, int mask )
677{
678 require( this->sample_rate ); // sample rate must be set first
679 this->mute_mask_ = mask;
680
681 int i;
682 for ( i = this->voice_count; i--; )
683 {
684 if ( mask & (1 << i) )
685 {
686 set_voice( this, i, 0, 0, 0 );
687 }
688 else
689 {
690 struct channel_t ch = Buffer_channel( &this->stereo_buf, i );
691 assert( (ch.center && ch.left && ch.right) ||
692 (!ch.center && !ch.left && !ch.right) ); // all or nothing
693 set_voice( this, i, ch.center, ch.left, ch.right );
694 }
695 }
696
697 // TODO: what was this for?
698 //core.pcm.output( &core.blip_buf );
699
700 // TODO: silence PCM if FM isn't used?
701 if ( uses_fm( this ) )
702 {
703 for ( i = sms_osc_count; --i >= 0; )
704 Sms_apu_set_output( &this->psg, i, ( mask & 0x80 ) ? 0 : &this->blip_buf, NULL, NULL );
705 if ( Ym2612_enabled( &this->ym2612 ) )
706 {
707 Synth_volume( &this->pcm, (mask & 0x40) ? 0 : (int)((long long)(0.1115*FP_ONE_VOLUME) / 256 * fm_gain * this->gain / FP_ONE_VOLUME) );
708 Ym2612_mute_voices( &this->ym2612, mask );
709 }
710
711 if ( Ym2413_enabled( &this->ym2413 ) )
712 {
713 int m = mask & 0x3F;
714 if ( mask & 0x20 )
715 m |= 0x01E0; // channels 5-8
716 if ( mask & 0x40 )
717 m |= 0x3E00;
718 Ym2413_mute_voices( &this->ym2413, m );
719 }
720 }
721}
722
723void Sound_set_tempo( struct Vgm_Emu* this, int t )
724{
725 require( this->sample_rate ); // sample rate must be set first
726 int const min = (int)(FP_ONE_TEMPO*0.02);
727 int const max = (int)(FP_ONE_TEMPO*4.00);
728 if ( t < min ) t = min;
729 if ( t > max ) t = max;
730 this->tempo = t;
731
732 if ( this->file_begin )
733 {
734 this->vgm_rate = (long) ((44100LL * t) / FP_ONE_TEMPO);
735 this->blip_time_factor = (int) (((1LL << blip_time_bits) * Blip_clock_rate( &this->blip_buf )) / this->vgm_rate);
736 //debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
737 //debug_printf( "vgm_rate: %ld\n", vgm_rate );
738 // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
739 //blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
740 //vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
741
742 this->fm_time_factor = 2 + (int) ((this->fm_rate * (1LL << fm_time_bits)) / this->vgm_rate);
743 }
744}
745
746blargg_err_t Vgm_start_track( struct Vgm_Emu* this )
747{
748 clear_track_vars( this );
749
750 Sms_apu_reset( &this->psg, get_le16( header( this )->noise_feedback ), header( this )->noise_width );
751
752 this->dac_disabled = -1;
753 this->pos = this->file_begin + header_size;
754 this->pcm_data = this->pos;
755 this->pcm_pos = this->pos;
756 this->dac_amp = -1;
757 this->vgm_time = 0;
758 if ( get_le32( header( this )->version ) >= 0x150 )
759 {
760 int data_offset = get_le32( header( this )->data_offset );
761 check( data_offset );
762 if ( data_offset )
763 this->pos += data_offset + offsetof (struct header_t,data_offset) - 0x40;
764 }
765
766 if ( uses_fm( this ) )
767 {
768 if ( Ym2413_enabled( &this->ym2413 ) )
769 Ym2413_reset( &this->ym2413 );
770
771 if ( Ym2612_enabled( &this->ym2612 ) )
772 Ym2612_reset( &this->ym2612 );
773
774 Blip_clear( &this->blip_buf );
775 Resampler_clear( &this->resampler );
776 }
777
778 this->fm_time_offset = 0;
779
780 Buffer_clear( &this->stereo_buf );
781
782 // convert filter times to samples
783 struct setup_t s = this->tfilter;
784 s.max_initial *= this->sample_rate * stereo;
785 #ifdef GME_DISABLE_SILENCE_LOOKAHEAD
786 s.lookahead = 1;
787 #endif
788 track_setup( &this->track_filter, &s );
789
790 return track_start( &this->track_filter );
791}
792
793// Tell/Seek
794
795static int msec_to_samples( int msec, int sample_rate )
796{
797 int sec = msec / 1000;
798 msec -= sec * 1000;
799 return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
800}
801
802int Track_tell( struct Vgm_Emu* this )
803{
804 int rate = this->sample_rate * stereo;
805 int sec = track_sample_count( &this->track_filter ) / rate;
806 return sec * 1000 + (track_sample_count( &this->track_filter ) - sec * rate) * 1000 / rate;
807}
808
809blargg_err_t Track_seek( struct Vgm_Emu* this, int msec )
810{
811 int time = msec_to_samples( msec, this->sample_rate );
812 if ( time < track_sample_count( &this->track_filter ) )
813 RETURN_ERR( Vgm_start_track( this ) );
814 return Track_skip( this, time - track_sample_count( &this->track_filter ) );
815}
816
817blargg_err_t Track_skip( struct Vgm_Emu* this, int count )
818{
819 require( this->current_track >= 0 ); // start_track() must have been called already
820 return track_skip( &this->track_filter, count );
821}
822
823blargg_err_t skip_( void* emu, int count )
824{
825 struct Vgm_Emu* this = (struct Vgm_Emu*) emu;
826
827 // for long skip, mute sound
828 const int threshold = 32768;
829 if ( count > threshold )
830 {
831 int saved_mute = this->mute_mask_;
832 Sound_mute_voices( this, ~0 );
833
834 int n = count - threshold/2;
835 n &= ~(2048-1); // round to multiple of 2048
836 count -= n;
837 RETURN_ERR( skippy_( &this->track_filter, n ) );
838
839 Sound_mute_voices( this, saved_mute );
840 }
841
842 return skippy_( &this->track_filter, count );
843}
844
845// Fading
846
847void Track_set_fade( struct Vgm_Emu* this, int start_msec, int length_msec )
848{
849 track_set_fade( &this->track_filter, msec_to_samples( start_msec, this->sample_rate ),
850 length_msec * this->sample_rate / (1000 / stereo) );
851}
852
853blargg_err_t Vgm_play( struct Vgm_Emu* this, int out_count, sample_t* out )
854{
855 require( this->current_track >= 0 );
856 require( out_count % stereo == 0 );
857 return track_play( &this->track_filter, out_count, out );
858}
diff --git a/lib/rbcodec/codecs/libgme/vgm_emu.h b/lib/rbcodec/codecs/libgme/vgm_emu.h
new file mode 100644
index 0000000000..8c39482008
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/vgm_emu.h
@@ -0,0 +1,206 @@
1// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef VGM_EMU_H
5#define VGM_EMU_H
6
7#include "blargg_common.h"
8#include "blargg_source.h"
9
10#include "track_filter.h"
11#include "resampler.h"
12#include "multi_buffer.h"
13#include "ym2413_emu.h"
14#include "ym2612_emu.h"
15#include "sms_apu.h"
16
17typedef int vgm_time_t;
18typedef int fm_time_t;
19
20enum { fm_time_bits = 12 };
21enum { blip_time_bits = 12 };
22
23// VGM header format
24enum { header_size = 0x40 };
25struct header_t
26{
27 char tag [4];
28 byte data_size [4];
29 byte version [4];
30 byte psg_rate [4];
31 byte ym2413_rate [4];
32 byte gd3_offset [4];
33 byte track_duration [4];
34 byte loop_offset [4];
35 byte loop_duration [4];
36 byte frame_rate [4];
37 byte noise_feedback [2];
38 byte noise_width;
39 byte unused1;
40 byte ym2612_rate [4];
41 byte ym2151_rate [4];
42 byte data_offset [4];
43 byte unused2 [8];
44};
45
46enum { gme_max_field = 63 };
47struct track_info_t
48{
49 /* times in milliseconds; -1 if unknown */
50 int length;
51 int intro_length;
52 int loop_length;
53
54 /* empty string if not available */
55 char game [64];
56 char song [96];
57 char author [64];
58};
59
60// Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips.
61// Supports custom sound buffer and frequency equalization when VGM uses just the PSG.
62// FM sound chips can be run at their proper rates, or slightly higher to reduce
63// aliasing on high notes. Currently YM2413 support requires that you supply a
64// YM2413 sound chip emulator. I can provide one I've modified to work with the library.
65struct Vgm_Emu {
66 int fm_rate;
67 int psg_rate;
68 int vgm_rate;
69 bool disable_oversampling;
70
71 int fm_time_offset;
72 int fm_time_factor;
73
74 int blip_time_factor;
75
76 byte const* file_begin;
77 byte const* file_end;
78
79 vgm_time_t vgm_time;
80 byte const* loop_begin;
81 byte const* pos;
82
83 byte const* pcm_data;
84 byte const* pcm_pos;
85 int dac_amp;
86 int dac_disabled; // -1 if disabled
87
88 // general
89 int current_track;
90 int clock_rate_;
91 unsigned buf_changed_count;
92 int max_initial_silence;
93 int voice_count;
94 int const *voice_types;
95 int mute_mask_;
96 int tempo;
97 int gain;
98
99 int sample_rate;
100
101 // larger items at the end
102 struct track_info_t info;
103
104 struct setup_t tfilter;
105 struct Track_Filter track_filter;
106
107 struct Ym2612_Emu ym2612;
108 struct Ym2413_Emu ym2413;
109
110 struct Sms_Apu psg;
111 struct Blip_Synth pcm;
112 struct Blip_Buffer blip_buf;
113
114 struct Resampler resampler;
115 struct Multi_Buffer stereo_buf;
116};
117
118void Vgm_init( struct Vgm_Emu* this );
119
120// Disable running FM chips at higher than normal rate. Will result in slightly
121// more aliasing of high notes.
122static inline void Vgm_disable_oversampling( struct Vgm_Emu* this, bool disable ) { this->disable_oversampling = disable; }
123
124// Header for currently loaded file
125static inline struct header_t *header( struct Vgm_Emu* this ) { return (struct header_t*) this->file_begin; }
126
127// Basic functionality (see Gme_File.h for file loading/track info functions)
128blargg_err_t Vgm_load_mem( struct Vgm_Emu* this, byte const* new_data, long new_size, bool parse_info );
129
130// True if any FM chips are used by file. Always false until init_fm()
131// is called.
132static inline bool uses_fm( struct Vgm_Emu* this ) { return Ym2612_enabled( &this->ym2612 ) || Ym2413_enabled( &this->ym2413 ); }
133
134// Set output sample rate. Must be called only once before loading file.
135blargg_err_t Vgm_set_sample_rate( struct Vgm_Emu* this, int sample_rate );
136
137// Start a track, where 0 is the first track. Also clears warning string.
138blargg_err_t Vgm_start_track( struct Vgm_Emu* this );
139
140// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
141// errors set warning string, and major errors also end track.
142blargg_err_t Vgm_play( struct Vgm_Emu* this, int count, sample_t* buf );
143
144// Track status/control
145
146// Number of milliseconds (1000 msec = 1 second) played since beginning of track
147int Track_tell( struct Vgm_Emu* this );
148
149// Seek to new time in track. Seeking backwards or far forward can take a while.
150blargg_err_t Track_seek( struct Vgm_Emu* this, int msec );
151
152// Skip n samples
153blargg_err_t Track_skip( struct Vgm_Emu* this, int n );
154
155// Set start time and length of track fade out. Once fade ends track_ended() returns
156// true. Fade time can be changed while track is playing.
157void Track_set_fade( struct Vgm_Emu* this, int start_msec, int length_msec );
158
159// True if a track has reached its end
160static inline bool Track_ended( struct Vgm_Emu* this )
161{
162 return track_ended( &this->track_filter );
163}
164
165// Disables automatic end-of-track detection and skipping of silence at beginning
166static inline void Track_ignore_silence( struct Vgm_Emu* this, bool disable )
167{
168 this->track_filter.silence_ignored_ = disable;
169}
170
171// Get track length in milliseconds
172static inline int Track_get_length( struct Vgm_Emu* this )
173{
174 int length = this->info.length;
175 if ( length <= 0 )
176 {
177 length = this->info.intro_length + 2 * this->info.loop_length; // intro + 2 loops
178 if ( length <= 0 )
179 length = 150 * 1000; // 2.5 minutes
180 }
181
182 return length;
183}
184
185// Sound customization
186
187// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
188// Track length as returned by track_info() assumes a tempo of 1.0.
189void Sound_set_tempo( struct Vgm_Emu* this, int t );
190
191// Mute/unmute voice i, where voice 0 is first voice
192void Sound_mute_voice( struct Vgm_Emu* this, int index, bool mute );
193
194// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
195// 0 unmutes them all, 0x01 mutes just the first voice, etc.
196void Sound_mute_voices( struct Vgm_Emu* this, int mask );
197
198// Change overall output amplitude, where 1.0 results in minimal clamping.
199// Must be called before set_sample_rate().
200static inline void Sound_set_gain( struct Vgm_Emu* this, int g )
201{
202 assert( !this->sample_rate ); // you must set gain before setting sample rate
203 this->gain = g;
204}
205
206#endif
diff --git a/lib/rbcodec/codecs/libgme/vrc7tone.h b/lib/rbcodec/codecs/libgme/vrc7tone.h
new file mode 100644
index 0000000000..c589335c3c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/vrc7tone.h
@@ -0,0 +1,20 @@
1/* VRC7 TONES by okazaki@angel.ne.jp */
20x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
30x33,0x01,0x09,0x0e,0x94,0x90,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40x13,0x41,0x0f,0x0d,0xce,0xd3,0x43,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50x01,0x12,0x1b,0x06,0xff,0xd2,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60x61,0x61,0x1b,0x07,0xaf,0x63,0x20,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
70x22,0x21,0x1e,0x06,0xf0,0x76,0x08,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80x66,0x21,0x15,0x00,0x93,0x94,0x20,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90x21,0x61,0x1c,0x07,0x82,0x81,0x10,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100x23,0x21,0x20,0x1f,0xc0,0x71,0x07,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110x25,0x31,0x26,0x05,0x64,0x41,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120x17,0x21,0x28,0x07,0xff,0x83,0x02,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130x97,0x81,0x25,0x07,0xcf,0xc8,0x02,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140x21,0x21,0x54,0x0f,0x80,0x7f,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150x01,0x01,0x56,0x03,0xd3,0xb2,0x43,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
160x31,0x21,0x0c,0x03,0x82,0xc0,0x40,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
170x21,0x01,0x0c,0x03,0xd4,0xd3,0x40,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
180x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
190x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
200x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/lib/rbcodec/codecs/libgme/ym2413_emu.c b/lib/rbcodec/codecs/libgme/ym2413_emu.c
new file mode 100644
index 0000000000..d9ada431ca
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ym2413_emu.c
@@ -0,0 +1,45 @@
1// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
2
3#include "ym2413_emu.h"
4
5void Ym2413_init( struct Ym2413_Emu* this )
6{
7 this->last_time = disabled_time; this->out = 0;
8}
9
10int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate )
11{
12 OPLL_new ( &this->opll, clock_rate, sample_rate );
13 OPLL_reset_patch( &this->opll, OPLL_2413_TONE );
14
15 Ym2413_reset( this );
16 return 0;
17}
18
19void Ym2413_reset( struct Ym2413_Emu* this )
20{
21 OPLL_reset( &this->opll );
22 OPLL_setMask( &this->opll, 0 );
23}
24
25void Ym2413_write( struct Ym2413_Emu* this, int addr, int data )
26{
27 OPLL_writeIO( &this->opll, 0, addr );
28 OPLL_writeIO( &this->opll, 1, data );
29}
30
31void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask )
32{
33 OPLL_setMask( &this->opll, mask );
34}
35
36void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out )
37{
38 while ( pair_count-- )
39 {
40 int s = OPLL_calc( &this->opll ) << 1;
41 out [0] = s;
42 out [1] = s;
43 out += 2;
44 }
45}
diff --git a/lib/rbcodec/codecs/libgme/ym2413_emu.h b/lib/rbcodec/codecs/libgme/ym2413_emu.h
new file mode 100644
index 0000000000..8f52b04fbd
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ym2413_emu.h
@@ -0,0 +1,61 @@
1// YM2413 FM sound chip emulator interface
2
3// Game_Music_Emu 0.6-pre
4#ifndef YM2413_EMU_H
5#define YM2413_EMU_H
6
7#include "blargg_common.h"
8#include "emu2413.h"
9
10enum { out_chan_count = 2 }; // stereo
11enum { channel_count = 14 };
12enum { disabled_time = -1 };
13
14struct Ym2413_Emu {
15 OPLL opll;
16
17 // Impl
18 int last_time;
19 short* out;
20};
21
22void Ym2413_init( struct Ym2413_Emu* this );
23
24static inline bool Ym2413_supported( void ) { return true; }
25
26// Sets output sample rate and chip clock rates, in Hz. Returns non-zero
27// if error.
28int Ym2413_set_rate( struct Ym2413_Emu* this, int sample_rate, int clock_rate );
29
30// Resets to power-up state
31void Ym2413_reset( struct Ym2413_Emu* this );
32
33// Mutes voice n if bit n (1 << n) of mask is set
34void Ym2413_mute_voices( struct Ym2413_Emu* this, int mask );
35
36// Writes data to addr
37void Ym2413_write( struct Ym2413_Emu* this, int addr, int data );
38
39// Runs and writes pair_count*2 samples to output
40void Ym2413_run( struct Ym2413_Emu* this, int pair_count, short* out );
41
42static inline void Ym2413_enable( struct Ym2413_Emu* this, bool b ) { this->last_time = b ? 0 : disabled_time; }
43static inline bool Ym2413_enabled( struct Ym2413_Emu* this ) { return this->last_time != disabled_time; }
44static inline void Ym2413_begin_frame( struct Ym2413_Emu* this, short* buf ) { this->out = buf; this->last_time = 0; }
45
46static inline int Ym2413_run_until( struct Ym2413_Emu* this, int time )
47{
48 int count = time - this->last_time;
49 if ( count > 0 )
50 {
51 if ( this->last_time < 0 )
52 return false;
53 this->last_time = time;
54 short* p = this->out;
55 this->out += count * out_chan_count;
56 Ym2413_run( this, count, p );
57 }
58 return true;
59}
60
61#endif
diff --git a/lib/rbcodec/codecs/libgme/ym2612_emu.c b/lib/rbcodec/codecs/libgme/ym2612_emu.c
new file mode 100644
index 0000000000..60df30a33c
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ym2612_emu.c
@@ -0,0 +1,1374 @@
1// Game_Music_Emu $vers. http://www.slack.net/~ant/
2
3// Based on Gens 2.10 ym2612.c
4
5#include <stdlib.h>
6#include <string.h>
7#include <limits.h>
8#include <stdio.h>
9#include <math.h>
10
11#include "ym2612_emu.h"
12
13/* Copyright (C) 2002 Stéphane Dallongeville (gens AT consolemul.com) */
14/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
15can redistribute it and/or modify it under the terms of the GNU Lesser
16General Public License as published by the Free Software Foundation; either
17version 2.1 of the License, or (at your option) any later version. This
18module is distributed in the hope that it will be useful, but WITHOUT ANY
19WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
21details. You should have received a copy of the GNU Lesser General Public
22License along with this module; if not, write to the Free Software Foundation,
23Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
24
25// This is mostly the original source in its C style and all.
26//
27// Somewhat optimized and simplified. Uses a template to generate the many
28// variants of Update_Chan. Rewrote header file. In need of full rewrite by
29// someone more familiar with FM sound and the YM2612. Has some inaccuracies
30// compared to the Sega Genesis sound, particularly being mixed at such a
31// high sample accuracy (the Genesis sounds like it has only 8 bit samples).
32// - Shay
33
34// Ported again to c by gama.
35// Not sure if performance is better than the original c version.
36
37#if !defined(YM2612_CALCUL_TABLES)
38 #include "ymtables.h"
39#endif
40
41#ifdef YM2612_CALCUL_TABLES
42 #define FREQ_TAB_LOOKUP g->LFO_FREQ_TAB
43 #define ENV_TAB_LOOKUP g->LFO_ENV_TAB
44#else
45 #define FREQ_TAB_LOOKUP lfo_freq_coeff
46 #define ENV_TAB_LOOKUP lfo_env_coeff
47#endif
48
49const int output_bits = 14;
50
51static const unsigned char DT_DEF_TAB [4 * 32] =
52{
53// FD = 0
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56
57// FD = 1
58 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
59 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
60
61// FD = 2
62 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
63 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
64
65// FD = 3
66 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
67 8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
68};
69
70static const unsigned char FKEY_TAB [16] =
71{
72 0, 0, 0, 0,
73 0, 0, 0, 1,
74 2, 3, 3, 3,
75 3, 3, 3, 3
76};
77
78static const unsigned char LFO_AMS_TAB [4] =
79{
80 31, 4, 1, 0
81};
82
83static const unsigned char LFO_FMS_TAB [8] =
84{
85 LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
86 LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
87 LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
88 LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
89};
90
91int in0, in1, in2, in3; // current phase calculation
92// int en0, en1, en2, en3; // current enveloppe calculation
93
94static inline void set_seg( struct slot_t* s, int seg )
95{
96 s->env_xor = 0;
97 s->env_max = INT_MAX;
98 s->SEG = seg;
99 if ( seg & 4 )
100 {
101 s->env_xor = ENV_MASK;
102 s->env_max = ENV_MASK;
103 }
104}
105
106static inline void YM2612_Special_Update(void) { }
107
108static void KEY_ON( struct channel_* ch, struct tables_t *g, int nsl )
109{
110 struct slot_t *SL = &(ch->SLOT [nsl]); // on recupere le bon pointeur de slot
111
112 if (SL->Ecurp == RELEASE) // la touche est-elle rel'chee ?
113 {
114 SL->Fcnt = 0;
115
116 // Fix Ecco 2 splash sound
117
118 SL->Ecnt = (g->DECAY_TO_ATTACK [g->ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
119 SL->ChgEnM = ~0;
120
121// SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
122// SL->Ecnt = 0;
123
124 SL->Einc = SL->EincA;
125 SL->Ecmp = ENV_DECAY;
126 SL->Ecurp = ATTACK;
127 }
128}
129
130
131static void KEY_OFF( struct channel_* ch, struct tables_t *g, int nsl )
132{
133 struct slot_t *SL = &(ch->SLOT [nsl]); // on recupere le bon pointeur de slot
134
135 if (SL->Ecurp != RELEASE) // la touche est-elle appuyee ?
136 {
137 if (SL->Ecnt < ENV_DECAY) // attack phase ?
138 {
139 SL->Ecnt = (g->ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
140 }
141
142 SL->Einc = SL->EincR;
143 SL->Ecmp = ENV_END;
144 SL->Ecurp = RELEASE;
145 }
146}
147
148
149static int SLOT_SET( struct Ym2612_Impl* impl, int Adr, int data )
150{
151 int nch = Adr & 3;
152 if ( nch == 3 )
153 return 1;
154
155 struct tables_t *g = &impl->g;
156 struct state_t *YM2612 = &impl->YM2612;
157 struct channel_* ch = &YM2612->CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
158 struct slot_t* sl = &ch->SLOT [(Adr >> 2) & 3];
159
160 switch ( Adr & 0xF0 )
161 {
162 case 0x30:
163 if ( (sl->MUL = (data & 0x0F)) != 0 ) sl->MUL <<= 1;
164 else sl->MUL = 1;
165
166 sl->DT = (int*) g->DT_TAB [(data >> 4) & 7];
167
168 ch->SLOT [0].Finc = -1;
169
170 break;
171
172 case 0x40:
173 sl->TL = data & 0x7F;
174
175 // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
176 YM2612_Special_Update();
177
178#if ((ENV_HBITS - 7) < 0)
179 sl->TLL = sl->TL >> (7 - ENV_HBITS);
180#else
181 sl->TLL = sl->TL << (ENV_HBITS - 7);
182#endif
183
184 break;
185
186 case 0x50:
187 sl->KSR_S = 3 - (data >> 6);
188
189 ch->SLOT [0].Finc = -1;
190
191 if (data &= 0x1F) sl->AR = (int*) &g->AR_TAB [data << 1];
192 else sl->AR = (int*) &g->NULL_RATE [0];
193
194 sl->EincA = sl->AR [sl->KSR];
195 if (sl->Ecurp == ATTACK) sl->Einc = sl->EincA;
196 break;
197
198 case 0x60:
199 if ( (sl->AMSon = (data & 0x80)) != 0 ) sl->AMS = ch->AMS;
200 else sl->AMS = 31;
201
202 if (data &= 0x1F) sl->DR = (int*) &g->DR_TAB [data << 1];
203 else sl->DR = (int*) &g->NULL_RATE [0];
204
205 sl->EincD = sl->DR [sl->KSR];
206 if (sl->Ecurp == DECAY) sl->Einc = sl->EincD;
207 break;
208
209 case 0x70:
210 if (data &= 0x1F) sl->SR = (int*) &g->DR_TAB [data << 1];
211 else sl->SR = (int*) &g->NULL_RATE [0];
212
213 sl->EincS = sl->SR [sl->KSR];
214 if ((sl->Ecurp == SUBSTAIN) && (sl->Ecnt < ENV_END)) sl->Einc = sl->EincS;
215 break;
216
217 case 0x80:
218 sl->SLL = g->SL_TAB [data >> 4];
219
220 sl->RR = (int*) &g->DR_TAB [((data & 0xF) << 2) + 2];
221
222 sl->EincR = sl->RR [sl->KSR];
223 if ((sl->Ecurp == RELEASE) && (sl->Ecnt < ENV_END)) sl->Einc = sl->EincR;
224 break;
225
226 case 0x90:
227 // SSG-EG envelope shapes :
228 /*
229 E At Al H
230
231 1 0 0 0 \\\\
232 1 0 0 1 \___
233 1 0 1 0 \/\/
234 1 0 1 1 \
235 1 1 0 0 ////
236 1 1 0 1 /
237 1 1 1 0 /\/\
238 1 1 1 1 /___
239
240 E = SSG-EG enable
241 At = Start negate
242 Al = Altern
243 H = Hold */
244
245 set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
246 break;
247 }
248
249 return 0;
250}
251
252
253static int CHANNEL_SET( struct state_t* YM2612, int Adr, int data )
254{
255 int num = Adr & 3;
256 if ( num == 3 )
257 return 1;
258
259 struct channel_* ch = &YM2612->CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
260
261 switch ( Adr & 0xFC )
262 {
263 case 0xA0:
264 YM2612_Special_Update();
265
266 ch->FNUM [0] = (ch->FNUM [0] & 0x700) + data;
267 ch->KC [0] = (ch->FOCT [0] << 2) | FKEY_TAB [ch->FNUM [0] >> 7];
268
269 ch->SLOT [0].Finc = -1;
270 break;
271
272 case 0xA4:
273 YM2612_Special_Update();
274
275 ch->FNUM [0] = (ch->FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
276 ch->FOCT [0] = (data & 0x38) >> 3;
277 ch->KC [0] = (ch->FOCT [0] << 2) | FKEY_TAB [ch->FNUM [0] >> 7];
278
279 ch->SLOT [0].Finc = -1;
280 break;
281
282 case 0xA8:
283 if ( Adr < 0x100 )
284 {
285 num++;
286
287 YM2612_Special_Update();
288
289 YM2612->CHANNEL [2].FNUM [num] = (YM2612->CHANNEL [2].FNUM [num] & 0x700) + data;
290 YM2612->CHANNEL [2].KC [num] = (YM2612->CHANNEL [2].FOCT [num] << 2) |
291 FKEY_TAB [YM2612->CHANNEL [2].FNUM [num] >> 7];
292
293 YM2612->CHANNEL [2].SLOT [0].Finc = -1;
294 }
295 break;
296
297 case 0xAC:
298 if ( Adr < 0x100 )
299 {
300 num++;
301
302 YM2612_Special_Update();
303
304 YM2612->CHANNEL [2].FNUM [num] = (YM2612->CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
305 YM2612->CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
306 YM2612->CHANNEL [2].KC [num] = (YM2612->CHANNEL [2].FOCT [num] << 2) |
307 FKEY_TAB [YM2612->CHANNEL [2].FNUM [num] >> 7];
308
309 YM2612->CHANNEL [2].SLOT [0].Finc = -1;
310 }
311 break;
312
313 case 0xB0:
314 if ( ch->ALGO != (data & 7) )
315 {
316 // Fix VectorMan 2 heli sound (level 1)
317 YM2612_Special_Update();
318
319 ch->ALGO = data & 7;
320
321 ch->SLOT [0].ChgEnM = 0;
322 ch->SLOT [1].ChgEnM = 0;
323 ch->SLOT [2].ChgEnM = 0;
324 ch->SLOT [3].ChgEnM = 0;
325 }
326
327 ch->FB = 9 - ((data >> 3) & 7); // Real thing ?
328
329// if (ch->FB = ((data >> 3) & 7)) ch->FB = 9 - ch->FB; // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
330// else ch->FB = 31;
331 break;
332
333 case 0xB4: {
334 YM2612_Special_Update();
335
336 ch->LEFT = 0 - ((data >> 7) & 1);
337 ch->RIGHT = 0 - ((data >> 6) & 1);
338
339 ch->AMS = LFO_AMS_TAB [(data >> 4) & 3];
340 ch->FMS = LFO_FMS_TAB [data & 7];
341
342 int i;
343 for ( i = 0; i < 4; i++ )
344 {
345 struct slot_t* sl = &ch->SLOT [i];
346 sl->AMS = (sl->AMSon ? ch->AMS : 31);
347 }
348 break;
349 }
350 }
351
352 return 0;
353}
354
355
356static int YM_SET( struct Ym2612_Impl* impl, int Adr, int data )
357{
358 struct state_t* YM2612 = &impl->YM2612;
359 struct tables_t* g = &impl->g;
360 switch ( Adr )
361 {
362 case 0x22:
363 if (data & 8) // LFO enable
364 {
365 // Cool Spot music 1, LFO modified severals time which
366 // distord the sound, have to check that on a real genesis...
367
368 g->LFOinc = g->LFO_INC_TAB [data & 7];
369 }
370 else
371 {
372 g->LFOinc = g->LFOcnt = 0;
373 }
374 break;
375
376 case 0x24:
377 YM2612->TimerA = (YM2612->TimerA & 0x003) | (((int) data) << 2);
378
379 if (YM2612->TimerAL != (1024 - YM2612->TimerA) << 12)
380 {
381 YM2612->TimerAcnt = YM2612->TimerAL = (1024 - YM2612->TimerA) << 12;
382 }
383 break;
384
385 case 0x25:
386 YM2612->TimerA = (YM2612->TimerA & 0x3FC) | (data & 3);
387
388 if (YM2612->TimerAL != (1024 - YM2612->TimerA) << 12)
389 {
390 YM2612->TimerAcnt = YM2612->TimerAL = (1024 - YM2612->TimerA) << 12;
391 }
392 break;
393
394 case 0x26:
395 YM2612->TimerB = data;
396
397 if (YM2612->TimerBL != (256 - YM2612->TimerB) << (4 + 12))
398 {
399 YM2612->TimerBcnt = YM2612->TimerBL = (256 - YM2612->TimerB) << (4 + 12);
400 }
401 break;
402
403 case 0x27:
404 // Parametre divers
405 // b7 = CSM MODE
406 // b6 = 3 slot mode
407 // b5 = reset b
408 // b4 = reset a
409 // b3 = timer enable b
410 // b2 = timer enable a
411 // b1 = load b
412 // b0 = load a
413
414 if ((data ^ YM2612->Mode) & 0x40)
415 {
416 // We changed the channel 2 mode, so recalculate phase step
417 // This fix the punch sound in Street of Rage 2
418
419 YM2612_Special_Update();
420
421 YM2612->CHANNEL [2].SLOT [0].Finc = -1; // recalculate phase step
422 }
423
424// if ((data & 2) && (YM2612->Status & 2)) YM2612->TimerBcnt = YM2612->TimerBL;
425// if ((data & 1) && (YM2612->Status & 1)) YM2612->TimerAcnt = YM2612->TimerAL;
426
427// YM2612->Status &= (~data >> 4); // Reset du Status au cas ou c'est demande
428 YM2612->Status &= (~data >> 4) & (data >> 2); // Reset Status
429
430 YM2612->Mode = data;
431 break;
432
433 case 0x28: {
434 int nch = data & 3;
435 if ( nch == 3 )
436 return 1;
437 if ( data & 4 )
438 nch += 3;
439 struct channel_* ch = &YM2612->CHANNEL [nch];
440
441 YM2612_Special_Update();
442
443 if (data & 0x10) KEY_ON(ch, g, S0); // On appuie sur la touche pour le slot 1
444 else KEY_OFF(ch, g, S0); // On rel'che la touche pour le slot 1
445 if (data & 0x20) KEY_ON(ch, g, S1); // On appuie sur la touche pour le slot 3
446 else KEY_OFF(ch, g, S1); // On rel'che la touche pour le slot 3
447 if (data & 0x40) KEY_ON(ch, g, S2); // On appuie sur la touche pour le slot 2
448 else KEY_OFF(ch, g, S2); // On rel'che la touche pour le slot 2
449 if (data & 0x80) KEY_ON(ch, g, S3); // On appuie sur la touche pour le slot 4
450 else KEY_OFF(ch, g, S3); // On rel'che la touche pour le slot 4
451 break;
452 }
453
454 case 0x2B:
455 if (YM2612->DAC ^ (data & 0x80)) YM2612_Special_Update();
456
457 YM2612->DAC = data & 0x80; // activation/desactivation du DAC
458 break;
459 }
460
461 return 0;
462}
463
464void impl_reset( struct Ym2612_Impl* impl );
465static void impl_set_rate( struct Ym2612_Impl* impl, int sample_rate, int clock_rate )
466{
467 assert( sample_rate );
468 assert( !clock_rate || clock_rate > sample_rate );
469
470 int i;
471
472 // 144 = 12 * (prescale * 2) = 12 * 6 * 2
473 // prescale set to 6 by default
474
475 int Frequency = (clock_rate ? (int)((FP_ONE_CLOCK * clock_rate) / sample_rate / 144) : (int)FP_ONE_CLOCK);
476 if ( abs( Frequency - FP_ONE_CLOCK ) < 1 )
477 Frequency = FP_ONE_CLOCK;
478 impl->YM2612.TimerBase = Frequency;
479
480 /* double Frequence = (double)Frequency / FP_ONE_CLOCK; */
481
482 // Tableau TL :
483 // [0 - 4095] = +output [4095 - ...] = +output overflow (fill with 0)
484 // [12288 - 16383] = -output [16384 - ...] = -output overflow (fill with 0)
485
486#ifdef YM2612_USE_TL_TAB
487 for ( i = 0; i < TL_LENGHT; i++ )
488 {
489 if (i >= PG_CUT_OFF) // YM2612 cut off sound after 78 dB (14 bits output ?)
490 {
491 impl->g.TL_TAB [TL_LENGHT + i] = impl->g.TL_TAB [i] = 0;
492 }
493 else
494 {
495 // Decibel -> Voltage
496 #ifdef YM2612_CALCUL_TABLES
497 impl->g.TL_TAB [i] = (int) (MAX_OUT / pow( 10.0, ENV_STEP / 20.0f * i ));
498 #else
499 impl->g.TL_TAB [i] = tl_coeff [i];
500 #endif
501 impl->g.TL_TAB [TL_LENGHT + i] = -impl->g.TL_TAB [i];
502 }
503 }
504#endif
505
506 // Tableau SIN :
507 // impl->g.SIN_TAB [x] [y] = sin(x) * y;
508 // x = phase and y = volume
509
510 impl->g.SIN_TAB [0] = impl->g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
511
512 for ( i = 1; i <= SIN_LENGHT / 4; i++ )
513 {
514 // Sinus in dB
515 #ifdef YM2612_CALCUL_TABLES
516 double x = 20 * log10( 1 / sin( 2.0 * PI * i / SIN_LENGHT ) ); // convert to dB
517
518 int j = (int) (x / ENV_STEP); // Get TL range
519
520 if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
521 #else
522 int j = sindb_coeff [i-1];
523 #endif
524
525 impl->g.SIN_TAB [i] = impl->g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
526 impl->g.SIN_TAB [(SIN_LENGHT / 2) + i] = impl->g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
527 }
528
529 #ifdef YM2612_CALCUL_TABLES
530 // Tableau LFO (LFO wav) :
531 for ( i = 0; i < LFO_LENGHT; i++ )
532 {
533 double x = 1 + sin( 2.0 * PI * i * (1.0 / LFO_LENGHT) ); // Sinus
534 x *= 11.8 / ENV_STEP / 2; // ajusted to MAX enveloppe modulation
535
536 impl->g.LFO_ENV_TAB [i] = (int) x;
537
538 x = sin( 2.0 * PI * i * (1.0 / LFO_LENGHT) ); // Sinus
539 x *= (1 << (LFO_HBITS - 1)) - 1;
540
541 impl->g.LFO_FREQ_TAB [i] = (int) x;
542 }
543 #endif
544
545 // Tableau Enveloppe :
546 // impl->g.ENV_TAB [0] -> impl->g.ENV_TAB [ENV_LENGHT - 1] = attack curve
547 // impl->g.ENV_TAB [ENV_LENGHT] -> impl->g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
548
549 for ( i = 0; i < ENV_LENGHT; i++ )
550 {
551 // Attack curve (x^8 - music level 2 Vectorman 2)
552 #if defined(ROCKBOX)
553 int k;
554 int prescale = (31 - 2*ENV_HBITS); /* used to gain higher precision */
555 int x = ENV_LENGHT * (1 << prescale);
556 for ( k = 0; k < 8; ++k)
557 {
558 x = ( x * ((ENV_LENGHT - 1) - i) ) / ENV_LENGHT;
559 }
560 x >>= prescale;
561 #else
562 double x = pow( ((ENV_LENGHT - 1) - i) / (double) ENV_LENGHT, 8.0 );
563 x *= ENV_LENGHT;
564 #endif
565
566 impl->g.ENV_TAB [i] = (int) x;
567
568 // Decay curve (just linear)
569 impl->g.ENV_TAB [ENV_LENGHT + i] = i;
570 }
571 for ( i = 0; i < 8; i++ )
572 impl->g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
573
574 impl->g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1; // for the stopped state
575
576 // Tableau pour la conversion Attack -> Decay and Decay -> Attack
577
578 int j = ENV_LENGHT - 1;
579 for ( i = 0; i < ENV_LENGHT; i++ )
580 {
581 while ( j && impl->g.ENV_TAB [j] < i )
582 j--;
583
584 impl->g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
585 }
586
587 // Tableau pour le Substain Level
588
589 for ( i = 0; i < 15; i++ )
590 {
591 int x = i * 3 * (int)( (1 << ENV_LBITS) / ENV_STEP); // 3 and not 6 (Mickey Mania first music for test)
592
593 impl->g.SL_TAB [i] = x + ENV_DECAY;
594 }
595
596 impl->g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
597
598 // Tableau Frequency Step
599
600 {
601 // * 1 / 2 because MUL = value * 2
602 #if SIN_LBITS + SIN_HBITS - (21 - 7) < 0
603 /* double const factor = Frequence / 2.0 / (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS)); */
604 int const factor = (int)(Frequency / 2 / (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS)) / FP_ONE_CLOCK);
605 #else
606 /* double const factor = Frequence / 2.0 * (1 << (SIN_LBITS + SIN_HBITS - (21 - 7))); */
607 int const factor = (int)(Frequency / 2 * (1 << (SIN_LBITS + SIN_HBITS - (21 - 7))) / FP_ONE_CLOCK);
608 #endif
609 for ( i = 0; i < 2048; i++ )
610 {
611 impl->g.FINC_TAB [i] = i * factor;
612 }
613 }
614
615 // Tableaux Attack & Decay Rate
616
617 for ( i = 0; i < 4; i++ )
618 {
619 impl->g.AR_TAB [i] = 0;
620 impl->g.DR_TAB [i] = 0;
621 }
622
623 for ( i = 0; i < 60; i++ )
624 {
625 long long x =
626 (4LL + ((i & 3))) * // bits 0-1 : 4*(x1.00, x1.25, x1.50, x1.75)
627 (ENV_LENGHT << ENV_LBITS) * // on ajuste pour le tableau impl->g.ENV_TAB
628 Frequency *
629 (1 << (i >> 2)) / // bits 2-5 : shift bits (x2^0 - x2^15)
630 FP_ONE_CLOCK / 4;
631
632 long long x_AR = x / AR_RATE;
633 long long x_DR = x / DR_RATE;
634
635 impl->g.AR_TAB [i + 4] = (unsigned int) ( x_AR > ((1LL<<32) - 1) ? ((1LL<<32) - 1) : x_AR );
636 impl->g.DR_TAB [i + 4] = (unsigned int) ( x_DR > ((1LL<<32) - 1) ? ((1LL<<32) - 1) : x_DR );
637 }
638
639 for ( i = 64; i < 96; i++ )
640 {
641 impl->g.AR_TAB [i] = impl->g.AR_TAB [63];
642 impl->g.DR_TAB [i] = impl->g.DR_TAB [63];
643
644 impl->g.NULL_RATE [i - 64] = 0;
645 }
646
647 for ( i = 96; i < 128; i++ )
648 impl->g.AR_TAB [i] = 0;
649
650 // Tableau Detune
651 {
652 #if SIN_LBITS + SIN_HBITS - 21 < 0
653 /* double const factor = 1.0 / (1 << (21 - SIN_LBITS - SIN_HBITS)) * Frequence; */
654 int const factor = Frequency / (1 << (21 - SIN_LBITS - SIN_HBITS)) / FP_ONE_CLOCK;
655 #else
656 /* double const factor = (1 << (SIN_LBITS + SIN_HBITS - 21)) * Frequence; */
657 int const factor = Frequency * (1 << (SIN_LBITS + SIN_HBITS - 21)) / FP_ONE_CLOCK;
658 #endif
659 for ( i = 0; i < 4; i++ )
660 {
661 int j;
662 for ( j = 0; j < 32; j++ )
663 {
664 /* double y = DT_DEF_TAB [(i << 5) + j] * factor; */
665 int y = DT_DEF_TAB [(i << 5) + j] * factor;
666
667 impl->g.DT_TAB [i + 0] [j] = (int) y;
668 impl->g.DT_TAB [i + 4] [j] = (int) -y;
669 }
670 }
671 }
672
673 // Tableau LFO
674 impl->g.LFO_INC_TAB [0] = (int) (3.98 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
675 impl->g.LFO_INC_TAB [1] = (int) (5.56 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
676 impl->g.LFO_INC_TAB [2] = (int) (6.02 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
677 impl->g.LFO_INC_TAB [3] = (int) (6.37 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
678 impl->g.LFO_INC_TAB [4] = (int) (6.88 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
679 impl->g.LFO_INC_TAB [5] = (int) (9.63 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
680 impl->g.LFO_INC_TAB [6] = (int) (48.1 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
681 impl->g.LFO_INC_TAB [7] = (int) (72.2 * (1 << (LFO_HBITS + LFO_LBITS))) / sample_rate;
682
683 impl_reset( impl );
684}
685
686const char* Ym2612_set_rate( struct Ym2612_Emu* this, int sample_rate, int clock_rate )
687{
688// Only set rates if necessary
689#if defined(ROCKBOX)
690 static int last_sample_rate = 0, last_clock_rate = 0;
691 if (last_sample_rate == sample_rate && last_clock_rate == clock_rate) return 0;
692#endif
693 memset( &this->impl.YM2612, 0, sizeof this->impl.YM2612 );
694 impl_set_rate( &this->impl, sample_rate, clock_rate );
695
696 return 0;
697}
698
699static inline void write0( struct Ym2612_Impl* impl, int opn_addr, int data )
700{
701 assert( (unsigned) data <= 0xFF );
702
703 if ( opn_addr < 0x30 )
704 {
705 impl->YM2612.REG [0] [opn_addr] = data;
706 YM_SET( impl, opn_addr, data );
707 }
708 else if ( impl->YM2612.REG [0] [opn_addr] != data )
709 {
710 impl->YM2612.REG [0] [opn_addr] = data;
711
712 if ( opn_addr < 0xA0 )
713 SLOT_SET( impl, opn_addr, data );
714 else
715 CHANNEL_SET( &impl->YM2612, opn_addr, data );
716 }
717}
718
719static inline void write1( struct Ym2612_Impl* impl, int opn_addr, int data )
720{
721 assert( (unsigned) data <= 0xFF );
722
723 if ( opn_addr >= 0x30 && impl->YM2612.REG [1] [opn_addr] != data )
724 {
725 impl->YM2612.REG [1] [opn_addr] = data;
726
727 if ( opn_addr < 0xA0 )
728 SLOT_SET( impl, opn_addr + 0x100, data );
729 else
730 CHANNEL_SET( &impl->YM2612, opn_addr + 0x100, data );
731 }
732}
733
734void impl_reset( struct Ym2612_Impl* impl )
735{
736 impl->g.LFOcnt = 0;
737 impl->YM2612.TimerA = 0;
738 impl->YM2612.TimerAL = 0;
739 impl->YM2612.TimerAcnt = 0;
740 impl->YM2612.TimerB = 0;
741 impl->YM2612.TimerBL = 0;
742 impl->YM2612.TimerBcnt = 0;
743 impl->YM2612.DAC = 0;
744
745 impl->YM2612.Status = 0;
746
747 int i;
748 for ( i = 0; i < ym2612_channel_count; i++ )
749 {
750 struct channel_* ch = &impl->YM2612.CHANNEL [i];
751
752 ch->LEFT = ~0;
753 ch->RIGHT = ~0;
754 ch->ALGO = 0;
755 ch->FB = 31;
756 ch->FMS = 0;
757 ch->AMS = 0;
758
759 int j;
760 for ( j = 0 ;j < 4 ; j++ )
761 {
762 ch->S0_OUT [j] = 0;
763 ch->FNUM [j] = 0;
764 ch->FOCT [j] = 0;
765 ch->KC [j] = 0;
766
767 ch->SLOT [j].Fcnt = 0;
768 ch->SLOT [j].Finc = 0;
769 ch->SLOT [j].Ecnt = ENV_END; // Put it at the end of Decay phase...
770 ch->SLOT [j].Einc = 0;
771 ch->SLOT [j].Ecmp = 0;
772 ch->SLOT [j].Ecurp = RELEASE;
773
774 ch->SLOT [j].ChgEnM = 0;
775 }
776 }
777
778 for ( i = 0; i < 0x100; i++ )
779 {
780 impl->YM2612.REG [0] [i] = -1;
781 impl->YM2612.REG [1] [i] = -1;
782 }
783
784 for ( i = 0xB6; i >= 0xB4; i-- )
785 {
786 write0( impl, i, 0xC0 );
787 write1( impl, i, 0xC0 );
788 }
789
790 for ( i = 0xB2; i >= 0x22; i-- )
791 {
792 write0( impl, i, 0 );
793 write1( impl, i, 0 );
794 }
795
796 write0( impl, 0x2A, 0x80 );
797}
798
799void Ym2612_reset( struct Ym2612_Emu* this )
800{
801 impl_reset( &this->impl );
802}
803
804void Ym2612_write0( struct Ym2612_Emu* this, int addr, int data )
805{
806 write0( &this->impl, addr, data );
807}
808
809void Ym2612_write1( struct Ym2612_Emu* this, int addr, int data )
810{
811 write1( &this->impl, addr, data );
812}
813
814void Ym2612_mute_voices( struct Ym2612_Emu* this, int mask ) { this->impl.mute_mask = mask; }
815
816static void update_envelope_( struct slot_t* sl )
817{
818 switch ( sl->Ecurp )
819 {
820 case 0:
821 // Env_Attack_Next
822
823 // Verified with Gynoug even in HQ (explode SFX)
824 sl->Ecnt = ENV_DECAY;
825
826 sl->Einc = sl->EincD;
827 sl->Ecmp = sl->SLL;
828 sl->Ecurp = DECAY;
829 break;
830
831 case 1:
832 // Env_Decay_Next
833
834 // Verified with Gynoug even in HQ (explode SFX)
835 sl->Ecnt = sl->SLL;
836
837 sl->Einc = sl->EincS;
838 sl->Ecmp = ENV_END;
839 sl->Ecurp = SUBSTAIN;
840 break;
841
842 case 2:
843 // Env_Substain_Next(slot_t *SL)
844 if (sl->SEG & 8) // SSG envelope type
845 {
846 int release = sl->SEG & 1;
847
848 if ( !release )
849 {
850 // re KEY ON
851
852 // sl->Fcnt = 0;
853 // sl->ChgEnM = ~0;
854
855 sl->Ecnt = 0;
856 sl->Einc = sl->EincA;
857 sl->Ecmp = ENV_DECAY;
858 sl->Ecurp = ATTACK;
859 }
860
861 set_seg( sl, (sl->SEG << 1) & 4 );
862
863 if ( !release )
864 break;
865 }
866 // fall through
867
868 case 3:
869 // Env_Release_Next
870 sl->Ecnt = ENV_END;
871 sl->Einc = 0;
872 sl->Ecmp = ENV_END + 1;
873 break;
874
875 // default: no op
876 }
877}
878
879static inline void update_envelope( struct slot_t* sl )
880{
881 int ecmp = sl->Ecmp;
882 if ( (sl->Ecnt += sl->Einc) >= ecmp )
883 update_envelope_( sl );
884}
885
886
887typedef void (*ym2612_update_chan_t)( struct tables_t*, struct channel_*, short*, int );
888
889#define GET_CURRENT_PHASE \
890int in0 = ch->SLOT[S0].Fcnt; \
891int in1 = ch->SLOT[S1].Fcnt; \
892int in2 = ch->SLOT[S2].Fcnt; \
893int in3 = ch->SLOT[S3].Fcnt; \
894
895#define GET_CURRENT_LFO \
896int YM2612_LFOinc = g->LFOinc; \
897int YM2612_LFOcnt = g->LFOcnt + YM2612_LFOinc;
898
899#define CALC_EN( x ) \
900 int temp##x = ENV_TAB [ch->SLOT [S##x].Ecnt >> ENV_LBITS] + ch->SLOT [S##x].TLL; \
901 int en##x = ((temp##x ^ ch->SLOT [S##x].env_xor) + (env_LFO >> ch->SLOT [S##x].AMS)) & \
902 ((temp##x - ch->SLOT [S##x].env_max) >> 31);
903
904#define GET_ENV \
905int const env_LFO = ENV_TAB_LOOKUP [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK]; \
906short const* const ENV_TAB = g->ENV_TAB; \
907CALC_EN( 0 ) \
908CALC_EN( 1 ) \
909CALC_EN( 2 ) \
910CALC_EN( 3 )
911
912#ifndef YM2612_USE_TL_TAB
913static inline int tl_level( int i )
914{
915 if (i >= (PG_CUT_OFF + TL_LENGHT)) {
916 return 0;
917 } else if (i >= TL_LENGHT) {
918 return -tl_coeff [i - TL_LENGHT];
919 } else if (i >= PG_CUT_OFF) {
920 return 0;
921 } else
922 return tl_coeff [i];
923}
924#define SINT( i, o ) (tl_level (g->SIN_TAB [(i)] + (o)))
925#else
926#define SINT( i, o ) (g->TL_TAB [g->SIN_TAB [(i)] + (o)])
927#endif
928
929#define DO_FEEDBACK \
930int CH_S0_OUT_0 = ch->S0_OUT [0]; \
931{ \
932 int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch->FB); \
933 CH_S0_OUT_1 = CH_S0_OUT_0; \
934 CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 ); \
935} \
936
937#define DO_LIMIT \
938CH_OUTd >>= MAX_OUT_BITS - output_bits + 2; \
939
940#define UPDATE_PHASE_CYCLE \
941unsigned freq_LFO = ((FREQ_TAB_LOOKUP [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] * \
942 ch->FMS) >> (LFO_HBITS - 1 + 1)) + (1 << (LFO_FMS_LBITS - 1)); \
943YM2612_LFOcnt += YM2612_LFOinc; \
944in0 += (ch->SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1); \
945in1 += (ch->SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1); \
946in2 += (ch->SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1); \
947in3 += (ch->SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
948
949#define UPDATE_ENV \
950int t0 = buf [0] + (CH_OUTd & ch->LEFT); \
951int t1 = buf [1] + (CH_OUTd & ch->RIGHT); \
952update_envelope( &ch->SLOT [0] ); \
953update_envelope( &ch->SLOT [1] ); \
954update_envelope( &ch->SLOT [2] ); \
955update_envelope( &ch->SLOT [3] );
956
957#define DO_OUTPUT_0 \
958ch->S0_OUT [0] = CH_S0_OUT_0; \
959buf [0] = t0; \
960buf [1] = t1; \
961buf += 2; \
962
963#define DO_OUTPUT_1 \
964ch->S0_OUT [1] = CH_S0_OUT_1;
965
966#define UPDATE_PHASE \
967ch->SLOT [S0].Fcnt = in0; \
968ch->SLOT [S1].Fcnt = in1; \
969ch->SLOT [S2].Fcnt = in2; \
970ch->SLOT [S3].Fcnt = in3;
971
972static void ym2612_update_chan0( struct tables_t* g, struct channel_* ch,
973 short* buf, int length )
974{
975 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
976 int CH_S0_OUT_1 = ch->S0_OUT [1];
977
978 GET_CURRENT_PHASE
979 GET_CURRENT_LFO
980
981 if ( !not_end )
982 return;
983
984 do
985 {
986 GET_ENV
987 DO_FEEDBACK
988
989 int CH_OUTd;
990 int temp = in1 + CH_S0_OUT_1;
991 temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
992 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
993 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
994
995 DO_LIMIT
996 UPDATE_PHASE_CYCLE
997 UPDATE_ENV
998 DO_OUTPUT_0
999 }
1000 while ( --length );
1001 DO_OUTPUT_1
1002 UPDATE_PHASE
1003}
1004
1005static void ym2612_update_chan1( struct tables_t* g, struct channel_* ch,
1006 short* buf, int length )
1007{
1008 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1009 int CH_S0_OUT_1 = ch->S0_OUT [1];
1010
1011 GET_CURRENT_PHASE
1012 GET_CURRENT_LFO
1013
1014 if ( !not_end )
1015 return;
1016
1017 do
1018 {
1019 GET_ENV
1020 DO_FEEDBACK
1021
1022 int CH_OUTd;
1023 int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
1024 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
1025 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1026
1027 DO_LIMIT
1028 UPDATE_PHASE_CYCLE
1029 UPDATE_ENV
1030 DO_OUTPUT_0
1031 }
1032 while ( --length );
1033 DO_OUTPUT_1
1034 UPDATE_PHASE
1035}
1036
1037static void ym2612_update_chan2( struct tables_t* g, struct channel_* ch,
1038 short* buf, int length )
1039{
1040 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1041 int CH_S0_OUT_1 = ch->S0_OUT [1];
1042
1043 GET_CURRENT_PHASE
1044 GET_CURRENT_LFO
1045
1046 if ( !not_end )
1047 return;
1048
1049 do
1050 {
1051 GET_ENV
1052 DO_FEEDBACK
1053
1054 int CH_OUTd;
1055 int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
1056 temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
1057 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1058
1059 DO_LIMIT
1060 UPDATE_PHASE_CYCLE
1061 UPDATE_ENV
1062 DO_OUTPUT_0
1063 }
1064 while ( --length );
1065 DO_OUTPUT_1
1066 UPDATE_PHASE
1067}
1068
1069static void ym2612_update_chan3( struct tables_t* g, struct channel_* ch,
1070 short* buf, int length )
1071{
1072 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1073 int CH_S0_OUT_1 = ch->S0_OUT [1];
1074
1075 GET_CURRENT_PHASE
1076 GET_CURRENT_LFO
1077
1078 if ( !not_end )
1079 return;
1080
1081 do
1082 {
1083 GET_ENV
1084 DO_FEEDBACK
1085
1086 int CH_OUTd;
1087 int temp = in1 + CH_S0_OUT_1;
1088 temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
1089 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1090 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
1091
1092 DO_LIMIT
1093 UPDATE_PHASE_CYCLE
1094 UPDATE_ENV
1095 DO_OUTPUT_0
1096 }
1097 while ( --length );
1098 DO_OUTPUT_1
1099 UPDATE_PHASE
1100}
1101
1102static void ym2612_update_chan4( struct tables_t* g, struct channel_* ch,
1103 short* buf, int length )
1104{
1105 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1106 not_end |= ch->SLOT [S1].Ecnt - ENV_END;
1107
1108 int CH_S0_OUT_1 = ch->S0_OUT [1];
1109
1110 GET_CURRENT_PHASE
1111 GET_CURRENT_LFO
1112
1113 if ( !not_end )
1114 return;
1115
1116 do
1117 {
1118 GET_ENV
1119 DO_FEEDBACK
1120
1121 int CH_OUTd;
1122 int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1123 CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
1124 SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
1125
1126 DO_LIMIT
1127 UPDATE_PHASE_CYCLE
1128 UPDATE_ENV
1129 DO_OUTPUT_0
1130 }
1131 while ( --length );
1132 DO_OUTPUT_1
1133 UPDATE_PHASE
1134}
1135
1136static void ym2612_update_chan5( struct tables_t* g, struct channel_* ch,
1137 short* buf, int length )
1138{
1139 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1140 not_end |= ch->SLOT [S2].Ecnt - ENV_END;
1141 not_end |= ch->SLOT [S1].Ecnt - ENV_END;
1142
1143 int CH_S0_OUT_1 = ch->S0_OUT [1];
1144
1145 GET_CURRENT_PHASE
1146 GET_CURRENT_LFO
1147
1148 if ( !not_end )
1149 return;
1150
1151 do
1152 {
1153 GET_ENV
1154 DO_FEEDBACK
1155
1156 int CH_OUTd;
1157 int temp = CH_S0_OUT_1;
1158 CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
1159 SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
1160 SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
1161
1162 DO_LIMIT
1163 UPDATE_PHASE_CYCLE
1164 UPDATE_ENV
1165 DO_OUTPUT_0
1166 }
1167 while ( --length );
1168 DO_OUTPUT_1
1169 UPDATE_PHASE
1170}
1171
1172static void ym2612_update_chan6( struct tables_t* g, struct channel_* ch,
1173 short* buf, int length )
1174{
1175 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1176 not_end |= ch->SLOT [S2].Ecnt - ENV_END;
1177 not_end |= ch->SLOT [S1].Ecnt - ENV_END;
1178
1179 int CH_S0_OUT_1 = ch->S0_OUT [1];
1180
1181 GET_CURRENT_PHASE
1182 GET_CURRENT_LFO
1183
1184 if ( !not_end )
1185 return;
1186
1187 do
1188 {
1189 GET_ENV
1190 DO_FEEDBACK
1191
1192 int CH_OUTd;
1193 CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
1194 SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
1195 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
1196
1197 DO_LIMIT
1198 UPDATE_PHASE_CYCLE
1199 UPDATE_ENV
1200 DO_OUTPUT_0
1201 }
1202 while ( --length );
1203 DO_OUTPUT_1
1204 UPDATE_PHASE
1205}
1206
1207static void ym2612_update_chan7( struct tables_t* g, struct channel_* ch,
1208 short* buf, int length )
1209{
1210 int not_end = ch->SLOT [S3].Ecnt - ENV_END;
1211 not_end |= ch->SLOT [S0].Ecnt - ENV_END;
1212 not_end |= ch->SLOT [S2].Ecnt - ENV_END;
1213 not_end |= ch->SLOT [S1].Ecnt - ENV_END;
1214
1215 int CH_S0_OUT_1 = ch->S0_OUT [1];
1216
1217 GET_CURRENT_PHASE
1218 GET_CURRENT_LFO
1219
1220 if ( !not_end )
1221 return;
1222
1223 do
1224 {
1225 GET_ENV
1226 DO_FEEDBACK
1227
1228 int CH_OUTd;
1229 CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
1230 SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
1231 SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
1232
1233 DO_LIMIT
1234 UPDATE_PHASE_CYCLE
1235 UPDATE_ENV
1236 DO_OUTPUT_0
1237 }
1238 while ( --length );
1239 DO_OUTPUT_1
1240 UPDATE_PHASE
1241}
1242
1243static void (*UPDATE_CHAN[8])(struct tables_t* g, struct channel_* ch,
1244 short* buf, int length) =
1245{
1246 (void *)ym2612_update_chan0,
1247 (void *)ym2612_update_chan1,
1248 (void *)ym2612_update_chan2,
1249 (void *)ym2612_update_chan3,
1250 (void *)ym2612_update_chan4,
1251 (void *)ym2612_update_chan5,
1252 (void *)ym2612_update_chan6,
1253 (void *)ym2612_update_chan7
1254};
1255
1256static void run_timer( struct Ym2612_Impl* impl, int length )
1257{
1258 int const step = 6;
1259 int remain = length;
1260 do
1261 {
1262 int n = step;
1263 if ( n > remain )
1264 n = remain;
1265 remain -= n;
1266
1267 int i = n * impl->YM2612.TimerBase;
1268 if (impl->YM2612.Mode & 1) // Timer A ON ?
1269 {
1270 // if ((impl->YM2612.TimerAcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
1271 if ((impl->YM2612.TimerAcnt -= i) <= 0)
1272 {
1273 // timer a overflow
1274
1275 impl->YM2612.Status |= (impl->YM2612.Mode & 0x04) >> 2;
1276 impl->YM2612.TimerAcnt += impl->YM2612.TimerAL;
1277
1278 if (impl->YM2612.Mode & 0x80)
1279 {
1280 KEY_ON( &impl->YM2612.CHANNEL [2], &impl->g, 0 );
1281 KEY_ON( &impl->YM2612.CHANNEL [2], &impl->g, 1 );
1282 KEY_ON( &impl->YM2612.CHANNEL [2], &impl->g, 2 );
1283 KEY_ON( &impl->YM2612.CHANNEL [2], &impl->g, 3 );
1284 }
1285 }
1286 }
1287
1288 if (impl->YM2612.Mode & 2) // Timer B ON ?
1289 {
1290 // if ((impl->YM2612.TimerBcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
1291 if ((impl->YM2612.TimerBcnt -= i) <= 0)
1292 {
1293 // timer b overflow
1294 impl->YM2612.Status |= (impl->YM2612.Mode & 0x08) >> 2;
1295 impl->YM2612.TimerBcnt += impl->YM2612.TimerBL;
1296 }
1297 }
1298 }
1299 while ( remain > 0 );
1300}
1301
1302static void impl_run( struct Ym2612_Impl* impl, int pair_count, short out [] )
1303{
1304 if ( pair_count <= 0 )
1305 return;
1306
1307 if ( impl->YM2612.Mode & 3 )
1308 run_timer( impl, pair_count );
1309
1310 // Mise à jour des pas des compteurs-frequences s'ils ont ete modifies
1311
1312 int chi;
1313 for ( chi = 0; chi < ym2612_channel_count; chi++ )
1314 {
1315 struct channel_* ch = &impl->YM2612.CHANNEL [chi];
1316 if ( ch->SLOT [0].Finc != -1 )
1317 continue;
1318
1319 int i2 = 0;
1320 if ( chi == 2 && (impl->YM2612.Mode & 0x40) )
1321 i2 = 2;
1322
1323 int i;
1324 for ( i = 0; i < 4; i++ )
1325 {
1326 // static int seq [4] = { 2, 1, 3, 0 };
1327 // if ( i2 ) i2 = seq [i];
1328
1329 struct slot_t* sl = &ch->SLOT [i];
1330 int finc = impl->g.FINC_TAB [ch->FNUM [i2]] >> (7 - ch->FOCT [i2]);
1331 int ksr = ch->KC [i2] >> sl->KSR_S; // keycode attenuation
1332 sl->Finc = (finc + sl->DT [ch->KC [i2]]) * sl->MUL;
1333 if (sl->KSR != ksr) // si le KSR a change alors
1334 { // les differents taux pour l'enveloppe sont mis à jour
1335 sl->KSR = ksr;
1336
1337 sl->EincA = sl->AR [ksr];
1338 sl->EincD = sl->DR [ksr];
1339 sl->EincS = sl->SR [ksr];
1340 sl->EincR = sl->RR [ksr];
1341
1342 if (sl->Ecurp == ATTACK)
1343 {
1344 sl->Einc = sl->EincA;
1345 }
1346 else if (sl->Ecurp == DECAY)
1347 {
1348 sl->Einc = sl->EincD;
1349 }
1350 else if (sl->Ecnt < ENV_END)
1351 {
1352 if (sl->Ecurp == SUBSTAIN)
1353 sl->Einc = sl->EincS;
1354 else if (sl->Ecurp == RELEASE)
1355 sl->Einc = sl->EincR;
1356 }
1357 }
1358
1359 if ( i2 )
1360 i2 = (i2 ^ 2) ^ (i2 >> 1);
1361 }
1362 }
1363
1364 int i;
1365 for ( i = 0; i < ym2612_channel_count; i++ )
1366 {
1367 if ( !(impl->mute_mask & (1 << i)) && (i != 5 || !impl->YM2612.DAC) )
1368 UPDATE_CHAN [impl->YM2612.CHANNEL [i].ALGO]( &impl->g, &impl->YM2612.CHANNEL [i], out, pair_count );
1369 }
1370
1371 impl->g.LFOcnt += impl->g.LFOinc * pair_count;
1372}
1373
1374void Ym2612_run( struct Ym2612_Emu* this, int pair_count, short out [] ) { impl_run( &this->impl, pair_count, out ); }
diff --git a/lib/rbcodec/codecs/libgme/ym2612_emu.h b/lib/rbcodec/codecs/libgme/ym2612_emu.h
new file mode 100644
index 0000000000..146d92a0a3
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ym2612_emu.h
@@ -0,0 +1,248 @@
1// YM2612 FM sound chip emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef YM2612_EMU_H
5#define YM2612_EMU_H
6
7#include "blargg_common.h"
8
9#if !defined(ROCKBOX)
10 #define YM2612_CALCUL_TABLES
11#endif
12
13#if MEMORYSIZE > 2
14 #define YM2612_USE_TL_TAB
15#endif
16
17enum { ym2612_out_chan_count = 2 }; // stereo
18enum { ym2612_channel_count = 6 };
19enum { ym2612_disabled_time = -1 };
20
21struct slot_t
22{
23 const int *DT; // parametre detune
24 int MUL; // parametre "multiple de frequence"
25 int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
26 int TLL; // Total Level ajusted
27 int SLL; // Sustin Level (ajusted) = volume où l'enveloppe termine sa premiere phase de regression
28 int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
29 int KSR; // Key Scale Rate = cette valeur est calculee par rapport à la frequence actuelle, elle va influer
30 // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
31 int SEG; // Type enveloppe SSG
32 int env_xor;
33 int env_max;
34
35 const int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR [KSR])
36 const int *DR; // Decay Rate (table pointeur) = Taux pour la regression (DR [KSR])
37 const int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR [KSR])
38 const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR [KSR])
39 int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN [Finc >> 16])
40 int Finc; // frequency step = pas d'incrementation du compteur-frequence
41 // plus le pas est grand, plus la frequence est aïgu (ou haute)
42 int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
43 // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
44 // en fonction de la valeur de cette variable, on va appeler une fonction permettant
45 // de mettre à jour l'enveloppe courante.
46 int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir où l'on se trouve dans l'enveloppe
47 int Einc; // Envelope step courant
48 int Ecmp; // Envelope counter limite pour la prochaine phase
49 int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
50 // cette valeur est egal à AR [KSR]
51 int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
52 // cette valeur est egal à DR [KSR]
53 int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
54 // cette valeur est egal à SR [KSR]
55 int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
56 // cette valeur est egal à RR [KSR]
57 int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot à l'entree
58 // d'un autre ou carrement à la sortie de la voie
59 int INd; // input data of the slot = donnees en entree du slot
60 int ChgEnM; // Change envelop mask.
61 int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
62 int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
63};
64
65struct channel_
66{
67 int S0_OUT [4]; // anciennes sorties slot 0 (pour le feed back)
68 int LEFT; // LEFT enable flag
69 int RIGHT; // RIGHT enable flag
70 int ALGO; // Algorythm = determine les connections entre les operateurs
71 int FB; // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
72 int FMS; // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
73 int AMS; // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
74 int FNUM [4]; // hauteur frequence de la voie (+ 3 pour le mode special)
75 int FOCT [4]; // octave de la voie (+ 3 pour le mode special)
76 int KC [4]; // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
77 struct slot_t SLOT [4]; // four slot.operators = les 4 slots de la voie
78 int FFlag; // Frequency step recalculation flag
79};
80
81struct state_t
82{
83 int TimerBase; // TimerBase calculation
84 int Status; // YM2612 Status (timer overflow)
85 int TimerA; // timerA limit = valeur jusqu'à laquelle le timer A doit compter
86 int TimerAL;
87 int TimerAcnt; // timerA counter = valeur courante du Timer A
88 int TimerB; // timerB limit = valeur jusqu'à laquelle le timer B doit compter
89 int TimerBL;
90 int TimerBcnt; // timerB counter = valeur courante du Timer B
91 int Mode; // Mode actuel des voie 3 et 6 (normal / special)
92 int DAC; // DAC enabled flag
93 struct channel_ CHANNEL [ym2612_channel_count]; // Les 6 voies du YM2612
94 int REG [2] [0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
95 // cela nous rend le debuggage plus facile
96};
97
98#undef PI
99#define PI 3.14159265358979323846
100
101#define ATTACK 0
102#define DECAY 1
103#define SUBSTAIN 2
104#define RELEASE 3
105
106// SIN_LBITS <= 16
107// LFO_HBITS <= 16
108// (SIN_LBITS + SIN_HBITS) <= 26
109// (ENV_LBITS + ENV_HBITS) <= 28
110// (LFO_LBITS + LFO_HBITS) <= 28
111
112#define SIN_HBITS 12 // Sinus phase counter int part
113#define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting)
114
115#if (SIN_LBITS > 16)
116#define SIN_LBITS 16 // Can't be greater than 16 bits
117#endif
118
119#define ENV_HBITS 12 // Env phase counter int part
120#define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting)
121
122#define LFO_HBITS 10 // LFO phase counter int part
123#define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting)
124
125#define SIN_LENGHT (1 << SIN_HBITS)
126#define ENV_LENGHT (1 << ENV_HBITS)
127#define LFO_LENGHT (1 << LFO_HBITS)
128
129#define TL_LENGHT (ENV_LENGHT * 3) // Env + TL scaling + LFO
130
131#define SIN_MASK (SIN_LENGHT - 1)
132#define ENV_MASK (ENV_LENGHT - 1)
133#define LFO_MASK (LFO_LENGHT - 1)
134
135#define ENV_STEP (96.0 / ENV_LENGHT) // ENV_MAX = 96 dB
136
137#define ENV_ATTACK ((ENV_LENGHT * 0) << ENV_LBITS)
138#define ENV_DECAY ((ENV_LENGHT * 1) << ENV_LBITS)
139#define ENV_END ((ENV_LENGHT * 2) << ENV_LBITS)
140
141#define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4
142#define MAX_OUT ((1 << MAX_OUT_BITS) - 1)
143
144#define PG_CUT_OFF ((int) (78.0 / ENV_STEP))
145//#define ENV_CUT_OFF ((int) (68.0 / ENV_STEP))
146
147#define AR_RATE 399128
148#define DR_RATE 5514396
149
150//#define AR_RATE 426136
151//#define DR_RATE (AR_RATE * 12)
152
153#define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1)
154#define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
155
156#define S0 0 // Stupid typo of the YM2612
157#define S1 2
158#define S2 1
159#define S3 3
160
161struct tables_t
162{
163 short SIN_TAB [SIN_LENGHT]; // SINUS TABLE (offset into TL TABLE)
164 int LFOcnt; // LFO counter = compteur-frequence pour le LFO
165 int LFOinc; // LFO step counter = pas d'incrementation du compteur-frequence du LFO
166 // plus le pas est grand, plus la frequence est grande
167 unsigned int AR_TAB [128]; // Attack rate table
168 unsigned int DR_TAB [96]; // Decay rate table
169 unsigned int DT_TAB [8] [32]; // Detune table
170 unsigned int SL_TAB [16]; // Substain level table
171 unsigned int NULL_RATE [32]; // Table for NULL rate
172 int LFO_INC_TAB [8]; // LFO step table
173
174 short ENV_TAB [2 * ENV_LENGHT + 8]; // ENV CURVE TABLE (attack & decay)
175#ifdef YM2612_CALCUL_TABLES
176 short LFO_ENV_TAB [LFO_LENGHT]; // LFO AMS TABLE (adjusted for 11.8 dB)
177 short LFO_FREQ_TAB [LFO_LENGHT]; // LFO FMS TABLE
178#endif
179#ifdef YM2612_USE_TL_TAB
180 int TL_TAB [TL_LENGHT * 2]; // TOTAL LEVEL TABLE (positif and minus)
181#endif
182 unsigned int DECAY_TO_ATTACK [ENV_LENGHT]; // Conversion from decay to attack phase
183 unsigned int FINC_TAB [2048]; // Frequency step table
184};
185
186struct Ym2612_Impl
187{
188 struct state_t YM2612;
189 int mute_mask;
190 struct tables_t g;
191};
192
193void impl_reset( struct Ym2612_Impl* impl );
194
195struct Ym2612_Emu {
196 struct Ym2612_Impl impl;
197
198 // Impl
199 int last_time;
200 int sample_rate;
201 int clock_rate;
202 short* out;
203};
204
205static inline void Ym2612_init( struct Ym2612_Emu* this_ )
206{
207 this_->last_time = ym2612_disabled_time; this_->out = 0;
208 this_->impl.mute_mask = 0;
209}
210
211// Sets sample rate and chip clock rate, in Hz. Returns non-zero
212// if error. If clock_rate=0, uses sample_rate*144
213const char* Ym2612_set_rate( struct Ym2612_Emu* this_, int sample_rate, int clock_rate );
214
215// Resets to power-up state
216void Ym2612_reset( struct Ym2612_Emu* this_ );
217
218// Mutes voice n if bit n (1 << n) of mask is set
219void Ym2612_mute_voices( struct Ym2612_Emu* this_, int mask );
220
221// Writes addr to register 0 then data to register 1
222void Ym2612_write0( struct Ym2612_Emu* this_, int addr, int data );
223
224// Writes addr to register 2 then data to register 3
225void Ym2612_write1( struct Ym2612_Emu* this_, int addr, int data );
226
227// Runs and adds pair_count*2 samples into current output buffer contents
228void Ym2612_run( struct Ym2612_Emu* this_, int pair_count, short* out );
229
230static inline void Ym2612_enable( struct Ym2612_Emu* this_, bool b ) { this_->last_time = b ? 0 : ym2612_disabled_time; }
231static inline bool Ym2612_enabled( struct Ym2612_Emu* this_ ) { return this_->last_time != ym2612_disabled_time; }
232static inline void Ym2612_begin_frame( struct Ym2612_Emu* this_, short* buf ) { this_->out = buf; this_->last_time = 0; }
233
234static inline int Ym2612_run_until( struct Ym2612_Emu* this_, int time )
235{
236 int count = time - this_->last_time;
237 if ( count > 0 )
238 {
239 if ( this_->last_time < 0 )
240 return false;
241 this_->last_time = time;
242 short* p = this_->out;
243 this_->out += count * ym2612_out_chan_count;
244 Ym2612_run( this_, count, p );
245 }
246 return true;
247}
248#endif
diff --git a/lib/rbcodec/codecs/libgme/ymtables.h b/lib/rbcodec/codecs/libgme/ymtables.h
new file mode 100644
index 0000000000..c1619026b2
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/ymtables.h
@@ -0,0 +1,559 @@
1#ifndef _EMUTABLES_H_
2#define _EMUTABLES_H_
3
4/* Precompiled ym2612 tables for use in Rockbox */
5
6static const int tl_coeff[] = {
7 268435455, 267712100, 266990695, 266271234, 265553712, 264838123, 264124462, 263412725, 262702906, 261994999, 261289000,
8 260584903, 259882704, 259182396, 258483976, 257787438, 257092777, 256399988, 255709066, 255020006, 254332802, 253647450,
9 252963945, 252282282, 251602456, 250924462, 250248294, 249573949, 248901421, 248230705, 247561797, 246894691, 246229383,
10 245565867, 244904140, 244244195, 243586029, 242929637, 242275013, 241622154, 240971053, 240321708, 239674112, 239028261,
11 238384150, 237741775, 237101131, 236462214, 235825018, 235189539, 234555773, 233923714, 233293359, 232664702, 232037740,
12 231412466, 230788878, 230166970, 229546738, 228928178, 228311284, 227696052, 227082479, 226470558, 225860287, 225251660,
13 224644674, 224039323, 223435603, 222833510, 222233039, 221634187, 221036948, 220441319, 219847295, 219254871, 218664044,
14 218074809, 217487162, 216901098, 216316614, 215733704, 215152366, 214572594, 213994384, 213417732, 212842635, 212269087,
15 211697084, 211126623, 210557699, 209990308, 209424446, 208860109, 208297293, 207735993, 207176206, 206617927, 206061153,
16 205505879, 204952102, 204399816, 203849019, 203299706, 202751873, 202205517, 201660633, 201117217, 200575266, 200034774,
17 199495740, 198958158, 198422024, 197887335, 197354088, 196822277, 196291899, 195762950, 195235427, 194709325, 194184641,
18 193661370, 193139510, 192619056, 192100005, 191582352, 191066094, 190551228, 190037748, 189525653, 189014937, 188505598,
19 187997631, 187491033, 186985800, 186481928, 185979414, 185478255, 184978446, 184479983, 183982864, 183487085, 182992641,
20 182499530, 182007748, 181517291, 181028155, 180540338, 180053835, 179568643, 179084759, 178602178, 178120898, 177640915,
21 177162225, 176684825, 176208712, 175733881, 175260330, 174788055, 174317053, 173847320, 173378853, 172911648, 172445702,
22 171981012, 171517574, 171055385, 170594441, 170134740, 169676277, 169219049, 168763054, 168308287, 167854746, 167402427,
23 166951327, 166501443, 166052770, 165605307, 165159050, 164713995, 164270139, 163827480, 163386013, 162945736, 162506646,
24 162068738, 161632011, 161196460, 160762083, 160328877, 159896838, 159465963, 159036250, 158607694, 158180293, 157754044,
25 157328943, 156904988, 156482176, 156060502, 155639965, 155220562, 154802288, 154385142, 153969119, 153554218, 153140435,
26 152727766, 152316210, 151905763, 151496422, 151088184, 150681046, 150275005, 149870058, 149466203, 149063435, 148661753,
27 148261154, 147861634, 147463190, 147065821, 146669522, 146274291, 145880125, 145487021, 145094976, 144703988, 144314054,
28 143925170, 143537334, 143150543, 142764795, 142380086, 141996414, 141613775, 141232168, 140851589, 140472035, 140093505,
29 139715994, 139339501, 138964022, 138589555, 138216097, 137843646, 137472198, 137101751, 136732302, 136363849, 135996388,
30 135629918, 135264436, 134899938, 134536423, 134173887, 133812328, 133451743, 133092130, 132733486, 132375808, 132019095,
31 131663342, 131308548, 130954711, 130601826, 130249893, 129898908, 129548869, 129199773, 128851618, 128504401, 128158119,
32 127812771, 127468353, 127124864, 126782300, 126440659, 126099939, 125760137, 125421250, 125083277, 124746214, 124410060,
33 124074812, 123740467, 123407023, 123074477, 122742828, 122412072, 122082208, 121753232, 121425143, 121097939, 120771615,
34 120446172, 120121605, 119797912, 119475092, 119153142, 118832060, 118511843, 118192488, 117873994, 117556359, 117239579,
35 116923653, 116608578, 116294353, 115980974, 115668439, 115356747, 115045894, 114735880, 114426700, 114118354, 113810839,
36 113504152, 113198292, 112893256, 112589042, 112285648, 111983071, 111681310, 111380362, 111080225, 110780896, 110482375,
37 110184657, 109887742, 109591627, 109296310, 109001789, 108708061, 108415125, 108122978, 107831619, 107541044, 107251253,
38 106962243, 106674011, 106386556, 106099876, 105813968, 105528830, 105244461, 104960859, 104678020, 104395944, 104114628,
39 103834069, 103554267, 103275219, 102996923, 102719377, 102442578, 102166526, 101891217, 101616650, 101342823, 101069734,
40 100797381, 100525762, 100254875, 99984718, 99715288, 99446585, 99178606, 98911349, 98644812, 98378993, 98113891,
41 97849503, 97585828, 97322863, 97060606, 96799057, 96538212, 96278070, 96018629, 95759887, 95501842, 95244493,
42 94987837, 94731873, 94476599, 94222012, 93968112, 93714895, 93462361, 93210508, 92959333, 92708835, 92459012,
43 92209863, 91961384, 91713575, 91466434, 91219959, 90974149, 90729000, 90484512, 90240683, 89997511, 89754994,
44 89513131, 89271920, 89031358, 88791445, 88552178, 88313556, 88075578, 87838240, 87601542, 87365481, 87130057,
45 86895267, 86661110, 86427584, 86194687, 85962418, 85730775, 85499756, 85269359, 85039583, 84810427, 84581888,
46 84353965, 84126656, 83899959, 83673874, 83448397, 83223528, 82999266, 82775607, 82552551, 82330096, 82108241,
47 81886984, 81666322, 81446256, 81226782, 81007900, 80789608, 80571904, 80354786, 80138254, 79922305, 79706938,
48 79492151, 79277943, 79064313, 78851258, 78638777, 78426868, 78215531, 78004763, 77794564, 77584930, 77375862,
49 77167357, 76959413, 76752031, 76545207, 76338940, 76133229, 75928072, 75723469, 75519416, 75315914, 75112960,
50 74910552, 74708690, 74507373, 74306597, 74106363, 73906668, 73707512, 73508892, 73310807, 73113256, 72916237,
51 72719749, 72523791, 72328361, 72133457, 71939079, 71745225, 71551892, 71359081, 71166789, 70975016, 70783759,
52 70593018, 70402791, 70213076, 70023872, 69835179, 69646994, 69459315, 69272143, 69085475, 68899310, 68713647,
53 68528484, 68343820, 68159653, 67975983, 67792808, 67610127, 67427937, 67246239, 67065030, 66884310, 66704076,
54 66524328, 66345065, 66166285, 65987986, 65810168, 65632829, 65455968, 65279583, 65103674, 64928239, 64753277,
55 64578786, 64404765, 64231213, 64058129, 63885511, 63713359, 63541670, 63370444, 63199679, 63029375, 62859529,
56 62690141, 62521210, 62352734, 62184711, 62017142, 61850024, 61683357, 61517138, 61351368, 61186044, 61021166,
57 60856731, 60692741, 60529192, 60366083, 60203414, 60041184, 59879391, 59718034, 59557111, 59396622, 59236566,
58 59076941, 58917746, 58758980, 58600642, 58442730, 58285245, 58128183, 57971545, 57815329, 57659533, 57504158,
59 57349201, 57194662, 57040539, 56886832, 56733539, 56580659, 56428190, 56276133, 56124486, 55973247, 55822415,
60 55671990, 55521971, 55372355, 55223143, 55074333, 54925924, 54777915, 54630305, 54483092, 54336276, 54189856,
61 54043830, 53898198, 53752959, 53608110, 53463652, 53319583, 53175903, 53032610, 52889702, 52747180, 52605042,
62 52463287, 52321914, 52180922, 52040310, 51900076, 51760221, 51620743, 51481640, 51342912, 51204558, 51066577,
63 50928968, 50791729, 50654860, 50518360, 50382228, 50246463, 50111064, 49976029, 49841359, 49707051, 49573105,
64 49439520, 49306295, 49173429, 49040922, 48908771, 48776976, 48645537, 48514451, 48383719, 48253339, 48123311,
65 47993633, 47864304, 47735324, 47606691, 47478405, 47350465, 47222869, 47095618, 46968709, 46842142, 46715916,
66 46590031, 46464484, 46339276, 46214406, 46089871, 45965673, 45841809, 45718279, 45595082, 45472216, 45349682,
67 45227478, 45105603, 44984057, 44862838, 44741946, 44621380, 44501139, 44381221, 44261627, 44142355, 44023404,
68 43904774, 43786464, 43668472, 43550798, 43433442, 43316402, 43199677, 43083266, 42967170, 42851386, 42735914,
69 42620753, 42505903, 42391362, 42277130, 42163206, 42049588, 41936277, 41823271, 41710570, 41598172, 41486077,
70 41374285, 41262793, 41151602, 41040711, 40930118, 40819823, 40709826, 40600125, 40490720, 40381609, 40272793,
71 40164269, 40056039, 39948099, 39840451, 39733093, 39626024, 39519243, 39412751, 39306545, 39200625, 39094991,
72 38989642, 38884576, 38779794, 38675294, 38571075, 38467138, 38363480, 38260102, 38157002, 38054180, 37951635,
73 37849367, 37747374, 37645656, 37544212, 37443042, 37342144, 37241518, 37141163, 37041078, 36941264, 36841718,
74 36742440, 36643430, 36544687, 36446210, 36347998, 36250051, 36152368, 36054948, 35957790, 35860895, 35764260,
75 35667886, 35571772, 35475916, 35380319, 35284980, 35189897, 35095071, 35000500, 34906184, 34812122, 34718314,
76 34624758, 34531454, 34438402, 34345601, 34253050, 34160748, 34068695, 33976890, 33885332, 33794021, 33702956,
77 33612137, 33521562, 33431231, 33341144, 33251299, 33161697, 33072336, 32983216, 32894336, 32805695, 32717294,
78 32629130, 32541204, 32453515, 32366063, 32278846, 32191864, 32105116, 32018602, 31932322, 31846273, 31760457,
79 31674872, 31589518, 31504393, 31419498, 31334832, 31250394, 31166183, 31082200, 30998442, 30914911, 30831604,
80 30748522, 30665664, 30583029, 30500617, 30418426, 30336458, 30254710, 30173183, 30091875, 30010786, 29929916,
81 29849263, 29768829, 29688610, 29608608, 29528822, 29449250, 29369893, 29290750, 29211820, 29133103, 29054598,
82 28976304, 28898222, 28820350, 28742687, 28665234, 28587990, 28510954, 28434125, 28357503, 28281088, 28204879,
83 28128875, 28053076, 27977482, 27902091, 27826903, 27751917, 27677134, 27602552, 27528172, 27453991, 27380011,
84 27306230, 27232648, 27159264, 27086078, 27013089, 26940296, 26867700, 26795300, 26723094, 26651083, 26579267,
85 26507643, 26436213, 26364975, 26293929, 26223075, 26152412, 26081939, 26011656, 25941562, 25871657, 25801940,
86 25732412, 25663071, 25593916, 25524948, 25456166, 25387569, 25319157, 25250929, 25182886, 25115025, 25047348,
87 24979852, 24912539, 24845407, 24778456, 24711686, 24645095, 24578684, 24512451, 24446397, 24380522, 24314823,
88 24249302, 24183957, 24118789, 24053796, 23988978, 23924335, 23859866, 23795570, 23731448, 23667499, 23603722,
89 23540117, 23476683, 23413421, 23350328, 23287406, 23224653, 23162070, 23099655, 23037408, 22975329, 22913417,
90 22851673, 22790094, 22728681, 22667434, 22606352, 22545435, 22484682, 22424092, 22363666, 22303402, 22243301,
91 22183362, 22123584, 22063968, 22004512, 21945216, 21886080, 21827104, 21768286, 21709627, 21651126, 21592783,
92 21534597, 21476567, 21418694, 21360977, 21303416, 21246009, 21188758, 21131660, 21074717, 21017926, 20961289,
93 20904805, 20848473, 20792292, 20736263, 20680385, 20624657, 20569080, 20513652, 20458374, 20403245, 20348264,
94 20293432, 20238747, 20184209, 20129819, 20075575, 20021477, 19967525, 19913719, 19860057, 19806540, 19753167,
95 19699938, 19646853, 19593910, 19541111, 19488453, 19435937, 19383563, 19331330, 19279238, 19227286, 19175474,
96 19123802, 19072269, 19020875, 18969619, 18918502, 18867522, 18816680, 18765974, 18715405, 18664973, 18614676,
97 18564515, 18514489, 18464598, 18414842, 18365219, 18315730, 18266375, 18217152, 18168062, 18119105, 18070279,
98 18021585, 17973022, 17924590, 17876289, 17828118, 17780076, 17732164, 17684381, 17636727, 17589201, 17541803,
99 17494533, 17447391, 17400375, 17353486, 17306724, 17260087, 17213577, 17167191, 17120930, 17074795, 17028783,
100 16982896, 16937132, 16891491, 16845974, 16800579, 16755306, 16710155, 16665126, 16620219, 16575432, 16530766,
101 16486221, 16441795, 16397490, 16353303, 16309236, 16265287, 16221457, 16177745, 16134151, 16090674, 16047314,
102 16004072, 15960945, 15917935, 15875041, 15832263, 15789599, 15747051, 15704617, 15662298, 15620093, 15578001,
103 15536023, 15494158, 15452406, 15410766, 15369239, 15327823, 15286519, 15245327, 15204245, 15163274, 15122414,
104 15081663, 15041023, 15000491, 14960070, 14919757, 14879552, 14839456, 14799468, 14759588, 14719815, 14680150,
105 14640591, 14601139, 14561793, 14522554, 14483420, 14444391, 14405468, 14366649, 14327935, 14289326, 14250820,
106 14212418, 14174120, 14135925, 14097833, 14059843, 14021956, 13984171, 13946488, 13908906, 13871426, 13834047,
107 13796768, 13759590, 13722512, 13685534, 13648655, 13611876, 13575196, 13538615, 13502132, 13465748, 13429462,
108 13393273, 13357183, 13321189, 13285292, 13249492, 13213789, 13178182, 13142670, 13107255, 13071934, 13036709,
109 13001579, 12966544, 12931603, 12896756, 12862003, 12827344, 12792778, 12758305, 12723925, 12689638, 12655443,
110 12621341, 12587330, 12553411, 12519583, 12485846, 12452201, 12418646, 12385181, 12351807, 12318522, 12285327,
111 12252222, 12219206, 12186279, 12153440, 12120690, 12088029, 12055455, 12022969, 11990571, 11958260, 11926036,
112 11893899, 11861848, 11829884, 11798006, 11766214, 11734507, 11702886, 11671350, 11639900, 11608533, 11577252,
113 11546055, 11514941, 11483912, 11452966, 11422104, 11391325, 11360628, 11330015, 11299484, 11269035, 11238668,
114 11208384, 11178180, 11148058, 11118018, 11088058, 11058179, 11028380, 10998662, 10969024, 10939466, 10909987,
115 10880588, 10851268, 10822027, 10792865, 10763781, 10734776, 10705849, 10677000, 10648228, 10619535, 10590918,
116 10562379, 10533916, 10505530, 10477221, 10448988, 10420831, 10392750, 10364745, 10336815, 10308960, 10281180,
117 10253476, 10225846, 10198290, 10170809, 10143401, 10116068, 10088808, 10061622, 10034509, 10007468, 9980501,
118 9953607, 9926785, 9900035, 9873357, 9846752, 9820217, 9793755, 9767364, 9741043, 9714794, 9688616,
119 9662508, 9636470, 9610503, 9584605, 9558778, 9533019, 9507331, 9481711, 9456161, 9430679, 9405266,
120 9379922, 9354646, 9329438, 9304298, 9279225, 9254221, 9229283, 9204413, 9179610, 9154874, 9130204,
121 9105601, 9081064, 9056593, 9032188, 9007849, 8983576, 8959368, 8935225, 8911147, 8887134, 8863186,
122 8839302, 8815483, 8791728, 8768037, 8744409, 8720846, 8697346, 8673909, 8650535, 8627225, 8603977,
123 8580792, 8557669, 8534608, 8511610, 8488674, 8465799, 8442987, 8420235, 8397545, 8374916, 8352348,
124 8329841, 8307395, 8285009, 8262683, 8240418, 8218212, 8196067, 8173981, 8151954, 8129987, 8108079,
125 8086230, 8064440, 8042709, 8021036, 7999422, 7977866, 7956368, 7934928, 7913545, 7892221, 7870954,
126 7849744, 7828591, 7807495, 7786456, 7765474, 7744548, 7723679, 7702866, 7682109, 7661408, 7640763,
127 7620173, 7599639, 7579160, 7558737, 7538368, 7518055, 7497796, 7477591, 7457441, 7437346, 7417304,
128 7397317, 7377383, 7357503, 7337677, 7317904, 7298185, 7278518, 7258905, 7239344, 7219836, 7200381,
129 7180978, 7161627, 7142329, 7123082, 7103888, 7084745, 7065654, 7046614, 7027625, 7008688, 6989802,
130 6970966, 6952181, 6933447, 6914764, 6896130, 6877547, 6859014, 6840531, 6822098, 6803715, 6785381,
131 6767096, 6748861, 6730675, 6712537, 6694449, 6676410, 6658419, 6640476, 6622582, 6604736, 6586938,
132 6569188, 6551486, 6533832, 6516225, 6498666, 6481154, 6463689, 6446272, 6428901, 6411577, 6394299,
133 6377069, 6359884, 6342746, 6325655, 6308609, 6291609, 6274655, 6257747, 6240884, 6224066, 6207294,
134 6190568, 6173886, 6157249, 6140657, 6124110, 6107607, 6091149, 6074735, 6058365, 6042040, 6025758,
135 6009521, 5993327, 5977177, 5961070, 5945007, 5928987, 5913010, 5897076, 5881185, 5865337, 5849532,
136 5833769, 5818049, 5802371, 5786735, 5771141, 5755590, 5740080, 5724612, 5709186, 5693802, 5678459,
137 5663157, 5647896, 5632677, 5617498, 5602361, 5587264, 5572208, 5557193, 5542218, 5527283, 5512389,
138 5497534, 5482720, 5467946, 5453211, 5438517, 5423861, 5409246, 5394669, 5380132, 5365635, 5351176,
139 5336756, 5322375, 5308033, 5293729, 5279464, 5265237, 5251049, 5236899, 5222787, 5208713, 5194677,
140 5180679, 5166719, 5152796, 5138911, 5125063, 5111252, 5097479, 5083743, 5070044, 5056382, 5042756,
141 5029167, 5015615, 5002100, 4988620, 4975178, 4961771, 4948400, 4935066, 4921767, 4908505, 4895278,
142 4882086, 4868931, 4855810, 4842725, 4829676, 4816661, 4803682, 4790737, 4777827, 4764953, 4752112,
143 4739307, 4726536, 4713799, 4701097, 4688429, 4675795, 4663195, 4650629, 4638097, 4625599, 4613134,
144 4600703, 4588306, 4575941, 4563611, 4551313, 4539049, 4526817, 4514619, 4502453, 4490320, 4478220,
145 4466153, 4454118, 4442115, 4430145, 4418207, 4406301, 4394428, 4382586, 4370776, 4358998, 4347252,
146 4335538, 4323855, 4312203, 4300583, 4288994, 4277437, 4265910, 4254415, 4242950, 4231517, 4220114,
147 4208742, 4197401, 4186090, 4174810, 4163560, 4152340, 4141151, 4129992, 4118863, 4107764, 4096694,
148 4085655, 4074645, 4063665, 4052715, 4041794, 4030903, 4020041, 4009208, 3998404, 3987630, 3976884,
149 3966168, 3955480, 3944821, 3934191, 3923590, 3913017, 3902472, 3891956, 3881469, 3871009, 3860578,
150 3850175, 3839800, 3829453, 3819133, 3808842, 3798578, 3788342, 3778134, 3767953, 3757799, 3747673,
151 3737574, 3727503, 3717458, 3707441, 3697450, 3687487, 3677550, 3667640, 3657757, 3647900, 3638070,
152 3628267, 3618490, 3608739, 3599014, 3589316, 3579644, 3569998, 3560378, 3550783, 3541215, 3531673,
153 3522156, 3512665, 3503199, 3493759, 3484344, 3474955, 3465591, 3456252, 3446939, 3437650, 3428387,
154 3419148, 3409935, 3400746, 3391582, 3382443, 3373328, 3364238, 3355172, 3346131, 3337114, 3328122,
155 3319153, 3310209, 3301289, 3292393, 3283521, 3274673, 3265849, 3257048, 3248271, 3239518, 3230789,
156 3222083, 3213400, 3204741, 3196105, 3187493, 3178903, 3170337, 3161794, 3153274, 3144777, 3136302,
157 3127851, 3119422, 3111016, 3102633, 3094272, 3085934, 3077619, 3069325, 3061054, 3052806, 3044579,
158 3036375, 3028193, 3020033, 3011895, 3003779, 2995684, 2987612, 2979561, 2971532, 2963525, 2955539,
159 2947575, 2939632, 2931710, 2923810, 2915931, 2908074, 2900237, 2892422, 2884628, 2876855, 2869102,
160 2861371, 2853660, 2845971, 2838302, 2830653, 2823025, 2815418, 2807832, 2800265, 2792719, 2785194,
161 2777689, 2770203, 2762739, 2755294, 2747869, 2740464, 2733080, 2725715, 2718370, 2711045, 2703739,
162 2696453, 2689187, 2681941, 2674714, 2667506, 2660318, 2653149, 2646000, 2638870, 2631759, 2624667,
163 2617594, 2610540, 2603506, 2596490, 2589493, 2582515, 2575556, 2568616, 2561694, 2554791, 2547907,
164 2541041, 2534194, 2527365, 2520554, 2513762, 2506988, 2500233, 2493495, 2486776, 2480075, 2473392,
165 2466727, 2460080, 2453450, 2446839, 2440246, 2433670, 2427112, 2420571, 2414049, 2407544, 2401056,
166 2394586, 2388133, 2381698, 2375280, 2368879, 2362496, 2356130, 2349780, 2343448, 2337134, 2330836,
167 2324555, 2318291, 2312044, 2305813, 2299600, 2293403, 2287223, 2281060, 2274913, 2268783, 2262669,
168 2256572, 2250491, 2244427, 2238379, 2232347, 2226331, 2220332, 2214349, 2208382, 2202431, 2196496,
169 2190577, 2184674, 2178787, 2172916, 2167060, 2161221, 2155397, 2149589, 2143796, 2138019, 2132258,
170 2126512, 2120782, 2115067, 2109368, 2103683, 2098015, 2092361, 2086723, 2081100, 2075492, 2069899,
171 2064321, 2058758, 2053211, 2047678, 2042160, 2036657, 2031169, 2025695, 2020237, 2014793, 2009364,
172 2003949, 1998549, 1993163, 1987792, 1982436, 1977094, 1971766, 1966453, 1961154, 1955869, 1950599,
173 1945342, 1940100, 1934872, 1929658, 1924458, 1919272, 1914101, 1908943, 1903799, 1898668, 1893552,
174 1888450, 1883361, 1878286, 1873224, 1868176, 1863142, 1858122, 1853115, 1848121, 1843141, 1838174,
175 1833221, 1828281, 1823354, 1818441, 1813540, 1808654, 1803780, 1798919, 1794072, 1789237, 1784416,
176 1779607, 1774812, 1770029, 1765259, 1760502, 1755758, 1751027, 1746309, 1741603, 1736910, 1732229,
177 1727561, 1722906, 1718263, 1713633, 1709015, 1704410, 1699817, 1695237, 1690669, 1686113, 1681569,
178 1677038, 1672519, 1668012, 1663517, 1659034, 1654564, 1650105, 1645659, 1641224, 1636801, 1632391,
179 1627992, 1623605, 1619230, 1614866, 1610515, 1606175, 1601847, 1597530, 1593225, 1588932, 1584650,
180 1580380, 1576122, 1571874, 1567639, 1563414, 1559201, 1555000, 1550810, 1546631, 1542463, 1538306,
181 1534161, 1530027, 1525904, 1521792, 1517691, 1513602, 1509523, 1505455, 1501399, 1497353, 1493318,
182 1489294, 1485281, 1481278, 1477287, 1473306, 1469336, 1465376, 1461427, 1457489, 1453562, 1449645,
183 1445738, 1441843, 1437957, 1434082, 1430218, 1426364, 1422520, 1418687, 1414864, 1411051, 1407249,
184 1403457, 1399675, 1395903, 1392142, 1388390, 1384649, 1380918, 1377197, 1373486, 1369784, 1366093,
185 1362412, 1358741, 1355079, 1351428, 1347786, 1344154, 1340532, 1336920, 1333317, 1329724, 1326141,
186 1322567, 1319004, 1315449, 1311904, 1308369, 1304844, 1301327, 1297821, 1294323, 1290836, 1287357,
187 1283888, 1280429, 1276978, 1273537, 1270105, 1266683, 1263269, 1259865, 1256470, 1253084, 1249708,
188 1246340, 1242982, 1239632, 1236292, 1232960, 1229638, 1226324, 1223020, 1219724, 1216437, 1213159,
189 1209890, 1206630, 1203378, 1200136, 1196902, 1193676, 1190460, 1187252, 1184052, 1180862, 1177680,
190 1174506, 1171341, 1168185, 1165037, 1161897, 1158767, 1155644, 1152530, 1149424, 1146327, 1143238,
191 1140157, 1137085, 1134021, 1130965, 1127917, 1124878, 1121846, 1118823, 1115809, 1112802, 1109803,
192 1106813, 1103830, 1100855, 1097889, 1094931, 1091980, 1089037, 1086103, 1083176, 1080257, 1077346,
193 1074443, 1071548, 1068660, 1065781, 1062909, 1060044, 1057188, 1054339, 1051498, 1048664, 1045839,
194 1043020, 1040210, 1037407, 1034611, 1031823, 1029043, 1026270, 1023504, 1020746, 1017996, 1015252,
195 1012517, 1009788, 1007067, 1004353, 1001647, 998948, 996256, 993571, 990894, 988224, 985561,
196 982905, 980256, 977615, 974980, 972353, 969733, 967120, 964514, 961915, 959323, 956737,
197 954159, 951588, 949024, 946467, 943916, 941373, 938836, 936306, 933783, 931267, 928757,
198 926254, 923758, 921269, 918787, 916311, 913842, 911379, 908923, 906474, 904031, 901595,
199 899166, 896743, 894326, 891916, 889513, 887116, 884725, 882341, 879963, 877592, 875227,
200 872869, 870517, 868171, 865831, 863498, 861171, 858851, 856536, 854228, 851926, 849631,
201 847341, 845058, 842781, 840510, 838245, 835986, 833733, 831487, 829246, 827011, 824783,
202 822560, 820344, 818133, 815929, 813730, 811537, 809350, 807169, 804994, 802825, 800662,
203 798504, 796352, 794206, 792066, 789932, 787803, 785680, 783563, 781452, 779346, 777246,
204 775151, 773062, 770979, 768902, 766830, 764763, 762703, 760647, 758598, 756553, 754515,
205 752482, 750454, 748432, 746415, 744403, 742397, 740397, 738402, 736412, 734428, 732448,
206 730475, 728506, 726543, 724585, 722633, 720686, 718744, 716807, 714875, 712949, 711028,
207 709112, 707201, 705295, 703394, 701499, 699609, 697723, 695843, 693968, 692098, 690233,
208 688373, 686518, 684668, 682823, 680983, 679148, 677318, 675493, 673673, 671857, 670047,
209 668241, 666441, 664645, 662854, 661067, 659286, 657510, 655738, 653971, 652208, 650451,
210 648698, 646950, 645207, 643468, 641734, 640005, 638280, 636560, 634845, 633134, 631428,
211 629727, 628030, 626337, 624650, 622966, 621288, 619613, 617944, 616279, 614618, 612962,
212 611310, 609663, 608020, 606381, 604747, 603118, 601492, 599872, 598255, 596643, 595035,
213 593432, 591833, 590238, 588647, 587061, 585479, 583901, 582328, 580759, 579194, 577633,
214 576076, 574524, 572976, 571432, 569892, 568356, 566825, 565297, 563774, 562255, 560740,
215 559229, 557722, 556219, 554720, 553225, 551734, 550248, 548765, 547286, 545811, 544341,
216 542874, 541411, 539952, 538497, 537046, 535599, 534155, 532716, 531280, 529849, 528421,
217 526997, 525577, 524161, 522748, 521340, 519935, 518534, 517136, 515743, 514353, 512967,
218 511585, 510206, 508831, 507460, 506093, 504729, 503369, 502012, 500660, 499310, 497965,
219 496623, 495285, 493950, 492619, 491292, 489968, 488648, 487331, 486018, 484708, 483402,
220 482099, 480800, 479504, 478212, 476924, 475638, 474357, 473078, 471804, 470532, 469264,
221 468000, 466739, 465481, 464227, 462976, 461728, 460484, 459243, 458005, 456771, 455540,
222 454313, 453089, 451868, 450650, 449436, 448225, 447017, 445812, 444611, 443413, 442218,
223 441026, 439838, 438653, 437470, 436292, 435116, 433943, 432774, 431608, 430445, 429285,
224 428128, 426974, 425824, 424676, 423532, 422391, 421252, 420117, 418985, 417856, 416730,
225 415607, 414487, 413370, 412256, 411146, 410038, 408933, 407831, 406732, 405636, 404543,
226 403453, 402365, 401281, 400200, 399121, 398046, 396973, 395903, 394837, 393773, 392712,
227 391653, 390598, 389545, 388496, 387449, 386405, 385363, 384325, 383289, 382257, 381226,
228 380199, 379175, 378153, 377134, 376118, 375104, 374093, 373085, 372080, 371077, 370077,
229 369080, 368085, 367094, 366104, 365118, 364134, 363153, 362174, 361198, 360225, 359254,
230 358286, 357321, 356358, 355397, 354440, 353485, 352532, 351582, 350635, 349690, 348748,
231 347808, 346871, 345936, 345004, 344074, 343147, 342222, 341300, 340380, 339463, 338548,
232 337636, 336726, 335819, 334914, 334011, 333111, 332214, 331318, 330426, 329535, 328647,
233 327762, 326878, 325997, 325119, 324243, 323369, 322498, 321629, 320762, 319898, 319036,
234 318176, 317319, 316463, 315611, 314760, 313912, 313066, 312222, 311381, 310542, 309705,
235 308871, 308038, 307208, 306380, 305555, 304731, 303910, 303091, 302275, 301460, 300648,
236 299838, 299030, 298224, 297420, 296619, 295819, 295022, 294227, 293434, 292644, 291855,
237 291069, 290284, 289502, 288722, 287944, 287168, 286394, 285622, 284853, 284085, 283320,
238 282556, 281795, 281035, 280278, 279523, 278770, 278018, 277269, 276522, 275777, 275034,
239 274293, 273553, 272816, 272081, 271348, 270617, 269888, 269160, 268435, 267712, 266990,
240 266271, 265553, 264838, 264124, 263412, 262702, 261994, 261289, 260584, 259882, 259182,
241 258483, 257787, 257092, 256399, 255709, 255020, 254332, 253647, 252963, 252282, 251602,
242 250924, 250248, 249573, 248901, 248230, 247561, 246894, 246229, 245565, 244904, 244244,
243 243586, 242929, 242275, 241622, 240971, 240321, 239674, 239028, 238384, 237741, 237101,
244 236462, 235825, 235189, 234555, 233923, 233293, 232664, 232037, 231412, 230788, 230166,
245 229546, 228928, 228311, 227696, 227082, 226470, 225860, 225251, 224644, 224039, 223435,
246 222833, 222233, 221634, 221036, 220441, 219847, 219254, 218664, 218074, 217487, 216901,
247 216316, 215733, 215152, 214572, 213994, 213417, 212842, 212269, 211697, 211126, 210557,
248 209990, 209424, 208860, 208297, 207735, 207176, 206617, 206061, 205505, 204952, 204399,
249 203849, 203299, 202751, 202205, 201660, 201117, 200575, 200034, 199495, 198958, 198422,
250 197887, 197354, 196822, 196291, 195762, 195235, 194709, 194184, 193661, 193139, 192619,
251 192100, 191582, 191066, 190551, 190037, 189525, 189014, 188505, 187997, 187491, 186985,
252 186481, 185979, 185478, 184978, 184479, 183982, 183487, 182992, 182499, 182007, 181517,
253 181028, 180540, 180053, 179568, 179084, 178602, 178120, 177640, 177162, 176684, 176208,
254 175733, 175260, 174788, 174317, 173847, 173378, 172911, 172445, 171981, 171517, 171055,
255 170594, 170134, 169676, 169219, 168763, 168308, 167854, 167402, 166951, 166501, 166052,
256 165605, 165159, 164713, 164270, 163827, 163386, 162945, 162506, 162068, 161632, 161196,
257 160762, 160328, 159896, 159465, 159036, 158607, 158180, 157754, 157328, 156904, 156482,
258 156060, 155639, 155220, 154802, 154385, 153969, 153554, 153140, 152727, 152316, 151905,
259 151496, 151088, 150681, 150275, 149870, 149466, 149063, 148661, 148261, 147861, 147463,
260 147065, 146669, 146274, 145880, 145487, 145094, 144703, 144314, 143925, 143537, 143150,
261 142764, 142380, 141996, 141613, 141232, 140851, 140472, 140093, 139715, 139339, 138964,
262 138589, 138216, 137843, 137472, 137101, 136732, 136363, 135996, 135629, 135264, 134899,
263 134536, 134173, 133812, 133451, 133092, 132733, 132375, 132019, 131663, 131308, 130954,
264 130601, 130249, 129898, 129548, 129199, 128851, 128504, 128158, 127812, 127468, 127124,
265 126782, 126440, 126099, 125760, 125421, 125083, 124746, 124410, 124074, 123740, 123407,
266 123074, 122742, 122412, 122082, 121753, 121425, 121097, 120771, 120446, 120121, 119797,
267 119475, 119153, 118832, 118511, 118192, 117873, 117556, 117239, 116923, 116608, 116294,
268 115980, 115668, 115356, 115045, 114735, 114426, 114118, 113810, 113504, 113198, 112893,
269 112589, 112285, 111983, 111681, 111380, 111080, 110780, 110482, 110184, 109887, 109591,
270 109296, 109001, 108708, 108415, 108122, 107831, 107541, 107251, 106962, 106674, 106386,
271 106099, 105813, 105528, 105244, 104960, 104678, 104395, 104114, 103834, 103554, 103275,
272 102996, 102719, 102442, 102166, 101891, 101616, 101342, 101069, 100797, 100525, 100254,
273 99984, 99715, 99446, 99178, 98911, 98644, 98378, 98113, 97849, 97585, 97322,
274 97060, 96799, 96538, 96278, 96018, 95759, 95501, 95244, 94987, 94731, 94476,
275 94222, 93968, 93714, 93462, 93210, 92959, 92708, 92459, 92209, 91961, 91713,
276 91466, 91219, 90974, 90729, 90484, 90240, 89997, 89754, 89513, 89271, 89031,
277 88791, 88552, 88313, 88075, 87838, 87601, 87365, 87130, 86895, 86661, 86427,
278 86194, 85962, 85730, 85499, 85269, 85039, 84810, 84581, 84353, 84126, 83899,
279 83673, 83448, 83223, 82999, 82775, 82552, 82330, 82108, 81886, 81666, 81446,
280 81226, 81007, 80789, 80571, 80354, 80138, 79922, 79706, 79492, 79277, 79064,
281 78851, 78638, 78426, 78215, 78004, 77794, 77584, 77375, 77167, 76959, 76752,
282 76545, 76338, 76133, 75928, 75723, 75519, 75315, 75112, 74910, 74708, 74507,
283 74306, 74106, 73906, 73707, 73508, 73310, 73113, 72916, 72719, 72523, 72328,
284 72133, 71939, 71745, 71551, 71359, 71166, 70975, 70783, 70593, 70402, 70213,
285 70023, 69835, 69646, 69459, 69272, 69085, 68899, 68713, 68528, 68343, 68159,
286 67975, 67792, 67610, 67427, 67246, 67065, 66884, 66704, 66524, 66345, 66166,
287 65987, 65810, 65632, 65455, 65279, 65103, 64928, 64753, 64578, 64404, 64231,
288 64058, 63885, 63713, 63541, 63370, 63199, 63029, 62859, 62690, 62521, 62352,
289 62184, 62017, 61850, 61683, 61517, 61351, 61186, 61021, 60856, 60692, 60529,
290 60366, 60203, 60041, 59879, 59718, 59557, 59396, 59236, 59076, 58917, 58758,
291 58600, 58442, 58285, 58128, 57971, 57815, 57659, 57504, 57349, 57194, 57040,
292 56886, 56733, 56580, 56428, 56276, 56124, 55973, 55822, 55671, 55521, 55372,
293 55223, 55074, 54925, 54777, 54630, 54483, 54336, 54189, 54043, 53898, 53752,
294 53608, 53463, 53319, 53175, 53032, 52889, 52747, 52605, 52463, 52321, 52180,
295 52040, 51900, 51760, 51620, 51481, 51342, 51204, 51066, 50928, 50791, 50654,
296 50518, 50382, 50246, 50111, 49976, 49841, 49707, 49573, 49439, 49306, 49173,
297 49040, 48908, 48776, 48645, 48514, 48383, 48253, 48123, 47993, 47864, 47735,
298 47606, 47478, 47350, 47222, 47095, 46968, 46842, 46715, 46590, 46464, 46339,
299 46214, 46089, 45965, 45841, 45718, 45595, 45472, 45349, 45227, 45105, 44984,
300 44862, 44741, 44621, 44501, 44381, 44261, 44142, 44023, 43904, 43786, 43668,
301 43550, 43433, 43316, 43199, 43083, 42967, 42851, 42735, 42620, 42505, 42391,
302 42277, 42163, 42049, 41936, 41823, 41710, 41598, 41486, 41374, 41262, 41151,
303 41040, 40930, 40819, 40709, 40600, 40490, 40381, 40272, 40164, 40056, 39948,
304 39840, 39733, 39626, 39519, 39412, 39306, 39200, 39094, 38989, 38884, 38779,
305 38675, 38571, 38467, 38363, 38260, 38157, 38054, 37951, 37849, 37747, 37645,
306 37544, 37443, 37342, 37241, 37141, 37041, 36941, 36841, 36742, 36643, 36544,
307 36446, 36347, 36250, 36152, 36054, 35957, 35860, 35764, 35667, 35571, 35475,
308 35380, 35284, 35189, 35095, 35000, 34906, 34812, 34718, 34624, 34531, 34438,
309 34345, 34253, 34160, 34068, 33976, 33885
310};
311
312static const short sindb_coeff[] = {
313 2401, 2144, 1994, 1887, 1804, 1737, 1680, 1630, 1587, 1548, 1512, 1480, 1450,
314 1423, 1397, 1373, 1351, 1330, 1310, 1291, 1273, 1255, 1239, 1223, 1208, 1194,
315 1180, 1166, 1153, 1141, 1128, 1117, 1105, 1094, 1084, 1073, 1063, 1053, 1043,
316 1034, 1025, 1016, 1007, 999, 990, 982, 974, 967, 959, 952, 944, 937,
317 930, 923, 916, 910, 903, 897, 890, 884, 878, 872, 866, 860, 855,
318 849, 843, 838, 832, 827, 822, 817, 812, 807, 802, 797, 792, 787,
319 783, 778, 773, 769, 764, 760, 756, 751, 747, 743, 739, 734, 730,
320 726, 722, 718, 715, 711, 707, 703, 699, 696, 692, 688, 685, 681,
321 678, 674, 671, 667, 664, 661, 657, 654, 651, 648, 644, 641, 638,
322 635, 632, 629, 626, 623, 620, 617, 614, 611, 608, 605, 602, 599,
323 597, 594, 591, 588, 586, 583, 580, 578, 575, 572, 570, 567, 565,
324 562, 560, 557, 555, 552, 550, 547, 545, 542, 540, 538, 535, 533,
325 531, 528, 526, 524, 522, 519, 517, 515, 513, 510, 508, 506, 504,
326 502, 500, 498, 495, 493, 491, 489, 487, 485, 483, 481, 479, 477,
327 475, 473, 471, 469, 467, 465, 464, 462, 460, 458, 456, 454, 452,
328 450, 449, 447, 445, 443, 441, 440, 438, 436, 434, 433, 431, 429,
329 427, 426, 424, 422, 421, 419, 417, 416, 414, 412, 411, 409, 408,
330 406, 404, 403, 401, 400, 398, 396, 395, 393, 392, 390, 389, 387,
331 386, 384, 383, 381, 380, 378, 377, 375, 374, 372, 371, 370, 368,
332 367, 365, 364, 362, 361, 360, 358, 357, 355, 354, 353, 351, 350,
333 349, 347, 346, 345, 343, 342, 341, 339, 338, 337, 336, 334, 333,
334 332, 330, 329, 328, 327, 325, 324, 323, 322, 320, 319, 318, 317,
335 316, 314, 313, 312, 311, 310, 308, 307, 306, 305, 304, 303, 301,
336 300, 299, 298, 297, 296, 295, 293, 292, 291, 290, 289, 288, 287,
337 286, 285, 284, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273,
338 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260,
339 259, 258, 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247,
340 246, 245, 244, 243, 242, 241, 240, 240, 239, 238, 237, 236, 235,
341 234, 233, 232, 231, 230, 230, 229, 228, 227, 226, 225, 224, 223,
342 222, 222, 221, 220, 219, 218, 217, 216, 216, 215, 214, 213, 212,
343 211, 211, 210, 209, 208, 207, 206, 206, 205, 204, 203, 202, 202,
344 201, 200, 199, 198, 198, 197, 196, 195, 195, 194, 193, 192, 191,
345 191, 190, 189, 188, 188, 187, 186, 185, 185, 184, 183, 182, 182,
346 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172,
347 172, 171, 170, 170, 169, 168, 167, 167, 166, 165, 165, 164, 163,
348 163, 162, 161, 161, 160, 159, 159, 158, 157, 157, 156, 155, 155,
349 154, 153, 153, 152, 151, 151, 150, 150, 149, 148, 148, 147, 146,
350 146, 145, 145, 144, 143, 143, 142, 141, 141, 140, 140, 139, 138,
351 138, 137, 137, 136, 135, 135, 134, 134, 133, 133, 132, 131, 131,
352 130, 130, 129, 129, 128, 127, 127, 126, 126, 125, 125, 124, 123,
353 123, 122, 122, 121, 121, 120, 120, 119, 119, 118, 117, 117, 116,
354 116, 115, 115, 114, 114, 113, 113, 112, 112, 111, 111, 110, 110,
355 109, 109, 108, 108, 107, 107, 106, 106, 105, 105, 104, 104, 103,
356 103, 102, 102, 101, 101, 100, 100, 99, 99, 98, 98, 97, 97,
357 96, 96, 95, 95, 94, 94, 94, 93, 93, 92, 92, 91, 91,
358 90, 90, 89, 89, 89, 88, 88, 87, 87, 86, 86, 85, 85,
359 85, 84, 84, 83, 83, 82, 82, 82, 81, 81, 80, 80, 79,
360 79, 79, 78, 78, 77, 77, 77, 76, 76, 75, 75, 75, 74,
361 74, 73, 73, 73, 72, 72, 71, 71, 71, 70, 70, 69, 69,
362 69, 68, 68, 68, 67, 67, 66, 66, 66, 65, 65, 65, 64,
363 64, 63, 63, 63, 62, 62, 62, 61, 61, 61, 60, 60, 59,
364 59, 59, 58, 58, 58, 57, 57, 57, 56, 56, 56, 55, 55,
365 55, 54, 54, 54, 53, 53, 53, 52, 52, 52, 51, 51, 51,
366 50, 50, 50, 49, 49, 49, 49, 48, 48, 48, 47, 47, 47,
367 46, 46, 46, 45, 45, 45, 45, 44, 44, 44, 43, 43, 43,
368 43, 42, 42, 42, 41, 41, 41, 40, 40, 40, 40, 39, 39,
369 39, 39, 38, 38, 38, 37, 37, 37, 37, 36, 36, 36, 36,
370 35, 35, 35, 35, 34, 34, 34, 34, 33, 33, 33, 32, 32,
371 32, 32, 31, 31, 31, 31, 31, 30, 30, 30, 30, 29, 29,
372 29, 29, 28, 28, 28, 28, 27, 27, 27, 27, 27, 26, 26,
373 26, 26, 25, 25, 25, 25, 25, 24, 24, 24, 24, 23, 23,
374 23, 23, 23, 22, 22, 22, 22, 22, 21, 21, 21, 21, 21,
375 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 18, 18,
376 18, 18, 18, 17, 17, 17, 17, 17, 17, 16, 16, 16, 16,
377 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14,
378 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
379 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,
380 10, 10, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8,
381 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7,
382 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5,
383 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
384 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
385 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
386 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
387 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
388 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
390 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
392};
393
394
395static const short lfo_freq_coeff[] = {
396 0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37,
397 40, 43, 46, 50, 53, 56, 59, 62, 65, 68, 71, 74, 78,
398 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118,
399 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157,
400 160, 163, 166, 169, 172, 175, 178, 180, 183, 186, 189, 192, 195,
401 198, 201, 204, 207, 209, 212, 215, 218, 221, 224, 226, 229, 232,
402 235, 238, 240, 243, 246, 249, 251, 254, 257, 260, 262, 265, 268,
403 270, 273, 276, 278, 281, 283, 286, 289, 291, 294, 296, 299, 301,
404 304, 306, 309, 311, 314, 316, 319, 321, 324, 326, 328, 331, 333,
405 336, 338, 340, 343, 345, 347, 350, 352, 354, 356, 359, 361, 363,
406 365, 367, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 391,
407 393, 395, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 415,
408 417, 419, 421, 423, 424, 426, 428, 430, 431, 433, 435, 436, 438,
409 439, 441, 443, 444, 446, 447, 449, 450, 452, 453, 455, 456, 457,
410 459, 460, 461, 463, 464, 465, 467, 468, 469, 470, 472, 473, 474,
411 475, 476, 477, 478, 480, 481, 482, 483, 484, 485, 486, 487, 488,
412 488, 489, 490, 491, 492, 493, 494, 494, 495, 496, 497, 497, 498,
413 499, 499, 500, 501, 501, 502, 502, 503, 504, 504, 504, 505, 505,
414 506, 506, 507, 507, 507, 508, 508, 508, 509, 509, 509, 509, 510,
415 510, 510, 510, 510, 510, 510, 510, 510, 510, 511, 510, 510, 510,
416 510, 510, 510, 510, 510, 510, 510, 509, 509, 509, 509, 508, 508,
417 508, 507, 507, 507, 506, 506, 505, 505, 504, 504, 504, 503, 502,
418 502, 501, 501, 500, 499, 499, 498, 497, 497, 496, 495, 494, 494,
419 493, 492, 491, 490, 489, 488, 488, 487, 486, 485, 484, 483, 482,
420 481, 480, 478, 477, 476, 475, 474, 473, 472, 470, 469, 468, 467,
421 465, 464, 463, 461, 460, 459, 457, 456, 455, 453, 452, 450, 449,
422 447, 446, 444, 443, 441, 439, 438, 436, 435, 433, 431, 430, 428,
423 426, 424, 423, 421, 419, 417, 415, 414, 412, 410, 408, 406, 404,
424 402, 400, 398, 396, 395, 393, 391, 388, 386, 384, 382, 380, 378,
425 376, 374, 372, 370, 367, 365, 363, 361, 359, 356, 354, 352, 350,
426 347, 345, 343, 340, 338, 336, 333, 331, 328, 326, 324, 321, 319,
427 316, 314, 311, 309, 306, 304, 301, 299, 296, 294, 291, 289, 286,
428 283, 281, 278, 276, 273, 270, 268, 265, 262, 260, 257, 254, 251,
429 249, 246, 243, 240, 238, 235, 232, 229, 226, 224, 221, 218, 215,
430 212, 209, 207, 204, 201, 198, 195, 192, 189, 186, 183, 180, 178,
431 175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139,
432 136, 133, 130, 127, 124, 121, 118, 115, 111, 108, 105, 102, 99,
433 96, 93, 90, 87, 84, 81, 78, 74, 71, 68, 65, 62, 59,
434 56, 53, 50, 46, 43, 40, 37, 34, 31, 28, 25, 21, 18,
435 15, 12, 9, 6, 3, 0, -3, -6, -9, -12, -15, -18, -21,
436 -25, -28, -31, -34, -37, -40, -43, -46, -50, -53, -56, -59, -62,
437 -65, -68, -71, -74, -78, -81, -84, -87, -90, -93, -96, -99, -102,
438 -105, -108, -111, -115, -118, -121, -124, -127, -130, -133, -136, -139, -142,
439 -145, -148, -151, -154, -157, -160, -163, -166, -169, -172, -175, -178, -180,
440 -183, -186, -189, -192, -195, -198, -201, -204, -207, -209, -212, -215, -218,
441 -221, -224, -226, -229, -232, -235, -238, -240, -243, -246, -249, -251, -254,
442 -257, -260, -262, -265, -268, -270, -273, -276, -278, -281, -283, -286, -289,
443 -291, -294, -296, -299, -301, -304, -306, -309, -311, -314, -316, -319, -321,
444 -324, -326, -328, -331, -333, -336, -338, -340, -343, -345, -347, -350, -352,
445 -354, -356, -359, -361, -363, -365, -367, -370, -372, -374, -376, -378, -380,
446 -382, -384, -386, -388, -391, -393, -395, -396, -398, -400, -402, -404, -406,
447 -408, -410, -412, -414, -415, -417, -419, -421, -423, -424, -426, -428, -430,
448 -431, -433, -435, -436, -438, -439, -441, -443, -444, -446, -447, -449, -450,
449 -452, -453, -455, -456, -457, -459, -460, -461, -463, -464, -465, -467, -468,
450 -469, -470, -472, -473, -474, -475, -476, -477, -478, -480, -481, -482, -483,
451 -484, -485, -486, -487, -488, -488, -489, -490, -491, -492, -493, -494, -494,
452 -495, -496, -497, -497, -498, -499, -499, -500, -501, -501, -502, -502, -503,
453 -504, -504, -504, -505, -505, -506, -506, -507, -507, -507, -508, -508, -508,
454 -509, -509, -509, -509, -510, -510, -510, -510, -510, -510, -510, -510, -510,
455 -510, -511, -510, -510, -510, -510, -510, -510, -510, -510, -510, -510, -509,
456 -509, -509, -509, -508, -508, -508, -507, -507, -507, -506, -506, -505, -505,
457 -504, -504, -504, -503, -502, -502, -501, -501, -500, -499, -499, -498, -497,
458 -497, -496, -495, -494, -494, -493, -492, -491, -490, -489, -488, -488, -487,
459 -486, -485, -484, -483, -482, -481, -480, -478, -477, -476, -475, -474, -473,
460 -472, -470, -469, -468, -467, -465, -464, -463, -461, -460, -459, -457, -456,
461 -455, -453, -452, -450, -449, -447, -446, -444, -443, -441, -439, -438, -436,
462 -435, -433, -431, -430, -428, -426, -424, -423, -421, -419, -417, -415, -414,
463 -412, -410, -408, -406, -404, -402, -400, -398, -396, -395, -393, -391, -388,
464 -386, -384, -382, -380, -378, -376, -374, -372, -370, -367, -365, -363, -361,
465 -359, -356, -354, -352, -350, -347, -345, -343, -340, -338, -336, -333, -331,
466 -328, -326, -324, -321, -319, -316, -314, -311, -309, -306, -304, -301, -299,
467 -296, -294, -291, -289, -286, -283, -281, -278, -276, -273, -270, -268, -265,
468 -262, -260, -257, -254, -251, -249, -246, -243, -240, -238, -235, -232, -229,
469 -226, -224, -221, -218, -215, -212, -209, -207, -204, -201, -198, -195, -192,
470 -189, -186, -183, -180, -178, -175, -172, -169, -166, -163, -160, -157, -154,
471 -151, -148, -145, -142, -139, -136, -133, -130, -127, -124, -121, -118, -115,
472 -111, -108, -105, -102, -99, -96, -93, -90, -87, -84, -81, -78, -74,
473 -71, -68, -65, -62, -59, -56, -53, -50, -46, -43, -40, -37, -34,
474 -31, -28, -25, -21, -18, -15, -12, -9, -6, -3
475};
476
477static const short lfo_env_coeff[] = {
478 251, 253, 254, 256, 257, 259, 260, 262, 264, 265, 267, 268, 270,
479 271, 273, 274, 276, 277, 279, 281, 282, 284, 285, 287, 288, 290,
480 291, 293, 294, 296, 297, 299, 300, 302, 303, 305, 306, 308, 309,
481 311, 312, 314, 315, 317, 318, 320, 321, 323, 324, 326, 327, 329,
482 330, 332, 333, 335, 336, 337, 339, 340, 342, 343, 345, 346, 348,
483 349, 350, 352, 353, 355, 356, 357, 359, 360, 362, 363, 364, 366,
484 367, 369, 370, 371, 373, 374, 375, 377, 378, 379, 381, 382, 383,
485 385, 386, 387, 389, 390, 391, 392, 394, 395, 396, 397, 399, 400,
486 401, 402, 404, 405, 406, 407, 409, 410, 411, 412, 413, 414, 416,
487 417, 418, 419, 420, 421, 423, 424, 425, 426, 427, 428, 429, 430,
488 431, 432, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444,
489 445, 446, 447, 448, 449, 450, 451, 452, 453, 453, 454, 455, 456,
490 457, 458, 459, 460, 461, 461, 462, 463, 464, 465, 466, 466, 467,
491 468, 469, 469, 470, 471, 472, 473, 473, 474, 475, 475, 476, 477,
492 477, 478, 479, 479, 480, 481, 481, 482, 483, 483, 484, 484, 485,
493 486, 486, 487, 487, 488, 488, 489, 489, 490, 490, 491, 491, 492,
494 492, 493, 493, 493, 494, 494, 495, 495, 495, 496, 496, 497, 497,
495 497, 498, 498, 498, 498, 499, 499, 499, 500, 500, 500, 500, 500,
496 501, 501, 501, 501, 501, 502, 502, 502, 502, 502, 502, 502, 502,
497 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503, 503,
498 503, 503, 503, 503, 503, 503, 502, 502, 502, 502, 502, 502, 502,
499 502, 501, 501, 501, 501, 501, 500, 500, 500, 500, 500, 499, 499,
500 499, 498, 498, 498, 498, 497, 497, 497, 496, 496, 495, 495, 495,
501 494, 494, 493, 493, 493, 492, 492, 491, 491, 490, 490, 489, 489,
502 488, 488, 487, 487, 486, 486, 485, 484, 484, 483, 483, 482, 481,
503 481, 480, 479, 479, 478, 477, 477, 476, 475, 475, 474, 473, 473,
504 472, 471, 470, 469, 469, 468, 467, 466, 466, 465, 464, 463, 462,
505 461, 461, 460, 459, 458, 457, 456, 455, 454, 453, 453, 452, 451,
506 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438,
507 437, 436, 435, 434, 432, 431, 430, 429, 428, 427, 426, 425, 424,
508 423, 421, 420, 419, 418, 417, 416, 414, 413, 412, 411, 410, 409,
509 407, 406, 405, 404, 402, 401, 400, 399, 397, 396, 395, 394, 392,
510 391, 390, 389, 387, 386, 385, 383, 382, 381, 379, 378, 377, 375,
511 374, 373, 371, 370, 369, 367, 366, 364, 363, 362, 360, 359, 357,
512 356, 355, 353, 352, 350, 349, 348, 346, 345, 343, 342, 340, 339,
513 337, 336, 335, 333, 332, 330, 329, 327, 326, 324, 323, 321, 320,
514 318, 317, 315, 314, 312, 311, 309, 308, 306, 305, 303, 302, 300,
515 299, 297, 296, 294, 293, 291, 290, 288, 287, 285, 284, 282, 281,
516 279, 277, 276, 274, 273, 271, 270, 268, 267, 265, 264, 262, 260,
517 259, 257, 256, 254, 253, 251, 250, 248, 247, 245, 244, 242, 240,
518 239, 237, 236, 234, 233, 231, 230, 228, 227, 225, 223, 222, 220,
519 219, 217, 216, 214, 213, 211, 210, 208, 207, 205, 204, 202, 201,
520 199, 198, 196, 195, 193, 192, 190, 189, 187, 186, 184, 183, 181,
521 180, 178, 177, 175, 174, 172, 171, 169, 168, 166, 165, 164, 162,
522 161, 159, 158, 156, 155, 153, 152, 151, 149, 148, 146, 145, 144,
523 142, 141, 139, 138, 137, 135, 134, 133, 131, 130, 129, 127, 126,
524 124, 123, 122, 120, 119, 118, 117, 115, 114, 113, 111, 110, 109,
525 108, 106, 105, 104, 103, 101, 100, 99, 98, 96, 95, 94, 93,
526 92, 90, 89, 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
527 77, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64,
528 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
529 50, 49, 48, 47, 46, 45, 45, 44, 43, 42, 41, 40, 39,
530 39, 38, 37, 36, 35, 35, 34, 33, 32, 31, 31, 30, 29,
531 29, 28, 27, 26, 26, 25, 24, 24, 23, 22, 22, 21, 20,
532 20, 19, 19, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13,
533 13, 12, 12, 11, 11, 10, 10, 9, 9, 9, 8, 8, 7,
534 7, 7, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3,
535 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
538 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
539 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
540 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 11,
541 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
542 19, 19, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26,
543 27, 28, 29, 29, 30, 31, 31, 32, 33, 34, 35, 35, 36,
544 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 45, 46, 47,
545 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
546 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
547 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88,
548 89, 90, 92, 93, 94, 95, 96, 98, 99, 100, 101, 103, 104,
549 105, 106, 108, 109, 110, 111, 113, 114, 115, 117, 118, 119, 120,
550 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 135, 137, 138,
551 139, 141, 142, 144, 145, 146, 148, 149, 151, 152, 153, 155, 156,
552 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 174, 175,
553 177, 178, 180, 181, 183, 184, 186, 187, 189, 190, 192, 193, 195,
554 196, 198, 199, 201, 202, 204, 205, 207, 208, 210, 211, 213, 214,
555 216, 217, 219, 220, 222, 223, 225, 227, 228, 230, 231, 233, 234,
556 236, 237, 239, 240, 242, 244, 245, 247, 248, 250
557};
558
559#endif
diff --git a/lib/rbcodec/codecs/libgme/z80_cpu.c b/lib/rbcodec/codecs/libgme/z80_cpu.c
new file mode 100644
index 0000000000..a31236020e
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/z80_cpu.c
@@ -0,0 +1,85 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3#include "z80_cpu.h"
4
5/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
6can redistribute it and/or modify it under the terms of the GNU Lesser
7General Public License as published by the Free Software Foundation; either
8version 2.1 of the License, or (at your option) any later version. This
9module is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12details. You should have received a copy of the GNU Lesser General Public
13License along with this module; if not, write to the Free Software Foundation,
14Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "blargg_source.h"
17
18// flags, named with hex value for clarity
19int const S80 = 0x80;
20int const Z40 = 0x40;
21int const F20 = 0x20;
22int const H10 = 0x10;
23int const F08 = 0x08;
24int const V04 = 0x04;
25int const P04 = 0x04;
26int const N02 = 0x02;
27int const C01 = 0x01;
28
29void Z80_init( struct Z80_Cpu* this )
30{
31 this->cpu_state = &this->cpu_state_;
32
33 int i;
34 for ( i = 0x100; --i >= 0; )
35 {
36 int p, even = 1;
37 for ( p = i; p; p >>= 1 )
38 even ^= p;
39 int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
40 this->szpc [i] = n;
41 this->szpc [i + 0x100] = n | C01;
42 }
43 this->szpc [0x000] |= Z40;
44 this->szpc [0x100] |= Z40;
45}
46
47static inline void set_page( struct Z80_Cpu* this, int i, void* write, void const* read )
48{
49 int offset = Z80_CPU_OFFSET( i * page_size );
50 byte * write2 = STATIC_CAST(byte *,write) - offset;
51 byte const* read2 = STATIC_CAST(byte const*,read ) - offset;
52 this->cpu_state_.write [i] = write2;
53 this->cpu_state_.read [i] = read2;
54 this->cpu_state->write [i] = write2;
55 this->cpu_state->read [i] = read2;
56}
57
58void Z80_reset( struct Z80_Cpu* this, void* unmapped_write, void const* unmapped_read )
59{
60 check( this->cpu_state == &this->cpu_state_ );
61 this->cpu_state = &this->cpu_state_;
62 this->cpu_state_.time = 0;
63 this->cpu_state_.base = 0;
64 this->end_time_ = 0;
65
66 int i;
67 for ( i = 0; i < page_count + 1; i++ )
68 set_page( this, i, unmapped_write, unmapped_read );
69
70 memset( &this->r, 0, sizeof this->r );
71}
72
73void Z80_map_mem( struct Z80_Cpu* this, addr_t start, int size, void* write, void const* read )
74{
75 // address range must begin and end on page boundaries
76 require( start % page_size == 0 );
77 require( size % page_size == 0 );
78 require( start + size <= 0x10000 );
79
80 int offset;
81 for ( offset = 0; offset < size; offset += page_size )
82 set_page( this, (start + offset) >> page_bits,
83 STATIC_CAST(char *,write) + offset,
84 STATIC_CAST(char const*,read ) + offset );
85}
diff --git a/lib/rbcodec/codecs/libgme/z80_cpu.h b/lib/rbcodec/codecs/libgme/z80_cpu.h
new file mode 100644
index 0000000000..341119b6b1
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/z80_cpu.h
@@ -0,0 +1,116 @@
1// Z80 CPU emulator
2
3// Game_Music_Emu 0.6-pre
4#ifndef Z80_CPU_H
5#define Z80_CPU_H
6
7#include "blargg_source.h"
8#include "blargg_endian.h"
9
10typedef int cpu_time_t;
11typedef int addr_t;
12
13enum { page_bits = 10 };
14enum { page_size = 1 << page_bits };
15enum { page_count = 0x10000 / page_size };
16
17// Can read this far past end of memory
18enum { cpu_padding = 0x100 };
19
20// Can read this many bytes past end of a page
21enum { page_padding = 4 };
22
23#ifdef BLARGG_BIG_ENDIAN
24 struct regs_t { byte b,c, d,e, h,l, flags,a; };
25#else
26 struct regs_t { byte c,b, e,d, l,h, a,flags; };
27#endif
28// BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
29
30struct pairs_t { uint16_t bc, de, hl, fa; };
31
32// Registers are not updated until run() returns
33struct registers_t {
34 uint16_t pc;
35 uint16_t sp;
36 uint16_t ix;
37 uint16_t iy;
38 union {
39 struct regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
40 struct pairs_t w; // w.bc, w.de, w.hl. w.fa
41 };
42 union {
43 struct regs_t b;
44 struct pairs_t w;
45 } alt;
46 byte iff1;
47 byte iff2;
48 byte r;
49 byte i;
50 byte im;
51};
52
53struct cpu_state_t {
54 byte const* read [page_count + 1];
55 byte * write [page_count + 1];
56 cpu_time_t base;
57 cpu_time_t time;
58};
59
60struct Z80_Cpu {
61 byte szpc [0x200];
62 cpu_time_t end_time_;
63
64 struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy within run()
65 struct cpu_state_t cpu_state_;
66
67 struct registers_t r;
68};
69
70void Z80_init( struct Z80_Cpu* this );
71
72// Clears registers and maps all pages to unmapped
73void Z80_reset( struct Z80_Cpu* this, void* unmapped_write, void const* unmapped_read );
74
75// TODO: split mapping out of CPU
76
77// Maps memory. Start and size must be multiple of page_size.
78void Z80_map_mem( struct Z80_Cpu* this, addr_t addr, int size, void* write, void const* read );
79
80// Time of beginning of next instruction
81static inline cpu_time_t Z80_time( struct Z80_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; }
82
83// Alter current time
84static inline void Z80_set_time( struct Z80_Cpu* this, cpu_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
85static inline void Z80_adjust_time( struct Z80_Cpu* this, int delta ) { this->cpu_state->time += delta; }
86
87#ifdef BLARGG_NONPORTABLE
88 #define Z80_CPU_OFFSET( addr ) (addr)
89#else
90 #define Z80_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
91#endif
92
93// Maps address to pointer to that byte
94static inline byte* Z80_write( struct Z80_Cpu* this, addr_t addr )
95{
96 return this->cpu_state->write [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
97}
98
99static inline byte const* Z80_read( struct Z80_Cpu* this, addr_t addr )
100{
101 return this->cpu_state->read [(unsigned) addr >> page_bits] + Z80_CPU_OFFSET( addr );
102}
103
104static inline void Z80_map_mem_rw( struct Z80_Cpu* this, addr_t addr, int size, void* p )
105{
106 Z80_map_mem( this, addr, size, p, p );
107}
108
109static inline void Z80_set_end_time( struct Z80_Cpu* this, cpu_time_t t )
110{
111 cpu_time_t delta = this->cpu_state->base - t;
112 this->cpu_state->base = t;
113 this->cpu_state->time += delta;
114}
115
116#endif
diff --git a/lib/rbcodec/codecs/libgme/z80_cpu_run.h b/lib/rbcodec/codecs/libgme/z80_cpu_run.h
new file mode 100644
index 0000000000..a453487bb0
--- /dev/null
+++ b/lib/rbcodec/codecs/libgme/z80_cpu_run.h
@@ -0,0 +1,1696 @@
1// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
2
3// Last validated with zexall 2009.12.05.
4// Doesn't implement the R register or immediate interrupt after EI.
5// Address wrap-around isn't completely correct, but is prevented from crashing emulator.
6// 16-bit memory accesses are made directly to mapped memory, instead of using macro.
7
8#if 0
9/* Define these macros in the source file before #including this file.
10- Parameters might be expressions, so they are best evaluated only once,
11though they NEVER have side-effects, so multiple evaluation is OK.
12- Output parameters might be a multiple-assignment expression like "a=x",
13so they must NOT be parenthesized.
14- Except where noted, time() and related functions will NOT work
15correctly inside a macro. TIME() is always correct, and between FLUSH_TIME() and
16CACHE_TIME() the normal time changing functions can be used.
17- Macros "returning" void may use a {} statement block. */
18
19 // 0 <= addr <= 0xFFFF + 0x100
20 // Optional; default uses whatever was set with map_mem()
21 int READ_MEM( addr_t );
22 void WRITE_MEM( addr_t, int data );
23
24 // 0 <= port <= 0xFFFF (apparently upper 8 bits are output by hardware)
25 void OUT_PORT( int port, int data );
26 int IN_PORT int port );
27
28 // Reference to Z80_Cpu object used for emulation
29 #define CPU cpu
30
31// The following can be used within macros:
32
33 // Current time
34 time_t TIME();
35
36 // Allows use of time functions
37 void FLUSH_TIME();
38
39 // Must be used before end of macro if FLUSH_TIME() was used earlier
40 void CACHE_TIME();
41
42// Configuration (optional; commented behavior if defined)
43
44 // Optimizes as if map_mem( 0, 0x10000, FLAT_MEM, FLAT_MEM ) is always in effect
45 #define FLAT_MEM my_mem_array
46
47 // If RST 7 ($FF) is encountered and PC = IDLE_ADDR, stops execution
48 #define IDLE_ADDR 0x1234
49
50 // Expanded just before beginning of code, to help debugger
51 #define CPU_BEGIN void my_run_cpu() {
52
53#endif
54
55/* Copyright (C) 2006-2008 Shay Green. This module is free software; you
56can redistribute it and/or modify it under the terms of the GNU Lesser
57General Public License as published by the Free Software Foundation; either
58version 2.1 of the License, or (at your option) any later version. This
59module is distributed in the hope that it will be useful, but WITHOUT ANY
60WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
61FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
62details. You should have received a copy of the GNU Lesser General Public
63License along with this module; if not, write to the Free Software Foundation,
64Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
65
66#ifdef CPU_BEGIN
67 CPU_BEGIN
68#endif
69
70#define R cpu->r
71
72// flags, named with hex value for clarity
73int const S80 = 0x80;
74int const Z40 = 0x40;
75int const F20 = 0x20;
76int const H10 = 0x10;
77int const F08 = 0x08;
78int const V04 = 0x04;
79int const P04 = 0x04;
80int const N02 = 0x02;
81int const C01 = 0x01;
82
83#define SZ28P( n ) cpu->szpc [n]
84#define SZ28PC( n ) cpu->szpc [n]
85#define SZ28C( n ) (cpu->szpc [n] & ~P04)
86#define SZ28( n ) SZ28C( n )
87
88#define SET_R( n ) (void) (R.r = n)
89#define GET_R() (R.r)
90
91// Time
92#define TIME() (s_time + s.base)
93#define FLUSH_TIME() {s.time = s_time;}
94#define CACHE_TIME() {s_time = s.time;}
95
96// Memory
97#define RW_MEM( addr, rw ) RW_PAGE( addr, rw ) [RW_OFFSET( addr )]
98#define READ_CODE( addr ) RW_MEM( addr, read )
99
100#ifdef FLAT_MEM
101 #define RW_PAGE( addr, rw ) FLAT_MEM
102 #define RW_OFFSET( addr ) (addr)
103 #define INSTR( off, addr ) READ_CODE( addr )
104#else
105 #define RW_PAGE( addr, rw ) s.rw [(unsigned) (addr) >> page_bits]
106 #define RW_OFFSET( addr ) Z80_CPU_OFFSET( addr )
107 #define INSTR( off, addr ) instr [off]
108#endif
109
110#ifndef READ_MEM
111 #define READ_MEM( addr ) RW_MEM( addr, read )
112#endif
113
114#ifndef WRITE_MEM
115 #define WRITE_MEM( addr, data ) (RW_MEM( addr, write ) = data)
116#endif
117
118#define READ_WORD( addr ) GET_LE16( &RW_MEM( addr, read ) )
119#define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data )
120
121// Truncation
122#define BYTE( n ) ((uint8_t ) (n)) /* (unsigned) n & 0xFF */
123#define SBYTE( n ) ((int8_t ) (n)) /* (BYTE( n ) ^ 0x80) - 0x80 */
124#define WORD( n ) ((uint16_t) (n)) /* (unsigned) n & 0xFFFF */
125
126// Misc
127#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
128#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
129#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
130#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
131
132#ifdef BLARGG_BIG_ENDIAN
133 #define R8( n, offset ) ((r.r8_ - offset) [n])
134#elif BLARGG_LITTLE_ENDIAN
135 #define R8( n, offset ) ((r.r8_ - offset) [(n) ^ 1])
136#else
137 #error "Byte order of CPU must be known"
138#endif
139
140#define R16( n, shift, offset ) (r.r16_ [((unsigned) (n) >> shift) - (offset >> shift)])
141
142#define EX( x, y ) \
143 {\
144 int temp = x;\
145 x = y;\
146 y = temp;\
147 }
148
149#define EXX( name ) \
150 EX( R.alt.name, r.name )
151
152bool warning = false;
153{
154 struct cpu_state_t s;
155 #ifdef FLAT_MEM
156 s.base = cpu->cpu_state_.base;
157 #else
158 s = cpu->cpu_state_;
159 #endif
160 cpu->cpu_state = &s;
161
162
163 union r_t {
164 struct regs_t b;
165 struct pairs_t w;
166 byte r8_ [8]; // indexed
167 uint16_t r16_ [4];
168 } r;
169 r.b = R.b;
170
171 cpu_time_t s_time = cpu->cpu_state_.time;
172 int pc = R.pc;
173 int sp = R.sp;
174 int ix = R.ix; // TODO: keep in memory for direct access?
175 int iy = R.iy;
176 int flags = R.b.flags;
177
178 //goto loop; // confuses optimizer
179 s_time += 7;
180 pc -= 2;
181
182call_not_taken:
183 s_time -= 7;
184jp_not_taken:
185 pc += 2;
186loop:
187
188 check( (unsigned) pc < 0x10000 + 1 ); // +1 so emulator can catch wrap-around
189 check( (unsigned) sp < 0x10000 );
190 check( (unsigned) flags < 0x100 );
191 check( (unsigned) ix < 0x10000 );
192 check( (unsigned) iy < 0x10000 );
193
194 byte const* instr = RW_PAGE( pc, read );
195
196 int opcode;
197
198 if ( RW_OFFSET( ~0 ) == ~0 )
199 {
200 opcode = instr [RW_OFFSET( pc )];
201 pc++;
202 instr += RW_OFFSET( pc );
203 }
204 else
205 {
206 instr += RW_OFFSET( pc );
207 opcode = *instr++;
208 pc++;
209 }
210
211 static byte const clock_table [256 * 2] = {
212 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
213 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
214 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
215 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, // 2
216 7,10,13, 6,11,11,10, 4, 7,11,13, 6, 4, 4, 7, 4, // 3
217 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
218 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
219 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
220 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
221 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
222 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
223 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
224 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
225 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
226 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
227 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
228 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
229
230 // high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
231 //0 1 2 3 4 5 6 7 8 9 A B C D E F
232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
233 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
234 0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
235 0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
236 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
237 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
238 0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
239 0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
240 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
241 0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
242 0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
243 0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
244 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
245 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
246 0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
247 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
248 };
249
250 if ( s_time >= 0 )
251 goto out_of_time;
252 s_time += clock_table [opcode];
253
254 #ifdef Z80_CPU_LOG_H
255 //log_opcode( opcode, READ_CODE( pc ) );
256 z80_cpu_log( "log.txt", pc - 1, opcode, READ_CODE( pc ),
257 READ_CODE( pc + 1 ), READ_CODE( pc + 2 ) );
258 z80_log_regs( r.b.a, r.w.bc, r.w.de, r.w.hl, sp, ix, iy );
259 #endif
260
261#define GET_ADDR() GET_LE16( &INSTR( 0, pc ) )
262
263 int data;
264 data = INSTR( 0, pc );
265
266 switch ( opcode )
267 {
268// Common
269
270 case 0x00: // NOP
271 CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
272 goto loop;
273
274 case 0x08:{// EX AF,AF'
275 EXX( b.a );
276 EX( R.alt.b.flags, flags );
277 goto loop;
278 }
279
280 case 0xD3: // OUT (imm),A
281 pc++;
282 OUT_PORT( (data + r.b.a * 0x100), r.b.a );
283 goto loop;
284
285 case 0x2E: // LD L,imm
286 pc++;
287 r.b.l = data;
288 goto loop;
289
290 case 0x3E: // LD A,imm
291 pc++;
292 r.b.a = data;
293 goto loop;
294
295 case 0x3A:{// LD A,(addr)
296 int addr = GET_ADDR();
297 pc += 2;
298 r.b.a = READ_MEM( addr );
299 goto loop;
300 }
301
302// Conditional
303
304#define ZERO (flags & Z40)
305#define CARRY (flags & C01)
306#define EVEN (flags & P04)
307#define MINUS (flags & S80)
308
309// JR
310// TODO: more efficient way to handle negative branch that wraps PC around
311#define JR_( cond, clocks ) {\
312 pc++;\
313 if ( !(cond) )\
314 goto loop;\
315 int offset = SBYTE( data );\
316 pc = WORD( pc + offset );\
317 s_time += clocks;\
318 goto loop;\
319}
320
321#define JR( cond ) JR_( cond, 5 )
322
323 case 0x20: JR( !ZERO ) // JR NZ,disp
324 case 0x28: JR( ZERO ) // JR Z,disp
325 case 0x30: JR( !CARRY ) // JR NC,disp
326 case 0x38: JR( CARRY ) // JR C,disp
327 case 0x18: JR_( true,0) // JR disp
328
329 case 0x10:{// DJNZ disp
330 int temp = r.b.b - 1;
331 r.b.b = temp;
332 JR( temp )
333 }
334
335// JP
336#define JP( cond ) \
337 if ( !(cond) )\
338 goto jp_not_taken;\
339 pc = GET_ADDR();\
340 goto loop;
341
342 case 0xC2: JP( !ZERO ) // JP NZ,addr
343 case 0xCA: JP( ZERO ) // JP Z,addr
344 case 0xD2: JP( !CARRY ) // JP NC,addr
345 case 0xDA: JP( CARRY ) // JP C,addr
346 case 0xE2: JP( !EVEN ) // JP PO,addr
347 case 0xEA: JP( EVEN ) // JP PE,addr
348 case 0xF2: JP( !MINUS ) // JP P,addr
349 case 0xFA: JP( MINUS ) // JP M,addr
350
351 case 0xC3: // JP addr
352 pc = GET_ADDR();
353 goto loop;
354
355 case 0xE9: // JP HL
356 pc = r.w.hl;
357 goto loop;
358
359// RET
360#define RET( cond ) \
361 if ( cond )\
362 goto ret_taken;\
363 s_time -= 6;\
364 goto loop;
365
366 case 0xC0: RET( !ZERO ) // RET NZ
367 case 0xC8: RET( ZERO ) // RET Z
368 case 0xD0: RET( !CARRY ) // RET NC
369 case 0xD8: RET( CARRY ) // RET C
370 case 0xE0: RET( !EVEN ) // RET PO
371 case 0xE8: RET( EVEN ) // RET PE
372 case 0xF0: RET( !MINUS ) // RET P
373 case 0xF8: RET( MINUS ) // RET M
374
375 case 0xC9: // RET
376 ret_taken:
377 pc = READ_WORD( sp );
378 sp = WORD( sp + 2 );
379 goto loop;
380
381// CALL
382#define CALL( cond ) \
383 if ( cond )\
384 goto call_taken;\
385 goto call_not_taken;
386
387 case 0xC4: CALL( !ZERO ) // CALL NZ,addr
388 case 0xCC: CALL( ZERO ) // CALL Z,addr
389 case 0xD4: CALL( !CARRY ) // CALL NC,addr
390 case 0xDC: CALL( CARRY ) // CALL C,addr
391 case 0xE4: CALL( !EVEN ) // CALL PO,addr
392 case 0xEC: CALL( EVEN ) // CALL PE,addr
393 case 0xF4: CALL( !MINUS ) // CALL P,addr
394 case 0xFC: CALL( MINUS ) // CALL M,addr
395
396 case 0xCD:{// CALL addr
397 call_taken: {
398 int addr = pc + 2;
399 pc = GET_ADDR();
400 sp = WORD( sp - 2 );
401 WRITE_WORD( sp, addr );
402 goto loop;
403 }
404 }
405
406 case 0xFF: // RST
407 #ifdef IDLE_ADDR
408 if ( pc == IDLE_ADDR + 1 )
409 goto hit_idle_addr;
410 #else
411 if ( pc > 0x10000 )
412 {
413 pc = WORD( pc - 1 );
414 s_time -= 11;
415 goto loop;
416 }
417 #endif
418 CASE7( C7, CF, D7, DF, E7, EF, F7 ):
419 data = pc;
420 pc = opcode & 0x38;
421 #ifdef RST_BASE
422 pc += RST_BASE;
423 #endif
424 goto push_data;
425
426// PUSH/POP
427 case 0xF5: // PUSH AF
428 data = r.b.a * 0x100u + flags;
429 goto push_data;
430
431 case 0xC5: // PUSH BC
432 case 0xD5: // PUSH DE
433 case 0xE5: // PUSH HL
434 data = R16( opcode, 4, 0xC5 );
435 push_data:
436 sp = WORD( sp - 2 );
437 WRITE_WORD( sp, data );
438 goto loop;
439
440 case 0xF1: // POP AF
441 flags = READ_MEM( sp );
442 r.b.a = READ_MEM( (sp + 1) );
443 sp = WORD( sp + 2 );
444 goto loop;
445
446 case 0xC1: // POP BC
447 case 0xD1: // POP DE
448 case 0xE1: // POP HL
449 R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
450 sp = WORD( sp + 2 );
451 goto loop;
452
453// ADC/ADD/SBC/SUB
454 case 0x96: // SUB (HL)
455 case 0x86: // ADD (HL)
456 flags &= ~C01;
457 case 0x9E: // SBC (HL)
458 case 0x8E: // ADC (HL)
459 data = READ_MEM( r.w.hl );
460 goto adc_data;
461
462 case 0xD6: // SUB A,imm
463 case 0xC6: // ADD imm
464 flags &= ~C01;
465 case 0xDE: // SBC A,imm
466 case 0xCE: // ADC imm
467 pc++;
468 goto adc_data;
469
470 CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
471 CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
472 flags &= ~C01;
473 CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
474 CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
475 data = R8( opcode & 7, 0 );
476 adc_data: {
477 int result = data + (flags & C01);
478 data ^= r.b.a;
479 flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
480 if ( flags )
481 result = -result;
482 result += r.b.a;
483 data ^= result;
484 flags +=(data & H10) +
485 ((data + 0x80) >> 6 & V04) +
486 SZ28C( result & 0x1FF );
487 r.b.a = result;
488 goto loop;
489 }
490
491// CP
492 case 0xBE: // CP (HL)
493 data = READ_MEM( r.w.hl );
494 goto cp_data;
495
496 case 0xFE: // CP imm
497 pc++;
498 goto cp_data;
499
500 CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
501 data = R8( opcode, 0xB8 );
502 cp_data: {
503 int result = r.b.a - data;
504 flags = N02 + (data & (F20 | F08)) + (result >> 8 & C01);
505 data ^= r.b.a;
506 flags +=(((result ^ r.b.a) & data) >> 5 & V04) +
507 (((data & H10) ^ result) & (S80 | H10));
508 if ( BYTE( result ) )
509 goto loop;
510 flags += Z40;
511 goto loop;
512 }
513
514// ADD HL,r.w
515
516 case 0x39: // ADD HL,SP
517 data = sp;
518 goto add_hl_data;
519
520 case 0x09: // ADD HL,BC
521 case 0x19: // ADD HL,DE
522 case 0x29: // ADD HL,HL
523 data = R16( opcode, 4, 0x09 );
524 add_hl_data: {
525 int sum = r.w.hl + data;
526 data ^= r.w.hl;
527 r.w.hl = sum;
528 flags = (flags & (S80 | Z40 | V04)) +
529 (sum >> 16) +
530 (sum >> 8 & (F20 | F08)) +
531 ((data ^ sum) >> 8 & H10);
532 goto loop;
533 }
534
535 case 0x27:{// DAA
536 int a = r.b.a;
537 if ( a > 0x99 )
538 flags |= C01;
539
540 int adjust = 0x60 * (flags & C01);
541
542 if ( flags & H10 || (a & 0x0F) > 9 )
543 adjust += 0x06;
544
545 if ( flags & N02 )
546 adjust = -adjust;
547 a += adjust;
548
549 flags = (flags & (C01 | N02)) +
550 ((r.b.a ^ a) & H10) +
551 SZ28P( BYTE( a ) );
552 r.b.a = a;
553 goto loop;
554 }
555
556// INC/DEC
557 case 0x34: // INC (HL)
558 data = READ_MEM( r.w.hl ) + 1;
559 WRITE_MEM( r.w.hl, data );
560 goto inc_set_flags;
561
562 CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
563 data = ++R8( opcode >> 3, 0 );
564 inc_set_flags:
565 flags = (flags & C01) +
566 (((data & 0x0F) - 1) & H10) +
567 SZ28( BYTE( data ) );
568 if ( data != 0x80 )
569 goto loop;
570 flags += V04;
571 goto loop;
572
573 case 0x35: // DEC (HL)
574 data = READ_MEM( r.w.hl ) - 1;
575 WRITE_MEM( r.w.hl, data );
576 goto dec_set_flags;
577
578 CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
579 data = --R8( opcode >> 3, 0 );
580 dec_set_flags:
581 flags = (flags & C01) + N02 +
582 (((data & 0x0F) + 1) & H10) +
583 SZ28( BYTE( data ) );
584 if ( data != 0x7F )
585 goto loop;
586 flags += V04;
587 goto loop;
588
589 case 0x03: // INC BC
590 case 0x13: // INC DE
591 case 0x23: // INC HL
592 R16( opcode, 4, 0x03 )++;
593 goto loop;
594
595 case 0x33: // INC SP
596 sp = WORD( sp + 1 );
597 goto loop;
598
599 case 0x0B: // DEC BC
600 case 0x1B: // DEC DE
601 case 0x2B: // DEC HL
602 R16( opcode, 4, 0x0B )--;
603 goto loop;
604
605 case 0x3B: // DEC SP
606 sp = WORD( sp - 1 );
607 goto loop;
608
609// AND
610 case 0xA6: // AND (HL)
611 data = READ_MEM( r.w.hl );
612 goto and_data;
613
614 case 0xE6: // AND imm
615 pc++;
616 goto and_data;
617
618 CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
619 data = R8( opcode, 0xA0 );
620 and_data:
621 r.b.a &= data;
622 flags = SZ28P( r.b.a ) + H10;
623 goto loop;
624
625// OR
626 case 0xB6: // OR (HL)
627 data = READ_MEM( r.w.hl );
628 goto or_data;
629
630 case 0xF6: // OR imm
631 pc++;
632 goto or_data;
633
634 CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
635 data = R8( opcode, 0xB0 );
636 or_data:
637 r.b.a |= data;
638 flags = SZ28P( r.b.a );
639 goto loop;
640
641// XOR
642 case 0xAE: // XOR (HL)
643 data = READ_MEM( r.w.hl );
644 goto xor_data;
645
646 case 0xEE: // XOR imm
647 pc++;
648 goto xor_data;
649
650 CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
651 data = R8( opcode, 0xA8 );
652 xor_data:
653 r.b.a ^= data;
654 flags = SZ28P( r.b.a );
655 goto loop;
656
657// LD
658 CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
659 WRITE_MEM( r.w.hl, R8( opcode, 0x70 ) );
660 goto loop;
661
662 CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
663 CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
664 CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
665 CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
666 CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
667 CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
668 CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
669 R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
670 goto loop;
671
672 CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
673 R8( opcode >> 3, 0 ) = data;
674 pc++;
675 goto loop;
676
677 case 0x36: // LD (HL),imm
678 pc++;
679 WRITE_MEM( r.w.hl, data );
680 goto loop;
681
682 CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
683 R8( opcode >> 3, 8 ) = READ_MEM( r.w.hl );
684 goto loop;
685
686 case 0x01: // LD r.w,imm
687 case 0x11:
688 case 0x21:
689 R16( opcode, 4, 0x01 ) = GET_ADDR();
690 pc += 2;
691 goto loop;
692
693 case 0x31: // LD sp,imm
694 sp = GET_ADDR();
695 pc += 2;
696 goto loop;
697
698 case 0x2A:{// LD HL,(addr)
699 int addr = GET_ADDR();
700 pc += 2;
701 r.w.hl = READ_WORD( addr );
702 goto loop;
703 }
704
705 case 0x32:{// LD (addr),A
706 int addr = GET_ADDR();
707 pc += 2;
708 WRITE_MEM( addr, r.b.a );
709 goto loop;
710 }
711
712 case 0x22:{// LD (addr),HL
713 int addr = GET_ADDR();
714 pc += 2;
715 WRITE_WORD( addr, r.w.hl );
716 goto loop;
717 }
718
719 case 0x02: // LD (BC),A
720 case 0x12: // LD (DE),A
721 WRITE_MEM( R16( opcode, 4, 0x02 ), r.b.a );
722 goto loop;
723
724 case 0x0A: // LD A,(BC)
725 case 0x1A: // LD A,(DE)
726 r.b.a = READ_MEM( R16( opcode, 4, 0x0A ) );
727 goto loop;
728
729 case 0xF9: // LD SP,HL
730 sp = r.w.hl;
731 goto loop;
732
733// Rotate
734
735 case 0x07:{// RLCA
736 int temp = r.b.a;
737 temp = (temp << 1) + (temp >> 7);
738 flags = (flags & (S80 | Z40 | P04)) +
739 (temp & (F20 | F08 | C01));
740 r.b.a = temp;
741 goto loop;
742 }
743
744 case 0x0F:{// RRCA
745 int temp = r.b.a;
746 flags = (flags & (S80 | Z40 | P04)) +
747 (temp & C01);
748 temp = (temp << 7) + (temp >> 1);
749 flags += temp & (F20 | F08);
750 r.b.a = temp;
751 goto loop;
752 }
753
754 case 0x17:{// RLA
755 int temp = (r.b.a << 1) + (flags & C01);
756 flags = (flags & (S80 | Z40 | P04)) +
757 (temp & (F20 | F08)) +
758 (temp >> 8);
759 r.b.a = temp;
760 goto loop;
761 }
762
763 case 0x1F:{// RRA
764 int temp = (flags << 7) + (r.b.a >> 1);
765 flags = (flags & (S80 | Z40 | P04)) +
766 (temp & (F20 | F08)) +
767 (r.b.a & C01);
768 r.b.a = temp;
769 goto loop;
770 }
771
772// Misc
773 case 0x2F:{// CPL
774 int temp = ~r.b.a;
775 flags = (flags & (S80 | Z40 | P04 | C01)) +
776 (temp & (F20 | F08)) +
777 (H10 | N02);
778 r.b.a = temp;
779 goto loop;
780 }
781
782 case 0x3F:{// CCF
783 flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) +
784 (flags << 4 & H10) +
785 (r.b.a & (F20 | F08));
786 goto loop;
787 }
788
789 case 0x37: // SCF
790 flags = ((flags & (S80 | Z40 | P04)) | C01) +
791 (r.b.a & (F20 | F08));
792 goto loop;
793
794 case 0xDB: // IN A,(imm)
795 pc++;
796 r.b.a = IN_PORT( (data + r.b.a * 0x100) );
797 goto loop;
798
799 case 0xE3:{// EX (SP),HL
800 int temp = READ_WORD( sp );
801 WRITE_WORD( sp, r.w.hl );
802 r.w.hl = temp;
803 goto loop;
804 }
805
806 case 0xEB: // EX DE,HL
807 EX( r.w.hl, r.w.de );
808 goto loop;
809
810 case 0xD9: // EXX DE,HL
811 EXX( w.bc );
812 EXX( w.de );
813 EXX( w.hl );
814 goto loop;
815
816 case 0xF3: // DI
817 R.iff1 = 0;
818 R.iff2 = 0;
819 goto loop;
820
821 case 0xFB: // EI
822 R.iff1 = 1;
823 R.iff2 = 1;
824 // TODO: delayed effect
825 goto loop;
826
827 case 0x76: // HALT
828 goto halt;
829
830//////////////////////////////////////// CB prefix
831 {
832 case 0xCB:
833 pc++;
834 switch ( data )
835 {
836
837 // Rotate left
838
839 #define RLC( read, write ) {\
840 int result = read;\
841 result = BYTE( result << 1 ) + (result >> 7);\
842 flags = SZ28P( result ) + (result & C01);\
843 write;\
844 goto loop;\
845 }
846
847 case 0x06: // RLC (HL)
848 s_time += 7;
849 data = r.w.hl;
850 rlc_data_addr:
851 RLC( READ_MEM( data ), WRITE_MEM( data, result ) )
852
853 CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
854 byte* reg = &R8( data, 0 );
855 RLC( *reg, *reg = result )
856 }
857
858 #define RL( read, write ) {\
859 int result = (read << 1) + (flags & C01);\
860 flags = SZ28PC( result );\
861 write;\
862 goto loop;\
863 }
864
865 case 0x16: // RL (HL)
866 s_time += 7;
867 data = r.w.hl;
868 rl_data_addr:
869 RL( READ_MEM( data ), WRITE_MEM( data, result ) )
870
871 CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
872 byte* reg = &R8( data, 0x10 );
873 RL( *reg, *reg = result )
874 }
875
876 #define SLA( read, low_bit, write ) {\
877 int result = (read << 1) + low_bit;\
878 flags = SZ28PC( result );\
879 write;\
880 goto loop;\
881 }
882
883 case 0x26: // SLA (HL)
884 s_time += 7;
885 data = r.w.hl;
886 sla_data_addr:
887 SLA( READ_MEM( data ), 0, WRITE_MEM( data, result ) )
888
889 CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
890 byte* reg = &R8( data, 0x20 );
891 SLA( *reg, 0, *reg = result )
892 }
893
894 case 0x36: // SLL (HL)
895 s_time += 7;
896 data = r.w.hl;
897 sll_data_addr:
898 SLA( READ_MEM( data ), 1, WRITE_MEM( data, result ) )
899
900 CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
901 byte* reg = &R8( data, 0x30 );
902 SLA( *reg, 1, *reg = result )
903 }
904
905 // Rotate right
906
907 #define RRC( read, write ) {\
908 int result = read;\
909 flags = result & C01;\
910 result = BYTE( result << 7 ) + (result >> 1);\
911 flags += SZ28P( result );\
912 write;\
913 goto loop;\
914 }
915
916 case 0x0E: // RRC (HL)
917 s_time += 7;
918 data = r.w.hl;
919 rrc_data_addr:
920 RRC( READ_MEM( data ), WRITE_MEM( data, result ) )
921
922 CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
923 byte* reg = &R8( data, 0x08 );
924 RRC( *reg, *reg = result )
925 }
926
927 #define RR( read, write ) {\
928 int result = read;\
929 int temp = result & C01;\
930 result = BYTE( flags << 7 ) + (result >> 1);\
931 flags = SZ28P( result ) + temp;\
932 write;\
933 goto loop;\
934 }
935
936 case 0x1E: // RR (HL)
937 s_time += 7;
938 data = r.w.hl;
939 rr_data_addr:
940 RR( READ_MEM( data ), WRITE_MEM( data, result ) )
941
942 CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
943 byte* reg = &R8( data, 0x18 );
944 RR( *reg, *reg = result )
945 }
946
947 #define SRA( read, write ) {\
948 int result = read;\
949 flags = result & C01;\
950 result = (result & 0x80) + (result >> 1);\
951 flags += SZ28P( result );\
952 write;\
953 goto loop;\
954 }
955
956 case 0x2E: // SRA (HL)
957 data = r.w.hl;
958 s_time += 7;
959 sra_data_addr:
960 SRA( READ_MEM( data ), WRITE_MEM( data, result ) )
961
962 CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
963 byte* reg = &R8( data, 0x28 );
964 SRA( *reg, *reg = result )
965 }
966
967 #define SRL( read, write ) {\
968 int result = read;\
969 flags = result & C01;\
970 result >>= 1;\
971 flags += SZ28P( result );\
972 write;\
973 goto loop;\
974 }
975
976 case 0x3E: // SRL (HL)
977 s_time += 7;
978 data = r.w.hl;
979 srl_data_addr:
980 SRL( READ_MEM( data ), WRITE_MEM( data, result ) )
981
982 CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
983 byte* reg = &R8( data, 0x38 );
984 SRL( *reg, *reg = result )
985 }
986
987 // BIT
988 {
989 int temp;
990 CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
991 s_time += 4;
992 temp = READ_MEM( r.w.hl );
993 flags &= C01;
994 goto bit_temp;
995 CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
996 CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
997 CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
998 CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
999 CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
1000 CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
1001 CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
1002 CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
1003 temp = R8( data & 7, 0 );
1004 flags = (flags & C01) + (temp & (F20 | F08));
1005 bit_temp:
1006 temp = temp & (1 << (data >> 3 & 7));
1007 flags += (temp & S80) + H10;
1008 flags += (unsigned) --temp >> 8 & (Z40 | P04);
1009 goto loop;
1010 }
1011
1012 // SET/RES
1013 CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
1014 CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
1015 s_time += 7;
1016 int temp = READ_MEM( r.w.hl );
1017 int bit = 1 << (data >> 3 & 7);
1018 temp |= bit; // SET
1019 if ( !(data & 0x40) )
1020 temp ^= bit; // RES
1021 WRITE_MEM( r.w.hl, temp );
1022 goto loop;
1023 }
1024
1025 CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
1026 CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
1027 CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
1028 CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
1029 CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
1030 CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
1031 CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
1032 CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
1033 R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
1034 goto loop;
1035
1036 CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
1037 CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
1038 CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
1039 CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
1040 CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
1041 CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
1042 CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
1043 CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
1044 R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
1045 goto loop;
1046 }
1047 assert( false );
1048 }
1049
1050#undef GET_ADDR
1051#define GET_ADDR() GET_LE16( &INSTR( 1, pc ) )
1052
1053//////////////////////////////////////// ED prefix
1054 {
1055 case 0xED:
1056 pc++;
1057 s_time += (clock_table + 256) [data] >> 4;
1058 switch ( data )
1059 {
1060 {
1061 int temp;
1062 case 0x72: // SBC HL,SP
1063 case 0x7A: // ADC HL,SP
1064 temp = sp;
1065 if ( 0 )
1066 case 0x42: // SBC HL,BC
1067 case 0x52: // SBC HL,DE
1068 case 0x62: // SBC HL,HL
1069 case 0x4A: // ADC HL,BC
1070 case 0x5A: // ADC HL,DE
1071 case 0x6A: // ADC HL,HL
1072 temp = R16( data >> 3 & 6, 1, 0 );
1073 int sum = temp + (flags & C01);
1074 flags = ~data >> 2 & N02;
1075 if ( flags )
1076 sum = -sum;
1077 sum += r.w.hl;
1078 temp ^= r.w.hl;
1079 temp ^= sum;
1080 flags +=(sum >> 16 & C01) +
1081 (temp >> 8 & H10) +
1082 (sum >> 8 & (S80 | F20 | F08)) +
1083 ((temp + 0x8000) >> 14 & V04);
1084 r.w.hl = sum;
1085 if ( WORD( sum ) )
1086 goto loop;
1087 flags += Z40;
1088 goto loop;
1089 }
1090
1091 CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
1092 int temp = IN_PORT( r.w.bc );
1093 R8( data >> 3, 8 ) = temp;
1094 flags = (flags & C01) + SZ28P( temp );
1095 goto loop;
1096 }
1097
1098 case 0x71: // OUT (C),0
1099 r.b.flags = 0;
1100 CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
1101 OUT_PORT( r.w.bc, R8( data >> 3, 8 ) );
1102 goto loop;
1103
1104 {
1105 int temp;
1106 case 0x73: // LD (ADDR),SP
1107 temp = sp;
1108 if ( 0 )
1109 case 0x43: // LD (ADDR),BC
1110 case 0x53: // LD (ADDR),DE
1111 temp = R16( data, 4, 0x43 );
1112 int addr = GET_ADDR();
1113 pc += 2;
1114 WRITE_WORD( addr, temp );
1115 goto loop;
1116 }
1117
1118 case 0x4B: // LD BC,(ADDR)
1119 case 0x5B:{// LD DE,(ADDR)
1120 int addr = GET_ADDR();
1121 pc += 2;
1122 R16( data, 4, 0x4B ) = READ_WORD( addr );
1123 goto loop;
1124 }
1125
1126 case 0x7B:{// LD SP,(ADDR)
1127 int addr = GET_ADDR();
1128 pc += 2;
1129 sp = READ_WORD( addr );
1130 goto loop;
1131 }
1132
1133 case 0x67:{// RRD
1134 int temp = READ_MEM( r.w.hl );
1135 WRITE_MEM( r.w.hl, ((r.b.a << 4) + (temp >> 4)) );
1136 temp = (r.b.a & 0xF0) + (temp & 0x0F);
1137 flags = (flags & C01) + SZ28P( temp );
1138 r.b.a = temp;
1139 goto loop;
1140 }
1141
1142 case 0x6F:{// RLD
1143 int temp = READ_MEM( r.w.hl );
1144 WRITE_MEM( r.w.hl, ((temp << 4) + (r.b.a & 0x0F)) );
1145 temp = (r.b.a & 0xF0) + (temp >> 4);
1146 flags = (flags & C01) + SZ28P( temp );
1147 r.b.a = temp;
1148 goto loop;
1149 }
1150
1151 CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
1152 opcode = 0x10; // flag to do SBC instead of ADC
1153 flags &= ~C01;
1154 data = r.b.a;
1155 r.b.a = 0;
1156 goto adc_data;
1157
1158 {
1159 int inc;
1160 case 0xA9: // CPD
1161 case 0xB9: // CPDR
1162 inc = -1;
1163 if ( 0 )
1164 case 0xA1: // CPI
1165 case 0xB1: // CPIR
1166 inc = +1;
1167 int addr = r.w.hl;
1168 r.w.hl = addr + inc;
1169 int temp = READ_MEM( addr );
1170
1171 int result = r.b.a - temp;
1172 flags = (flags & C01) + N02 +
1173 ((((temp ^ r.b.a) & H10) ^ result) & (S80 | H10));
1174
1175 if ( !BYTE( result ) )
1176 flags += Z40;
1177 result -= (flags & H10) >> 4;
1178 flags += result & F08;
1179 flags += result << 4 & F20;
1180 if ( !--r.w.bc )
1181 goto loop;
1182
1183 flags += V04;
1184 if ( flags & Z40 || data < 0xB0 )
1185 goto loop;
1186
1187 pc -= 2;
1188 s_time += 5;
1189 goto loop;
1190 }
1191
1192 {
1193 int inc;
1194 case 0xA8: // LDD
1195 case 0xB8: // LDDR
1196 inc = -1;
1197 if ( 0 )
1198 case 0xA0: // LDI
1199 case 0xB0: // LDIR
1200 inc = +1;
1201 int addr = r.w.hl;
1202 r.w.hl = addr + inc;
1203 int temp = READ_MEM( addr );
1204
1205 addr = r.w.de;
1206 r.w.de = addr + inc;
1207 WRITE_MEM( addr, temp );
1208
1209 temp += r.b.a;
1210 flags = (flags & (S80 | Z40 | C01)) +
1211 (temp & F08) + (temp << 4 & F20);
1212 if ( !--r.w.bc )
1213 goto loop;
1214
1215 flags += V04;
1216 if ( data < 0xB0 )
1217 goto loop;
1218
1219 pc -= 2;
1220 s_time += 5;
1221 goto loop;
1222 }
1223
1224 {
1225 int inc;
1226 case 0xAB: // OUTD
1227 case 0xBB: // OTDR
1228 inc = -1;
1229 if ( 0 )
1230 case 0xA3: // OUTI
1231 case 0xB3: // OTIR
1232 inc = +1;
1233 int addr = r.w.hl;
1234 r.w.hl = addr + inc;
1235 int temp = READ_MEM( addr );
1236
1237 int b = --r.b.b;
1238 flags = (temp >> 6 & N02) + SZ28( b );
1239 if ( b && data >= 0xB0 )
1240 {
1241 pc -= 2;
1242 s_time += 5;
1243 }
1244
1245 OUT_PORT( r.w.bc, temp );
1246 goto loop;
1247 }
1248
1249 {
1250 int inc;
1251 case 0xAA: // IND
1252 case 0xBA: // INDR
1253 inc = -1;
1254 if ( 0 )
1255 case 0xA2: // INI
1256 case 0xB2: // INIR
1257 inc = +1;
1258
1259 int addr = r.w.hl;
1260 r.w.hl = addr + inc;
1261
1262 int temp = IN_PORT( r.w.bc );
1263
1264 int b = --r.b.b;
1265 flags = (temp >> 6 & N02) + SZ28( b );
1266 if ( b && data >= 0xB0 )
1267 {
1268 pc -= 2;
1269 s_time += 5;
1270 }
1271
1272 WRITE_MEM( addr, temp );
1273 goto loop;
1274 }
1275
1276 case 0x47: // LD I,A
1277 R.i = r.b.a;
1278 goto loop;
1279
1280 case 0x4F: // LD R,A
1281 SET_R( r.b.a );
1282 dprintf( "LD R,A not supported\n" );
1283 warning = true;
1284 goto loop;
1285
1286 case 0x57: // LD A,I
1287 r.b.a = R.i;
1288 goto ld_ai_common;
1289
1290 case 0x5F: // LD A,R
1291 r.b.a = GET_R();
1292 dprintf( "LD A,R not supported\n" );
1293 warning = true;
1294 ld_ai_common:
1295 flags = (flags & C01) + SZ28( r.b.a ) + (R.iff2 << 2 & V04);
1296 goto loop;
1297
1298 CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
1299 R.iff1 = R.iff2;
1300 goto ret_taken;
1301
1302 case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
1303 R.im = 0;
1304 goto loop;
1305
1306 case 0x56: case 0x76: // IM 1
1307 R.im = 1;
1308 goto loop;
1309
1310 case 0x5E: case 0x7E: // IM 2
1311 R.im = 2;
1312 goto loop;
1313
1314 default:
1315 dprintf( "Opcode $ED $%02X not supported\n", data );
1316 warning = true;
1317 goto loop;
1318 }
1319 assert( false );
1320 }
1321
1322//////////////////////////////////////// DD/FD prefix
1323 {
1324 int ixy;
1325 case 0xDD:
1326 ixy = ix;
1327 goto ix_prefix;
1328 case 0xFD:
1329 ixy = iy;
1330 ix_prefix:
1331 pc++;
1332 int data2 = READ_CODE( pc );
1333 s_time += (clock_table + 256) [data] & 0x0F;
1334 switch ( data )
1335 {
1336 // TODO: more efficient way of avoid negative address
1337 // TODO: avoid using this as argument to READ_MEM() since it is evaluated twice
1338 #define IXY_DISP( ixy, disp ) WORD( (ixy ) + (disp))
1339
1340 #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
1341
1342 // ADD/ADC/SUB/SBC
1343
1344 case 0x96: // SUB (IXY+disp)
1345 case 0x86: // ADD (IXY+disp)
1346 flags &= ~C01;
1347 case 0x9E: // SBC (IXY+disp)
1348 case 0x8E: // ADC (IXY+disp)
1349 pc++;
1350 opcode = data;
1351 data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1352 goto adc_data;
1353
1354 case 0x94: // SUB HXY
1355 case 0x84: // ADD HXY
1356 flags &= ~C01;
1357 case 0x9C: // SBC HXY
1358 case 0x8C: // ADC HXY
1359 opcode = data;
1360 data = ixy >> 8;
1361 goto adc_data;
1362
1363 case 0x95: // SUB LXY
1364 case 0x85: // ADD LXY
1365 flags &= ~C01;
1366 case 0x9D: // SBC LXY
1367 case 0x8D: // ADC LXY
1368 opcode = data;
1369 data = BYTE( ixy );
1370 goto adc_data;
1371
1372 {
1373 int temp;
1374 case 0x39: // ADD IXY,SP
1375 temp = sp;
1376 goto add_ixy_data;
1377
1378 case 0x29: // ADD IXY,HL
1379 temp = ixy;
1380 goto add_ixy_data;
1381
1382 case 0x09: // ADD IXY,BC
1383 case 0x19: // ADD IXY,DE
1384 temp = R16( data, 4, 0x09 );
1385 add_ixy_data: {
1386 int sum = ixy + temp;
1387 temp ^= ixy;
1388 ixy = WORD( sum );
1389 flags = (flags & (S80 | Z40 | V04)) +
1390 (sum >> 16) +
1391 (sum >> 8 & (F20 | F08)) +
1392 ((temp ^ sum) >> 8 & H10);
1393 goto set_ixy;
1394 }
1395 }
1396
1397 // AND
1398 case 0xA6: // AND (IXY+disp)
1399 pc++;
1400 data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1401 goto and_data;
1402
1403 case 0xA4: // AND HXY
1404 data = ixy >> 8;
1405 goto and_data;
1406
1407 case 0xA5: // AND LXY
1408 data = BYTE( ixy );
1409 goto and_data;
1410
1411 // OR
1412 case 0xB6: // OR (IXY+disp)
1413 pc++;
1414 data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1415 goto or_data;
1416
1417 case 0xB4: // OR HXY
1418 data = ixy >> 8;
1419 goto or_data;
1420
1421 case 0xB5: // OR LXY
1422 data = BYTE( ixy );
1423 goto or_data;
1424
1425 // XOR
1426 case 0xAE: // XOR (IXY+disp)
1427 pc++;
1428 data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1429 goto xor_data;
1430
1431 case 0xAC: // XOR HXY
1432 data = ixy >> 8;
1433 goto xor_data;
1434
1435 case 0xAD: // XOR LXY
1436 data = BYTE( ixy );
1437 goto xor_data;
1438
1439 // CP
1440 case 0xBE: // CP (IXY+disp)
1441 pc++;
1442 data = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1443 goto cp_data;
1444
1445 case 0xBC: // CP HXY
1446 data = ixy >> 8;
1447 goto cp_data;
1448
1449 case 0xBD: // CP LXY
1450 data = BYTE( ixy );
1451 goto cp_data;
1452
1453 // LD
1454 CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
1455 data = R8( data, 0x70 );
1456 if ( 0 )
1457 case 0x36: // LD (IXY+disp),imm
1458 pc++, data = READ_CODE( pc );
1459 pc++;
1460 WRITE_MEM( IXY_DISP( ixy, SBYTE( data2 ) ), data );
1461 goto loop;
1462
1463 CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
1464 R8( data >> 3, 8 ) = ixy >> 8;
1465 goto loop;
1466
1467 case 0x64: // LD HXY,HXY
1468 case 0x6D: // LD LXY,LXY
1469 goto loop;
1470
1471 CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
1472 R8( data >> 3, 8 ) = ixy;
1473 goto loop;
1474
1475 CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
1476 pc++;
1477 R8( data >> 3, 8 ) = READ_MEM( IXY_DISP( ixy, SBYTE( data2 ) ) );
1478 goto loop;
1479
1480 case 0x26: // LD HXY,imm
1481 pc++;
1482 goto ld_hxy_data;
1483
1484 case 0x65: // LD HXY,LXY
1485 data2 = BYTE( ixy );
1486 goto ld_hxy_data;
1487
1488 CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
1489 data2 = R8( data, 0x60 );
1490 ld_hxy_data:
1491 ixy = BYTE( ixy ) + (data2 << 8);
1492 goto set_ixy;
1493
1494 case 0x2E: // LD LXY,imm
1495 pc++;
1496 goto ld_lxy_data;
1497
1498 case 0x6C: // LD LXY,HXY
1499 data2 = ixy >> 8;
1500 goto ld_lxy_data;
1501
1502 CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
1503 data2 = R8( data, 0x68 );
1504 ld_lxy_data:
1505 ixy = (ixy & 0xFF00) + data2;
1506 set_ixy:
1507 if ( opcode == 0xDD )
1508 {
1509 ix = ixy;
1510 goto loop;
1511 }
1512 iy = ixy;
1513 goto loop;
1514
1515 case 0xF9: // LD SP,IXY
1516 sp = ixy;
1517 goto loop;
1518
1519 case 0x22:{// LD (ADDR),IXY
1520 int addr = GET_ADDR();
1521 pc += 2;
1522 WRITE_WORD( addr, ixy );
1523 goto loop;
1524 }
1525
1526 case 0x21: // LD IXY,imm
1527 ixy = GET_ADDR();
1528 pc += 2;
1529 goto set_ixy;
1530
1531 case 0x2A:{// LD IXY,(addr)
1532 int addr = GET_ADDR();
1533 ixy = READ_WORD( addr );
1534 pc += 2;
1535 goto set_ixy;
1536 }
1537
1538 // DD/FD CB prefix
1539 case 0xCB: {
1540 data = IXY_DISP( ixy, SBYTE( data2 ) );
1541 pc++;
1542 data2 = READ_CODE( pc );
1543 pc++;
1544 switch ( data2 )
1545 {
1546 case 0x06: goto rlc_data_addr; // RLC (IXY)
1547 case 0x16: goto rl_data_addr; // RL (IXY)
1548 case 0x26: goto sla_data_addr; // SLA (IXY)
1549 case 0x36: goto sll_data_addr; // SLL (IXY)
1550 case 0x0E: goto rrc_data_addr; // RRC (IXY)
1551 case 0x1E: goto rr_data_addr; // RR (IXY)
1552 case 0x2E: goto sra_data_addr; // SRA (IXY)
1553 case 0x3E: goto srl_data_addr; // SRL (IXY)
1554
1555 CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
1556 int temp = READ_MEM( data );
1557 temp = temp & (1 << (data2 >> 3 & 7));
1558 flags = (flags & C01) + H10 + (temp & S80);
1559 flags += (unsigned) --temp >> 8 & (Z40 | P04);
1560 goto loop;
1561 }
1562
1563 CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
1564 CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
1565 int temp = READ_MEM( data );
1566 int bit = 1 << (data2 >> 3 & 7);
1567 temp |= bit; // SET
1568 if ( !(data2 & 0x40) )
1569 temp ^= bit; // RES
1570 WRITE_MEM( data, temp );
1571 goto loop;
1572 }
1573
1574 default:
1575 dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
1576 warning = true;
1577 goto loop;
1578 }
1579 assert( false );
1580 }
1581
1582 // INC/DEC
1583 case 0x23: // INC IXY
1584 ixy = WORD( ixy + 1 );
1585 goto set_ixy;
1586
1587 case 0x2B: // DEC IXY
1588 ixy = WORD( ixy - 1 );
1589 goto set_ixy;
1590
1591 case 0x34: // INC (IXY+disp)
1592 ixy = IXY_DISP( ixy, SBYTE( data2 ) );
1593 pc++;
1594 data = READ_MEM( ixy ) + 1;
1595 WRITE_MEM( ixy, data );
1596 goto inc_set_flags;
1597
1598 case 0x35: // DEC (IXY+disp)
1599 ixy = IXY_DISP( ixy, SBYTE( data2 ) );
1600 pc++;
1601 data = READ_MEM( ixy ) - 1;
1602 WRITE_MEM( ixy, data );
1603 goto dec_set_flags;
1604
1605 case 0x24: // INC HXY
1606 ixy = WORD( ixy + 0x100 );
1607 data = ixy >> 8;
1608 goto inc_xy_common;
1609
1610 case 0x2C: // INC LXY
1611 data = BYTE( ixy + 1 );
1612 ixy = (ixy & 0xFF00) + data;
1613 inc_xy_common:
1614 if ( opcode == 0xDD )
1615 {
1616 ix = ixy;
1617 goto inc_set_flags;
1618 }
1619 iy = ixy;
1620 goto inc_set_flags;
1621
1622 case 0x25: // DEC HXY
1623 ixy = WORD( ixy - 0x100 );
1624 data = ixy >> 8;
1625 goto dec_xy_common;
1626
1627 case 0x2D: // DEC LXY
1628 data = BYTE( ixy - 1 );
1629 ixy = (ixy & 0xFF00) + data;
1630 dec_xy_common:
1631 if ( opcode == 0xDD )
1632 {
1633 ix = ixy;
1634 goto dec_set_flags;
1635 }
1636 iy = ixy;
1637 goto dec_set_flags;
1638
1639 // PUSH/POP
1640 case 0xE5: // PUSH IXY
1641 data = ixy;
1642 goto push_data;
1643
1644 case 0xE1:{// POP IXY
1645 ixy = READ_WORD( sp );
1646 sp = WORD( sp + 2 );
1647 goto set_ixy;
1648 }
1649
1650 // Misc
1651
1652 case 0xE9: // JP (IXY)
1653 pc = ixy;
1654 goto loop;
1655
1656 case 0xE3:{// EX (SP),IXY
1657 int temp = READ_WORD( sp );
1658 WRITE_WORD( sp, ixy );
1659 ixy = temp;
1660 goto set_ixy;
1661 }
1662
1663 default:
1664 dprintf( "Unnecessary DD/FD prefix encountered\n" );
1665 warning = true;
1666 pc--;
1667 goto loop;
1668 }
1669 assert( false );
1670 }
1671
1672 }
1673 dprintf( "Unhandled main opcode: $%02X\n", opcode );
1674 assert( false );
1675
1676#ifdef IDLE_ADDR
1677hit_idle_addr:
1678 s_time -= 11;
1679 goto out_of_time;
1680#endif
1681halt:
1682 s_time &= 3; // increment by multiple of 4
1683out_of_time:
1684 pc--;
1685
1686 r.b.flags = flags;
1687 R.ix = ix;
1688 R.iy = iy;
1689 R.sp = sp;
1690 R.pc = pc;
1691 R.b = r.b;
1692
1693 cpu->cpu_state_.base = s.base;
1694 cpu->cpu_state_.time = s_time;
1695 cpu->cpu_state = &cpu->cpu_state_;
1696}