summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--PORTABLE_VERSION2
-rw-r--r--README4
-rw-r--r--about.txt9
-rw-r--r--configure.ac15
-rw-r--r--deadbeef.desktop.in2
-rw-r--r--main.c127
-rw-r--r--pixmaps/Makefile.am2
-rw-r--r--pixmaps/noartwork.jpgbin3670 -> 0 bytes
-rw-r--r--pixmaps/noartwork.pngbin0 -> 157827 bytes
-rw-r--r--playlist.c17
-rw-r--r--plugins/aac/aac.c11
-rw-r--r--plugins/alsa/alsa.c22
-rw-r--r--plugins/artwork/artwork.c119
-rw-r--r--plugins/converter/converter.c10
-rw-r--r--plugins/converter/convgui.c7
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/Makefile.am3
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/changes.txt218
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.cpp182
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.h73
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/demo/basics.c57
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/demo/cpp_basics.cpp67
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/demo/features.c149
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/design.txt194
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme.txt464
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.cpp395
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.h107
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.cpp1665
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.h92
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.cpp404
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.h70
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.cpp446
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.h485
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.cpp184
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.h127
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.cpp315
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.h151
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.cpp131
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.h50
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.cpp529
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.h86
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.cpp199
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.h171
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.cpp306
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.h90
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.cpp1056
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.h93
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.cpp336
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.h83
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.cpp288
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.h88
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.cpp216
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.h145
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.cpp379
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.h82
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.cpp315
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.h66
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.cpp1303
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.h125
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.cpp529
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.h94
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.cpp1706
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.h124
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.cpp414
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.h96
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.cpp97
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.h106
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.cpp426
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.h67
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Makefile.am66
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.cpp232
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.h156
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.cpp410
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.h211
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.cpp391
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.h179
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.cpp1084
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.h114
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.cpp121
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.h131
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.cpp145
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.h102
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.cpp551
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.h147
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.cpp215
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.h95
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.cpp557
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.h106
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.cpp330
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.h68
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.cpp334
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.h77
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.cpp1011
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.h83
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.cpp442
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.h69
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.cpp330
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.h75
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Oscs.h49
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.cpp489
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h121
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.cpp1062
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.h57
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.cpp666
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h152
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.cpp326
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.h77
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.cpp412
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.h84
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.cpp314
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.h71
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.cpp21
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.h33
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.cpp1319
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.h38
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_common.h179
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_config.h30
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_endian.h158
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_source.h78
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/gb_cpu_io.h72
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/gme.cpp256
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/gme.h222
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/hes_cpu_io.h101
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/nes_cpu_io.h83
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/gme/sap_cpu_io.h26
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/license.txt504
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.cpp198
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.h36
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.cpp231
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.h69
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/player/player.cpp213
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/readme.txt205
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/test.m3u2
-rw-r--r--plugins/gme/Game_Music_Emu-0.5.2/test.nsfbin749 -> 0 bytes
-rw-r--r--plugins/gme/game-music-emu-0.5.5/changes.txt225
-rw-r--r--plugins/gme/game-music-emu-0.5.5/design.txt194
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme.txt464
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.cpp395
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.h107
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.cpp1665
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.h92
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.cpp410
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.h70
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp446
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.orig446
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.rej11
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h488
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.orig488
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.rej23
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.cpp184
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.h127
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.cpp315
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.h151
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.cpp133
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.h50
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.cpp529
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.h86
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.cpp199
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.h171
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.cpp306
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.h90
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.cpp1056
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.h93
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.cpp336
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.h83
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.cpp289
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.h88
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gme_File.cpp216
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gme_File.h159
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.cpp380
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.h82
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.cpp315
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.h66
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.cpp1303
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.h124
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.cpp531
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.h94
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.cpp1706
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.h124
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.cpp416
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.h96
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.cpp97
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.h106
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.cpp426
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.h67
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.cpp232
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.h158
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.cpp410
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.h211
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.cpp391
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.h179
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.cpp1084
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.h114
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.cpp121
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.h131
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.cpp145
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.h102
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.cpp551
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.h147
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.cpp215
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.h95
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.cpp559
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.h106
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.cpp332
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.h68
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.cpp334
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.h77
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.cpp1011
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.h83
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.cpp444
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.h69
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.cpp330
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.h75
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Sms_Oscs.h49
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.cpp489
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.h121
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.cpp1062
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.h57
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.cpp666
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.h152
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.cpp328
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.h77
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.cpp416
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.h84
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.cpp314
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.h71
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.cpp21
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.h33
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.cpp1319
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.h38
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/blargg_common.h175
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/blargg_config.h29
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/blargg_endian.h158
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/blargg_source.h78
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/gb_cpu_io.h72
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/gme.cpp367
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/gme.h254
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/gme_types.h15
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/gme_types.h.in23
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/hes_cpu_io.h101
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/nes_cpu_io.h83
-rw-r--r--plugins/gme/game-music-emu-0.5.5/gme/sap_cpu_io.h26
-rw-r--r--plugins/gme/game-music-emu-0.5.5/license.txt504
-rw-r--r--plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.cpp198
-rw-r--r--plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.h36
-rw-r--r--plugins/gme/game-music-emu-0.5.5/player/Music_Player.cpp231
-rw-r--r--plugins/gme/game-music-emu-0.5.5/player/Music_Player.h69
-rw-r--r--plugins/gme/game-music-emu-0.5.5/player/player.cpp213
-rw-r--r--plugins/gme/game-music-emu-0.5.5/readme.txt218
-rw-r--r--plugins/gtkui/Makefile.am27
-rw-r--r--plugins/gtkui/ddbcellrenderertextmultiline.c144
-rw-r--r--plugins/gtkui/ddbcellrenderertextmultiline.h1
-rw-r--r--plugins/gtkui/deadbeef.glade1
-rw-r--r--plugins/gtkui/gtkui.c54
-rw-r--r--plugins/gtkui/interface.c3
-rw-r--r--plugins/gtkui/prefwin.c31
-rw-r--r--plugins/gtkui/smclient/eggdesktopfile.c1528
-rw-r--r--plugins/gtkui/smclient/eggdesktopfile.h163
-rw-r--r--plugins/gtkui/smclient/eggsmclient-private.h59
-rw-r--r--plugins/gtkui/smclient/eggsmclient-xsmp.c1381
-rw-r--r--plugins/gtkui/smclient/eggsmclient.c604
-rw-r--r--plugins/gtkui/smclient/eggsmclient.h117
-rw-r--r--plugins/hotkeys/hotkeys.c26
-rw-r--r--plugins/mpgmad/mpgmad.c7
-rw-r--r--plugins/shellexecui/shellexecui.c20
-rw-r--r--plugins/sndfile/sndfile.c32
-rw-r--r--plugins/vfs_curl/vfs_curl.c2
-rw-r--r--plugins/vorbis/vorbis.c4
-rw-r--r--po/zh_TW.po4
-rwxr-xr-xscripts/portable_build.sh4
-rwxr-xr-xscripts/portable_package_static.sh9
-rwxr-xr-xscripts/portable_postbuild.sh4
-rwxr-xr-xscripts/static_build.sh20
-rw-r--r--streamer.c11
-rwxr-xr-xtools/apbuild/apgcc6
-rwxr-xr-xtools/apbuild/apinit9
-rwxr-xr-xtools/packages/arch.sh9
-rw-r--r--tools/packages/arch_install2
-rw-r--r--tools/packages/arch_pkginfo2
-rwxr-xr-xtools/packages/debian.sh8
-rw-r--r--translation/extra.c10
281 files changed, 4396 insertions, 63734 deletions
diff --git a/ChangeLog b/ChangeLog
index 1bb947eb..cd4211b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+version 0.5.4
+ fixed starting the player using "deadbeef" command without path
+ fixed missing ; in deadbeef.desktop
+ fixed big-endian support in sndfile plugin
+
version 0.5.3
m3u: fixed few parser bugs; added audio/x-scpls mime-type support; fixed m3uext support
adplug: upgraded to 2.2.1, added fake-surround support and emu selection
@@ -19,6 +24,13 @@ version 0.5.3
fixed possible crash when loading corrupted playlist files
EQ window will reflect changes in the DSP chain configuration
fixed excessive CPU load while streamer is waiting for the last track to finish
+ alsa: fixed sleep time bug, which should improve CPU load (thanks to Martin Panter)
+ alsa: fixed buffer underrun handling problem which was causing sound jittering on slow media like sshfs, cd, etc (thanks to Martin Panter)
+ mp3: added option to disable gapless playback, but improve speed (thanks to Martin Panter)
+ aac: fix to potential reading past the end of array (thanks to Martin Panter)
+ new default cover-art image by TheSame
+ fixed loading m3u/pls over http when the file size is unknown
+ added m3u and pls url mime types (audio/x-mpegurl;audio/x-scpls) to deadbeef.desktop
version 0.5.2
fixed reading id3v2 and apev2 tags from raw AAC files
diff --git a/PORTABLE_VERSION b/PORTABLE_VERSION
index 6db426b0..7d856835 100644
--- a/PORTABLE_VERSION
+++ b/PORTABLE_VERSION
@@ -1 +1 @@
-0.5.3-rc2
+0.5.4
diff --git a/README b/README
index ddf83475..c418af71 100644
--- a/README
+++ b/README
@@ -9,9 +9,9 @@ TABLE OF CONTENTS
* first you need to install dependencies. full list is provided at the end of this section for your convenience
-* you will need intltool to be installed. if you don't need translations -- run ./configure --disable-nls (in this case you won't need to install intltool)
+* you will need intltool to be installed. if you don't need translations -- run ./configure --disable-nls (in this case you won't need to install intltool, as long as the configure script is already generated)
-* if you want to build from git - install autotools, and run ./autogen.sh to bootstrap
+* if you want to build from git - install autotools and intltool, and run ./autogen.sh to bootstrap
* run "./configure --help", and read it.
diff --git a/about.txt b/about.txt
index 05423602..93b4ec7b 100644
--- a/about.txt
+++ b/about.txt
@@ -31,13 +31,16 @@ Contributors:
Sofias <sofias@radikalismus.com>
Icon
+ starws
+ The best QA dude in the world
+
Stas Akimushkin <uncle.lag@gmail.com>
Original artwork
Viktor Semykin <thesame.ml@gmail.com>
- Global Hotkeys, CD Audio, Cover Art, ShellExec plugins, lots of patches and suggestions
+ Global Hotkeys, CD Audio, Cover Art, ShellExec plugins, lots of patches and suggestions, and the default cover art image
- These people sent patches or helped with testing, distribution, or in other ways:
+ These people have also contributed significantly to the project by sending patches, testing, etc:
Alex Dedul <rotmer@gmail.com>
David Bryant <david@wavpack.com>
@@ -46,9 +49,11 @@ Contributors:
Igor Rudchenko <igor@thinkpads.net>
Jan D. Behrens <zykure@web.de>
Kryksyh <druid@foobar2000.ru>
+ Martin Panter
Serghey Kotlyarov <shadowsbrother@gmail.com>
Themaister <maister@archlinux.us>
Veniamin Gvozdikov <g.veniamin@googlemail.com>
+
If you think your name is missing here, or needs to be removed, please send an email to Alexey Yakovenko <waker@users.sf.net>
diff --git a/configure.ac b/configure.ac
index b446237a..37559fa5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AC_INIT([deadbeef], [devel])
AC_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE([1.11 dist-bzip2])
-AM_SILENT_RULES([yes])
+dnl AM_SILENT_RULES([yes])
AM_MAINTAINER_MODE()
AC_USE_SYSTEM_EXTENSIONS
@@ -13,7 +13,7 @@ AC_PROG_CC
AC_PROG_CXX
AC_STDC_HEADERS
AC_PROG_INSTALL
-#AC_PROG_LIBTOOL
+dnl AC_PROG_LIBTOOL
AC_CONFIG_MACRO_DIR([m4])
AC_C_BIGENDIAN
AM_GNU_GETTEXT
@@ -126,6 +126,8 @@ dnl check libsocket (OpenIndiana)
AC_CHECK_LIB([socket], [main], [HAVE_SOCKET=yes;DL_LIBS="-lsocket";AC_SUBST(DL_LIBS)])
dnl check for seperate alloca.h (OpenIndiana)
AC_CHECK_HEADER([alloca.h],[],[alloca.h not found.])
+dnl check for syslimits.h (BSD)
+AC_CHECK_HEADERS([sys/syslimits.h])
if test "x$enable_portable" != "xno" && test "x$enable_staticlink" != "xno" ; then
AC_DEFINE_UNQUOTED([PORTABLE], [1], [Define if building portable version])
@@ -165,12 +167,16 @@ AC_SUBST(ZIP_LIBS)
if test "x$enable_gtk3" == "xyes" ; then
PKG_CHECK_MODULES(GTK3_DEPS, gtk+-3.0 >= 3.0 gthread-2.0 glib-2.0, HAVE_GTK3=yes, HAVE_GTK3=no)
+ AC_CHECK_LIB([SM], [main], [HAVE_SM=yes;SM_LIBS="-lSM";AC_SUBST(SM_LIBS)])
+ AC_CHECK_LIB([ICE], [main], [HAVE_ICE=yes;ICE_LIBS="-lICE";AC_SUBST(ICE_LIBS)])
else
HAVE_GTK3=no
fi
if test "x$enable_gtk2" == "xyes" ; then
PKG_CHECK_MODULES(GTK2_DEPS, gtk+-2.0 >= 2.12 gthread-2.0 glib-2.0, HAVE_GTK2=yes, HAVE_GTK2=no)
+ AC_CHECK_LIB([SM], [main], [HAVE_SM=yes;SM_LIBS="-lSM";AC_SUBST(SM_LIBS)])
+ AC_CHECK_LIB([ICE], [main], [HAVE_ICE=yes;ICE_LIBS="-lICE";AC_SUBST(ICE_LIBS)])
else
HAVE_GTK2=no
fi
@@ -181,7 +187,10 @@ fi
if test "x$enable_ffmpeg" != "xno" ; then
if test "x$enable_staticlink" != "xno" ; then
- FFMPEG_DEPS_LIBS="../../$LIB/lib/libavcodec.a -lpthread ../../$LIB/lib/libavformat.a ../../$LIB/lib/libavcodec.a ../../$LIB/lib/libavutil.a ../../$LIB/lib/libavcore.a -lm ../../$LIB/lib/libz.a "
+ echo "static ffmpeg"
+ FFMPEG_DEPS_CFLAGS="-I../../$LIB/include"
+ FFMPEG_DEPS_LIBS="../../$LIB/lib/libavcodec.a -lpthread ../../$LIB/lib/libavformat.a ../../$LIB/lib/libavcodec.a ../../$LIB/lib/libavutil.a ../../$LIB/lib/libavcore.a -lm ../../$LIB/lib/libz.a"
+ AC_SUBST(FFMPEG_DEPS_CFLAGS)
AC_SUBST(FFMPEG_DEPS_LIBS)
HAVE_FFMPEG=yes
else
diff --git a/deadbeef.desktop.in b/deadbeef.desktop.in
index 3149fbd8..19e16556 100644
--- a/deadbeef.desktop.in
+++ b/deadbeef.desktop.in
@@ -7,7 +7,7 @@ Comment=Listen to music
Comment[pt_BR]=Escute músicas
Comment[ru]=Слушай музыку
Exec=deadbeef %F
-MimeType=application/ogg;audio/x-vorbis+ogg;application/x-ogg;audio/mp3;audio/prs.sid;audio/x-flac;audio/mpeg;audio/x-mpeg;audio/x-mod;audio/x-it;audio/x-s3m;audio/x-xm;
+MimeType=application/ogg;audio/x-vorbis+ogg;application/x-ogg;audio/mp3;audio/prs.sid;audio/x-flac;audio/mpeg;audio/x-mpeg;audio/x-mod;audio/x-it;audio/x-s3m;audio/x-xm;audio/x-mpegurl;audio/x-scpls;
Categories=AudioVideo;Player;GTK;
Terminal=false
Type=Application
diff --git a/main.c b/main.c
index 77751595..9153b2ee 100644
--- a/main.c
+++ b/main.c
@@ -261,6 +261,15 @@ server_exec_command_line (const char *cmdline, int len, char *sendback, int sbsi
else if (!strcmp (parg, "--quit")) {
messagepump_push (DB_EV_TERMINATE, 0, 0, 0);
}
+ else if (!strcmp (parg, "--sm-client-id")) {
+ parg += strlen (parg);
+ parg++;
+ if (parg < pend) {
+ parg += strlen (parg);
+ parg++;
+ }
+ continue;
+ }
else if (parg[0] != '-') {
break; // unknown option is filename
}
@@ -671,15 +680,44 @@ restore_resume_state (void) {
int
main (int argc, char *argv[]) {
+ int portable = 0;
+#if STATICLINK
+ int staticlink = 1;
+#else
+ int staticlink = 0;
+#endif
#if PORTABLE
- strcpy (dbinstalldir, argv[0]);
- char *e = dbinstalldir + strlen (dbinstalldir);
- while (e >= dbinstalldir && *e != '/') {
- e--;
+ portable = 1;
+ if (!realpath (argv[0], dbinstalldir)) {
+ strcpy (dbinstalldir, argv[0]);
+ }
+ char *e = strrchr (dbinstalldir, '/');
+ if (e) {
+ *e = 0;
+ }
+ else {
+ fprintf (stderr, "couldn't determine install folder from path %s\n", argv[0]);
+ exit (-1);
}
- *e = 0;
#else
- strcpy (dbinstalldir, PREFIX);
+ if (!realpath (argv[0], dbinstalldir)) {
+ strcpy (dbinstalldir, argv[0]);
+ }
+ char *e = strrchr (dbinstalldir, '/');
+ if (e) {
+ *e = 0;
+ struct stat st;
+ char checkpath[PATH_MAX];
+ snprintf (checkpath, sizeof (checkpath), "%s/.ddb_portable", dbinstalldir);
+ if (!stat (checkpath, &st)) {
+ if (S_ISREG (st.st_mode)) {
+ portable = 1;
+ }
+ }
+ }
+ if (!portable) {
+ strcpy (dbinstalldir, PREFIX);
+ }
#endif
#ifdef __linux__
@@ -689,26 +727,18 @@ main (int argc, char *argv[]) {
setlocale (LC_NUMERIC, "C");
#ifdef ENABLE_NLS
// fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
-#if PORTABLE
- char localedir[PATH_MAX];
- snprintf (localedir, sizeof (localedir), "%s/locale", dbinstalldir);
- bindtextdomain (PACKAGE, localedir);
-#else
- bindtextdomain (PACKAGE, LOCALEDIR);
-#endif
+ if (portable) {
+ char localedir[PATH_MAX];
+ snprintf (localedir, sizeof (localedir), "%s/locale", dbinstalldir);
+ bindtextdomain (PACKAGE, localedir);
+ }
+ else {
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ }
bind_textdomain_codeset (PACKAGE, "UTF-8");
textdomain (PACKAGE);
#endif
- int staticlink = 0;
- int portable = 0;
-#if STATICLINK
- staticlink = 1;
-#endif
-#if PORTABLE
- portable = 1;
-#endif
-
fprintf (stderr, "starting deadbeef " VERSION "%s%s\n", staticlink ? " [static]" : "", portable ? " [portable]" : "");
srand (time (NULL));
#ifdef __linux__
@@ -750,34 +780,35 @@ main (int argc, char *argv[]) {
#endif
-#if PORTABLE
- if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", dbinstalldir) > sizeof (dbdocdir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
- }
- if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", dbinstalldir) > sizeof (dbplugindir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
- }
- if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", dbinstalldir) > sizeof (dbpixmapdir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
- }
- mkdir (dbplugindir, 0755);
-#else
- if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
- }
- if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
+ if (portable) {
+ if (snprintf (dbdocdir, sizeof (dbdocdir), "%s/doc", dbinstalldir) > sizeof (dbdocdir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
+ if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/plugins", dbinstalldir) > sizeof (dbplugindir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
+ if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/pixmaps", dbinstalldir) > sizeof (dbpixmapdir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
+ mkdir (dbplugindir, 0755);
}
- if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
- fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
- return -1;
+ else {
+ if (snprintf (dbdocdir, sizeof (dbdocdir), "%s", DOCDIR) > sizeof (dbdocdir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
+ if (snprintf (dbplugindir, sizeof (dbplugindir), "%s/deadbeef", LIBDIR) > sizeof (dbplugindir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
+ if (snprintf (dbpixmapdir, sizeof (dbpixmapdir), "%s/share/deadbeef/pixmaps", PREFIX) > sizeof (dbpixmapdir)) {
+ fprintf (stderr, "fatal: too long install path %s\n", dbinstalldir);
+ return -1;
+ }
}
-#endif
for (int i = 1; i < argc; i++) {
// help, version and nowplaying are executed with any filter
diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am
index 9eaf9d55..aa1e3854 100644
--- a/pixmaps/Makefile.am
+++ b/pixmaps/Makefile.am
@@ -4,7 +4,7 @@ pixmaps_DATA =\
pause_16.png\
play_16.png\
buffering_16.png\
-noartwork.jpg
+noartwork.png
EXTRA_DIST = $(pixmaps_DATA)
diff --git a/pixmaps/noartwork.jpg b/pixmaps/noartwork.jpg
deleted file mode 100644
index e6f5669f..00000000
--- a/pixmaps/noartwork.jpg
+++ /dev/null
Binary files differ
diff --git a/pixmaps/noartwork.png b/pixmaps/noartwork.png
new file mode 100644
index 00000000..cb5341cb
--- /dev/null
+++ b/pixmaps/noartwork.png
Binary files differ
diff --git a/playlist.c b/playlist.c
index cc8eca64..11a280c1 100644
--- a/playlist.c
+++ b/playlist.c
@@ -3543,9 +3543,20 @@ plt_search_process (playlist_t *playlist, const char *text) {
if (*text) {
DB_metaInfo_t *m = NULL;
for (m = it->meta; m; m = m->next) {
- if (m->key[0] == ':' || m->key[0] == '_' || m->key[0] == '!') {
+ int is_uri = !strcmp (m->key, ":URI");
+ if ((m->key[0] == ':' && !is_uri) || m->key[0] == '_' || m->key[0] == '!') {
break;
}
+ const char *value = m->value;
+ if (is_uri) {
+ value = strrchr (value, '/');
+ if (value) {
+ value++;
+ }
+ else {
+ value = m->value;
+ }
+ }
if (strcasecmp(m->key, "cuesheet") && strcasecmp (m->key, "log")) {
char cmp = *(m->value-1);
@@ -3565,8 +3576,8 @@ plt_search_process (playlist_t *playlist, const char *text) {
break;
}
}
- else if (utfcasestr_fast (m->value, lc)) {
- //fprintf (stderr, "%s -> %s match (%s.%s)\n", text, m->value, pl_find_meta_raw (it, ":URI"), m->key);
+ else if (utfcasestr_fast (value, lc)) {
+ //fprintf (stderr, "%s -> %s match (%s.%s)\n", text, value, pl_find_meta_raw (it, ":URI"), m->key);
// add to list
it->next[PL_SEARCH] = NULL;
it->prev[PL_SEARCH] = playlist->tail[PL_SEARCH];
diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c
index b3417879..2f2755f0 100644
--- a/plugins/aac/aac.c
+++ b/plugins/aac/aac.c
@@ -878,11 +878,16 @@ aac_read (DB_fileinfo_t *_info, char *bytes, int size) {
char *samples = NULL;
if (info->mp4file) {
+ if (info->mp4sample >= info->mp4samples) {
+ break;
+ }
+
unsigned char *buffer = NULL;
int buffer_size = 0;
#ifdef USE_MP4FF
int rc = mp4ff_read_sample (info->mp4file, info->mp4track, info->mp4sample, &buffer, &buffer_size);
if (rc == 0) {
+ trace ("mp4ff_read_sample failed\n");
info->eof = 1;
break;
}
@@ -902,12 +907,6 @@ aac_read (DB_fileinfo_t *_info, char *bytes, int size) {
u_int64_t myDuration = MP4ConvertFromTrackDuration (info->mp4file, info->mp4track,
sampleDuration, MP4_MSECS_TIME_SCALE);
#endif
- if (info->mp4sample >= info->mp4samples) {
- if (buffer) {
- free (buffer);
- }
- break;
- }
info->mp4sample++;
samples = NeAACDecDecode(info->dec, &info->frame_info, buffer, buffer_size);
diff --git a/plugins/alsa/alsa.c b/plugins/alsa/alsa.c
index 3579e9c3..08fbc9b8 100644
--- a/plugins/alsa/alsa.c
+++ b/plugins/alsa/alsa.c
@@ -613,6 +613,9 @@ palsa_thread (void *context) {
continue;
}
LOCK;
+ char buf[period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels];
+ int bytes_to_write = 0;
+
/* find out how much space is available for playback data */
snd_pcm_sframes_t frames_to_deliver = snd_pcm_avail_update (audio);
@@ -624,12 +627,13 @@ palsa_thread (void *context) {
break;
}
err = 0;
- char buf[period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels];
- UNLOCK; // holding a lock here may cause deadlock in the streamer
- int bytes_to_write = palsa_callback (buf, period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels);
- LOCK;
- if (alsa_terminate) {
- break;
+ if (!bytes_to_write) {
+ UNLOCK; // holding a lock here may cause deadlock in the streamer
+ bytes_to_write = palsa_callback (buf, period_size * (plugin.fmt.bps>>3) * plugin.fmt.channels);
+ LOCK;
+ if (OUTPUT_STATE_PLAYING != state || alsa_terminate) {
+ break;
+ }
}
if (bytes_to_write >= (plugin.fmt.bps>>3) * plugin.fmt.channels) {
@@ -643,6 +647,7 @@ palsa_thread (void *context) {
else {
UNLOCK;
usleep (10000);
+ bytes_to_write = 0;
LOCK;
continue;
}
@@ -669,15 +674,16 @@ palsa_thread (void *context) {
//}
snd_pcm_prepare (audio);
snd_pcm_start (audio);
- continue;
}
+ continue;
}
+ bytes_to_write = 0;
frames_to_deliver = snd_pcm_avail_update (audio);
}
UNLOCK;
int sleeptime = period_size-frames_to_deliver;
if (sleeptime > 0 && plugin.fmt.samplerate > 0 && plugin.fmt.channels > 0) {
- usleep (sleeptime * 1000 / plugin.fmt.samplerate / plugin.fmt.channels * 1000);
+ usleep (sleeptime * 1000 / plugin.fmt.samplerate * 1000);
}
}
}
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index 47aaf748..aa941b81 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -10,6 +10,9 @@
#include <unistd.h>
#include <fnmatch.h>
#include <inttypes.h>
+#if HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
#include "../../deadbeef.h"
#include "artwork.h"
#include "lastfm.h"
@@ -976,72 +979,66 @@ fetcher_thread (void *none)
#ifdef USE_METAFLAC
// try to load embedded from flac metadata
{
- FLAC__StreamMetadata *meta = NULL;
- do {
- trace ("trying to load artwork flac metadata for %s\n", param->fname);
-
- if (!FLAC__metadata_get_picture (
- param->fname, // filename
- &meta, // picture
- FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER, // type
- NULL, // mime_type
- NULL, // description
- (unsigned)(-1), // max_width
- (unsigned)(-1), // max_height
- (unsigned)(-1), // max_depth
- (unsigned)(-1) // max_colors
- )){
- trace ("%s don't have an embedded cover\n",param->fname);
-
- if (!FLAC__metadata_get_picture (
- param->fname, // filename
- &meta, // picture
- -1, // type
- NULL, // mime_type
- NULL, // description
- (unsigned)(-1), // max_width
- (unsigned)(-1), // max_height
- (unsigned)(-1), // max_depth
- (unsigned)(-1) // max_colors
- )){
- trace ("%s don't have an embedded album art\n",param->fname);
- break;
- }
+ const char *filename = param->fname;
+ FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
+ int is_ogg = 0;
+ if(strlen(filename) >= 4 && (0 == strcmp(filename+strlen(filename)-4, ".oga") || 0 == strcasecmp(filename+strlen(filename)-4, ".ogg"))) {
+ is_ogg = 1;
+ }
- }
- FLAC__StreamMetadata_Picture *pic = &meta->data.picture;
+ if(! (is_ogg? FLAC__metadata_chain_read_ogg(chain, filename) : FLAC__metadata_chain_read(chain, filename)) ) {
+ trace ("%s: ERROR: reading metadata", filename);
+ FLAC__metadata_chain_delete(chain);
+ break;
+ }
+ FLAC__StreamMetadata *picture = 0;
+ FLAC__Metadata_Iterator *iterator = FLAC__metadata_iterator_new();
+ FLAC__metadata_iterator_init(iterator, chain);
- trace ("found flac cover art of %d bytes (%s)\n", pic->data_length, pic->description);
- char tmp_path[1024];
- char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
- trace ("will write flac cover art into %s\n", cache_path);
- snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
- FILE *out = fopen (tmp_path, "w+b");
- if (!out) {
- trace ("artwork: failed to open %s for writing\n", tmp_path);
- break;
- }
- if (fwrite (pic->data, 1, pic->data_length, out) != pic->data_length) {
- trace ("artwork: failed to write flac picture into %s\n", tmp_path);
- fclose (out);
- unlink (tmp_path);
- break;
+ do {
+ FLAC__StreamMetadata *block = FLAC__metadata_iterator_get_block(iterator);
+ if(block->type == FLAC__METADATA_TYPE_PICTURE) {
+ picture = block;
}
+ } while(FLAC__metadata_iterator_next(iterator) && 0 == picture);
+
+ if (!picture) {
+ trace ("%s doesn't have an embedded cover\n", param->fname);
+ break;
+ }
+ FLAC__StreamMetadata_Picture *pic = &picture->data.picture;
+ trace ("found flac cover art of %d bytes (%s)\n", pic->data_length, pic->description);
+ char tmp_path[1024];
+ char cache_path[1024];
+ make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
+ trace ("will write flac cover art into %s\n", cache_path);
+ snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
+ FILE *out = fopen (tmp_path, "w+b");
+ if (!out) {
+ trace ("artwork: failed to open %s for writing\n", tmp_path);
+ break;
+ }
+ if (fwrite (pic->data, 1, pic->data_length, out) != pic->data_length) {
+ trace ("artwork: failed to write flac picture into %s\n", tmp_path);
fclose (out);
- int err = rename (tmp_path, cache_path);
- if (err != 0) {
- trace ("Failed not move %s to %s: %s\n", tmp_path, cache_path, strerror (err));
- unlink (tmp_path);
- break;
- }
unlink (tmp_path);
- got_pic = 1;
- } while (0);
+ break;
+ }
+ fclose (out);
+ int err = rename (tmp_path, cache_path);
+ if (err != 0) {
+ trace ("Failed not move %s to %s: %s\n", tmp_path, cache_path, strerror (err));
+ unlink (tmp_path);
+ break;
+ }
+ unlink (tmp_path);
+ got_pic = 1;
- if (meta != NULL) {
- trace ("release flac metadata block\n");
- FLAC__metadata_object_delete (meta);
+ if (chain) {
+ FLAC__metadata_chain_delete(chain);
+ }
+ if (iterator) {
+ FLAC__metadata_iterator_delete(iterator);
}
}
#endif
@@ -1334,7 +1331,7 @@ artwork_plugin_start (void)
const char *def_art = deadbeef->conf_get_str_fast ("gtkui.nocover_pixmap", NULL);
if (!def_art) {
- snprintf (default_cover, sizeof (default_cover), "%s/noartwork.jpg", deadbeef->get_pixmap_dir ());
+ snprintf (default_cover, sizeof (default_cover), "%s/noartwork.png", deadbeef->get_pixmap_dir ());
}
else {
strcpy (default_cover, def_art);
diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c
index ee25dede..7c884eb1 100644
--- a/plugins/converter/converter.c
+++ b/plugins/converter/converter.c
@@ -26,6 +26,16 @@
#include "converter.h"
#include "../../deadbeef.h"
+#ifndef strdupa
+# define strdupa(s) \
+ ({ \
+ const char *old = (s); \
+ size_t len = strlen (old) + 1; \
+ char *new = (char *) alloca (len); \
+ (char *) memcpy (new, old, len); \
+ })
+#endif
+
#ifndef PATH_MAX
#define PATH_MAX 1024 /* max # of characters in a path name */
#endif
diff --git a/plugins/converter/convgui.c b/plugins/converter/convgui.c
index ad7fa4c4..6e1fb335 100644
--- a/plugins/converter/convgui.c
+++ b/plugins/converter/convgui.c
@@ -1312,6 +1312,7 @@ convgui_connect (void) {
}
if (!converter_plugin) {
fprintf (stderr, "convgui: converter plugin not found\n");
+ return -1;
}
if (converter_plugin->misc.plugin.version_major != 1 || converter_plugin->misc.plugin.version_minor < 2) {
fprintf (stderr, "convgui: need converter>=1.2, but found %d.%d\n", converter_plugin->misc.plugin.version_major, converter_plugin->misc.plugin.version_minor);
@@ -1326,7 +1327,11 @@ DB_misc_t plugin = {
.plugin.version_major = 1,
.plugin.version_minor = 1,
.plugin.type = DB_PLUGIN_MISC,
- .plugin.name = "Converter GTK UI",
+#if GTK_CHECK_VERSION(3,0,0)
+ .plugin.name = "Converter GTK3 UI",
+#else
+ .plugin.name = "Converter GTK2 UI",
+#endif
.plugin.descr = "GTK2 User interface for the Converter plugin\n"
"Usage:\n"
"· select some tracks in playlist\n"
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/Makefile.am b/plugins/gme/Game_Music_Emu-0.5.2/Makefile.am
deleted file mode 100644
index 49e0b8b8..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-EXTRA_DIST = changes.txt design.txt gme.txt license.txt readme.txt
-
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/changes.txt b/plugins/gme/Game_Music_Emu-0.5.2/changes.txt
deleted file mode 100644
index 0405b590..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/changes.txt
+++ /dev/null
@@ -1,218 +0,0 @@
-Game_Music_Emu Change Log
--------------------------
-
-Game_Music_Emu 0.5.2
---------------------
-- *TONS* of changes and improvements. You should re-read the new header
-files and documentation as the changes will allow you to simplify your
-code a lot (it might even be simpler to just rewrite it). Existing code
-should continue to work without changes in most cases (see Deprecated
-features in gme.txt).
-
-- New file formats: AY, HES, KSS, SAP, NSFE
-
-- All-new comprehensive C interface (also usable from C++). Simplifies
-many things, especially file loading, and brings everything together in
-one header file (gme.h).
-
-- Information tags and track names and times can be accessed for all
-game music formats
-
-- New features supported by all emulators: end of track fading,
-automatic silence detection, adjustable song tempo, seek to new time in
-track
-
-- Updated mini player example to support track names and times, echo,
-tempo, and channel muting, and added visual waveform display
-
-- Improved configuration to use blargg_config.h, which you can modify
-and keep when you update to a newer libary version. Includes flag for
-library to automatically handle gzipped files using zlib (so you don't
-need to use Gzip_File_Reader anymore).
-
-- GBS: Fixed wave channel to not reset waveform when APU is powered off
-(affected Garfield). Also improved invalid bank selection (affected Game
-& Watch and others).
-
-- VGM: Added support for alternate noise shifter register
-configurations, used by other systems like the BBC Micro.
-
-- SPC: Removed IPL ROM dump from emulator, as none of the SPC files I
-scanned needed it, and an SPC file can include a copy if necessary. Also
-re-enabled supposed clamping in gaussian interpolation between the third
-and fourth lookups, though I don't know whether it matters
-
-- Added Music_Emu::load_mem() to use music data already in memory
-(without copying it)
-
-- Added Music_Emu::warning(), which reports minor problems when loading
-and playing a music file
-
-- Added Music_Emu::set_gain() for uniform adjustment of gain. Can only
-be set during initialization, so not useful as a general volume control.
-
-- Added custom operator new to ensure that no exceptions are thrown in
-the library (I'd use std::nothrow if it were part of pre-ISO (ARM) C++)
-
-- Added BLIP_BUFFER_FAST flag to blargg_config.h to use a lower quality
-bandlimited synthesis in "classic" emulators, which might help
-performance on ancient processors (measure first!). Don't use this
-unless absolutely necessary, as quality suffers.
-
-- Improved performance a bit for x86 platforms
-
-- Text files now in DOS newline format so they will open in Notepad
-properly
-
-- Removed requirement that file header structures not have any padding
-added to the end
-
-- Fixed common bug in all CPU emulators where negative program counter
-could crash emulator (occurred during a negative branch from the
-beginning of memory). Also fixed related bug in Z80 emulator for
-IX/IY+displacement mode.
-
-- Eliminated all warnings when compiling on gcc 4.0. The following
-generates no diagnostics:
-
- gcc -S gme/*.cpp -o /dev/null -ansi -fno-gnu-keywords
- -fno-nonansi-builtins -pedantic -W -Wabi -Wall -Wcast-align
- -Wcast-qual -Wchar-subscripts -Wdisabled-optimization -Werror
- -Winline -Wlong-long -Wmultichar -Winvalid-offsetof
- -Wnon-virtual-dtor -Woverloaded-virtual -Wparentheses
- -Wpointer-arith -Wredundant-decls -Wreorder -Wsign-compare
- -Wsign-promo -Wunknown-pragmas -Wwrite-strings
-
-
-Game_Music_Emu 0.3.0
---------------------
-- Added more demos, including music player using the SDL multimedia
-library for sound, and improved documentation
-
-- All: Improved interface to emulators to allow simpler setup and
-loading. Instead of various init() functions, all now support
-set_sample_rate( long rate ) and load( const char* file_path ).
-
-- All: Removed error return from start_track() and play(), and added
-error_count() to get the total number of emulation errors since the
-track was last started. See demos for examples of new usage.
-
-- All: Fixed mute_voices() muting to be preserved after loading files
-and starting tracks, instead of being cleared as it was whenever a track
-was started
-
-- VGM: Rewrote Vgm_Emu to support Sega Genesis/Mega Drive FM sound at
-any sample rate with optional FM oversampling, support for alternate
-YM2612 sound cores, and support for optional YM2413
-
-- VGM: Added tempo control, useful for slowing 60Hz NTSC Sega Genesis
-music to 50Hz PAL
-
-- VGM: Removed Vgm_Emu::track_data(), since I realized that this
-information is already present in the VGM header (oops!)
-
-- GYM: Changed Gym_Emu::track_length() operation (see Gym_Emu.h)
-
-- NSF: Added support for Sunsoft FME-7 sound chip used by Gimmick
-soundtrack
-
-- NSF: Fixed Namco 106 problems with Final Lap and others
-
-- Moved library sources to gme/ directory to reduce clutter, and merged
-boost/ functionality into blargg_common.h
-
-- Added Gzip_File_Reader for transparently using gzipped files
-
-
-Game_Music_Emu 0.2.4
---------------------
-- Created a discussion forum for problems and feedback:
-http://groups-beta.google.com/group/blargg-sound-libs
-
-- Changed error return value of Blip_Buffer::sample_rate() (also for
-Stereo_Buffer, Effects_Buffer, etc.) to blargg_err_t (defined in
-blargg_common.h), to make error reporting consistent with other
-functions. This means the "no error" return value is the opposite of
-what it was before, which will break current code which checks the error
-return value:
-
- // current code (broken)
- if ( !buf.sample_rate( samples_per_sec ) )
- out_of_memory();
-
- // quick-and-dirty fix (just remove the ! operation)
- if ( buf.sample_rate( samples_per_sec ) )
- out_of_memory();
-
- // proper fix
- blargg_err_t error = buf.sample_rate( samples_per_sec );
- if ( error )
- report_error( error );
-
-- Implemented workaround for MSVC++ 6 compiler limitations, allowing it
-to work on that compiler again
-
-- Added sample clamping to avoid wrap-around at high volumes, allowing
-higher volume with little distortion
-
-- Added to-do list and design notes
-
-- Added Music_Emu::skip( long sample_count ) to skip ahead in current
-track
-
-- Added Gym_Emu::track_length() and Vgm_Emu::track_length() for
-determining the length of non-looped GYM and VGM files
-
-- Partially implemented DMC non-linearity when its value is directly set
-using $4011, which reduces previously over-emphasized "popping" of
-percussion on some games (TMNT II in particular)
-
-- Fixed Fir_Resampler, used for SPC and GYM playback (was incorrectly
-using abs() instead of fabs()...argh)
-
-- Fixed SPC emulation bugs: eliminated clicks in Plok! soundtrack and
-now stops sample slightly earlier than the end, as the SNES does. Fixed
-a totally broken CPU addressing mode.
-
-- Fixed Konami VRC6 saw wave (was very broken before). Now VRC6 music
-sounds decent
-
-- Fixed a minor GBS emulation bug
-
-- Fixed GYM loop point bug when track was restarted before loop point
-had been reached
-
-- Made default GBS frequency equalization less muffled
-
-- Added pseudo-surround effect removal for SPC files
-
-- Added Music_Emu::voice_names() which returns names for each voice.
-
-- Added BLARGG_SOURCE_BEGIN which allows custom compiler options to be
-easily set for library sources
-
-- Changed assignment of expansion sound chips in Nsf_Emu to be spread
-more evenly when using Effects_Buffer
-
-- Changed 'size_t' values in Blip_Buffer interface to 'long'
-
-- Changed demo to generate a WAVE sound file rather than an AIFF file
-
-
-Game_Music_Emu 0.2.0
---------------------
-- Redid framework and rewrote/cleaned up emulators
-
-- Changed licensing to GNU Lesser General Public License (LGPL)
-
-- Added Sega Genesis GYM and Super Nintendo SPC emulators
-
-- Added Namco-106 and Konami VRC6 sound chip support to NSF emulator
-
-- Eliminated use of static mutable data in emulators, allowing
-multi-instance safety
-
-
-Game_Music_Emu 0.1.0
---------------------
-- First release
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.cpp b/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.cpp
deleted file mode 100644
index ec40959d..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Wave_Writer.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-/* Copyright (C) 2003-2006 by Shay Green. Permission is hereby granted, free
-of charge, to any person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-const int header_size = 0x2C;
-
-static void exit_with_error( const char* str )
-{
- printf( "Error: %s\n", str ); getchar();
- exit( EXIT_FAILURE );
-}
-
-Wave_Writer::Wave_Writer( long sample_rate, const char* filename )
-{
- sample_count_ = 0;
- rate = sample_rate;
- buf_pos = header_size;
- chan_count = 1;
-
- buf = (unsigned char*) malloc( buf_size * sizeof *buf );
- if ( !buf )
- exit_with_error( "Out of memory" );
-
- file = fopen( filename, "wb" );
- if ( !file )
- exit_with_error( "Couldn't open WAVE file for writing" );
-
- setvbuf( file, 0, _IOFBF, 32 * 1024L );
-}
-
-void Wave_Writer::flush()
-{
- if ( buf_pos && !fwrite( buf, buf_pos, 1, file ) )
- exit_with_error( "Couldn't write WAVE data" );
- buf_pos = 0;
-}
-
-void Wave_Writer::write( const sample_t* in, long remain, int skip )
-{
- sample_count_ += remain;
- while ( remain )
- {
- if ( buf_pos >= buf_size )
- flush();
-
- long n = (buf_size - buf_pos) / sizeof (sample_t);
- if ( n > remain )
- n = remain;
- remain -= n;
-
- // convert to lsb first format
- unsigned char* p = &buf [buf_pos];
- while ( n-- )
- {
- int s = *in;
- in += skip;
- *p++ = (unsigned char) s;
- *p++ = (unsigned char) (s >> 8);
- }
-
- buf_pos = p - buf;
- assert( buf_pos <= buf_size );
- }
-}
-
-
-void Wave_Writer::write( const float* in, long remain, int skip )
-{
- sample_count_ += remain;
- while ( remain )
- {
- if ( buf_pos >= buf_size )
- flush();
-
- long n = (buf_size - buf_pos) / sizeof (sample_t);
- if ( n > remain )
- n = remain;
- remain -= n;
-
- // convert to lsb first format
- unsigned char* p = &buf [buf_pos];
- while ( n-- )
- {
- long s = (long) (*in * 0x7FFF);
- in += skip;
- if ( (short) s != s )
- s = 0x7FFF - (s >> 24); // clamp to 16 bits
- *p++ = (unsigned char) s;
- *p++ = (unsigned char) (s >> 8);
- }
-
- buf_pos = p - buf;
- assert( buf_pos <= buf_size );
- }
-}
-
-void Wave_Writer::close()
-{
- if ( file )
- {
- flush();
-
- // generate header
- long ds = sample_count_ * sizeof (sample_t);
- long rs = header_size - 8 + ds;
- int frame_size = chan_count * sizeof (sample_t);
- long bps = rate * frame_size;
- unsigned char header [header_size] =
- {
- 'R','I','F','F',
- rs,rs>>8, // length of rest of file
- rs>>16,rs>>24,
- 'W','A','V','E',
- 'f','m','t',' ',
- 0x10,0,0,0, // size of fmt chunk
- 1,0, // uncompressed format
- chan_count,0, // channel count
- rate,rate >> 8, // sample rate
- rate>>16,rate>>24,
- bps,bps>>8, // bytes per second
- bps>>16,bps>>24,
- frame_size,0, // bytes per sample frame
- 16,0, // bits per sample
- 'd','a','t','a',
- ds,ds>>8,ds>>16,ds>>24// size of sample data
- // ... // sample data
- };
-
- // write header
- fseek( file, 0, SEEK_SET );
- fwrite( header, sizeof header, 1, file );
-
- fclose( file );
- file = 0;
- free( buf );
- }
-}
-
-Wave_Writer::~Wave_Writer()
-{
- close();
-}
-
-// C interface
-
-static Wave_Writer* ww;
-
-void wave_open( long sample_rate, const char* filename )
-{
- ww = new Wave_Writer( sample_rate, filename );
- assert( ww );
-}
-
-void wave_enable_stereo() { ww->enable_stereo(); }
-
-long wave_sample_count() { return ww->sample_count(); }
-
-void wave_write( const short* buf, long count ) { ww->write( buf, count ); }
-
-void wave_close()
-{
- delete ww;
- ww = 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.h b/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.h
deleted file mode 100644
index da08cc2a..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/demo/Wave_Writer.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* WAVE sound file writer for recording 16-bit output during program development */
-
-#ifndef WAVE_WRITER_H
-#define WAVE_WRITER_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/* C interface */
-void wave_open( long sample_rate, const char* filename );
-void wave_enable_stereo( void );
-void wave_write( const short* buf, long count );
-long wave_sample_count( void );
-void wave_close( void );
-
-#ifdef __cplusplus
- }
-#endif
-
-#ifdef __cplusplus
-#include <stddef.h>
-#include <stdio.h>
-
-/* C++ interface */
-class Wave_Writer {
-public:
- typedef short sample_t;
-
- // Create sound file with given sample rate (in Hz) and filename.
- // Exits program if there's an error.
- Wave_Writer( long sample_rate, char const* filename = "out.wav" );
-
- // Enable stereo output
- void enable_stereo();
-
- // Append 'count' samples to file. Use every 'skip'th source sample; allows
- // one channel of stereo sample pairs to be written by specifying a skip of 2.
- void write( const sample_t*, long count, int skip = 1 );
-
- // Append 'count' floating-point samples to file. Use every 'skip'th source sample;
- // allows one channel of stereo sample pairs to be written by specifying a skip of 2.
- void write( const float*, long count, int skip = 1 );
-
- // Number of samples written so far
- long sample_count() const;
-
- // Finish writing sound file and close it
- void close();
-
- ~Wave_Writer();
-public:
- // Deprecated
- void stereo( bool b ) { chan_count = b ? 2 : 1; }
-private:
- enum { buf_size = 32768 * 2 };
- unsigned char* buf;
- FILE* file;
- long sample_count_;
- long rate;
- long buf_pos;
- int chan_count;
-
- void flush();
-};
-
-inline void Wave_Writer::enable_stereo() { chan_count = 2; }
-
-inline long Wave_Writer::sample_count() const { return sample_count_; }
-
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/demo/basics.c b/plugins/gme/Game_Music_Emu-0.5.2/demo/basics.c
deleted file mode 100644
index 55178251..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/demo/basics.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* C example that opens a game music file and records 10 seconds to "out.wav" */
-
-static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
-
-#include "gme/gme.h"
-
-#include "Wave_Writer.h" /* wave_ functions for writing sound file */
-#include <stdlib.h>
-#include <stdio.h>
-
-void handle_error( const char* str );
-
-int main()
-{
- long sample_rate = 44100; /* number of samples per second */
- int track = 0; /* index of track to play (0 = first) */
-
- /* Open music file in new emulator */
- Music_Emu* emu;
- handle_error( gme_open_file( filename, &emu, sample_rate ) );
-
- /* Start track */
- handle_error( gme_start_track( emu, track ) );
-
- /* Begin writing to wave file */
- wave_open( sample_rate, "out.wav" );
- wave_enable_stereo();
-
- /* Record 10 seconds of track */
- while ( gme_tell( emu ) < 10 * 1000L )
- {
- /* Sample buffer */
- #define buf_size 1024 /* can be any multiple of 2 */
- short buf [buf_size];
-
- /* Fill sample buffer */
- handle_error( gme_play( emu, buf_size, buf ) );
-
- /* Write samples to wave file */
- wave_write( buf, buf_size );
- }
-
- /* Cleanup */
- gme_delete( emu );
- wave_close();
-
- return 0;
-}
-
-void handle_error( const char* str )
-{
- if ( str )
- {
- printf( "Error: %s\n", str ); getchar();
- exit( EXIT_FAILURE );
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/demo/cpp_basics.cpp b/plugins/gme/Game_Music_Emu-0.5.2/demo/cpp_basics.cpp
deleted file mode 100644
index 53fab418..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/demo/cpp_basics.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// C++ example that opens a game music file and records 10 seconds to "out.wav"
-
-static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
-
-#include "gme/Music_Emu.h"
-
-#include "Wave_Writer.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-void handle_error( const char* str );
-
-int main()
-{
- long sample_rate = 44100; // number of samples per second
- int track = 0; // index of track to play (0 = first)
-
- // Determine file type
- gme_type_t file_type;
- handle_error( gme_identify_file( filename, &file_type ) );
- if ( !file_type )
- handle_error( "Unsupported music type" );
-
- // Create emulator and set sample rate
- Music_Emu* emu = file_type->new_emu();
- if ( !emu )
- handle_error( "Out of memory" );
- handle_error( emu->set_sample_rate( sample_rate ) );
-
- // Load music file into emulator
- handle_error( emu->load_file( filename ) );
-
- // Start track
- handle_error( emu->start_track( track ) );
-
- // Begin writing to wave file
- Wave_Writer wave( sample_rate, "out.wav" );
- wave.enable_stereo();
-
- // Record 10 seconds of track
- while ( emu->tell() < 10 * 1000L )
- {
- // Sample buffer
- const long size = 1024; // can be any multiple of 2
- short buf [size];
-
- // Fill buffer
- handle_error( emu->play( size, buf ) );
-
- // Write samples to wave file
- wave.write( buf, size );
- }
-
- // Cleanup
- delete emu;
-
- return 0;
-}
-
-void handle_error( const char* str )
-{
- if ( str )
- {
- printf( "Error: %s\n", str ); getchar();
- exit( EXIT_FAILURE );
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/demo/features.c b/plugins/gme/Game_Music_Emu-0.5.2/demo/features.c
deleted file mode 100644
index 96a9a8a9..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/demo/features.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* C example that opens any music file type, opens an m3u playlist if present,
-prints its info and voice names, customizes the sound, and fades a track out.
-Records to "out.wav". */
-
-static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
-static char playlist [] = "test.m3u"; /* uses this playlist, if present*/
-
-#include "gme/gme.h"
-
-#include "Wave_Writer.h" /* wave_ functions for writing sound file */
-#include <stdlib.h>
-#include <stdio.h>
-
-void handle_error( const char* );
-
-/* Example of loading from memory, which would be useful if using a zip file or
-other custom format. In this example it's silly because we could just use
-gme_load( &emu, sample_rate, path, 0 ). */
-Music_Emu* load_file( const char* path, long sample_rate )
-{
- Music_Emu* emu;
- char* data;
- long size;
-
- /* Read file data into memory. You might read the data from a zip file or
- other compressed format. */
- FILE* in = fopen( path, "rb" );
- if ( !in )
- handle_error( "Couldn't open file" );
- fseek( in, 0, SEEK_END );
- size = ftell( in );
- rewind( in );
-
- data = malloc( size );
- if ( !data )
- handle_error( "Out of memory" );
- if ( fread( data, size, 1, in ) <= 0 )
- handle_error( "Read error" );
- fclose( in );
-
- handle_error( gme_open_data( data, size, &emu, sample_rate ) );
- free( data ); /* a copy is made of the data */
- return emu;
-}
-
-/* Print any warning for most recent emulator action (load, start_track, play) */
-void print_warning( Music_Emu* emu )
-{
- const char* warning = gme_warning( emu );
- if ( warning )
- printf( "**** Warning: %s\n\n", warning );
-}
-
-static char my_data [] = "Our cleanup function was called";
-
-/* Example cleanup function automatically called when emulator is deleted. */
-static void my_cleanup( void* my_data )
-{
- printf( "\n%s\n", (char*) my_data );
-}
-
-int main()
-{
- long sample_rate = 44100;
- int track = 0; /* index of track to play (0 = first) */
- int i;
-
- /* Load file into emulator */
- Music_Emu* emu = load_file( filename, sample_rate );
- print_warning( emu );
-
- /* Register cleanup function and confirmation string as data */
- gme_set_user_data( emu, my_data );
- gme_set_user_cleanup( emu, my_cleanup );
-
- /* Load .m3u playlist file. All tracks are assumed to use current file.
- We ignore error here in case there is no m3u file present. */
- gme_load_m3u( emu, playlist );
- print_warning( emu );
-
- /* Get and print main info for track */
- {
- track_info_t info;
- handle_error( gme_track_info( emu, &info, track ) );
- printf( "System : %s\n", info.system );
- printf( "Game : %s\n", info.game );
- printf( "Author : %s\n", info.author );
- printf( "Copyright: %s\n", info.copyright );
- printf( "Comment : %s\n", info.comment );
- printf( "Dumper : %s\n", info.dumper );
- printf( "Tracks : %d\n", (int) info.track_count );
- printf( "\n" );
- printf( "Track : %d\n", (int) track + 1 );
- printf( "Name : %s\n", info.song );
- printf( "Length : %ld:%02ld",
- (long) info.length / 1000 / 60, (long) info.length / 1000 % 60 );
- if ( info.loop_length != 0 )
- printf( " (endless)" );
- printf( "\n\n" );
- }
-
- /* Print voice names */
- for ( i = 0; i < gme_voice_count( emu ); i++ )
- printf( "Voice %d: %s\n", i, gme_voice_names( emu ) [i] );
-
- /* Add some stereo enhancement */
- gme_set_stereo_depth( emu, 0.20 );
-
- /* Adjust equalizer for crisp, bassy sound */
- {
- gme_equalizer_t eq;
- eq.treble = 0.0;
- eq.bass = 20;
- gme_set_equalizer( emu, &eq );
- }
-
- /* Start track and begin fade at 10 seconds */
- handle_error( gme_start_track( emu, track ) );
- print_warning( emu );
- gme_set_fade( emu, 10 * 1000L );
-
- /* Record track until it ends */
- wave_open( sample_rate, "out.wav" );
- wave_enable_stereo();
- while ( !gme_track_ended( emu ) )
- {
- #define buf_size 1024
- short buf [buf_size];
- handle_error( gme_play( emu, buf_size, buf ) );
- print_warning( emu );
- wave_write( buf, buf_size );
- }
-
- /* Cleanup */
- gme_delete( emu );
- wave_close();
-
- getchar();
- return 0;
-}
-
-void handle_error( const char* str )
-{
- if ( str )
- {
- printf( "Error: %s\n", str ); getchar();
- exit( EXIT_FAILURE );
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/design.txt b/plugins/gme/Game_Music_Emu-0.5.2/design.txt
deleted file mode 100644
index 8c8c65b1..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/design.txt
+++ /dev/null
@@ -1,194 +0,0 @@
-Game_Music_Emu 0.5.2 Design
----------------------------
-This might be slightly out-of-date at times, but will be a big help in
-understanding the library implementation.
-
-
-Architecture
-------------
-The library is essentially a bunch of independent game music file
-emulators unified with a common interface.
-
-Gme_File and Music_Emu provide a common interface to the emulators. The
-virtual functions are protected rather than public to allow pre- and
-post-processing of arguments and data in one place. This allows the
-emulator classes to assume that everything is set up properly when
-starting a track and playing samples.
-
-All file input is done with the Data_Reader interface. Many derived
-classes are present, for the usual disk-based file and block of memory,
-to specialized adaptors for things like reading a subset of data or
-combining a block of memory with a Data_Reader to the remaining data.
-This makes the library much more flexible with regard to the source of
-game music file data. I still added a specialized load_mem() function to
-have the emulator keep a pointer to data already read in memory, for
-those formats whose files can be absolutely huge (GYM, some VGMs). This
-is important if for some reason the caller must load the data ahead of
-time, but doesn't want the emulator needlessly making a copy.
-
-Since silence checking and fading are relatively complex, they are kept
-separate from basic file loading and track information, which are
-handled in the base class Gme_File. My original intent was to use
-Gme_File as the common base class for full emulators and track
-information-only readers, but implementing the C interface was much
-simpler if both derived from Music_Emu. User C++ code can still benefit
-from static checking by using Gme_File where only track information will
-be accessed.
-
-Each emulator generally has three components: main emulator, CPU
-emulator, and sound chip emulator(s). Each component has minimal
-coupling, so use in a full emulator or stand alone is fairly easy. This
-modularity really helps reduce complexity. Blip_Buffer helps a lot with
-simplifying the APU interfaces and implementation.
-
-The "classic" emulators derive from Classic_Emu, which handles
-Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
-output, allowing you to derive a custom buffer that could output each
-voice to a separate sound channel and do different processing on each.
-At some point I'm going to implement a better Effects_Buffer that allows
-individual control of every channel.
-
-In implementing the C interface, I wanted a way to specify an emulator
-type that didn't require linking in all the emulators. For each emulator
-type there is a global object with pointers to functions to create the
-emulator or a track information reader. The emulator type is thus a
-pointer to this, which conveniently allows for a NULL value. The user
-referencing this emulator type object is what ultimately links the
-emulator in (unless new Foo_Emu is used in C++, of course). This type
-also serves as a useful substitute for RTTI on older C++ compilers.
-
-Addendum: I have since added gme_type_list(), which causes all listed
-emulators to be linked in. To avoid this, I make the list itself
-editable in blargg_config.h. Having a built-in list allows
-gme_load_file() to take a path and give back an emulator with the file
-loaded, which is extremely useful for new users.
-
-
-Interface conventions
-----------------------
-If a function retains a pointer to or replaces the value of an object
-passed, it takes a pointer so that it will be clear in the caller's
-source code that care is required.
-
-Multi-word names have an underscore '_' separator between individual
-words.
-
-Functions are named with lowercase words. Functions which perform an
-action with side-effects are named with a verb phrase (i.e. load, move,
-run). Functions which return the value of a piece of state are named
-using a noun phrase (i.e. loaded, moved, running).
-
-Classes are named with capitalized words. Only the first letter of an
-acronym is capitalized. Class names are nouns, sometimes suggestive of
-what they do (i.e. File_Scanner).
-
-Structure, enumeration, and typedefs to these and built-in types are
-named using lowercase words with a _t suffix.
-
-Macros are named with all-uppercase words.
-
-Internal names which can't be hidden due to technical reasons have an
-underscore '_' suffix.
-
-
-Managing Complexity
--------------------
-Complexity has been a factor in most library decisions. Many features
-have been passed by due to the complexity they would add. Once
-complexity goes past a certain level, it mentally grasping the library
-in its entirety, at which point more defects will occur and be hard to
-find.
-
-I chose 16-bit signed samples because it seems to be the most common
-format. Supporting multiple formats would add too much complexity to be
-worth it. Other formats can be obtained via conversion.
-
-I've kept interfaces fairly lean, leaving many possible features
-untapped but easy to add if necessary. For example the classic emulators
-could have volume and frequency equalization adjusted separately for
-each channel, since they each have an associated Blip_Synth.
-
-Source files of 400 lines or less seem to be the best size to limit
-complexity. In a few cases there is no reasonable way to split longer
-files, or there is benefit from having the source together in one file.
-
-
-Preventing Bugs
----------------
-I've done many things to reduce the opportunity for defects. A general
-principle is to write code so that defects will be as visible as
-possible. I've used several techniques to achieve this.
-
-I put assertions at key points where defects seem likely or where
-corruption due to a defect is likely to be visible. I've also put
-assertions where violations of the interface are likely. In emulators
-where I am unsure of exact hardware operation in a particular case, I
-output a debug-only message noting that this has occurred; many times I
-haven't implemented a hardware feature because nothing uses it. I've
-made code brittle where there is no clear reason flexibility; code
-written to handle every possibility sacrifices quality and reliability
-to handle vaguely defined situations.
-
-
-Flexibility through indirection
--------------------------------
-I've tried to allow the most flexibility of modules by using indirection
-to allow extension by the user. This keeps each module simpler and more
-focused on its unique task.
-
-The classic emulators use Multi_Buffer, which potentially allows a
-separate Blip_Buffer for each channel. This keeps emulators free of
-typical code to allow output in mono, stereo, panning, etc.
-
-All emulators use a reader object to access file data, allowing it to be
-stored in a regular file, compressed archive, memory, or generated
-on-the-fly. Again, the library can be kept free of the particulars of
-file access and changes required to support new formats.
-
-
-Emulators in general
---------------------
-When I wrote the first NES sound emulator, I stored most of the state in
-an emulator-specific format, with significant redundancy. In the
-register write function I decoded everything into named variables. I
-became tired of the verbosity and wanted to more closely model the
-hardware, so I moved to a style of storing the last written value to
-each register, along with as little other state as possible, mostly the
-internal hardware registers. While this involves slightly more
-recalculation, in most cases the emulation code is of comparable size.
-It also makes state save/restore (for use in a full emulator) much
-simpler. Finally, it makes debugging easier since the hardware registers
-used in emulation are obvious.
-
-
-CPU Cores
----------
-I've spent lots of time coming up with techniques to optimize the CPU
-cores. Some of the most important: execute multiple instructions during
-an emulation call, keep state in local variables to allow register
-assignment, optimize state representation for most common instructions,
-defer status flag calculation until actually needed, read program code
-directly without a call to the memory read function, always pre-fetch
-the operand byte before decoding instruction, and emulate instructions
-using common blocks of code.
-
-I've successfully used Nes_Cpu in a fairly complete NES emulator, and
-I'd like to make all the CPU emulators suitable for use in emulators. It
-seems a waste for them to be used only for the small amount of emulation
-necessary for game music files.
-
-I debugged the CPU cores by writing a test shell that ran them in
-parallel with other CPU cores and compared all memory accesses and
-processor states at each step. This provided good value at little cost.
-
-The CPU mapping page size is adjustable to allow the best tradeoff
-between memory/cache usage and handler granularity. The interface allows
-code to be somewhat independent of the page size.
-
-I optimize program memory accesses to direct reads rather than calls to
-the memory read function. My assumption is that it would be difficult to
-get useful code out of hardware I/O addresses, so no software will
-intentionally execute out of I/O space. Since the page size can be
-changed easily, most program memory mapping schemes can be accommodated.
-This greatly reduces memory access function calls.
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme.txt b/plugins/gme/Game_Music_Emu-0.5.2/gme.txt
deleted file mode 100644
index 2c963d8e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme.txt
+++ /dev/null
@@ -1,464 +0,0 @@
-Game_Music_Emu 0.5.2
---------------------
-Author : Shay Green <gblargg@gmail.com>
-Website: http://www.slack.net/~ant/libs/
-Forum : http://groups.google.com/group/blargg-sound-libs
-License: GNU Lesser General Public License (LGPL)
-
-Contents
---------
-* Overview
-* C and C++ interfaces
-* Function reference
-* Error handling
-* Emulator types
-* M3U playlist support
-* Information fields
-* Track length
-* Loading file data
-* Sound parameters
-* VGM/GYM YM2413 & YM2612 FM sound
-* Modular construction
-* Obscure features
-* Solving problems
-* Deprecated features
-* Thanks
-
-
-Overview
---------
-This library can open game music files, play tracks, and read game and
-track information tags. To play a game music file, do the following:
-
-* Open the file with gme_open_file()
-* Start a track with gme_start_track();
-* Generate samples as needed with gme_play()
-* Play samples through speaker using your operating system
-* Delete emulator when done with gme_delete()
-
-Your code must arrange for the generated samples to be played through
-the computer's speaker using whatever method your operating system
-requires.
-
-There are many additional features available; you can:
-
-* Determine of the type of a music file without opening it with
-gme_identify_*()
-* Load just the file's information tags with gme_info_only
-* Load from a block of memory rather than a file with gme_load_data()
-* Arrange for a fade-out at a particular time with gme_set_fade
-* Find when a track has ended with gme_track_ended()
-* Seek to a new time in the track with gme_seek()
-* Load an extended m3u playlist with gme_load_m3u()
-* Get a list of the voices (channels) and mute them individually with
-gme_voice_names() and gme_mute_voice()
-* Change the playback tempo without affecting pitch with gme_set_tempo()
-* Adjust treble/bass equalization with gme_set_equalizer()
-* Associate your own data with an emulator and later get it back with
-gme_set_user_data()
-* Register a function of yours to be called back when the emulator is
-deleted with gme_set_user_cleanup()
-
-Refer to gme.h for a comprehensive summary of features.
-
-
-C and C++ interfaces
---------------------
-While the library is written in C++, an extensive C interface is
-provided in gme.h. This C interface will be referred to throughout this
-documentation unless a feature is only available in the full C++
-interface. All C interface functions and other names have the gme_
-prefix, so you can recognize a C++-only feature by the lack of gme_ in
-the names used (contact me if you'd like a feature added to the C
-interface). If you're building a shared library, I highly recommend
-sticking to the C interface only, because it will be more stable between
-releases of the library than the C++ interface. Finally, the C and C++
-interfaces can be freely mixed without problems. Compare demo/basics.c
-with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
-between each other.
-
-
-Function reference
-------------------
-Read the following header files for a complete reference to functions
-and features. The second group of header files can only be used in C++.
-
-blargg_config.h Library configuration
-gme.h C interface (also usable from C++)
-
-Gme_File.h File loading and track information
-Music_Emu.h Track playback and adjustments
-Data_Reader.h Custom data readers
-Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
-M3u_Playlist.h M3U playlist support
-Gbs_Emu.h GBS equalizer settings
-Nsf_Emu.h NSF equalizer settings
-Spc_Emu.h SPC surround disable
-Vgm_Emu.h VGM oversampling disable and custom buffer query
-
-
-Error handling
---------------
-Functions which can fail have a return type of gme_err_t (blargg_err_t
-in the C++ interfaces), which is a pointer to an error string (const
-char*). If a function is successful it returns NULL. Errors that you can
-easily avoid are checked with debug assertions; gme_err_t return values
-are only used for genuine run-time errors that can't be easily predicted
-in advance (out of memory, I/O errors, incompatible file data). Your
-code should check all error values.
-
-To improve usability for C programmers, C++ programmers unfamiliar with
-exceptions, and compatibility with older C++ compilers, the library does
-*not* throw any C++ exceptions and uses malloc() instead of the standard
-operator new. This means that you *must* check for NULL when creating a
-library object with the new operator.
-
-When loading a music file in the wrong emulator or trying to load a
-non-music file, gme_wrong_file_type is returned. You can check for this
-error in C++ like this:
-
- gme_err_t err = gme_open_file( path, &emu );
- if ( err == gme_wrong_file_type )
- ...
-
-To check for minor problems, call gme_warning() to get a string
-describing the last warning. Your player should allow the user some way
-of knowing when this is the case, since these minor errors could affect
-playback. Without this information the user can't solve problems as
-well. When playing a track, gme_warning() returns minor playback-related
-problems (major playback problems end the track immediately and set the
-warning string).
-
-
-Emulator types
---------------
-The library includes several game music emulators that each support a
-different file type. Each is identified by a gme_type_t constant defined
-in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
-gme_open_file() or gme_open_data(), the library does the work of
-determining the file type and creating an appropriate emulator. If you
-want more control over this process, read on.
-
-There are two basic ways to identify a game music file's type: look at
-its file extension, or read the header data. The library includes
-functions to help with both methods. The first is preferable because it
-is fast and the most common way to identify files. Sometimes the
-extension is lost or wrong, so the header must be read.
-
-Use gme_identify_extension() to find the correct game music type based
-on a filename. To identify a file based on its extension and header
-contents, use gme_identify_file(). If you read the header data yourself,
-use gme_identify_header().
-
-If you want to remove support for some music types to reduce your
-executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
-support just NSF and GBS, use this:
-
- #define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
-
-
-M3U playlist support
---------------------
-The library supports playlists in an extended m3u format with
-gme_load_m3u() to give track names and times to multi-song formats: AY,
-GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
-itself is not well-defined so some m3u files won't work properly
-(particularly those provided with KSS files). Only m3u files referencing
-a single file are supported; your code must handle m3u files covering
-more than one game music file, though it can use the built-in m3u
-parsing provided by the library.
-
-
-Information fields
-------------------
-Support is provided for the various text fields and length information
-in a file with gme_track_info(). If you just need track information for
-a file (for example, building a playlist), use gme_new_info() in place
-of gme_new_emu(), load the file normally, then you can access the track
-count and info, but nothing else.
-
- M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
- -------------------------------------------------------
-Track Count | * * * * * * * * *
- |
-System | * * * * * * * * * *
- |
-Game | * * * * * * *
- |
-Song | * * * * * * *
- |
-Author | * * * * * * * *
- |
-Copyright | * * * * * * * *
- |
-Comment | * * * *
- |
-Dumper | * * * *
- |
-Length | * * * * * *
- |
-Intro Length| * * *
- |
-Loop Length | * * *
-
-As listed above, the HES and KSS file formats don't include a track
-count, and tracks are often scattered over the 0-255 range, so an m3u
-playlist for these is a must.
-
-Unavailable text fields are set to an empty string and times to -1. Your
-code should be prepared for any combination of available and unavailable
-fields, as a particular music file might not use all of the supported
-fields listed above.
-
-Currently text fields are truncated to 255 characters. Obscure fields of
-some formats are not currently decoded; contact me if you want one
-added.
-
-
-Track length
-------------
-The library leaves it up to you as to when to stop playing a track. You
-can ask for available length information and then tell the library what
-time it should start fading the track with gme_set_fade(). By default it
-also continually checks for 6 or more seconds of silence to mark the end
-of a track. Here is a reasonable algorithm you can use to decide how
-long to play a track:
-
-* If the track length is > 0, use it
-* If the loop length > 0, play for intro + loop * 2
-* Otherwise, default to 2.5 minutes (150000 msec)
-
-If you want to play a track longer than normal, be sure the loop length
-isn't zero. See Music_Player.cpp around line 145 for example code.
-
-By default, the library skips silence at the beginning of a track. It
-also continually checks for the end of a non-looping track by watching
-for 6 seconds of unbroken silence. When doing this is scans *ahead* by
-several seconds so it can report the end of the track after only one
-second of silence has actually played. This feature can be disabled with
-gme_ignore_silence().
-
-
-Loading file data
------------------
-The library allows file data to be loaded in many different ways. All
-load functions return an error which you should check. The following
-examples assume these variables:
-
- Music_Emu* emu;
- gme_err_t error;
-
-If you're letting the library determine a file's type, you can use
-either gme_open_file() or gme_open_data():
-
- error = gme_open_file( pathname, &emu );
- error = gme_open_data( pointer, size, &emu );
-
-If you're manually determining file type and using used gme_new_emu() to
-create an emulator, you can use the following methods of loading:
-
-* From a block of memory:
-
- error = gme_load_data( emu, pointer, size );
-
-* Have library call your function to read data:
-
- gme_err_t my_read( void* my_data, void* out, long count )
- {
- // code that reads 'count' bytes into 'out' buffer
- // and return 0 if no error
- }
-
- error = gme_load_custom( emu, my_read, file_size, my_data );
-
-* If you must load the file data into memory yourself, you can have the
-library use your data directly *without* making a copy. If you do this,
-you must not free the data until you're done playing the file.
-
- error = emu->load_mem( pointer, size );
-
-* If you've already read the first bytes of a file (perhaps to determine
-the file type) and want to avoid seeking back to the beginning for
-performance reasons, use Remaining_Reader:
-
- Std_File_Reader in;
- error = in.open( file_path );
-
- char header [4];
- error = in.read( &header, sizeof header );
- ...
-
- Remaining_Reader rem( &header, sizeof header, &in );
- error = emu->load( rem );
-
-If you merely need access to a file's header after loading, use the
-emulator-specific header() functions, after casting the Music_Emu
-pointer to the specific emulator's type. This example examines the
-chip_flags field of the header if it's an NSF file:
-
- if ( music_emu->type() == gme_nsf_type )
- {
- Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
- if ( nsf_emu->header().chip_flags & 0x01 )
- ...
- }
-
-Contact me if you want more information about loading files.
-
-
-Sound parameters
-----------------
-All emulators support an arbitrary output sampling rate. A rate of 44100
-Hz should work well on most systems. Since band-limited synthesis is
-used, a sampling rate above 48000 Hz is not necessary and will actually
-reduce sound quality and performance.
-
-All emulators also support adjustable gain, mainly for the purpose of
-getting consistent volume between different music formats and avoiding
-excessive modulation. The gain can only be set *before* setting the
-emulator's sampling rate, so it's not useful as a general volume
-control. The default gains of emulators are set so that they give
-generally similar volumes, though some soundtracks are significantly
-louder or quieter than normal.
-
-Some emulators support adjustable treble and bass frequency equalization
-(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
-Parameters are specified using gme_equalizer_t eq = { treble_dB,
-bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
-normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
-for an extra crisp sound. Bass_freq sets the frequency where bass
-response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
-and 15000 Hz removes all bass. For example, the following makes the
-sound extra-crisp but lacking bass:
-
- gme_equalizer_t eq = { 5.0, 1000 };
- gme_set_equalizer( music_emu, &eq );
-
-Each emulator's equalization defaults to approximate the particular
-console's sound quality; this default can be determined by calling
-equalizer() just after creating the emulator. The Music_Emu::tv_eq
-profile gives sound as if coming from a TV speaker, and some emulators
-include other profiles for different versions of the system. For
-example, to use Famicom sound equalization with the NSF emulator, do the
-following:
-
- music_emu->set_equalizer( Nsf_Emu::famicom_eq );
-
-
-VGM/GYM YM2413 & YM2612 FM sound
---------------------------------
-The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
-chip emulator based on the Gens project. Because this has some
-inaccuracies, other YM2612 emulators can be used in its place by
-re-implementing the interface in YM2612_Emu.h. Available on my website
-is a modified version of MAME's YM2612 emulator, which sounds better in
-some ways and whose author is still making improvements.
-
-VGM music files using the YM2413 FM sound chip are also supported, but a
-YM2413 emulator isn't included with the library due to technical
-reasons. I have put one of the available YM2413 emulators on my website
-that can be used directly.
-
-
-Modular construction
---------------------
-The library is made of many fairly independent modules. If you're using
-only one music file emulator, you can eliminate many of the library
-sources from your program. Refer to the files list in readme.txt to get
-a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
-(see "Emulator types" above). Post to the forum if you'd like me to put
-together a smaller version for a particular use, as this only takes me a
-few minutes to do.
-
-If you want to use one of the individual sound chip emulators (or CPU
-cores) in your own console emulator, first check the libraries page on
-my website since I have released several of them as stand alone
-libraries with included documentation and examples on their use. If you
-don't find it as a standalone library, contact me and I'll consider
-separating it.
-
-The "classic" sound chips use my Blip_Buffer library, which greatly
-simplifies their implementation and efficiently handles band-limited
-synthesis. It is also available as a stand alone library with
-documentation and many examples.
-
-
-Obscure features
-----------------
-The library's flexibility allows many possibilities. Contact me if you
-want help implementing ideas or removing limitations.
-
-* Uses no global/static variables, allowing multiple instances of any
-emulator. This is useful in a music player if you want to allow
-simultaneous recording or scanning of other tracks while one is already
-playing. This will also be useful if your platform disallows global
-data.
-
-* Emulators that support a custom sound buffer can have *every* voice
-routed to a different Blip_Buffer, allowing custom processing on each
-voice. For example you could record a Game Boy track as a 4-channel
-sound file.
-
-* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
-synthesis on "classic" emulators, which might help on some really old
-processors. This significantly lowers sound quality and prevents treble
-equalization. Try this if your platform's processor isn't fast enough
-for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
-processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
-the quality loss.
-
-
-Solving problems
-----------------
-If you're having problems, try the following:
-
-* If you're getting garbled sound, try this simple siren generator in
-place of your call to play(). This will quickly tell whether the problem
-is in the library or in your code.
-
- static void play_siren( long count, short* out )
- {
- static double a, a2;
- while ( count-- )
- *out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
- }
-
-* Enable debugging support in your environment. This enables assertions
-and other run-time checks.
-
-* Turn the compiler's optimizer is off. Sometimes an optimizer generates
-bad code.
-
-* If multiple threads are being used, ensure that only one at a time is
-accessing a given set of objects from the library. This library is not
-in general thread-safe, though independent objects can be used in
-separate threads.
-
-* If all else fails, see if the demos work.
-
-
-Deprecated features
--------------------
-The following functions and other features have been deprecated and will
-be removed in a future release of the library. Alternatives to the
-deprecated features are listed to the right.
-
-Music_Emu::error_count() warning()
-load( header, reader ) see "Loading file data" above
-Spc_Emu::trailer() track_info()
-Spc_Emu::trailer_size()
-Gym_Emu::track_length() track_info()
-Vgm_Emu::gd3_data() track_info()
-Nsfe_Emu::disable_playlist() clear_playlist()
-
-
-Thanks
-------
-Big thanks to Chris Moeller (kode54) for help with library testing and
-feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
-for original work on openspc++ that was used when developing Spc_Emu.
-Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
-start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
-nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
-and giving feedback for the library in their respective game music
-players.
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.cpp
deleted file mode 100644
index 9dc5bb28..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Ay_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Emulation inaccuracies:
-// * Noise isn't run when not in use
-// * Changes to envelope and noise periods are delayed until next reload
-// * Super-sonic tone should attenuate output to about 60%, not 50%
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const period_factor = 16;
-
-static byte const amp_table [16] =
-{
-#define ENTRY( n ) byte (n * Ay_Apu::amp_range + 0.5)
- // With channels tied together and 1K resistor to ground (as datasheet recommends),
- // output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
- ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
- ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
- ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
- ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
-
- /*
- // Measured from an AY-3-8910A chip with date code 8611.
-
- // Direct voltages without any load (very linear)
- ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
- ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
- ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
- ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
- // With only some load
- ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
- ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
- ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
- ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
- */
-#undef ENTRY
-};
-
-static byte const modes [8] =
-{
-#define MODE( a0,a1, b0,b1, c0,c1 ) \
- (a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
- MODE( 1,0, 1,0, 1,0 ),
- MODE( 1,0, 0,0, 0,0 ),
- MODE( 1,0, 0,1, 1,0 ),
- MODE( 1,0, 1,1, 1,1 ),
- MODE( 0,1, 0,1, 0,1 ),
- MODE( 0,1, 1,1, 1,1 ),
- MODE( 0,1, 1,0, 0,1 ),
- MODE( 0,1, 0,0, 0,0 ),
-};
-
-Ay_Apu::Ay_Apu()
-{
- // build full table of the upper 8 envelope waveforms
- for ( int m = 8; m--; )
- {
- byte* out = env.modes [m];
- int flags = modes [m];
- for ( int x = 3; --x >= 0; )
- {
- int amp = flags & 1;
- int end = flags >> 1 & 1;
- int step = end - amp;
- amp *= 15;
- for ( int y = 16; --y >= 0; )
- {
- *out++ = amp_table [amp];
- amp += step;
- }
- flags >>= 2;
- }
- }
-
- output( 0 );
- volume( 1.0 );
- reset();
-}
-
-void Ay_Apu::reset()
-{
- last_time = 0;
- noise.delay = 0;
- noise.lfsr = 1;
-
- osc_t* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->period = period_factor;
- osc->delay = 0;
- osc->last_amp = 0;
- osc->phase = 0;
- }
- while ( osc != oscs );
-
- for ( int i = sizeof regs; --i >= 0; )
- regs [i] = 0;
- regs [7] = 0xFF;
- write_data_( 13, 0 );
-}
-
-void Ay_Apu::write_data_( int addr, int data )
-{
- assert( (unsigned) addr < reg_count );
-
- if ( (unsigned) addr >= 14 )
- {
- #ifdef dprintf
- dprintf( "Wrote to I/O port %02X\n", (int) addr );
- #endif
- }
-
- // envelope mode
- if ( addr == 13 )
- {
- if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
- data = (data & 4) ? 15 : 9;
- env.wave = env.modes [data - 7];
- env.pos = -48;
- env.delay = 0; // will get set to envelope period in run_until()
- }
- regs [addr] = data;
-
- // handle period changes accurately
- int i = addr >> 1;
- if ( i < osc_count )
- {
- blip_time_t period = (regs [i * 2 + 1] & 0x0F) * (0x100L * period_factor) +
- regs [i * 2] * period_factor;
- if ( !period )
- period = period_factor;
-
- // adjust time of next timer expiration based on change in period
- osc_t& osc = oscs [i];
- if ( (osc.delay += period - osc.period) < 0 )
- osc.delay = 0;
- osc.period = period;
- }
-
- // TODO: same as above for envelope timer, and it also has a divide by two after it
-}
-
-int const noise_off = 0x08;
-int const tone_off = 0x01;
-
-void Ay_Apu::run_until( blip_time_t final_end_time )
-{
- require( final_end_time >= last_time );
-
- // noise period and initial values
- blip_time_t const noise_period_factor = period_factor * 2; // verified
- blip_time_t noise_period = (regs [6] & 0x1F) * noise_period_factor;
- if ( !noise_period )
- noise_period = noise_period_factor;
- blip_time_t const old_noise_delay = noise.delay;
- blargg_ulong const old_noise_lfsr = noise.lfsr;
-
- // envelope period
- blip_time_t const env_period_factor = period_factor * 2; // verified
- blip_time_t env_period = (regs [12] * 0x100L + regs [11]) * env_period_factor;
- if ( !env_period )
- env_period = env_period_factor; // same as period 1 on my AY chip
- if ( !env.delay )
- env.delay = env_period;
-
- // run each osc separately
- for ( int index = 0; index < osc_count; index++ )
- {
- osc_t* const osc = &oscs [index];
- int osc_mode = regs [7] >> index;
-
- // output
- Blip_Buffer* const osc_output = osc->output;
- if ( !osc_output )
- continue;
- osc_output->set_modified();
-
- // period
- int half_vol = 0;
- blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() +
- inaudible_freq) / (inaudible_freq * 2);
- if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
- {
- half_vol = 1; // Actually around 60%, but 50% is close enough
- osc_mode |= tone_off;
- }
-
- // envelope
- blip_time_t start_time = last_time;
- blip_time_t end_time = final_end_time;
- int const vol_mode = regs [0x08 + index];
- int volume = amp_table [vol_mode & 0x0F] >> half_vol;
- int osc_env_pos = env.pos;
- if ( vol_mode & 0x10 )
- {
- volume = env.wave [osc_env_pos] >> half_vol;
- // use envelope only if it's a repeating wave or a ramp that hasn't finished
- if ( !(regs [13] & 1) || osc_env_pos < -32 )
- {
- end_time = start_time + env.delay;
- if ( end_time >= final_end_time )
- end_time = final_end_time;
-
- //if ( !(regs [12] | regs [11]) )
- // dprintf( "Used envelope period 0\n" );
- }
- else if ( !volume )
- {
- osc_mode = noise_off | tone_off;
- }
- }
- else if ( !volume )
- {
- osc_mode = noise_off | tone_off;
- }
-
- // tone time
- blip_time_t const period = osc->period;
- blip_time_t time = start_time + osc->delay;
- if ( osc_mode & tone_off ) // maintain tone's phase when off
- {
- blargg_long count = (final_end_time - time + period - 1) / period;
- time += count * period;
- osc->phase ^= count & 1;
- }
-
- // noise time
- blip_time_t ntime = final_end_time;
- blargg_ulong noise_lfsr = 1;
- if ( !(osc_mode & noise_off) )
- {
- ntime = start_time + old_noise_delay;
- noise_lfsr = old_noise_lfsr;
- //if ( (regs [6] & 0x1F) == 0 )
- // dprintf( "Used noise period 0\n" );
- }
-
- // The following efficiently handles several cases (least demanding first):
- // * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
- // * Just tone or just noise, envelope disabled
- // * Envelope controlling tone and/or noise
- // * Tone and noise disabled, envelope enabled with high frequency
- // * Tone and noise together
- // * Tone and noise together with envelope
-
- // This loop only runs one iteration if envelope is disabled. If envelope
- // is being used as a waveform (tone and noise disabled), this loop will
- // still be reasonably efficient since the bulk of it will be skipped.
- while ( 1 )
- {
- // current amplitude
- int amp = 0;
- if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
- amp = volume;
- {
- int delta = amp - osc->last_amp;
- if ( delta )
- {
- osc->last_amp = amp;
- synth_.offset( start_time, delta, osc_output );
- }
- }
-
- // Run wave and noise interleved with each catching up to the other.
- // If one or both are disabled, their "current time" will be past end time,
- // so there will be no significant performance hit.
- if ( ntime < end_time || time < end_time )
- {
- // Since amplitude was updated above, delta will always be +/- volume,
- // so we can avoid using last_amp every time to calculate the delta.
- int delta = amp * 2 - volume;
- int delta_non_zero = delta != 0;
- int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
- do
- {
- // run noise
- blip_time_t end = end_time;
- if ( end_time > time ) end = time;
- if ( phase & delta_non_zero )
- {
- while ( ntime <= end ) // must advance *past* time to avoid hang
- {
- int changed = noise_lfsr + 1;
- noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
- if ( changed & 2 )
- {
- delta = -delta;
- synth_.offset( ntime, delta, osc_output );
- }
- ntime += noise_period;
- }
- }
- else
- {
- // 20 or more noise periods on average for some music
- blargg_long remain = end - ntime;
- blargg_long count = remain / noise_period;
- if ( remain >= 0 )
- ntime += noise_period + count * noise_period;
- }
-
- // run tone
- end = end_time;
- if ( end_time > ntime ) end = ntime;
- if ( noise_lfsr & delta_non_zero )
- {
- while ( time < end )
- {
- delta = -delta;
- synth_.offset( time, delta, osc_output );
- time += period;
- //phase ^= 1;
- }
- //assert( phase == (delta > 0) );
- phase = unsigned (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
- // (delta > 0)
- }
- else
- {
- // loop usually runs less than once
- //SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
-
- while ( time < end )
- {
- time += period;
- phase ^= 1;
- }
- }
- }
- while ( time < end_time || ntime < end_time );
-
- osc->last_amp = (delta + volume) >> 1;
- if ( !(osc_mode & tone_off) )
- osc->phase = phase;
- }
-
- if ( end_time >= final_end_time )
- break; // breaks first time when envelope is disabled
-
- // next envelope step
- if ( ++osc_env_pos >= 0 )
- osc_env_pos -= 32;
- volume = env.wave [osc_env_pos] >> half_vol;
-
- start_time = end_time;
- end_time += env_period;
- if ( end_time > final_end_time )
- end_time = final_end_time;
- }
- osc->delay = time - final_end_time;
-
- if ( !(osc_mode & noise_off) )
- {
- noise.delay = ntime - final_end_time;
- noise.lfsr = noise_lfsr;
- }
- }
-
- // TODO: optimized saw wave envelope?
-
- // maintain envelope phase
- blip_time_t remain = final_end_time - last_time - env.delay;
- if ( remain >= 0 )
- {
- blargg_long count = (remain + env_period) / env_period;
- env.pos += count;
- if ( env.pos >= 0 )
- env.pos = (env.pos & 31) - 32;
- remain -= count * env_period;
- assert( -remain <= env_period );
- }
- env.delay = -remain;
- assert( env.delay > 0 );
- assert( env.pos < 0 );
-
- last_time = final_end_time;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.h
deleted file mode 100644
index 31956939..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Apu.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// AY-3-8910 sound chip emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef AY_APU_H
-#define AY_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Ay_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Reset sound chip
- void reset();
-
- // Write to register at specified time
- enum { reg_count = 16 };
- void write( blip_time_t time, int addr, int data );
-
- // Run sound to specified time, end current time frame, then start a new
- // time frame at time 0. Time frames have no effect on emulation and each
- // can be whatever length is convenient.
- void end_frame( blip_time_t length );
-
-// Additional features
-
- // Set sound output of specific oscillator to buffer, where index is
- // 0, 1, or 2. If buffer is NULL, the specified oscillator is muted.
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see documentation)
- void treble_eq( blip_eq_t const& );
-
-public:
- Ay_Apu();
- typedef unsigned char byte;
-private:
- struct osc_t
- {
- blip_time_t period;
- blip_time_t delay;
- short last_amp;
- short phase;
- Blip_Buffer* output;
- } oscs [osc_count];
- blip_time_t last_time;
- byte latch;
- byte regs [reg_count];
-
- struct {
- blip_time_t delay;
- blargg_ulong lfsr;
- } noise;
-
- struct {
- blip_time_t delay;
- byte const* wave;
- int pos;
- byte modes [8] [48]; // values already passed through volume table
- } env;
-
- void run_until( blip_time_t );
- void write_data_( int addr, int data );
-public:
- enum { amp_range = 255 };
- Blip_Synth<blip_good_quality,1> synth_;
-};
-
-inline void Ay_Apu::volume( double v ) { synth_.volume( 0.7 / osc_count / amp_range * v ); }
-
-inline void Ay_Apu::treble_eq( blip_eq_t const& eq ) { synth_.treble_eq( eq ); }
-
-inline void Ay_Apu::write( blip_time_t time, int addr, int data )
-{
- run_until( time );
- write_data_( addr, data );
-}
-
-inline void Ay_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Ay_Apu::output( Blip_Buffer* buf )
-{
- osc_output( 0, buf );
- osc_output( 1, buf );
- osc_output( 2, buf );
-}
-
-inline void Ay_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.cpp
deleted file mode 100644
index 6ff7156b..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.cpp
+++ /dev/null
@@ -1,1665 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.21 5:26 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Ay_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME() (void) (s.time = s_time)
-#define RELOAD_TIME() (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, TIME )\
- ay_cpu_out( cpu, TIME, addr, data )
-
-#define CPU_IN( cpu, addr, TIME )\
- ay_cpu_in( cpu, addr )
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n ) szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n ) (szpc [n] & ~P04)
-#define SZ28( n ) SZ28C( n )
-
-#define SET_R( n ) (void) (r.r = n)
-#define GET_R() (r.r)
-
-Ay_Cpu::Ay_Cpu()
-{
- state = &state_;
- for ( int i = 0x100; --i >= 0; )
- {
- int even = 1;
- for ( int p = i; p; p >>= 1 )
- even ^= p;
- int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
- szpc [i] = n;
- szpc [i + 0x100] = n | C01;
- }
- szpc [0x000] |= Z40;
- szpc [0x100] |= Z40;
-}
-
-void Ay_Cpu::reset( void* m )
-{
- mem = (uint8_t*) m;
-
- check( state == &state_ );
- state = &state_;
- state_.time = 0;
- state_.base = 0;
- end_time_ = 0;
-
- memset( &r, 0, sizeof r );
-}
-
-#define TIME (s_time + s.base)
-#define READ_PROG( addr ) (mem [addr])
-#define INSTR( offset ) READ_PROG( pc + (offset) )
-#define GET_ADDR() GET_LE16( &READ_PROG( pc ) )
-#define READ( addr ) READ_PROG( addr )
-#define WRITE( addr, data ) (void) (READ_PROG( addr ) = data)
-#define READ_WORD( addr ) GET_LE16( &READ_PROG( addr ) )
-#define WRITE_WORD( addr, data ) SET_LE16( &READ_PROG( addr ), data )
-#define IN( addr ) CPU_IN( this, addr, TIME )
-#define OUT( addr, data ) CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
- (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Ay_Cpu::run( cpu_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- bool warning = false;
-
- typedef BOOST::int8_t int8_t;
-
- union {
- regs_t rg;
- pairs_t rp;
- uint8_t r8_ [8]; // indexed
- uint16_t r16_ [4];
- };
- rg = this->r.b;
-
- cpu_time_t s_time = s.time;
- uint8_t* const mem = this->mem; // cache
- fuint16 pc = r.pc;
- fuint16 sp = r.sp;
- fuint16 ix = r.ix; // TODO: keep in memory for direct access?
- fuint16 iy = r.iy;
- int flags = r.b.flags;
-
- goto loop;
-jr_not_taken:
- s_time -= 5;
- goto loop;
-call_not_taken:
- s_time -= 7;
-jp_not_taken:
- pc += 2;
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (unsigned) flags < 0x100 );
- check( (unsigned) ix < 0x10000 );
- check( (unsigned) iy < 0x10000 );
-
- fuint8 opcode;
- opcode = READ_PROG( pc );
- pc++;
-
- static byte const base_timing [0x100] = {
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
- 13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
- 12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
- 12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
- 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
- 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
- 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
- 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
- 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
- };
-
- fuint16 data;
- data = base_timing [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = READ_PROG( pc );
-
- #ifdef Z80_CPU_LOG_H
- //log_opcode( opcode, READ_PROG( pc ) );
- z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
- z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
- READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Common
-
- case 0x00: // NOP
- CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
- goto loop;
-
- case 0x08:{// EX AF,AF'
- int temp = r.alt.b.a;
- r.alt.b.a = rg.a;
- rg.a = temp;
-
- temp = r.alt.b.flags;
- r.alt.b.flags = flags;
- flags = temp;
- goto loop;
- }
-
- case 0xD3: // OUT (imm),A
- pc++;
- OUT( data + rg.a * 0x100, rg.a );
- goto loop;
-
- case 0x2E: // LD L,imm
- pc++;
- rg.l = data;
- goto loop;
-
- case 0x3E: // LD A,imm
- pc++;
- rg.a = data;
- goto loop;
-
- case 0x3A:{// LD A,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rg.a = READ( addr );
- goto loop;
- }
-
-// Conditional
-
-#define ZERO (flags & Z40)
-#define CARRY (flags & C01)
-#define EVEN (flags & P04)
-#define MINUS (flags & S80)
-
-// JR
-#define JR( cond ) {\
- int disp = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) )\
- goto jr_not_taken;\
- pc += disp;\
- goto loop;\
-}
-
- case 0x20: JR( !ZERO ) // JR NZ,disp
- case 0x28: JR( ZERO ) // JR Z,disp
- case 0x30: JR( !CARRY ) // JR NC,disp
- case 0x38: JR( CARRY ) // JR C,disp
- case 0x18: JR( true ) // JR disp
-
- case 0x10:{// DJNZ disp
- int temp = rg.b - 1;
- rg.b = temp;
- JR( temp )
- }
-
-// JP
-#define JP( cond ) if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
- case 0xC2: JP( !ZERO ) // JP NZ,addr
- case 0xCA: JP( ZERO ) // JP Z,addr
- case 0xD2: JP( !CARRY ) // JP NC,addr
- case 0xDA: JP( CARRY ) // JP C,addr
- case 0xE2: JP( !EVEN ) // JP PO,addr
- case 0xEA: JP( EVEN ) // JP PE,addr
- case 0xF2: JP( !MINUS ) // JP P,addr
- case 0xFA: JP( MINUS ) // JP M,addr
-
- case 0xC3: // JP addr
- pc = GET_ADDR();
- goto loop;
-
- case 0xE9: // JP HL
- pc = rp.hl;
- goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
- case 0xC0: RET( !ZERO ) // RET NZ
- case 0xC8: RET( ZERO ) // RET Z
- case 0xD0: RET( !CARRY ) // RET NC
- case 0xD8: RET( CARRY ) // RET C
- case 0xE0: RET( !EVEN ) // RET PO
- case 0xE8: RET( EVEN ) // RET PE
- case 0xF0: RET( !MINUS ) // RET P
- case 0xF8: RET( MINUS ) // RET M
-
- case 0xC9: // RET
- ret_taken:
- pc = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
- case 0xC4: CALL( !ZERO ) // CALL NZ,addr
- case 0xCC: CALL( ZERO ) // CALL Z,addr
- case 0xD4: CALL( !CARRY ) // CALL NC,addr
- case 0xDC: CALL( CARRY ) // CALL C,addr
- case 0xE4: CALL( !EVEN ) // CALL PO,addr
- case 0xEC: CALL( EVEN ) // CALL PE,addr
- case 0xF4: CALL( !MINUS ) // CALL P,addr
- case 0xFC: CALL( MINUS ) // CALL M,addr
-
- case 0xCD:{// CALL addr
- call_taken:
- fuint16 addr = pc + 2;
- pc = GET_ADDR();
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, addr );
- goto loop;
- }
-
- case 0xFF: // RST
- if ( (pc - 1) > 0xFFFF )
- {
- pc = uint16_t (pc - 1);
- s_time -= 11;
- goto loop;
- }
- CASE7( C7, CF, D7, DF, E7, EF, F7 ):
- data = pc;
- pc = opcode & 0x38;
- goto push_data;
-
-// PUSH/POP
- case 0xF5: // PUSH AF
- data = rg.a * 0x100u + flags;
- goto push_data;
-
- case 0xC5: // PUSH BC
- case 0xD5: // PUSH DE
- case 0xE5: // PUSH HL
- data = R16( opcode, 4, 0xC5 );
- push_data:
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, data );
- goto loop;
-
- case 0xF1: // POP AF
- flags = READ( sp );
- rg.a = READ( sp + 1 );
- sp = uint16_t (sp + 2);
- goto loop;
-
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL
- R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// ADC/ADD/SBC/SUB
- case 0x96: // SUB (HL)
- case 0x86: // ADD (HL)
- flags &= ~C01;
- case 0x9E: // SBC (HL)
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_data;
-
- case 0xD6: // SUB A,imm
- case 0xC6: // ADD imm
- flags &= ~C01;
- case 0xDE: // SBC A,imm
- case 0xCE: // ADC imm
- pc++;
- goto adc_data;
-
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
- flags &= ~C01;
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
- data = R8( opcode & 7, 0 );
- adc_data: {
- int result = data + (flags & C01);
- data ^= rg.a;
- flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
- if ( flags )
- result = -result;
- result += rg.a;
- data ^= result;
- flags |=(data & H10) |
- ((data - -0x80) >> 6 & V04) |
- SZ28C( result & 0x1FF );
- rg.a = result;
- goto loop;
- }
-
-// CP
- case 0xBE: // CP (HL)
- data = READ( rp.hl );
- goto cp_data;
-
- case 0xFE: // CP imm
- pc++;
- goto cp_data;
-
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
- data = R8( opcode, 0xB8 );
- cp_data: {
- int result = rg.a - data;
- flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
- data ^= rg.a;
- flags |=(((result ^ rg.a) & data) >> 5 & V04) |
- (((data & H10) ^ result) & (S80 | H10));
- if ( (uint8_t) result )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
-// ADD HL,rp
-
- case 0x39: // ADD HL,SP
- data = sp;
- goto add_hl_data;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- data = R16( opcode, 4, 0x09 );
- add_hl_data: {
- blargg_ulong sum = rp.hl + data;
- data ^= rp.hl;
- rp.hl = sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((data ^ sum) >> 8 & H10);
- goto loop;
- }
-
- case 0x27:{// DAA
- int a = rg.a;
- if ( a > 0x99 )
- flags |= C01;
-
- int adjust = 0x60 & -(flags & C01);
-
- if ( flags & H10 || (a & 0x0F) > 9 )
- adjust |= 0x06;
-
- if ( flags & N02 )
- adjust = -adjust;
- a += adjust;
-
- flags = (flags & (C01 | N02)) |
- ((rg.a ^ a) & H10) |
- SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- /*
- case 0x27:{// DAA
- // more optimized, but probably not worth the obscurity
- int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
- int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
- if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
- adjust |= 0x06;
-
- if ( f & N02 )
- adjust = -adjust;
- int a = rg.a + adjust;
-
- flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- */
-
-// INC/DEC
- case 0x34: // INC (HL)
- data = READ( rp.hl ) + 1;
- WRITE( rp.hl, data );
- goto inc_set_flags;
-
- CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
- data = ++R8( opcode >> 3, 0 );
- inc_set_flags:
- flags = (flags & C01) |
- (((data & 0x0F) - 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x80 )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x35: // DEC (HL)
- data = READ( rp.hl ) - 1;
- WRITE( rp.hl, data );
- goto dec_set_flags;
-
- CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
- data = --R8( opcode >> 3, 0 );
- dec_set_flags:
- flags = (flags & C01) | N02 |
- (((data & 0x0F) + 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x7F )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- R16( opcode, 4, 0x03 )++;
- goto loop;
-
- case 0x33: // INC SP
- sp = uint16_t (sp + 1);
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- R16( opcode, 4, 0x0B )--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = uint16_t (sp - 1);
- goto loop;
-
-// AND
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- goto and_data;
-
- case 0xE6: // AND imm
- pc++;
- goto and_data;
-
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
- data = R8( opcode, 0xA0 );
- and_data:
- rg.a &= data;
- flags = SZ28P( rg.a ) | H10;
- goto loop;
-
-// OR
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- goto or_data;
-
- case 0xF6: // OR imm
- pc++;
- goto or_data;
-
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
- data = R8( opcode, 0xB0 );
- or_data:
- rg.a |= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// XOR
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- goto xor_data;
-
- case 0xEE: // XOR imm
- pc++;
- goto xor_data;
-
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
- data = R8( opcode, 0xA8 );
- xor_data:
- rg.a ^= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
- WRITE( rp.hl, R8( opcode, 0x70 ) );
- goto loop;
-
- CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
- CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
- CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
- CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
- CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
- CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
- CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
- R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
- goto loop;
-
- CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
- R8( opcode >> 3, 0 ) = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),imm
- pc++;
- WRITE( rp.hl, data );
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
- R8( opcode >> 3, 8 ) = READ( rp.hl );
- goto loop;
-
- case 0x01: // LD rp,imm
- case 0x11:
- case 0x21:
- R16( opcode, 4, 0x01 ) = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x31: // LD sp,imm
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x2A:{// LD HL,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rp.hl = READ_WORD( addr );
- goto loop;
- }
-
- case 0x32:{// LD (addr),A
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE( addr, rg.a );
- goto loop;
- }
-
- case 0x22:{// LD (addr),HL
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, rp.hl );
- goto loop;
- }
-
- case 0x02: // LD (BC),A
- case 0x12: // LD (DE),A
- WRITE( R16( opcode, 4, 0x02 ), rg.a );
- goto loop;
-
- case 0x0A: // LD A,(BC)
- case 0x1A: // LD A,(DE)
- rg.a = READ( R16( opcode, 4, 0x0A ) );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
-// Rotate
-
- case 0x07:{// RLCA
- fuint16 temp = rg.a;
- temp = (temp << 1) | (temp >> 7);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08 | C01));
- rg.a = temp;
- goto loop;
- }
-
- case 0x0F:{// RRCA
- fuint16 temp = rg.a;
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & C01);
- temp = (temp << 7) | (temp >> 1);
- flags |= temp & (F20 | F08);
- rg.a = temp;
- goto loop;
- }
-
- case 0x17:{// RLA
- blargg_ulong temp = (rg.a << 1) | (flags & C01);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (temp >> 8);
- rg.a = temp;
- goto loop;
- }
-
- case 0x1F:{// RRA
- fuint16 temp = (flags << 7) | (rg.a >> 1);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (rg.a & C01);
- rg.a = temp;
- goto loop;
- }
-
-// Misc
- case 0x2F:{// CPL
- fuint16 temp = ~rg.a;
- flags = (flags & (S80 | Z40 | P04 | C01)) |
- (temp & (F20 | F08)) |
- (H10 | N02);
- rg.a = temp;
- goto loop;
- }
-
- case 0x3F:{// CCF
- flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
- (flags << 4 & H10) |
- (rg.a & (F20 | F08));
- goto loop;
- }
-
- case 0x37: // SCF
- flags = (flags & (S80 | Z40 | P04)) | C01 |
- (rg.a & (F20 | F08));
- goto loop;
-
- case 0xDB: // IN A,(imm)
- pc++;
- rg.a = IN( data + rg.a * 0x100 );
- goto loop;
-
- case 0xE3:{// EX (SP),HL
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, rp.hl );
- rp.hl = temp;
- goto loop;
- }
-
- case 0xEB:{// EX DE,HL
- fuint16 temp = rp.hl;
- rp.hl = rp.de;
- rp.de = temp;
- goto loop;
- }
-
- case 0xD9:{// EXX DE,HL
- fuint16 temp = r.alt.w.bc;
- r.alt.w.bc = rp.bc;
- rp.bc = temp;
-
- temp = r.alt.w.de;
- r.alt.w.de = rp.de;
- rp.de = temp;
-
- temp = r.alt.w.hl;
- r.alt.w.hl = rp.hl;
- rp.hl = temp;
- goto loop;
- }
-
- case 0xF3: // DI
- r.iff1 = 0;
- r.iff2 = 0;
- goto loop;
-
- case 0xFB: // EI
- r.iff1 = 1;
- r.iff2 = 1;
- // TODO: delayed effect
- goto loop;
-
- case 0x76: // HALT
- goto halt;
-
-//////////////////////////////////////// CB prefix
- {
- case 0xCB:
- unsigned data2;
- data2 = INSTR( 1 );
- pc++;
- switch ( data )
- {
-
- // Rotate left
-
- #define RLC( read, write ) {\
- fuint8 result = read;\
- result = uint8_t (result << 1) | (result >> 7);\
- flags = SZ28P( result ) | (result & C01);\
- write;\
- goto loop;\
- }
-
- case 0x06: // RLC (HL)
- s_time += 7;
- data = rp.hl;
- rlc_data_addr:
- RLC( READ( data ), WRITE( data, result ) )
-
- CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
- uint8_t& reg = R8( data, 0 );
- RLC( reg, reg = result )
- }
-
- #define RL( read, write ) {\
- fuint16 result = (read << 1) | (flags & C01);\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x16: // RL (HL)
- s_time += 7;
- data = rp.hl;
- rl_data_addr:
- RL( READ( data ), WRITE( data, result ) )
-
- CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
- uint8_t& reg = R8( data, 0x10 );
- RL( reg, reg = result )
- }
-
- #define SLA( read, add, write ) {\
- fuint16 result = (read << 1) | add;\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x26: // SLA (HL)
- s_time += 7;
- data = rp.hl;
- sla_data_addr:
- SLA( READ( data ), 0, WRITE( data, result ) )
-
- CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
- uint8_t& reg = R8( data, 0x20 );
- SLA( reg, 0, reg = result )
- }
-
- case 0x36: // SLL (HL)
- s_time += 7;
- data = rp.hl;
- sll_data_addr:
- SLA( READ( data ), 1, WRITE( data, result ) )
-
- CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
- uint8_t& reg = R8( data, 0x30 );
- SLA( reg, 1, reg = result )
- }
-
- // Rotate right
-
- #define RRC( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = uint8_t (result << 7) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x0E: // RRC (HL)
- s_time += 7;
- data = rp.hl;
- rrc_data_addr:
- RRC( READ( data ), WRITE( data, result ) )
-
- CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
- uint8_t& reg = R8( data, 0x08 );
- RRC( reg, reg = result )
- }
-
- #define RR( read, write ) {\
- fuint8 result = read;\
- fuint8 temp = result & C01;\
- result = uint8_t (flags << 7) | (result >> 1);\
- flags = SZ28P( result ) | temp;\
- write;\
- goto loop;\
- }
-
- case 0x1E: // RR (HL)
- s_time += 7;
- data = rp.hl;
- rr_data_addr:
- RR( READ( data ), WRITE( data, result ) )
-
- CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
- uint8_t& reg = R8( data, 0x18 );
- RR( reg, reg = result )
- }
-
- #define SRA( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = (result & 0x80) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x2E: // SRA (HL)
- data = rp.hl;
- s_time += 7;
- sra_data_addr:
- SRA( READ( data ), WRITE( data, result ) )
-
- CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
- uint8_t& reg = R8( data, 0x28 );
- SRA( reg, reg = result )
- }
-
- #define SRL( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result >>= 1;\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x3E: // SRL (HL)
- s_time += 7;
- data = rp.hl;
- srl_data_addr:
- SRL( READ( data ), WRITE( data, result ) )
-
- CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
- uint8_t& reg = R8( data, 0x38 );
- SRL( reg, reg = result )
- }
-
- // BIT
- {
- unsigned temp;
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
- s_time += 4;
- temp = READ( rp.hl );
- flags &= C01;
- goto bit_temp;
- CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
- CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
- CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
- CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
- CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
- CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
- CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
- temp = R8( data & 7, 0 );
- flags = (flags & C01) | (temp & (F20 | F08));
- bit_temp:
- int masked = temp & 1 << (data >> 3 & 7);
- flags |=(masked & S80) | H10 |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- // SET/RES
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
- s_time += 7;
- int temp = READ( rp.hl );
- int bit = 1 << (data >> 3 & 7);
- temp |= bit; // SET
- if ( !(data & 0x40) )
- temp ^= bit; // RES
- WRITE( rp.hl, temp );
- goto loop;
- }
-
- CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
- CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
- CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
- CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
- CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
- CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
- CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
- CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
- R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
- goto loop;
-
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
- R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// ED prefix
- {
- case 0xED:
- pc++;
- s_time += ed_dd_timing [data] >> 4;
- switch ( data )
- {
- {
- blargg_ulong temp;
- case 0x72: // SBC HL,SP
- case 0x7A: // ADC HL,SP
- temp = sp;
- if ( 0 )
- case 0x42: // SBC HL,BC
- case 0x52: // SBC HL,DE
- case 0x62: // SBC HL,HL
- case 0x4A: // ADC HL,BC
- case 0x5A: // ADC HL,DE
- case 0x6A: // ADC HL,HL
- temp = R16( data >> 3 & 6, 1, 0 );
- blargg_ulong sum = temp + (flags & C01);
- flags = ~data >> 2 & N02;
- if ( flags )
- sum = -sum;
- sum += rp.hl;
- temp ^= rp.hl;
- temp ^= sum;
- flags |=(sum >> 16 & C01) |
- (temp >> 8 & H10) |
- (sum >> 8 & (S80 | F20 | F08)) |
- ((temp - -0x8000) >> 14 & V04);
- rp.hl = sum;
- if ( (uint16_t) sum )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
- CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
- int temp = IN( rp.bc );
- R8( data >> 3, 8 ) = temp;
- flags = (flags & C01) | SZ28P( temp );
- goto loop;
- }
-
- case 0x71: // OUT (C),0
- rg.flags = 0;
- CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
- OUT( rp.bc, R8( data >> 3, 8 ) );
- goto loop;
-
- {
- unsigned temp;
- case 0x73: // LD (ADDR),SP
- temp = sp;
- if ( 0 )
- case 0x43: // LD (ADDR),BC
- case 0x53: // LD (ADDR),DE
- temp = R16( data, 4, 0x43 );
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, temp );
- goto loop;
- }
-
- case 0x4B: // LD BC,(ADDR)
- case 0x5B:{// LD DE,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- R16( data, 4, 0x4B ) = READ_WORD( addr );
- goto loop;
- }
-
- case 0x7B:{// LD SP,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- sp = READ_WORD( addr );
- goto loop;
- }
-
- case 0x67:{// RRD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
- temp = (rg.a & 0xF0) | (temp & 0x0F);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- case 0x6F:{// RLD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
- temp = (rg.a & 0xF0) | (temp >> 4);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
- opcode = 0x10; // flag to do SBC instead of ADC
- flags &= ~C01;
- data = rg.a;
- rg.a = 0;
- goto adc_data;
-
- {
- int inc;
- case 0xA9: // CPD
- case 0xB9: // CPDR
- inc = -1;
- if ( 0 )
- case 0xA1: // CPI
- case 0xB1: // CPIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int result = rg.a - temp;
- flags = (flags & C01) | N02 |
- ((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
- if ( !(uint8_t) result ) flags |= Z40;
- result -= (flags & H10) >> 4;
- flags |= result & F08;
- flags |= result << 4 & F20;
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( flags & Z40 || data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xA8: // LDD
- case 0xB8: // LDDR
- inc = -1;
- if ( 0 )
- case 0xA0: // LDI
- case 0xB0: // LDIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- addr = rp.de;
- rp.de = addr + inc;
- WRITE( addr, temp );
-
- temp += rg.a;
- flags = (flags & (S80 | Z40 | C01)) |
- (temp & F08) | (temp << 4 & F20);
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xAB: // OUTD
- case 0xBB: // OTDR
- inc = -1;
- if ( 0 )
- case 0xA3: // OUTI
- case 0xB3: // OTIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- OUT( rp.bc, temp );
- goto loop;
- }
-
- {
- int inc;
- case 0xAA: // IND
- case 0xBA: // INDR
- inc = -1;
- if ( 0 )
- case 0xA2: // INI
- case 0xB2: // INIR
- inc = +1;
-
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
-
- int temp = IN( rp.bc );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- WRITE( addr, temp );
- goto loop;
- }
-
- case 0x47: // LD I,A
- r.i = rg.a;
- goto loop;
-
- case 0x4F: // LD R,A
- SET_R( rg.a );
- dprintf( "LD R,A not supported\n" );
- warning = true;
- goto loop;
-
- case 0x57: // LD A,I
- rg.a = r.i;
- goto ld_ai_common;
-
- case 0x5F: // LD A,R
- rg.a = GET_R();
- dprintf( "LD A,R not supported\n" );
- warning = true;
- ld_ai_common:
- flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
- goto loop;
-
- CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
- r.iff1 = r.iff2;
- goto ret_taken;
-
- case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
- r.im = 0;
- goto loop;
-
- case 0x56: case 0x76: // IM 1
- r.im = 1;
- goto loop;
-
- case 0x5E: case 0x7E: // IM 2
- r.im = 2;
- goto loop;
-
- default:
- dprintf( "Opcode $ED $%02X not supported\n", data );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// DD/FD prefix
- {
- fuint16 ixy;
- case 0xDD:
- ixy = ix;
- goto ix_prefix;
- case 0xFD:
- ixy = iy;
- ix_prefix:
- pc++;
- unsigned data2 = READ_PROG( pc );
- s_time += ed_dd_timing [data] & 0x0F;
- switch ( data )
- {
- // TODO: more efficient way of avoid negative address
- #define IXY_DISP( ixy, disp ) uint16_t ((ixy) + (disp))
-
- #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
- // ADD/ADC/SUB/SBC
-
- case 0x96: // SUB (IXY+disp)
- case 0x86: // ADD (IXY+disp)
- flags &= ~C01;
- case 0x9E: // SBC (IXY+disp)
- case 0x8E: // ADC (IXY+disp)
- pc++;
- opcode = data;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto adc_data;
-
- case 0x94: // SUB HXY
- case 0x84: // ADD HXY
- flags &= ~C01;
- case 0x9C: // SBC HXY
- case 0x8C: // ADC HXY
- opcode = data;
- data = ixy >> 8;
- goto adc_data;
-
- case 0x95: // SUB LXY
- case 0x85: // ADD LXY
- flags &= ~C01;
- case 0x9D: // SBC LXY
- case 0x8D: // ADC LXY
- opcode = data;
- data = (uint8_t) ixy;
- goto adc_data;
-
- {
- unsigned temp;
- case 0x39: // ADD IXY,SP
- temp = sp;
- goto add_ixy_data;
-
- case 0x29: // ADD IXY,HL
- temp = ixy;
- goto add_ixy_data;
-
- case 0x09: // ADD IXY,BC
- case 0x19: // ADD IXY,DE
- temp = R16( data, 4, 0x09 );
- add_ixy_data: {
- blargg_ulong sum = ixy + temp;
- temp ^= ixy;
- ixy = (uint16_t) sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((temp ^ sum) >> 8 & H10);
- goto set_ixy;
- }
- }
-
- // AND
- case 0xA6: // AND (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto and_data;
-
- case 0xA4: // AND HXY
- data = ixy >> 8;
- goto and_data;
-
- case 0xA5: // AND LXY
- data = (uint8_t) ixy;
- goto and_data;
-
- // OR
- case 0xB6: // OR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto or_data;
-
- case 0xB4: // OR HXY
- data = ixy >> 8;
- goto or_data;
-
- case 0xB5: // OR LXY
- data = (uint8_t) ixy;
- goto or_data;
-
- // XOR
- case 0xAE: // XOR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto xor_data;
-
- case 0xAC: // XOR HXY
- data = ixy >> 8;
- goto xor_data;
-
- case 0xAD: // XOR LXY
- data = (uint8_t) ixy;
- goto xor_data;
-
- // CP
- case 0xBE: // CP (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto cp_data;
-
- case 0xBC: // CP HXY
- data = ixy >> 8;
- goto cp_data;
-
- case 0xBD: // CP LXY
- data = (uint8_t) ixy;
- goto cp_data;
-
- // LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
- data = R8( data, 0x70 );
- if ( 0 )
- case 0x36: // LD (IXY+disp),imm
- pc++, data = READ_PROG( pc );
- pc++;
- WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
- goto loop;
-
- CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
- R8( data >> 3, 8 ) = ixy >> 8;
- goto loop;
-
- case 0x64: // LD HXY,HXY
- case 0x6D: // LD LXY,LXY
- goto loop;
-
- CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
- R8( data >> 3, 8 ) = ixy;
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
- pc++;
- R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto loop;
-
- case 0x26: // LD HXY,imm
- pc++;
- goto ld_hxy_data;
-
- case 0x65: // LD HXY,LXY
- data2 = (uint8_t) ixy;
- goto ld_hxy_data;
-
- CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
- data2 = R8( data, 0x60 );
- ld_hxy_data:
- ixy = (uint8_t) ixy | (data2 << 8);
- goto set_ixy;
-
- case 0x2E: // LD LXY,imm
- pc++;
- goto ld_lxy_data;
-
- case 0x6C: // LD LXY,HXY
- data2 = ixy >> 8;
- goto ld_lxy_data;
-
- CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
- data2 = R8( data, 0x68 );
- ld_lxy_data:
- ixy = (ixy & 0xFF00) | data2;
- set_ixy:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto loop;
- }
- iy = ixy;
- goto loop;
-
- case 0xF9: // LD SP,IXY
- sp = ixy;
- goto loop;
-
- case 0x22:{// LD (ADDR),IXY
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, ixy );
- goto loop;
- }
-
- case 0x21: // LD IXY,imm
- ixy = GET_ADDR();
- pc += 2;
- goto set_ixy;
-
- case 0x2A:{// LD IXY,(addr)
- fuint16 addr = GET_ADDR();
- ixy = READ_WORD( addr );
- pc += 2;
- goto set_ixy;
- }
-
- // DD/FD CB prefix
- case 0xCB: {
- data = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data2 = READ_PROG( pc );
- pc++;
- switch ( data2 )
- {
- case 0x06: goto rlc_data_addr; // RLC (IXY)
- case 0x16: goto rl_data_addr; // RL (IXY)
- case 0x26: goto sla_data_addr; // SLA (IXY)
- case 0x36: goto sll_data_addr; // SLL (IXY)
- case 0x0E: goto rrc_data_addr; // RRC (IXY)
- case 0x1E: goto rr_data_addr; // RR (IXY)
- case 0x2E: goto sra_data_addr; // SRA (IXY)
- case 0x3E: goto srl_data_addr; // SRL (IXY)
-
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
- fuint8 temp = READ( data );
- int masked = temp & 1 << (data2 >> 3 & 7);
- flags = (flags & C01) | H10 |
- (masked & S80) |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
- int temp = READ( data );
- int bit = 1 << (data2 >> 3 & 7);
- temp |= bit; // SET
- if ( !(data2 & 0x40) )
- temp ^= bit; // RES
- WRITE( data, temp );
- goto loop;
- }
-
- default:
- dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
- // INC/DEC
- case 0x23: // INC IXY
- ixy = uint16_t (ixy + 1);
- goto set_ixy;
-
- case 0x2B: // DEC IXY
- ixy = uint16_t (ixy - 1);
- goto set_ixy;
-
- case 0x34: // INC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) + 1;
- WRITE( ixy, data );
- goto inc_set_flags;
-
- case 0x35: // DEC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) - 1;
- WRITE( ixy, data );
- goto dec_set_flags;
-
- case 0x24: // INC HXY
- ixy = uint16_t (ixy + 0x100);
- data = ixy >> 8;
- goto inc_xy_common;
-
- case 0x2C: // INC LXY
- data = uint8_t (ixy + 1);
- ixy = (ixy & 0xFF00) | data;
- inc_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto inc_set_flags;
- }
- iy = ixy;
- goto inc_set_flags;
-
- case 0x25: // DEC HXY
- ixy = uint16_t (ixy - 0x100);
- data = ixy >> 8;
- goto dec_xy_common;
-
- case 0x2D: // DEC LXY
- data = uint8_t (ixy - 1);
- ixy = (ixy & 0xFF00) | data;
- dec_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto dec_set_flags;
- }
- iy = ixy;
- goto dec_set_flags;
-
- // PUSH/POP
- case 0xE5: // PUSH IXY
- data = ixy;
- goto push_data;
-
- case 0xE1:{// POP IXY
- ixy = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto set_ixy;
- }
-
- // Misc
-
- case 0xE9: // JP (IXY)
- pc = ixy;
- goto loop;
-
- case 0xE3:{// EX (SP),IXY
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, ixy );
- ixy = temp;
- goto set_ixy;
- }
-
- default:
- dprintf( "Unnecessary DD/FD prefix encountered\n" );
- warning = true;
- pc--;
- goto loop;
- }
- assert( false );
- }
-
- }
- dprintf( "Unhandled main opcode: $%02X\n", opcode );
- assert( false );
-
-halt:
- s_time &= 3; // increment by multiple of 4
-out_of_time:
- pc--;
-
- s.time = s_time;
- rg.flags = flags;
- r.ix = ix;
- r.iy = iy;
- r.sp = sp;
- r.pc = pc;
- this->r.b = rg;
- this->state_ = s;
- this->state = &this->state_;
-
- return warning;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.h
deleted file mode 100644
index 07241d5e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Cpu.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Z80 CPU emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef AY_CPU_H
-#define AY_CPU_H
-
-#include "blargg_endian.h"
-
-typedef blargg_long cpu_time_t;
-
-// must be defined by caller
-void ay_cpu_out( class Ay_Cpu*, cpu_time_t, unsigned addr, int data );
-int ay_cpu_in( class Ay_Cpu*, unsigned addr );
-
-class Ay_Cpu {
-public:
- // Clear all registers and keep pointer to 64K memory passed in
- void reset( void* mem_64k );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( cpu_time_t end_time );
-
- // Time of beginning of next instruction
- cpu_time_t time() const { return state->time + state->base; }
-
- // Alter current time. Not supported during run() call.
- void set_time( cpu_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- typedef BOOST::uint8_t uint8_t;
- typedef BOOST::uint16_t uint16_t;
-
- #if BLARGG_BIG_ENDIAN
- struct regs_t { uint8_t b, c, d, e, h, l, flags, a; };
- #else
- struct regs_t { uint8_t c, b, e, d, l, h, a, flags; };
- #endif
- BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
-
- struct pairs_t { uint16_t bc, de, hl, fa; };
-
- // Registers are not updated until run() returns
- struct registers_t {
- uint16_t pc;
- uint16_t sp;
- uint16_t ix;
- uint16_t iy;
- union {
- regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
- pairs_t w; // w.bc, w.de, w.hl. w.fa
- };
- union {
- regs_t b;
- pairs_t w;
- } alt;
- uint8_t iff1;
- uint8_t iff2;
- uint8_t r;
- uint8_t i;
- uint8_t im;
- };
- //registers_t r; (below for efficiency)
-
- // can read this far past end of memory
- enum { cpu_padding = 0x100 };
-
-public:
- Ay_Cpu();
-private:
- uint8_t szpc [0x200];
- uint8_t* mem;
- cpu_time_t end_time_;
- struct state_t {
- cpu_time_t base;
- cpu_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- void set_end_time( cpu_time_t t );
-public:
- registers_t r;
-};
-
-inline void Ay_Cpu::set_end_time( cpu_time_t t )
-{
- cpu_time_t delta = state->base - t;
- state->base = t;
- state->time += delta;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.cpp
deleted file mode 100644
index bdc82e9e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Ay_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const spectrum_clock = 3546900;
-long const cpc_clock = 2000000;
-
-unsigned const ram_start = 0x4000;
-int const osc_count = Ay_Apu::osc_count + 1;
-
-Ay_Emu::Ay_Emu()
-{
- beeper_output = 0;
- set_type( gme_ay_type );
-
- static const char* const names [osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Beeper"
- };
- set_voice_names( names );
-
- static int const types [osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2, mixed_type | 0
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
-}
-
-Ay_Emu::~Ay_Emu() { }
-
-// Track info
-
-static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size )
-{
- long pos = ptr - (byte const*) file.header;
- long file_size = file.end - (byte const*) file.header;
- assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
- int offset = (BOOST::int16_t) get_be16( ptr );
- if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
- return 0;
- return ptr + offset;
-}
-
-static blargg_err_t parse_header( byte const* in, long size, Ay_Emu::file_t* out )
-{
- typedef Ay_Emu::header_t header_t;
- out->header = (header_t const*) in;
- out->end = in + size;
-
- if ( size < Ay_Emu::header_size )
- return gme_wrong_file_type;
-
- header_t const& h = *(header_t const*) in;
- if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
- return gme_wrong_file_type;
-
- out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
- if ( !out->tracks )
- return "Missing track data";
-
- return 0;
-}
-
-static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
-{
- Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
- byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
- if ( track_info )
- out->length = get_be16( track_info + 4 ) * (1000L / 50); // frames to msec
-
- Gme_File::copy_field_( out->author, (char const*) get_data( file, file.header->author, 1 ) );
- Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
-}
-
-blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
-{
- copy_ay_fields( file, out, track );
- return 0;
-}
-
-struct Ay_File : Gme_Info_
-{
- Ay_Emu::file_t file;
-
- Ay_File() { set_type( gme_ay_type ); }
-
- blargg_err_t load_mem_( byte const* begin, long size )
- {
- RETURN_ERR( parse_header( begin, size, &file ) );
- set_track_count( file.header->max_track + 1 );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- copy_ay_fields( file, out, track );
- return 0;
- }
-};
-
-static Music_Emu* new_ay_emu () { return BLARGG_NEW Ay_Emu ; }
-static Music_Emu* new_ay_file() { return BLARGG_NEW Ay_File; }
-
-gme_type_t_ const gme_ay_type [1] = { "ZX Spectrum", 0, &new_ay_emu, &new_ay_file, "AY", 1 };
-
-// Setup
-
-blargg_err_t Ay_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,track_info [2]) == header_size );
-
- RETURN_ERR( parse_header( in, size, &file ) );
- set_track_count( file.header->max_track + 1 );
-
- if ( file.header->vers > 2 )
- set_warning( "Unknown file version" );
-
- set_voice_count( osc_count );
- apu.volume( gain() );
-
- return setup_buffer( spectrum_clock );
-}
-
-void Ay_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
-{
- if ( i >= Ay_Apu::osc_count )
- beeper_output = center;
- else
- apu.osc_output( i, center );
-}
-
-// Emulation
-
-void Ay_Emu::set_tempo_( double t )
-{
- play_period = blip_time_t (clock_rate() / 50 / t);
-}
-
-blargg_err_t Ay_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( mem.ram + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
- memset( mem.ram + 0x0100, 0xFF, 0x4000 - 0x100 );
- memset( mem.ram + ram_start, 0x00, sizeof mem.ram - ram_start );
- memset( mem.padding1, 0xFF, sizeof mem.padding1 );
- memset( mem.ram + 0x10000, 0xFF, sizeof mem.ram - 0x10000 );
-
- // locate data blocks
- byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
- if ( !data ) return "File data missing";
-
- byte const* const more_data = get_data( file, data + 10, 6 );
- if ( !more_data ) return "File data missing";
-
- byte const* blocks = get_data( file, data + 12, 8 );
- if ( !blocks ) return "File data missing";
-
- // initial addresses
- cpu::reset( mem.ram );
- r.sp = get_be16( more_data );
- r.b.a = r.b.b = r.b.d = r.b.h = data [8];
- r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
- r.alt.w = r.w;
- r.ix = r.iy = r.w.hl;
-
- unsigned addr = get_be16( blocks );
- if ( !addr ) return "File data missing";
-
- unsigned init = get_be16( more_data + 2 );
- if ( !init )
- init = addr;
-
- // copy blocks into memory
- do
- {
- blocks += 2;
- unsigned len = get_be16( blocks ); blocks += 2;
- if ( addr + len > 0x10000 )
- {
- set_warning( "Bad data block size" );
- len = 0x10000 - addr;
- }
- check( len );
- byte const* in = get_data( file, blocks, 0 ); blocks += 2;
- if ( len > blargg_ulong (file.end - in) )
- {
- set_warning( "Missing file data" );
- len = file.end - in;
- }
- //dprintf( "addr: $%04X, len: $%04X\n", addr, len );
- if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
- dprintf( "Block addr in ROM\n" );
- memcpy( mem.ram + addr, in, len );
-
- if ( file.end - blocks < 8 )
- {
- set_warning( "Missing file data" );
- break;
- }
- }
- while ( (addr = get_be16( blocks )) != 0 );
-
- // copy and configure driver
- static byte const passive [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x5E, // LOOP: IM 2
- 0xFB, // EI
- 0x76, // HALT
- 0x18, 0xFA // JR LOOP
- };
- static byte const active [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x56, // LOOP: IM 1
- 0xFB, // EI
- 0x76, // HALT
- 0xCD, 0, 0, // CALL play
- 0x18, 0xF7 // JR LOOP
- };
- memcpy( mem.ram, passive, sizeof passive );
- unsigned play_addr = get_be16( more_data + 4 );
- //dprintf( "Play: $%04X\n", play_addr );
- if ( play_addr )
- {
- memcpy( mem.ram, active, sizeof active );
- mem.ram [ 9] = play_addr;
- mem.ram [10] = play_addr >> 8;
- }
- mem.ram [2] = init;
- mem.ram [3] = init >> 8;
-
- mem.ram [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
-
- memcpy( mem.ram + 0x10000, mem.ram, 0x80 ); // some code wraps around (ugh)
-
- beeper_delta = int (apu.amp_range * 0.65);
- last_beeper = 0;
- apu.reset();
- next_play = play_period;
-
- // start at spectrum speed
- change_clock_rate( spectrum_clock );
- set_tempo( tempo() );
-
- spectrum_mode = false;
- cpc_mode = false;
- cpc_latch = 0;
-
- return 0;
-}
-
-// Emulation
-
-void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
-{
- if ( !cpc_mode )
- {
- switch ( addr & 0xFEFF )
- {
- case 0xFEFD:
- spectrum_mode = true;
- apu_addr = data & 0x0F;
- return;
-
- case 0xBEFD:
- spectrum_mode = true;
- apu.write( time, apu_addr, data );
- return;
- }
- }
-
- if ( !spectrum_mode )
- {
- switch ( addr >> 8 )
- {
- case 0xF6:
- switch ( data & 0xC0 )
- {
- case 0xC0:
- apu_addr = cpc_latch & 0x0F;
- goto enable_cpc;
-
- case 0x80:
- apu.write( time, apu_addr, cpc_latch );
- goto enable_cpc;
- }
- break;
-
- case 0xF4:
- cpc_latch = data;
- goto enable_cpc;
- }
- }
-
- dprintf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
- return;
-
-enable_cpc:
- if ( !cpc_mode )
- {
- cpc_mode = true;
- change_clock_rate( cpc_clock );
- set_tempo( tempo() );
- }
-}
-
-void ay_cpu_out( Ay_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
- Ay_Emu& emu = STATIC_CAST(Ay_Emu&,*cpu);
-
- if ( (addr & 0xFF) == 0xFE && !emu.cpc_mode )
- {
- int delta = emu.beeper_delta;
- data &= 0x10;
- if ( emu.last_beeper != data )
- {
- emu.last_beeper = data;
- emu.beeper_delta = -delta;
- emu.spectrum_mode = true;
- if ( emu.beeper_output )
- emu.apu.synth_.offset( time, delta, emu.beeper_output );
- }
- }
- else
- {
- emu.cpu_out_misc( time, addr, data );
- }
-}
-
-int ay_cpu_in( Ay_Cpu*, unsigned addr )
-{
- // keyboard read and other things
- if ( (addr & 0xFF) == 0xFE )
- return 0xFF; // other values break some beeper tunes
-
- dprintf( "Unmapped IN : $%04X\n", addr );
- return 0xFF;
-}
-
-blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- if ( !(spectrum_mode | cpc_mode) )
- duration /= 2; // until mode is set, leave room for halved clock rate
-
- while ( time() < duration )
- {
- cpu::run( min( duration, (blip_time_t) next_play ) );
-
- if ( time() >= next_play )
- {
- next_play += play_period;
-
- if ( r.iff1 )
- {
- if ( mem.ram [r.pc] == 0x76 )
- r.pc++;
-
- r.iff1 = r.iff2 = 0;
-
- mem.ram [--r.sp] = uint8_t (r.pc >> 8);
- mem.ram [--r.sp] = uint8_t (r.pc);
- r.pc = 0x38;
- cpu::adjust_time( 12 );
- if ( r.im == 2 )
- {
- cpu::adjust_time( 6 );
- unsigned addr = r.i * 0x100u + 0xFF;
- r.pc = mem.ram [(addr + 1) & 0xFFFF] * 0x100u + mem.ram [addr];
- }
- }
- }
- }
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- adjust_time( -duration );
-
- apu.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.h
deleted file mode 100644
index ba8445d3..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ay_Emu.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Sinclair Spectrum AY music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef AY_EMU_H
-#define AY_EMU_H
-
-#include "Classic_Emu.h"
-#include "Ay_Apu.h"
-#include "Ay_Cpu.h"
-
-class Ay_Emu : private Ay_Cpu, public Classic_Emu {
- typedef Ay_Cpu cpu;
-public:
- // AY file header
- enum { header_size = 0x14 };
- struct header_t
- {
- byte tag [8];
- byte vers;
- byte player;
- byte unused [2];
- byte author [2];
- byte comment [2];
- byte max_track;
- byte first_track;
- byte track_info [2];
- };
-
- static gme_type_t static_type() { return gme_ay_type; }
-public:
- Ay_Emu();
- ~Ay_Emu();
- struct file_t {
- header_t const* header;
- byte const* end;
- byte const* tracks;
- };
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-private:
- file_t file;
-
- unsigned play_addr;
- cpu_time_t play_period;
- cpu_time_t next_play;
- Blip_Buffer* beeper_output;
- int beeper_delta;
- int last_beeper;
- int apu_addr;
- int cpc_latch;
- bool spectrum_mode;
- bool cpc_mode;
-
- // large items
- struct {
- byte padding1 [0x100];
- byte ram [0x10000 + 0x100];
- } mem;
- Ay_Apu apu;
- friend void ay_cpu_out( Ay_Cpu*, cpu_time_t, unsigned addr, int data );
- void cpu_out_misc( cpu_time_t, unsigned addr, int data );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.cpp
deleted file mode 100644
index 07e9d658..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Blip_Buffer.h"
-#include "blargg_common.h"
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
- factor_ = 0x7fffffff;
- offset_ = 0;
- buffer_ = 0;
- buffer_size_ = 0;
- sample_rate_ = 0;
- reader_accum_ = 0;
- bass_shift_ = 0;
- clock_rate_ = 0;
- bass_freq_ = 16;
- length_ = 0;
-
- // assumptions code makes about implementation-defined features
- #ifndef NDEBUG
- // right shift of negative value preserves sign
- buf_t_ i = -0x7FFFFFFE;
- assert( (i >> 1) == -0x3FFFFFFF );
-
- // casting to short truncates to 16 bits and sign-extends
- i = 0x18000;
- assert( (short) i == -0x8000 );
- #endif
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
- if ( buffer_size_ != silent_buf_size )
- free( buffer_ );
-}
-
-Silent_Blip_Buffer::Silent_Blip_Buffer()
-{
- factor_ = 0;
- buffer_ = buf;
- buffer_size_ = silent_buf_size;
- memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
-}
-
-void Blip_Buffer::clear( int entire_buffer )
-{
- offset_ = 0;
- reader_accum_ = 0;
- modified_ = 0;
- if ( buffer_ )
- {
- long count = (entire_buffer ? buffer_size_ : samples_avail());
- memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
- }
-}
-
-Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return "Internal (tried to resize Silent_Blip_Buffer)";
- }
-
- // start with maximum length that resampled time can represent
- long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
- if ( msec != blip_max_length )
- {
- long s = (new_rate * (msec + 1) + 999) / 1000;
- if ( s < new_size )
- new_size = s;
- else
- assert( 0 ); // fails if requested buffer length exceeds limit
- }
-
- if ( buffer_size_ != new_size )
- {
- void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- if ( !p )
- return "Out of memory";
- buffer_ = (buf_t_*) p;
- }
-
- buffer_size_ = new_size;
- assert( buffer_size_ != silent_buf_size );
-
- // update things based on the sample rate
- sample_rate_ = new_rate;
- length_ = new_size * 1000 / new_rate - 1;
- if ( msec )
- assert( length_ == msec ); // ensure length is same as that passed in
- if ( clock_rate_ )
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
-
- clear();
-
- return 0; // success
-}
-
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
-{
- double ratio = (double) sample_rate_ / rate;
- blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
- assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
- return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- int shift = 31;
- if ( freq > 0 )
- {
- shift = 13;
- long f = (freq << 16) / sample_rate_;
- while ( (f >>= 1) && --shift ) { }
- }
- bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
- offset_ += t * factor_;
- assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
-}
-
-void Blip_Buffer::remove_silence( long count )
-{
- assert( count <= samples_avail() ); // tried to remove more samples than available
- offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const
-{
- unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
- unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
- return (long) (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( long count ) const
-{
- if ( !factor_ )
- {
- assert( 0 ); // sample rate and clock rates must be set first
- return 0;
- }
-
- if ( count > buffer_size_ )
- count = buffer_size_;
- blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
- return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
- if ( count )
- {
- remove_silence( count );
-
- // copy remaining samples to beginning and clear old samples
- long remain = samples_avail() + blip_buffer_extra_;
- memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
- memset( buffer_ + remain, 0, count * sizeof *buffer_ );
- }
-}
-
-// Blip_Synth_
-
-Blip_Synth_Fast_::Blip_Synth_Fast_()
-{
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
- delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
-}
-
-#if !BLIP_BUFFER_FAST
-
-Blip_Synth_::Blip_Synth_( short* p, int w ) :
- impulses( p ),
- width( w )
-{
- volume_unit_ = 0.0;
- kernel_unit = 0;
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
-{
- if ( cutoff >= 0.999 )
- cutoff = 0.999;
-
- if ( treble < -300.0 )
- treble = -300.0;
- if ( treble > 5.0 )
- treble = 5.0;
-
- double const maxh = 4096.0;
- double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
- double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
- double const to_angle = PI / 2 / maxh / oversample;
- for ( int i = 0; i < count; i++ )
- {
- double angle = ((i - count) * 2 + 1) * to_angle;
- double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
- double cos_nc_angle = cos( maxh * cutoff * angle );
- double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
- double cos_angle = cos( angle );
-
- c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
- double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
- double b = 2.0 - cos_angle - cos_angle;
- double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
-
- out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
- }
-}
-
-void blip_eq_t::generate( float* out, int count ) const
-{
- // lower cutoff freq for narrow kernels with their wider transition band
- // (8 points->1.49, 16 points->1.15)
- double oversample = blip_res * 2.25 / count + 0.85;
- double half_rate = sample_rate * 0.5;
- if ( cutoff_freq )
- oversample = half_rate / cutoff_freq;
- double cutoff = rolloff_freq * oversample / half_rate;
-
- gen_sinc( out, count, blip_res * oversample, treble, cutoff );
-
- // apply (half of) hamming window
- double to_fraction = PI / (count - 1);
- for ( int i = count; i--; )
- out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
-}
-
-void Blip_Synth_::adjust_impulse()
-{
- // sum pairs for each phase and add error correction to end of first half
- int const size = impulses_size();
- for ( int p = blip_res; p-- >= blip_res / 2; )
- {
- int p2 = blip_res - 2 - p;
- long error = kernel_unit;
- for ( int i = 1; i < size; i += blip_res )
- {
- error -= impulses [i + p ];
- error -= impulses [i + p2];
- }
- if ( p == p2 )
- error /= 2; // phase = 0.5 impulse uses same half for both sides
- impulses [size - blip_res + p] += (short) error;
- //printf( "error: %ld\n", error );
- }
-
- //for ( int i = blip_res; i--; printf( "\n" ) )
- // for ( int j = 0; j < width / 2; j++ )
- // printf( "%5ld,", impulses [j * blip_res + i + 1] );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
- float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
-
- int const half_size = blip_res / 2 * (width - 1);
- eq.generate( &fimpulse [blip_res], half_size );
-
- int i;
-
- // need mirror slightly past center for calculation
- for ( i = blip_res; i--; )
- fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
-
- // starts at 0
- for ( i = 0; i < blip_res; i++ )
- fimpulse [i] = 0.0f;
-
- // find rescale factor
- double total = 0.0;
- for ( i = 0; i < half_size; i++ )
- total += fimpulse [blip_res + i];
-
- //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
- //double const base_unit = 37888.0; // allows treble to +5 dB
- double const base_unit = 32768.0; // necessary for blip_unscaled to work
- double rescale = base_unit / 2 / total;
- kernel_unit = (long) base_unit;
-
- // integrate, first difference, rescale, convert to int
- double sum = 0.0;
- double next = 0.0;
- int const impulses_size = this->impulses_size();
- for ( i = 0; i < impulses_size; i++ )
- {
- impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
- sum += fimpulse [i];
- next += fimpulse [i + blip_res];
- }
- adjust_impulse();
-
- // volume might require rescaling
- double vol = volume_unit_;
- if ( vol )
- {
- volume_unit_ = 0.0;
- volume_unit( vol );
- }
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
- if ( new_unit != volume_unit_ )
- {
- // use default eq if it hasn't been set yet
- if ( !kernel_unit )
- treble_eq( -8.0 );
-
- volume_unit_ = new_unit;
- double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
-
- if ( factor > 0.0 )
- {
- int shift = 0;
-
- // if unit is really small, might need to attenuate kernel
- while ( factor < 2.0 )
- {
- shift++;
- factor *= 2.0;
- }
-
- if ( shift )
- {
- kernel_unit >>= shift;
- assert( kernel_unit > 0 ); // fails if volume unit is too low
-
- // keep values positive to avoid round-towards-zero of sign-preserving
- // right shift for negative values
- long offset = 0x8000 + (1 << (shift - 1));
- long offset2 = 0x8000 >> shift;
- for ( int i = impulses_size(); i--; )
- impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
- adjust_impulse();
- }
- }
- delta_factor = (int) floor( factor + 0.5 );
- //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
- }
-}
-#endif
-
-long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
-{
- long count = samples_avail();
- if ( count > max_samples )
- count = max_samples;
-
- if ( count )
- {
- int const bass = BLIP_READER_BASS( *this );
- BLIP_READER_BEGIN( reader, *this );
-
- if ( !stereo )
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out++ = (blip_sample_t) s;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- else
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out = (blip_sample_t) s;
- out += 2;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- BLIP_READER_END( reader, *this );
-
- remove_samples( count );
- }
- return count;
-}
-
-void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return;
- }
-
- buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
-
- int const sample_shift = blip_sample_bits - 16;
- int prev = 0;
- while ( count-- )
- {
- blip_long s = (blip_long) *in++ << sample_shift;
- *out += s - prev;
- prev = s;
- ++out;
- }
- *out -= prev;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.h
deleted file mode 100644
index 73341b8c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Blip_Buffer.h
+++ /dev/null
@@ -1,485 +0,0 @@
-// Band-limited sound synthesis buffer
-
-// Blip_Buffer 0.4.1
-#ifndef BLIP_BUFFER_H
-#define BLIP_BUFFER_H
-
-// internal
-#include <limits.h>
-#include <stdint.h>
-typedef int32_t blip_long;
-typedef uint32_t blip_ulong;
-
-// Time unit at source clock rate
-typedef blip_long blip_time_t;
-
-// Output samples are 16-bit signed, with a range of -32768 to 32767
-typedef short blip_sample_t;
-enum { blip_sample_max = 32767 };
-
-class Blip_Buffer {
-public:
- typedef const char* blargg_err_t;
-
- // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
- // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
- // isn't enough memory, returns error without affecting current buffer setup.
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
-
- // Set number of source time units per second
- void clock_rate( long );
-
- // End current time frame of specified duration and make its samples available
- // (along with any still-unread samples) for reading with read_samples(). Begins
- // a new time frame at the end of the current frame.
- void end_frame( blip_time_t time );
-
- // Read at most 'max_samples' out of buffer into 'dest', removing them from from
- // the buffer. Returns number of samples actually read and removed. If stereo is
- // true, increments 'dest' one extra time after writing each sample, to allow
- // easy interleving of two channels into a stereo output buffer.
- long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
-
-// Additional optional features
-
- // Current output sample rate
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // Number of source time units per second
- long clock_rate() const;
-
- // Set frequency high-pass filter frequency, where higher values reduce bass more
- void bass_freq( int frequency );
-
- // Number of samples delay from synthesis to samples read out
- int output_latency() const;
-
- // Remove all available samples and clear buffer to silence. If 'entire_buffer' is
- // false, just clears out any samples waiting rather than the entire buffer.
- void clear( int entire_buffer = 1 );
-
- // Number of samples available for reading with read_samples()
- long samples_avail() const;
-
- // Remove 'count' samples from those waiting to be read
- void remove_samples( long count );
-
-// Experimental features
-
- // Count number of clocks needed until 'count' samples will be available.
- // If buffer can't even hold 'count' samples, returns number of clocks until
- // buffer becomes full.
- blip_time_t count_clocks( long count ) const;
-
- // Number of raw samples that can be mixed within frame of specified duration.
- long count_samples( blip_time_t duration ) const;
-
- // Mix 'count' samples from 'buf' into buffer.
- void mix_samples( blip_sample_t const* buf, long count );
-
- // not documented yet
- void set_modified() { modified_ = 1; }
- int clear_modified() { int b = modified_; modified_ = 0; return b; }
- typedef blip_ulong blip_resampled_time_t;
- void remove_silence( long count );
- blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
- blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
- blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
-public:
- Blip_Buffer();
- ~Blip_Buffer();
-
- // Deprecated
- typedef blip_resampled_time_t resampled_time_t;
- blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
- blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
-private:
- // noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-public:
- typedef blip_time_t buf_t_;
- blip_ulong factor_;
- blip_resampled_time_t offset_;
- buf_t_* buffer_;
- blip_long buffer_size_;
- blip_long reader_accum_;
- int bass_shift_;
-private:
- long sample_rate_;
- long clock_rate_;
- int bass_freq_;
- int length_;
- int modified_;
- friend class Blip_Reader;
-};
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
-// but reduce maximum buffer size.
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
-
-// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
-// noticeable broadband noise when synthesizing high frequency square waves.
-// Affects size of Blip_Synth objects since they store the waveform directly.
-#ifndef BLIP_PHASE_BITS
- #if BLIP_BUFFER_FAST
- #define BLIP_PHASE_BITS 8
- #else
- #define BLIP_PHASE_BITS 6
- #endif
-#endif
-
- // Internal
- typedef blip_ulong blip_resampled_time_t;
- int const blip_widest_impulse_ = 16;
- int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
- int const blip_res = 1 << BLIP_PHASE_BITS;
- class blip_eq_t;
-
- class Blip_Synth_Fast_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_Fast_();
- void treble_eq( blip_eq_t const& ) { }
- };
-
- class Blip_Synth_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_( short* impulses, int width );
- void treble_eq( blip_eq_t const& );
- private:
- double volume_unit_;
- short* const impulses;
- int const width;
- blip_long kernel_unit;
- int impulses_size() const { return blip_res / 2 * width + 1; }
- void adjust_impulse();
- };
-
-// Quality level. Start with blip_good_quality.
-const int blip_med_quality = 8;
-const int blip_good_quality = 12;
-const int blip_high_quality = 16;
-
-// Range specifies the greatest expected change in amplitude. Calculate it
-// by finding the difference between the maximum and minimum expected
-// amplitudes (max - min).
-template<int quality,int range>
-class Blip_Synth {
-public:
- // Set overall volume of waveform
- void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
-
- // Configure low-pass filter (see blip_buffer.txt)
- void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
-
- // Get/set Blip_Buffer used for output
- Blip_Buffer* output() const { return impl.buf; }
- void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
-
- // Update amplitude of waveform at given time. Using this requires a separate
- // Blip_Synth for each waveform.
- void update( blip_time_t time, int amplitude );
-
-// Low-level interface
-
- // Add an amplitude transition of specified delta, optionally into specified buffer
- // rather than the one set with output(). Delta can be positive or negative.
- // The actual change in amplitude is delta * (volume / range)
- void offset( blip_time_t, int delta, Blip_Buffer* ) const;
- void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
-
- // Works directly in terms of fractional output samples. Contact author for more info.
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
-
- // Same as offset(), except code is inlined for higher performance
- void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
- }
- void offset_inline( blip_time_t t, int delta ) const {
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
- }
-
-private:
-#if BLIP_BUFFER_FAST
- Blip_Synth_Fast_ impl;
-#else
- Blip_Synth_ impl;
- typedef short imp_t;
- imp_t impulses [blip_res * (quality / 2) + 1];
-public:
- Blip_Synth() : impl( impulses, quality ) { }
-#endif
-};
-
-// Low-pass equalization parameters
-class blip_eq_t {
-public:
- // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
- // treble, small positive values (0 to 5.0) increase treble.
- blip_eq_t( double treble_db = 0 );
-
- // See blip_buffer.txt
- blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
-
-private:
- double treble;
- long rolloff_freq;
- long sample_rate;
- long cutoff_freq;
- void generate( float* out, int count ) const;
- friend class Blip_Synth_;
-};
-
-int const blip_sample_bits = 30;
-
-// Dummy Blip_Buffer to direct sound output to, for easy muting without
-// having to stop sound code.
-class Silent_Blip_Buffer : public Blip_Buffer {
- buf_t_ buf [blip_buffer_extra_ + 1];
-public:
- // The following cannot be used (an assertion will fail if attempted):
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
- blip_time_t count_clocks( long count ) const;
- void mix_samples( blip_sample_t const* buf, long count );
-
- Silent_Blip_Buffer();
-};
-
- #if defined (__GNUC__) || _MSC_VER >= 1100
- #define BLIP_RESTRICT __restrict
- #else
- #define BLIP_RESTRICT
- #endif
-
-// Optimized reading from Blip_Buffer, for use in custom sample output
-
-// Begin reading from buffer. Name should be unique to the current block.
-#define BLIP_READER_BEGIN( name, blip_buffer ) \
- const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
- blip_long name##_reader_accum = (blip_buffer).reader_accum_
-
-// Get value to pass to BLIP_READER_NEXT()
-#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
-
-// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
-// code at the cost of having no bass control
-int const blip_reader_default_bass = 9;
-
-// Current sample
-#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
-
-// Current raw sample in full internal resolution
-#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
-
-// Advance to next sample
-#define BLIP_READER_NEXT( name, bass ) \
- (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
-
-// End reading samples from buffer. The number of samples read must now be removed
-// using Blip_Buffer::remove_samples().
-#define BLIP_READER_END( name, blip_buffer ) \
- (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
-
-
-// Compatibility with older version
-const long blip_unscaled = 65535;
-const int blip_low_quality = blip_med_quality;
-const int blip_best_quality = blip_high_quality;
-
-// Deprecated; use BLIP_READER macros as follows:
-// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
-// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
-// r.read() -> BLIP_READER_READ( r )
-// r.read_raw() -> BLIP_READER_READ_RAW( r )
-// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
-// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
-// r.end( buf ) -> BLIP_READER_END( r, buf )
-class Blip_Reader {
-public:
- int begin( Blip_Buffer& );
- blip_long read() const { return accum >> (blip_sample_bits - 16); }
- blip_long read_raw() const { return accum; }
- void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
- void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
-
-private:
- const Blip_Buffer::buf_t_* buf;
- blip_long accum;
-};
-
-// End of public interface
-
-#include <assert.h>
-
-template<int quality,int range>
-inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
- int delta, Blip_Buffer* blip_buf ) const
-{
- // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
- // need for a longer buffer as set by set_sample_rate().
- assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
- delta *= impl.delta_factor;
- blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
- int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
-
-#if BLIP_BUFFER_FAST
- blip_long left = buf [0] + delta;
-
- // Kind of crappy, but doing shift after multiply results in overflow.
- // Alternate way of delaying multiply by delta_factor results in worse
- // sub-sample resolution.
- blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
- left -= right;
- right += buf [1];
-
- buf [0] = left;
- buf [1] = right;
-#else
-
- int const fwd = (blip_widest_impulse_ - quality) / 2;
- int const rev = fwd + quality - 2;
- int const mid = quality / 2 - 1;
-
- imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
-
- #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
-
- // straight forward implementation resulted in better code on GCC for x86
-
- #define ADD_IMP( out, in ) \
- buf [out] += (blip_long) imp [blip_res * (in)] * delta
-
- #define BLIP_FWD( i ) {\
- ADD_IMP( fwd + i, i );\
- ADD_IMP( fwd + 1 + i, i + 1 );\
- }
- #define BLIP_REV( r ) {\
- ADD_IMP( rev - r, r + 1 );\
- ADD_IMP( rev + 1 - r, r );\
- }
-
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- ADD_IMP( fwd + mid - 1, mid - 1 );
- ADD_IMP( fwd + mid , mid );
- imp = impulses + phase;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- ADD_IMP( rev , 1 );
- ADD_IMP( rev + 1, 0 );
-
- #else
-
- // for RISC processors, help compiler by reading ahead of writes
-
- #define BLIP_FWD( i ) {\
- blip_long t0 = i0 * delta + buf [fwd + i];\
- blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
- i0 = imp [blip_res * (i + 2)];\
- buf [fwd + i] = t0;\
- buf [fwd + 1 + i] = t1;\
- }
- #define BLIP_REV( r ) {\
- blip_long t0 = i0 * delta + buf [rev - r];\
- blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
- i0 = imp [blip_res * (r - 1)];\
- buf [rev - r] = t0;\
- buf [rev + 1 - r] = t1;\
- }
-
- blip_long i0 = *imp;
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- blip_long t0 = i0 * delta + buf [fwd + mid - 1];
- blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
- imp = impulses + phase;
- i0 = imp [blip_res * mid];
- buf [fwd + mid - 1] = t0;
- buf [fwd + mid ] = t1;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- blip_long t0 = i0 * delta + buf [rev ];
- blip_long t1 = *imp * delta + buf [rev + 1];
- buf [rev ] = t0;
- buf [rev + 1] = t1;
- #endif
-
-#endif
-}
-
-#undef BLIP_FWD
-#undef BLIP_REV
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
-{
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
-}
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
-{
- int delta = amp - impl.last_amp;
- impl.last_amp = amp;
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
-}
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
-inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
- treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
-
-inline int Blip_Buffer::length() const { return length_; }
-inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
-inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
-inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
-inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
-inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
-
-inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
-{
- buf = blip_buf.buffer_;
- accum = blip_buf.reader_accum_;
- return blip_buf.bass_shift_;
-}
-
-int const blip_max_length = 0;
-int const blip_default_length = 250;
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.cpp
deleted file mode 100644
index 063444fe..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Classic_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Classic_Emu::Classic_Emu()
-{
- buf = 0;
- stereo_buffer = 0;
- voice_types = 0;
-
- // avoid inconsistency in our duplicated constants
- assert( (int) wave_type == (int) Multi_Buffer::wave_type );
- assert( (int) noise_type == (int) Multi_Buffer::noise_type );
- assert( (int) mixed_type == (int) Multi_Buffer::mixed_type );
-}
-
-Classic_Emu::~Classic_Emu()
-{
- delete stereo_buffer;
-}
-
-void Classic_Emu::set_equalizer_( equalizer_t const& eq )
-{
- Music_Emu::set_equalizer_( eq );
- update_eq( eq.treble );
- if ( buf )
- buf->bass_freq( equalizer().bass );
-}
-
-blargg_err_t Classic_Emu::set_sample_rate_( long rate )
-{
- if ( !buf )
- {
- if ( !stereo_buffer )
- CHECK_ALLOC( stereo_buffer = BLARGG_NEW Stereo_Buffer );
- buf = stereo_buffer;
- }
- return buf->set_sample_rate( rate, 1000 / 20 );
-}
-
-void Classic_Emu::mute_voices_( int mask )
-{
- Music_Emu::mute_voices_( mask );
- for ( int i = voice_count(); i--; )
- {
- if ( mask & (1 << i) )
- {
- set_voice( i, 0, 0, 0 );
- }
- else
- {
- Multi_Buffer::channel_t ch = buf->channel( i, (voice_types ? voice_types [i] : 0) );
- assert( (ch.center && ch.left && ch.right) ||
- (!ch.center && !ch.left && !ch.right) ); // all or nothing
- set_voice( i, ch.center, ch.left, ch.right );
- }
- }
-}
-
-void Classic_Emu::change_clock_rate( long rate )
-{
- clock_rate_ = rate;
- buf->clock_rate( rate );
-}
-
-blargg_err_t Classic_Emu::setup_buffer( long rate )
-{
- change_clock_rate( rate );
- RETURN_ERR( buf->set_channel_count( voice_count() ) );
- set_equalizer( equalizer() );
- buf_changed_count = buf->channels_changed_count();
- return 0;
-}
-
-blargg_err_t Classic_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- buf->clear();
- return 0;
-}
-
-blargg_err_t Classic_Emu::play_( long count, sample_t* out )
-{
- long remain = count;
- while ( remain )
- {
- remain -= buf->read_samples( &out [count - remain], remain );
- if ( remain )
- {
- if ( buf_changed_count != buf->channels_changed_count() )
- {
- buf_changed_count = buf->channels_changed_count();
- remute_voices();
- }
- int msec = buf->length();
- blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000;
- RETURN_ERR( run_clocks( clocks_emulated, msec ) );
- assert( clocks_emulated );
- buf->end_frame( clocks_emulated );
- }
- }
- return 0;
-}
-
-// Rom_Data
-
-blargg_err_t Rom_Data_::load_rom_data_( Data_Reader& in,
- int header_size, void* header_out, int fill, long pad_size )
-{
- long file_offset = pad_size - header_size;
-
- rom_addr = 0;
- mask = 0;
- size_ = 0;
- rom.clear();
-
- file_size_ = in.remain();
- if ( file_size_ <= header_size ) // <= because there must be data after header
- return gme_wrong_file_type;
- blargg_err_t err = rom.resize( file_offset + file_size_ + pad_size );
- if ( !err )
- err = in.read( rom.begin() + file_offset, file_size_ );
- if ( err )
- {
- rom.clear();
- return err;
- }
-
- file_size_ -= header_size;
- memcpy( header_out, &rom [file_offset], header_size );
-
- memset( rom.begin() , fill, pad_size );
- memset( rom.end() - pad_size, fill, pad_size );
-
- return 0;
-}
-
-void Rom_Data_::set_addr_( long addr, int unit )
-{
- rom_addr = addr - unit - pad_extra;
-
- long rounded = (addr + file_size_ + unit - 1) / unit * unit;
- if ( rounded <= 0 )
- {
- rounded = 0;
- }
- else
- {
- int shift = 0;
- unsigned long max_addr = (unsigned long) (rounded - 1);
- while ( max_addr >> shift )
- shift++;
- mask = (1L << shift) - 1;
- }
-
- if ( addr < 0 )
- addr = 0;
- size_ = rounded;
- if ( rom.resize( rounded - rom_addr + pad_extra ) ) { } // OK if shrink fails
-
- if ( 0 )
- {
- dprintf( "addr: %X\n", addr );
- dprintf( "file_size: %d\n", file_size_ );
- dprintf( "rounded: %d\n", rounded );
- dprintf( "mask: $%X\n", mask );
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.h
deleted file mode 100644
index 8cd822ca..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Classic_Emu.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Common aspects of emulators which use Blip_Buffer for sound output
-
-// Game_Music_Emu 0.5.2
-#ifndef CLASSIC_EMU_H
-#define CLASSIC_EMU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-#include "Music_Emu.h"
-
-class Classic_Emu : public Music_Emu {
-public:
- Classic_Emu();
- ~Classic_Emu();
- void set_buffer( Multi_Buffer* );
-protected:
- // Services
- enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
- void set_voice_types( int const* t ) { voice_types = t; }
- blargg_err_t setup_buffer( long clock_rate );
- long clock_rate() const { return clock_rate_; }
- void change_clock_rate( long ); // experimental
-
- // Overridable
- virtual void set_voice( int index, Blip_Buffer* center,
- Blip_Buffer* left, Blip_Buffer* right ) = 0;
- virtual void update_eq( blip_eq_t const& ) = 0;
- virtual blargg_err_t start_track_( int track ) = 0;
- virtual blargg_err_t run_clocks( blip_time_t& time_io, int msec ) = 0;
-protected:
- blargg_err_t set_sample_rate_( long sample_rate );
- void mute_voices_( int );
- void set_equalizer_( equalizer_t const& );
- blargg_err_t play_( long, sample_t* );
-private:
- Multi_Buffer* buf;
- Multi_Buffer* stereo_buffer; // NULL if using custom buffer
- long clock_rate_;
- unsigned buf_changed_count;
- int const* voice_types;
-};
-
-inline void Classic_Emu::set_buffer( Multi_Buffer* new_buf )
-{
- assert( !buf && new_buf );
- buf = new_buf;
-}
-
-// ROM data handler, used by several Classic_Emu derivitives. Loads file data
-// with padding on both sides, allowing direct use in bank mapping. The main purpose
-// is to allow all file data to be loaded with only one read() call (for efficiency).
-
-class Rom_Data_ {
-public:
- typedef unsigned char byte;
-protected:
- enum { pad_extra = 8 };
- blargg_vector<byte> rom;
- long file_size_;
- blargg_long rom_addr;
- blargg_long mask;
- blargg_long size_; // TODO: eliminate
-
- blargg_err_t load_rom_data_( Data_Reader& in, int header_size, void* header_out,
- int fill, long pad_size );
- void set_addr_( long addr, int unit );
-};
-
-template<int unit>
-class Rom_Data : public Rom_Data_ {
- enum { pad_size = unit + pad_extra };
-public:
- // Load file data, using already-loaded header 'h' if not NULL. Copy header
- // from loaded file data into *out and fill unmapped bytes with 'fill'.
- blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill )
- {
- return load_rom_data_( in, header_size, header_out, fill, pad_size );
- }
-
- // Size of file data read in (excluding header)
- long file_size() const { return file_size_; }
-
- // Pointer to beginning of file data
- byte* begin() const { return rom.begin() + pad_size; }
-
- // Set address that file data should start at
- void set_addr( long addr ) { set_addr_( addr, unit ); }
-
- // Free data
- void clear() { rom.clear(); }
-
- // Size of data + start addr, rounded to a multiple of unit
- long size() const { return size_; }
-
- // Pointer to unmapped page filled with same value
- byte* unmapped() { return rom.begin(); }
-
- // Mask address to nearest power of two greater than size()
- blargg_long mask_addr( blargg_long addr ) const
- {
- #ifdef check
- check( addr <= mask );
- #endif
- return addr & mask;
- }
-
- // Pointer to page starting at addr. Returns unmapped() if outside data.
- byte* at_addr( blargg_long addr )
- {
- blargg_ulong offset = mask_addr( addr ) - rom_addr;
- if ( offset > blargg_ulong (rom.size() - pad_size) )
- offset = 0; // unmapped
- return &rom [offset];
- }
-};
-
-#ifndef GME_APU_HOOK
- #define GME_APU_HOOK( emu, addr, data ) ((void) 0)
-#endif
-
-#ifndef GME_FRAME_HOOK
- #define GME_FRAME_HOOK( emu ) ((void) 0)
-#else
- #define GME_FRAME_HOOK_DEFINED 1
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.cpp
deleted file mode 100644
index 5bbfbf55..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-// File_Extractor 0.4.0. http://www.slack.net/~ant/
-
-#include "Data_Reader.h"
-
-#include "blargg_endian.h"
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char Data_Reader::eof_error [] = "Unexpected end of file";
-
-blargg_err_t Data_Reader::read( void* p, long s )
-{
- long result = read_avail( p, s );
- if ( result != s )
- {
- if ( result >= 0 && result < s )
- return eof_error;
-
- return "Read error";
- }
-
- return 0;
-}
-
-blargg_err_t Data_Reader::skip( long count )
-{
- char buf [512];
- while ( count )
- {
- long n = sizeof buf;
- if ( n > count )
- n = count;
- count -= n;
- RETURN_ERR( read( buf, n ) );
- }
- return 0;
-}
-
-long File_Reader::remain() const { return size() - tell(); }
-
-blargg_err_t File_Reader::skip( long n )
-{
- assert( n >= 0 );
- if ( !n )
- return 0;
- return seek( tell() + n );
-}
-
-// Subset_Reader
-
-Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
-{
- in = dr;
- remain_ = dr->remain();
- if ( remain_ > size )
- remain_ = size;
-}
-
-long Subset_Reader::remain() const { return remain_; }
-
-long Subset_Reader::read_avail( void* p, long s )
-{
- if ( s > remain_ )
- s = remain_;
- remain_ -= s;
- return in->read_avail( p, s );
-}
-
-// Remaining_Reader
-
-Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
-{
- header = (char const*) h;
- header_end = header + size;
- in = r;
-}
-
-long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
-
-long Remaining_Reader::read_first( void* out, long count )
-{
- long first = header_end - header;
- if ( first )
- {
- if ( first > count )
- first = count;
- void const* old = header;
- header += first;
- memcpy( out, old, first );
- }
- return first;
-}
-
-long Remaining_Reader::read_avail( void* out, long count )
-{
- long first = read_first( out, count );
- long second = count - first;
- if ( second )
- {
- second = in->read_avail( (char*) out + first, second );
- if ( second <= 0 )
- return second;
- }
- return first + second;
-}
-
-blargg_err_t Remaining_Reader::read( void* out, long count )
-{
- long first = read_first( out, count );
- long second = count - first;
- if ( !second )
- return 0;
- return in->read( (char*) out + first, second );
-}
-
-// Mem_File_Reader
-
-Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
- begin( (const char*) p ),
- size_( s )
-{
- pos = 0;
-}
-
-long Mem_File_Reader::size() const { return size_; }
-
-long Mem_File_Reader::read_avail( void* p, long s )
-{
- long r = remain();
- if ( s > r )
- s = r;
- memcpy( p, begin + pos, s );
- pos += s;
- return s;
-}
-
-long Mem_File_Reader::tell() const { return pos; }
-
-blargg_err_t Mem_File_Reader::seek( long n )
-{
- if ( n > size_ )
- return eof_error;
- pos = n;
- return 0;
-}
-
-// Callback_Reader
-
-Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
- callback( c ),
- data( d )
-{
- remain_ = size;
-}
-
-long Callback_Reader::remain() const { return remain_; }
-
-long Callback_Reader::read_avail( void* out, long count )
-{
- if ( count > remain_ )
- count = remain_;
- if ( Callback_Reader::read( out, count ) )
- count = -1;
- return count;
-}
-
-blargg_err_t Callback_Reader::read( void* out, long count )
-{
- if ( count > remain_ )
- return eof_error;
- return callback( data, out, count );
-}
-
-// Std_File_Reader
-
-Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
-
-Std_File_Reader::~Std_File_Reader() { close(); }
-
-blargg_err_t Std_File_Reader::open( const char* path )
-{
- file_ = fopen( path, "rb" );
- if ( !file_ )
- return "Couldn't open file";
- return 0;
-}
-
-long Std_File_Reader::size() const
-{
- long pos = tell();
- fseek( (FILE*) file_, 0, SEEK_END );
- long result = tell();
- fseek( (FILE*) file_, pos, SEEK_SET );
- return result;
-}
-
-long Std_File_Reader::read_avail( void* p, long s )
-{
- return fread( p, 1, s, (FILE*) file_ );
-}
-
-blargg_err_t Std_File_Reader::read( void* p, long s )
-{
- if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
- return 0;
- if ( feof( (FILE*) file_ ) )
- return eof_error;
- return "Couldn't read from file";
-}
-
-long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
-
-blargg_err_t Std_File_Reader::seek( long n )
-{
- if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
- return 0;
- if ( n > size() )
- return eof_error;
- return "Error seeking in file";
-}
-
-void Std_File_Reader::close()
-{
- if ( file_ )
- {
- fclose( (FILE*) file_ );
- file_ = 0;
- }
-}
-
-// Gzip_File_Reader
-
-#ifdef HAVE_ZLIB_H
-
-#include "zlib.h"
-
-static const char* get_gzip_eof( const char* path, long* eof )
-{
- FILE* file = fopen( path, "rb" );
- if ( !file )
- return "Couldn't open file";
-
- unsigned char buf [4];
- if ( fread( buf, 2, 1, file ) > 0 && buf [0] == 0x1F && buf [1] == 0x8B )
- {
- fseek( file, -4, SEEK_END );
- fread( buf, 4, 1, file );
- *eof = get_le32( buf );
- }
- else
- {
- fseek( file, 0, SEEK_END );
- *eof = ftell( file );
- }
- const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0;
- fclose( file );
- return err;
-}
-
-Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
-
-Gzip_File_Reader::~Gzip_File_Reader() { close(); }
-
-blargg_err_t Gzip_File_Reader::open( const char* path )
-{
- close();
-
- RETURN_ERR( get_gzip_eof( path, &size_ ) );
-
- file_ = gzopen( path, "rb" );
- if ( !file_ )
- return "Couldn't open file";
-
- return 0;
-}
-
-long Gzip_File_Reader::size() const { return size_; }
-
-long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
-
-long Gzip_File_Reader::tell() const { return gztell( file_ ); }
-
-blargg_err_t Gzip_File_Reader::seek( long n )
-{
- if ( gzseek( file_, n, SEEK_SET ) >= 0 )
- return 0;
- if ( n > size_ )
- return eof_error;
- return "Error seeking in file";
-}
-
-void Gzip_File_Reader::close()
-{
- if ( file_ )
- {
- gzclose( file_ );
- file_ = 0;
- }
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.h
deleted file mode 100644
index 00b53b9e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Data_Reader.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Data reader interface for uniform access
-
-// File_Extractor 0.4.0
-#ifndef DATA_READER_H
-#define DATA_READER_H
-
-#include "blargg_common.h"
-
-// Supports reading and finding out how many bytes are remaining
-class Data_Reader {
-public:
- virtual ~Data_Reader() { }
-
- static const char eof_error []; // returned by read() when request goes beyond end
-
- // Read at most count bytes and return number actually read, or <= 0 if error
- virtual long read_avail( void*, long n ) = 0;
-
- // Read exactly count bytes and return error if they couldn't be read
- virtual blargg_err_t read( void*, long count );
-
- // Number of bytes remaining until end of file
- virtual long remain() const = 0;
-
- // Read and discard count bytes
- virtual blargg_err_t skip( long count );
-
-public:
- Data_Reader() { }
- typedef blargg_err_t error_t; // deprecated
-private:
- // noncopyable
- Data_Reader( const Data_Reader& );
- Data_Reader& operator = ( const Data_Reader& );
-};
-
-// Supports seeking in addition to Data_Reader operations
-class File_Reader : public Data_Reader {
-public:
- // Size of file
- virtual long size() const = 0;
-
- // Current position in file
- virtual long tell() const = 0;
-
- // Go to new position
- virtual blargg_err_t seek( long ) = 0;
-
- long remain() const;
- blargg_err_t skip( long n );
-};
-
-// Disk file reader
-class Std_File_Reader : public File_Reader {
-public:
- blargg_err_t open( const char* path );
- void close();
-
-public:
- Std_File_Reader();
- ~Std_File_Reader();
- long size() const;
- blargg_err_t read( void*, long );
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- void* file_;
-};
-
-// Treats range of memory as a file
-class Mem_File_Reader : public File_Reader {
-public:
- Mem_File_Reader( const void*, long size );
-
-public:
- long size() const;
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- const char* const begin;
- const long size_;
- long pos;
-};
-
-// Makes it look like there are only count bytes remaining
-class Subset_Reader : public Data_Reader {
-public:
- Subset_Reader( Data_Reader*, long count );
-
-public:
- long remain() const;
- long read_avail( void*, long );
-private:
- Data_Reader* in;
- long remain_;
-};
-
-// Joins already-read header and remaining data into original file (to avoid seeking)
-class Remaining_Reader : public Data_Reader {
-public:
- Remaining_Reader( void const* header, long size, Data_Reader* );
-
-public:
- long remain() const;
- long read_avail( void*, long );
- blargg_err_t read( void*, long );
-private:
- char const* header;
- char const* header_end;
- Data_Reader* in;
- long read_first( void* out, long count );
-};
-
-// Invokes callback function to read data. Size of data must be specified in advance.
-class Callback_Reader : public Data_Reader {
-public:
- typedef const char* (*callback_t)( void* data, void* out, long count );
- Callback_Reader( callback_t, long size, void* data = 0 );
-public:
- long read_avail( void*, long );
- blargg_err_t read( void*, long );
- long remain() const;
-private:
- callback_t const callback;
- void* const data;
- long remain_;
-};
-
-#ifdef HAVE_ZLIB_H
-// Gzip compressed file reader
-class Gzip_File_Reader : public File_Reader {
-public:
- blargg_err_t open( const char* path );
- void close();
-
-public:
- Gzip_File_Reader();
- ~Gzip_File_Reader();
- long size() const;
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- void* file_;
- long size_;
-};
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.cpp
deleted file mode 100644
index 8644517c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Dual_Resampler.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const resampler_extra = 256;
-
-Dual_Resampler::Dual_Resampler() { }
-
-Dual_Resampler::~Dual_Resampler() { }
-
-blargg_err_t Dual_Resampler::reset( int pairs )
-{
- // expand allocations a bit
- RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
- resize( pairs );
- resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
- return resampler.buffer_size( resampler_size );
-}
-
-void Dual_Resampler::resize( int pairs )
-{
- int new_sample_buf_size = pairs * 2;
- if ( sample_buf_size != new_sample_buf_size )
- {
- if ( (unsigned) new_sample_buf_size > sample_buf.size() )
- {
- check( false );
- return;
- }
- sample_buf_size = new_sample_buf_size;
- oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2;
- clear();
- }
-}
-
-void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
-{
- long pair_count = sample_buf_size >> 1;
- blip_time_t blip_time = blip_buf.count_clocks( pair_count );
- int sample_count = oversamples_per_frame - resampler.written();
-
- int new_count = play_frame( blip_time, sample_count, resampler.buffer() );
- assert( new_count < resampler_size );
-
- blip_buf.end_frame( blip_time );
- assert( blip_buf.samples_avail() == pair_count );
-
- resampler.write( new_count );
-
- long count = resampler.read( sample_buf.begin(), sample_buf_size );
- assert( count == (long) sample_buf_size );
-
- mix_samples( blip_buf, out );
- blip_buf.remove_samples( pair_count );
-}
-
-void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf )
-{
- // empty extra buffer
- long remain = sample_buf_size - buf_pos;
- if ( remain )
- {
- if ( remain > count )
- remain = count;
- count -= remain;
- memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
- out += remain;
- buf_pos += remain;
- }
-
- // entire frames
- while ( count >= (long) sample_buf_size )
- {
- play_frame_( blip_buf, out );
- out += sample_buf_size;
- count -= sample_buf_size;
- }
-
- // extra
- if ( count )
- {
- play_frame_( blip_buf, sample_buf.begin() );
- buf_pos = count;
- memcpy( out, sample_buf.begin(), count * sizeof *out );
- out += count;
- }
-}
-
-void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
-{
- Blip_Reader sn;
- int bass = sn.begin( blip_buf );
- const dsample_t* in = sample_buf.begin();
-
- for ( int n = sample_buf_size >> 1; n--; )
- {
- int s = sn.read();
- blargg_long l = (blargg_long) in [0] * 2 + s;
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- sn.next( bass );
- blargg_long r = (blargg_long) in [1] * 2 + s;
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- in += 2;
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- sn.end( blip_buf );
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.h
deleted file mode 100644
index 61beb8a0..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Dual_Resampler.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators.
-
-// Game_Music_Emu 0.5.2
-#ifndef DUAL_RESAMPLER_H
-#define DUAL_RESAMPLER_H
-
-#include "Fir_Resampler.h"
-#include "Blip_Buffer.h"
-
-class Dual_Resampler {
-public:
- Dual_Resampler();
- virtual ~Dual_Resampler();
-
- typedef short dsample_t;
-
- double setup( double oversample, double rolloff, double gain );
- blargg_err_t reset( int max_pairs );
- void resize( int pairs_per_frame );
- void clear();
-
- void dual_play( long count, dsample_t* out, Blip_Buffer& );
-
-protected:
- virtual int play_frame( blip_time_t, int pcm_count, dsample_t* pcm_out ) = 0;
-private:
-
- blargg_vector<dsample_t> sample_buf;
- int sample_buf_size;
- int oversamples_per_frame;
- int buf_pos;
- int resampler_size;
-
- Fir_Resampler<12> resampler;
- void mix_samples( Blip_Buffer&, dsample_t* );
- void play_frame_( Blip_Buffer&, dsample_t* );
-};
-
-inline double Dual_Resampler::setup( double oversample, double rolloff, double gain )
-{
- return resampler.time_ratio( oversample, rolloff, gain * 0.5 );
-}
-
-inline void Dual_Resampler::clear()
-{
- buf_pos = sample_buf_size;
- resampler.clear();
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.cpp
deleted file mode 100644
index 730f8e94..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Effects_Buffer.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-typedef blargg_long fixed_t;
-
-#define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5)
-#define FMUL( x, y ) (((x) * (y)) >> 15)
-
-const unsigned echo_size = 4096;
-const unsigned echo_mask = echo_size - 1;
-BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2
-
-const unsigned reverb_size = 8192 * 2;
-const unsigned reverb_mask = reverb_size - 1;
-BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2
-
-Effects_Buffer::config_t::config_t()
-{
- pan_1 = -0.15f;
- pan_2 = 0.15f;
- reverb_delay = 88.0f;
- reverb_level = 0.12f;
- echo_delay = 61.0f;
- echo_level = 0.10f;
- delay_variance = 18.0f;
- effects_enabled = false;
-}
-
-void Effects_Buffer::set_depth( double d )
-{
- float f = (float) d;
- config_t c;
- c.pan_1 = -0.6f * f;
- c.pan_2 = 0.6f * f;
- c.reverb_delay = 880 * 0.1f;
- c.echo_delay = 610 * 0.1f;
- if ( f > 0.5 )
- f = 0.5; // TODO: more linear reduction of extreme reverb/echo
- c.reverb_level = 0.5f * f;
- c.echo_level = 0.30f * f;
- c.delay_variance = 180 * 0.1f;
- c.effects_enabled = (d > 0.0f);
- config( c );
-}
-
-Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 )
-{
- buf_count = center_only ? max_buf_count - 4 : max_buf_count;
-
- echo_pos = 0;
- reverb_pos = 0;
-
- stereo_remain = 0;
- effect_remain = 0;
- effects_enabled = false;
- set_depth( 0 );
-}
-
-Effects_Buffer::~Effects_Buffer() { }
-
-blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
-{
- if ( !echo_buf.size() )
- RETURN_ERR( echo_buf.resize( echo_size ) );
-
- if ( !reverb_buf.size() )
- RETURN_ERR( reverb_buf.resize( reverb_size ) );
-
- for ( int i = 0; i < buf_count; i++ )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
-
- config( config_ );
- clear();
-
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Effects_Buffer::clock_rate( long rate )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clock_rate( rate );
-}
-
-void Effects_Buffer::bass_freq( int freq )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].bass_freq( freq );
-}
-
-void Effects_Buffer::clear()
-{
- stereo_remain = 0;
- effect_remain = 0;
- if ( echo_buf.size() )
- memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
-
- if ( reverb_buf.size() )
- memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
-
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clear();
-}
-
-inline int pin_range( int n, int max, int min = 0 )
-{
- if ( n < min )
- return min;
- if ( n > max )
- return max;
- return n;
-}
-
-void Effects_Buffer::config( const config_t& cfg )
-{
- channels_changed();
-
- // clear echo and reverb buffers
- if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf.size() )
- {
- memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
- memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
- }
-
- config_ = cfg;
-
- if ( config_.effects_enabled )
- {
- // convert to internal format
-
- chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 );
- chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0];
-
- chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 );
- chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0];
-
- chans.reverb_level = TO_FIXED( config_.reverb_level );
- chans.echo_level = TO_FIXED( config_.echo_level );
-
- int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate());
-
- int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate());
- chans.reverb_delay_l = pin_range( reverb_size -
- (reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
- chans.reverb_delay_r = pin_range( reverb_size + 1 -
- (reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
-
- int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate());
- chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset),
- echo_size - 1 );
- chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset),
- echo_size - 1 );
-
- chan_types [0].center = &bufs [0];
- chan_types [0].left = &bufs [3];
- chan_types [0].right = &bufs [4];
-
- chan_types [1].center = &bufs [1];
- chan_types [1].left = &bufs [3];
- chan_types [1].right = &bufs [4];
-
- chan_types [2].center = &bufs [2];
- chan_types [2].left = &bufs [5];
- chan_types [2].right = &bufs [6];
- assert( 2 < chan_types_count );
- }
- else
- {
- // set up outputs
- for ( unsigned i = 0; i < chan_types_count; i++ )
- {
- channel_t& c = chan_types [i];
- c.center = &bufs [0];
- c.left = &bufs [1];
- c.right = &bufs [2];
- }
- }
-
- if ( buf_count < max_buf_count )
- {
- for ( int i = 0; i < chan_types_count; i++ )
- {
- channel_t& c = chan_types [i];
- c.left = c.center;
- c.right = c.center;
- }
- }
-}
-
-Effects_Buffer::channel_t Effects_Buffer::channel( int i, int type )
-{
- int out = 2;
- if ( !type )
- {
- out = i % 5;
- if ( out > 2 )
- out = 2;
- }
- else if ( !(type & noise_type) && (type & type_index_mask) % 3 != 0 )
- {
- out = type & 1;
- }
- return chan_types [out];
-}
-
-void Effects_Buffer::end_frame( blip_time_t clock_count )
-{
- int bufs_used = 0;
- for ( int i = 0; i < buf_count; i++ )
- {
- bufs_used |= bufs [i].clear_modified() << i;
- bufs [i].end_frame( clock_count );
- }
-
- int stereo_mask = (config_.effects_enabled ? 0x78 : 0x06);
- if ( (bufs_used & stereo_mask) && buf_count == max_buf_count )
- stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
- if ( effects_enabled || config_.effects_enabled )
- effect_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
- effects_enabled = config_.effects_enabled;
-}
-
-long Effects_Buffer::samples_avail() const
-{
- return bufs [0].samples_avail() * 2;
-}
-
-long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
-{
- require( total_samples % 2 == 0 ); // count must be even
-
- long remain = bufs [0].samples_avail();
- if ( remain > (total_samples >> 1) )
- remain = (total_samples >> 1);
- total_samples = remain;
- while ( remain )
- {
- int active_bufs = buf_count;
- long count = remain;
-
- // optimizing mixing to skip any channels which had nothing added
- if ( effect_remain )
- {
- if ( count > effect_remain )
- count = effect_remain;
-
- if ( stereo_remain )
- {
- mix_enhanced( out, count );
- }
- else
- {
- mix_mono_enhanced( out, count );
- active_bufs = 3;
- }
- }
- else if ( stereo_remain )
- {
- mix_stereo( out, count );
- active_bufs = 3;
- }
- else
- {
- mix_mono( out, count );
- active_bufs = 1;
- }
-
- out += count * 2;
- remain -= count;
-
- stereo_remain -= count;
- if ( stereo_remain < 0 )
- stereo_remain = 0;
-
- effect_remain -= count;
- if ( effect_remain < 0 )
- effect_remain = 0;
-
- for ( int i = 0; i < buf_count; i++ )
- {
- if ( i < active_bufs )
- bufs [i].remove_samples( count );
- else
- bufs [i].remove_silence( count ); // keep time synchronized
- }
- }
-
- return total_samples * 2;
-}
-
-void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( c, bufs [0] );
-
- // unrolled loop
- for ( blargg_long n = count >> 1; n; --n )
- {
- blargg_long cs0 = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
-
- blargg_long cs1 = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
-
- if ( (BOOST::int16_t) cs0 != cs0 )
- cs0 = 0x7FFF - (cs0 >> 24);
- ((BOOST::uint32_t*) out) [0] = ((BOOST::uint16_t) cs0) | (cs0 << 16);
-
- if ( (BOOST::int16_t) cs1 != cs1 )
- cs1 = 0x7FFF - (cs1 >> 24);
- ((BOOST::uint32_t*) out) [1] = ((BOOST::uint16_t) cs1) | (cs1 << 16);
- out += 4;
- }
-
- if ( count & 1 )
- {
- int s = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
- out [0] = s;
- out [1] = s;
- if ( (BOOST::int16_t) s != s )
- {
- s = 0x7FFF - (s >> 24);
- out [0] = s;
- out [1] = s;
- }
- }
-
- BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( c, bufs [0] );
- BLIP_READER_BEGIN( l, bufs [1] );
- BLIP_READER_BEGIN( r, bufs [2] );
-
- while ( count-- )
- {
- int cs = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
- int left = cs + BLIP_READER_READ( l );
- int right = cs + BLIP_READER_READ( r );
- BLIP_READER_NEXT( l, bass );
- BLIP_READER_NEXT( r, bass );
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
-
- BLIP_READER_END( r, bufs [2] );
- BLIP_READER_END( l, bufs [1] );
- BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [2] );
- BLIP_READER_BEGIN( center, bufs [2] );
- BLIP_READER_BEGIN( sq1, bufs [0] );
- BLIP_READER_BEGIN( sq2, bufs [1] );
-
- blip_sample_t* const reverb_buf = this->reverb_buf.begin();
- blip_sample_t* const echo_buf = this->echo_buf.begin();
- int echo_pos = this->echo_pos;
- int reverb_pos = this->reverb_pos;
-
- while ( count-- )
- {
- int sum1_s = BLIP_READER_READ( sq1 );
- int sum2_s = BLIP_READER_READ( sq2 );
-
- BLIP_READER_NEXT( sq1, bass );
- BLIP_READER_NEXT( sq2, bass );
-
- int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
- FMUL( sum2_s, chans.pan_2_levels [0] ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
- int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
- FMUL( sum2_s, chans.pan_2_levels [1] ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
- fixed_t reverb_level = chans.reverb_level;
- reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
- reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
- reverb_pos = (reverb_pos + 2) & reverb_mask;
-
- int sum3_s = BLIP_READER_READ( center );
- BLIP_READER_NEXT( center, bass );
-
- int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
- int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
- echo_buf [echo_pos] = sum3_s;
- echo_pos = (echo_pos + 1) & echo_mask;
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
- this->reverb_pos = reverb_pos;
- this->echo_pos = echo_pos;
-
- BLIP_READER_END( sq1, bufs [0] );
- BLIP_READER_END( sq2, bufs [1] );
- BLIP_READER_END( center, bufs [2] );
-}
-
-void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [2] );
- BLIP_READER_BEGIN( center, bufs [2] );
- BLIP_READER_BEGIN( l1, bufs [3] );
- BLIP_READER_BEGIN( r1, bufs [4] );
- BLIP_READER_BEGIN( l2, bufs [5] );
- BLIP_READER_BEGIN( r2, bufs [6] );
- BLIP_READER_BEGIN( sq1, bufs [0] );
- BLIP_READER_BEGIN( sq2, bufs [1] );
-
- blip_sample_t* const reverb_buf = this->reverb_buf.begin();
- blip_sample_t* const echo_buf = this->echo_buf.begin();
- int echo_pos = this->echo_pos;
- int reverb_pos = this->reverb_pos;
-
- while ( count-- )
- {
- int sum1_s = BLIP_READER_READ( sq1 );
- int sum2_s = BLIP_READER_READ( sq2 );
-
- BLIP_READER_NEXT( sq1, bass );
- BLIP_READER_NEXT( sq2, bass );
-
- int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
- FMUL( sum2_s, chans.pan_2_levels [0] ) + BLIP_READER_READ( l1 ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
- int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
- FMUL( sum2_s, chans.pan_2_levels [1] ) + BLIP_READER_READ( r1 ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
- BLIP_READER_NEXT( l1, bass );
- BLIP_READER_NEXT( r1, bass );
-
- fixed_t reverb_level = chans.reverb_level;
- reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
- reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
- reverb_pos = (reverb_pos + 2) & reverb_mask;
-
- int sum3_s = BLIP_READER_READ( center );
- BLIP_READER_NEXT( center, bass );
-
- int left = new_reverb_l + sum3_s + BLIP_READER_READ( l2 ) + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
- int right = new_reverb_r + sum3_s + BLIP_READER_READ( r2 ) + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
- BLIP_READER_NEXT( l2, bass );
- BLIP_READER_NEXT( r2, bass );
-
- echo_buf [echo_pos] = sum3_s;
- echo_pos = (echo_pos + 1) & echo_mask;
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
- this->reverb_pos = reverb_pos;
- this->echo_pos = echo_pos;
-
- BLIP_READER_END( l1, bufs [3] );
- BLIP_READER_END( r1, bufs [4] );
- BLIP_READER_END( l2, bufs [5] );
- BLIP_READER_END( r2, bufs [6] );
- BLIP_READER_END( sq1, bufs [0] );
- BLIP_READER_END( sq2, bufs [1] );
- BLIP_READER_END( center, bufs [2] );
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.h
deleted file mode 100644
index eb0aa67a..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Effects_Buffer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Multi-channel effects buffer with panning, echo and reverb
-
-// Game_Music_Emu 0.5.2
-#ifndef EFFECTS_BUFFER_H
-#define EFFECTS_BUFFER_H
-
-#include "Multi_Buffer.h"
-
-// Effects_Buffer uses several buffers and outputs stereo sample pairs.
-class Effects_Buffer : public Multi_Buffer {
-public:
- // If center_only is true, only center buffers are created and
- // less memory is used.
- Effects_Buffer( bool center_only = false );
-
- // Channel Effect Center Pan
- // ---------------------------------
- // 0,5 reverb pan_1
- // 1,6 reverb pan_2
- // 2,7 echo -
- // 3 echo -
- // 4 echo -
-
- // Channel configuration
- struct config_t {
- double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right
- double pan_2;
- double echo_delay; // msec
- double echo_level; // 0.0 to 1.0
- double reverb_delay; // msec
- double delay_variance; // difference between left/right delays (msec)
- double reverb_level; // 0.0 to 1.0
- bool effects_enabled; // if false, use optimized simple mixer
- config_t();
- };
-
- // Set configuration of buffer
- virtual void config( const config_t& );
- void set_depth( double );
-
-public:
- ~Effects_Buffer();
- blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length );
- void clock_rate( long );
- void bass_freq( int );
- void clear();
- channel_t channel( int, int );
- void end_frame( blip_time_t );
- long read_samples( blip_sample_t*, long );
- long samples_avail() const;
-private:
- typedef long fixed_t;
-
- enum { max_buf_count = 7 };
- Blip_Buffer bufs [max_buf_count];
- enum { chan_types_count = 3 };
- channel_t chan_types [3];
- config_t config_;
- long stereo_remain;
- long effect_remain;
- int buf_count;
- bool effects_enabled;
-
- blargg_vector<blip_sample_t> reverb_buf;
- blargg_vector<blip_sample_t> echo_buf;
- int reverb_pos;
- int echo_pos;
-
- struct {
- fixed_t pan_1_levels [2];
- fixed_t pan_2_levels [2];
- int echo_delay_l;
- int echo_delay_r;
- fixed_t echo_level;
- int reverb_delay_l;
- int reverb_delay_r;
- fixed_t reverb_level;
- } chans;
-
- void mix_mono( blip_sample_t*, blargg_long );
- void mix_stereo( blip_sample_t*, blargg_long );
- void mix_enhanced( blip_sample_t*, blargg_long );
- void mix_mono_enhanced( blip_sample_t*, blargg_long );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.cpp
deleted file mode 100644
index 4e0a4631..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Fir_Resampler.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
- int count, short* out )
-{
- double const maxh = 256;
- double const step = PI / maxh * spacing;
- double const to_w = maxh * 2 / width;
- double const pow_a_n = pow( rolloff, maxh );
- scale /= maxh * 2;
-
- double angle = (count / 2 - 1 + offset) * -step;
- while ( count-- )
- {
- *out++ = 0;
- double w = angle * to_w;
- if ( fabs( w ) < PI )
- {
- double rolloff_cos_a = rolloff * cos( angle );
- double num = 1 - rolloff_cos_a -
- pow_a_n * cos( maxh * angle ) +
- pow_a_n * rolloff * cos( (maxh - 1) * angle );
- double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
- double sinc = scale * num / den - scale;
-
- out [-1] = (short) (cos( w ) * sinc + sinc);
- }
- angle += step;
- }
-}
-
-Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) :
- width_( width ),
- write_offset( width * stereo - stereo ),
- impulses( impulses_ )
-{
- write_pos = 0;
- res = 1;
- imp_phase = 0;
- skip_bits = 0;
- step = stereo;
- ratio_ = 1.0;
-}
-
-Fir_Resampler_::~Fir_Resampler_() { }
-
-void Fir_Resampler_::clear()
-{
- imp_phase = 0;
- if ( buf.size() )
- {
- write_pos = &buf [write_offset];
- memset( buf.begin(), 0, write_offset * sizeof buf [0] );
- }
-}
-
-blargg_err_t Fir_Resampler_::buffer_size( int new_size )
-{
- RETURN_ERR( buf.resize( new_size + write_offset ) );
- clear();
- return 0;
-}
-
-double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gain )
-{
- ratio_ = new_factor;
-
- double fstep = 0.0;
- {
- double least_error = 2;
- double pos = 0;
- res = -1;
- for ( int r = 1; r <= max_res; r++ )
- {
- pos += ratio_;
- double nearest = floor( pos + 0.5 );
- double error = fabs( pos - nearest );
- if ( error < least_error )
- {
- res = r;
- fstep = nearest / res;
- least_error = error;
- }
- }
- }
-
- skip_bits = 0;
-
- step = stereo * (int) floor( fstep );
-
- ratio_ = fstep;
- fstep = fmod( fstep, 1.0 );
-
- double filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
- double pos = 0.0;
- input_per_cycle = 0;
- for ( int i = 0; i < res; i++ )
- {
- gen_sinc( rolloff, int (width_ * filter + 1) & ~1, pos, filter,
- double (0x7FFF * gain * filter),
- (int) width_, impulses + i * width_ );
-
- pos += fstep;
- input_per_cycle += step;
- if ( pos >= 0.9999999 )
- {
- pos -= 1.0;
- skip_bits |= 1 << i;
- input_per_cycle++;
- }
- }
-
- clear();
-
- return ratio_;
-}
-
-int Fir_Resampler_::input_needed( blargg_long output_count ) const
-{
- blargg_long input_count = 0;
-
- unsigned long skip = skip_bits >> imp_phase;
- int remain = res - imp_phase;
- while ( (output_count -= 2) > 0 )
- {
- input_count += step + (skip & 1) * stereo;
- skip >>= 1;
- if ( !--remain )
- {
- skip = skip_bits;
- remain = res;
- }
- output_count -= 2;
- }
-
- long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
- if ( input_extra < 0 )
- input_extra = 0;
- return input_extra;
-}
-
-int Fir_Resampler_::avail_( blargg_long input_count ) const
-{
- int cycle_count = input_count / input_per_cycle;
- int output_count = cycle_count * res * stereo;
- input_count -= cycle_count * input_per_cycle;
-
- blargg_ulong skip = skip_bits >> imp_phase;
- int remain = res - imp_phase;
- while ( input_count >= 0 )
- {
- input_count -= step + (skip & 1) * stereo;
- skip >>= 1;
- if ( !--remain )
- {
- skip = skip_bits;
- remain = res;
- }
- output_count += 2;
- }
- return output_count;
-}
-
-int Fir_Resampler_::skip_input( long count )
-{
- int remain = write_pos - buf.begin();
- int max_count = remain - width_ * stereo;
- if ( count > max_count )
- count = max_count;
-
- remain -= count;
- write_pos = &buf [remain];
- memmove( buf.begin(), &buf [count], remain * sizeof buf [0] );
-
- return count;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.h
deleted file mode 100644
index 339dfce3..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Fir_Resampler.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// Finite impulse response (FIR) resampler with adjustable FIR size
-
-// Game_Music_Emu 0.5.2
-#ifndef FIR_RESAMPLER_H
-#define FIR_RESAMPLER_H
-
-#include "blargg_common.h"
-#include <string.h>
-
-class Fir_Resampler_ {
-public:
-
- // Use Fir_Resampler<width> (below)
-
- // Set input/output resampling ratio and optionally low-pass rolloff and gain.
- // Returns actual ratio used (rounded to internal precision).
- double time_ratio( double factor, double rolloff = 0.999, double gain = 1.0 );
-
- // Current input/output ratio
- double ratio() const { return ratio_; }
-
-// Input
-
- typedef short sample_t;
-
- // Resize and clear input buffer
- blargg_err_t buffer_size( int );
-
- // Clear input buffer. At least two output samples will be available after
- // two input samples are written.
- void clear();
-
- // Number of input samples that can be written
- int max_write() const { return buf.end() - write_pos; }
-
- // Pointer to place to write input samples
- sample_t* buffer() { return write_pos; }
-
- // Notify resampler that 'count' input samples have been written
- void write( long count );
-
- // Number of input samples in buffer
- int written() const { return write_pos - &buf [write_offset]; }
-
- // Skip 'count' input samples. Returns number of samples actually skipped.
- int skip_input( long count );
-
-// Output
-
- // Number of extra input samples needed until 'count' output samples are available
- int input_needed( blargg_long count ) const;
-
- // Number of output samples available
- int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); }
-
-public:
- ~Fir_Resampler_();
-protected:
- enum { stereo = 2 };
- enum { max_res = 32 };
- blargg_vector<sample_t> buf;
- sample_t* write_pos;
- int res;
- int imp_phase;
- int const width_;
- int const write_offset;
- blargg_ulong skip_bits;
- int step;
- int input_per_cycle;
- double ratio_;
- sample_t* impulses;
-
- Fir_Resampler_( int width, sample_t* );
- int avail_( blargg_long input_count ) const;
-};
-
-// Width is number of points in FIR. Must be even and 4 or more. More points give
-// better quality and rolloff effectiveness, and take longer to calculate.
-template<int width>
-class Fir_Resampler : public Fir_Resampler_ {
- BOOST_STATIC_ASSERT( width >= 4 && width % 2 == 0 );
- short impulses [max_res] [width];
-public:
- Fir_Resampler() : Fir_Resampler_( width, impulses [0] ) { }
-
- // Read at most 'count' samples. Returns number of samples actually read.
- typedef short sample_t;
- int read( sample_t* out, blargg_long count );
-};
-
-// End of public interface
-
-inline void Fir_Resampler_::write( long count )
-{
- write_pos += count;
- assert( write_pos <= buf.end() );
-}
-
-template<int width>
-int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count )
-{
- sample_t* out = out_begin;
- const sample_t* in = buf.begin();
- sample_t* end_pos = write_pos;
- blargg_ulong skip = skip_bits >> imp_phase;
- sample_t const* imp = impulses [imp_phase];
- int remain = res - imp_phase;
- int const step = this->step;
-
- count >>= 1;
-
- if ( end_pos - in >= width * stereo )
- {
- end_pos -= width * stereo;
- do
- {
- count--;
-
- // accumulate in extended precision
- blargg_long l = 0;
- blargg_long r = 0;
-
- const sample_t* i = in;
- if ( count < 0 )
- break;
-
- for ( int n = width / 2; n; --n )
- {
- int pt0 = imp [0];
- l += pt0 * i [0];
- r += pt0 * i [1];
- int pt1 = imp [1];
- imp += 2;
- l += pt1 * i [2];
- r += pt1 * i [3];
- i += 4;
- }
-
- remain--;
-
- l >>= 15;
- r >>= 15;
-
- in += (skip * stereo) & stereo;
- skip >>= 1;
- in += step;
-
- if ( !remain )
- {
- imp = impulses [0];
- skip = skip_bits;
- remain = res;
- }
-
- out [0] = (sample_t) l;
- out [1] = (sample_t) r;
- out += 2;
- }
- while ( in <= end_pos );
- }
-
- imp_phase = res - remain;
-
- int left = write_pos - in;
- write_pos = &buf [left];
- memmove( buf.begin(), in, left * sizeof *in );
-
- return out - out_begin;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.cpp
deleted file mode 100644
index 932ebb83..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const vol_reg = 0xFF24;
-unsigned const status_reg = 0xFF26;
-
-Gb_Apu::Gb_Apu()
-{
- square1.synth = &square_synth;
- square2.synth = &square_synth;
- wave.synth = &other_synth;
- noise.synth = &other_synth;
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &wave;
- oscs [3] = &noise;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- osc.regs = &regs [i * 5];
- osc.output = 0;
- osc.outputs [0] = 0;
- osc.outputs [1] = 0;
- osc.outputs [2] = 0;
- osc.outputs [3] = 0;
- }
-
- set_tempo( 1.0 );
- volume( 1.0 );
- reset();
-}
-
-void Gb_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- other_synth.treble_eq( eq );
-}
-
-void Gb_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- require( (center && left && right) || (!center && !left && !right) );
- Gb_Osc& osc = *oscs [index];
- osc.outputs [1] = right;
- osc.outputs [2] = left;
- osc.outputs [3] = center;
- osc.output = osc.outputs [osc.output_select];
-}
-
-void Gb_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, center, left, right );
-}
-
-void Gb_Apu::update_volume()
-{
- // TODO: doesn't handle differing left/right global volume (support would
- // require modification to all oscillator code)
- int data = regs [vol_reg - start_addr];
- double vol = (max( data & 7, data >> 4 & 7 ) + 1) * volume_unit;
- square_synth.volume( vol );
- other_synth.volume( vol );
-}
-
-static unsigned char const powerup_regs [0x20] = {
- 0x80,0x3F,0x00,0xFF,0xBF, // square 1
- 0xFF,0x3F,0x00,0xFF,0xBF, // square 2
- 0x7F,0xFF,0x9F,0xFF,0xBF, // wave
- 0xFF,0xFF,0x00,0x00,0xBF, // noise
- 0x00, // left/right enables
- 0x77, // master volume
- 0x80, // power
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-void Gb_Apu::set_tempo( double t )
-{
- frame_period = 4194304 / 256; // 256 Hz
- if ( t != 1.0 )
- frame_period = blip_time_t (frame_period / t);
-}
-
-void Gb_Apu::reset()
-{
- next_frame_time = 0;
- last_time = 0;
- frame_count = 0;
-
- square1.reset();
- square2.reset();
- wave.reset();
- noise.reset();
- noise.bits = 1;
- wave.wave_pos = 0;
-
- // avoid click at beginning
- regs [vol_reg - start_addr] = 0x77;
- update_volume();
-
- regs [status_reg - start_addr] = 0x01; // force power
- write_register( 0, status_reg, 0x00 );
-
- static unsigned char const initial_wave [] = {
- 0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
- 0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
- };
- memcpy( wave.wave, initial_wave, sizeof wave.wave );
-}
-
-void Gb_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time ); // end_time must not be before previous time
- if ( end_time == last_time )
- return;
-
- while ( true )
- {
- blip_time_t time = next_frame_time;
- if ( time > end_time )
- time = end_time;
-
- // run oscillators
- for ( int i = 0; i < osc_count; ++i )
- {
- Gb_Osc& osc = *oscs [i];
- if ( osc.output )
- {
- osc.output->set_modified(); // TODO: misses optimization opportunities?
- int playing = false;
- if ( osc.enabled && osc.volume &&
- (!(osc.regs [4] & osc.len_enabled_mask) || osc.length) )
- playing = -1;
- switch ( i )
- {
- case 0: square1.run( last_time, time, playing ); break;
- case 1: square2.run( last_time, time, playing ); break;
- case 2: wave .run( last_time, time, playing ); break;
- case 3: noise .run( last_time, time, playing ); break;
- }
- }
- }
- last_time = time;
-
- if ( time == end_time )
- break;
-
- next_frame_time += frame_period;
-
- // 256 Hz actions
- square1.clock_length();
- square2.clock_length();
- wave.clock_length();
- noise.clock_length();
-
- frame_count = (frame_count + 1) & 3;
- if ( frame_count == 0 )
- {
- // 64 Hz actions
- square1.clock_envelope();
- square2.clock_envelope();
- noise.clock_envelope();
- }
-
- if ( frame_count & 1 )
- square1.clock_sweep(); // 128 Hz action
- }
-}
-
-void Gb_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- assert( next_frame_time >= end_time );
- next_frame_time -= end_time;
-
- assert( last_time >= end_time );
- last_time -= end_time;
-}
-
-void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
-{
- require( (unsigned) data < 0x100 );
-
- int reg = addr - start_addr;
- if ( (unsigned) reg >= register_count )
- return;
-
- run_until( time );
-
- int old_reg = regs [reg];
- regs [reg] = data;
-
- if ( addr < vol_reg )
- {
- write_osc( reg / 5, reg, data );
- }
- else if ( addr == vol_reg && data != old_reg ) // global volume
- {
- // return all oscs to 0
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- int amp = osc.last_amp;
- osc.last_amp = 0;
- if ( amp && osc.enabled && osc.output )
- other_synth.offset( time, -amp, osc.output );
- }
-
- if ( wave.outputs [3] )
- other_synth.offset( time, 30, wave.outputs [3] );
-
- update_volume();
-
- if ( wave.outputs [3] )
- other_synth.offset( time, -30, wave.outputs [3] );
-
- // oscs will update with new amplitude when next run
- }
- else if ( addr == 0xFF25 || addr == status_reg )
- {
- int mask = (regs [status_reg - start_addr] & 0x80) ? ~0 : 0;
- int flags = regs [0xFF25 - start_addr] & mask;
-
- // left/right assignments
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- osc.enabled &= mask;
- int bits = flags >> i;
- Blip_Buffer* old_output = osc.output;
- osc.output_select = (bits >> 3 & 2) | (bits & 1);
- osc.output = osc.outputs [osc.output_select];
- if ( osc.output != old_output )
- {
- int amp = osc.last_amp;
- osc.last_amp = 0;
- if ( amp && old_output )
- other_synth.offset( time, -amp, old_output );
- }
- }
-
- if ( addr == status_reg && data != old_reg )
- {
- if ( !(data & 0x80) )
- {
- for ( unsigned i = 0; i < sizeof powerup_regs; i++ )
- {
- if ( i != status_reg - start_addr )
- write_register( time, i + start_addr, powerup_regs [i] );
- }
- }
- else
- {
- //dprintf( "APU powered on\n" );
- }
- }
- }
- else if ( addr >= 0xFF30 )
- {
- int index = (addr & 0x0F) * 2;
- wave.wave [index] = data >> 4;
- wave.wave [index + 1] = data & 0x0F;
- }
-}
-
-int Gb_Apu::read_register( blip_time_t time, unsigned addr )
-{
- run_until( time );
-
- int index = addr - start_addr;
- require( (unsigned) index < register_count );
- int data = regs [index];
-
- if ( addr == status_reg )
- {
- data = (data & 0x80) | 0x70;
- for ( int i = 0; i < osc_count; i++ )
- {
- const Gb_Osc& osc = *oscs [i];
- if ( osc.enabled && (osc.length || !(osc.regs [4] & osc.len_enabled_mask)) )
- data |= 1 << i;
- }
- }
-
- return data;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.h
deleted file mode 100644
index e74ebc55..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Apu.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Nintendo Game Boy PAPU sound chip emulator
-
-// Gb_Snd_Emu 0.1.5
-#ifndef GB_APU_H
-#define GB_APU_H
-
-#include "Gb_Oscs.h"
-
-class Gb_Apu {
-public:
-
- // Set overall volume of all oscillators, where 1.0 is full volume
- void volume( double );
-
- // Set treble equalization
- void treble_eq( const blip_eq_t& );
-
- // Outputs can be assigned to a single buffer for mono output, or to three
- // buffers for stereo output (using Stereo_Buffer to do the mixing).
-
- // Assign all oscillator outputs to specified buffer(s). If buffer
- // is NULL, silences all oscillators.
- void output( Blip_Buffer* mono );
- void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
- // which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL,
- // silences oscillator.
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* mono );
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Reset oscillators and internal state
- void reset();
-
- // Reads and writes at addr must satisfy start_addr <= addr <= end_addr
- enum { start_addr = 0xFF10 };
- enum { end_addr = 0xFF3F };
- enum { register_count = end_addr - start_addr + 1 };
-
- // Write 'data' to address at specified time
- void write_register( blip_time_t, unsigned addr, int data );
-
- // Read from address at specified time
- int read_register( blip_time_t, unsigned addr );
-
- // Run all oscillators up to specified time, end current time frame, then
- // start a new frame at time 0.
- void end_frame( blip_time_t );
-
- void set_tempo( double );
-
-public:
- Gb_Apu();
-private:
- // noncopyable
- Gb_Apu( const Gb_Apu& );
- Gb_Apu& operator = ( const Gb_Apu& );
-
- Gb_Osc* oscs [osc_count];
- blip_time_t next_frame_time;
- blip_time_t last_time;
- blip_time_t frame_period;
- double volume_unit;
- int frame_count;
-
- Gb_Square square1;
- Gb_Square square2;
- Gb_Wave wave;
- Gb_Noise noise;
- BOOST::uint8_t regs [register_count];
- Gb_Square::Synth square_synth; // used by squares
- Gb_Wave::Synth other_synth; // used by wave and noise
-
- void update_volume();
- void run_until( blip_time_t );
- void write_osc( int index, int reg, int data );
-};
-
-inline void Gb_Apu::output( Blip_Buffer* b ) { output( b, b, b ); }
-
-inline void Gb_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); }
-
-inline void Gb_Apu::volume( double vol )
-{
- volume_unit = 0.60 / osc_count / 15 /*steps*/ / 2 /*?*/ / 8 /*master vol range*/ * vol;
- update_volume();
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.cpp
deleted file mode 100644
index b1f22bd9..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.cpp
+++ /dev/null
@@ -1,1056 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Gb_Cpu.h"
-
-#include <string.h>
-
-//#include "gb_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "gb_cpu_io.h"
-
-#include "blargg_source.h"
-
-// Common instructions:
-//
-// 365880 FA LD A,IND16
-// 355863 20 JR NZ
-// 313655 21 LD HL,IMM
-// 274580 28 JR Z
-// 252878 FE CMP IMM
-// 230541 7E LD A,(HL)
-// 226209 2A LD A,(HL+)
-// 217467 CD CALL
-// 212034 C9 RET
-// 208376 CB CB prefix
-//
-// 27486 CB 7E BIT 7,(HL)
-// 15925 CB 76 BIT 6,(HL)
-// 13035 CB 19 RR C
-// 11557 CB 7F BIT 7,A
-// 10898 CB 37 SWAP A
-// 10208 CB 66 BIT 4,(HL)
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
-{
- state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size );
-}
-
-void Gb_Cpu::reset( void* unmapped )
-{
- check( state == &state_ );
- state = &state_;
-
- state_.remain = 0;
-
- for ( int i = 0; i < page_count + 1; i++ )
- set_code_page( i, (uint8_t*) unmapped );
-
- memset( &r, 0, sizeof r );
- //interrupts_enabled = false;
-
- blargg_verify_byte_order();
-}
-
-void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
-{
- // address range must begin and end on page boundaries
- require( start % page_size == 0 );
- require( size % page_size == 0 );
-
- unsigned first_page = start / page_size;
- for ( unsigned i = size / page_size; i--; )
- set_code_page( first_page + i, (uint8_t*) data + i * page_size );
-}
-
-#define READ( addr ) CPU_READ( this, (addr), s.remain )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), s.remain );}
-#define READ_FAST( addr, out ) CPU_READ_FAST( this, (addr), s.remain, out )
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-unsigned const z_flag = 0x80;
-unsigned const n_flag = 0x40;
-unsigned const h_flag = 0x20;
-unsigned const c_flag = 0x10;
-
-bool Gb_Cpu::run( blargg_long cycle_count )
-{
- state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
- state_t s;
- this->state = &s;
- memcpy( &s, &this->state_, sizeof s );
-
- typedef BOOST::uint16_t uint16_t;
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n ) (r8_ [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n ) (r8_ [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
- union {
- core_regs_t rg; // individual registers
-
- struct {
- BOOST::uint16_t bc, de, hl, unused; // pairs
- } rp;
-
- uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
- BOOST::uint16_t r16 [4]; // indexed pairs
- };
- BOOST_STATIC_ASSERT( sizeof rg == 8 && sizeof rp == 8 );
-
- rg = r;
- unsigned pc = r.pc;
- unsigned sp = r.sp;
- unsigned flags = r.flags;
-
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (flags & ~0xF0) == 0 );
-
- uint8_t const* instr = s.code_map [pc >> page_shift];
- unsigned op;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- op = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- op = *instr++;
- pc++;
- #endif
-
-#define GET_ADDR() GET_LE16( instr )
-
- if ( !--s.remain )
- goto stop;
-
- unsigned data;
- data = *instr;
-
- #ifdef GB_CPU_LOG_H
- gb_cpu_log( "new", pc - 1, op, data, instr [1] );
- #endif
-
- switch ( op )
- {
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- pc++;\
- int offset = (BOOST::int8_t) data;\
- if ( !(cond) ) goto loop;\
- pc = uint16_t (pc + offset);\
- goto loop;\
-}
-
-// Most Common
-
- case 0x20: // JR NZ
- BRANCH( !(flags & z_flag) )
-
- case 0x21: // LD HL,IMM (common)
- rp.hl = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x28: // JR Z
- BRANCH( flags & z_flag )
-
- {
- unsigned temp;
- case 0xF0: // LD A,(0xFF00+imm)
- temp = data | 0xFF00;
- pc++;
- goto ld_a_ind_comm;
-
- case 0xF2: // LD A,(0xFF00+C)
- temp = rg.c | 0xFF00;
- goto ld_a_ind_comm;
-
- case 0x0A: // LD A,(BC)
- temp = rp.bc;
- goto ld_a_ind_comm;
-
- case 0x3A: // LD A,(HL-)
- temp = rp.hl;
- rp.hl = temp - 1;
- goto ld_a_ind_comm;
-
- case 0x1A: // LD A,(DE)
- temp = rp.de;
- goto ld_a_ind_comm;
-
- case 0x2A: // LD A,(HL+) (common)
- temp = rp.hl;
- rp.hl = temp + 1;
- goto ld_a_ind_comm;
-
- case 0xFA: // LD A,IND16 (common)
- temp = GET_ADDR();
- pc += 2;
- ld_a_ind_comm:
- READ_FAST( temp, rg.a );
- goto loop;
- }
-
- case 0xBE: // CMP (HL)
- data = READ( rp.hl );
- goto cmp_comm;
-
- case 0xB8: // CMP B
- case 0xB9: // CMP C
- case 0xBA: // CMP D
- case 0xBB: // CMP E
- case 0xBC: // CMP H
- case 0xBD: // CMP L
- data = R8( op & 7 );
- goto cmp_comm;
-
- case 0xFE: // CMP IMM
- pc++;
- cmp_comm:
- op = rg.a;
- data = op - data;
- sub_set_flags:
- flags = ((op & 15) - (data & 15)) & h_flag;
- flags |= (data >> 4) & c_flag;
- flags |= n_flag;
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
- case 0x46: // LD B,(HL)
- case 0x4E: // LD C,(HL)
- case 0x56: // LD D,(HL)
- case 0x5E: // LD E,(HL)
- case 0x66: // LD H,(HL)
- case 0x6E: // LD L,(HL)
- case 0x7E:{// LD A,(HL)
- unsigned addr = rp.hl;
- READ_FAST( addr, R8( (op >> 3) & 7 ) );
- goto loop;
- }
-
- case 0xC4: // CNZ (next-most-common)
- pc += 2;
- if ( flags & z_flag )
- goto loop;
- call:
- pc -= 2;
- case 0xCD: // CALL (most-common)
- data = pc + 2;
- pc = GET_ADDR();
- push:
- sp = (sp - 1) & 0xFFFF;
- WRITE( sp, data >> 8 );
- sp = (sp - 1) & 0xFFFF;
- WRITE( sp, data & 0xFF );
- goto loop;
-
- case 0xC8: // RNZ (next-most-common)
- if ( !(flags & z_flag) )
- goto loop;
- case 0xC9: // RET (most common)
- ret:
- pc = READ( sp );
- pc += 0x100 * READ( sp + 1 );
- sp = (sp + 2) & 0xFFFF;
- goto loop;
-
- case 0x00: // NOP
- case 0x40: // LD B,B
- case 0x49: // LD C,C
- case 0x52: // LD D,D
- case 0x5B: // LD E,E
- case 0x64: // LD H,H
- case 0x6D: // LD L,L
- case 0x7F: // LD A,A
- goto loop;
-
-// CB Instructions
-
- case 0xCB:
- pc++;
- // now data is the opcode
- switch ( data ) {
-
- {
- int temp;
- case 0x46: // BIT b,(HL)
- case 0x4E:
- case 0x56:
- case 0x5E:
- case 0x66:
- case 0x6E:
- case 0x76:
- case 0x7E:
- {
- unsigned addr = rp.hl;
- READ_FAST( addr, temp );
- goto bit_comm;
- }
-
- case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
- case 0x44: case 0x45: case 0x47: case 0x48:
- case 0x49: case 0x4A: case 0x4B: case 0x4C:
- case 0x4D: case 0x4F: case 0x50: case 0x51:
- case 0x52: case 0x53: case 0x54: case 0x55:
- case 0x57: case 0x58: case 0x59: case 0x5A:
- case 0x5B: case 0x5C: case 0x5D: case 0x5F:
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x65: case 0x67: case 0x68:
- case 0x69: case 0x6A: case 0x6B: case 0x6C:
- case 0x6D: case 0x6F: case 0x70: case 0x71:
- case 0x72: case 0x73: case 0x74: case 0x75:
- case 0x77: case 0x78: case 0x79: case 0x7A:
- case 0x7B: case 0x7C: case 0x7D: case 0x7F:
- temp = R8( data & 7 );
- bit_comm:
- int bit = (~data >> 3) & 7;
- flags &= ~n_flag;
- flags |= h_flag | z_flag;
- flags ^= (temp << bit) & z_flag;
- goto loop;
- }
-
- case 0x86: // RES b,(HL)
- case 0x8E:
- case 0x96:
- case 0x9E:
- case 0xA6:
- case 0xAE:
- case 0xB6:
- case 0xBE:
- case 0xC6: // SET b,(HL)
- case 0xCE:
- case 0xD6:
- case 0xDE:
- case 0xE6:
- case 0xEE:
- case 0xF6:
- case 0xFE: {
- int temp = READ( rp.hl );
- int bit = 1 << ((data >> 3) & 7);
- temp &= ~bit;
- if ( !(data & 0x40) )
- bit = 0;
- WRITE( rp.hl, temp | bit );
- goto loop;
- }
-
- case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
- case 0xC4: case 0xC5: case 0xC7: case 0xC8:
- case 0xC9: case 0xCA: case 0xCB: case 0xCC:
- case 0xCD: case 0xCF: case 0xD0: case 0xD1:
- case 0xD2: case 0xD3: case 0xD4: case 0xD5:
- case 0xD7: case 0xD8: case 0xD9: case 0xDA:
- case 0xDB: case 0xDC: case 0xDD: case 0xDF:
- case 0xE0: case 0xE1: case 0xE2: case 0xE3:
- case 0xE4: case 0xE5: case 0xE7: case 0xE8:
- case 0xE9: case 0xEA: case 0xEB: case 0xEC:
- case 0xED: case 0xEF: case 0xF0: case 0xF1:
- case 0xF2: case 0xF3: case 0xF4: case 0xF5:
- case 0xF7: case 0xF8: case 0xF9: case 0xFA:
- case 0xFB: case 0xFC: case 0xFD: case 0xFF:
- R8( data & 7 ) |= 1 << ((data >> 3) & 7);
- goto loop;
-
- case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
- case 0x84: case 0x85: case 0x87: case 0x88:
- case 0x89: case 0x8A: case 0x8B: case 0x8C:
- case 0x8D: case 0x8F: case 0x90: case 0x91:
- case 0x92: case 0x93: case 0x94: case 0x95:
- case 0x97: case 0x98: case 0x99: case 0x9A:
- case 0x9B: case 0x9C: case 0x9D: case 0x9F:
- case 0xA0: case 0xA1: case 0xA2: case 0xA3:
- case 0xA4: case 0xA5: case 0xA7: case 0xA8:
- case 0xA9: case 0xAA: case 0xAB: case 0xAC:
- case 0xAD: case 0xAF: case 0xB0: case 0xB1:
- case 0xB2: case 0xB3: case 0xB4: case 0xB5:
- case 0xB7: case 0xB8: case 0xB9: case 0xBA:
- case 0xBB: case 0xBC: case 0xBD: case 0xBF:
- R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
- goto loop;
-
- {
- int temp;
- case 0x36: // SWAP (HL)
- temp = READ( rp.hl );
- goto swap_comm;
-
- case 0x30: // SWAP B
- case 0x31: // SWAP C
- case 0x32: // SWAP D
- case 0x33: // SWAP E
- case 0x34: // SWAP H
- case 0x35: // SWAP L
- case 0x37: // SWAP A
- temp = R8( data & 7 );
- swap_comm:
- op = (temp >> 4) | (temp << 4);
- flags = 0;
- goto shift_comm;
- }
-
-// Shift/Rotate
-
- case 0x06: // RLC (HL)
- case 0x16: // RL (HL)
- case 0x26: // SLA (HL)
- op = READ( rp.hl );
- goto rl_comm;
-
- case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
- op = R8( data & 7 );
- goto rl_comm;
-
- case 0x3E: // SRL (HL)
- data += 0x10; // bump up to 0x4n to avoid preserving sign bit
- case 0x1E: // RR (HL)
- case 0x0E: // RRC (HL)
- case 0x2E: // SRA (HL)
- op = READ( rp.hl );
- goto rr_comm;
-
- case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
- data += 0x10; // bump up to 0x4n
- case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
- case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
- case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
- op = R8( data & 7 );
- goto rr_comm;
-
- } // CB op
- assert( false ); // unhandled CB op
-
- case 0x07: // RLCA
- case 0x17: // RLA
- data = op;
- op = rg.a;
- rl_comm:
- op <<= 1;
- op |= ((data & flags) >> 4) & 1; // RL and carry is set
- flags = (op >> 4) & c_flag; // C = bit shifted out
- if ( data < 0x10 ) // RLC
- op |= op >> 8;
- // SLA doesn't fill lower bit
- goto shift_comm;
-
- case 0x0F: // RRCA
- case 0x1F: // RRA
- data = op;
- op = rg.a;
- rr_comm:
- op |= (data & flags) << 4; // RR and carry is set
- flags = (op << 4) & c_flag; // C = bit shifted out
- if ( data < 0x10 ) // RRC
- op |= op << 8;
- op >>= 1;
- if ( data & 0x20 ) // SRA propagates sign bit
- op |= (op << 1) & 0x80;
- shift_comm:
- data &= 7;
- if ( !(op & 0xFF) )
- flags |= z_flag;
- if ( data == 6 )
- goto write_hl_op_ff;
- R8( data ) = op;
- goto loop;
-
-// Load
-
- case 0x70: // LD (HL),B
- case 0x71: // LD (HL),C
- case 0x72: // LD (HL),D
- case 0x73: // LD (HL),E
- case 0x74: // LD (HL),H
- case 0x75: // LD (HL),L
- case 0x77: // LD (HL),A
- op = R8( op & 7 );
- write_hl_op_ff:
- WRITE( rp.hl, op & 0xFF );
- goto loop;
-
- case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
- case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
- case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
- case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
- case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
- case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
- case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
- R8( (op >> 3) & 7 ) = R8( op & 7 );
- goto loop;
-
- case 0x08: // LD IND16,SP
- data = GET_ADDR();
- pc += 2;
- WRITE( data, sp&0xFF );
- data++;
- WRITE( data, sp >> 8 );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
- case 0x31: // LD SP,IMM
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x01: // LD BC,IMM
- case 0x11: // LD DE,IMM
- r16 [op >> 4] = GET_ADDR();
- pc += 2;
- goto loop;
-
- {
- unsigned temp;
- case 0xE0: // LD (0xFF00+imm),A
- temp = data | 0xFF00;
- pc++;
- goto write_data_rg_a;
-
- case 0xE2: // LD (0xFF00+C),A
- temp = rg.c | 0xFF00;
- goto write_data_rg_a;
-
- case 0x32: // LD (HL-),A
- temp = rp.hl;
- rp.hl = temp - 1;
- goto write_data_rg_a;
-
- case 0x02: // LD (BC),A
- temp = rp.bc;
- goto write_data_rg_a;
-
- case 0x12: // LD (DE),A
- temp = rp.de;
- goto write_data_rg_a;
-
- case 0x22: // LD (HL+),A
- temp = rp.hl;
- rp.hl = temp + 1;
- goto write_data_rg_a;
-
- case 0xEA: // LD IND16,A (common)
- temp = GET_ADDR();
- pc += 2;
- write_data_rg_a:
- WRITE( temp, rg.a );
- goto loop;
- }
-
- case 0x06: // LD B,IMM
- rg.b = data;
- pc++;
- goto loop;
-
- case 0x0E: // LD C,IMM
- rg.c = data;
- pc++;
- goto loop;
-
- case 0x16: // LD D,IMM
- rg.d = data;
- pc++;
- goto loop;
-
- case 0x1E: // LD E,IMM
- rg.e = data;
- pc++;
- goto loop;
-
- case 0x26: // LD H,IMM
- rg.h = data;
- pc++;
- goto loop;
-
- case 0x2E: // LD L,IMM
- rg.l = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),IMM
- WRITE( rp.hl, data );
- pc++;
- goto loop;
-
- case 0x3E: // LD A,IMM
- rg.a = data;
- pc++;
- goto loop;
-
-// Increment/Decrement
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- r16 [op >> 4]++;
- goto loop;
-
- case 0x33: // INC SP
- sp = (sp + 1) & 0xFFFF;
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- r16 [op >> 4]--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = (sp - 1) & 0xFFFF;
- goto loop;
-
- case 0x34: // INC (HL)
- op = rp.hl;
- data = READ( op );
- data++;
- WRITE( op, data & 0xFF );
- goto inc_comm;
-
- case 0x04: // INC B
- case 0x0C: // INC C (common)
- case 0x14: // INC D
- case 0x1C: // INC E
- case 0x24: // INC H
- case 0x2C: // INC L
- case 0x3C: // INC A
- op = (op >> 3) & 7;
- R8( op ) = data = R8( op ) + 1;
- inc_comm:
- flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
- goto loop;
-
- case 0x35: // DEC (HL)
- op = rp.hl;
- data = READ( op );
- data--;
- WRITE( op, data & 0xFF );
- goto dec_comm;
-
- case 0x05: // DEC B
- case 0x0D: // DEC C
- case 0x15: // DEC D
- case 0x1D: // DEC E
- case 0x25: // DEC H
- case 0x2D: // DEC L
- case 0x3D: // DEC A
- op = (op >> 3) & 7;
- data = R8( op ) - 1;
- R8( op ) = data;
- dec_comm:
- flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
-// Add 16-bit
-
- {
- blargg_ulong temp; // need more than 16 bits for carry
- unsigned prev;
-
- case 0xF8: // LD HL,SP+imm
- temp = BOOST::int8_t (data); // sign-extend to 16 bits
- pc++;
- flags = 0;
- temp += sp;
- prev = sp;
- goto add_16_hl;
-
- case 0xE8: // ADD SP,IMM
- temp = BOOST::int8_t (data); // sign-extend to 16 bits
- pc++;
- flags = 0;
- temp += sp;
- prev = sp;
- sp = temp & 0xFFFF;
- goto add_16_comm;
-
- case 0x39: // ADD HL,SP
- temp = sp;
- goto add_hl_comm;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- temp = r16 [op >> 4];
- add_hl_comm:
- prev = rp.hl;
- temp += prev;
- flags &= z_flag;
- add_16_hl:
- rp.hl = temp;
- add_16_comm:
- flags |= (temp >> 12) & c_flag;
- flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;
- goto loop;
- }
-
- case 0x86: // ADD (HL)
- data = READ( rp.hl );
- goto add_comm;
-
- case 0x80: // ADD B
- case 0x81: // ADD C
- case 0x82: // ADD D
- case 0x83: // ADD E
- case 0x84: // ADD H
- case 0x85: // ADD L
- case 0x87: // ADD A
- data = R8( op & 7 );
- goto add_comm;
-
- case 0xC6: // ADD IMM
- pc++;
- add_comm:
- flags = rg.a;
- data += flags;
- flags = ((data & 15) - (flags & 15)) & h_flag;
- flags |= (data >> 4) & c_flag;
- rg.a = data;
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
-// Add/Subtract
-
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_comm;
-
- case 0x88: // ADC B
- case 0x89: // ADC C
- case 0x8A: // ADC D
- case 0x8B: // ADC E
- case 0x8C: // ADC H
- case 0x8D: // ADC L
- case 0x8F: // ADC A
- data = R8( op & 7 );
- goto adc_comm;
-
- case 0xCE: // ADC IMM
- pc++;
- adc_comm:
- data += (flags >> 4) & 1;
- data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
- goto add_comm;
-
- case 0x96: // SUB (HL)
- data = READ( rp.hl );
- goto sub_comm;
-
- case 0x90: // SUB B
- case 0x91: // SUB C
- case 0x92: // SUB D
- case 0x93: // SUB E
- case 0x94: // SUB H
- case 0x95: // SUB L
- case 0x97: // SUB A
- data = R8( op & 7 );
- goto sub_comm;
-
- case 0xD6: // SUB IMM
- pc++;
- sub_comm:
- op = rg.a;
- data = op - data;
- rg.a = data;
- goto sub_set_flags;
-
- case 0x9E: // SBC (HL)
- data = READ( rp.hl );
- goto sbc_comm;
-
- case 0x98: // SBC B
- case 0x99: // SBC C
- case 0x9A: // SBC D
- case 0x9B: // SBC E
- case 0x9C: // SBC H
- case 0x9D: // SBC L
- case 0x9F: // SBC A
- data = R8( op & 7 );
- goto sbc_comm;
-
- case 0xDE: // SBC IMM
- pc++;
- sbc_comm:
- data += (flags >> 4) & 1;
- data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
- goto sub_comm;
-
-// Logical
-
- case 0xA0: // AND B
- case 0xA1: // AND C
- case 0xA2: // AND D
- case 0xA3: // AND E
- case 0xA4: // AND H
- case 0xA5: // AND L
- data = R8( op & 7 );
- goto and_comm;
-
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- pc--;
- case 0xE6: // AND IMM
- pc++;
- and_comm:
- rg.a &= data;
- case 0xA7: // AND A
- flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
- goto loop;
-
- case 0xB0: // OR B
- case 0xB1: // OR C
- case 0xB2: // OR D
- case 0xB3: // OR E
- case 0xB4: // OR H
- case 0xB5: // OR L
- data = R8( op & 7 );
- goto or_comm;
-
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- pc--;
- case 0xF6: // OR IMM
- pc++;
- or_comm:
- rg.a |= data;
- case 0xB7: // OR A
- flags = ((rg.a - 1) >> 1) & z_flag;
- goto loop;
-
- case 0xA8: // XOR B
- case 0xA9: // XOR C
- case 0xAA: // XOR D
- case 0xAB: // XOR E
- case 0xAC: // XOR H
- case 0xAD: // XOR L
- data = R8( op & 7 );
- goto xor_comm;
-
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- pc--;
- case 0xEE: // XOR IMM
- pc++;
- xor_comm:
- data ^= rg.a;
- rg.a = data;
- data--;
- flags = (data >> 1) & z_flag;
- goto loop;
-
- case 0xAF: // XOR A
- rg.a = 0;
- flags = z_flag;
- goto loop;
-
-// Stack
-
- case 0xF1: // POP FA
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL (common)
- data = READ( sp );
- r16 [(op >> 4) & 3] = data + 0x100 * READ( sp + 1 );
- sp = (sp + 2) & 0xFFFF;
- if ( op != 0xF1 )
- goto loop;
- flags = rg.flags & 0xF0;
- goto loop;
-
- case 0xC5: // PUSH BC
- data = rp.bc;
- goto push;
-
- case 0xD5: // PUSH DE
- data = rp.de;
- goto push;
-
- case 0xE5: // PUSH HL
- data = rp.hl;
- goto push;
-
- case 0xF5: // PUSH FA
- data = (flags << 8) | rg.a;
- goto push;
-
-// Flow control
-
- case 0xFF:
- if ( pc == idle_addr + 1 )
- goto stop;
- case 0xC7: case 0xCF: case 0xD7: case 0xDF: // RST
- case 0xE7: case 0xEF: case 0xF7:
- data = pc;
- pc = (op & 0x38) + rst_base;
- goto push;
-
- case 0xCC: // CZ
- pc += 2;
- if ( flags & z_flag )
- goto call;
- goto loop;
-
- case 0xD4: // CNC
- pc += 2;
- if ( !(flags & c_flag) )
- goto call;
- goto loop;
-
- case 0xDC: // CC
- pc += 2;
- if ( flags & c_flag )
- goto call;
- goto loop;
-
- case 0xD9: // RETI
- //interrupts_enabled = 1;
- goto ret;
-
- case 0xC0: // RZ
- if ( !(flags & z_flag) )
- goto ret;
- goto loop;
-
- case 0xD0: // RNC
- if ( !(flags & c_flag) )
- goto ret;
- goto loop;
-
- case 0xD8: // RC
- if ( flags & c_flag )
- goto ret;
- goto loop;
-
- case 0x18: // JR
- BRANCH( true )
-
- case 0x30: // JR NC
- BRANCH( !(flags & c_flag) )
-
- case 0x38: // JR C
- BRANCH( flags & c_flag )
-
- case 0xE9: // JP_HL
- pc = rp.hl;
- goto loop;
-
- case 0xC3: // JP (next-most-common)
- pc = GET_ADDR();
- goto loop;
-
- case 0xC2: // JP NZ
- pc += 2;
- if ( !(flags & z_flag) )
- goto jp_taken;
- goto loop;
-
- case 0xCA: // JP Z (most common)
- pc += 2;
- if ( !(flags & z_flag) )
- goto loop;
- jp_taken:
- pc -= 2;
- pc = GET_ADDR();
- goto loop;
-
- case 0xD2: // JP NC
- pc += 2;
- if ( !(flags & c_flag) )
- goto jp_taken;
- goto loop;
-
- case 0xDA: // JP C
- pc += 2;
- if ( flags & c_flag )
- goto jp_taken;
- goto loop;
-
-// Flags
-
- case 0x2F: // CPL
- rg.a = ~rg.a;
- flags |= n_flag | h_flag;
- goto loop;
-
- case 0x3F: // CCF
- flags = (flags ^ c_flag) & ~(n_flag | h_flag);
- goto loop;
-
- case 0x37: // SCF
- flags = (flags | c_flag) & ~(n_flag | h_flag);
- goto loop;
-
- case 0xF3: // DI
- //interrupts_enabled = 0;
- goto loop;
-
- case 0xFB: // EI
- //interrupts_enabled = 1;
- goto loop;
-
-// Special
-
- case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
- case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
- case 0x10: // STOP
- case 0x27: // DAA (I'll have to implement this eventually...)
- case 0xBF:
- case 0xED: // Z80 prefix
- case 0x76: // HALT
- s.remain++;
- goto stop;
- }
-
- // If this fails then the case above is missing an opcode
- assert( false );
-
-stop:
- pc--;
-
- // copy state back
- STATIC_CAST(core_regs_t&,r) = rg;
- r.pc = pc;
- r.sp = sp;
- r.flags = flags;
-
- this->state = &state_;
- memcpy( &this->state_, &s, sizeof this->state_ );
-
- return s.remain > 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.h
deleted file mode 100644
index 953fbaf5..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Cpu.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Nintendo Game Boy CPU emulator
-// Treats every instruction as taking 4 cycles
-
-// Game_Music_Emu 0.5.2
-#ifndef GB_CPU_H
-#define GB_CPU_H
-
-#include "blargg_common.h"
-#include "blargg_endian.h"
-
-typedef unsigned gb_addr_t; // 16-bit CPU address
-
-class Gb_Cpu {
- enum { clocks_per_instr = 4 };
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers and map all pages to unmapped
- void reset( void* unmapped = 0 );
-
- // Map code memory (memory accessed via the program counter). Start and size
- // must be multiple of page_size.
- enum { page_size = 0x2000 };
- void map_code( gb_addr_t start, unsigned size, void* code );
-
- uint8_t* get_code( gb_addr_t );
-
- // Push a byte on the stack
- void push_byte( int );
-
- // Game Boy Z80 registers. *Not* kept updated during a call to run().
- struct core_regs_t {
- #if BLARGG_BIG_ENDIAN
- uint8_t b, c, d, e, h, l, flags, a;
- #else
- uint8_t c, b, e, d, l, h, a, flags;
- #endif
- };
-
- struct registers_t : core_regs_t {
- long pc; // more than 16 bits to allow overflow detection
- BOOST::uint16_t sp;
- };
- registers_t r;
-
- // Interrupt enable flag set by EI and cleared by DI
- //bool interrupts_enabled; // unused
-
- // Base address for RST vectors (normally 0)
- gb_addr_t rst_base;
-
- // If CPU executes opcode 0xFF at this address, it treats as illegal instruction
- enum { idle_addr = 0xF00D };
-
- // Run CPU for at least 'count' cycles and return false, or return true if
- // illegal instruction is encountered.
- bool run( blargg_long count );
-
- // Number of clock cycles remaining for most recent run() call
- blargg_long remain() const { return state->remain * clocks_per_instr; }
-
- // Can read this many bytes past end of a page
- enum { cpu_padding = 8 };
-
-public:
- Gb_Cpu() : rst_base( 0 ) { state = &state_; }
- enum { page_shift = 13 };
- enum { page_count = 0x10000 >> page_shift };
-private:
- // noncopyable
- Gb_Cpu( const Gb_Cpu& );
- Gb_Cpu& operator = ( const Gb_Cpu& );
-
- struct state_t {
- uint8_t* code_map [page_count + 1];
- blargg_long remain;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
-
- void set_code_page( int, uint8_t* );
-};
-
-inline BOOST::uint8_t* Gb_Cpu::get_code( gb_addr_t addr )
-{
- return state->code_map [addr >> page_shift] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.cpp
deleted file mode 100644
index 735653fa..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Gb_Osc
-
-void Gb_Osc::reset()
-{
- delay = 0;
- last_amp = 0;
- length = 0;
- output_select = 3;
- output = outputs [output_select];
-}
-
-void Gb_Osc::clock_length()
-{
- if ( (regs [4] & len_enabled_mask) && length )
- length--;
-}
-
-// Gb_Env
-
-void Gb_Env::clock_envelope()
-{
- if ( env_delay && !--env_delay )
- {
- env_delay = regs [2] & 7;
- int v = volume - 1 + (regs [2] >> 2 & 2);
- if ( (unsigned) v < 15 )
- volume = v;
- }
-}
-
-bool Gb_Env::write_register( int reg, int data )
-{
- switch ( reg )
- {
- case 1:
- length = 64 - (regs [1] & 0x3F);
- break;
-
- case 2:
- if ( !(data >> 4) )
- enabled = false;
- break;
-
- case 4:
- if ( data & trigger )
- {
- env_delay = regs [2] & 7;
- volume = regs [2] >> 4;
- enabled = true;
- if ( length == 0 )
- length = 64;
- return true;
- }
- }
- return false;
-}
-
-// Gb_Square
-
-void Gb_Square::reset()
-{
- phase = 0;
- sweep_freq = 0;
- sweep_delay = 0;
- Gb_Env::reset();
-}
-
-void Gb_Square::clock_sweep()
-{
- int sweep_period = (regs [0] & period_mask) >> 4;
- if ( sweep_period && sweep_delay && !--sweep_delay )
- {
- sweep_delay = sweep_period;
- regs [3] = sweep_freq & 0xFF;
- regs [4] = (regs [4] & ~0x07) | (sweep_freq >> 8 & 0x07);
-
- int offset = sweep_freq >> (regs [0] & shift_mask);
- if ( regs [0] & 0x08 )
- offset = -offset;
- sweep_freq += offset;
-
- if ( sweep_freq < 0 )
- {
- sweep_freq = 0;
- }
- else if ( sweep_freq >= 2048 )
- {
- sweep_delay = 0; // don't modify channel frequency any further
- sweep_freq = 2048; // silence sound immediately
- }
- }
-}
-
-void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- if ( sweep_freq == 2048 )
- playing = false;
-
- static unsigned char const table [4] = { 1, 2, 4, 6 };
- int const duty = table [regs [1] >> 6];
- int amp = volume & playing;
- if ( phase >= duty )
- amp = -amp;
-
- int frequency = this->frequency();
- if ( unsigned (frequency - 1) > 2040 ) // frequency < 1 || frequency > 2041
- {
- // really high frequency results in DC at half volume
- amp = volume >> 1;
- playing = false;
- }
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- int const period = (2048 - frequency) * 4;
- Blip_Buffer* const output = this->output;
- int phase = this->phase;
- int delta = amp * 2;
- do
- {
- phase = (phase + 1) & 7;
- if ( phase == 0 || phase == duty )
- {
- delta = -delta;
- synth->offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->phase = phase;
- last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Gb_Noise
-
-void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- int amp = volume & playing;
- int tap = 13 - (regs [3] & 8);
- if ( bits >> tap & 2 )
- amp = -amp;
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- static unsigned char const table [8] = { 8, 16, 32, 48, 64, 80, 96, 112 };
- int period = table [regs [3] & 7] << (regs [3] >> 4);
-
- // keep parallel resampled time to eliminate time conversion in the loop
- Blip_Buffer* const output = this->output;
- const blip_resampled_time_t resampled_period =
- output->resampled_duration( period );
- blip_resampled_time_t resampled_time = output->resampled_time( time );
- unsigned bits = this->bits;
- int delta = amp * 2;
-
- do
- {
- unsigned changed = (bits >> tap) + 1;
- time += period;
- bits <<= 1;
- if ( changed & 2 )
- {
- delta = -delta;
- bits |= 1;
- synth->offset_resampled( resampled_time, delta, output );
- }
- resampled_time += resampled_period;
- }
- while ( time < end_time );
-
- this->bits = bits;
- last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Gb_Wave
-
-inline void Gb_Wave::write_register( int reg, int data )
-{
- switch ( reg )
- {
- case 0:
- if ( !(data & 0x80) )
- enabled = false;
- break;
-
- case 1:
- length = 256 - regs [1];
- break;
-
- case 2:
- volume = data >> 5 & 3;
- break;
-
- case 4:
- if ( data & trigger & regs [0] )
- {
- wave_pos = 0;
- enabled = true;
- if ( length == 0 )
- length = 256;
- }
- }
-}
-
-void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
- int frequency;
- {
- int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
-
- frequency = this->frequency();
- if ( unsigned (frequency - 1) > 2044 ) // frequency < 1 || frequency > 2045
- {
- amp = 30 >> volume_shift & playing;
- playing = false;
- }
-
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- int const period = (2048 - frequency) * 2;
- int wave_pos = (this->wave_pos + 1) & (wave_size - 1);
-
- do
- {
- int amp = (wave [wave_pos] >> volume_shift) * 2;
- wave_pos = (wave_pos + 1) & (wave_size - 1);
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->wave_pos = (wave_pos - 1) & (wave_size - 1);
- }
- delay = time - end_time;
-}
-
-// Gb_Apu::write_osc
-
-void Gb_Apu::write_osc( int index, int reg, int data )
-{
- reg -= index * 5;
- Gb_Square* sq = &square2;
- switch ( index )
- {
- case 0:
- sq = &square1;
- case 1:
- if ( sq->write_register( reg, data ) && index == 0 )
- {
- square1.sweep_freq = square1.frequency();
- if ( (regs [0] & sq->period_mask) && (regs [0] & sq->shift_mask) )
- {
- square1.sweep_delay = 1; // cause sweep to recalculate now
- square1.clock_sweep();
- }
- }
- break;
-
- case 2:
- wave.write_register( reg, data );
- break;
-
- case 3:
- if ( noise.write_register( reg, data ) )
- noise.bits = 0x7FFF;
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.h
deleted file mode 100644
index d7f88ea1..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gb_Oscs.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Private oscillators used by Gb_Apu
-
-// Gb_Snd_Emu 0.1.5
-#ifndef GB_OSCS_H
-#define GB_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Gb_Osc
-{
- enum { trigger = 0x80 };
- enum { len_enabled_mask = 0x40 };
-
- Blip_Buffer* outputs [4]; // NULL, right, left, center
- Blip_Buffer* output;
- int output_select;
- BOOST::uint8_t* regs; // osc's 5 registers
-
- int delay;
- int last_amp;
- int volume;
- int length;
- int enabled;
-
- void reset();
- void clock_length();
- int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
-};
-
-struct Gb_Env : Gb_Osc
-{
- int env_delay;
-
- void reset();
- void clock_envelope();
- bool write_register( int, int );
-};
-
-struct Gb_Square : Gb_Env
-{
- enum { period_mask = 0x70 };
- enum { shift_mask = 0x07 };
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- Synth const* synth;
- int sweep_delay;
- int sweep_freq;
- int phase;
-
- void reset();
- void clock_sweep();
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-struct Gb_Noise : Gb_Env
-{
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth const* synth;
- unsigned bits;
-
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-struct Gb_Wave : Gb_Osc
-{
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth const* synth;
- int wave_pos;
- enum { wave_size = 32 };
- BOOST::uint8_t wave [wave_size];
-
- void write_register( int, int );
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-inline void Gb_Env::reset()
-{
- env_delay = 0;
- Gb_Osc::reset();
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.cpp
deleted file mode 100644
index 30a147e5..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Gbs_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000 };
-Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300 };
-
-Gbs_Emu::Gbs_Emu()
-{
- set_type( gme_gbs_type );
-
- static const char* const names [Gb_Apu::osc_count] = {
- "Square 1", "Square 2", "Wave", "Noise"
- };
- set_voice_names( names );
-
- static int const types [Gb_Apu::osc_count] = {
- wave_type | 1, wave_type | 2, wave_type | 0, mixed_type | 0
- };
- set_voice_types( types );
-
- set_silence_lookahead( 6 );
- set_max_initial_silence( 21 );
- set_gain( 1.2 );
-
- static equalizer_t const eq = { -1.0, 120 };
- set_equalizer( eq );
-}
-
-Gbs_Emu::~Gbs_Emu() { }
-
-void Gbs_Emu::unload()
-{
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
-}
-
-blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_gbs_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_gbs_header( void const* header )
-{
- if ( memcmp( header, "GBS", 3 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Gbs_File : Gme_Info_
-{
- Gbs_Emu::header_t h;
-
- Gbs_File() { set_type( gme_gbs_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &h, Gbs_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
-
- set_track_count( h.track_count );
- return check_gbs_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_gbs_fields( h, out );
- return 0;
- }
-};
-
-static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
-static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
-
-gme_type_t_ const gme_gbs_type [1] = { "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 };
-
-// Setup
-
-blargg_err_t Gbs_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,copyright [32]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
- set_track_count( header_.track_count );
- RETURN_ERR( check_gbs_header( &header_ ) );
-
- if ( header_.vers != 1 )
- set_warning( "Unknown file version" );
-
- if ( header_.timer_mode & 0x78 )
- set_warning( "Invalid timer mode" );
-
- unsigned load_addr = get_le16( header_.load_addr );
- if ( (header_.load_addr [1] | header_.init_addr [1] | header_.play_addr [1]) > 0x7F ||
- load_addr < 0x400 )
- set_warning( "Invalid load/init/play address" );
-
- set_voice_count( Gb_Apu::osc_count );
-
- apu.volume( gain() );
-
- return setup_buffer( 4194304 );
-}
-
-void Gbs_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- apu.osc_output( i, c, l, r );
-}
-
-// Emulation
-
-// see gb_cpu_io.h for read/write functions
-
-void Gbs_Emu::set_bank( int n )
-{
- blargg_long addr = rom.mask_addr( n * (blargg_long) bank_size );
- if ( addr == 0 && rom.size() > bank_size )
- {
- // TODO: what is the correct behavior? Current Game & Watch Gallery
- // rip requires that this have no effect or set to bank 1.
- //dprintf( "Selected ROM bank 0\n" );
- return;
- //n = 1;
- }
- cpu::map_code( bank_size, bank_size, rom.at_addr( addr ) );
-}
-
-void Gbs_Emu::update_timer()
-{
- if ( header_.timer_mode & 0x04 )
- {
- static byte const rates [4] = { 10, 4, 6, 8 };
- int shift = rates [ram [hi_page + 7] & 3] - (header_.timer_mode >> 7);
- play_period = (256L - ram [hi_page + 6]) << shift;
- }
- else
- {
- play_period = 70224; // 59.73 Hz
- }
- if ( tempo() != 1.0 )
- play_period = blip_time_t (play_period / tempo());
-}
-
-static BOOST::uint8_t const sound_data [Gb_Apu::register_count] = {
- 0x80, 0xBF, 0x00, 0x00, 0xBF, // square 1
- 0x00, 0x3F, 0x00, 0x00, 0xBF, // square 2
- 0x7F, 0xFF, 0x9F, 0x00, 0xBF, // wave
- 0x00, 0xFF, 0x00, 0x00, 0xBF, // noise
- 0x77, 0xF3, 0xF1, // vin/volume, status, power mode
- 0, 0, 0, 0, 0, 0, 0, 0, 0, // unused
- 0xAC, 0xDD, 0xDA, 0x48, 0x36, 0x02, 0xCF, 0x16, // waveform data
- 0x2C, 0x04, 0xE5, 0x2C, 0xAC, 0xDD, 0xDA, 0x48
-};
-
-void Gbs_Emu::cpu_jsr( gb_addr_t addr )
-{
- check( cpu::r.sp == get_le16( header_.stack_ptr ) );
- cpu::r.pc = addr;
- cpu_write( --cpu::r.sp, idle_addr >> 8 );
- cpu_write( --cpu::r.sp, idle_addr&0xFF );
-}
-
-void Gbs_Emu::set_tempo_( double t )
-{
- apu.set_tempo( t );
- update_timer();
-}
-
-blargg_err_t Gbs_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0, 0x4000 );
- memset( ram + 0x4000, 0xFF, 0x1F80 );
- memset( ram + 0x5F80, 0, sizeof ram - 0x5F80 );
- ram [hi_page] = 0; // joypad reads back as 0
-
- apu.reset();
- for ( int i = 0; i < (int) sizeof sound_data; i++ )
- apu.write_register( 0, i + apu.start_addr, sound_data [i] );
-
- cpu::reset( rom.unmapped() );
-
- unsigned load_addr = get_le16( header_.load_addr );
- cpu::rst_base = load_addr;
- rom.set_addr( load_addr );
-
- cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
- cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
- set_bank( rom.size() > bank_size );
-
- ram [hi_page + 6] = header_.timer_modulo;
- ram [hi_page + 7] = header_.timer_mode;
- update_timer();
- next_play = play_period;
-
- cpu::r.a = track;
- cpu::r.pc = idle_addr;
- cpu::r.sp = get_le16( header_.stack_ptr );
- cpu_time = 0;
- cpu_jsr( get_le16( header_.init_addr ) );
-
- return 0;
-}
-
-blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
-{
- cpu_time = 0;
- while ( cpu_time < duration )
- {
- long count = duration - cpu_time;
- cpu_time = duration;
- bool result = cpu::run( count );
- cpu_time -= cpu::remain();
-
- if ( result )
- {
- if ( cpu::r.pc == idle_addr )
- {
- if ( next_play > duration )
- {
- cpu_time = duration;
- break;
- }
-
- if ( cpu_time < next_play )
- cpu_time = next_play;
- next_play += play_period;
- cpu_jsr( get_le16( header_.play_addr ) );
- GME_FRAME_HOOK( this );
- // TODO: handle timer rates different than 60 Hz
- }
- else if ( cpu::r.pc > 0xFFFF )
- {
- dprintf( "PC wrapped around\n" );
- cpu::r.pc &= 0xFFFF;
- }
- else
- {
- set_warning( "Emulation error (illegal/unsupported instruction)" );
- dprintf( "Bad opcode $%.2x at $%.4x\n",
- (int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
- cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
- cpu_time += 6;
- }
- }
- }
-
- duration = cpu_time;
- next_play -= cpu_time;
- if ( next_play < 0 ) // could go negative if routine is taking too long to return
- next_play = 0;
- apu.end_frame( cpu_time );
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.h
deleted file mode 100644
index 93fe691e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gbs_Emu.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Nintendo Game Boy GBS music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef GBS_EMU_H
-#define GBS_EMU_H
-
-#include "Classic_Emu.h"
-#include "Gb_Apu.h"
-#include "Gb_Cpu.h"
-
-class Gbs_Emu : private Gb_Cpu, public Classic_Emu {
- typedef Gb_Cpu cpu;
-public:
- // Equalizer profiles for Game Boy Color speaker and headphones
- static equalizer_t const handheld_eq;
- static equalizer_t const headphones_eq;
-
- // GBS file header
- enum { header_size = 112 };
- struct header_t
- {
- char tag [3];
- byte vers;
- byte track_count;
- byte first_track;
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte stack_ptr [2];
- byte timer_modulo;
- byte timer_mode;
- char game [32];
- char author [32];
- char copyright [32];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_gbs_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
-
-public:
- Gbs_Emu();
- ~Gbs_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-private:
- // rom
- enum { bank_size = 0x4000 };
- Rom_Data<bank_size> rom;
- void set_bank( int );
-
- // timer
- blip_time_t cpu_time;
- blip_time_t play_period;
- blip_time_t next_play;
- void update_timer();
-
- header_t header_;
- void cpu_jsr( gb_addr_t );
-
-public: private: friend class Gb_Cpu;
- blip_time_t clock() const { return cpu_time - cpu::remain(); }
-
- enum { joypad_addr = 0xFF00 };
- enum { ram_addr = 0xA000 };
- enum { hi_page = 0xFF00 - ram_addr };
- byte ram [0x4000 + 0x2000 + Gb_Cpu::cpu_padding];
- Gb_Apu apu;
-
- int cpu_read( gb_addr_t );
- void cpu_write( gb_addr_t, int );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.cpp
deleted file mode 100644
index 6821c3a5..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Gme_File.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char gme_wrong_file_type [] = "Wrong file type for this emulator";
-
-void Gme_File::clear_playlist()
-{
- playlist.clear();
- clear_playlist_();
- track_count_ = raw_track_count_;
-}
-
-void Gme_File::unload()
-{
- clear_playlist(); // *before* clearing track count
- track_count_ = 0;
- raw_track_count_ = 0;
- file_data.clear();
-}
-
-Gme_File::Gme_File()
-{
- type_ = 0;
- user_data_ = 0;
- user_cleanup_ = 0;
- unload(); // clears fields
- blargg_verify_byte_order(); // used by most emulator types, so save them the trouble
-}
-
-Gme_File::~Gme_File()
-{
- if ( user_cleanup_ )
- user_cleanup_( user_data_ );
-}
-
-blargg_err_t Gme_File::load_mem_( byte const* data, long size )
-{
- require( data != file_data.begin() ); // load_mem_() or load_() must be overridden
- Mem_File_Reader in( data, size );
- return load_( in );
-}
-
-blargg_err_t Gme_File::load_( Data_Reader& in )
-{
- RETURN_ERR( file_data.resize( in.remain() ) );
- RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
- return load_mem_( file_data.begin(), file_data.size() );
-}
-
-// public load functions call this at beginning
-void Gme_File::pre_load() { unload(); }
-
-void Gme_File::post_load_() { }
-
-// public load functions call this at end
-blargg_err_t Gme_File::post_load( blargg_err_t err )
-{
- if ( !track_count() )
- set_track_count( type()->track_count );
- if ( !err )
- post_load_();
- else
- unload();
-
- return err;
-}
-
-// Public load functions
-
-blargg_err_t Gme_File::load_mem( void const* in, long size )
-{
- pre_load();
- return post_load( load_mem_( (byte const*) in, size ) );
-}
-
-blargg_err_t Gme_File::load( Data_Reader& in )
-{
- pre_load();
- return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_file( const char* path )
-{
- pre_load();
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_remaining_( void const* h, long s, Data_Reader& in )
-{
- Remaining_Reader rem( h, s, &in );
- return load( rem );
-}
-
-// Track info
-
-void Gme_File::copy_field_( char* out, const char* in, int in_size )
-{
- if ( !in || !*in )
- return;
-
- // remove spaces/junk from beginning
- while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
- {
- in++;
- in_size--;
- }
-
- // truncate
- if ( in_size > max_field_ )
- in_size = max_field_;
-
- // find terminator
- int len = 0;
- while ( len < in_size && in [len] )
- len++;
-
- // remove spaces/junk from end
- while ( len && unsigned (in [len - 1]) <= ' ' )
- len--;
-
- // copy
- out [len] = 0;
- memcpy( out, in, len );
-
- // strip out stupid fields that should have been left blank
- if ( !strcmp( out, "?" ) || !strcmp( out, "<?>" ) || !strcmp( out, "< ? >" ) )
- out [0] = 0;
-}
-
-void Gme_File::copy_field_( char* out, const char* in )
-{
- copy_field_( out, in, max_field_ );
-}
-
-blargg_err_t Gme_File::remap_track_( int* track_io ) const
-{
- if ( (unsigned) *track_io >= (unsigned) track_count() )
- return "Invalid track";
-
- if ( (unsigned) *track_io < (unsigned) playlist.size() )
- {
- M3u_Playlist::entry_t const& e = playlist [*track_io];
- *track_io = 0;
- if ( e.track >= 0 )
- {
- *track_io = e.track;
- if ( !(type_->flags_ & 0x02) )
- *track_io -= e.decimal_track;
- }
- if ( *track_io >= raw_track_count_ )
- return "Invalid track in m3u playlist";
- }
- else
- {
- check( !playlist.size() );
- }
- return 0;
-}
-
-blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
-{
- out->track_count = track_count();
- out->length = -1;
- out->loop_length = -1;
- out->intro_length = -1;
- out->song [0] = 0;
-
- out->game [0] = 0;
- out->author [0] = 0;
- out->copyright [0] = 0;
- out->comment [0] = 0;
- out->dumper [0] = 0;
- out->system [0] = 0;
-
- copy_field_( out->system, type()->system );
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- RETURN_ERR( track_info_( out, remapped ) );
-
- // override with m3u info
- if ( playlist.size() )
- {
- M3u_Playlist::info_t const& i = playlist.info();
- copy_field_( out->game , i.title );
- copy_field_( out->author, i.engineer );
- copy_field_( out->author, i.composer );
- copy_field_( out->dumper, i.ripping );
-
- M3u_Playlist::entry_t const& e = playlist [track];
- copy_field_( out->song, e.name );
- if ( e.length >= 0 ) out->length = e.length * 1000L;
- if ( e.intro >= 0 ) out->intro_length = e.intro * 1000L;
- if ( e.loop >= 0 ) out->loop_length = e.loop * 1000L;
- }
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.h
deleted file mode 100644
index a535633b..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gme_File.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// Common interface to game music file loading and information
-
-// Game_Music_Emu 0.5.2
-#ifndef GME_FILE_H
-#define GME_FILE_H
-
-#include "gme.h"
-#include "blargg_common.h"
-#include "Data_Reader.h"
-#include "M3u_Playlist.h"
-
-// Error returned if file is wrong type
-//extern const char gme_wrong_file_type []; // declared in gme.h
-
-struct Gme_File {
-public:
-// File loading
-
- // Each loads game music data from a file and returns an error if
- // file is wrong type or is seriously corrupt. They also set warning
- // string for minor problems.
-
- // Load from file on disk
- blargg_err_t load_file( const char* path );
-
- // Load from custom data source (see Data_Reader.h)
- blargg_err_t load( Data_Reader& );
-
- // Load from file already read into memory. Keeps pointer to data, so you
- // must not free it until you're done with the file.
- blargg_err_t load_mem( void const* data, long size );
-
- // Load an m3u playlist. Must be done after loading main music file.
- blargg_err_t load_m3u( const char* path );
- blargg_err_t load_m3u( Data_Reader& in );
-
- // Clears any loaded m3u playlist and any internal playlist that the music
- // format supports (NSFE for example).
- void clear_playlist();
-
-// Informational
-
- // Type of emulator. For example if this returns gme_nsfe_type, this object
- // is an NSFE emulator, and you can cast to an Nsfe_Emu* if necessary.
- gme_type_t type() const;
-
- // Most recent warning string, or NULL if none. Clears current warning after
- // returning.
- const char* warning();
-
- // Number of tracks or 0 if no file has been loaded
- int track_count() const;
-
- // Get information for a track (length, name, author, etc.)
- // See gme.h for definition of struct track_info_t.
- blargg_err_t track_info( track_info_t* out, int track ) const;
-
-// User data/cleanup
-
- // Set/get pointer to data you want to associate with this emulator.
- // You can use this for whatever you want.
- void set_user_data( void* p ) { user_data_ = p; }
- void* user_data() const { return user_data_; }
-
- // Register cleanup function to be called when deleting emulator, or NULL to
- // clear it. Passes user_data to cleanup function.
- void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
-
-public:
- // deprecated
- int error_count() const; // use warning()
-public:
- Gme_File();
- virtual ~Gme_File();
- BLARGG_DISABLE_NOTHROW
- typedef BOOST::uint8_t byte;
-protected:
- // Services
- void set_track_count( int n ) { track_count_ = raw_track_count_ = n; }
- void set_warning( const char* s ) { warning_ = s; }
- void set_type( gme_type_t t ) { type_ = t; }
- blargg_err_t load_remaining_( void const* header, long header_size, Data_Reader& remaining );
-
- // Overridable
- virtual void unload(); // called before loading file and if loading fails
- virtual blargg_err_t load_( Data_Reader& ); // default loads then calls load_mem_()
- virtual blargg_err_t load_mem_( byte const* data, long size ); // use data in memory
- virtual blargg_err_t track_info_( track_info_t* out, int track ) const = 0;
- virtual void pre_load();
- virtual void post_load_();
- virtual void clear_playlist_() { }
-
-public:
- blargg_err_t remap_track_( int* track_io ) const; // need by Music_Emu
-private:
- // noncopyable
- Gme_File( const Gme_File& );
- Gme_File& operator = ( const Gme_File& );
-
- gme_type_t type_;
- int track_count_;
- int raw_track_count_;
- const char* warning_;
- void* user_data_;
- gme_user_cleanup_t user_cleanup_;
- M3u_Playlist playlist;
- char playlist_warning [64];
- blargg_vector<byte> file_data; // only if loaded into memory using default load
-
- blargg_err_t load_m3u_( blargg_err_t );
- blargg_err_t post_load( blargg_err_t err );
-public:
- // track_info field copying
- enum { max_field_ = 255 };
- static void copy_field_( char* out, const char* in );
- static void copy_field_( char* out, const char* in, int len );
-};
-
-Music_Emu* gme_new_( Music_Emu*, long sample_rate );
-
-#define GME_COPY_FIELD( in, out, name ) \
- { Gme_File::copy_field_( out->name, in.name, sizeof in.name ); }
-
-#ifndef GME_FILE_READER
- #ifdef HAVE_ZLIB_H
- #define GME_FILE_READER Gzip_File_Reader
- #else
- #define GME_FILE_READER Std_File_Reader
- #endif
-#elif defined (GME_FILE_READER_INCLUDE)
- #include GME_FILE_READER_INCLUDE
-#endif
-
-inline gme_type_t Gme_File::type() const { return type_; }
-inline int Gme_File::error_count() const { return warning_ != 0; }
-inline int Gme_File::track_count() const { return track_count_; }
-
-inline const char* Gme_File::warning()
-{
- const char* s = warning_;
- warning_ = 0;
- return s;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.cpp
deleted file mode 100644
index 499a9ca2..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Gym_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const min_tempo = 0.25;
-double const oversample_factor = 5 / 3.0;
-double const fm_gain = 3.0;
-
-const long base_clock = 53700300;
-const long clock_rate = base_clock / 15;
-
-Gym_Emu::Gym_Emu()
-{
- data = 0;
- pos = 0;
- set_type( gme_gym_type );
-
- static const char* const names [] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
- };
- set_voice_names( names );
- set_silence_lookahead( 1 ); // tracks should already be trimmed
-}
-
-Gym_Emu::~Gym_Emu() { }
-
-// Track info
-
-static void get_gym_info( Gym_Emu::header_t const& h, long length, track_info_t* out )
-{
- if ( !memcmp( h.tag, "GYMX", 4 ) )
- {
- length = length * 50 / 3; // 1000 / 60
- long loop = get_le32( h.loop_start );
- if ( loop )
- {
- out->intro_length = loop * 50 / 3;
- out->loop_length = length - out->intro_length;
- }
- else
- {
- out->length = length;
- out->intro_length = length; // make it clear that track is no longer than length
- out->loop_length = 0;
- }
-
- // more stupidity where the field should have been left
- if ( strcmp( h.song, "Unknown Song" ) )
- GME_COPY_FIELD( h, out, song );
-
- if ( strcmp( h.game, "Unknown Game" ) )
- GME_COPY_FIELD( h, out, game );
-
- if ( strcmp( h.copyright, "Unknown Publisher" ) )
- GME_COPY_FIELD( h, out, copyright );
-
- if ( strcmp( h.dumper, "Unknown Person" ) )
- GME_COPY_FIELD( h, out, dumper );
-
- if ( strcmp( h.comment, "Header added by YMAMP" ) )
- GME_COPY_FIELD( h, out, comment );
- }
-}
-
-blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
-{
- get_gym_info( header_, track_length(), out );
- return 0;
-}
-
-static long gym_track_length( byte const* p, byte const* end )
-{
- long time = 0;
- while ( p < end )
- {
- switch ( *p++ )
- {
- case 0:
- time++;
- break;
-
- case 1:
- case 2:
- p += 2;
- break;
-
- case 3:
- p += 1;
- break;
- }
- }
- return time;
-}
-
-long Gym_Emu::track_length() const { return gym_track_length( data, data_end ); }
-
-static blargg_err_t check_header( byte const* in, long size, int* data_offset = 0 )
-{
- if ( size < 4 )
- return gme_wrong_file_type;
-
- if ( memcmp( in, "GYMX", 4 ) == 0 )
- {
- if ( size < Gym_Emu::header_size + 1 )
- return gme_wrong_file_type;
-
- if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
- return "Packed GYM file not supported";
-
- if ( data_offset )
- *data_offset = Gym_Emu::header_size;
- }
- else if ( *in > 3 )
- {
- return gme_wrong_file_type;
- }
-
- return 0;
-}
-
-struct Gym_File : Gme_Info_
-{
- byte const* file_begin;
- byte const* file_end;
- int data_offset;
-
- Gym_File() { set_type( gme_gym_type ); }
-
- blargg_err_t load_mem_( byte const* in, long size )
- {
- file_begin = in;
- file_end = in + size;
- data_offset = 0;
- return check_header( in, size, &data_offset );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- long length = gym_track_length( &file_begin [data_offset], file_end );
- get_gym_info( *(Gym_Emu::header_t const*) file_begin, length, out );
- return 0;
- }
-};
-
-static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
-static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
-
-gme_type_t_ const gme_gym_type [1] = { "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 };
-
-// Setup
-
-blargg_err_t Gym_Emu::set_sample_rate_( long sample_rate )
-{
- blip_eq_t eq( -32, 8000, sample_rate );
- apu.treble_eq( eq );
- dac_synth.treble_eq( eq );
- apu.volume( 0.135 * fm_gain * gain() );
- dac_synth.volume( 0.125 / 256 * fm_gain * gain() );
- double factor = Dual_Resampler::setup( oversample_factor, 0.990, fm_gain * gain() );
- fm_sample_rate = sample_rate * factor;
-
- RETURN_ERR( blip_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
- blip_buf.clock_rate( clock_rate );
-
- RETURN_ERR( fm.set_rate( fm_sample_rate, base_clock / 7.0 ) );
- RETURN_ERR( Dual_Resampler::reset( long (1.0 / 60 / min_tempo * sample_rate) ) );
-
- return 0;
-}
-
-void Gym_Emu::set_tempo_( double t )
-{
- if ( t < min_tempo )
- {
- set_tempo( min_tempo );
- return;
- }
-
- if ( blip_buf.sample_rate() )
- {
- clocks_per_frame = long (clock_rate / 60 / tempo());
- Dual_Resampler::resize( long (sample_rate() / (60.0 * tempo())) );
- }
-}
-
-void Gym_Emu::mute_voices_( int mask )
-{
- Music_Emu::mute_voices_( mask );
- fm.mute_voices( mask );
- dac_muted = (mask & 0x40) != 0;
- apu.output( (mask & 0x80) ? 0 : &blip_buf );
-}
-
-blargg_err_t Gym_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,packed [4]) == header_size );
- int offset = 0;
- RETURN_ERR( check_header( in, size, &offset ) );
- set_voice_count( 8 );
-
- data = in + offset;
- data_end = in + size;
- loop_begin = 0;
-
- if ( offset )
- header_ = *(header_t const*) in;
- else
- memset( &header_, 0, sizeof header_ );
-
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Gym_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
-
- pos = data;
- loop_remain = get_le32( header_.loop_start );
-
- prev_dac_count = 0;
- dac_enabled = false;
- dac_amp = -1;
-
- fm.reset();
- apu.reset();
- blip_buf.clear();
- Dual_Resampler::clear();
- return 0;
-}
-
-void Gym_Emu::run_dac( int dac_count )
-{
- // Guess beginning and end of sample and adjust rate and buffer position accordingly.
-
- // count dac samples in next frame
- int next_dac_count = 0;
- const byte* p = this->pos;
- int cmd;
- while ( (cmd = *p++) != 0 )
- {
- int data = *p++;
- if ( cmd <= 2 )
- ++p;
- if ( cmd == 1 && data == 0x2A )
- next_dac_count++;
- }
-
- // detect beginning and end of sample
- int rate_count = dac_count;
- int start = 0;
- if ( !prev_dac_count && next_dac_count && dac_count < next_dac_count )
- {
- rate_count = next_dac_count;
- start = next_dac_count - dac_count;
- }
- else if ( prev_dac_count && !next_dac_count && dac_count < prev_dac_count )
- {
- rate_count = prev_dac_count;
- }
-
- // Evenly space samples within buffer section being used
- blip_resampled_time_t period = blip_buf.resampled_duration( clocks_per_frame ) / rate_count;
-
- blip_resampled_time_t time = blip_buf.resampled_time( 0 ) +
- period * start + (period >> 1);
-
- int dac_amp = this->dac_amp;
- if ( dac_amp < 0 )
- dac_amp = dac_buf [0];
-
- for ( int i = 0; i < dac_count; i++ )
- {
- int delta = dac_buf [i] - dac_amp;
- dac_amp += delta;
- dac_synth.offset_resampled( time, delta, &blip_buf );
- time += period;
- }
- this->dac_amp = dac_amp;
-}
-
-void Gym_Emu::parse_frame()
-{
- int dac_count = 0;
- const byte* pos = this->pos;
-
- if ( loop_remain && !--loop_remain )
- loop_begin = pos; // find loop on first time through sequence
-
- int cmd;
- while ( (cmd = *pos++) != 0 )
- {
- int data = *pos++;
- if ( cmd == 1 )
- {
- int data2 = *pos++;
- if ( data != 0x2A )
- {
- if ( data == 0x2B )
- dac_enabled = (data2 & 0x80) != 0;
-
- fm.write0( data, data2 );
- }
- else if ( dac_count < (int) sizeof dac_buf )
- {
- dac_buf [dac_count] = data2;
- dac_count += dac_enabled;
- }
- }
- else if ( cmd == 2 )
- {
- fm.write1( data, *pos++ );
- }
- else if ( cmd == 3 )
- {
- apu.write_data( 0, data );
- }
- else
- {
- // to do: many GYM streams are full of errors, and error count should
- // reflect cases where music is really having problems
- //log_error();
- --pos; // put data back
- }
- }
-
- // loop
- if ( pos >= data_end )
- {
- check( pos == data_end );
-
- if ( loop_begin )
- pos = loop_begin;
- else
- set_track_ended();
- }
- this->pos = pos;
-
- // dac
- if ( dac_count && !dac_muted )
- run_dac( dac_count );
- prev_dac_count = dac_count;
-}
-
-int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
- if ( !track_ended() )
- parse_frame();
-
- apu.end_frame( blip_time );
-
- memset( buf, 0, sample_count * sizeof *buf );
- fm.run( sample_count >> 1, buf );
-
- return sample_count;
-}
-
-blargg_err_t Gym_Emu::play_( long count, sample_t* out )
-{
- Dual_Resampler::dual_play( count, out, blip_buf );
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.h
deleted file mode 100644
index 05419ea2..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Gym_Emu.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Sega Genesis/Mega Drive GYM music file emulator
-// Includes with PCM timing recovery to improve sample quality.
-
-// Game_Music_Emu 0.5.2
-#ifndef GYM_EMU_H
-#define GYM_EMU_H
-
-#include "Dual_Resampler.h"
-#include "Ym2612_Emu.h"
-#include "Music_Emu.h"
-#include "Sms_Apu.h"
-
-class Gym_Emu : public Music_Emu, private Dual_Resampler {
-public:
- // GYM file header
- enum { header_size = 428 };
- struct header_t
- {
- char tag [4];
- char song [32];
- char game [32];
- char copyright [32];
- char emulator [32];
- char dumper [32];
- char comment [256];
- byte loop_start [4]; // in 1/60 seconds, 0 if not looped
- byte packed [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_gym_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- enum { gym_rate = 60 };
- long track_length() const; // use track_info()
-
-public:
- Gym_Emu();
- ~Gym_Emu();
-protected:
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t set_sample_rate_( long sample_rate );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long count, sample_t* );
- void mute_voices_( int );
- void set_tempo_( double );
- int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf );
-private:
- // sequence data begin, loop begin, current position, end
- const byte* data;
- const byte* loop_begin;
- const byte* pos;
- const byte* data_end;
- blargg_long loop_remain; // frames remaining until loop beginning has been located
- header_t header_;
- double fm_sample_rate;
- blargg_long clocks_per_frame;
- void parse_frame();
-
- // dac (pcm)
- int dac_amp;
- int prev_dac_count;
- bool dac_enabled;
- bool dac_muted;
- void run_dac( int );
-
- // sound
- Blip_Buffer blip_buf;
- Ym2612_Emu fm;
- Blip_Synth<blip_med_quality,1> dac_synth;
- Sms_Apu apu;
- byte dac_buf [1024];
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.cpp
deleted file mode 100644
index 22389121..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Hes_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-bool const center_waves = true; // reduces asymmetry and clamping when starting notes
-
-Hes_Apu::Hes_Apu()
-{
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->outputs [0] = 0;
- osc->outputs [1] = 0;
- osc->chans [0] = 0;
- osc->chans [1] = 0;
- osc->chans [2] = 0;
- }
- while ( osc != oscs );
-
- reset();
-}
-
-void Hes_Apu::reset()
-{
- latch = 0;
- balance = 0xFF;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- memset( osc, 0, offsetof (Hes_Osc,outputs) );
- osc->noise_lfsr = 1;
- osc->control = 0x40;
- osc->balance = 0xFF;
- }
- while ( osc != oscs );
-}
-
-void Hes_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- oscs [index].chans [0] = center;
- oscs [index].chans [1] = left;
- oscs [index].chans [2] = right;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- balance_changed( *osc );
- }
- while ( osc != oscs );
-}
-
-void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
-{
- Blip_Buffer* const osc_outputs_0 = outputs [0]; // cache often-used values
- if ( osc_outputs_0 && control & 0x80 )
- {
- int dac = this->dac;
-
- int const volume_0 = volume [0];
- {
- int delta = dac * volume_0 - last_amp [0];
- if ( delta )
- synth_.offset( last_time, delta, osc_outputs_0 );
- osc_outputs_0->set_modified();
- }
-
- Blip_Buffer* const osc_outputs_1 = outputs [1];
- int const volume_1 = volume [1];
- if ( osc_outputs_1 )
- {
- int delta = dac * volume_1 - last_amp [1];
- if ( delta )
- synth_.offset( last_time, delta, osc_outputs_1 );
- osc_outputs_1->set_modified();
- }
-
- blip_time_t time = last_time + delay;
- if ( time < end_time )
- {
- if ( noise & 0x80 )
- {
- if ( volume_0 | volume_1 )
- {
- // noise
- int const period = (32 - (noise & 0x1F)) * 64; // TODO: correct?
- unsigned noise_lfsr = this->noise_lfsr;
- do
- {
- int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
- // Implemented using "Galios configuration"
- // TODO: find correct LFSR algorithm
- noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1));
- //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
- int delta = new_dac - dac;
- if ( delta )
- {
- dac = new_dac;
- synth_.offset( time, delta * volume_0, osc_outputs_0 );
- if ( osc_outputs_1 )
- synth_.offset( time, delta * volume_1, osc_outputs_1 );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->noise_lfsr = noise_lfsr;
- assert( noise_lfsr );
- }
- }
- else if ( !(control & 0x40) )
- {
- // wave
- int phase = (this->phase + 1) & 0x1F; // pre-advance for optimal inner loop
- int period = this->period * 2;
- if ( period >= 14 && (volume_0 | volume_1) )
- {
- do
- {
- int new_dac = wave [phase];
- phase = (phase + 1) & 0x1F;
- int delta = new_dac - dac;
- if ( delta )
- {
- dac = new_dac;
- synth_.offset( time, delta * volume_0, osc_outputs_0 );
- if ( osc_outputs_1 )
- synth_.offset( time, delta * volume_1, osc_outputs_1 );
- }
- time += period;
- }
- while ( time < end_time );
- }
- else
- {
- if ( !period )
- {
- // TODO: Gekisha Boy assumes that period = 0 silences wave
- //period = 0x1000 * 2;
- period = 1;
- //if ( !(volume_0 | volume_1) )
- // dprintf( "Used period 0\n" );
- }
-
- // maintain phase when silent
- blargg_long count = (end_time - time + period - 1) / period;
- phase += count; // phase will be masked below
- time += count * period;
- }
- this->phase = (phase - 1) & 0x1F; // undo pre-advance
- }
- }
- time -= end_time;
- if ( time < 0 )
- time = 0;
- delay = time;
-
- this->dac = dac;
- last_amp [0] = dac * volume_0;
- last_amp [1] = dac * volume_1;
- }
- last_time = end_time;
-}
-
-void Hes_Apu::balance_changed( Hes_Osc& osc )
-{
- static short const log_table [32] = { // ~1.5 db per step
- #define ENTRY( factor ) short (factor * Hes_Osc::amp_range / 31.0 + 0.5)
- ENTRY( 0.000000 ),ENTRY( 0.005524 ),ENTRY( 0.006570 ),ENTRY( 0.007813 ),
- ENTRY( 0.009291 ),ENTRY( 0.011049 ),ENTRY( 0.013139 ),ENTRY( 0.015625 ),
- ENTRY( 0.018581 ),ENTRY( 0.022097 ),ENTRY( 0.026278 ),ENTRY( 0.031250 ),
- ENTRY( 0.037163 ),ENTRY( 0.044194 ),ENTRY( 0.052556 ),ENTRY( 0.062500 ),
- ENTRY( 0.074325 ),ENTRY( 0.088388 ),ENTRY( 0.105112 ),ENTRY( 0.125000 ),
- ENTRY( 0.148651 ),ENTRY( 0.176777 ),ENTRY( 0.210224 ),ENTRY( 0.250000 ),
- ENTRY( 0.297302 ),ENTRY( 0.353553 ),ENTRY( 0.420448 ),ENTRY( 0.500000 ),
- ENTRY( 0.594604 ),ENTRY( 0.707107 ),ENTRY( 0.840896 ),ENTRY( 1.000000 ),
- #undef ENTRY
- };
-
- int vol = (osc.control & 0x1F) - 0x1E * 2;
-
- int left = vol + (osc.balance >> 3 & 0x1E) + (balance >> 3 & 0x1E);
- if ( left < 0 ) left = 0;
-
- int right = vol + (osc.balance << 1 & 0x1E) + (balance << 1 & 0x1E);
- if ( right < 0 ) right = 0;
-
- left = log_table [left ];
- right = log_table [right];
-
- // optimizing for the common case of being centered also allows easy
- // panning using Effects_Buffer
- osc.outputs [0] = osc.chans [0]; // center
- osc.outputs [1] = 0;
- if ( left != right )
- {
- osc.outputs [0] = osc.chans [1]; // left
- osc.outputs [1] = osc.chans [2]; // right
- }
-
- if ( center_waves )
- {
- osc.last_amp [0] += (left - osc.volume [0]) * 16;
- osc.last_amp [1] += (right - osc.volume [1]) * 16;
- }
-
- osc.volume [0] = left;
- osc.volume [1] = right;
-}
-
-void Hes_Apu::write_data( blip_time_t time, int addr, int data )
-{
- if ( addr == 0x800 )
- {
- latch = data & 7;
- }
- else if ( addr == 0x801 )
- {
- if ( balance != data )
- {
- balance = data;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->run_until( synth, time );
- balance_changed( *oscs );
- }
- while ( osc != oscs );
- }
- }
- else if ( latch < osc_count )
- {
- Hes_Osc& osc = oscs [latch];
- osc.run_until( synth, time );
- switch ( addr )
- {
- case 0x802:
- osc.period = (osc.period & 0xF00) | data;
- break;
-
- case 0x803:
- osc.period = (osc.period & 0x0FF) | ((data & 0x0F) << 8);
- break;
-
- case 0x804:
- if ( osc.control & 0x40 & ~data )
- osc.phase = 0;
- osc.control = data;
- balance_changed( osc );
- break;
-
- case 0x805:
- osc.balance = data;
- balance_changed( osc );
- break;
-
- case 0x806:
- data &= 0x1F;
- if ( !(osc.control & 0x40) )
- {
- osc.wave [osc.phase] = data;
- osc.phase = (osc.phase + 1) & 0x1F;
- }
- else if ( osc.control & 0x80 )
- {
- osc.dac = data;
- }
- break;
-
- case 0x807:
- if ( &osc >= &oscs [4] )
- osc.noise = data;
- break;
-
- case 0x809:
- if ( !(data & 0x80) && (data & 0x03) != 0 )
- dprintf( "HES LFO not supported\n" );
- }
- }
-}
-
-void Hes_Apu::end_frame( blip_time_t end_time )
-{
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- if ( end_time > osc->last_time )
- osc->run_until( synth, end_time );
- assert( osc->last_time >= end_time );
- osc->last_time -= end_time;
- }
- while ( osc != oscs );
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.h
deleted file mode 100644
index ca0c932f..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Apu.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Turbo Grafx 16 (PC Engine) PSG sound chip emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef HES_APU_H
-#define HES_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Hes_Osc
-{
- unsigned char wave [32];
- short volume [2];
- int last_amp [2];
- int delay;
- int period;
- unsigned char noise;
- unsigned char phase;
- unsigned char balance;
- unsigned char dac;
- blip_time_t last_time;
-
- Blip_Buffer* outputs [2];
- Blip_Buffer* chans [3];
- unsigned noise_lfsr;
- unsigned char control;
-
- enum { amp_range = 0x8000 };
- typedef Blip_Synth<blip_med_quality,1> synth_t;
-
- void run_until( synth_t& synth, blip_time_t );
-};
-
-class Hes_Apu {
-public:
- void treble_eq( blip_eq_t const& );
- void volume( double );
-
- enum { osc_count = 6 };
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- void reset();
-
- enum { start_addr = 0x0800 };
- enum { end_addr = 0x0809 };
- void write_data( blip_time_t, int addr, int data );
-
- void end_frame( blip_time_t );
-
-public:
- Hes_Apu();
-private:
- Hes_Osc oscs [osc_count];
- int latch;
- int balance;
- Hes_Osc::synth_t synth;
-
- void balance_changed( Hes_Osc& );
- void recalc_chans();
-};
-
-inline void Hes_Apu::volume( double v ) { synth.volume( 1.8 / osc_count / Hes_Osc::amp_range * v ); }
-
-inline void Hes_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.cpp
deleted file mode 100644
index 2615a0bb..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.cpp
+++ /dev/null
@@ -1,1303 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Hes_Cpu.h"
-
-#include "blargg_endian.h"
-
-//#include "hes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// TODO: support T flag, including clearing it at appropriate times?
-
-// all zero-page should really use whatever is at page 1, but that would
-// reduce efficiency quite a bit
-int const ram_addr = 0x2000;
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "hes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-// status flags
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_t = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Hes_Cpu::reset()
-{
- check( state == &state_ );
- state = &state_;
-
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_hes_time;
- end_time_ = future_hes_time;
-
- r.status = st_i;
- r.sp = 0;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
-
- blargg_verify_byte_order();
-}
-
-void Hes_Cpu::set_mmr( int reg, int bank )
-{
- assert( (unsigned) reg <= page_count ); // allow page past end to be set
- assert( (unsigned) bank < 0x100 );
- mmr [reg] = bank;
- uint8_t const* code = CPU_SET_MMR( this, reg, bank );
- state->code_map [reg] = code - PAGE_OFFSET( reg << page_shift );
-}
-
-#define TIME (s_time + s.base)
-
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (ram [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-typedef blargg_long fint32;
-
-bool Hes_Cpu::run( hes_time_t end_time )
-{
- bool illegal_encountered = false;
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- // even on x86, using s.time in place of s_time was slower
- fint16 s_time = s.time;
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-branch_not_taken:
- s_time -= 2;
-loop:
-
- #ifndef NDEBUG
- {
- hes_time_t correct = end_time_;
- if ( !(status & st_i) && correct > irq_time_ )
- correct = irq_time_;
- check( s.base == correct );
- /*
- static long count;
- if ( count == 1844 ) Debugger();
- if ( s.base != correct ) dprintf( "%ld\n", count );
- count++;
- */
- }
- #endif
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
-
- uint8_t const* instr = s.code_map [pc >> page_shift];
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- // TODO: each reference lists slightly different timing values, ugh
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,6,// 0
- 4,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,6,// 1
- 7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,6,// 2
- 4,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,6,// 3
- 7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,6,// 4
- 4,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,6,// 5
- 7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,6,// 6
- 4,7,7,17,4,4,6,7,2,5,4,2,7,5,7,6,// 7
- 4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// 8
- 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// 9
- 2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// A
- 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// B
- 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// C
- 4,7,7,17,2,4,6,7,2,5,3,2,2,5,7,6,// D
- 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// E
- 4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
- }; // 0x00 was 8
-
- fuint16 data;
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- #ifdef HES_CPU_LOG_H
- log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
- instr [3], instr [4], instr [5] );
- //log_opcode( opcode );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB());
-#define GET_ADDR() GET_LE16( instr )
-
-// TODO: is the penalty really always added? the original 6502 was much better
-//#define PAGE_CROSS_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
-#define PAGE_CROSS_PENALTY( lsb )
-
-// Branch
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) ) goto branch_not_taken;\
- pc = BOOST::uint16_t (pc + offset);\
- goto loop;\
-}
-
- case 0xF0: // BEQ
- BRANCH( !((uint8_t) nz) );
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x10: // BPL
- BRANCH( !IS_NEG );
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x80: // BRA
- branch_taken:
- BRANCH( true );
-
- case 0xFF:
- if ( pc == idle_addr + 1 )
- goto idle_done;
- case 0x0F: // BBRn
- case 0x1F:
- case 0x2F:
- case 0x3F:
- case 0x4F:
- case 0x5F:
- case 0x6F:
- case 0x7F:
- case 0x8F: // BBSn
- case 0x9F:
- case 0xAF:
- case 0xBF:
- case 0xCF:
- case 0xDF:
- case 0xEF: {
- fuint16 t = 0x101 * READ_LOW( data );
- t ^= 0xFF;
- pc++;
- data = GET_MSB();
- BRANCH( t & (1 << (opcode >> 4)) )
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0x7C: // JMP (ind+X)
- data += x;
- case 0x6C:{// JMP (ind)
- data += 0x100 * GET_MSB();
- pc = GET_LE16( &READ_PROG( data ) );
- goto loop;
- }
-
-// Subroutine
-
- case 0x44: // BSR
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, pc );
- goto branch_taken;
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- pc += 1 + READ_LOW( sp );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Common
-
- case 0xBD:{// LDA abs,X
- PAGE_CROSS_PENALTY( data + x );
- fuint16 addr = GET_ADDR() + x;
- pc += 2;
- CPU_READ_FAST( this, addr, TIME, nz );
- a = nz;
- goto loop;
- }
-
- case 0x9D:{// STA abs,X
- fuint16 addr = GET_ADDR() + x;
- pc += 2;
- CPU_WRITE_FAST( this, addr, a, TIME );
- goto loop;
- }
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xAE:{// LDX abs
- fuint16 addr = GET_ADDR();
- pc += 2;
- CPU_READ_FAST( this, addr, TIME, nz );
- x = nz;
- goto loop;
- }
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
-// Load/store
-
- {
- fuint16 addr;
- case 0x91: // STA (ind),Y
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data ) + y;
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- data = uint8_t (data + x);
- case 0x92: // STA (ind)
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data );
- pc++;
- goto sta_ptr;
-
- case 0x99: // STA abs,Y
- data += y;
- case 0x8D: // STA abs
- addr = data + 0x100 * GET_MSB();
- pc += 2;
- sta_ptr:
- CPU_WRITE_FAST( this, addr, a, TIME );
- goto loop;
- }
-
- {
- fuint16 addr;
- case 0xA1: // LDA (ind,X)
- data = uint8_t (data + x);
- case 0xB2: // LDA (ind)
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data );
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- PAGE_CROSS_PENALTY( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- data += y;
- PAGE_CROSS_PENALTY( data );
- case 0xAD: // LDA abs
- addr = data + 0x100 * GET_MSB();
- pc += 2;
- a_nz_read_addr:
- CPU_READ_FAST( this, addr, TIME, nz );
- a = nz;
- goto loop;
- }
-
- case 0xBE:{// LDX abs,y
- PAGE_CROSS_PENALTY( data + y );
- fuint16 addr = GET_ADDR() + y;
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
-// Bit operations
-
- case 0x3C: // BIT abs,x
- data += x;
- case 0x2C:{// BIT abs
- fuint16 addr;
- ADD_PAGE( addr );
- FLUSH_TIME();
- nz = READ( addr );
- CACHE_TIME();
- goto bit_common;
- }
- case 0x34: // BIT zp,x
- data = uint8_t (data + x);
- case 0x24: // BIT zp
- data = READ_LOW( data );
- case 0x89: // BIT imm
- nz = data;
- bit_common:
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( nz & a )
- goto loop; // Z should be clear, and nz must be non-zero if nz & a is
- nz <<= 8; // set Z flag without affecting N flag
- goto loop;
-
- {
- fuint16 addr;
-
- case 0xB3: // TST abs,x
- addr = GET_MSB() + x;
- goto tst_abs;
-
- case 0x93: // TST abs
- addr = GET_MSB();
- tst_abs:
- addr += 0x100 * instr [2];
- pc++;
- FLUSH_TIME();
- nz = READ( addr );
- CACHE_TIME();
- goto tst_common;
- }
-
- case 0xA3: // TST zp,x
- nz = READ_LOW( uint8_t (GET_MSB() + x) );
- goto tst_common;
-
- case 0x83: // TST zp
- nz = READ_LOW( GET_MSB() );
- tst_common:
- pc += 2;
- status &= ~st_v;
- status |= nz & st_v;
- if ( nz & data )
- goto loop; // Z should be clear, and nz must be non-zero if nz & data is
- nz <<= 8; // set Z flag without affecting N flag
- goto loop;
-
- {
- fuint16 addr;
- case 0x0C: // TSB abs
- case 0x1C: // TRB abs
- addr = GET_ADDR();
- pc++;
- goto txb_addr;
-
- // TODO: everyone lists different behaviors for the status flags, ugh
- case 0x04: // TSB zp
- case 0x14: // TRB zp
- addr = data + ram_addr;
- txb_addr:
- FLUSH_TIME();
- nz = a | READ( addr );
- if ( opcode & 0x10 )
- nz ^= a; // bits from a will already be set, so this clears them
- status &= ~st_v;
- status |= nz & st_v;
- pc++;
- WRITE( addr, nz );
- CACHE_TIME();
- goto loop;
- }
-
- case 0x07: // RMBn
- case 0x17:
- case 0x27:
- case 0x37:
- case 0x47:
- case 0x57:
- case 0x67:
- case 0x77:
- pc++;
- READ_LOW( data ) &= ~(1 << (opcode >> 4));
- goto loop;
-
- case 0x87: // SMBn
- case 0x97:
- case 0xA7:
- case 0xB7:
- case 0xC7:
- case 0xD7:
- case 0xE7:
- case 0xF7:
- pc++;
- READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
- goto loop;
-
-// Load/store
-
- case 0x9E: // STZ abs,x
- data += x;
- case 0x9C: // STZ abs
- ADD_PAGE( data );
- pc++;
- FLUSH_TIME();
- WRITE( data, 0 );
- CACHE_TIME();
- goto loop;
-
- case 0x74: // STZ zp,x
- data = uint8_t (data + x);
- case 0x64: // STZ zp
- pc++;
- WRITE_LOW( data, 0 );
- goto loop;
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- PAGE_CROSS_PENALTY( data );
- case 0xAC:{// LDY abs
- fuint16 addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- fuint16 addr = GET_ADDR();
- pc += 2;
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- fuint16 addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- fuint16 addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
-#define ARITH_ADDR_MODES( op )\
- case op - 0x04: /* (ind,x) */\
- data = uint8_t (data + x);\
- case op + 0x0D: /* (ind) */\
- data = 0x100 * READ_LOW( uint8_t (data + 1) ) + READ_LOW( data );\
- goto ptr##op;\
- case op + 0x0C:{/* (ind),y */\
- fuint16 temp = READ_LOW( data ) + y;\
- PAGE_CROSS_PENALTY( temp );\
- data = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- goto ptr##op;\
- }\
- case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
- case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
- case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
- case op + 0x18: /* abs,X */\
- data += x;\
- ind##op:\
- PAGE_CROSS_PENALTY( data );\
- case op + 0x08: /* abs */\
- ADD_PAGE( data );\
- ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
- case op + 0x04: /* imm */\
- imm##op:
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- if ( status & st_d )
- dprintf( "Decimal mode not supported\n" );
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE( data );
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE( data );
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
-#define INC_DEC_AXY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
- case 0x1A: // INA
- INC_DEC_AXY( a, +1 )
-
- case 0xE8: // INX
- INC_DEC_AXY( x, +1 )
-
- case 0xC8: // INY
- INC_DEC_AXY( y, +1 )
-
- case 0x3A: // DEA
- INC_DEC_AXY( a, -1 )
-
- case 0xCA: // DEX
- INC_DEC_AXY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_AXY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
- #define SWAP_REGS( r1, r2 ) {\
- fuint8 t = r1;\
- r1 = r2;\
- r2 = t;\
- goto loop;\
- }
-
- case 0x02: // SXY
- SWAP_REGS( x, y );
-
- case 0x22: // SAX
- SWAP_REGS( a, x );
-
- case 0x42: // SAY
- SWAP_REGS( a, y );
-
- case 0x62: // CLA
- a = 0;
- goto loop;
-
- case 0x82: // CLX
- x = 0;
- goto loop;
-
- case 0xC2: // CLY
- y = 0;
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a );
- goto loop;
-
- case 0xDA: // PHX
- PUSH( x );
- goto loop;
-
- case 0x5A: // PHY
- PUSH( y );
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- this->r.status = status; // update externally-visible I flag
- if ( (data ^ status) & st_i )
- {
- hes_time_t new_time = end_time_;
- if ( !(status & st_i) && new_time > irq_time_ )
- new_time = irq_time_;
- blargg_long delta = s.base - new_time;
- s.base = new_time;
- s_time += delta;
- }
- goto loop;
- }
-
- #define POP() READ_LOW( sp ); sp = (sp - 0xFF) | 0x100
-
- case 0x68: // PLA
- a = nz = POP();
- goto loop;
-
- case 0xFA: // PLX
- x = nz = POP();
- goto loop;
-
- case 0x7A: // PLY
- y = nz = POP();
- goto loop;
-
- case 0x28:{// PLP
- fuint8 temp = POP();
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
- #undef POP
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | st_b );
- goto loop;
- }
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- // delayed irq until after next instruction
- s.base += s_time + 1;
- s_time = -1;
- irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
- goto loop;
- }
- delayed_cli:
- dprintf( "Delayed CLI not supported\n" ); // TODO: implement
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
- dprintf( "Delayed SEI not supported\n" ); // TODO: implement
- goto loop;
- }
-
-// Special
-
- case 0x53:{// TAM
- fuint8 const bits = data; // avoid using data across function call
- pc++;
- for ( int i = 0; i < 8; i++ )
- if ( bits & (1 << i) )
- set_mmr( i, a );
- goto loop;
- }
-
- case 0x43:{// TMA
- pc++;
- byte const* in = mmr;
- do
- {
- if ( data & 1 )
- a = *in;
- in++;
- }
- while ( (data >>= 1) != 0 );
- goto loop;
- }
-
- case 0x03: // ST0
- case 0x13: // ST1
- case 0x23:{// ST2
- fuint16 addr = opcode >> 4;
- if ( addr )
- addr++;
- pc++;
- FLUSH_TIME();
- CPU_WRITE_VDP( this, addr, data, TIME );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xEA: // NOP
- goto loop;
-
- case 0x54: // CSL
- dprintf( "CSL not supported\n" );
- illegal_encountered = true;
- goto loop;
-
- case 0xD4: // CSH
- goto loop;
-
- case 0xF4: { // SET
- //fuint16 operand = GET_MSB();
- dprintf( "SET not handled\n" );
- //switch ( data )
- //{
- //}
- illegal_encountered = true;
- goto loop;
- }
-
-// Block transfer
-
- {
- fuint16 in_alt;
- fint16 in_inc;
- fuint16 out_alt;
- fint16 out_inc;
-
- case 0xE3: // TIA
- in_alt = 0;
- goto bxfer_alt;
-
- case 0xF3: // TAI
- in_alt = 1;
- bxfer_alt:
- in_inc = in_alt ^ 1;
- out_alt = in_inc;
- out_inc = in_alt;
- goto bxfer;
-
- case 0xD3: // TIN
- in_inc = 1;
- out_inc = 0;
- goto bxfer_no_alt;
-
- case 0xC3: // TDD
- in_inc = -1;
- out_inc = -1;
- goto bxfer_no_alt;
-
- case 0x73: // TII
- in_inc = 1;
- out_inc = 1;
- bxfer_no_alt:
- in_alt = 0;
- out_alt = 0;
- bxfer:
- fuint16 in = GET_LE16( instr + 0 );
- fuint16 out = GET_LE16( instr + 2 );
- int count = GET_LE16( instr + 4 );
- if ( !count )
- count = 0x10000;
- pc += 6;
- WRITE_LOW( 0x100 | (sp - 1), y );
- WRITE_LOW( 0x100 | (sp - 2), a );
- WRITE_LOW( 0x100 | (sp - 3), x );
- FLUSH_TIME();
- do
- {
- // TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
- fuint8 t = READ( in );
- in += in_inc;
- in &= 0xFFFF;
- s.time += 6;
- if ( in_alt )
- in_inc = -in_inc;
- WRITE( out, t );
- out += out_inc;
- out &= 0xFFFF;
- if ( out_alt )
- out_inc = -out_inc;
- }
- while ( --count );
- CACHE_TIME();
- goto loop;
- }
-
-// Illegal
-
- default:
- assert( (unsigned) opcode <= 0xFF );
- dprintf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
- illegal_encountered = true;
- goto loop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- pc++;
- result_ = 6;
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- if ( result_ == 6 )
- temp |= st_b;
- WRITE_LOW( sp, temp );
-
- status &= ~st_d;
- status |= st_i;
- this->r.status = status; // update externally-visible I flag
-
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- goto loop;
- }
-
-idle_done:
- s_time = 0;
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ > 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return illegal_encountered;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.h
deleted file mode 100644
index 437d0908..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Cpu.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// PC Engine CPU emulator for use with HES music files
-
-// Game_Music_Emu 0.5.2
-#ifndef HES_CPU_H
-#define HES_CPU_H
-
-#include "blargg_common.h"
-#include <limits.h>
-
-typedef blargg_long hes_time_t; // clock cycle count
-typedef unsigned hes_addr_t; // 16-bit address
-enum { future_hes_time = LONG_MAX / 2 + 1 };
-
-class Hes_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- void reset();
-
- enum { page_size = 0x2000 };
- enum { page_shift = 13 };
- enum { page_count = 8 };
- void set_mmr( int reg, int bank );
-
- uint8_t const* get_code( hes_addr_t );
-
- uint8_t ram [page_size];
-
- // not kept updated during a call to run()
- struct registers_t {
- BOOST::uint16_t pc;
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- };
- registers_t r;
-
- // page mapping registers
- uint8_t mmr [page_count + 1];
-
- // Set end_time and run CPU from current time. Returns true if any illegal
- // instructions were encountered.
- bool run( hes_time_t end_time );
-
- // Time of beginning of next instruction to be executed
- hes_time_t time() const { return state->time + state->base; }
- void set_time( hes_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- hes_time_t irq_time() const { return irq_time_; }
- void set_irq_time( hes_time_t );
-
- hes_time_t end_time() const { return end_time_; }
- void set_end_time( hes_time_t );
-
- void end_frame( hes_time_t );
-
- // Attempt to execute instruction here results in CPU advancing time to
- // lesser of irq_time() and end_time() (or end_time() if IRQs are
- // disabled)
- enum { idle_addr = 0x1FFF };
-
- // Can read this many bytes past end of a page
- enum { cpu_padding = 8 };
-
-public:
- Hes_Cpu() { state = &state_; }
- enum { irq_inhibit = 0x04 };
-private:
- // noncopyable
- Hes_Cpu( const Hes_Cpu& );
- Hes_Cpu& operator = ( const Hes_Cpu& );
-
- struct state_t {
- uint8_t const* code_map [page_count + 1];
- hes_time_t base;
- blargg_long time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- hes_time_t irq_time_;
- hes_time_t end_time_;
-
- void set_code_page( int, void const* );
- inline int update_end_time( hes_time_t end, hes_time_t irq );
-};
-
-inline BOOST::uint8_t const* Hes_Cpu::get_code( hes_addr_t addr )
-{
- return state->code_map [addr >> page_shift] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-inline int Hes_Cpu::update_end_time( hes_time_t t, hes_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- int delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Hes_Cpu::set_irq_time( hes_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Hes_Cpu::set_end_time( hes_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-inline void Hes_Cpu::end_frame( hes_time_t t )
-{
- assert( state == &state_ );
- state_.base -= t;
- if ( irq_time_ < future_hes_time ) irq_time_ -= t;
- if ( end_time_ < future_hes_time ) end_time_ -= t;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.cpp
deleted file mode 100644
index fafb2666..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Hes_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const timer_mask = 0x04;
-int const vdp_mask = 0x02;
-int const i_flag_mask = 0x04;
-int const unmapped = 0xFF;
-
-long const period_60hz = 262 * 455L; // scanlines * clocks per scanline
-
-Hes_Emu::Hes_Emu()
-{
- timer.raw_load = 0;
- set_type( gme_hes_type );
-
- static const char* const names [Hes_Apu::osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2"
- };
- set_voice_names( names );
-
- static int const types [Hes_Apu::osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2, wave_type | 3,
- mixed_type | 0, mixed_type | 1
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
- set_gain( 1.11 );
-}
-
-Hes_Emu::~Hes_Emu() { }
-
-void Hes_Emu::unload()
-{
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static byte const* copy_field( byte const* in, char* out )
-{
- if ( in )
- {
- int len = 0x20;
- if ( in [0x1F] && !in [0x2F] )
- len = 0x30; // fields are sometimes 16 bytes longer (ugh)
-
- // since text fields are where any data could be, detect non-text
- // and fields with data after zero byte terminator
-
- int i = 0;
- for ( i = 0; i < len && in [i]; i++ )
- if ( ((in [i] + 1) & 0xFF) < ' ' + 1 ) // also treat 0xFF as non-text
- return 0; // non-ASCII found
-
- for ( ; i < len; i++ )
- if ( in [i] )
- return 0; // data after terminator
-
- Gme_File::copy_field_( out, (char const*) in, len );
- in += len;
- }
- return in;
-}
-
-static void copy_hes_fields( byte const* in, track_info_t* out )
-{
- if ( *in >= ' ' )
- {
- in = copy_field( in, out->game );
- in = copy_field( in, out->author );
- in = copy_field( in, out->copyright );
- }
-}
-
-blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_hes_fields( rom.begin() + 0x20, out );
- return 0;
-}
-
-static blargg_err_t check_hes_header( void const* header )
-{
- if ( memcmp( header, "HESM", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Hes_File : Gme_Info_
-{
- struct header_t {
- char header [Hes_Emu::header_size];
- char unused [0x20];
- byte fields [0x30 * 3];
- } h;
-
- Hes_File() { set_type( gme_hes_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20 );
- blargg_err_t err = in.read( &h, sizeof h );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- return check_hes_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_hes_fields( h.fields, out );
- return 0;
- }
-};
-
-static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
-static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
-
-gme_type_t_ const gme_hes_type [1] = { "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 };
-
-// Setup
-
-blargg_err_t Hes_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,unused [4]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) );
-
- RETURN_ERR( check_hes_header( header_.tag ) );
-
- if ( header_.vers != 0 )
- set_warning( "Unknown file version" );
-
- if ( memcmp( header_.data_tag, "DATA", 4 ) )
- set_warning( "Data header missing" );
-
- if ( memcmp( header_.unused, "\0\0\0\0", 4 ) )
- set_warning( "Unknown header data" );
-
- // File spec supports multiple blocks, but I haven't found any, and
- // many files have bad sizes in the only block, so it's simpler to
- // just try to load the damn data as best as possible.
-
- long addr = get_le32( header_.addr );
- long size = get_le32( header_.size );
- long const rom_max = 0x100000;
- if ( addr & ~(rom_max - 1) )
- {
- set_warning( "Invalid address" );
- addr &= rom_max - 1;
- }
- if ( (unsigned long) (addr + size) > (unsigned long) rom_max )
- set_warning( "Invalid size" );
-
- if ( size != rom.file_size() )
- {
- if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) )
- set_warning( "Multiple DATA not supported" );
- else if ( size < rom.file_size() )
- set_warning( "Extra file data" );
- else
- set_warning( "Missing file data" );
- }
-
- rom.set_addr( addr );
-
- set_voice_count( apu.osc_count );
-
- apu.volume( gain() );
-
- return setup_buffer( 7159091 );
-}
-
-void Hes_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Hes_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- apu.osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Hes_Emu::recalc_timer_load()
-{
- timer.load = timer.raw_load * timer_base + 1;
-}
-
-void Hes_Emu::set_tempo_( double t )
-{
- play_period = hes_time_t (period_60hz / t);
- timer_base = int (1024 / t);
- recalc_timer_load();
-}
-
-blargg_err_t Hes_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0, sizeof ram ); // some HES music relies on zero fill
- memset( sgx, 0, sizeof sgx );
-
- apu.reset();
- cpu::reset();
-
- for ( unsigned i = 0; i < sizeof header_.banks; i++ )
- set_mmr( i, header_.banks [i] );
- set_mmr( page_count, 0xFF ); // unmapped beyond end of address space
-
- irq.disables = timer_mask | vdp_mask;
- irq.timer = future_hes_time;
- irq.vdp = future_hes_time;
-
- timer.enabled = false;
- timer.raw_load= 0x80;
- timer.count = timer.load;
- timer.fired = false;
- timer.last_time = 0;
-
- vdp.latch = 0;
- vdp.control = 0;
- vdp.next_vbl = 0;
-
- ram [0x1FF] = (idle_addr - 1) >> 8;
- ram [0x1FE] = (idle_addr - 1) & 0xFF;
- r.sp = 0xFD;
- r.pc = get_le16( header_.init_addr );
- r.a = track;
-
- recalc_timer_load();
- last_frame_hook = 0;
-
- return 0;
-}
-
-// Hardware
-
-void Hes_Emu::cpu_write_vdp( int addr, int data )
-{
- switch ( addr )
- {
- case 0:
- vdp.latch = data & 0x1F;
- break;
-
- case 2:
- if ( vdp.latch == 5 )
- {
- if ( data & 0x04 )
- set_warning( "Scanline interrupt unsupported" );
- run_until( time() );
- vdp.control = data;
- irq_changed();
- }
- else
- {
- dprintf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
- }
- break;
-
- case 3:
- dprintf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
- break;
- }
-}
-
-void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
-{
- if ( unsigned (addr - apu.start_addr) <= apu.end_addr - apu.start_addr )
- {
- GME_APU_HOOK( this, addr - apu.start_addr, data );
- // avoid going way past end when a long block xfer is writing to I/O space
- hes_time_t t = min( time(), end_time() + 8 );
- apu.write_data( t, addr, data );
- return;
- }
-
- hes_time_t time = this->time();
- switch ( addr )
- {
- case 0x0000:
- case 0x0002:
- case 0x0003:
- cpu_write_vdp( addr, data );
- return;
-
- case 0x0C00: {
- run_until( time );
- timer.raw_load = (data & 0x7F) + 1;
- recalc_timer_load();
- timer.count = timer.load;
- break;
- }
-
- case 0x0C01:
- data &= 1;
- if ( timer.enabled == data )
- return;
- run_until( time );
- timer.enabled = data;
- if ( data )
- timer.count = timer.load;
- break;
-
- case 0x1402:
- run_until( time );
- irq.disables = data;
- if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
- dprintf( "Int mask: $%02X\n", data );
- break;
-
- case 0x1403:
- run_until( time );
- if ( timer.enabled )
- timer.count = timer.load;
- timer.fired = false;
- break;
-
-#ifndef NDEBUG
- case 0x1000: // I/O port
- case 0x0402: // palette
- case 0x0403:
- case 0x0404:
- case 0x0405:
- return;
-
- default:
- dprintf( "unmapped write $%04X <- $%02X\n", addr, data );
- return;
-#endif
- }
-
- irq_changed();
-}
-
-int Hes_Emu::cpu_read_( hes_addr_t addr )
-{
- hes_time_t time = this->time();
- addr &= page_size - 1;
- switch ( addr )
- {
- case 0x0000:
- if ( irq.vdp > time )
- return 0;
- irq.vdp = future_hes_time;
- run_until( time );
- irq_changed();
- return 0x20;
-
- case 0x0002:
- case 0x0003:
- dprintf( "VDP read not supported: %d\n", addr );
- return 0;
-
- case 0x0C01:
- //return timer.enabled; // TODO: remove?
- case 0x0C00:
- run_until( time );
- dprintf( "Timer count read\n" );
- return (unsigned) (timer.count - 1) / timer_base;
-
- case 0x1402:
- return irq.disables;
-
- case 0x1403:
- {
- int status = 0;
- if ( irq.timer <= time ) status |= timer_mask;
- if ( irq.vdp <= time ) status |= vdp_mask;
- return status;
- }
-
- #ifndef NDEBUG
- case 0x1000: // I/O port
- case 0x180C: // CD-ROM
- case 0x180D:
- break;
-
- default:
- dprintf( "unmapped read $%04X\n", addr );
- #endif
- }
-
- return unmapped;
-}
-
-// see hes_cpu_io.h for core read/write functions
-
-// Emulation
-
-void Hes_Emu::run_until( hes_time_t present )
-{
- while ( vdp.next_vbl < present )
- vdp.next_vbl += play_period;
-
- hes_time_t elapsed = present - timer.last_time;
- if ( elapsed > 0 )
- {
- if ( timer.enabled )
- {
- timer.count -= elapsed;
- if ( timer.count <= 0 )
- timer.count += timer.load;
- }
- timer.last_time = present;
- }
-}
-
-void Hes_Emu::irq_changed()
-{
- hes_time_t present = time();
-
- if ( irq.timer > present )
- {
- irq.timer = future_hes_time;
- if ( timer.enabled && !timer.fired )
- irq.timer = present + timer.count;
- }
-
- if ( irq.vdp > present )
- {
- irq.vdp = future_hes_time;
- if ( vdp.control & 0x08 )
- irq.vdp = vdp.next_vbl;
- }
-
- hes_time_t time = future_hes_time;
- if ( !(irq.disables & timer_mask) ) time = irq.timer;
- if ( !(irq.disables & vdp_mask) ) time = min( time, irq.vdp );
-
- set_irq_time( time );
-}
-
-int Hes_Emu::cpu_done()
-{
- check( time() >= end_time() ||
- (!(r.status & i_flag_mask) && time() >= irq_time()) );
-
- if ( !(r.status & i_flag_mask) )
- {
- hes_time_t present = time();
-
- if ( irq.timer <= present && !(irq.disables & timer_mask) )
- {
- timer.fired = true;
- irq.timer = future_hes_time;
- irq_changed(); // overkill, but not worth writing custom code
- #if GME_FRAME_HOOK_DEFINED
- {
- unsigned const threshold = period_60hz / 30;
- unsigned long elapsed = present - last_frame_hook;
- if ( elapsed - period_60hz + threshold / 2 < threshold )
- {
- last_frame_hook = present;
- GME_FRAME_HOOK( this );
- }
- }
- #endif
- return 0x0A;
- }
-
- if ( irq.vdp <= present && !(irq.disables & vdp_mask) )
- {
- // work around for bugs with music not acknowledging VDP
- //run_until( present );
- //irq.vdp = future_hes_time;
- //irq_changed();
- #if GME_FRAME_HOOK_DEFINED
- last_frame_hook = present;
- GME_FRAME_HOOK( this );
- #endif
- return 0x08;
- }
- }
- return 0;
-}
-
-static void adjust_time( blargg_long& time, hes_time_t delta )
-{
- if ( time < future_hes_time )
- {
- time -= delta;
- if ( time < 0 )
- time = 0;
- }
-}
-
-blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
-{
- blip_time_t const duration = duration_; // cache
-
- if ( cpu::run( duration ) )
- set_warning( "Emulation error (illegal instruction)" );
-
- check( time() >= duration );
- //check( time() - duration < 20 ); // Txx instruction could cause going way over
-
- run_until( duration );
-
- // end time frame
- timer.last_time -= duration;
- vdp.next_vbl -= duration;
- #if GME_FRAME_HOOK_DEFINED
- last_frame_hook -= duration;
- #endif
- cpu::end_frame( duration );
- ::adjust_time( irq.timer, duration );
- ::adjust_time( irq.vdp, duration );
- apu.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.h
deleted file mode 100644
index 9951eb6a..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Hes_Emu.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// TurboGrafx-16/PC Engine HES music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef HES_EMU_H
-#define HES_EMU_H
-
-#include "Classic_Emu.h"
-#include "Hes_Apu.h"
-#include "Hes_Cpu.h"
-
-class Hes_Emu : private Hes_Cpu, public Classic_Emu {
- typedef Hes_Cpu cpu;
-public:
- // HES file header
- enum { header_size = 0x20 };
- struct header_t
- {
- byte tag [4];
- byte vers;
- byte first_track;
- byte init_addr [2];
- byte banks [8];
- byte data_tag [4];
- byte size [4];
- byte addr [4];
- byte unused [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_hes_type; }
-
-public:
- Hes_Emu();
- ~Hes_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-public: private: friend class Hes_Cpu;
- byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space
-
- int cpu_read_( hes_addr_t );
- int cpu_read( hes_addr_t );
- void cpu_write_( hes_addr_t, int data );
- void cpu_write( hes_addr_t, int );
- void cpu_write_vdp( int addr, int data );
- byte const* cpu_set_mmr( int page, int bank );
- int cpu_done();
-private:
- Rom_Data<page_size> rom;
- header_t header_;
- hes_time_t play_period;
- hes_time_t last_frame_hook;
- int timer_base;
-
- struct {
- hes_time_t last_time;
- blargg_long count;
- blargg_long load;
- int raw_load;
- byte enabled;
- byte fired;
- } timer;
-
- struct {
- hes_time_t next_vbl;
- byte latch;
- byte control;
- } vdp;
-
- struct {
- hes_time_t timer;
- hes_time_t vdp;
- byte disables;
- } irq;
-
- void recalc_timer_load();
-
- // large items
- Hes_Apu apu;
- byte sgx [3 * page_size + cpu_padding];
-
- void irq_changed();
- void run_until( hes_time_t );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.cpp
deleted file mode 100644
index 37c4a724..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.cpp
+++ /dev/null
@@ -1,1706 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.14 2:19 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Kss_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME() (void) (s.time = s_time)
-#define RELOAD_TIME() (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, time )\
- kss_cpu_out( this, time, addr, data )
-
-#define CPU_IN( cpu, addr, time )\
- kss_cpu_in( this, time, addr )
-
-#define CPU_WRITE( cpu, addr, data, time )\
- (SYNC_TIME(), kss_cpu_write( this, addr, data ))
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n ) szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n ) (szpc [n] & ~P04)
-#define SZ28( n ) SZ28C( n )
-
-#define SET_R( n ) (void) (r.r = n)
-#define GET_R() (r.r)
-
-Kss_Cpu::Kss_Cpu()
-{
- state = &state_;
-
- for ( int i = 0x100; --i >= 0; )
- {
- int even = 1;
- for ( int p = i; p; p >>= 1 )
- even ^= p;
- int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
- szpc [i] = n;
- szpc [i + 0x100] = n | C01;
- }
- szpc [0x000] |= Z40;
- szpc [0x100] |= Z40;
-}
-
-inline void Kss_Cpu::set_page( int i, void* write, void const* read )
-{
- blargg_long offset = KSS_CPU_PAGE_OFFSET( i * (blargg_long) page_size );
- state->write [i] = (byte *) write - offset;
- state->read [i] = (byte const*) read - offset;
-}
-
-void Kss_Cpu::reset( void* unmapped_write, void const* unmapped_read )
-{
- check( state == &state_ );
- state = &state_;
- state_.time = 0;
- state_.base = 0;
- end_time_ = 0;
-
- for ( int i = 0; i < page_count + 1; i++ )
- set_page( i, unmapped_write, unmapped_read );
-
- memset( &r, 0, sizeof r );
-}
-
-void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const* read )
-{
- // address range must begin and end on page boundaries
- require( addr % page_size == 0 );
- require( size % page_size == 0 );
-
- unsigned first_page = addr / page_size;
- for ( unsigned i = size / page_size; i--; )
- {
- blargg_long offset = i * (blargg_long) page_size;
- set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset );
- }
-}
-
-#define TIME (s_time + s.base)
-#define RW_MEM( addr, rw ) (s.rw [(addr) >> page_shift] [KSS_CPU_PAGE_OFFSET( addr )])
-#define READ_PROG( addr ) RW_MEM( addr, read )
-#define READ( addr ) READ_PROG( addr )
-//#define WRITE( addr, data ) (void) (RW_MEM( addr, write ) = data)
-#define WRITE( addr, data ) CPU_WRITE( this, addr, data, TIME )
-#define READ_WORD( addr ) GET_LE16( &READ( addr ) )
-#define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data )
-#define IN( addr ) CPU_IN( this, addr, TIME )
-#define OUT( addr, data ) CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
- (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Kss_Cpu::run( cpu_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- bool warning = false;
-
- typedef BOOST::int8_t int8_t;
-
- union {
- regs_t rg;
- pairs_t rp;
- uint8_t r8_ [8]; // indexed
- uint16_t r16_ [4];
- };
- rg = this->r.b;
-
- cpu_time_t s_time = s.time;
- fuint16 pc = r.pc;
- fuint16 sp = r.sp;
- fuint16 ix = r.ix; // TODO: keep in memory for direct access?
- fuint16 iy = r.iy;
- int flags = r.b.flags;
-
- goto loop;
-jr_not_taken:
- s_time -= 5;
- goto loop;
-call_not_taken:
- s_time -= 7;
-jp_not_taken:
- pc += 2;
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (unsigned) flags < 0x100 );
- check( (unsigned) ix < 0x10000 );
- check( (unsigned) iy < 0x10000 );
-
- uint8_t const* instr = s.read [pc >> page_shift];
-#define GET_ADDR() GET_LE16( instr )
-
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += KSS_CPU_PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- static byte const base_timing [0x100] = {
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
- 13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
- 12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
- 12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
- 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
- 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
- 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
- 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
- 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
- };
-
- fuint16 data;
- data = base_timing [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = READ_PROG( pc );
-
- #ifdef Z80_CPU_LOG_H
- //log_opcode( opcode, READ_PROG( pc ) );
- z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
- z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
- READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Common
-
- case 0x00: // NOP
- CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
- goto loop;
-
- case 0x08:{// EX AF,AF'
- int temp = r.alt.b.a;
- r.alt.b.a = rg.a;
- rg.a = temp;
-
- temp = r.alt.b.flags;
- r.alt.b.flags = flags;
- flags = temp;
- goto loop;
- }
-
- case 0xD3: // OUT (imm),A
- pc++;
- OUT( data + rg.a * 0x100, rg.a );
- goto loop;
-
- case 0x2E: // LD L,imm
- pc++;
- rg.l = data;
- goto loop;
-
- case 0x3E: // LD A,imm
- pc++;
- rg.a = data;
- goto loop;
-
- case 0x3A:{// LD A,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rg.a = READ( addr );
- goto loop;
- }
-
-// Conditional
-
-#define ZERO (flags & Z40)
-#define CARRY (flags & C01)
-#define EVEN (flags & P04)
-#define MINUS (flags & S80)
-
-// JR
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define JR( cond ) {\
- int offset = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) )\
- goto jr_not_taken;\
- pc = uint16_t (pc + offset);\
- goto loop;\
-}
-
- case 0x20: JR( !ZERO ) // JR NZ,disp
- case 0x28: JR( ZERO ) // JR Z,disp
- case 0x30: JR( !CARRY ) // JR NC,disp
- case 0x38: JR( CARRY ) // JR C,disp
- case 0x18: JR( true ) // JR disp
-
- case 0x10:{// DJNZ disp
- int temp = rg.b - 1;
- rg.b = temp;
- JR( temp )
- }
-
-// JP
-#define JP( cond ) if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
- case 0xC2: JP( !ZERO ) // JP NZ,addr
- case 0xCA: JP( ZERO ) // JP Z,addr
- case 0xD2: JP( !CARRY ) // JP NC,addr
- case 0xDA: JP( CARRY ) // JP C,addr
- case 0xE2: JP( !EVEN ) // JP PO,addr
- case 0xEA: JP( EVEN ) // JP PE,addr
- case 0xF2: JP( !MINUS ) // JP P,addr
- case 0xFA: JP( MINUS ) // JP M,addr
-
- case 0xC3: // JP addr
- pc = GET_ADDR();
- goto loop;
-
- case 0xE9: // JP HL
- pc = rp.hl;
- goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
- case 0xC0: RET( !ZERO ) // RET NZ
- case 0xC8: RET( ZERO ) // RET Z
- case 0xD0: RET( !CARRY ) // RET NC
- case 0xD8: RET( CARRY ) // RET C
- case 0xE0: RET( !EVEN ) // RET PO
- case 0xE8: RET( EVEN ) // RET PE
- case 0xF0: RET( !MINUS ) // RET P
- case 0xF8: RET( MINUS ) // RET M
-
- case 0xC9: // RET
- ret_taken:
- pc = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
- case 0xC4: CALL( !ZERO ) // CALL NZ,addr
- case 0xCC: CALL( ZERO ) // CALL Z,addr
- case 0xD4: CALL( !CARRY ) // CALL NC,addr
- case 0xDC: CALL( CARRY ) // CALL C,addr
- case 0xE4: CALL( !EVEN ) // CALL PO,addr
- case 0xEC: CALL( EVEN ) // CALL PE,addr
- case 0xF4: CALL( !MINUS ) // CALL P,addr
- case 0xFC: CALL( MINUS ) // CALL M,addr
-
- case 0xCD:{// CALL addr
- call_taken:
- fuint16 addr = pc + 2;
- pc = GET_ADDR();
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, addr );
- goto loop;
- }
-
- case 0xFF: // RST
- if ( pc > idle_addr )
- goto hit_idle_addr;
- CASE7( C7, CF, D7, DF, E7, EF, F7 ):
- data = pc;
- pc = opcode & 0x38;
- goto push_data;
-
-// PUSH/POP
- case 0xF5: // PUSH AF
- data = rg.a * 0x100u + flags;
- goto push_data;
-
- case 0xC5: // PUSH BC
- case 0xD5: // PUSH DE
- case 0xE5: // PUSH HL
- data = R16( opcode, 4, 0xC5 );
- push_data:
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, data );
- goto loop;
-
- case 0xF1: // POP AF
- flags = READ( sp );
- rg.a = READ( sp + 1 );
- sp = uint16_t (sp + 2);
- goto loop;
-
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL
- R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// ADC/ADD/SBC/SUB
- case 0x96: // SUB (HL)
- case 0x86: // ADD (HL)
- flags &= ~C01;
- case 0x9E: // SBC (HL)
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_data;
-
- case 0xD6: // SUB A,imm
- case 0xC6: // ADD imm
- flags &= ~C01;
- case 0xDE: // SBC A,imm
- case 0xCE: // ADC imm
- pc++;
- goto adc_data;
-
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
- flags &= ~C01;
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
- data = R8( opcode & 7, 0 );
- adc_data: {
- int result = data + (flags & C01);
- data ^= rg.a;
- flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
- if ( flags )
- result = -result;
- result += rg.a;
- data ^= result;
- flags |=(data & H10) |
- ((data - -0x80) >> 6 & V04) |
- SZ28C( result & 0x1FF );
- rg.a = result;
- goto loop;
- }
-
-// CP
- case 0xBE: // CP (HL)
- data = READ( rp.hl );
- goto cp_data;
-
- case 0xFE: // CP imm
- pc++;
- goto cp_data;
-
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
- data = R8( opcode, 0xB8 );
- cp_data: {
- int result = rg.a - data;
- flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
- data ^= rg.a;
- flags |=(((result ^ rg.a) & data) >> 5 & V04) |
- (((data & H10) ^ result) & (S80 | H10));
- if ( (uint8_t) result )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
-// ADD HL,rp
-
- case 0x39: // ADD HL,SP
- data = sp;
- goto add_hl_data;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- data = R16( opcode, 4, 0x09 );
- add_hl_data: {
- blargg_ulong sum = rp.hl + data;
- data ^= rp.hl;
- rp.hl = sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((data ^ sum) >> 8 & H10);
- goto loop;
- }
-
- case 0x27:{// DAA
- int a = rg.a;
- if ( a > 0x99 )
- flags |= C01;
-
- int adjust = 0x60 & -(flags & C01);
-
- if ( flags & H10 || (a & 0x0F) > 9 )
- adjust |= 0x06;
-
- if ( flags & N02 )
- adjust = -adjust;
- a += adjust;
-
- flags = (flags & (C01 | N02)) |
- ((rg.a ^ a) & H10) |
- SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- /*
- case 0x27:{// DAA
- // more optimized, but probably not worth the obscurity
- int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
- int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
- if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
- adjust |= 0x06;
-
- if ( f & N02 )
- adjust = -adjust;
- int a = rg.a + adjust;
-
- flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- */
-
-// INC/DEC
- case 0x34: // INC (HL)
- data = READ( rp.hl ) + 1;
- WRITE( rp.hl, data );
- goto inc_set_flags;
-
- CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
- data = ++R8( opcode >> 3, 0 );
- inc_set_flags:
- flags = (flags & C01) |
- (((data & 0x0F) - 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x80 )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x35: // DEC (HL)
- data = READ( rp.hl ) - 1;
- WRITE( rp.hl, data );
- goto dec_set_flags;
-
- CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
- data = --R8( opcode >> 3, 0 );
- dec_set_flags:
- flags = (flags & C01) | N02 |
- (((data & 0x0F) + 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x7F )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- R16( opcode, 4, 0x03 )++;
- goto loop;
-
- case 0x33: // INC SP
- sp = uint16_t (sp + 1);
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- R16( opcode, 4, 0x0B )--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = uint16_t (sp - 1);
- goto loop;
-
-// AND
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- goto and_data;
-
- case 0xE6: // AND imm
- pc++;
- goto and_data;
-
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
- data = R8( opcode, 0xA0 );
- and_data:
- rg.a &= data;
- flags = SZ28P( rg.a ) | H10;
- goto loop;
-
-// OR
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- goto or_data;
-
- case 0xF6: // OR imm
- pc++;
- goto or_data;
-
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
- data = R8( opcode, 0xB0 );
- or_data:
- rg.a |= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// XOR
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- goto xor_data;
-
- case 0xEE: // XOR imm
- pc++;
- goto xor_data;
-
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
- data = R8( opcode, 0xA8 );
- xor_data:
- rg.a ^= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
- WRITE( rp.hl, R8( opcode, 0x70 ) );
- goto loop;
-
- CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
- CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
- CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
- CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
- CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
- CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
- CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
- R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
- goto loop;
-
- CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
- R8( opcode >> 3, 0 ) = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),imm
- pc++;
- WRITE( rp.hl, data );
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
- R8( opcode >> 3, 8 ) = READ( rp.hl );
- goto loop;
-
- case 0x01: // LD rp,imm
- case 0x11:
- case 0x21:
- R16( opcode, 4, 0x01 ) = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x31: // LD sp,imm
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x2A:{// LD HL,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rp.hl = READ_WORD( addr );
- goto loop;
- }
-
- case 0x32:{// LD (addr),A
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE( addr, rg.a );
- goto loop;
- }
-
- case 0x22:{// LD (addr),HL
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, rp.hl );
- goto loop;
- }
-
- case 0x02: // LD (BC),A
- case 0x12: // LD (DE),A
- WRITE( R16( opcode, 4, 0x02 ), rg.a );
- goto loop;
-
- case 0x0A: // LD A,(BC)
- case 0x1A: // LD A,(DE)
- rg.a = READ( R16( opcode, 4, 0x0A ) );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
-// Rotate
-
- case 0x07:{// RLCA
- fuint16 temp = rg.a;
- temp = (temp << 1) | (temp >> 7);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08 | C01));
- rg.a = temp;
- goto loop;
- }
-
- case 0x0F:{// RRCA
- fuint16 temp = rg.a;
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & C01);
- temp = (temp << 7) | (temp >> 1);
- flags |= temp & (F20 | F08);
- rg.a = temp;
- goto loop;
- }
-
- case 0x17:{// RLA
- blargg_ulong temp = (rg.a << 1) | (flags & C01);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (temp >> 8);
- rg.a = temp;
- goto loop;
- }
-
- case 0x1F:{// RRA
- fuint16 temp = (flags << 7) | (rg.a >> 1);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (rg.a & C01);
- rg.a = temp;
- goto loop;
- }
-
-// Misc
- case 0x2F:{// CPL
- fuint16 temp = ~rg.a;
- flags = (flags & (S80 | Z40 | P04 | C01)) |
- (temp & (F20 | F08)) |
- (H10 | N02);
- rg.a = temp;
- goto loop;
- }
-
- case 0x3F:{// CCF
- flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
- (flags << 4 & H10) |
- (rg.a & (F20 | F08));
- goto loop;
- }
-
- case 0x37: // SCF
- flags = (flags & (S80 | Z40 | P04)) | C01 |
- (rg.a & (F20 | F08));
- goto loop;
-
- case 0xDB: // IN A,(imm)
- pc++;
- rg.a = IN( data + rg.a * 0x100 );
- goto loop;
-
- case 0xE3:{// EX (SP),HL
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, rp.hl );
- rp.hl = temp;
- goto loop;
- }
-
- case 0xEB:{// EX DE,HL
- fuint16 temp = rp.hl;
- rp.hl = rp.de;
- rp.de = temp;
- goto loop;
- }
-
- case 0xD9:{// EXX DE,HL
- fuint16 temp = r.alt.w.bc;
- r.alt.w.bc = rp.bc;
- rp.bc = temp;
-
- temp = r.alt.w.de;
- r.alt.w.de = rp.de;
- rp.de = temp;
-
- temp = r.alt.w.hl;
- r.alt.w.hl = rp.hl;
- rp.hl = temp;
- goto loop;
- }
-
- case 0xF3: // DI
- r.iff1 = 0;
- r.iff2 = 0;
- goto loop;
-
- case 0xFB: // EI
- r.iff1 = 1;
- r.iff2 = 1;
- // TODO: delayed effect
- goto loop;
-
- case 0x76: // HALT
- goto halt;
-
-//////////////////////////////////////// CB prefix
- {
- case 0xCB:
- unsigned data2;
- data2 = instr [1];
- pc++;
- switch ( data )
- {
-
- // Rotate left
-
- #define RLC( read, write ) {\
- fuint8 result = read;\
- result = uint8_t (result << 1) | (result >> 7);\
- flags = SZ28P( result ) | (result & C01);\
- write;\
- goto loop;\
- }
-
- case 0x06: // RLC (HL)
- s_time += 7;
- data = rp.hl;
- rlc_data_addr:
- RLC( READ( data ), WRITE( data, result ) )
-
- CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
- uint8_t& reg = R8( data, 0 );
- RLC( reg, reg = result )
- }
-
- #define RL( read, write ) {\
- fuint16 result = (read << 1) | (flags & C01);\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x16: // RL (HL)
- s_time += 7;
- data = rp.hl;
- rl_data_addr:
- RL( READ( data ), WRITE( data, result ) )
-
- CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
- uint8_t& reg = R8( data, 0x10 );
- RL( reg, reg = result )
- }
-
- #define SLA( read, add, write ) {\
- fuint16 result = (read << 1) | add;\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x26: // SLA (HL)
- s_time += 7;
- data = rp.hl;
- sla_data_addr:
- SLA( READ( data ), 0, WRITE( data, result ) )
-
- CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
- uint8_t& reg = R8( data, 0x20 );
- SLA( reg, 0, reg = result )
- }
-
- case 0x36: // SLL (HL)
- s_time += 7;
- data = rp.hl;
- sll_data_addr:
- SLA( READ( data ), 1, WRITE( data, result ) )
-
- CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
- uint8_t& reg = R8( data, 0x30 );
- SLA( reg, 1, reg = result )
- }
-
- // Rotate right
-
- #define RRC( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = uint8_t (result << 7) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x0E: // RRC (HL)
- s_time += 7;
- data = rp.hl;
- rrc_data_addr:
- RRC( READ( data ), WRITE( data, result ) )
-
- CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
- uint8_t& reg = R8( data, 0x08 );
- RRC( reg, reg = result )
- }
-
- #define RR( read, write ) {\
- fuint8 result = read;\
- fuint8 temp = result & C01;\
- result = uint8_t (flags << 7) | (result >> 1);\
- flags = SZ28P( result ) | temp;\
- write;\
- goto loop;\
- }
-
- case 0x1E: // RR (HL)
- s_time += 7;
- data = rp.hl;
- rr_data_addr:
- RR( READ( data ), WRITE( data, result ) )
-
- CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
- uint8_t& reg = R8( data, 0x18 );
- RR( reg, reg = result )
- }
-
- #define SRA( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = (result & 0x80) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x2E: // SRA (HL)
- data = rp.hl;
- s_time += 7;
- sra_data_addr:
- SRA( READ( data ), WRITE( data, result ) )
-
- CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
- uint8_t& reg = R8( data, 0x28 );
- SRA( reg, reg = result )
- }
-
- #define SRL( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result >>= 1;\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x3E: // SRL (HL)
- s_time += 7;
- data = rp.hl;
- srl_data_addr:
- SRL( READ( data ), WRITE( data, result ) )
-
- CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
- uint8_t& reg = R8( data, 0x38 );
- SRL( reg, reg = result )
- }
-
- // BIT
- {
- unsigned temp;
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
- s_time += 4;
- temp = READ( rp.hl );
- flags &= C01;
- goto bit_temp;
- CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
- CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
- CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
- CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
- CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
- CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
- CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
- temp = R8( data & 7, 0 );
- flags = (flags & C01) | (temp & (F20 | F08));
- bit_temp:
- int masked = temp & 1 << (data >> 3 & 7);
- flags |=(masked & S80) | H10 |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- // SET/RES
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
- s_time += 7;
- int temp = READ( rp.hl );
- int bit = 1 << (data >> 3 & 7);
- temp |= bit; // SET
- if ( !(data & 0x40) )
- temp ^= bit; // RES
- WRITE( rp.hl, temp );
- goto loop;
- }
-
- CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
- CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
- CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
- CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
- CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
- CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
- CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
- CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
- R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
- goto loop;
-
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
- R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
- goto loop;
- }
- assert( false );
- }
-
-#undef GET_ADDR
-#define GET_ADDR() GET_LE16( instr + 1 )
-
-//////////////////////////////////////// ED prefix
- {
- case 0xED:
- pc++;
- s_time += ed_dd_timing [data] >> 4;
- switch ( data )
- {
- {
- blargg_ulong temp;
- case 0x72: // SBC HL,SP
- case 0x7A: // ADC HL,SP
- temp = sp;
- if ( 0 )
- case 0x42: // SBC HL,BC
- case 0x52: // SBC HL,DE
- case 0x62: // SBC HL,HL
- case 0x4A: // ADC HL,BC
- case 0x5A: // ADC HL,DE
- case 0x6A: // ADC HL,HL
- temp = R16( data >> 3 & 6, 1, 0 );
- blargg_ulong sum = temp + (flags & C01);
- flags = ~data >> 2 & N02;
- if ( flags )
- sum = -sum;
- sum += rp.hl;
- temp ^= rp.hl;
- temp ^= sum;
- flags |=(sum >> 16 & C01) |
- (temp >> 8 & H10) |
- (sum >> 8 & (S80 | F20 | F08)) |
- ((temp - -0x8000) >> 14 & V04);
- rp.hl = sum;
- if ( (uint16_t) sum )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
- CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
- int temp = IN( rp.bc );
- R8( data >> 3, 8 ) = temp;
- flags = (flags & C01) | SZ28P( temp );
- goto loop;
- }
-
- case 0x71: // OUT (C),0
- rg.flags = 0;
- CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
- OUT( rp.bc, R8( data >> 3, 8 ) );
- goto loop;
-
- {
- unsigned temp;
- case 0x73: // LD (ADDR),SP
- temp = sp;
- if ( 0 )
- case 0x43: // LD (ADDR),BC
- case 0x53: // LD (ADDR),DE
- temp = R16( data, 4, 0x43 );
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, temp );
- goto loop;
- }
-
- case 0x4B: // LD BC,(ADDR)
- case 0x5B:{// LD DE,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- R16( data, 4, 0x4B ) = READ_WORD( addr );
- goto loop;
- }
-
- case 0x7B:{// LD SP,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- sp = READ_WORD( addr );
- goto loop;
- }
-
- case 0x67:{// RRD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
- temp = (rg.a & 0xF0) | (temp & 0x0F);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- case 0x6F:{// RLD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
- temp = (rg.a & 0xF0) | (temp >> 4);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
- opcode = 0x10; // flag to do SBC instead of ADC
- flags &= ~C01;
- data = rg.a;
- rg.a = 0;
- goto adc_data;
-
- {
- int inc;
- case 0xA9: // CPD
- case 0xB9: // CPDR
- inc = -1;
- if ( 0 )
- case 0xA1: // CPI
- case 0xB1: // CPIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int result = rg.a - temp;
- flags = (flags & C01) | N02 |
- ((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
- if ( !(uint8_t) result ) flags |= Z40;
- result -= (flags & H10) >> 4;
- flags |= result & F08;
- flags |= result << 4 & F20;
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( flags & Z40 || data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xA8: // LDD
- case 0xB8: // LDDR
- inc = -1;
- if ( 0 )
- case 0xA0: // LDI
- case 0xB0: // LDIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- addr = rp.de;
- rp.de = addr + inc;
- WRITE( addr, temp );
-
- temp += rg.a;
- flags = (flags & (S80 | Z40 | C01)) |
- (temp & F08) | (temp << 4 & F20);
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xAB: // OUTD
- case 0xBB: // OTDR
- inc = -1;
- if ( 0 )
- case 0xA3: // OUTI
- case 0xB3: // OTIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- OUT( rp.bc, temp );
- goto loop;
- }
-
- {
- int inc;
- case 0xAA: // IND
- case 0xBA: // INDR
- inc = -1;
- if ( 0 )
- case 0xA2: // INI
- case 0xB2: // INIR
- inc = +1;
-
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
-
- int temp = IN( rp.bc );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- WRITE( addr, temp );
- goto loop;
- }
-
- case 0x47: // LD I,A
- r.i = rg.a;
- goto loop;
-
- case 0x4F: // LD R,A
- SET_R( rg.a );
- dprintf( "LD R,A not supported\n" );
- warning = true;
- goto loop;
-
- case 0x57: // LD A,I
- rg.a = r.i;
- goto ld_ai_common;
-
- case 0x5F: // LD A,R
- rg.a = GET_R();
- dprintf( "LD A,R not supported\n" );
- warning = true;
- ld_ai_common:
- flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
- goto loop;
-
- CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
- r.iff1 = r.iff2;
- goto ret_taken;
-
- case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
- r.im = 0;
- goto loop;
-
- case 0x56: case 0x76: // IM 1
- r.im = 1;
- goto loop;
-
- case 0x5E: case 0x7E: // IM 2
- r.im = 2;
- goto loop;
-
- default:
- dprintf( "Opcode $ED $%02X not supported\n", data );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// DD/FD prefix
- {
- fuint16 ixy;
- case 0xDD:
- ixy = ix;
- goto ix_prefix;
- case 0xFD:
- ixy = iy;
- ix_prefix:
- pc++;
- unsigned data2 = READ_PROG( pc );
- s_time += ed_dd_timing [data] & 0x0F;
- switch ( data )
- {
- // TODO: more efficient way of avoid negative address
- // TODO: avoid using this as argument to READ() since it is evaluated twice
- #define IXY_DISP( ixy, disp ) uint16_t ((ixy) + (disp))
-
- #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
- // ADD/ADC/SUB/SBC
-
- case 0x96: // SUB (IXY+disp)
- case 0x86: // ADD (IXY+disp)
- flags &= ~C01;
- case 0x9E: // SBC (IXY+disp)
- case 0x8E: // ADC (IXY+disp)
- pc++;
- opcode = data;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto adc_data;
-
- case 0x94: // SUB HXY
- case 0x84: // ADD HXY
- flags &= ~C01;
- case 0x9C: // SBC HXY
- case 0x8C: // ADC HXY
- opcode = data;
- data = ixy >> 8;
- goto adc_data;
-
- case 0x95: // SUB LXY
- case 0x85: // ADD LXY
- flags &= ~C01;
- case 0x9D: // SBC LXY
- case 0x8D: // ADC LXY
- opcode = data;
- data = (uint8_t) ixy;
- goto adc_data;
-
- {
- unsigned temp;
- case 0x39: // ADD IXY,SP
- temp = sp;
- goto add_ixy_data;
-
- case 0x29: // ADD IXY,HL
- temp = ixy;
- goto add_ixy_data;
-
- case 0x09: // ADD IXY,BC
- case 0x19: // ADD IXY,DE
- temp = R16( data, 4, 0x09 );
- add_ixy_data: {
- blargg_ulong sum = ixy + temp;
- temp ^= ixy;
- ixy = (uint16_t) sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((temp ^ sum) >> 8 & H10);
- goto set_ixy;
- }
- }
-
- // AND
- case 0xA6: // AND (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto and_data;
-
- case 0xA4: // AND HXY
- data = ixy >> 8;
- goto and_data;
-
- case 0xA5: // AND LXY
- data = (uint8_t) ixy;
- goto and_data;
-
- // OR
- case 0xB6: // OR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto or_data;
-
- case 0xB4: // OR HXY
- data = ixy >> 8;
- goto or_data;
-
- case 0xB5: // OR LXY
- data = (uint8_t) ixy;
- goto or_data;
-
- // XOR
- case 0xAE: // XOR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto xor_data;
-
- case 0xAC: // XOR HXY
- data = ixy >> 8;
- goto xor_data;
-
- case 0xAD: // XOR LXY
- data = (uint8_t) ixy;
- goto xor_data;
-
- // CP
- case 0xBE: // CP (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto cp_data;
-
- case 0xBC: // CP HXY
- data = ixy >> 8;
- goto cp_data;
-
- case 0xBD: // CP LXY
- data = (uint8_t) ixy;
- goto cp_data;
-
- // LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
- data = R8( data, 0x70 );
- if ( 0 )
- case 0x36: // LD (IXY+disp),imm
- pc++, data = READ_PROG( pc );
- pc++;
- WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
- goto loop;
-
- CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
- R8( data >> 3, 8 ) = ixy >> 8;
- goto loop;
-
- case 0x64: // LD HXY,HXY
- case 0x6D: // LD LXY,LXY
- goto loop;
-
- CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
- R8( data >> 3, 8 ) = ixy;
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
- pc++;
- R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto loop;
-
- case 0x26: // LD HXY,imm
- pc++;
- goto ld_hxy_data;
-
- case 0x65: // LD HXY,LXY
- data2 = (uint8_t) ixy;
- goto ld_hxy_data;
-
- CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
- data2 = R8( data, 0x60 );
- ld_hxy_data:
- ixy = (uint8_t) ixy | (data2 << 8);
- goto set_ixy;
-
- case 0x2E: // LD LXY,imm
- pc++;
- goto ld_lxy_data;
-
- case 0x6C: // LD LXY,HXY
- data2 = ixy >> 8;
- goto ld_lxy_data;
-
- CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
- data2 = R8( data, 0x68 );
- ld_lxy_data:
- ixy = (ixy & 0xFF00) | data2;
- set_ixy:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto loop;
- }
- iy = ixy;
- goto loop;
-
- case 0xF9: // LD SP,IXY
- sp = ixy;
- goto loop;
-
- case 0x22:{// LD (ADDR),IXY
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, ixy );
- goto loop;
- }
-
- case 0x21: // LD IXY,imm
- ixy = GET_ADDR();
- pc += 2;
- goto set_ixy;
-
- case 0x2A:{// LD IXY,(addr)
- fuint16 addr = GET_ADDR();
- ixy = READ_WORD( addr );
- pc += 2;
- goto set_ixy;
- }
-
- // DD/FD CB prefix
- case 0xCB: {
- data = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data2 = READ_PROG( pc );
- pc++;
- switch ( data2 )
- {
- case 0x06: goto rlc_data_addr; // RLC (IXY)
- case 0x16: goto rl_data_addr; // RL (IXY)
- case 0x26: goto sla_data_addr; // SLA (IXY)
- case 0x36: goto sll_data_addr; // SLL (IXY)
- case 0x0E: goto rrc_data_addr; // RRC (IXY)
- case 0x1E: goto rr_data_addr; // RR (IXY)
- case 0x2E: goto sra_data_addr; // SRA (IXY)
- case 0x3E: goto srl_data_addr; // SRL (IXY)
-
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
- fuint8 temp = READ( data );
- int masked = temp & 1 << (data2 >> 3 & 7);
- flags = (flags & C01) | H10 |
- (masked & S80) |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
- int temp = READ( data );
- int bit = 1 << (data2 >> 3 & 7);
- temp |= bit; // SET
- if ( !(data2 & 0x40) )
- temp ^= bit; // RES
- WRITE( data, temp );
- goto loop;
- }
-
- default:
- dprintf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
- // INC/DEC
- case 0x23: // INC IXY
- ixy = uint16_t (ixy + 1);
- goto set_ixy;
-
- case 0x2B: // DEC IXY
- ixy = uint16_t (ixy - 1);
- goto set_ixy;
-
- case 0x34: // INC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) + 1;
- WRITE( ixy, data );
- goto inc_set_flags;
-
- case 0x35: // DEC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) - 1;
- WRITE( ixy, data );
- goto dec_set_flags;
-
- case 0x24: // INC HXY
- ixy = uint16_t (ixy + 0x100);
- data = ixy >> 8;
- goto inc_xy_common;
-
- case 0x2C: // INC LXY
- data = uint8_t (ixy + 1);
- ixy = (ixy & 0xFF00) | data;
- inc_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto inc_set_flags;
- }
- iy = ixy;
- goto inc_set_flags;
-
- case 0x25: // DEC HXY
- ixy = uint16_t (ixy - 0x100);
- data = ixy >> 8;
- goto dec_xy_common;
-
- case 0x2D: // DEC LXY
- data = uint8_t (ixy - 1);
- ixy = (ixy & 0xFF00) | data;
- dec_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto dec_set_flags;
- }
- iy = ixy;
- goto dec_set_flags;
-
- // PUSH/POP
- case 0xE5: // PUSH IXY
- data = ixy;
- goto push_data;
-
- case 0xE1:{// POP IXY
- ixy = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto set_ixy;
- }
-
- // Misc
-
- case 0xE9: // JP (IXY)
- pc = ixy;
- goto loop;
-
- case 0xE3:{// EX (SP),IXY
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, ixy );
- ixy = temp;
- goto set_ixy;
- }
-
- default:
- dprintf( "Unnecessary DD/FD prefix encountered\n" );
- warning = true;
- pc--;
- goto loop;
- }
- assert( false );
- }
-
- }
- dprintf( "Unhandled main opcode: $%02X\n", opcode );
- assert( false );
-
-hit_idle_addr:
- s_time -= 11;
- goto out_of_time;
-halt:
- s_time &= 3; // increment by multiple of 4
-out_of_time:
- pc--;
-
- s.time = s_time;
- rg.flags = flags;
- r.ix = ix;
- r.iy = iy;
- r.sp = sp;
- r.pc = pc;
- this->r.b = rg;
- this->state_ = s;
- this->state = &this->state_;
-
- return warning;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.h
deleted file mode 100644
index 6297d100..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Cpu.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Z80 CPU emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef KSS_CPU_H
-#define KSS_CPU_H
-
-#include "blargg_endian.h"
-
-typedef blargg_long cpu_time_t;
-
-// must be defined by caller
-void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data );
-int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr );
-void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data );
-
-class Kss_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers and map all pages to unmapped
- void reset( void* unmapped_write, void const* unmapped_read );
-
- // Map memory. Start and size must be multiple of page_size.
- enum { page_size = 0x2000 };
- void map_mem( unsigned addr, blargg_ulong size, void* write, void const* read );
-
- // Map address to page
- uint8_t* write( unsigned addr );
- uint8_t const* read( unsigned addr );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( cpu_time_t end_time );
-
- // Time of beginning of next instruction
- cpu_time_t time() const { return state->time + state->base; }
-
- // Alter current time. Not supported during run() call.
- void set_time( cpu_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- typedef BOOST::uint16_t uint16_t;
-
- #if BLARGG_BIG_ENDIAN
- struct regs_t { uint8_t b, c, d, e, h, l, flags, a; };
- #else
- struct regs_t { uint8_t c, b, e, d, l, h, a, flags; };
- #endif
- BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
-
- struct pairs_t { uint16_t bc, de, hl, fa; };
-
- // Registers are not updated until run() returns
- struct registers_t {
- uint16_t pc;
- uint16_t sp;
- uint16_t ix;
- uint16_t iy;
- union {
- regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
- pairs_t w; // w.bc, w.de, w.hl. w.fa
- };
- union {
- regs_t b;
- pairs_t w;
- } alt;
- uint8_t iff1;
- uint8_t iff2;
- uint8_t r;
- uint8_t i;
- uint8_t im;
- };
- //registers_t r; (below for efficiency)
-
- enum { idle_addr = 0xFFFF };
-
- // can read this far past end of a page
- enum { cpu_padding = 0x100 };
-
-public:
- Kss_Cpu();
- enum { page_shift = 13 };
- enum { page_count = 0x10000 >> page_shift };
-private:
- uint8_t szpc [0x200];
- cpu_time_t end_time_;
- struct state_t {
- uint8_t const* read [page_count + 1];
- uint8_t * write [page_count + 1];
- cpu_time_t base;
- cpu_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- void set_end_time( cpu_time_t t );
- void set_page( int i, void* write, void const* read );
-public:
- registers_t r;
-};
-
-#if BLARGG_NONPORTABLE
- #define KSS_CPU_PAGE_OFFSET( addr ) (addr)
-#else
- #define KSS_CPU_PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline BOOST::uint8_t* Kss_Cpu::write( unsigned addr )
-{
- return state->write [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr );
-}
-
-inline BOOST::uint8_t const* Kss_Cpu::read( unsigned addr )
-{
- return state->read [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr );
-}
-
-inline void Kss_Cpu::set_end_time( cpu_time_t t )
-{
- cpu_time_t delta = state->base - t;
- state->base = t;
- state->time += delta;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.cpp
deleted file mode 100644
index 1b26ef0b..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Kss_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const clock_rate = 3579545;
-int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count;
-
-Kss_Emu::Kss_Emu()
-{
- sn = 0;
- set_type( gme_kss_type );
- set_silence_lookahead( 6 );
- static const char* const names [osc_count] = {
- "Square 1", "Square 2", "Square 3",
- "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5"
- };
- set_voice_names( names );
-
- static int const types [osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2,
- wave_type | 3, wave_type | 4, wave_type | 5, wave_type | 6, wave_type | 7
- };
- set_voice_types( types );
-
- memset( unmapped_read, 0xFF, sizeof unmapped_read );
-}
-
-Kss_Emu::~Kss_Emu() { unload(); }
-
-void Kss_Emu::unload()
-{
- delete sn;
- sn = 0;
- Classic_Emu::unload();
-}
-
-// Track info
-
-static void copy_kss_fields( Kss_Emu::header_t const& h, track_info_t* out )
-{
- const char* system = "MSX";
- if ( h.device_flags & 0x02 )
- {
- system = "Sega Master System";
- if ( h.device_flags & 0x04 )
- system = "Game Gear";
- }
- Gme_File::copy_field_( out->system, system );
-}
-
-blargg_err_t Kss_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_kss_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_kss_header( void const* header )
-{
- if ( memcmp( header, "KSCC", 4 ) && memcmp( header, "KSSX", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Kss_File : Gme_Info_
-{
- Kss_Emu::header_t header_;
-
- Kss_File() { set_type( gme_kss_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &header_, Kss_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- return check_kss_header( &header_ );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_kss_fields( header_, out );
- return 0;
- }
-};
-
-static Music_Emu* new_kss_emu () { return BLARGG_NEW Kss_Emu ; }
-static Music_Emu* new_kss_file() { return BLARGG_NEW Kss_File; }
-
-gme_type_t_ const gme_kss_type [1] = { "MSX", 256, &new_kss_emu, &new_kss_file, "KSS", 0x03 };
-
-// Setup
-
-void Kss_Emu::update_gain()
-{
- double g = gain() * 1.4;
- if ( scc_accessed )
- g *= 1.5;
- ay.volume( g );
- scc.volume( g );
- if ( sn )
- sn->volume( g );
-}
-
-blargg_err_t Kss_Emu::load_( Data_Reader& in )
-{
- memset( &header_, 0, sizeof header_ );
- assert( offsetof (header_t,device_flags) == header_size - 1 );
- assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1 );
- RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) );
-
- RETURN_ERR( check_kss_header( header_.tag ) );
-
- if ( header_.tag [3] == 'C' )
- {
- if ( header_.extra_header )
- {
- header_.extra_header = 0;
- set_warning( "Unknown data in header" );
- }
- if ( header_.device_flags & ~0x0F )
- {
- header_.device_flags &= 0x0F;
- set_warning( "Unknown data in header" );
- }
- }
- else
- {
- ext_header_t& ext = header_;
- memcpy( &ext, rom.begin(), min( (int) ext_header_size, (int) header_.extra_header ) );
- if ( header_.extra_header > 0x10 )
- set_warning( "Unknown data in header" );
- }
-
- if ( header_.device_flags & 0x09 )
- set_warning( "FM sound not supported" );
-
- scc_enabled = 0xC000;
- if ( header_.device_flags & 0x04 )
- scc_enabled = 0;
-
- if ( header_.device_flags & 0x02 && !sn )
- CHECK_ALLOC( sn = BLARGG_NEW( Sms_Apu ) );
-
- set_voice_count( osc_count );
-
- return setup_buffer( ::clock_rate );
-}
-
-void Kss_Emu::update_eq( blip_eq_t const& eq )
-{
- ay.treble_eq( eq );
- scc.treble_eq( eq );
- if ( sn )
- sn->treble_eq( eq );
-}
-
-void Kss_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- int i2 = i - ay.osc_count;
- if ( i2 >= 0 )
- scc.osc_output( i2, center );
- else
- ay.osc_output( i, center );
- if ( sn && i < sn->osc_count )
- sn->osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Kss_Emu::set_tempo_( double t )
-{
- blip_time_t period =
- (header_.device_flags & 0x40 ? ::clock_rate / 50 : ::clock_rate / 60);
- play_period = blip_time_t (period / t);
-}
-
-blargg_err_t Kss_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0xC9, 0x4000 );
- memset( ram + 0x4000, 0, sizeof ram - 0x4000 );
-
- // copy driver code to lo RAM
- static byte const bios [] = {
- 0xD3, 0xA0, 0xF5, 0x7B, 0xD3, 0xA1, 0xF1, 0xC9, // $0001: WRTPSG
- 0xD3, 0xA0, 0xDB, 0xA2, 0xC9 // $0009: RDPSG
- };
- static byte const vectors [] = {
- 0xC3, 0x01, 0x00, // $0093: WRTPSG vector
- 0xC3, 0x09, 0x00, // $0096: RDPSG vector
- };
- memcpy( ram + 0x01, bios, sizeof bios );
- memcpy( ram + 0x93, vectors, sizeof vectors );
-
- // copy non-banked data into RAM
- unsigned load_addr = get_le16( header_.load_addr );
- long orig_load_size = get_le16( header_.load_size );
- long load_size = min( orig_load_size, rom.file_size() );
- load_size = min( load_size, long (mem_size - load_addr) );
- if ( load_size != orig_load_size )
- set_warning( "Excessive data size" );
- memcpy( ram + load_addr, rom.begin() + header_.extra_header, load_size );
-
- rom.set_addr( -load_size - header_.extra_header );
-
- // check available bank data
- blargg_long const bank_size = this->bank_size();
- int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size;
- bank_count = header_.bank_mode & 0x7F;
- if ( bank_count > max_banks )
- {
- bank_count = max_banks;
- set_warning( "Bank data missing" );
- }
- //dprintf( "load_size : $%X\n", load_size );
- //dprintf( "bank_size : $%X\n", bank_size );
- //dprintf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
-
- ram [idle_addr] = 0xFF;
- cpu::reset( unmapped_write, unmapped_read );
- cpu::map_mem( 0, mem_size, ram, ram );
-
- ay.reset();
- scc.reset();
- if ( sn )
- sn->reset();
- r.sp = 0xF380;
- ram [--r.sp] = idle_addr >> 8;
- ram [--r.sp] = idle_addr & 0xFF;
- r.b.a = track;
- r.pc = get_le16( header_.init_addr );
- next_play = play_period;
- scc_accessed = false;
- gain_updated = false;
- update_gain();
- ay_latch = 0;
-
- return 0;
-}
-
-void Kss_Emu::set_bank( int logical, int physical )
-{
- unsigned const bank_size = this->bank_size();
-
- unsigned addr = 0x8000;
- if ( logical && bank_size == 8 * 1024 )
- addr = 0xA000;
-
- physical -= header_.first_bank;
- if ( (unsigned) physical >= (unsigned) bank_count )
- {
- byte* data = ram + addr;
- cpu::map_mem( addr, bank_size, data, data );
- }
- else
- {
- long phys = physical * (blargg_long) bank_size;
- for ( unsigned offset = 0; offset < bank_size; offset += page_size )
- cpu::map_mem( addr + offset, page_size,
- unmapped_write, rom.at_addr( phys + offset ) );
- }
-}
-
-void Kss_Emu::cpu_write( unsigned addr, int data )
-{
- data &= 0xFF;
- switch ( addr )
- {
- case 0x9000:
- set_bank( 0, data );
- return;
-
- case 0xB000:
- set_bank( 1, data );
- return;
- }
-
- int scc_addr = (addr & 0xDFFF) ^ 0x9800;
- if ( scc_addr < scc.reg_count )
- {
- scc_accessed = true;
- scc.write( time(), scc_addr, data );
- return;
- }
-
- dprintf( "LD ($%04X),$%02X\n", addr, data );
-}
-
-void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
-{
- *cpu->write( addr ) = data;
- if ( (addr & STATIC_CAST(Kss_Emu&,*cpu).scc_enabled) == 0x8000 )
- STATIC_CAST(Kss_Emu&,*cpu).cpu_write( addr, data );
-}
-
-void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
- data &= 0xFF;
- Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
- switch ( addr & 0xFF )
- {
- case 0xA0:
- emu.ay_latch = data & 0x0F;
- return;
-
- case 0xA1:
- GME_APU_HOOK( &emu, emu.ay_latch, data );
- emu.ay.write( time, emu.ay_latch, data );
- return;
-
- case 0x06:
- if ( emu.sn && (emu.header_.device_flags & 0x04) )
- {
- emu.sn->write_ggstereo( time, data );
- return;
- }
- break;
-
- case 0x7E:
- case 0x7F:
- if ( emu.sn )
- {
- GME_APU_HOOK( &emu, 16, data );
- emu.sn->write_data( time, data );
- return;
- }
- break;
-
- case 0xFE:
- emu.set_bank( 0, data );
- return;
-
- #ifndef NDEBUG
- case 0xF1: // FM data
- if ( data )
- break; // trap non-zero data
- case 0xF0: // FM addr
- case 0xA8: // PPI
- return;
- #endif
- }
-
- dprintf( "OUT $%04X,$%02X\n", addr, data );
-}
-
-int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
-{
- //Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
- //switch ( addr & 0xFF )
- //{
- //}
-
- dprintf( "IN $%04X\n", addr );
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Kss_Emu::run_clocks( blip_time_t& duration, int )
-{
- while ( time() < duration )
- {
- blip_time_t end = min( duration, next_play );
- cpu::run( min( duration, next_play ) );
- if ( r.pc == idle_addr )
- set_time( end );
-
- if ( time() >= next_play )
- {
- next_play += play_period;
- if ( r.pc == idle_addr )
- {
- if ( !gain_updated )
- {
- gain_updated = true;
- if ( scc_accessed )
- update_gain();
- }
-
- ram [--r.sp] = idle_addr >> 8;
- ram [--r.sp] = idle_addr & 0xFF;
- r.pc = get_le16( header_.play_addr );
- GME_FRAME_HOOK( this );
- }
- }
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- adjust_time( -duration );
- ay.end_frame( duration );
- scc.end_frame( duration );
- if ( sn )
- sn->end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.h
deleted file mode 100644
index 4d8463ab..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Emu.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// MSX computer KSS music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef KSS_EMU_H
-#define KSS_EMU_H
-
-#include "Classic_Emu.h"
-#include "Kss_Scc_Apu.h"
-#include "Kss_Cpu.h"
-#include "Sms_Apu.h"
-#include "Ay_Apu.h"
-
-class Kss_Emu : private Kss_Cpu, public Classic_Emu {
- typedef Kss_Cpu cpu;
-public:
- // KSS file header
- enum { header_size = 0x10 };
- struct header_t
- {
- byte tag [4];
- byte load_addr [2];
- byte load_size [2];
- byte init_addr [2];
- byte play_addr [2];
- byte first_bank;
- byte bank_mode;
- byte extra_header;
- byte device_flags;
- };
-
- enum { ext_header_size = 0x10 };
- struct ext_header_t
- {
- byte data_size [4];
- byte unused [4];
- byte first_track [2];
- byte last_tack [2];
- byte psg_vol;
- byte scc_vol;
- byte msx_music_vol;
- byte msx_audio_vol;
- };
-
- struct composite_header_t : header_t, ext_header_t { };
-
- // Header for currently loaded file
- composite_header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_kss_type; }
-public:
- Kss_Emu();
- ~Kss_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-private:
- Rom_Data<page_size> rom;
- composite_header_t header_;
-
- bool scc_accessed;
- bool gain_updated;
- void update_gain();
-
- unsigned scc_enabled; // 0 or 0xC000
- byte const* bank_data;
- int bank_count;
- void set_bank( int logical, int physical );
- blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
-
- blip_time_t play_period;
- blip_time_t next_play;
- int ay_latch;
-
- friend void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data );
- friend int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr );
- void cpu_write( unsigned addr, int data );
- friend void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data );
-
- // large items
- enum { mem_size = 0x10000 };
- byte ram [mem_size + cpu_padding];
-
- Ay_Apu ay;
- Scc_Apu scc;
- Sms_Apu* sn;
- byte unmapped_read [0x100];
- byte unmapped_write [page_size];
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.cpp
deleted file mode 100644
index 1660ac3d..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Kss_Scc_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const wave_size = 0x20;
-
-void Scc_Apu::run_until( blip_time_t end_time )
-{
- for ( int index = 0; index < osc_count; index++ )
- {
- osc_t& osc = oscs [index];
-
- Blip_Buffer* const output = osc.output;
- if ( !output )
- continue;
- output->set_modified();
-
- blip_time_t period = (regs [0x80 + index * 2 + 1] & 0x0F) * 0x100 +
- regs [0x80 + index * 2] + 1;
- int volume = 0;
- if ( regs [0x8F] & (1 << index) )
- {
- blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() +
- inaudible_freq * 32) / (inaudible_freq * 16);
- if ( period > inaudible_period )
- volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15);
- }
-
- BOOST::int8_t const* wave = (BOOST::int8_t*) regs + index * wave_size;
- if ( index == osc_count - 1 )
- wave -= wave_size; // last two oscs share wave
- {
- int amp = wave [osc.phase] * volume;
- int delta = amp - osc.last_amp;
- if ( delta )
- {
- osc.last_amp = amp;
- synth.offset( last_time, delta, output );
- }
- }
-
- blip_time_t time = last_time + osc.delay;
- if ( time < end_time )
- {
- if ( !volume )
- {
- // maintain phase
- blargg_long count = (end_time - time + period - 1) / period;
- osc.phase = (osc.phase + count) & (wave_size - 1);
- time += count * period;
- }
- else
- {
-
- int phase = osc.phase;
- int last_wave = wave [phase];
- phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop
-
- do
- {
- int amp = wave [phase];
- phase = (phase + 1) & (wave_size - 1);
- int delta = amp - last_wave;
- if ( delta )
- {
- last_wave = amp;
- synth.offset( time, delta * volume, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- osc.phase = phase = (phase - 1) & (wave_size - 1); // undo pre-advance
- osc.last_amp = wave [phase] * volume;
- }
- }
- osc.delay = time - end_time;
- }
- last_time = end_time;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.h
deleted file mode 100644
index 03a6a108..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Kss_Scc_Apu.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Konami SCC sound chip emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef KSS_SCC_APU_H
-#define KSS_SCC_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-#include <string.h>
-
-class Scc_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Reset sound chip
- void reset();
-
- // Write to register at specified time
- enum { reg_count = 0x90 };
- void write( blip_time_t time, int reg, int data );
-
- // Run sound to specified time, end current time frame, then start a new
- // time frame at time 0. Time frames have no effect on emulation and each
- // can be whatever length is convenient.
- void end_frame( blip_time_t length );
-
-// Additional features
-
- // Set sound output of specific oscillator to buffer, where index is
- // 0 to 4. If buffer is NULL, the specified oscillator is muted.
- enum { osc_count = 5 };
- void osc_output( int index, Blip_Buffer* );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see documentation)
- void treble_eq( blip_eq_t const& );
-
-public:
- Scc_Apu();
-private:
- enum { amp_range = 0x8000 };
- struct osc_t
- {
- int delay;
- int phase;
- int last_amp;
- Blip_Buffer* output;
- };
- osc_t oscs [osc_count];
- blip_time_t last_time;
- unsigned char regs [reg_count];
- Blip_Synth<blip_med_quality,1> synth;
-
- void run_until( blip_time_t );
-};
-
-inline void Scc_Apu::volume( double v ) { synth.volume( 0.43 / osc_count / amp_range * v ); }
-
-inline void Scc_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
-
-inline void Scc_Apu::osc_output( int index, Blip_Buffer* b )
-{
- assert( (unsigned) index < osc_count );
- oscs [index].output = b;
-}
-
-inline void Scc_Apu::write( blip_time_t time, int addr, int data )
-{
- assert( (unsigned) addr < reg_count );
- run_until( time );
- regs [addr] = data;
-}
-
-inline void Scc_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
- last_time -= end_time;
- assert( last_time >= 0 );
-}
-
-inline void Scc_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- oscs [i].output = buf;
-}
-
-inline Scc_Apu::Scc_Apu()
-{
- output( 0 );
-}
-
-inline void Scc_Apu::reset()
-{
- last_time = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- memset( &oscs [i], 0, offsetof (osc_t,output) );
-
- memset( regs, 0, sizeof regs );
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.cpp
deleted file mode 100644
index 0a1475db..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "M3u_Playlist.h"
-#include "Music_Emu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// gme functions defined here to avoid linking in m3u code unless it's used
-
-blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
-{
- require( raw_track_count_ ); // file must be loaded first
-
- if ( !err )
- {
- if ( playlist.size() )
- track_count_ = playlist.size();
-
- int line = playlist.first_error();
- if ( line )
- {
- // avoid using bloated printf()
- char* out = &playlist_warning [sizeof playlist_warning];
- *--out = 0;
- do {
- *--out = line % 10 + '0';
- } while ( (line /= 10) > 0 );
-
- static const char str [] = "Problem in m3u at line ";
- out -= sizeof str - 1;
- memcpy( out, str, sizeof str - 1 );
- set_warning( out );
- }
- }
- return err;
-}
-
-blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist.load( path ) ); }
-
-blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
-
-gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
-
-gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
-{
- Mem_File_Reader in( data, size );
- return me->load_m3u( in );
-}
-
-
-
-static char* skip_white( char* in )
-{
- while ( *in == ' ' )
- in++;
- return in;
-}
-
-inline unsigned from_dec( unsigned n ) { return n - '0'; }
-
-static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
-{
- entry.file = in;
- entry.type = "";
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in filename
- {
- char* p = skip_white( in );
- if ( *p == '$' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
- {
- entry.type = ++in;
- while ( (c = *in) != 0 && c != ',' )
- in++;
- if ( c == ',' )
- {
- *in++ = 0; // terminate type
- in = skip_white( in );
- }
- break;
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static char* next_field( char* in, int* result )
-{
- while ( 1 )
- {
- in = skip_white( in );
-
- if ( !*in )
- break;
-
- if ( *in == ',' )
- {
- in++;
- break;
- }
-
- *result = 1;
- in++;
- }
- return skip_white( in );
-}
-
-static char* parse_int_( char* in, int* out )
-{
- int n = 0;
- while ( 1 )
- {
- unsigned d = from_dec( *in );
- if ( d > 9 )
- break;
- in++;
- n = n * 10 + d;
- *out = n;
- }
- return in;
-}
-
-static char* parse_int( char* in, int* out, int* result )
-{
- return next_field( parse_int_( in, out ), result );
-}
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
-{
- if ( *in == '$' )
- {
- in++;
- int n = 0;
- while ( 1 )
- {
- int h = from_hex_char( *in );
- if ( h > 15 )
- break;
- in++;
- n = n * 16 + h;
- entry.track = n;
- }
- }
- else
- {
- in = parse_int_( in, &entry.track );
- if ( entry.track >= 0 )
- entry.decimal_track = 1;
- }
- return next_field( in, result );
-}
-
-static char* parse_time_( char* in, int* out )
-{
- *out = -1;
- int n = -1;
- in = parse_int_( in, &n );
- if ( n >= 0 )
- {
- *out = n;
- if ( *in == ':' )
- {
- n = -1;
- in = parse_int_( in + 1, &n );
- if ( n >= 0 )
- *out = *out * 60 + n;
- }
- }
- return in;
-}
-
-static char* parse_time( char* in, int* out, int* result )
-{
- return next_field( parse_time_( in, out ), result );
-}
-
-static char* parse_name( char* in )
-{
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in string
- {
- char* p = skip_white( in );
- if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static int parse_line( char* in, M3u_Playlist::entry_t& entry )
-{
- int result = 0;
-
- // file
- entry.file = in;
- entry.type = "";
- in = parse_filename( in, entry );
-
- // track
- entry.track = -1;
- entry.decimal_track = 0;
- in = parse_track( in, entry, &result );
-
- // name
- entry.name = in;
- in = parse_name( in );
-
- // time
- entry.length = -1;
- in = parse_time( in, &entry.length, &result );
-
- // loop
- entry.intro = -1;
- entry.loop = -1;
- if ( *in == '-' )
- {
- entry.loop = entry.length;
- in++;
- }
- else
- {
- in = parse_time_( in, &entry.loop );
- if ( entry.loop >= 0 )
- {
- entry.intro = 0;
- if ( *in == '-' ) // trailing '-' means that intro length was specified
- {
- in++;
- entry.intro = entry.loop;
- entry.loop = entry.length - entry.intro;
- }
- }
- }
- in = next_field( in, &result );
-
- // fade
- entry.fade = -1;
- in = parse_time( in, &entry.fade, &result );
-
- // repeat
- entry.repeat = -1;
- in = parse_int( in, &entry.repeat, &result );
-
- return result;
-}
-
-static void parse_comment( char* in, M3u_Playlist::info_t& info, bool first )
-{
- in = skip_white( in + 1 );
- const char* field = in;
- while ( *in && *in != ':' )
- in++;
-
- if ( *in == ':' )
- {
- const char* text = skip_white( in + 1 );
- if ( *text )
- {
- *in = 0;
- if ( !strcmp( "Composer", field ) ) info.composer = text;
- else if ( !strcmp( "Engineer", field ) ) info.engineer = text;
- else if ( !strcmp( "Ripping" , field ) ) info.ripping = text;
- else if ( !strcmp( "Tagging" , field ) ) info.tagging = text;
- else
- text = 0;
- if ( text )
- return;
- *in = ':';
- }
- }
-
- if ( first )
- info.title = field;
-}
-
-blargg_err_t M3u_Playlist::parse_()
-{
- info_.title = "";
- info_.composer = "";
- info_.engineer = "";
- info_.ripping = "";
- info_.tagging = "";
-
- int const CR = 13;
- int const LF = 10;
-
- data.end() [-1] = LF; // terminate input
-
- first_error_ = 0;
- bool first_comment = true;
- int line = 0;
- int count = 0;
- char* in = data.begin();
- while ( in < data.end() )
- {
- // find end of line and terminate it
- line++;
- char* begin = in;
- while ( *in != CR && *in != LF )
- {
- if ( !*in )
- return "Not an m3u playlist";
- in++;
- }
- if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
- *in++ = 0;
- *in++ = 0;
-
- // parse line
- if ( *begin == '#' )
- {
- parse_comment( begin, info_, first_comment );
- first_comment = false;
- }
- else if ( *begin )
- {
- if ( (int) entries.size() <= count )
- RETURN_ERR( entries.resize( count * 2 + 64 ) );
-
- if ( !parse_line( begin, entries [count] ) )
- count++;
- else if ( !first_error_ )
- first_error_ = line;
- first_comment = false;
- }
- }
- if ( count <= 0 )
- return "Not an m3u playlist";
-
- if ( !(info_.composer [0] | info_.engineer [0] | info_.ripping [0] | info_.tagging [0]) )
- info_.title = "";
-
- return entries.resize( count );
-}
-
-blargg_err_t M3u_Playlist::parse()
-{
- blargg_err_t err = parse_();
- if ( err )
- {
- entries.clear();
- data.clear();
- }
- return err;
-}
-
-blargg_err_t M3u_Playlist::load( Data_Reader& in )
-{
- RETURN_ERR( data.resize( in.remain() + 1 ) );
- RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
- return parse();
-}
-
-blargg_err_t M3u_Playlist::load( const char* path )
-{
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- return load( in );
-}
-
-blargg_err_t M3u_Playlist::load( void const* in, long size )
-{
- RETURN_ERR( data.resize( size + 1 ) );
- memcpy( data.begin(), in, size );
- return parse();
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.h
deleted file mode 100644
index eda0dc89..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/M3u_Playlist.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// M3U playlist file parser, with support for subtrack information
-
-// Game_Music_Emu 0.5.2
-#ifndef M3U_PLAYLIST_H
-#define M3U_PLAYLIST_H
-
-#include "blargg_common.h"
-#include "Data_Reader.h"
-
-class M3u_Playlist {
-public:
- // Load playlist data
- blargg_err_t load( const char* path );
- blargg_err_t load( Data_Reader& in );
- blargg_err_t load( void const* data, long size );
-
- // Line number of first parse error, 0 if no error. Any lines with parse
- // errors are ignored.
- int first_error() const { return first_error_; }
-
- struct info_t
- {
- const char* title;
- const char* composer;
- const char* engineer;
- const char* ripping;
- const char* tagging;
- };
- info_t const& info() const { return info_; }
-
- struct entry_t
- {
- const char* file; // filename without stupid ::TYPE suffix
- const char* type; // if filename has ::TYPE suffix, this will be "TYPE". "" if none.
- const char* name;
- bool decimal_track; // true if track was specified in hex
- // integers are -1 if not present
- int track; // 1-based
- int length; // seconds
- int intro;
- int loop;
- int fade;
- int repeat; // count
- };
- entry_t const& operator [] ( int i ) const { return entries [i]; }
- int size() const { return entries.size(); }
-
- void clear();
-
-private:
- blargg_vector<entry_t> entries;
- blargg_vector<char> data;
- int first_error_;
- info_t info_;
-
- blargg_err_t parse();
- blargg_err_t parse_();
-};
-
-inline void M3u_Playlist::clear()
-{
- first_error_ = 0;
- entries.clear();
- data.clear();
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Makefile.am b/plugins/gme/Game_Music_Emu-0.5.2/gme/Makefile.am
deleted file mode 100644
index d728deea..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Makefile.am
+++ /dev/null
@@ -1,66 +0,0 @@
-noinst_LIBRARIES = libgme.a
-libgme_a_SOURCES = Ay_Apu.cpp Gb_Apu.cpp Hes_Emu.cpp Nes_Fme7_Apu.cpp Sms_Apu.cpp\
-Ay_Cpu.cpp Gb_Cpu.cpp Kss_Cpu.cpp Nes_Namco_Apu.cpp Snes_Spc.cpp\
-Ay_Emu.cpp Gb_Oscs.cpp Kss_Emu.cpp Nes_Oscs.cpp Spc_Cpu.cpp\
-Blip_Buffer.cpp Gbs_Emu.cpp Kss_Scc_Apu.cpp Nes_Vrc6_Apu.cpp Spc_Dsp.cpp\
-Classic_Emu.cpp gme.cpp M3u_Playlist.cpp Nsfe_Emu.cpp Spc_Emu.cpp\
-Data_Reader.cpp Gme_File.cpp Multi_Buffer.cpp Nsf_Emu.cpp Vgm_Emu.cpp\
-Dual_Resampler.cpp Gym_Emu.cpp Music_Emu.cpp Sap_Apu.cpp Vgm_Emu_Impl.cpp\
-Effects_Buffer.cpp Hes_Apu.cpp Nes_Apu.cpp Sap_Cpu.cpp Ym2413_Emu.cpp\
-Fir_Resampler.cpp Hes_Cpu.cpp Nes_Cpu.cpp Sap_Emu.cpp Ym2612_Emu.cpp\
-Ay_Apu.h\
-Ay_Cpu.h\
-Ay_Emu.h\
-blargg_common.h\
-blargg_config.h\
-blargg_endian.h\
-blargg_source.h\
-Blip_Buffer.h\
-Classic_Emu.h\
-Data_Reader.h\
-Dual_Resampler.h\
-Effects_Buffer.h\
-Fir_Resampler.h\
-Gb_Apu.h\
-Gb_Cpu.h\
-gb_cpu_io.h\
-Gb_Oscs.h\
-Gbs_Emu.h\
-Gme_File.h\
-gme.h\
-Gym_Emu.h\
-Hes_Apu.h\
-Hes_Cpu.h\
-hes_cpu_io.h\
-Hes_Emu.h\
-Kss_Cpu.h\
-Kss_Emu.h\
-Kss_Scc_Apu.h\
-M3u_Playlist.h\
-Multi_Buffer.h\
-Music_Emu.h\
-Nes_Apu.h\
-Nes_Cpu.h\
-nes_cpu_io.h\
-Nes_Fme7_Apu.h\
-Nes_Namco_Apu.h\
-Nes_Oscs.h\
-Nes_Vrc6_Apu.h\
-Nsfe_Emu.h\
-Nsf_Emu.h\
-Sap_Apu.h\
-Sap_Cpu.h\
-sap_cpu_io.h\
-Sap_Emu.h\
-Sms_Apu.h\
-Sms_Oscs.h\
-Snes_Spc.h\
-Spc_Cpu.h\
-Spc_Dsp.h\
-Spc_Emu.h\
-Vgm_Emu.h\
-Vgm_Emu_Impl.h\
-Ym2413_Emu.h\
-Ym2612_Emu.h
-
-AM_CPPFLAGS = $(CXXFLAGS) -fPIC
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.cpp
deleted file mode 100644
index ecd8f8ad..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Multi_Buffer.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
- length_ = 0;
- sample_rate_ = 0;
- channels_changed_count_ = 1;
-}
-
-blargg_err_t Multi_Buffer::set_channel_count( int ) { return 0; }
-
-// Silent_Buffer
-
-Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
-{
- // TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
- chan.left = 0;
- chan.center = 0;
- chan.right = 0;
-}
-
-// Mono_Buffer
-
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
- chan.center = &buf;
- chan.left = &buf;
- chan.right = &buf;
-}
-
-Mono_Buffer::~Mono_Buffer() { }
-
-blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
-{
- RETURN_ERR( buf.set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
-}
-
-// Stereo_Buffer
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
- chan.center = &bufs [0];
- chan.left = &bufs [1];
- chan.right = &bufs [2];
-}
-
-Stereo_Buffer::~Stereo_Buffer() { }
-
-blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
-{
- for ( int i = 0; i < buf_count; i++ )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( long rate )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
- for ( unsigned i = 0; i < buf_count; i++ )
- bufs [i].bass_freq( bass );
-}
-
-void Stereo_Buffer::clear()
-{
- stereo_added = 0;
- was_stereo = false;
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t clock_count )
-{
- stereo_added = 0;
- for ( unsigned i = 0; i < buf_count; i++ )
- {
- stereo_added |= bufs [i].clear_modified() << i;
- bufs [i].end_frame( clock_count );
- }
-}
-
-long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
-{
- require( !(count & 1) ); // count must be even
- count = (unsigned) count / 2;
-
- long avail = bufs [0].samples_avail();
- if ( count > avail )
- count = avail;
- if ( count )
- {
- int bufs_used = stereo_added | was_stereo;
- //dprintf( "%X\n", bufs_used );
- if ( bufs_used <= 1 )
- {
- mix_mono( out, count );
- bufs [0].remove_samples( count );
- bufs [1].remove_silence( count );
- bufs [2].remove_silence( count );
- }
- else if ( bufs_used & 1 )
- {
- mix_stereo( out, count );
- bufs [0].remove_samples( count );
- bufs [1].remove_samples( count );
- bufs [2].remove_samples( count );
- }
- else
- {
- mix_stereo_no_center( out, count );
- bufs [0].remove_silence( count );
- bufs [1].remove_samples( count );
- bufs [2].remove_samples( count );
- }
-
- // to do: this might miss opportunities for optimization
- if ( !bufs [0].samples_avail() )
- {
- was_stereo = stereo_added;
- stereo_added = 0;
- }
- }
-
- return count * 2;
-}
-
-void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [1] );
- BLIP_READER_BEGIN( left, bufs [1] );
- BLIP_READER_BEGIN( right, bufs [2] );
- BLIP_READER_BEGIN( center, bufs [0] );
-
- for ( ; count; --count )
- {
- int c = BLIP_READER_READ( center );
- blargg_long l = c + BLIP_READER_READ( left );
- blargg_long r = c + BLIP_READER_READ( right );
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- BLIP_READER_NEXT( center, bass );
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- BLIP_READER_NEXT( left, bass );
- BLIP_READER_NEXT( right, bass );
-
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- BLIP_READER_END( center, bufs [0] );
- BLIP_READER_END( right, bufs [2] );
- BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [1] );
- BLIP_READER_BEGIN( left, bufs [1] );
- BLIP_READER_BEGIN( right, bufs [2] );
-
- for ( ; count; --count )
- {
- blargg_long l = BLIP_READER_READ( left );
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- blargg_long r = BLIP_READER_READ( right );
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- BLIP_READER_NEXT( left, bass );
- BLIP_READER_NEXT( right, bass );
-
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- BLIP_READER_END( right, bufs [2] );
- BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( center, bufs [0] );
-
- for ( ; count; --count )
- {
- blargg_long s = BLIP_READER_READ( center );
- if ( (BOOST::int16_t) s != s )
- s = 0x7FFF - (s >> 24);
-
- BLIP_READER_NEXT( center, bass );
- out [0] = s;
- out [1] = s;
- out += 2;
- }
-
- BLIP_READER_END( center, bufs [0] );
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.h
deleted file mode 100644
index a39cca1a..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Multi_Buffer.h
+++ /dev/null
@@ -1,156 +0,0 @@
-// Multi-channel sound buffer interface, and basic mono and stereo buffers
-
-// Blip_Buffer 0.4.1
-#ifndef MULTI_BUFFER_H
-#define MULTI_BUFFER_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-// Interface to one or more Blip_Buffers mapped to one or more channels
-// consisting of left, center, and right buffers.
-class Multi_Buffer {
-public:
- Multi_Buffer( int samples_per_frame );
- virtual ~Multi_Buffer() { }
-
- // Set the number of channels available
- virtual blargg_err_t set_channel_count( int );
-
- // Get indexed channel, from 0 to channel count - 1
- struct channel_t {
- Blip_Buffer* center;
- Blip_Buffer* left;
- Blip_Buffer* right;
- };
- enum { type_index_mask = 0xFF };
- enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
- virtual channel_t channel( int index, int type ) = 0;
-
- // See Blip_Buffer.h
- virtual blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ) = 0;
- virtual void clock_rate( long ) = 0;
- virtual void bass_freq( int ) = 0;
- virtual void clear() = 0;
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // See Blip_Buffer.h
- virtual void end_frame( blip_time_t ) = 0;
-
- // Number of samples per output frame (1 = mono, 2 = stereo)
- int samples_per_frame() const;
-
- // Count of changes to channel configuration. Incremented whenever
- // a change is made to any of the Blip_Buffers for any channel.
- unsigned channels_changed_count() { return channels_changed_count_; }
-
- // See Blip_Buffer.h
- virtual long read_samples( blip_sample_t*, long ) = 0;
- virtual long samples_avail() const = 0;
-
-public:
- BLARGG_DISABLE_NOTHROW
-protected:
- void channels_changed() { channels_changed_count_++; }
-private:
- // noncopyable
- Multi_Buffer( const Multi_Buffer& );
- Multi_Buffer& operator = ( const Multi_Buffer& );
-
- unsigned channels_changed_count_;
- long sample_rate_;
- int length_;
- int const samples_per_frame_;
-};
-
-// Uses a single buffer and outputs mono samples.
-class Mono_Buffer : public Multi_Buffer {
- Blip_Buffer buf;
- channel_t chan;
-public:
- // Buffer used for all channels
- Blip_Buffer* center() { return &buf; }
-
-public:
- Mono_Buffer();
- ~Mono_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length );
- void clock_rate( long rate ) { buf.clock_rate( rate ); }
- void bass_freq( int freq ) { buf.bass_freq( freq ); }
- void clear() { buf.clear(); }
- long samples_avail() const { return buf.samples_avail(); }
- long read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); }
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t t ) { buf.end_frame( t ); }
-};
-
-// Uses three buffers (one for center) and outputs stereo sample pairs.
-class Stereo_Buffer : public Multi_Buffer {
-public:
-
- // Buffers used for all channels
- Blip_Buffer* center() { return &bufs [0]; }
- Blip_Buffer* left() { return &bufs [1]; }
- Blip_Buffer* right() { return &bufs [2]; }
-
-public:
- Stereo_Buffer();
- ~Stereo_Buffer();
- blargg_err_t set_sample_rate( long, int msec = blip_default_length );
- void clock_rate( long );
- void bass_freq( int );
- void clear();
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t );
-
- long samples_avail() const { return bufs [0].samples_avail() * 2; }
- long read_samples( blip_sample_t*, long );
-
-private:
- enum { buf_count = 3 };
- Blip_Buffer bufs [buf_count];
- channel_t chan;
- int stereo_added;
- int was_stereo;
-
- void mix_stereo_no_center( blip_sample_t*, blargg_long );
- void mix_stereo( blip_sample_t*, blargg_long );
- void mix_mono( blip_sample_t*, blargg_long );
-};
-
-// Silent_Buffer generates no samples, useful where no sound is wanted
-class Silent_Buffer : public Multi_Buffer {
- channel_t chan;
-public:
- Silent_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length )
- {
- return Multi_Buffer::set_sample_rate( rate, msec );
- }
- void clock_rate( long ) { }
- void bass_freq( int ) { }
- void clear() { }
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t ) { }
- long samples_avail() const { return 0; }
- long read_samples( blip_sample_t*, long ) { return 0; }
-};
-
-
-inline blargg_err_t Multi_Buffer::set_sample_rate( long rate, int msec )
-{
- sample_rate_ = rate;
- length_ = msec;
- return 0;
-}
-
-inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; }
-
-inline long Multi_Buffer::sample_rate() const { return sample_rate_; }
-
-inline int Multi_Buffer::length() const { return length_; }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.cpp
deleted file mode 100644
index 31c7233c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const stereo = 2; // number of channels for stereo
-int const silence_max = 6; // seconds
-int const silence_threshold = 0x10;
-long const fade_block_size = 512;
-int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
-
-Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180 };
-
-void Music_Emu::clear_track_vars()
-{
- current_track_ = -1;
- out_time = 0;
- emu_time = 0;
- emu_track_ended_ = true;
- track_ended_ = true;
- fade_start = LONG_MAX / 2 + 1;
- fade_step = 1;
- silence_time = 0;
- silence_count = 0;
- buf_remain = 0;
- warning(); // clear warning
-}
-
-void Music_Emu::unload()
-{
- voice_count_ = 0;
- clear_track_vars();
- Gme_File::unload();
-}
-
-Music_Emu::Music_Emu()
-{
- effects_buffer = 0;
-
- sample_rate_ = 0;
- mute_mask_ = 0;
- tempo_ = 1.0;
- gain_ = 1.0;
-
- // defaults
- max_initial_silence = 2;
- silence_lookahead = 3;
- ignore_silence_ = false;
- equalizer_.treble = -1.0;
- equalizer_.bass = 60;
-
- static const char* const names [] = {
- "Voice 1", "Voice 2", "Voice 3", "Voice 4",
- "Voice 5", "Voice 6", "Voice 7", "Voice 8"
- };
- set_voice_names( names );
- Music_Emu::unload(); // non-virtual
-}
-
-Music_Emu::~Music_Emu() { delete effects_buffer; }
-
-blargg_err_t Music_Emu::set_sample_rate( long rate )
-{
- require( !sample_rate() ); // sample rate can't be changed once set
- RETURN_ERR( set_sample_rate_( rate ) );
- RETURN_ERR( buf.resize( buf_size ) );
- sample_rate_ = rate;
- return 0;
-}
-
-void Music_Emu::pre_load()
-{
- require( sample_rate() ); // set_sample_rate() must be called before loading a file
- Gme_File::pre_load();
-}
-
-void Music_Emu::set_equalizer( equalizer_t const& eq )
-{
- equalizer_ = eq;
- set_equalizer_( eq );
-}
-
-void Music_Emu::mute_voice( int index, bool mute )
-{
- require( (unsigned) index < (unsigned) voice_count() );
- int bit = 1 << index;
- int mask = mute_mask_ | bit;
- if ( !mute )
- mask ^= bit;
- mute_voices( mask );
-}
-
-void Music_Emu::mute_voices( int mask )
-{
- require( sample_rate() ); // sample rate must be set first
- mute_mask_ = mask;
- mute_voices_( mask );
-}
-
-void Music_Emu::set_tempo( double t )
-{
- require( sample_rate() ); // sample rate must be set first
- double const min = 0.02;
- double const max = 4.00;
- if ( t < min ) t = min;
- if ( t > max ) t = max;
- tempo_ = t;
- set_tempo_( t );
-}
-
-void Music_Emu::post_load_()
-{
- set_tempo( tempo_ );
- remute_voices();
-}
-
-blargg_err_t Music_Emu::start_track( int track )
-{
- clear_track_vars();
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- current_track_ = track;
- RETURN_ERR( start_track_( remapped ) );
-
- emu_track_ended_ = false;
- track_ended_ = false;
-
- if ( !ignore_silence_ )
- {
- // play until non-silence or end of track
- for ( long end = max_initial_silence * stereo * sample_rate(); emu_time < end; )
- {
- fill_buf();
- if ( buf_remain | (int) emu_track_ended_ )
- break;
- }
-
- emu_time = buf_remain;
- out_time = 0;
- silence_time = 0;
- silence_count = 0;
- }
- return track_ended() ? warning() : 0;
-}
-
-void Music_Emu::end_track_if_error( blargg_err_t err )
-{
- if ( err )
- {
- emu_track_ended_ = true;
- set_warning( err );
- }
-}
-
-// Tell/Seek
-
-blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
-{
- blargg_long sec = msec / 1000;
- msec -= sec * 1000;
- return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
-}
-
-long Music_Emu::tell() const
-{
- blargg_long rate = sample_rate() * stereo;
- blargg_long sec = out_time / rate;
- return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Music_Emu::seek( long msec )
-{
- blargg_long time = msec_to_samples( msec );
- if ( time < out_time )
- RETURN_ERR( start_track( current_track_ ) );
- return skip( time - out_time );
-}
-
-blargg_err_t Music_Emu::skip( long count )
-{
- require( current_track() >= 0 ); // start_track() must have been called already
- out_time += count;
-
- // remove from silence and buf first
- {
- long n = min( count, silence_count );
- silence_count -= n;
- count -= n;
-
- n = min( count, buf_remain );
- buf_remain -= n;
- count -= n;
- }
-
- if ( count && !emu_track_ended_ )
- {
- emu_time += count;
- end_track_if_error( skip_( count ) );
- }
-
- if ( !(silence_count | buf_remain) ) // caught up to emulator, so update track ended
- track_ended_ |= emu_track_ended_;
-
- return 0;
-}
-
-blargg_err_t Music_Emu::skip_( long count )
-{
- // for long skip, mute sound
- const long threshold = 30000;
- if ( count > threshold )
- {
- int saved_mute = mute_mask_;
- mute_voices( ~0 );
-
- while ( count > threshold / 2 && !emu_track_ended_ )
- {
- RETURN_ERR( play_( buf_size, buf.begin() ) );
- count -= buf_size;
- }
-
- mute_voices( saved_mute );
- }
-
- while ( count && !emu_track_ended_ )
- {
- long n = buf_size;
- if ( n > count )
- n = count;
- count -= n;
- RETURN_ERR( play_( n, buf.begin() ) );
- }
- return 0;
-}
-
-// Fading
-
-void Music_Emu::set_fade( long start_msec, long length_msec )
-{
- fade_step = sample_rate() * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
- fade_start = msec_to_samples( start_msec );
-}
-
-// unit / pow( 2.0, (double) x / step )
-static int int_log( blargg_long x, int step, int unit )
-{
- int shift = x / step;
- int fraction = (x - shift * step) * unit / step;
- return ((unit - fraction) + (fraction >> 1)) >> shift;
-}
-
-void Music_Emu::handle_fade( long out_count, sample_t* out )
-{
- for ( int i = 0; i < out_count; i += fade_block_size )
- {
- int const shift = 14;
- int const unit = 1 << shift;
- int gain = int_log( (out_time + i - fade_start) / fade_block_size,
- fade_step, unit );
- if ( gain < (unit >> fade_shift) )
- track_ended_ = emu_track_ended_ = true;
-
- sample_t* io = &out [i];
- for ( int count = min( fade_block_size, out_count - i ); count; --count )
- {
- *io = sample_t ((*io * gain) >> shift);
- ++io;
- }
- }
-}
-
-// Silence detection
-
-void Music_Emu::emu_play( long count, sample_t* out )
-{
- check( current_track_ >= 0 );
- emu_time += count;
- if ( current_track_ >= 0 && !emu_track_ended_ )
- end_track_if_error( play_( count, out ) );
- else
- memset( out, 0, count * sizeof *out );
-}
-
-// number of consecutive silent samples at end
-static long count_silence( Music_Emu::sample_t* begin, long size )
-{
- Music_Emu::sample_t first = *begin;
- *begin = silence_threshold; // sentinel
- Music_Emu::sample_t* p = begin + size;
- while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
- *begin = first;
- return size - (p - begin);
-}
-
-// fill internal buffer and check it for silence
-void Music_Emu::fill_buf()
-{
- assert( !buf_remain );
- if ( !emu_track_ended_ )
- {
- emu_play( buf_size, buf.begin() );
- long silence = count_silence( buf.begin(), buf_size );
- if ( silence < buf_size )
- {
- silence_time = emu_time - silence;
- buf_remain = buf_size;
- return;
- }
- }
- silence_count += buf_size;
-}
-
-blargg_err_t Music_Emu::play( long out_count, sample_t* out )
-{
- if ( track_ended_ )
- {
- memset( out, 0, out_count * sizeof *out );
- }
- else
- {
- require( current_track() >= 0 );
- require( out_count % stereo == 0 );
-
- assert( emu_time >= out_time );
-
- // prints nifty graph of how far ahead we are when searching for silence
- //dprintf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
-
- long pos = 0;
- if ( silence_count )
- {
- // during a run of silence, run emulator at >=2x speed so it gets ahead
- long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
- while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) )
- fill_buf();
-
- // fill with silence
- pos = min( silence_count, out_count );
- memset( out, 0, pos * sizeof *out );
- silence_count -= pos;
-
- if ( emu_time - silence_time > silence_max * stereo * sample_rate() )
- {
- track_ended_ = emu_track_ended_ = true;
- silence_count = 0;
- buf_remain = 0;
- }
- }
-
- if ( buf_remain )
- {
- // empty silence buf
- long n = min( buf_remain, out_count - pos );
- memcpy( &out [pos], buf.begin() + (buf_size - buf_remain), n * sizeof *out );
- buf_remain -= n;
- pos += n;
- }
-
- // generate remaining samples normally
- long remain = out_count - pos;
- if ( remain )
- {
- emu_play( remain, out + pos );
- track_ended_ |= emu_track_ended_;
-
- if ( !ignore_silence_ || out_time > fade_start )
- {
- // check end for a new run of silence
- long silence = count_silence( out + pos, remain );
- if ( silence < remain )
- silence_time = emu_time - silence;
-
- if ( emu_time - silence_time >= buf_size )
- fill_buf(); // cause silence detection on next play()
- }
- }
-
- if ( out_time > fade_start )
- handle_fade( out_count, out );
- }
- out_time += out_count;
- return 0;
-}
-
-// Gme_Info_
-
-blargg_err_t Gme_Info_::set_sample_rate_( long ) { return 0; }
-void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
-void Gme_Info_::post_load_() { Gme_File::post_load_(); } // skip Music_Emu
-void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
-void Gme_Info_::mute_voices_( int ) { check( false ); }
-void Gme_Info_::set_tempo_( double ) { }
-blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; }
-blargg_err_t Gme_Info_::play_( long, sample_t* ) { return "Use full emulator for playback"; }
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.h
deleted file mode 100644
index 573403ce..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Music_Emu.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// Common interface to game music file emulators
-
-// Game_Music_Emu 0.5.2
-#ifndef MUSIC_EMU_H
-#define MUSIC_EMU_H
-
-#include "Gme_File.h"
-class Multi_Buffer;
-
-struct Music_Emu : public Gme_File {
-public:
-// Basic functionality (see Gme_File.h for file loading/track info functions)
-
- // Set output sample rate. Must be called only once before loading file.
- blargg_err_t set_sample_rate( long sample_rate );
-
- // Start a track, where 0 is the first track. Also clears warning string.
- blargg_err_t start_track( int );
-
- // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
- // errors set warning string, and major errors also end track.
- typedef short sample_t;
- blargg_err_t play( long count, sample_t* buf );
-
-// Informational
-
- // Sample rate sound is generated at
- long sample_rate() const;
-
- // Index of current track or -1 if one hasn't been started
- int current_track() const;
-
- // Number of voices used by currently loaded file
- int voice_count() const;
-
- // Names of voices
- const char** voice_names() const;
-
-// Track status/control
-
- // Number of milliseconds (1000 msec = 1 second) played since beginning of track
- long tell() const;
-
- // Seek to new time in track. Seeking backwards or far forward can take a while.
- blargg_err_t seek( long msec );
-
- // Skip n samples
- blargg_err_t skip( long n );
-
- // True if a track has reached its end
- bool track_ended() const;
-
- // Set start time and length of track fade out. Once fade ends track_ended() returns
- // true. Fade time can be changed while track is playing.
- void set_fade( long start_msec, long length_msec = 8000 );
-
- // Disable automatic end-of-track detection and skipping of silence at beginning
- void ignore_silence( bool disable = true );
-
- // Info for current track
- Gme_File::track_info;
- blargg_err_t track_info( track_info_t* out ) const;
-
-// Sound customization
-
- // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
- // Track length as returned by track_info() assumes a tempo of 1.0.
- void set_tempo( double );
-
- // Mute/unmute voice i, where voice 0 is first voice
- void mute_voice( int index, bool mute = true );
-
- // Set muting state of all voices at once using a bit mask, where -1 mutes them all,
- // 0 unmutes them all, 0x01 mutes just the first voice, etc.
- void mute_voices( int mask );
-
- // Change overall output amplitude, where 1.0 results in minimal clamping.
- // Must be called before set_sample_rate().
- void set_gain( double );
-
- // Request use of custom multichannel buffer. Only supported by "classic" emulators;
- // on others this has no effect. Should be called only once *before* set_sample_rate().
- virtual void set_buffer( Multi_Buffer* ) { }
-
-// Sound equalization (treble/bass)
-
- // Frequency equalizer parameters (see gme.txt)
- // See gme.h for definition of struct gme_equalizer_t.
- typedef gme_equalizer_t equalizer_t;
-
- // Current frequency equalizater parameters
- equalizer_t const& equalizer() const;
-
- // Set frequency equalizer parameters
- void set_equalizer( equalizer_t const& );
-
- // Equalizer settings for TV speaker
- static equalizer_t const tv_eq;
-
-public:
- Music_Emu();
- ~Music_Emu();
-protected:
- void set_max_initial_silence( int n ) { max_initial_silence = n; }
- void set_silence_lookahead( int n ) { silence_lookahead = n; }
- void set_voice_count( int n ) { voice_count_ = n; }
- void set_voice_names( const char* const* names );
- void set_track_ended() { emu_track_ended_ = true; }
- double gain() const { return gain_; }
- double tempo() const { return tempo_; }
- void remute_voices();
-
- virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
- virtual void set_equalizer_( equalizer_t const& ) { };
- virtual void mute_voices_( int mask ) = 0;
- virtual void set_tempo_( double ) = 0;
- virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
- virtual blargg_err_t play_( long count, sample_t* out ) = 0;
- virtual blargg_err_t skip_( long count );
-protected:
- virtual void unload();
- virtual void pre_load();
- virtual void post_load_();
-private:
- // general
- equalizer_t equalizer_;
- int max_initial_silence;
- const char** voice_names_;
- int voice_count_;
- int mute_mask_;
- double tempo_;
- double gain_;
-
- long sample_rate_;
- blargg_long msec_to_samples( blargg_long msec ) const;
-
- // track-specific
- int current_track_;
- blargg_long out_time; // number of samples played since start of track
- blargg_long emu_time; // number of samples emulator has generated since start of track
- bool emu_track_ended_; // emulator has reached end of track
- volatile bool track_ended_;
- void clear_track_vars();
- void end_track_if_error( blargg_err_t );
-
- // fading
- blargg_long fade_start;
- int fade_step;
- void handle_fade( long count, sample_t* out );
-
- // silence detection
- int silence_lookahead; // speed to run emulator when looking ahead for silence
- bool ignore_silence_;
- long silence_time; // number of samples where most recent silence began
- long silence_count; // number of samples of silence to play before using buf
- long buf_remain; // number of samples left in silence buffer
- enum { buf_size = 2048 };
- blargg_vector<sample_t> buf;
- void fill_buf();
- void emu_play( long count, sample_t* out );
-
- Multi_Buffer* effects_buffer;
- friend Music_Emu* gme_new_emu( gme_type_t, long );
- friend void gme_set_stereo_depth( Music_Emu*, double );
-};
-
-// base class for info-only derivations
-struct Gme_Info_ : Music_Emu
-{
- virtual blargg_err_t set_sample_rate_( long sample_rate );
- virtual void set_equalizer_( equalizer_t const& );
- virtual void mute_voices_( int mask );
- virtual void set_tempo_( double );
- virtual blargg_err_t start_track_( int );
- virtual blargg_err_t play_( long count, sample_t* out );
- virtual void pre_load();
- virtual void post_load_();
-};
-
-inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
-{
- return track_info( out, current_track_ );
-}
-
-inline long Music_Emu::sample_rate() const { return sample_rate_; }
-inline const char** Music_Emu::voice_names() const { return voice_names_; }
-inline int Music_Emu::voice_count() const { return voice_count_; }
-inline int Music_Emu::current_track() const { return current_track_; }
-inline bool Music_Emu::track_ended() const { return track_ended_; }
-inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
-
-inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
-inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
-inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
-inline blargg_err_t Music_Emu::start_track_( int ) { return 0; }
-
-inline void Music_Emu::set_voice_names( const char* const* names )
-{
- // Intentional removal of const, so users don't have to remember obscure const in middle
- voice_names_ = (const char**) names;
-}
-
-inline void Music_Emu::mute_voices_( int ) { }
-
-inline void Music_Emu::set_gain( double g )
-{
- assert( !sample_rate() ); // you must set gain before setting sample rate
- gain_ = g;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.cpp
deleted file mode 100644
index 8daf5d0e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.cpp
+++ /dev/null
@@ -1,391 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const amp_range = 15;
-
-Nes_Apu::Nes_Apu() :
- square1( &square_synth ),
- square2( &square_synth )
-{
- tempo_ = 1.0;
- dmc.apu = this;
- dmc.prg_reader = NULL;
- irq_notifier_ = NULL;
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &triangle;
- oscs [3] = &noise;
- oscs [4] = &dmc;
-
- output( NULL );
- volume( 1.0 );
- reset( false );
-}
-
-void Nes_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- triangle.synth.treble_eq( eq );
- noise.synth.treble_eq( eq );
- dmc.synth.treble_eq( eq );
-}
-
-void Nes_Apu::enable_nonlinear( double v )
-{
- dmc.nonlinear = true;
- square_synth.volume( 1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v );
-
- const double tnd = 0.48 / 202 * nonlinear_tnd_gain();
- triangle.synth.volume( 3.0 * tnd );
- noise.synth.volume( 2.0 * tnd );
- dmc.synth.volume( tnd );
-
- square1 .last_amp = 0;
- square2 .last_amp = 0;
- triangle.last_amp = 0;
- noise .last_amp = 0;
- dmc .last_amp = 0;
-}
-
-void Nes_Apu::volume( double v )
-{
- dmc.nonlinear = false;
- square_synth.volume( 0.1128 / amp_range * v );
- triangle.synth.volume( 0.12765 / amp_range * v );
- noise.synth.volume( 0.0741 / amp_range * v );
- dmc.synth.volume( 0.42545 / 127 * v );
-}
-
-void Nes_Apu::output( Blip_Buffer* buffer )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buffer );
-}
-
-void Nes_Apu::set_tempo( double t )
-{
- tempo_ = t;
- frame_period = (dmc.pal_mode ? 8314 : 7458);
- if ( t != 1.0 )
- frame_period = (int) (frame_period / t) & ~1; // must be even
-}
-
-void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
-{
- dmc.pal_mode = pal_mode;
- set_tempo( tempo_ );
-
- square1.reset();
- square2.reset();
- triangle.reset();
- noise.reset();
- dmc.reset();
-
- last_time = 0;
- last_dmc_time = 0;
- osc_enables = 0;
- irq_flag = false;
- earliest_irq_ = no_irq;
- frame_delay = 1;
- write_register( 0, 0x4017, 0x00 );
- write_register( 0, 0x4015, 0x00 );
-
- for ( nes_addr_t addr = start_addr; addr <= 0x4013; addr++ )
- write_register( 0, addr, (addr & 3) ? 0x00 : 0x10 );
-
- dmc.dac = initial_dmc_dac;
- if ( !dmc.nonlinear )
- triangle.last_amp = 15;
- if ( !dmc.nonlinear ) // TODO: remove?
- dmc.last_amp = initial_dmc_dac; // prevent output transition
-}
-
-void Nes_Apu::irq_changed()
-{
- nes_time_t new_irq = dmc.next_irq;
- if ( dmc.irq_flag | irq_flag ) {
- new_irq = 0;
- }
- else if ( new_irq > next_irq ) {
- new_irq = next_irq;
- }
-
- if ( new_irq != earliest_irq_ ) {
- earliest_irq_ = new_irq;
- if ( irq_notifier_ )
- irq_notifier_( irq_data );
- }
-}
-
-// frames
-
-void Nes_Apu::run_until( nes_time_t end_time )
-{
- require( end_time >= last_dmc_time );
- if ( end_time > next_dmc_read_time() )
- {
- nes_time_t start = last_dmc_time;
- last_dmc_time = end_time;
- dmc.run( start, end_time );
- }
-}
-
-void Nes_Apu::run_until_( nes_time_t end_time )
-{
- require( end_time >= last_time );
-
- if ( end_time == last_time )
- return;
-
- if ( last_dmc_time < end_time )
- {
- nes_time_t start = last_dmc_time;
- last_dmc_time = end_time;
- dmc.run( start, end_time );
- }
-
- while ( true )
- {
- // earlier of next frame time or end time
- nes_time_t time = last_time + frame_delay;
- if ( time > end_time )
- time = end_time;
- frame_delay -= time - last_time;
-
- // run oscs to present
- square1.run( last_time, time );
- square2.run( last_time, time );
- triangle.run( last_time, time );
- noise.run( last_time, time );
- last_time = time;
-
- if ( time == end_time )
- break; // no more frames to run
-
- // take frame-specific actions
- frame_delay = frame_period;
- switch ( frame++ )
- {
- case 0:
- if ( !(frame_mode & 0xC0) ) {
- next_irq = time + frame_period * 4 + 2;
- irq_flag = true;
- }
- // fall through
- case 2:
- // clock length and sweep on frames 0 and 2
- square1.clock_length( 0x20 );
- square2.clock_length( 0x20 );
- noise.clock_length( 0x20 );
- triangle.clock_length( 0x80 ); // different bit for halt flag on triangle
-
- square1.clock_sweep( -1 );
- square2.clock_sweep( 0 );
-
- // frame 2 is slightly shorter in mode 1
- if ( dmc.pal_mode && frame == 3 )
- frame_delay -= 2;
- break;
-
- case 1:
- // frame 1 is slightly shorter in mode 0
- if ( !dmc.pal_mode )
- frame_delay -= 2;
- break;
-
- case 3:
- frame = 0;
-
- // frame 3 is almost twice as long in mode 1
- if ( frame_mode & 0x80 )
- frame_delay += frame_period - (dmc.pal_mode ? 2 : 6);
- break;
- }
-
- // clock envelopes and linear counter every frame
- triangle.clock_linear_counter();
- square1.clock_envelope();
- square2.clock_envelope();
- noise.clock_envelope();
- }
-}
-
-template<class T>
-inline void zero_apu_osc( T* osc, nes_time_t time )
-{
- Blip_Buffer* output = osc->output;
- int last_amp = osc->last_amp;
- osc->last_amp = 0;
- if ( output && last_amp )
- osc->synth.offset( time, -last_amp, output );
-}
-
-void Nes_Apu::end_frame( nes_time_t end_time )
-{
- if ( end_time > last_time )
- run_until_( end_time );
-
- if ( dmc.nonlinear )
- {
- zero_apu_osc( &square1, last_time );
- zero_apu_osc( &square2, last_time );
- zero_apu_osc( &triangle, last_time );
- zero_apu_osc( &noise, last_time );
- zero_apu_osc( &dmc, last_time );
- }
-
- // make times relative to new frame
- last_time -= end_time;
- require( last_time >= 0 );
-
- last_dmc_time -= end_time;
- require( last_dmc_time >= 0 );
-
- if ( next_irq != no_irq ) {
- next_irq -= end_time;
- check( next_irq >= 0 );
- }
- if ( dmc.next_irq != no_irq ) {
- dmc.next_irq -= end_time;
- check( dmc.next_irq >= 0 );
- }
- if ( earliest_irq_ != no_irq ) {
- earliest_irq_ -= end_time;
- if ( earliest_irq_ < 0 )
- earliest_irq_ = 0;
- }
-}
-
-// registers
-
-static const unsigned char length_table [0x20] = {
- 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
- 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
- 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
- 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
-};
-
-void Nes_Apu::write_register( nes_time_t time, nes_addr_t addr, int data )
-{
- require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
- require( (unsigned) data <= 0xFF );
-
- // Ignore addresses outside range
- if ( unsigned (addr - start_addr) > end_addr - start_addr )
- return;
-
- run_until_( time );
-
- if ( addr < 0x4014 )
- {
- // Write to channel
- int osc_index = (addr - start_addr) >> 2;
- Nes_Osc* osc = oscs [osc_index];
-
- int reg = addr & 3;
- osc->regs [reg] = data;
- osc->reg_written [reg] = true;
-
- if ( osc_index == 4 )
- {
- // handle DMC specially
- dmc.write_register( reg, data );
- }
- else if ( reg == 3 )
- {
- // load length counter
- if ( (osc_enables >> osc_index) & 1 )
- osc->length_counter = length_table [(data >> 3) & 0x1F];
-
- // reset square phase
- if ( osc_index < 2 )
- ((Nes_Square*) osc)->phase = Nes_Square::phase_range - 1;
- }
- }
- else if ( addr == 0x4015 )
- {
- // Channel enables
- for ( int i = osc_count; i--; )
- if ( !((data >> i) & 1) )
- oscs [i]->length_counter = 0;
-
- bool recalc_irq = dmc.irq_flag;
- dmc.irq_flag = false;
-
- int old_enables = osc_enables;
- osc_enables = data;
- if ( !(data & 0x10) ) {
- dmc.next_irq = no_irq;
- recalc_irq = true;
- }
- else if ( !(old_enables & 0x10) ) {
- dmc.start(); // dmc just enabled
- }
-
- if ( recalc_irq )
- irq_changed();
- }
- else if ( addr == 0x4017 )
- {
- // Frame mode
- frame_mode = data;
-
- bool irq_enabled = !(data & 0x40);
- irq_flag &= irq_enabled;
- next_irq = no_irq;
-
- // mode 1
- frame_delay = (frame_delay & 1);
- frame = 0;
-
- if ( !(data & 0x80) )
- {
- // mode 0
- frame = 1;
- frame_delay += frame_period;
- if ( irq_enabled )
- next_irq = time + frame_delay + frame_period * 3 + 1;
- }
-
- irq_changed();
- }
-}
-
-int Nes_Apu::read_status( nes_time_t time )
-{
- run_until_( time - 1 );
-
- int result = (dmc.irq_flag << 7) | (irq_flag << 6);
-
- for ( int i = 0; i < osc_count; i++ )
- if ( oscs [i]->length_counter )
- result |= 1 << i;
-
- run_until_( time );
-
- if ( irq_flag )
- {
- result |= 0x40;
- irq_flag = false;
- irq_changed();
- }
-
- //dprintf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
-
- return result;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.h
deleted file mode 100644
index dbd8484c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Apu.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// NES 2A03 APU sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_APU_H
-#define NES_APU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long nes_time_t; // CPU clock cycle count
-typedef unsigned nes_addr_t; // 16-bit memory address
-
-#include "Nes_Oscs.h"
-
-struct apu_state_t;
-class Nes_Buffer;
-
-class Nes_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Set memory reader callback used by DMC oscillator to fetch samples.
- // When callback is invoked, 'user_data' is passed unchanged as the
- // first parameter.
- void dmc_reader( int (*callback)( void* user_data, nes_addr_t ), void* user_data = NULL );
-
- // All time values are the number of CPU clock cycles relative to the
- // beginning of the current time frame. Before resetting the CPU clock
- // count, call end_frame( last_cpu_time ).
-
- // Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
- enum { start_addr = 0x4000 };
- enum { end_addr = 0x4017 };
- void write_register( nes_time_t, nes_addr_t, int data );
-
- // Read from status register at 0x4015
- enum { status_addr = 0x4015 };
- int read_status( nes_time_t );
-
- // Run all oscillators up to specified time, end current time frame, then
- // start a new time frame at time 0. Time frames have no effect on emulation
- // and each can be whatever length is convenient.
- void end_frame( nes_time_t );
-
-// Additional optional features (can be ignored without any problem)
-
- // Reset internal frame counter, registers, and all oscillators.
- // Use PAL timing if pal_timing is true, otherwise use NTSC timing.
- // Set the DMC oscillator's initial DAC value to initial_dmc_dac without
- // any audible click.
- void reset( bool pal_mode = false, int initial_dmc_dac = 0 );
-
- // Adjust frame period
- void set_tempo( double );
-
- // Save/load exact emulation state
- void save_state( apu_state_t* out ) const;
- void load_state( apu_state_t const& );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see notes.txt)
- void treble_eq( const blip_eq_t& );
-
- // Set sound output of specific oscillator to buffer. If buffer is NULL,
- // the specified oscillator is muted and emulation accuracy is reduced.
- // The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
- // 2) Triangle, 3) Noise, 4) DMC.
- enum { osc_count = 5 };
- void osc_output( int index, Blip_Buffer* buffer );
-
- // Set IRQ time callback that is invoked when the time of earliest IRQ
- // may have changed, or NULL to disable. When callback is invoked,
- // 'user_data' is passed unchanged as the first parameter.
- void irq_notifier( void (*callback)( void* user_data ), void* user_data = NULL );
-
- // Get time that APU-generated IRQ will occur if no further register reads
- // or writes occur. If IRQ is already pending, returns irq_waiting. If no
- // IRQ will occur, returns no_irq.
- enum { no_irq = LONG_MAX / 2 + 1 };
- enum { irq_waiting = 0 };
- nes_time_t earliest_irq( nes_time_t ) const;
-
- // Count number of DMC reads that would occur if 'run_until( t )' were executed.
- // If last_read is not NULL, set *last_read to the earliest time that
- // 'count_dmc_reads( time )' would result in the same result.
- int count_dmc_reads( nes_time_t t, nes_time_t* last_read = NULL ) const;
-
- // Time when next DMC memory read will occur
- nes_time_t next_dmc_read_time() const;
-
- // Run DMC until specified time, so that any DMC memory reads can be
- // accounted for (i.e. inserting CPU wait states).
- void run_until( nes_time_t );
-
-public:
- Nes_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- friend class Nes_Nonlinearizer;
- void enable_nonlinear( double volume );
- static double nonlinear_tnd_gain() { return 0.75; }
-private:
- friend struct Nes_Dmc;
-
- // noncopyable
- Nes_Apu( const Nes_Apu& );
- Nes_Apu& operator = ( const Nes_Apu& );
-
- Nes_Osc* oscs [osc_count];
- Nes_Square square1;
- Nes_Square square2;
- Nes_Noise noise;
- Nes_Triangle triangle;
- Nes_Dmc dmc;
-
- double tempo_;
- nes_time_t last_time; // has been run until this time in current frame
- nes_time_t last_dmc_time;
- nes_time_t earliest_irq_;
- nes_time_t next_irq;
- int frame_period;
- int frame_delay; // cycles until frame counter runs next
- int frame; // current frame (0-3)
- int osc_enables;
- int frame_mode;
- bool irq_flag;
- void (*irq_notifier_)( void* user_data );
- void* irq_data;
- Nes_Square::Synth square_synth; // shared by squares
-
- void irq_changed();
- void state_restored();
- void run_until_( nes_time_t );
-
- // TODO: remove
- friend class Nes_Core;
-};
-
-inline void Nes_Apu::osc_output( int osc, Blip_Buffer* buf )
-{
- assert( (unsigned) osc < osc_count );
- oscs [osc]->output = buf;
-}
-
-inline nes_time_t Nes_Apu::earliest_irq( nes_time_t ) const
-{
- return earliest_irq_;
-}
-
-inline void Nes_Apu::dmc_reader( int (*func)( void*, nes_addr_t ), void* user_data )
-{
- dmc.prg_reader_data = user_data;
- dmc.prg_reader = func;
-}
-
-inline void Nes_Apu::irq_notifier( void (*func)( void* user_data ), void* user_data )
-{
- irq_notifier_ = func;
- irq_data = user_data;
-}
-
-inline int Nes_Apu::count_dmc_reads( nes_time_t time, nes_time_t* last_read ) const
-{
- return dmc.count_reads( time, last_read );
-}
-
-inline nes_time_t Nes_Dmc::next_read_time() const
-{
- if ( length_counter == 0 )
- return Nes_Apu::no_irq; // not reading
-
- return apu->last_dmc_time + delay + long (bits_remain - 1) * period;
-}
-
-inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.cpp
deleted file mode 100644
index 480b4aa4..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.cpp
+++ /dev/null
@@ -1,1084 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Nes_Cpu.h"
-
-#include "blargg_endian.h"
-#include <limits.h>
-
-#define BLARGG_CPU_X86 1
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "nes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#ifndef CPU_DONE
- #define CPU_DONE( cpu, time, result_out ) { result_out = -1; }
-#endif
-
-#ifndef CPU_READ_PPU
- #define CPU_READ_PPU( cpu, addr, out, time )\
- {\
- FLUSH_TIME();\
- out = CPU_READ( cpu, addr, time );\
- CACHE_TIME();\
- }
-#endif
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Nes_Cpu::set_code_page( int i, void const* p )
-{
- state->code_map [i] = (uint8_t const*) p - PAGE_OFFSET( i * page_size );
-}
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Nes_Cpu::reset( void const* unmapped_page )
-{
- check( state == &state_ );
- state = &state_;
- r.status = st_i;
- r.sp = 0xFF;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_nes_time;
- end_time_ = future_nes_time;
- error_count_ = 0;
-
- assert( page_size == 0x800 ); // assumes this
- set_code_page( page_count, unmapped_page );
- map_code( 0x2000, 0xE000, unmapped_page, true );
- map_code( 0x0000, 0x2000, low_mem, true );
-
- blargg_verify_byte_order();
-}
-
-void Nes_Cpu::map_code( nes_addr_t start, unsigned size, void const* data, bool mirror )
-{
- // address range must begin and end on page boundaries
- require( start % page_size == 0 );
- require( size % page_size == 0 );
- require( start + size <= 0x10000 );
-
- unsigned page = start / page_size;
- for ( unsigned n = size / page_size; n; --n )
- {
- set_code_page( page++, data );
- if ( !mirror )
- data = (char const*) data + page_size;
- }
-}
-
-#define TIME (s_time + s.base)
-#define READ_LIKELY_PPU( addr, out ) {CPU_READ_PPU( this, (addr), out, TIME );}
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (low_mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_bits] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Nes_Cpu::run( nes_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- // even on x86, using s.time in place of s_time was slower
- fint16 s_time = s.time;
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- // status flags
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-dec_clock_loop:
- s_time--;
-loop:
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) pc < 0x10000 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
- check( -32768 <= s_time && s_time < 32767 );
-
- uint8_t const* instr = s.code_map [pc >> page_bits];
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
- 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
- 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
- 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
- 3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
- 3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
- 3,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
- }; // 0x00 was 7 and 0xF2 was 2
-
- fuint16 data;
-
-#if !BLARGG_CPU_X86
- if ( s_time >= 0 )
- goto out_of_time;
- s_time += clock_table [opcode];
-
- data = *instr;
-
- switch ( opcode )
- {
-#else
-
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-#endif
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE() (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR() GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
- fuint16 temp = READ_LOW( data ) + y;\
- out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- cross( temp );\
- }
-
-#define IND_X( out ) {\
- fuint16 temp = data + x;\
- out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
- }
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
- IND_X( data )\
- goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
- IND_Y( HANDLE_PAGE_CROSSING, data )\
- goto ptr##op;\
-case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
-case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
-case op + 0x18: /* abs,X */\
- data += x;\
-ind##op:\
- HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
- ADD_PAGE();\
-ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- fuint16 extra_clock = (++pc & 0xFF) + offset;\
- if ( !(cond) ) goto dec_clock_loop;\
- pc = BOOST::uint16_t (pc + offset);\
- s_time += extra_clock >> 8 & 1;\
- goto loop;\
-}
-
-// Often-Used
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0xE8: // INX
- INC_DEC_XY( x, 1 )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0xF0: // BEQ
- BRANCH( !(uint8_t) nz );
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xC8: // INY
- INC_DEC_XY( y, 1 )
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAD:{// LDA abs
- unsigned addr = GET_ADDR();
- pc += 2;
- READ_LIKELY_PPU( addr, nz );
- a = nz;
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 1 + READ_LOW( sp );
- pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- {
- fuint16 addr;
-
- case 0x99: // STA abs,Y
- addr = y + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x8D: // STA abs
- addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x9D: // STA abs,X (slightly more common than STA abs)
- addr = x + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- sta_ptr:
- FLUSH_TIME();
- WRITE( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x91: // STA (ind),Y
- IND_Y( NO_PAGE_CROSSING, addr )
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- IND_X( addr )
- pc++;
- goto sta_ptr;
-
- }
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
- // common read instructions
- {
- fuint16 addr;
-
- case 0xA1: // LDA (ind,X)
- IND_X( addr )
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- HANDLE_PAGE_CROSSING( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- HANDLE_PAGE_CROSSING( data + y );
- addr = GET_ADDR() + y;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xBD: // LDA abs,X
- HANDLE_PAGE_CROSSING( data + x );
- addr = GET_ADDR() + x;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- a_nz_read_addr:
- FLUSH_TIME();
- a = nz = READ( addr );
- CACHE_TIME();
- goto loop;
-
- }
-
-// Branch
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
-// Load/store
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- HANDLE_PAGE_CROSSING( data );
- case 0xAC:{// LDY abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xBE: // LDX abs,y
- data += y;
- HANDLE_PAGE_CROSSING( data );
- case 0xAE:{// LDX abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- unsigned addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, temp );
- goto loop;
- }
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
- case 0x2C:{// BIT abs
- unsigned addr = GET_ADDR();
- pc += 2;
- status &= ~st_v;
- READ_LIKELY_PPU( addr, nz );
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
- }
-
- case 0x24: // BIT zp
- nz = READ_LOW( data );
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- case 0xEB: // unofficial equivalent
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE();
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE();
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
- case 0xCA: // DEX
- INC_DEC_XY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_XY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a ); // verified
- goto loop;
-
- case 0x68: // PLA
- a = nz = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 ) goto loop;
- if ( status & st_i ) goto loop;
- s_time += delta;
- s.base = irq_time_;
- goto loop;
- }
-
- case 0x28:{// PLP
- fuint8 temp = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | (st_b | st_r) );
- goto loop;
- }
-
- case 0x6C:{// JMP (ind)
- data = GET_ADDR();
- check( unsigned (data - 0x2000) >= 0x4000 ); // ensure it's outside I/O space
- uint8_t const* page = s.code_map [data >> page_bits];
- pc = page [PAGE_OFFSET( data )];
- data = (data & 0xFF00) | ((data + 1) & 0xFF);
- pc |= page [PAGE_OFFSET( data )] << 8;
- goto loop;
- }
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- //dprintf( "CLI at %d\n", TIME );
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- s.base += s_time + 1;
- s_time = -1;
- goto loop;
- }
-
- // TODO: implement
- delayed_cli:
- dprintf( "Delayed CLI not emulated\n" );
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- dprintf( "Delayed SEI not emulated\n" );
- goto loop;
- }
-
-// Unofficial
-
- // SKW - Skip word
- case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
- HANDLE_PAGE_CROSSING( data + x );
- case 0x0C:
- pc++;
- // SKB - Skip byte
- case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
- case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
- pc++;
- goto loop;
-
- // NOP
- case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
- goto loop;
-
- case bad_opcode: // HLT
- pc--;
- if ( pc > 0xFFFF )
- {
- // handle wrap-around (assumes caller has put page of HLT at 0x10000)
- pc &= 0xFFFF;
- goto loop;
- }
- case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2:
- goto stop;
-
-// Unimplemented
-
- case 0xFF: // force 256-entry jump table for optimization purposes
- c |= 1;
- default:
- check( (unsigned) opcode <= 0xFF );
- // skip over proper number of bytes
- static unsigned char const illop_lens [8] = {
- 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
- };
- fuint8 opcode = instr [-1];
- fint16 len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
- if ( opcode == 0x9C )
- len = 2;
- pc += len;
- error_count_++;
-
- if ( (opcode >> 4) == 0x0B )
- {
- if ( opcode == 0xB3 )
- data = READ_LOW( data );
- if ( opcode != 0xB7 )
- HANDLE_PAGE_CROSSING( data + y );
- }
- goto loop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- pc++;
- result_ = 4;
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- temp |= st_r;
- if ( result_ )
- temp |= st_b; // TODO: incorrectly sets B flag for IRQ
- WRITE_LOW( sp, temp );
-
- this->r.status = status |= st_i;
- blargg_long delta = s.base - end_time_;
- if ( delta >= 0 ) goto loop;
- s_time += delta;
- s.base = end_time_;
- goto loop;
- }
-
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ >= 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
-stop:
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return s_time < 0;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.h
deleted file mode 100644
index d303b57c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Cpu.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// NES 6502 CPU emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef NES_CPU_H
-#define NES_CPU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long nes_time_t; // clock cycle count
-typedef unsigned nes_addr_t; // 16-bit address
-enum { future_nes_time = LONG_MAX / 2 + 1 };
-
-class Nes_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers, map low memory and its three mirrors to address 0,
- // and mirror unmapped_page in remaining memory
- void reset( void const* unmapped_page = 0 );
-
- // Map code memory (memory accessed via the program counter). Start and size
- // must be multiple of page_size. If mirror is true, repeats code page
- // throughout address range.
- enum { page_size = 0x800 };
- void map_code( nes_addr_t start, unsigned size, void const* code, bool mirror = false );
-
- // Access emulated memory as CPU does
- uint8_t const* get_code( nes_addr_t );
-
- // 2KB of RAM at address 0
- uint8_t low_mem [0x800];
-
- // NES 6502 registers. Not kept updated during a call to run().
- struct registers_t {
- BOOST::uint16_t pc;
- BOOST::uint8_t a;
- BOOST::uint8_t x;
- BOOST::uint8_t y;
- BOOST::uint8_t status;
- BOOST::uint8_t sp;
- };
- registers_t r;
-
- // Set end_time and run CPU from current time. Returns true if execution
- // stopped due to encountering bad_opcode.
- bool run( nes_time_t end_time );
-
- // Time of beginning of next instruction to be executed
- nes_time_t time() const { return state->time + state->base; }
- void set_time( nes_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- nes_time_t irq_time() const { return irq_time_; }
- void set_irq_time( nes_time_t );
-
- nes_time_t end_time() const { return end_time_; }
- void set_end_time( nes_time_t );
-
- // Number of undefined instructions encountered and skipped
- void clear_error_count() { error_count_ = 0; }
- unsigned long error_count() const { return error_count_; }
-
- // CPU invokes bad opcode handler if it encounters this
- enum { bad_opcode = 0xF2 };
-
-public:
- Nes_Cpu() { state = &state_; }
- enum { page_bits = 11 };
- enum { page_count = 0x10000 >> page_bits };
- enum { irq_inhibit = 0x04 };
-private:
- struct state_t {
- uint8_t const* code_map [page_count + 1];
- nes_time_t base;
- int time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- nes_time_t irq_time_;
- nes_time_t end_time_;
- unsigned long error_count_;
-
- void set_code_page( int, void const* );
- inline int update_end_time( nes_time_t end, nes_time_t irq );
-};
-
-inline BOOST::uint8_t const* Nes_Cpu::get_code( nes_addr_t addr )
-{
- return state->code_map [addr >> page_bits] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-inline int Nes_Cpu::update_end_time( nes_time_t t, nes_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- int delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Nes_Cpu::set_irq_time( nes_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Nes_Cpu::set_end_time( nes_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.cpp
deleted file mode 100644
index c058f6b1..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Nes_Fme7_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Nes_Fme7_Apu::reset()
-{
- last_time = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- oscs [i].last_amp = 0;
-
- fme7_apu_state_t* state = this;
- memset( state, 0, sizeof *state );
-}
-
-unsigned char const Nes_Fme7_Apu::amp_table [16] =
-{
- #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
- ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
- ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
- ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
- ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
- #undef ENTRY
-};
-
-void Nes_Fme7_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time );
-
- for ( int index = 0; index < osc_count; index++ )
- {
- int mode = regs [7] >> index;
- int vol_mode = regs [010 + index];
- int volume = amp_table [vol_mode & 0x0F];
-
- Blip_Buffer* const osc_output = oscs [index].output;
- if ( !osc_output )
- continue;
- osc_output->set_modified();
-
- // check for unsupported mode
- #ifndef NDEBUG
- if ( (mode & 011) <= 001 && vol_mode & 0x1F )
- dprintf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
- mode, vol_mode & 0x1F );
- #endif
-
- if ( (mode & 001) | (vol_mode & 0x10) )
- volume = 0; // noise and envelope aren't supported
-
- // period
- int const period_factor = 16;
- unsigned period = (regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
- regs [index * 2] * period_factor;
- if ( period < 50 ) // around 22 kHz
- {
- volume = 0;
- if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
- period = period_factor;
- }
-
- // current amplitude
- int amp = volume;
- if ( !phases [index] )
- amp = 0;
- {
- int delta = amp - oscs [index].last_amp;
- if ( delta )
- {
- oscs [index].last_amp = amp;
- synth.offset( last_time, delta, osc_output );
- }
- }
-
- blip_time_t time = last_time + delays [index];
- if ( time < end_time )
- {
- int delta = amp * 2 - volume;
- if ( volume )
- {
- do
- {
- delta = -delta;
- synth.offset_inline( time, delta, osc_output );
- time += period;
- }
- while ( time < end_time );
-
- oscs [index].last_amp = (delta + volume) >> 1;
- phases [index] = (delta > 0);
- }
- else
- {
- // maintain phase when silent
- int count = (end_time - time + period - 1) / period;
- phases [index] ^= count & 1;
- time += (blargg_long) count * period;
- }
- }
-
- delays [index] = time - end_time;
- }
-
- last_time = end_time;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.h
deleted file mode 100644
index eb60af03..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Fme7_Apu.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Sunsoft FME-7 sound emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef NES_FME7_APU_H
-#define NES_FME7_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct fme7_apu_state_t
-{
- enum { reg_count = 14 };
- BOOST::uint8_t regs [reg_count];
- BOOST::uint8_t phases [3]; // 0 or 1
- BOOST::uint8_t latch;
- BOOST::uint16_t delays [3]; // a, b, c
-};
-
-class Nes_Fme7_Apu : private fme7_apu_state_t {
-public:
- // See Nes_Apu.h for reference
- void reset();
- void volume( double );
- void treble_eq( blip_eq_t const& );
- void output( Blip_Buffer* );
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
- void end_frame( blip_time_t );
- void save_state( fme7_apu_state_t* ) const;
- void load_state( fme7_apu_state_t const& );
-
- // Mask and addresses of registers
- enum { addr_mask = 0xE000 };
- enum { data_addr = 0xE000 };
- enum { latch_addr = 0xC000 };
-
- // (addr & addr_mask) == latch_addr
- void write_latch( int );
-
- // (addr & addr_mask) == data_addr
- void write_data( blip_time_t, int data );
-
-public:
- Nes_Fme7_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Fme7_Apu( const Nes_Fme7_Apu& );
- Nes_Fme7_Apu& operator = ( const Nes_Fme7_Apu& );
-
- static unsigned char const amp_table [16];
-
- struct {
- Blip_Buffer* output;
- int last_amp;
- } oscs [osc_count];
- blip_time_t last_time;
-
- enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff
- Blip_Synth<blip_good_quality,1> synth;
-
- void run_until( blip_time_t );
-};
-
-inline void Nes_Fme7_Apu::volume( double v )
-{
- synth.volume( 0.38 / amp_range * v ); // to do: fine-tune
-}
-
-inline void Nes_Fme7_Apu::treble_eq( blip_eq_t const& eq )
-{
- synth.treble_eq( eq );
-}
-
-inline void Nes_Fme7_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Fme7_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-inline Nes_Fme7_Apu::Nes_Fme7_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-inline void Nes_Fme7_Apu::write_latch( int data ) { latch = data; }
-
-inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data )
-{
- if ( (unsigned) latch >= reg_count )
- {
- #ifdef dprintf
- dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
- #endif
- return;
- }
-
- run_until( time );
- regs [latch] = data;
-}
-
-inline void Nes_Fme7_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-inline void Nes_Fme7_Apu::save_state( fme7_apu_state_t* out ) const
-{
- *out = *this;
-}
-
-inline void Nes_Fme7_Apu::load_state( fme7_apu_state_t const& in )
-{
- reset();
- fme7_apu_state_t* state = this;
- *state = in;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.cpp
deleted file mode 100644
index f3235b38..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Namco_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Namco_Apu::Nes_Namco_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-void Nes_Namco_Apu::reset()
-{
- last_time = 0;
- addr_reg = 0;
-
- int i;
- for ( i = 0; i < reg_count; i++ )
- reg [i] = 0;
-
- for ( i = 0; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- osc.delay = 0;
- osc.last_amp = 0;
- osc.wave_pos = 0;
- }
-}
-
-void Nes_Namco_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-/*
-void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
-{
- reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
-
- static const char hex [17] = "0123456789ABCDEF";
- int i;
- for ( i = 0; i < reg_count; i++ )
- reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
-
- for ( i = 0; i < osc_count; i++ )
- {
- reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
- reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
- }
-}
-*/
-
-void Nes_Namco_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
-{
- int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
- for ( int i = osc_count - active_oscs; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- Blip_Buffer* output = osc.output;
- if ( !output )
- continue;
- output->set_modified();
-
- blip_resampled_time_t time =
- output->resampled_time( last_time ) + osc.delay;
- blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
- osc.delay = 0;
- if ( time < end_time )
- {
- const BOOST::uint8_t* osc_reg = &reg [i * 8 + 0x40];
- if ( !(osc_reg [4] & 0xE0) )
- continue;
-
- int volume = osc_reg [7] & 15;
- if ( !volume )
- continue;
-
- blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
- if ( freq < 64 * active_oscs )
- continue; // prevent low frequencies from excessively delaying freq changes
- blip_resampled_time_t period =
- output->resampled_duration( 983040 ) / freq * active_oscs;
-
- int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
- if ( !wave_size )
- continue;
-
- int last_amp = osc.last_amp;
- int wave_pos = osc.wave_pos;
-
- do
- {
- // read wave sample
- int addr = wave_pos + osc_reg [6];
- int sample = reg [addr >> 1] >> (addr << 2 & 4);
- wave_pos++;
- sample = (sample & 15) * volume;
-
- // output impulse if amplitude changed
- int delta = sample - last_amp;
- if ( delta )
- {
- last_amp = sample;
- synth.offset_resampled( time, delta, output );
- }
-
- // next sample
- time += period;
- if ( wave_pos >= wave_size )
- wave_pos = 0;
- }
- while ( time < end_time );
-
- osc.wave_pos = wave_pos;
- osc.last_amp = last_amp;
- }
- osc.delay = time - end_time;
- }
-
- last_time = nes_end_time;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.h
deleted file mode 100644
index db5fea4b..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Namco_Apu.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Namco 106 sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_NAMCO_APU_H
-#define NES_NAMCO_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct namco_state_t;
-
-class Nes_Namco_Apu {
-public:
- // See Nes_Apu.h for reference.
- void volume( double );
- void treble_eq( const blip_eq_t& );
- void output( Blip_Buffer* );
- enum { osc_count = 8 };
- void osc_output( int index, Blip_Buffer* );
- void reset();
- void end_frame( blip_time_t );
-
- // Read/write data register is at 0x4800
- enum { data_reg_addr = 0x4800 };
- void write_data( blip_time_t, int );
- int read_data();
-
- // Write-only address register is at 0xF800
- enum { addr_reg_addr = 0xF800 };
- void write_addr( int );
-
- // to do: implement save/restore
- void save_state( namco_state_t* out ) const;
- void load_state( namco_state_t const& );
-
-public:
- Nes_Namco_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Namco_Apu( const Nes_Namco_Apu& );
- Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& );
-
- struct Namco_Osc {
- blargg_long delay;
- Blip_Buffer* output;
- short last_amp;
- short wave_pos;
- };
-
- Namco_Osc oscs [osc_count];
-
- blip_time_t last_time;
- int addr_reg;
-
- enum { reg_count = 0x80 };
- BOOST::uint8_t reg [reg_count];
- Blip_Synth<blip_good_quality,15> synth;
-
- BOOST::uint8_t& access();
- void run_until( blip_time_t );
-};
-/*
-struct namco_state_t
-{
- BOOST::uint8_t regs [0x80];
- BOOST::uint8_t addr;
- BOOST::uint8_t unused;
- BOOST::uint8_t positions [8];
- BOOST::uint32_t delays [8];
-};
-*/
-
-inline BOOST::uint8_t& Nes_Namco_Apu::access()
-{
- int addr = addr_reg & 0x7F;
- if ( addr_reg & 0x80 )
- addr_reg = (addr + 1) | 0x80;
- return reg [addr];
-}
-
-inline void Nes_Namco_Apu::volume( double v ) { synth.volume( 0.10 / osc_count * v ); }
-
-inline void Nes_Namco_Apu::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); }
-
-inline void Nes_Namco_Apu::write_addr( int v ) { addr_reg = v; }
-
-inline int Nes_Namco_Apu::read_data() { return access(); }
-
-inline void Nes_Namco_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Namco_Apu::write_data( blip_time_t time, int data )
-{
- run_until( time );
- access() = data;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.cpp
deleted file mode 100644
index 1ad3f59c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Nes_Osc
-
-void Nes_Osc::clock_length( int halt_mask )
-{
- if ( length_counter && !(regs [0] & halt_mask) )
- length_counter--;
-}
-
-void Nes_Envelope::clock_envelope()
-{
- int period = regs [0] & 15;
- if ( reg_written [3] ) {
- reg_written [3] = false;
- env_delay = period;
- envelope = 15;
- }
- else if ( --env_delay < 0 ) {
- env_delay = period;
- if ( envelope | (regs [0] & 0x20) )
- envelope = (envelope - 1) & 15;
- }
-}
-
-int Nes_Envelope::volume() const
-{
- return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
-}
-
-// Nes_Square
-
-void Nes_Square::clock_sweep( int negative_adjust )
-{
- int sweep = regs [1];
-
- if ( --sweep_delay < 0 )
- {
- reg_written [1] = true;
-
- int period = this->period();
- int shift = sweep & shift_mask;
- if ( shift && (sweep & 0x80) && period >= 8 )
- {
- int offset = period >> shift;
-
- if ( sweep & negate_flag )
- offset = negative_adjust - offset;
-
- if ( period + offset < 0x800 )
- {
- period += offset;
- // rewrite period
- regs [2] = period & 0xFF;
- regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
- }
- }
- }
-
- if ( reg_written [1] ) {
- reg_written [1] = false;
- sweep_delay = (sweep >> 4) & 7;
- }
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period )
-{
- nes_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- int count = (remain + timer_period - 1) / timer_period;
- phase = (phase + count) & (phase_range - 1);
- time += (blargg_long) count * timer_period;
- }
- return time;
-}
-
-void Nes_Square::run( nes_time_t time, nes_time_t end_time )
-{
- const int period = this->period();
- const int timer_period = (period + 1) * 2;
-
- if ( !output )
- {
- delay = maintain_phase( time + delay, end_time, timer_period ) - end_time;
- return;
- }
-
- output->set_modified();
-
- int offset = period >> (regs [1] & shift_mask);
- if ( regs [1] & negate_flag )
- offset = 0;
-
- const int volume = this->volume();
- if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
- {
- if ( last_amp ) {
- synth.offset( time, -last_amp, output );
- last_amp = 0;
- }
-
- time += delay;
- time = maintain_phase( time, end_time, timer_period );
- }
- else
- {
- // handle duty select
- int duty_select = (regs [0] >> 6) & 3;
- int duty = 1 << duty_select; // 1, 2, 4, 2
- int amp = 0;
- if ( duty_select == 3 ) {
- duty = 2; // negated 25%
- amp = volume;
- }
- if ( phase < duty )
- amp ^= volume;
-
- {
- int delta = update_amp( amp );
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- const Synth& synth = this->synth;
- int delta = amp * 2 - volume;
- int phase = this->phase;
-
- do {
- phase = (phase + 1) & (phase_range - 1);
- if ( phase == 0 || phase == duty ) {
- delta = -delta;
- synth.offset_inline( time, delta, output );
- }
- time += timer_period;
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->phase = phase;
- }
- }
-
- delay = time - end_time;
-}
-
-// Nes_Triangle
-
-void Nes_Triangle::clock_linear_counter()
-{
- if ( reg_written [3] )
- linear_counter = regs [0] & 0x7F;
- else if ( linear_counter )
- linear_counter--;
-
- if ( !(regs [0] & 0x80) )
- reg_written [3] = false;
-}
-
-inline int Nes_Triangle::calc_amp() const
-{
- int amp = phase_range - phase;
- if ( amp < 0 )
- amp = phase - (phase_range + 1);
- return amp;
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period )
-{
- nes_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- int count = (remain + timer_period - 1) / timer_period;
- phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
- phase++;
- time += (blargg_long) count * timer_period;
- }
- return time;
-}
-
-void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
-{
- const int timer_period = period() + 1;
- if ( !output )
- {
- time += delay;
- delay = 0;
- if ( length_counter && linear_counter && timer_period >= 3 )
- delay = maintain_phase( time, end_time, timer_period ) - end_time;
- return;
- }
-
- output->set_modified();
-
- // to do: track phase when period < 3
- // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
-
- int delta = update_amp( calc_amp() );
- if ( delta )
- synth.offset( time, delta, output );
-
- time += delay;
- if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
- {
- time = end_time;
- }
- else if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
-
- int phase = this->phase;
- int volume = 1;
- if ( phase > phase_range ) {
- phase -= phase_range;
- volume = -volume;
- }
-
- do {
- if ( --phase == 0 ) {
- phase = phase_range;
- volume = -volume;
- }
- else {
- synth.offset_inline( time, volume, output );
- }
-
- time += timer_period;
- }
- while ( time < end_time );
-
- if ( volume < 0 )
- phase += phase_range;
- this->phase = phase;
- last_amp = calc_amp();
- }
- delay = time - end_time;
-}
-
-// Nes_Dmc
-
-void Nes_Dmc::reset()
-{
- address = 0;
- dac = 0;
- buf = 0;
- bits_remain = 1;
- bits = 0;
- buf_full = false;
- silence = true;
- next_irq = Nes_Apu::no_irq;
- irq_flag = false;
- irq_enabled = false;
-
- Nes_Osc::reset();
- period = 0x1AC;
-}
-
-void Nes_Dmc::recalc_irq()
-{
- nes_time_t irq = Nes_Apu::no_irq;
- if ( irq_enabled && length_counter )
- irq = apu->last_dmc_time + delay +
- ((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t (period) + 1;
- if ( irq != next_irq ) {
- next_irq = irq;
- apu->irq_changed();
- }
-}
-
-int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
-{
- if ( last_read )
- *last_read = time;
-
- if ( length_counter == 0 )
- return 0; // not reading
-
- nes_time_t first_read = next_read_time();
- nes_time_t avail = time - first_read;
- if ( avail <= 0 )
- return 0;
-
- int count = (avail - 1) / (period * 8) + 1;
- if ( !(regs [0] & loop_flag) && count > length_counter )
- count = length_counter;
-
- if ( last_read )
- {
- *last_read = first_read + (count - 1) * (period * 8) + 1;
- check( *last_read <= time );
- check( count == count_reads( *last_read, NULL ) );
- check( count - 1 == count_reads( *last_read - 1, NULL ) );
- }
-
- return count;
-}
-
-static short const dmc_period_table [2] [16] = {
- {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
- 190, 160, 142, 128, 106, 84, 72, 54},
-
- {398, 354, 316, 298, 276, 236, 210, 198, // PAL
- 176, 148, 132, 118, 98, 78, 66, 50}
-};
-
-inline void Nes_Dmc::reload_sample()
-{
- address = 0x4000 + regs [2] * 0x40;
- length_counter = regs [3] * 0x10 + 1;
-}
-
-static byte const dac_table [128] =
-{
- 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
- 15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
- 27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
- 39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
- 50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
- 59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
- 68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
- 76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
-};
-
-void Nes_Dmc::write_register( int addr, int data )
-{
- if ( addr == 0 )
- {
- period = dmc_period_table [pal_mode] [data & 15];
- irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
- irq_flag &= irq_enabled;
- recalc_irq();
- }
- else if ( addr == 1 )
- {
- int old_dac = dac;
- dac = data & 0x7F;
-
- // adjust last_amp so that "pop" amplitude will be properly non-linear
- // with respect to change in dac
- int faked_nonlinear = dac - (dac_table [dac] - dac_table [old_dac]);
- if ( !nonlinear )
- last_amp = faked_nonlinear;
- }
-}
-
-void Nes_Dmc::start()
-{
- reload_sample();
- fill_buffer();
- recalc_irq();
-}
-
-void Nes_Dmc::fill_buffer()
-{
- if ( !buf_full && length_counter )
- {
- require( prg_reader ); // prg_reader must be set
- buf = prg_reader( prg_reader_data, 0x8000u + address );
- address = (address + 1) & 0x7FFF;
- buf_full = true;
- if ( --length_counter == 0 )
- {
- if ( regs [0] & loop_flag ) {
- reload_sample();
- }
- else {
- apu->osc_enables &= ~0x10;
- irq_flag = irq_enabled;
- next_irq = Nes_Apu::no_irq;
- apu->irq_changed();
- }
- }
- }
-}
-
-void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
-{
- int delta = update_amp( dac );
- if ( !output )
- {
- silence = true;
- }
- else
- {
- output->set_modified();
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- int bits_remain = this->bits_remain;
- if ( silence && !buf_full )
- {
- int count = (end_time - time + period - 1) / period;
- bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
- time += count * period;
- }
- else
- {
- Blip_Buffer* const output = this->output;
- const int period = this->period;
- int bits = this->bits;
- int dac = this->dac;
-
- do
- {
- if ( !silence )
- {
- int step = (bits & 1) * 4 - 2;
- bits >>= 1;
- if ( unsigned (dac + step) <= 0x7F ) {
- dac += step;
- synth.offset_inline( time, step, output );
- }
- }
-
- time += period;
-
- if ( --bits_remain == 0 )
- {
- bits_remain = 8;
- if ( !buf_full ) {
- silence = true;
- }
- else {
- silence = false;
- bits = buf;
- buf_full = false;
- if ( !output )
- silence = true;
- fill_buffer();
- }
- }
- }
- while ( time < end_time );
-
- this->dac = dac;
- this->last_amp = dac;
- this->bits = bits;
- }
- this->bits_remain = bits_remain;
- }
- delay = time - end_time;
-}
-
-// Nes_Noise
-
-static short const noise_period_table [16] = {
- 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
- 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
-};
-
-void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
-{
- int period = noise_period_table [regs [2] & 15];
-
- if ( !output )
- {
- // TODO: clean up
- time += delay;
- delay = time + (end_time - time + period - 1) / period * period - end_time;
- return;
- }
-
- output->set_modified();
-
- const int volume = this->volume();
- int amp = (noise & 1) ? volume : 0;
- {
- int delta = update_amp( amp );
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- const int mode_flag = 0x80;
-
- if ( !volume )
- {
- // round to next multiple of period
- time += (end_time - time + period - 1) / period * period;
-
- // approximate noise cycling while muted, by shuffling up noise register
- // to do: precise muted noise cycling?
- if ( !(regs [2] & mode_flag) ) {
- int feedback = (noise << 13) ^ (noise << 14);
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- }
- else
- {
- Blip_Buffer* const output = this->output;
-
- // using resampled time avoids conversion in synth.offset()
- blip_resampled_time_t rperiod = output->resampled_duration( period );
- blip_resampled_time_t rtime = output->resampled_time( time );
-
- int noise = this->noise;
- int delta = amp * 2 - volume;
- const int tap = (regs [2] & mode_flag ? 8 : 13);
-
- do {
- int feedback = (noise << tap) ^ (noise << 14);
- time += period;
-
- if ( (noise + 1) & 2 ) {
- // bits 0 and 1 of noise differ
- delta = -delta;
- synth.offset_resampled( rtime, delta, output );
- }
-
- rtime += rperiod;
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->noise = noise;
- }
- }
-
- delay = time - end_time;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.h
deleted file mode 100644
index b675bfb4..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Oscs.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Private oscillators used by Nes_Apu
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_OSCS_H
-#define NES_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Nes_Apu;
-
-struct Nes_Osc
-{
- unsigned char regs [4];
- bool reg_written [4];
- Blip_Buffer* output;
- int length_counter;// length counter (0 if unused by oscillator)
- int delay; // delay until next (potential) transition
- int last_amp; // last amplitude oscillator was outputting
-
- void clock_length( int halt_mask );
- int period() const {
- return (regs [3] & 7) * 0x100 + (regs [2] & 0xFF);
- }
- void reset() {
- delay = 0;
- last_amp = 0;
- }
- int update_amp( int amp ) {
- int delta = amp - last_amp;
- last_amp = amp;
- return delta;
- }
-};
-
-struct Nes_Envelope : Nes_Osc
-{
- int envelope;
- int env_delay;
-
- void clock_envelope();
- int volume() const;
- void reset() {
- envelope = 0;
- env_delay = 0;
- Nes_Osc::reset();
- }
-};
-
-// Nes_Square
-struct Nes_Square : Nes_Envelope
-{
- enum { negate_flag = 0x08 };
- enum { shift_mask = 0x07 };
- enum { phase_range = 8 };
- int phase;
- int sweep_delay;
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- Synth const& synth; // shared between squares
-
- Nes_Square( Synth const* s ) : synth( *s ) { }
-
- void clock_sweep( int adjust );
- void run( nes_time_t, nes_time_t );
- void reset() {
- sweep_delay = 0;
- Nes_Envelope::reset();
- }
- nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period );
-};
-
-// Nes_Triangle
-struct Nes_Triangle : Nes_Osc
-{
- enum { phase_range = 16 };
- int phase;
- int linear_counter;
- Blip_Synth<blip_med_quality,1> synth;
-
- int calc_amp() const;
- void run( nes_time_t, nes_time_t );
- void clock_linear_counter();
- void reset() {
- linear_counter = 0;
- phase = 1;
- Nes_Osc::reset();
- }
- nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period );
-};
-
-// Nes_Noise
-struct Nes_Noise : Nes_Envelope
-{
- int noise;
- Blip_Synth<blip_med_quality,1> synth;
-
- void run( nes_time_t, nes_time_t );
- void reset() {
- noise = 1 << 14;
- Nes_Envelope::reset();
- }
-};
-
-// Nes_Dmc
-struct Nes_Dmc : Nes_Osc
-{
- int address; // address of next byte to read
- int period;
- //int length_counter; // bytes remaining to play (already defined in Nes_Osc)
- int buf;
- int bits_remain;
- int bits;
- bool buf_full;
- bool silence;
-
- enum { loop_flag = 0x40 };
-
- int dac;
-
- nes_time_t next_irq;
- bool irq_enabled;
- bool irq_flag;
- bool pal_mode;
- bool nonlinear;
-
- int (*prg_reader)( void*, nes_addr_t ); // needs to be initialized to prg read function
- void* prg_reader_data;
-
- Nes_Apu* apu;
-
- Blip_Synth<blip_med_quality,1> synth;
-
- void start();
- void write_register( int, int );
- void run( nes_time_t, nes_time_t );
- void recalc_irq();
- void fill_buffer();
- void reload_sample();
- void reset();
- int count_reads( nes_time_t, nes_time_t* ) const;
- nes_time_t next_read_time() const;
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.cpp
deleted file mode 100644
index d178407c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Vrc6_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Vrc6_Apu::Nes_Vrc6_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-void Nes_Vrc6_Apu::reset()
-{
- last_time = 0;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc& osc = oscs [i];
- for ( int j = 0; j < reg_count; j++ )
- osc.regs [j] = 0;
- osc.delay = 0;
- osc.last_amp = 0;
- osc.phase = 1;
- osc.amp = 0;
- }
-}
-
-void Nes_Vrc6_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-void Nes_Vrc6_Apu::run_until( blip_time_t time )
-{
- require( time >= last_time );
- run_square( oscs [0], time );
- run_square( oscs [1], time );
- run_saw( time );
- last_time = time;
-}
-
-void Nes_Vrc6_Apu::write_osc( blip_time_t time, int osc_index, int reg, int data )
-{
- require( (unsigned) osc_index < osc_count );
- require( (unsigned) reg < reg_count );
-
- run_until( time );
- oscs [osc_index].regs [reg] = data;
-}
-
-void Nes_Vrc6_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const
-{
- assert( sizeof (vrc6_apu_state_t) == 20 );
- out->saw_amp = oscs [2].amp;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc const& osc = oscs [i];
- for ( int r = 0; r < reg_count; r++ )
- out->regs [i] [r] = osc.regs [r];
-
- out->delays [i] = osc.delay;
- out->phases [i] = osc.phase;
- }
-}
-
-void Nes_Vrc6_Apu::load_state( vrc6_apu_state_t const& in )
-{
- reset();
- oscs [2].amp = in.saw_amp;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc& osc = oscs [i];
- for ( int r = 0; r < reg_count; r++ )
- osc.regs [r] = in.regs [i] [r];
-
- osc.delay = in.delays [i];
- osc.phase = in.phases [i];
- }
- if ( !oscs [2].phase )
- oscs [2].phase = 1;
-}
-
-void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, blip_time_t end_time )
-{
- Blip_Buffer* output = osc.output;
- if ( !output )
- return;
- output->set_modified();
-
- int volume = osc.regs [0] & 15;
- if ( !(osc.regs [2] & 0x80) )
- volume = 0;
-
- int gate = osc.regs [0] & 0x80;
- int duty = ((osc.regs [0] >> 4) & 7) + 1;
- int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp;
- blip_time_t time = last_time;
- if ( delta )
- {
- osc.last_amp += delta;
- square_synth.offset( time, delta, output );
- }
-
- time += osc.delay;
- osc.delay = 0;
- int period = osc.period();
- if ( volume && !gate && period > 4 )
- {
- if ( time < end_time )
- {
- int phase = osc.phase;
-
- do
- {
- phase++;
- if ( phase == 16 )
- {
- phase = 0;
- osc.last_amp = volume;
- square_synth.offset( time, volume, output );
- }
- if ( phase == duty )
- {
- osc.last_amp = 0;
- square_synth.offset( time, -volume, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- osc.phase = phase;
- }
- osc.delay = time - end_time;
- }
-}
-
-void Nes_Vrc6_Apu::run_saw( blip_time_t end_time )
-{
- Vrc6_Osc& osc = oscs [2];
- Blip_Buffer* output = osc.output;
- if ( !output )
- return;
- output->set_modified();
-
- int amp = osc.amp;
- int amp_step = osc.regs [0] & 0x3F;
- blip_time_t time = last_time;
- int last_amp = osc.last_amp;
- if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) )
- {
- osc.delay = 0;
- int delta = (amp >> 3) - last_amp;
- last_amp = amp >> 3;
- saw_synth.offset( time, delta, output );
- }
- else
- {
- time += osc.delay;
- if ( time < end_time )
- {
- int period = osc.period() * 2;
- int phase = osc.phase;
-
- do
- {
- if ( --phase == 0 )
- {
- phase = 7;
- amp = 0;
- }
-
- int delta = (amp >> 3) - last_amp;
- if ( delta )
- {
- last_amp = amp >> 3;
- saw_synth.offset( time, delta, output );
- }
-
- time += period;
- amp = (amp + amp_step) & 0xFF;
- }
- while ( time < end_time );
-
- osc.phase = phase;
- osc.amp = amp;
- }
-
- osc.delay = time - end_time;
- }
-
- osc.last_amp = last_amp;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.h
deleted file mode 100644
index 18722233..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nes_Vrc6_Apu.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Konami VRC6 sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_VRC6_APU_H
-#define NES_VRC6_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct vrc6_apu_state_t;
-
-class Nes_Vrc6_Apu {
-public:
- // See Nes_Apu.h for reference
- void reset();
- void volume( double );
- void treble_eq( blip_eq_t const& );
- void output( Blip_Buffer* );
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
- void end_frame( blip_time_t );
- void save_state( vrc6_apu_state_t* ) const;
- void load_state( vrc6_apu_state_t const& );
-
- // Oscillator 0 write-only registers are at $9000-$9002
- // Oscillator 1 write-only registers are at $A000-$A002
- // Oscillator 2 write-only registers are at $B000-$B002
- enum { reg_count = 3 };
- enum { base_addr = 0x9000 };
- enum { addr_step = 0x1000 };
- void write_osc( blip_time_t, int osc, int reg, int data );
-
-public:
- Nes_Vrc6_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Vrc6_Apu( const Nes_Vrc6_Apu& );
- Nes_Vrc6_Apu& operator = ( const Nes_Vrc6_Apu& );
-
- struct Vrc6_Osc
- {
- BOOST::uint8_t regs [3];
- Blip_Buffer* output;
- int delay;
- int last_amp;
- int phase;
- int amp; // only used by saw
-
- int period() const
- {
- return (regs [2] & 0x0F) * 0x100L + regs [1] + 1;
- }
- };
-
- Vrc6_Osc oscs [osc_count];
- blip_time_t last_time;
-
- Blip_Synth<blip_med_quality,1> saw_synth;
- Blip_Synth<blip_good_quality,1> square_synth;
-
- void run_until( blip_time_t );
- void run_square( Vrc6_Osc& osc, blip_time_t );
- void run_saw( blip_time_t );
-};
-
-struct vrc6_apu_state_t
-{
- BOOST::uint8_t regs [3] [3];
- BOOST::uint8_t saw_amp;
- BOOST::uint16_t delays [3];
- BOOST::uint8_t phases [3];
- BOOST::uint8_t unused;
-};
-
-inline void Nes_Vrc6_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Vrc6_Apu::volume( double v )
-{
- double const factor = 0.0967 * 2;
- saw_synth.volume( factor / 31 * v );
- square_synth.volume( factor * 0.5 / 15 * v );
-}
-
-inline void Nes_Vrc6_Apu::treble_eq( blip_eq_t const& eq )
-{
- saw_synth.treble_eq( eq );
- square_synth.treble_eq( eq );
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.cpp
deleted file mode 100644
index 678bddb2..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Nsf_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <stdio.h>
-
-#if !NSF_EMU_APU_ONLY
- #include "Nes_Namco_Apu.h"
- #include "Nes_Vrc6_Apu.h"
- #include "Nes_Fme7_Apu.h"
-#endif
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const vrc6_flag = 0x01;
-int const namco_flag = 0x10;
-int const fme7_flag = 0x20;
-
-long const clock_divisor = 12;
-
-Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = { -1.0, 80 };
-Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80 };
-
-int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
-{
- return *((Nsf_Emu*) emu)->cpu::get_code( addr );
-}
-
-Nsf_Emu::Nsf_Emu()
-{
- vrc6 = 0;
- namco = 0;
- fme7 = 0;
-
- set_type( gme_nsf_type );
- set_silence_lookahead( 6 );
- apu.dmc_reader( pcm_read, this );
- Music_Emu::set_equalizer( nes_eq );
- set_gain( 1.4 );
- memset( unmapped_code, Nes_Cpu::bad_opcode, sizeof unmapped_code );
-}
-
-Nsf_Emu::~Nsf_Emu() { unload(); }
-
-void Nsf_Emu::unload()
-{
- #if !NSF_EMU_APU_ONLY
- {
- delete vrc6;
- vrc6 = 0;
-
- delete namco;
- namco = 0;
-
- delete fme7;
- fme7 = 0;
- }
- #endif
-
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
- if ( h.chip_flags )
- Gme_File::copy_field_( out->system, "Famicom" );
-}
-
-blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_nsf_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_nsf_header( void const* header )
-{
- if ( memcmp( header, "NESM\x1A", 5 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Nsf_File : Gme_Info_
-{
- Nsf_Emu::header_t h;
-
- Nsf_File() { set_type( gme_nsf_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &h, Nsf_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
-
- if ( h.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
- set_warning( "Uses unsupported audio expansion hardware" );
-
- set_track_count( h.track_count );
- return check_nsf_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_nsf_fields( h, out );
- return 0;
- }
-};
-
-static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
-static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
-
-gme_type_t_ const gme_nsf_type [1] = { "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 };
-
-// Setup
-
-void Nsf_Emu::set_tempo_( double t )
-{
- unsigned playback_rate = get_le16( header_.ntsc_speed );
- unsigned standard_rate = 0x411A;
- clock_rate_ = 1789772.72727;
- play_period = 262 * 341L * 4 - 2; // two fewer PPU clocks every four frames
-
- if ( pal_only )
- {
- play_period = 33247 * clock_divisor;
- clock_rate_ = 1662607.125;
- standard_rate = 0x4E20;
- playback_rate = get_le16( header_.pal_speed );
- }
-
- if ( !playback_rate )
- playback_rate = standard_rate;
-
- if ( playback_rate != standard_rate || t != 1.0 )
- play_period = long (playback_rate * clock_rate_ / (1000000.0 / clock_divisor * t));
-
- apu.set_tempo( t );
-}
-
-blargg_err_t Nsf_Emu::init_sound()
-{
- if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
- set_warning( "Uses unsupported audio expansion hardware" );
-
- {
- #define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC"
-
- int const count = Nes_Apu::osc_count;
- static const char* const apu_names [count] = { APU_NAMES };
- set_voice_count( count );
- set_voice_names( apu_names );
-
- }
-
- static int const types [] = {
- wave_type | 1, wave_type | 2, wave_type | 0,
- noise_type | 0, mixed_type | 1,
- wave_type | 3, wave_type | 4, wave_type | 5,
- wave_type | 6, wave_type | 7, wave_type | 8, wave_type | 9,
- wave_type |10, wave_type |11, wave_type |12, wave_type |13
- };
- set_voice_types( types ); // common to all sound chip configurations
-
- double adjusted_gain = gain();
-
- #if NSF_EMU_APU_ONLY
- {
- if ( header_.chip_flags )
- set_warning( "Uses unsupported audio expansion hardware" );
- }
- #else
- {
- if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) )
- set_voice_count( Nes_Apu::osc_count + 3 );
-
- if ( header_.chip_flags & namco_flag )
- {
- namco = BLARGG_NEW Nes_Namco_Apu;
- CHECK_ALLOC( namco );
- adjusted_gain *= 0.75;
-
- int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( header_.chip_flags & vrc6_flag )
- {
- vrc6 = BLARGG_NEW Nes_Vrc6_Apu;
- CHECK_ALLOC( vrc6 );
- adjusted_gain *= 0.75;
-
- {
- int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Saw Wave", "Square 3", "Square 4"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( header_.chip_flags & namco_flag )
- {
- int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count +
- Nes_Namco_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Saw Wave", "Square 3", "Square 4",
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
- }
-
- if ( header_.chip_flags & fme7_flag )
- {
- fme7 = BLARGG_NEW Nes_Fme7_Apu;
- CHECK_ALLOC( fme7 );
- adjusted_gain *= 0.75;
-
- int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Square 3", "Square 4", "Square 5"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( namco ) namco->volume( adjusted_gain );
- if ( vrc6 ) vrc6 ->volume( adjusted_gain );
- if ( fme7 ) fme7 ->volume( adjusted_gain );
- }
- #endif
-
- apu.volume( adjusted_gain );
-
- return 0;
-}
-
-blargg_err_t Nsf_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,unused [4]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
- set_track_count( header_.track_count );
- RETURN_ERR( check_nsf_header( &header_ ) );
-
- if ( header_.vers != 1 )
- set_warning( "Unknown file version" );
-
- // sound and memory
- blargg_err_t err = init_sound();
- if ( err )
- return err;
-
- // set up data
- nes_addr_t load_addr = get_le16( header_.load_addr );
- init_addr = get_le16( header_.init_addr );
- play_addr = get_le16( header_.play_addr );
- if ( !load_addr ) load_addr = rom_begin;
- if ( !init_addr ) init_addr = rom_begin;
- if ( !play_addr ) play_addr = rom_begin;
- if ( load_addr < rom_begin || init_addr < rom_begin )
- {
- const char* w = warning();
- if ( !w )
- w = "Corrupt file (invalid load/init/play address)";
- return w;
- }
-
- rom.set_addr( load_addr % bank_size );
- int total_banks = rom.size() / bank_size;
-
- // bank switching
- int first_bank = (load_addr - rom_begin) / bank_size;
- for ( int i = 0; i < bank_count; i++ )
- {
- unsigned bank = i - first_bank;
- if ( bank >= (unsigned) total_banks )
- bank = 0;
- initial_banks [i] = bank;
-
- if ( header_.banks [i] )
- {
- // bank-switched
- memcpy( initial_banks, header_.banks, sizeof initial_banks );
- break;
- }
- }
-
- pal_only = (header_.speed_flags & 3) == 1;
-
- #if !NSF_EMU_EXTRA_FLAGS
- header_.speed_flags = 0;
- #endif
-
- set_tempo( tempo() );
-
- return setup_buffer( (long) (clock_rate_ + 0.5) );
-}
-
-void Nsf_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->treble_eq( eq );
- if ( vrc6 ) vrc6 ->treble_eq( eq );
- if ( fme7 ) fme7 ->treble_eq( eq );
- }
- #endif
-}
-
-void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
-{
- if ( i < Nes_Apu::osc_count )
- {
- apu.osc_output( i, buf );
- return;
- }
- i -= Nes_Apu::osc_count;
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( fme7 && i < Nes_Fme7_Apu::osc_count )
- {
- fme7->osc_output( i, buf );
- return;
- }
-
- if ( vrc6 )
- {
- if ( i < Nes_Vrc6_Apu::osc_count )
- {
- // put saw first
- if ( --i < 0 )
- i = 2;
- vrc6->osc_output( i, buf );
- return;
- }
- i -= Nes_Vrc6_Apu::osc_count;
- }
-
- if ( namco && i < Nes_Namco_Apu::osc_count )
- {
- namco->osc_output( i, buf );
- return;
- }
- }
- #endif
-}
-
-// Emulation
-
-// see nes_cpu_io.h for read/write functions
-
-void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
-{
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco )
- {
- switch ( addr )
- {
- case Nes_Namco_Apu::data_reg_addr:
- namco->write_data( time(), data );
- return;
-
- case Nes_Namco_Apu::addr_reg_addr:
- namco->write_addr( data );
- return;
- }
- }
-
- if ( addr >= Nes_Fme7_Apu::latch_addr && fme7 )
- {
- switch ( addr & Nes_Fme7_Apu::addr_mask )
- {
- case Nes_Fme7_Apu::latch_addr:
- fme7->write_latch( data );
- return;
-
- case Nes_Fme7_Apu::data_addr:
- fme7->write_data( time(), data );
- return;
- }
- }
-
- if ( vrc6 )
- {
- unsigned reg = addr & (Nes_Vrc6_Apu::addr_step - 1);
- unsigned osc = unsigned (addr - Nes_Vrc6_Apu::base_addr) / Nes_Vrc6_Apu::addr_step;
- if ( osc < Nes_Vrc6_Apu::osc_count && reg < Nes_Vrc6_Apu::reg_count )
- {
- vrc6->write_osc( time(), osc, reg, data );
- return;
- }
- }
- }
- #endif
-
- // unmapped write
-
- #ifndef NDEBUG
- {
- // some games write to $8000 and $8001 repeatedly
- if ( addr == 0x8000 || addr == 0x8001 ) return;
-
- // probably namco sound mistakenly turned on in mck
- if ( addr == 0x4800 || addr == 0xF800 ) return;
-
- // memory mapper?
- if ( addr == 0xFFF8 ) return;
-
- dprintf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
- }
- #endif
-}
-
-blargg_err_t Nsf_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( low_mem, 0, sizeof low_mem );
- memset( sram, 0, sizeof sram );
-
- cpu::reset( unmapped_code ); // also maps low_mem
- cpu::map_code( sram_addr, sizeof sram, sram );
- for ( int i = 0; i < bank_count; ++i )
- cpu_write( bank_select_addr + i, initial_banks [i] );
-
- apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
- apu.write_register( 0, 0x4015, 0x0F );
- apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->reset();
- if ( vrc6 ) vrc6 ->reset();
- if ( fme7 ) fme7 ->reset();
- }
- #endif
-
- play_ready = 4;
- play_extra = 0;
- next_play = play_period / clock_divisor;
-
- saved_state.pc = badop_addr;
- low_mem [0x1FF] = (badop_addr - 1) >> 8;
- low_mem [0x1FE] = (badop_addr - 1) & 0xFF;
- r.sp = 0xFD;
- r.pc = init_addr;
- r.a = track;
- r.x = pal_only;
-
- return 0;
-}
-
-blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- while ( time() < duration )
- {
- nes_time_t end = min( (blip_time_t) next_play, duration );
- end = min( end, time() + 32767 ); // allows CPU to use 16-bit time delta
- if ( cpu::run( end ) )
- {
- if ( r.pc != badop_addr )
- {
- set_warning( "Emulation error (illegal instruction)" );
- r.pc++;
- }
- else
- {
- play_ready = 1;
- if ( saved_state.pc != badop_addr )
- {
- cpu::r = saved_state;
- saved_state.pc = badop_addr;
- }
- else
- {
- set_time( end );
- }
- }
- }
-
- if ( time() >= next_play )
- {
- nes_time_t period = (play_period + play_extra) / clock_divisor;
- play_extra = play_period - period * clock_divisor;
- next_play += period;
- if ( play_ready && !--play_ready )
- {
- check( saved_state.pc == badop_addr );
- if ( r.pc != badop_addr )
- saved_state = cpu::r;
-
- r.pc = play_addr;
- low_mem [0x100 + r.sp--] = (badop_addr - 1) >> 8;
- low_mem [0x100 + r.sp--] = (badop_addr - 1) & 0xFF;
- GME_FRAME_HOOK( this );
- }
- }
- }
-
- if ( cpu::error_count() )
- {
- cpu::clear_error_count();
- set_warning( "Emulation error (illegal instruction)" );
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- if ( next_play < 0 )
- next_play = 0;
-
- apu.end_frame( duration );
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->end_frame( duration );
- if ( vrc6 ) vrc6 ->end_frame( duration );
- if ( fme7 ) fme7 ->end_frame( duration );
- }
- #endif
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.h
deleted file mode 100644
index e06b9172..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsf_Emu.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Nintendo NES/Famicom NSF music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef NSF_EMU_H
-#define NSF_EMU_H
-
-#include "Classic_Emu.h"
-#include "Nes_Apu.h"
-#include "Nes_Cpu.h"
-
-class Nsf_Emu : private Nes_Cpu, public Classic_Emu {
- typedef Nes_Cpu cpu;
-public:
- // Equalizer profiles for US NES and Japanese Famicom
- static equalizer_t const nes_eq;
- static equalizer_t const famicom_eq;
-
- // NSF file header
- enum { header_size = 0x80 };
- struct header_t
- {
- char tag [5];
- byte vers;
- byte track_count;
- byte first_track;
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- char game [32];
- char author [32];
- char copyright [32];
- byte ntsc_speed [2];
- byte banks [8];
- byte pal_speed [2];
- byte speed_flags;
- byte chip_flags;
- byte unused [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_nsf_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
-
-public:
- Nsf_Emu();
- ~Nsf_Emu();
- Nes_Apu* apu_() { return &apu; }
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-protected:
- enum { bank_count = 8 };
- byte initial_banks [bank_count];
- nes_addr_t init_addr;
- nes_addr_t play_addr;
- double clock_rate_;
- bool pal_only;
-
- // timing
- Nes_Cpu::registers_t saved_state;
- nes_time_t next_play;
- nes_time_t play_period;
- int play_extra;
- int play_ready;
-
- enum { rom_begin = 0x8000 };
- enum { bank_select_addr = 0x5FF8 };
- enum { bank_size = 0x1000 };
- Rom_Data<bank_size> rom;
-
-public: private: friend class Nes_Cpu;
- void cpu_jsr( nes_addr_t );
- int cpu_read( nes_addr_t );
- void cpu_write( nes_addr_t, int );
- void cpu_write_misc( nes_addr_t, int );
- enum { badop_addr = bank_select_addr };
-
-private:
- class Nes_Namco_Apu* namco;
- class Nes_Vrc6_Apu* vrc6;
- class Nes_Fme7_Apu* fme7;
- Nes_Apu apu;
- static int pcm_read( void*, nes_addr_t );
- blargg_err_t init_sound();
-
- header_t header_;
-
- enum { sram_addr = 0x6000 };
- byte sram [0x2000];
- byte unmapped_code [Nes_Cpu::page_size + 8];
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.cpp
deleted file mode 100644
index 0a785e60..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Nsfe_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
-
-Nsfe_Info::~Nsfe_Info() { }
-
-inline void Nsfe_Info::unload()
-{
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-}
-
-// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
-void Nsfe_Info::disable_playlist( bool b )
-{
- playlist_disabled = b;
- info.track_count = playlist.size();
- if ( !info.track_count || playlist_disabled )
- info.track_count = actual_track_count_;
-}
-
-int Nsfe_Info::remap_track( int track ) const
-{
- if ( !playlist_disabled && (unsigned) track < playlist.size() )
- track = playlist [track];
- return track;
-}
-
-// Read multiple strings and separate into individual strings
-static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
- blargg_vector<const char*>& strs )
-{
- RETURN_ERR( chars.resize( size + 1 ) );
- chars [size] = 0; // in case last string doesn't have terminator
- RETURN_ERR( in.read( &chars [0], size ) );
-
- RETURN_ERR( strs.resize( 128 ) );
- int count = 0;
- for ( int i = 0; i < size; i++ )
- {
- if ( (int) strs.size() <= count )
- RETURN_ERR( strs.resize( count * 2 ) );
- strs [count++] = &chars [i];
- while ( i < size && chars [i] )
- i++;
- }
-
- return strs.resize( count );
-}
-
-// Copy in to out, where out has out_max characters allocated. Truncate to
-// out_max - 1 characters.
-static void copy_str( const char* in, char* out, int out_max )
-{
- out [out_max - 1] = 0;
- strncpy( out, in, out_max - 1 );
-}
-
-struct nsfe_info_t
-{
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte speed_flags;
- byte chip_flags;
- byte track_count;
- byte first_track;
- byte unused [6];
-};
-
-blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
-{
- int const nsfe_info_size = 16;
- assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
-
- // check header
- byte signature [4];
- blargg_err_t err = in.read( signature, sizeof signature );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- if ( memcmp( signature, "NSFE", 4 ) )
- return gme_wrong_file_type;
-
- // free previous info
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-
- // default nsf header
- static const Nsf_Emu::header_t base_header =
- {
- {'N','E','S','M','\x1A'},// tag
- 1, // version
- 1, 1, // track count, first track
- {0,0},{0,0},{0,0}, // addresses
- "","","", // strings
- {0x1A, 0x41}, // NTSC rate
- {0,0,0,0,0,0,0,0}, // banks
- {0x20, 0x4E}, // PAL rate
- 0, 0, // flags
- {0,0,0,0} // unused
- };
- Nsf_Emu::header_t& header = info;
- header = base_header;
-
- // parse tags
- int phase = 0;
- while ( phase != 3 )
- {
- // read size and tag
- byte block_header [2] [4];
- RETURN_ERR( in.read( block_header, sizeof block_header ) );
- blargg_long size = get_le32( block_header [0] );
- blargg_long tag = get_le32( block_header [1] );
-
- //dprintf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
-
- switch ( tag )
- {
- case BLARGG_4CHAR('O','F','N','I'): {
- check( phase == 0 );
- if ( size < 8 )
- return "Corrupt file";
-
- nsfe_info_t finfo;
- finfo.track_count = 1;
- finfo.first_track = 0;
-
- RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
- if ( size > nsfe_info_size )
- RETURN_ERR( in.skip( size - nsfe_info_size ) );
- phase = 1;
- info.speed_flags = finfo.speed_flags;
- info.chip_flags = finfo.chip_flags;
- info.track_count = finfo.track_count;
- this->actual_track_count_ = finfo.track_count;
- info.first_track = finfo.first_track;
- memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
- break;
- }
-
- case BLARGG_4CHAR('K','N','A','B'):
- if ( size > (int) sizeof info.banks )
- return "Corrupt file";
- RETURN_ERR( in.read( info.banks, size ) );
- break;
-
- case BLARGG_4CHAR('h','t','u','a'): {
- blargg_vector<char> chars;
- blargg_vector<const char*> strs;
- RETURN_ERR( read_strs( in, size, chars, strs ) );
- int n = strs.size();
-
- if ( n > 3 )
- copy_str( strs [3], info.dumper, sizeof info.dumper );
-
- if ( n > 2 )
- copy_str( strs [2], info.copyright, sizeof info.copyright );
-
- if ( n > 1 )
- copy_str( strs [1], info.author, sizeof info.author );
-
- if ( n > 0 )
- copy_str( strs [0], info.game, sizeof info.game );
-
- break;
- }
-
- case BLARGG_4CHAR('e','m','i','t'):
- RETURN_ERR( track_times.resize( size / 4 ) );
- RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
- break;
-
- case BLARGG_4CHAR('l','b','l','t'):
- RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
- break;
-
- case BLARGG_4CHAR('t','s','l','p'):
- RETURN_ERR( playlist.resize( size ) );
- RETURN_ERR( in.read( &playlist [0], size ) );
- break;
-
- case BLARGG_4CHAR('A','T','A','D'): {
- check( phase == 1 );
- phase = 2;
- if ( !nsf_emu )
- {
- RETURN_ERR( in.skip( size ) );
- }
- else
- {
- Subset_Reader sub( &in, size ); // limit emu to nsf data
- Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
- RETURN_ERR( nsf_emu->load( rem ) );
- check( rem.remain() == 0 );
- }
- break;
- }
-
- case BLARGG_4CHAR('D','N','E','N'):
- check( phase == 2 );
- phase = 3;
- break;
-
- default:
- // tags that can be skipped start with a lowercase character
- check( islower( (tag >> 24) & 0xFF ) );
- RETURN_ERR( in.skip( size ) );
- break;
- }
- }
-
- return 0;
-}
-
-blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
-{
- int remapped = remap_track( track );
- if ( (unsigned) remapped < track_times.size() )
- {
- long length = (BOOST::int32_t) get_le32( track_times [remapped] );
- if ( length > 0 )
- out->length = length;
- }
- if ( (unsigned) remapped < track_names.size() )
- Gme_File::copy_field_( out->song, track_names [remapped] );
-
- GME_COPY_FIELD( info, out, game );
- GME_COPY_FIELD( info, out, author );
- GME_COPY_FIELD( info, out, copyright );
- GME_COPY_FIELD( info, out, dumper );
- return 0;
-}
-
-Nsfe_Emu::Nsfe_Emu()
-{
- loading = false;
- set_type( gme_nsfe_type );
-}
-
-Nsfe_Emu::~Nsfe_Emu() { }
-
-void Nsfe_Emu::unload()
-{
- if ( !loading )
- info.unload(); // TODO: extremely hacky!
- Nsf_Emu::unload();
-}
-
-blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
-{
- return info.track_info_( out, track );
-}
-
-struct Nsfe_File : Gme_Info_
-{
- Nsfe_Info info;
-
- Nsfe_File() { set_type( gme_nsfe_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- RETURN_ERR( info.load( in, 0 ) );
- info.disable_playlist( false );
- set_track_count( info.info.track_count );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- return info.track_info_( out, track );
- }
-};
-
-static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
-static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
-
-gme_type_t_ const gme_nsfe_type [1] = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
-
-blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
-{
- if ( loading )
- return Nsf_Emu::load_( in );
-
- // TODO: this hacky recursion-avoidance could have subtle problems
- loading = true;
- blargg_err_t err = info.load( in, this );
- loading = false;
- disable_playlist( false );
- return err;
-}
-
-void Nsfe_Emu::disable_playlist( bool b )
-{
- info.disable_playlist( b );
- set_track_count( info.info.track_count );
-}
-
-void Nsfe_Emu::clear_playlist_()
-{
- disable_playlist();
- Nsf_Emu::clear_playlist_();
-}
-
-blargg_err_t Nsfe_Emu::start_track_( int track )
-{
- return Nsf_Emu::start_track_( info.remap_track( track ) );
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.h
deleted file mode 100644
index 561c3be0..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Nsfe_Emu.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Nintendo NES/Famicom NSFE music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef NSFE_EMU_H
-#define NSFE_EMU_H
-
-#include "blargg_common.h"
-#include "Nsf_Emu.h"
-
-// Allows reading info from NSFE file without creating emulator
-class Nsfe_Info {
-public:
- blargg_err_t load( Data_Reader&, Nsf_Emu* );
-
- struct info_t : Nsf_Emu::header_t
- {
- char game [256];
- char author [256];
- char copyright [256];
- char dumper [256];
- } info;
-
- void disable_playlist( bool = true );
-
- blargg_err_t track_info_( track_info_t* out, int track ) const;
-
- int remap_track( int i ) const;
-
- void unload();
-
- Nsfe_Info();
- ~Nsfe_Info();
-private:
- blargg_vector<char> track_name_data;
- blargg_vector<const char*> track_names;
- blargg_vector<unsigned char> playlist;
- blargg_vector<char [4]> track_times;
- int actual_track_count_;
- bool playlist_disabled;
-};
-
-class Nsfe_Emu : public Nsf_Emu {
-public:
- static gme_type_t static_type() { return gme_nsfe_type; }
-
-public:
- // deprecated
- struct header_t { char tag [4]; };
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- void disable_playlist( bool = true ); // use clear_playlist()
-
-public:
- Nsfe_Emu();
- ~Nsfe_Emu();
-protected:
- blargg_err_t load_( Data_Reader& );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t start_track_( int );
- void unload();
- void clear_playlist_();
-private:
- Nsfe_Info info;
- bool loading;
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.cpp
deleted file mode 100644
index 23fa9072..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Sap_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const max_frequency = 12000; // pure waves above this frequency are silenced
-
-static void gen_poly( blargg_ulong mask, int count, byte* out )
-{
- blargg_ulong n = 1;
- do
- {
- int bits = 0;
- int b = 0;
- do
- {
- // implemented using "Galios configuration"
- bits |= (n & 1) << b;
- n = (n >> 1) ^ (mask & -(n & 1));
- }
- while ( b++ < 7 );
- *out++ = bits;
- }
- while ( --count );
-}
-
-// poly5
-int const poly5_len = (1 << 5) - 1;
-blargg_ulong const poly5_mask = (1UL << poly5_len) - 1;
-blargg_ulong const poly5 = 0x167C6EA1;
-
-inline blargg_ulong run_poly5( blargg_ulong in, int shift )
-{
- return (in << shift & poly5_mask) | (in >> (poly5_len - shift));
-}
-
-#define POLY_MASK( width, tap1, tap2 ) \
- ((1UL << (width - 1 - tap1)) | (1UL << (width - 1 - tap2)))
-
-Sap_Apu_Impl::Sap_Apu_Impl()
-{
- gen_poly( POLY_MASK( 4, 1, 0 ), sizeof poly4, poly4 );
- gen_poly( POLY_MASK( 9, 5, 0 ), sizeof poly9, poly9 );
- gen_poly( POLY_MASK( 17, 5, 0 ), sizeof poly17, poly17 );
-
- if ( 0 ) // comment out to recauculate poly5 constant
- {
- byte poly5 [4];
- gen_poly( POLY_MASK( 5, 2, 0 ), sizeof poly5, poly5 );
- blargg_ulong n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L +
- poly5 [1] * 0x100L + poly5 [0];
- blargg_ulong rev = n & 1;
- for ( int i = 1; i < poly5_len; i++ )
- rev |= (n >> i & 1) << (poly5_len - i);
- dprintf( "poly5: 0x%08lX\n", rev );
- }
-}
-
-Sap_Apu::Sap_Apu()
-{
- impl = 0;
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, 0 );
-}
-
-void Sap_Apu::reset( Sap_Apu_Impl* new_impl )
-{
- impl = new_impl;
- last_time = 0;
- poly5_pos = 0;
- poly4_pos = 0;
- polym_pos = 0;
- control = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- memset( &oscs [i], 0, offsetof (osc_t,output) );
-}
-
-inline void Sap_Apu::calc_periods()
-{
- // 15/64 kHz clock
- int divider = 28;
- if ( this->control & 1 )
- divider = 114;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- osc_t* const osc = &oscs [i];
-
- int const osc_reload = osc->regs [0]; // cache
- blargg_long period = (osc_reload + 1) * divider;
- static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 };
- if ( this->control & fast_bits [i] )
- {
- period = osc_reload + 4;
- if ( i & 1 )
- {
- period = osc_reload * 0x100L + osc [-1].regs [0] + 7;
- if ( !(this->control & fast_bits [i - 1]) )
- period = (period - 6) * divider;
-
- if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
- dprintf( "Use of slave channel in 16-bit mode not supported\n" );
- }
- }
- osc->period = period;
- }
-}
-
-void Sap_Apu::run_until( blip_time_t end_time )
-{
- calc_periods();
- Sap_Apu_Impl* const impl = this->impl; // cache
-
- // 17/9-bit poly selection
- byte const* polym = impl->poly17;
- int polym_len = poly17_len;
- if ( this->control & 0x80 )
- {
- polym_len = poly9_len;
- polym = impl->poly9;
- }
- polym_pos %= polym_len;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- osc_t* const osc = &oscs [i];
- blip_time_t time = last_time + osc->delay;
- blip_time_t const period = osc->period;
-
- // output
- Blip_Buffer* output = osc->output;
- if ( output )
- {
- output->set_modified();
-
- int const osc_control = osc->regs [1]; // cache
- int volume = (osc_control & 0x0F) * 2;
- if ( !volume || osc_control & 0x10 || // silent, DAC mode, or inaudible frequency
- ((osc_control & 0xA0) == 0xA0 && period < 1789773 / 2 / max_frequency) )
- {
- if ( !(osc_control & 0x10) )
- volume >>= 1; // inaudible frequency = half volume
-
- int delta = volume - osc->last_amp;
- if ( delta )
- {
- osc->last_amp = volume;
- impl->synth.offset( last_time, delta, output );
- }
-
- // TODO: doesn't maintain high pass flip-flop (very minor issue)
- }
- else
- {
- // high pass
- static byte const hipass_bits [osc_count] = { 1 << 2, 1 << 1, 0, 0 };
- blip_time_t period2 = 0; // unused if no high pass
- blip_time_t time2 = end_time;
- if ( this->control & hipass_bits [i] )
- {
- period2 = osc [2].period;
- time2 = last_time + osc [2].delay;
- if ( osc->invert )
- {
- // trick inner wave loop into inverting output
- osc->last_amp -= volume;
- volume = -volume;
- }
- }
-
- if ( time < end_time || time2 < end_time )
- {
- // poly source
- static byte const poly1 [] = { 0x55, 0x55 }; // square wave
- byte const* poly = poly1;
- int poly_len = 8 * sizeof poly1; // can be just 2 bits, but this is faster
- int poly_pos = osc->phase & 1;
- int poly_inc = 1;
- if ( !(osc_control & 0x20) )
- {
- poly = polym;
- poly_len = polym_len;
- poly_pos = polym_pos;
- if ( osc_control & 0x40 )
- {
- poly = impl->poly4;
- poly_len = poly4_len;
- poly_pos = poly4_pos;
- }
- poly_inc = period % poly_len;
- poly_pos = (poly_pos + osc->delay) % poly_len;
- }
- poly_inc -= poly_len; // allows more optimized inner loop below
-
- // square/poly5 wave
- blargg_ulong wave = poly5;
- check( poly5 & 1 ); // low bit is set for pure wave
- int poly5_inc = 0;
- if ( !(osc_control & 0x80) )
- {
- wave = run_poly5( wave, (osc->delay + poly5_pos) % poly5_len );
- poly5_inc = period % poly5_len;
- }
-
- // Run wave and high pass interleved with each catching up to the other.
- // Disabled high pass has no performance effect since inner wave loop
- // makes no compromise for high pass, and only runs once in that case.
- int osc_last_amp = osc->last_amp;
- do
- {
- // run high pass
- if ( time2 < time )
- {
- int delta = -osc_last_amp;
- if ( volume < 0 )
- delta += volume;
- if ( delta )
- {
- osc_last_amp += delta - volume;
- volume = -volume;
- impl->synth.offset( time2, delta, output );
- }
- }
- while ( time2 <= time ) // must advance *past* time to avoid hang
- time2 += period2;
-
- // run wave
- blip_time_t end = end_time;
- if ( end > time2 )
- end = time2;
- while ( time < end )
- {
- if ( wave & 1 )
- {
- int amp = volume & -(poly [poly_pos >> 3] >> (poly_pos & 7) & 1);
- if ( (poly_pos += poly_inc) < 0 )
- poly_pos += poly_len;
- int delta = amp - osc_last_amp;
- if ( delta )
- {
- osc_last_amp = amp;
- impl->synth.offset( time, delta, output );
- }
- }
- wave = run_poly5( wave, poly5_inc );
- time += period;
- }
- }
- while ( time < end_time || time2 < end_time );
-
- osc->phase = poly_pos;
- osc->last_amp = osc_last_amp;
- }
-
- osc->invert = 0;
- if ( volume < 0 )
- {
- // undo inversion trickery
- osc->last_amp -= volume;
- osc->invert = 1;
- }
- }
- }
-
- // maintain divider
- blip_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- blargg_long count = (remain + period - 1) / period;
- osc->phase ^= count;
- time += count * period;
- }
- osc->delay = time - end_time;
- }
-
- // advance polies
- blip_time_t duration = end_time - last_time;
- last_time = end_time;
- poly4_pos = (poly4_pos + duration) % poly4_len;
- poly5_pos = (poly5_pos + duration) % poly5_len;
- polym_pos += duration; // will get %'d on next call
-}
-
-void Sap_Apu::write_data( blip_time_t time, unsigned addr, int data )
-{
- run_until( time );
- int i = (addr ^ 0xD200) >> 1;
- if ( i < osc_count )
- {
- oscs [i].regs [addr & 1] = data;
- }
- else if ( addr == 0xD208 )
- {
- control = data;
- }
- else if ( addr == 0xD209 )
- {
- oscs [0].delay = 0;
- oscs [1].delay = 0;
- oscs [2].delay = 0;
- oscs [3].delay = 0;
- }
- /*
- // TODO: are polynomials reset in this case?
- else if ( addr == 0xD20F )
- {
- if ( (data & 3) == 0 )
- polym_pos = 0;
- }
- */
-}
-
-void Sap_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- last_time -= end_time;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.h
deleted file mode 100644
index c71ce31e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Apu.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Atari POKEY sound chip emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SAP_APU_H
-#define SAP_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Sap_Apu_Impl;
-
-class Sap_Apu {
-public:
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* );
-
- void reset( Sap_Apu_Impl* );
-
- enum { start_addr = 0xD200 };
- enum { end_addr = 0xD209 };
- void write_data( blip_time_t, unsigned addr, int data );
-
- void end_frame( blip_time_t );
-
-public:
- Sap_Apu();
-private:
- struct osc_t
- {
- unsigned char regs [2];
- unsigned char phase;
- unsigned char invert;
- int last_amp;
- blip_time_t delay;
- blip_time_t period; // always recalculated before use; here for convenience
- Blip_Buffer* output;
- };
- osc_t oscs [osc_count];
- Sap_Apu_Impl* impl;
- blip_time_t last_time;
- int poly5_pos;
- int poly4_pos;
- int polym_pos;
- int control;
-
- void calc_periods();
- void run_until( blip_time_t );
-
- enum { poly4_len = (1L << 4) - 1 };
- enum { poly9_len = (1L << 9) - 1 };
- enum { poly17_len = (1L << 17) - 1 };
- friend class Sap_Apu_Impl;
-};
-
-// Common tables and Blip_Synth that can be shared among multiple Sap_Apu objects
-class Sap_Apu_Impl {
-public:
- Blip_Synth<blip_good_quality,1> synth;
-
- Sap_Apu_Impl();
- void volume( double d ) { synth.volume( 1.0 / Sap_Apu::osc_count / 30 * d ); }
-
-private:
- typedef unsigned char byte;
- byte poly4 [Sap_Apu::poly4_len / 8 + 1];
- byte poly9 [Sap_Apu::poly9_len / 8 + 1];
- byte poly17 [Sap_Apu::poly17_len / 8 + 1];
- friend class Sap_Apu;
-};
-
-inline void Sap_Apu::osc_output( int i, Blip_Buffer* b )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = b;
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.cpp
deleted file mode 100644
index 10dc6061..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.cpp
+++ /dev/null
@@ -1,1011 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Sap_Cpu.h"
-
-#include <limits.h>
-#include "blargg_endian.h"
-
-//#include "nes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "sap_cpu_io.h"
-
-#ifndef CPU_DONE
- #define CPU_DONE( cpu, time, result_out ) { result_out = -1; }
-#endif
-
-#include "blargg_source.h"
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Sap_Cpu::reset( void* new_mem )
-{
- check( state == &state_ );
- state = &state_;
- mem = (uint8_t*) new_mem;
- r.status = st_i;
- r.sp = 0xFF;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_sap_time;
- end_time_ = future_sap_time;
-
- blargg_verify_byte_order();
-}
-
-#define TIME (s_time + s.base)
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (READ_LOW( addr ))
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-typedef blargg_long fint32;
-
-bool Sap_Cpu::run( sap_time_t end_time )
-{
- bool illegal_encountered = false;
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- fint32 s_time = s.time;
- uint8_t* const mem = this->mem; // cache
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- // status flags
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-dec_clock_loop:
- s_time--;
-loop:
-
- #ifndef NDEBUG
- {
- sap_time_t correct = end_time_;
- if ( !(status & st_i) && correct > irq_time_ )
- correct = irq_time_;
- check( s.base == correct );
- }
- #endif
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- fuint8 opcode = mem [pc];
- pc++;
- uint8_t const* instr = mem + pc;
-
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
- 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
- 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
- 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
- 3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
- 3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
- }; // 0x00 was 7
-
- fuint16 data;
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- #ifdef NES_CPU_LOG_H
- nes_cpu_log( "cpu_log", pc - 1, opcode, instr [0], instr [1] );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE() (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR() GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
- fuint16 temp = READ_LOW( data ) + y;\
- out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- cross( temp );\
- }
-
-#define IND_X( out ) {\
- fuint16 temp = data + x;\
- out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
- }
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
- IND_X( data )\
- goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
- IND_Y( HANDLE_PAGE_CROSSING, data )\
- goto ptr##op;\
-case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
-case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
-case op + 0x18: /* abs,X */\
- data += x;\
-ind##op:\
- HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
- ADD_PAGE();\
-ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- fuint16 extra_clock = (++pc & 0xFF) + offset;\
- if ( !(cond) ) goto dec_clock_loop;\
- pc += offset;\
- s_time += extra_clock >> 8 & 1;\
- goto loop;\
-}
-
-// Often-Used
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0xE8: // INX
- INC_DEC_XY( x, 1 )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0xF0: // BEQ
- BRANCH( !(uint8_t) nz );
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xC8: // INY
- INC_DEC_XY( y, 1 )
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAD:{// LDA abs
- unsigned addr = GET_ADDR();
- pc += 2;
- nz = READ( addr );
- a = nz;
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 1 + READ_LOW( sp );
- pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- {
- fuint16 addr;
-
- case 0x99: // STA abs,Y
- addr = y + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x8D: // STA abs
- addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x9D: // STA abs,X (slightly more common than STA abs)
- addr = x + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- sta_ptr:
- FLUSH_TIME();
- WRITE( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x91: // STA (ind),Y
- IND_Y( NO_PAGE_CROSSING, addr )
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- IND_X( addr )
- pc++;
- goto sta_ptr;
-
- }
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
- // common read instructions
- {
- fuint16 addr;
-
- case 0xA1: // LDA (ind,X)
- IND_X( addr )
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- HANDLE_PAGE_CROSSING( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- HANDLE_PAGE_CROSSING( data + y );
- addr = GET_ADDR() + y;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xBD: // LDA abs,X
- HANDLE_PAGE_CROSSING( data + x );
- addr = GET_ADDR() + x;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- a_nz_read_addr:
- FLUSH_TIME();
- a = nz = READ( addr );
- CACHE_TIME();
- goto loop;
-
- }
-
-// Branch
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
-// Load/store
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- HANDLE_PAGE_CROSSING( data );
- case 0xAC:{// LDY abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xBE: // LDX abs,y
- data += y;
- HANDLE_PAGE_CROSSING( data );
- case 0xAE:{// LDX abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- unsigned addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, temp );
- goto loop;
- }
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
- case 0x2C:{// BIT abs
- unsigned addr = GET_ADDR();
- pc += 2;
- status &= ~st_v;
- nz = READ( addr );
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
- }
-
- case 0x24: // BIT zp
- nz = READ_LOW( data );
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- case 0xEB: // unofficial equivalent
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- check( !(status & st_d) );
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE();
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE();
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
- case 0xCA: // DEX
- INC_DEC_XY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_XY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a ); // verified
- goto loop;
-
- case 0x68: // PLA
- a = nz = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- this->r.status = status; // update externally-visible I flag
- if ( (data ^ status) & st_i )
- {
- sap_time_t new_time = end_time_;
- if ( !(status & st_i) && new_time > irq_time_ )
- new_time = irq_time_;
- blargg_long delta = s.base - new_time;
- s.base = new_time;
- s_time += delta;
- }
- goto loop;
- }
-
- case 0x28:{// PLP
- fuint8 temp = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | (st_b | st_r) );
- goto loop;
- }
-
- case 0x6C:{// JMP (ind)
- data = GET_ADDR();
- pc = READ_PROG( data );
- data = (data & 0xFF00) | ((data + 1) & 0xFF);
- pc |= 0x100 * READ_PROG( data );
- goto loop;
- }
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- // delayed irq until after next instruction
- s.base += s_time + 1;
- s_time = -1;
- irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
- goto loop;
- }
- delayed_cli:
- dprintf( "Delayed CLI not emulated\n" );
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
- dprintf( "Delayed SEI not emulated\n" );
- goto loop;
- }
-
-// Unofficial
-
- // SKW - Skip word
- case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
- HANDLE_PAGE_CROSSING( data + x );
- case 0x0C:
- pc++;
- // SKB - Skip byte
- case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
- case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
- pc++;
- goto loop;
-
- // NOP
- case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
- goto loop;
-
-// Unimplemented
-
- // halt
- //case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- //case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
-
- default:
- assert( (unsigned) opcode <= 0xFF );
- illegal_encountered = true;
- pc--;
- goto stop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- if ( (pc - 1) >= idle_addr )
- goto idle_done;
- pc++;
- result_ = 4;
- dprintf( "BRK executed\n" );
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- temp |= st_r;
- if ( result_ )
- temp |= st_b; // TODO: incorrectly sets B flag for IRQ
- WRITE_LOW( sp, temp );
-
- status &= ~st_d;
- status |= st_i;
- this->r.status = status; // update externally-visible I flag
-
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- goto loop;
- }
-
-idle_done:
- //s_time = 0;
- pc--;
- goto stop;
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ >= 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
-stop:
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return illegal_encountered;
-}
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.h
deleted file mode 100644
index 712f63cd..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Cpu.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Atari 6502 CPU emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SAP_CPU_H
-#define SAP_CPU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long sap_time_t; // clock cycle count
-typedef unsigned sap_addr_t; // 16-bit address
-enum { future_sap_time = LONG_MAX / 2 + 1 };
-
-class Sap_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear all registers and keep pointer to 64K memory passed in
- void reset( void* mem_64k );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( sap_time_t end_time );
-
- // Registers are not updated until run() returns (except I flag in status)
- struct registers_t {
- BOOST::uint16_t pc;
- BOOST::uint8_t a;
- BOOST::uint8_t x;
- BOOST::uint8_t y;
- BOOST::uint8_t status;
- BOOST::uint8_t sp;
- };
- registers_t r;
-
- enum { idle_addr = 0xFEFF };
-
- // Time of beginning of next instruction to be executed
- sap_time_t time() const { return state->time + state->base; }
- void set_time( sap_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- sap_time_t irq_time() const { return irq_time_; }
- void set_irq_time( sap_time_t );
-
- sap_time_t end_time() const { return end_time_; }
- void set_end_time( sap_time_t );
-
-public:
- Sap_Cpu() { state = &state_; }
- enum { irq_inhibit = 0x04 };
-private:
- struct state_t {
- sap_time_t base;
- sap_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- sap_time_t irq_time_;
- sap_time_t end_time_;
- uint8_t* mem;
-
- inline sap_time_t update_end_time( sap_time_t end, sap_time_t irq );
-};
-
-inline sap_time_t Sap_Cpu::update_end_time( sap_time_t t, sap_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- sap_time_t delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Sap_Cpu::set_irq_time( sap_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Sap_Cpu::set_end_time( sap_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.cpp
deleted file mode 100644
index 8314fd6e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Sap_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const base_scanline_period = 114;
-
-Sap_Emu::Sap_Emu()
-{
- set_type( gme_sap_type );
-
- static const char* const names [Sap_Apu::osc_count * 2] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8",
- };
- set_voice_names( names );
-
- static int const types [Sap_Apu::osc_count * 2] = {
- wave_type | 1, wave_type | 2, wave_type | 3, wave_type | 0,
- wave_type | 5, wave_type | 6, wave_type | 7, wave_type | 4,
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
-}
-
-Sap_Emu::~Sap_Emu() { }
-
-// Track info
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static long from_hex( byte const* in )
-{
- unsigned result = 0;
- for ( int n = 4; n--; )
- {
- int h = from_hex_char( *in++ );
- if ( h > 15 )
- return -1;
- result = result * 0x10 + h;
- }
- return result;
-}
-
-static int from_dec( byte const* in, byte const* end )
-{
- if ( in >= end )
- return -1;
-
- int n = 0;
- while ( in < end )
- {
- int dig = *in++ - '0';
- if ( (unsigned) dig > 9 )
- return -1;
- n = n * 10 + dig;
- }
- return n;
-}
-
-static void parse_string( byte const* in, byte const* end, int len, char* out )
-{
- byte const* start = in;
- if ( *in++ == '\"' )
- {
- start++;
- while ( in < end && *in != '\"' )
- in++;
- }
- else
- {
- in = end;
- }
- len = min( len - 1, int (in - start) );
- out [len] = 0;
- memcpy( out, start, len );
-}
-
-static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out )
-{
- out->track_count = 1;
- out->author [0] = 0;
- out->name [0] = 0;
- out->copyright [0] = 0;
-
- if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
- return gme_wrong_file_type;
-
- byte const* file_end = in + size - 5;
- in += 5;
- while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
- {
- byte const* line_end = in;
- while ( line_end < file_end && *line_end != 0x0D )
- line_end++;
-
- char const* tag = (char const*) in;
- while ( in < line_end && *in > ' ' )
- in++;
- int tag_len = (char const*) in - tag;
-
- while ( in < line_end && *in <= ' ' ) in++;
-
- if ( tag_len <= 0 )
- {
- // skip line
- }
- else if ( !strncmp( "INIT", tag, tag_len ) )
- {
- out->init_addr = from_hex( in );
- if ( (unsigned long) out->init_addr > 0xFFFF )
- return "Invalid init address";
- }
- else if ( !strncmp( "PLAYER", tag, tag_len ) )
- {
- out->play_addr = from_hex( in );
- if ( (unsigned long) out->play_addr > 0xFFFF )
- return "Invalid play address";
- }
- else if ( !strncmp( "MUSIC", tag, tag_len ) )
- {
- out->music_addr = from_hex( in );
- if ( (unsigned long) out->music_addr > 0xFFFF )
- return "Invalid music address";
- }
- else if ( !strncmp( "SONGS", tag, tag_len ) )
- {
- out->track_count = from_dec( in, line_end );
- if ( out->track_count <= 0 )
- return "Invalid track count";
- }
- else if ( !strncmp( "TYPE", tag, tag_len ) )
- {
- switch ( out->type = *in )
- {
- case 'C':
- case 'B':
- break;
-
- case 'D':
- return "Digimusic not supported";
-
- default:
- return "Unsupported player type";
- }
- }
- else if ( !strncmp( "STEREO", tag, tag_len ) )
- {
- out->stereo = true;
- }
- else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
- {
- out->fastplay = from_dec( in, line_end );
- if ( out->fastplay <= 0 )
- return "Invalid fastplay value";
- }
- else if ( !strncmp( "AUTHOR", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->author, out->author );
- }
- else if ( !strncmp( "NAME", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->name, out->name );
- }
- else if ( !strncmp( "DATE", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->copyright, out->copyright );
- }
-
- in = line_end + 2;
- }
-
- if ( in [0] != 0xFF || in [1] != 0xFF )
- return "ROM data missing";
- out->rom_data = in + 2;
-
- return 0;
-}
-
-static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
-{
- Gme_File::copy_field_( out->game, in.name );
- Gme_File::copy_field_( out->author, in.author );
- Gme_File::copy_field_( out->copyright, in.copyright );
-}
-
-blargg_err_t Sap_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_sap_fields( info, out );
- return 0;
-}
-
-struct Sap_File : Gme_Info_
-{
- Sap_Emu::info_t info;
-
- Sap_File() { set_type( gme_sap_type ); }
-
- blargg_err_t load_mem_( byte const* begin, long size )
- {
- RETURN_ERR( parse_info( begin, size, &info ) );
- set_track_count( info.track_count );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_sap_fields( info, out );
- return 0;
- }
-};
-
-static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
-static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
-
-gme_type_t_ const gme_sap_type [1] = { "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 };
-
-// Setup
-
-blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
-{
- file_end = in + size;
-
- info.warning = 0;
- info.type = 'B';
- info.stereo = false;
- info.init_addr = -1;
- info.play_addr = -1;
- info.music_addr = -1;
- info.fastplay = 312;
- RETURN_ERR( parse_info( in, size, &info ) );
-
- set_warning( info.warning );
- set_track_count( info.track_count );
- set_voice_count( Sap_Apu::osc_count << info.stereo );
- apu_impl.volume( gain() );
-
- return setup_buffer( 1773447 );
-}
-
-void Sap_Emu::update_eq( blip_eq_t const& eq )
-{
- apu_impl.synth.treble_eq( eq );
-}
-
-void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- int i2 = i - Sap_Apu::osc_count;
- if ( i2 >= 0 )
- apu2.osc_output( i2, right );
- else
- apu.osc_output( i, (info.stereo ? left : center) );
-}
-
-// Emulation
-
-void Sap_Emu::set_tempo_( double t )
-{
- scanline_period = sap_time_t (base_scanline_period / t);
-}
-
-inline sap_time_t Sap_Emu::play_period() const { return info.fastplay * scanline_period; }
-
-void Sap_Emu::cpu_jsr( sap_addr_t addr )
-{
- check( r.sp >= 0xFE ); // catch anything trying to leave data on stack
- r.pc = addr;
- int high_byte = (idle_addr - 1) >> 8;
- if ( r.sp == 0xFE && mem.ram [0x1FF] == high_byte )
- r.sp = 0xFF; // pop extra byte off
- mem.ram [0x100 + r.sp--] = high_byte; // some routines use RTI to return
- mem.ram [0x100 + r.sp--] = high_byte;
- mem.ram [0x100 + r.sp--] = (idle_addr - 1) & 0xFF;
-}
-
-void Sap_Emu::run_routine( sap_addr_t addr )
-{
- cpu_jsr( addr );
- cpu::run( 312 * base_scanline_period * 60 );
- check( r.pc == idle_addr );
-}
-
-inline void Sap_Emu::call_init( int track )
-{
- switch ( info.type )
- {
- case 'B':
- r.a = track;
- run_routine( info.init_addr );
- break;
-
- case 'C':
- r.a = 0x70;
- r.x = info.music_addr&0xFF;
- r.y = info.music_addr >> 8;
- run_routine( info.play_addr + 3 );
- r.a = 0;
- r.x = track;
- run_routine( info.play_addr + 3 );
- break;
- }
-}
-
-blargg_err_t Sap_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( &mem, 0, sizeof mem );
-
- byte const* in = info.rom_data;
- while ( file_end - in >= 5 )
- {
- unsigned start = get_le16( in );
- unsigned end = get_le16( in + 2 );
- //dprintf( "Block $%04X-$%04X\n", start, end );
- in += 4;
- if ( end < start )
- {
- set_warning( "Invalid file data block" );
- break;
- }
- long len = end - start + 1;
- if ( len > file_end - in )
- {
- set_warning( "Invalid file data block" );
- break;
- }
-
- memcpy( mem.ram + start, in, len );
- in += len;
- if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
- in += 2;
- }
-
- apu.reset( &apu_impl );
- apu2.reset( &apu_impl );
- cpu::reset( mem.ram );
- time_mask = 0; // disables sound during init
- call_init( track );
- time_mask = -1;
-
- next_play = play_period();
-
- return 0;
-}
-
-// Emulation
-
-// see sap_cpu_io.h for read/write functions
-
-void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
-{
- if ( (addr ^ Sap_Apu::start_addr) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) )
- {
- GME_APU_HOOK( this, addr - Sap_Apu::start_addr, data );
- apu.write_data( time() & time_mask, addr, data );
- return;
- }
-
- if ( (addr ^ (Sap_Apu::start_addr + 0x10)) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) &&
- info.stereo )
- {
- GME_APU_HOOK( this, addr - 0x10 - Sap_Apu::start_addr + 10, data );
- apu2.write_data( time() & time_mask, addr ^ 0x10, data );
- return;
- }
-
- if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
- dprintf( "Unmapped write $%04X <- $%02X\n", addr, data );
-}
-
-inline void Sap_Emu::call_play()
-{
- switch ( info.type )
- {
- case 'B':
- cpu_jsr( info.play_addr );
- break;
-
- case 'C':
- cpu_jsr( info.play_addr + 6 );
- break;
- }
-}
-
-blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- while ( time() < duration )
- {
- if ( cpu::run( duration ) || r.pc > idle_addr )
- return "Emulation error (illegal instruction)";
-
- if ( r.pc == idle_addr )
- {
- if ( next_play <= duration )
- {
- set_time( next_play );
- next_play += play_period();
- call_play();
- GME_FRAME_HOOK( this );
- }
- else
- {
- set_time( duration );
- }
- }
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- if ( next_play < 0 )
- next_play = 0;
- apu.end_frame( duration );
- if ( info.stereo )
- apu2.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.h
deleted file mode 100644
index 4878faa6..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sap_Emu.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Atari XL/XE SAP music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SAP_EMU_H
-#define SAP_EMU_H
-
-#include "Classic_Emu.h"
-#include "Sap_Apu.h"
-#include "Sap_Cpu.h"
-
-class Sap_Emu : private Sap_Cpu, public Classic_Emu {
- typedef Sap_Cpu cpu;
-public:
- static gme_type_t static_type() { return gme_sap_type; }
-public:
- Sap_Emu();
- ~Sap_Emu();
- struct info_t {
- byte const* rom_data;
- const char* warning;
- long init_addr;
- long play_addr;
- long music_addr;
- int type;
- int track_count;
- int fastplay;
- bool stereo;
- char author [256];
- char name [256];
- char copyright [ 32];
- };
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-public: private: friend class Sap_Cpu;
- int cpu_read( sap_addr_t );
- void cpu_write( sap_addr_t, int );
- void cpu_write_( sap_addr_t, int );
-private:
- info_t info;
-
- byte const* file_end;
- sap_time_t scanline_period;
- sap_time_t next_play;
- sap_time_t time_mask;
- Sap_Apu apu;
- Sap_Apu apu2;
-
- // large items
- struct {
- byte padding1 [0x100];
- byte ram [0x10000];
- byte padding2 [0x100];
- } mem;
- Sap_Apu_Impl apu_impl;
-
- sap_time_t play_period() const;
- void call_play();
- void cpu_jsr( sap_addr_t );
- void call_init( int track );
- void run_routine( sap_addr_t );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.cpp
deleted file mode 100644
index b41fdec4..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Sms_Snd_Emu 0.1.4. http://www.slack.net/~ant/
-
-#include "Sms_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Sms_Osc
-
-Sms_Osc::Sms_Osc()
-{
- output = 0;
- outputs [0] = 0; // always stays NULL
- outputs [1] = 0;
- outputs [2] = 0;
- outputs [3] = 0;
-}
-
-void Sms_Osc::reset()
-{
- delay = 0;
- last_amp = 0;
- volume = 0;
- output_select = 3;
- output = outputs [3];
-}
-
-// Sms_Square
-
-inline void Sms_Square::reset()
-{
- period = 0;
- phase = 0;
- Sms_Osc::reset();
-}
-
-void Sms_Square::run( blip_time_t time, blip_time_t end_time )
-{
- if ( !volume || period <= 128 )
- {
- // ignore 16kHz and higher
- if ( last_amp )
- {
- synth->offset( time, -last_amp, output );
- last_amp = 0;
- }
- time += delay;
- if ( !period )
- {
- time = end_time;
- }
- else if ( time < end_time )
- {
- // keep calculating phase
- int count = (end_time - time + period - 1) / period;
- phase = (phase + count) & 1;
- time += count * period;
- }
- }
- else
- {
- int amp = phase ? volume : -volume;
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- int delta = amp * 2;
- do
- {
- delta = -delta;
- synth->offset_inline( time, delta, output );
- time += period;
- phase ^= 1;
- }
- while ( time < end_time );
- this->last_amp = phase ? volume : -volume;
- }
- }
- delay = time - end_time;
-}
-
-// Sms_Noise
-
-static int const noise_periods [3] = { 0x100, 0x200, 0x400 };
-
-inline void Sms_Noise::reset()
-{
- period = &noise_periods [0];
- shifter = 0x8000;
- feedback = 0x9000;
- Sms_Osc::reset();
-}
-
-void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
-{
- int amp = volume;
- if ( shifter & 1 )
- amp = -amp;
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth.offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !volume )
- time = end_time;
-
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- unsigned shifter = this->shifter;
- int delta = amp * 2;
- int period = *this->period * 2;
- if ( !period )
- period = 16;
-
- do
- {
- int changed = shifter + 1;
- shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1);
- if ( changed & 2 ) // true if bits 0 and 1 differ
- {
- delta = -delta;
- synth.offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->shifter = shifter;
- this->last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Sms_Apu
-
-Sms_Apu::Sms_Apu()
-{
- for ( int i = 0; i < 3; i++ )
- {
- squares [i].synth = &square_synth;
- oscs [i] = &squares [i];
- }
- oscs [3] = &noise;
-
- volume( 1.0 );
- reset();
-}
-
-Sms_Apu::~Sms_Apu()
-{
-}
-
-void Sms_Apu::volume( double vol )
-{
- vol *= 0.85 / (osc_count * 64 * 2);
- square_synth.volume( vol );
- noise.synth.volume( vol );
-}
-
-void Sms_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- noise.synth.treble_eq( eq );
-}
-
-void Sms_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- require( (center && left && right) || (!center && !left && !right) );
- Sms_Osc& osc = *oscs [index];
- osc.outputs [1] = right;
- osc.outputs [2] = left;
- osc.outputs [3] = center;
- osc.output = osc.outputs [osc.output_select];
-}
-
-void Sms_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, center, left, right );
-}
-
-void Sms_Apu::reset( unsigned feedback, int noise_width )
-{
- last_time = 0;
- latch = 0;
-
- if ( !feedback || !noise_width )
- {
- feedback = 0x0009;
- noise_width = 16;
- }
- // convert to "Galios configuration"
- looped_feedback = 1 << (noise_width - 1);
- noise_feedback = 0;
- while ( noise_width-- )
- {
- noise_feedback = (noise_feedback << 1) | (feedback & 1);
- feedback >>= 1;
- }
-
- squares [0].reset();
- squares [1].reset();
- squares [2].reset();
- noise.reset();
-}
-
-void Sms_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time ); // end_time must not be before previous time
-
- if ( end_time > last_time )
- {
- // run oscillators
- for ( int i = 0; i < osc_count; ++i )
- {
- Sms_Osc& osc = *oscs [i];
- if ( osc.output )
- {
- osc.output->set_modified();
- if ( i < 3 )
- squares [i].run( last_time, end_time );
- else
- noise.run( last_time, end_time );
- }
- }
-
- last_time = end_time;
- }
-}
-
-void Sms_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- assert( last_time >= end_time );
- last_time -= end_time;
-}
-
-void Sms_Apu::write_ggstereo( blip_time_t time, int data )
-{
- require( (unsigned) data <= 0xFF );
-
- run_until( time );
-
- for ( int i = 0; i < osc_count; i++ )
- {
- Sms_Osc& osc = *oscs [i];
- int flags = data >> i;
- Blip_Buffer* old_output = osc.output;
- osc.output_select = (flags >> 3 & 2) | (flags & 1);
- osc.output = osc.outputs [osc.output_select];
- if ( osc.output != old_output && osc.last_amp )
- {
- if ( old_output )
- {
- old_output->set_modified();
- square_synth.offset( time, -osc.last_amp, old_output );
- }
- osc.last_amp = 0;
- }
- }
-}
-
-// volumes [i] = 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
-static unsigned char const volumes [16] = {
- 64, 50, 39, 31, 24, 19, 15, 12, 9, 7, 5, 4, 3, 2, 1, 0
-};
-
-void Sms_Apu::write_data( blip_time_t time, int data )
-{
- require( (unsigned) data <= 0xFF );
-
- run_until( time );
-
- if ( data & 0x80 )
- latch = data;
-
- int index = (latch >> 5) & 3;
- if ( latch & 0x10 )
- {
- oscs [index]->volume = volumes [data & 15];
- }
- else if ( index < 3 )
- {
- Sms_Square& sq = squares [index];
- if ( data & 0x80 )
- sq.period = (sq.period & 0xFF00) | (data << 4 & 0x00FF);
- else
- sq.period = (sq.period & 0x00FF) | (data << 8 & 0x3F00);
- }
- else
- {
- int select = data & 3;
- if ( select < 3 )
- noise.period = &noise_periods [select];
- else
- noise.period = &squares [2].period;
-
- noise.feedback = (data & 0x04) ? noise_feedback : looped_feedback;
- noise.shifter = 0x8000;
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.h
deleted file mode 100644
index 3c11a9c3..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Apu.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Sega Master System SN76489 PSG sound chip emulator
-
-// Sms_Snd_Emu 0.1.4
-#ifndef SMS_APU_H
-#define SMS_APU_H
-
-#include "Sms_Oscs.h"
-
-class Sms_Apu {
-public:
- // Set overall volume of all oscillators, where 1.0 is full volume
- void volume( double );
-
- // Set treble equalization
- void treble_eq( const blip_eq_t& );
-
- // Outputs can be assigned to a single buffer for mono output, or to three
- // buffers for stereo output (using Stereo_Buffer to do the mixing).
-
- // Assign all oscillator outputs to specified buffer(s). If buffer
- // is NULL, silences all oscillators.
- void output( Blip_Buffer* mono );
- void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
- // which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL,
- // silences oscillator.
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* mono );
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Reset oscillators and internal state
- void reset( unsigned noise_feedback = 0, int noise_width = 0 );
-
- // Write GameGear left/right assignment byte
- void write_ggstereo( blip_time_t, int );
-
- // Write to data port
- void write_data( blip_time_t, int );
-
- // Run all oscillators up to specified time, end current frame, then
- // start a new frame at time 0.
- void end_frame( blip_time_t );
-
-public:
- Sms_Apu();
- ~Sms_Apu();
-private:
- // noncopyable
- Sms_Apu( const Sms_Apu& );
- Sms_Apu& operator = ( const Sms_Apu& );
-
- Sms_Osc* oscs [osc_count];
- Sms_Square squares [3];
- Sms_Square::Synth square_synth; // used by squares
- blip_time_t last_time;
- int latch;
- Sms_Noise noise;
- unsigned noise_feedback;
- unsigned looped_feedback;
-
- void run_until( blip_time_t );
-};
-
-struct sms_apu_state_t
-{
- unsigned char regs [8] [2];
- unsigned char latch;
-};
-
-inline void Sms_Apu::output( Blip_Buffer* b ) { output( b, b, b ); }
-
-inline void Sms_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Oscs.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Oscs.h
deleted file mode 100644
index 2a896fef..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Sms_Oscs.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Private oscillators used by Sms_Apu
-
-// Sms_Snd_Emu 0.1.4
-#ifndef SMS_OSCS_H
-#define SMS_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Sms_Osc
-{
- Blip_Buffer* outputs [4]; // NULL, right, left, center
- Blip_Buffer* output;
- int output_select;
-
- int delay;
- int last_amp;
- int volume;
-
- Sms_Osc();
- void reset();
-};
-
-struct Sms_Square : Sms_Osc
-{
- int period;
- int phase;
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- const Synth* synth;
-
- void reset();
- void run( blip_time_t, blip_time_t );
-};
-
-struct Sms_Noise : Sms_Osc
-{
- const int* period;
- unsigned shifter;
- unsigned feedback;
-
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth synth;
-
- void reset();
- void run( blip_time_t, blip_time_t );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.cpp
deleted file mode 100644
index e909ea18..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.cpp
+++ /dev/null
@@ -1,489 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Snes_Spc.h"
-
-#include <string.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// always in the future (CPU time can go over 0, but not by this much)
-int const timer_disabled_time = 127;
-
-Snes_Spc::Snes_Spc() : dsp( mem.ram ), cpu( this, mem.ram )
-{
- set_tempo( 1.0 );
-
- // Put STOP instruction around memory to catch PC underflow/overflow.
- memset( mem.padding1, 0xFF, sizeof mem.padding1 );
- memset( mem.padding2, 0xFF, sizeof mem.padding2 );
-
- // A few tracks read from the last four bytes of IPL ROM
- boot_rom [sizeof boot_rom - 2] = 0xC0;
- boot_rom [sizeof boot_rom - 1] = 0xFF;
- memset( boot_rom, 0, sizeof boot_rom - 2 );
-}
-
-void Snes_Spc::set_tempo( double t )
-{
- int unit = (int) (16.0 / t + 0.5);
-
- timer [0].divisor = unit * 8; // 8 kHz
- timer [1].divisor = unit * 8; // 8 kHz
- timer [2].divisor = unit; // 64 kHz
-}
-
-// Load
-
-void Snes_Spc::set_ipl_rom( void const* in )
-{
- memcpy( boot_rom, in, sizeof boot_rom );
-}
-
-blargg_err_t Snes_Spc::load_spc( const void* data, long size )
-{
- struct spc_file_t {
- char signature [27];
- char unused [10];
- uint8_t pc [2];
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- char unused2 [212];
- uint8_t ram [0x10000];
- uint8_t dsp [128];
- uint8_t ipl_rom [128];
- };
- assert( offsetof (spc_file_t,ipl_rom) == spc_file_size );
-
- const spc_file_t* spc = (spc_file_t const*) data;
-
- if ( size < spc_file_size )
- return "Not an SPC file";
-
- if ( strncmp( spc->signature, "SNES-SPC700 Sound File Data", 27 ) != 0 )
- return "Not an SPC file";
-
- registers_t regs;
- regs.pc = spc->pc [1] * 0x100 + spc->pc [0];
- regs.a = spc->a;
- regs.x = spc->x;
- regs.y = spc->y;
- regs.status = spc->status;
- regs.sp = spc->sp;
-
- if ( (unsigned long) size >= sizeof *spc )
- set_ipl_rom( spc->ipl_rom );
-
- const char* error = load_state( regs, spc->ram, spc->dsp );
-
- echo_accessed = false;
-
- return error;
-}
-
-void Snes_Spc::clear_echo()
-{
- if ( !(dsp.read( 0x6C ) & 0x20) )
- {
- unsigned addr = 0x100 * dsp.read( 0x6D );
- size_t size = 0x800 * dsp.read( 0x7D );
- memset( mem.ram + addr, 0xFF, min( size, sizeof mem.ram - addr ) );
- }
-}
-
-// Handle other file formats (emulator save states) in user code, not here.
-
-blargg_err_t Snes_Spc::load_state( const registers_t& cpu_state, const void* new_ram,
- const void* dsp_state )
-{
- // cpu
- cpu.r = cpu_state;
-
- // Allow DSP to generate one sample before code starts
- // (Tengai Makyo Zero, Tenjin's Table Toss first notes are lost since it
- // clears KON 31 cycles from starting execution. It works on the SNES
- // since the SPC player adds a few extra cycles delay after restoring
- // KON from the DSP registers at the end of an SPC file).
- extra_cycles = 32;
-
- // ram
- memcpy( mem.ram, new_ram, sizeof mem.ram );
- memcpy( extra_ram, mem.ram + rom_addr, sizeof extra_ram );
-
- // boot rom (have to force enable_rom() to update it)
- rom_enabled = !(mem.ram [0xF1] & 0x80);
- enable_rom( !rom_enabled );
-
- // dsp
- dsp.reset();
- int i;
- for ( i = 0; i < Spc_Dsp::register_count; i++ )
- dsp.write( i, ((uint8_t const*) dsp_state) [i] );
-
- // timers
- for ( i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
-
- t.next_tick = 0;
- t.enabled = (mem.ram [0xF1] >> i) & 1;
- if ( !t.enabled )
- t.next_tick = timer_disabled_time;
- t.count = 0;
- t.counter = mem.ram [0xFD + i] & 15;
-
- int p = mem.ram [0xFA + i];
- t.period = p ? p : 0x100;
- }
-
- // Handle registers which already give 0 when read by setting RAM and not changing it.
- // Put STOP instruction in registers which can be read, to catch attempted CPU execution.
- mem.ram [0xF0] = 0;
- mem.ram [0xF1] = 0;
- mem.ram [0xF3] = 0xFF;
- mem.ram [0xFA] = 0;
- mem.ram [0xFB] = 0;
- mem.ram [0xFC] = 0;
- mem.ram [0xFD] = 0xFF;
- mem.ram [0xFE] = 0xFF;
- mem.ram [0xFF] = 0xFF;
-
- return 0; // success
-}
-
-// Hardware
-
-// Current time starts negative and ends at 0
-inline spc_time_t Snes_Spc::time() const
-{
- return -cpu.remain();
-}
-
-// Keep track of next time to run and avoid a function call if it hasn't been reached.
-
-// Timers
-
-void Snes_Spc::Timer::run_until_( spc_time_t time )
-{
- if ( !enabled )
- dprintf( "next_tick: %ld, time: %ld", (long) next_tick, (long) time );
- assert( enabled ); // when disabled, next_tick should always be in the future
-
- int elapsed = ((time - next_tick) / divisor) + 1;
- next_tick += elapsed * divisor;
-
- elapsed += count;
- if ( elapsed >= period ) // avoid unnecessary division
- {
- int n = elapsed / period;
- elapsed -= n * period;
- counter = (counter + n) & 15;
- }
- count = elapsed;
-}
-
-// DSP
-
-const int clocks_per_sample = 32; // 1.024 MHz CPU clock / 32000 samples per second
-
-void Snes_Spc::run_dsp_( spc_time_t time )
-{
- int count = ((time - next_dsp) >> 5) + 1; // divide by clocks_per_sample
- sample_t* buf = sample_buf;
- if ( buf ) {
- sample_buf = buf + count * 2; // stereo
- assert( sample_buf <= buf_end );
- }
- next_dsp += count * clocks_per_sample;
- dsp.run( count, buf );
-}
-
-inline void Snes_Spc::run_dsp( spc_time_t time )
-{
- if ( time >= next_dsp )
- run_dsp_( time );
-}
-
-// Debug-only check for read/write within echo buffer, since this might result in
-// inaccurate emulation due to the DSP not being caught up to the present.
-inline void Snes_Spc::check_for_echo_access( spc_addr_t addr )
-{
- if ( !echo_accessed && !(dsp.read( 0x6C ) & 0x20) )
- {
- // ** If echo accesses are found that require running the DSP, cache
- // the start and end address on DSP writes to speed up checking.
-
- unsigned start = 0x100 * dsp.read( 0x6D );
- unsigned end = start + 0x800 * dsp.read( 0x7D );
- if ( start <= addr && addr < end ) {
- echo_accessed = true;
- dprintf( "Read/write at $%04X within echo buffer\n", (unsigned) addr );
- }
- }
-}
-
-// Read
-
-int Snes_Spc::read( spc_addr_t addr )
-{
- int result = mem.ram [addr];
-
- if ( (rom_addr <= addr && addr < 0xFFFC || addr >= 0xFFFE) && rom_enabled )
- dprintf( "Read from ROM: %04X -> %02X\n", addr, result );
-
- if ( unsigned (addr - 0xF0) < 0x10 )
- {
- assert( 0xF0 <= addr && addr <= 0xFF );
-
- // counters
- int i = addr - 0xFD;
- if ( i >= 0 )
- {
- Timer& t = timer [i];
- t.run_until( time() );
- int old = t.counter;
- t.counter = 0;
- return old;
- }
-
- // dsp
- if ( addr == 0xF3 )
- {
- run_dsp( time() );
- if ( mem.ram [0xF2] >= Spc_Dsp::register_count )
- dprintf( "DSP read from $%02X\n", (int) mem.ram [0xF2] );
- return dsp.read( mem.ram [0xF2] & 0x7F );
- }
-
- if ( addr == 0xF0 || addr == 0xF1 || addr == 0xF8 ||
- addr == 0xF9 || addr == 0xFA )
- dprintf( "Read from register $%02X\n", (int) addr );
-
- // Registers which always read as 0 are handled by setting mem.ram [reg] to 0
- // at startup then never changing that value.
-
- check(( check_for_echo_access( addr ), true ));
- }
-
- return result;
-}
-
-
-// Write
-
-void Snes_Spc::enable_rom( bool enable )
-{
- if ( rom_enabled != enable )
- {
- rom_enabled = enable;
- memcpy( mem.ram + rom_addr, (enable ? boot_rom : extra_ram), rom_size );
- // TODO: ROM can still get overwritten when DSP writes to echo buffer
- }
-}
-
-void Snes_Spc::write( spc_addr_t addr, int data )
-{
- // first page is very common
- if ( addr < 0xF0 ) {
- mem.ram [addr] = (uint8_t) data;
- }
- else switch ( addr )
- {
- // RAM
- default:
- check(( check_for_echo_access( addr ), true ));
- if ( addr < rom_addr ) {
- mem.ram [addr] = (uint8_t) data;
- }
- else {
- extra_ram [addr - rom_addr] = (uint8_t) data;
- if ( !rom_enabled )
- mem.ram [addr] = (uint8_t) data;
- }
- break;
-
- // DSP
- //case 0xF2: // mapped to RAM
- case 0xF3: {
- run_dsp( time() );
- int reg = mem.ram [0xF2];
- if ( next_dsp > 0 ) {
- // skip mode
-
- // key press
- if ( reg == 0x4C )
- keys_pressed |= data & ~dsp.read( 0x5C );
-
- // key release
- if ( reg == 0x5C ) {
- keys_released |= data;
- keys_pressed &= ~data;
- }
- }
- if ( reg < Spc_Dsp::register_count ) {
- dsp.write( reg, data );
- }
- else {
- dprintf( "DSP write to $%02X\n", (int) reg );
- }
- break;
- }
-
- case 0xF0: // Test register
- dprintf( "Wrote $%02X to $F0\n", (int) data );
- break;
-
- // Config
- case 0xF1:
- {
- // timers
- for ( int i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
- if ( !(data & (1 << i)) ) {
- t.enabled = 0;
- t.next_tick = timer_disabled_time;
- }
- else if ( !t.enabled ) {
- // just enabled
- t.enabled = 1;
- t.counter = 0;
- t.count = 0;
- t.next_tick = time();
- }
- }
-
- // port clears
- if ( data & 0x10 ) {
- mem.ram [0xF4] = 0;
- mem.ram [0xF5] = 0;
- }
- if ( data & 0x20 ) {
- mem.ram [0xF6] = 0;
- mem.ram [0xF7] = 0;
- }
-
- enable_rom( (data & 0x80) != 0 );
-
- break;
- }
-
- // Ports
- case 0xF4:
- case 0xF5:
- case 0xF6:
- case 0xF7:
- // to do: handle output ports
- break;
-
- //case 0xF8: // verified on SNES that these are read/write (RAM)
- //case 0xF9:
-
- // Timers
- case 0xFA:
- case 0xFB:
- case 0xFC: {
- Timer& t = timer [addr - 0xFA];
- if ( (t.period & 0xFF) != data ) {
- t.run_until( time() );
- t.period = data ? data : 0x100;
- }
- break;
- }
-
- // Counters (cleared on write)
- case 0xFD:
- case 0xFE:
- case 0xFF:
- dprintf( "Wrote to counter $%02X\n", (int) addr );
- timer [addr - 0xFD].counter = 0;
- break;
- }
-}
-
-// Play
-
-blargg_err_t Snes_Spc::skip( long count )
-{
- if ( count > 4 * 32000L )
- {
- // don't run DSP for long durations (2-3 times faster)
-
- const long sync_count = 32000L * 2;
-
- // keep track of any keys pressed/released (and not subsequently released)
- keys_pressed = 0;
- keys_released = 0;
- // sentinel tells play to ignore DSP
- RETURN_ERR( play( count - sync_count, skip_sentinel ) );
-
- // press/release keys now
- dsp.write( 0x5C, keys_released & ~keys_pressed );
- dsp.write( 0x4C, keys_pressed );
-
- clear_echo();
-
- // play the last few seconds normally to help synchronize DSP
- count = sync_count;
- }
-
- return play( count );
-}
-
-blargg_err_t Snes_Spc::play( long count, sample_t* out )
-{
- require( count % 2 == 0 ); // output is always in pairs of samples
-
- // CPU time() runs from -duration to 0
- spc_time_t duration = (count / 2) * clocks_per_sample;
-
- // DSP output is made on-the-fly when the CPU reads/writes DSP registers
- sample_buf = out;
- buf_end = out + (out && out != skip_sentinel ? count : 0);
- next_dsp = (out == skip_sentinel) ? clocks_per_sample : -duration + clocks_per_sample;
-
- // Localize timer next_tick times and run them to the present to prevent a running
- // but ignored timer's next_tick from getting too far behind and overflowing.
- for ( int i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
- if ( t.enabled )
- {
- t.next_tick -= duration;
- t.run_until( -duration );
- }
- }
-
- // Run CPU for duration, reduced by any extra cycles from previous run
- int elapsed = cpu.run( duration - extra_cycles );
- if ( elapsed > 0 )
- {
- dprintf( "Unhandled instruction $%02X, pc = $%04X\n",
- (int) cpu.read( cpu.r.pc ), (unsigned) cpu.r.pc );
- return "Emulation error (illegal/unsupported instruction)";
- }
- extra_cycles = -elapsed;
-
- // Catch DSP up to present.
- run_dsp( 0 );
- if ( out ) {
- assert( next_dsp == clocks_per_sample );
- assert( out == skip_sentinel || sample_buf - out == count );
- }
- buf_end = 0;
-
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h
deleted file mode 100644
index b558fb71..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Snes_Spc.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Super Nintendo (SNES) SPC-700 APU Emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SNES_SPC_H
-#define SNES_SPC_H
-
-#include "blargg_common.h"
-#include "Spc_Cpu.h"
-#include "Spc_Dsp.h"
-
-class Snes_Spc {
-public:
-
- // Load copy of SPC data into emulator. Clear echo buffer if 'clear_echo' is true.
- enum { spc_file_size = 0x10180 };
- blargg_err_t load_spc( const void* spc, long spc_size );
-
- // Generate 'count' samples and optionally write to 'buf'. Count must be even.
- // Sample output is 16-bit 32kHz, signed stereo pairs with the left channel first.
- typedef short sample_t;
- blargg_err_t play( long count, sample_t* buf = NULL );
-
-// Optional functionality
-
- // Load copy of state into emulator.
- typedef Spc_Cpu::registers_t registers_t;
- blargg_err_t load_state( const registers_t& cpu_state, const void* ram_64k,
- const void* dsp_regs_128 );
-
- // Clear echo buffer, useful because many tracks have junk in the buffer.
- void clear_echo();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { voice_count = Spc_Dsp::voice_count };
- void mute_voices( int mask );
-
- // Skip forward by the specified number of samples (64000 samples = 1 second)
- blargg_err_t skip( long count );
-
- // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped the
- // 16-bit sample range.
- void set_gain( double );
-
- // If true, prevent channels and global volumes from being phase-negated
- void disable_surround( bool disable = true );
-
- // Set 128 bytes to use for IPL boot ROM. Makes copy. Default is zero filled,
- // to avoid including copyrighted code from the SPC-700.
- void set_ipl_rom( const void* );
-
- void set_tempo( double );
-
-public:
- Snes_Spc();
- typedef BOOST::uint8_t uint8_t;
-private:
- // timers
- struct Timer
- {
- spc_time_t next_tick;
- int period;
- int count;
- int divisor;
- int enabled;
- int counter;
-
- void run_until_( spc_time_t );
- void run_until( spc_time_t time )
- {
- if ( time >= next_tick )
- run_until_( time );
- }
- };
- enum { timer_count = 3 };
- Timer timer [timer_count];
-
- // hardware
- int extra_cycles;
- spc_time_t time() const;
- int read( spc_addr_t );
- void write( spc_addr_t, int );
- friend class Spc_Cpu;
-
- // dsp
- sample_t* sample_buf;
- sample_t* buf_end; // to do: remove this once possible bug resolved
- spc_time_t next_dsp;
- Spc_Dsp dsp;
- int keys_pressed;
- int keys_released;
- sample_t skip_sentinel [1]; // special value for play() passed by skip()
- void run_dsp( spc_time_t );
- void run_dsp_( spc_time_t );
- bool echo_accessed;
- void check_for_echo_access( spc_addr_t );
-
- // boot rom
- enum { rom_size = 64 };
- enum { rom_addr = 0xFFC0 };
- bool rom_enabled;
- void enable_rom( bool );
-
- // CPU and RAM (at end because it's large)
- Spc_Cpu cpu;
- uint8_t extra_ram [rom_size];
- struct {
- // padding to catch jumps before beginning or past end
- uint8_t padding1 [0x100];
- uint8_t ram [0x10000];
- uint8_t padding2 [0x100];
- } mem;
- uint8_t boot_rom [rom_size];
-};
-
-inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
-
-inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
-
-inline void Snes_Spc::set_gain( double v ) { dsp.set_gain( v ); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.cpp
deleted file mode 100644
index fb9983b8..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.cpp
+++ /dev/null
@@ -1,1062 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Spc_Cpu.h"
-
-#include "blargg_endian.h"
-#include "Snes_Spc.h"
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Several instructions are commented out (or not even implemented). These aren't
-// used by the SPC files tested.
-
-// Optimize performance for the most common instructions, and size for the rest:
-//
-// 15% 0xF0 BEQ rel
-// 8% 0xE4 MOV A,dp
-// 4% 0xF5 MOV A,abs+X
-// 4% 0xD0 BNE rel
-// 4% 0x6F RET
-// 4% 0x3F CALL addr
-// 4% 0xF4 MOV A,dp+X
-// 3% 0xC4 MOV dp,A
-// 2% 0xEB MOV Y,dp
-// 2% 0x3D INC X
-// 2% 0xF6 MOV A,abs+Y
-// (1% and below not shown)
-
-Spc_Cpu::Spc_Cpu( Snes_Spc* e, uint8_t* ram_in ) : ram( ram_in ), emu( *e )
-{
- remain_ = 0;
- assert( INT_MAX >= 0x7FFFFFFF ); // requires 32-bit int
- blargg_verify_byte_order();
-}
-
-#define READ( addr ) (emu.read( addr ))
-#define WRITE( addr, value ) (emu.write( addr, value ))
-
-#define READ_DP( addr ) READ( (addr) + dp )
-#define WRITE_DP( addr, value ) WRITE( (addr) + dp, value )
-
-#define READ_PROG( addr ) (ram [addr])
-#define READ_PROG16( addr ) GET_LE16( &READ_PROG( addr ) )
-
-int Spc_Cpu::read( spc_addr_t addr )
-{
- return READ( addr );
-}
-
-void Spc_Cpu::write( spc_addr_t addr, int data )
-{
- WRITE( addr, data );
-}
-
-// Cycle table derived from text copy of SPC-700 manual (using regular expressions)
-static unsigned char const cycle_table [0x100] = {
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,6,8, // 0
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,4,6, // 1
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,5,4, // 2
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,3,8, // 3
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,6,6, // 4
- 2,8,4,5,4,5,5,6,5,5,4,5,2,2,4,3, // 5
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,5,5, // 6
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,6, // 7
- 2,8,4,5,3,4,3,6,2,6,5,4,5,2,4,5, // 8
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,12,5,// 9
- 3,8,4,5,3,4,3,6,2,6,4,4,5,2,4,4, // A
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,4, // B
- 3,8,4,5,4,5,4,7,2,5,6,4,5,2,4,9, // C
- 2,8,4,5,5,6,6,7,4,5,4,5,2,2,6,3, // D
- 2,8,4,5,3,4,3,6,2,4,5,3,4,3,4,3, // E
- 2,8,4,5,4,5,5,6,3,4,5,4,2,2,4,3 // F
-};
-
-// The C,mem instructions are hardly used, so a non-inline function is used for
-// the common access code.
-unsigned Spc_Cpu::mem_bit( spc_addr_t pc )
-{
- unsigned addr = READ_PROG16( pc );
- unsigned t = READ( addr & 0x1FFF ) >> (addr >> 13);
- return (t << 8) & 0x100;
-}
-
-spc_time_t Spc_Cpu::run( spc_time_t cycle_count )
-{
- remain_ = cycle_count;
-
- uint8_t* const ram = this->ram; // cache
-
- // Stack pointer is kept one greater than usual SPC stack pointer to allow
- // common pre-decrement and post-increment memory instructions that some
- // processors have. Address wrap-around isn't supported.
- #define PUSH( v ) (*--sp = uint8_t (v))
- #define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
- #define POP() (*sp++)
- #define SET_SP( v ) (sp = ram + 0x101 + (v))
- #define GET_SP() (sp - 0x101 - ram)
-
- uint8_t* sp;
- SET_SP( r.sp );
-
- // registers
- unsigned pc = (unsigned) r.pc;
- int a = r.a;
- int x = r.x;
- int y = r.y;
-
- // status flags
-
- const int st_n = 0x80;
- const int st_v = 0x40;
- const int st_p = 0x20;
- const int st_b = 0x10;
- const int st_h = 0x08;
- const int st_i = 0x04;
- const int st_z = 0x02;
- const int st_c = 0x01;
-
- #define IS_NEG (nz & 0x880)
-
- #define CALC_STATUS( out ) do {\
- out = status & ~(st_n | st_z | st_c);\
- out |= (c >> 8) & st_c;\
- out |= (dp >> 3) & st_p;\
- if ( IS_NEG ) out |= st_n;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & ~(st_n | st_z | st_c | st_p);\
- c = in << 8;\
- nz = (in << 4) & 0x800;\
- nz |= ~in & st_z;\
- dp = (in << 3) & 0x100;\
- } while ( 0 )
-
- int status;
- int c; // store C as 'c' & 0x100.
- int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x880) != 0
- unsigned dp; // direct page base
- {
- int temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-
- unsigned data; // first operand of instruction and temporary across function calls
-
- // Common endings for instructions
-cbranch_taken_loop: // compare and branch
- pc += (BOOST::int8_t) READ_PROG( pc );
- remain_ -= 2;
-inc_pc_loop: // end of instruction with an operand
- pc++;
-loop:
-
- check( (unsigned) pc < 0x10000 );
- check( (unsigned) GET_SP() < 0x100 );
-
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- unsigned opcode = READ_PROG( pc );
- pc++;
- // to do: if pc is at end of memory, this will get wrong byte
- data = READ_PROG( pc );
-
- if ( remain_ <= 0 )
- goto stop;
-
- remain_ -= cycle_table [opcode];
-
- // Use 'data' for temporaries whose lifetime crosses read/write calls, otherwise
- // use a local temporary.
- switch ( opcode )
- {
-
- #define BRANCH( cond ) {\
- pc++;\
- int offset = (BOOST::int8_t) data;\
- if ( cond ) {\
- pc += offset;\
- remain_ -= 2;\
- }\
- goto loop;\
- }
-
-// Most-Common
-
- case 0xF0: // BEQ (most common)
- BRANCH( !(uint8_t) nz )
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz )
-
- case 0x3F: // CALL
- PUSH16( pc + 2 );
- pc = READ_PROG16( pc );
- goto loop;
-
- case 0x6F: // RET
- pc = POP();
- pc += POP() * 0x100;
- goto loop;
-
-#define CASE( n ) case n:
-
-// Define common address modes based on opcode for immediate mode. Execution
-// ends with data set to the address of the operand.
-#define ADDR_MODES( op )\
- CASE( op - 0x02 ) /* (X) */\
- data = x + dp;\
- pc--;\
- goto end_##op;\
- CASE( op + 0x0F ) /* (dp)+Y */\
- data = READ_PROG16( data + dp ) + y;\
- goto end_##op;\
- CASE( op - 0x01 ) /* (dp+X) */\
- data = READ_PROG16( uint8_t (data + x) + dp );\
- goto end_##op;\
- CASE( op + 0x0E ) /* abs+Y */\
- data += y;\
- goto abs_##op;\
- CASE( op + 0x0D ) /* abs+X */\
- data += x;\
- CASE( op - 0x03 ) /* abs */\
- abs_##op:\
- pc++;\
- data += 0x100 * READ_PROG( pc );\
- goto end_##op;\
- CASE( op + 0x0C ) /* dp+X */\
- data = uint8_t (data + x);\
- CASE( op - 0x04 ) /* dp */\
- data += dp;\
- end_##op:
-
-// 1. 8-bit Data Transmission Commands. Group I
-
- ADDR_MODES( 0xE8 ) // MOV A,addr
- // case 0xE4: // MOV a,dp (most common)
- mov_a_addr:
- a = nz = READ( data );
- goto inc_pc_loop;
- case 0xBF: // MOV A,(X)+
- data = x + dp;
- x = uint8_t (x + 1);
- pc--;
- goto mov_a_addr;
-
- case 0xE8: // MOV A,imm
- a = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xF9: // MOV X,dp+Y
- data = uint8_t (data + y);
- case 0xF8: // MOV X,dp
- data += dp;
- goto mov_x_addr;
- case 0xE9: // MOV X,abs
- data = READ_PROG16( pc );
- pc++;
- mov_x_addr:
- data = READ( data );
- case 0xCD: // MOV X,imm
- x = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xFB: // MOV Y,dp+X
- data = uint8_t (data + x);
- case 0xEB: // MOV Y,dp
- data += dp;
- goto mov_y_addr;
- case 0xEC: // MOV Y,abs
- data = READ_PROG16( pc );
- pc++;
- mov_y_addr:
- data = READ( data );
- case 0x8D: // MOV Y,imm
- y = data;
- nz = data;
- goto inc_pc_loop;
-
-// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
-
- ADDR_MODES( 0xC8 ) // MOV addr,A
- WRITE( data, a );
- goto inc_pc_loop;
-
- {
- int temp;
- case 0xCC: // MOV abs,Y
- temp = y;
- goto mov_abs_temp;
- case 0xC9: // MOV abs,X
- temp = x;
- mov_abs_temp:
- WRITE( READ_PROG16( pc ), temp );
- pc += 2;
- goto loop;
- }
-
- case 0xD9: // MOV dp+Y,X
- data = uint8_t (data + y);
- case 0xD8: // MOV dp,X
- WRITE( data + dp, x );
- goto inc_pc_loop;
-
- case 0xDB: // MOV dp+X,Y
- data = uint8_t (data + x);
- case 0xCB: // MOV dp,Y
- WRITE( data + dp, y );
- goto inc_pc_loop;
-
- case 0xFA: // MOV dp,dp
- data = READ( data + dp );
- case 0x8F: // MOV dp,#imm
- pc++;
- WRITE_DP( READ_PROG( pc ), data );
- goto inc_pc_loop;
-
-// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
-
- case 0x7D: // MOV A,X
- a = x;
- nz = x;
- goto loop;
-
- case 0xDD: // MOV A,Y
- a = y;
- nz = y;
- goto loop;
-
- case 0x5D: // MOV X,A
- x = a;
- nz = a;
- goto loop;
-
- case 0xFD: // MOV Y,A
- y = a;
- nz = a;
- goto loop;
-
- case 0x9D: // MOV X,SP
- x = nz = GET_SP();
- goto loop;
-
- case 0xBD: // MOV SP,X
- SET_SP( x );
- goto loop;
-
- //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
-
- case 0xAF: // MOV (X)+,A
- WRITE_DP( x, a );
- x++;
- goto loop;
-
-// 5. 8-BIT LOGIC OPERATION COMMANDS
-
-#define LOGICAL_OP( op, func )\
- ADDR_MODES( op ) /* addr */\
- data = READ( data );\
- case op: /* imm */\
- nz = a func##= data;\
- goto inc_pc_loop;\
- { unsigned addr;\
- case op + 0x11: /* X,Y */\
- data = READ_DP( y );\
- addr = x + dp;\
- pc--;\
- goto addr_##op;\
- case op + 0x01: /* dp,dp */\
- data = READ_DP( data );\
- case op + 0x10: /*dp,imm*/\
- pc++;\
- addr = READ_PROG( pc ) + dp;\
- addr_##op:\
- nz = data func READ( addr );\
- WRITE( addr, nz );\
- goto inc_pc_loop;\
- }
-
- LOGICAL_OP( 0x28, & ); // AND
-
- LOGICAL_OP( 0x08, | ); // OR
-
- LOGICAL_OP( 0x48, ^ ); // EOR
-
-// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
-
- ADDR_MODES( 0x68 ) // CMP addr
- data = READ( data );
- case 0x68: // CMP imm
- nz = a - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x79: // CMP (X),(Y)
- data = READ_DP( x );
- nz = data - READ_DP( y );
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x69: // CMP (dp),(dp)
- data = READ_DP( data );
- case 0x78: // CMP dp,imm
- pc++;
- nz = READ_DP( READ_PROG( pc ) ) - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x3E: // CMP X,dp
- data += dp;
- goto cmp_x_addr;
- case 0x1E: // CMP X,abs
- data = READ_PROG16( pc );
- pc++;
- cmp_x_addr:
- data = READ( data );
- case 0xC8: // CMP X,imm
- nz = x - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x7E: // CMP Y,dp
- data += dp;
- goto cmp_y_addr;
- case 0x5E: // CMP Y,abs
- data = READ_PROG16( pc );
- pc++;
- cmp_y_addr:
- data = READ( data );
- case 0xAD: // CMP Y,imm
- nz = y - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- {
- int addr;
- case 0xB9: // SBC (x),(y)
- case 0x99: // ADC (x),(y)
- pc--; // compensate for inc later
- data = READ_DP( x );
- addr = y + dp;
- goto adc_addr;
- case 0xA9: // SBC dp,dp
- case 0x89: // ADC dp,dp
- data = READ_DP( data );
- case 0xB8: // SBC dp,imm
- case 0x98: // ADC dp,imm
- pc++;
- addr = READ_PROG( pc ) + dp;
- adc_addr:
- nz = READ( addr );
- goto adc_data;
-
-// catch ADC and SBC together, then decode later based on operand
-#undef CASE
-#define CASE( n ) case n: case (n) + 0x20:
- ADDR_MODES( 0x88 ) // ADC/SBC addr
- data = READ( data );
- case 0xA8: // SBC imm
- case 0x88: // ADC imm
- addr = -1; // A
- nz = a;
- adc_data: {
- if ( opcode & 0x20 )
- data ^= 0xFF; // SBC
- int carry = (c >> 8) & 1;
- int ov = (nz ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- int hc = (nz & 15) + carry;
- c = nz += data + carry;
- hc = (nz & 15) - hc;
- status = (status & ~(st_v | st_h)) | ((ov >> 2) & st_v) | ((hc >> 1) & st_h);
- if ( addr < 0 ) {
- a = (uint8_t) nz;
- goto inc_pc_loop;
- }
- WRITE( addr, (uint8_t) nz );
- goto inc_pc_loop;
- }
-
- }
-
-// 6. ADDITION & SUBTRACTION COMMANDS
-
-#define INC_DEC_REG( reg, n )\
- nz = reg + n;\
- reg = (uint8_t) nz;\
- goto loop;
-
- case 0xBC: INC_DEC_REG( a, 1 ) // INC A
- case 0x3D: INC_DEC_REG( x, 1 ) // INC X
- case 0xFC: INC_DEC_REG( y, 1 ) // INC Y
-
- case 0x9C: INC_DEC_REG( a, -1 ) // DEC A
- case 0x1D: INC_DEC_REG( x, -1 ) // DEC X
- case 0xDC: INC_DEC_REG( y, -1 ) // DEC Y
-
- case 0x9B: // DEC dp+X
- case 0xBB: // INC dp+X
- data = uint8_t (data + x);
- case 0x8B: // DEC dp
- case 0xAB: // INC dp
- data += dp;
- goto inc_abs;
- case 0x8C: // DEC abs
- case 0xAC: // INC abs
- data = READ_PROG16( pc );
- pc++;
- inc_abs:
- nz = ((opcode >> 4) & 2) - 1;
- nz += READ( data );
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
-// 7. SHIFT, ROTATION COMMANDS
-
- case 0x5C: // LSR A
- c = 0;
- case 0x7C:{// ROR A
- nz = ((c >> 1) & 0x80) | (a >> 1);
- c = a << 8;
- a = nz;
- goto loop;
- }
-
- case 0x1C: // ASL A
- c = 0;
- case 0x3C:{// ROL A
- int temp = (c >> 8) & 1;
- c = a << 1;
- nz = c | temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x0B: // ASL dp
- c = 0;
- data += dp;
- goto rol_mem;
- case 0x1B: // ASL dp+X
- c = 0;
- case 0x3B: // ROL dp+X
- data = uint8_t (data + x);
- case 0x2B: // ROL dp
- data += dp;
- goto rol_mem;
- case 0x0C: // ASL abs
- c = 0;
- case 0x2C: // ROL abs
- data = READ_PROG16( pc );
- pc++;
- rol_mem:
- nz = (c >> 8) & 1;
- nz |= (c = READ( data ) << 1);
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
- case 0x4B: // LSR dp
- c = 0;
- data += dp;
- goto ror_mem;
- case 0x5B: // LSR dp+X
- c = 0;
- case 0x7B: // ROR dp+X
- data = uint8_t (data + x);
- case 0x6B: // ROR dp
- data += dp;
- goto ror_mem;
- case 0x4C: // LSR abs
- c = 0;
- case 0x6C: // ROR abs
- data = READ_PROG16( pc );
- pc++;
- ror_mem: {
- int temp = READ( data );
- nz = ((c >> 1) & 0x80) | (temp >> 1);
- c = temp << 8;
- WRITE( data, nz );
- goto inc_pc_loop;
- }
-
- case 0x9F: // XCN
- nz = a = (a >> 4) | uint8_t (a << 4);
- goto loop;
-
-// 8. 16-BIT TRANSMISION COMMANDS
-
- case 0xBA: // MOVW YA,dp
- a = READ_DP( data );
- nz = (a & 0x7F) | (a >> 1);
- y = READ_DP( uint8_t (data + 1) );
- nz |= y;
- goto inc_pc_loop;
-
- case 0xDA: // MOVW dp,YA
- WRITE_DP( data, a );
- WRITE_DP( uint8_t (data + 1), y );
- goto inc_pc_loop;
-
-// 9. 16-BIT OPERATION COMMANDS
-
- case 0x3A: // INCW dp
- case 0x1A:{// DECW dp
- data += dp;
-
- // low byte
- int temp = READ( data );
- temp += ((opcode >> 4) & 2) - 1; // +1 for INCW, -1 for DECW
- nz = ((temp >> 1) | temp) & 0x7F;
- WRITE( data, (uint8_t) temp );
-
- // high byte
- data = uint8_t (data + 1) + dp;
- temp >>= 8;
- temp = uint8_t (temp + READ( data ));
- nz |= temp;
- WRITE( data, temp );
-
- goto inc_pc_loop;
- }
-
- case 0x9A: // SUBW YA,dp
- case 0x7A: // ADDW YA,dp
- {
- // read 16-bit addend
- int temp = READ_DP( data );
- int sign = READ_DP( uint8_t (data + 1) );
- temp += 0x100 * sign;
- status &= ~(st_v | st_h);
-
- // to do: fix half-carry for SUBW (it's probably wrong)
-
- // for SUBW, negate and truncate to 16 bits
- if ( opcode & 0x80 ) {
- temp = (temp ^ 0xFFFF) + 1;
- sign = temp >> 8;
- }
-
- // add low byte (A)
- temp += a;
- a = (uint8_t) temp;
- nz = (temp | (temp >> 1)) & 0x7F;
-
- // add high byte (Y)
- temp >>= 8;
- c = y + temp;
- nz = (nz | c) & 0xFF;
-
- // half-carry (temporary avoids CodeWarrior optimizer bug)
- unsigned hc = (c & 15) - (y & 15);
- status |= (hc >> 4) & st_h;
-
- // overflow if sign of YA changed when previous sign and addend sign were same
- status |= (((c ^ y) & ~(y ^ sign)) >> 1) & st_v;
-
- y = (uint8_t) c;
-
- goto inc_pc_loop;
- }
-
- case 0x5A: { // CMPW YA,dp
- int temp = a - READ_DP( data );
- nz = ((temp >> 1) | temp) & 0x7F;
- temp = y + (temp >> 8);
- temp -= READ_DP( uint8_t (data + 1) );
- nz |= temp;
- c = ~temp;
- nz &= 0xFF;
- goto inc_pc_loop;
- }
-
-// 10. MULTIPLICATION & DIVISON COMMANDS
-
- case 0xCF: { // MUL YA
- unsigned temp = y * a;
- a = (uint8_t) temp;
- nz = ((temp >> 1) | temp) & 0x7F;
- y = temp >> 8;
- nz |= y;
- goto loop;
- }
-
- case 0x9E: // DIV YA,X
- {
- // behavior based on SPC CPU tests
-
- status &= ~(st_h | st_v);
-
- if ( (y & 15) >= (x & 15) )
- status |= st_h;
-
- if ( y >= x )
- status |= st_v;
-
- unsigned ya = y * 0x100 + a;
- if ( y < x * 2 )
- {
- a = ya / x;
- y = ya - a * x;
- }
- else
- {
- a = 255 - (ya - x * 0x200) / (256 - x);
- y = x + (ya - x * 0x200) % (256 - x);
- }
-
- nz = (uint8_t) a;
- a = (uint8_t) a;
-
- goto loop;
- }
-
-// 11. DECIMAL COMPENSATION COMMANDS
-
- // seem unused
- // case 0xDF: // DAA
- // case 0xBE: // DAS
-
-// 12. BRANCHING COMMANDS
-
- case 0x2F: // BRA rel
- pc += (BOOST::int8_t) data;
- goto inc_pc_loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x03: // BBS dp.bit,rel
- case 0x23:
- case 0x43:
- case 0x63:
- case 0x83:
- case 0xA3:
- case 0xC3:
- case 0xE3:
- pc++;
- if ( (READ_DP( data ) >> (opcode >> 5)) & 1 )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0x13: // BBC dp.bit,rel
- case 0x33:
- case 0x53:
- case 0x73:
- case 0x93:
- case 0xB3:
- case 0xD3:
- case 0xF3:
- pc++;
- if ( !((READ_DP( data ) >> (opcode >> 5)) & 1) )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xDE: // CBNE dp+X,rel
- data = uint8_t (data + x);
- // fall through
- case 0x2E: // CBNE dp,rel
- pc++;
- if ( READ_DP( data ) != a )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xFE: // DBNZ Y,rel
- y = uint8_t (y - 1);
- BRANCH( y )
-
- case 0x6E: { // DBNZ dp,rel
- pc++;
- unsigned temp = READ_DP( data ) - 1;
- WRITE_DP( (uint8_t) data, (uint8_t) temp );
- if ( temp )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
- }
-
- case 0x1F: // JMP (abs+X)
- pc = READ_PROG16( pc ) + x;
- // fall through
- case 0x5F: // JMP abs
- pc = READ_PROG16( pc );
- goto loop;
-
-// 13. SUB-ROUTINE CALL RETURN COMMANDS
-
- case 0x0F:{// BRK
- check( false ); // untested
- PUSH16( pc + 1 );
- pc = READ_PROG16( 0xFFDE ); // vector address verified
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- status = (status | st_b) & ~st_i;
- goto loop;
- }
-
- case 0x4F: // PCALL offset
- pc++;
- PUSH16( pc );
- pc = 0xFF00 + data;
- goto loop;
-
- case 0x01: // TCALL n
- case 0x11:
- case 0x21:
- case 0x31:
- case 0x41:
- case 0x51:
- case 0x61:
- case 0x71:
- case 0x81:
- case 0x91:
- case 0xA1:
- case 0xB1:
- case 0xC1:
- case 0xD1:
- case 0xE1:
- case 0xF1:
- PUSH16( pc );
- pc = READ_PROG16( 0xFFDE - (opcode >> 3) );
- goto loop;
-
-// 14. STACK OPERATION COMMANDS
-
- {
- int temp;
- case 0x7F: // RET1
- temp = POP();
- pc = POP();
- pc |= POP() << 8;
- goto set_status;
- case 0x8E: // POP PSW
- temp = POP();
- set_status:
- SET_STATUS( temp );
- goto loop;
- }
-
- case 0x0D: { // PUSH PSW
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- goto loop;
- }
-
- case 0x2D: // PUSH A
- PUSH( a );
- goto loop;
-
- case 0x4D: // PUSH X
- PUSH( x );
- goto loop;
-
- case 0x6D: // PUSH Y
- PUSH( y );
- goto loop;
-
- case 0xAE: // POP A
- a = POP();
- goto loop;
-
- case 0xCE: // POP X
- x = POP();
- goto loop;
-
- case 0xEE: // POP Y
- y = POP();
- goto loop;
-
-// 15. BIT OPERATION COMMANDS
-
- case 0x02: // SET1
- case 0x22:
- case 0x42:
- case 0x62:
- case 0x82:
- case 0xA2:
- case 0xC2:
- case 0xE2:
- case 0x12: // CLR1
- case 0x32:
- case 0x52:
- case 0x72:
- case 0x92:
- case 0xB2:
- case 0xD2:
- case 0xF2: {
- data += dp;
- int bit = 1 << (opcode >> 5);
- int mask = ~bit;
- if ( opcode & 0x10 )
- bit = 0;
- WRITE( data, (READ( data ) & mask) | bit );
- goto inc_pc_loop;
- }
-
- case 0x0E: // TSET1 abs
- case 0x4E:{// TCLR1 abs
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data );
- nz = temp & a;
- temp &= ~a;
- if ( !(opcode & 0x40) )
- temp |= a;
- WRITE( data, temp );
- goto loop;
- }
-
- case 0x4A: // AND1 C,mem.bit
- c &= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x6A: // AND1 C,/mem.bit
- check( false ); // untested
- c &= ~mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x0A: // OR1 C,mem.bit
- check( false ); // untested
- c |= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x2A: // OR1 C,/mem.bit
- check( false ); // untested
- c |= ~mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x8A: // EOR1 C,mem.bit
- c ^= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0xEA: { // NOT1 mem.bit
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- temp ^= 1 << (data >> 13);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xCA: { // MOV1 mem.bit,C
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- unsigned bit = data >> 13;
- temp = (temp & ~(1 << bit)) | (((c >> 8) & 1) << bit);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xAA: // MOV1 C,mem.bit
- c = mem_bit( pc );
- pc += 2;
- goto loop;
-
-// 16. PROGRAM STATUS FLAG OPERATION COMMANDS
-
- case 0x60: // CLRC
- c = 0;
- goto loop;
-
- case 0x80: // SETC
- c = ~0;
- goto loop;
-
- case 0xED: // NOTC
- c ^= 0x100;
- goto loop;
-
- case 0xE0: // CLRV
- status &= ~(st_v | st_h);
- goto loop;
-
- case 0x20: // CLRP
- dp = 0;
- goto loop;
-
- case 0x40: // SETP
- dp = 0x100;
- goto loop;
-
- case 0xA0: // EI
- check( false ); // untested
- status |= st_i;
- goto loop;
-
- case 0xC0: // DI
- check( false ); // untested
- status &= ~st_i;
- goto loop;
-
-// 17. OTHER COMMANDS
-
- case 0x00: // NOP
- goto loop;
-
- //case 0xEF: // SLEEP
- //case 0xFF: // STOP
-
- } // switch
-
- // unhandled instructions fall out of switch so emulator can catch them
-
-stop:
- pc--;
-
- {
- int temp;
- CALC_STATUS( temp );
- r.status = (uint8_t) temp;
- }
-
- r.pc = pc;
- r.sp = (uint8_t) GET_SP();
- r.a = (uint8_t) a;
- r.x = (uint8_t) x;
- r.y = (uint8_t) y;
-
- return remain_;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.h
deleted file mode 100644
index 2252663b..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Cpu.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Super Nintendo (SNES) SPC-700 CPU emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SPC_CPU_H
-#define SPC_CPU_H
-
-#include "blargg_common.h"
-
-typedef unsigned spc_addr_t;
-typedef blargg_long spc_time_t;
-
-class Snes_Spc;
-
-class Spc_Cpu {
- typedef BOOST::uint8_t uint8_t;
- uint8_t* const ram;
-public:
- // Keeps pointer to 64K RAM
- Spc_Cpu( Snes_Spc* spc, uint8_t* ram );
-
- // SPC-700 registers. *Not* kept updated during a call to run().
- struct registers_t {
- long pc; // more than 16 bits to allow overflow detection
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- } r;
-
- // Run CPU for at least 'count' cycles. Return the number of cycles remaining
- // when emulation stopped (negative if extra cycles were emulated). Emulation
- // stops when there are no more remaining cycles or an unhandled instruction
- // is encountered (STOP, SLEEP, and any others not yet implemented). In the
- // latter case, the return value is greater than zero.
- spc_time_t run( spc_time_t count );
-
- // Number of clock cycles remaining for current run() call
- spc_time_t remain() const;
-
- // Access memory as the emulated CPU does
- int read ( spc_addr_t );
- void write( spc_addr_t, int );
-
-private:
- // noncopyable
- Spc_Cpu( const Spc_Cpu& );
- Spc_Cpu& operator = ( const Spc_Cpu& );
- unsigned mem_bit( spc_addr_t );
-
- spc_time_t remain_;
- Snes_Spc& emu;
-};
-
-inline spc_time_t Spc_Cpu::remain() const { return remain_; }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.cpp
deleted file mode 100644
index 3d934f63..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.cpp
+++ /dev/null
@@ -1,666 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-// Based on Brad Martin's OpenSPC DSP emulator
-
-#include "Spc_Dsp.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2002 Brad Martin */
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-Spc_Dsp::Spc_Dsp( uint8_t* ram_ ) : ram( ram_ )
-{
- set_gain( 1.0 );
- mute_voices( 0 );
- disable_surround( false );
-
- assert( offsetof (globals_t,unused9 [2]) == register_count );
- assert( sizeof (voice) == register_count );
- blargg_verify_byte_order();
-}
-
-void Spc_Dsp::mute_voices( int mask )
-{
- for ( int i = 0; i < voice_count; i++ )
- voice_state [i].enabled = (mask >> i & 1) ? 31 : 7;
-}
-
-void Spc_Dsp::reset()
-{
- keys = 0;
- echo_ptr = 0;
- noise_count = 0;
- noise = 1;
- fir_offset = 0;
-
- g.flags = 0xE0; // reset, mute, echo off
- g.key_ons = 0;
-
- for ( int i = 0; i < voice_count; i++ )
- {
- voice_t& v = voice_state [i];
- v.on_cnt = 0;
- v.volume [0] = 0;
- v.volume [1] = 0;
- v.envstate = state_release;
- }
-
- memset( fir_buf, 0, sizeof fir_buf );
-}
-
-void Spc_Dsp::write( int i, int data )
-{
- require( (unsigned) i < register_count );
-
- reg [i] = data;
- int high = i >> 4;
- switch ( i & 0x0F )
- {
- // voice volume
- case 0:
- case 1: {
- short* volume = voice_state [high].volume;
- int left = (int8_t) reg [i & ~1];
- int right = (int8_t) reg [i | 1];
- volume [0] = left;
- volume [1] = right;
- // kill surround only if enabled and signs of volumes differ
- if ( left * right < surround_threshold )
- {
- if ( left < 0 )
- volume [0] = -left;
- else
- volume [1] = -right;
- }
- break;
- }
-
- // fir coefficients
- case 0x0F:
- fir_coeff [high] = (int8_t) data; // sign-extend
- break;
- }
-}
-
-// This table is for envelope timing. It represents the number of counts
-// that should be subtracted from the counter each sample period (32kHz).
-// The counter starts at 30720 (0x7800). Each count divides exactly into
-// 0x7800 without remainder.
-const int env_rate_init = 0x7800;
-static short const env_rates [0x20] =
-{
- 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
- 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
- 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
- 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
-};
-
-const int env_range = 0x800;
-
-inline int Spc_Dsp::clock_envelope( int v )
-{ /* Return value is current
- * ENVX */
- raw_voice_t& raw_voice = this->voice [v];
- voice_t& voice = voice_state [v];
-
- int envx = voice.envx;
- if ( voice.envstate == state_release )
- {
- /*
- * Docs: "When in the state of "key off". the "click" sound is
- * prevented by the addition of the fixed value 1/256" WTF???
- * Alright, I'm going to choose to interpret that this way:
- * When a note is keyed off, start the RELEASE state, which
- * subtracts 1/256th each sample period (32kHz). Note there's
- * no need for a count because it always happens every update.
- */
- envx -= env_range / 256;
- if ( envx <= 0 )
- {
- envx = 0;
- keys &= ~(1 << v);
- return -1;
- }
- voice.envx = envx;
- raw_voice.envx = envx >> 8;
- return envx;
- }
-
- int cnt = voice.envcnt;
- int adsr1 = raw_voice.adsr [0];
- if ( adsr1 & 0x80 )
- {
- switch ( voice.envstate )
- {
- case state_attack: {
- // increase envelope by 1/64 each step
- int t = adsr1 & 15;
- if ( t == 15 )
- {
- envx += env_range / 2;
- }
- else
- {
- cnt -= env_rates [t * 2 + 1];
- if ( cnt > 0 )
- break;
- envx += env_range / 64;
- cnt = env_rate_init;
- }
- if ( envx >= env_range )
- {
- envx = env_range - 1;
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- }
-
- case state_decay: {
- // Docs: "DR... [is multiplied] by the fixed value
- // 1-1/256." Well, at least that makes some sense.
- // Multiplying ENVX by 255/256 every time DECAY is
- // updated.
- cnt -= env_rates [((adsr1 >> 3) & 0xE) + 0x10];
- if ( cnt <= 0 )
- {
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- voice.envx = envx;
- }
- int sustain_level = raw_voice.adsr [1] >> 5;
-
- if ( envx <= (sustain_level + 1) * 0x100 )
- voice.envstate = state_sustain;
- break;
- }
-
- case state_sustain:
- // Docs: "SR [is multiplied] by the fixed value 1-1/256."
- // Multiplying ENVX by 255/256 every time SUSTAIN is
- // updated.
- cnt -= env_rates [raw_voice.adsr [1] & 0x1F];
- if ( cnt <= 0 )
- {
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- voice.envx = envx;
- }
- break;
-
- case state_release:
- // handled above
- break;
- }
- }
- else
- { /* GAIN mode is set */
- /*
- * Note: if the game switches between ADSR and GAIN modes
- * partway through, should the count be reset, or should it
- * continue from where it was? Does the DSP actually watch for
- * that bit to change, or does it just go along with whatever
- * it sees when it performs the update? I'm going to assume
- * the latter and not update the count, unless I see a game
- * that obviously wants the other behavior. The effect would
- * be pretty subtle, in any case.
- */
- int t = raw_voice.gain;
- if (t < 0x80)
- {
- envx = voice.envx = t << 4;
- }
- else switch (t >> 5)
- {
- case 4: /* Docs: "Decrease (linear): Subtraction
- * of the fixed value 1/64." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx -= env_range / 64;
- if ( envx < 0 )
- {
- envx = 0;
- if ( voice.envstate == state_attack )
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- case 5: /* Docs: "Drecrease <sic> (exponential):
- * Multiplication by the fixed value
- * 1-1/256." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- if ( envx < 0 )
- {
- envx = 0;
- if ( voice.envstate == state_attack )
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- case 6: /* Docs: "Increase (linear): Addition of
- * the fixed value 1/64." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx += env_range / 64;
- if ( envx >= env_range )
- envx = env_range - 1;
- voice.envx = envx;
- break;
- case 7: /* Docs: "Increase (bent line): Addition
- * of the constant 1/64 up to .75 of the
- * constaint <sic> 1/256 from .75 to 1." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- if ( envx < env_range * 3 / 4 )
- envx += env_range / 64;
- else
- envx += env_range / 256;
- if ( envx >= env_range )
- envx = env_range - 1;
- voice.envx = envx;
- break;
- }
- }
- voice.envcnt = cnt;
- raw_voice.envx = envx >> 4;
- return envx;
-}
-
-// Clamp n into range -32768 <= n <= 32767
-inline int clamp_16( int n )
-{
- if ( (BOOST::int16_t) n != n )
- n = BOOST::int16_t (0x7FFF - (n >> 31));
- return n;
-}
-
-void Spc_Dsp::run( long count, short* out_buf )
-{
- // to do: make clock_envelope() inline so that this becomes a leaf function?
-
- // Should we just fill the buffer with silence? Flags won't be cleared
- // during this run so it seems it should keep resetting every sample.
- if ( g.flags & 0x80 )
- reset();
-
- struct src_dir {
- char start [2];
- char loop [2];
- };
-
- const src_dir* const sd = (src_dir*) &ram [g.wave_page * 0x100];
-
- int left_volume = g.left_volume;
- int right_volume = g.right_volume;
- if ( left_volume * right_volume < surround_threshold )
- right_volume = -right_volume; // kill global surround
- left_volume *= emu_gain;
- right_volume *= emu_gain;
-
- while ( --count >= 0 )
- {
- // Here we check for keys on/off. Docs say that successive writes
- // to KON/KOF must be separated by at least 2 Ts periods or risk
- // being neglected. Therefore DSP only looks at these during an
- // update, and not at the time of the write. Only need to do this
- // once however, since the regs haven't changed over the whole
- // period we need to catch up with.
-
- g.wave_ended &= ~g.key_ons; // Keying on a voice resets that bit in ENDX.
-
- if ( g.noise_enables )
- {
- noise_count -= env_rates [g.flags & 0x1F];
- if ( noise_count <= 0 )
- {
- noise_count = env_rate_init;
-
- noise_amp = BOOST::int16_t (noise * 2);
-
- // TODO: switch to Galios style
- int feedback = (noise << 13) ^ (noise << 14);
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- }
-
- // What is the expected behavior when pitch modulation is enabled on
- // voice 0? Jurassic Park 2 does this. Assume 0 for now.
- blargg_long prev_outx = 0;
-
- int echol = 0;
- int echor = 0;
- int left = 0;
- int right = 0;
- for ( int vidx = 0; vidx < voice_count; vidx++ )
- {
- const int vbit = 1 << vidx;
- raw_voice_t& raw_voice = voice [vidx];
- voice_t& voice = voice_state [vidx];
-
- if ( voice.on_cnt && !--voice.on_cnt )
- {
- // key on
- keys |= vbit;
- voice.addr = GET_LE16( sd [raw_voice.waveform].start );
- voice.block_remain = 1;
- voice.envx = 0;
- voice.block_header = 0;
- voice.fraction = 0x3FFF; // decode three samples immediately
- voice.interp0 = 0; // BRR decoder filter uses previous two samples
- voice.interp1 = 0;
-
- // NOTE: Real SNES does *not* appear to initialize the
- // envelope counter to anything in particular. The first
- // cycle always seems to come at a random time sooner than
- // expected; as yet, I have been unable to find any
- // pattern. I doubt it will matter though, so we'll go
- // ahead and do the full time for now.
- voice.envcnt = env_rate_init;
- voice.envstate = state_attack;
- }
-
- if ( g.key_ons & vbit & ~g.key_offs )
- {
- // voice doesn't come on if key off is set
- g.key_ons &= ~vbit;
- voice.on_cnt = 8;
- }
-
- if ( keys & g.key_offs & vbit )
- {
- // key off
- voice.envstate = state_release;
- voice.on_cnt = 0;
- }
-
- int envx;
- if ( !(keys & vbit) || (envx = clock_envelope( vidx )) < 0 )
- {
- raw_voice.envx = 0;
- raw_voice.outx = 0;
- prev_outx = 0;
- continue;
- }
-
- // Decode samples when fraction >= 1.0 (0x1000)
- for ( int n = voice.fraction >> 12; --n >= 0; )
- {
- if ( !--voice.block_remain )
- {
- if ( voice.block_header & 1 )
- {
- g.wave_ended |= vbit;
-
- if ( voice.block_header & 2 )
- {
- // verified (played endless looping sample and ENDX was set)
- voice.addr = GET_LE16( sd [raw_voice.waveform].loop );
- }
- else
- {
- // first block was end block; don't play anything (verified)
- goto sample_ended; // to do: find alternative to goto
- }
- }
-
- voice.block_header = ram [voice.addr++];
- voice.block_remain = 16; // nybbles
- }
-
- // if next block has end flag set, *this* block ends *early* (verified)
- if ( voice.block_remain == 9 && (ram [voice.addr + 5] & 3) == 1 &&
- (voice.block_header & 3) != 3 )
- {
- sample_ended:
- g.wave_ended |= vbit;
- keys &= ~vbit;
- raw_voice.envx = 0;
- voice.envx = 0;
- // add silence samples to interpolation buffer
- do
- {
- voice.interp3 = voice.interp2;
- voice.interp2 = voice.interp1;
- voice.interp1 = voice.interp0;
- voice.interp0 = 0;
- }
- while ( --n >= 0 );
- break;
- }
-
- int delta = ram [voice.addr];
- if ( voice.block_remain & 1 )
- {
- delta <<= 4; // use lower nybble
- voice.addr++;
- }
-
- // Use sign-extended upper nybble
- delta = int8_t (delta) >> 4;
-
- // For invalid ranges (D,E,F): if the nybble is negative,
- // the result is F000. If positive, 0000. Nothing else
- // like previous range, etc seems to have any effect. If
- // range is valid, do the shift normally. Note these are
- // both shifted right once to do the filters properly, but
- // the output will be shifted back again at the end.
- int shift = voice.block_header >> 4;
- delta = (delta << shift) >> 1;
- if ( shift > 0x0C )
- delta = (delta >> 14) & ~0x7FF;
-
- // One, two and three point IIR filters
- int smp1 = voice.interp0;
- int smp2 = voice.interp1;
- if ( voice.block_header & 8 )
- {
- delta += smp1;
- delta -= smp2 >> 1;
- if ( !(voice.block_header & 4) )
- {
- delta += (-smp1 - (smp1 >> 1)) >> 5;
- delta += smp2 >> 5;
- }
- else
- {
- delta += (-smp1 * 13) >> 7;
- delta += (smp2 + (smp2 >> 1)) >> 4;
- }
- }
- else if ( voice.block_header & 4 )
- {
- delta += smp1 >> 1;
- delta += (-smp1) >> 5;
- }
-
- voice.interp3 = voice.interp2;
- voice.interp2 = smp2;
- voice.interp1 = smp1;
- voice.interp0 = BOOST::int16_t (clamp_16( delta ) * 2); // sign-extend
- }
-
- // rate (with possible modulation)
- int rate = GET_LE16( raw_voice.rate ) & 0x3FFF;
- if ( g.pitch_mods & vbit )
- rate = (rate * (prev_outx + 32768)) >> 15;
-
- // Gaussian interpolation using most recent 4 samples
- int index = voice.fraction >> 2 & 0x3FC;
- voice.fraction = (voice.fraction & 0x0FFF) + rate;
- const BOOST::int16_t* table = (BOOST::int16_t const*) ((char const*) gauss + index);
- const BOOST::int16_t* table2 = (BOOST::int16_t const*) ((char const*) gauss + (255*4 - index));
- int s = ((table [0] * voice.interp3) >> 12) +
- ((table [1] * voice.interp2) >> 12) +
- ((table2 [1] * voice.interp1) >> 12);
- s = (BOOST::int16_t) (s * 2);
- s += (table2 [0] * voice.interp0) >> 11 & ~1;
- int output = clamp_16( s );
- if ( g.noise_enables & vbit )
- output = noise_amp;
-
- // scale output and set outx values
- output = (output * envx) >> 11 & ~1;
-
- // output and apply muting (by setting voice.enabled to 31)
- // if voice is externally disabled (not a SNES feature)
- int l = (voice.volume [0] * output) >> voice.enabled;
- int r = (voice.volume [1] * output) >> voice.enabled;
- prev_outx = output;
- raw_voice.outx = int8_t (output >> 8);
- if ( g.echo_ons & vbit )
- {
- echol += l;
- echor += r;
- }
- left += l;
- right += r;
- }
- // end of channel loop
-
- // main volume control
- left = (left * left_volume ) >> (7 + emu_gain_bits);
- right = (right * right_volume) >> (7 + emu_gain_bits);
-
- // Echo FIR filter
-
- // read feedback from echo buffer
- int echo_ptr = this->echo_ptr;
- uint8_t* echo_buf = &ram [(g.echo_page * 0x100 + echo_ptr) & 0xFFFF];
- echo_ptr += 4;
- if ( echo_ptr >= (g.echo_delay & 15) * 0x800 )
- echo_ptr = 0;
- int fb_left = (BOOST::int16_t) GET_LE16( echo_buf ); // sign-extend
- int fb_right = (BOOST::int16_t) GET_LE16( echo_buf + 2 ); // sign-extend
- this->echo_ptr = echo_ptr;
-
- // put samples in history ring buffer
- const int fir_offset = this->fir_offset;
- short (*fir_pos) [2] = &fir_buf [fir_offset];
- this->fir_offset = (fir_offset + 7) & 7; // move backwards one step
- fir_pos [0] [0] = (short) fb_left;
- fir_pos [0] [1] = (short) fb_right;
- fir_pos [8] [0] = (short) fb_left; // duplicate at +8 eliminates wrap checking below
- fir_pos [8] [1] = (short) fb_right;
-
- // FIR
- fb_left = fb_left * fir_coeff [7] +
- fir_pos [1] [0] * fir_coeff [6] +
- fir_pos [2] [0] * fir_coeff [5] +
- fir_pos [3] [0] * fir_coeff [4] +
- fir_pos [4] [0] * fir_coeff [3] +
- fir_pos [5] [0] * fir_coeff [2] +
- fir_pos [6] [0] * fir_coeff [1] +
- fir_pos [7] [0] * fir_coeff [0];
-
- fb_right = fb_right * fir_coeff [7] +
- fir_pos [1] [1] * fir_coeff [6] +
- fir_pos [2] [1] * fir_coeff [5] +
- fir_pos [3] [1] * fir_coeff [4] +
- fir_pos [4] [1] * fir_coeff [3] +
- fir_pos [5] [1] * fir_coeff [2] +
- fir_pos [6] [1] * fir_coeff [1] +
- fir_pos [7] [1] * fir_coeff [0];
-
- left += (fb_left * g.left_echo_volume ) >> 14;
- right += (fb_right * g.right_echo_volume) >> 14;
-
- // echo buffer feedback
- if ( !(g.flags & 0x20) )
- {
- echol += (fb_left * g.echo_feedback) >> 14;
- echor += (fb_right * g.echo_feedback) >> 14;
- SET_LE16( echo_buf , clamp_16( echol ) );
- SET_LE16( echo_buf + 2, clamp_16( echor ) );
- }
-
- if ( out_buf )
- {
- // write final samples
-
- left = clamp_16( left );
- right = clamp_16( right );
-
- int mute = g.flags & 0x40;
-
- out_buf [0] = (short) left;
- out_buf [1] = (short) right;
- out_buf += 2;
-
- // muting
- if ( mute )
- {
- out_buf [-2] = 0;
- out_buf [-1] = 0;
- }
- }
- }
-}
-
-// Base normal_gauss table is almost exactly (with an error of 0 or -1 for each entry):
-// int normal_gauss [512];
-// normal_gauss [i] = exp((i-511)*(i-511)*-9.975e-6)*pow(sin(0.00307096*i),1.7358)*1304.45
-
-// Interleved gauss table (to improve cache coherency).
-// gauss [i * 2 + j] = normal_gauss [(1 - j) * 256 + i]
-const BOOST::int16_t Spc_Dsp::gauss [512] =
-{
- 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
- 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
- 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
- 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
- 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
- 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
- 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
- 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
- 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
- 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
- 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
- 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
- 102,1102, 100,1098, 99,1094, 97,1090, 95,1086, 94,1082, 92,1078, 90,1074,
- 89,1070, 87,1066, 86,1061, 84,1057, 83,1053, 81,1049, 80,1045, 78,1040,
- 77,1036, 76,1032, 74,1027, 73,1023, 71,1019, 70,1014, 69,1010, 67,1005,
- 66,1001, 65, 997, 64, 992, 62, 988, 61, 983, 60, 978, 59, 974, 58, 969,
- 56, 965, 55, 960, 54, 955, 53, 951, 52, 946, 51, 941, 50, 937, 49, 932,
- 48, 927, 47, 923, 46, 918, 45, 913, 44, 908, 43, 904, 42, 899, 41, 894,
- 40, 889, 39, 884, 38, 880, 37, 875, 36, 870, 36, 865, 35, 860, 34, 855,
- 33, 851, 32, 846, 32, 841, 31, 836, 30, 831, 29, 826, 29, 821, 28, 816,
- 27, 811, 27, 806, 26, 802, 25, 797, 24, 792, 24, 787, 23, 782, 23, 777,
- 22, 772, 21, 767, 21, 762, 20, 757, 20, 752, 19, 747, 19, 742, 18, 737,
- 17, 732, 17, 728, 16, 723, 16, 718, 15, 713, 15, 708, 15, 703, 14, 698,
- 14, 693, 13, 688, 13, 683, 12, 678, 12, 674, 11, 669, 11, 664, 11, 659,
- 10, 654, 10, 649, 10, 644, 9, 640, 9, 635, 9, 630, 8, 625, 8, 620,
- 8, 615, 7, 611, 7, 606, 7, 601, 6, 596, 6, 592, 6, 587, 6, 582,
- 5, 577, 5, 573, 5, 568, 5, 563, 4, 559, 4, 554, 4, 550, 4, 545,
- 4, 540, 3, 536, 3, 531, 3, 527, 3, 522, 3, 517, 2, 513, 2, 508,
- 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
- 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
- 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
- 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
-};
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h
deleted file mode 100644
index 36492275..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Dsp.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Super Nintendo (SNES) SPC DSP emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SPC_DSP_H
-#define SPC_DSP_H
-
-#include "blargg_common.h"
-
-class Spc_Dsp {
- typedef BOOST::int8_t int8_t;
- typedef BOOST::uint8_t uint8_t;
-public:
-
- // Keeps pointer to 64K ram
- Spc_Dsp( uint8_t* ram );
-
- // Mute voice n if bit n (1 << n) of mask is clear.
- enum { voice_count = 8 };
- void mute_voices( int mask );
-
- // Clear state and silence everything.
- void reset();
-
- // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped to
- // the 16-bit sample range.
- void set_gain( double );
-
- // If true, prevent channels and global volumes from being phase-negated
- void disable_surround( bool disable );
-
- // Read/write register 'n', where n ranges from 0 to register_count - 1.
- enum { register_count = 128 };
- int read ( int n );
- void write( int n, int );
-
- // Run DSP for 'count' samples. Write resulting samples to 'buf' if not NULL.
- void run( long count, short* buf = NULL );
-
-
-// End of public interface
-private:
-
- struct raw_voice_t {
- int8_t left_vol;
- int8_t right_vol;
- uint8_t rate [2];
- uint8_t waveform;
- uint8_t adsr [2]; // envelope rates for attack, decay, and sustain
- uint8_t gain; // envelope gain (if not using ADSR)
- int8_t envx; // current envelope level
- int8_t outx; // current sample
- int8_t unused [6];
- };
-
- struct globals_t {
- int8_t unused1 [12];
- int8_t left_volume; // 0C Main Volume Left (-.7)
- int8_t echo_feedback; // 0D Echo Feedback (-.7)
- int8_t unused2 [14];
- int8_t right_volume; // 1C Main Volume Right (-.7)
- int8_t unused3 [15];
- int8_t left_echo_volume; // 2C Echo Volume Left (-.7)
- uint8_t pitch_mods; // 2D Pitch Modulation on/off for each voice
- int8_t unused4 [14];
- int8_t right_echo_volume; // 3C Echo Volume Right (-.7)
- uint8_t noise_enables; // 3D Noise output on/off for each voice
- int8_t unused5 [14];
- uint8_t key_ons; // 4C Key On for each voice
- uint8_t echo_ons; // 4D Echo on/off for each voice
- int8_t unused6 [14];
- uint8_t key_offs; // 5C key off for each voice (instantiates release mode)
- uint8_t wave_page; // 5D source directory (wave table offsets)
- int8_t unused7 [14];
- uint8_t flags; // 6C flags and noise freq
- uint8_t echo_page; // 6D
- int8_t unused8 [14];
- uint8_t wave_ended; // 7C
- uint8_t echo_delay; // 7D ms >> 4
- char unused9 [2];
- };
-
- union {
- raw_voice_t voice [voice_count];
- uint8_t reg [register_count];
- globals_t g;
- };
-
- uint8_t* const ram;
-
- // Cache of echo FIR values for faster access
- short fir_coeff [voice_count];
-
- // fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code
- short fir_buf [16] [2];
- int fir_offset; // (0 to 7)
-
- enum { emu_gain_bits = 8 };
- int emu_gain;
-
- int keyed_on; // 8-bits for 8 voices
- int keys;
-
- int echo_ptr;
- int noise_amp;
- int noise;
- int noise_count;
-
- int surround_threshold;
-
- static BOOST::int16_t const gauss [];
-
- enum state_t {
- state_attack,
- state_decay,
- state_sustain,
- state_release
- };
-
- struct voice_t {
- short volume [2];
- short fraction;// 12-bit fractional position
- short interp3; // most recent four decoded samples
- short interp2;
- short interp1;
- short interp0;
- short block_remain; // number of nybbles remaining in current block
- unsigned short addr;
- short block_header; // header byte from current block
- short envcnt;
- short envx;
- short on_cnt;
- short enabled; // 7 if enabled, 31 if disabled
- short envstate;
- short unused; // pad to power of 2
- };
-
- voice_t voice_state [voice_count];
-
- int clock_envelope( int );
-};
-
-inline void Spc_Dsp::disable_surround( bool disable ) { surround_threshold = disable ? 0 : -0x7FFF; }
-
-inline void Spc_Dsp::set_gain( double v ) { emu_gain = (int) (v * (1 << emu_gain_bits)); }
-
-inline int Spc_Dsp::read( int i )
-{
- assert( (unsigned) i < register_count );
- return reg [i];
-}
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.cpp
deleted file mode 100644
index 22be9e2a..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Spc_Emu.h"
-
-#include "blargg_endian.h"
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Spc_Emu::Spc_Emu()
-{
- set_type( gme_spc_type );
-
- static const char* const names [Snes_Spc::voice_count] = {
- "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
- };
- set_voice_names( names );
-
- set_gain( 1.4 );
-}
-
-Spc_Emu::~Spc_Emu() { }
-
-// Track info
-
-long const trailer_offset = 0x10200;
-
-byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }
-
-long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }
-
-static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
-{
- // header
- byte const* end = begin + size;
- if ( size < 8 || memcmp( begin, "xid6", 4 ) )
- {
- check( false );
- return;
- }
- long info_size = get_le32( begin + 4 );
- byte const* in = begin + 8;
- if ( end - in > info_size )
- {
- dprintf( "Extra data after SPC xid6 info\n" );
- end = in + info_size;
- }
-
- int year = 0;
- char copyright [256 + 5];
- int copyright_len = 0;
- int const year_len = 5;
-
- while ( end - in >= 4 )
- {
- // header
- int id = in [0];
- int data = in [3] * 0x100 + in [2];
- int type = in [1];
- int len = type ? data : 0;
- in += 4;
- if ( len > end - in )
- {
- check( false );
- break; // block goes past end of data
- }
-
- // handle specific block types
- char* field = 0;
- switch ( id )
- {
- case 0x01: field = out->song; break;
- case 0x02: field = out->game; break;
- case 0x03: field = out->author; break;
- case 0x04: field = out->dumper; break;
- case 0x07: field = out->comment; break;
- case 0x14: year = data; break;
-
- //case 0x30: // intro length
- // Many SPCs have intro length set wrong for looped tracks, making it useless
- /*
- case 0x30:
- check( len == 4 );
- if ( len >= 4 )
- {
- out->intro_length = get_le32( in ) / 64;
- if ( out->length > 0 )
- {
- long loop = out->length - out->intro_length;
- if ( loop >= 2000 )
- out->loop_length = loop;
- }
- }
- break;
- */
-
- case 0x13:
- copyright_len = min( len, (int) sizeof copyright - year_len );
- memcpy( &copyright [year_len], in, copyright_len );
- break;
-
- default:
- if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
- (id > 0x14 && id < 0x30) || id > 0x36 )
- dprintf( "Unknown SPC xid6 block: %X\n", (int) id );
- break;
- }
- if ( field )
- {
- check( type == 1 );
- Gme_File::copy_field_( field, (char const*) in, len );
- }
-
- // skip to next block
- in += len;
-
- // blocks are supposed to be 4-byte aligned with zero-padding...
- byte const* unaligned = in;
- while ( (in - begin) & 3 && in < end )
- {
- if ( *in++ != 0 )
- {
- // ...but some files have no padding
- in = unaligned;
- dprintf( "SPC info tag wasn't properly padded to align\n" );
- break;
- }
- }
- }
-
- char* p = &copyright [year_len];
- if ( year )
- {
- *--p = ' ';
- for ( int n = 4; n--; )
- {
- *--p = char (year % 10 + '0');
- year /= 10;
- }
- copyright_len += year_len;
- }
- if ( copyright_len )
- Gme_File::copy_field_( out->copyright, p, copyright_len );
-
- check( in == end );
-}
-
-static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
- track_info_t* out )
-{
- // decode length (can be in text or binary format, sometimes ambiguous ugh)
- long len_secs = 0;
- for ( int i = 0; i < 3; i++ )
- {
- unsigned n = h.len_secs [i] - '0';
- if ( n > 9 )
- {
- // ignore single-digit text lengths
- // (except if author field is present and begins at offset 1, ugh)
- if ( i == 1 && (h.author [0] || !h.author [1]) )
- len_secs = 0;
- break;
- }
- len_secs *= 10;
- len_secs += n;
- }
- if ( !len_secs || len_secs > 0x1FFF )
- len_secs = get_le16( h.len_secs );
- if ( len_secs < 0x1FFF )
- out->length = len_secs * 1000;
-
- int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
- Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
-
- GME_COPY_FIELD( h, out, song );
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, dumper );
- GME_COPY_FIELD( h, out, comment );
-
- if ( xid6_size )
- get_spc_xid6( xid6, xid6_size, out );
-}
-
-blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
-{
- get_spc_info( header(), trailer(), trailer_size(), out );
- return 0;
-}
-
-static blargg_err_t check_spc_header( void const* header )
-{
- if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Spc_File : Gme_Info_
-{
- Spc_Emu::header_t header;
- blargg_vector<byte> xid6;
-
- Spc_File() { set_type( gme_spc_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- long file_size = in.remain();
- if ( file_size < Snes_Spc::spc_file_size )
- return gme_wrong_file_type;
- RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
- RETURN_ERR( check_spc_header( header.tag ) );
- long const xid6_offset = 0x10200;
- long xid6_size = file_size - xid6_offset;
- if ( xid6_size > 0 )
- {
- RETURN_ERR( xid6.resize( xid6_size ) );
- RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
- RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
- }
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- get_spc_info( header, xid6.begin(), xid6.size(), out );
- return 0;
- }
-};
-
-static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
-static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
-
-gme_type_t_ const gme_spc_type [1] = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
-
-// Setup
-
-blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
-{
- apu.set_gain( gain() );
- if ( sample_rate != native_sample_rate )
- {
- RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
- resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
- }
- return 0;
-}
-
-void Spc_Emu::mute_voices_( int m )
-{
- Music_Emu::mute_voices_( m );
- apu.mute_voices( m );
-}
-
-blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,unused2 [46]) == header_size );
- file_data = in;
- file_size = size;
- set_voice_count( Snes_Spc::voice_count );
- if ( size < Snes_Spc::spc_file_size )
- return gme_wrong_file_type;
- return check_spc_header( in );
-}
-
-// Emulation
-
-void Spc_Emu::set_tempo_( double t ) { apu.set_tempo( t ); }
-
-blargg_err_t Spc_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- resampler.clear();
- RETURN_ERR( apu.load_spc( file_data, file_size ) );
- apu.clear_echo();
- return 0;
-}
-
-blargg_err_t Spc_Emu::skip_( long count )
-{
- if ( sample_rate() != native_sample_rate )
- {
- count = long (count * resampler.ratio()) & ~1;
- count -= resampler.skip_input( count );
- }
-
- // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
-
- if ( count > 0 )
- RETURN_ERR( apu.skip( count ) );
-
- // eliminate pop due to resampler
- const int resampler_latency = 64;
- sample_t buf [resampler_latency];
- return play_( resampler_latency, buf );
-}
-
-blargg_err_t Spc_Emu::play_( long count, sample_t* out )
-{
- if ( sample_rate() == native_sample_rate )
- return apu.play( count, out );
-
- long remain = count;
- while ( remain > 0 )
- {
- remain -= resampler.read( &out [count - remain], remain );
- if ( remain > 0 )
- {
- long n = resampler.max_write();
- RETURN_ERR( apu.play( n, resampler.buffer() ) );
- resampler.write( n );
- }
- }
- check( remain == 0 );
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.h
deleted file mode 100644
index 44b54c30..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Spc_Emu.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Super Nintendo SPC music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef SPC_EMU_H
-#define SPC_EMU_H
-
-#include "Fir_Resampler.h"
-#include "Music_Emu.h"
-#include "Snes_Spc.h"
-
-class Spc_Emu : public Music_Emu {
-public:
- // The Super Nintendo hardware samples at 32kHz. Other sample rates are
- // handled by resampling the 32kHz output; emulation accuracy is not affected.
- enum { native_sample_rate = 32000 };
-
- // SPC file header
- enum { header_size = 0x100 };
- struct header_t
- {
- char tag [35];
- byte format;
- byte version;
- byte pc [2];
- byte a, x, y, psw, sp;
- byte unused [2];
- char song [32];
- char game [32];
- char dumper [16];
- char comment [32];
- byte date [11];
- byte len_secs [3];
- byte fade_msec [4];
- char author [32]; // sometimes first char should be skipped (see official SPC spec)
- byte mute_mask;
- byte emulator;
- byte unused2 [46];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return *(header_t const*) file_data; }
-
- // Prevents channels and global volumes from being phase-negated
- void disable_surround( bool disable = true );
-
- static gme_type_t static_type() { return gme_spc_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- byte const* trailer() const; // use track_info()
- long trailer_size() const;
-
-public:
- Spc_Emu();
- ~Spc_Emu();
-protected:
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t set_sample_rate_( long );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long, sample_t* );
- blargg_err_t skip_( long );
- void mute_voices_( int );
- void set_tempo_( double );
-private:
- byte const* file_data;
- long file_size;
- Fir_Resampler<24> resampler;
- Snes_Spc apu;
-};
-
-inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.cpp
deleted file mode 100644
index 0fef6bd9..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
-double const rolloff = 0.990;
-double const oversample_factor = 1.5;
-
-Vgm_Emu::Vgm_Emu()
-{
- disable_oversampling_ = false;
- psg_rate = 0;
- set_type( gme_vgm_type );
-
- static int const types [8] = {
- wave_type | 1, wave_type | 0, wave_type | 2, noise_type | 0
- };
- set_voice_types( types );
-
- set_silence_lookahead( 1 ); // tracks should already be trimmed
-
- static equalizer_t const eq = { -14.0, 80 };
- set_equalizer( eq );
-}
-
-Vgm_Emu::~Vgm_Emu() { }
-
-// Track info
-
-static byte const* skip_gd3_str( byte const* in, byte const* end )
-{
- while ( end - in >= 2 )
- {
- in += 2;
- if ( !(in [-2] | in [-1]) )
- break;
- }
- return in;
-}
-
-static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
-{
- byte const* mid = skip_gd3_str( in, end );
- int len = (mid - in) / 2 - 1;
- if ( len > 0 )
- {
- len = min( len, (int) Gme_File::max_field_ );
- field [len] = 0;
- for ( int i = 0; i < len; i++ )
- field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
- }
- return mid;
-}
-
-static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
-{
- return skip_gd3_str( get_gd3_str( in, end, field ), end );
-}
-
-static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
-{
- in = get_gd3_pair( in, end, out->song );
- in = get_gd3_pair( in, end, out->game );
- in = get_gd3_pair( in, end, out->system );
- in = get_gd3_pair( in, end, out->author );
- in = get_gd3_str ( in, end, out->copyright );
- in = get_gd3_pair( in, end, out->dumper );
- in = get_gd3_str ( in, end, out->comment );
-}
-
-int const gd3_header_size = 12;
-
-static long check_gd3_header( byte const* h, long remain )
-{
- if ( remain < gd3_header_size ) return 0;
- if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
- if ( get_le32( h + 4 ) >= 0x200 ) return 0;
-
- long gd3_size = get_le32( h + 8 );
- if ( gd3_size > remain - gd3_header_size ) return 0;
-
- return gd3_size;
-}
-
-byte const* Vgm_Emu::gd3_data( int* size ) const
-{
- if ( size )
- *size = 0;
-
- long gd3_offset = get_le32( header().gd3_offset ) - 0x2C;
- if ( gd3_offset < 0 )
- return 0;
-
- byte const* gd3 = data + header_size + gd3_offset;
- long gd3_size = check_gd3_header( gd3, data_end - gd3 );
- if ( !gd3_size )
- return 0;
-
- if ( size )
- *size = gd3_size + gd3_header_size;
-
- return gd3;
-}
-
-static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
-{
- long length = get_le32( h.track_duration ) * 10 / 441;
- if ( length > 0 )
- {
- long loop = get_le32( h.loop_duration );
- if ( loop > 0 && get_le32( h.loop_offset ) )
- {
- out->loop_length = loop * 10 / 441;
- out->intro_length = length - out->loop_length;
- }
- else
- {
- out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
- out->intro_length = length; // make it clear that track is no longer than length
- out->loop_length = 0;
- }
- }
-}
-
-blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
-{
- get_vgm_length( header(), out );
-
- int size;
- byte const* gd3 = gd3_data( &size );
- if ( gd3 )
- parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
-
- return 0;
-}
-
-static blargg_err_t check_vgm_header( Vgm_Emu::header_t const& h )
-{
- if ( memcmp( h.tag, "Vgm ", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Vgm_File : Gme_Info_
-{
- Vgm_Emu::header_t h;
- blargg_vector<byte> gd3;
-
- Vgm_File() { set_type( gme_vgm_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- long file_size = in.remain();
- if ( file_size <= Vgm_Emu::header_size )
- return gme_wrong_file_type;
-
- RETURN_ERR( in.read( &h, Vgm_Emu::header_size ) );
- RETURN_ERR( check_vgm_header( h ) );
-
- long gd3_offset = get_le32( h.gd3_offset ) - 0x2C;
- long remain = file_size - Vgm_Emu::header_size - gd3_offset;
- byte gd3_h [gd3_header_size];
- if ( gd3_offset > 0 && remain >= gd3_header_size )
- {
- RETURN_ERR( in.skip( gd3_offset ) );
- RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
- long gd3_size = check_gd3_header( gd3_h, remain );
- if ( gd3_size )
- {
- RETURN_ERR( gd3.resize( gd3_size ) );
- RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
- }
- }
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- get_vgm_length( h, out );
- if ( gd3.size() )
- parse_gd3( gd3.begin(), gd3.end(), out );
- return 0;
- }
-};
-
-static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
-static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
-
-gme_type_t_ const gme_vgm_type [1] = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 };
-gme_type_t_ const gme_vgz_type [1] = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 };
-
-// Setup
-
-void Vgm_Emu::set_tempo_( double t )
-{
- if ( psg_rate )
- {
- vgm_rate = (long) (44100 * t + 0.5);
- blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
- //dprintf( "blip_time_factor: %ld\n", blip_time_factor );
- //dprintf( "vgm_rate: %ld\n", vgm_rate );
- // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
- //blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
- //vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
-
- fm_time_factor = 2 + (long) floor( fm_rate * (1L << fm_time_bits) / vgm_rate + 0.5 );
- }
-}
-
-blargg_err_t Vgm_Emu::set_sample_rate_( long sample_rate )
-{
- RETURN_ERR( blip_buf.set_sample_rate( sample_rate, 1000 / 30 ) );
- return Classic_Emu::set_sample_rate_( sample_rate );
-}
-
-void Vgm_Emu::update_eq( blip_eq_t const& eq )
-{
- psg.treble_eq( eq );
- dac_synth.treble_eq( eq );
-}
-
-void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- if ( i < psg.osc_count )
- psg.osc_output( i, c, l, r );
-}
-
-void Vgm_Emu::mute_voices_( int mask )
-{
- Classic_Emu::mute_voices_( mask );
- dac_synth.output( &blip_buf );
- if ( uses_fm )
- {
- psg.output( (mask & 0x80) ? 0 : &blip_buf );
- if ( ym2612.enabled() )
- {
- dac_synth.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
- ym2612.mute_voices( mask );
- }
-
- if ( ym2413.enabled() )
- {
- int m = mask & 0x3F;
- if ( mask & 0x20 )
- m |= 0x01E0; // channels 5-8
- if ( mask & 0x40 )
- m |= 0x3E00;
- ym2413.mute_voices( m );
- }
- }
-}
-
-blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
-{
- assert( offsetof (header_t,unused2 [8]) == header_size );
-
- if ( new_size <= header_size )
- return gme_wrong_file_type;
-
- header_t const& h = *(header_t const*) new_data;
-
- RETURN_ERR( check_vgm_header( h ) );
-
- check( get_le32( h.version ) <= 0x150 );
-
- // psg rate
- psg_rate = get_le32( h.psg_rate );
- if ( !psg_rate )
- psg_rate = 3579545;
- blip_buf.clock_rate( psg_rate );
-
- data = new_data;
- data_end = new_data + new_size;
-
- // get loop
- loop_begin = data_end;
- if ( get_le32( h.loop_offset ) )
- loop_begin = &data [get_le32( h.loop_offset ) + offsetof (header_t,loop_offset)];
-
- set_voice_count( psg.osc_count );
-
- RETURN_ERR( setup_fm() );
-
- static const char* const fm_names [] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
- };
- static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
- set_voice_names( uses_fm ? fm_names : psg_names );
-
- // do after FM in case output buffer is changed
- return Classic_Emu::setup_buffer( psg_rate );
-}
-
-blargg_err_t Vgm_Emu::setup_fm()
-{
- long ym2612_rate = get_le32( header().ym2612_rate );
- long ym2413_rate = get_le32( header().ym2413_rate );
- if ( ym2413_rate && get_le32( header().version ) < 0x110 )
- update_fm_rates( &ym2413_rate, &ym2612_rate );
-
- uses_fm = false;
-
- fm_rate = blip_buf.sample_rate() * oversample_factor;
-
- if ( ym2612_rate )
- {
- uses_fm = true;
- if ( disable_oversampling_ )
- fm_rate = ym2612_rate / 144.0;
- Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
- RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) );
- ym2612.enable( true );
- set_voice_count( 8 );
- }
-
- if ( !uses_fm && ym2413_rate )
- {
- uses_fm = true;
- if ( disable_oversampling_ )
- fm_rate = ym2413_rate / 72.0;
- Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
- int result = ym2413.set_rate( fm_rate, ym2413_rate );
- if ( result == 2 )
- return "YM2413 FM sound isn't supported";
- CHECK_ALLOC( !result );
- ym2413.enable( true );
- set_voice_count( 8 );
- }
-
- if ( uses_fm )
- {
- RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) );
- psg.volume( 0.135 * fm_gain * gain() );
- }
- else
- {
- ym2612.enable( false );
- ym2413.enable( false );
- psg.volume( gain() );
- }
-
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Vgm_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
- psg.reset( get_le16( header().noise_feedback ), header().noise_width );
-
- dac_disabled = -1;
- pos = data + header_size;
- pcm_data = pos;
- pcm_pos = pos;
- dac_amp = -1;
- vgm_time = 0;
- if ( get_le32( header().version ) >= 0x150 )
- {
- long data_offset = get_le32( header().data_offset );
- check( data_offset );
- if ( data_offset )
- pos += data_offset + offsetof (header_t,data_offset) - 0x40;
- }
-
- if ( uses_fm )
- {
- if ( ym2413.enabled() )
- ym2413.reset();
-
- if ( ym2612.enabled() )
- ym2612.reset();
-
- fm_time_offset = 0;
- blip_buf.clear();
- Dual_Resampler::clear();
- }
- return 0;
-}
-
-blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
-{
- time_io = run_commands( msec * vgm_rate / 1000 );
- psg.end_frame( time_io );
- return 0;
-}
-
-blargg_err_t Vgm_Emu::play_( long count, sample_t* out )
-{
- if ( !uses_fm )
- return Classic_Emu::play_( count, out );
-
- Dual_Resampler::dual_play( count, out, blip_buf );
- return 0;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.h
deleted file mode 100644
index bcb784d5..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
-
-// Game_Music_Emu 0.5.2
-#ifndef VGM_EMU_H
-#define VGM_EMU_H
-
-#include "Vgm_Emu_Impl.h"
-
-// Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips.
-// Supports custom sound buffer and frequency equalization when VGM uses just the PSG.
-// FM sound chips can be run at their proper rates, or slightly higher to reduce
-// aliasing on high notes. Currently YM2413 support requires that you supply a
-// YM2413 sound chip emulator. I can provide one I've modified to work with the library.
-class Vgm_Emu : public Vgm_Emu_Impl {
-public:
- // True if custom buffer and custom equalization are supported
- // TODO: move into Music_Emu and rename to something like supports_custom_buffer()
- bool is_classic_emu() const { return !uses_fm; }
-
- // Disable running FM chips at higher than normal rate. Will result in slightly
- // more aliasing of high notes.
- void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
-
- // VGM header format
- enum { header_size = 0x40 };
- struct header_t
- {
- char tag [4];
- byte data_size [4];
- byte version [4];
- byte psg_rate [4];
- byte ym2413_rate [4];
- byte gd3_offset [4];
- byte track_duration [4];
- byte loop_offset [4];
- byte loop_duration [4];
- byte frame_rate [4];
- byte noise_feedback [2];
- byte noise_width;
- byte unused1;
- byte ym2612_rate [4];
- byte ym2151_rate [4];
- byte data_offset [4];
- byte unused2 [8];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return *(header_t const*) data; }
-
- static gme_type_t static_type() { return gme_vgm_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- byte const* gd3_data( int* size_out = 0 ) const; // use track_info()
-
-public:
- Vgm_Emu();
- ~Vgm_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t set_sample_rate_( long sample_rate );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long count, sample_t* );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void mute_voices_( int mask );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-private:
- // removed; use disable_oversampling() and set_tempo() instead
- Vgm_Emu( bool oversample, double tempo = 1.0 );
- double fm_rate;
- long psg_rate;
- long vgm_rate;
- bool disable_oversampling_;
- bool uses_fm;
- blargg_err_t setup_fm();
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.cpp
deleted file mode 100644
index a2d7c93e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include <math.h>
-#include <string.h>
-#include "blargg_endian.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-enum {
- cmd_gg_stereo = 0x4F,
- cmd_psg = 0x50,
- cmd_ym2413 = 0x51,
- cmd_ym2612_port0 = 0x52,
- cmd_ym2612_port1 = 0x53,
- cmd_ym2151 = 0x54,
- cmd_delay = 0x61,
- cmd_delay_735 = 0x62,
- cmd_delay_882 = 0x63,
- cmd_byte_delay = 0x64,
- cmd_end = 0x66,
- cmd_data_block = 0x67,
- cmd_short_delay = 0x70,
- cmd_pcm_delay = 0x80,
- cmd_pcm_seek = 0xE0,
-
- pcm_block_type = 0x00,
- ym2612_dac_port = 0x2A
-};
-
-inline int command_len( int command )
-{
- switch ( command >> 4 )
- {
- case 0x03:
- case 0x04:
- return 2;
-
- case 0x05:
- case 0x0A:
- case 0x0B:
- return 3;
-
- case 0x0C:
- case 0x0D:
- return 4;
-
- case 0x0E:
- case 0x0F:
- return 5;
- }
-
- check( false );
- return 1;
-}
-
-template<class Emu>
-inline void Ym_Emu<Emu>::begin_frame( short* p )
-{
- require( enabled() );
- out = p;
- last_time = 0;
-}
-
-template<class Emu>
-inline int Ym_Emu<Emu>::run_until( int time )
-{
- int count = time - last_time;
- if ( count > 0 )
- {
- if ( last_time < 0 )
- return false;
- last_time = time;
- short* p = out;
- out += count * Emu::out_chan_count;
- Emu::run( count, p );
- }
- return true;
-}
-
-inline Vgm_Emu_Impl::fm_time_t Vgm_Emu_Impl::to_fm_time( vgm_time_t t ) const
-{
- return (t * fm_time_factor + fm_time_offset) >> fm_time_bits;
-}
-
-inline blip_time_t Vgm_Emu_Impl::to_blip_time( vgm_time_t t ) const
-{
- return (t * blip_time_factor) >> blip_time_bits;
-}
-
-void Vgm_Emu_Impl::write_pcm( vgm_time_t vgm_time, int amp )
-{
- blip_time_t blip_time = to_blip_time( vgm_time );
- int old = dac_amp;
- int delta = amp - old;
- dac_amp = amp;
- if ( old >= 0 )
- dac_synth.offset_inline( blip_time, delta, &blip_buf );
- else
- dac_amp |= dac_disabled;
-}
-
-blip_time_t Vgm_Emu_Impl::run_commands( vgm_time_t end_time )
-{
- vgm_time_t vgm_time = this->vgm_time;
- byte const* pos = this->pos;
- if ( pos >= data_end )
- {
- set_track_ended();
- if ( pos > data_end )
- set_warning( "Stream lacked end event" );
- }
-
- while ( vgm_time < end_time && pos < data_end )
- {
- // TODO: be sure there are enough bytes left in stream for particular command
- // so we don't read past end
- switch ( *pos++ )
- {
- case cmd_end:
- pos = loop_begin; // if not looped, loop_begin == data_end
- break;
-
- case cmd_delay_735:
- vgm_time += 735;
- break;
-
- case cmd_delay_882:
- vgm_time += 882;
- break;
-
- case cmd_gg_stereo:
- psg.write_ggstereo( to_blip_time( vgm_time ), *pos++ );
- break;
-
- case cmd_psg:
- psg.write_data( to_blip_time( vgm_time ), *pos++ );
- break;
-
- case cmd_delay:
- vgm_time += pos [1] * 0x100L + pos [0];
- pos += 2;
- break;
-
- case cmd_byte_delay:
- vgm_time += *pos++;
- break;
-
- case cmd_ym2413:
- if ( ym2413.run_until( to_fm_time( vgm_time ) ) )
- ym2413.write( pos [0], pos [1] );
- pos += 2;
- break;
-
- case cmd_ym2612_port0:
- if ( pos [0] == ym2612_dac_port )
- {
- write_pcm( vgm_time, pos [1] );
- }
- else if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
- {
- if ( pos [0] == 0x2B )
- {
- dac_disabled = (pos [1] >> 7 & 1) - 1;
- dac_amp |= dac_disabled;
- }
- ym2612.write0( pos [0], pos [1] );
- }
- pos += 2;
- break;
-
- case cmd_ym2612_port1:
- if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
- ym2612.write1( pos [0], pos [1] );
- pos += 2;
- break;
-
- case cmd_data_block: {
- check( *pos == cmd_end );
- int type = pos [1];
- long size = get_le32( pos + 2 );
- pos += 6;
- if ( type == pcm_block_type )
- pcm_data = pos;
- pos += size;
- break;
- }
-
- case cmd_pcm_seek:
- pcm_pos = pcm_data + pos [3] * 0x1000000L + pos [2] * 0x10000L +
- pos [1] * 0x100L + pos [0];
- pos += 4;
- break;
-
- default:
- int cmd = pos [-1];
- switch ( cmd & 0xF0 )
- {
- case cmd_pcm_delay:
- write_pcm( vgm_time, *pcm_pos++ );
- vgm_time += cmd & 0x0F;
- break;
-
- case cmd_short_delay:
- vgm_time += (cmd & 0x0F) + 1;
- break;
-
- case 0x50:
- pos += 2;
- break;
-
- default:
- pos += command_len( cmd ) - 1;
- set_warning( "Unknown stream event" );
- }
- }
- }
- vgm_time -= end_time;
- this->pos = pos;
- this->vgm_time = vgm_time;
-
- return to_blip_time( end_time );
-}
-
-int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
- // to do: timing is working mostly by luck
-
- int min_pairs = sample_count >> 1;
- int vgm_time = ((long) min_pairs << fm_time_bits) / fm_time_factor - 1;
- assert( to_fm_time( vgm_time ) <= min_pairs );
- int pairs = min_pairs;
- while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
- vgm_time++;
- //dprintf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
-
- if ( ym2612.enabled() )
- {
- ym2612.begin_frame( buf );
- memset( buf, 0, pairs * stereo * sizeof *buf );
- }
- else if ( ym2413.enabled() )
- {
- ym2413.begin_frame( buf );
- }
-
- run_commands( vgm_time );
- ym2612.run_until( pairs );
- ym2413.run_until( pairs );
-
- fm_time_offset = (vgm_time * fm_time_factor + fm_time_offset) -
- ((long) pairs << fm_time_bits);
-
- psg.end_frame( blip_time );
-
- return pairs * stereo;
-}
-
-// Update pre-1.10 header FM rates by scanning commands
-void Vgm_Emu_Impl::update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const
-{
- byte const* p = data + 0x40;
- while ( p < data_end )
- {
- switch ( *p )
- {
- case cmd_end:
- return;
-
- case cmd_psg:
- case cmd_byte_delay:
- p += 2;
- break;
-
- case cmd_delay:
- p += 3;
- break;
-
- case cmd_data_block:
- p += 7 + get_le32( p + 3 );
- break;
-
- case cmd_ym2413:
- *ym2612_rate = 0;
- return;
-
- case cmd_ym2612_port0:
- case cmd_ym2612_port1:
- *ym2612_rate = *ym2413_rate;
- *ym2413_rate = 0;
- return;
-
- case cmd_ym2151:
- *ym2413_rate = 0;
- *ym2612_rate = 0;
- return;
-
- default:
- p += command_len( *p );
- }
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.h
deleted file mode 100644
index 4d387d09..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Vgm_Emu_Impl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Low-level parts of Vgm_Emu
-
-// Game_Music_Emu 0.5.2
-#ifndef VGM_EMU_IMPL_H
-#define VGM_EMU_IMPL_H
-
-#include "Dual_Resampler.h"
-#include "Classic_Emu.h"
-#include "Ym2413_Emu.h"
-#include "Ym2612_Emu.h"
-#include "Sms_Apu.h"
-
-template<class Emu>
-class Ym_Emu : public Emu {
-protected:
- int last_time;
- short* out;
- enum { disabled_time = -1 };
-public:
- Ym_Emu() : last_time( disabled_time ), out( NULL ) { }
- void enable( bool b ) { last_time = b ? 0 : disabled_time; }
- bool enabled() const { return last_time != disabled_time; }
- void begin_frame( short* p );
- int run_until( int time );
-};
-
-class Vgm_Emu_Impl : public Classic_Emu, private Dual_Resampler {
-public:
- typedef Classic_Emu::sample_t sample_t;
-protected:
- enum { stereo = 2 };
-
- typedef int vgm_time_t;
-
- enum { fm_time_bits = 12 };
- typedef int fm_time_t;
- long fm_time_offset;
- int fm_time_factor;
- fm_time_t to_fm_time( vgm_time_t ) const;
-
- enum { blip_time_bits = 12 };
- int blip_time_factor;
- blip_time_t to_blip_time( vgm_time_t ) const;
-
- byte const* data;
- byte const* loop_begin;
- byte const* data_end;
- void update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const;
-
- vgm_time_t vgm_time;
- byte const* pos;
- blip_time_t run_commands( vgm_time_t );
- int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf );
-
- byte const* pcm_data;
- byte const* pcm_pos;
- int dac_amp;
- int dac_disabled; // -1 if disabled
- void write_pcm( vgm_time_t, int amp );
-
- Ym_Emu<Ym2612_Emu> ym2612;
- Ym_Emu<Ym2413_Emu> ym2413;
-
- Blip_Buffer blip_buf;
- Sms_Apu psg;
- Blip_Synth<blip_med_quality,1> dac_synth;
-
- friend class Vgm_Emu;
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.cpp
deleted file mode 100644
index ede67304..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-
-// Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip
-
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Ym2413_Emu.h"
-
-Ym2413_Emu::Ym2413_Emu() { }
-
-Ym2413_Emu::~Ym2413_Emu() { }
-
-int Ym2413_Emu::set_rate( double, double ) { return 2; }
-
-void Ym2413_Emu::reset() { }
-
-void Ym2413_Emu::write( int, int ) { }
-
-void Ym2413_Emu::mute_voices( int ) { }
-
-void Ym2413_Emu::run( int, sample_t* ) { }
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.h
deleted file mode 100644
index 98a2a48e..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2413_Emu.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// YM2413 FM sound chip emulator interface
-
-// Game_Music_Emu 0.5.2
-#ifndef YM2413_EMU_H
-#define YM2413_EMU_H
-
-class Ym2413_Emu {
- struct OPLL* opll;
-public:
- Ym2413_Emu();
- ~Ym2413_Emu();
-
- // Set output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( double sample_rate, double clock_rate );
-
- // Reset to power-up state
- void reset();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { channel_count = 14 };
- void mute_voices( int mask );
-
- // Write 'data' to 'addr'
- void write( int addr, int data );
-
- // Run and write pair_count samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.cpp
deleted file mode 100644
index 41ebb093..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.cpp
+++ /dev/null
@@ -1,1319 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-// Based on Gens 2.10 ym2612.c
-
-#include "Ym2612_Emu.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2002 Stphane Dallongeville (gens AT consolemul.com) */
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// This is mostly the original source in its C style and all.
-//
-// Somewhat optimized and simplified. Uses a template to generate the many
-// variants of Update_Chan. Rewrote header file. In need of full rewrite by
-// someone more familiar with FM sound and the YM2612. Has some inaccuracies
-// compared to the Sega Genesis sound, particularly being mixed at such a
-// high sample accuracy (the Genesis sounds like it has only 8 bit samples).
-// - Shay
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-const int output_bits = 14;
-
-struct slot_t
-{
- const int *DT; // parametre detune
- int MUL; // parametre "multiple de frequence"
- int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
- int TLL; // Total Level ajusted
- int SLL; // Sustin Level (ajusted) = volume o l'enveloppe termine sa premiere phase de regression
- int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
- int KSR; // Key Scale Rate = cette valeur est calculee par rapport la frequence actuelle, elle va influer
- // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
- int SEG; // Type enveloppe SSG
- int env_xor;
- int env_max;
-
- const int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
- const int *DR; // Decay Rate (table pointeur) = Taux pour la regression (DR[KSR])
- const int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
- const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
- int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
- int Finc; // frequency step = pas d'incrementation du compteur-frequence
- // plus le pas est grand, plus la frequence est agu (ou haute)
- int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
- // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
- // en fonction de la valeur de cette variable, on va appeler une fonction permettant
- // de mettre jour l'enveloppe courante.
- int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir o l'on se trouve dans l'enveloppe
- int Einc; // Envelope step courant
- int Ecmp; // Envelope counter limite pour la prochaine phase
- int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
- // cette valeur est egal AR[KSR]
- int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
- // cette valeur est egal DR[KSR]
- int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
- // cette valeur est egal SR[KSR]
- int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
- // cette valeur est egal RR[KSR]
- int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot l'entree
- // d'un autre ou carrement la sortie de la voie
- int INd; // input data of the slot = donnees en entree du slot
- int ChgEnM; // Change envelop mask.
- int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
- int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
-};
-
-struct channel_t
-{
- int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back)
- int LEFT; // LEFT enable flag
- int RIGHT; // RIGHT enable flag
- int ALGO; // Algorythm = determine les connections entre les operateurs
- int FB; // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
- int FMS; // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
- int AMS; // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
- int FNUM[4]; // hauteur frequence de la voie (+ 3 pour le mode special)
- int FOCT[4]; // octave de la voie (+ 3 pour le mode special)
- int KC[4]; // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
- slot_t SLOT[4]; // four slot.operators = les 4 slots de la voie
- int FFlag; // Frequency step recalculation flag
-};
-
-struct state_t
-{
- int TimerBase; // TimerBase calculation
- int Status; // YM2612 Status (timer overflow)
- int TimerA; // timerA limit = valeur jusqu' laquelle le timer A doit compter
- int TimerAL;
- int TimerAcnt; // timerA counter = valeur courante du Timer A
- int TimerB; // timerB limit = valeur jusqu' laquelle le timer B doit compter
- int TimerBL;
- int TimerBcnt; // timerB counter = valeur courante du Timer B
- int Mode; // Mode actuel des voie 3 et 6 (normal / special)
- int DAC; // DAC enabled flag
- channel_t CHANNEL[Ym2612_Emu::channel_count]; // Les 6 voies du YM2612
- int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
- // cela nous rend le debuggage plus facile
-};
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-#define ATTACK 0
-#define DECAY 1
-#define SUBSTAIN 2
-#define RELEASE 3
-
-// SIN_LBITS <= 16
-// LFO_HBITS <= 16
-// (SIN_LBITS + SIN_HBITS) <= 26
-// (ENV_LBITS + ENV_HBITS) <= 28
-// (LFO_LBITS + LFO_HBITS) <= 28
-
-#define SIN_HBITS 12 // Sinus phase counter int part
-#define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting)
-
-#if (SIN_LBITS > 16)
-#define SIN_LBITS 16 // Can't be greater than 16 bits
-#endif
-
-#define ENV_HBITS 12 // Env phase counter int part
-#define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting)
-
-#define LFO_HBITS 10 // LFO phase counter int part
-#define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting)
-
-#define SIN_LENGHT (1 << SIN_HBITS)
-#define ENV_LENGHT (1 << ENV_HBITS)
-#define LFO_LENGHT (1 << LFO_HBITS)
-
-#define TL_LENGHT (ENV_LENGHT * 3) // Env + TL scaling + LFO
-
-#define SIN_MASK (SIN_LENGHT - 1)
-#define ENV_MASK (ENV_LENGHT - 1)
-#define LFO_MASK (LFO_LENGHT - 1)
-
-#define ENV_STEP (96.0 / ENV_LENGHT) // ENV_MAX = 96 dB
-
-#define ENV_ATTACK ((ENV_LENGHT * 0) << ENV_LBITS)
-#define ENV_DECAY ((ENV_LENGHT * 1) << ENV_LBITS)
-#define ENV_END ((ENV_LENGHT * 2) << ENV_LBITS)
-
-#define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4
-#define MAX_OUT ((1 << MAX_OUT_BITS) - 1)
-
-#define PG_CUT_OFF ((int) (78.0 / ENV_STEP))
-#define ENV_CUT_OFF ((int) (68.0 / ENV_STEP))
-
-#define AR_RATE 399128
-#define DR_RATE 5514396
-
-//#define AR_RATE 426136
-//#define DR_RATE (AR_RATE * 12)
-
-#define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1)
-#define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
-
-#define S0 0 // Stupid typo of the YM2612
-#define S1 2
-#define S2 1
-#define S3 3
-
-inline void set_seg( slot_t& s, int seg )
-{
- s.env_xor = 0;
- s.env_max = INT_MAX;
- s.SEG = seg;
- if ( seg & 4 )
- {
- s.env_xor = ENV_MASK;
- s.env_max = ENV_MASK;
- }
-}
-
-struct tables_t
-{
- short SIN_TAB [SIN_LENGHT]; // SINUS TABLE (offset into TL TABLE)
- int LFOcnt; // LFO counter = compteur-frequence pour le LFO
- int LFOinc; // LFO step counter = pas d'incrementation du compteur-frequence du LFO
- // plus le pas est grand, plus la frequence est grande
- unsigned int AR_TAB [128]; // Attack rate table
- unsigned int DR_TAB [96]; // Decay rate table
- unsigned int DT_TAB [8] [32]; // Detune table
- unsigned int SL_TAB [16]; // Substain level table
- unsigned int NULL_RATE [32]; // Table for NULL rate
- int LFO_INC_TAB [8]; // LFO step table
-
- short ENV_TAB [2 * ENV_LENGHT + 8]; // ENV CURVE TABLE (attack & decay)
-
- short LFO_ENV_TAB [LFO_LENGHT]; // LFO AMS TABLE (adjusted for 11.8 dB)
- short LFO_FREQ_TAB [LFO_LENGHT]; // LFO FMS TABLE
- int TL_TAB [TL_LENGHT * 2]; // TOTAL LEVEL TABLE (positif and minus)
- unsigned int DECAY_TO_ATTACK [ENV_LENGHT]; // Conversion from decay to attack phase
- unsigned int FINC_TAB [2048]; // Frequency step table
-};
-
-static const unsigned char DT_DEF_TAB [4 * 32] =
-{
-// FD = 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// FD = 1
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
-
-// FD = 2
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
- 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
-
-// FD = 3
- 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
- 8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
-};
-
-static const unsigned char FKEY_TAB [16] =
-{
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 2, 3, 3, 3,
- 3, 3, 3, 3
-};
-
-static const unsigned char LFO_AMS_TAB [4] =
-{
- 31, 4, 1, 0
-};
-
-static const unsigned char LFO_FMS_TAB [8] =
-{
- LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
- LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
- LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
- LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
-};
-
-inline void YM2612_Special_Update() { }
-
-struct Ym2612_Impl
-{
- enum { channel_count = Ym2612_Emu::channel_count };
-
- state_t YM2612;
- int mute_mask;
- tables_t g;
-
- void KEY_ON( channel_t&, int );
- void KEY_OFF( channel_t&, int );
- int SLOT_SET( int, int );
- int CHANNEL_SET( int, int );
- int YM_SET( int, int );
-
- void set_rate( double sample_rate, double clock_factor );
- void reset();
- void write0( int addr, int data );
- void write1( int addr, int data );
- void run_timer( int );
- void run( int pair_count, Ym2612_Emu::sample_t* );
-};
-
-void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl)
-{
- slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
-
- if (SL->Ecurp == RELEASE) // la touche est-elle rel'chee ?
- {
- SL->Fcnt = 0;
-
- // Fix Ecco 2 splash sound
-
- SL->Ecnt = (g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
- SL->ChgEnM = ~0;
-
-// SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
-// SL->Ecnt = 0;
-
- SL->Einc = SL->EincA;
- SL->Ecmp = ENV_DECAY;
- SL->Ecurp = ATTACK;
- }
-}
-
-
-void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl)
-{
- slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
-
- if (SL->Ecurp != RELEASE) // la touche est-elle appuyee ?
- {
- if (SL->Ecnt < ENV_DECAY) // attack phase ?
- {
- SL->Ecnt = (g.ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
- }
-
- SL->Einc = SL->EincR;
- SL->Ecmp = ENV_END;
- SL->Ecurp = RELEASE;
- }
-}
-
-
-int Ym2612_Impl::SLOT_SET( int Adr, int data )
-{
- int nch = Adr & 3;
- if ( nch == 3 )
- return 1;
-
- channel_t& ch = YM2612.CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
- slot_t& sl = ch.SLOT [(Adr >> 2) & 3];
-
- switch ( Adr & 0xF0 )
- {
- case 0x30:
- if ( (sl.MUL = (data & 0x0F)) != 0 ) sl.MUL <<= 1;
- else sl.MUL = 1;
-
- sl.DT = (int*) g.DT_TAB [(data >> 4) & 7];
-
- ch.SLOT [0].Finc = -1;
-
- break;
-
- case 0x40:
- sl.TL = data & 0x7F;
-
- // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
- YM2612_Special_Update();
-
-#if ((ENV_HBITS - 7) < 0)
- sl.TLL = sl.TL >> (7 - ENV_HBITS);
-#else
- sl.TLL = sl.TL << (ENV_HBITS - 7);
-#endif
-
- break;
-
- case 0x50:
- sl.KSR_S = 3 - (data >> 6);
-
- ch.SLOT [0].Finc = -1;
-
- if (data &= 0x1F) sl.AR = (int*) &g.AR_TAB [data << 1];
- else sl.AR = (int*) &g.NULL_RATE [0];
-
- sl.EincA = sl.AR [sl.KSR];
- if (sl.Ecurp == ATTACK) sl.Einc = sl.EincA;
- break;
-
- case 0x60:
- if ( (sl.AMSon = (data & 0x80)) != 0 ) sl.AMS = ch.AMS;
- else sl.AMS = 31;
-
- if (data &= 0x1F) sl.DR = (int*) &g.DR_TAB [data << 1];
- else sl.DR = (int*) &g.NULL_RATE [0];
-
- sl.EincD = sl.DR [sl.KSR];
- if (sl.Ecurp == DECAY) sl.Einc = sl.EincD;
- break;
-
- case 0x70:
- if (data &= 0x1F) sl.SR = (int*) &g.DR_TAB [data << 1];
- else sl.SR = (int*) &g.NULL_RATE [0];
-
- sl.EincS = sl.SR [sl.KSR];
- if ((sl.Ecurp == SUBSTAIN) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincS;
- break;
-
- case 0x80:
- sl.SLL = g.SL_TAB [data >> 4];
-
- sl.RR = (int*) &g.DR_TAB [((data & 0xF) << 2) + 2];
-
- sl.EincR = sl.RR [sl.KSR];
- if ((sl.Ecurp == RELEASE) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincR;
- break;
-
- case 0x90:
- // SSG-EG envelope shapes :
- /*
- E At Al H
-
- 1 0 0 0 \\\\
- 1 0 0 1 \___
- 1 0 1 0 \/\/
- 1 0 1 1 \
- 1 1 0 0 ////
- 1 1 0 1 /
- 1 1 1 0 /\/\
- 1 1 1 1 /___
-
- E = SSG-EG enable
- At = Start negate
- Al = Altern
- H = Hold */
-
- set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
- break;
- }
-
- return 0;
-}
-
-
-int Ym2612_Impl::CHANNEL_SET( int Adr, int data )
-{
- int num = Adr & 3;
- if ( num == 3 )
- return 1;
-
- channel_t& ch = YM2612.CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
-
- switch ( Adr & 0xFC )
- {
- case 0xA0:
- YM2612_Special_Update();
-
- ch.FNUM [0] = (ch.FNUM [0] & 0x700) + data;
- ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
- ch.SLOT [0].Finc = -1;
- break;
-
- case 0xA4:
- YM2612_Special_Update();
-
- ch.FNUM [0] = (ch.FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
- ch.FOCT [0] = (data & 0x38) >> 3;
- ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
- ch.SLOT [0].Finc = -1;
- break;
-
- case 0xA8:
- if ( Adr < 0x100 )
- {
- num++;
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x700) + data;
- YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
- FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1;
- }
- break;
-
- case 0xAC:
- if ( Adr < 0x100 )
- {
- num++;
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
- YM2612.CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
- YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
- FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1;
- }
- break;
-
- case 0xB0:
- if ( ch.ALGO != (data & 7) )
- {
- // Fix VectorMan 2 heli sound (level 1)
- YM2612_Special_Update();
-
- ch.ALGO = data & 7;
-
- ch.SLOT [0].ChgEnM = 0;
- ch.SLOT [1].ChgEnM = 0;
- ch.SLOT [2].ChgEnM = 0;
- ch.SLOT [3].ChgEnM = 0;
- }
-
- ch.FB = 9 - ((data >> 3) & 7); // Real thing ?
-
-// if (ch.FB = ((data >> 3) & 7)) ch.FB = 9 - ch.FB; // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
-// else ch.FB = 31;
- break;
-
- case 0xB4: {
- YM2612_Special_Update();
-
- ch.LEFT = 0 - ((data >> 7) & 1);
- ch.RIGHT = 0 - ((data >> 6) & 1);
-
- ch.AMS = LFO_AMS_TAB [(data >> 4) & 3];
- ch.FMS = LFO_FMS_TAB [data & 7];
-
- for ( int i = 0; i < 4; i++ )
- {
- slot_t& sl = ch.SLOT [i];
- sl.AMS = (sl.AMSon ? ch.AMS : 31);
- }
- break;
- }
- }
-
- return 0;
-}
-
-
-int Ym2612_Impl::YM_SET(int Adr, int data)
-{
- switch ( Adr )
- {
- case 0x22:
- if (data & 8) // LFO enable
- {
- // Cool Spot music 1, LFO modified severals time which
- // distord the sound, have to check that on a real genesis...
-
- g.LFOinc = g.LFO_INC_TAB [data & 7];
- }
- else
- {
- g.LFOinc = g.LFOcnt = 0;
- }
- break;
-
- case 0x24:
- YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2);
-
- if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
- {
- YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
- }
- break;
-
- case 0x25:
- YM2612.TimerA = (YM2612.TimerA & 0x3FC) | (data & 3);
-
- if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
- {
- YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
- }
- break;
-
- case 0x26:
- YM2612.TimerB = data;
-
- if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12))
- {
- YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12);
- }
- break;
-
- case 0x27:
- // Parametre divers
- // b7 = CSM MODE
- // b6 = 3 slot mode
- // b5 = reset b
- // b4 = reset a
- // b3 = timer enable b
- // b2 = timer enable a
- // b1 = load b
- // b0 = load a
-
- if ((data ^ YM2612.Mode) & 0x40)
- {
- // We changed the channel 2 mode, so recalculate phase step
- // This fix the punch sound in Street of Rage 2
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1; // recalculate phase step
- }
-
-// if ((data & 2) && (YM2612.Status & 2)) YM2612.TimerBcnt = YM2612.TimerBL;
-// if ((data & 1) && (YM2612.Status & 1)) YM2612.TimerAcnt = YM2612.TimerAL;
-
-// YM2612.Status &= (~data >> 4); // Reset du Status au cas ou c'est demande
- YM2612.Status &= (~data >> 4) & (data >> 2); // Reset Status
-
- YM2612.Mode = data;
- break;
-
- case 0x28: {
- int nch = data & 3;
- if ( nch == 3 )
- return 1;
- if ( data & 4 )
- nch += 3;
- channel_t& ch = YM2612.CHANNEL [nch];
-
- YM2612_Special_Update();
-
- if (data & 0x10) KEY_ON(ch, S0); // On appuie sur la touche pour le slot 1
- else KEY_OFF(ch, S0); // On rel'che la touche pour le slot 1
- if (data & 0x20) KEY_ON(ch, S1); // On appuie sur la touche pour le slot 3
- else KEY_OFF(ch, S1); // On rel'che la touche pour le slot 3
- if (data & 0x40) KEY_ON(ch, S2); // On appuie sur la touche pour le slot 2
- else KEY_OFF(ch, S2); // On rel'che la touche pour le slot 2
- if (data & 0x80) KEY_ON(ch, S3); // On appuie sur la touche pour le slot 4
- else KEY_OFF(ch, S3); // On rel'che la touche pour le slot 4
- break;
- }
-
- case 0x2B:
- if (YM2612.DAC ^ (data & 0x80)) YM2612_Special_Update();
-
- YM2612.DAC = data & 0x80; // activation/desactivation du DAC
- break;
- }
-
- return 0;
-}
-
-void Ym2612_Impl::set_rate( double sample_rate, double clock_rate )
-{
- assert( sample_rate );
- assert( clock_rate > sample_rate );
-
- int i;
-
- // 144 = 12 * (prescale * 2) = 12 * 6 * 2
- // prescale set to 6 by default
-
- double Frequence = clock_rate / sample_rate / 144.0;
- if ( fabs( Frequence - 1.0 ) < 0.0000001 )
- Frequence = 1.0;
- YM2612.TimerBase = int (Frequence * 4096.0);
-
- // Tableau TL :
- // [0 - 4095] = +output [4095 - ...] = +output overflow (fill with 0)
- // [12288 - 16383] = -output [16384 - ...] = -output overflow (fill with 0)
-
- for(i = 0; i < TL_LENGHT; i++)
- {
- if (i >= PG_CUT_OFF) // YM2612 cut off sound after 78 dB (14 bits output ?)
- {
- g.TL_TAB [TL_LENGHT + i] = g.TL_TAB [i] = 0;
- }
- else
- {
- double x = MAX_OUT; // Max output
- x /= pow( 10.0, (ENV_STEP * i) / 20.0 ); // Decibel -> Voltage
-
- g.TL_TAB [i] = (int) x;
- g.TL_TAB [TL_LENGHT + i] = -g.TL_TAB [i];
- }
- }
-
- // Tableau SIN :
- // g.SIN_TAB [x] [y] = sin(x) * y;
- // x = phase and y = volume
-
- g.SIN_TAB [0] = g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
-
- for(i = 1; i <= SIN_LENGHT / 4; i++)
- {
- double x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT)); // Sinus
- x = 20 * log10(1 / x); // convert to dB
-
- int j = (int) (x / ENV_STEP); // Get TL range
-
- if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
-
- g.SIN_TAB [i] = g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
- g.SIN_TAB [(SIN_LENGHT / 2) + i] = g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
- }
-
- // Tableau LFO (LFO wav) :
-
- for(i = 0; i < LFO_LENGHT; i++)
- {
- double x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
- x += 1.0;
- x /= 2.0; // positive only
- x *= 11.8 / ENV_STEP; // ajusted to MAX enveloppe modulation
-
- g.LFO_ENV_TAB [i] = (int) x;
-
- x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
- x *= (double) ((1 << (LFO_HBITS - 1)) - 1);
-
- g.LFO_FREQ_TAB [i] = (int) x;
-
- }
-
- // Tableau Enveloppe :
- // g.ENV_TAB [0] -> g.ENV_TAB [ENV_LENGHT - 1] = attack curve
- // g.ENV_TAB [ENV_LENGHT] -> g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
-
- for(i = 0; i < ENV_LENGHT; i++)
- {
- // Attack curve (x^8 - music level 2 Vectorman 2)
- double x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);
- x *= ENV_LENGHT;
-
- g.ENV_TAB [i] = (int) x;
-
- // Decay curve (just linear)
- x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);
- x *= ENV_LENGHT;
-
- g.ENV_TAB [ENV_LENGHT + i] = (int) x;
- }
- for ( i = 0; i < 8; i++ )
- g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
-
- g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1; // for the stopped state
-
- // Tableau pour la conversion Attack -> Decay and Decay -> Attack
-
- int j = ENV_LENGHT - 1;
- for ( i = 0; i < ENV_LENGHT; i++ )
- {
- while ( j && g.ENV_TAB [j] < i )
- j--;
-
- g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
- }
-
- // Tableau pour le Substain Level
-
- for(i = 0; i < 15; i++)
- {
- double x = i * 3; // 3 and not 6 (Mickey Mania first music for test)
- x /= ENV_STEP;
-
- g.SL_TAB [i] = ((int) x << ENV_LBITS) + ENV_DECAY;
- }
-
- g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
-
- // Tableau Frequency Step
-
- for(i = 0; i < 2048; i++)
- {
- double x = (double) (i) * Frequence;
-
-#if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)
- x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));
-#else
- x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));
-#endif
-
- x /= 2.0; // because MUL = value * 2
-
- g.FINC_TAB [i] = (unsigned int) x;
- }
-
- // Tableaux Attack & Decay Rate
-
- for(i = 0; i < 4; i++)
- {
- g.AR_TAB [i] = 0;
- g.DR_TAB [i] = 0;
- }
-
- for(i = 0; i < 60; i++)
- {
- double x = Frequence;
-
- x *= 1.0 + ((i & 3) * 0.25); // bits 0-1 : x1.00, x1.25, x1.50, x1.75
- x *= (double) (1 << ((i >> 2))); // bits 2-5 : shift bits (x2^0 - x2^15)
- x *= (double) (ENV_LENGHT << ENV_LBITS); // on ajuste pour le tableau g.ENV_TAB
-
- g.AR_TAB [i + 4] = (unsigned int) (x / AR_RATE);
- g.DR_TAB [i + 4] = (unsigned int) (x / DR_RATE);
- }
-
- for(i = 64; i < 96; i++)
- {
- g.AR_TAB [i] = g.AR_TAB [63];
- g.DR_TAB [i] = g.DR_TAB [63];
-
- g.NULL_RATE [i - 64] = 0;
- }
-
- for ( i = 96; i < 128; i++ )
- g.AR_TAB [i] = 0;
-
- // Tableau Detune
-
- for(i = 0; i < 4; i++)
- {
- for (int j = 0; j < 32; j++)
- {
-#if ((SIN_LBITS + SIN_HBITS - 21) < 0)
- double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));
-#else
- double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));
-#endif
-
- g.DT_TAB [i + 0] [j] = (int) y;
- g.DT_TAB [i + 4] [j] = (int) -y;
- }
- }
-
- // Tableau LFO
- g.LFO_INC_TAB [0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-
- reset();
-}
-
-const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
-{
- if ( !impl )
- {
- impl = (Ym2612_Impl*) malloc( sizeof *impl );
- if ( !impl )
- return "Out of memory";
- impl->mute_mask = 0;
- }
- memset( &impl->YM2612, 0, sizeof impl->YM2612 );
-
- impl->set_rate( sample_rate, clock_rate );
-
- return 0;
-}
-
-Ym2612_Emu::~Ym2612_Emu()
-{
- free( impl );
-}
-
-inline void Ym2612_Impl::write0( int opn_addr, int data )
-{
- assert( (unsigned) data <= 0xFF );
-
- if ( opn_addr < 0x30 )
- {
- YM2612.REG [0] [opn_addr] = data;
- YM_SET( opn_addr, data );
- }
- else if ( YM2612.REG [0] [opn_addr] != data )
- {
- YM2612.REG [0] [opn_addr] = data;
-
- if ( opn_addr < 0xA0 )
- SLOT_SET( opn_addr, data );
- else
- CHANNEL_SET( opn_addr, data );
- }
-}
-
-inline void Ym2612_Impl::write1( int opn_addr, int data )
-{
- assert( (unsigned) data <= 0xFF );
-
- if ( opn_addr >= 0x30 && YM2612.REG [1] [opn_addr] != data )
- {
- YM2612.REG [1] [opn_addr] = data;
-
- if ( opn_addr < 0xA0 )
- SLOT_SET( opn_addr + 0x100, data );
- else
- CHANNEL_SET( opn_addr + 0x100, data );
- }
-}
-
-void Ym2612_Emu::reset()
-{
- impl->reset();
-}
-
-void Ym2612_Impl::reset()
-{
- g.LFOcnt = 0;
- YM2612.TimerA = 0;
- YM2612.TimerAL = 0;
- YM2612.TimerAcnt = 0;
- YM2612.TimerB = 0;
- YM2612.TimerBL = 0;
- YM2612.TimerBcnt = 0;
- YM2612.DAC = 0;
-
- YM2612.Status = 0;
-
- int i;
- for ( i = 0; i < channel_count; i++ )
- {
- channel_t& ch = YM2612.CHANNEL [i];
-
- ch.LEFT = ~0;
- ch.RIGHT = ~0;
- ch.ALGO = 0;
- ch.FB = 31;
- ch.FMS = 0;
- ch.AMS = 0;
-
- for ( int j = 0 ;j < 4 ; j++ )
- {
- ch.S0_OUT [j] = 0;
- ch.FNUM [j] = 0;
- ch.FOCT [j] = 0;
- ch.KC [j] = 0;
-
- ch.SLOT [j].Fcnt = 0;
- ch.SLOT [j].Finc = 0;
- ch.SLOT [j].Ecnt = ENV_END; // Put it at the end of Decay phase...
- ch.SLOT [j].Einc = 0;
- ch.SLOT [j].Ecmp = 0;
- ch.SLOT [j].Ecurp = RELEASE;
-
- ch.SLOT [j].ChgEnM = 0;
- }
- }
-
- for ( i = 0; i < 0x100; i++ )
- {
- YM2612.REG [0] [i] = -1;
- YM2612.REG [1] [i] = -1;
- }
-
- for ( i = 0xB6; i >= 0xB4; i-- )
- {
- write0( i, 0xC0 );
- write1( i, 0xC0 );
- }
-
- for ( i = 0xB2; i >= 0x22; i-- )
- {
- write0( i, 0 );
- write1( i, 0 );
- }
-
- write0( 0x2A, 0x80 );
-}
-
-void Ym2612_Emu::write0( int addr, int data )
-{
- impl->write0( addr, data );
-}
-
-void Ym2612_Emu::write1( int addr, int data )
-{
- impl->write1( addr, data );
-}
-
-void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; }
-
-static void update_envelope_( slot_t* sl )
-{
- switch ( sl->Ecurp )
- {
- case 0:
- // Env_Attack_Next
-
- // Verified with Gynoug even in HQ (explode SFX)
- sl->Ecnt = ENV_DECAY;
-
- sl->Einc = sl->EincD;
- sl->Ecmp = sl->SLL;
- sl->Ecurp = DECAY;
- break;
-
- case 1:
- // Env_Decay_Next
-
- // Verified with Gynoug even in HQ (explode SFX)
- sl->Ecnt = sl->SLL;
-
- sl->Einc = sl->EincS;
- sl->Ecmp = ENV_END;
- sl->Ecurp = SUBSTAIN;
- break;
-
- case 2:
- // Env_Substain_Next(slot_t *SL)
- if (sl->SEG & 8) // SSG envelope type
- {
- int release = sl->SEG & 1;
-
- if ( !release )
- {
- // re KEY ON
-
- // sl->Fcnt = 0;
- // sl->ChgEnM = ~0;
-
- sl->Ecnt = 0;
- sl->Einc = sl->EincA;
- sl->Ecmp = ENV_DECAY;
- sl->Ecurp = ATTACK;
- }
-
- set_seg( *sl, (sl->SEG << 1) & 4 );
-
- if ( !release )
- break;
- }
- // fall through
-
- case 3:
- // Env_Release_Next
- sl->Ecnt = ENV_END;
- sl->Einc = 0;
- sl->Ecmp = ENV_END + 1;
- break;
-
- // default: no op
- }
-}
-
-inline void update_envelope( slot_t& sl )
-{
- int ecmp = sl.Ecmp;
- if ( (sl.Ecnt += sl.Einc) >= ecmp )
- update_envelope_( &sl );
-}
-
-template<int algo>
-struct ym2612_update_chan {
- static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-};
-
-typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-
-template<int algo>
-void ym2612_update_chan<algo>::func( tables_t& g, channel_t& ch,
- Ym2612_Emu::sample_t* buf, int length )
-{
- int not_end = ch.SLOT [S3].Ecnt - ENV_END;
-
- // algo is a compile-time constant, so all conditions based on it are resolved
- // during compilation
-
- // special cases
- if ( algo == 7 )
- not_end |= ch.SLOT [S0].Ecnt - ENV_END;
-
- if ( algo >= 5 )
- not_end |= ch.SLOT [S2].Ecnt - ENV_END;
-
- if ( algo >= 4 )
- not_end |= ch.SLOT [S1].Ecnt - ENV_END;
-
- int CH_S0_OUT_1 = ch.S0_OUT [1];
-
- int in0 = ch.SLOT [S0].Fcnt;
- int in1 = ch.SLOT [S1].Fcnt;
- int in2 = ch.SLOT [S2].Fcnt;
- int in3 = ch.SLOT [S3].Fcnt;
-
- int YM2612_LFOinc = g.LFOinc;
- int YM2612_LFOcnt = g.LFOcnt + YM2612_LFOinc;
-
- if ( !not_end )
- return;
-
- do
- {
- // envelope
- int const env_LFO = g.LFO_ENV_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK];
-
- short const* const ENV_TAB = g.ENV_TAB;
-
- #define CALC_EN( x ) \
- int temp##x = ENV_TAB [ch.SLOT [S##x].Ecnt >> ENV_LBITS] + ch.SLOT [S##x].TLL; \
- int en##x = ((temp##x ^ ch.SLOT [S##x].env_xor) + (env_LFO >> ch.SLOT [S##x].AMS)) & \
- ((temp##x - ch.SLOT [S##x].env_max) >> 31);
-
- CALC_EN( 0 )
- CALC_EN( 1 )
- CALC_EN( 2 )
- CALC_EN( 3 )
-
- int const* const TL_TAB = g.TL_TAB;
-
- #define SINT( i, o ) (TL_TAB [g.SIN_TAB [(i)] + (o)])
-
- // feedback
- int CH_S0_OUT_0 = ch.S0_OUT [0];
- {
- int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch.FB);
- CH_S0_OUT_1 = CH_S0_OUT_0;
- CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 );
- }
-
- int CH_OUTd;
- if ( algo == 0 )
- {
- int temp = in1 + CH_S0_OUT_1;
- temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 1 )
- {
- int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 2 )
- {
- int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 3 )
- {
- int temp = in1 + CH_S0_OUT_1;
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 4 )
- {
- int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
- //DO_LIMIT
- }
- else if ( algo == 5 )
- {
- int temp = CH_S0_OUT_1;
- CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
- //DO_LIMIT
- }
- else if ( algo == 6 )
- {
- CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- //DO_LIMIT
- }
- else if ( algo == 7 )
- {
- CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
- //DO_LIMIT
- }
-
- CH_OUTd >>= MAX_OUT_BITS - output_bits + 2;
-
- // update phase
- unsigned freq_LFO = ((g.LFO_FREQ_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] *
- ch.FMS) >> (LFO_HBITS - 1 + 1)) + (1L << (LFO_FMS_LBITS - 1));
- YM2612_LFOcnt += YM2612_LFOinc;
- in0 += (ch.SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in1 += (ch.SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in2 += (ch.SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in3 += (ch.SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-
- int t0 = buf [0] + (CH_OUTd & ch.LEFT);
- int t1 = buf [1] + (CH_OUTd & ch.RIGHT);
-
- update_envelope( ch.SLOT [0] );
- update_envelope( ch.SLOT [1] );
- update_envelope( ch.SLOT [2] );
- update_envelope( ch.SLOT [3] );
-
- ch.S0_OUT [0] = CH_S0_OUT_0;
- buf [0] = t0;
- buf [1] = t1;
- buf += 2;
- }
- while ( --length );
-
- ch.S0_OUT [1] = CH_S0_OUT_1;
-
- ch.SLOT [S0].Fcnt = in0;
- ch.SLOT [S1].Fcnt = in1;
- ch.SLOT [S2].Fcnt = in2;
- ch.SLOT [S3].Fcnt = in3;
-}
-
-static const ym2612_update_chan_t UPDATE_CHAN [8] = {
- &ym2612_update_chan<0>::func,
- &ym2612_update_chan<1>::func,
- &ym2612_update_chan<2>::func,
- &ym2612_update_chan<3>::func,
- &ym2612_update_chan<4>::func,
- &ym2612_update_chan<5>::func,
- &ym2612_update_chan<6>::func,
- &ym2612_update_chan<7>::func
-};
-
-void Ym2612_Impl::run_timer( int length )
-{
- int const step = 6;
- int remain = length;
- do
- {
- int n = step;
- if ( n > remain )
- n = remain;
- remain -= n;
-
- long i = n * YM2612.TimerBase;
- if (YM2612.Mode & 1) // Timer A ON ?
- {
- // if ((YM2612.TimerAcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
- if ((YM2612.TimerAcnt -= i) <= 0)
- {
- // timer a overflow
-
- YM2612.Status |= (YM2612.Mode & 0x04) >> 2;
- YM2612.TimerAcnt += YM2612.TimerAL;
-
- if (YM2612.Mode & 0x80)
- {
- KEY_ON( YM2612.CHANNEL [2], 0 );
- KEY_ON( YM2612.CHANNEL [2], 1 );
- KEY_ON( YM2612.CHANNEL [2], 2 );
- KEY_ON( YM2612.CHANNEL [2], 3 );
- }
- }
- }
-
- if (YM2612.Mode & 2) // Timer B ON ?
- {
- // if ((YM2612.TimerBcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
- if ((YM2612.TimerBcnt -= i) <= 0)
- {
- // timer b overflow
- YM2612.Status |= (YM2612.Mode & 0x08) >> 2;
- YM2612.TimerBcnt += YM2612.TimerBL;
- }
- }
- }
- while ( remain > 0 );
-}
-
-void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
-{
- if ( pair_count <= 0 )
- return;
-
- if ( YM2612.Mode & 3 )
- run_timer( pair_count );
-
- // Mise jour des pas des compteurs-frequences s'ils ont ete modifies
-
- for ( int chi = 0; chi < channel_count; chi++ )
- {
- channel_t& ch = YM2612.CHANNEL [chi];
- if ( ch.SLOT [0].Finc != -1 )
- continue;
-
- int i2 = 0;
- if ( chi == 2 && (YM2612.Mode & 0x40) )
- i2 = 2;
-
- for ( int i = 0; i < 4; i++ )
- {
- // static int seq [4] = { 2, 1, 3, 0 };
- // if ( i2 ) i2 = seq [i];
-
- slot_t& sl = ch.SLOT [i];
- int finc = g.FINC_TAB [ch.FNUM [i2]] >> (7 - ch.FOCT [i2]);
- int ksr = ch.KC [i2] >> sl.KSR_S; // keycode attenuation
- sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
- if (sl.KSR != ksr) // si le KSR a change alors
- { // les differents taux pour l'enveloppe sont mis jour
- sl.KSR = ksr;
-
- sl.EincA = sl.AR [ksr];
- sl.EincD = sl.DR [ksr];
- sl.EincS = sl.SR [ksr];
- sl.EincR = sl.RR [ksr];
-
- if (sl.Ecurp == ATTACK)
- {
- sl.Einc = sl.EincA;
- }
- else if (sl.Ecurp == DECAY)
- {
- sl.Einc = sl.EincD;
- }
- else if (sl.Ecnt < ENV_END)
- {
- if (sl.Ecurp == SUBSTAIN)
- sl.Einc = sl.EincS;
- else if (sl.Ecurp == RELEASE)
- sl.Einc = sl.EincR;
- }
- }
-
- if ( i2 )
- i2 = (i2 ^ 2) ^ (i2 >> 1);
- }
- }
-
- for ( int i = 0; i < channel_count; i++ )
- {
- if ( !(mute_mask & (1 << i)) && (i != 5 || !YM2612.DAC) )
- UPDATE_CHAN [YM2612.CHANNEL [i].ALGO]( g, YM2612.CHANNEL [i], out, pair_count );
- }
-
- g.LFOcnt += g.LFOinc * pair_count;
-}
-
-void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.h
deleted file mode 100644
index 383ac72d..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/Ym2612_Emu.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// YM2612 FM sound chip emulator interface
-
-// Game_Music_Emu 0.5.2
-#ifndef YM2612_EMU_H
-#define YM2612_EMU_H
-
-struct Ym2612_Impl;
-
-class Ym2612_Emu {
- Ym2612_Impl* impl;
-public:
- Ym2612_Emu() { impl = 0; }
- ~Ym2612_Emu();
-
- // Set output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- const char* set_rate( double sample_rate, double clock_rate );
-
- // Reset to power-up state
- void reset();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { channel_count = 6 };
- void mute_voices( int mask );
-
- // Write addr to register 0 then data to register 1
- void write0( int addr, int data );
-
- // Write addr to register 2 then data to register 3
- void write1( int addr, int data );
-
- // Run and add pair_count samples into current output buffer contents
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_common.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_common.h
deleted file mode 100644
index 9ab0bd7d..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_common.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// Sets up common environment for Shay Green's libraries.
-// To change configuration options, modify blargg_config.h, not this file.
-
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
-#include <stdint.h>
-
-#undef BLARGG_COMMON_H
-// allow blargg_config.h to #include blargg_common.h
-#include "blargg_config.h"
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
-#ifndef STATIC_CAST
- #define STATIC_CAST(T,expr) ((T) (expr))
-#endif
-
-// blargg_err_t (0 on success, otherwise error string)
-#ifndef blargg_err_t
- typedef const char* blargg_err_t;
-#endif
-
-// blargg_vector - very lightweight vector of POD types (no constructor/destructor)
-template<class T>
-class blargg_vector {
- T* begin_;
- size_t size_;
-public:
- blargg_vector() : begin_( 0 ), size_( 0 ) { }
- ~blargg_vector() { free( begin_ ); }
- size_t size() const { return size_; }
- T* begin() const { return begin_; }
- T* end() const { return begin_ + size_; }
- blargg_err_t resize( size_t n )
- {
- void* p = realloc( begin_, n * sizeof (T) );
- if ( !p && n )
- return "Out of memory";
- begin_ = (T*) p;
- size_ = n;
- return 0;
- }
- void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); }
- T& operator [] ( size_t n ) const
- {
- assert( n <= size_ ); // <= to allow past-the-end value
- return begin_ [n];
- }
-};
-
-#ifndef BLARGG_DISABLE_NOTHROW
- #if __cplusplus < 199711
- #define BLARGG_THROWS( spec )
- #else
- #define BLARGG_THROWS( spec ) throw spec
- #endif
- #define BLARGG_DISABLE_NOTHROW \
- void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
- void operator delete ( void* p ) { free( p ); }
- #define BLARGG_NEW new
-#else
- #include <new>
- #define BLARGG_NEW new (std::nothrow)
-#endif
-
-#define BLARGG_4CHAR( a, b, c, d ) \
- ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
-
-// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
-#ifndef BOOST_STATIC_ASSERT
- #ifdef _MSC_VER
- // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
- #else
- // Some other compilers fail when declaring same function multiple times in class,
- // so differentiate them by line
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
- #endif
-#endif
-
-// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
-// compiler is assumed to support bool. If undefined, availability is determined.
-#ifndef BLARGG_COMPILER_HAS_BOOL
- #if defined (__MWERKS__)
- #if !__option(bool)
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (_MSC_VER)
- #if _MSC_VER < 1100
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (__GNUC__)
- // supports bool
- #elif __cplusplus < 199711
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
-#endif
-#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
- // If you get errors here, modify your blargg_config.h file
- typedef int bool;
- const bool true = 1;
- const bool false = 0;
-#endif
-
-// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
-#include <limits.h>
-
-#if 0
-#if INT_MAX >= 0x7FFFFFFF
- typedef int blargg_long;
-#else
- typedef long blargg_long;
-#endif
-#endif
-typedef int64_t blargg_long;
-
-#if UINT_MAX >= 0xFFFFFFFF
- typedef unsigned blargg_ulong;
-#else
- typedef unsigned long blargg_ulong;
-#endif
-
-// BOOST::int8_t etc.
-
-// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
-#if defined (HAVE_STDINT_H)
- #include <stdint.h>
- #define BOOST
-
-// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
-#elif defined (HAVE_INTTYPES_H)
- #include <inttypes.h>
- #define BOOST
-
-#else
- struct BOOST
- {
- #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
- typedef signed char int8_t;
- typedef unsigned char uint8_t;
- #else
- // No suitable 8-bit type available
- typedef struct see_blargg_common_h int8_t;
- typedef struct see_blargg_common_h uint8_t;
- #endif
-
- #if USHRT_MAX == 0xFFFF
- typedef short int16_t;
- typedef unsigned short uint16_t;
- #else
- // No suitable 16-bit type available
- typedef struct see_blargg_common_h int16_t;
- typedef struct see_blargg_common_h uint16_t;
- #endif
-
- #if ULONG_MAX == 0xFFFFFFFF
- typedef long int32_t;
- typedef unsigned long uint32_t;
- #elif UINT_MAX == 0xFFFFFFFF
- typedef int int32_t;
- typedef unsigned int uint32_t;
- #else
- // No suitable 32-bit type available
- typedef struct see_blargg_common_h int32_t;
- typedef struct see_blargg_common_h uint32_t;
- #endif
- };
-#endif
-
-#endif
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_config.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_config.h
deleted file mode 100644
index 9e9c751d..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_config.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Library configuration. Modify this file as necessary.
-
-#ifndef BLARGG_CONFIG_H
-#define BLARGG_CONFIG_H
-
-// Uncomment to use zlib for transparent decompression of gzipped files
-//#define HAVE_ZLIB_H
-
-// Uncomment to support only the listed game music types. See gme_type_list.cpp
-// for a list of all types.
-//#define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
-
-// Uncomment to enable platform-specific optimizations
-//#define BLARGG_NONPORTABLE 1
-
-// Uncomment to use faster, lower quality sound synthesis
-//#define BLIP_BUFFER_FAST 1
-
-// Uncomment if automatic byte-order determination doesn't work
-//#define BLARGG_BIG_ENDIAN 1
-
-// Uncomment if you get errors in the bool section of blargg_common.h
-//#define BLARGG_COMPILER_HAS_BOOL 1
-
-// Use standard config.h if present
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_endian.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_endian.h
deleted file mode 100644
index 67165565..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_endian.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// CPU Byte Order Utilities
-
-// Game_Music_Emu 0.5.2
-#ifndef BLARGG_ENDIAN
-#define BLARGG_ENDIAN
-
-#include "blargg_common.h"
-
-// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
-#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
- #define BLARGG_CPU_X86 1
- #define BLARGG_CPU_CISC 1
-#endif
-
-#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
- #define BLARGG_CPU_POWERPC 1
-#endif
-
-// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
-// one may be #defined to 1. Only needed if something actually depends on byte order.
-#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
-#ifdef __GLIBC__
- // GCC handles this for us
- #include <endian.h>
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- #define BLARGG_LITTLE_ENDIAN 1
- #elif __BYTE_ORDER == __BIG_ENDIAN
- #define BLARGG_BIG_ENDIAN 1
- #endif
-#else
-
-#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
- (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-
-#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
- defined (__mips__) || defined (__sparc__) || BLARGG_CPU_POWERPC || \
- (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
- #define BLARGG_BIG_ENDIAN 1
-#else
- // No endian specified; assume little-endian, since it's most common
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-#endif
-#endif
-
-#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
- #undef BLARGG_LITTLE_ENDIAN
- #undef BLARGG_BIG_ENDIAN
-#endif
-
-inline void blargg_verify_byte_order()
-{
- #ifndef NDEBUG
- #if BLARGG_BIG_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i == 0 );
- #elif BLARGG_LITTLE_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i != 0 );
- #endif
- #endif
-}
-
-inline unsigned get_le16( void const* p ) {
- return ((unsigned char const*) p) [1] * 0x100u +
- ((unsigned char const*) p) [0];
-}
-inline unsigned get_be16( void const* p ) {
- return ((unsigned char const*) p) [0] * 0x100u +
- ((unsigned char const*) p) [1];
-}
-inline blargg_ulong get_le32( void const* p ) {
- return ((unsigned char const*) p) [3] * 0x01000000u +
- ((unsigned char const*) p) [2] * 0x00010000u +
- ((unsigned char const*) p) [1] * 0x00000100u +
- ((unsigned char const*) p) [0];
-}
-inline blargg_ulong get_be32( void const* p ) {
- return ((unsigned char const*) p) [0] * 0x01000000u +
- ((unsigned char const*) p) [1] * 0x00010000u +
- ((unsigned char const*) p) [2] * 0x00000100u +
- ((unsigned char const*) p) [3];
-}
-inline void set_le16( void* p, unsigned n ) {
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [0] = (unsigned char) n;
-}
-inline void set_be16( void* p, unsigned n ) {
- ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [1] = (unsigned char) n;
-}
-inline void set_le32( void* p, blargg_ulong n ) {
- ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [0] = (unsigned char) n;
-}
-inline void set_be32( void* p, blargg_ulong n ) {
- ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [3] = (unsigned char) n;
-}
-
-#if BLARGG_NONPORTABLE
- // Optimized implementation if byte order is known
- #if BLARGG_LITTLE_ENDIAN
- #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr))
- #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr))
- #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
- #elif BLARGG_BIG_ENDIAN
- #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr))
- #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
- #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
- #endif
-
- #if BLARGG_CPU_POWERPC && defined (__MWERKS__)
- // PowerPC has special byte-reversed instructions
- // to do: assumes that PowerPC is running in big-endian mode
- // to do: implement for other compilers which don't support these macros
- #define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
- #define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
- #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
- #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
- #endif
-#endif
-
-#ifndef GET_LE16
- #define GET_LE16( addr ) get_le16( addr )
- #define GET_LE32( addr ) get_le32( addr )
- #define SET_LE16( addr, data ) set_le16( addr, data )
- #define SET_LE32( addr, data ) set_le32( addr, data )
-#endif
-
-#ifndef GET_BE16
- #define GET_BE16( addr ) get_be16( addr )
- #define GET_BE32( addr ) get_be32( addr )
- #define SET_BE16( addr, data ) set_be16( addr, data )
- #define SET_BE32( addr, data ) set_be32( addr, data )
-#endif
-
-// auto-selecting versions
-
-inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
-inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); }
-inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
-inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); }
-inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); }
-inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); }
-inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); }
-inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); }
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_source.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_source.h
deleted file mode 100644
index 945bf349..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/blargg_source.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Included at the beginning of library source files, after all other #include lines
-#ifndef BLARGG_SOURCE_H
-#define BLARGG_SOURCE_H
-
-// If debugging is enabled, abort program if expr is false. Meant for checking
-// internal state and consistency. A failed assertion indicates a bug in the module.
-// void assert( bool expr );
-#include <assert.h>
-
-// If debugging is enabled and expr is false, abort program. Meant for checking
-// caller-supplied parameters and operations that are outside the control of the
-// module. A failed requirement indicates a bug outside the module.
-// void require( bool expr );
-#undef require
-#define require( expr ) assert( expr )
-
-// Like printf() except output goes to debug log file. Might be defined to do
-// nothing (not even evaluate its arguments).
-// void dprintf( const char* format, ... );
-inline void blargg_dprintf_( const char*, ... ) { }
-#undef dprintf
-#define dprintf (1) ? (void) 0 : blargg_dprintf_
-
-// If enabled, evaluate expr and if false, make debug log entry with source file
-// and line. Meant for finding situations that should be examined further, but that
-// don't indicate a problem. In all cases, execution continues normally.
-#undef check
-#define check( expr ) ((void) 0)
-
-// If expr yields error string, return it from current function, otherwise continue.
-#undef RETURN_ERR
-#define RETURN_ERR( expr ) do { \
- blargg_err_t blargg_return_err_ = (expr); \
- if ( blargg_return_err_ ) return blargg_return_err_; \
- } while ( 0 )
-
-// If ptr is 0, return out of memory error string.
-#undef CHECK_ALLOC
-#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
-
-// Avoid any macros which evaluate their arguments multiple times
-#undef min
-#undef max
-
-// using const references generates crappy code, and I am currenly only using these
-// for built-in types, so they take arguments by value
-
-template<class T>
-inline T min( T x, T y )
-{
- if ( x < y )
- return x;
- return y;
-}
-
-template<class T>
-inline T max( T x, T y )
-{
- if ( x < y )
- return y;
- return x;
-}
-
-// TODO: good idea? bad idea?
-#undef byte
-#define byte byte_
-typedef unsigned char byte;
-
-// deprecated
-#define BLARGG_CHECK_ALLOC CHECK_ALLOC
-#define BLARGG_RETURN_ERR RETURN_ERR
-
-// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
-#ifdef BLARGG_SOURCE_BEGIN
- #include BLARGG_SOURCE_BEGIN
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/gb_cpu_io.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/gb_cpu_io.h
deleted file mode 100644
index ada99ead..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/gb_cpu_io.h
+++ /dev/null
@@ -1,72 +0,0 @@
-
-#include "Gbs_Emu.h"
-
-#include "blargg_source.h"
-
-int Gbs_Emu::cpu_read( gb_addr_t addr )
-{
- int result = *cpu::get_code( addr );
- if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )
- result = apu.read_register( clock(), addr );
-#ifndef NDEBUG
- else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
- dprintf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
- else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 )
- dprintf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
-#endif
- return result;
-}
-
-void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
-{
- unsigned offset = addr - ram_addr;
- if ( offset <= 0xFFFF - ram_addr )
- {
- ram [offset] = data;
- if ( (addr ^ 0xE000) <= 0x1F80 - 1 )
- {
- if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )
- {
- GME_APU_HOOK( this, addr - Gb_Apu::start_addr, data );
- apu.write_register( clock(), addr, data );
- }
- else if ( (addr ^ 0xFF06) < 2 )
- update_timer();
- else if ( addr == joypad_addr )
- ram [offset] = 0; // keep joypad return value 0
- else
- ram [offset] = 0xFF;
-
- //if ( addr == 0xFFFF )
- // dprintf( "Wrote interrupt mask\n" );
- }
- }
- else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
- {
- set_bank( data );
- }
-#ifndef NDEBUG
- else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
- {
- dprintf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
- }
-#endif
-}
-
-#define CPU_READ_FAST( cpu, addr, time, out ) \
- CPU_READ_FAST_( STATIC_CAST(Gbs_Emu*,cpu), addr, time, out )
-
-#define CPU_READ_FAST_( emu, addr, time, out ) \
-{\
- out = READ_PROG( addr );\
- if ( unsigned (addr - Gb_Apu::start_addr) <= Gb_Apu::register_count )\
- out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\
- else\
- check( out == emu->cpu_read( addr ) );\
-}
-
-#define CPU_READ( cpu, addr, time ) \
- STATIC_CAST(Gbs_Emu*,cpu)->cpu_read( addr )
-
-#define CPU_WRITE( cpu, addr, data, time ) \
- STATIC_CAST(Gbs_Emu*,cpu)->cpu_write( addr, data )
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.cpp b/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.cpp
deleted file mode 100644
index d6cebfa8..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.cpp
+++ /dev/null
@@ -1,256 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#if !GME_DISABLE_STEREO_DEPTH
-#include "Effects_Buffer.h"
-#endif
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifndef GME_TYPE_LIST
-
-// Default list of all supported game music types (copy this to blargg_config.h
-// if you want to modify it)
-#define GME_TYPE_LIST \
- gme_ay_type,\
- gme_gbs_type,\
- gme_gym_type,\
- gme_hes_type,\
- gme_kss_type,\
- gme_nsf_type,\
- gme_nsfe_type,\
- gme_sap_type,\
- gme_spc_type,\
- gme_vgm_type,\
- gme_vgz_type
-
-#endif
-
-static gme_type_t const gme_type_list_ [] = { GME_TYPE_LIST, 0 };
-
-gme_type_t const* gme_type_list()
-{
- return gme_type_list_;
-}
-
-const char* gme_identify_header( void const* header )
-{
- switch ( get_be32( header ) )
- {
- case BLARGG_4CHAR('Z','X','A','Y'): return "AY";
- case BLARGG_4CHAR('G','B','S',0x01): return "GBS";
- case BLARGG_4CHAR('G','Y','M','X'): return "GYM";
- case BLARGG_4CHAR('H','E','S','M'): return "HES";
- case BLARGG_4CHAR('K','S','C','C'):
- case BLARGG_4CHAR('K','S','S','X'): return "KSS";
- case BLARGG_4CHAR('N','E','S','M'): return "NSF";
- case BLARGG_4CHAR('N','S','F','E'): return "NSFE";
- case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
- case BLARGG_4CHAR('S','N','E','S'): return "SPC";
- case BLARGG_4CHAR('V','g','m',' '): return "VGM";
- }
- return "";
-}
-
-static void to_uppercase( const char* in, int len, char* out )
-{
- for ( int i = 0; i < len; i++ )
- {
- if ( !(out [i] = toupper( in [i] )) )
- return;
- }
- *out = 0; // extension too long
-}
-
-gme_type_t gme_identify_extension( const char* extension_ )
-{
- char const* end = strrchr( extension_, '.' );
- if ( end )
- extension_ = end + 1;
-
- char extension [6];
- to_uppercase( extension_, sizeof extension, extension );
-
- for ( gme_type_t const* types = gme_type_list_; *types; types++ )
- if ( !strcmp( extension, (*types)->extension_ ) )
- return *types;
- return 0;
-}
-
-gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
-{
- *type_out = gme_identify_extension( path );
- // TODO: don't examine header if file has extension?
- if ( !*type_out )
- {
- char header [4];
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- RETURN_ERR( in.read( header, sizeof header ) );
- *type_out = gme_identify_extension( gme_identify_header( header ) );
- }
- return 0;
-}
-
-gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, long sample_rate )
-{
- require( (data || !size) && out );
- *out = 0;
-
- gme_type_t file_type = 0;
- if ( size >= 4 )
- file_type = gme_identify_extension( gme_identify_header( data ) );
- if ( !file_type )
- return gme_wrong_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- gme_err_t err = gme_load_data( emu, data, size );
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-gme_err_t gme_open_file( const char* path, Music_Emu** out, long sample_rate )
-{
- require( path && out );
- *out = 0;
-
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
-
- char header [4];
- int header_size = 0;
-
- gme_type_t file_type = gme_identify_extension( path );
- if ( !file_type )
- {
- header_size = sizeof header;
- RETURN_ERR( in.read( header, sizeof header ) );
- file_type = gme_identify_extension( gme_identify_header( header ) );
- }
- if ( !file_type )
- return gme_wrong_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- // optimization: avoids seeking/re-reading header
- Remaining_Reader rem( header, header_size, &in );
- gme_err_t err = emu->load( rem );
- in.close();
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-Music_Emu* gme_new_emu( gme_type_t type, long rate )
-{
- if ( type )
- {
- if ( rate == gme_info_only )
- return type->new_info();
-
- Music_Emu* me = type->new_emu();
- if ( me )
- {
- #if !GME_DISABLE_STEREO_DEPTH
- if ( type->flags_ & 1 )
- {
- me->effects_buffer = BLARGG_NEW Effects_Buffer;
- if ( me->effects_buffer )
- me->set_buffer( me->effects_buffer );
- }
-
- if ( !(type->flags_ & 1) || me->effects_buffer )
- #endif
- {
- if ( !me->set_sample_rate( rate ) )
- {
- check( me->type() == type );
- return me;
- }
- }
- delete me;
- }
- }
- return 0;
-}
-
-gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
-
-gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
-{
- Mem_File_Reader in( data, size );
- return me->load( in );
-}
-
-gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
-{
- Callback_Reader in( func, size, data );
- return me->load( in );
-}
-
-void gme_delete( Music_Emu* me ) { delete me; }
-
-gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
-
-const char* gme_warning( Music_Emu* me ) { return me->warning(); }
-
-int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
-
-const char* gme_track_info( Music_Emu const* me, track_info_t* out, int track )
-{
- return me->track_info( out, track );
-}
-
-void gme_set_stereo_depth( Music_Emu* me, double depth )
-{
-#if !GME_DISABLE_STEREO_DEPTH
- if ( me->effects_buffer )
- STATIC_CAST(Effects_Buffer*,me->effects_buffer)->set_depth( depth );
-#endif
-}
-
-void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
-void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
-void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
-
-gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
-gme_err_t gme_play ( Music_Emu* me, long n, short* p ) { return me->play( n, p ); }
-void gme_set_fade ( Music_Emu* me, long start_msec ) { me->set_fade( start_msec ); }
-int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
-long gme_tell ( Music_Emu const* me ) { return me->tell(); }
-gme_err_t gme_seek ( Music_Emu* me, long msec ) { return me->seek( msec ); }
-int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
-void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
-void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
-void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
-void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
-void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq ) { me->set_equalizer( *eq ); }
-gme_equalizer_t gme_equalizer( Music_Emu const* me ) { return me->equalizer(); }
-const char** gme_voice_names ( Music_Emu const* me ) { return me->voice_names(); }
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.h
deleted file mode 100644
index 469c901c..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/gme.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/* Game music emulator library C interface (also usable from C++) */
-
-/* Game_Music_Emu 0.5.2 */
-#ifndef GME_H
-#define GME_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/* Error string returned by library functions, or NULL if no error (success) */
-typedef const char* gme_err_t;
-
-/* First parameter of most gme_ functions is a pointer to the Music_Emu */
-typedef struct Music_Emu Music_Emu;
-
-
-/******** Basic operations ********/
-
-/* Create emulator and load game music file/data into it. Sets *out to new emulator. */
-gme_err_t gme_open_file( const char* path, Music_Emu** out, long sample_rate );
-
-/* Number of tracks available */
-int gme_track_count( Music_Emu const* );
-
-/* Start a track, where 0 is the first track */
-gme_err_t gme_start_track( Music_Emu*, int index );
-
-/* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */
-gme_err_t gme_play( Music_Emu*, long count, short* out );
-
-/* Finish using emulator and free memory */
-void gme_delete( Music_Emu* );
-
-
-/******** Track position/length ********/
-
-/* Set time to start fading track out. Once fade ends track_ended() returns true.
-Fade time can be changed while track is playing. */
-void gme_set_fade( Music_Emu*, long start_msec );
-
-/* True if a track has reached its end */
-int gme_track_ended( Music_Emu const* );
-
-/* Number of milliseconds (1000 = one second) played since beginning of track */
-long gme_tell( Music_Emu const* );
-
-/* Seek to new time in track. Seeking backwards or far forward can take a while. */
-gme_err_t gme_seek( Music_Emu*, long msec );
-
-
-/******** Informational ********/
-
-/* If you only need track information from a music file, pass gme_info_only for
-sample_rate to open/load. */
-enum { gme_info_only = -1 };
-
-/* Most recent warning string, or NULL if none. Clears current warning after returning.
-Warning is also cleared when loading a file and starting a track. */
-const char* gme_warning( Music_Emu* );
-
-/* Load m3u playlist file (must be done after loading music) */
-gme_err_t gme_load_m3u( Music_Emu*, const char* path );
-
-/* Clear any loaded m3u playlist and any internal playlist that the music format
-supports (NSFE for example). */
-void gme_clear_playlist( Music_Emu* );
-
-/* Get information for a particular track (length, name, author, etc.) */
-typedef struct track_info_t track_info_t;
-gme_err_t gme_track_info( Music_Emu const*, track_info_t* out, int track );
-
-struct track_info_t
-{
- long track_count;
-
- /* times in milliseconds; -1 if unknown */
- long length;
- long intro_length;
- long loop_length;
-
- /* empty string if not available */
- char system [256];
- char game [256];
- char song [256];
- char author [256];
- char copyright [256];
- char comment [256];
- char dumper [256];
-};
-enum { gme_max_field = 255 };
-
-
-/******** Advanced playback ********/
-
-/* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for
-GYM, SPC, and Sega Genesis VGM music */
-void gme_set_stereo_depth( Music_Emu*, double depth );
-
-/* Disable automatic end-of-track detection and skipping of silence at beginning
-if ignore is true */
-void gme_ignore_silence( Music_Emu*, int ignore );
-
-/* Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
-Track length as returned by track_info() assumes a tempo of 1.0. */
-void gme_set_tempo( Music_Emu*, double tempo );
-
-/* Number of voices used by currently loaded file */
-int gme_voice_count( Music_Emu const* );
-
-/* Names of voices */
-const char** gme_voice_names( Music_Emu const* );
-
-/* Mute/unmute voice i, where voice 0 is first voice */
-void gme_mute_voice( Music_Emu*, int index, int mute );
-
-/* Set muting state of all voices at once using a bit mask, where -1 mutes all
-voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
-void gme_mute_voices( Music_Emu*, int muting_mask );
-
-/* Frequency equalizer parameters (see gme.txt) */
-typedef struct gme_equalizer_t
-{
- double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
- long bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */
-} gme_equalizer_t;
-
-/* Get current frequency equalizater parameters */
-gme_equalizer_t gme_equalizer( Music_Emu const* );
-
-/* Change frequency equalizer parameters */
-void gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
-
-
-
-/******** Game music types ********/
-
-/* gme_type_t is a pointer to this structure. For example, gme_nsf_type->system is
-"Nintendo NES" and gme_nsf_type->new_emu() is equilvant to new Nsf_Emu (in C++). */
-typedef struct gme_type_t_ const* gme_type_t;
-struct gme_type_t_
-{
- const char* system; /* name of system this music file type is generally for */
- int track_count; /* non-zero for formats with a fixed number of tracks */
- Music_Emu* (*new_emu)(); /* Create new emulator for this type (useful in C++ only) */
- Music_Emu* (*new_info)(); /* Create new info reader for this type */
-
- /* internal */
- const char* extension_;
- int flags_;
-};
-
-/* Emulator type constants for each supported file type */
-extern struct gme_type_t_ const gme_ay_type [], gme_gbs_type [], gme_gym_type [],
- gme_hes_type [], gme_kss_type [], gme_nsf_type [], gme_nsfe_type [],
- gme_sap_type [], gme_spc_type [], gme_vgm_type [], gme_vgz_type [];
-
-/* Type of this emulator */
-gme_type_t gme_type( Music_Emu const* );
-
-/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
-to this library to support new music types without having to be updated. */
-gme_type_t const* gme_type_list();
-
-
-/******** Advanced file loading ********/
-
-/* Error returned if file type is not supported */
-extern const char gme_wrong_file_type [];
-
-/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
-gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, long sample_rate );
-
-/* Determine likely game music type based on first four bytes of file. Returns
-string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if
-file header is not recognized. */
-const char* gme_identify_header( void const* header );
-
-/* Get corresponding music type for file path or extension passed in. */
-gme_type_t gme_identify_extension( const char* path_or_extension );
-
-/* Determine file type based on file's extension or header (if extension isn't recognized).
-Sets *type_out to type, or 0 if unrecognized or error. */
-gme_err_t gme_identify_file( const char* path, gme_type_t* type_out );
-
-/* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need
-track information, pass gme_info_only for sample_rate. */
-Music_Emu* gme_new_emu( gme_type_t, long sample_rate );
-
-/* Load music file into emulator */
-gme_err_t gme_load_file( Music_Emu*, const char* path );
-
-/* Load music file from memory into emulator. Makes a copy of data passed. */
-gme_err_t gme_load_data( Music_Emu*, void const* data, long size );
-
-/* Load music file using custom data reader function that will be called to
-read file data. Most emulators load the entire file in one read call. */
-typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, long count );
-gme_err_t gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
-
-/* Load m3u playlist file from memory (must be done after loading music) */
-gme_err_t gme_load_m3u_data( Music_Emu*, void const* data, long size );
-
-
-/******** User data ********/
-
-/* Set/get pointer to data you want to associate with this emulator.
-You can use this for whatever you want. */
-void gme_set_user_data( Music_Emu*, void* new_user_data );
-void* gme_user_data( Music_Emu const* );
-
-/* Register cleanup function to be called when deleting emulator, or NULL to
-clear it. Passes user_data to cleanup function. */
-typedef void (*gme_user_cleanup_t)( void* user_data );
-void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/hes_cpu_io.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/hes_cpu_io.h
deleted file mode 100644
index b3d71dad..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/hes_cpu_io.h
+++ /dev/null
@@ -1,101 +0,0 @@
-
-#include "Hes_Emu.h"
-
-#include "blargg_source.h"
-
-int Hes_Emu::cpu_read( hes_addr_t addr )
-{
- check( addr <= 0xFFFF );
- int result = *cpu::get_code( addr );
- if ( mmr [addr >> page_shift] == 0xFF )
- result = cpu_read_( addr );
- return result;
-}
-
-void Hes_Emu::cpu_write( hes_addr_t addr, int data )
-{
- check( addr <= 0xFFFF );
- byte* out = write_pages [addr >> page_shift];
- addr &= page_size - 1;
- if ( out )
- out [addr] = data;
- else if ( mmr [addr >> page_shift] == 0xFF )
- cpu_write_( addr, data );
-}
-
-inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank )
-{
- write_pages [page] = 0;
- if ( bank < 0x80 )
- return rom.at_addr( bank * (blargg_long) page_size );
-
- byte* data = 0;
- switch ( bank )
- {
- case 0xF8:
- data = cpu::ram;
- break;
-
- case 0xF9:
- case 0xFA:
- case 0xFB:
- data = &sgx [(bank - 0xF9) * page_size];
- break;
-
- default:
- if ( bank != 0xFF )
- dprintf( "Unmapped bank $%02X\n", bank );
- return rom.unmapped();
- }
-
- write_pages [page] = data;
- return data;
-}
-
-#define CPU_READ_FAST( cpu, addr, time, out ) \
- CPU_READ_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, time, out )
-
-#define CPU_READ_FAST_( cpu, addr, time, out ) \
-{\
- out = READ_PROG( addr );\
- if ( mmr [addr >> page_shift] == 0xFF )\
- {\
- FLUSH_TIME();\
- out = cpu->cpu_read_( addr );\
- CACHE_TIME();\
- }\
-}
-
-#define CPU_WRITE_FAST( cpu, addr, data, time ) \
- CPU_WRITE_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, data, time )
-
-#define CPU_WRITE_FAST_( cpu, addr, data, time ) \
-{\
- byte* out = cpu->write_pages [addr >> page_shift];\
- addr &= page_size - 1;\
- if ( out )\
- {\
- out [addr] = data;\
- }\
- else if ( mmr [addr >> page_shift] == 0xFF )\
- {\
- FLUSH_TIME();\
- cpu->cpu_write_( addr, data );\
- CACHE_TIME();\
- }\
-}
-
-#define CPU_READ( cpu, addr, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_read( addr )
-
-#define CPU_WRITE( cpu, addr, data, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_write( addr, data )
-
-#define CPU_WRITE_VDP( cpu, addr, data, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_write_vdp( addr, data )
-
-#define CPU_SET_MMR( cpu, page, bank ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_set_mmr( page, bank )
-
-#define CPU_DONE( cpu, time, result_out ) \
- result_out = STATIC_CAST(Hes_Emu*,cpu)->cpu_done()
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/nes_cpu_io.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/nes_cpu_io.h
deleted file mode 100644
index 4bae3793..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/nes_cpu_io.h
+++ /dev/null
@@ -1,83 +0,0 @@
-
-#include "Nsf_Emu.h"
-
-#if !NSF_EMU_APU_ONLY
- #include "Nes_Namco_Apu.h"
-#endif
-
-#include "blargg_source.h"
-
-int Nsf_Emu::cpu_read( nes_addr_t addr )
-{
- int result;
-
- result = cpu::low_mem [addr & 0x7FF];
- if ( !(addr & 0xE000) )
- goto exit;
-
- result = *cpu::get_code( addr );
- if ( addr > 0x7FFF )
- goto exit;
-
- result = sram [addr & (sizeof sram - 1)];
- if ( addr > 0x5FFF )
- goto exit;
-
- if ( addr == Nes_Apu::status_addr )
- return apu.read_status( cpu::time() );
-
- #if !NSF_EMU_APU_ONLY
- if ( addr == Nes_Namco_Apu::data_reg_addr && namco )
- return namco->read_data();
- #endif
-
- result = addr >> 8; // simulate open bus
-
- if ( addr != 0x2002 )
- dprintf( "Read unmapped $%.4X\n", (unsigned) addr );
-
-exit:
- return result;
-}
-
-void Nsf_Emu::cpu_write( nes_addr_t addr, int data )
-{
- {
- nes_addr_t offset = addr ^ sram_addr;
- if ( offset < sizeof sram )
- {
- sram [offset] = data;
- return;
- }
- }
- {
- int temp = addr & 0x7FF;
- if ( !(addr & 0xE000) )
- {
- cpu::low_mem [temp] = data;
- return;
- }
- }
-
- if ( unsigned (addr - Nes_Apu::start_addr) <= Nes_Apu::end_addr - Nes_Apu::start_addr )
- {
- GME_APU_HOOK( this, addr - Nes_Apu::start_addr, data );
- apu.write_register( cpu::time(), addr, data );
- return;
- }
-
- unsigned bank = addr - bank_select_addr;
- if ( bank < bank_count )
- {
- blargg_long offset = rom.mask_addr( data * (blargg_long) bank_size );
- if ( offset >= rom.size() )
- set_warning( "Invalid bank" );
- cpu::map_code( (bank + 8) * bank_size, bank_size, rom.at_addr( offset ) );
- return;
- }
-
- cpu_write_misc( addr, data );
-}
-
-#define CPU_READ( cpu, addr, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_read( addr )
-#define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_write( addr, data )
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/gme/sap_cpu_io.h b/plugins/gme/Game_Music_Emu-0.5.2/gme/sap_cpu_io.h
deleted file mode 100644
index 8c2f6dd0..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/gme/sap_cpu_io.h
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include "Sap_Emu.h"
-
-#include "blargg_source.h"
-
-#define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_write( addr, data )
-
-void Sap_Emu::cpu_write( sap_addr_t addr, int data )
-{
- mem.ram [addr] = data;
- if ( (addr >> 8) == 0xD2 )
- cpu_write_( addr, data );
-}
-
-#ifdef NDEBUG
- #define CPU_READ( cpu, addr, time ) READ_LOW( addr )
-#else
- #define CPU_READ( cpu, addr, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_read( addr )
-
- int Sap_Emu::cpu_read( sap_addr_t addr )
- {
- if ( (addr & 0xF900) == 0xD000 )
- dprintf( "Unmapped read $%04X\n", addr );
- return mem.ram [addr];
- }
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/license.txt b/plugins/gme/Game_Music_Emu-0.5.2/license.txt
deleted file mode 100644
index 5faba9d4..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/license.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.cpp b/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.cpp
deleted file mode 100644
index 74cb2c32..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Audio_Scope.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-/* Copyright (C) 2005-2006 by Shay Green. Permission is hereby granted, free of
-charge, to any person obtaining a copy of this software module and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-int const step_bits = 8;
-int const step_unit = 1 << step_bits;
-int const erase_color = 1;
-int const draw_color = 2;
-
-Audio_Scope::Audio_Scope()
-{
- surface = 0;
- buf = 0;
-}
-
-Audio_Scope::~Audio_Scope()
-{
- free( buf );
-
- if ( surface )
- SDL_FreeSurface( surface );
-}
-
-const char* Audio_Scope::init( int width, int height )
-{
- assert( height <= 256 );
- assert( !buf ); // can only call init() once
-
- buf = (byte*) calloc( width * sizeof *buf, 1 );
- if ( !buf )
- return "Out of memory";
-
- low_y = 0;
- high_y = height;
- buf_size = width;
-
- for ( sample_shift = 6; sample_shift < 14; )
- if ( ((0x7FFFL * 2) >> sample_shift++) < height )
- break;
-
- v_offset = height / 2 - (0x10000 >> sample_shift);
-
- screen = SDL_SetVideoMode( width, height, 0, 0 );
- if ( !screen )
- return "Couldn't set video mode";
-
- surface = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0 );
- if ( !screen )
- return "Couldn't create surface";
-
- static SDL_Color palette [2] = { {0, 0, 0}, {0, 255, 0} };
- SDL_SetColors( surface, palette, 1, 2 );
-
- return 0; // success
-}
-
-const char* Audio_Scope::draw( const short* in, long count, double step )
-{
- int low = low_y;
- int high = high_y;
-
- if ( count >= buf_size )
- {
- count = buf_size;
- low_y = 0x7FFF;
- high_y = 0;
- }
-
- if ( SDL_LockSurface( surface ) < 0 )
- return "Couldn't lock surface";
- render( in, count, (long) (step * step_unit) );
- SDL_UnlockSurface( surface );
-
- if ( low > low_y )
- low = low_y;
-
- if ( high < high_y )
- high = high_y;
-
- SDL_Rect r;
- r.x = 0;
- r.w = buf_size;
- r.y = low + v_offset;
- r.h = high - low + 1;
-
- if ( SDL_BlitSurface( surface, &r, screen, &r ) < 0 )
- return "Blit to screen failed";
-
- if ( SDL_Flip( screen ) < 0 )
- return "Couldn't flip screen";
-
- return 0; // success
-}
-
-void Audio_Scope::render( short const* in, long count, long step )
-{
- byte* old_pos = buf;
- long surface_pitch = surface->pitch;
- byte* out = (byte*) surface->pixels + v_offset * surface_pitch;
- int old_erase = *old_pos;
- int old_draw = 0;
- long in_pos = 0;
-
- int low_y = this->low_y;
- int high_y = this->high_y;
- int half_step = (step + step_unit / 2) >> (step_bits + 1);
-
- while ( count-- )
- {
- // Line drawing/erasing starts at previous sample and ends one short of
- // current sample, except when previous and current are the same.
-
- // Extra read on the last iteration of line loops will always be at the
- // height of the next sample, and thus within the gworld bounds.
-
- // Erase old line
- {
- int delta = *old_pos - old_erase;
- int offset = old_erase * surface_pitch;
- old_erase += delta;
-
- int next_line = surface_pitch;
- if ( delta < 0 )
- {
- delta = -delta;
- next_line = -surface_pitch;
- }
-
- do
- {
- out [offset] = erase_color;
- offset += next_line;
- }
- while ( delta-- > 1 );
- }
-
- // Draw new line and put in old_buf
- {
-
- int in_whole = in_pos >> step_bits;
- int sample = (0x7FFF * 2 - in [in_whole] - in [in_whole + half_step]) >> sample_shift;
- if ( !in_pos )
- old_draw = sample;
- in_pos += step;
-
- int delta = sample - old_draw;
- int offset = old_draw * surface_pitch;
- old_draw += delta;
-
- int next_line = surface_pitch;
- if ( delta < 0 )
- {
- delta = -delta;
- next_line = -surface_pitch;
- }
-
- *old_pos++ = sample;
-
- // min/max updating can be interleved anywhere
-
- if ( low_y > sample )
- low_y = sample;
-
- do
- {
- out [offset] = draw_color;
- offset += next_line;
- }
- while ( delta-- > 1 );
-
- if ( high_y < sample )
- high_y = sample;
- }
-
- out++;
- }
-
- this->low_y = low_y;
- this->high_y = high_y;
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.h b/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.h
deleted file mode 100644
index 75334676..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/player/Audio_Scope.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Simple audio waveform scope in a window, using SDL multimedia library
-
-#ifndef AUDIO_SCOPE_H
-#define AUDIO_SCOPE_H
-
-#include "SDL.h"
-
-class Audio_Scope {
-public:
- typedef const char* error_t;
-
- // Initialize scope window of specified size. Height must be 256 or less.
- error_t init( int width, int height );
-
- // Draw at most 'count' samples from 'in', skipping 'step' samples after
- // each sample drawn. Step can be less than 1.0.
- error_t draw( const short* in, long count, double step = 1.0 );
-
- Audio_Scope();
- ~Audio_Scope();
-
-private:
- typedef unsigned char byte;
- SDL_Surface* screen;
- SDL_Surface* surface;
- byte* buf;
- int buf_size;
- int sample_shift;
- int low_y;
- int high_y;
- int v_offset;
-
- void render( short const* in, long count, long step );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.cpp b/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.cpp
deleted file mode 100644
index a39819f1..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
-
-#include "Music_Player.h"
-
-#include "gme/Music_Emu.h"
-
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2005-2006 by Shay Green. Permission is hereby granted, free of
-charge, to any person obtaining a copy of this software module and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#include "blargg_source.h"
-
-// Number of audio buffers per second. Adjust if you encounter audio skipping.
-const int fill_rate = 45;
-
-// Simple sound driver using SDL
-typedef void (*sound_callback_t)( void* data, short* out, int count );
-static const char* sound_init( long sample_rate, int buf_size, sound_callback_t, void* data );
-static void sound_start();
-static void sound_stop();
-static void sound_cleanup();
-
-Music_Player::Music_Player()
-{
- emu_ = 0;
- scope_buf = 0;
- paused = false;
-}
-
-blargg_err_t Music_Player::init( long rate )
-{
- sample_rate = rate;
-
- int min_size = sample_rate * 2 / fill_rate;
- int buf_size = 512;
- while ( buf_size < min_size )
- buf_size *= 2;
-
- return sound_init( sample_rate, buf_size, fill_buffer, this );
-}
-
-void Music_Player::stop()
-{
- sound_stop();
- delete emu_;
- emu_ = 0;
-}
-
-Music_Player::~Music_Player()
-{
- stop();
- sound_cleanup();
-}
-
-blargg_err_t Music_Player::load_file( const char* path )
-{
- stop();
-
- RETURN_ERR( gme_open_file( path, &emu_, sample_rate ) );
-
- char m3u_path [256 + 5];
- strncpy( m3u_path, path, 256 );
- m3u_path [256] = 0;
- char* p = strrchr( m3u_path, '.' );
- if ( !p )
- p = m3u_path + strlen( m3u_path );
- strcpy( p, ".m3u" );
- if ( emu_->load_m3u( m3u_path ) ) { } // ignore error
-
- return 0;
-}
-
-int Music_Player::track_count() const
-{
- return emu_ ? emu_->track_count() : false;
-}
-
-blargg_err_t Music_Player::start_track( int track )
-{
- if ( emu_ )
- {
- // Sound must not be running when operating on emulator
- sound_stop();
- RETURN_ERR( emu_->start_track( track ) );
-
- // Calculate track length
- if ( !emu_->track_info( &track_info_ ) )
- {
- if ( track_info_.length <= 0 )
- track_info_.length = track_info_.intro_length +
- track_info_.loop_length * 2;
- }
- if ( track_info_.length <= 0 )
- track_info_.length = (long) (2.5 * 60 * 1000);
- emu_->set_fade( track_info_.length );
-
- paused = false;
- sound_start();
- }
- return 0;
-}
-
-void Music_Player::pause( int b )
-{
- paused = b;
- if ( b )
- sound_stop();
- else
- sound_start();
-}
-
-void Music_Player::suspend()
-{
- if ( !paused )
- sound_stop();
-}
-
-void Music_Player::resume()
-{
- if ( !paused )
- sound_start();
-}
-
-bool Music_Player::track_ended() const
-{
- return emu_ ? emu_->track_ended() : false;
-}
-
-void Music_Player::set_stereo_depth( double tempo )
-{
- suspend();
- gme_set_stereo_depth( emu_, tempo );
- resume();
-}
-
-void Music_Player::set_tempo( double tempo )
-{
- suspend();
- emu_->set_tempo( tempo );
- resume();
-}
-
-void Music_Player::mute_voices( int mask )
-{
- suspend();
- emu_->mute_voices( mask );
- emu_->ignore_silence( mask != 0 );
- resume();
-}
-
-void Music_Player::fill_buffer( void* data, sample_t* out, int count )
-{
- Music_Player* self = (Music_Player*) data;
- if ( self->emu_ )
- {
- if ( self->emu_->play( count, out ) ) { } // ignore error
-
- if ( self->scope_buf )
- memcpy( self->scope_buf, out, self->scope_buf_size * sizeof *self->scope_buf );
- }
-}
-
-// Sound output driver using SDL
-
-#include "SDL.h"
-
-static sound_callback_t sound_callback;
-static void* sound_callback_data;
-
-static void sdl_callback( void* data, Uint8* out, int count )
-{
- if ( sound_callback )
- sound_callback( sound_callback_data, (short*) out, count / 2 );
-}
-
-static const char* sound_init( long sample_rate, int buf_size,
- sound_callback_t cb, void* data )
-{
- sound_callback = cb;
- sound_callback_data = data;
-
- static SDL_AudioSpec as; // making static clears all fields to 0
- as.freq = sample_rate;
- as.format = AUDIO_S16SYS;
- as.channels = 2;
- as.callback = sdl_callback;
- as.samples = buf_size;
- if ( SDL_OpenAudio( &as, 0 ) < 0 )
- {
- const char* err = SDL_GetError();
- if ( !err )
- err = "Couldn't open SDL audio";
- return err;
- }
-
- return 0;
-}
-
-static void sound_start()
-{
- SDL_PauseAudio( false );
-}
-
-static void sound_stop()
-{
- SDL_PauseAudio( true );
-
- // be sure audio thread is not active
- SDL_LockAudio();
- SDL_UnlockAudio();
-}
-
-static void sound_cleanup()
-{
- sound_stop();
- SDL_CloseAudio();
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.h b/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.h
deleted file mode 100644
index 7a573c45..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/player/Music_Player.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Simple game music file player
-
-// Game_Music_Emu 0.5.2
-#ifndef MUSIC_PLAYER_H
-#define MUSIC_PLAYER_H
-
-#include "gme/Music_Emu.h"
-
-class Music_Player {
-public:
- // Initialize player and set sample rate
- blargg_err_t init( long sample_rate = 44100 );
-
- // Load game music file. NULL on success, otherwise error string.
- blargg_err_t load_file( const char* path );
-
- // (Re)start playing track. Tracks are numbered from 0 to track_count() - 1.
- blargg_err_t start_track( int track );
-
- // Stop playing current file
- void stop();
-
-// Optional functions
-
- // Number of tracks in current file, or 0 if no file loaded.
- int track_count() const;
-
- // Info for current track
- track_info_t const& track_info() const { return track_info_; }
-
- // Pause/resume playing current track.
- void pause( int );
-
- // True if track ended
- bool track_ended() const;
-
- // Pointer to emulator
- Music_Emu* emu() const { return emu_; }
-
- // Set stereo depth, where 0.0 = none and 1.0 = maximum
- void set_stereo_depth( double );
-
- // Set tempo, where 0.5 = half speed, 1.0 = normal, 2.0 = double speed
- void set_tempo( double );
-
- // Set voice muting bitmask
- void mute_voices( int );
-
- // Set buffer to copy samples from each buffer into, or NULL to disable
- typedef short sample_t;
- void set_scope_buffer( sample_t* buf, int size ) { scope_buf = buf; scope_buf_size = size; }
-
-public:
- Music_Player();
- ~Music_Player();
-private:
- Music_Emu* emu_;
- sample_t* scope_buf;
- long sample_rate;
- int scope_buf_size;
- bool paused;
- track_info_t track_info_;
-
- void suspend();
- void resume();
- static void fill_buffer( void*, sample_t*, int );
-};
-
-#endif
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/player/player.cpp b/plugins/gme/Game_Music_Emu-0.5.2/player/player.cpp
deleted file mode 100644
index a0685997..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/player/player.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* How to play game music files with Music_Player (requires SDL library)
-
-Run program with path to a game music file.
-
-Left/Right Change track
-Space Pause/unpause
-E Normal/slight stereo echo/more stereo echo
--/= Adjust tempo
-1-9 Toggle channel on/off
-0 Reset tempo and turn channels back on */
-
-int const scope_width = 512;
-
-#include "Music_Player.h"
-#include "Audio_Scope.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "SDL.h"
-
-void handle_error( const char* );
-
-static bool paused;
-static Audio_Scope* scope;
-static Music_Player* player;
-static short scope_buf [scope_width * 2];
-
-static void init()
-{
- // Start SDL
- if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
- exit( EXIT_FAILURE );
- atexit( SDL_Quit );
- SDL_EnableKeyRepeat( 500, 80 );
-
- // Init scope
- scope = new Audio_Scope;
- if ( !scope )
- handle_error( "Out of memory" );
- if ( scope->init( scope_width, 256 ) )
- handle_error( "Couldn't initialize scope" );
- memset( scope_buf, 0, sizeof scope_buf );
-
- // Create player
- player = new Music_Player;
- if ( !player )
- handle_error( "Out of memory" );
- handle_error( player->init() );
- player->set_scope_buffer( scope_buf, scope_width * 2 );
-}
-
-static void start_track( int track, const char* path )
-{
- paused = false;
- handle_error( player->start_track( track - 1 ) );
-
- // update window title with track info
-
- long seconds = player->track_info().length / 1000;
- const char* game = player->track_info().game;
- if ( !*game )
- {
- // extract filename
- game = strrchr( path, '\\' ); // DOS
- if ( !game )
- game = strrchr( path, '/' ); // UNIX
- if ( !game )
- game = path;
- else
- game++; // skip path separator
- }
-
- char title [512];
- sprintf( title, "%s: %d/%d %s (%ld:%02ld)",
- game, track, player->track_count(), player->track_info().song,
- seconds / 60, seconds % 60 );
- SDL_WM_SetCaption( title, title );
-}
-
-int main( int argc, char** argv )
-{
- init();
-
- // Load file
- const char* path = (argc > 1 ? argv [argc - 1] : "test.nsf");
- handle_error( player->load_file( path ) );
- start_track( 1, path );
-
- // Main loop
- int track = 1;
- double tempo = 1.0;
- bool running = true;
- double stereo_depth = 0.0;
- int muting_mask = 0;
- while ( running )
- {
- SDL_Delay( 1000 / 100 );
-
- // Update scope
- scope->draw( scope_buf, scope_width, 2 );
-
- // Automatically go to next track when current one ends
- if ( player->track_ended() )
- {
- if ( track < player->track_count() )
- start_track( ++track, path );
- else
- player->pause( paused = true );
- }
-
- // Handle keyboard input
- SDL_Event e;
- while ( SDL_PollEvent( &e ) )
- {
- switch ( e.type )
- {
- case SDL_QUIT:
- running = false;
- break;
-
- case SDL_KEYDOWN:
- int key = e.key.keysym.sym;
- switch ( key )
- {
- case SDLK_q:
- case SDLK_ESCAPE: // quit
- running = false;
- break;
-
- case SDLK_LEFT: // prev track
- if ( !paused && !--track )
- track = 1;
- start_track( track, path );
- break;
-
- case SDLK_RIGHT: // next track
- if ( track < player->track_count() )
- start_track( ++track, path );
- break;
-
- case SDLK_MINUS: // reduce tempo
- tempo -= 0.1;
- if ( tempo < 0.1 )
- tempo = 0.1;
- player->set_tempo( tempo );
- break;
-
- case SDLK_EQUALS: // increase tempo
- tempo += 0.1;
- if ( tempo > 2.0 )
- tempo = 2.0;
- player->set_tempo( tempo );
- break;
-
- case SDLK_SPACE: // toggle pause
- paused = !paused;
- player->pause( paused );
- break;
-
- case SDLK_e: // toggle echo
- stereo_depth += 0.2;
- if ( stereo_depth > 0.5 )
- stereo_depth = 0;
- player->set_stereo_depth( stereo_depth );
- break;
-
- case SDLK_0: // reset tempo and muting
- tempo = 1.0;
- muting_mask = 0;
- player->set_tempo( tempo );
- player->mute_voices( muting_mask );
- break;
-
- default:
- if ( SDLK_1 <= key && key <= SDLK_9 ) // toggle muting
- {
- muting_mask ^= 1 << (key - SDLK_1);
- player->mute_voices( muting_mask );
- }
- }
- }
- }
- }
-
- // Cleanup
- delete player;
- delete scope;
-
- return 0;
-}
-
-void handle_error( const char* error )
-{
- if ( error )
- {
- // put error in window title
- char str [256];
- sprintf( str, "Error: %s", error );
- fprintf( stderr, str );
- SDL_WM_SetCaption( str, str );
-
- // wait for keyboard or mouse activity
- SDL_Event e;
- do
- {
- while ( !SDL_PollEvent( &e ) ) { }
- }
- while ( e.type != SDL_QUIT && e.type != SDL_KEYDOWN && e.type != SDL_MOUSEBUTTONDOWN );
-
- exit( EXIT_FAILURE );
- }
-}
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/readme.txt b/plugins/gme/Game_Music_Emu-0.5.2/readme.txt
deleted file mode 100644
index e3470bfa..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/readme.txt
+++ /dev/null
@@ -1,205 +0,0 @@
-Game_Music_Emu 0.5.2: Game Music Emulators
-------------------------------------------
-Game_Music_Emu is a collection of video game music file emulators that
-support the following formats and systems:
-
-AY ZX Spectrum/Amstrad CPC
-GBS Nintendo Game Boy
-GYM Sega Genesis/Mega Drive
-HES NEC TurboGrafx-16/PC Engine
-KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
-NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
-SAP Atari systems using POKEY sound chip
-SPC Super Nintendo/Super Famicom
-VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
-
-Features:
-* Can be used in C and C++ code
-* High emphasis has been placed on making the library very easy to use
-* One set of common functions work with all emulators the same way
-* Several code examples, including music player using SDL
-* Portable code for use on any system with modern or older C++ compilers
-* Adjustable output sample rate using quality band-limited resampling
-* Uniform access to text information fields and track timing information
-* End-of-track fading and automatic look ahead silence detection
-* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
-* Tempo can be adjusted and individual voices can be muted while playing
-* Can read music data from file, memory, or custom reader function/class
-* Can access track information without having to load into full emulator
-* M3U track listing support for multi-track formats
-* Modular design allows elimination of unneeded emulators/features
-
-This library has been used in game music players for Windows, Linux on
-several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
-GP2X, and Nintendo DS.
-
-Author : Shay Green <gblargg@gmail.com>
-Website: http://www.slack.net/~ant/
-Forum : http://groups.google.com/group/blargg-sound-libs
-License: GNU Lesser General Public License (LGPL)
-
-
-Getting Started
----------------
-Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
-all source files in gme/. Be sure "test.nsf" is in the same directory.
-Running the program should generate the recording "out.wav".
-
-Read gme.txt for more information. Post to the discussion forum for
-assistance.
-
-
-Files
------
-gme.txt General notes about the library
-changes.txt Changes made since previous releases
-design.txt Library design notes
-license.txt GNU Lesser General Public License
-
-test.nsf Test file for NSF emulator
-test.m3u Test m3u playlist for features.c demo
-
-demo/
- basics.c Records NSF file to wave sound file
- cpp_basics.cpp C++ version of basics.c
- features.c Demonstrates many additional features
- Wave_Writer.h WAVE sound file writer used for demo output
- Wave_Writer.cpp
-
-player/ Player using the SDL multimedia library
- player.cpp Simple music player with waveform display
- Music_Player.cpp Stand alone player for background music
- Music_Player.h
- Audio_Scope.cpp Audio waveform scope
- Audio_Scope.h
-
-gme/
- blargg_config.h Library configuration (modify this file as needed)
-
- gme.h C interface (also usable in C++, and simpler too)
- gme.cpp
-
- Gme_File.h File loading and track information
- Music_Emu.h Track playback and adjustments
- Data_Reader.h Custom data readers
-
- Effects_Buffer.h Sound buffer with stereo echo and panning
- Effects_Buffer.cpp
-
- M3u_Playlist.h M3U playlist support
- M3u_Playlist.cpp
-
- Ay_Emu.h ZX Spectrum AY emulator
- Ay_Emu.cpp
- Ay_Apu.cpp
- Ay_Apu.h
- Ay_Cpu.cpp
- Ay_Cpu.h
-
- Gbs_Emu.h Nintendo Game Boy GBS emulator
- Gbs_Emu.cpp
- Gb_Apu.cpp
- Gb_Apu.h
- Gb_Cpu.cpp
- Gb_Cpu.h
- gb_cpu_io.h
- Gb_Oscs.cpp
- Gb_Oscs.h
-
- Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
- Hes_Apu.cpp
- Hes_Apu.h
- Hes_Cpu.cpp
- Hes_Cpu.h
- hes_cpu_io.h
- Hes_Emu.cpp
-
- Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
- Kss_Emu.cpp
- Kss_Cpu.cpp
- Kss_Cpu.h
- Kss_Scc_Apu.cpp
- Kss_Scc_Apu.h
- Ay_Apu.h
- Ay_Apu.cpp
- Sms_Apu.h
- Sms_Apu.cpp
- Sms_Oscs.h
-
- Nsf_Emu.h Nintendo NES NSF/NSFE emulator
- Nsf_Emu.cpp
- Nes_Apu.cpp
- Nes_Apu.h
- Nes_Cpu.cpp
- Nes_Cpu.h
- nes_cpu_io.h
- Nes_Oscs.cpp
- Nes_Oscs.h
- Nes_Fme7_Apu.cpp
- Nes_Fme7_Apu.h
- Nes_Namco_Apu.cpp
- Nes_Namco_Apu.h
- Nes_Vrc6_Apu.cpp
- Nes_Vrc6_Apu.h
- Nsfe_Emu.h NSFE support
- Nsfe_Emu.cpp
-
- Spc_Emu.h Super Nintendo SPC emulator
- Spc_Emu.cpp
- Snes_Spc.cpp
- Snes_Spc.h
- Spc_Cpu.cpp
- Spc_Cpu.h
- Spc_Dsp.cpp
- Spc_Dsp.h
- Fir_Resampler.cpp
- Fir_Resampler.h
-
- Sap_Emu.h Atari SAP emulator
- Sap_Emu.cpp
- Sap_Apu.cpp
- Sap_Apu.h
- Sap_Cpu.cpp
- Sap_Cpu.h
- sap_cpu_io.h
-
- Vgm_Emu.h Sega VGM emulator
- Vgm_Emu_Impl.cpp
- Vgm_Emu_Impl.h
- Vgm_Emu.cpp
- Ym2413_Emu.cpp
- Ym2413_Emu.h
- Gym_Emu.h Sega Genesis GYM emulator
- Gym_Emu.cpp
- Sms_Apu.cpp Common Sega emulator files
- Sms_Apu.h
- Sms_Oscs.h
- Ym2612_Emu.cpp
- Ym2612_Emu.h
- Dual_Resampler.cpp
- Dual_Resampler.h
- Fir_Resampler.cpp
- Fir_Resampler.h
-
- blargg_common.h Common files needed by all emulators
- blargg_endian.h
- blargg_source.h
- Blip_Buffer.cpp
- Blip_Buffer.h
- Gme_File.cpp
- Music_Emu.cpp
- Classic_Emu.h
- Classic_Emu.cpp
- Multi_Buffer.h
- Multi_Buffer.cpp
- Data_Reader.cpp
-
-
-Legal
------
-Game_Music_Emu library copyright (C) 2003-2006 Shay Green.
-SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin.
-Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
-
---
-Shay Green <gblargg@gmail.com>
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/test.m3u b/plugins/gme/Game_Music_Emu-0.5.2/test.m3u
deleted file mode 100644
index fd46bfe1..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/test.m3u
+++ /dev/null
@@ -1,2 +0,0 @@
-# filename,track number,track name,track time
-test.nsf,$00,BGM C,1:16
diff --git a/plugins/gme/Game_Music_Emu-0.5.2/test.nsf b/plugins/gme/Game_Music_Emu-0.5.2/test.nsf
deleted file mode 100644
index da5fcedd..00000000
--- a/plugins/gme/Game_Music_Emu-0.5.2/test.nsf
+++ /dev/null
Binary files differ
diff --git a/plugins/gme/game-music-emu-0.5.5/changes.txt b/plugins/gme/game-music-emu-0.5.5/changes.txt
deleted file mode 100644
index f3038387..00000000
--- a/plugins/gme/game-music-emu-0.5.5/changes.txt
+++ /dev/null
@@ -1,225 +0,0 @@
-Game_Music_Emu Change Log
--------------------------
-
-Game_Music_Emu 0.5.5
---------------------
-- CMake build support has been added. You can build Game_Music_Emu as
-a shared library and install it so that you do not have to include your
-own copy if you know libgme will be present on your target system.
-Requires CMake 2.6 or higher.
-
-Game_Music_Emu 0.5.2
---------------------
-- *TONS* of changes and improvements. You should re-read the new header
-files and documentation as the changes will allow you to simplify your
-code a lot (it might even be simpler to just rewrite it). Existing code
-should continue to work without changes in most cases (see Deprecated
-features in gme.txt).
-
-- New file formats: AY, HES, KSS, SAP, NSFE
-
-- All-new comprehensive C interface (also usable from C++). Simplifies
-many things, especially file loading, and brings everything together in
-one header file (gme.h).
-
-- Information tags and track names and times can be accessed for all
-game music formats
-
-- New features supported by all emulators: end of track fading,
-automatic silence detection, adjustable song tempo, seek to new time in
-track
-
-- Updated mini player example to support track names and times, echo,
-tempo, and channel muting, and added visual waveform display
-
-- Improved configuration to use blargg_config.h, which you can modify
-and keep when you update to a newer libary version. Includes flag for
-library to automatically handle gzipped files using zlib (so you don't
-need to use Gzip_File_Reader anymore).
-
-- GBS: Fixed wave channel to not reset waveform when APU is powered off
-(affected Garfield). Also improved invalid bank selection (affected Game
-& Watch and others).
-
-- VGM: Added support for alternate noise shifter register
-configurations, used by other systems like the BBC Micro.
-
-- SPC: Removed IPL ROM dump from emulator, as none of the SPC files I
-scanned needed it, and an SPC file can include a copy if necessary. Also
-re-enabled supposed clamping in gaussian interpolation between the third
-and fourth lookups, though I don't know whether it matters
-
-- Added Music_Emu::load_mem() to use music data already in memory
-(without copying it)
-
-- Added Music_Emu::warning(), which reports minor problems when loading
-and playing a music file
-
-- Added Music_Emu::set_gain() for uniform adjustment of gain. Can only
-be set during initialization, so not useful as a general volume control.
-
-- Added custom operator new to ensure that no exceptions are thrown in
-the library (I'd use std::nothrow if it were part of pre-ISO (ARM) C++)
-
-- Added BLIP_BUFFER_FAST flag to blargg_config.h to use a lower quality
-bandlimited synthesis in "classic" emulators, which might help
-performance on ancient processors (measure first!). Don't use this
-unless absolutely necessary, as quality suffers.
-
-- Improved performance a bit for x86 platforms
-
-- Text files now in DOS newline format so they will open in Notepad
-properly
-
-- Removed requirement that file header structures not have any padding
-added to the end
-
-- Fixed common bug in all CPU emulators where negative program counter
-could crash emulator (occurred during a negative branch from the
-beginning of memory). Also fixed related bug in Z80 emulator for
-IX/IY+displacement mode.
-
-- Eliminated all warnings when compiling on gcc 4.0. The following
-generates no diagnostics:
-
- gcc -S gme/*.cpp -o /dev/null -ansi -fno-gnu-keywords
- -fno-nonansi-builtins -pedantic -W -Wabi -Wall -Wcast-align
- -Wcast-qual -Wchar-subscripts -Wdisabled-optimization -Werror
- -Winline -Wlong-long -Wmultichar -Winvalid-offsetof
- -Wnon-virtual-dtor -Woverloaded-virtual -Wparentheses
- -Wpointer-arith -Wredundant-decls -Wreorder -Wsign-compare
- -Wsign-promo -Wunknown-pragmas -Wwrite-strings
-
-
-Game_Music_Emu 0.3.0
---------------------
-- Added more demos, including music player using the SDL multimedia
-library for sound, and improved documentation
-
-- All: Improved interface to emulators to allow simpler setup and
-loading. Instead of various init() functions, all now support
-set_sample_rate( long rate ) and load( const char* file_path ).
-
-- All: Removed error return from start_track() and play(), and added
-error_count() to get the total number of emulation errors since the
-track was last started. See demos for examples of new usage.
-
-- All: Fixed mute_voices() muting to be preserved after loading files
-and starting tracks, instead of being cleared as it was whenever a track
-was started
-
-- VGM: Rewrote Vgm_Emu to support Sega Genesis/Mega Drive FM sound at
-any sample rate with optional FM oversampling, support for alternate
-YM2612 sound cores, and support for optional YM2413
-
-- VGM: Added tempo control, useful for slowing 60Hz NTSC Sega Genesis
-music to 50Hz PAL
-
-- VGM: Removed Vgm_Emu::track_data(), since I realized that this
-information is already present in the VGM header (oops!)
-
-- GYM: Changed Gym_Emu::track_length() operation (see Gym_Emu.h)
-
-- NSF: Added support for Sunsoft FME-7 sound chip used by Gimmick
-soundtrack
-
-- NSF: Fixed Namco 106 problems with Final Lap and others
-
-- Moved library sources to gme/ directory to reduce clutter, and merged
-boost/ functionality into blargg_common.h
-
-- Added Gzip_File_Reader for transparently using gzipped files
-
-
-Game_Music_Emu 0.2.4
---------------------
-- Created a discussion forum for problems and feedback:
-http://groups-beta.google.com/group/blargg-sound-libs
-
-- Changed error return value of Blip_Buffer::sample_rate() (also for
-Stereo_Buffer, Effects_Buffer, etc.) to blargg_err_t (defined in
-blargg_common.h), to make error reporting consistent with other
-functions. This means the "no error" return value is the opposite of
-what it was before, which will break current code which checks the error
-return value:
-
- // current code (broken)
- if ( !buf.sample_rate( samples_per_sec ) )
- out_of_memory();
-
- // quick-and-dirty fix (just remove the ! operation)
- if ( buf.sample_rate( samples_per_sec ) )
- out_of_memory();
-
- // proper fix
- blargg_err_t error = buf.sample_rate( samples_per_sec );
- if ( error )
- report_error( error );
-
-- Implemented workaround for MSVC++ 6 compiler limitations, allowing it
-to work on that compiler again
-
-- Added sample clamping to avoid wrap-around at high volumes, allowing
-higher volume with little distortion
-
-- Added to-do list and design notes
-
-- Added Music_Emu::skip( long sample_count ) to skip ahead in current
-track
-
-- Added Gym_Emu::track_length() and Vgm_Emu::track_length() for
-determining the length of non-looped GYM and VGM files
-
-- Partially implemented DMC non-linearity when its value is directly set
-using $4011, which reduces previously over-emphasized "popping" of
-percussion on some games (TMNT II in particular)
-
-- Fixed Fir_Resampler, used for SPC and GYM playback (was incorrectly
-using abs() instead of fabs()...argh)
-
-- Fixed SPC emulation bugs: eliminated clicks in Plok! soundtrack and
-now stops sample slightly earlier than the end, as the SNES does. Fixed
-a totally broken CPU addressing mode.
-
-- Fixed Konami VRC6 saw wave (was very broken before). Now VRC6 music
-sounds decent
-
-- Fixed a minor GBS emulation bug
-
-- Fixed GYM loop point bug when track was restarted before loop point
-had been reached
-
-- Made default GBS frequency equalization less muffled
-
-- Added pseudo-surround effect removal for SPC files
-
-- Added Music_Emu::voice_names() which returns names for each voice.
-
-- Added BLARGG_SOURCE_BEGIN which allows custom compiler options to be
-easily set for library sources
-
-- Changed assignment of expansion sound chips in Nsf_Emu to be spread
-more evenly when using Effects_Buffer
-
-- Changed 'size_t' values in Blip_Buffer interface to 'long'
-
-- Changed demo to generate a WAVE sound file rather than an AIFF file
-
-
-Game_Music_Emu 0.2.0
---------------------
-- Redid framework and rewrote/cleaned up emulators
-
-- Changed licensing to GNU Lesser General Public License (LGPL)
-
-- Added Sega Genesis GYM and Super Nintendo SPC emulators
-
-- Added Namco-106 and Konami VRC6 sound chip support to NSF emulator
-
-- Eliminated use of static mutable data in emulators, allowing
-multi-instance safety
-
-
-Game_Music_Emu 0.1.0
---------------------
-- First release
diff --git a/plugins/gme/game-music-emu-0.5.5/design.txt b/plugins/gme/game-music-emu-0.5.5/design.txt
deleted file mode 100644
index 8c8c65b1..00000000
--- a/plugins/gme/game-music-emu-0.5.5/design.txt
+++ /dev/null
@@ -1,194 +0,0 @@
-Game_Music_Emu 0.5.2 Design
----------------------------
-This might be slightly out-of-date at times, but will be a big help in
-understanding the library implementation.
-
-
-Architecture
-------------
-The library is essentially a bunch of independent game music file
-emulators unified with a common interface.
-
-Gme_File and Music_Emu provide a common interface to the emulators. The
-virtual functions are protected rather than public to allow pre- and
-post-processing of arguments and data in one place. This allows the
-emulator classes to assume that everything is set up properly when
-starting a track and playing samples.
-
-All file input is done with the Data_Reader interface. Many derived
-classes are present, for the usual disk-based file and block of memory,
-to specialized adaptors for things like reading a subset of data or
-combining a block of memory with a Data_Reader to the remaining data.
-This makes the library much more flexible with regard to the source of
-game music file data. I still added a specialized load_mem() function to
-have the emulator keep a pointer to data already read in memory, for
-those formats whose files can be absolutely huge (GYM, some VGMs). This
-is important if for some reason the caller must load the data ahead of
-time, but doesn't want the emulator needlessly making a copy.
-
-Since silence checking and fading are relatively complex, they are kept
-separate from basic file loading and track information, which are
-handled in the base class Gme_File. My original intent was to use
-Gme_File as the common base class for full emulators and track
-information-only readers, but implementing the C interface was much
-simpler if both derived from Music_Emu. User C++ code can still benefit
-from static checking by using Gme_File where only track information will
-be accessed.
-
-Each emulator generally has three components: main emulator, CPU
-emulator, and sound chip emulator(s). Each component has minimal
-coupling, so use in a full emulator or stand alone is fairly easy. This
-modularity really helps reduce complexity. Blip_Buffer helps a lot with
-simplifying the APU interfaces and implementation.
-
-The "classic" emulators derive from Classic_Emu, which handles
-Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
-output, allowing you to derive a custom buffer that could output each
-voice to a separate sound channel and do different processing on each.
-At some point I'm going to implement a better Effects_Buffer that allows
-individual control of every channel.
-
-In implementing the C interface, I wanted a way to specify an emulator
-type that didn't require linking in all the emulators. For each emulator
-type there is a global object with pointers to functions to create the
-emulator or a track information reader. The emulator type is thus a
-pointer to this, which conveniently allows for a NULL value. The user
-referencing this emulator type object is what ultimately links the
-emulator in (unless new Foo_Emu is used in C++, of course). This type
-also serves as a useful substitute for RTTI on older C++ compilers.
-
-Addendum: I have since added gme_type_list(), which causes all listed
-emulators to be linked in. To avoid this, I make the list itself
-editable in blargg_config.h. Having a built-in list allows
-gme_load_file() to take a path and give back an emulator with the file
-loaded, which is extremely useful for new users.
-
-
-Interface conventions
-----------------------
-If a function retains a pointer to or replaces the value of an object
-passed, it takes a pointer so that it will be clear in the caller's
-source code that care is required.
-
-Multi-word names have an underscore '_' separator between individual
-words.
-
-Functions are named with lowercase words. Functions which perform an
-action with side-effects are named with a verb phrase (i.e. load, move,
-run). Functions which return the value of a piece of state are named
-using a noun phrase (i.e. loaded, moved, running).
-
-Classes are named with capitalized words. Only the first letter of an
-acronym is capitalized. Class names are nouns, sometimes suggestive of
-what they do (i.e. File_Scanner).
-
-Structure, enumeration, and typedefs to these and built-in types are
-named using lowercase words with a _t suffix.
-
-Macros are named with all-uppercase words.
-
-Internal names which can't be hidden due to technical reasons have an
-underscore '_' suffix.
-
-
-Managing Complexity
--------------------
-Complexity has been a factor in most library decisions. Many features
-have been passed by due to the complexity they would add. Once
-complexity goes past a certain level, it mentally grasping the library
-in its entirety, at which point more defects will occur and be hard to
-find.
-
-I chose 16-bit signed samples because it seems to be the most common
-format. Supporting multiple formats would add too much complexity to be
-worth it. Other formats can be obtained via conversion.
-
-I've kept interfaces fairly lean, leaving many possible features
-untapped but easy to add if necessary. For example the classic emulators
-could have volume and frequency equalization adjusted separately for
-each channel, since they each have an associated Blip_Synth.
-
-Source files of 400 lines or less seem to be the best size to limit
-complexity. In a few cases there is no reasonable way to split longer
-files, or there is benefit from having the source together in one file.
-
-
-Preventing Bugs
----------------
-I've done many things to reduce the opportunity for defects. A general
-principle is to write code so that defects will be as visible as
-possible. I've used several techniques to achieve this.
-
-I put assertions at key points where defects seem likely or where
-corruption due to a defect is likely to be visible. I've also put
-assertions where violations of the interface are likely. In emulators
-where I am unsure of exact hardware operation in a particular case, I
-output a debug-only message noting that this has occurred; many times I
-haven't implemented a hardware feature because nothing uses it. I've
-made code brittle where there is no clear reason flexibility; code
-written to handle every possibility sacrifices quality and reliability
-to handle vaguely defined situations.
-
-
-Flexibility through indirection
--------------------------------
-I've tried to allow the most flexibility of modules by using indirection
-to allow extension by the user. This keeps each module simpler and more
-focused on its unique task.
-
-The classic emulators use Multi_Buffer, which potentially allows a
-separate Blip_Buffer for each channel. This keeps emulators free of
-typical code to allow output in mono, stereo, panning, etc.
-
-All emulators use a reader object to access file data, allowing it to be
-stored in a regular file, compressed archive, memory, or generated
-on-the-fly. Again, the library can be kept free of the particulars of
-file access and changes required to support new formats.
-
-
-Emulators in general
---------------------
-When I wrote the first NES sound emulator, I stored most of the state in
-an emulator-specific format, with significant redundancy. In the
-register write function I decoded everything into named variables. I
-became tired of the verbosity and wanted to more closely model the
-hardware, so I moved to a style of storing the last written value to
-each register, along with as little other state as possible, mostly the
-internal hardware registers. While this involves slightly more
-recalculation, in most cases the emulation code is of comparable size.
-It also makes state save/restore (for use in a full emulator) much
-simpler. Finally, it makes debugging easier since the hardware registers
-used in emulation are obvious.
-
-
-CPU Cores
----------
-I've spent lots of time coming up with techniques to optimize the CPU
-cores. Some of the most important: execute multiple instructions during
-an emulation call, keep state in local variables to allow register
-assignment, optimize state representation for most common instructions,
-defer status flag calculation until actually needed, read program code
-directly without a call to the memory read function, always pre-fetch
-the operand byte before decoding instruction, and emulate instructions
-using common blocks of code.
-
-I've successfully used Nes_Cpu in a fairly complete NES emulator, and
-I'd like to make all the CPU emulators suitable for use in emulators. It
-seems a waste for them to be used only for the small amount of emulation
-necessary for game music files.
-
-I debugged the CPU cores by writing a test shell that ran them in
-parallel with other CPU cores and compared all memory accesses and
-processor states at each step. This provided good value at little cost.
-
-The CPU mapping page size is adjustable to allow the best tradeoff
-between memory/cache usage and handler granularity. The interface allows
-code to be somewhat independent of the page size.
-
-I optimize program memory accesses to direct reads rather than calls to
-the memory read function. My assumption is that it would be difficult to
-get useful code out of hardware I/O addresses, so no software will
-intentionally execute out of I/O space. Since the page size can be
-changed easily, most program memory mapping schemes can be accommodated.
-This greatly reduces memory access function calls.
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme.txt b/plugins/gme/game-music-emu-0.5.5/gme.txt
deleted file mode 100644
index ca3da769..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme.txt
+++ /dev/null
@@ -1,464 +0,0 @@
-Game_Music_Emu 0.5.5
---------------------
-Author : Shay Green <gblargg@gmail.com>
-Website: http://www.slack.net/~ant/libs/
-Forum : http://groups.google.com/group/blargg-sound-libs
-License: GNU Lesser General Public License (LGPL)
-
-Contents
---------
-* Overview
-* C and C++ interfaces
-* Function reference
-* Error handling
-* Emulator types
-* M3U playlist support
-* Information fields
-* Track length
-* Loading file data
-* Sound parameters
-* VGM/GYM YM2413 & YM2612 FM sound
-* Modular construction
-* Obscure features
-* Solving problems
-* Deprecated features
-* Thanks
-
-
-Overview
---------
-This library can open game music files, play tracks, and read game and
-track information tags. To play a game music file, do the following:
-
-* Open the file with gme_open_file()
-* Start a track with gme_start_track();
-* Generate samples as needed with gme_play()
-* Play samples through speaker using your operating system
-* Delete emulator when done with gme_delete()
-
-Your code must arrange for the generated samples to be played through
-the computer's speaker using whatever method your operating system
-requires.
-
-There are many additional features available; you can:
-
-* Determine of the type of a music file without opening it with
-gme_identify_*()
-* Load just the file's information tags with gme_info_only
-* Load from a block of memory rather than a file with gme_load_data()
-* Arrange for a fade-out at a particular time with gme_set_fade
-* Find when a track has ended with gme_track_ended()
-* Seek to a new time in the track with gme_seek()
-* Load an extended m3u playlist with gme_load_m3u()
-* Get a list of the voices (channels) and mute them individually with
-gme_voice_names() and gme_mute_voice()
-* Change the playback tempo without affecting pitch with gme_set_tempo()
-* Adjust treble/bass equalization with gme_set_equalizer()
-* Associate your own data with an emulator and later get it back with
-gme_set_user_data()
-* Register a function of yours to be called back when the emulator is
-deleted with gme_set_user_cleanup()
-
-Refer to gme.h for a comprehensive summary of features.
-
-
-C and C++ interfaces
---------------------
-While the library is written in C++, an extensive C interface is
-provided in gme.h. This C interface will be referred to throughout this
-documentation unless a feature is only available in the full C++
-interface. All C interface functions and other names have the gme_
-prefix, so you can recognize a C++-only feature by the lack of gme_ in
-the names used (contact me if you'd like a feature added to the C
-interface). If you're building a shared library, I highly recommend
-sticking to the C interface only, because it will be more stable between
-releases of the library than the C++ interface. Finally, the C and C++
-interfaces can be freely mixed without problems. Compare demo/basics.c
-with demo/cpp_basics.cpp to see how the C and C++ interfaces translate
-between each other.
-
-
-Function reference
-------------------
-Read the following header files for a complete reference to functions
-and features. The second group of header files can only be used in C++.
-
-blargg_config.h Library configuration
-gme.h C interface (also usable from C++)
-
-Gme_File.h File loading and track information
-Music_Emu.h Track playback and adjustments
-Data_Reader.h Custom data readers
-Effects_Buffer.h Sound buffer with adjustable stereo echo and panning
-M3u_Playlist.h M3U playlist support
-Gbs_Emu.h GBS equalizer settings
-Nsf_Emu.h NSF equalizer settings
-Spc_Emu.h SPC surround disable
-Vgm_Emu.h VGM oversampling disable and custom buffer query
-
-
-Error handling
---------------
-Functions which can fail have a return type of gme_err_t (blargg_err_t
-in the C++ interfaces), which is a pointer to an error string (const
-char*). If a function is successful it returns NULL. Errors that you can
-easily avoid are checked with debug assertions; gme_err_t return values
-are only used for genuine run-time errors that can't be easily predicted
-in advance (out of memory, I/O errors, incompatible file data). Your
-code should check all error values.
-
-To improve usability for C programmers, C++ programmers unfamiliar with
-exceptions, and compatibility with older C++ compilers, the library does
-*not* throw any C++ exceptions and uses malloc() instead of the standard
-operator new. This means that you *must* check for NULL when creating a
-library object with the new operator.
-
-When loading a music file in the wrong emulator or trying to load a
-non-music file, gme_wrong_file_type is returned. You can check for this
-error in C++ like this:
-
- gme_err_t err = gme_open_file( path, &emu );
- if ( err == gme_wrong_file_type )
- ...
-
-To check for minor problems, call gme_warning() to get a string
-describing the last warning. Your player should allow the user some way
-of knowing when this is the case, since these minor errors could affect
-playback. Without this information the user can't solve problems as
-well. When playing a track, gme_warning() returns minor playback-related
-problems (major playback problems end the track immediately and set the
-warning string).
-
-
-Emulator types
---------------
-The library includes several game music emulators that each support a
-different file type. Each is identified by a gme_type_t constant defined
-in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
-gme_open_file() or gme_open_data(), the library does the work of
-determining the file type and creating an appropriate emulator. If you
-want more control over this process, read on.
-
-There are two basic ways to identify a game music file's type: look at
-its file extension, or read the header data. The library includes
-functions to help with both methods. The first is preferable because it
-is fast and the most common way to identify files. Sometimes the
-extension is lost or wrong, so the header must be read.
-
-Use gme_identify_extension() to find the correct game music type based
-on a filename. To identify a file based on its extension and header
-contents, use gme_identify_file(). If you read the header data yourself,
-use gme_identify_header().
-
-If you want to remove support for some music types to reduce your
-executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
-support just NSF and GBS, use this:
-
- #define GME_TYPE_LIST gme_nsf_type, gme_gbs_type
-
-
-M3U playlist support
---------------------
-The library supports playlists in an extended m3u format with
-gme_load_m3u() to give track names and times to multi-song formats: AY,
-GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
-itself is not well-defined so some m3u files won't work properly
-(particularly those provided with KSS files). Only m3u files referencing
-a single file are supported; your code must handle m3u files covering
-more than one game music file, though it can use the built-in m3u
-parsing provided by the library.
-
-
-Information fields
-------------------
-Support is provided for the various text fields and length information
-in a file with gme_track_info(). If you just need track information for
-a file (for example, building a playlist), use gme_new_info() in place
-of gme_new_emu(), load the file normally, then you can access the track
-count and info, but nothing else.
-
- M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
- -------------------------------------------------------
-Track Count | * * * * * * * * *
- |
-System | * * * * * * * * * *
- |
-Game | * * * * * * *
- |
-Song | * * * * * * *
- |
-Author | * * * * * * * *
- |
-Copyright | * * * * * * * *
- |
-Comment | * * * *
- |
-Dumper | * * * *
- |
-Length | * * * * * *
- |
-Intro Length| * * *
- |
-Loop Length | * * *
-
-As listed above, the HES and KSS file formats don't include a track
-count, and tracks are often scattered over the 0-255 range, so an m3u
-playlist for these is a must.
-
-Unavailable text fields are set to an empty string and times to -1. Your
-code should be prepared for any combination of available and unavailable
-fields, as a particular music file might not use all of the supported
-fields listed above.
-
-Currently text fields are truncated to 255 characters. Obscure fields of
-some formats are not currently decoded; contact me if you want one
-added.
-
-
-Track length
-------------
-The library leaves it up to you as to when to stop playing a track. You
-can ask for available length information and then tell the library what
-time it should start fading the track with gme_set_fade(). By default it
-also continually checks for 6 or more seconds of silence to mark the end
-of a track. Here is a reasonable algorithm you can use to decide how
-long to play a track:
-
-* If the track length is > 0, use it
-* If the loop length > 0, play for intro + loop * 2
-* Otherwise, default to 2.5 minutes (150000 msec)
-
-If you want to play a track longer than normal, be sure the loop length
-isn't zero. See Music_Player.cpp around line 145 for example code.
-
-By default, the library skips silence at the beginning of a track. It
-also continually checks for the end of a non-looping track by watching
-for 6 seconds of unbroken silence. When doing this is scans *ahead* by
-several seconds so it can report the end of the track after only one
-second of silence has actually played. This feature can be disabled with
-gme_ignore_silence().
-
-
-Loading file data
------------------
-The library allows file data to be loaded in many different ways. All
-load functions return an error which you should check. The following
-examples assume these variables:
-
- Music_Emu* emu;
- gme_err_t error;
-
-If you're letting the library determine a file's type, you can use
-either gme_open_file() or gme_open_data():
-
- error = gme_open_file( pathname, &emu );
- error = gme_open_data( pointer, size, &emu );
-
-If you're manually determining file type and using used gme_new_emu() to
-create an emulator, you can use the following methods of loading:
-
-* From a block of memory:
-
- error = gme_load_data( emu, pointer, size );
-
-* Have library call your function to read data:
-
- gme_err_t my_read( void* my_data, void* out, long count )
- {
- // code that reads 'count' bytes into 'out' buffer
- // and return 0 if no error
- }
-
- error = gme_load_custom( emu, my_read, file_size, my_data );
-
-* If you must load the file data into memory yourself, you can have the
-library use your data directly *without* making a copy. If you do this,
-you must not free the data until you're done playing the file.
-
- error = emu->load_mem( pointer, size );
-
-* If you've already read the first bytes of a file (perhaps to determine
-the file type) and want to avoid seeking back to the beginning for
-performance reasons, use Remaining_Reader:
-
- Std_File_Reader in;
- error = in.open( file_path );
-
- char header [4];
- error = in.read( &header, sizeof header );
- ...
-
- Remaining_Reader rem( &header, sizeof header, &in );
- error = emu->load( rem );
-
-If you merely need access to a file's header after loading, use the
-emulator-specific header() functions, after casting the Music_Emu
-pointer to the specific emulator's type. This example examines the
-chip_flags field of the header if it's an NSF file:
-
- if ( music_emu->type() == gme_nsf_type )
- {
- Nsf_Emu* nsf_emu = (Nsf_Emu*) music_emu;
- if ( nsf_emu->header().chip_flags & 0x01 )
- ...
- }
-
-Contact me if you want more information about loading files.
-
-
-Sound parameters
-----------------
-All emulators support an arbitrary output sampling rate. A rate of 44100
-Hz should work well on most systems. Since band-limited synthesis is
-used, a sampling rate above 48000 Hz is not necessary and will actually
-reduce sound quality and performance.
-
-All emulators also support adjustable gain, mainly for the purpose of
-getting consistent volume between different music formats and avoiding
-excessive modulation. The gain can only be set *before* setting the
-emulator's sampling rate, so it's not useful as a general volume
-control. The default gains of emulators are set so that they give
-generally similar volumes, though some soundtracks are significantly
-louder or quieter than normal.
-
-Some emulators support adjustable treble and bass frequency equalization
-(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
-Parameters are specified using gme_equalizer_t eq = { treble_dB,
-bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
-normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
-for an extra crisp sound. Bass_freq sets the frequency where bass
-response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
-and 15000 Hz removes all bass. For example, the following makes the
-sound extra-crisp but lacking bass:
-
- gme_equalizer_t eq = { 5.0, 1000 };
- gme_set_equalizer( music_emu, &eq );
-
-Each emulator's equalization defaults to approximate the particular
-console's sound quality; this default can be determined by calling
-equalizer() just after creating the emulator. The Music_Emu::tv_eq
-profile gives sound as if coming from a TV speaker, and some emulators
-include other profiles for different versions of the system. For
-example, to use Famicom sound equalization with the NSF emulator, do the
-following:
-
- music_emu->set_equalizer( Nsf_Emu::famicom_eq );
-
-
-VGM/GYM YM2413 & YM2612 FM sound
---------------------------------
-The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
-chip emulator based on the Gens project. Because this has some
-inaccuracies, other YM2612 emulators can be used in its place by
-re-implementing the interface in YM2612_Emu.h. Available on my website
-is a modified version of MAME's YM2612 emulator, which sounds better in
-some ways and whose author is still making improvements.
-
-VGM music files using the YM2413 FM sound chip are also supported, but a
-YM2413 emulator isn't included with the library due to technical
-reasons. I have put one of the available YM2413 emulators on my website
-that can be used directly.
-
-
-Modular construction
---------------------
-The library is made of many fairly independent modules. If you're using
-only one music file emulator, you can eliminate many of the library
-sources from your program. Refer to the files list in readme.txt to get
-a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
-(see "Emulator types" above). Post to the forum if you'd like me to put
-together a smaller version for a particular use, as this only takes me a
-few minutes to do.
-
-If you want to use one of the individual sound chip emulators (or CPU
-cores) in your own console emulator, first check the libraries page on
-my website since I have released several of them as stand alone
-libraries with included documentation and examples on their use. If you
-don't find it as a standalone library, contact me and I'll consider
-separating it.
-
-The "classic" sound chips use my Blip_Buffer library, which greatly
-simplifies their implementation and efficiently handles band-limited
-synthesis. It is also available as a stand alone library with
-documentation and many examples.
-
-
-Obscure features
-----------------
-The library's flexibility allows many possibilities. Contact me if you
-want help implementing ideas or removing limitations.
-
-* Uses no global/static variables, allowing multiple instances of any
-emulator. This is useful in a music player if you want to allow
-simultaneous recording or scanning of other tracks while one is already
-playing. This will also be useful if your platform disallows global
-data.
-
-* Emulators that support a custom sound buffer can have *every* voice
-routed to a different Blip_Buffer, allowing custom processing on each
-voice. For example you could record a Game Boy track as a 4-channel
-sound file.
-
-* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
-synthesis on "classic" emulators, which might help on some really old
-processors. This significantly lowers sound quality and prevents treble
-equalization. Try this if your platform's processor isn't fast enough
-for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
-processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
-the quality loss.
-
-
-Solving problems
-----------------
-If you're having problems, try the following:
-
-* If you're getting garbled sound, try this simple siren generator in
-place of your call to play(). This will quickly tell whether the problem
-is in the library or in your code.
-
- static void play_siren( long count, short* out )
- {
- static double a, a2;
- while ( count-- )
- *out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
- }
-
-* Enable debugging support in your environment. This enables assertions
-and other run-time checks.
-
-* Turn the compiler's optimizer is off. Sometimes an optimizer generates
-bad code.
-
-* If multiple threads are being used, ensure that only one at a time is
-accessing a given set of objects from the library. This library is not
-in general thread-safe, though independent objects can be used in
-separate threads.
-
-* If all else fails, see if the demos work.
-
-
-Deprecated features
--------------------
-The following functions and other features have been deprecated and will
-be removed in a future release of the library. Alternatives to the
-deprecated features are listed to the right.
-
-Music_Emu::error_count() warning()
-load( header, reader ) see "Loading file data" above
-Spc_Emu::trailer() track_info()
-Spc_Emu::trailer_size()
-Gym_Emu::track_length() track_info()
-Vgm_Emu::gd3_data() track_info()
-Nsfe_Emu::disable_playlist() clear_playlist()
-
-
-Thanks
-------
-Big thanks to Chris Moeller (kode54) for help with library testing and
-feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
-for original work on openspc++ that was used when developing Spc_Emu.
-Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
-start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
-nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
-and giving feedback for the library in their respective game music
-players.
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.cpp
deleted file mode 100644
index 8204abf2..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Ay_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Emulation inaccuracies:
-// * Noise isn't run when not in use
-// * Changes to envelope and noise periods are delayed until next reload
-// * Super-sonic tone should attenuate output to about 60%, not 50%
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const period_factor = 16;
-
-static byte const amp_table [16] =
-{
-#define ENTRY( n ) byte (n * Ay_Apu::amp_range + 0.5)
- // With channels tied together and 1K resistor to ground (as datasheet recommends),
- // output nearly matches logarithmic curve as claimed. Approx. 1.5 dB per step.
- ENTRY(0.000000),ENTRY(0.007813),ENTRY(0.011049),ENTRY(0.015625),
- ENTRY(0.022097),ENTRY(0.031250),ENTRY(0.044194),ENTRY(0.062500),
- ENTRY(0.088388),ENTRY(0.125000),ENTRY(0.176777),ENTRY(0.250000),
- ENTRY(0.353553),ENTRY(0.500000),ENTRY(0.707107),ENTRY(1.000000),
-
- /*
- // Measured from an AY-3-8910A chip with date code 8611.
-
- // Direct voltages without any load (very linear)
- ENTRY(0.000000),ENTRY(0.046237),ENTRY(0.064516),ENTRY(0.089785),
- ENTRY(0.124731),ENTRY(0.173118),ENTRY(0.225806),ENTRY(0.329032),
- ENTRY(0.360215),ENTRY(0.494624),ENTRY(0.594624),ENTRY(0.672043),
- ENTRY(0.766129),ENTRY(0.841935),ENTRY(0.926882),ENTRY(1.000000),
- // With only some load
- ENTRY(0.000000),ENTRY(0.011940),ENTRY(0.017413),ENTRY(0.024876),
- ENTRY(0.036318),ENTRY(0.054229),ENTRY(0.072637),ENTRY(0.122388),
- ENTRY(0.174129),ENTRY(0.239303),ENTRY(0.323881),ENTRY(0.410945),
- ENTRY(0.527363),ENTRY(0.651741),ENTRY(0.832338),ENTRY(1.000000),
- */
-#undef ENTRY
-};
-
-static byte const modes [8] =
-{
-#define MODE( a0,a1, b0,b1, c0,c1 ) \
- (a0 | a1<<1 | b0<<2 | b1<<3 | c0<<4 | c1<<5)
- MODE( 1,0, 1,0, 1,0 ),
- MODE( 1,0, 0,0, 0,0 ),
- MODE( 1,0, 0,1, 1,0 ),
- MODE( 1,0, 1,1, 1,1 ),
- MODE( 0,1, 0,1, 0,1 ),
- MODE( 0,1, 1,1, 1,1 ),
- MODE( 0,1, 1,0, 0,1 ),
- MODE( 0,1, 0,0, 0,0 ),
-};
-
-Ay_Apu::Ay_Apu()
-{
- // build full table of the upper 8 envelope waveforms
- for ( int m = 8; m--; )
- {
- byte* out = env.modes [m];
- int flags = modes [m];
- for ( int x = 3; --x >= 0; )
- {
- int amp = flags & 1;
- int end = flags >> 1 & 1;
- int step = end - amp;
- amp *= 15;
- for ( int y = 16; --y >= 0; )
- {
- *out++ = amp_table [amp];
- amp += step;
- }
- flags >>= 2;
- }
- }
-
- output( 0 );
- volume( 1.0 );
- reset();
-}
-
-void Ay_Apu::reset()
-{
- last_time = 0;
- noise.delay = 0;
- noise.lfsr = 1;
-
- osc_t* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->period = period_factor;
- osc->delay = 0;
- osc->last_amp = 0;
- osc->phase = 0;
- }
- while ( osc != oscs );
-
- for ( int i = sizeof regs; --i >= 0; )
- regs [i] = 0;
- regs [7] = 0xFF;
- write_data_( 13, 0 );
-}
-
-void Ay_Apu::write_data_( int addr, int data )
-{
- assert( (unsigned) addr < reg_count );
-
- if ( (unsigned) addr >= 14 )
- {
- #ifdef debug_printf
- debug_printf( "Wrote to I/O port %02X\n", (int) addr );
- #endif
- }
-
- // envelope mode
- if ( addr == 13 )
- {
- if ( !(data & 8) ) // convert modes 0-7 to proper equivalents
- data = (data & 4) ? 15 : 9;
- env.wave = env.modes [data - 7];
- env.pos = -48;
- env.delay = 0; // will get set to envelope period in run_until()
- }
- regs [addr] = data;
-
- // handle period changes accurately
- int i = addr >> 1;
- if ( i < osc_count )
- {
- blip_time_t period = (regs [i * 2 + 1] & 0x0F) * (0x100L * period_factor) +
- regs [i * 2] * period_factor;
- if ( !period )
- period = period_factor;
-
- // adjust time of next timer expiration based on change in period
- osc_t& osc = oscs [i];
- if ( (osc.delay += period - osc.period) < 0 )
- osc.delay = 0;
- osc.period = period;
- }
-
- // TODO: same as above for envelope timer, and it also has a divide by two after it
-}
-
-int const noise_off = 0x08;
-int const tone_off = 0x01;
-
-void Ay_Apu::run_until( blip_time_t final_end_time )
-{
- require( final_end_time >= last_time );
-
- // noise period and initial values
- blip_time_t const noise_period_factor = period_factor * 2; // verified
- blip_time_t noise_period = (regs [6] & 0x1F) * noise_period_factor;
- if ( !noise_period )
- noise_period = noise_period_factor;
- blip_time_t const old_noise_delay = noise.delay;
- blargg_ulong const old_noise_lfsr = noise.lfsr;
-
- // envelope period
- blip_time_t const env_period_factor = period_factor * 2; // verified
- blip_time_t env_period = (regs [12] * 0x100L + regs [11]) * env_period_factor;
- if ( !env_period )
- env_period = env_period_factor; // same as period 1 on my AY chip
- if ( !env.delay )
- env.delay = env_period;
-
- // run each osc separately
- for ( int index = 0; index < osc_count; index++ )
- {
- osc_t* const osc = &oscs [index];
- int osc_mode = regs [7] >> index;
-
- // output
- Blip_Buffer* const osc_output = osc->output;
- if ( !osc_output )
- continue;
- osc_output->set_modified();
-
- // period
- int half_vol = 0;
- blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() +
- inaudible_freq) / (inaudible_freq * 2);
- if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
- {
- half_vol = 1; // Actually around 60%, but 50% is close enough
- osc_mode |= tone_off;
- }
-
- // envelope
- blip_time_t start_time = last_time;
- blip_time_t end_time = final_end_time;
- int const vol_mode = regs [0x08 + index];
- int volume = amp_table [vol_mode & 0x0F] >> half_vol;
- int osc_env_pos = env.pos;
- if ( vol_mode & 0x10 )
- {
- volume = env.wave [osc_env_pos] >> half_vol;
- // use envelope only if it's a repeating wave or a ramp that hasn't finished
- if ( !(regs [13] & 1) || osc_env_pos < -32 )
- {
- end_time = start_time + env.delay;
- if ( end_time >= final_end_time )
- end_time = final_end_time;
-
- //if ( !(regs [12] | regs [11]) )
- // debug_printf( "Used envelope period 0\n" );
- }
- else if ( !volume )
- {
- osc_mode = noise_off | tone_off;
- }
- }
- else if ( !volume )
- {
- osc_mode = noise_off | tone_off;
- }
-
- // tone time
- blip_time_t const period = osc->period;
- blip_time_t time = start_time + osc->delay;
- if ( osc_mode & tone_off ) // maintain tone's phase when off
- {
- blargg_long count = (final_end_time - time + period - 1) / period;
- time += count * period;
- osc->phase ^= count & 1;
- }
-
- // noise time
- blip_time_t ntime = final_end_time;
- blargg_ulong noise_lfsr = 1;
- if ( !(osc_mode & noise_off) )
- {
- ntime = start_time + old_noise_delay;
- noise_lfsr = old_noise_lfsr;
- //if ( (regs [6] & 0x1F) == 0 )
- // debug_printf( "Used noise period 0\n" );
- }
-
- // The following efficiently handles several cases (least demanding first):
- // * Tone, noise, and envelope disabled, where channel acts as 4-bit DAC
- // * Just tone or just noise, envelope disabled
- // * Envelope controlling tone and/or noise
- // * Tone and noise disabled, envelope enabled with high frequency
- // * Tone and noise together
- // * Tone and noise together with envelope
-
- // This loop only runs one iteration if envelope is disabled. If envelope
- // is being used as a waveform (tone and noise disabled), this loop will
- // still be reasonably efficient since the bulk of it will be skipped.
- while ( 1 )
- {
- // current amplitude
- int amp = 0;
- if ( (osc_mode | osc->phase) & 1 & (osc_mode >> 3 | noise_lfsr) )
- amp = volume;
- {
- int delta = amp - osc->last_amp;
- if ( delta )
- {
- osc->last_amp = amp;
- synth_.offset( start_time, delta, osc_output );
- }
- }
-
- // Run wave and noise interleved with each catching up to the other.
- // If one or both are disabled, their "current time" will be past end time,
- // so there will be no significant performance hit.
- if ( ntime < end_time || time < end_time )
- {
- // Since amplitude was updated above, delta will always be +/- volume,
- // so we can avoid using last_amp every time to calculate the delta.
- int delta = amp * 2 - volume;
- int delta_non_zero = delta != 0;
- int phase = osc->phase | (osc_mode & tone_off); assert( tone_off == 0x01 );
- do
- {
- // run noise
- blip_time_t end = end_time;
- if ( end_time > time ) end = time;
- if ( phase & delta_non_zero )
- {
- while ( ntime <= end ) // must advance *past* time to avoid hang
- {
- int changed = noise_lfsr + 1;
- noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
- if ( changed & 2 )
- {
- delta = -delta;
- synth_.offset( ntime, delta, osc_output );
- }
- ntime += noise_period;
- }
- }
- else
- {
- // 20 or more noise periods on average for some music
- blargg_long remain = end - ntime;
- blargg_long count = remain / noise_period;
- if ( remain >= 0 )
- ntime += noise_period + count * noise_period;
- }
-
- // run tone
- end = end_time;
- if ( end_time > ntime ) end = ntime;
- if ( noise_lfsr & delta_non_zero )
- {
- while ( time < end )
- {
- delta = -delta;
- synth_.offset( time, delta, osc_output );
- time += period;
- //phase ^= 1;
- }
- //assert( phase == (delta > 0) );
- phase = unsigned (-delta) >> (CHAR_BIT * sizeof (unsigned) - 1);
- // (delta > 0)
- }
- else
- {
- // loop usually runs less than once
- //SUB_CASE_COUNTER( (time < end) * (end - time + period - 1) / period );
-
- while ( time < end )
- {
- time += period;
- phase ^= 1;
- }
- }
- }
- while ( time < end_time || ntime < end_time );
-
- osc->last_amp = (delta + volume) >> 1;
- if ( !(osc_mode & tone_off) )
- osc->phase = phase;
- }
-
- if ( end_time >= final_end_time )
- break; // breaks first time when envelope is disabled
-
- // next envelope step
- if ( ++osc_env_pos >= 0 )
- osc_env_pos -= 32;
- volume = env.wave [osc_env_pos] >> half_vol;
-
- start_time = end_time;
- end_time += env_period;
- if ( end_time > final_end_time )
- end_time = final_end_time;
- }
- osc->delay = time - final_end_time;
-
- if ( !(osc_mode & noise_off) )
- {
- noise.delay = ntime - final_end_time;
- noise.lfsr = noise_lfsr;
- }
- }
-
- // TODO: optimized saw wave envelope?
-
- // maintain envelope phase
- blip_time_t remain = final_end_time - last_time - env.delay;
- if ( remain >= 0 )
- {
- blargg_long count = (remain + env_period) / env_period;
- env.pos += count;
- if ( env.pos >= 0 )
- env.pos = (env.pos & 31) - 32;
- remain -= count * env_period;
- assert( -remain <= env_period );
- }
- env.delay = -remain;
- assert( env.delay > 0 );
- assert( env.pos < 0 );
-
- last_time = final_end_time;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.h
deleted file mode 100644
index 42395e37..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Apu.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// AY-3-8910 sound chip emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef AY_APU_H
-#define AY_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Ay_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Reset sound chip
- void reset();
-
- // Write to register at specified time
- enum { reg_count = 16 };
- void write( blip_time_t time, int addr, int data );
-
- // Run sound to specified time, end current time frame, then start a new
- // time frame at time 0. Time frames have no effect on emulation and each
- // can be whatever length is convenient.
- void end_frame( blip_time_t length );
-
-// Additional features
-
- // Set sound output of specific oscillator to buffer, where index is
- // 0, 1, or 2. If buffer is NULL, the specified oscillator is muted.
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see documentation)
- void treble_eq( blip_eq_t const& );
-
-public:
- Ay_Apu();
- typedef unsigned char byte;
-private:
- struct osc_t
- {
- blip_time_t period;
- blip_time_t delay;
- short last_amp;
- short phase;
- Blip_Buffer* output;
- } oscs [osc_count];
- blip_time_t last_time;
- byte latch;
- byte regs [reg_count];
-
- struct {
- blip_time_t delay;
- blargg_ulong lfsr;
- } noise;
-
- struct {
- blip_time_t delay;
- byte const* wave;
- int pos;
- byte modes [8] [48]; // values already passed through volume table
- } env;
-
- void run_until( blip_time_t );
- void write_data_( int addr, int data );
-public:
- enum { amp_range = 255 };
- Blip_Synth<blip_good_quality,1> synth_;
-};
-
-inline void Ay_Apu::volume( double v ) { synth_.volume( 0.7 / osc_count / amp_range * v ); }
-
-inline void Ay_Apu::treble_eq( blip_eq_t const& eq ) { synth_.treble_eq( eq ); }
-
-inline void Ay_Apu::write( blip_time_t time, int addr, int data )
-{
- run_until( time );
- write_data_( addr, data );
-}
-
-inline void Ay_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Ay_Apu::output( Blip_Buffer* buf )
-{
- osc_output( 0, buf );
- osc_output( 1, buf );
- osc_output( 2, buf );
-}
-
-inline void Ay_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.cpp
deleted file mode 100644
index 0f67db1b..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.cpp
+++ /dev/null
@@ -1,1665 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.21 5:26 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Ay_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME() (void) (s.time = s_time)
-#define RELOAD_TIME() (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, TIME )\
- ay_cpu_out( cpu, TIME, addr, data )
-
-#define CPU_IN( cpu, addr, TIME )\
- ay_cpu_in( cpu, addr )
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n ) szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n ) (szpc [n] & ~P04)
-#define SZ28( n ) SZ28C( n )
-
-#define SET_R( n ) (void) (r.r = n)
-#define GET_R() (r.r)
-
-Ay_Cpu::Ay_Cpu()
-{
- state = &state_;
- for ( int i = 0x100; --i >= 0; )
- {
- int even = 1;
- for ( int p = i; p; p >>= 1 )
- even ^= p;
- int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
- szpc [i] = n;
- szpc [i + 0x100] = n | C01;
- }
- szpc [0x000] |= Z40;
- szpc [0x100] |= Z40;
-}
-
-void Ay_Cpu::reset( void* m )
-{
- mem = (uint8_t*) m;
-
- check( state == &state_ );
- state = &state_;
- state_.time = 0;
- state_.base = 0;
- end_time_ = 0;
-
- memset( &r, 0, sizeof r );
-}
-
-#define TIME (s_time + s.base)
-#define READ_PROG( addr ) (mem [addr])
-#define INSTR( offset ) READ_PROG( pc + (offset) )
-#define GET_ADDR() GET_LE16( &READ_PROG( pc ) )
-#define READ( addr ) READ_PROG( addr )
-#define WRITE( addr, data ) (void) (READ_PROG( addr ) = data)
-#define READ_WORD( addr ) GET_LE16( &READ_PROG( addr ) )
-#define WRITE_WORD( addr, data ) SET_LE16( &READ_PROG( addr ), data )
-#define IN( addr ) CPU_IN( this, addr, TIME )
-#define OUT( addr, data ) CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
- (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Ay_Cpu::run( cpu_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- bool warning = false;
-
- typedef BOOST::int8_t int8_t;
-
- union {
- regs_t rg;
- pairs_t rp;
- uint8_t r8_ [8]; // indexed
- uint16_t r16_ [4];
- };
- rg = this->r.b;
-
- cpu_time_t s_time = s.time;
- uint8_t* const mem = this->mem; // cache
- fuint16 pc = r.pc;
- fuint16 sp = r.sp;
- fuint16 ix = r.ix; // TODO: keep in memory for direct access?
- fuint16 iy = r.iy;
- int flags = r.b.flags;
-
- goto loop;
-jr_not_taken:
- s_time -= 5;
- goto loop;
-call_not_taken:
- s_time -= 7;
-jp_not_taken:
- pc += 2;
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (unsigned) flags < 0x100 );
- check( (unsigned) ix < 0x10000 );
- check( (unsigned) iy < 0x10000 );
-
- fuint8 opcode;
- opcode = READ_PROG( pc );
- pc++;
-
- static byte const base_timing [0x100] = {
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
- 13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
- 12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
- 12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
- 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
- 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
- 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
- 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
- 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
- };
-
- fuint16 data;
- data = base_timing [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = READ_PROG( pc );
-
- #ifdef Z80_CPU_LOG_H
- //log_opcode( opcode, READ_PROG( pc ) );
- z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
- z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
- READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Common
-
- case 0x00: // NOP
- CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
- goto loop;
-
- case 0x08:{// EX AF,AF'
- int temp = r.alt.b.a;
- r.alt.b.a = rg.a;
- rg.a = temp;
-
- temp = r.alt.b.flags;
- r.alt.b.flags = flags;
- flags = temp;
- goto loop;
- }
-
- case 0xD3: // OUT (imm),A
- pc++;
- OUT( data + rg.a * 0x100, rg.a );
- goto loop;
-
- case 0x2E: // LD L,imm
- pc++;
- rg.l = data;
- goto loop;
-
- case 0x3E: // LD A,imm
- pc++;
- rg.a = data;
- goto loop;
-
- case 0x3A:{// LD A,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rg.a = READ( addr );
- goto loop;
- }
-
-// Conditional
-
-#define ZERO (flags & Z40)
-#define CARRY (flags & C01)
-#define EVEN (flags & P04)
-#define MINUS (flags & S80)
-
-// JR
-#define JR( cond ) {\
- int disp = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) )\
- goto jr_not_taken;\
- pc += disp;\
- goto loop;\
-}
-
- case 0x20: JR( !ZERO ) // JR NZ,disp
- case 0x28: JR( ZERO ) // JR Z,disp
- case 0x30: JR( !CARRY ) // JR NC,disp
- case 0x38: JR( CARRY ) // JR C,disp
- case 0x18: JR( true ) // JR disp
-
- case 0x10:{// DJNZ disp
- int temp = rg.b - 1;
- rg.b = temp;
- JR( temp )
- }
-
-// JP
-#define JP( cond ) if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
- case 0xC2: JP( !ZERO ) // JP NZ,addr
- case 0xCA: JP( ZERO ) // JP Z,addr
- case 0xD2: JP( !CARRY ) // JP NC,addr
- case 0xDA: JP( CARRY ) // JP C,addr
- case 0xE2: JP( !EVEN ) // JP PO,addr
- case 0xEA: JP( EVEN ) // JP PE,addr
- case 0xF2: JP( !MINUS ) // JP P,addr
- case 0xFA: JP( MINUS ) // JP M,addr
-
- case 0xC3: // JP addr
- pc = GET_ADDR();
- goto loop;
-
- case 0xE9: // JP HL
- pc = rp.hl;
- goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
- case 0xC0: RET( !ZERO ) // RET NZ
- case 0xC8: RET( ZERO ) // RET Z
- case 0xD0: RET( !CARRY ) // RET NC
- case 0xD8: RET( CARRY ) // RET C
- case 0xE0: RET( !EVEN ) // RET PO
- case 0xE8: RET( EVEN ) // RET PE
- case 0xF0: RET( !MINUS ) // RET P
- case 0xF8: RET( MINUS ) // RET M
-
- case 0xC9: // RET
- ret_taken:
- pc = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
- case 0xC4: CALL( !ZERO ) // CALL NZ,addr
- case 0xCC: CALL( ZERO ) // CALL Z,addr
- case 0xD4: CALL( !CARRY ) // CALL NC,addr
- case 0xDC: CALL( CARRY ) // CALL C,addr
- case 0xE4: CALL( !EVEN ) // CALL PO,addr
- case 0xEC: CALL( EVEN ) // CALL PE,addr
- case 0xF4: CALL( !MINUS ) // CALL P,addr
- case 0xFC: CALL( MINUS ) // CALL M,addr
-
- case 0xCD:{// CALL addr
- call_taken:
- fuint16 addr = pc + 2;
- pc = GET_ADDR();
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, addr );
- goto loop;
- }
-
- case 0xFF: // RST
- if ( (pc - 1) > 0xFFFF )
- {
- pc = uint16_t (pc - 1);
- s_time -= 11;
- goto loop;
- }
- CASE7( C7, CF, D7, DF, E7, EF, F7 ):
- data = pc;
- pc = opcode & 0x38;
- goto push_data;
-
-// PUSH/POP
- case 0xF5: // PUSH AF
- data = rg.a * 0x100u + flags;
- goto push_data;
-
- case 0xC5: // PUSH BC
- case 0xD5: // PUSH DE
- case 0xE5: // PUSH HL
- data = R16( opcode, 4, 0xC5 );
- push_data:
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, data );
- goto loop;
-
- case 0xF1: // POP AF
- flags = READ( sp );
- rg.a = READ( sp + 1 );
- sp = uint16_t (sp + 2);
- goto loop;
-
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL
- R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// ADC/ADD/SBC/SUB
- case 0x96: // SUB (HL)
- case 0x86: // ADD (HL)
- flags &= ~C01;
- case 0x9E: // SBC (HL)
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_data;
-
- case 0xD6: // SUB A,imm
- case 0xC6: // ADD imm
- flags &= ~C01;
- case 0xDE: // SBC A,imm
- case 0xCE: // ADC imm
- pc++;
- goto adc_data;
-
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
- flags &= ~C01;
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
- data = R8( opcode & 7, 0 );
- adc_data: {
- int result = data + (flags & C01);
- data ^= rg.a;
- flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
- if ( flags )
- result = -result;
- result += rg.a;
- data ^= result;
- flags |=(data & H10) |
- ((data - -0x80) >> 6 & V04) |
- SZ28C( result & 0x1FF );
- rg.a = result;
- goto loop;
- }
-
-// CP
- case 0xBE: // CP (HL)
- data = READ( rp.hl );
- goto cp_data;
-
- case 0xFE: // CP imm
- pc++;
- goto cp_data;
-
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
- data = R8( opcode, 0xB8 );
- cp_data: {
- int result = rg.a - data;
- flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
- data ^= rg.a;
- flags |=(((result ^ rg.a) & data) >> 5 & V04) |
- (((data & H10) ^ result) & (S80 | H10));
- if ( (uint8_t) result )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
-// ADD HL,rp
-
- case 0x39: // ADD HL,SP
- data = sp;
- goto add_hl_data;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- data = R16( opcode, 4, 0x09 );
- add_hl_data: {
- blargg_ulong sum = rp.hl + data;
- data ^= rp.hl;
- rp.hl = sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((data ^ sum) >> 8 & H10);
- goto loop;
- }
-
- case 0x27:{// DAA
- int a = rg.a;
- if ( a > 0x99 )
- flags |= C01;
-
- int adjust = 0x60 & -(flags & C01);
-
- if ( flags & H10 || (a & 0x0F) > 9 )
- adjust |= 0x06;
-
- if ( flags & N02 )
- adjust = -adjust;
- a += adjust;
-
- flags = (flags & (C01 | N02)) |
- ((rg.a ^ a) & H10) |
- SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- /*
- case 0x27:{// DAA
- // more optimized, but probably not worth the obscurity
- int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
- int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
- if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
- adjust |= 0x06;
-
- if ( f & N02 )
- adjust = -adjust;
- int a = rg.a + adjust;
-
- flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- */
-
-// INC/DEC
- case 0x34: // INC (HL)
- data = READ( rp.hl ) + 1;
- WRITE( rp.hl, data );
- goto inc_set_flags;
-
- CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
- data = ++R8( opcode >> 3, 0 );
- inc_set_flags:
- flags = (flags & C01) |
- (((data & 0x0F) - 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x80 )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x35: // DEC (HL)
- data = READ( rp.hl ) - 1;
- WRITE( rp.hl, data );
- goto dec_set_flags;
-
- CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
- data = --R8( opcode >> 3, 0 );
- dec_set_flags:
- flags = (flags & C01) | N02 |
- (((data & 0x0F) + 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x7F )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- R16( opcode, 4, 0x03 )++;
- goto loop;
-
- case 0x33: // INC SP
- sp = uint16_t (sp + 1);
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- R16( opcode, 4, 0x0B )--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = uint16_t (sp - 1);
- goto loop;
-
-// AND
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- goto and_data;
-
- case 0xE6: // AND imm
- pc++;
- goto and_data;
-
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
- data = R8( opcode, 0xA0 );
- and_data:
- rg.a &= data;
- flags = SZ28P( rg.a ) | H10;
- goto loop;
-
-// OR
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- goto or_data;
-
- case 0xF6: // OR imm
- pc++;
- goto or_data;
-
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
- data = R8( opcode, 0xB0 );
- or_data:
- rg.a |= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// XOR
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- goto xor_data;
-
- case 0xEE: // XOR imm
- pc++;
- goto xor_data;
-
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
- data = R8( opcode, 0xA8 );
- xor_data:
- rg.a ^= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
- WRITE( rp.hl, R8( opcode, 0x70 ) );
- goto loop;
-
- CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
- CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
- CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
- CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
- CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
- CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
- CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
- R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
- goto loop;
-
- CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
- R8( opcode >> 3, 0 ) = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),imm
- pc++;
- WRITE( rp.hl, data );
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
- R8( opcode >> 3, 8 ) = READ( rp.hl );
- goto loop;
-
- case 0x01: // LD rp,imm
- case 0x11:
- case 0x21:
- R16( opcode, 4, 0x01 ) = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x31: // LD sp,imm
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x2A:{// LD HL,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rp.hl = READ_WORD( addr );
- goto loop;
- }
-
- case 0x32:{// LD (addr),A
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE( addr, rg.a );
- goto loop;
- }
-
- case 0x22:{// LD (addr),HL
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, rp.hl );
- goto loop;
- }
-
- case 0x02: // LD (BC),A
- case 0x12: // LD (DE),A
- WRITE( R16( opcode, 4, 0x02 ), rg.a );
- goto loop;
-
- case 0x0A: // LD A,(BC)
- case 0x1A: // LD A,(DE)
- rg.a = READ( R16( opcode, 4, 0x0A ) );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
-// Rotate
-
- case 0x07:{// RLCA
- fuint16 temp = rg.a;
- temp = (temp << 1) | (temp >> 7);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08 | C01));
- rg.a = temp;
- goto loop;
- }
-
- case 0x0F:{// RRCA
- fuint16 temp = rg.a;
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & C01);
- temp = (temp << 7) | (temp >> 1);
- flags |= temp & (F20 | F08);
- rg.a = temp;
- goto loop;
- }
-
- case 0x17:{// RLA
- blargg_ulong temp = (rg.a << 1) | (flags & C01);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (temp >> 8);
- rg.a = temp;
- goto loop;
- }
-
- case 0x1F:{// RRA
- fuint16 temp = (flags << 7) | (rg.a >> 1);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (rg.a & C01);
- rg.a = temp;
- goto loop;
- }
-
-// Misc
- case 0x2F:{// CPL
- fuint16 temp = ~rg.a;
- flags = (flags & (S80 | Z40 | P04 | C01)) |
- (temp & (F20 | F08)) |
- (H10 | N02);
- rg.a = temp;
- goto loop;
- }
-
- case 0x3F:{// CCF
- flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
- (flags << 4 & H10) |
- (rg.a & (F20 | F08));
- goto loop;
- }
-
- case 0x37: // SCF
- flags = (flags & (S80 | Z40 | P04)) | C01 |
- (rg.a & (F20 | F08));
- goto loop;
-
- case 0xDB: // IN A,(imm)
- pc++;
- rg.a = IN( data + rg.a * 0x100 );
- goto loop;
-
- case 0xE3:{// EX (SP),HL
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, rp.hl );
- rp.hl = temp;
- goto loop;
- }
-
- case 0xEB:{// EX DE,HL
- fuint16 temp = rp.hl;
- rp.hl = rp.de;
- rp.de = temp;
- goto loop;
- }
-
- case 0xD9:{// EXX DE,HL
- fuint16 temp = r.alt.w.bc;
- r.alt.w.bc = rp.bc;
- rp.bc = temp;
-
- temp = r.alt.w.de;
- r.alt.w.de = rp.de;
- rp.de = temp;
-
- temp = r.alt.w.hl;
- r.alt.w.hl = rp.hl;
- rp.hl = temp;
- goto loop;
- }
-
- case 0xF3: // DI
- r.iff1 = 0;
- r.iff2 = 0;
- goto loop;
-
- case 0xFB: // EI
- r.iff1 = 1;
- r.iff2 = 1;
- // TODO: delayed effect
- goto loop;
-
- case 0x76: // HALT
- goto halt;
-
-//////////////////////////////////////// CB prefix
- {
- case 0xCB:
- unsigned data2;
- data2 = INSTR( 1 );
- pc++;
- switch ( data )
- {
-
- // Rotate left
-
- #define RLC( read, write ) {\
- fuint8 result = read;\
- result = uint8_t (result << 1) | (result >> 7);\
- flags = SZ28P( result ) | (result & C01);\
- write;\
- goto loop;\
- }
-
- case 0x06: // RLC (HL)
- s_time += 7;
- data = rp.hl;
- rlc_data_addr:
- RLC( READ( data ), WRITE( data, result ) )
-
- CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
- uint8_t& reg = R8( data, 0 );
- RLC( reg, reg = result )
- }
-
- #define RL( read, write ) {\
- fuint16 result = (read << 1) | (flags & C01);\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x16: // RL (HL)
- s_time += 7;
- data = rp.hl;
- rl_data_addr:
- RL( READ( data ), WRITE( data, result ) )
-
- CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
- uint8_t& reg = R8( data, 0x10 );
- RL( reg, reg = result )
- }
-
- #define SLA( read, add, write ) {\
- fuint16 result = (read << 1) | add;\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x26: // SLA (HL)
- s_time += 7;
- data = rp.hl;
- sla_data_addr:
- SLA( READ( data ), 0, WRITE( data, result ) )
-
- CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
- uint8_t& reg = R8( data, 0x20 );
- SLA( reg, 0, reg = result )
- }
-
- case 0x36: // SLL (HL)
- s_time += 7;
- data = rp.hl;
- sll_data_addr:
- SLA( READ( data ), 1, WRITE( data, result ) )
-
- CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
- uint8_t& reg = R8( data, 0x30 );
- SLA( reg, 1, reg = result )
- }
-
- // Rotate right
-
- #define RRC( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = uint8_t (result << 7) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x0E: // RRC (HL)
- s_time += 7;
- data = rp.hl;
- rrc_data_addr:
- RRC( READ( data ), WRITE( data, result ) )
-
- CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
- uint8_t& reg = R8( data, 0x08 );
- RRC( reg, reg = result )
- }
-
- #define RR( read, write ) {\
- fuint8 result = read;\
- fuint8 temp = result & C01;\
- result = uint8_t (flags << 7) | (result >> 1);\
- flags = SZ28P( result ) | temp;\
- write;\
- goto loop;\
- }
-
- case 0x1E: // RR (HL)
- s_time += 7;
- data = rp.hl;
- rr_data_addr:
- RR( READ( data ), WRITE( data, result ) )
-
- CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
- uint8_t& reg = R8( data, 0x18 );
- RR( reg, reg = result )
- }
-
- #define SRA( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = (result & 0x80) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x2E: // SRA (HL)
- data = rp.hl;
- s_time += 7;
- sra_data_addr:
- SRA( READ( data ), WRITE( data, result ) )
-
- CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
- uint8_t& reg = R8( data, 0x28 );
- SRA( reg, reg = result )
- }
-
- #define SRL( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result >>= 1;\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x3E: // SRL (HL)
- s_time += 7;
- data = rp.hl;
- srl_data_addr:
- SRL( READ( data ), WRITE( data, result ) )
-
- CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
- uint8_t& reg = R8( data, 0x38 );
- SRL( reg, reg = result )
- }
-
- // BIT
- {
- unsigned temp;
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
- s_time += 4;
- temp = READ( rp.hl );
- flags &= C01;
- goto bit_temp;
- CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
- CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
- CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
- CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
- CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
- CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
- CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
- temp = R8( data & 7, 0 );
- flags = (flags & C01) | (temp & (F20 | F08));
- bit_temp:
- int masked = temp & 1 << (data >> 3 & 7);
- flags |=(masked & S80) | H10 |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- // SET/RES
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
- s_time += 7;
- int temp = READ( rp.hl );
- int bit = 1 << (data >> 3 & 7);
- temp |= bit; // SET
- if ( !(data & 0x40) )
- temp ^= bit; // RES
- WRITE( rp.hl, temp );
- goto loop;
- }
-
- CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
- CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
- CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
- CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
- CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
- CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
- CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
- CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
- R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
- goto loop;
-
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
- R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// ED prefix
- {
- case 0xED:
- pc++;
- s_time += ed_dd_timing [data] >> 4;
- switch ( data )
- {
- {
- blargg_ulong temp;
- case 0x72: // SBC HL,SP
- case 0x7A: // ADC HL,SP
- temp = sp;
- if ( 0 )
- case 0x42: // SBC HL,BC
- case 0x52: // SBC HL,DE
- case 0x62: // SBC HL,HL
- case 0x4A: // ADC HL,BC
- case 0x5A: // ADC HL,DE
- case 0x6A: // ADC HL,HL
- temp = R16( data >> 3 & 6, 1, 0 );
- blargg_ulong sum = temp + (flags & C01);
- flags = ~data >> 2 & N02;
- if ( flags )
- sum = -sum;
- sum += rp.hl;
- temp ^= rp.hl;
- temp ^= sum;
- flags |=(sum >> 16 & C01) |
- (temp >> 8 & H10) |
- (sum >> 8 & (S80 | F20 | F08)) |
- ((temp - -0x8000) >> 14 & V04);
- rp.hl = sum;
- if ( (uint16_t) sum )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
- CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
- int temp = IN( rp.bc );
- R8( data >> 3, 8 ) = temp;
- flags = (flags & C01) | SZ28P( temp );
- goto loop;
- }
-
- case 0x71: // OUT (C),0
- rg.flags = 0;
- CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
- OUT( rp.bc, R8( data >> 3, 8 ) );
- goto loop;
-
- {
- unsigned temp;
- case 0x73: // LD (ADDR),SP
- temp = sp;
- if ( 0 )
- case 0x43: // LD (ADDR),BC
- case 0x53: // LD (ADDR),DE
- temp = R16( data, 4, 0x43 );
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, temp );
- goto loop;
- }
-
- case 0x4B: // LD BC,(ADDR)
- case 0x5B:{// LD DE,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- R16( data, 4, 0x4B ) = READ_WORD( addr );
- goto loop;
- }
-
- case 0x7B:{// LD SP,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- sp = READ_WORD( addr );
- goto loop;
- }
-
- case 0x67:{// RRD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
- temp = (rg.a & 0xF0) | (temp & 0x0F);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- case 0x6F:{// RLD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
- temp = (rg.a & 0xF0) | (temp >> 4);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
- opcode = 0x10; // flag to do SBC instead of ADC
- flags &= ~C01;
- data = rg.a;
- rg.a = 0;
- goto adc_data;
-
- {
- int inc;
- case 0xA9: // CPD
- case 0xB9: // CPDR
- inc = -1;
- if ( 0 )
- case 0xA1: // CPI
- case 0xB1: // CPIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int result = rg.a - temp;
- flags = (flags & C01) | N02 |
- ((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
- if ( !(uint8_t) result ) flags |= Z40;
- result -= (flags & H10) >> 4;
- flags |= result & F08;
- flags |= result << 4 & F20;
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( flags & Z40 || data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xA8: // LDD
- case 0xB8: // LDDR
- inc = -1;
- if ( 0 )
- case 0xA0: // LDI
- case 0xB0: // LDIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- addr = rp.de;
- rp.de = addr + inc;
- WRITE( addr, temp );
-
- temp += rg.a;
- flags = (flags & (S80 | Z40 | C01)) |
- (temp & F08) | (temp << 4 & F20);
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xAB: // OUTD
- case 0xBB: // OTDR
- inc = -1;
- if ( 0 )
- case 0xA3: // OUTI
- case 0xB3: // OTIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- OUT( rp.bc, temp );
- goto loop;
- }
-
- {
- int inc;
- case 0xAA: // IND
- case 0xBA: // INDR
- inc = -1;
- if ( 0 )
- case 0xA2: // INI
- case 0xB2: // INIR
- inc = +1;
-
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
-
- int temp = IN( rp.bc );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- WRITE( addr, temp );
- goto loop;
- }
-
- case 0x47: // LD I,A
- r.i = rg.a;
- goto loop;
-
- case 0x4F: // LD R,A
- SET_R( rg.a );
- debug_printf( "LD R,A not supported\n" );
- warning = true;
- goto loop;
-
- case 0x57: // LD A,I
- rg.a = r.i;
- goto ld_ai_common;
-
- case 0x5F: // LD A,R
- rg.a = GET_R();
- debug_printf( "LD A,R not supported\n" );
- warning = true;
- ld_ai_common:
- flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
- goto loop;
-
- CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
- r.iff1 = r.iff2;
- goto ret_taken;
-
- case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
- r.im = 0;
- goto loop;
-
- case 0x56: case 0x76: // IM 1
- r.im = 1;
- goto loop;
-
- case 0x5E: case 0x7E: // IM 2
- r.im = 2;
- goto loop;
-
- default:
- debug_printf( "Opcode $ED $%02X not supported\n", data );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// DD/FD prefix
- {
- fuint16 ixy;
- case 0xDD:
- ixy = ix;
- goto ix_prefix;
- case 0xFD:
- ixy = iy;
- ix_prefix:
- pc++;
- unsigned data2 = READ_PROG( pc );
- s_time += ed_dd_timing [data] & 0x0F;
- switch ( data )
- {
- // TODO: more efficient way of avoid negative address
- #define IXY_DISP( ixy, disp ) uint16_t ((ixy) + (disp))
-
- #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
- // ADD/ADC/SUB/SBC
-
- case 0x96: // SUB (IXY+disp)
- case 0x86: // ADD (IXY+disp)
- flags &= ~C01;
- case 0x9E: // SBC (IXY+disp)
- case 0x8E: // ADC (IXY+disp)
- pc++;
- opcode = data;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto adc_data;
-
- case 0x94: // SUB HXY
- case 0x84: // ADD HXY
- flags &= ~C01;
- case 0x9C: // SBC HXY
- case 0x8C: // ADC HXY
- opcode = data;
- data = ixy >> 8;
- goto adc_data;
-
- case 0x95: // SUB LXY
- case 0x85: // ADD LXY
- flags &= ~C01;
- case 0x9D: // SBC LXY
- case 0x8D: // ADC LXY
- opcode = data;
- data = (uint8_t) ixy;
- goto adc_data;
-
- {
- unsigned temp;
- case 0x39: // ADD IXY,SP
- temp = sp;
- goto add_ixy_data;
-
- case 0x29: // ADD IXY,HL
- temp = ixy;
- goto add_ixy_data;
-
- case 0x09: // ADD IXY,BC
- case 0x19: // ADD IXY,DE
- temp = R16( data, 4, 0x09 );
- add_ixy_data: {
- blargg_ulong sum = ixy + temp;
- temp ^= ixy;
- ixy = (uint16_t) sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((temp ^ sum) >> 8 & H10);
- goto set_ixy;
- }
- }
-
- // AND
- case 0xA6: // AND (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto and_data;
-
- case 0xA4: // AND HXY
- data = ixy >> 8;
- goto and_data;
-
- case 0xA5: // AND LXY
- data = (uint8_t) ixy;
- goto and_data;
-
- // OR
- case 0xB6: // OR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto or_data;
-
- case 0xB4: // OR HXY
- data = ixy >> 8;
- goto or_data;
-
- case 0xB5: // OR LXY
- data = (uint8_t) ixy;
- goto or_data;
-
- // XOR
- case 0xAE: // XOR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto xor_data;
-
- case 0xAC: // XOR HXY
- data = ixy >> 8;
- goto xor_data;
-
- case 0xAD: // XOR LXY
- data = (uint8_t) ixy;
- goto xor_data;
-
- // CP
- case 0xBE: // CP (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto cp_data;
-
- case 0xBC: // CP HXY
- data = ixy >> 8;
- goto cp_data;
-
- case 0xBD: // CP LXY
- data = (uint8_t) ixy;
- goto cp_data;
-
- // LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
- data = R8( data, 0x70 );
- if ( 0 )
- case 0x36: // LD (IXY+disp),imm
- pc++, data = READ_PROG( pc );
- pc++;
- WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
- goto loop;
-
- CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
- R8( data >> 3, 8 ) = ixy >> 8;
- goto loop;
-
- case 0x64: // LD HXY,HXY
- case 0x6D: // LD LXY,LXY
- goto loop;
-
- CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
- R8( data >> 3, 8 ) = ixy;
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
- pc++;
- R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto loop;
-
- case 0x26: // LD HXY,imm
- pc++;
- goto ld_hxy_data;
-
- case 0x65: // LD HXY,LXY
- data2 = (uint8_t) ixy;
- goto ld_hxy_data;
-
- CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
- data2 = R8( data, 0x60 );
- ld_hxy_data:
- ixy = (uint8_t) ixy | (data2 << 8);
- goto set_ixy;
-
- case 0x2E: // LD LXY,imm
- pc++;
- goto ld_lxy_data;
-
- case 0x6C: // LD LXY,HXY
- data2 = ixy >> 8;
- goto ld_lxy_data;
-
- CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
- data2 = R8( data, 0x68 );
- ld_lxy_data:
- ixy = (ixy & 0xFF00) | data2;
- set_ixy:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto loop;
- }
- iy = ixy;
- goto loop;
-
- case 0xF9: // LD SP,IXY
- sp = ixy;
- goto loop;
-
- case 0x22:{// LD (ADDR),IXY
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, ixy );
- goto loop;
- }
-
- case 0x21: // LD IXY,imm
- ixy = GET_ADDR();
- pc += 2;
- goto set_ixy;
-
- case 0x2A:{// LD IXY,(addr)
- fuint16 addr = GET_ADDR();
- ixy = READ_WORD( addr );
- pc += 2;
- goto set_ixy;
- }
-
- // DD/FD CB prefix
- case 0xCB: {
- data = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data2 = READ_PROG( pc );
- pc++;
- switch ( data2 )
- {
- case 0x06: goto rlc_data_addr; // RLC (IXY)
- case 0x16: goto rl_data_addr; // RL (IXY)
- case 0x26: goto sla_data_addr; // SLA (IXY)
- case 0x36: goto sll_data_addr; // SLL (IXY)
- case 0x0E: goto rrc_data_addr; // RRC (IXY)
- case 0x1E: goto rr_data_addr; // RR (IXY)
- case 0x2E: goto sra_data_addr; // SRA (IXY)
- case 0x3E: goto srl_data_addr; // SRL (IXY)
-
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
- fuint8 temp = READ( data );
- int masked = temp & 1 << (data2 >> 3 & 7);
- flags = (flags & C01) | H10 |
- (masked & S80) |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
- int temp = READ( data );
- int bit = 1 << (data2 >> 3 & 7);
- temp |= bit; // SET
- if ( !(data2 & 0x40) )
- temp ^= bit; // RES
- WRITE( data, temp );
- goto loop;
- }
-
- default:
- debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
- // INC/DEC
- case 0x23: // INC IXY
- ixy = uint16_t (ixy + 1);
- goto set_ixy;
-
- case 0x2B: // DEC IXY
- ixy = uint16_t (ixy - 1);
- goto set_ixy;
-
- case 0x34: // INC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) + 1;
- WRITE( ixy, data );
- goto inc_set_flags;
-
- case 0x35: // DEC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) - 1;
- WRITE( ixy, data );
- goto dec_set_flags;
-
- case 0x24: // INC HXY
- ixy = uint16_t (ixy + 0x100);
- data = ixy >> 8;
- goto inc_xy_common;
-
- case 0x2C: // INC LXY
- data = uint8_t (ixy + 1);
- ixy = (ixy & 0xFF00) | data;
- inc_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto inc_set_flags;
- }
- iy = ixy;
- goto inc_set_flags;
-
- case 0x25: // DEC HXY
- ixy = uint16_t (ixy - 0x100);
- data = ixy >> 8;
- goto dec_xy_common;
-
- case 0x2D: // DEC LXY
- data = uint8_t (ixy - 1);
- ixy = (ixy & 0xFF00) | data;
- dec_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto dec_set_flags;
- }
- iy = ixy;
- goto dec_set_flags;
-
- // PUSH/POP
- case 0xE5: // PUSH IXY
- data = ixy;
- goto push_data;
-
- case 0xE1:{// POP IXY
- ixy = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto set_ixy;
- }
-
- // Misc
-
- case 0xE9: // JP (IXY)
- pc = ixy;
- goto loop;
-
- case 0xE3:{// EX (SP),IXY
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, ixy );
- ixy = temp;
- goto set_ixy;
- }
-
- default:
- debug_printf( "Unnecessary DD/FD prefix encountered\n" );
- warning = true;
- pc--;
- goto loop;
- }
- assert( false );
- }
-
- }
- debug_printf( "Unhandled main opcode: $%02X\n", opcode );
- assert( false );
-
-halt:
- s_time &= 3; // increment by multiple of 4
-out_of_time:
- pc--;
-
- s.time = s_time;
- rg.flags = flags;
- r.ix = ix;
- r.iy = iy;
- r.sp = sp;
- r.pc = pc;
- this->r.b = rg;
- this->state_ = s;
- this->state = &this->state_;
-
- return warning;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.h
deleted file mode 100644
index 2f4d351e..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Cpu.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Z80 CPU emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef AY_CPU_H
-#define AY_CPU_H
-
-#include "blargg_endian.h"
-
-typedef blargg_long cpu_time_t;
-
-// must be defined by caller
-void ay_cpu_out( class Ay_Cpu*, cpu_time_t, unsigned addr, int data );
-int ay_cpu_in( class Ay_Cpu*, unsigned addr );
-
-class Ay_Cpu {
-public:
- // Clear all registers and keep pointer to 64K memory passed in
- void reset( void* mem_64k );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( cpu_time_t end_time );
-
- // Time of beginning of next instruction
- cpu_time_t time() const { return state->time + state->base; }
-
- // Alter current time. Not supported during run() call.
- void set_time( cpu_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- typedef BOOST::uint8_t uint8_t;
- typedef BOOST::uint16_t uint16_t;
-
- #if BLARGG_BIG_ENDIAN
- struct regs_t { uint8_t b, c, d, e, h, l, flags, a; };
- #else
- struct regs_t { uint8_t c, b, e, d, l, h, a, flags; };
- #endif
- BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
-
- struct pairs_t { uint16_t bc, de, hl, fa; };
-
- // Registers are not updated until run() returns
- struct registers_t {
- uint16_t pc;
- uint16_t sp;
- uint16_t ix;
- uint16_t iy;
- union {
- regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
- pairs_t w; // w.bc, w.de, w.hl. w.fa
- };
- union {
- regs_t b;
- pairs_t w;
- } alt;
- uint8_t iff1;
- uint8_t iff2;
- uint8_t r;
- uint8_t i;
- uint8_t im;
- };
- //registers_t r; (below for efficiency)
-
- // can read this far past end of memory
- enum { cpu_padding = 0x100 };
-
-public:
- Ay_Cpu();
-private:
- uint8_t szpc [0x200];
- uint8_t* mem;
- cpu_time_t end_time_;
- struct state_t {
- cpu_time_t base;
- cpu_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- void set_end_time( cpu_time_t t );
-public:
- registers_t r;
-};
-
-inline void Ay_Cpu::set_end_time( cpu_time_t t )
-{
- cpu_time_t delta = state->base - t;
- state->base = t;
- state->time += delta;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.cpp
deleted file mode 100644
index 7f2c0613..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Ay_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-#include <stdio.h>
-
-long const spectrum_clock = 3546900;
-long const cpc_clock = 2000000;
-
-unsigned const ram_start = 0x4000;
-int const osc_count = Ay_Apu::osc_count + 1;
-
-Ay_Emu::Ay_Emu()
-{
- beeper_output = 0;
- set_type( gme_ay_type );
-
- static const char* const names [osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Beeper"
- };
- set_voice_names( names );
-
- static int const types [osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2, mixed_type | 0
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
-}
-
-Ay_Emu::~Ay_Emu() { }
-
-// Track info
-
-static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int min_size )
-{
- long pos = ptr - (byte const*) file.header;
- long file_size = file.end - (byte const*) file.header;
- assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
- int offset = (BOOST::int16_t) get_be16( ptr );
- if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) )
- return 0;
- return ptr + offset;
-}
-
-static blargg_err_t parse_header( byte const* in, long size, Ay_Emu::file_t* out )
-{
- typedef Ay_Emu::header_t header_t;
- out->header = (header_t const*) in;
- out->end = in + size;
-
- if ( size < Ay_Emu::header_size )
- return gme_wrong_file_type;
-
- header_t const& h = *(header_t const*) in;
- if ( memcmp( h.tag, "ZXAYEMUL", 8 ) )
- return gme_wrong_file_type;
-
- out->tracks = get_data( *out, h.track_info, (h.max_track + 1) * 4 );
- if ( !out->tracks )
- return "Missing track data";
-
- return 0;
-}
-
-static void copy_ay_fields( Ay_Emu::file_t const& file, track_info_t* out, int track )
-{
- Gme_File::copy_field_( out->song, (char const*) get_data( file, file.tracks + track * 4, 1 ) );
- byte const* track_info = get_data( file, file.tracks + track * 4 + 2, 6 );
- if ( track_info )
- out->length = get_be16( track_info + 4 ) * (1000L / 50); // frames to msec
-
- Gme_File::copy_field_( out->author, (char const*) get_data( file, file.header->author, 1 ) );
- Gme_File::copy_field_( out->comment, (char const*) get_data( file, file.header->comment, 1 ) );
-}
-
-blargg_err_t Ay_Emu::track_info_( track_info_t* out, int track ) const
-{
- copy_ay_fields( file, out, track );
- return 0;
-}
-
-struct Ay_File : Gme_Info_
-{
- Ay_Emu::file_t file;
-
- Ay_File() { set_type( gme_ay_type ); }
-
- blargg_err_t load_mem_( byte const* begin, long size )
- {
- RETURN_ERR( parse_header( begin, size, &file ) );
- set_track_count( file.header->max_track + 1 );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- copy_ay_fields( file, out, track );
- return 0;
- }
-};
-
-static Music_Emu* new_ay_emu () { return BLARGG_NEW Ay_Emu ; }
-static Music_Emu* new_ay_file() { return BLARGG_NEW Ay_File; }
-
-static gme_type_t_ const gme_ay_type_ = { "ZX Spectrum", 0, &new_ay_emu, &new_ay_file, "AY", 1 };
-gme_type_t const gme_ay_type = &gme_ay_type_;
-
-// Setup
-
-blargg_err_t Ay_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,track_info [2]) == header_size );
-
- RETURN_ERR( parse_header( in, size, &file ) );
- set_track_count( file.header->max_track + 1 );
-
- if ( file.header->vers > 2 )
- set_warning( "Unknown file version" );
-
- set_voice_count( osc_count );
- apu.volume( gain() );
-
- return setup_buffer( spectrum_clock );
-}
-
-void Ay_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Ay_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer*, Blip_Buffer* )
-{
- if ( i >= Ay_Apu::osc_count )
- beeper_output = center;
- else
- apu.osc_output( i, center );
-}
-
-// Emulation
-
-void Ay_Emu::set_tempo_( double t )
-{
- play_period = blip_time_t (clock_rate() / 50 / t);
-}
-
-blargg_err_t Ay_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( mem.ram + 0x0000, 0xC9, 0x100 ); // fill RST vectors with RET
- memset( mem.ram + 0x0100, 0xFF, 0x4000 - 0x100 );
- memset( mem.ram + ram_start, 0x00, sizeof mem.ram - ram_start );
- memset( mem.padding1, 0xFF, sizeof mem.padding1 );
- memset( mem.ram + 0x10000, 0xFF, sizeof mem.ram - 0x10000 );
-
- // locate data blocks
- byte const* const data = get_data( file, file.tracks + track * 4 + 2, 14 );
- if ( !data ) return "File data missing";
-
- byte const* const more_data = get_data( file, data + 10, 6 );
- if ( !more_data ) return "File data missing";
-
- byte const* blocks = get_data( file, data + 12, 8 );
- if ( !blocks ) return "File data missing";
-
- // initial addresses
- cpu::reset( mem.ram );
- r.sp = get_be16( more_data );
- r.b.a = r.b.b = r.b.d = r.b.h = data [8];
- r.b.flags = r.b.c = r.b.e = r.b.l = data [9];
- r.alt.w = r.w;
- r.ix = r.iy = r.w.hl;
-
- unsigned addr = get_be16( blocks );
- if ( !addr ) return "File data missing";
-
- unsigned init = get_be16( more_data + 2 );
- if ( !init )
- init = addr;
-
- // copy blocks into memory
- do
- {
- blocks += 2;
- unsigned len = get_be16( blocks ); blocks += 2;
- if ( addr + len > 0x10000 )
- {
- set_warning( "Bad data block size" );
- len = 0x10000 - addr;
- }
- check( len );
- byte const* in = get_data( file, blocks, 0 ); blocks += 2;
- if ( len > blargg_ulong (file.end - in) )
- {
- set_warning( "Missing file data" );
- len = file.end - in;
- }
- //debug_printf( "addr: $%04X, len: $%04X\n", addr, len );
- if ( addr < ram_start && addr >= 0x400 ) // several tracks use low data
- debug_printf( "Block addr in ROM\n" );
-
- if (!in) {
- return "NULL in pointer\n";
- }
- memcpy( mem.ram + addr, in, len );
-
- if ( file.end - blocks < 8 )
- {
- set_warning( "Missing file data" );
- break;
- }
- }
- while ( (addr = get_be16( blocks )) != 0 );
-
- // copy and configure driver
- static byte const passive [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x5E, // LOOP: IM 2
- 0xFB, // EI
- 0x76, // HALT
- 0x18, 0xFA // JR LOOP
- };
- static byte const active [] = {
- 0xF3, // DI
- 0xCD, 0, 0, // CALL init
- 0xED, 0x56, // LOOP: IM 1
- 0xFB, // EI
- 0x76, // HALT
- 0xCD, 0, 0, // CALL play
- 0x18, 0xF7 // JR LOOP
- };
- memcpy( mem.ram, passive, sizeof passive );
- unsigned play_addr = get_be16( more_data + 4 );
- //debug_printf( "Play: $%04X\n", play_addr );
- if ( play_addr )
- {
- memcpy( mem.ram, active, sizeof active );
- mem.ram [ 9] = play_addr;
- mem.ram [10] = play_addr >> 8;
- }
- mem.ram [2] = init;
- mem.ram [3] = init >> 8;
-
- mem.ram [0x38] = 0xFB; // Put EI at interrupt vector (followed by RET)
-
- memcpy( mem.ram + 0x10000, mem.ram, 0x80 ); // some code wraps around (ugh)
-
- beeper_delta = int (apu.amp_range * 0.65);
- last_beeper = 0;
- apu.reset();
- next_play = play_period;
-
- // start at spectrum speed
- change_clock_rate( spectrum_clock );
- set_tempo( tempo() );
-
- spectrum_mode = false;
- cpc_mode = false;
- cpc_latch = 0;
-
- return 0;
-}
-
-// Emulation
-
-void Ay_Emu::cpu_out_misc( cpu_time_t time, unsigned addr, int data )
-{
- if ( !cpc_mode )
- {
- switch ( addr & 0xFEFF )
- {
- case 0xFEFD:
- spectrum_mode = true;
- apu_addr = data & 0x0F;
- return;
-
- case 0xBEFD:
- spectrum_mode = true;
- apu.write( time, apu_addr, data );
- return;
- }
- }
-
- if ( !spectrum_mode )
- {
- switch ( addr >> 8 )
- {
- case 0xF6:
- switch ( data & 0xC0 )
- {
- case 0xC0:
- apu_addr = cpc_latch & 0x0F;
- goto enable_cpc;
-
- case 0x80:
- apu.write( time, apu_addr, cpc_latch );
- goto enable_cpc;
- }
- break;
-
- case 0xF4:
- cpc_latch = data;
- goto enable_cpc;
- }
- }
-
- debug_printf( "Unmapped OUT: $%04X <- $%02X\n", addr, data );
- return;
-
-enable_cpc:
- if ( !cpc_mode )
- {
- cpc_mode = true;
- change_clock_rate( cpc_clock );
- set_tempo( tempo() );
- }
-}
-
-void ay_cpu_out( Ay_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
- Ay_Emu& emu = STATIC_CAST(Ay_Emu&,*cpu);
-
- if ( (addr & 0xFF) == 0xFE && !emu.cpc_mode )
- {
- int delta = emu.beeper_delta;
- data &= 0x10;
- if ( emu.last_beeper != data )
- {
- emu.last_beeper = data;
- emu.beeper_delta = -delta;
- emu.spectrum_mode = true;
- if ( emu.beeper_output )
- emu.apu.synth_.offset( time, delta, emu.beeper_output );
- }
- }
- else
- {
- emu.cpu_out_misc( time, addr, data );
- }
-}
-
-int ay_cpu_in( Ay_Cpu*, unsigned addr )
-{
- // keyboard read and other things
- if ( (addr & 0xFF) == 0xFE )
- return 0xFF; // other values break some beeper tunes
-
- debug_printf( "Unmapped IN : $%04X\n", addr );
- return 0xFF;
-}
-
-blargg_err_t Ay_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- if ( !(spectrum_mode | cpc_mode) )
- duration /= 2; // until mode is set, leave room for halved clock rate
-
- while ( time() < duration )
- {
- cpu::run( min( duration, (blip_time_t) next_play ) );
-
- if ( time() >= next_play )
- {
- next_play += play_period;
-
- if ( r.iff1 )
- {
- if ( mem.ram [r.pc] == 0x76 )
- r.pc++;
-
- r.iff1 = r.iff2 = 0;
-
- mem.ram [--r.sp] = uint8_t (r.pc >> 8);
- mem.ram [--r.sp] = uint8_t (r.pc);
- r.pc = 0x38;
- cpu::adjust_time( 12 );
- if ( r.im == 2 )
- {
- cpu::adjust_time( 6 );
- unsigned addr = r.i * 0x100u + 0xFF;
- r.pc = mem.ram [(addr + 1) & 0xFFFF] * 0x100u + mem.ram [addr];
- }
- }
- }
- }
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- adjust_time( -duration );
-
- apu.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.h
deleted file mode 100644
index 8cd2231d..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ay_Emu.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Sinclair Spectrum AY music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef AY_EMU_H
-#define AY_EMU_H
-
-#include "Classic_Emu.h"
-#include "Ay_Apu.h"
-#include "Ay_Cpu.h"
-
-class Ay_Emu : private Ay_Cpu, public Classic_Emu {
- typedef Ay_Cpu cpu;
-public:
- // AY file header
- enum { header_size = 0x14 };
- struct header_t
- {
- byte tag [8];
- byte vers;
- byte player;
- byte unused [2];
- byte author [2];
- byte comment [2];
- byte max_track;
- byte first_track;
- byte track_info [2];
- };
-
- static gme_type_t static_type() { return gme_ay_type; }
-public:
- Ay_Emu();
- ~Ay_Emu();
- struct file_t {
- header_t const* header;
- byte const* end;
- byte const* tracks;
- };
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-private:
- file_t file;
-
- unsigned play_addr;
- cpu_time_t play_period;
- cpu_time_t next_play;
- Blip_Buffer* beeper_output;
- int beeper_delta;
- int last_beeper;
- int apu_addr;
- int cpc_latch;
- bool spectrum_mode;
- bool cpc_mode;
-
- // large items
- struct {
- byte padding1 [0x100];
- byte ram [0x10000 + 0x100];
- } mem;
- Ay_Apu apu;
- friend void ay_cpu_out( Ay_Cpu*, cpu_time_t, unsigned addr, int data );
- void cpu_out_misc( cpu_time_t, unsigned addr, int data );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp
deleted file mode 100644
index 9dc89ea8..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Blip_Buffer.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
- factor_ = (blip_ulong)-1 / 2;
- offset_ = 0;
- buffer_ = 0;
- buffer_size_ = 0;
- sample_rate_ = 0;
- reader_accum_ = 0;
- bass_shift_ = 0;
- clock_rate_ = 0;
- bass_freq_ = 16;
- length_ = 0;
-
- // assumptions code makes about implementation-defined features
- #ifndef NDEBUG
- // right shift of negative value preserves sign
- buf_t_ i = -0x7FFFFFFE;
- assert( (i >> 1) == -0x3FFFFFFF );
-
- // casting to short truncates to 16 bits and sign-extends
- i = 0x18000;
- assert( (short) i == -0x8000 );
- #endif
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
- if ( buffer_size_ != silent_buf_size )
- free( buffer_ );
-}
-
-Silent_Blip_Buffer::Silent_Blip_Buffer()
-{
- factor_ = 0;
- buffer_ = buf;
- buffer_size_ = silent_buf_size;
- memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
-}
-
-void Blip_Buffer::clear( int entire_buffer )
-{
- offset_ = 0;
- reader_accum_ = 0;
- modified_ = 0;
- if ( buffer_ )
- {
- long count = (entire_buffer ? buffer_size_ : samples_avail());
- memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
- }
-}
-
-Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return "Internal (tried to resize Silent_Blip_Buffer)";
- }
-
- // start with maximum length that resampled time can represent
- long new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
- if ( msec != blip_max_length )
- {
- long s = (new_rate * (msec + 1) + 999) / 1000;
- if ( s < new_size )
- new_size = s;
- else
- assert( 0 ); // fails if requested buffer length exceeds limit
- }
-
- if ( buffer_size_ != new_size )
- {
- void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- if ( !p )
- return "Out of memory";
- buffer_ = (buf_t_*) p;
- }
-
- buffer_size_ = new_size;
- assert( buffer_size_ != silent_buf_size );
-
- // update things based on the sample rate
- sample_rate_ = new_rate;
- length_ = new_size * 1000 / new_rate - 1;
- if ( msec )
- assert( length_ == msec ); // ensure length is same as that passed in
- if ( clock_rate_ )
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
-
- clear();
-
- return 0; // success
-}
-
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
-{
- double ratio = (double) sample_rate_ / rate;
- blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
- assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
- return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- int shift = 31;
- if ( freq > 0 )
- {
- shift = 13;
- long f = (freq << 16) / sample_rate_;
- while ( (f >>= 1) && --shift ) { }
- }
- bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
- offset_ += t * factor_;
- assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
-}
-
-void Blip_Buffer::remove_silence( long count )
-{
- assert( count <= samples_avail() ); // tried to remove more samples than available
- offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const
-{
- unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
- unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
- return (long) (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( long count ) const
-{
- if ( !factor_ )
- {
- assert( 0 ); // sample rate and clock rates must be set first
- return 0;
- }
-
- if ( count > buffer_size_ )
- count = buffer_size_;
- blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
- return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
- if ( count )
- {
- remove_silence( count );
-
- // copy remaining samples to beginning and clear old samples
- long remain = samples_avail() + blip_buffer_extra_;
- memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
- memset( buffer_ + remain, 0, count * sizeof *buffer_ );
- }
-}
-
-// Blip_Synth_
-
-Blip_Synth_Fast_::Blip_Synth_Fast_()
-{
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
- delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
-}
-
-#if !BLIP_BUFFER_FAST
-
-Blip_Synth_::Blip_Synth_( short* p, int w ) :
- impulses( p ),
- width( w )
-{
- volume_unit_ = 0.0;
- kernel_unit = 0;
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
-{
- if ( cutoff >= 0.999 )
- cutoff = 0.999;
-
- if ( treble < -300.0 )
- treble = -300.0;
- if ( treble > 5.0 )
- treble = 5.0;
-
- double const maxh = 4096.0;
- double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
- double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
- double const to_angle = PI / 2 / maxh / oversample;
- for ( int i = 0; i < count; i++ )
- {
- double angle = ((i - count) * 2 + 1) * to_angle;
- double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
- double cos_nc_angle = cos( maxh * cutoff * angle );
- double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
- double cos_angle = cos( angle );
-
- c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
- double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
- double b = 2.0 - cos_angle - cos_angle;
- double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
-
- out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
- }
-}
-
-void blip_eq_t::generate( float* out, int count ) const
-{
- // lower cutoff freq for narrow kernels with their wider transition band
- // (8 points->1.49, 16 points->1.15)
- double oversample = blip_res * 2.25 / count + 0.85;
- double half_rate = sample_rate * 0.5;
- if ( cutoff_freq )
- oversample = half_rate / cutoff_freq;
- double cutoff = rolloff_freq * oversample / half_rate;
-
- gen_sinc( out, count, blip_res * oversample, treble, cutoff );
-
- // apply (half of) hamming window
- double to_fraction = PI / (count - 1);
- for ( int i = count; i--; )
- out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
-}
-
-void Blip_Synth_::adjust_impulse()
-{
- // sum pairs for each phase and add error correction to end of first half
- int const size = impulses_size();
- for ( int p = blip_res; p-- >= blip_res / 2; )
- {
- int p2 = blip_res - 2 - p;
- long error = kernel_unit;
- for ( int i = 1; i < size; i += blip_res )
- {
- error -= impulses [i + p ];
- error -= impulses [i + p2];
- }
- if ( p == p2 )
- error /= 2; // phase = 0.5 impulse uses same half for both sides
- impulses [size - blip_res + p] += (short) error;
- //printf( "error: %ld\n", error );
- }
-
- //for ( int i = blip_res; i--; printf( "\n" ) )
- // for ( int j = 0; j < width / 2; j++ )
- // printf( "%5ld,", impulses [j * blip_res + i + 1] );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
- float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
-
- int const half_size = blip_res / 2 * (width - 1);
- eq.generate( &fimpulse [blip_res], half_size );
-
- int i;
-
- // need mirror slightly past center for calculation
- for ( i = blip_res; i--; )
- fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
-
- // starts at 0
- for ( i = 0; i < blip_res; i++ )
- fimpulse [i] = 0.0f;
-
- // find rescale factor
- double total = 0.0;
- for ( i = 0; i < half_size; i++ )
- total += fimpulse [blip_res + i];
-
- //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
- //double const base_unit = 37888.0; // allows treble to +5 dB
- double const base_unit = 32768.0; // necessary for blip_unscaled to work
- double rescale = base_unit / 2 / total;
- kernel_unit = (long) base_unit;
-
- // integrate, first difference, rescale, convert to int
- double sum = 0.0;
- double next = 0.0;
- int const impulses_size = this->impulses_size();
- for ( i = 0; i < impulses_size; i++ )
- {
- impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
- sum += fimpulse [i];
- next += fimpulse [i + blip_res];
- }
- adjust_impulse();
-
- // volume might require rescaling
- double vol = volume_unit_;
- if ( vol )
- {
- volume_unit_ = 0.0;
- volume_unit( vol );
- }
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
- if ( new_unit != volume_unit_ )
- {
- // use default eq if it hasn't been set yet
- if ( !kernel_unit )
- treble_eq( -8.0 );
-
- volume_unit_ = new_unit;
- double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
-
- if ( factor > 0.0 )
- {
- int shift = 0;
-
- // if unit is really small, might need to attenuate kernel
- while ( factor < 2.0 )
- {
- shift++;
- factor *= 2.0;
- }
-
- if ( shift )
- {
- kernel_unit >>= shift;
- assert( kernel_unit > 0 ); // fails if volume unit is too low
-
- // keep values positive to avoid round-towards-zero of sign-preserving
- // right shift for negative values
- long offset = 0x8000 + (1 << (shift - 1));
- long offset2 = 0x8000 >> shift;
- for ( int i = impulses_size(); i--; )
- impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
- adjust_impulse();
- }
- }
- delta_factor = (int) floor( factor + 0.5 );
- //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
- }
-}
-#endif
-
-long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
-{
- long count = samples_avail();
- if ( count > max_samples )
- count = max_samples;
-
- if ( count )
- {
- int const bass = BLIP_READER_BASS( *this );
- BLIP_READER_BEGIN( reader, *this );
-
- if ( !stereo )
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out++ = (blip_sample_t) s;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- else
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out = (blip_sample_t) s;
- out += 2;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- BLIP_READER_END( reader, *this );
-
- remove_samples( count );
- }
- return count;
-}
-
-void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return;
- }
-
- buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
-
- int const sample_shift = blip_sample_bits - 16;
- int prev = 0;
- while ( count-- )
- {
- blip_long s = (blip_long) *in++ << sample_shift;
- *out += s - prev;
- prev = s;
- ++out;
- }
- *out -= prev;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.orig b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.orig
deleted file mode 100644
index 9dc89ea8..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.orig
+++ /dev/null
@@ -1,446 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Blip_Buffer.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
-
-Blip_Buffer::Blip_Buffer()
-{
- factor_ = (blip_ulong)-1 / 2;
- offset_ = 0;
- buffer_ = 0;
- buffer_size_ = 0;
- sample_rate_ = 0;
- reader_accum_ = 0;
- bass_shift_ = 0;
- clock_rate_ = 0;
- bass_freq_ = 16;
- length_ = 0;
-
- // assumptions code makes about implementation-defined features
- #ifndef NDEBUG
- // right shift of negative value preserves sign
- buf_t_ i = -0x7FFFFFFE;
- assert( (i >> 1) == -0x3FFFFFFF );
-
- // casting to short truncates to 16 bits and sign-extends
- i = 0x18000;
- assert( (short) i == -0x8000 );
- #endif
-}
-
-Blip_Buffer::~Blip_Buffer()
-{
- if ( buffer_size_ != silent_buf_size )
- free( buffer_ );
-}
-
-Silent_Blip_Buffer::Silent_Blip_Buffer()
-{
- factor_ = 0;
- buffer_ = buf;
- buffer_size_ = silent_buf_size;
- memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
-}
-
-void Blip_Buffer::clear( int entire_buffer )
-{
- offset_ = 0;
- reader_accum_ = 0;
- modified_ = 0;
- if ( buffer_ )
- {
- long count = (entire_buffer ? buffer_size_ : samples_avail());
- memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
- }
-}
-
-Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return "Internal (tried to resize Silent_Blip_Buffer)";
- }
-
- // start with maximum length that resampled time can represent
- long new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
- if ( msec != blip_max_length )
- {
- long s = (new_rate * (msec + 1) + 999) / 1000;
- if ( s < new_size )
- new_size = s;
- else
- assert( 0 ); // fails if requested buffer length exceeds limit
- }
-
- if ( buffer_size_ != new_size )
- {
- void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
- if ( !p )
- return "Out of memory";
- buffer_ = (buf_t_*) p;
- }
-
- buffer_size_ = new_size;
- assert( buffer_size_ != silent_buf_size );
-
- // update things based on the sample rate
- sample_rate_ = new_rate;
- length_ = new_size * 1000 / new_rate - 1;
- if ( msec )
- assert( length_ == msec ); // ensure length is same as that passed in
- if ( clock_rate_ )
- clock_rate( clock_rate_ );
- bass_freq( bass_freq_ );
-
- clear();
-
- return 0; // success
-}
-
-blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
-{
- double ratio = (double) sample_rate_ / rate;
- blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
- assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
- return (blip_resampled_time_t) factor;
-}
-
-void Blip_Buffer::bass_freq( int freq )
-{
- bass_freq_ = freq;
- int shift = 31;
- if ( freq > 0 )
- {
- shift = 13;
- long f = (freq << 16) / sample_rate_;
- while ( (f >>= 1) && --shift ) { }
- }
- bass_shift_ = shift;
-}
-
-void Blip_Buffer::end_frame( blip_time_t t )
-{
- offset_ += t * factor_;
- assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
-}
-
-void Blip_Buffer::remove_silence( long count )
-{
- assert( count <= samples_avail() ); // tried to remove more samples than available
- offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
-}
-
-long Blip_Buffer::count_samples( blip_time_t t ) const
-{
- unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
- unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
- return (long) (last_sample - first_sample);
-}
-
-blip_time_t Blip_Buffer::count_clocks( long count ) const
-{
- if ( !factor_ )
- {
- assert( 0 ); // sample rate and clock rates must be set first
- return 0;
- }
-
- if ( count > buffer_size_ )
- count = buffer_size_;
- blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
- return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
-}
-
-void Blip_Buffer::remove_samples( long count )
-{
- if ( count )
- {
- remove_silence( count );
-
- // copy remaining samples to beginning and clear old samples
- long remain = samples_avail() + blip_buffer_extra_;
- memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
- memset( buffer_ + remain, 0, count * sizeof *buffer_ );
- }
-}
-
-// Blip_Synth_
-
-Blip_Synth_Fast_::Blip_Synth_Fast_()
-{
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-void Blip_Synth_Fast_::volume_unit( double new_unit )
-{
- delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
-}
-
-#if !BLIP_BUFFER_FAST
-
-Blip_Synth_::Blip_Synth_( short* p, int w ) :
- impulses( p ),
- width( w )
-{
- volume_unit_ = 0.0;
- kernel_unit = 0;
- buf = 0;
- last_amp = 0;
- delta_factor = 0;
-}
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
-{
- if ( cutoff >= 0.999 )
- cutoff = 0.999;
-
- if ( treble < -300.0 )
- treble = -300.0;
- if ( treble > 5.0 )
- treble = 5.0;
-
- double const maxh = 4096.0;
- double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
- double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
- double const to_angle = PI / 2 / maxh / oversample;
- for ( int i = 0; i < count; i++ )
- {
- double angle = ((i - count) * 2 + 1) * to_angle;
- double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
- double cos_nc_angle = cos( maxh * cutoff * angle );
- double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
- double cos_angle = cos( angle );
-
- c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
- double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
- double b = 2.0 - cos_angle - cos_angle;
- double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
-
- out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
- }
-}
-
-void blip_eq_t::generate( float* out, int count ) const
-{
- // lower cutoff freq for narrow kernels with their wider transition band
- // (8 points->1.49, 16 points->1.15)
- double oversample = blip_res * 2.25 / count + 0.85;
- double half_rate = sample_rate * 0.5;
- if ( cutoff_freq )
- oversample = half_rate / cutoff_freq;
- double cutoff = rolloff_freq * oversample / half_rate;
-
- gen_sinc( out, count, blip_res * oversample, treble, cutoff );
-
- // apply (half of) hamming window
- double to_fraction = PI / (count - 1);
- for ( int i = count; i--; )
- out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
-}
-
-void Blip_Synth_::adjust_impulse()
-{
- // sum pairs for each phase and add error correction to end of first half
- int const size = impulses_size();
- for ( int p = blip_res; p-- >= blip_res / 2; )
- {
- int p2 = blip_res - 2 - p;
- long error = kernel_unit;
- for ( int i = 1; i < size; i += blip_res )
- {
- error -= impulses [i + p ];
- error -= impulses [i + p2];
- }
- if ( p == p2 )
- error /= 2; // phase = 0.5 impulse uses same half for both sides
- impulses [size - blip_res + p] += (short) error;
- //printf( "error: %ld\n", error );
- }
-
- //for ( int i = blip_res; i--; printf( "\n" ) )
- // for ( int j = 0; j < width / 2; j++ )
- // printf( "%5ld,", impulses [j * blip_res + i + 1] );
-}
-
-void Blip_Synth_::treble_eq( blip_eq_t const& eq )
-{
- float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
-
- int const half_size = blip_res / 2 * (width - 1);
- eq.generate( &fimpulse [blip_res], half_size );
-
- int i;
-
- // need mirror slightly past center for calculation
- for ( i = blip_res; i--; )
- fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
-
- // starts at 0
- for ( i = 0; i < blip_res; i++ )
- fimpulse [i] = 0.0f;
-
- // find rescale factor
- double total = 0.0;
- for ( i = 0; i < half_size; i++ )
- total += fimpulse [blip_res + i];
-
- //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
- //double const base_unit = 37888.0; // allows treble to +5 dB
- double const base_unit = 32768.0; // necessary for blip_unscaled to work
- double rescale = base_unit / 2 / total;
- kernel_unit = (long) base_unit;
-
- // integrate, first difference, rescale, convert to int
- double sum = 0.0;
- double next = 0.0;
- int const impulses_size = this->impulses_size();
- for ( i = 0; i < impulses_size; i++ )
- {
- impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
- sum += fimpulse [i];
- next += fimpulse [i + blip_res];
- }
- adjust_impulse();
-
- // volume might require rescaling
- double vol = volume_unit_;
- if ( vol )
- {
- volume_unit_ = 0.0;
- volume_unit( vol );
- }
-}
-
-void Blip_Synth_::volume_unit( double new_unit )
-{
- if ( new_unit != volume_unit_ )
- {
- // use default eq if it hasn't been set yet
- if ( !kernel_unit )
- treble_eq( -8.0 );
-
- volume_unit_ = new_unit;
- double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
-
- if ( factor > 0.0 )
- {
- int shift = 0;
-
- // if unit is really small, might need to attenuate kernel
- while ( factor < 2.0 )
- {
- shift++;
- factor *= 2.0;
- }
-
- if ( shift )
- {
- kernel_unit >>= shift;
- assert( kernel_unit > 0 ); // fails if volume unit is too low
-
- // keep values positive to avoid round-towards-zero of sign-preserving
- // right shift for negative values
- long offset = 0x8000 + (1 << (shift - 1));
- long offset2 = 0x8000 >> shift;
- for ( int i = impulses_size(); i--; )
- impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
- adjust_impulse();
- }
- }
- delta_factor = (int) floor( factor + 0.5 );
- //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
- }
-}
-#endif
-
-long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
-{
- long count = samples_avail();
- if ( count > max_samples )
- count = max_samples;
-
- if ( count )
- {
- int const bass = BLIP_READER_BASS( *this );
- BLIP_READER_BEGIN( reader, *this );
-
- if ( !stereo )
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out++ = (blip_sample_t) s;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- else
- {
- for ( blip_long n = count; n; --n )
- {
- blip_long s = BLIP_READER_READ( reader );
- if ( (blip_sample_t) s != s )
- s = 0x7FFF - (s >> 24);
- *out = (blip_sample_t) s;
- out += 2;
- BLIP_READER_NEXT( reader, bass );
- }
- }
- BLIP_READER_END( reader, *this );
-
- remove_samples( count );
- }
- return count;
-}
-
-void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
-{
- if ( buffer_size_ == silent_buf_size )
- {
- assert( 0 );
- return;
- }
-
- buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
-
- int const sample_shift = blip_sample_bits - 16;
- int prev = 0;
- while ( count-- )
- {
- blip_long s = (blip_long) *in++ << sample_shift;
- *out += s - prev;
- prev = s;
- ++out;
- }
- *out -= prev;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.rej b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.rej
deleted file mode 100644
index 64b81cab..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.cpp.rej
+++ /dev/null
@@ -1,11 +0,0 @@
---- /home/waker/Downloads/Game_Music_Emu-0.5.2//gme/Blip_Buffer.cpp 2006-12-11 17:13:57.000000000 +0100
-+++ .//gme/Blip_Buffer.cpp 2010-05-09 20:40:36.000000000 +0200
-@@ -27,7 +27,7 @@
-
- Blip_Buffer::Blip_Buffer()
- {
-- factor_ = LONG_MAX;
-+ factor_ = 0x7fffffff;
- offset_ = 0;
- buffer_ = 0;
- buffer_size_ = 0;
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h
deleted file mode 100644
index 4cc526d2..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h
+++ /dev/null
@@ -1,488 +0,0 @@
-// Band-limited sound synthesis buffer
-
-// Blip_Buffer 0.4.1
-#ifndef BLIP_BUFFER_H
-#define BLIP_BUFFER_H
-
- // internal
- #include <limits.h>
- #if INT_MAX < 0x7FFFFFFF
- #error "int must be at least 32 bits"
- #endif
-
- typedef int blip_long;
- typedef unsigned blip_ulong;
-
-// Time unit at source clock rate
-typedef blip_long blip_time_t;
-
-// Output samples are 16-bit signed, with a range of -32768 to 32767
-typedef short blip_sample_t;
-enum { blip_sample_max = 32767 };
-
-class Blip_Buffer {
-public:
- typedef const char* blargg_err_t;
-
- // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
- // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
- // isn't enough memory, returns error without affecting current buffer setup.
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
-
- // Set number of source time units per second
- void clock_rate( long );
-
- // End current time frame of specified duration and make its samples available
- // (along with any still-unread samples) for reading with read_samples(). Begins
- // a new time frame at the end of the current frame.
- void end_frame( blip_time_t time );
-
- // Read at most 'max_samples' out of buffer into 'dest', removing them from from
- // the buffer. Returns number of samples actually read and removed. If stereo is
- // true, increments 'dest' one extra time after writing each sample, to allow
- // easy interleving of two channels into a stereo output buffer.
- long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
-
-// Additional optional features
-
- // Current output sample rate
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // Number of source time units per second
- long clock_rate() const;
-
- // Set frequency high-pass filter frequency, where higher values reduce bass more
- void bass_freq( int frequency );
-
- // Number of samples delay from synthesis to samples read out
- int output_latency() const;
-
- // Remove all available samples and clear buffer to silence. If 'entire_buffer' is
- // false, just clears out any samples waiting rather than the entire buffer.
- void clear( int entire_buffer = 1 );
-
- // Number of samples available for reading with read_samples()
- long samples_avail() const;
-
- // Remove 'count' samples from those waiting to be read
- void remove_samples( long count );
-
-// Experimental features
-
- // Count number of clocks needed until 'count' samples will be available.
- // If buffer can't even hold 'count' samples, returns number of clocks until
- // buffer becomes full.
- blip_time_t count_clocks( long count ) const;
-
- // Number of raw samples that can be mixed within frame of specified duration.
- long count_samples( blip_time_t duration ) const;
-
- // Mix 'count' samples from 'buf' into buffer.
- void mix_samples( blip_sample_t const* buf, long count );
-
- // not documented yet
- void set_modified() { modified_ = 1; }
- int clear_modified() { int b = modified_; modified_ = 0; return b; }
- typedef blip_ulong blip_resampled_time_t;
- void remove_silence( long count );
- blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
- blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
- blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
-public:
- Blip_Buffer();
- ~Blip_Buffer();
-
- // Deprecated
- typedef blip_resampled_time_t resampled_time_t;
- blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
- blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
-private:
- // noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-public:
- typedef blip_time_t buf_t_;
- blip_ulong factor_;
- blip_resampled_time_t offset_;
- buf_t_* buffer_;
- blip_long buffer_size_;
- blip_long reader_accum_;
- int bass_shift_;
-private:
- long sample_rate_;
- long clock_rate_;
- int bass_freq_;
- int length_;
- int modified_;
- friend class Blip_Reader;
-};
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
-// but reduce maximum buffer size.
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
-
-// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
-// noticeable broadband noise when synthesizing high frequency square waves.
-// Affects size of Blip_Synth objects since they store the waveform directly.
-#ifndef BLIP_PHASE_BITS
- #if BLIP_BUFFER_FAST
- #define BLIP_PHASE_BITS 8
- #else
- #define BLIP_PHASE_BITS 6
- #endif
-#endif
-
- // Internal
- typedef blip_ulong blip_resampled_time_t;
- int const blip_widest_impulse_ = 16;
- int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
- int const blip_res = 1 << BLIP_PHASE_BITS;
- class blip_eq_t;
-
- class Blip_Synth_Fast_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_Fast_();
- void treble_eq( blip_eq_t const& ) { }
- };
-
- class Blip_Synth_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_( short* impulses, int width );
- void treble_eq( blip_eq_t const& );
- private:
- double volume_unit_;
- short* const impulses;
- int const width;
- blip_long kernel_unit;
- int impulses_size() const { return blip_res / 2 * width + 1; }
- void adjust_impulse();
- };
-
-// Quality level. Start with blip_good_quality.
-const int blip_med_quality = 8;
-const int blip_good_quality = 12;
-const int blip_high_quality = 16;
-
-// Range specifies the greatest expected change in amplitude. Calculate it
-// by finding the difference between the maximum and minimum expected
-// amplitudes (max - min).
-template<int quality,int range>
-class Blip_Synth {
-public:
- // Set overall volume of waveform
- void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
-
- // Configure low-pass filter (see blip_buffer.txt)
- void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
-
- // Get/set Blip_Buffer used for output
- Blip_Buffer* output() const { return impl.buf; }
- void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
-
- // Update amplitude of waveform at given time. Using this requires a separate
- // Blip_Synth for each waveform.
- void update( blip_time_t time, int amplitude );
-
-// Low-level interface
-
- // Add an amplitude transition of specified delta, optionally into specified buffer
- // rather than the one set with output(). Delta can be positive or negative.
- // The actual change in amplitude is delta * (volume / range)
- void offset( blip_time_t, int delta, Blip_Buffer* ) const;
- void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
-
- // Works directly in terms of fractional output samples. Contact author for more info.
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
-
- // Same as offset(), except code is inlined for higher performance
- void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
- }
- void offset_inline( blip_time_t t, int delta ) const {
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
- }
-
-private:
-#if BLIP_BUFFER_FAST
- Blip_Synth_Fast_ impl;
-#else
- Blip_Synth_ impl;
- typedef short imp_t;
- imp_t impulses [blip_res * (quality / 2) + 1];
-public:
- Blip_Synth() : impl( impulses, quality ) { }
-#endif
-};
-
-// Low-pass equalization parameters
-class blip_eq_t {
-public:
- // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
- // treble, small positive values (0 to 5.0) increase treble.
- blip_eq_t( double treble_db = 0 );
-
- // See blip_buffer.txt
- blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
-
-private:
- double treble;
- long rolloff_freq;
- long sample_rate;
- long cutoff_freq;
- void generate( float* out, int count ) const;
- friend class Blip_Synth_;
-};
-
-int const blip_sample_bits = 30;
-
-// Dummy Blip_Buffer to direct sound output to, for easy muting without
-// having to stop sound code.
-class Silent_Blip_Buffer : public Blip_Buffer {
- buf_t_ buf [blip_buffer_extra_ + 1];
-public:
- // The following cannot be used (an assertion will fail if attempted):
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
- blip_time_t count_clocks( long count ) const;
- void mix_samples( blip_sample_t const* buf, long count );
-
- Silent_Blip_Buffer();
-};
-
- #if defined (__GNUC__) || _MSC_VER >= 1100
- #define BLIP_RESTRICT __restrict
- #else
- #define BLIP_RESTRICT
- #endif
-
-// Optimized reading from Blip_Buffer, for use in custom sample output
-
-// Begin reading from buffer. Name should be unique to the current block.
-#define BLIP_READER_BEGIN( name, blip_buffer ) \
- const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
- blip_long name##_reader_accum = (blip_buffer).reader_accum_
-
-// Get value to pass to BLIP_READER_NEXT()
-#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
-
-// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
-// code at the cost of having no bass control
-int const blip_reader_default_bass = 9;
-
-// Current sample
-#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
-
-// Current raw sample in full internal resolution
-#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
-
-// Advance to next sample
-#define BLIP_READER_NEXT( name, bass ) \
- (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
-
-// End reading samples from buffer. The number of samples read must now be removed
-// using Blip_Buffer::remove_samples().
-#define BLIP_READER_END( name, blip_buffer ) \
- (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
-
-
-// Compatibility with older version
-const long blip_unscaled = 65535;
-const int blip_low_quality = blip_med_quality;
-const int blip_best_quality = blip_high_quality;
-
-// Deprecated; use BLIP_READER macros as follows:
-// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
-// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
-// r.read() -> BLIP_READER_READ( r )
-// r.read_raw() -> BLIP_READER_READ_RAW( r )
-// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
-// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
-// r.end( buf ) -> BLIP_READER_END( r, buf )
-class Blip_Reader {
-public:
- int begin( Blip_Buffer& );
- blip_long read() const { return accum >> (blip_sample_bits - 16); }
- blip_long read_raw() const { return accum; }
- void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
- void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
-
-private:
- const Blip_Buffer::buf_t_* buf;
- blip_long accum;
-};
-
-// End of public interface
-
-#include <assert.h>
-
-template<int quality,int range>
-inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
- int delta, Blip_Buffer* blip_buf ) const
-{
- // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
- // need for a longer buffer as set by set_sample_rate().
- assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
- delta *= impl.delta_factor;
- blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
- int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
-
-#if BLIP_BUFFER_FAST
- blip_long left = buf [0] + delta;
-
- // Kind of crappy, but doing shift after multiply results in overflow.
- // Alternate way of delaying multiply by delta_factor results in worse
- // sub-sample resolution.
- blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
- left -= right;
- right += buf [1];
-
- buf [0] = left;
- buf [1] = right;
-#else
-
- int const fwd = (blip_widest_impulse_ - quality) / 2;
- int const rev = fwd + quality - 2;
- int const mid = quality / 2 - 1;
-
- imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
-
- #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
-
- // straight forward implementation resulted in better code on GCC for x86
-
- #define ADD_IMP( out, in ) \
- buf [out] += (blip_long) imp [blip_res * (in)] * delta
-
- #define BLIP_FWD( i ) {\
- ADD_IMP( fwd + i, i );\
- ADD_IMP( fwd + 1 + i, i + 1 );\
- }
- #define BLIP_REV( r ) {\
- ADD_IMP( rev - r, r + 1 );\
- ADD_IMP( rev + 1 - r, r );\
- }
-
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- ADD_IMP( fwd + mid - 1, mid - 1 );
- ADD_IMP( fwd + mid , mid );
- imp = impulses + phase;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- ADD_IMP( rev , 1 );
- ADD_IMP( rev + 1, 0 );
-
- #else
-
- // for RISC processors, help compiler by reading ahead of writes
-
- #define BLIP_FWD( i ) {\
- blip_long t0 = i0 * delta + buf [fwd + i];\
- blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
- i0 = imp [blip_res * (i + 2)];\
- buf [fwd + i] = t0;\
- buf [fwd + 1 + i] = t1;\
- }
- #define BLIP_REV( r ) {\
- blip_long t0 = i0 * delta + buf [rev - r];\
- blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
- i0 = imp [blip_res * (r - 1)];\
- buf [rev - r] = t0;\
- buf [rev + 1 - r] = t1;\
- }
-
- blip_long i0 = *imp;
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- blip_long t0 = i0 * delta + buf [fwd + mid - 1];
- blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
- imp = impulses + phase;
- i0 = imp [blip_res * mid];
- buf [fwd + mid - 1] = t0;
- buf [fwd + mid ] = t1;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- blip_long t0 = i0 * delta + buf [rev ];
- blip_long t1 = *imp * delta + buf [rev + 1];
- buf [rev ] = t0;
- buf [rev + 1] = t1;
- #endif
-
-#endif
-}
-
-#undef BLIP_FWD
-#undef BLIP_REV
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
-{
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
-}
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
-{
- int delta = amp - impl.last_amp;
- impl.last_amp = amp;
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
-}
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
-inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
- treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
-
-inline int Blip_Buffer::length() const { return length_; }
-inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
-inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
-inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
-inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
-inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
-
-inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
-{
- buf = blip_buf.buffer_;
- accum = blip_buf.reader_accum_;
- return blip_buf.bass_shift_;
-}
-
-int const blip_max_length = 0;
-int const blip_default_length = 250;
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.orig b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.orig
deleted file mode 100644
index 4cc526d2..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.orig
+++ /dev/null
@@ -1,488 +0,0 @@
-// Band-limited sound synthesis buffer
-
-// Blip_Buffer 0.4.1
-#ifndef BLIP_BUFFER_H
-#define BLIP_BUFFER_H
-
- // internal
- #include <limits.h>
- #if INT_MAX < 0x7FFFFFFF
- #error "int must be at least 32 bits"
- #endif
-
- typedef int blip_long;
- typedef unsigned blip_ulong;
-
-// Time unit at source clock rate
-typedef blip_long blip_time_t;
-
-// Output samples are 16-bit signed, with a range of -32768 to 32767
-typedef short blip_sample_t;
-enum { blip_sample_max = 32767 };
-
-class Blip_Buffer {
-public:
- typedef const char* blargg_err_t;
-
- // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
- // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
- // isn't enough memory, returns error without affecting current buffer setup.
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
-
- // Set number of source time units per second
- void clock_rate( long );
-
- // End current time frame of specified duration and make its samples available
- // (along with any still-unread samples) for reading with read_samples(). Begins
- // a new time frame at the end of the current frame.
- void end_frame( blip_time_t time );
-
- // Read at most 'max_samples' out of buffer into 'dest', removing them from from
- // the buffer. Returns number of samples actually read and removed. If stereo is
- // true, increments 'dest' one extra time after writing each sample, to allow
- // easy interleving of two channels into a stereo output buffer.
- long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
-
-// Additional optional features
-
- // Current output sample rate
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // Number of source time units per second
- long clock_rate() const;
-
- // Set frequency high-pass filter frequency, where higher values reduce bass more
- void bass_freq( int frequency );
-
- // Number of samples delay from synthesis to samples read out
- int output_latency() const;
-
- // Remove all available samples and clear buffer to silence. If 'entire_buffer' is
- // false, just clears out any samples waiting rather than the entire buffer.
- void clear( int entire_buffer = 1 );
-
- // Number of samples available for reading with read_samples()
- long samples_avail() const;
-
- // Remove 'count' samples from those waiting to be read
- void remove_samples( long count );
-
-// Experimental features
-
- // Count number of clocks needed until 'count' samples will be available.
- // If buffer can't even hold 'count' samples, returns number of clocks until
- // buffer becomes full.
- blip_time_t count_clocks( long count ) const;
-
- // Number of raw samples that can be mixed within frame of specified duration.
- long count_samples( blip_time_t duration ) const;
-
- // Mix 'count' samples from 'buf' into buffer.
- void mix_samples( blip_sample_t const* buf, long count );
-
- // not documented yet
- void set_modified() { modified_ = 1; }
- int clear_modified() { int b = modified_; modified_ = 0; return b; }
- typedef blip_ulong blip_resampled_time_t;
- void remove_silence( long count );
- blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
- blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
- blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
-public:
- Blip_Buffer();
- ~Blip_Buffer();
-
- // Deprecated
- typedef blip_resampled_time_t resampled_time_t;
- blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
- blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
-private:
- // noncopyable
- Blip_Buffer( const Blip_Buffer& );
- Blip_Buffer& operator = ( const Blip_Buffer& );
-public:
- typedef blip_time_t buf_t_;
- blip_ulong factor_;
- blip_resampled_time_t offset_;
- buf_t_* buffer_;
- blip_long buffer_size_;
- blip_long reader_accum_;
- int bass_shift_;
-private:
- long sample_rate_;
- long clock_rate_;
- int bass_freq_;
- int length_;
- int modified_;
- friend class Blip_Reader;
-};
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
-// but reduce maximum buffer size.
-#ifndef BLIP_BUFFER_ACCURACY
- #define BLIP_BUFFER_ACCURACY 16
-#endif
-
-// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
-// noticeable broadband noise when synthesizing high frequency square waves.
-// Affects size of Blip_Synth objects since they store the waveform directly.
-#ifndef BLIP_PHASE_BITS
- #if BLIP_BUFFER_FAST
- #define BLIP_PHASE_BITS 8
- #else
- #define BLIP_PHASE_BITS 6
- #endif
-#endif
-
- // Internal
- typedef blip_ulong blip_resampled_time_t;
- int const blip_widest_impulse_ = 16;
- int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
- int const blip_res = 1 << BLIP_PHASE_BITS;
- class blip_eq_t;
-
- class Blip_Synth_Fast_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_Fast_();
- void treble_eq( blip_eq_t const& ) { }
- };
-
- class Blip_Synth_ {
- public:
- Blip_Buffer* buf;
- int last_amp;
- int delta_factor;
-
- void volume_unit( double );
- Blip_Synth_( short* impulses, int width );
- void treble_eq( blip_eq_t const& );
- private:
- double volume_unit_;
- short* const impulses;
- int const width;
- blip_long kernel_unit;
- int impulses_size() const { return blip_res / 2 * width + 1; }
- void adjust_impulse();
- };
-
-// Quality level. Start with blip_good_quality.
-const int blip_med_quality = 8;
-const int blip_good_quality = 12;
-const int blip_high_quality = 16;
-
-// Range specifies the greatest expected change in amplitude. Calculate it
-// by finding the difference between the maximum and minimum expected
-// amplitudes (max - min).
-template<int quality,int range>
-class Blip_Synth {
-public:
- // Set overall volume of waveform
- void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
-
- // Configure low-pass filter (see blip_buffer.txt)
- void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
-
- // Get/set Blip_Buffer used for output
- Blip_Buffer* output() const { return impl.buf; }
- void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
-
- // Update amplitude of waveform at given time. Using this requires a separate
- // Blip_Synth for each waveform.
- void update( blip_time_t time, int amplitude );
-
-// Low-level interface
-
- // Add an amplitude transition of specified delta, optionally into specified buffer
- // rather than the one set with output(). Delta can be positive or negative.
- // The actual change in amplitude is delta * (volume / range)
- void offset( blip_time_t, int delta, Blip_Buffer* ) const;
- void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
-
- // Works directly in terms of fractional output samples. Contact author for more info.
- void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
-
- // Same as offset(), except code is inlined for higher performance
- void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
- }
- void offset_inline( blip_time_t t, int delta ) const {
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
- }
-
-private:
-#if BLIP_BUFFER_FAST
- Blip_Synth_Fast_ impl;
-#else
- Blip_Synth_ impl;
- typedef short imp_t;
- imp_t impulses [blip_res * (quality / 2) + 1];
-public:
- Blip_Synth() : impl( impulses, quality ) { }
-#endif
-};
-
-// Low-pass equalization parameters
-class blip_eq_t {
-public:
- // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
- // treble, small positive values (0 to 5.0) increase treble.
- blip_eq_t( double treble_db = 0 );
-
- // See blip_buffer.txt
- blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
-
-private:
- double treble;
- long rolloff_freq;
- long sample_rate;
- long cutoff_freq;
- void generate( float* out, int count ) const;
- friend class Blip_Synth_;
-};
-
-int const blip_sample_bits = 30;
-
-// Dummy Blip_Buffer to direct sound output to, for easy muting without
-// having to stop sound code.
-class Silent_Blip_Buffer : public Blip_Buffer {
- buf_t_ buf [blip_buffer_extra_ + 1];
-public:
- // The following cannot be used (an assertion will fail if attempted):
- blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
- blip_time_t count_clocks( long count ) const;
- void mix_samples( blip_sample_t const* buf, long count );
-
- Silent_Blip_Buffer();
-};
-
- #if defined (__GNUC__) || _MSC_VER >= 1100
- #define BLIP_RESTRICT __restrict
- #else
- #define BLIP_RESTRICT
- #endif
-
-// Optimized reading from Blip_Buffer, for use in custom sample output
-
-// Begin reading from buffer. Name should be unique to the current block.
-#define BLIP_READER_BEGIN( name, blip_buffer ) \
- const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
- blip_long name##_reader_accum = (blip_buffer).reader_accum_
-
-// Get value to pass to BLIP_READER_NEXT()
-#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
-
-// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
-// code at the cost of having no bass control
-int const blip_reader_default_bass = 9;
-
-// Current sample
-#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
-
-// Current raw sample in full internal resolution
-#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
-
-// Advance to next sample
-#define BLIP_READER_NEXT( name, bass ) \
- (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
-
-// End reading samples from buffer. The number of samples read must now be removed
-// using Blip_Buffer::remove_samples().
-#define BLIP_READER_END( name, blip_buffer ) \
- (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
-
-
-// Compatibility with older version
-const long blip_unscaled = 65535;
-const int blip_low_quality = blip_med_quality;
-const int blip_best_quality = blip_high_quality;
-
-// Deprecated; use BLIP_READER macros as follows:
-// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
-// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
-// r.read() -> BLIP_READER_READ( r )
-// r.read_raw() -> BLIP_READER_READ_RAW( r )
-// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
-// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
-// r.end( buf ) -> BLIP_READER_END( r, buf )
-class Blip_Reader {
-public:
- int begin( Blip_Buffer& );
- blip_long read() const { return accum >> (blip_sample_bits - 16); }
- blip_long read_raw() const { return accum; }
- void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
- void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
-
-private:
- const Blip_Buffer::buf_t_* buf;
- blip_long accum;
-};
-
-// End of public interface
-
-#include <assert.h>
-
-template<int quality,int range>
-inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
- int delta, Blip_Buffer* blip_buf ) const
-{
- // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
- // need for a longer buffer as set by set_sample_rate().
- assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
- delta *= impl.delta_factor;
- blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
- int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
-
-#if BLIP_BUFFER_FAST
- blip_long left = buf [0] + delta;
-
- // Kind of crappy, but doing shift after multiply results in overflow.
- // Alternate way of delaying multiply by delta_factor results in worse
- // sub-sample resolution.
- blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
- left -= right;
- right += buf [1];
-
- buf [0] = left;
- buf [1] = right;
-#else
-
- int const fwd = (blip_widest_impulse_ - quality) / 2;
- int const rev = fwd + quality - 2;
- int const mid = quality / 2 - 1;
-
- imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
-
- #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
-
- // straight forward implementation resulted in better code on GCC for x86
-
- #define ADD_IMP( out, in ) \
- buf [out] += (blip_long) imp [blip_res * (in)] * delta
-
- #define BLIP_FWD( i ) {\
- ADD_IMP( fwd + i, i );\
- ADD_IMP( fwd + 1 + i, i + 1 );\
- }
- #define BLIP_REV( r ) {\
- ADD_IMP( rev - r, r + 1 );\
- ADD_IMP( rev + 1 - r, r );\
- }
-
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- ADD_IMP( fwd + mid - 1, mid - 1 );
- ADD_IMP( fwd + mid , mid );
- imp = impulses + phase;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- ADD_IMP( rev , 1 );
- ADD_IMP( rev + 1, 0 );
-
- #else
-
- // for RISC processors, help compiler by reading ahead of writes
-
- #define BLIP_FWD( i ) {\
- blip_long t0 = i0 * delta + buf [fwd + i];\
- blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
- i0 = imp [blip_res * (i + 2)];\
- buf [fwd + i] = t0;\
- buf [fwd + 1 + i] = t1;\
- }
- #define BLIP_REV( r ) {\
- blip_long t0 = i0 * delta + buf [rev - r];\
- blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
- i0 = imp [blip_res * (r - 1)];\
- buf [rev - r] = t0;\
- buf [rev + 1 - r] = t1;\
- }
-
- blip_long i0 = *imp;
- BLIP_FWD( 0 )
- if ( quality > 8 ) BLIP_FWD( 2 )
- if ( quality > 12 ) BLIP_FWD( 4 )
- {
- blip_long t0 = i0 * delta + buf [fwd + mid - 1];
- blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
- imp = impulses + phase;
- i0 = imp [blip_res * mid];
- buf [fwd + mid - 1] = t0;
- buf [fwd + mid ] = t1;
- }
- if ( quality > 12 ) BLIP_REV( 6 )
- if ( quality > 8 ) BLIP_REV( 4 )
- BLIP_REV( 2 )
-
- blip_long t0 = i0 * delta + buf [rev ];
- blip_long t1 = *imp * delta + buf [rev + 1];
- buf [rev ] = t0;
- buf [rev + 1] = t1;
- #endif
-
-#endif
-}
-
-#undef BLIP_FWD
-#undef BLIP_REV
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
-{
- offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
-}
-
-template<int quality,int range>
-#if BLIP_BUFFER_FAST
- inline
-#endif
-void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
-{
- int delta = amp - impl.last_amp;
- impl.last_amp = amp;
- offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
-}
-
-inline blip_eq_t::blip_eq_t( double t ) :
- treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
-inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
- treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
-
-inline int Blip_Buffer::length() const { return length_; }
-inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
-inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
-inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
-inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
-inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
-
-inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
-{
- buf = blip_buf.buffer_;
- accum = blip_buf.reader_accum_;
- return blip_buf.bass_shift_;
-}
-
-int const blip_max_length = 0;
-int const blip_default_length = 250;
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.rej b/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.rej
deleted file mode 100644
index 27e9d6c5..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Blip_Buffer.h.rej
+++ /dev/null
@@ -1,23 +0,0 @@
---- /home/waker/Downloads/Game_Music_Emu-0.5.2//gme/Blip_Buffer.h 2006-12-07 21:16:54.000000000 +0100
-+++ .//gme/Blip_Buffer.h 2010-05-09 20:40:36.000000000 +0200
-@@ -4,15 +4,11 @@
- #ifndef BLIP_BUFFER_H
- #define BLIP_BUFFER_H
-
-- // internal
-- #include <limits.h>
-- #if INT_MAX >= 0x7FFFFFFF
-- typedef int blip_long;
-- typedef unsigned blip_ulong;
-- #else
-- typedef long blip_long;
-- typedef unsigned long blip_ulong;
-- #endif
-+// internal
-+#include <limits.h>
-+#include <stdint.h>
-+typedef int32_t blip_long;
-+typedef uint32_t blip_ulong;
-
- // Time unit at source clock rate
- typedef blip_long blip_time_t;
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.cpp
deleted file mode 100644
index 9b68a445..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Classic_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Classic_Emu::Classic_Emu()
-{
- buf = 0;
- stereo_buffer = 0;
- voice_types = 0;
-
- // avoid inconsistency in our duplicated constants
- assert( (int) wave_type == (int) Multi_Buffer::wave_type );
- assert( (int) noise_type == (int) Multi_Buffer::noise_type );
- assert( (int) mixed_type == (int) Multi_Buffer::mixed_type );
-}
-
-Classic_Emu::~Classic_Emu()
-{
- delete stereo_buffer;
-}
-
-void Classic_Emu::set_equalizer_( equalizer_t const& eq )
-{
- Music_Emu::set_equalizer_( eq );
- update_eq( eq.treble );
- if ( buf )
- buf->bass_freq( (int) equalizer().bass );
-}
-
-blargg_err_t Classic_Emu::set_sample_rate_( long rate )
-{
- if ( !buf )
- {
- if ( !stereo_buffer )
- CHECK_ALLOC( stereo_buffer = BLARGG_NEW Stereo_Buffer );
- buf = stereo_buffer;
- }
- return buf->set_sample_rate( rate, 1000 / 20 );
-}
-
-void Classic_Emu::mute_voices_( int mask )
-{
- Music_Emu::mute_voices_( mask );
- for ( int i = voice_count(); i--; )
- {
- if ( mask & (1 << i) )
- {
- set_voice( i, 0, 0, 0 );
- }
- else
- {
- Multi_Buffer::channel_t ch = buf->channel( i, (voice_types ? voice_types [i] : 0) );
- assert( (ch.center && ch.left && ch.right) ||
- (!ch.center && !ch.left && !ch.right) ); // all or nothing
- set_voice( i, ch.center, ch.left, ch.right );
- }
- }
-}
-
-void Classic_Emu::change_clock_rate( long rate )
-{
- clock_rate_ = rate;
- buf->clock_rate( rate );
-}
-
-blargg_err_t Classic_Emu::setup_buffer( long rate )
-{
- change_clock_rate( rate );
- RETURN_ERR( buf->set_channel_count( voice_count() ) );
- set_equalizer( equalizer() );
- buf_changed_count = buf->channels_changed_count();
- return 0;
-}
-
-blargg_err_t Classic_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- buf->clear();
- return 0;
-}
-
-blargg_err_t Classic_Emu::play_( long count, sample_t* out )
-{
- long remain = count;
- while ( remain )
- {
- remain -= buf->read_samples( &out [count - remain], remain );
- if ( remain )
- {
- if ( buf_changed_count != buf->channels_changed_count() )
- {
- buf_changed_count = buf->channels_changed_count();
- remute_voices();
- }
- int msec = buf->length();
- blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000;
- RETURN_ERR( run_clocks( clocks_emulated, msec ) );
- assert( clocks_emulated );
- buf->end_frame( clocks_emulated );
- }
- }
- return 0;
-}
-
-// Rom_Data
-
-blargg_err_t Rom_Data_::load_rom_data_( Data_Reader& in,
- int header_size, void* header_out, int fill, long pad_size )
-{
- long file_offset = pad_size - header_size;
-
- rom_addr = 0;
- mask = 0;
- size_ = 0;
- rom.clear();
-
- file_size_ = in.remain();
- if ( file_size_ <= header_size ) // <= because there must be data after header
- return gme_wrong_file_type;
- blargg_err_t err = rom.resize( file_offset + file_size_ + pad_size );
- if ( !err )
- err = in.read( rom.begin() + file_offset, file_size_ );
- if ( err )
- {
- rom.clear();
- return err;
- }
-
- file_size_ -= header_size;
- memcpy( header_out, &rom [file_offset], header_size );
-
- memset( rom.begin() , fill, pad_size );
- memset( rom.end() - pad_size, fill, pad_size );
-
- return 0;
-}
-
-void Rom_Data_::set_addr_( long addr, int unit )
-{
- rom_addr = addr - unit - pad_extra;
-
- long rounded = (addr + file_size_ + unit - 1) / unit * unit;
- if ( rounded <= 0 )
- {
- rounded = 0;
- }
- else
- {
- int shift = 0;
- unsigned long max_addr = (unsigned long) (rounded - 1);
- while ( max_addr >> shift )
- shift++;
- mask = (1L << shift) - 1;
- }
-
- if ( addr < 0 )
- addr = 0;
- size_ = rounded;
- if ( rom.resize( rounded - rom_addr + pad_extra ) ) { } // OK if shrink fails
-
- if ( 0 )
- {
- debug_printf( "addr: %X\n", addr );
- debug_printf( "file_size: %d\n", file_size_ );
- debug_printf( "rounded: %d\n", rounded );
- debug_printf( "mask: $%X\n", mask );
- }
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.h
deleted file mode 100644
index d0cfda25..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Classic_Emu.h
+++ /dev/null
@@ -1,127 +0,0 @@
-// Common aspects of emulators which use Blip_Buffer for sound output
-
-// Game_Music_Emu 0.5.5
-#ifndef CLASSIC_EMU_H
-#define CLASSIC_EMU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-#include "Music_Emu.h"
-
-class Classic_Emu : public Music_Emu {
-public:
- Classic_Emu();
- ~Classic_Emu();
- void set_buffer( Multi_Buffer* );
-protected:
- // Services
- enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
- void set_voice_types( int const* t ) { voice_types = t; }
- blargg_err_t setup_buffer( long clock_rate );
- long clock_rate() const { return clock_rate_; }
- void change_clock_rate( long ); // experimental
-
- // Overridable
- virtual void set_voice( int index, Blip_Buffer* center,
- Blip_Buffer* left, Blip_Buffer* right ) = 0;
- virtual void update_eq( blip_eq_t const& ) = 0;
- virtual blargg_err_t start_track_( int track ) = 0;
- virtual blargg_err_t run_clocks( blip_time_t& time_io, int msec ) = 0;
-protected:
- blargg_err_t set_sample_rate_( long sample_rate );
- void mute_voices_( int );
- void set_equalizer_( equalizer_t const& );
- blargg_err_t play_( long, sample_t* );
-private:
- Multi_Buffer* buf;
- Multi_Buffer* stereo_buffer; // NULL if using custom buffer
- long clock_rate_;
- unsigned buf_changed_count;
- int const* voice_types;
-};
-
-inline void Classic_Emu::set_buffer( Multi_Buffer* new_buf )
-{
- assert( !buf && new_buf );
- buf = new_buf;
-}
-
-// ROM data handler, used by several Classic_Emu derivitives. Loads file data
-// with padding on both sides, allowing direct use in bank mapping. The main purpose
-// is to allow all file data to be loaded with only one read() call (for efficiency).
-
-class Rom_Data_ {
-public:
- typedef unsigned char byte;
-protected:
- enum { pad_extra = 8 };
- blargg_vector<byte> rom;
- long file_size_;
- blargg_long rom_addr;
- blargg_long mask;
- blargg_long size_; // TODO: eliminate
-
- blargg_err_t load_rom_data_( Data_Reader& in, int header_size, void* header_out,
- int fill, long pad_size );
- void set_addr_( long addr, int unit );
-};
-
-template<int unit>
-class Rom_Data : public Rom_Data_ {
- enum { pad_size = unit + pad_extra };
-public:
- // Load file data, using already-loaded header 'h' if not NULL. Copy header
- // from loaded file data into *out and fill unmapped bytes with 'fill'.
- blargg_err_t load( Data_Reader& in, int header_size, void* header_out, int fill )
- {
- return load_rom_data_( in, header_size, header_out, fill, pad_size );
- }
-
- // Size of file data read in (excluding header)
- long file_size() const { return file_size_; }
-
- // Pointer to beginning of file data
- byte* begin() const { return rom.begin() + pad_size; }
-
- // Set address that file data should start at
- void set_addr( long addr ) { set_addr_( addr, unit ); }
-
- // Free data
- void clear() { rom.clear(); }
-
- // Size of data + start addr, rounded to a multiple of unit
- long size() const { return size_; }
-
- // Pointer to unmapped page filled with same value
- byte* unmapped() { return rom.begin(); }
-
- // Mask address to nearest power of two greater than size()
- blargg_long mask_addr( blargg_long addr ) const
- {
- #ifdef check
- check( addr <= mask );
- #endif
- return addr & mask;
- }
-
- // Pointer to page starting at addr. Returns unmapped() if outside data.
- byte* at_addr( blargg_long addr )
- {
- blargg_ulong offset = mask_addr( addr ) - rom_addr;
- if ( offset > blargg_ulong (rom.size() - pad_size) )
- offset = 0; // unmapped
- return &rom [offset];
- }
-};
-
-#ifndef GME_APU_HOOK
- #define GME_APU_HOOK( emu, addr, data ) ((void) 0)
-#endif
-
-#ifndef GME_FRAME_HOOK
- #define GME_FRAME_HOOK( emu ) ((void) 0)
-#else
- #define GME_FRAME_HOOK_DEFINED 1
-#endif
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.cpp
deleted file mode 100644
index 5bbfbf55..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-// File_Extractor 0.4.0. http://www.slack.net/~ant/
-
-#include "Data_Reader.h"
-
-#include "blargg_endian.h"
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char Data_Reader::eof_error [] = "Unexpected end of file";
-
-blargg_err_t Data_Reader::read( void* p, long s )
-{
- long result = read_avail( p, s );
- if ( result != s )
- {
- if ( result >= 0 && result < s )
- return eof_error;
-
- return "Read error";
- }
-
- return 0;
-}
-
-blargg_err_t Data_Reader::skip( long count )
-{
- char buf [512];
- while ( count )
- {
- long n = sizeof buf;
- if ( n > count )
- n = count;
- count -= n;
- RETURN_ERR( read( buf, n ) );
- }
- return 0;
-}
-
-long File_Reader::remain() const { return size() - tell(); }
-
-blargg_err_t File_Reader::skip( long n )
-{
- assert( n >= 0 );
- if ( !n )
- return 0;
- return seek( tell() + n );
-}
-
-// Subset_Reader
-
-Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
-{
- in = dr;
- remain_ = dr->remain();
- if ( remain_ > size )
- remain_ = size;
-}
-
-long Subset_Reader::remain() const { return remain_; }
-
-long Subset_Reader::read_avail( void* p, long s )
-{
- if ( s > remain_ )
- s = remain_;
- remain_ -= s;
- return in->read_avail( p, s );
-}
-
-// Remaining_Reader
-
-Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
-{
- header = (char const*) h;
- header_end = header + size;
- in = r;
-}
-
-long Remaining_Reader::remain() const { return header_end - header + in->remain(); }
-
-long Remaining_Reader::read_first( void* out, long count )
-{
- long first = header_end - header;
- if ( first )
- {
- if ( first > count )
- first = count;
- void const* old = header;
- header += first;
- memcpy( out, old, first );
- }
- return first;
-}
-
-long Remaining_Reader::read_avail( void* out, long count )
-{
- long first = read_first( out, count );
- long second = count - first;
- if ( second )
- {
- second = in->read_avail( (char*) out + first, second );
- if ( second <= 0 )
- return second;
- }
- return first + second;
-}
-
-blargg_err_t Remaining_Reader::read( void* out, long count )
-{
- long first = read_first( out, count );
- long second = count - first;
- if ( !second )
- return 0;
- return in->read( (char*) out + first, second );
-}
-
-// Mem_File_Reader
-
-Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
- begin( (const char*) p ),
- size_( s )
-{
- pos = 0;
-}
-
-long Mem_File_Reader::size() const { return size_; }
-
-long Mem_File_Reader::read_avail( void* p, long s )
-{
- long r = remain();
- if ( s > r )
- s = r;
- memcpy( p, begin + pos, s );
- pos += s;
- return s;
-}
-
-long Mem_File_Reader::tell() const { return pos; }
-
-blargg_err_t Mem_File_Reader::seek( long n )
-{
- if ( n > size_ )
- return eof_error;
- pos = n;
- return 0;
-}
-
-// Callback_Reader
-
-Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
- callback( c ),
- data( d )
-{
- remain_ = size;
-}
-
-long Callback_Reader::remain() const { return remain_; }
-
-long Callback_Reader::read_avail( void* out, long count )
-{
- if ( count > remain_ )
- count = remain_;
- if ( Callback_Reader::read( out, count ) )
- count = -1;
- return count;
-}
-
-blargg_err_t Callback_Reader::read( void* out, long count )
-{
- if ( count > remain_ )
- return eof_error;
- return callback( data, out, count );
-}
-
-// Std_File_Reader
-
-Std_File_Reader::Std_File_Reader() : file_( 0 ) { }
-
-Std_File_Reader::~Std_File_Reader() { close(); }
-
-blargg_err_t Std_File_Reader::open( const char* path )
-{
- file_ = fopen( path, "rb" );
- if ( !file_ )
- return "Couldn't open file";
- return 0;
-}
-
-long Std_File_Reader::size() const
-{
- long pos = tell();
- fseek( (FILE*) file_, 0, SEEK_END );
- long result = tell();
- fseek( (FILE*) file_, pos, SEEK_SET );
- return result;
-}
-
-long Std_File_Reader::read_avail( void* p, long s )
-{
- return fread( p, 1, s, (FILE*) file_ );
-}
-
-blargg_err_t Std_File_Reader::read( void* p, long s )
-{
- if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
- return 0;
- if ( feof( (FILE*) file_ ) )
- return eof_error;
- return "Couldn't read from file";
-}
-
-long Std_File_Reader::tell() const { return ftell( (FILE*) file_ ); }
-
-blargg_err_t Std_File_Reader::seek( long n )
-{
- if ( !fseek( (FILE*) file_, n, SEEK_SET ) )
- return 0;
- if ( n > size() )
- return eof_error;
- return "Error seeking in file";
-}
-
-void Std_File_Reader::close()
-{
- if ( file_ )
- {
- fclose( (FILE*) file_ );
- file_ = 0;
- }
-}
-
-// Gzip_File_Reader
-
-#ifdef HAVE_ZLIB_H
-
-#include "zlib.h"
-
-static const char* get_gzip_eof( const char* path, long* eof )
-{
- FILE* file = fopen( path, "rb" );
- if ( !file )
- return "Couldn't open file";
-
- unsigned char buf [4];
- if ( fread( buf, 2, 1, file ) > 0 && buf [0] == 0x1F && buf [1] == 0x8B )
- {
- fseek( file, -4, SEEK_END );
- fread( buf, 4, 1, file );
- *eof = get_le32( buf );
- }
- else
- {
- fseek( file, 0, SEEK_END );
- *eof = ftell( file );
- }
- const char* err = (ferror( file ) || feof( file )) ? "Couldn't get file size" : 0;
- fclose( file );
- return err;
-}
-
-Gzip_File_Reader::Gzip_File_Reader() : file_( 0 ) { }
-
-Gzip_File_Reader::~Gzip_File_Reader() { close(); }
-
-blargg_err_t Gzip_File_Reader::open( const char* path )
-{
- close();
-
- RETURN_ERR( get_gzip_eof( path, &size_ ) );
-
- file_ = gzopen( path, "rb" );
- if ( !file_ )
- return "Couldn't open file";
-
- return 0;
-}
-
-long Gzip_File_Reader::size() const { return size_; }
-
-long Gzip_File_Reader::read_avail( void* p, long s ) { return gzread( file_, p, s ); }
-
-long Gzip_File_Reader::tell() const { return gztell( file_ ); }
-
-blargg_err_t Gzip_File_Reader::seek( long n )
-{
- if ( gzseek( file_, n, SEEK_SET ) >= 0 )
- return 0;
- if ( n > size_ )
- return eof_error;
- return "Error seeking in file";
-}
-
-void Gzip_File_Reader::close()
-{
- if ( file_ )
- {
- gzclose( file_ );
- file_ = 0;
- }
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.h b/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.h
deleted file mode 100644
index acf571f6..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Data_Reader.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Data reader interface for uniform access
-
-// File_Extractor 0.4.0
-#ifndef DATA_READER_H
-#define DATA_READER_H
-
-#include "blargg_common.h"
-
-// Supports reading and finding out how many bytes are remaining
-class Data_Reader {
-public:
- virtual ~Data_Reader() { }
-
- static const char eof_error []; // returned by read() when request goes beyond end
-
- // Read at most count bytes and return number actually read, or <= 0 if error
- virtual long read_avail( void*, long n ) = 0;
-
- // Read exactly count bytes and return error if they couldn't be read
- virtual blargg_err_t read( void*, long count );
-
- // Number of bytes remaining until end of file
- virtual long remain() const = 0;
-
- // Read and discard count bytes
- virtual blargg_err_t skip( long count );
-
-public:
- Data_Reader() { }
- typedef blargg_err_t error_t; // deprecated
-private:
- // noncopyable
- Data_Reader( const Data_Reader& );
- Data_Reader& operator = ( const Data_Reader& );
-};
-
-// Supports seeking in addition to Data_Reader operations
-class File_Reader : public Data_Reader {
-public:
- // Size of file
- virtual long size() const = 0;
-
- // Current position in file
- virtual long tell() const = 0;
-
- // Go to new position
- virtual blargg_err_t seek( long ) = 0;
-
- long remain() const;
- blargg_err_t skip( long n );
-};
-
-// Disk file reader
-class Std_File_Reader : public File_Reader {
-public:
- blargg_err_t open( const char* path );
- void close();
-
-public:
- Std_File_Reader();
- ~Std_File_Reader();
- long size() const;
- blargg_err_t read( void*, long );
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- void* file_;
-};
-
-// Treats range of memory as a file
-class Mem_File_Reader : public File_Reader {
-public:
- Mem_File_Reader( const void*, long size );
-
-public:
- long size() const;
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- const char* const begin;
- const long size_;
- long pos;
-};
-
-// Makes it look like there are only count bytes remaining
-class Subset_Reader : public Data_Reader {
-public:
- Subset_Reader( Data_Reader*, long count );
-
-public:
- long remain() const;
- long read_avail( void*, long );
-private:
- Data_Reader* in;
- long remain_;
-};
-
-// Joins already-read header and remaining data into original file (to avoid seeking)
-class Remaining_Reader : public Data_Reader {
-public:
- Remaining_Reader( void const* header, long size, Data_Reader* );
-
-public:
- long remain() const;
- long read_avail( void*, long );
- blargg_err_t read( void*, long );
-private:
- char const* header;
- char const* header_end;
- Data_Reader* in;
- long read_first( void* out, long count );
-};
-
-// Invokes callback function to read data. Size of data must be specified in advance.
-class Callback_Reader : public Data_Reader {
-public:
- typedef const char* (*callback_t)( void* data, void* out, int count );
- Callback_Reader( callback_t, long size, void* data = 0 );
-public:
- long read_avail( void*, long );
- blargg_err_t read( void*, long );
- long remain() const;
-private:
- callback_t const callback;
- void* const data;
- long remain_;
-};
-
-#ifdef HAVE_ZLIB_H
-// Gzip compressed file reader
-class Gzip_File_Reader : public File_Reader {
-public:
- blargg_err_t open( const char* path );
- void close();
-
-public:
- Gzip_File_Reader();
- ~Gzip_File_Reader();
- long size() const;
- long read_avail( void*, long );
- long tell() const;
- blargg_err_t seek( long );
-private:
- void* file_;
- long size_;
-};
-#endif
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.cpp
deleted file mode 100644
index 91b48472..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Dual_Resampler.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const resampler_extra = 256;
-
-Dual_Resampler::Dual_Resampler() {
- sample_buf_size = 0;
-}
-
-Dual_Resampler::~Dual_Resampler() { }
-
-blargg_err_t Dual_Resampler::reset( int pairs )
-{
- // expand allocations a bit
- RETURN_ERR( sample_buf.resize( (pairs + (pairs >> 2)) * 2 ) );
- resize( pairs );
- resampler_size = oversamples_per_frame + (oversamples_per_frame >> 2);
- return resampler.buffer_size( resampler_size );
-}
-
-void Dual_Resampler::resize( int pairs )
-{
- int new_sample_buf_size = pairs * 2;
- if ( sample_buf_size != new_sample_buf_size )
- {
- if ( (unsigned) new_sample_buf_size > sample_buf.size() )
- {
- check( false );
- return;
- }
- sample_buf_size = new_sample_buf_size;
- oversamples_per_frame = int (pairs * resampler.ratio()) * 2 + 2;
- clear();
- }
-}
-
-void Dual_Resampler::play_frame_( Blip_Buffer& blip_buf, dsample_t* out )
-{
- long pair_count = sample_buf_size >> 1;
- blip_time_t blip_time = blip_buf.count_clocks( pair_count );
- int sample_count = oversamples_per_frame - resampler.written();
-
- int new_count = play_frame( blip_time, sample_count, resampler.buffer() );
- assert( new_count < resampler_size );
-
- blip_buf.end_frame( blip_time );
- assert( blip_buf.samples_avail() == pair_count );
-
- resampler.write( new_count );
-
- long count = resampler.read( sample_buf.begin(), sample_buf_size );
- assert( count == (long) sample_buf_size );
-
- mix_samples( blip_buf, out );
- blip_buf.remove_samples( pair_count );
-}
-
-void Dual_Resampler::dual_play( long count, dsample_t* out, Blip_Buffer& blip_buf )
-{
- // empty extra buffer
- long remain = sample_buf_size - buf_pos;
- if ( remain )
- {
- if ( remain > count )
- remain = count;
- count -= remain;
- memcpy( out, &sample_buf [buf_pos], remain * sizeof *out );
- out += remain;
- buf_pos += remain;
- }
-
- // entire frames
- while ( count >= (long) sample_buf_size )
- {
- play_frame_( blip_buf, out );
- out += sample_buf_size;
- count -= sample_buf_size;
- }
-
- // extra
- if ( count )
- {
- play_frame_( blip_buf, sample_buf.begin() );
- buf_pos = count;
- memcpy( out, sample_buf.begin(), count * sizeof *out );
- out += count;
- }
-}
-
-void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
-{
- Blip_Reader sn;
- int bass = sn.begin( blip_buf );
- const dsample_t* in = sample_buf.begin();
-
- for ( int n = sample_buf_size >> 1; n--; )
- {
- int s = sn.read();
- blargg_long l = (blargg_long) in [0] * 2 + s;
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- sn.next( bass );
- blargg_long r = (blargg_long) in [1] * 2 + s;
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- in += 2;
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- sn.end( blip_buf );
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.h b/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.h
deleted file mode 100644
index e3194fe7..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Dual_Resampler.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators.
-
-// Game_Music_Emu 0.5.5
-#ifndef DUAL_RESAMPLER_H
-#define DUAL_RESAMPLER_H
-
-#include "Fir_Resampler.h"
-#include "Blip_Buffer.h"
-
-class Dual_Resampler {
-public:
- Dual_Resampler();
- virtual ~Dual_Resampler();
-
- typedef short dsample_t;
-
- double setup( double oversample, double rolloff, double gain );
- blargg_err_t reset( int max_pairs );
- void resize( int pairs_per_frame );
- void clear();
-
- void dual_play( long count, dsample_t* out, Blip_Buffer& );
-
-protected:
- virtual int play_frame( blip_time_t, int pcm_count, dsample_t* pcm_out ) = 0;
-private:
-
- blargg_vector<dsample_t> sample_buf;
- int sample_buf_size;
- int oversamples_per_frame;
- int buf_pos;
- int resampler_size;
-
- Fir_Resampler<12> resampler;
- void mix_samples( Blip_Buffer&, dsample_t* );
- void play_frame_( Blip_Buffer&, dsample_t* );
-};
-
-inline double Dual_Resampler::setup( double oversample, double rolloff, double gain )
-{
- return resampler.time_ratio( oversample, rolloff, gain * 0.5 );
-}
-
-inline void Dual_Resampler::clear()
-{
- buf_pos = sample_buf_size;
- resampler.clear();
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.cpp
deleted file mode 100644
index 181b11e9..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Effects_Buffer.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-typedef blargg_long fixed_t;
-
-#define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5)
-#define FMUL( x, y ) (((x) * (y)) >> 15)
-
-const unsigned echo_size = 4096;
-const unsigned echo_mask = echo_size - 1;
-BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2
-
-const unsigned reverb_size = 8192 * 2;
-const unsigned reverb_mask = reverb_size - 1;
-BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2
-
-Effects_Buffer::config_t::config_t()
-{
- pan_1 = -0.15f;
- pan_2 = 0.15f;
- reverb_delay = 88.0f;
- reverb_level = 0.12f;
- echo_delay = 61.0f;
- echo_level = 0.10f;
- delay_variance = 18.0f;
- effects_enabled = false;
-}
-
-void Effects_Buffer::set_depth( double d )
-{
- float f = (float) d;
- config_t c;
- c.pan_1 = -0.6f * f;
- c.pan_2 = 0.6f * f;
- c.reverb_delay = 880 * 0.1f;
- c.echo_delay = 610 * 0.1f;
- if ( f > 0.5 )
- f = 0.5; // TODO: more linear reduction of extreme reverb/echo
- c.reverb_level = 0.5f * f;
- c.echo_level = 0.30f * f;
- c.delay_variance = 180 * 0.1f;
- c.effects_enabled = (d > 0.0f);
- config( c );
-}
-
-Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 )
-{
- buf_count = center_only ? max_buf_count - 4 : max_buf_count;
-
- echo_pos = 0;
- reverb_pos = 0;
-
- stereo_remain = 0;
- effect_remain = 0;
- effects_enabled = false;
- set_depth( 0 );
-}
-
-Effects_Buffer::~Effects_Buffer() { }
-
-blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec )
-{
- if ( !echo_buf.size() )
- RETURN_ERR( echo_buf.resize( echo_size ) );
-
- if ( !reverb_buf.size() )
- RETURN_ERR( reverb_buf.resize( reverb_size ) );
-
- for ( int i = 0; i < buf_count; i++ )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
-
- config( config_ );
- clear();
-
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Effects_Buffer::clock_rate( long rate )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clock_rate( rate );
-}
-
-void Effects_Buffer::bass_freq( int freq )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].bass_freq( freq );
-}
-
-void Effects_Buffer::clear()
-{
- stereo_remain = 0;
- effect_remain = 0;
- if ( echo_buf.size() )
- memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
-
- if ( reverb_buf.size() )
- memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
-
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clear();
-}
-
-inline int pin_range( int n, int max, int min = 0 )
-{
- if ( n < min )
- return min;
- if ( n > max )
- return max;
- return n;
-}
-
-void Effects_Buffer::config( const config_t& cfg )
-{
- channels_changed();
-
- // clear echo and reverb buffers
- if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf.size() )
- {
- memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] );
- memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] );
- }
-
- config_ = cfg;
-
- if ( config_.effects_enabled )
- {
- // convert to internal format
-
- chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 );
- chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0];
-
- chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 );
- chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0];
-
- chans.reverb_level = TO_FIXED( config_.reverb_level );
- chans.echo_level = TO_FIXED( config_.echo_level );
-
- int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate());
-
- int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate());
- chans.reverb_delay_l = pin_range( reverb_size -
- (reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 );
- chans.reverb_delay_r = pin_range( reverb_size + 1 -
- (reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 );
-
- int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate());
- chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset),
- echo_size - 1 );
- chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset),
- echo_size - 1 );
-
- chan_types [0].center = &bufs [0];
- chan_types [0].left = &bufs [3];
- chan_types [0].right = &bufs [4];
-
- chan_types [1].center = &bufs [1];
- chan_types [1].left = &bufs [3];
- chan_types [1].right = &bufs [4];
-
- chan_types [2].center = &bufs [2];
- chan_types [2].left = &bufs [5];
- chan_types [2].right = &bufs [6];
- assert( 2 < chan_types_count );
- }
- else
- {
- // set up outputs
- for ( unsigned i = 0; i < chan_types_count; i++ )
- {
- channel_t& c = chan_types [i];
- c.center = &bufs [0];
- c.left = &bufs [1];
- c.right = &bufs [2];
- }
- }
-
- if ( buf_count < max_buf_count )
- {
- for ( int i = 0; i < chan_types_count; i++ )
- {
- channel_t& c = chan_types [i];
- c.left = c.center;
- c.right = c.center;
- }
- }
-}
-
-Effects_Buffer::channel_t Effects_Buffer::channel( int i, int type )
-{
- int out = 2;
- if ( !type )
- {
- out = i % 5;
- if ( out > 2 )
- out = 2;
- }
- else if ( !(type & noise_type) && (type & type_index_mask) % 3 != 0 )
- {
- out = type & 1;
- }
- return chan_types [out];
-}
-
-void Effects_Buffer::end_frame( blip_time_t clock_count )
-{
- int bufs_used = 0;
- for ( int i = 0; i < buf_count; i++ )
- {
- bufs_used |= bufs [i].clear_modified() << i;
- bufs [i].end_frame( clock_count );
- }
-
- int stereo_mask = (config_.effects_enabled ? 0x78 : 0x06);
- if ( (bufs_used & stereo_mask) && buf_count == max_buf_count )
- stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
- if ( effects_enabled || config_.effects_enabled )
- effect_remain = bufs [0].samples_avail() + bufs [0].output_latency();
-
- effects_enabled = config_.effects_enabled;
-}
-
-long Effects_Buffer::samples_avail() const
-{
- return bufs [0].samples_avail() * 2;
-}
-
-long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
-{
- require( total_samples % 2 == 0 ); // count must be even
-
- long remain = bufs [0].samples_avail();
- if ( remain > (total_samples >> 1) )
- remain = (total_samples >> 1);
- total_samples = remain;
- while ( remain )
- {
- int active_bufs = buf_count;
- long count = remain;
-
- // optimizing mixing to skip any channels which had nothing added
- if ( effect_remain )
- {
- if ( count > effect_remain )
- count = effect_remain;
-
- if ( stereo_remain )
- {
- mix_enhanced( out, count );
- }
- else
- {
- mix_mono_enhanced( out, count );
- active_bufs = 3;
- }
- }
- else if ( stereo_remain )
- {
- mix_stereo( out, count );
- active_bufs = 3;
- }
- else
- {
- mix_mono( out, count );
- active_bufs = 1;
- }
-
- out += count * 2;
- remain -= count;
-
- stereo_remain -= count;
- if ( stereo_remain < 0 )
- stereo_remain = 0;
-
- effect_remain -= count;
- if ( effect_remain < 0 )
- effect_remain = 0;
-
- for ( int i = 0; i < buf_count; i++ )
- {
- if ( i < active_bufs )
- bufs [i].remove_samples( count );
- else
- bufs [i].remove_silence( count ); // keep time synchronized
- }
- }
-
- return total_samples * 2;
-}
-
-void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( c, bufs [0] );
-
- // unrolled loop
- for ( blargg_long n = count >> 1; n; --n )
- {
- blargg_long cs0 = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
-
- blargg_long cs1 = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
-
- if ( (BOOST::int16_t) cs0 != cs0 )
- cs0 = 0x7FFF - (cs0 >> 24);
- ((BOOST::uint32_t*) out) [0] = ((BOOST::uint16_t) cs0) | (cs0 << 16);
-
- if ( (BOOST::int16_t) cs1 != cs1 )
- cs1 = 0x7FFF - (cs1 >> 24);
- ((BOOST::uint32_t*) out) [1] = ((BOOST::uint16_t) cs1) | (cs1 << 16);
- out += 4;
- }
-
- if ( count & 1 )
- {
- int s = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
- out [0] = s;
- out [1] = s;
- if ( (BOOST::int16_t) s != s )
- {
- s = 0x7FFF - (s >> 24);
- out [0] = s;
- out [1] = s;
- }
- }
-
- BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( c, bufs [0] );
- BLIP_READER_BEGIN( l, bufs [1] );
- BLIP_READER_BEGIN( r, bufs [2] );
-
- while ( count-- )
- {
- int cs = BLIP_READER_READ( c );
- BLIP_READER_NEXT( c, bass );
- int left = cs + BLIP_READER_READ( l );
- int right = cs + BLIP_READER_READ( r );
- BLIP_READER_NEXT( l, bass );
- BLIP_READER_NEXT( r, bass );
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
-
- BLIP_READER_END( r, bufs [2] );
- BLIP_READER_END( l, bufs [1] );
- BLIP_READER_END( c, bufs [0] );
-}
-
-void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [2] );
- BLIP_READER_BEGIN( center, bufs [2] );
- BLIP_READER_BEGIN( sq1, bufs [0] );
- BLIP_READER_BEGIN( sq2, bufs [1] );
-
- blip_sample_t* const reverb_buf = this->reverb_buf.begin();
- blip_sample_t* const echo_buf = this->echo_buf.begin();
- int echo_pos = this->echo_pos;
- int reverb_pos = this->reverb_pos;
-
- while ( count-- )
- {
- int sum1_s = BLIP_READER_READ( sq1 );
- int sum2_s = BLIP_READER_READ( sq2 );
-
- BLIP_READER_NEXT( sq1, bass );
- BLIP_READER_NEXT( sq2, bass );
-
- int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
- FMUL( sum2_s, chans.pan_2_levels [0] ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
- int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
- FMUL( sum2_s, chans.pan_2_levels [1] ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
- fixed_t reverb_level = chans.reverb_level;
- reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
- reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
- reverb_pos = (reverb_pos + 2) & reverb_mask;
-
- int sum3_s = BLIP_READER_READ( center );
- BLIP_READER_NEXT( center, bass );
-
- int left = new_reverb_l + sum3_s + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
- int right = new_reverb_r + sum3_s + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
- echo_buf [echo_pos] = sum3_s;
- echo_pos = (echo_pos + 1) & echo_mask;
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
- this->reverb_pos = reverb_pos;
- this->echo_pos = echo_pos;
-
- BLIP_READER_END( sq1, bufs [0] );
- BLIP_READER_END( sq2, bufs [1] );
- BLIP_READER_END( center, bufs [2] );
-}
-
-void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [2] );
- BLIP_READER_BEGIN( center, bufs [2] );
- BLIP_READER_BEGIN( l1, bufs [3] );
- BLIP_READER_BEGIN( r1, bufs [4] );
- BLIP_READER_BEGIN( l2, bufs [5] );
- BLIP_READER_BEGIN( r2, bufs [6] );
- BLIP_READER_BEGIN( sq1, bufs [0] );
- BLIP_READER_BEGIN( sq2, bufs [1] );
-
- blip_sample_t* const reverb_buf = this->reverb_buf.begin();
- blip_sample_t* const echo_buf = this->echo_buf.begin();
- int echo_pos = this->echo_pos;
- int reverb_pos = this->reverb_pos;
-
- while ( count-- )
- {
- int sum1_s = BLIP_READER_READ( sq1 );
- int sum2_s = BLIP_READER_READ( sq2 );
-
- BLIP_READER_NEXT( sq1, bass );
- BLIP_READER_NEXT( sq2, bass );
-
- int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) +
- FMUL( sum2_s, chans.pan_2_levels [0] ) + BLIP_READER_READ( l1 ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask];
-
- int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) +
- FMUL( sum2_s, chans.pan_2_levels [1] ) + BLIP_READER_READ( r1 ) +
- reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask];
-
- BLIP_READER_NEXT( l1, bass );
- BLIP_READER_NEXT( r1, bass );
-
- fixed_t reverb_level = chans.reverb_level;
- reverb_buf [reverb_pos] = (blip_sample_t) FMUL( new_reverb_l, reverb_level );
- reverb_buf [reverb_pos + 1] = (blip_sample_t) FMUL( new_reverb_r, reverb_level );
- reverb_pos = (reverb_pos + 2) & reverb_mask;
-
- int sum3_s = BLIP_READER_READ( center );
- BLIP_READER_NEXT( center, bass );
-
- int left = new_reverb_l + sum3_s + BLIP_READER_READ( l2 ) + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] );
- int right = new_reverb_r + sum3_s + BLIP_READER_READ( r2 ) + FMUL( chans.echo_level,
- echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] );
-
- BLIP_READER_NEXT( l2, bass );
- BLIP_READER_NEXT( r2, bass );
-
- echo_buf [echo_pos] = sum3_s;
- echo_pos = (echo_pos + 1) & echo_mask;
-
- if ( (BOOST::int16_t) left != left )
- left = 0x7FFF - (left >> 24);
-
- out [0] = left;
- out [1] = right;
-
- out += 2;
-
- if ( (BOOST::int16_t) right != right )
- out [-1] = 0x7FFF - (right >> 24);
- }
- this->reverb_pos = reverb_pos;
- this->echo_pos = echo_pos;
-
- BLIP_READER_END( l1, bufs [3] );
- BLIP_READER_END( r1, bufs [4] );
- BLIP_READER_END( l2, bufs [5] );
- BLIP_READER_END( r2, bufs [6] );
- BLIP_READER_END( sq1, bufs [0] );
- BLIP_READER_END( sq2, bufs [1] );
- BLIP_READER_END( center, bufs [2] );
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.h b/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.h
deleted file mode 100644
index 061f74ab..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Effects_Buffer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Multi-channel effects buffer with panning, echo and reverb
-
-// Game_Music_Emu 0.5.5
-#ifndef EFFECTS_BUFFER_H
-#define EFFECTS_BUFFER_H
-
-#include "Multi_Buffer.h"
-
-// Effects_Buffer uses several buffers and outputs stereo sample pairs.
-class Effects_Buffer : public Multi_Buffer {
-public:
- // If center_only is true, only center buffers are created and
- // less memory is used.
- Effects_Buffer( bool center_only = false );
-
- // Channel Effect Center Pan
- // ---------------------------------
- // 0,5 reverb pan_1
- // 1,6 reverb pan_2
- // 2,7 echo -
- // 3 echo -
- // 4 echo -
-
- // Channel configuration
- struct config_t {
- double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right
- double pan_2;
- double echo_delay; // msec
- double echo_level; // 0.0 to 1.0
- double reverb_delay; // msec
- double delay_variance; // difference between left/right delays (msec)
- double reverb_level; // 0.0 to 1.0
- bool effects_enabled; // if false, use optimized simple mixer
- config_t();
- };
-
- // Set configuration of buffer
- virtual void config( const config_t& );
- void set_depth( double );
-
-public:
- ~Effects_Buffer();
- blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length );
- void clock_rate( long );
- void bass_freq( int );
- void clear();
- channel_t channel( int, int );
- void end_frame( blip_time_t );
- long read_samples( blip_sample_t*, long );
- long samples_avail() const;
-private:
- typedef long fixed_t;
-
- enum { max_buf_count = 7 };
- Blip_Buffer bufs [max_buf_count];
- enum { chan_types_count = 3 };
- channel_t chan_types [3];
- config_t config_;
- long stereo_remain;
- long effect_remain;
- int buf_count;
- bool effects_enabled;
-
- blargg_vector<blip_sample_t> reverb_buf;
- blargg_vector<blip_sample_t> echo_buf;
- int reverb_pos;
- int echo_pos;
-
- struct {
- fixed_t pan_1_levels [2];
- fixed_t pan_2_levels [2];
- int echo_delay_l;
- int echo_delay_r;
- fixed_t echo_level;
- int reverb_delay_l;
- int reverb_delay_r;
- fixed_t reverb_level;
- } chans;
-
- void mix_mono( blip_sample_t*, blargg_long );
- void mix_stereo( blip_sample_t*, blargg_long );
- void mix_enhanced( blip_sample_t*, blargg_long );
- void mix_mono_enhanced( blip_sample_t*, blargg_long );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.cpp
deleted file mode 100644
index f2c905a9..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Fir_Resampler.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#undef PI
-#define PI 3.1415926535897932384626433832795029
-
-static void gen_sinc( double rolloff, int width, double offset, double spacing, double scale,
- int count, short* out )
-{
- double const maxh = 256;
- double const step = PI / maxh * spacing;
- double const to_w = maxh * 2 / width;
- double const pow_a_n = pow( rolloff, maxh );
- scale /= maxh * 2;
-
- double angle = (count / 2 - 1 + offset) * -step;
- while ( count-- )
- {
- *out++ = 0;
- double w = angle * to_w;
- if ( fabs( w ) < PI )
- {
- double rolloff_cos_a = rolloff * cos( angle );
- double num = 1 - rolloff_cos_a -
- pow_a_n * cos( maxh * angle ) +
- pow_a_n * rolloff * cos( (maxh - 1) * angle );
- double den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
- double sinc = scale * num / den - scale;
-
- out [-1] = (short) (cos( w ) * sinc + sinc);
- }
- angle += step;
- }
-}
-
-Fir_Resampler_::Fir_Resampler_( int width, sample_t* impulses_ ) :
- width_( width ),
- write_offset( width * stereo - stereo ),
- impulses( impulses_ )
-{
- write_pos = 0;
- res = 1;
- imp_phase = 0;
- skip_bits = 0;
- step = stereo;
- ratio_ = 1.0;
-}
-
-Fir_Resampler_::~Fir_Resampler_() { }
-
-void Fir_Resampler_::clear()
-{
- imp_phase = 0;
- if ( buf.size() )
- {
- write_pos = &buf [write_offset];
- memset( buf.begin(), 0, write_offset * sizeof buf [0] );
- }
-}
-
-blargg_err_t Fir_Resampler_::buffer_size( int new_size )
-{
- RETURN_ERR( buf.resize( new_size + write_offset ) );
- clear();
- return 0;
-}
-
-double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gain )
-{
- ratio_ = new_factor;
-
- double fstep = 0.0;
- {
- double least_error = 2;
- double pos = 0;
- res = -1;
- for ( int r = 1; r <= max_res; r++ )
- {
- pos += ratio_;
- double nearest = floor( pos + 0.5 );
- double error = fabs( pos - nearest );
- if ( error < least_error )
- {
- res = r;
- fstep = nearest / res;
- least_error = error;
- }
- }
- }
-
- skip_bits = 0;
-
- step = stereo * (int) floor( fstep );
-
- ratio_ = fstep;
- fstep = fmod( fstep, 1.0 );
-
- double filter = (ratio_ < 1.0) ? 1.0 : 1.0 / ratio_;
- double pos = 0.0;
- input_per_cycle = 0;
- for ( int i = 0; i < res; i++ )
- {
- gen_sinc( rolloff, int (width_ * filter + 1) & ~1, pos, filter,
- double (0x7FFF * gain * filter),
- (int) width_, impulses + i * width_ );
-
- pos += fstep;
- input_per_cycle += step;
- if ( pos >= 0.9999999 )
- {
- pos -= 1.0;
- skip_bits |= 1 << i;
- input_per_cycle++;
- }
- }
-
- clear();
-
- return ratio_;
-}
-
-int Fir_Resampler_::input_needed( blargg_long output_count ) const
-{
- blargg_long input_count = 0;
-
- unsigned long skip = skip_bits >> imp_phase;
- int remain = res - imp_phase;
- while ( (output_count -= 2) > 0 )
- {
- input_count += step + (skip & 1) * stereo;
- skip >>= 1;
- if ( !--remain )
- {
- skip = skip_bits;
- remain = res;
- }
- output_count -= 2;
- }
-
- long input_extra = input_count - (write_pos - &buf [(width_ - 1) * stereo]);
- if ( input_extra < 0 )
- input_extra = 0;
- return input_extra;
-}
-
-int Fir_Resampler_::avail_( blargg_long input_count ) const
-{
- int cycle_count = input_count / input_per_cycle;
- int output_count = cycle_count * res * stereo;
- input_count -= cycle_count * input_per_cycle;
-
- blargg_ulong skip = skip_bits >> imp_phase;
- int remain = res - imp_phase;
- while ( input_count >= 0 )
- {
- input_count -= step + (skip & 1) * stereo;
- skip >>= 1;
- if ( !--remain )
- {
- skip = skip_bits;
- remain = res;
- }
- output_count += 2;
- }
- return output_count;
-}
-
-int Fir_Resampler_::skip_input( long count )
-{
- int remain = write_pos - buf.begin();
- int max_count = remain - width_ * stereo;
- if ( count > max_count )
- count = max_count;
-
- remain -= count;
- write_pos = &buf [remain];
- memmove( buf.begin(), &buf [count], remain * sizeof buf [0] );
-
- return count;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.h b/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.h
deleted file mode 100644
index aed87492..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Fir_Resampler.h
+++ /dev/null
@@ -1,171 +0,0 @@
-// Finite impulse response (FIR) resampler with adjustable FIR size
-
-// Game_Music_Emu 0.5.5
-#ifndef FIR_RESAMPLER_H
-#define FIR_RESAMPLER_H
-
-#include "blargg_common.h"
-#include <string.h>
-
-class Fir_Resampler_ {
-public:
-
- // Use Fir_Resampler<width> (below)
-
- // Set input/output resampling ratio and optionally low-pass rolloff and gain.
- // Returns actual ratio used (rounded to internal precision).
- double time_ratio( double factor, double rolloff = 0.999, double gain = 1.0 );
-
- // Current input/output ratio
- double ratio() const { return ratio_; }
-
-// Input
-
- typedef short sample_t;
-
- // Resize and clear input buffer
- blargg_err_t buffer_size( int );
-
- // Clear input buffer. At least two output samples will be available after
- // two input samples are written.
- void clear();
-
- // Number of input samples that can be written
- int max_write() const { return buf.end() - write_pos; }
-
- // Pointer to place to write input samples
- sample_t* buffer() { return write_pos; }
-
- // Notify resampler that 'count' input samples have been written
- void write( long count );
-
- // Number of input samples in buffer
- int written() const { return write_pos - &buf [write_offset]; }
-
- // Skip 'count' input samples. Returns number of samples actually skipped.
- int skip_input( long count );
-
-// Output
-
- // Number of extra input samples needed until 'count' output samples are available
- int input_needed( blargg_long count ) const;
-
- // Number of output samples available
- int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); }
-
-public:
- ~Fir_Resampler_();
-protected:
- enum { stereo = 2 };
- enum { max_res = 32 };
- blargg_vector<sample_t> buf;
- sample_t* write_pos;
- int res;
- int imp_phase;
- int const width_;
- int const write_offset;
- blargg_ulong skip_bits;
- int step;
- int input_per_cycle;
- double ratio_;
- sample_t* impulses;
-
- Fir_Resampler_( int width, sample_t* );
- int avail_( blargg_long input_count ) const;
-};
-
-// Width is number of points in FIR. Must be even and 4 or more. More points give
-// better quality and rolloff effectiveness, and take longer to calculate.
-template<int width>
-class Fir_Resampler : public Fir_Resampler_ {
- BOOST_STATIC_ASSERT( width >= 4 && width % 2 == 0 );
- short impulses [max_res] [width];
-public:
- Fir_Resampler() : Fir_Resampler_( width, impulses [0] ) { }
-
- // Read at most 'count' samples. Returns number of samples actually read.
- typedef short sample_t;
- int read( sample_t* out, blargg_long count );
-};
-
-// End of public interface
-
-inline void Fir_Resampler_::write( long count )
-{
- write_pos += count;
- assert( write_pos <= buf.end() );
-}
-
-template<int width>
-int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count )
-{
- sample_t* out = out_begin;
- const sample_t* in = buf.begin();
- sample_t* end_pos = write_pos;
- blargg_ulong skip = skip_bits >> imp_phase;
- sample_t const* imp = impulses [imp_phase];
- int remain = res - imp_phase;
- int const step = this->step;
-
- count >>= 1;
-
- if ( end_pos - in >= width * stereo )
- {
- end_pos -= width * stereo;
- do
- {
- count--;
-
- // accumulate in extended precision
- blargg_long l = 0;
- blargg_long r = 0;
-
- const sample_t* i = in;
- if ( count < 0 )
- break;
-
- for ( int n = width / 2; n; --n )
- {
- int pt0 = imp [0];
- l += pt0 * i [0];
- r += pt0 * i [1];
- int pt1 = imp [1];
- imp += 2;
- l += pt1 * i [2];
- r += pt1 * i [3];
- i += 4;
- }
-
- remain--;
-
- l >>= 15;
- r >>= 15;
-
- in += (skip * stereo) & stereo;
- skip >>= 1;
- in += step;
-
- if ( !remain )
- {
- imp = impulses [0];
- skip = skip_bits;
- remain = res;
- }
-
- out [0] = (sample_t) l;
- out [1] = (sample_t) r;
- out += 2;
- }
- while ( in <= end_pos );
- }
-
- imp_phase = res - remain;
-
- int left = write_pos - in;
- write_pos = &buf [left];
- memmove( buf.begin(), in, left * sizeof *in );
-
- return out - out_begin;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.cpp
deleted file mode 100644
index 866594dd..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-unsigned const vol_reg = 0xFF24;
-unsigned const status_reg = 0xFF26;
-
-Gb_Apu::Gb_Apu()
-{
- square1.synth = &square_synth;
- square2.synth = &square_synth;
- wave.synth = &other_synth;
- noise.synth = &other_synth;
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &wave;
- oscs [3] = &noise;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- osc.regs = &regs [i * 5];
- osc.output = 0;
- osc.outputs [0] = 0;
- osc.outputs [1] = 0;
- osc.outputs [2] = 0;
- osc.outputs [3] = 0;
- }
-
- set_tempo( 1.0 );
- volume( 1.0 );
- reset();
-}
-
-void Gb_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- other_synth.treble_eq( eq );
-}
-
-void Gb_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- require( (center && left && right) || (!center && !left && !right) );
- Gb_Osc& osc = *oscs [index];
- osc.outputs [1] = right;
- osc.outputs [2] = left;
- osc.outputs [3] = center;
- osc.output = osc.outputs [osc.output_select];
-}
-
-void Gb_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, center, left, right );
-}
-
-void Gb_Apu::update_volume()
-{
- // TODO: doesn't handle differing left/right global volume (support would
- // require modification to all oscillator code)
- int data = regs [vol_reg - start_addr];
- double vol = (max( data & 7, data >> 4 & 7 ) + 1) * volume_unit;
- square_synth.volume( vol );
- other_synth.volume( vol );
-}
-
-static unsigned char const powerup_regs [0x20] = {
- 0x80,0x3F,0x00,0xFF,0xBF, // square 1
- 0xFF,0x3F,0x00,0xFF,0xBF, // square 2
- 0x7F,0xFF,0x9F,0xFF,0xBF, // wave
- 0xFF,0xFF,0x00,0x00,0xBF, // noise
- 0x00, // left/right enables
- 0x77, // master volume
- 0x80, // power
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
-};
-
-void Gb_Apu::set_tempo( double t )
-{
- frame_period = 4194304 / 256; // 256 Hz
- if ( t != 1.0 )
- frame_period = blip_time_t (frame_period / t);
-}
-
-void Gb_Apu::reset()
-{
- next_frame_time = 0;
- last_time = 0;
- frame_count = 0;
-
- square1.reset();
- square2.reset();
- wave.reset();
- noise.reset();
- noise.bits = 1;
- wave.wave_pos = 0;
-
- // avoid click at beginning
- regs [vol_reg - start_addr] = 0x77;
- update_volume();
-
- regs [status_reg - start_addr] = 0x01; // force power
- write_register( 0, status_reg, 0x00 );
-
- static unsigned char const initial_wave [] = {
- 0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
- 0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
- };
- memcpy( wave.wave, initial_wave, sizeof wave.wave );
-}
-
-void Gb_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time ); // end_time must not be before previous time
- if ( end_time == last_time )
- return;
-
- while ( true )
- {
- blip_time_t time = next_frame_time;
- if ( time > end_time )
- time = end_time;
-
- // run oscillators
- for ( int i = 0; i < osc_count; ++i )
- {
- Gb_Osc& osc = *oscs [i];
- if ( osc.output )
- {
- osc.output->set_modified(); // TODO: misses optimization opportunities?
- int playing = false;
- if ( osc.enabled && osc.volume &&
- (!(osc.regs [4] & osc.len_enabled_mask) || osc.length) )
- playing = -1;
- switch ( i )
- {
- case 0: square1.run( last_time, time, playing ); break;
- case 1: square2.run( last_time, time, playing ); break;
- case 2: wave .run( last_time, time, playing ); break;
- case 3: noise .run( last_time, time, playing ); break;
- }
- }
- }
- last_time = time;
-
- if ( time == end_time )
- break;
-
- next_frame_time += frame_period;
-
- // 256 Hz actions
- square1.clock_length();
- square2.clock_length();
- wave.clock_length();
- noise.clock_length();
-
- frame_count = (frame_count + 1) & 3;
- if ( frame_count == 0 )
- {
- // 64 Hz actions
- square1.clock_envelope();
- square2.clock_envelope();
- noise.clock_envelope();
- }
-
- if ( frame_count & 1 )
- square1.clock_sweep(); // 128 Hz action
- }
-}
-
-void Gb_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- assert( next_frame_time >= end_time );
- next_frame_time -= end_time;
-
- assert( last_time >= end_time );
- last_time -= end_time;
-}
-
-void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
-{
- require( (unsigned) data < 0x100 );
-
- int reg = addr - start_addr;
- if ( (unsigned) reg >= register_count )
- return;
-
- run_until( time );
-
- int old_reg = regs [reg];
- regs [reg] = data;
-
- if ( addr < vol_reg )
- {
- write_osc( reg / 5, reg, data );
- }
- else if ( addr == vol_reg && data != old_reg ) // global volume
- {
- // return all oscs to 0
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- int amp = osc.last_amp;
- osc.last_amp = 0;
- if ( amp && osc.enabled && osc.output )
- other_synth.offset( time, -amp, osc.output );
- }
-
- if ( wave.outputs [3] )
- other_synth.offset( time, 30, wave.outputs [3] );
-
- update_volume();
-
- if ( wave.outputs [3] )
- other_synth.offset( time, -30, wave.outputs [3] );
-
- // oscs will update with new amplitude when next run
- }
- else if ( addr == 0xFF25 || addr == status_reg )
- {
- int mask = (regs [status_reg - start_addr] & 0x80) ? ~0 : 0;
- int flags = regs [0xFF25 - start_addr] & mask;
-
- // left/right assignments
- for ( int i = 0; i < osc_count; i++ )
- {
- Gb_Osc& osc = *oscs [i];
- osc.enabled &= mask;
- int bits = flags >> i;
- Blip_Buffer* old_output = osc.output;
- osc.output_select = (bits >> 3 & 2) | (bits & 1);
- osc.output = osc.outputs [osc.output_select];
- if ( osc.output != old_output )
- {
- int amp = osc.last_amp;
- osc.last_amp = 0;
- if ( amp && old_output )
- other_synth.offset( time, -amp, old_output );
- }
- }
-
- if ( addr == status_reg && data != old_reg )
- {
- if ( !(data & 0x80) )
- {
- for ( unsigned i = 0; i < sizeof powerup_regs; i++ )
- {
- if ( i != status_reg - start_addr )
- write_register( time, i + start_addr, powerup_regs [i] );
- }
- }
- else
- {
- //debug_printf( "APU powered on\n" );
- }
- }
- }
- else if ( addr >= 0xFF30 )
- {
- int index = (addr & 0x0F) * 2;
- wave.wave [index] = data >> 4;
- wave.wave [index + 1] = data & 0x0F;
- }
-}
-
-int Gb_Apu::read_register( blip_time_t time, unsigned addr )
-{
- run_until( time );
-
- int index = addr - start_addr;
- require( (unsigned) index < register_count );
- int data = regs [index];
-
- if ( addr == status_reg )
- {
- data = (data & 0x80) | 0x70;
- for ( int i = 0; i < osc_count; i++ )
- {
- const Gb_Osc& osc = *oscs [i];
- if ( osc.enabled && (osc.length || !(osc.regs [4] & osc.len_enabled_mask)) )
- data |= 1 << i;
- }
- }
-
- return data;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.h
deleted file mode 100644
index e74ebc55..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Apu.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Nintendo Game Boy PAPU sound chip emulator
-
-// Gb_Snd_Emu 0.1.5
-#ifndef GB_APU_H
-#define GB_APU_H
-
-#include "Gb_Oscs.h"
-
-class Gb_Apu {
-public:
-
- // Set overall volume of all oscillators, where 1.0 is full volume
- void volume( double );
-
- // Set treble equalization
- void treble_eq( const blip_eq_t& );
-
- // Outputs can be assigned to a single buffer for mono output, or to three
- // buffers for stereo output (using Stereo_Buffer to do the mixing).
-
- // Assign all oscillator outputs to specified buffer(s). If buffer
- // is NULL, silences all oscillators.
- void output( Blip_Buffer* mono );
- void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
- // which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL,
- // silences oscillator.
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* mono );
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Reset oscillators and internal state
- void reset();
-
- // Reads and writes at addr must satisfy start_addr <= addr <= end_addr
- enum { start_addr = 0xFF10 };
- enum { end_addr = 0xFF3F };
- enum { register_count = end_addr - start_addr + 1 };
-
- // Write 'data' to address at specified time
- void write_register( blip_time_t, unsigned addr, int data );
-
- // Read from address at specified time
- int read_register( blip_time_t, unsigned addr );
-
- // Run all oscillators up to specified time, end current time frame, then
- // start a new frame at time 0.
- void end_frame( blip_time_t );
-
- void set_tempo( double );
-
-public:
- Gb_Apu();
-private:
- // noncopyable
- Gb_Apu( const Gb_Apu& );
- Gb_Apu& operator = ( const Gb_Apu& );
-
- Gb_Osc* oscs [osc_count];
- blip_time_t next_frame_time;
- blip_time_t last_time;
- blip_time_t frame_period;
- double volume_unit;
- int frame_count;
-
- Gb_Square square1;
- Gb_Square square2;
- Gb_Wave wave;
- Gb_Noise noise;
- BOOST::uint8_t regs [register_count];
- Gb_Square::Synth square_synth; // used by squares
- Gb_Wave::Synth other_synth; // used by wave and noise
-
- void update_volume();
- void run_until( blip_time_t );
- void write_osc( int index, int reg, int data );
-};
-
-inline void Gb_Apu::output( Blip_Buffer* b ) { output( b, b, b ); }
-
-inline void Gb_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); }
-
-inline void Gb_Apu::volume( double vol )
-{
- volume_unit = 0.60 / osc_count / 15 /*steps*/ / 2 /*?*/ / 8 /*master vol range*/ * vol;
- update_volume();
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.cpp
deleted file mode 100644
index 6980aafe..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.cpp
+++ /dev/null
@@ -1,1056 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gb_Cpu.h"
-
-#include <string.h>
-
-//#include "gb_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "gb_cpu_io.h"
-
-#include "blargg_source.h"
-
-// Common instructions:
-//
-// 365880 FA LD A,IND16
-// 355863 20 JR NZ
-// 313655 21 LD HL,IMM
-// 274580 28 JR Z
-// 252878 FE CMP IMM
-// 230541 7E LD A,(HL)
-// 226209 2A LD A,(HL+)
-// 217467 CD CALL
-// 212034 C9 RET
-// 208376 CB CB prefix
-//
-// 27486 CB 7E BIT 7,(HL)
-// 15925 CB 76 BIT 6,(HL)
-// 13035 CB 19 RR C
-// 11557 CB 7F BIT 7,A
-// 10898 CB 37 SWAP A
-// 10208 CB 66 BIT 4,(HL)
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
-{
- state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size );
-}
-
-void Gb_Cpu::reset( void* unmapped )
-{
- check( state == &state_ );
- state = &state_;
-
- state_.remain = 0;
-
- for ( int i = 0; i < page_count + 1; i++ )
- set_code_page( i, (uint8_t*) unmapped );
-
- memset( &r, 0, sizeof r );
- //interrupts_enabled = false;
-
- blargg_verify_byte_order();
-}
-
-void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
-{
- // address range must begin and end on page boundaries
- require( start % page_size == 0 );
- require( size % page_size == 0 );
-
- unsigned first_page = start / page_size;
- for ( unsigned i = size / page_size; i--; )
- set_code_page( first_page + i, (uint8_t*) data + i * page_size );
-}
-
-#define READ( addr ) CPU_READ( this, (addr), s.remain )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), s.remain );}
-#define READ_FAST( addr, out ) CPU_READ_FAST( this, (addr), s.remain, out )
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-unsigned const z_flag = 0x80;
-unsigned const n_flag = 0x40;
-unsigned const h_flag = 0x20;
-unsigned const c_flag = 0x10;
-
-bool Gb_Cpu::run( blargg_long cycle_count )
-{
- state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr;
- state_t s;
- this->state = &s;
- memcpy( &s, &this->state_, sizeof s );
-
- typedef BOOST::uint16_t uint16_t;
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n ) (r8_ [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n ) (r8_ [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
- union {
- core_regs_t rg; // individual registers
-
- struct {
- BOOST::uint16_t bc, de, hl, unused; // pairs
- } rp;
-
- uint8_t r8_ [8]; // indexed registers (use R8 macro due to endian dependence)
- BOOST::uint16_t r16 [4]; // indexed pairs
- };
- BOOST_STATIC_ASSERT( sizeof rg == 8 && sizeof rp == 8 );
-
- rg = r;
- unsigned pc = r.pc;
- unsigned sp = r.sp;
- unsigned flags = r.flags;
-
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (flags & ~0xF0) == 0 );
-
- uint8_t const* instr = s.code_map [pc >> page_shift];
- unsigned op;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- op = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- op = *instr++;
- pc++;
- #endif
-
-#define GET_ADDR() GET_LE16( instr )
-
- if ( !--s.remain )
- goto stop;
-
- unsigned data;
- data = *instr;
-
- #ifdef GB_CPU_LOG_H
- gb_cpu_log( "new", pc - 1, op, data, instr [1] );
- #endif
-
- switch ( op )
- {
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- pc++;\
- int offset = (BOOST::int8_t) data;\
- if ( !(cond) ) goto loop;\
- pc = uint16_t (pc + offset);\
- goto loop;\
-}
-
-// Most Common
-
- case 0x20: // JR NZ
- BRANCH( !(flags & z_flag) )
-
- case 0x21: // LD HL,IMM (common)
- rp.hl = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x28: // JR Z
- BRANCH( flags & z_flag )
-
- {
- unsigned temp;
- case 0xF0: // LD A,(0xFF00+imm)
- temp = data | 0xFF00;
- pc++;
- goto ld_a_ind_comm;
-
- case 0xF2: // LD A,(0xFF00+C)
- temp = rg.c | 0xFF00;
- goto ld_a_ind_comm;
-
- case 0x0A: // LD A,(BC)
- temp = rp.bc;
- goto ld_a_ind_comm;
-
- case 0x3A: // LD A,(HL-)
- temp = rp.hl;
- rp.hl = temp - 1;
- goto ld_a_ind_comm;
-
- case 0x1A: // LD A,(DE)
- temp = rp.de;
- goto ld_a_ind_comm;
-
- case 0x2A: // LD A,(HL+) (common)
- temp = rp.hl;
- rp.hl = temp + 1;
- goto ld_a_ind_comm;
-
- case 0xFA: // LD A,IND16 (common)
- temp = GET_ADDR();
- pc += 2;
- ld_a_ind_comm:
- READ_FAST( temp, rg.a );
- goto loop;
- }
-
- case 0xBE: // CMP (HL)
- data = READ( rp.hl );
- goto cmp_comm;
-
- case 0xB8: // CMP B
- case 0xB9: // CMP C
- case 0xBA: // CMP D
- case 0xBB: // CMP E
- case 0xBC: // CMP H
- case 0xBD: // CMP L
- data = R8( op & 7 );
- goto cmp_comm;
-
- case 0xFE: // CMP IMM
- pc++;
- cmp_comm:
- op = rg.a;
- data = op - data;
- sub_set_flags:
- flags = ((op & 15) - (data & 15)) & h_flag;
- flags |= (data >> 4) & c_flag;
- flags |= n_flag;
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
- case 0x46: // LD B,(HL)
- case 0x4E: // LD C,(HL)
- case 0x56: // LD D,(HL)
- case 0x5E: // LD E,(HL)
- case 0x66: // LD H,(HL)
- case 0x6E: // LD L,(HL)
- case 0x7E:{// LD A,(HL)
- unsigned addr = rp.hl;
- READ_FAST( addr, R8( (op >> 3) & 7 ) );
- goto loop;
- }
-
- case 0xC4: // CNZ (next-most-common)
- pc += 2;
- if ( flags & z_flag )
- goto loop;
- call:
- pc -= 2;
- case 0xCD: // CALL (most-common)
- data = pc + 2;
- pc = GET_ADDR();
- push:
- sp = (sp - 1) & 0xFFFF;
- WRITE( sp, data >> 8 );
- sp = (sp - 1) & 0xFFFF;
- WRITE( sp, data & 0xFF );
- goto loop;
-
- case 0xC8: // RNZ (next-most-common)
- if ( !(flags & z_flag) )
- goto loop;
- case 0xC9: // RET (most common)
- ret:
- pc = READ( sp );
- pc += 0x100 * READ( sp + 1 );
- sp = (sp + 2) & 0xFFFF;
- goto loop;
-
- case 0x00: // NOP
- case 0x40: // LD B,B
- case 0x49: // LD C,C
- case 0x52: // LD D,D
- case 0x5B: // LD E,E
- case 0x64: // LD H,H
- case 0x6D: // LD L,L
- case 0x7F: // LD A,A
- goto loop;
-
-// CB Instructions
-
- case 0xCB:
- pc++;
- // now data is the opcode
- switch ( data ) {
-
- {
- int temp;
- case 0x46: // BIT b,(HL)
- case 0x4E:
- case 0x56:
- case 0x5E:
- case 0x66:
- case 0x6E:
- case 0x76:
- case 0x7E:
- {
- unsigned addr = rp.hl;
- READ_FAST( addr, temp );
- goto bit_comm;
- }
-
- case 0x40: case 0x41: case 0x42: case 0x43: // BIT b,r
- case 0x44: case 0x45: case 0x47: case 0x48:
- case 0x49: case 0x4A: case 0x4B: case 0x4C:
- case 0x4D: case 0x4F: case 0x50: case 0x51:
- case 0x52: case 0x53: case 0x54: case 0x55:
- case 0x57: case 0x58: case 0x59: case 0x5A:
- case 0x5B: case 0x5C: case 0x5D: case 0x5F:
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x65: case 0x67: case 0x68:
- case 0x69: case 0x6A: case 0x6B: case 0x6C:
- case 0x6D: case 0x6F: case 0x70: case 0x71:
- case 0x72: case 0x73: case 0x74: case 0x75:
- case 0x77: case 0x78: case 0x79: case 0x7A:
- case 0x7B: case 0x7C: case 0x7D: case 0x7F:
- temp = R8( data & 7 );
- bit_comm:
- int bit = (~data >> 3) & 7;
- flags &= ~n_flag;
- flags |= h_flag | z_flag;
- flags ^= (temp << bit) & z_flag;
- goto loop;
- }
-
- case 0x86: // RES b,(HL)
- case 0x8E:
- case 0x96:
- case 0x9E:
- case 0xA6:
- case 0xAE:
- case 0xB6:
- case 0xBE:
- case 0xC6: // SET b,(HL)
- case 0xCE:
- case 0xD6:
- case 0xDE:
- case 0xE6:
- case 0xEE:
- case 0xF6:
- case 0xFE: {
- int temp = READ( rp.hl );
- int bit = 1 << ((data >> 3) & 7);
- temp &= ~bit;
- if ( !(data & 0x40) )
- bit = 0;
- WRITE( rp.hl, temp | bit );
- goto loop;
- }
-
- case 0xC0: case 0xC1: case 0xC2: case 0xC3: // SET b,r
- case 0xC4: case 0xC5: case 0xC7: case 0xC8:
- case 0xC9: case 0xCA: case 0xCB: case 0xCC:
- case 0xCD: case 0xCF: case 0xD0: case 0xD1:
- case 0xD2: case 0xD3: case 0xD4: case 0xD5:
- case 0xD7: case 0xD8: case 0xD9: case 0xDA:
- case 0xDB: case 0xDC: case 0xDD: case 0xDF:
- case 0xE0: case 0xE1: case 0xE2: case 0xE3:
- case 0xE4: case 0xE5: case 0xE7: case 0xE8:
- case 0xE9: case 0xEA: case 0xEB: case 0xEC:
- case 0xED: case 0xEF: case 0xF0: case 0xF1:
- case 0xF2: case 0xF3: case 0xF4: case 0xF5:
- case 0xF7: case 0xF8: case 0xF9: case 0xFA:
- case 0xFB: case 0xFC: case 0xFD: case 0xFF:
- R8( data & 7 ) |= 1 << ((data >> 3) & 7);
- goto loop;
-
- case 0x80: case 0x81: case 0x82: case 0x83: // RES b,r
- case 0x84: case 0x85: case 0x87: case 0x88:
- case 0x89: case 0x8A: case 0x8B: case 0x8C:
- case 0x8D: case 0x8F: case 0x90: case 0x91:
- case 0x92: case 0x93: case 0x94: case 0x95:
- case 0x97: case 0x98: case 0x99: case 0x9A:
- case 0x9B: case 0x9C: case 0x9D: case 0x9F:
- case 0xA0: case 0xA1: case 0xA2: case 0xA3:
- case 0xA4: case 0xA5: case 0xA7: case 0xA8:
- case 0xA9: case 0xAA: case 0xAB: case 0xAC:
- case 0xAD: case 0xAF: case 0xB0: case 0xB1:
- case 0xB2: case 0xB3: case 0xB4: case 0xB5:
- case 0xB7: case 0xB8: case 0xB9: case 0xBA:
- case 0xBB: case 0xBC: case 0xBD: case 0xBF:
- R8( data & 7 ) &= ~(1 << ((data >> 3) & 7));
- goto loop;
-
- {
- int temp;
- case 0x36: // SWAP (HL)
- temp = READ( rp.hl );
- goto swap_comm;
-
- case 0x30: // SWAP B
- case 0x31: // SWAP C
- case 0x32: // SWAP D
- case 0x33: // SWAP E
- case 0x34: // SWAP H
- case 0x35: // SWAP L
- case 0x37: // SWAP A
- temp = R8( data & 7 );
- swap_comm:
- op = (temp >> 4) | (temp << 4);
- flags = 0;
- goto shift_comm;
- }
-
-// Shift/Rotate
-
- case 0x06: // RLC (HL)
- case 0x16: // RL (HL)
- case 0x26: // SLA (HL)
- op = READ( rp.hl );
- goto rl_comm;
-
- case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x27: // SLA A
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: // RLC A
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x17: // RL A
- op = R8( data & 7 );
- goto rl_comm;
-
- case 0x3E: // SRL (HL)
- data += 0x10; // bump up to 0x4n to avoid preserving sign bit
- case 0x1E: // RR (HL)
- case 0x0E: // RRC (HL)
- case 0x2E: // SRA (HL)
- op = READ( rp.hl );
- goto rr_comm;
-
- case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3F: // SRL A
- data += 0x10; // bump up to 0x4n
- case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1F: // RR A
- case 0x08: case 0x09: case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0F: // RRC A
- case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2F: // SRA A
- op = R8( data & 7 );
- goto rr_comm;
-
- } // CB op
- assert( false ); // unhandled CB op
-
- case 0x07: // RLCA
- case 0x17: // RLA
- data = op;
- op = rg.a;
- rl_comm:
- op <<= 1;
- op |= ((data & flags) >> 4) & 1; // RL and carry is set
- flags = (op >> 4) & c_flag; // C = bit shifted out
- if ( data < 0x10 ) // RLC
- op |= op >> 8;
- // SLA doesn't fill lower bit
- goto shift_comm;
-
- case 0x0F: // RRCA
- case 0x1F: // RRA
- data = op;
- op = rg.a;
- rr_comm:
- op |= (data & flags) << 4; // RR and carry is set
- flags = (op << 4) & c_flag; // C = bit shifted out
- if ( data < 0x10 ) // RRC
- op |= op << 8;
- op >>= 1;
- if ( data & 0x20 ) // SRA propagates sign bit
- op |= (op << 1) & 0x80;
- shift_comm:
- data &= 7;
- if ( !(op & 0xFF) )
- flags |= z_flag;
- if ( data == 6 )
- goto write_hl_op_ff;
- R8( data ) = op;
- goto loop;
-
-// Load
-
- case 0x70: // LD (HL),B
- case 0x71: // LD (HL),C
- case 0x72: // LD (HL),D
- case 0x73: // LD (HL),E
- case 0x74: // LD (HL),H
- case 0x75: // LD (HL),L
- case 0x77: // LD (HL),A
- op = R8( op & 7 );
- write_hl_op_ff:
- WRITE( rp.hl, op & 0xFF );
- goto loop;
-
- case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x47: // LD r,r
- case 0x48: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4F:
- case 0x50: case 0x51: case 0x53: case 0x54: case 0x55: case 0x57:
- case 0x58: case 0x59: case 0x5A: case 0x5C: case 0x5D: case 0x5F:
- case 0x60: case 0x61: case 0x62: case 0x63: case 0x65: case 0x67:
- case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6F:
- case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D:
- R8( (op >> 3) & 7 ) = R8( op & 7 );
- goto loop;
-
- case 0x08: // LD IND16,SP
- data = GET_ADDR();
- pc += 2;
- WRITE( data, sp&0xFF );
- data++;
- WRITE( data, sp >> 8 );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
- case 0x31: // LD SP,IMM
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x01: // LD BC,IMM
- case 0x11: // LD DE,IMM
- r16 [op >> 4] = GET_ADDR();
- pc += 2;
- goto loop;
-
- {
- unsigned temp;
- case 0xE0: // LD (0xFF00+imm),A
- temp = data | 0xFF00;
- pc++;
- goto write_data_rg_a;
-
- case 0xE2: // LD (0xFF00+C),A
- temp = rg.c | 0xFF00;
- goto write_data_rg_a;
-
- case 0x32: // LD (HL-),A
- temp = rp.hl;
- rp.hl = temp - 1;
- goto write_data_rg_a;
-
- case 0x02: // LD (BC),A
- temp = rp.bc;
- goto write_data_rg_a;
-
- case 0x12: // LD (DE),A
- temp = rp.de;
- goto write_data_rg_a;
-
- case 0x22: // LD (HL+),A
- temp = rp.hl;
- rp.hl = temp + 1;
- goto write_data_rg_a;
-
- case 0xEA: // LD IND16,A (common)
- temp = GET_ADDR();
- pc += 2;
- write_data_rg_a:
- WRITE( temp, rg.a );
- goto loop;
- }
-
- case 0x06: // LD B,IMM
- rg.b = data;
- pc++;
- goto loop;
-
- case 0x0E: // LD C,IMM
- rg.c = data;
- pc++;
- goto loop;
-
- case 0x16: // LD D,IMM
- rg.d = data;
- pc++;
- goto loop;
-
- case 0x1E: // LD E,IMM
- rg.e = data;
- pc++;
- goto loop;
-
- case 0x26: // LD H,IMM
- rg.h = data;
- pc++;
- goto loop;
-
- case 0x2E: // LD L,IMM
- rg.l = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),IMM
- WRITE( rp.hl, data );
- pc++;
- goto loop;
-
- case 0x3E: // LD A,IMM
- rg.a = data;
- pc++;
- goto loop;
-
-// Increment/Decrement
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- r16 [op >> 4]++;
- goto loop;
-
- case 0x33: // INC SP
- sp = (sp + 1) & 0xFFFF;
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- r16 [op >> 4]--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = (sp - 1) & 0xFFFF;
- goto loop;
-
- case 0x34: // INC (HL)
- op = rp.hl;
- data = READ( op );
- data++;
- WRITE( op, data & 0xFF );
- goto inc_comm;
-
- case 0x04: // INC B
- case 0x0C: // INC C (common)
- case 0x14: // INC D
- case 0x1C: // INC E
- case 0x24: // INC H
- case 0x2C: // INC L
- case 0x3C: // INC A
- op = (op >> 3) & 7;
- R8( op ) = data = R8( op ) + 1;
- inc_comm:
- flags = (flags & c_flag) | (((data & 15) - 1) & h_flag) | ((data >> 1) & z_flag);
- goto loop;
-
- case 0x35: // DEC (HL)
- op = rp.hl;
- data = READ( op );
- data--;
- WRITE( op, data & 0xFF );
- goto dec_comm;
-
- case 0x05: // DEC B
- case 0x0D: // DEC C
- case 0x15: // DEC D
- case 0x1D: // DEC E
- case 0x25: // DEC H
- case 0x2D: // DEC L
- case 0x3D: // DEC A
- op = (op >> 3) & 7;
- data = R8( op ) - 1;
- R8( op ) = data;
- dec_comm:
- flags = (flags & c_flag) | n_flag | (((data & 15) + 0x31) & h_flag);
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
-// Add 16-bit
-
- {
- blargg_ulong temp; // need more than 16 bits for carry
- unsigned prev;
-
- case 0xF8: // LD HL,SP+imm
- temp = BOOST::int8_t (data); // sign-extend to 16 bits
- pc++;
- flags = 0;
- temp += sp;
- prev = sp;
- goto add_16_hl;
-
- case 0xE8: // ADD SP,IMM
- temp = BOOST::int8_t (data); // sign-extend to 16 bits
- pc++;
- flags = 0;
- temp += sp;
- prev = sp;
- sp = temp & 0xFFFF;
- goto add_16_comm;
-
- case 0x39: // ADD HL,SP
- temp = sp;
- goto add_hl_comm;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- temp = r16 [op >> 4];
- add_hl_comm:
- prev = rp.hl;
- temp += prev;
- flags &= z_flag;
- add_16_hl:
- rp.hl = temp;
- add_16_comm:
- flags |= (temp >> 12) & c_flag;
- flags |= (((temp & 0x0FFF) - (prev & 0x0FFF)) >> 7) & h_flag;
- goto loop;
- }
-
- case 0x86: // ADD (HL)
- data = READ( rp.hl );
- goto add_comm;
-
- case 0x80: // ADD B
- case 0x81: // ADD C
- case 0x82: // ADD D
- case 0x83: // ADD E
- case 0x84: // ADD H
- case 0x85: // ADD L
- case 0x87: // ADD A
- data = R8( op & 7 );
- goto add_comm;
-
- case 0xC6: // ADD IMM
- pc++;
- add_comm:
- flags = rg.a;
- data += flags;
- flags = ((data & 15) - (flags & 15)) & h_flag;
- flags |= (data >> 4) & c_flag;
- rg.a = data;
- if ( data & 0xFF )
- goto loop;
- flags |= z_flag;
- goto loop;
-
-// Add/Subtract
-
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_comm;
-
- case 0x88: // ADC B
- case 0x89: // ADC C
- case 0x8A: // ADC D
- case 0x8B: // ADC E
- case 0x8C: // ADC H
- case 0x8D: // ADC L
- case 0x8F: // ADC A
- data = R8( op & 7 );
- goto adc_comm;
-
- case 0xCE: // ADC IMM
- pc++;
- adc_comm:
- data += (flags >> 4) & 1;
- data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
- goto add_comm;
-
- case 0x96: // SUB (HL)
- data = READ( rp.hl );
- goto sub_comm;
-
- case 0x90: // SUB B
- case 0x91: // SUB C
- case 0x92: // SUB D
- case 0x93: // SUB E
- case 0x94: // SUB H
- case 0x95: // SUB L
- case 0x97: // SUB A
- data = R8( op & 7 );
- goto sub_comm;
-
- case 0xD6: // SUB IMM
- pc++;
- sub_comm:
- op = rg.a;
- data = op - data;
- rg.a = data;
- goto sub_set_flags;
-
- case 0x9E: // SBC (HL)
- data = READ( rp.hl );
- goto sbc_comm;
-
- case 0x98: // SBC B
- case 0x99: // SBC C
- case 0x9A: // SBC D
- case 0x9B: // SBC E
- case 0x9C: // SBC H
- case 0x9D: // SBC L
- case 0x9F: // SBC A
- data = R8( op & 7 );
- goto sbc_comm;
-
- case 0xDE: // SBC IMM
- pc++;
- sbc_comm:
- data += (flags >> 4) & 1;
- data &= 0xFF; // to do: does carry get set when sum + carry = 0x100?
- goto sub_comm;
-
-// Logical
-
- case 0xA0: // AND B
- case 0xA1: // AND C
- case 0xA2: // AND D
- case 0xA3: // AND E
- case 0xA4: // AND H
- case 0xA5: // AND L
- data = R8( op & 7 );
- goto and_comm;
-
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- pc--;
- case 0xE6: // AND IMM
- pc++;
- and_comm:
- rg.a &= data;
- case 0xA7: // AND A
- flags = h_flag | (((rg.a - 1) >> 1) & z_flag);
- goto loop;
-
- case 0xB0: // OR B
- case 0xB1: // OR C
- case 0xB2: // OR D
- case 0xB3: // OR E
- case 0xB4: // OR H
- case 0xB5: // OR L
- data = R8( op & 7 );
- goto or_comm;
-
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- pc--;
- case 0xF6: // OR IMM
- pc++;
- or_comm:
- rg.a |= data;
- case 0xB7: // OR A
- flags = ((rg.a - 1) >> 1) & z_flag;
- goto loop;
-
- case 0xA8: // XOR B
- case 0xA9: // XOR C
- case 0xAA: // XOR D
- case 0xAB: // XOR E
- case 0xAC: // XOR H
- case 0xAD: // XOR L
- data = R8( op & 7 );
- goto xor_comm;
-
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- pc--;
- case 0xEE: // XOR IMM
- pc++;
- xor_comm:
- data ^= rg.a;
- rg.a = data;
- data--;
- flags = (data >> 1) & z_flag;
- goto loop;
-
- case 0xAF: // XOR A
- rg.a = 0;
- flags = z_flag;
- goto loop;
-
-// Stack
-
- case 0xF1: // POP FA
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL (common)
- data = READ( sp );
- r16 [(op >> 4) & 3] = data + 0x100 * READ( sp + 1 );
- sp = (sp + 2) & 0xFFFF;
- if ( op != 0xF1 )
- goto loop;
- flags = rg.flags & 0xF0;
- goto loop;
-
- case 0xC5: // PUSH BC
- data = rp.bc;
- goto push;
-
- case 0xD5: // PUSH DE
- data = rp.de;
- goto push;
-
- case 0xE5: // PUSH HL
- data = rp.hl;
- goto push;
-
- case 0xF5: // PUSH FA
- data = (flags << 8) | rg.a;
- goto push;
-
-// Flow control
-
- case 0xFF:
- if ( pc == idle_addr + 1 )
- goto stop;
- case 0xC7: case 0xCF: case 0xD7: case 0xDF: // RST
- case 0xE7: case 0xEF: case 0xF7:
- data = pc;
- pc = (op & 0x38) + rst_base;
- goto push;
-
- case 0xCC: // CZ
- pc += 2;
- if ( flags & z_flag )
- goto call;
- goto loop;
-
- case 0xD4: // CNC
- pc += 2;
- if ( !(flags & c_flag) )
- goto call;
- goto loop;
-
- case 0xDC: // CC
- pc += 2;
- if ( flags & c_flag )
- goto call;
- goto loop;
-
- case 0xD9: // RETI
- //interrupts_enabled = 1;
- goto ret;
-
- case 0xC0: // RZ
- if ( !(flags & z_flag) )
- goto ret;
- goto loop;
-
- case 0xD0: // RNC
- if ( !(flags & c_flag) )
- goto ret;
- goto loop;
-
- case 0xD8: // RC
- if ( flags & c_flag )
- goto ret;
- goto loop;
-
- case 0x18: // JR
- BRANCH( true )
-
- case 0x30: // JR NC
- BRANCH( !(flags & c_flag) )
-
- case 0x38: // JR C
- BRANCH( flags & c_flag )
-
- case 0xE9: // JP_HL
- pc = rp.hl;
- goto loop;
-
- case 0xC3: // JP (next-most-common)
- pc = GET_ADDR();
- goto loop;
-
- case 0xC2: // JP NZ
- pc += 2;
- if ( !(flags & z_flag) )
- goto jp_taken;
- goto loop;
-
- case 0xCA: // JP Z (most common)
- pc += 2;
- if ( !(flags & z_flag) )
- goto loop;
- jp_taken:
- pc -= 2;
- pc = GET_ADDR();
- goto loop;
-
- case 0xD2: // JP NC
- pc += 2;
- if ( !(flags & c_flag) )
- goto jp_taken;
- goto loop;
-
- case 0xDA: // JP C
- pc += 2;
- if ( flags & c_flag )
- goto jp_taken;
- goto loop;
-
-// Flags
-
- case 0x2F: // CPL
- rg.a = ~rg.a;
- flags |= n_flag | h_flag;
- goto loop;
-
- case 0x3F: // CCF
- flags = (flags ^ c_flag) & ~(n_flag | h_flag);
- goto loop;
-
- case 0x37: // SCF
- flags = (flags | c_flag) & ~(n_flag | h_flag);
- goto loop;
-
- case 0xF3: // DI
- //interrupts_enabled = 0;
- goto loop;
-
- case 0xFB: // EI
- //interrupts_enabled = 1;
- goto loop;
-
-// Special
-
- case 0xDD: case 0xD3: case 0xDB: case 0xE3: case 0xE4: // ?
- case 0xEB: case 0xEC: case 0xF4: case 0xFD: case 0xFC:
- case 0x10: // STOP
- case 0x27: // DAA (I'll have to implement this eventually...)
- case 0xBF:
- case 0xED: // Z80 prefix
- case 0x76: // HALT
- s.remain++;
- goto stop;
- }
-
- // If this fails then the case above is missing an opcode
- assert( false );
-
-stop:
- pc--;
-
- // copy state back
- STATIC_CAST(core_regs_t&,r) = rg;
- r.pc = pc;
- r.sp = sp;
- r.flags = flags;
-
- this->state = &state_;
- memcpy( &this->state_, &s, sizeof this->state_ );
-
- return s.remain > 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.h
deleted file mode 100644
index 9d623e04..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Cpu.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Nintendo Game Boy CPU emulator
-// Treats every instruction as taking 4 cycles
-
-// Game_Music_Emu 0.5.5
-#ifndef GB_CPU_H
-#define GB_CPU_H
-
-#include "blargg_common.h"
-#include "blargg_endian.h"
-
-typedef unsigned gb_addr_t; // 16-bit CPU address
-
-class Gb_Cpu {
- enum { clocks_per_instr = 4 };
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers and map all pages to unmapped
- void reset( void* unmapped = 0 );
-
- // Map code memory (memory accessed via the program counter). Start and size
- // must be multiple of page_size.
- enum { page_size = 0x2000 };
- void map_code( gb_addr_t start, unsigned size, void* code );
-
- uint8_t* get_code( gb_addr_t );
-
- // Push a byte on the stack
- void push_byte( int );
-
- // Game Boy Z80 registers. *Not* kept updated during a call to run().
- struct core_regs_t {
- #if BLARGG_BIG_ENDIAN
- uint8_t b, c, d, e, h, l, flags, a;
- #else
- uint8_t c, b, e, d, l, h, a, flags;
- #endif
- };
-
- struct registers_t : core_regs_t {
- long pc; // more than 16 bits to allow overflow detection
- BOOST::uint16_t sp;
- };
- registers_t r;
-
- // Interrupt enable flag set by EI and cleared by DI
- //bool interrupts_enabled; // unused
-
- // Base address for RST vectors (normally 0)
- gb_addr_t rst_base;
-
- // If CPU executes opcode 0xFF at this address, it treats as illegal instruction
- enum { idle_addr = 0xF00D };
-
- // Run CPU for at least 'count' cycles and return false, or return true if
- // illegal instruction is encountered.
- bool run( blargg_long count );
-
- // Number of clock cycles remaining for most recent run() call
- blargg_long remain() const { return state->remain * clocks_per_instr; }
-
- // Can read this many bytes past end of a page
- enum { cpu_padding = 8 };
-
-public:
- Gb_Cpu() : rst_base( 0 ) { state = &state_; }
- enum { page_shift = 13 };
- enum { page_count = 0x10000 >> page_shift };
-private:
- // noncopyable
- Gb_Cpu( const Gb_Cpu& );
- Gb_Cpu& operator = ( const Gb_Cpu& );
-
- struct state_t {
- uint8_t* code_map [page_count + 1];
- blargg_long remain;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
-
- void set_code_page( int, uint8_t* );
-};
-
-inline BOOST::uint8_t* Gb_Cpu::get_code( gb_addr_t addr )
-{
- return state->code_map [addr >> page_shift] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.cpp
deleted file mode 100644
index 735653fa..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
-
-#include "Gb_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Gb_Osc
-
-void Gb_Osc::reset()
-{
- delay = 0;
- last_amp = 0;
- length = 0;
- output_select = 3;
- output = outputs [output_select];
-}
-
-void Gb_Osc::clock_length()
-{
- if ( (regs [4] & len_enabled_mask) && length )
- length--;
-}
-
-// Gb_Env
-
-void Gb_Env::clock_envelope()
-{
- if ( env_delay && !--env_delay )
- {
- env_delay = regs [2] & 7;
- int v = volume - 1 + (regs [2] >> 2 & 2);
- if ( (unsigned) v < 15 )
- volume = v;
- }
-}
-
-bool Gb_Env::write_register( int reg, int data )
-{
- switch ( reg )
- {
- case 1:
- length = 64 - (regs [1] & 0x3F);
- break;
-
- case 2:
- if ( !(data >> 4) )
- enabled = false;
- break;
-
- case 4:
- if ( data & trigger )
- {
- env_delay = regs [2] & 7;
- volume = regs [2] >> 4;
- enabled = true;
- if ( length == 0 )
- length = 64;
- return true;
- }
- }
- return false;
-}
-
-// Gb_Square
-
-void Gb_Square::reset()
-{
- phase = 0;
- sweep_freq = 0;
- sweep_delay = 0;
- Gb_Env::reset();
-}
-
-void Gb_Square::clock_sweep()
-{
- int sweep_period = (regs [0] & period_mask) >> 4;
- if ( sweep_period && sweep_delay && !--sweep_delay )
- {
- sweep_delay = sweep_period;
- regs [3] = sweep_freq & 0xFF;
- regs [4] = (regs [4] & ~0x07) | (sweep_freq >> 8 & 0x07);
-
- int offset = sweep_freq >> (regs [0] & shift_mask);
- if ( regs [0] & 0x08 )
- offset = -offset;
- sweep_freq += offset;
-
- if ( sweep_freq < 0 )
- {
- sweep_freq = 0;
- }
- else if ( sweep_freq >= 2048 )
- {
- sweep_delay = 0; // don't modify channel frequency any further
- sweep_freq = 2048; // silence sound immediately
- }
- }
-}
-
-void Gb_Square::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- if ( sweep_freq == 2048 )
- playing = false;
-
- static unsigned char const table [4] = { 1, 2, 4, 6 };
- int const duty = table [regs [1] >> 6];
- int amp = volume & playing;
- if ( phase >= duty )
- amp = -amp;
-
- int frequency = this->frequency();
- if ( unsigned (frequency - 1) > 2040 ) // frequency < 1 || frequency > 2041
- {
- // really high frequency results in DC at half volume
- amp = volume >> 1;
- playing = false;
- }
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- int const period = (2048 - frequency) * 4;
- Blip_Buffer* const output = this->output;
- int phase = this->phase;
- int delta = amp * 2;
- do
- {
- phase = (phase + 1) & 7;
- if ( phase == 0 || phase == duty )
- {
- delta = -delta;
- synth->offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->phase = phase;
- last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Gb_Noise
-
-void Gb_Noise::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- int amp = volume & playing;
- int tap = 13 - (regs [3] & 8);
- if ( bits >> tap & 2 )
- amp = -amp;
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- static unsigned char const table [8] = { 8, 16, 32, 48, 64, 80, 96, 112 };
- int period = table [regs [3] & 7] << (regs [3] >> 4);
-
- // keep parallel resampled time to eliminate time conversion in the loop
- Blip_Buffer* const output = this->output;
- const blip_resampled_time_t resampled_period =
- output->resampled_duration( period );
- blip_resampled_time_t resampled_time = output->resampled_time( time );
- unsigned bits = this->bits;
- int delta = amp * 2;
-
- do
- {
- unsigned changed = (bits >> tap) + 1;
- time += period;
- bits <<= 1;
- if ( changed & 2 )
- {
- delta = -delta;
- bits |= 1;
- synth->offset_resampled( resampled_time, delta, output );
- }
- resampled_time += resampled_period;
- }
- while ( time < end_time );
-
- this->bits = bits;
- last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Gb_Wave
-
-inline void Gb_Wave::write_register( int reg, int data )
-{
- switch ( reg )
- {
- case 0:
- if ( !(data & 0x80) )
- enabled = false;
- break;
-
- case 1:
- length = 256 - regs [1];
- break;
-
- case 2:
- volume = data >> 5 & 3;
- break;
-
- case 4:
- if ( data & trigger & regs [0] )
- {
- wave_pos = 0;
- enabled = true;
- if ( length == 0 )
- length = 256;
- }
- }
-}
-
-void Gb_Wave::run( blip_time_t time, blip_time_t end_time, int playing )
-{
- int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
- int frequency;
- {
- int amp = (wave [wave_pos] >> volume_shift & playing) * 2;
-
- frequency = this->frequency();
- if ( unsigned (frequency - 1) > 2044 ) // frequency < 1 || frequency > 2045
- {
- amp = 30 >> volume_shift & playing;
- playing = false;
- }
-
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !playing )
- time = end_time;
-
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- int const period = (2048 - frequency) * 2;
- int wave_pos = (this->wave_pos + 1) & (wave_size - 1);
-
- do
- {
- int amp = (wave [wave_pos] >> volume_shift) * 2;
- wave_pos = (wave_pos + 1) & (wave_size - 1);
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->wave_pos = (wave_pos - 1) & (wave_size - 1);
- }
- delay = time - end_time;
-}
-
-// Gb_Apu::write_osc
-
-void Gb_Apu::write_osc( int index, int reg, int data )
-{
- reg -= index * 5;
- Gb_Square* sq = &square2;
- switch ( index )
- {
- case 0:
- sq = &square1;
- case 1:
- if ( sq->write_register( reg, data ) && index == 0 )
- {
- square1.sweep_freq = square1.frequency();
- if ( (regs [0] & sq->period_mask) && (regs [0] & sq->shift_mask) )
- {
- square1.sweep_delay = 1; // cause sweep to recalculate now
- square1.clock_sweep();
- }
- }
- break;
-
- case 2:
- wave.write_register( reg, data );
- break;
-
- case 3:
- if ( noise.write_register( reg, data ) )
- noise.bits = 0x7FFF;
- }
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.h b/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.h
deleted file mode 100644
index d7f88ea1..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gb_Oscs.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Private oscillators used by Gb_Apu
-
-// Gb_Snd_Emu 0.1.5
-#ifndef GB_OSCS_H
-#define GB_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Gb_Osc
-{
- enum { trigger = 0x80 };
- enum { len_enabled_mask = 0x40 };
-
- Blip_Buffer* outputs [4]; // NULL, right, left, center
- Blip_Buffer* output;
- int output_select;
- BOOST::uint8_t* regs; // osc's 5 registers
-
- int delay;
- int last_amp;
- int volume;
- int length;
- int enabled;
-
- void reset();
- void clock_length();
- int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
-};
-
-struct Gb_Env : Gb_Osc
-{
- int env_delay;
-
- void reset();
- void clock_envelope();
- bool write_register( int, int );
-};
-
-struct Gb_Square : Gb_Env
-{
- enum { period_mask = 0x70 };
- enum { shift_mask = 0x07 };
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- Synth const* synth;
- int sweep_delay;
- int sweep_freq;
- int phase;
-
- void reset();
- void clock_sweep();
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-struct Gb_Noise : Gb_Env
-{
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth const* synth;
- unsigned bits;
-
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-struct Gb_Wave : Gb_Osc
-{
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth const* synth;
- int wave_pos;
- enum { wave_size = 32 };
- BOOST::uint8_t wave [wave_size];
-
- void write_register( int, int );
- void run( blip_time_t, blip_time_t, int playing );
-};
-
-inline void Gb_Env::reset()
-{
- env_delay = 0;
- Gb_Osc::reset();
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.cpp
deleted file mode 100644
index ceb526e5..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gbs_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Gbs_Emu::equalizer_t const Gbs_Emu::handheld_eq = { -47.0, 2000 };
-Gbs_Emu::equalizer_t const Gbs_Emu::headphones_eq = { 0.0, 300 };
-
-Gbs_Emu::Gbs_Emu()
-{
- set_type( gme_gbs_type );
-
- static const char* const names [Gb_Apu::osc_count] = {
- "Square 1", "Square 2", "Wave", "Noise"
- };
- set_voice_names( names );
-
- static int const types [Gb_Apu::osc_count] = {
- wave_type | 1, wave_type | 2, wave_type | 0, mixed_type | 0
- };
- set_voice_types( types );
-
- set_silence_lookahead( 6 );
- set_max_initial_silence( 21 );
- set_gain( 1.2 );
-
- static equalizer_t const eq = { -1.0, 120 };
- set_equalizer( eq );
-}
-
-Gbs_Emu::~Gbs_Emu() { }
-
-void Gbs_Emu::unload()
-{
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_gbs_fields( Gbs_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
-}
-
-blargg_err_t Gbs_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_gbs_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_gbs_header( void const* header )
-{
- if ( memcmp( header, "GBS", 3 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Gbs_File : Gme_Info_
-{
- Gbs_Emu::header_t h;
-
- Gbs_File() { set_type( gme_gbs_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &h, Gbs_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
-
- set_track_count( h.track_count );
- return check_gbs_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_gbs_fields( h, out );
- return 0;
- }
-};
-
-static Music_Emu* new_gbs_emu () { return BLARGG_NEW Gbs_Emu ; }
-static Music_Emu* new_gbs_file() { return BLARGG_NEW Gbs_File; }
-
-static gme_type_t_ const gme_gbs_type_ = { "Game Boy", 0, &new_gbs_emu, &new_gbs_file, "GBS", 1 };
-gme_type_t const gme_gbs_type = &gme_gbs_type_;
-
-// Setup
-
-blargg_err_t Gbs_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,copyright [32]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
- set_track_count( header_.track_count );
- RETURN_ERR( check_gbs_header( &header_ ) );
-
- if ( header_.vers != 1 )
- set_warning( "Unknown file version" );
-
- if ( header_.timer_mode & 0x78 )
- set_warning( "Invalid timer mode" );
-
- unsigned load_addr = get_le16( header_.load_addr );
- if ( (header_.load_addr [1] | header_.init_addr [1] | header_.play_addr [1]) > 0x7F ||
- load_addr < 0x400 )
- set_warning( "Invalid load/init/play address" );
-
- set_voice_count( Gb_Apu::osc_count );
-
- apu.volume( gain() );
-
- return setup_buffer( 4194304 );
-}
-
-void Gbs_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Gbs_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- apu.osc_output( i, c, l, r );
-}
-
-// Emulation
-
-// see gb_cpu_io.h for read/write functions
-
-void Gbs_Emu::set_bank( int n )
-{
- blargg_long addr = rom.mask_addr( n * (blargg_long) bank_size );
- if ( addr == 0 && rom.size() > bank_size )
- {
- // TODO: what is the correct behavior? Current Game & Watch Gallery
- // rip requires that this have no effect or set to bank 1.
- //debug_printf( "Selected ROM bank 0\n" );
- return;
- //n = 1;
- }
- cpu::map_code( bank_size, bank_size, rom.at_addr( addr ) );
-}
-
-void Gbs_Emu::update_timer()
-{
- if ( header_.timer_mode & 0x04 )
- {
- static byte const rates [4] = { 10, 4, 6, 8 };
- int shift = rates [ram [hi_page + 7] & 3] - (header_.timer_mode >> 7);
- play_period = (256L - ram [hi_page + 6]) << shift;
- }
- else
- {
- play_period = 70224; // 59.73 Hz
- }
- if ( tempo() != 1.0 )
- play_period = blip_time_t (play_period / tempo());
-}
-
-static BOOST::uint8_t const sound_data [Gb_Apu::register_count] = {
- 0x80, 0xBF, 0x00, 0x00, 0xBF, // square 1
- 0x00, 0x3F, 0x00, 0x00, 0xBF, // square 2
- 0x7F, 0xFF, 0x9F, 0x00, 0xBF, // wave
- 0x00, 0xFF, 0x00, 0x00, 0xBF, // noise
- 0x77, 0xF3, 0xF1, // vin/volume, status, power mode
- 0, 0, 0, 0, 0, 0, 0, 0, 0, // unused
- 0xAC, 0xDD, 0xDA, 0x48, 0x36, 0x02, 0xCF, 0x16, // waveform data
- 0x2C, 0x04, 0xE5, 0x2C, 0xAC, 0xDD, 0xDA, 0x48
-};
-
-void Gbs_Emu::cpu_jsr( gb_addr_t addr )
-{
- check( cpu::r.sp == get_le16( header_.stack_ptr ) );
- cpu::r.pc = addr;
- cpu_write( --cpu::r.sp, idle_addr >> 8 );
- cpu_write( --cpu::r.sp, idle_addr&0xFF );
-}
-
-void Gbs_Emu::set_tempo_( double t )
-{
- apu.set_tempo( t );
- update_timer();
-}
-
-blargg_err_t Gbs_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0, 0x4000 );
- memset( ram + 0x4000, 0xFF, 0x1F80 );
- memset( ram + 0x5F80, 0, sizeof ram - 0x5F80 );
- ram [hi_page] = 0; // joypad reads back as 0
-
- apu.reset();
- for ( int i = 0; i < (int) sizeof sound_data; i++ )
- apu.write_register( 0, i + apu.start_addr, sound_data [i] );
-
- cpu::reset( rom.unmapped() );
-
- unsigned load_addr = get_le16( header_.load_addr );
- cpu::rst_base = load_addr;
- rom.set_addr( load_addr );
-
- cpu::map_code( ram_addr, 0x10000 - ram_addr, ram );
- cpu::map_code( 0, bank_size, rom.at_addr( 0 ) );
- set_bank( rom.size() > bank_size );
-
- ram [hi_page + 6] = header_.timer_modulo;
- ram [hi_page + 7] = header_.timer_mode;
- update_timer();
- next_play = play_period;
-
- cpu::r.a = track;
- cpu::r.pc = idle_addr;
- cpu::r.sp = get_le16( header_.stack_ptr );
- cpu_time = 0;
- cpu_jsr( get_le16( header_.init_addr ) );
-
- return 0;
-}
-
-blargg_err_t Gbs_Emu::run_clocks( blip_time_t& duration, int )
-{
- cpu_time = 0;
- while ( cpu_time < duration )
- {
- long count = duration - cpu_time;
- cpu_time = duration;
- bool result = cpu::run( count );
- cpu_time -= cpu::remain();
-
- if ( result )
- {
- if ( cpu::r.pc == idle_addr )
- {
- if ( next_play > duration )
- {
- cpu_time = duration;
- break;
- }
-
- if ( cpu_time < next_play )
- cpu_time = next_play;
- next_play += play_period;
- cpu_jsr( get_le16( header_.play_addr ) );
- GME_FRAME_HOOK( this );
- // TODO: handle timer rates different than 60 Hz
- }
- else if ( cpu::r.pc > 0xFFFF )
- {
- debug_printf( "PC wrapped around\n" );
- cpu::r.pc &= 0xFFFF;
- }
- else
- {
- set_warning( "Emulation error (illegal/unsupported instruction)" );
- debug_printf( "Bad opcode $%.2x at $%.4x\n",
- (int) *cpu::get_code( cpu::r.pc ), (int) cpu::r.pc );
- cpu::r.pc = (cpu::r.pc + 1) & 0xFFFF;
- cpu_time += 6;
- }
- }
- }
-
- duration = cpu_time;
- next_play -= cpu_time;
- if ( next_play < 0 ) // could go negative if routine is taking too long to return
- next_play = 0;
- apu.end_frame( cpu_time );
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.h
deleted file mode 100644
index f3318dc8..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gbs_Emu.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Nintendo Game Boy GBS music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef GBS_EMU_H
-#define GBS_EMU_H
-
-#include "Classic_Emu.h"
-#include "Gb_Apu.h"
-#include "Gb_Cpu.h"
-
-class Gbs_Emu : private Gb_Cpu, public Classic_Emu {
- typedef Gb_Cpu cpu;
-public:
- // Equalizer profiles for Game Boy Color speaker and headphones
- static equalizer_t const handheld_eq;
- static equalizer_t const headphones_eq;
-
- // GBS file header
- enum { header_size = 112 };
- struct header_t
- {
- char tag [3];
- byte vers;
- byte track_count;
- byte first_track;
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte stack_ptr [2];
- byte timer_modulo;
- byte timer_mode;
- char game [32];
- char author [32];
- char copyright [32];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_gbs_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
-
-public:
- Gbs_Emu();
- ~Gbs_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-private:
- // rom
- enum { bank_size = 0x4000 };
- Rom_Data<bank_size> rom;
- void set_bank( int );
-
- // timer
- blip_time_t cpu_time;
- blip_time_t play_period;
- blip_time_t next_play;
- void update_timer();
-
- header_t header_;
- void cpu_jsr( gb_addr_t );
-
-public: private: friend class Gb_Cpu;
- blip_time_t clock() const { return cpu_time - cpu::remain(); }
-
- enum { joypad_addr = 0xFF00 };
- enum { ram_addr = 0xA000 };
- enum { hi_page = 0xFF00 - ram_addr };
- byte ram [0x4000 + 0x2000 + Gb_Cpu::cpu_padding];
- Gb_Apu apu;
-
- int cpu_read( gb_addr_t );
- void cpu_write( gb_addr_t, int );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.cpp
deleted file mode 100644
index 17edc9f8..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gme_File.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-const char* const gme_wrong_file_type = "Wrong file type for this emulator";
-
-void Gme_File::clear_playlist()
-{
- playlist.clear();
- clear_playlist_();
- track_count_ = raw_track_count_;
-}
-
-void Gme_File::unload()
-{
- clear_playlist(); // *before* clearing track count
- track_count_ = 0;
- raw_track_count_ = 0;
- file_data.clear();
-}
-
-Gme_File::Gme_File()
-{
- type_ = 0;
- user_data_ = 0;
- user_cleanup_ = 0;
- unload(); // clears fields
- blargg_verify_byte_order(); // used by most emulator types, so save them the trouble
-}
-
-Gme_File::~Gme_File()
-{
- if ( user_cleanup_ )
- user_cleanup_( user_data_ );
-}
-
-blargg_err_t Gme_File::load_mem_( byte const* data, long size )
-{
- require( data != file_data.begin() ); // load_mem_() or load_() must be overridden
- Mem_File_Reader in( data, size );
- return load_( in );
-}
-
-blargg_err_t Gme_File::load_( Data_Reader& in )
-{
- RETURN_ERR( file_data.resize( in.remain() ) );
- RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
- return load_mem_( file_data.begin(), file_data.size() );
-}
-
-// public load functions call this at beginning
-void Gme_File::pre_load() { unload(); }
-
-void Gme_File::post_load_() { }
-
-// public load functions call this at end
-blargg_err_t Gme_File::post_load( blargg_err_t err )
-{
- if ( !track_count() )
- set_track_count( type()->track_count );
- if ( !err )
- post_load_();
- else
- unload();
-
- return err;
-}
-
-// Public load functions
-
-blargg_err_t Gme_File::load_mem( void const* in, long size )
-{
- pre_load();
- return post_load( load_mem_( (byte const*) in, size ) );
-}
-
-blargg_err_t Gme_File::load( Data_Reader& in )
-{
- pre_load();
- return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_file( const char* path )
-{
- pre_load();
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- return post_load( load_( in ) );
-}
-
-blargg_err_t Gme_File::load_remaining_( void const* h, long s, Data_Reader& in )
-{
- Remaining_Reader rem( h, s, &in );
- return load( rem );
-}
-
-// Track info
-
-void Gme_File::copy_field_( char* out, const char* in, int in_size )
-{
- if ( !in || !*in )
- return;
-
- // remove spaces/junk from beginning
- while ( in_size && unsigned (*in - 1) <= ' ' - 1 )
- {
- in++;
- in_size--;
- }
-
- // truncate
- if ( in_size > max_field_ )
- in_size = max_field_;
-
- // find terminator
- int len = 0;
- while ( len < in_size && in [len] )
- len++;
-
- // remove spaces/junk from end
- while ( len && unsigned (in [len - 1]) <= ' ' )
- len--;
-
- // copy
- out [len] = 0;
- memcpy( out, in, len );
-
- // strip out stupid fields that should have been left blank
- if ( !strcmp( out, "?" ) || !strcmp( out, "<?>" ) || !strcmp( out, "< ? >" ) )
- out [0] = 0;
-}
-
-void Gme_File::copy_field_( char* out, const char* in )
-{
- copy_field_( out, in, max_field_ );
-}
-
-blargg_err_t Gme_File::remap_track_( int* track_io ) const
-{
- if ( (unsigned) *track_io >= (unsigned) track_count() )
- return "Invalid track";
-
- if ( (unsigned) *track_io < (unsigned) playlist.size() )
- {
- M3u_Playlist::entry_t const& e = playlist [*track_io];
- *track_io = 0;
- if ( e.track >= 0 )
- {
- *track_io = e.track;
- if ( !(type_->flags_ & 0x02) )
- *track_io -= e.decimal_track;
- }
- if ( *track_io >= raw_track_count_ )
- return "Invalid track in m3u playlist";
- }
- else
- {
- check( !playlist.size() );
- }
- return 0;
-}
-
-blargg_err_t Gme_File::track_info( track_info_t* out, int track ) const
-{
- out->track_count = track_count();
- out->length = -1;
- out->loop_length = -1;
- out->intro_length = -1;
- out->song [0] = 0;
-
- out->game [0] = 0;
- out->author [0] = 0;
- out->copyright [0] = 0;
- out->comment [0] = 0;
- out->dumper [0] = 0;
- out->system [0] = 0;
-
- copy_field_( out->system, type()->system );
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- RETURN_ERR( track_info_( out, remapped ) );
-
- // override with m3u info
- if ( playlist.size() )
- {
- M3u_Playlist::info_t const& i = playlist.info();
- copy_field_( out->game , i.title );
- copy_field_( out->author, i.engineer );
- copy_field_( out->author, i.composer );
- copy_field_( out->dumper, i.ripping );
-
- M3u_Playlist::entry_t const& e = playlist [track];
- copy_field_( out->song, e.name );
- if ( e.length >= 0 ) out->length = e.length * 1000L;
- if ( e.intro >= 0 ) out->intro_length = e.intro * 1000L;
- if ( e.loop >= 0 ) out->loop_length = e.loop * 1000L;
- }
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.h b/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.h
deleted file mode 100644
index f50dceae..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gme_File.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Common interface to game music file loading and information
-
-// Game_Music_Emu 0.5.5
-#ifndef GME_FILE_H
-#define GME_FILE_H
-
-#include "gme.h"
-#include "blargg_common.h"
-#include "Data_Reader.h"
-#include "M3u_Playlist.h"
-
-// Error returned if file is wrong type
-//extern const char gme_wrong_file_type []; // declared in gme.h
-
-struct gme_type_t_
-{
- const char* system; /* name of system this music file type is generally for */
- int track_count; /* non-zero for formats with a fixed number of tracks */
- Music_Emu* (*new_emu)(); /* Create new emulator for this type (useful in C++ only) */
- Music_Emu* (*new_info)(); /* Create new info reader for this type */
-
- /* internal */
- const char* extension_;
- int flags_;
-};
-
-enum { gme_max_field = 255 };
-
-struct Gme_File {
-public:
-// File loading
-
- // Each loads game music data from a file and returns an error if
- // file is wrong type or is seriously corrupt. They also set warning
- // string for minor problems.
-
- // Load from file on disk
- blargg_err_t load_file( const char* path );
-
- // Load from custom data source (see Data_Reader.h)
- blargg_err_t load( Data_Reader& );
-
- // Load from file already read into memory. Keeps pointer to data, so you
- // must not free it until you're done with the file.
- blargg_err_t load_mem( void const* data, long size );
-
- // Load an m3u playlist. Must be done after loading main music file.
- blargg_err_t load_m3u( const char* path );
- blargg_err_t load_m3u( Data_Reader& in );
-
- // Clears any loaded m3u playlist and any internal playlist that the music
- // format supports (NSFE for example).
- void clear_playlist();
-
-// Informational
-
- // Type of emulator. For example if this returns gme_nsfe_type, this object
- // is an NSFE emulator, and you can cast to an Nsfe_Emu* if necessary.
- gme_type_t type() const;
-
- // Most recent warning string, or NULL if none. Clears current warning after
- // returning.
- const char* warning();
-
- // Number of tracks or 0 if no file has been loaded
- int track_count() const;
-
- // Get information for a track (length, name, author, etc.)
- // See gme.h for definition of struct track_info_t.
- blargg_err_t track_info( track_info_t* out, int track ) const;
-
-// User data/cleanup
-
- // Set/get pointer to data you want to associate with this emulator.
- // You can use this for whatever you want.
- void set_user_data( void* p ) { user_data_ = p; }
- void* user_data() const { return user_data_; }
-
- // Register cleanup function to be called when deleting emulator, or NULL to
- // clear it. Passes user_data to cleanup function.
- void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
-
-public:
- // deprecated
- int error_count() const; // use warning()
-public:
- Gme_File();
- virtual ~Gme_File();
- BLARGG_DISABLE_NOTHROW
- typedef BOOST::uint8_t byte;
-protected:
- // Services
- void set_track_count( int n ) { track_count_ = raw_track_count_ = n; }
- void set_warning( const char* s ) { warning_ = s; }
- void set_type( gme_type_t t ) { type_ = t; }
- blargg_err_t load_remaining_( void const* header, long header_size, Data_Reader& remaining );
-
- // Overridable
- virtual void unload(); // called before loading file and if loading fails
- virtual blargg_err_t load_( Data_Reader& ); // default loads then calls load_mem_()
- virtual blargg_err_t load_mem_( byte const* data, long size ); // use data in memory
- virtual blargg_err_t track_info_( track_info_t* out, int track ) const = 0;
- virtual void pre_load();
- virtual void post_load_();
- virtual void clear_playlist_() { }
-
-public:
- blargg_err_t remap_track_( int* track_io ) const; // need by Music_Emu
-private:
- // noncopyable
- Gme_File( const Gme_File& );
- Gme_File& operator = ( const Gme_File& );
-
- gme_type_t type_;
- int track_count_;
- int raw_track_count_;
- const char* warning_;
- void* user_data_;
- gme_user_cleanup_t user_cleanup_;
- M3u_Playlist playlist;
- char playlist_warning [64];
- blargg_vector<byte> file_data; // only if loaded into memory using default load
-
- blargg_err_t load_m3u_( blargg_err_t );
- blargg_err_t post_load( blargg_err_t err );
-public:
- // track_info field copying
- enum { max_field_ = 255 };
- static void copy_field_( char* out, const char* in );
- static void copy_field_( char* out, const char* in, int len );
-};
-
-Music_Emu* gme_new_( Music_Emu*, long sample_rate );
-
-#define GME_COPY_FIELD( in, out, name ) \
- { Gme_File::copy_field_( out->name, in.name, sizeof in.name ); }
-
-#ifndef GME_FILE_READER
- #ifdef HAVE_ZLIB_H
- #define GME_FILE_READER Gzip_File_Reader
- #else
- #define GME_FILE_READER Std_File_Reader
- #endif
-#elif defined (GME_FILE_READER_INCLUDE)
- #include GME_FILE_READER_INCLUDE
-#endif
-
-inline gme_type_t Gme_File::type() const { return type_; }
-inline int Gme_File::error_count() const { return warning_ != 0; }
-inline int Gme_File::track_count() const { return track_count_; }
-
-inline const char* Gme_File::warning()
-{
- const char* s = warning_;
- warning_ = 0;
- return s;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.cpp
deleted file mode 100644
index c286dea9..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Gym_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const min_tempo = 0.25;
-double const oversample_factor = 5 / 3.0;
-double const fm_gain = 3.0;
-
-const long base_clock = 53700300;
-const long clock_rate = base_clock / 15;
-
-Gym_Emu::Gym_Emu()
-{
- data = 0;
- pos = 0;
- set_type( gme_gym_type );
-
- static const char* const names [] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
- };
- set_voice_names( names );
- set_silence_lookahead( 1 ); // tracks should already be trimmed
-}
-
-Gym_Emu::~Gym_Emu() { }
-
-// Track info
-
-static void get_gym_info( Gym_Emu::header_t const& h, long length, track_info_t* out )
-{
- if ( !memcmp( h.tag, "GYMX", 4 ) )
- {
- length = length * 50 / 3; // 1000 / 60
- long loop = get_le32( h.loop_start );
- if ( loop )
- {
- out->intro_length = loop * 50 / 3;
- out->loop_length = length - out->intro_length;
- }
- else
- {
- out->length = length;
- out->intro_length = length; // make it clear that track is no longer than length
- out->loop_length = 0;
- }
-
- // more stupidity where the field should have been left
- if ( strcmp( h.song, "Unknown Song" ) )
- GME_COPY_FIELD( h, out, song );
-
- if ( strcmp( h.game, "Unknown Game" ) )
- GME_COPY_FIELD( h, out, game );
-
- if ( strcmp( h.copyright, "Unknown Publisher" ) )
- GME_COPY_FIELD( h, out, copyright );
-
- if ( strcmp( h.dumper, "Unknown Person" ) )
- GME_COPY_FIELD( h, out, dumper );
-
- if ( strcmp( h.comment, "Header added by YMAMP" ) )
- GME_COPY_FIELD( h, out, comment );
- }
-}
-
-blargg_err_t Gym_Emu::track_info_( track_info_t* out, int ) const
-{
- get_gym_info( header_, track_length(), out );
- return 0;
-}
-
-static long gym_track_length( byte const* p, byte const* end )
-{
- long time = 0;
- while ( p < end )
- {
- switch ( *p++ )
- {
- case 0:
- time++;
- break;
-
- case 1:
- case 2:
- p += 2;
- break;
-
- case 3:
- p += 1;
- break;
- }
- }
- return time;
-}
-
-long Gym_Emu::track_length() const { return gym_track_length( data, data_end ); }
-
-static blargg_err_t check_header( byte const* in, long size, int* data_offset = 0 )
-{
- if ( size < 4 )
- return gme_wrong_file_type;
-
- if ( memcmp( in, "GYMX", 4 ) == 0 )
- {
- if ( size < Gym_Emu::header_size + 1 )
- return gme_wrong_file_type;
-
- if ( memcmp( ((Gym_Emu::header_t const*) in)->packed, "\0\0\0\0", 4 ) != 0 )
- return "Packed GYM file not supported";
-
- if ( data_offset )
- *data_offset = Gym_Emu::header_size;
- }
- else if ( *in > 3 )
- {
- return gme_wrong_file_type;
- }
-
- return 0;
-}
-
-struct Gym_File : Gme_Info_
-{
- byte const* file_begin;
- byte const* file_end;
- int data_offset;
-
- Gym_File() { set_type( gme_gym_type ); }
-
- blargg_err_t load_mem_( byte const* in, long size )
- {
- file_begin = in;
- file_end = in + size;
- data_offset = 0;
- return check_header( in, size, &data_offset );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- long length = gym_track_length( &file_begin [data_offset], file_end );
- get_gym_info( *(Gym_Emu::header_t const*) file_begin, length, out );
- return 0;
- }
-};
-
-static Music_Emu* new_gym_emu () { return BLARGG_NEW Gym_Emu ; }
-static Music_Emu* new_gym_file() { return BLARGG_NEW Gym_File; }
-
-static gme_type_t_ const gme_gym_type_ = { "Sega Genesis", 1, &new_gym_emu, &new_gym_file, "GYM", 0 };
-gme_type_t const gme_gym_type = &gme_gym_type_;
-
-// Setup
-
-blargg_err_t Gym_Emu::set_sample_rate_( long sample_rate )
-{
- blip_eq_t eq( -32, 8000, sample_rate );
- apu.treble_eq( eq );
- dac_synth.treble_eq( eq );
- apu.volume( 0.135 * fm_gain * gain() );
- dac_synth.volume( 0.125 / 256 * fm_gain * gain() );
- double factor = Dual_Resampler::setup( oversample_factor, 0.990, fm_gain * gain() );
- fm_sample_rate = sample_rate * factor;
-
- RETURN_ERR( blip_buf.set_sample_rate( sample_rate, int (1000 / 60.0 / min_tempo) ) );
- blip_buf.clock_rate( clock_rate );
-
- RETURN_ERR( fm.set_rate( fm_sample_rate, base_clock / 7.0 ) );
- RETURN_ERR( Dual_Resampler::reset( long (1.0 / 60 / min_tempo * sample_rate) ) );
-
- return 0;
-}
-
-void Gym_Emu::set_tempo_( double t )
-{
- if ( t < min_tempo )
- {
- set_tempo( min_tempo );
- return;
- }
-
- if ( blip_buf.sample_rate() )
- {
- clocks_per_frame = long (clock_rate / 60 / tempo());
- Dual_Resampler::resize( long (sample_rate() / (60.0 * tempo())) );
- }
-}
-
-void Gym_Emu::mute_voices_( int mask )
-{
- Music_Emu::mute_voices_( mask );
- fm.mute_voices( mask );
- dac_muted = (mask & 0x40) != 0;
- apu.output( (mask & 0x80) ? 0 : &blip_buf );
-}
-
-blargg_err_t Gym_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,packed [4]) == header_size );
- int offset = 0;
- RETURN_ERR( check_header( in, size, &offset ) );
- set_voice_count( 8 );
-
- data = in + offset;
- data_end = in + size;
- loop_begin = 0;
-
- if ( offset )
- header_ = *(header_t const*) in;
- else
- memset( &header_, 0, sizeof header_ );
-
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Gym_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
-
- pos = data;
- loop_remain = get_le32( header_.loop_start );
-
- prev_dac_count = 0;
- dac_enabled = false;
- dac_amp = -1;
-
- fm.reset();
- apu.reset();
- blip_buf.clear();
- Dual_Resampler::clear();
- return 0;
-}
-
-void Gym_Emu::run_dac( int dac_count )
-{
- // Guess beginning and end of sample and adjust rate and buffer position accordingly.
-
- // count dac samples in next frame
- int next_dac_count = 0;
- const byte* p = this->pos;
- int cmd;
- while ( (cmd = *p++) != 0 )
- {
- int data = *p++;
- if ( cmd <= 2 )
- ++p;
- if ( cmd == 1 && data == 0x2A )
- next_dac_count++;
- }
-
- // detect beginning and end of sample
- int rate_count = dac_count;
- int start = 0;
- if ( !prev_dac_count && next_dac_count && dac_count < next_dac_count )
- {
- rate_count = next_dac_count;
- start = next_dac_count - dac_count;
- }
- else if ( prev_dac_count && !next_dac_count && dac_count < prev_dac_count )
- {
- rate_count = prev_dac_count;
- }
-
- // Evenly space samples within buffer section being used
- blip_resampled_time_t period = blip_buf.resampled_duration( clocks_per_frame ) / rate_count;
-
- blip_resampled_time_t time = blip_buf.resampled_time( 0 ) +
- period * start + (period >> 1);
-
- int dac_amp = this->dac_amp;
- if ( dac_amp < 0 )
- dac_amp = dac_buf [0];
-
- for ( int i = 0; i < dac_count; i++ )
- {
- int delta = dac_buf [i] - dac_amp;
- dac_amp += delta;
- dac_synth.offset_resampled( time, delta, &blip_buf );
- time += period;
- }
- this->dac_amp = dac_amp;
-}
-
-void Gym_Emu::parse_frame()
-{
- int dac_count = 0;
- const byte* pos = this->pos;
-
- if ( loop_remain && !--loop_remain )
- loop_begin = pos; // find loop on first time through sequence
-
- int cmd;
- while ( (cmd = *pos++) != 0 )
- {
- int data = *pos++;
- if ( cmd == 1 )
- {
- int data2 = *pos++;
- if ( data != 0x2A )
- {
- if ( data == 0x2B )
- dac_enabled = (data2 & 0x80) != 0;
-
- fm.write0( data, data2 );
- }
- else if ( dac_count < (int) sizeof dac_buf )
- {
- dac_buf [dac_count] = data2;
- dac_count += dac_enabled;
- }
- }
- else if ( cmd == 2 )
- {
- fm.write1( data, *pos++ );
- }
- else if ( cmd == 3 )
- {
- apu.write_data( 0, data );
- }
- else
- {
- // to do: many GYM streams are full of errors, and error count should
- // reflect cases where music is really having problems
- //log_error();
- --pos; // put data back
- }
- }
-
- // loop
- if ( pos >= data_end )
- {
- check( pos == data_end );
-
- if ( loop_begin )
- pos = loop_begin;
- else
- set_track_ended();
- }
- this->pos = pos;
-
- // dac
- if ( dac_count && !dac_muted )
- run_dac( dac_count );
- prev_dac_count = dac_count;
-}
-
-int Gym_Emu::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
- if ( !track_ended() )
- parse_frame();
-
- apu.end_frame( blip_time );
-
- memset( buf, 0, sample_count * sizeof *buf );
- fm.run( sample_count >> 1, buf );
-
- return sample_count;
-}
-
-blargg_err_t Gym_Emu::play_( long count, sample_t* out )
-{
- Dual_Resampler::dual_play( count, out, blip_buf );
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.h
deleted file mode 100644
index f2e13238..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Gym_Emu.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Sega Genesis/Mega Drive GYM music file emulator
-// Includes with PCM timing recovery to improve sample quality.
-
-// Game_Music_Emu 0.5.5
-#ifndef GYM_EMU_H
-#define GYM_EMU_H
-
-#include "Dual_Resampler.h"
-#include "Ym2612_Emu.h"
-#include "Music_Emu.h"
-#include "Sms_Apu.h"
-
-class Gym_Emu : public Music_Emu, private Dual_Resampler {
-public:
- // GYM file header
- enum { header_size = 428 };
- struct header_t
- {
- char tag [4];
- char song [32];
- char game [32];
- char copyright [32];
- char emulator [32];
- char dumper [32];
- char comment [256];
- byte loop_start [4]; // in 1/60 seconds, 0 if not looped
- byte packed [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_gym_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- enum { gym_rate = 60 };
- long track_length() const; // use track_info()
-
-public:
- Gym_Emu();
- ~Gym_Emu();
-protected:
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t set_sample_rate_( long sample_rate );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long count, sample_t* );
- void mute_voices_( int );
- void set_tempo_( double );
- int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf );
-private:
- // sequence data begin, loop begin, current position, end
- const byte* data;
- const byte* loop_begin;
- const byte* pos;
- const byte* data_end;
- blargg_long loop_remain; // frames remaining until loop beginning has been located
- header_t header_;
- double fm_sample_rate;
- blargg_long clocks_per_frame;
- void parse_frame();
-
- // dac (pcm)
- int dac_amp;
- int prev_dac_count;
- bool dac_enabled;
- bool dac_muted;
- void run_dac( int );
-
- // sound
- Blip_Buffer blip_buf;
- Ym2612_Emu fm;
- Blip_Synth<blip_med_quality,1> dac_synth;
- Sms_Apu apu;
- byte dac_buf [1024];
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.cpp
deleted file mode 100644
index 63c2b707..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-bool const center_waves = true; // reduces asymmetry and clamping when starting notes
-
-Hes_Apu::Hes_Apu()
-{
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->outputs [0] = 0;
- osc->outputs [1] = 0;
- osc->chans [0] = 0;
- osc->chans [1] = 0;
- osc->chans [2] = 0;
- }
- while ( osc != oscs );
-
- reset();
-}
-
-void Hes_Apu::reset()
-{
- latch = 0;
- balance = 0xFF;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- memset( osc, 0, offsetof (Hes_Osc,outputs) );
- osc->noise_lfsr = 1;
- osc->control = 0x40;
- osc->balance = 0xFF;
- }
- while ( osc != oscs );
-}
-
-void Hes_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- oscs [index].chans [0] = center;
- oscs [index].chans [1] = left;
- oscs [index].chans [2] = right;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- balance_changed( *osc );
- }
- while ( osc != oscs );
-}
-
-void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
-{
- Blip_Buffer* const osc_outputs_0 = outputs [0]; // cache often-used values
- if ( osc_outputs_0 && control & 0x80 )
- {
- int dac = this->dac;
-
- int const volume_0 = volume [0];
- {
- int delta = dac * volume_0 - last_amp [0];
- if ( delta )
- synth_.offset( last_time, delta, osc_outputs_0 );
- osc_outputs_0->set_modified();
- }
-
- Blip_Buffer* const osc_outputs_1 = outputs [1];
- int const volume_1 = volume [1];
- if ( osc_outputs_1 )
- {
- int delta = dac * volume_1 - last_amp [1];
- if ( delta )
- synth_.offset( last_time, delta, osc_outputs_1 );
- osc_outputs_1->set_modified();
- }
-
- blip_time_t time = last_time + delay;
- if ( time < end_time )
- {
- if ( noise & 0x80 )
- {
- if ( volume_0 | volume_1 )
- {
- // noise
- int const period = (32 - (noise & 0x1F)) * 64; // TODO: correct?
- unsigned noise_lfsr = this->noise_lfsr;
- do
- {
- int new_dac = 0x1F & -(noise_lfsr >> 1 & 1);
- // Implemented using "Galios configuration"
- // TODO: find correct LFSR algorithm
- noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1));
- //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
- int delta = new_dac - dac;
- if ( delta )
- {
- dac = new_dac;
- synth_.offset( time, delta * volume_0, osc_outputs_0 );
- if ( osc_outputs_1 )
- synth_.offset( time, delta * volume_1, osc_outputs_1 );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->noise_lfsr = noise_lfsr;
- assert( noise_lfsr );
- }
- }
- else if ( !(control & 0x40) )
- {
- // wave
- int phase = (this->phase + 1) & 0x1F; // pre-advance for optimal inner loop
- int period = this->period * 2;
- if ( period >= 14 && (volume_0 | volume_1) )
- {
- do
- {
- int new_dac = wave [phase];
- phase = (phase + 1) & 0x1F;
- int delta = new_dac - dac;
- if ( delta )
- {
- dac = new_dac;
- synth_.offset( time, delta * volume_0, osc_outputs_0 );
- if ( osc_outputs_1 )
- synth_.offset( time, delta * volume_1, osc_outputs_1 );
- }
- time += period;
- }
- while ( time < end_time );
- }
- else
- {
- if ( !period )
- {
- // TODO: Gekisha Boy assumes that period = 0 silences wave
- //period = 0x1000 * 2;
- period = 1;
- //if ( !(volume_0 | volume_1) )
- // debug_printf( "Used period 0\n" );
- }
-
- // maintain phase when silent
- blargg_long count = (end_time - time + period - 1) / period;
- phase += count; // phase will be masked below
- time += count * period;
- }
- this->phase = (phase - 1) & 0x1F; // undo pre-advance
- }
- }
- time -= end_time;
- if ( time < 0 )
- time = 0;
- delay = time;
-
- this->dac = dac;
- last_amp [0] = dac * volume_0;
- last_amp [1] = dac * volume_1;
- }
- last_time = end_time;
-}
-
-void Hes_Apu::balance_changed( Hes_Osc& osc )
-{
- static short const log_table [32] = { // ~1.5 db per step
- #define ENTRY( factor ) short (factor * Hes_Osc::amp_range / 31.0 + 0.5)
- ENTRY( 0.000000 ),ENTRY( 0.005524 ),ENTRY( 0.006570 ),ENTRY( 0.007813 ),
- ENTRY( 0.009291 ),ENTRY( 0.011049 ),ENTRY( 0.013139 ),ENTRY( 0.015625 ),
- ENTRY( 0.018581 ),ENTRY( 0.022097 ),ENTRY( 0.026278 ),ENTRY( 0.031250 ),
- ENTRY( 0.037163 ),ENTRY( 0.044194 ),ENTRY( 0.052556 ),ENTRY( 0.062500 ),
- ENTRY( 0.074325 ),ENTRY( 0.088388 ),ENTRY( 0.105112 ),ENTRY( 0.125000 ),
- ENTRY( 0.148651 ),ENTRY( 0.176777 ),ENTRY( 0.210224 ),ENTRY( 0.250000 ),
- ENTRY( 0.297302 ),ENTRY( 0.353553 ),ENTRY( 0.420448 ),ENTRY( 0.500000 ),
- ENTRY( 0.594604 ),ENTRY( 0.707107 ),ENTRY( 0.840896 ),ENTRY( 1.000000 ),
- #undef ENTRY
- };
-
- int vol = (osc.control & 0x1F) - 0x1E * 2;
-
- int left = vol + (osc.balance >> 3 & 0x1E) + (balance >> 3 & 0x1E);
- if ( left < 0 ) left = 0;
-
- int right = vol + (osc.balance << 1 & 0x1E) + (balance << 1 & 0x1E);
- if ( right < 0 ) right = 0;
-
- left = log_table [left ];
- right = log_table [right];
-
- // optimizing for the common case of being centered also allows easy
- // panning using Effects_Buffer
- osc.outputs [0] = osc.chans [0]; // center
- osc.outputs [1] = 0;
- if ( left != right )
- {
- osc.outputs [0] = osc.chans [1]; // left
- osc.outputs [1] = osc.chans [2]; // right
- }
-
- if ( center_waves )
- {
- osc.last_amp [0] += (left - osc.volume [0]) * 16;
- osc.last_amp [1] += (right - osc.volume [1]) * 16;
- }
-
- osc.volume [0] = left;
- osc.volume [1] = right;
-}
-
-void Hes_Apu::write_data( blip_time_t time, int addr, int data )
-{
- if ( addr == 0x800 )
- {
- latch = data & 7;
- }
- else if ( addr == 0x801 )
- {
- if ( balance != data )
- {
- balance = data;
-
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- osc->run_until( synth, time );
- balance_changed( *oscs );
- }
- while ( osc != oscs );
- }
- }
- else if ( latch < osc_count )
- {
- Hes_Osc& osc = oscs [latch];
- osc.run_until( synth, time );
- switch ( addr )
- {
- case 0x802:
- osc.period = (osc.period & 0xF00) | data;
- break;
-
- case 0x803:
- osc.period = (osc.period & 0x0FF) | ((data & 0x0F) << 8);
- break;
-
- case 0x804:
- if ( osc.control & 0x40 & ~data )
- osc.phase = 0;
- osc.control = data;
- balance_changed( osc );
- break;
-
- case 0x805:
- osc.balance = data;
- balance_changed( osc );
- break;
-
- case 0x806:
- data &= 0x1F;
- if ( !(osc.control & 0x40) )
- {
- osc.wave [osc.phase] = data;
- osc.phase = (osc.phase + 1) & 0x1F;
- }
- else if ( osc.control & 0x80 )
- {
- osc.dac = data;
- }
- break;
-
- case 0x807:
- if ( &osc >= &oscs [4] )
- osc.noise = data;
- break;
-
- case 0x809:
- if ( !(data & 0x80) && (data & 0x03) != 0 )
- debug_printf( "HES LFO not supported\n" );
- }
- }
-}
-
-void Hes_Apu::end_frame( blip_time_t end_time )
-{
- Hes_Osc* osc = &oscs [osc_count];
- do
- {
- osc--;
- if ( end_time > osc->last_time )
- osc->run_until( synth, end_time );
- assert( osc->last_time >= end_time );
- osc->last_time -= end_time;
- }
- while ( osc != oscs );
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.h
deleted file mode 100644
index 1e546053..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Apu.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Turbo Grafx 16 (PC Engine) PSG sound chip emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef HES_APU_H
-#define HES_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Hes_Osc
-{
- unsigned char wave [32];
- short volume [2];
- int last_amp [2];
- int delay;
- int period;
- unsigned char noise;
- unsigned char phase;
- unsigned char balance;
- unsigned char dac;
- blip_time_t last_time;
-
- Blip_Buffer* outputs [2];
- Blip_Buffer* chans [3];
- unsigned noise_lfsr;
- unsigned char control;
-
- enum { amp_range = 0x8000 };
- typedef Blip_Synth<blip_med_quality,1> synth_t;
-
- void run_until( synth_t& synth, blip_time_t );
-};
-
-class Hes_Apu {
-public:
- void treble_eq( blip_eq_t const& );
- void volume( double );
-
- enum { osc_count = 6 };
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- void reset();
-
- enum { start_addr = 0x0800 };
- enum { end_addr = 0x0809 };
- void write_data( blip_time_t, int addr, int data );
-
- void end_frame( blip_time_t );
-
-public:
- Hes_Apu();
-private:
- Hes_Osc oscs [osc_count];
- int latch;
- int balance;
- Hes_Osc::synth_t synth;
-
- void balance_changed( Hes_Osc& );
- void recalc_chans();
-};
-
-inline void Hes_Apu::volume( double v ) { synth.volume( 1.8 / osc_count / Hes_Osc::amp_range * v ); }
-
-inline void Hes_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.cpp
deleted file mode 100644
index 8acdd94f..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.cpp
+++ /dev/null
@@ -1,1303 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Cpu.h"
-
-#include "blargg_endian.h"
-
-//#include "hes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// TODO: support T flag, including clearing it at appropriate times?
-
-// all zero-page should really use whatever is at page 1, but that would
-// reduce efficiency quite a bit
-int const ram_addr = 0x2000;
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "hes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-// status flags
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_t = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Hes_Cpu::reset()
-{
- check( state == &state_ );
- state = &state_;
-
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_hes_time;
- end_time_ = future_hes_time;
-
- r.status = st_i;
- r.sp = 0;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
-
- blargg_verify_byte_order();
-}
-
-void Hes_Cpu::set_mmr( int reg, int bank )
-{
- assert( (unsigned) reg <= page_count ); // allow page past end to be set
- assert( (unsigned) bank < 0x100 );
- mmr [reg] = bank;
- uint8_t const* code = CPU_SET_MMR( this, reg, bank );
- state->code_map [reg] = code - PAGE_OFFSET( reg << page_shift );
-}
-
-#define TIME (s_time + s.base)
-
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (ram [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_shift] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-typedef blargg_long fint32;
-
-bool Hes_Cpu::run( hes_time_t end_time )
-{
- bool illegal_encountered = false;
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- // even on x86, using s.time in place of s_time was slower
- fint16 s_time = s.time;
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-branch_not_taken:
- s_time -= 2;
-loop:
-
- #ifndef NDEBUG
- {
- hes_time_t correct = end_time_;
- if ( !(status & st_i) && correct > irq_time_ )
- correct = irq_time_;
- check( s.base == correct );
- /*
- static long count;
- if ( count == 1844 ) Debugger();
- if ( s.base != correct ) debug_printf( "%ld\n", count );
- count++;
- */
- }
- #endif
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
-
- uint8_t const* instr = s.code_map [pc >> page_shift];
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- // TODO: each reference lists slightly different timing values, ugh
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 1,7,3, 4,6,4,6,7,3,2,2,2,7,5,7,6,// 0
- 4,7,7, 4,6,4,6,7,2,5,2,2,7,5,7,6,// 1
- 7,7,3, 4,4,4,6,7,4,2,2,2,5,5,7,6,// 2
- 4,7,7, 2,4,4,6,7,2,5,2,2,5,5,7,6,// 3
- 7,7,3, 4,8,4,6,7,3,2,2,2,4,5,7,6,// 4
- 4,7,7, 5,2,4,6,7,2,5,3,2,2,5,7,6,// 5
- 7,7,2, 2,4,4,6,7,4,2,2,2,7,5,7,6,// 6
- 4,7,7,17,4,4,6,7,2,5,4,2,7,5,7,6,// 7
- 4,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// 8
- 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// 9
- 2,7,2, 7,4,4,4,7,2,2,2,2,5,5,5,6,// A
- 4,7,7, 8,4,4,4,7,2,5,2,2,5,5,5,6,// B
- 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// C
- 4,7,7,17,2,4,6,7,2,5,3,2,2,5,7,6,// D
- 2,7,2,17,4,4,6,7,2,2,2,2,5,5,7,6,// E
- 4,7,7,17,2,4,6,7,2,5,4,2,2,5,7,6 // F
- }; // 0x00 was 8
-
- fuint16 data;
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- #ifdef HES_CPU_LOG_H
- log_cpu( "new", pc - 1, opcode, instr [0], instr [1], instr [2],
- instr [3], instr [4], instr [5] );
- //log_opcode( opcode );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE( out ) (pc++, out = data + 0x100 * GET_MSB());
-#define GET_ADDR() GET_LE16( instr )
-
-// TODO: is the penalty really always added? the original 6502 was much better
-//#define PAGE_CROSS_PENALTY( lsb ) (void) (s_time += (lsb) >> 8)
-#define PAGE_CROSS_PENALTY( lsb )
-
-// Branch
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) ) goto branch_not_taken;\
- pc = BOOST::uint16_t (pc + offset);\
- goto loop;\
-}
-
- case 0xF0: // BEQ
- BRANCH( !((uint8_t) nz) );
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x10: // BPL
- BRANCH( !IS_NEG );
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x80: // BRA
- branch_taken:
- BRANCH( true );
-
- case 0xFF:
- if ( pc == idle_addr + 1 )
- goto idle_done;
- case 0x0F: // BBRn
- case 0x1F:
- case 0x2F:
- case 0x3F:
- case 0x4F:
- case 0x5F:
- case 0x6F:
- case 0x7F:
- case 0x8F: // BBSn
- case 0x9F:
- case 0xAF:
- case 0xBF:
- case 0xCF:
- case 0xDF:
- case 0xEF: {
- fuint16 t = 0x101 * READ_LOW( data );
- t ^= 0xFF;
- pc++;
- data = GET_MSB();
- BRANCH( t & (1 << (opcode >> 4)) )
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0x7C: // JMP (ind+X)
- data += x;
- case 0x6C:{// JMP (ind)
- data += 0x100 * GET_MSB();
- pc = GET_LE16( &READ_PROG( data ) );
- goto loop;
- }
-
-// Subroutine
-
- case 0x44: // BSR
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, pc );
- goto branch_taken;
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- pc += 1 + READ_LOW( sp );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Common
-
- case 0xBD:{// LDA abs,X
- PAGE_CROSS_PENALTY( data + x );
- fuint16 addr = GET_ADDR() + x;
- pc += 2;
- CPU_READ_FAST( this, addr, TIME, nz );
- a = nz;
- goto loop;
- }
-
- case 0x9D:{// STA abs,X
- fuint16 addr = GET_ADDR() + x;
- pc += 2;
- CPU_WRITE_FAST( this, addr, a, TIME );
- goto loop;
- }
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xAE:{// LDX abs
- fuint16 addr = GET_ADDR();
- pc += 2;
- CPU_READ_FAST( this, addr, TIME, nz );
- x = nz;
- goto loop;
- }
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
-// Load/store
-
- {
- fuint16 addr;
- case 0x91: // STA (ind),Y
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data ) + y;
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- data = uint8_t (data + x);
- case 0x92: // STA (ind)
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data );
- pc++;
- goto sta_ptr;
-
- case 0x99: // STA abs,Y
- data += y;
- case 0x8D: // STA abs
- addr = data + 0x100 * GET_MSB();
- pc += 2;
- sta_ptr:
- CPU_WRITE_FAST( this, addr, a, TIME );
- goto loop;
- }
-
- {
- fuint16 addr;
- case 0xA1: // LDA (ind,X)
- data = uint8_t (data + x);
- case 0xB2: // LDA (ind)
- addr = 0x100 * READ_LOW( uint8_t (data + 1) );
- addr += READ_LOW( data );
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- PAGE_CROSS_PENALTY( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- data += y;
- PAGE_CROSS_PENALTY( data );
- case 0xAD: // LDA abs
- addr = data + 0x100 * GET_MSB();
- pc += 2;
- a_nz_read_addr:
- CPU_READ_FAST( this, addr, TIME, nz );
- a = nz;
- goto loop;
- }
-
- case 0xBE:{// LDX abs,y
- PAGE_CROSS_PENALTY( data + y );
- fuint16 addr = GET_ADDR() + y;
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
-// Bit operations
-
- case 0x3C: // BIT abs,x
- data += x;
- case 0x2C:{// BIT abs
- fuint16 addr;
- ADD_PAGE( addr );
- FLUSH_TIME();
- nz = READ( addr );
- CACHE_TIME();
- goto bit_common;
- }
- case 0x34: // BIT zp,x
- data = uint8_t (data + x);
- case 0x24: // BIT zp
- data = READ_LOW( data );
- case 0x89: // BIT imm
- nz = data;
- bit_common:
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( nz & a )
- goto loop; // Z should be clear, and nz must be non-zero if nz & a is
- nz <<= 8; // set Z flag without affecting N flag
- goto loop;
-
- {
- fuint16 addr;
-
- case 0xB3: // TST abs,x
- addr = GET_MSB() + x;
- goto tst_abs;
-
- case 0x93: // TST abs
- addr = GET_MSB();
- tst_abs:
- addr += 0x100 * instr [2];
- pc++;
- FLUSH_TIME();
- nz = READ( addr );
- CACHE_TIME();
- goto tst_common;
- }
-
- case 0xA3: // TST zp,x
- nz = READ_LOW( uint8_t (GET_MSB() + x) );
- goto tst_common;
-
- case 0x83: // TST zp
- nz = READ_LOW( GET_MSB() );
- tst_common:
- pc += 2;
- status &= ~st_v;
- status |= nz & st_v;
- if ( nz & data )
- goto loop; // Z should be clear, and nz must be non-zero if nz & data is
- nz <<= 8; // set Z flag without affecting N flag
- goto loop;
-
- {
- fuint16 addr;
- case 0x0C: // TSB abs
- case 0x1C: // TRB abs
- addr = GET_ADDR();
- pc++;
- goto txb_addr;
-
- // TODO: everyone lists different behaviors for the status flags, ugh
- case 0x04: // TSB zp
- case 0x14: // TRB zp
- addr = data + ram_addr;
- txb_addr:
- FLUSH_TIME();
- nz = a | READ( addr );
- if ( opcode & 0x10 )
- nz ^= a; // bits from a will already be set, so this clears them
- status &= ~st_v;
- status |= nz & st_v;
- pc++;
- WRITE( addr, nz );
- CACHE_TIME();
- goto loop;
- }
-
- case 0x07: // RMBn
- case 0x17:
- case 0x27:
- case 0x37:
- case 0x47:
- case 0x57:
- case 0x67:
- case 0x77:
- pc++;
- READ_LOW( data ) &= ~(1 << (opcode >> 4));
- goto loop;
-
- case 0x87: // SMBn
- case 0x97:
- case 0xA7:
- case 0xB7:
- case 0xC7:
- case 0xD7:
- case 0xE7:
- case 0xF7:
- pc++;
- READ_LOW( data ) |= 1 << ((opcode >> 4) - 8);
- goto loop;
-
-// Load/store
-
- case 0x9E: // STZ abs,x
- data += x;
- case 0x9C: // STZ abs
- ADD_PAGE( data );
- pc++;
- FLUSH_TIME();
- WRITE( data, 0 );
- CACHE_TIME();
- goto loop;
-
- case 0x74: // STZ zp,x
- data = uint8_t (data + x);
- case 0x64: // STZ zp
- pc++;
- WRITE_LOW( data, 0 );
- goto loop;
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- PAGE_CROSS_PENALTY( data );
- case 0xAC:{// LDY abs
- fuint16 addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- fuint16 addr = GET_ADDR();
- pc += 2;
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- fuint16 addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- fuint16 addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
-#define ARITH_ADDR_MODES( op )\
- case op - 0x04: /* (ind,x) */\
- data = uint8_t (data + x);\
- case op + 0x0D: /* (ind) */\
- data = 0x100 * READ_LOW( uint8_t (data + 1) ) + READ_LOW( data );\
- goto ptr##op;\
- case op + 0x0C:{/* (ind),y */\
- fuint16 temp = READ_LOW( data ) + y;\
- PAGE_CROSS_PENALTY( temp );\
- data = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- goto ptr##op;\
- }\
- case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
- case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
- case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
- case op + 0x18: /* abs,X */\
- data += x;\
- ind##op:\
- PAGE_CROSS_PENALTY( data );\
- case op + 0x08: /* abs */\
- ADD_PAGE( data );\
- ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
- case op + 0x04: /* imm */\
- imm##op:
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- if ( status & st_d )
- debug_printf( "Decimal mode not supported\n" );
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE( data );
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE( data );
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
-#define INC_DEC_AXY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
- case 0x1A: // INA
- INC_DEC_AXY( a, +1 )
-
- case 0xE8: // INX
- INC_DEC_AXY( x, +1 )
-
- case 0xC8: // INY
- INC_DEC_AXY( y, +1 )
-
- case 0x3A: // DEA
- INC_DEC_AXY( a, -1 )
-
- case 0xCA: // DEX
- INC_DEC_AXY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_AXY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
- #define SWAP_REGS( r1, r2 ) {\
- fuint8 t = r1;\
- r1 = r2;\
- r2 = t;\
- goto loop;\
- }
-
- case 0x02: // SXY
- SWAP_REGS( x, y );
-
- case 0x22: // SAX
- SWAP_REGS( a, x );
-
- case 0x42: // SAY
- SWAP_REGS( a, y );
-
- case 0x62: // CLA
- a = 0;
- goto loop;
-
- case 0x82: // CLX
- x = 0;
- goto loop;
-
- case 0xC2: // CLY
- y = 0;
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a );
- goto loop;
-
- case 0xDA: // PHX
- PUSH( x );
- goto loop;
-
- case 0x5A: // PHY
- PUSH( y );
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- this->r.status = status; // update externally-visible I flag
- if ( (data ^ status) & st_i )
- {
- hes_time_t new_time = end_time_;
- if ( !(status & st_i) && new_time > irq_time_ )
- new_time = irq_time_;
- blargg_long delta = s.base - new_time;
- s.base = new_time;
- s_time += delta;
- }
- goto loop;
- }
-
- #define POP() READ_LOW( sp ); sp = (sp - 0xFF) | 0x100
-
- case 0x68: // PLA
- a = nz = POP();
- goto loop;
-
- case 0xFA: // PLX
- x = nz = POP();
- goto loop;
-
- case 0x7A: // PLY
- y = nz = POP();
- goto loop;
-
- case 0x28:{// PLP
- fuint8 temp = POP();
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
- #undef POP
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | st_b );
- goto loop;
- }
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- // delayed irq until after next instruction
- s.base += s_time + 1;
- s_time = -1;
- irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
- goto loop;
- }
- delayed_cli:
- debug_printf( "Delayed CLI not supported\n" ); // TODO: implement
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
- debug_printf( "Delayed SEI not supported\n" ); // TODO: implement
- goto loop;
- }
-
-// Special
-
- case 0x53:{// TAM
- fuint8 const bits = data; // avoid using data across function call
- pc++;
- for ( int i = 0; i < 8; i++ )
- if ( bits & (1 << i) )
- set_mmr( i, a );
- goto loop;
- }
-
- case 0x43:{// TMA
- pc++;
- byte const* in = mmr;
- do
- {
- if ( data & 1 )
- a = *in;
- in++;
- }
- while ( (data >>= 1) != 0 );
- goto loop;
- }
-
- case 0x03: // ST0
- case 0x13: // ST1
- case 0x23:{// ST2
- fuint16 addr = opcode >> 4;
- if ( addr )
- addr++;
- pc++;
- FLUSH_TIME();
- CPU_WRITE_VDP( this, addr, data, TIME );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xEA: // NOP
- goto loop;
-
- case 0x54: // CSL
- debug_printf( "CSL not supported\n" );
- illegal_encountered = true;
- goto loop;
-
- case 0xD4: // CSH
- goto loop;
-
- case 0xF4: { // SET
- //fuint16 operand = GET_MSB();
- debug_printf( "SET not handled\n" );
- //switch ( data )
- //{
- //}
- illegal_encountered = true;
- goto loop;
- }
-
-// Block transfer
-
- {
- fuint16 in_alt;
- fint16 in_inc;
- fuint16 out_alt;
- fint16 out_inc;
-
- case 0xE3: // TIA
- in_alt = 0;
- goto bxfer_alt;
-
- case 0xF3: // TAI
- in_alt = 1;
- bxfer_alt:
- in_inc = in_alt ^ 1;
- out_alt = in_inc;
- out_inc = in_alt;
- goto bxfer;
-
- case 0xD3: // TIN
- in_inc = 1;
- out_inc = 0;
- goto bxfer_no_alt;
-
- case 0xC3: // TDD
- in_inc = -1;
- out_inc = -1;
- goto bxfer_no_alt;
-
- case 0x73: // TII
- in_inc = 1;
- out_inc = 1;
- bxfer_no_alt:
- in_alt = 0;
- out_alt = 0;
- bxfer:
- fuint16 in = GET_LE16( instr + 0 );
- fuint16 out = GET_LE16( instr + 2 );
- int count = GET_LE16( instr + 4 );
- if ( !count )
- count = 0x10000;
- pc += 6;
- WRITE_LOW( 0x100 | (sp - 1), y );
- WRITE_LOW( 0x100 | (sp - 2), a );
- WRITE_LOW( 0x100 | (sp - 3), x );
- FLUSH_TIME();
- do
- {
- // TODO: reads from $0800-$1400 in I/O page return 0 and don't access I/O
- fuint8 t = READ( in );
- in += in_inc;
- in &= 0xFFFF;
- s.time += 6;
- if ( in_alt )
- in_inc = -in_inc;
- WRITE( out, t );
- out += out_inc;
- out &= 0xFFFF;
- if ( out_alt )
- out_inc = -out_inc;
- }
- while ( --count );
- CACHE_TIME();
- goto loop;
- }
-
-// Illegal
-
- default:
- assert( (unsigned) opcode <= 0xFF );
- debug_printf( "Illegal opcode $%02X at $%04X\n", (int) opcode, (int) pc - 1 );
- illegal_encountered = true;
- goto loop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- pc++;
- result_ = 6;
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFF0 ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- if ( result_ == 6 )
- temp |= st_b;
- WRITE_LOW( sp, temp );
-
- status &= ~st_d;
- status |= st_i;
- this->r.status = status; // update externally-visible I flag
-
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- goto loop;
- }
-
-idle_done:
- s_time = 0;
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ > 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return illegal_encountered;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.h
deleted file mode 100644
index cf3af87d..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Cpu.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// PC Engine CPU emulator for use with HES music files
-
-// Game_Music_Emu 0.5.5
-#ifndef HES_CPU_H
-#define HES_CPU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long hes_time_t; // clock cycle count
-typedef unsigned hes_addr_t; // 16-bit address
-enum { future_hes_time = INT_MAX / 2 + 1 };
-
-class Hes_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- void reset();
-
- enum { page_size = 0x2000 };
- enum { page_shift = 13 };
- enum { page_count = 8 };
- void set_mmr( int reg, int bank );
-
- uint8_t const* get_code( hes_addr_t );
-
- uint8_t ram [page_size];
-
- // not kept updated during a call to run()
- struct registers_t {
- BOOST::uint16_t pc;
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- };
- registers_t r;
-
- // page mapping registers
- uint8_t mmr [page_count + 1];
-
- // Set end_time and run CPU from current time. Returns true if any illegal
- // instructions were encountered.
- bool run( hes_time_t end_time );
-
- // Time of beginning of next instruction to be executed
- hes_time_t time() const { return state->time + state->base; }
- void set_time( hes_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- hes_time_t irq_time() const { return irq_time_; }
- void set_irq_time( hes_time_t );
-
- hes_time_t end_time() const { return end_time_; }
- void set_end_time( hes_time_t );
-
- void end_frame( hes_time_t );
-
- // Attempt to execute instruction here results in CPU advancing time to
- // lesser of irq_time() and end_time() (or end_time() if IRQs are
- // disabled)
- enum { idle_addr = 0x1FFF };
-
- // Can read this many bytes past end of a page
- enum { cpu_padding = 8 };
-
-public:
- Hes_Cpu() { state = &state_; }
- enum { irq_inhibit = 0x04 };
-private:
- // noncopyable
- Hes_Cpu( const Hes_Cpu& );
- Hes_Cpu& operator = ( const Hes_Cpu& );
-
- struct state_t {
- uint8_t const* code_map [page_count + 1];
- hes_time_t base;
- blargg_long time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- hes_time_t irq_time_;
- hes_time_t end_time_;
-
- void set_code_page( int, void const* );
- inline int update_end_time( hes_time_t end, hes_time_t irq );
-};
-
-inline BOOST::uint8_t const* Hes_Cpu::get_code( hes_addr_t addr )
-{
- return state->code_map [addr >> page_shift] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-inline int Hes_Cpu::update_end_time( hes_time_t t, hes_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- int delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Hes_Cpu::set_irq_time( hes_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Hes_Cpu::set_end_time( hes_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-inline void Hes_Cpu::end_frame( hes_time_t t )
-{
- assert( state == &state_ );
- state_.base -= t;
- if ( irq_time_ < future_hes_time ) irq_time_ -= t;
- if ( end_time_ < future_hes_time ) end_time_ -= t;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.cpp
deleted file mode 100644
index 9a32b688..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.cpp
+++ /dev/null
@@ -1,531 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Hes_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const timer_mask = 0x04;
-int const vdp_mask = 0x02;
-int const i_flag_mask = 0x04;
-int const unmapped = 0xFF;
-
-long const period_60hz = 262 * 455L; // scanlines * clocks per scanline
-
-Hes_Emu::Hes_Emu()
-{
- timer.raw_load = 0;
- set_type( gme_hes_type );
-
- static const char* const names [Hes_Apu::osc_count] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Multi 1", "Multi 2"
- };
- set_voice_names( names );
-
- static int const types [Hes_Apu::osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2, wave_type | 3,
- mixed_type | 0, mixed_type | 1
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
- set_gain( 1.11 );
-}
-
-Hes_Emu::~Hes_Emu() { }
-
-void Hes_Emu::unload()
-{
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static byte const* copy_field( byte const* in, char* out )
-{
- if ( in )
- {
- int len = 0x20;
- if ( in [0x1F] && !in [0x2F] )
- len = 0x30; // fields are sometimes 16 bytes longer (ugh)
-
- // since text fields are where any data could be, detect non-text
- // and fields with data after zero byte terminator
-
- int i = 0;
- for ( i = 0; i < len && in [i]; i++ )
- if ( ((in [i] + 1) & 0xFF) < ' ' + 1 ) // also treat 0xFF as non-text
- return 0; // non-ASCII found
-
- for ( ; i < len; i++ )
- if ( in [i] )
- return 0; // data after terminator
-
- Gme_File::copy_field_( out, (char const*) in, len );
- in += len;
- }
- return in;
-}
-
-static void copy_hes_fields( byte const* in, track_info_t* out )
-{
- if ( *in >= ' ' )
- {
- in = copy_field( in, out->game );
- in = copy_field( in, out->author );
- in = copy_field( in, out->copyright );
- }
-}
-
-blargg_err_t Hes_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_hes_fields( rom.begin() + 0x20, out );
- return 0;
-}
-
-static blargg_err_t check_hes_header( void const* header )
-{
- if ( memcmp( header, "HESM", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Hes_File : Gme_Info_
-{
- struct header_t {
- char header [Hes_Emu::header_size];
- char unused [0x20];
- byte fields [0x30 * 3];
- } h;
-
- Hes_File() { set_type( gme_hes_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20 );
- blargg_err_t err = in.read( &h, sizeof h );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- return check_hes_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_hes_fields( h.fields, out );
- return 0;
- }
-};
-
-static Music_Emu* new_hes_emu () { return BLARGG_NEW Hes_Emu ; }
-static Music_Emu* new_hes_file() { return BLARGG_NEW Hes_File; }
-
-static gme_type_t_ const gme_hes_type_ = { "PC Engine", 256, &new_hes_emu, &new_hes_file, "HES", 1 };
-gme_type_t const gme_hes_type = &gme_hes_type_;
-
-
-// Setup
-
-blargg_err_t Hes_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,unused [4]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) );
-
- RETURN_ERR( check_hes_header( header_.tag ) );
-
- if ( header_.vers != 0 )
- set_warning( "Unknown file version" );
-
- if ( memcmp( header_.data_tag, "DATA", 4 ) )
- set_warning( "Data header missing" );
-
- if ( memcmp( header_.unused, "\0\0\0\0", 4 ) )
- set_warning( "Unknown header data" );
-
- // File spec supports multiple blocks, but I haven't found any, and
- // many files have bad sizes in the only block, so it's simpler to
- // just try to load the damn data as best as possible.
-
- long addr = get_le32( header_.addr );
- long size = get_le32( header_.size );
- long const rom_max = 0x100000;
- if ( addr & ~(rom_max - 1) )
- {
- set_warning( "Invalid address" );
- addr &= rom_max - 1;
- }
- if ( (unsigned long) (addr + size) > (unsigned long) rom_max )
- set_warning( "Invalid size" );
-
- if ( size != rom.file_size() )
- {
- if ( size <= rom.file_size() - 4 && !memcmp( rom.begin() + size, "DATA", 4 ) )
- set_warning( "Multiple DATA not supported" );
- else if ( size < rom.file_size() )
- set_warning( "Extra file data" );
- else
- set_warning( "Missing file data" );
- }
-
- rom.set_addr( addr );
-
- set_voice_count( apu.osc_count );
-
- apu.volume( gain() );
-
- return setup_buffer( 7159091 );
-}
-
-void Hes_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-}
-
-void Hes_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- apu.osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Hes_Emu::recalc_timer_load()
-{
- timer.load = timer.raw_load * timer_base + 1;
-}
-
-void Hes_Emu::set_tempo_( double t )
-{
- play_period = hes_time_t (period_60hz / t);
- timer_base = int (1024 / t);
- recalc_timer_load();
-}
-
-blargg_err_t Hes_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0, sizeof ram ); // some HES music relies on zero fill
- memset( sgx, 0, sizeof sgx );
-
- apu.reset();
- cpu::reset();
-
- for ( unsigned i = 0; i < sizeof header_.banks; i++ )
- set_mmr( i, header_.banks [i] );
- set_mmr( page_count, 0xFF ); // unmapped beyond end of address space
-
- irq.disables = timer_mask | vdp_mask;
- irq.timer = future_hes_time;
- irq.vdp = future_hes_time;
-
- timer.enabled = false;
- timer.raw_load= 0x80;
- timer.count = timer.load;
- timer.fired = false;
- timer.last_time = 0;
-
- vdp.latch = 0;
- vdp.control = 0;
- vdp.next_vbl = 0;
-
- ram [0x1FF] = (idle_addr - 1) >> 8;
- ram [0x1FE] = (idle_addr - 1) & 0xFF;
- r.sp = 0xFD;
- r.pc = get_le16( header_.init_addr );
- r.a = track;
-
- recalc_timer_load();
- last_frame_hook = 0;
-
- return 0;
-}
-
-// Hardware
-
-void Hes_Emu::cpu_write_vdp( int addr, int data )
-{
- switch ( addr )
- {
- case 0:
- vdp.latch = data & 0x1F;
- break;
-
- case 2:
- if ( vdp.latch == 5 )
- {
- if ( data & 0x04 )
- set_warning( "Scanline interrupt unsupported" );
- run_until( time() );
- vdp.control = data;
- irq_changed();
- }
- else
- {
- debug_printf( "VDP not supported: $%02X <- $%02X\n", vdp.latch, data );
- }
- break;
-
- case 3:
- debug_printf( "VDP MSB not supported: $%02X <- $%02X\n", vdp.latch, data );
- break;
- }
-}
-
-void Hes_Emu::cpu_write_( hes_addr_t addr, int data )
-{
- if ( unsigned (addr - apu.start_addr) <= apu.end_addr - apu.start_addr )
- {
- GME_APU_HOOK( this, addr - apu.start_addr, data );
- // avoid going way past end when a long block xfer is writing to I/O space
- hes_time_t t = min( time(), end_time() + 8 );
- apu.write_data( t, addr, data );
- return;
- }
-
- hes_time_t time = this->time();
- switch ( addr )
- {
- case 0x0000:
- case 0x0002:
- case 0x0003:
- cpu_write_vdp( addr, data );
- return;
-
- case 0x0C00: {
- run_until( time );
- timer.raw_load = (data & 0x7F) + 1;
- recalc_timer_load();
- timer.count = timer.load;
- break;
- }
-
- case 0x0C01:
- data &= 1;
- if ( timer.enabled == data )
- return;
- run_until( time );
- timer.enabled = data;
- if ( data )
- timer.count = timer.load;
- break;
-
- case 0x1402:
- run_until( time );
- irq.disables = data;
- if ( (data & 0xF8) && (data & 0xF8) != 0xF8 ) // flag questionable values
- debug_printf( "Int mask: $%02X\n", data );
- break;
-
- case 0x1403:
- run_until( time );
- if ( timer.enabled )
- timer.count = timer.load;
- timer.fired = false;
- break;
-
-#ifndef NDEBUG
- case 0x1000: // I/O port
- case 0x0402: // palette
- case 0x0403:
- case 0x0404:
- case 0x0405:
- return;
-
- default:
- debug_printf( "unmapped write $%04X <- $%02X\n", addr, data );
- return;
-#endif
- }
-
- irq_changed();
-}
-
-int Hes_Emu::cpu_read_( hes_addr_t addr )
-{
- hes_time_t time = this->time();
- addr &= page_size - 1;
- switch ( addr )
- {
- case 0x0000:
- if ( irq.vdp > time )
- return 0;
- irq.vdp = future_hes_time;
- run_until( time );
- irq_changed();
- return 0x20;
-
- case 0x0002:
- case 0x0003:
- debug_printf( "VDP read not supported: %d\n", addr );
- return 0;
-
- case 0x0C01:
- //return timer.enabled; // TODO: remove?
- case 0x0C00:
- run_until( time );
- debug_printf( "Timer count read\n" );
- return (unsigned) (timer.count - 1) / timer_base;
-
- case 0x1402:
- return irq.disables;
-
- case 0x1403:
- {
- int status = 0;
- if ( irq.timer <= time ) status |= timer_mask;
- if ( irq.vdp <= time ) status |= vdp_mask;
- return status;
- }
-
- #ifndef NDEBUG
- case 0x1000: // I/O port
- case 0x180C: // CD-ROM
- case 0x180D:
- break;
-
- default:
- debug_printf( "unmapped read $%04X\n", addr );
- #endif
- }
-
- return unmapped;
-}
-
-// see hes_cpu_io.h for core read/write functions
-
-// Emulation
-
-void Hes_Emu::run_until( hes_time_t present )
-{
- while ( vdp.next_vbl < present )
- vdp.next_vbl += play_period;
-
- hes_time_t elapsed = present - timer.last_time;
- if ( elapsed > 0 )
- {
- if ( timer.enabled )
- {
- timer.count -= elapsed;
- if ( timer.count <= 0 )
- timer.count += timer.load;
- }
- timer.last_time = present;
- }
-}
-
-void Hes_Emu::irq_changed()
-{
- hes_time_t present = time();
-
- if ( irq.timer > present )
- {
- irq.timer = future_hes_time;
- if ( timer.enabled && !timer.fired )
- irq.timer = present + timer.count;
- }
-
- if ( irq.vdp > present )
- {
- irq.vdp = future_hes_time;
- if ( vdp.control & 0x08 )
- irq.vdp = vdp.next_vbl;
- }
-
- hes_time_t time = future_hes_time;
- if ( !(irq.disables & timer_mask) ) time = irq.timer;
- if ( !(irq.disables & vdp_mask) ) time = min( time, irq.vdp );
-
- set_irq_time( time );
-}
-
-int Hes_Emu::cpu_done()
-{
- check( time() >= end_time() ||
- (!(r.status & i_flag_mask) && time() >= irq_time()) );
-
- if ( !(r.status & i_flag_mask) )
- {
- hes_time_t present = time();
-
- if ( irq.timer <= present && !(irq.disables & timer_mask) )
- {
- timer.fired = true;
- irq.timer = future_hes_time;
- irq_changed(); // overkill, but not worth writing custom code
- #if GME_FRAME_HOOK_DEFINED
- {
- unsigned const threshold = period_60hz / 30;
- unsigned long elapsed = present - last_frame_hook;
- if ( elapsed - period_60hz + threshold / 2 < threshold )
- {
- last_frame_hook = present;
- GME_FRAME_HOOK( this );
- }
- }
- #endif
- return 0x0A;
- }
-
- if ( irq.vdp <= present && !(irq.disables & vdp_mask) )
- {
- // work around for bugs with music not acknowledging VDP
- //run_until( present );
- //irq.vdp = future_hes_time;
- //irq_changed();
- #if GME_FRAME_HOOK_DEFINED
- last_frame_hook = present;
- GME_FRAME_HOOK( this );
- #endif
- return 0x08;
- }
- }
- return 0;
-}
-
-static void adjust_time( blargg_long& time, hes_time_t delta )
-{
- if ( time < future_hes_time )
- {
- time -= delta;
- if ( time < 0 )
- time = 0;
- }
-}
-
-blargg_err_t Hes_Emu::run_clocks( blip_time_t& duration_, int )
-{
- blip_time_t const duration = duration_; // cache
-
- if ( cpu::run( duration ) )
- set_warning( "Emulation error (illegal instruction)" );
-
- check( time() >= duration );
- //check( time() - duration < 20 ); // Txx instruction could cause going way over
-
- run_until( duration );
-
- // end time frame
- timer.last_time -= duration;
- vdp.next_vbl -= duration;
- #if GME_FRAME_HOOK_DEFINED
- last_frame_hook -= duration;
- #endif
- cpu::end_frame( duration );
- ::adjust_time( irq.timer, duration );
- ::adjust_time( irq.vdp, duration );
- apu.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.h
deleted file mode 100644
index d17983c5..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Hes_Emu.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// TurboGrafx-16/PC Engine HES music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef HES_EMU_H
-#define HES_EMU_H
-
-#include "Classic_Emu.h"
-#include "Hes_Apu.h"
-#include "Hes_Cpu.h"
-
-class Hes_Emu : private Hes_Cpu, public Classic_Emu {
- typedef Hes_Cpu cpu;
-public:
- // HES file header
- enum { header_size = 0x20 };
- struct header_t
- {
- byte tag [4];
- byte vers;
- byte first_track;
- byte init_addr [2];
- byte banks [8];
- byte data_tag [4];
- byte size [4];
- byte addr [4];
- byte unused [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_hes_type; }
-
-public:
- Hes_Emu();
- ~Hes_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-public: private: friend class Hes_Cpu;
- byte* write_pages [page_count + 1]; // 0 if unmapped or I/O space
-
- int cpu_read_( hes_addr_t );
- int cpu_read( hes_addr_t );
- void cpu_write_( hes_addr_t, int data );
- void cpu_write( hes_addr_t, int );
- void cpu_write_vdp( int addr, int data );
- byte const* cpu_set_mmr( int page, int bank );
- int cpu_done();
-private:
- Rom_Data<page_size> rom;
- header_t header_;
- hes_time_t play_period;
- hes_time_t last_frame_hook;
- int timer_base;
-
- struct {
- hes_time_t last_time;
- blargg_long count;
- blargg_long load;
- int raw_load;
- byte enabled;
- byte fired;
- } timer;
-
- struct {
- hes_time_t next_vbl;
- byte latch;
- byte control;
- } vdp;
-
- struct {
- hes_time_t timer;
- hes_time_t vdp;
- byte disables;
- } irq;
-
- void recalc_timer_load();
-
- // large items
- Hes_Apu apu;
- byte sgx [3 * page_size + cpu_padding];
-
- void irq_changed();
- void run_until( hes_time_t );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.cpp
deleted file mode 100644
index dac483c1..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.cpp
+++ /dev/null
@@ -1,1706 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-/*
-Last validated with zexall 2006.11.14 2:19 PM
-* Doesn't implement the R register or immediate interrupt after EI.
-* Address wrap-around isn't completely correct, but is prevented from crashing emulator.
-*/
-
-#include "Kss_Cpu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-//#include "z80_cpu_log.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define SYNC_TIME() (void) (s.time = s_time)
-#define RELOAD_TIME() (void) (s_time = s.time)
-
-// Callbacks to emulator
-
-#define CPU_OUT( cpu, addr, data, time )\
- kss_cpu_out( this, time, addr, data )
-
-#define CPU_IN( cpu, addr, time )\
- kss_cpu_in( this, time, addr )
-
-#define CPU_WRITE( cpu, addr, data, time )\
- (SYNC_TIME(), kss_cpu_write( this, addr, data ))
-
-#include "blargg_source.h"
-
-// flags, named with hex value for clarity
-int const S80 = 0x80;
-int const Z40 = 0x40;
-int const F20 = 0x20;
-int const H10 = 0x10;
-int const F08 = 0x08;
-int const V04 = 0x04;
-int const P04 = 0x04;
-int const N02 = 0x02;
-int const C01 = 0x01;
-
-#define SZ28P( n ) szpc [n]
-#define SZ28PC( n ) szpc [n]
-#define SZ28C( n ) (szpc [n] & ~P04)
-#define SZ28( n ) SZ28C( n )
-
-#define SET_R( n ) (void) (r.r = n)
-#define GET_R() (r.r)
-
-Kss_Cpu::Kss_Cpu()
-{
- state = &state_;
-
- for ( int i = 0x100; --i >= 0; )
- {
- int even = 1;
- for ( int p = i; p; p >>= 1 )
- even ^= p;
- int n = (i & (S80 | F20 | F08)) | ((even & 1) * P04);
- szpc [i] = n;
- szpc [i + 0x100] = n | C01;
- }
- szpc [0x000] |= Z40;
- szpc [0x100] |= Z40;
-}
-
-inline void Kss_Cpu::set_page( int i, void* write, void const* read )
-{
- blargg_long offset = KSS_CPU_PAGE_OFFSET( i * (blargg_long) page_size );
- state->write [i] = (byte *) write - offset;
- state->read [i] = (byte const*) read - offset;
-}
-
-void Kss_Cpu::reset( void* unmapped_write, void const* unmapped_read )
-{
- check( state == &state_ );
- state = &state_;
- state_.time = 0;
- state_.base = 0;
- end_time_ = 0;
-
- for ( int i = 0; i < page_count + 1; i++ )
- set_page( i, unmapped_write, unmapped_read );
-
- memset( &r, 0, sizeof r );
-}
-
-void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const* read )
-{
- // address range must begin and end on page boundaries
- require( addr % page_size == 0 );
- require( size % page_size == 0 );
-
- unsigned first_page = addr / page_size;
- for ( unsigned i = size / page_size; i--; )
- {
- blargg_long offset = i * (blargg_long) page_size;
- set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset );
- }
-}
-
-#define TIME (s_time + s.base)
-#define RW_MEM( addr, rw ) (s.rw [(addr) >> page_shift] [KSS_CPU_PAGE_OFFSET( addr )])
-#define READ_PROG( addr ) RW_MEM( addr, read )
-#define READ( addr ) READ_PROG( addr )
-//#define WRITE( addr, data ) (void) (RW_MEM( addr, write ) = data)
-#define WRITE( addr, data ) CPU_WRITE( this, addr, data, TIME )
-#define READ_WORD( addr ) GET_LE16( &READ( addr ) )
-#define WRITE_WORD( addr, data ) SET_LE16( &RW_MEM( addr, write ), data )
-#define IN( addr ) CPU_IN( this, addr, TIME )
-#define OUT( addr, data ) CPU_OUT( this, addr, data, TIME )
-
-#if BLARGG_BIG_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [n])
-#elif BLARGG_LITTLE_ENDIAN
- #define R8( n, offset ) ((r8_ - offset) [(n) ^ 1])
-#else
- #error "Byte order of CPU must be known"
-#endif
-
-//#define R16( n, shift, offset ) (r16_ [((n) >> shift) - (offset >> shift)])
-
-// help compiler see that it can just adjust stack offset, saving an extra instruction
-#define R16( n, shift, offset )\
- (*(uint16_t*) ((char*) r16_ - (offset >> (shift - 1)) + ((n) >> (shift - 1))))
-
-#define CASE5( a, b, c, d, e ) case 0x##a:case 0x##b:case 0x##c:case 0x##d:case 0x##e
-#define CASE6( a, b, c, d, e, f ) CASE5( a, b, c, d, e ): case 0x##f
-#define CASE7( a, b, c, d, e, f, g ) CASE6( a, b, c, d, e, f ): case 0x##g
-#define CASE8( a, b, c, d, e, f, g, h ) CASE7( a, b, c, d, e, f, g ): case 0x##h
-
-// high four bits are $ED time - 8, low four bits are $DD/$FD time - 8
-static byte const ed_dd_timing [0x100] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x0C,0x02,0x00,0x00,0x03,0x00,0x00,0x07,0x0C,0x02,0x00,0x00,0x03,0x00,
-0x00,0x00,0x00,0x00,0x0F,0x0F,0x0B,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x10,
-0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0xA0,
-0x4B,0x4B,0x7B,0xCB,0x0B,0x6B,0x00,0x0B,0x40,0x40,0x70,0xC0,0x00,0x60,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0B,0x00,
-0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0B,0x00,
-0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,0xD0,0xD0,0xD0,0xD0,0x00,0x00,0x0B,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x06,0x00,0x0F,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-};
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Kss_Cpu::run( cpu_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- bool warning = false;
-
- typedef BOOST::int8_t int8_t;
-
- union {
- regs_t rg;
- pairs_t rp;
- uint8_t r8_ [8]; // indexed
- uint16_t r16_ [4];
- };
- rg = this->r.b;
-
- cpu_time_t s_time = s.time;
- fuint16 pc = r.pc;
- fuint16 sp = r.sp;
- fuint16 ix = r.ix; // TODO: keep in memory for direct access?
- fuint16 iy = r.iy;
- int flags = r.b.flags;
-
- goto loop;
-jr_not_taken:
- s_time -= 5;
- goto loop;
-call_not_taken:
- s_time -= 7;
-jp_not_taken:
- pc += 2;
-loop:
-
- check( (unsigned long) pc < 0x10000 );
- check( (unsigned long) sp < 0x10000 );
- check( (unsigned) flags < 0x100 );
- check( (unsigned) ix < 0x10000 );
- check( (unsigned) iy < 0x10000 );
-
- uint8_t const* instr = s.read [pc >> page_shift];
-#define GET_ADDR() GET_LE16( instr )
-
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += KSS_CPU_PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- static byte const base_timing [0x100] = {
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, // 0
- 13,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, // 1
- 12,10,16, 6, 4, 4, 7, 4,12,11,16, 6, 4, 4, 7, 4, // 2
- 12,10,13, 6,11,11,10, 4,12,11,13, 6, 4, 4, 7, 4, // 3
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 4
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 5
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 6
- 7, 7, 7, 7, 7, 7, 4, 7, 4, 4, 4, 4, 4, 4, 7, 4, // 7
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 8
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // 9
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // A
- 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4, // B
- 11,10,10,10,17,11, 7,11,11,10,10, 8,17,17, 7,11, // C
- 11,10,10,11,17,11, 7,11,11, 4,10,11,17, 8, 7,11, // D
- 11,10,10,19,17,11, 7,11,11, 4,10, 4,17, 8, 7,11, // E
- 11,10,10, 4,17,11, 7,11,11, 6,10, 4,17, 8, 7,11, // F
- };
-
- fuint16 data;
- data = base_timing [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = READ_PROG( pc );
-
- #ifdef Z80_CPU_LOG_H
- //log_opcode( opcode, READ_PROG( pc ) );
- z80_log_regs( rg.a, rp.bc, rp.de, rp.hl, sp, ix, iy );
- z80_cpu_log( "new", pc - 1, opcode, READ_PROG( pc ),
- READ_PROG( pc + 1 ), READ_PROG( pc + 2 ) );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Common
-
- case 0x00: // NOP
- CASE7( 40, 49, 52, 5B, 64, 6D, 7F ): // LD B,B etc.
- goto loop;
-
- case 0x08:{// EX AF,AF'
- int temp = r.alt.b.a;
- r.alt.b.a = rg.a;
- rg.a = temp;
-
- temp = r.alt.b.flags;
- r.alt.b.flags = flags;
- flags = temp;
- goto loop;
- }
-
- case 0xD3: // OUT (imm),A
- pc++;
- OUT( data + rg.a * 0x100, rg.a );
- goto loop;
-
- case 0x2E: // LD L,imm
- pc++;
- rg.l = data;
- goto loop;
-
- case 0x3E: // LD A,imm
- pc++;
- rg.a = data;
- goto loop;
-
- case 0x3A:{// LD A,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rg.a = READ( addr );
- goto loop;
- }
-
-// Conditional
-
-#define ZERO (flags & Z40)
-#define CARRY (flags & C01)
-#define EVEN (flags & P04)
-#define MINUS (flags & S80)
-
-// JR
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define JR( cond ) {\
- int offset = (BOOST::int8_t) data;\
- pc++;\
- if ( !(cond) )\
- goto jr_not_taken;\
- pc = uint16_t (pc + offset);\
- goto loop;\
-}
-
- case 0x20: JR( !ZERO ) // JR NZ,disp
- case 0x28: JR( ZERO ) // JR Z,disp
- case 0x30: JR( !CARRY ) // JR NC,disp
- case 0x38: JR( CARRY ) // JR C,disp
- case 0x18: JR( true ) // JR disp
-
- case 0x10:{// DJNZ disp
- int temp = rg.b - 1;
- rg.b = temp;
- JR( temp )
- }
-
-// JP
-#define JP( cond ) if ( !(cond) ) goto jp_not_taken; pc = GET_ADDR(); goto loop;
-
- case 0xC2: JP( !ZERO ) // JP NZ,addr
- case 0xCA: JP( ZERO ) // JP Z,addr
- case 0xD2: JP( !CARRY ) // JP NC,addr
- case 0xDA: JP( CARRY ) // JP C,addr
- case 0xE2: JP( !EVEN ) // JP PO,addr
- case 0xEA: JP( EVEN ) // JP PE,addr
- case 0xF2: JP( !MINUS ) // JP P,addr
- case 0xFA: JP( MINUS ) // JP M,addr
-
- case 0xC3: // JP addr
- pc = GET_ADDR();
- goto loop;
-
- case 0xE9: // JP HL
- pc = rp.hl;
- goto loop;
-
-// RET
-#define RET( cond ) if ( cond ) goto ret_taken; s_time -= 6; goto loop;
-
- case 0xC0: RET( !ZERO ) // RET NZ
- case 0xC8: RET( ZERO ) // RET Z
- case 0xD0: RET( !CARRY ) // RET NC
- case 0xD8: RET( CARRY ) // RET C
- case 0xE0: RET( !EVEN ) // RET PO
- case 0xE8: RET( EVEN ) // RET PE
- case 0xF0: RET( !MINUS ) // RET P
- case 0xF8: RET( MINUS ) // RET M
-
- case 0xC9: // RET
- ret_taken:
- pc = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// CALL
-#define CALL( cond ) if ( cond ) goto call_taken; goto call_not_taken;
-
- case 0xC4: CALL( !ZERO ) // CALL NZ,addr
- case 0xCC: CALL( ZERO ) // CALL Z,addr
- case 0xD4: CALL( !CARRY ) // CALL NC,addr
- case 0xDC: CALL( CARRY ) // CALL C,addr
- case 0xE4: CALL( !EVEN ) // CALL PO,addr
- case 0xEC: CALL( EVEN ) // CALL PE,addr
- case 0xF4: CALL( !MINUS ) // CALL P,addr
- case 0xFC: CALL( MINUS ) // CALL M,addr
-
- case 0xCD:{// CALL addr
- call_taken:
- fuint16 addr = pc + 2;
- pc = GET_ADDR();
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, addr );
- goto loop;
- }
-
- case 0xFF: // RST
- if ( pc > idle_addr )
- goto hit_idle_addr;
- CASE7( C7, CF, D7, DF, E7, EF, F7 ):
- data = pc;
- pc = opcode & 0x38;
- goto push_data;
-
-// PUSH/POP
- case 0xF5: // PUSH AF
- data = rg.a * 0x100u + flags;
- goto push_data;
-
- case 0xC5: // PUSH BC
- case 0xD5: // PUSH DE
- case 0xE5: // PUSH HL
- data = R16( opcode, 4, 0xC5 );
- push_data:
- sp = uint16_t (sp - 2);
- WRITE_WORD( sp, data );
- goto loop;
-
- case 0xF1: // POP AF
- flags = READ( sp );
- rg.a = READ( sp + 1 );
- sp = uint16_t (sp + 2);
- goto loop;
-
- case 0xC1: // POP BC
- case 0xD1: // POP DE
- case 0xE1: // POP HL
- R16( opcode, 4, 0xC1 ) = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto loop;
-
-// ADC/ADD/SBC/SUB
- case 0x96: // SUB (HL)
- case 0x86: // ADD (HL)
- flags &= ~C01;
- case 0x9E: // SBC (HL)
- case 0x8E: // ADC (HL)
- data = READ( rp.hl );
- goto adc_data;
-
- case 0xD6: // SUB A,imm
- case 0xC6: // ADD imm
- flags &= ~C01;
- case 0xDE: // SBC A,imm
- case 0xCE: // ADC imm
- pc++;
- goto adc_data;
-
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // SUB r
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // ADD r
- flags &= ~C01;
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // SBC r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // ADC r
- data = R8( opcode & 7, 0 );
- adc_data: {
- int result = data + (flags & C01);
- data ^= rg.a;
- flags = opcode >> 3 & N02; // bit 4 is set in subtract opcodes
- if ( flags )
- result = -result;
- result += rg.a;
- data ^= result;
- flags |=(data & H10) |
- ((data - -0x80) >> 6 & V04) |
- SZ28C( result & 0x1FF );
- rg.a = result;
- goto loop;
- }
-
-// CP
- case 0xBE: // CP (HL)
- data = READ( rp.hl );
- goto cp_data;
-
- case 0xFE: // CP imm
- pc++;
- goto cp_data;
-
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // CP r
- data = R8( opcode, 0xB8 );
- cp_data: {
- int result = rg.a - data;
- flags = N02 | (data & (F20 | F08)) | (result >> 8 & C01);
- data ^= rg.a;
- flags |=(((result ^ rg.a) & data) >> 5 & V04) |
- (((data & H10) ^ result) & (S80 | H10));
- if ( (uint8_t) result )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
-// ADD HL,rp
-
- case 0x39: // ADD HL,SP
- data = sp;
- goto add_hl_data;
-
- case 0x09: // ADD HL,BC
- case 0x19: // ADD HL,DE
- case 0x29: // ADD HL,HL
- data = R16( opcode, 4, 0x09 );
- add_hl_data: {
- blargg_ulong sum = rp.hl + data;
- data ^= rp.hl;
- rp.hl = sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((data ^ sum) >> 8 & H10);
- goto loop;
- }
-
- case 0x27:{// DAA
- int a = rg.a;
- if ( a > 0x99 )
- flags |= C01;
-
- int adjust = 0x60 & -(flags & C01);
-
- if ( flags & H10 || (a & 0x0F) > 9 )
- adjust |= 0x06;
-
- if ( flags & N02 )
- adjust = -adjust;
- a += adjust;
-
- flags = (flags & (C01 | N02)) |
- ((rg.a ^ a) & H10) |
- SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- /*
- case 0x27:{// DAA
- // more optimized, but probably not worth the obscurity
- int f = (rg.a + (0xFF - 0x99)) >> 8 | flags; // (a > 0x99 ? C01 : 0) | flags
- int adjust = 0x60 & -(f & C01); // f & C01 ? 0x60 : 0
-
- if ( (((rg.a + (0x0F - 9)) ^ rg.a) | f) & H10 ) // flags & H10 || (rg.a & 0x0F) > 9
- adjust |= 0x06;
-
- if ( f & N02 )
- adjust = -adjust;
- int a = rg.a + adjust;
-
- flags = (f & (N02 | C01)) | ((rg.a ^ a) & H10) | SZ28P( (uint8_t) a );
- rg.a = a;
- goto loop;
- }
- */
-
-// INC/DEC
- case 0x34: // INC (HL)
- data = READ( rp.hl ) + 1;
- WRITE( rp.hl, data );
- goto inc_set_flags;
-
- CASE7( 04, 0C, 14, 1C, 24, 2C, 3C ): // INC r
- data = ++R8( opcode >> 3, 0 );
- inc_set_flags:
- flags = (flags & C01) |
- (((data & 0x0F) - 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x80 )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x35: // DEC (HL)
- data = READ( rp.hl ) - 1;
- WRITE( rp.hl, data );
- goto dec_set_flags;
-
- CASE7( 05, 0D, 15, 1D, 25, 2D, 3D ): // DEC r
- data = --R8( opcode >> 3, 0 );
- dec_set_flags:
- flags = (flags & C01) | N02 |
- (((data & 0x0F) + 1) & H10) |
- SZ28( (uint8_t) data );
- if ( data != 0x7F )
- goto loop;
- flags |= V04;
- goto loop;
-
- case 0x03: // INC BC
- case 0x13: // INC DE
- case 0x23: // INC HL
- R16( opcode, 4, 0x03 )++;
- goto loop;
-
- case 0x33: // INC SP
- sp = uint16_t (sp + 1);
- goto loop;
-
- case 0x0B: // DEC BC
- case 0x1B: // DEC DE
- case 0x2B: // DEC HL
- R16( opcode, 4, 0x0B )--;
- goto loop;
-
- case 0x3B: // DEC SP
- sp = uint16_t (sp - 1);
- goto loop;
-
-// AND
- case 0xA6: // AND (HL)
- data = READ( rp.hl );
- goto and_data;
-
- case 0xE6: // AND imm
- pc++;
- goto and_data;
-
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // AND r
- data = R8( opcode, 0xA0 );
- and_data:
- rg.a &= data;
- flags = SZ28P( rg.a ) | H10;
- goto loop;
-
-// OR
- case 0xB6: // OR (HL)
- data = READ( rp.hl );
- goto or_data;
-
- case 0xF6: // OR imm
- pc++;
- goto or_data;
-
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // OR r
- data = R8( opcode, 0xB0 );
- or_data:
- rg.a |= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// XOR
- case 0xAE: // XOR (HL)
- data = READ( rp.hl );
- goto xor_data;
-
- case 0xEE: // XOR imm
- pc++;
- goto xor_data;
-
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // XOR r
- data = R8( opcode, 0xA8 );
- xor_data:
- rg.a ^= data;
- flags = SZ28P( rg.a );
- goto loop;
-
-// LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (HL),r
- WRITE( rp.hl, R8( opcode, 0x70 ) );
- goto loop;
-
- CASE6( 41, 42, 43, 44, 45, 47 ): // LD B,r
- CASE6( 48, 4A, 4B, 4C, 4D, 4F ): // LD C,r
- CASE6( 50, 51, 53, 54, 55, 57 ): // LD D,r
- CASE6( 58, 59, 5A, 5C, 5D, 5F ): // LD E,r
- CASE6( 60, 61, 62, 63, 65, 67 ): // LD H,r
- CASE6( 68, 69, 6A, 6B, 6C, 6F ): // LD L,r
- CASE6( 78, 79, 7A, 7B, 7C, 7D ): // LD A,r
- R8( opcode >> 3 & 7, 0 ) = R8( opcode & 7, 0 );
- goto loop;
-
- CASE5( 06, 0E, 16, 1E, 26 ): // LD r,imm
- R8( opcode >> 3, 0 ) = data;
- pc++;
- goto loop;
-
- case 0x36: // LD (HL),imm
- pc++;
- WRITE( rp.hl, data );
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(HL)
- R8( opcode >> 3, 8 ) = READ( rp.hl );
- goto loop;
-
- case 0x01: // LD rp,imm
- case 0x11:
- case 0x21:
- R16( opcode, 4, 0x01 ) = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x31: // LD sp,imm
- sp = GET_ADDR();
- pc += 2;
- goto loop;
-
- case 0x2A:{// LD HL,(addr)
- fuint16 addr = GET_ADDR();
- pc += 2;
- rp.hl = READ_WORD( addr );
- goto loop;
- }
-
- case 0x32:{// LD (addr),A
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE( addr, rg.a );
- goto loop;
- }
-
- case 0x22:{// LD (addr),HL
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, rp.hl );
- goto loop;
- }
-
- case 0x02: // LD (BC),A
- case 0x12: // LD (DE),A
- WRITE( R16( opcode, 4, 0x02 ), rg.a );
- goto loop;
-
- case 0x0A: // LD A,(BC)
- case 0x1A: // LD A,(DE)
- rg.a = READ( R16( opcode, 4, 0x0A ) );
- goto loop;
-
- case 0xF9: // LD SP,HL
- sp = rp.hl;
- goto loop;
-
-// Rotate
-
- case 0x07:{// RLCA
- fuint16 temp = rg.a;
- temp = (temp << 1) | (temp >> 7);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08 | C01));
- rg.a = temp;
- goto loop;
- }
-
- case 0x0F:{// RRCA
- fuint16 temp = rg.a;
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & C01);
- temp = (temp << 7) | (temp >> 1);
- flags |= temp & (F20 | F08);
- rg.a = temp;
- goto loop;
- }
-
- case 0x17:{// RLA
- blargg_ulong temp = (rg.a << 1) | (flags & C01);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (temp >> 8);
- rg.a = temp;
- goto loop;
- }
-
- case 0x1F:{// RRA
- fuint16 temp = (flags << 7) | (rg.a >> 1);
- flags = (flags & (S80 | Z40 | P04)) |
- (temp & (F20 | F08)) |
- (rg.a & C01);
- rg.a = temp;
- goto loop;
- }
-
-// Misc
- case 0x2F:{// CPL
- fuint16 temp = ~rg.a;
- flags = (flags & (S80 | Z40 | P04 | C01)) |
- (temp & (F20 | F08)) |
- (H10 | N02);
- rg.a = temp;
- goto loop;
- }
-
- case 0x3F:{// CCF
- flags = ((flags & (S80 | Z40 | P04 | C01)) ^ C01) |
- (flags << 4 & H10) |
- (rg.a & (F20 | F08));
- goto loop;
- }
-
- case 0x37: // SCF
- flags = (flags & (S80 | Z40 | P04)) | C01 |
- (rg.a & (F20 | F08));
- goto loop;
-
- case 0xDB: // IN A,(imm)
- pc++;
- rg.a = IN( data + rg.a * 0x100 );
- goto loop;
-
- case 0xE3:{// EX (SP),HL
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, rp.hl );
- rp.hl = temp;
- goto loop;
- }
-
- case 0xEB:{// EX DE,HL
- fuint16 temp = rp.hl;
- rp.hl = rp.de;
- rp.de = temp;
- goto loop;
- }
-
- case 0xD9:{// EXX DE,HL
- fuint16 temp = r.alt.w.bc;
- r.alt.w.bc = rp.bc;
- rp.bc = temp;
-
- temp = r.alt.w.de;
- r.alt.w.de = rp.de;
- rp.de = temp;
-
- temp = r.alt.w.hl;
- r.alt.w.hl = rp.hl;
- rp.hl = temp;
- goto loop;
- }
-
- case 0xF3: // DI
- r.iff1 = 0;
- r.iff2 = 0;
- goto loop;
-
- case 0xFB: // EI
- r.iff1 = 1;
- r.iff2 = 1;
- // TODO: delayed effect
- goto loop;
-
- case 0x76: // HALT
- goto halt;
-
-//////////////////////////////////////// CB prefix
- {
- case 0xCB:
- unsigned data2;
- data2 = instr [1];
- pc++;
- switch ( data )
- {
-
- // Rotate left
-
- #define RLC( read, write ) {\
- fuint8 result = read;\
- result = uint8_t (result << 1) | (result >> 7);\
- flags = SZ28P( result ) | (result & C01);\
- write;\
- goto loop;\
- }
-
- case 0x06: // RLC (HL)
- s_time += 7;
- data = rp.hl;
- rlc_data_addr:
- RLC( READ( data ), WRITE( data, result ) )
-
- CASE7( 00, 01, 02, 03, 04, 05, 07 ):{// RLC r
- uint8_t& reg = R8( data, 0 );
- RLC( reg, reg = result )
- }
-
- #define RL( read, write ) {\
- fuint16 result = (read << 1) | (flags & C01);\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x16: // RL (HL)
- s_time += 7;
- data = rp.hl;
- rl_data_addr:
- RL( READ( data ), WRITE( data, result ) )
-
- CASE7( 10, 11, 12, 13, 14, 15, 17 ):{// RL r
- uint8_t& reg = R8( data, 0x10 );
- RL( reg, reg = result )
- }
-
- #define SLA( read, add, write ) {\
- fuint16 result = (read << 1) | add;\
- flags = SZ28PC( result );\
- write;\
- goto loop;\
- }
-
- case 0x26: // SLA (HL)
- s_time += 7;
- data = rp.hl;
- sla_data_addr:
- SLA( READ( data ), 0, WRITE( data, result ) )
-
- CASE7( 20, 21, 22, 23, 24, 25, 27 ):{// SLA r
- uint8_t& reg = R8( data, 0x20 );
- SLA( reg, 0, reg = result )
- }
-
- case 0x36: // SLL (HL)
- s_time += 7;
- data = rp.hl;
- sll_data_addr:
- SLA( READ( data ), 1, WRITE( data, result ) )
-
- CASE7( 30, 31, 32, 33, 34, 35, 37 ):{// SLL r
- uint8_t& reg = R8( data, 0x30 );
- SLA( reg, 1, reg = result )
- }
-
- // Rotate right
-
- #define RRC( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = uint8_t (result << 7) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x0E: // RRC (HL)
- s_time += 7;
- data = rp.hl;
- rrc_data_addr:
- RRC( READ( data ), WRITE( data, result ) )
-
- CASE7( 08, 09, 0A, 0B, 0C, 0D, 0F ):{// RRC r
- uint8_t& reg = R8( data, 0x08 );
- RRC( reg, reg = result )
- }
-
- #define RR( read, write ) {\
- fuint8 result = read;\
- fuint8 temp = result & C01;\
- result = uint8_t (flags << 7) | (result >> 1);\
- flags = SZ28P( result ) | temp;\
- write;\
- goto loop;\
- }
-
- case 0x1E: // RR (HL)
- s_time += 7;
- data = rp.hl;
- rr_data_addr:
- RR( READ( data ), WRITE( data, result ) )
-
- CASE7( 18, 19, 1A, 1B, 1C, 1D, 1F ):{// RR r
- uint8_t& reg = R8( data, 0x18 );
- RR( reg, reg = result )
- }
-
- #define SRA( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result = (result & 0x80) | (result >> 1);\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x2E: // SRA (HL)
- data = rp.hl;
- s_time += 7;
- sra_data_addr:
- SRA( READ( data ), WRITE( data, result ) )
-
- CASE7( 28, 29, 2A, 2B, 2C, 2D, 2F ):{// SRA r
- uint8_t& reg = R8( data, 0x28 );
- SRA( reg, reg = result )
- }
-
- #define SRL( read, write ) {\
- fuint8 result = read;\
- flags = result & C01;\
- result >>= 1;\
- flags |= SZ28P( result );\
- write;\
- goto loop;\
- }
-
- case 0x3E: // SRL (HL)
- s_time += 7;
- data = rp.hl;
- srl_data_addr:
- SRL( READ( data ), WRITE( data, result ) )
-
- CASE7( 38, 39, 3A, 3B, 3C, 3D, 3F ):{// SRL r
- uint8_t& reg = R8( data, 0x38 );
- SRL( reg, reg = result )
- }
-
- // BIT
- {
- unsigned temp;
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ): // BIT b,(HL)
- s_time += 4;
- temp = READ( rp.hl );
- flags &= C01;
- goto bit_temp;
- CASE7( 40, 41, 42, 43, 44, 45, 47 ): // BIT 0,r
- CASE7( 48, 49, 4A, 4B, 4C, 4D, 4F ): // BIT 1,r
- CASE7( 50, 51, 52, 53, 54, 55, 57 ): // BIT 2,r
- CASE7( 58, 59, 5A, 5B, 5C, 5D, 5F ): // BIT 3,r
- CASE7( 60, 61, 62, 63, 64, 65, 67 ): // BIT 4,r
- CASE7( 68, 69, 6A, 6B, 6C, 6D, 6F ): // BIT 5,r
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // BIT 6,r
- CASE7( 78, 79, 7A, 7B, 7C, 7D, 7F ): // BIT 7,r
- temp = R8( data & 7, 0 );
- flags = (flags & C01) | (temp & (F20 | F08));
- bit_temp:
- int masked = temp & 1 << (data >> 3 & 7);
- flags |=(masked & S80) | H10 |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- // SET/RES
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(HL)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(HL)
- s_time += 7;
- int temp = READ( rp.hl );
- int bit = 1 << (data >> 3 & 7);
- temp |= bit; // SET
- if ( !(data & 0x40) )
- temp ^= bit; // RES
- WRITE( rp.hl, temp );
- goto loop;
- }
-
- CASE7( C0, C1, C2, C3, C4, C5, C7 ): // SET 0,r
- CASE7( C8, C9, CA, CB, CC, CD, CF ): // SET 1,r
- CASE7( D0, D1, D2, D3, D4, D5, D7 ): // SET 2,r
- CASE7( D8, D9, DA, DB, DC, DD, DF ): // SET 3,r
- CASE7( E0, E1, E2, E3, E4, E5, E7 ): // SET 4,r
- CASE7( E8, E9, EA, EB, EC, ED, EF ): // SET 5,r
- CASE7( F0, F1, F2, F3, F4, F5, F7 ): // SET 6,r
- CASE7( F8, F9, FA, FB, FC, FD, FF ): // SET 7,r
- R8( data & 7, 0 ) |= 1 << (data >> 3 & 7);
- goto loop;
-
- CASE7( 80, 81, 82, 83, 84, 85, 87 ): // RES 0,r
- CASE7( 88, 89, 8A, 8B, 8C, 8D, 8F ): // RES 1,r
- CASE7( 90, 91, 92, 93, 94, 95, 97 ): // RES 2,r
- CASE7( 98, 99, 9A, 9B, 9C, 9D, 9F ): // RES 3,r
- CASE7( A0, A1, A2, A3, A4, A5, A7 ): // RES 4,r
- CASE7( A8, A9, AA, AB, AC, AD, AF ): // RES 5,r
- CASE7( B0, B1, B2, B3, B4, B5, B7 ): // RES 6,r
- CASE7( B8, B9, BA, BB, BC, BD, BF ): // RES 7,r
- R8( data & 7, 0 ) &= ~(1 << (data >> 3 & 7));
- goto loop;
- }
- assert( false );
- }
-
-#undef GET_ADDR
-#define GET_ADDR() GET_LE16( instr + 1 )
-
-//////////////////////////////////////// ED prefix
- {
- case 0xED:
- pc++;
- s_time += ed_dd_timing [data] >> 4;
- switch ( data )
- {
- {
- blargg_ulong temp;
- case 0x72: // SBC HL,SP
- case 0x7A: // ADC HL,SP
- temp = sp;
- if ( 0 )
- case 0x42: // SBC HL,BC
- case 0x52: // SBC HL,DE
- case 0x62: // SBC HL,HL
- case 0x4A: // ADC HL,BC
- case 0x5A: // ADC HL,DE
- case 0x6A: // ADC HL,HL
- temp = R16( data >> 3 & 6, 1, 0 );
- blargg_ulong sum = temp + (flags & C01);
- flags = ~data >> 2 & N02;
- if ( flags )
- sum = -sum;
- sum += rp.hl;
- temp ^= rp.hl;
- temp ^= sum;
- flags |=(sum >> 16 & C01) |
- (temp >> 8 & H10) |
- (sum >> 8 & (S80 | F20 | F08)) |
- ((temp - -0x8000) >> 14 & V04);
- rp.hl = sum;
- if ( (uint16_t) sum )
- goto loop;
- flags |= Z40;
- goto loop;
- }
-
- CASE8( 40, 48, 50, 58, 60, 68, 70, 78 ):{// IN r,(C)
- int temp = IN( rp.bc );
- R8( data >> 3, 8 ) = temp;
- flags = (flags & C01) | SZ28P( temp );
- goto loop;
- }
-
- case 0x71: // OUT (C),0
- rg.flags = 0;
- CASE7( 41, 49, 51, 59, 61, 69, 79 ): // OUT (C),r
- OUT( rp.bc, R8( data >> 3, 8 ) );
- goto loop;
-
- {
- unsigned temp;
- case 0x73: // LD (ADDR),SP
- temp = sp;
- if ( 0 )
- case 0x43: // LD (ADDR),BC
- case 0x53: // LD (ADDR),DE
- temp = R16( data, 4, 0x43 );
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, temp );
- goto loop;
- }
-
- case 0x4B: // LD BC,(ADDR)
- case 0x5B:{// LD DE,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- R16( data, 4, 0x4B ) = READ_WORD( addr );
- goto loop;
- }
-
- case 0x7B:{// LD SP,(ADDR)
- fuint16 addr = GET_ADDR();
- pc += 2;
- sp = READ_WORD( addr );
- goto loop;
- }
-
- case 0x67:{// RRD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (rg.a << 4) | (temp >> 4) );
- temp = (rg.a & 0xF0) | (temp & 0x0F);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- case 0x6F:{// RLD
- fuint8 temp = READ( rp.hl );
- WRITE( rp.hl, (temp << 4) | (rg.a & 0x0F) );
- temp = (rg.a & 0xF0) | (temp >> 4);
- flags = (flags & C01) | SZ28P( temp );
- rg.a = temp;
- goto loop;
- }
-
- CASE8( 44, 4C, 54, 5C, 64, 6C, 74, 7C ): // NEG
- opcode = 0x10; // flag to do SBC instead of ADC
- flags &= ~C01;
- data = rg.a;
- rg.a = 0;
- goto adc_data;
-
- {
- int inc;
- case 0xA9: // CPD
- case 0xB9: // CPDR
- inc = -1;
- if ( 0 )
- case 0xA1: // CPI
- case 0xB1: // CPIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int result = rg.a - temp;
- flags = (flags & C01) | N02 |
- ((((temp ^ rg.a) & H10) ^ result) & (S80 | H10));
-
- if ( !(uint8_t) result ) flags |= Z40;
- result -= (flags & H10) >> 4;
- flags |= result & F08;
- flags |= result << 4 & F20;
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( flags & Z40 || data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xA8: // LDD
- case 0xB8: // LDDR
- inc = -1;
- if ( 0 )
- case 0xA0: // LDI
- case 0xB0: // LDIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- addr = rp.de;
- rp.de = addr + inc;
- WRITE( addr, temp );
-
- temp += rg.a;
- flags = (flags & (S80 | Z40 | C01)) |
- (temp & F08) | (temp << 4 & F20);
- if ( !--rp.bc )
- goto loop;
-
- flags |= V04;
- if ( data < 0xB0 )
- goto loop;
-
- pc -= 2;
- s_time += 5;
- goto loop;
- }
-
- {
- int inc;
- case 0xAB: // OUTD
- case 0xBB: // OTDR
- inc = -1;
- if ( 0 )
- case 0xA3: // OUTI
- case 0xB3: // OTIR
- inc = +1;
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
- int temp = READ( addr );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- OUT( rp.bc, temp );
- goto loop;
- }
-
- {
- int inc;
- case 0xAA: // IND
- case 0xBA: // INDR
- inc = -1;
- if ( 0 )
- case 0xA2: // INI
- case 0xB2: // INIR
- inc = +1;
-
- fuint16 addr = rp.hl;
- rp.hl = addr + inc;
-
- int temp = IN( rp.bc );
-
- int b = --rg.b;
- flags = (temp >> 6 & N02) | SZ28( b );
- if ( b && data >= 0xB0 )
- {
- pc -= 2;
- s_time += 5;
- }
-
- WRITE( addr, temp );
- goto loop;
- }
-
- case 0x47: // LD I,A
- r.i = rg.a;
- goto loop;
-
- case 0x4F: // LD R,A
- SET_R( rg.a );
- debug_printf( "LD R,A not supported\n" );
- warning = true;
- goto loop;
-
- case 0x57: // LD A,I
- rg.a = r.i;
- goto ld_ai_common;
-
- case 0x5F: // LD A,R
- rg.a = GET_R();
- debug_printf( "LD A,R not supported\n" );
- warning = true;
- ld_ai_common:
- flags = (flags & C01) | SZ28( rg.a ) | (r.iff2 << 2 & V04);
- goto loop;
-
- CASE8( 45, 4D, 55, 5D, 65, 6D, 75, 7D ): // RETI/RETN
- r.iff1 = r.iff2;
- goto ret_taken;
-
- case 0x46: case 0x4E: case 0x66: case 0x6E: // IM 0
- r.im = 0;
- goto loop;
-
- case 0x56: case 0x76: // IM 1
- r.im = 1;
- goto loop;
-
- case 0x5E: case 0x7E: // IM 2
- r.im = 2;
- goto loop;
-
- default:
- debug_printf( "Opcode $ED $%02X not supported\n", data );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
-//////////////////////////////////////// DD/FD prefix
- {
- fuint16 ixy;
- case 0xDD:
- ixy = ix;
- goto ix_prefix;
- case 0xFD:
- ixy = iy;
- ix_prefix:
- pc++;
- unsigned data2 = READ_PROG( pc );
- s_time += ed_dd_timing [data] & 0x0F;
- switch ( data )
- {
- // TODO: more efficient way of avoid negative address
- // TODO: avoid using this as argument to READ() since it is evaluated twice
- #define IXY_DISP( ixy, disp ) uint16_t ((ixy) + (disp))
-
- #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
-
- // ADD/ADC/SUB/SBC
-
- case 0x96: // SUB (IXY+disp)
- case 0x86: // ADD (IXY+disp)
- flags &= ~C01;
- case 0x9E: // SBC (IXY+disp)
- case 0x8E: // ADC (IXY+disp)
- pc++;
- opcode = data;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto adc_data;
-
- case 0x94: // SUB HXY
- case 0x84: // ADD HXY
- flags &= ~C01;
- case 0x9C: // SBC HXY
- case 0x8C: // ADC HXY
- opcode = data;
- data = ixy >> 8;
- goto adc_data;
-
- case 0x95: // SUB LXY
- case 0x85: // ADD LXY
- flags &= ~C01;
- case 0x9D: // SBC LXY
- case 0x8D: // ADC LXY
- opcode = data;
- data = (uint8_t) ixy;
- goto adc_data;
-
- {
- unsigned temp;
- case 0x39: // ADD IXY,SP
- temp = sp;
- goto add_ixy_data;
-
- case 0x29: // ADD IXY,HL
- temp = ixy;
- goto add_ixy_data;
-
- case 0x09: // ADD IXY,BC
- case 0x19: // ADD IXY,DE
- temp = R16( data, 4, 0x09 );
- add_ixy_data: {
- blargg_ulong sum = ixy + temp;
- temp ^= ixy;
- ixy = (uint16_t) sum;
- flags = (flags & (S80 | Z40 | V04)) |
- (sum >> 16) |
- (sum >> 8 & (F20 | F08)) |
- ((temp ^ sum) >> 8 & H10);
- goto set_ixy;
- }
- }
-
- // AND
- case 0xA6: // AND (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto and_data;
-
- case 0xA4: // AND HXY
- data = ixy >> 8;
- goto and_data;
-
- case 0xA5: // AND LXY
- data = (uint8_t) ixy;
- goto and_data;
-
- // OR
- case 0xB6: // OR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto or_data;
-
- case 0xB4: // OR HXY
- data = ixy >> 8;
- goto or_data;
-
- case 0xB5: // OR LXY
- data = (uint8_t) ixy;
- goto or_data;
-
- // XOR
- case 0xAE: // XOR (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto xor_data;
-
- case 0xAC: // XOR HXY
- data = ixy >> 8;
- goto xor_data;
-
- case 0xAD: // XOR LXY
- data = (uint8_t) ixy;
- goto xor_data;
-
- // CP
- case 0xBE: // CP (IXY+disp)
- pc++;
- data = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto cp_data;
-
- case 0xBC: // CP HXY
- data = ixy >> 8;
- goto cp_data;
-
- case 0xBD: // CP LXY
- data = (uint8_t) ixy;
- goto cp_data;
-
- // LD
- CASE7( 70, 71, 72, 73, 74, 75, 77 ): // LD (IXY+disp),r
- data = R8( data, 0x70 );
- if ( 0 )
- case 0x36: // LD (IXY+disp),imm
- pc++, data = READ_PROG( pc );
- pc++;
- WRITE( IXY_DISP( ixy, (int8_t) data2 ), data );
- goto loop;
-
- CASE5( 44, 4C, 54, 5C, 7C ): // LD r,HXY
- R8( data >> 3, 8 ) = ixy >> 8;
- goto loop;
-
- case 0x64: // LD HXY,HXY
- case 0x6D: // LD LXY,LXY
- goto loop;
-
- CASE5( 45, 4D, 55, 5D, 7D ): // LD r,LXY
- R8( data >> 3, 8 ) = ixy;
- goto loop;
-
- CASE7( 46, 4E, 56, 5E, 66, 6E, 7E ): // LD r,(IXY+disp)
- pc++;
- R8( data >> 3, 8 ) = READ( IXY_DISP( ixy, (int8_t) data2 ) );
- goto loop;
-
- case 0x26: // LD HXY,imm
- pc++;
- goto ld_hxy_data;
-
- case 0x65: // LD HXY,LXY
- data2 = (uint8_t) ixy;
- goto ld_hxy_data;
-
- CASE5( 60, 61, 62, 63, 67 ): // LD HXY,r
- data2 = R8( data, 0x60 );
- ld_hxy_data:
- ixy = (uint8_t) ixy | (data2 << 8);
- goto set_ixy;
-
- case 0x2E: // LD LXY,imm
- pc++;
- goto ld_lxy_data;
-
- case 0x6C: // LD LXY,HXY
- data2 = ixy >> 8;
- goto ld_lxy_data;
-
- CASE5( 68, 69, 6A, 6B, 6F ): // LD LXY,r
- data2 = R8( data, 0x68 );
- ld_lxy_data:
- ixy = (ixy & 0xFF00) | data2;
- set_ixy:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto loop;
- }
- iy = ixy;
- goto loop;
-
- case 0xF9: // LD SP,IXY
- sp = ixy;
- goto loop;
-
- case 0x22:{// LD (ADDR),IXY
- fuint16 addr = GET_ADDR();
- pc += 2;
- WRITE_WORD( addr, ixy );
- goto loop;
- }
-
- case 0x21: // LD IXY,imm
- ixy = GET_ADDR();
- pc += 2;
- goto set_ixy;
-
- case 0x2A:{// LD IXY,(addr)
- fuint16 addr = GET_ADDR();
- ixy = READ_WORD( addr );
- pc += 2;
- goto set_ixy;
- }
-
- // DD/FD CB prefix
- case 0xCB: {
- data = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data2 = READ_PROG( pc );
- pc++;
- switch ( data2 )
- {
- case 0x06: goto rlc_data_addr; // RLC (IXY)
- case 0x16: goto rl_data_addr; // RL (IXY)
- case 0x26: goto sla_data_addr; // SLA (IXY)
- case 0x36: goto sll_data_addr; // SLL (IXY)
- case 0x0E: goto rrc_data_addr; // RRC (IXY)
- case 0x1E: goto rr_data_addr; // RR (IXY)
- case 0x2E: goto sra_data_addr; // SRA (IXY)
- case 0x3E: goto srl_data_addr; // SRL (IXY)
-
- CASE8( 46, 4E, 56, 5E, 66, 6E, 76, 7E ):{// BIT b,(IXY+disp)
- fuint8 temp = READ( data );
- int masked = temp & 1 << (data2 >> 3 & 7);
- flags = (flags & C01) | H10 |
- (masked & S80) |
- ((masked - 1) >> 8 & (Z40 | P04));
- goto loop;
- }
-
- CASE8( 86, 8E, 96, 9E, A6, AE, B6, BE ): // RES b,(IXY+disp)
- CASE8( C6, CE, D6, DE, E6, EE, F6, FE ):{// SET b,(IXY+disp)
- int temp = READ( data );
- int bit = 1 << (data2 >> 3 & 7);
- temp |= bit; // SET
- if ( !(data2 & 0x40) )
- temp ^= bit; // RES
- WRITE( data, temp );
- goto loop;
- }
-
- default:
- debug_printf( "Opcode $%02X $CB $%02X not supported\n", opcode, data2 );
- warning = true;
- goto loop;
- }
- assert( false );
- }
-
- // INC/DEC
- case 0x23: // INC IXY
- ixy = uint16_t (ixy + 1);
- goto set_ixy;
-
- case 0x2B: // DEC IXY
- ixy = uint16_t (ixy - 1);
- goto set_ixy;
-
- case 0x34: // INC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) + 1;
- WRITE( ixy, data );
- goto inc_set_flags;
-
- case 0x35: // DEC (IXY+disp)
- ixy = IXY_DISP( ixy, (int8_t) data2 );
- pc++;
- data = READ( ixy ) - 1;
- WRITE( ixy, data );
- goto dec_set_flags;
-
- case 0x24: // INC HXY
- ixy = uint16_t (ixy + 0x100);
- data = ixy >> 8;
- goto inc_xy_common;
-
- case 0x2C: // INC LXY
- data = uint8_t (ixy + 1);
- ixy = (ixy & 0xFF00) | data;
- inc_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto inc_set_flags;
- }
- iy = ixy;
- goto inc_set_flags;
-
- case 0x25: // DEC HXY
- ixy = uint16_t (ixy - 0x100);
- data = ixy >> 8;
- goto dec_xy_common;
-
- case 0x2D: // DEC LXY
- data = uint8_t (ixy - 1);
- ixy = (ixy & 0xFF00) | data;
- dec_xy_common:
- if ( opcode == 0xDD )
- {
- ix = ixy;
- goto dec_set_flags;
- }
- iy = ixy;
- goto dec_set_flags;
-
- // PUSH/POP
- case 0xE5: // PUSH IXY
- data = ixy;
- goto push_data;
-
- case 0xE1:{// POP IXY
- ixy = READ_WORD( sp );
- sp = uint16_t (sp + 2);
- goto set_ixy;
- }
-
- // Misc
-
- case 0xE9: // JP (IXY)
- pc = ixy;
- goto loop;
-
- case 0xE3:{// EX (SP),IXY
- fuint16 temp = READ_WORD( sp );
- WRITE_WORD( sp, ixy );
- ixy = temp;
- goto set_ixy;
- }
-
- default:
- debug_printf( "Unnecessary DD/FD prefix encountered\n" );
- warning = true;
- pc--;
- goto loop;
- }
- assert( false );
- }
-
- }
- debug_printf( "Unhandled main opcode: $%02X\n", opcode );
- assert( false );
-
-hit_idle_addr:
- s_time -= 11;
- goto out_of_time;
-halt:
- s_time &= 3; // increment by multiple of 4
-out_of_time:
- pc--;
-
- s.time = s_time;
- rg.flags = flags;
- r.ix = ix;
- r.iy = iy;
- r.sp = sp;
- r.pc = pc;
- this->r.b = rg;
- this->state_ = s;
- this->state = &this->state_;
-
- return warning;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.h
deleted file mode 100644
index 28a2fc0f..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Cpu.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Z80 CPU emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef KSS_CPU_H
-#define KSS_CPU_H
-
-#include "blargg_endian.h"
-
-typedef blargg_long cpu_time_t;
-
-// must be defined by caller
-void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data );
-int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr );
-void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data );
-
-class Kss_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers and map all pages to unmapped
- void reset( void* unmapped_write, void const* unmapped_read );
-
- // Map memory. Start and size must be multiple of page_size.
- enum { page_size = 0x2000 };
- void map_mem( unsigned addr, blargg_ulong size, void* write, void const* read );
-
- // Map address to page
- uint8_t* write( unsigned addr );
- uint8_t const* read( unsigned addr );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( cpu_time_t end_time );
-
- // Time of beginning of next instruction
- cpu_time_t time() const { return state->time + state->base; }
-
- // Alter current time. Not supported during run() call.
- void set_time( cpu_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- typedef BOOST::uint16_t uint16_t;
-
- #if BLARGG_BIG_ENDIAN
- struct regs_t { uint8_t b, c, d, e, h, l, flags, a; };
- #else
- struct regs_t { uint8_t c, b, e, d, l, h, a, flags; };
- #endif
- BOOST_STATIC_ASSERT( sizeof (regs_t) == 8 );
-
- struct pairs_t { uint16_t bc, de, hl, fa; };
-
- // Registers are not updated until run() returns
- struct registers_t {
- uint16_t pc;
- uint16_t sp;
- uint16_t ix;
- uint16_t iy;
- union {
- regs_t b; // b.b, b.c, b.d, b.e, b.h, b.l, b.flags, b.a
- pairs_t w; // w.bc, w.de, w.hl. w.fa
- };
- union {
- regs_t b;
- pairs_t w;
- } alt;
- uint8_t iff1;
- uint8_t iff2;
- uint8_t r;
- uint8_t i;
- uint8_t im;
- };
- //registers_t r; (below for efficiency)
-
- enum { idle_addr = 0xFFFF };
-
- // can read this far past end of a page
- enum { cpu_padding = 0x100 };
-
-public:
- Kss_Cpu();
- enum { page_shift = 13 };
- enum { page_count = 0x10000 >> page_shift };
-private:
- uint8_t szpc [0x200];
- cpu_time_t end_time_;
- struct state_t {
- uint8_t const* read [page_count + 1];
- uint8_t * write [page_count + 1];
- cpu_time_t base;
- cpu_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- void set_end_time( cpu_time_t t );
- void set_page( int i, void* write, void const* read );
-public:
- registers_t r;
-};
-
-#if BLARGG_NONPORTABLE
- #define KSS_CPU_PAGE_OFFSET( addr ) (addr)
-#else
- #define KSS_CPU_PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline BOOST::uint8_t* Kss_Cpu::write( unsigned addr )
-{
- return state->write [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr );
-}
-
-inline BOOST::uint8_t const* Kss_Cpu::read( unsigned addr )
-{
- return state->read [addr >> page_shift] + KSS_CPU_PAGE_OFFSET( addr );
-}
-
-inline void Kss_Cpu::set_end_time( cpu_time_t t )
-{
- cpu_time_t delta = state->base - t;
- state->base = t;
- state->time += delta;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.cpp
deleted file mode 100644
index 3b84509c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Kss_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const clock_rate = 3579545;
-int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count;
-
-Kss_Emu::Kss_Emu()
-{
- sn = 0;
- set_type( gme_kss_type );
- set_silence_lookahead( 6 );
- static const char* const names [osc_count] = {
- "Square 1", "Square 2", "Square 3",
- "Wave 1", "Wave 2", "Wave 3", "Wave 4", "Wave 5"
- };
- set_voice_names( names );
-
- static int const types [osc_count] = {
- wave_type | 0, wave_type | 1, wave_type | 2,
- wave_type | 3, wave_type | 4, wave_type | 5, wave_type | 6, wave_type | 7
- };
- set_voice_types( types );
-
- memset( unmapped_read, 0xFF, sizeof unmapped_read );
-}
-
-Kss_Emu::~Kss_Emu() { unload(); }
-
-void Kss_Emu::unload()
-{
- delete sn;
- sn = 0;
- Classic_Emu::unload();
-}
-
-// Track info
-
-static void copy_kss_fields( Kss_Emu::header_t const& h, track_info_t* out )
-{
- const char* system = "MSX";
- if ( h.device_flags & 0x02 )
- {
- system = "Sega Master System";
- if ( h.device_flags & 0x04 )
- system = "Game Gear";
- }
- Gme_File::copy_field_( out->system, system );
-}
-
-blargg_err_t Kss_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_kss_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_kss_header( void const* header )
-{
- if ( memcmp( header, "KSCC", 4 ) && memcmp( header, "KSSX", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Kss_File : Gme_Info_
-{
- Kss_Emu::header_t header_;
-
- Kss_File() { set_type( gme_kss_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &header_, Kss_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- return check_kss_header( &header_ );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_kss_fields( header_, out );
- return 0;
- }
-};
-
-static Music_Emu* new_kss_emu () { return BLARGG_NEW Kss_Emu ; }
-static Music_Emu* new_kss_file() { return BLARGG_NEW Kss_File; }
-
-static gme_type_t_ const gme_kss_type_ = { "MSX", 256, &new_kss_emu, &new_kss_file, "KSS", 0x03 };
-gme_type_t const gme_kss_type = &gme_kss_type_;
-
-
-// Setup
-
-void Kss_Emu::update_gain()
-{
- double g = gain() * 1.4;
- if ( scc_accessed )
- g *= 1.5;
- ay.volume( g );
- scc.volume( g );
- if ( sn )
- sn->volume( g );
-}
-
-blargg_err_t Kss_Emu::load_( Data_Reader& in )
-{
- memset( &header_, 0, sizeof header_ );
- assert( offsetof (header_t,device_flags) == header_size - 1 );
- assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1 );
- RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) );
-
- RETURN_ERR( check_kss_header( header_.tag ) );
-
- if ( header_.tag [3] == 'C' )
- {
- if ( header_.extra_header )
- {
- header_.extra_header = 0;
- set_warning( "Unknown data in header" );
- }
- if ( header_.device_flags & ~0x0F )
- {
- header_.device_flags &= 0x0F;
- set_warning( "Unknown data in header" );
- }
- }
- else
- {
- ext_header_t& ext = header_;
- memcpy( &ext, rom.begin(), min( (int) ext_header_size, (int) header_.extra_header ) );
- if ( header_.extra_header > 0x10 )
- set_warning( "Unknown data in header" );
- }
-
- if ( header_.device_flags & 0x09 )
- set_warning( "FM sound not supported" );
-
- scc_enabled = 0xC000;
- if ( header_.device_flags & 0x04 )
- scc_enabled = 0;
-
- if ( header_.device_flags & 0x02 && !sn )
- CHECK_ALLOC( sn = BLARGG_NEW( Sms_Apu ) );
-
- set_voice_count( osc_count );
-
- return setup_buffer( ::clock_rate );
-}
-
-void Kss_Emu::update_eq( blip_eq_t const& eq )
-{
- ay.treble_eq( eq );
- scc.treble_eq( eq );
- if ( sn )
- sn->treble_eq( eq );
-}
-
-void Kss_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- int i2 = i - ay.osc_count;
- if ( i2 >= 0 )
- scc.osc_output( i2, center );
- else
- ay.osc_output( i, center );
- if ( sn && i < sn->osc_count )
- sn->osc_output( i, center, left, right );
-}
-
-// Emulation
-
-void Kss_Emu::set_tempo_( double t )
-{
- blip_time_t period =
- (header_.device_flags & 0x40 ? ::clock_rate / 50 : ::clock_rate / 60);
- play_period = blip_time_t (period / t);
-}
-
-blargg_err_t Kss_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( ram, 0xC9, 0x4000 );
- memset( ram + 0x4000, 0, sizeof ram - 0x4000 );
-
- // copy driver code to lo RAM
- static byte const bios [] = {
- 0xD3, 0xA0, 0xF5, 0x7B, 0xD3, 0xA1, 0xF1, 0xC9, // $0001: WRTPSG
- 0xD3, 0xA0, 0xDB, 0xA2, 0xC9 // $0009: RDPSG
- };
- static byte const vectors [] = {
- 0xC3, 0x01, 0x00, // $0093: WRTPSG vector
- 0xC3, 0x09, 0x00, // $0096: RDPSG vector
- };
- memcpy( ram + 0x01, bios, sizeof bios );
- memcpy( ram + 0x93, vectors, sizeof vectors );
-
- // copy non-banked data into RAM
- unsigned load_addr = get_le16( header_.load_addr );
- long orig_load_size = get_le16( header_.load_size );
- long load_size = min( orig_load_size, rom.file_size() );
- load_size = min( load_size, long (mem_size - load_addr) );
- if ( load_size != orig_load_size )
- set_warning( "Excessive data size" );
- memcpy( ram + load_addr, rom.begin() + header_.extra_header, load_size );
-
- rom.set_addr( -load_size - header_.extra_header );
-
- // check available bank data
- blargg_long const bank_size = this->bank_size();
- int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size;
- bank_count = header_.bank_mode & 0x7F;
- if ( bank_count > max_banks )
- {
- bank_count = max_banks;
- set_warning( "Bank data missing" );
- }
- //debug_printf( "load_size : $%X\n", load_size );
- //debug_printf( "bank_size : $%X\n", bank_size );
- //debug_printf( "bank_count: %d (%d claimed)\n", bank_count, header_.bank_mode & 0x7F );
-
- ram [idle_addr] = 0xFF;
- cpu::reset( unmapped_write, unmapped_read );
- cpu::map_mem( 0, mem_size, ram, ram );
-
- ay.reset();
- scc.reset();
- if ( sn )
- sn->reset();
- r.sp = 0xF380;
- ram [--r.sp] = idle_addr >> 8;
- ram [--r.sp] = idle_addr & 0xFF;
- r.b.a = track;
- r.pc = get_le16( header_.init_addr );
- next_play = play_period;
- scc_accessed = false;
- gain_updated = false;
- update_gain();
- ay_latch = 0;
-
- return 0;
-}
-
-void Kss_Emu::set_bank( int logical, int physical )
-{
- unsigned const bank_size = this->bank_size();
-
- unsigned addr = 0x8000;
- if ( logical && bank_size == 8 * 1024 )
- addr = 0xA000;
-
- physical -= header_.first_bank;
- if ( (unsigned) physical >= (unsigned) bank_count )
- {
- byte* data = ram + addr;
- cpu::map_mem( addr, bank_size, data, data );
- }
- else
- {
- long phys = physical * (blargg_long) bank_size;
- for ( unsigned offset = 0; offset < bank_size; offset += page_size )
- cpu::map_mem( addr + offset, page_size,
- unmapped_write, rom.at_addr( phys + offset ) );
- }
-}
-
-void Kss_Emu::cpu_write( unsigned addr, int data )
-{
- data &= 0xFF;
- switch ( addr )
- {
- case 0x9000:
- set_bank( 0, data );
- return;
-
- case 0xB000:
- set_bank( 1, data );
- return;
- }
-
- int scc_addr = (addr & 0xDFFF) ^ 0x9800;
- if ( scc_addr < scc.reg_count )
- {
- scc_accessed = true;
- scc.write( time(), scc_addr, data );
- return;
- }
-
- debug_printf( "LD ($%04X),$%02X\n", addr, data );
-}
-
-void kss_cpu_write( Kss_Cpu* cpu, unsigned addr, int data )
-{
- *cpu->write( addr ) = data;
- if ( (addr & STATIC_CAST(Kss_Emu&,*cpu).scc_enabled) == 0x8000 )
- STATIC_CAST(Kss_Emu&,*cpu).cpu_write( addr, data );
-}
-
-void kss_cpu_out( Kss_Cpu* cpu, cpu_time_t time, unsigned addr, int data )
-{
- data &= 0xFF;
- Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
- switch ( addr & 0xFF )
- {
- case 0xA0:
- emu.ay_latch = data & 0x0F;
- return;
-
- case 0xA1:
- GME_APU_HOOK( &emu, emu.ay_latch, data );
- emu.ay.write( time, emu.ay_latch, data );
- return;
-
- case 0x06:
- if ( emu.sn && (emu.header_.device_flags & 0x04) )
- {
- emu.sn->write_ggstereo( time, data );
- return;
- }
- break;
-
- case 0x7E:
- case 0x7F:
- if ( emu.sn )
- {
- GME_APU_HOOK( &emu, 16, data );
- emu.sn->write_data( time, data );
- return;
- }
- break;
-
- case 0xFE:
- emu.set_bank( 0, data );
- return;
-
- #ifndef NDEBUG
- case 0xF1: // FM data
- if ( data )
- break; // trap non-zero data
- case 0xF0: // FM addr
- case 0xA8: // PPI
- return;
- #endif
- }
-
- debug_printf( "OUT $%04X,$%02X\n", addr, data );
-}
-
-int kss_cpu_in( Kss_Cpu*, cpu_time_t, unsigned addr )
-{
- //Kss_Emu& emu = STATIC_CAST(Kss_Emu&,*cpu);
- //switch ( addr & 0xFF )
- //{
- //}
-
- debug_printf( "IN $%04X\n", addr );
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Kss_Emu::run_clocks( blip_time_t& duration, int )
-{
- while ( time() < duration )
- {
- blip_time_t end = min( duration, next_play );
- cpu::run( min( duration, next_play ) );
- if ( r.pc == idle_addr )
- set_time( end );
-
- if ( time() >= next_play )
- {
- next_play += play_period;
- if ( r.pc == idle_addr )
- {
- if ( !gain_updated )
- {
- gain_updated = true;
- if ( scc_accessed )
- update_gain();
- }
-
- ram [--r.sp] = idle_addr >> 8;
- ram [--r.sp] = idle_addr & 0xFF;
- r.pc = get_le16( header_.play_addr );
- GME_FRAME_HOOK( this );
- }
- }
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- adjust_time( -duration );
- ay.end_frame( duration );
- scc.end_frame( duration );
- if ( sn )
- sn->end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.h
deleted file mode 100644
index 1d6ae475..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Emu.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// MSX computer KSS music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef KSS_EMU_H
-#define KSS_EMU_H
-
-#include "Classic_Emu.h"
-#include "Kss_Scc_Apu.h"
-#include "Kss_Cpu.h"
-#include "Sms_Apu.h"
-#include "Ay_Apu.h"
-
-class Kss_Emu : private Kss_Cpu, public Classic_Emu {
- typedef Kss_Cpu cpu;
-public:
- // KSS file header
- enum { header_size = 0x10 };
- struct header_t
- {
- byte tag [4];
- byte load_addr [2];
- byte load_size [2];
- byte init_addr [2];
- byte play_addr [2];
- byte first_bank;
- byte bank_mode;
- byte extra_header;
- byte device_flags;
- };
-
- enum { ext_header_size = 0x10 };
- struct ext_header_t
- {
- byte data_size [4];
- byte unused [4];
- byte first_track [2];
- byte last_tack [2];
- byte psg_vol;
- byte scc_vol;
- byte msx_music_vol;
- byte msx_audio_vol;
- };
-
- struct composite_header_t : header_t, ext_header_t { };
-
- // Header for currently loaded file
- composite_header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_kss_type; }
-public:
- Kss_Emu();
- ~Kss_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-private:
- Rom_Data<page_size> rom;
- composite_header_t header_;
-
- bool scc_accessed;
- bool gain_updated;
- void update_gain();
-
- unsigned scc_enabled; // 0 or 0xC000
- byte const* bank_data;
- int bank_count;
- void set_bank( int logical, int physical );
- blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
-
- blip_time_t play_period;
- blip_time_t next_play;
- int ay_latch;
-
- friend void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data );
- friend int kss_cpu_in( class Kss_Cpu*, cpu_time_t, unsigned addr );
- void cpu_write( unsigned addr, int data );
- friend void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data );
-
- // large items
- enum { mem_size = 0x10000 };
- byte ram [mem_size + cpu_padding];
-
- Ay_Apu ay;
- Scc_Apu scc;
- Sms_Apu* sn;
- byte unmapped_read [0x100];
- byte unmapped_write [page_size];
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.cpp
deleted file mode 100644
index cfccce64..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Kss_Scc_Apu.h"
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Tones above this frequency are treated as disabled tone at half volume.
-// Power of two is more efficient (avoids division).
-unsigned const inaudible_freq = 16384;
-
-int const wave_size = 0x20;
-
-void Scc_Apu::run_until( blip_time_t end_time )
-{
- for ( int index = 0; index < osc_count; index++ )
- {
- osc_t& osc = oscs [index];
-
- Blip_Buffer* const output = osc.output;
- if ( !output )
- continue;
- output->set_modified();
-
- blip_time_t period = (regs [0x80 + index * 2 + 1] & 0x0F) * 0x100 +
- regs [0x80 + index * 2] + 1;
- int volume = 0;
- if ( regs [0x8F] & (1 << index) )
- {
- blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() +
- inaudible_freq * 32) / (inaudible_freq * 16);
- if ( period > inaudible_period )
- volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15);
- }
-
- BOOST::int8_t const* wave = (BOOST::int8_t*) regs + index * wave_size;
- if ( index == osc_count - 1 )
- wave -= wave_size; // last two oscs share wave
- {
- int amp = wave [osc.phase] * volume;
- int delta = amp - osc.last_amp;
- if ( delta )
- {
- osc.last_amp = amp;
- synth.offset( last_time, delta, output );
- }
- }
-
- blip_time_t time = last_time + osc.delay;
- if ( time < end_time )
- {
- if ( !volume )
- {
- // maintain phase
- blargg_long count = (end_time - time + period - 1) / period;
- osc.phase = (osc.phase + count) & (wave_size - 1);
- time += count * period;
- }
- else
- {
-
- int phase = osc.phase;
- int last_wave = wave [phase];
- phase = (phase + 1) & (wave_size - 1); // pre-advance for optimal inner loop
-
- do
- {
- int amp = wave [phase];
- phase = (phase + 1) & (wave_size - 1);
- int delta = amp - last_wave;
- if ( delta )
- {
- last_wave = amp;
- synth.offset( time, delta * volume, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- osc.phase = phase = (phase - 1) & (wave_size - 1); // undo pre-advance
- osc.last_amp = wave [phase] * volume;
- }
- }
- osc.delay = time - end_time;
- }
- last_time = end_time;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.h
deleted file mode 100644
index 5c65461c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Kss_Scc_Apu.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Konami SCC sound chip emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef KSS_SCC_APU_H
-#define KSS_SCC_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-#include <string.h>
-
-class Scc_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Reset sound chip
- void reset();
-
- // Write to register at specified time
- enum { reg_count = 0x90 };
- void write( blip_time_t time, int reg, int data );
-
- // Run sound to specified time, end current time frame, then start a new
- // time frame at time 0. Time frames have no effect on emulation and each
- // can be whatever length is convenient.
- void end_frame( blip_time_t length );
-
-// Additional features
-
- // Set sound output of specific oscillator to buffer, where index is
- // 0 to 4. If buffer is NULL, the specified oscillator is muted.
- enum { osc_count = 5 };
- void osc_output( int index, Blip_Buffer* );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see documentation)
- void treble_eq( blip_eq_t const& );
-
-public:
- Scc_Apu();
-private:
- enum { amp_range = 0x8000 };
- struct osc_t
- {
- int delay;
- int phase;
- int last_amp;
- Blip_Buffer* output;
- };
- osc_t oscs [osc_count];
- blip_time_t last_time;
- unsigned char regs [reg_count];
- Blip_Synth<blip_med_quality,1> synth;
-
- void run_until( blip_time_t );
-};
-
-inline void Scc_Apu::volume( double v ) { synth.volume( 0.43 / osc_count / amp_range * v ); }
-
-inline void Scc_Apu::treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
-
-inline void Scc_Apu::osc_output( int index, Blip_Buffer* b )
-{
- assert( (unsigned) index < osc_count );
- oscs [index].output = b;
-}
-
-inline void Scc_Apu::write( blip_time_t time, int addr, int data )
-{
- assert( (unsigned) addr < reg_count );
- run_until( time );
- regs [addr] = data;
-}
-
-inline void Scc_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
- last_time -= end_time;
- assert( last_time >= 0 );
-}
-
-inline void Scc_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- oscs [i].output = buf;
-}
-
-inline Scc_Apu::Scc_Apu()
-{
- output( 0 );
-}
-
-inline void Scc_Apu::reset()
-{
- last_time = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- memset( &oscs [i], 0, offsetof (osc_t,output) );
-
- memset( regs, 0, sizeof regs );
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.cpp b/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.cpp
deleted file mode 100644
index 75d0fcb2..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "M3u_Playlist.h"
-#include "Music_Emu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// gme functions defined here to avoid linking in m3u code unless it's used
-
-blargg_err_t Gme_File::load_m3u_( blargg_err_t err )
-{
- require( raw_track_count_ ); // file must be loaded first
-
- if ( !err )
- {
- if ( playlist.size() )
- track_count_ = playlist.size();
-
- int line = playlist.first_error();
- if ( line )
- {
- // avoid using bloated printf()
- char* out = &playlist_warning [sizeof playlist_warning];
- *--out = 0;
- do {
- *--out = line % 10 + '0';
- } while ( (line /= 10) > 0 );
-
- static const char str [] = "Problem in m3u at line ";
- out -= sizeof str - 1;
- memcpy( out, str, sizeof str - 1 );
- set_warning( out );
- }
- }
- return err;
-}
-
-blargg_err_t Gme_File::load_m3u( const char* path ) { return load_m3u_( playlist.load( path ) ); }
-
-blargg_err_t Gme_File::load_m3u( Data_Reader& in ) { return load_m3u_( playlist.load( in ) ); }
-
-gme_err_t gme_load_m3u( Music_Emu* me, const char* path ) { return me->load_m3u( path ); }
-
-gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
-{
- Mem_File_Reader in( data, size );
- return me->load_m3u( in );
-}
-
-
-
-static char* skip_white( char* in )
-{
- while ( *in == ' ' )
- in++;
- return in;
-}
-
-inline unsigned from_dec( unsigned n ) { return n - '0'; }
-
-static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
-{
- entry.file = in;
- entry.type = "";
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in filename
- {
- char* p = skip_white( in );
- if ( *p == '$' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
- {
- entry.type = ++in;
- while ( (c = *in) != 0 && c != ',' )
- in++;
- if ( c == ',' )
- {
- *in++ = 0; // terminate type
- in = skip_white( in );
- }
- break;
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static char* next_field( char* in, int* result )
-{
- while ( 1 )
- {
- in = skip_white( in );
-
- if ( !*in )
- break;
-
- if ( *in == ',' )
- {
- in++;
- break;
- }
-
- *result = 1;
- in++;
- }
- return skip_white( in );
-}
-
-static char* parse_int_( char* in, int* out )
-{
- int n = 0;
- while ( 1 )
- {
- unsigned d = from_dec( *in );
- if ( d > 9 )
- break;
- in++;
- n = n * 10 + d;
- *out = n;
- }
- return in;
-}
-
-static char* parse_int( char* in, int* out, int* result )
-{
- return next_field( parse_int_( in, out ), result );
-}
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static char* parse_track( char* in, M3u_Playlist::entry_t& entry, int* result )
-{
- if ( *in == '$' )
- {
- in++;
- int n = 0;
- while ( 1 )
- {
- int h = from_hex_char( *in );
- if ( h > 15 )
- break;
- in++;
- n = n * 16 + h;
- entry.track = n;
- }
- }
- else
- {
- in = parse_int_( in, &entry.track );
- if ( entry.track >= 0 )
- entry.decimal_track = 1;
- }
- return next_field( in, result );
-}
-
-static char* parse_time_( char* in, int* out )
-{
- *out = -1;
- int n = -1;
- in = parse_int_( in, &n );
- if ( n >= 0 )
- {
- *out = n;
- if ( *in == ':' )
- {
- n = -1;
- in = parse_int_( in + 1, &n );
- if ( n >= 0 )
- *out = *out * 60 + n;
- }
- }
- return in;
-}
-
-static char* parse_time( char* in, int* out, int* result )
-{
- return next_field( parse_time_( in, out ), result );
-}
-
-static char* parse_name( char* in )
-{
- char* out = in;
- while ( 1 )
- {
- int c = *in;
- if ( !c ) break;
- in++;
-
- if ( c == ',' ) // commas in string
- {
- char* p = skip_white( in );
- if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
- {
- in = p;
- break;
- }
- }
-
- if ( c == '\\' ) // \ prefix for special characters
- {
- c = *in;
- if ( !c ) break;
- in++;
- }
- *out++ = (char) c;
- }
- *out = 0; // terminate string
- return in;
-}
-
-static int parse_line( char* in, M3u_Playlist::entry_t& entry )
-{
- int result = 0;
-
- // file
- entry.file = in;
- entry.type = "";
- in = parse_filename( in, entry );
-
- // track
- entry.track = -1;
- entry.decimal_track = 0;
- in = parse_track( in, entry, &result );
-
- // name
- entry.name = in;
- in = parse_name( in );
-
- // time
- entry.length = -1;
- in = parse_time( in, &entry.length, &result );
-
- // loop
- entry.intro = -1;
- entry.loop = -1;
- if ( *in == '-' )
- {
- entry.loop = entry.length;
- in++;
- }
- else
- {
- in = parse_time_( in, &entry.loop );
- if ( entry.loop >= 0 )
- {
- entry.intro = 0;
- if ( *in == '-' ) // trailing '-' means that intro length was specified
- {
- in++;
- entry.intro = entry.loop;
- entry.loop = entry.length - entry.intro;
- }
- }
- }
- in = next_field( in, &result );
-
- // fade
- entry.fade = -1;
- in = parse_time( in, &entry.fade, &result );
-
- // repeat
- entry.repeat = -1;
- in = parse_int( in, &entry.repeat, &result );
-
- return result;
-}
-
-static void parse_comment( char* in, M3u_Playlist::info_t& info, bool first )
-{
- in = skip_white( in + 1 );
- const char* field = in;
- while ( *in && *in != ':' )
- in++;
-
- if ( *in == ':' )
- {
- const char* text = skip_white( in + 1 );
- if ( *text )
- {
- *in = 0;
- if ( !strcmp( "Composer", field ) ) info.composer = text;
- else if ( !strcmp( "Engineer", field ) ) info.engineer = text;
- else if ( !strcmp( "Ripping" , field ) ) info.ripping = text;
- else if ( !strcmp( "Tagging" , field ) ) info.tagging = text;
- else
- text = 0;
- if ( text )
- return;
- *in = ':';
- }
- }
-
- if ( first )
- info.title = field;
-}
-
-blargg_err_t M3u_Playlist::parse_()
-{
- info_.title = "";
- info_.composer = "";
- info_.engineer = "";
- info_.ripping = "";
- info_.tagging = "";
-
- int const CR = 13;
- int const LF = 10;
-
- data.end() [-1] = LF; // terminate input
-
- first_error_ = 0;
- bool first_comment = true;
- int line = 0;
- int count = 0;
- char* in = data.begin();
- while ( in < data.end() )
- {
- // find end of line and terminate it
- line++;
- char* begin = in;
- while ( *in != CR && *in != LF )
- {
- if ( !*in )
- return "Not an m3u playlist";
- in++;
- }
- if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
- *in++ = 0;
- *in++ = 0;
-
- // parse line
- if ( *begin == '#' )
- {
- parse_comment( begin, info_, first_comment );
- first_comment = false;
- }
- else if ( *begin )
- {
- if ( (int) entries.size() <= count )
- RETURN_ERR( entries.resize( count * 2 + 64 ) );
-
- if ( !parse_line( begin, entries [count] ) )
- count++;
- else if ( !first_error_ )
- first_error_ = line;
- first_comment = false;
- }
- }
- if ( count <= 0 )
- return "Not an m3u playlist";
-
- if ( !(info_.composer [0] | info_.engineer [0] | info_.ripping [0] | info_.tagging [0]) )
- info_.title = "";
-
- return entries.resize( count );
-}
-
-blargg_err_t M3u_Playlist::parse()
-{
- blargg_err_t err = parse_();
- if ( err )
- {
- entries.clear();
- data.clear();
- }
- return err;
-}
-
-blargg_err_t M3u_Playlist::load( Data_Reader& in )
-{
- RETURN_ERR( data.resize( in.remain() + 1 ) );
- RETURN_ERR( in.read( data.begin(), data.size() - 1 ) );
- return parse();
-}
-
-blargg_err_t M3u_Playlist::load( const char* path )
-{
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- return load( in );
-}
-
-blargg_err_t M3u_Playlist::load( void const* in, long size )
-{
- RETURN_ERR( data.resize( size + 1 ) );
- memcpy( data.begin(), in, size );
- return parse();
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.h b/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.h
deleted file mode 100644
index 266a0653..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/M3u_Playlist.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// M3U playlist file parser, with support for subtrack information
-
-// Game_Music_Emu 0.5.5
-#ifndef M3U_PLAYLIST_H
-#define M3U_PLAYLIST_H
-
-#include "blargg_common.h"
-#include "Data_Reader.h"
-
-class M3u_Playlist {
-public:
- // Load playlist data
- blargg_err_t load( const char* path );
- blargg_err_t load( Data_Reader& in );
- blargg_err_t load( void const* data, long size );
-
- // Line number of first parse error, 0 if no error. Any lines with parse
- // errors are ignored.
- int first_error() const { return first_error_; }
-
- struct info_t
- {
- const char* title;
- const char* composer;
- const char* engineer;
- const char* ripping;
- const char* tagging;
- };
- info_t const& info() const { return info_; }
-
- struct entry_t
- {
- const char* file; // filename without stupid ::TYPE suffix
- const char* type; // if filename has ::TYPE suffix, this will be "TYPE". "" if none.
- const char* name;
- bool decimal_track; // true if track was specified in hex
- // integers are -1 if not present
- int track; // 1-based
- int length; // seconds
- int intro;
- int loop;
- int fade;
- int repeat; // count
- };
- entry_t const& operator [] ( int i ) const { return entries [i]; }
- int size() const { return entries.size(); }
-
- void clear();
-
-private:
- blargg_vector<entry_t> entries;
- blargg_vector<char> data;
- int first_error_;
- info_t info_;
-
- blargg_err_t parse();
- blargg_err_t parse_();
-};
-
-inline void M3u_Playlist::clear()
-{
- first_error_ = 0;
- entries.clear();
- data.clear();
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.cpp
deleted file mode 100644
index 57f93b31..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
-
-#include "Multi_Buffer.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
-{
- length_ = 0;
- sample_rate_ = 0;
- channels_changed_count_ = 1;
-}
-
-blargg_err_t Multi_Buffer::set_channel_count( int ) { return 0; }
-
-// Silent_Buffer
-
-Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
-{
- // TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
- chan.left = 0;
- chan.center = 0;
- chan.right = 0;
-}
-
-// Mono_Buffer
-
-Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
-{
- chan.center = &buf;
- chan.left = &buf;
- chan.right = &buf;
-}
-
-Mono_Buffer::~Mono_Buffer() { }
-
-blargg_err_t Mono_Buffer::set_sample_rate( long rate, int msec )
-{
- RETURN_ERR( buf.set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
-}
-
-// Stereo_Buffer
-
-Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
-{
- chan.center = &bufs [0];
- chan.left = &bufs [1];
- chan.right = &bufs [2];
-}
-
-Stereo_Buffer::~Stereo_Buffer() { }
-
-blargg_err_t Stereo_Buffer::set_sample_rate( long rate, int msec )
-{
- for ( int i = 0; i < buf_count; i++ )
- RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
- return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
-}
-
-void Stereo_Buffer::clock_rate( long rate )
-{
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clock_rate( rate );
-}
-
-void Stereo_Buffer::bass_freq( int bass )
-{
- for ( unsigned i = 0; i < buf_count; i++ )
- bufs [i].bass_freq( bass );
-}
-
-void Stereo_Buffer::clear()
-{
- stereo_added = 0;
- was_stereo = false;
- for ( int i = 0; i < buf_count; i++ )
- bufs [i].clear();
-}
-
-void Stereo_Buffer::end_frame( blip_time_t clock_count )
-{
- stereo_added = 0;
- for ( unsigned i = 0; i < buf_count; i++ )
- {
- stereo_added |= bufs [i].clear_modified() << i;
- bufs [i].end_frame( clock_count );
- }
-}
-
-long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
-{
- require( !(count & 1) ); // count must be even
- count = (unsigned) count / 2;
-
- long avail = bufs [0].samples_avail();
- if ( count > avail )
- count = avail;
- if ( count )
- {
- int bufs_used = stereo_added | was_stereo;
- //debug_printf( "%X\n", bufs_used );
- if ( bufs_used <= 1 )
- {
- mix_mono( out, count );
- bufs [0].remove_samples( count );
- bufs [1].remove_silence( count );
- bufs [2].remove_silence( count );
- }
- else if ( bufs_used & 1 )
- {
- mix_stereo( out, count );
- bufs [0].remove_samples( count );
- bufs [1].remove_samples( count );
- bufs [2].remove_samples( count );
- }
- else
- {
- mix_stereo_no_center( out, count );
- bufs [0].remove_silence( count );
- bufs [1].remove_samples( count );
- bufs [2].remove_samples( count );
- }
-
- // to do: this might miss opportunities for optimization
- if ( !bufs [0].samples_avail() )
- {
- was_stereo = stereo_added;
- stereo_added = 0;
- }
- }
-
- return count * 2;
-}
-
-void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [1] );
- BLIP_READER_BEGIN( left, bufs [1] );
- BLIP_READER_BEGIN( right, bufs [2] );
- BLIP_READER_BEGIN( center, bufs [0] );
-
- for ( ; count; --count )
- {
- int c = BLIP_READER_READ( center );
- blargg_long l = c + BLIP_READER_READ( left );
- blargg_long r = c + BLIP_READER_READ( right );
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- BLIP_READER_NEXT( center, bass );
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- BLIP_READER_NEXT( left, bass );
- BLIP_READER_NEXT( right, bass );
-
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- BLIP_READER_END( center, bufs [0] );
- BLIP_READER_END( right, bufs [2] );
- BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [1] );
- BLIP_READER_BEGIN( left, bufs [1] );
- BLIP_READER_BEGIN( right, bufs [2] );
-
- for ( ; count; --count )
- {
- blargg_long l = BLIP_READER_READ( left );
- if ( (BOOST::int16_t) l != l )
- l = 0x7FFF - (l >> 24);
-
- blargg_long r = BLIP_READER_READ( right );
- if ( (BOOST::int16_t) r != r )
- r = 0x7FFF - (r >> 24);
-
- BLIP_READER_NEXT( left, bass );
- BLIP_READER_NEXT( right, bass );
-
- out [0] = l;
- out [1] = r;
- out += 2;
- }
-
- BLIP_READER_END( right, bufs [2] );
- BLIP_READER_END( left, bufs [1] );
-}
-
-void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
-{
- blip_sample_t* BLIP_RESTRICT out = out_;
- int const bass = BLIP_READER_BASS( bufs [0] );
- BLIP_READER_BEGIN( center, bufs [0] );
-
- for ( ; count; --count )
- {
- blargg_long s = BLIP_READER_READ( center );
- if ( (BOOST::int16_t) s != s )
- s = 0x7FFF - (s >> 24);
-
- BLIP_READER_NEXT( center, bass );
- out [0] = s;
- out [1] = s;
- out += 2;
- }
-
- BLIP_READER_END( center, bufs [0] );
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.h b/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.h
deleted file mode 100644
index 82c8b3ab..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Multi_Buffer.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Multi-channel sound buffer interface, and basic mono and stereo buffers
-
-// Blip_Buffer 0.4.1
-#ifndef MULTI_BUFFER_H
-#define MULTI_BUFFER_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-// Interface to one or more Blip_Buffers mapped to one or more channels
-// consisting of left, center, and right buffers.
-class Multi_Buffer {
-public:
- Multi_Buffer( int samples_per_frame );
- virtual ~Multi_Buffer() { }
-
- // Set the number of channels available
- virtual blargg_err_t set_channel_count( int );
-
- // Get indexed channel, from 0 to channel count - 1
- struct channel_t {
- Blip_Buffer* center;
- Blip_Buffer* left;
- Blip_Buffer* right;
- };
- enum { type_index_mask = 0xFF };
- enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
- virtual channel_t channel( int index, int type ) = 0;
-
- // See Blip_Buffer.h
- virtual blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ) = 0;
- virtual void clock_rate( long ) = 0;
- virtual void bass_freq( int ) = 0;
- virtual void clear() = 0;
- long sample_rate() const;
-
- // Length of buffer, in milliseconds
- int length() const;
-
- // See Blip_Buffer.h
- virtual void end_frame( blip_time_t ) = 0;
-
- // Number of samples per output frame (1 = mono, 2 = stereo)
- int samples_per_frame() const;
-
- // Count of changes to channel configuration. Incremented whenever
- // a change is made to any of the Blip_Buffers for any channel.
- unsigned channels_changed_count() { return channels_changed_count_; }
-
- // See Blip_Buffer.h
- virtual long read_samples( blip_sample_t*, long ) = 0;
- virtual long samples_avail() const = 0;
-
-public:
- BLARGG_DISABLE_NOTHROW
-protected:
- void channels_changed() { channels_changed_count_++; }
-private:
- // noncopyable
- Multi_Buffer( const Multi_Buffer& );
- Multi_Buffer& operator = ( const Multi_Buffer& );
-
- unsigned channels_changed_count_;
- long sample_rate_;
- int length_;
- int const samples_per_frame_;
-};
-
-// Uses a single buffer and outputs mono samples.
-class Mono_Buffer : public Multi_Buffer {
- Blip_Buffer buf;
- channel_t chan;
-public:
- // Buffer used for all channels
- Blip_Buffer* center() { return &buf; }
-
-public:
- Mono_Buffer();
- ~Mono_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length );
- void clock_rate( long rate ) { buf.clock_rate( rate ); }
- void bass_freq( int freq ) { buf.bass_freq( freq ); }
- void clear() { buf.clear(); }
- long samples_avail() const { return buf.samples_avail(); }
- long read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); }
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t t ) { buf.end_frame( t ); }
-};
-
-// Uses three buffers (one for center) and outputs stereo sample pairs.
-class Stereo_Buffer : public Multi_Buffer {
-public:
-
- // Buffers used for all channels
- Blip_Buffer* center() { return &bufs [0]; }
- Blip_Buffer* left() { return &bufs [1]; }
- Blip_Buffer* right() { return &bufs [2]; }
-
-public:
- Stereo_Buffer();
- ~Stereo_Buffer();
- blargg_err_t set_sample_rate( long, int msec = blip_default_length );
- void clock_rate( long );
- void bass_freq( int );
- void clear();
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t );
-
- long samples_avail() const { return bufs [0].samples_avail() * 2; }
- long read_samples( blip_sample_t*, long );
-
-private:
- enum { buf_count = 3 };
- Blip_Buffer bufs [buf_count];
- channel_t chan;
- int stereo_added;
- int was_stereo;
-
- void mix_stereo_no_center( blip_sample_t*, blargg_long );
- void mix_stereo( blip_sample_t*, blargg_long );
- void mix_mono( blip_sample_t*, blargg_long );
-};
-
-// Silent_Buffer generates no samples, useful where no sound is wanted
-class Silent_Buffer : public Multi_Buffer {
- channel_t chan;
-public:
- Silent_Buffer();
- blargg_err_t set_sample_rate( long rate, int msec = blip_default_length );
- void clock_rate( long ) { }
- void bass_freq( int ) { }
- void clear() { }
- channel_t channel( int, int ) { return chan; }
- void end_frame( blip_time_t ) { }
- long samples_avail() const { return 0; }
- long read_samples( blip_sample_t*, long ) { return 0; }
-};
-
-
-inline blargg_err_t Multi_Buffer::set_sample_rate( long rate, int msec )
-{
- sample_rate_ = rate;
- length_ = msec;
- return 0;
-}
-
-inline blargg_err_t Silent_Buffer::set_sample_rate( long rate, int msec )
-{
- return Multi_Buffer::set_sample_rate( rate, msec );
-}
-
-inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; }
-
-inline long Multi_Buffer::sample_rate() const { return sample_rate_; }
-
-inline int Multi_Buffer::length() const { return length_; }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.cpp
deleted file mode 100644
index 5db66fb9..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#include "Multi_Buffer.h"
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const stereo = 2; // number of channels for stereo
-int const silence_max = 6; // seconds
-int const silence_threshold = 0x10;
-long const fade_block_size = 512;
-int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
-
-Music_Emu::equalizer_t const Music_Emu::tv_eq = { -8.0, 180 };
-
-void Music_Emu::clear_track_vars()
-{
- current_track_ = -1;
- out_time = 0;
- emu_time = 0;
- emu_track_ended_ = true;
- track_ended_ = true;
- fade_start = INT_MAX / 2 + 1;
- fade_step = 1;
- silence_time = 0;
- silence_count = 0;
- buf_remain = 0;
- warning(); // clear warning
-}
-
-void Music_Emu::unload()
-{
- voice_count_ = 0;
- clear_track_vars();
- Gme_File::unload();
-}
-
-Music_Emu::Music_Emu()
-{
- effects_buffer = 0;
-
- sample_rate_ = 0;
- mute_mask_ = 0;
- tempo_ = 1.0;
- gain_ = 1.0;
-
- // defaults
- max_initial_silence = 2;
- silence_lookahead = 3;
- ignore_silence_ = false;
- equalizer_.treble = -1.0;
- equalizer_.bass = 60;
-
- static const char* const names [] = {
- "Voice 1", "Voice 2", "Voice 3", "Voice 4",
- "Voice 5", "Voice 6", "Voice 7", "Voice 8"
- };
- set_voice_names( names );
- Music_Emu::unload(); // non-virtual
-}
-
-Music_Emu::~Music_Emu() { delete effects_buffer; }
-
-blargg_err_t Music_Emu::set_sample_rate( long rate )
-{
- require( !sample_rate() ); // sample rate can't be changed once set
- RETURN_ERR( set_sample_rate_( rate ) );
- RETURN_ERR( buf.resize( buf_size ) );
- sample_rate_ = rate;
- return 0;
-}
-
-void Music_Emu::pre_load()
-{
- require( sample_rate() ); // set_sample_rate() must be called before loading a file
- Gme_File::pre_load();
-}
-
-void Music_Emu::set_equalizer( equalizer_t const& eq )
-{
- equalizer_ = eq;
- set_equalizer_( eq );
-}
-
-void Music_Emu::mute_voice( int index, bool mute )
-{
- require( (unsigned) index < (unsigned) voice_count() );
- int bit = 1 << index;
- int mask = mute_mask_ | bit;
- if ( !mute )
- mask ^= bit;
- mute_voices( mask );
-}
-
-void Music_Emu::mute_voices( int mask )
-{
- require( sample_rate() ); // sample rate must be set first
- mute_mask_ = mask;
- mute_voices_( mask );
-}
-
-void Music_Emu::set_tempo( double t )
-{
- require( sample_rate() ); // sample rate must be set first
- double const min = 0.02;
- double const max = 4.00;
- if ( t < min ) t = min;
- if ( t > max ) t = max;
- tempo_ = t;
- set_tempo_( t );
-}
-
-void Music_Emu::post_load_()
-{
- set_tempo( tempo_ );
- remute_voices();
-}
-
-blargg_err_t Music_Emu::start_track( int track )
-{
- clear_track_vars();
-
- int remapped = track;
- RETURN_ERR( remap_track_( &remapped ) );
- current_track_ = track;
- RETURN_ERR( start_track_( remapped ) );
-
- emu_track_ended_ = false;
- track_ended_ = false;
-
- if ( !ignore_silence_ )
- {
- // play until non-silence or end of track
- for ( long end = max_initial_silence * stereo * sample_rate(); emu_time < end; )
- {
- fill_buf();
- if ( buf_remain | (int) emu_track_ended_ )
- break;
- }
-
- emu_time = buf_remain;
- out_time = 0;
- silence_time = 0;
- silence_count = 0;
- }
- return track_ended() ? warning() : 0;
-}
-
-void Music_Emu::end_track_if_error( blargg_err_t err )
-{
- if ( err )
- {
- emu_track_ended_ = true;
- set_warning( err );
- }
-}
-
-// Tell/Seek
-
-blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
-{
- blargg_long sec = msec / 1000;
- msec -= sec * 1000;
- return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
-}
-
-long Music_Emu::tell() const
-{
- blargg_long rate = sample_rate() * stereo;
- blargg_long sec = out_time / rate;
- return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
-}
-
-blargg_err_t Music_Emu::seek( long msec )
-{
- blargg_long time = msec_to_samples( msec );
- if ( time < out_time )
- RETURN_ERR( start_track( current_track_ ) );
- return skip( time - out_time );
-}
-
-blargg_err_t Music_Emu::skip( long count )
-{
- require( current_track() >= 0 ); // start_track() must have been called already
- out_time += count;
-
- // remove from silence and buf first
- {
- long n = min( count, silence_count );
- silence_count -= n;
- count -= n;
-
- n = min( count, buf_remain );
- buf_remain -= n;
- count -= n;
- }
-
- if ( count && !emu_track_ended_ )
- {
- emu_time += count;
- end_track_if_error( skip_( count ) );
- }
-
- if ( !(silence_count | buf_remain) ) // caught up to emulator, so update track ended
- track_ended_ |= emu_track_ended_;
-
- return 0;
-}
-
-blargg_err_t Music_Emu::skip_( long count )
-{
- // for long skip, mute sound
- const long threshold = 30000;
- if ( count > threshold )
- {
- int saved_mute = mute_mask_;
- mute_voices( ~0 );
-
- while ( count > threshold / 2 && !emu_track_ended_ )
- {
- RETURN_ERR( play_( buf_size, buf.begin() ) );
- count -= buf_size;
- }
-
- mute_voices( saved_mute );
- }
-
- while ( count && !emu_track_ended_ )
- {
- long n = buf_size;
- if ( n > count )
- n = count;
- count -= n;
- RETURN_ERR( play_( n, buf.begin() ) );
- }
- return 0;
-}
-
-// Fading
-
-void Music_Emu::set_fade( long start_msec, long length_msec )
-{
- fade_step = sample_rate() * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
- fade_start = msec_to_samples( start_msec );
-}
-
-// unit / pow( 2.0, (double) x / step )
-static int int_log( blargg_long x, int step, int unit )
-{
- int shift = x / step;
- int fraction = (x - shift * step) * unit / step;
- return ((unit - fraction) + (fraction >> 1)) >> shift;
-}
-
-void Music_Emu::handle_fade( long out_count, sample_t* out )
-{
- for ( int i = 0; i < out_count; i += fade_block_size )
- {
- int const shift = 14;
- int const unit = 1 << shift;
- int gain = int_log( (out_time + i - fade_start) / fade_block_size,
- fade_step, unit );
- if ( gain < (unit >> fade_shift) )
- track_ended_ = emu_track_ended_ = true;
-
- sample_t* io = &out [i];
- for ( int count = min( fade_block_size, out_count - i ); count; --count )
- {
- *io = sample_t ((*io * gain) >> shift);
- ++io;
- }
- }
-}
-
-// Silence detection
-
-void Music_Emu::emu_play( long count, sample_t* out )
-{
- check( current_track_ >= 0 );
- emu_time += count;
- if ( current_track_ >= 0 && !emu_track_ended_ )
- end_track_if_error( play_( count, out ) );
- else
- memset( out, 0, count * sizeof *out );
-}
-
-// number of consecutive silent samples at end
-static long count_silence( Music_Emu::sample_t* begin, long size )
-{
- Music_Emu::sample_t first = *begin;
- *begin = silence_threshold; // sentinel
- Music_Emu::sample_t* p = begin + size;
- while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
- *begin = first;
- return size - (p - begin);
-}
-
-// fill internal buffer and check it for silence
-void Music_Emu::fill_buf()
-{
- assert( !buf_remain );
- if ( !emu_track_ended_ )
- {
- emu_play( buf_size, buf.begin() );
- long silence = count_silence( buf.begin(), buf_size );
- if ( silence < buf_size )
- {
- silence_time = emu_time - silence;
- buf_remain = buf_size;
- return;
- }
- }
- silence_count += buf_size;
-}
-
-blargg_err_t Music_Emu::play( long out_count, sample_t* out )
-{
- if ( track_ended_ )
- {
- memset( out, 0, out_count * sizeof *out );
- }
- else
- {
- require( current_track() >= 0 );
- require( out_count % stereo == 0 );
-
- assert( emu_time >= out_time );
-
- // prints nifty graph of how far ahead we are when searching for silence
- //debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
-
- long pos = 0;
- if ( silence_count )
- {
- // during a run of silence, run emulator at >=2x speed so it gets ahead
- long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
- while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) )
- fill_buf();
-
- // fill with silence
- pos = min( silence_count, out_count );
- memset( out, 0, pos * sizeof *out );
- silence_count -= pos;
-
- if ( emu_time - silence_time > silence_max * stereo * sample_rate() )
- {
- track_ended_ = emu_track_ended_ = true;
- silence_count = 0;
- buf_remain = 0;
- }
- }
-
- if ( buf_remain )
- {
- // empty silence buf
- long n = min( buf_remain, out_count - pos );
- memcpy( &out [pos], buf.begin() + (buf_size - buf_remain), n * sizeof *out );
- buf_remain -= n;
- pos += n;
- }
-
- // generate remaining samples normally
- long remain = out_count - pos;
- if ( remain )
- {
- emu_play( remain, out + pos );
- track_ended_ |= emu_track_ended_;
-
- if ( !ignore_silence_ || out_time > fade_start )
- {
- // check end for a new run of silence
- long silence = count_silence( out + pos, remain );
- if ( silence < remain )
- silence_time = emu_time - silence;
-
- if ( emu_time - silence_time >= buf_size )
- fill_buf(); // cause silence detection on next play()
- }
- }
-
- if ( out_time > fade_start )
- handle_fade( out_count, out );
- }
- out_time += out_count;
- return 0;
-}
-
-// Gme_Info_
-
-blargg_err_t Gme_Info_::set_sample_rate_( long ) { return 0; }
-void Gme_Info_::pre_load() { Gme_File::pre_load(); } // skip Music_Emu
-void Gme_Info_::post_load_() { Gme_File::post_load_(); } // skip Music_Emu
-void Gme_Info_::set_equalizer_( equalizer_t const& ){ check( false ); }
-void Gme_Info_::mute_voices_( int ) { check( false ); }
-void Gme_Info_::set_tempo_( double ) { }
-blargg_err_t Gme_Info_::start_track_( int ) { return "Use full emulator for playback"; }
-blargg_err_t Gme_Info_::play_( long, sample_t* ) { return "Use full emulator for playback"; }
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.h
deleted file mode 100644
index c5f1d029..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Music_Emu.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// Common interface to game music file emulators
-
-// Game_Music_Emu 0.5.5
-#ifndef MUSIC_EMU_H
-#define MUSIC_EMU_H
-
-#include "Gme_File.h"
-class Multi_Buffer;
-
-struct Music_Emu : public Gme_File {
-public:
-// Basic functionality (see Gme_File.h for file loading/track info functions)
-
- // Set output sample rate. Must be called only once before loading file.
- blargg_err_t set_sample_rate( long sample_rate );
-
- // Start a track, where 0 is the first track. Also clears warning string.
- blargg_err_t start_track( int );
-
- // Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
- // errors set warning string, and major errors also end track.
- typedef short sample_t;
- blargg_err_t play( long count, sample_t* buf );
-
-// Informational
-
- // Sample rate sound is generated at
- long sample_rate() const;
-
- // Index of current track or -1 if one hasn't been started
- int current_track() const;
-
- // Number of voices used by currently loaded file
- int voice_count() const;
-
- // Names of voices
- const char** voice_names() const;
-
-// Track status/control
-
- // Number of milliseconds (1000 msec = 1 second) played since beginning of track
- long tell() const;
-
- // Seek to new time in track. Seeking backwards or far forward can take a while.
- blargg_err_t seek( long msec );
-
- // Skip n samples
- blargg_err_t skip( long n );
-
- // True if a track has reached its end
- bool track_ended() const;
-
- // Set start time and length of track fade out. Once fade ends track_ended() returns
- // true. Fade time can be changed while track is playing.
- void set_fade( long start_msec, long length_msec = 8000 );
-
- // Disable automatic end-of-track detection and skipping of silence at beginning
- void ignore_silence( bool disable = true );
-
- // Info for current track
- Gme_File::track_info;
- blargg_err_t track_info( track_info_t* out ) const;
-
-// Sound customization
-
- // Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
- // Track length as returned by track_info() assumes a tempo of 1.0.
- void set_tempo( double );
-
- // Mute/unmute voice i, where voice 0 is first voice
- void mute_voice( int index, bool mute = true );
-
- // Set muting state of all voices at once using a bit mask, where -1 mutes them all,
- // 0 unmutes them all, 0x01 mutes just the first voice, etc.
- void mute_voices( int mask );
-
- // Change overall output amplitude, where 1.0 results in minimal clamping.
- // Must be called before set_sample_rate().
- void set_gain( double );
-
- // Request use of custom multichannel buffer. Only supported by "classic" emulators;
- // on others this has no effect. Should be called only once *before* set_sample_rate().
- virtual void set_buffer( Multi_Buffer* ) { }
-
-// Sound equalization (treble/bass)
-
- // Frequency equalizer parameters (see gme.txt)
- // See gme.h for definition of struct gme_equalizer_t.
- typedef gme_equalizer_t equalizer_t;
-
- // Current frequency equalizater parameters
- equalizer_t const& equalizer() const;
-
- // Set frequency equalizer parameters
- void set_equalizer( equalizer_t const& );
-
- // Equalizer settings for TV speaker
- static equalizer_t const tv_eq;
-
-public:
- Music_Emu();
- ~Music_Emu();
-protected:
- void set_max_initial_silence( int n ) { max_initial_silence = n; }
- void set_silence_lookahead( int n ) { silence_lookahead = n; }
- void set_voice_count( int n ) { voice_count_ = n; }
- void set_voice_names( const char* const* names );
- void set_track_ended() { emu_track_ended_ = true; }
- double gain() const { return gain_; }
- double tempo() const { return tempo_; }
- void remute_voices();
-
- virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
- virtual void set_equalizer_( equalizer_t const& ) { };
- virtual void mute_voices_( int mask ) = 0;
- virtual void set_tempo_( double ) = 0;
- virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this
- virtual blargg_err_t play_( long count, sample_t* out ) = 0;
- virtual blargg_err_t skip_( long count );
-protected:
- virtual void unload();
- virtual void pre_load();
- virtual void post_load_();
-private:
- // general
- equalizer_t equalizer_;
- int max_initial_silence;
- const char** voice_names_;
- int voice_count_;
- int mute_mask_;
- double tempo_;
- double gain_;
-
- long sample_rate_;
- blargg_long msec_to_samples( blargg_long msec ) const;
-
- // track-specific
- int current_track_;
- blargg_long out_time; // number of samples played since start of track
- blargg_long emu_time; // number of samples emulator has generated since start of track
- bool emu_track_ended_; // emulator has reached end of track
- volatile bool track_ended_;
- void clear_track_vars();
- void end_track_if_error( blargg_err_t );
-
- // fading
- blargg_long fade_start;
- int fade_step;
- void handle_fade( long count, sample_t* out );
-
- // silence detection
- int silence_lookahead; // speed to run emulator when looking ahead for silence
- bool ignore_silence_;
- long silence_time; // number of samples where most recent silence began
- long silence_count; // number of samples of silence to play before using buf
- long buf_remain; // number of samples left in silence buffer
- enum { buf_size = 2048 };
- blargg_vector<sample_t> buf;
- void fill_buf();
- void emu_play( long count, sample_t* out );
-
- Multi_Buffer* effects_buffer;
- friend Music_Emu* gme_new_emu( gme_type_t, int );
- friend void gme_set_stereo_depth( Music_Emu*, double );
-};
-
-// base class for info-only derivations
-struct Gme_Info_ : Music_Emu
-{
- virtual blargg_err_t set_sample_rate_( long sample_rate );
- virtual void set_equalizer_( equalizer_t const& );
- virtual void mute_voices_( int mask );
- virtual void set_tempo_( double );
- virtual blargg_err_t start_track_( int );
- virtual blargg_err_t play_( long count, sample_t* out );
- virtual void pre_load();
- virtual void post_load_();
-};
-
-inline blargg_err_t Music_Emu::track_info( track_info_t* out ) const
-{
- return track_info( out, current_track_ );
-}
-
-inline long Music_Emu::sample_rate() const { return sample_rate_; }
-inline const char** Music_Emu::voice_names() const { return voice_names_; }
-inline int Music_Emu::voice_count() const { return voice_count_; }
-inline int Music_Emu::current_track() const { return current_track_; }
-inline bool Music_Emu::track_ended() const { return track_ended_; }
-inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; }
-
-inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
-inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
-inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
-inline blargg_err_t Music_Emu::start_track_( int ) { return 0; }
-
-inline void Music_Emu::set_voice_names( const char* const* names )
-{
- // Intentional removal of const, so users don't have to remember obscure const in middle
- voice_names_ = const_cast<const char**> (names);
-}
-
-inline void Music_Emu::mute_voices_( int ) { }
-
-inline void Music_Emu::set_gain( double g )
-{
- assert( !sample_rate() ); // you must set gain before setting sample rate
- gain_ = g;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.cpp
deleted file mode 100644
index 68edb446..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.cpp
+++ /dev/null
@@ -1,391 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const amp_range = 15;
-
-Nes_Apu::Nes_Apu() :
- square1( &square_synth ),
- square2( &square_synth )
-{
- tempo_ = 1.0;
- dmc.apu = this;
- dmc.prg_reader = NULL;
- irq_notifier_ = NULL;
-
- oscs [0] = &square1;
- oscs [1] = &square2;
- oscs [2] = &triangle;
- oscs [3] = &noise;
- oscs [4] = &dmc;
-
- output( NULL );
- volume( 1.0 );
- reset( false );
-}
-
-void Nes_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- triangle.synth.treble_eq( eq );
- noise.synth.treble_eq( eq );
- dmc.synth.treble_eq( eq );
-}
-
-void Nes_Apu::enable_nonlinear( double v )
-{
- dmc.nonlinear = true;
- square_synth.volume( 1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v );
-
- const double tnd = 0.48 / 202 * nonlinear_tnd_gain();
- triangle.synth.volume( 3.0 * tnd );
- noise.synth.volume( 2.0 * tnd );
- dmc.synth.volume( tnd );
-
- square1 .last_amp = 0;
- square2 .last_amp = 0;
- triangle.last_amp = 0;
- noise .last_amp = 0;
- dmc .last_amp = 0;
-}
-
-void Nes_Apu::volume( double v )
-{
- dmc.nonlinear = false;
- square_synth.volume( 0.1128 / amp_range * v );
- triangle.synth.volume( 0.12765 / amp_range * v );
- noise.synth.volume( 0.0741 / amp_range * v );
- dmc.synth.volume( 0.42545 / 127 * v );
-}
-
-void Nes_Apu::output( Blip_Buffer* buffer )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buffer );
-}
-
-void Nes_Apu::set_tempo( double t )
-{
- tempo_ = t;
- frame_period = (dmc.pal_mode ? 8314 : 7458);
- if ( t != 1.0 )
- frame_period = (int) (frame_period / t) & ~1; // must be even
-}
-
-void Nes_Apu::reset( bool pal_mode, int initial_dmc_dac )
-{
- dmc.pal_mode = pal_mode;
- set_tempo( tempo_ );
-
- square1.reset();
- square2.reset();
- triangle.reset();
- noise.reset();
- dmc.reset();
-
- last_time = 0;
- last_dmc_time = 0;
- osc_enables = 0;
- irq_flag = false;
- earliest_irq_ = no_irq;
- frame_delay = 1;
- write_register( 0, 0x4017, 0x00 );
- write_register( 0, 0x4015, 0x00 );
-
- for ( nes_addr_t addr = start_addr; addr <= 0x4013; addr++ )
- write_register( 0, addr, (addr & 3) ? 0x00 : 0x10 );
-
- dmc.dac = initial_dmc_dac;
- if ( !dmc.nonlinear )
- triangle.last_amp = 15;
- if ( !dmc.nonlinear ) // TODO: remove?
- dmc.last_amp = initial_dmc_dac; // prevent output transition
-}
-
-void Nes_Apu::irq_changed()
-{
- nes_time_t new_irq = dmc.next_irq;
- if ( dmc.irq_flag | irq_flag ) {
- new_irq = 0;
- }
- else if ( new_irq > next_irq ) {
- new_irq = next_irq;
- }
-
- if ( new_irq != earliest_irq_ ) {
- earliest_irq_ = new_irq;
- if ( irq_notifier_ )
- irq_notifier_( irq_data );
- }
-}
-
-// frames
-
-void Nes_Apu::run_until( nes_time_t end_time )
-{
- require( end_time >= last_dmc_time );
- if ( end_time > next_dmc_read_time() )
- {
- nes_time_t start = last_dmc_time;
- last_dmc_time = end_time;
- dmc.run( start, end_time );
- }
-}
-
-void Nes_Apu::run_until_( nes_time_t end_time )
-{
- require( end_time >= last_time );
-
- if ( end_time == last_time )
- return;
-
- if ( last_dmc_time < end_time )
- {
- nes_time_t start = last_dmc_time;
- last_dmc_time = end_time;
- dmc.run( start, end_time );
- }
-
- while ( true )
- {
- // earlier of next frame time or end time
- nes_time_t time = last_time + frame_delay;
- if ( time > end_time )
- time = end_time;
- frame_delay -= time - last_time;
-
- // run oscs to present
- square1.run( last_time, time );
- square2.run( last_time, time );
- triangle.run( last_time, time );
- noise.run( last_time, time );
- last_time = time;
-
- if ( time == end_time )
- break; // no more frames to run
-
- // take frame-specific actions
- frame_delay = frame_period;
- switch ( frame++ )
- {
- case 0:
- if ( !(frame_mode & 0xC0) ) {
- next_irq = time + frame_period * 4 + 2;
- irq_flag = true;
- }
- // fall through
- case 2:
- // clock length and sweep on frames 0 and 2
- square1.clock_length( 0x20 );
- square2.clock_length( 0x20 );
- noise.clock_length( 0x20 );
- triangle.clock_length( 0x80 ); // different bit for halt flag on triangle
-
- square1.clock_sweep( -1 );
- square2.clock_sweep( 0 );
-
- // frame 2 is slightly shorter in mode 1
- if ( dmc.pal_mode && frame == 3 )
- frame_delay -= 2;
- break;
-
- case 1:
- // frame 1 is slightly shorter in mode 0
- if ( !dmc.pal_mode )
- frame_delay -= 2;
- break;
-
- case 3:
- frame = 0;
-
- // frame 3 is almost twice as long in mode 1
- if ( frame_mode & 0x80 )
- frame_delay += frame_period - (dmc.pal_mode ? 2 : 6);
- break;
- }
-
- // clock envelopes and linear counter every frame
- triangle.clock_linear_counter();
- square1.clock_envelope();
- square2.clock_envelope();
- noise.clock_envelope();
- }
-}
-
-template<class T>
-inline void zero_apu_osc( T* osc, nes_time_t time )
-{
- Blip_Buffer* output = osc->output;
- int last_amp = osc->last_amp;
- osc->last_amp = 0;
- if ( output && last_amp )
- osc->synth.offset( time, -last_amp, output );
-}
-
-void Nes_Apu::end_frame( nes_time_t end_time )
-{
- if ( end_time > last_time )
- run_until_( end_time );
-
- if ( dmc.nonlinear )
- {
- zero_apu_osc( &square1, last_time );
- zero_apu_osc( &square2, last_time );
- zero_apu_osc( &triangle, last_time );
- zero_apu_osc( &noise, last_time );
- zero_apu_osc( &dmc, last_time );
- }
-
- // make times relative to new frame
- last_time -= end_time;
- require( last_time >= 0 );
-
- last_dmc_time -= end_time;
- require( last_dmc_time >= 0 );
-
- if ( next_irq != no_irq ) {
- next_irq -= end_time;
- check( next_irq >= 0 );
- }
- if ( dmc.next_irq != no_irq ) {
- dmc.next_irq -= end_time;
- check( dmc.next_irq >= 0 );
- }
- if ( earliest_irq_ != no_irq ) {
- earliest_irq_ -= end_time;
- if ( earliest_irq_ < 0 )
- earliest_irq_ = 0;
- }
-}
-
-// registers
-
-static const unsigned char length_table [0x20] = {
- 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
- 0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E,
- 0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
- 0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
-};
-
-void Nes_Apu::write_register( nes_time_t time, nes_addr_t addr, int data )
-{
- require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
- require( (unsigned) data <= 0xFF );
-
- // Ignore addresses outside range
- if ( unsigned (addr - start_addr) > end_addr - start_addr )
- return;
-
- run_until_( time );
-
- if ( addr < 0x4014 )
- {
- // Write to channel
- int osc_index = (addr - start_addr) >> 2;
- Nes_Osc* osc = oscs [osc_index];
-
- int reg = addr & 3;
- osc->regs [reg] = data;
- osc->reg_written [reg] = true;
-
- if ( osc_index == 4 )
- {
- // handle DMC specially
- dmc.write_register( reg, data );
- }
- else if ( reg == 3 )
- {
- // load length counter
- if ( (osc_enables >> osc_index) & 1 )
- osc->length_counter = length_table [(data >> 3) & 0x1F];
-
- // reset square phase
- if ( osc_index < 2 )
- ((Nes_Square*) osc)->phase = Nes_Square::phase_range - 1;
- }
- }
- else if ( addr == 0x4015 )
- {
- // Channel enables
- for ( int i = osc_count; i--; )
- if ( !((data >> i) & 1) )
- oscs [i]->length_counter = 0;
-
- bool recalc_irq = dmc.irq_flag;
- dmc.irq_flag = false;
-
- int old_enables = osc_enables;
- osc_enables = data;
- if ( !(data & 0x10) ) {
- dmc.next_irq = no_irq;
- recalc_irq = true;
- }
- else if ( !(old_enables & 0x10) ) {
- dmc.start(); // dmc just enabled
- }
-
- if ( recalc_irq )
- irq_changed();
- }
- else if ( addr == 0x4017 )
- {
- // Frame mode
- frame_mode = data;
-
- bool irq_enabled = !(data & 0x40);
- irq_flag &= irq_enabled;
- next_irq = no_irq;
-
- // mode 1
- frame_delay = (frame_delay & 1);
- frame = 0;
-
- if ( !(data & 0x80) )
- {
- // mode 0
- frame = 1;
- frame_delay += frame_period;
- if ( irq_enabled )
- next_irq = time + frame_delay + frame_period * 3 + 1;
- }
-
- irq_changed();
- }
-}
-
-int Nes_Apu::read_status( nes_time_t time )
-{
- run_until_( time - 1 );
-
- int result = (dmc.irq_flag << 7) | (irq_flag << 6);
-
- for ( int i = 0; i < osc_count; i++ )
- if ( oscs [i]->length_counter )
- result |= 1 << i;
-
- run_until_( time );
-
- if ( irq_flag )
- {
- result |= 0x40;
- irq_flag = false;
- irq_changed();
- }
-
- //debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
-
- return result;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.h
deleted file mode 100644
index 5e722248..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Apu.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// NES 2A03 APU sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_APU_H
-#define NES_APU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long nes_time_t; // CPU clock cycle count
-typedef unsigned nes_addr_t; // 16-bit memory address
-
-#include "Nes_Oscs.h"
-
-struct apu_state_t;
-class Nes_Buffer;
-
-class Nes_Apu {
-public:
- // Set buffer to generate all sound into, or disable sound if NULL
- void output( Blip_Buffer* );
-
- // Set memory reader callback used by DMC oscillator to fetch samples.
- // When callback is invoked, 'user_data' is passed unchanged as the
- // first parameter.
- void dmc_reader( int (*callback)( void* user_data, nes_addr_t ), void* user_data = NULL );
-
- // All time values are the number of CPU clock cycles relative to the
- // beginning of the current time frame. Before resetting the CPU clock
- // count, call end_frame( last_cpu_time ).
-
- // Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
- enum { start_addr = 0x4000 };
- enum { end_addr = 0x4017 };
- void write_register( nes_time_t, nes_addr_t, int data );
-
- // Read from status register at 0x4015
- enum { status_addr = 0x4015 };
- int read_status( nes_time_t );
-
- // Run all oscillators up to specified time, end current time frame, then
- // start a new time frame at time 0. Time frames have no effect on emulation
- // and each can be whatever length is convenient.
- void end_frame( nes_time_t );
-
-// Additional optional features (can be ignored without any problem)
-
- // Reset internal frame counter, registers, and all oscillators.
- // Use PAL timing if pal_timing is true, otherwise use NTSC timing.
- // Set the DMC oscillator's initial DAC value to initial_dmc_dac without
- // any audible click.
- void reset( bool pal_mode = false, int initial_dmc_dac = 0 );
-
- // Adjust frame period
- void set_tempo( double );
-
- // Save/load exact emulation state
- void save_state( apu_state_t* out ) const;
- void load_state( apu_state_t const& );
-
- // Set overall volume (default is 1.0)
- void volume( double );
-
- // Set treble equalization (see notes.txt)
- void treble_eq( const blip_eq_t& );
-
- // Set sound output of specific oscillator to buffer. If buffer is NULL,
- // the specified oscillator is muted and emulation accuracy is reduced.
- // The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
- // 2) Triangle, 3) Noise, 4) DMC.
- enum { osc_count = 5 };
- void osc_output( int index, Blip_Buffer* buffer );
-
- // Set IRQ time callback that is invoked when the time of earliest IRQ
- // may have changed, or NULL to disable. When callback is invoked,
- // 'user_data' is passed unchanged as the first parameter.
- void irq_notifier( void (*callback)( void* user_data ), void* user_data = NULL );
-
- // Get time that APU-generated IRQ will occur if no further register reads
- // or writes occur. If IRQ is already pending, returns irq_waiting. If no
- // IRQ will occur, returns no_irq.
- enum { no_irq = INT_MAX / 2 + 1 };
- enum { irq_waiting = 0 };
- nes_time_t earliest_irq( nes_time_t ) const;
-
- // Count number of DMC reads that would occur if 'run_until( t )' were executed.
- // If last_read is not NULL, set *last_read to the earliest time that
- // 'count_dmc_reads( time )' would result in the same result.
- int count_dmc_reads( nes_time_t t, nes_time_t* last_read = NULL ) const;
-
- // Time when next DMC memory read will occur
- nes_time_t next_dmc_read_time() const;
-
- // Run DMC until specified time, so that any DMC memory reads can be
- // accounted for (i.e. inserting CPU wait states).
- void run_until( nes_time_t );
-
-public:
- Nes_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- friend class Nes_Nonlinearizer;
- void enable_nonlinear( double volume );
- static double nonlinear_tnd_gain() { return 0.75; }
-private:
- friend struct Nes_Dmc;
-
- // noncopyable
- Nes_Apu( const Nes_Apu& );
- Nes_Apu& operator = ( const Nes_Apu& );
-
- Nes_Osc* oscs [osc_count];
- Nes_Square square1;
- Nes_Square square2;
- Nes_Noise noise;
- Nes_Triangle triangle;
- Nes_Dmc dmc;
-
- double tempo_;
- nes_time_t last_time; // has been run until this time in current frame
- nes_time_t last_dmc_time;
- nes_time_t earliest_irq_;
- nes_time_t next_irq;
- int frame_period;
- int frame_delay; // cycles until frame counter runs next
- int frame; // current frame (0-3)
- int osc_enables;
- int frame_mode;
- bool irq_flag;
- void (*irq_notifier_)( void* user_data );
- void* irq_data;
- Nes_Square::Synth square_synth; // shared by squares
-
- void irq_changed();
- void state_restored();
- void run_until_( nes_time_t );
-
- // TODO: remove
- friend class Nes_Core;
-};
-
-inline void Nes_Apu::osc_output( int osc, Blip_Buffer* buf )
-{
- assert( (unsigned) osc < osc_count );
- oscs [osc]->output = buf;
-}
-
-inline nes_time_t Nes_Apu::earliest_irq( nes_time_t ) const
-{
- return earliest_irq_;
-}
-
-inline void Nes_Apu::dmc_reader( int (*func)( void*, nes_addr_t ), void* user_data )
-{
- dmc.prg_reader_data = user_data;
- dmc.prg_reader = func;
-}
-
-inline void Nes_Apu::irq_notifier( void (*func)( void* user_data ), void* user_data )
-{
- irq_notifier_ = func;
- irq_data = user_data;
-}
-
-inline int Nes_Apu::count_dmc_reads( nes_time_t time, nes_time_t* last_read ) const
-{
- return dmc.count_reads( time, last_read );
-}
-
-inline nes_time_t Nes_Dmc::next_read_time() const
-{
- if ( length_counter == 0 )
- return Nes_Apu::no_irq; // not reading
-
- return apu->last_dmc_time + delay + long (bits_remain - 1) * period;
-}
-
-inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.cpp
deleted file mode 100644
index 864e0dde..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.cpp
+++ /dev/null
@@ -1,1084 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nes_Cpu.h"
-
-#include "blargg_endian.h"
-#include <limits.h>
-
-#define BLARGG_CPU_X86 1
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "nes_cpu_io.h"
-
-#include "blargg_source.h"
-
-#ifndef CPU_DONE
- #define CPU_DONE( cpu, time, result_out ) { result_out = -1; }
-#endif
-
-#ifndef CPU_READ_PPU
- #define CPU_READ_PPU( cpu, addr, out, time )\
- {\
- FLUSH_TIME();\
- out = CPU_READ( cpu, addr, time );\
- CACHE_TIME();\
- }
-#endif
-
-#if BLARGG_NONPORTABLE
- #define PAGE_OFFSET( addr ) (addr)
-#else
- #define PAGE_OFFSET( addr ) ((addr) & (page_size - 1))
-#endif
-
-inline void Nes_Cpu::set_code_page( int i, void const* p )
-{
- state->code_map [i] = (uint8_t const*) p - PAGE_OFFSET( i * page_size );
-}
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Nes_Cpu::reset( void const* unmapped_page )
-{
- check( state == &state_ );
- state = &state_;
- r.status = st_i;
- r.sp = 0xFF;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_nes_time;
- end_time_ = future_nes_time;
- error_count_ = 0;
-
- assert( page_size == 0x800 ); // assumes this
- set_code_page( page_count, unmapped_page );
- map_code( 0x2000, 0xE000, unmapped_page, true );
- map_code( 0x0000, 0x2000, low_mem, true );
-
- blargg_verify_byte_order();
-}
-
-void Nes_Cpu::map_code( nes_addr_t start, unsigned size, void const* data, bool mirror )
-{
- // address range must begin and end on page boundaries
- require( start % page_size == 0 );
- require( size % page_size == 0 );
- require( start + size <= 0x10000 );
-
- unsigned page = start / page_size;
- for ( unsigned n = size / page_size; n; --n )
- {
- set_code_page( page++, data );
- if ( !mirror )
- data = (char const*) data + page_size;
- }
-}
-
-#define TIME (s_time + s.base)
-#define READ_LIKELY_PPU( addr, out ) {CPU_READ_PPU( this, (addr), out, TIME );}
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (low_mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (s.code_map [(addr) >> page_bits] [PAGE_OFFSET( addr )])
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-
-bool Nes_Cpu::run( nes_time_t end_time )
-{
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- // even on x86, using s.time in place of s_time was slower
- fint16 s_time = s.time;
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- // status flags
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-dec_clock_loop:
- s_time--;
-loop:
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) pc < 0x10000 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
- check( -32768 <= s_time && s_time < 32767 );
-
- uint8_t const* instr = s.code_map [pc >> page_bits];
- fuint8 opcode;
-
- // TODO: eliminate this special case
- #if BLARGG_NONPORTABLE
- opcode = instr [pc];
- pc++;
- instr += pc;
- #else
- instr += PAGE_OFFSET( pc );
- opcode = *instr++;
- pc++;
- #endif
-
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
- 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
- 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
- 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
- 3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
- 3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
- 3,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
- }; // 0x00 was 7 and 0xF2 was 2
-
- fuint16 data;
-
-#if !BLARGG_CPU_X86
- if ( s_time >= 0 )
- goto out_of_time;
- s_time += clock_table [opcode];
-
- data = *instr;
-
- switch ( opcode )
- {
-#else
-
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-#endif
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE() (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR() GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
- fuint16 temp = READ_LOW( data ) + y;\
- out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- cross( temp );\
- }
-
-#define IND_X( out ) {\
- fuint16 temp = data + x;\
- out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
- }
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
- IND_X( data )\
- goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
- IND_Y( HANDLE_PAGE_CROSSING, data )\
- goto ptr##op;\
-case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
-case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
-case op + 0x18: /* abs,X */\
- data += x;\
-ind##op:\
- HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
- ADD_PAGE();\
-ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- fuint16 extra_clock = (++pc & 0xFF) + offset;\
- if ( !(cond) ) goto dec_clock_loop;\
- pc = BOOST::uint16_t (pc + offset);\
- s_time += extra_clock >> 8 & 1;\
- goto loop;\
-}
-
-// Often-Used
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0xE8: // INX
- INC_DEC_XY( x, 1 )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0xF0: // BEQ
- BRANCH( !(uint8_t) nz );
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xC8: // INY
- INC_DEC_XY( y, 1 )
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAD:{// LDA abs
- unsigned addr = GET_ADDR();
- pc += 2;
- READ_LIKELY_PPU( addr, nz );
- a = nz;
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 1 + READ_LOW( sp );
- pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- {
- fuint16 addr;
-
- case 0x99: // STA abs,Y
- addr = y + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x8D: // STA abs
- addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x9D: // STA abs,X (slightly more common than STA abs)
- addr = x + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- sta_ptr:
- FLUSH_TIME();
- WRITE( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x91: // STA (ind),Y
- IND_Y( NO_PAGE_CROSSING, addr )
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- IND_X( addr )
- pc++;
- goto sta_ptr;
-
- }
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
- // common read instructions
- {
- fuint16 addr;
-
- case 0xA1: // LDA (ind,X)
- IND_X( addr )
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- HANDLE_PAGE_CROSSING( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- HANDLE_PAGE_CROSSING( data + y );
- addr = GET_ADDR() + y;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xBD: // LDA abs,X
- HANDLE_PAGE_CROSSING( data + x );
- addr = GET_ADDR() + x;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- a_nz_read_addr:
- FLUSH_TIME();
- a = nz = READ( addr );
- CACHE_TIME();
- goto loop;
-
- }
-
-// Branch
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
-// Load/store
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- HANDLE_PAGE_CROSSING( data );
- case 0xAC:{// LDY abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xBE: // LDX abs,y
- data += y;
- HANDLE_PAGE_CROSSING( data );
- case 0xAE:{// LDX abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- unsigned addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, temp );
- goto loop;
- }
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
- case 0x2C:{// BIT abs
- unsigned addr = GET_ADDR();
- pc += 2;
- status &= ~st_v;
- READ_LIKELY_PPU( addr, nz );
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
- }
-
- case 0x24: // BIT zp
- nz = READ_LOW( data );
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- case 0xEB: // unofficial equivalent
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE();
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE();
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
- case 0xCA: // DEX
- INC_DEC_XY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_XY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a ); // verified
- goto loop;
-
- case 0x68: // PLA
- a = nz = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 ) goto loop;
- if ( status & st_i ) goto loop;
- s_time += delta;
- s.base = irq_time_;
- goto loop;
- }
-
- case 0x28:{// PLP
- fuint8 temp = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | (st_b | st_r) );
- goto loop;
- }
-
- case 0x6C:{// JMP (ind)
- data = GET_ADDR();
- check( unsigned (data - 0x2000) >= 0x4000 ); // ensure it's outside I/O space
- uint8_t const* page = s.code_map [data >> page_bits];
- pc = page [PAGE_OFFSET( data )];
- data = (data & 0xFF00) | ((data + 1) & 0xFF);
- pc |= page [PAGE_OFFSET( data )] << 8;
- goto loop;
- }
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- //debug_printf( "CLI at %d\n", TIME );
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- s.base += s_time + 1;
- s_time = -1;
- goto loop;
- }
-
- // TODO: implement
- delayed_cli:
- debug_printf( "Delayed CLI not emulated\n" );
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- debug_printf( "Delayed SEI not emulated\n" );
- goto loop;
- }
-
-// Unofficial
-
- // SKW - Skip word
- case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
- HANDLE_PAGE_CROSSING( data + x );
- case 0x0C:
- pc++;
- // SKB - Skip byte
- case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
- case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
- pc++;
- goto loop;
-
- // NOP
- case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
- goto loop;
-
- case bad_opcode: // HLT
- pc--;
- if ( pc > 0xFFFF )
- {
- // handle wrap-around (assumes caller has put page of HLT at 0x10000)
- pc &= 0xFFFF;
- goto loop;
- }
- case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2:
- goto stop;
-
-// Unimplemented
-
- case 0xFF: // force 256-entry jump table for optimization purposes
- c |= 1;
- default:
- check( (unsigned) opcode <= 0xFF );
- // skip over proper number of bytes
- static unsigned char const illop_lens [8] = {
- 0x40, 0x40, 0x40, 0x80, 0x40, 0x40, 0x80, 0xA0
- };
- fuint8 opcode = instr [-1];
- fint16 len = illop_lens [opcode >> 2 & 7] >> (opcode << 1 & 6) & 3;
- if ( opcode == 0x9C )
- len = 2;
- pc += len;
- error_count_++;
-
- if ( (opcode >> 4) == 0x0B )
- {
- if ( opcode == 0xB3 )
- data = READ_LOW( data );
- if ( opcode != 0xB7 )
- HANDLE_PAGE_CROSSING( data + y );
- }
- goto loop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- pc++;
- result_ = 4;
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- temp |= st_r;
- if ( result_ )
- temp |= st_b; // TODO: incorrectly sets B flag for IRQ
- WRITE_LOW( sp, temp );
-
- this->r.status = status |= st_i;
- blargg_long delta = s.base - end_time_;
- if ( delta >= 0 ) goto loop;
- s_time += delta;
- s.base = end_time_;
- goto loop;
- }
-
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ >= 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
-stop:
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return s_time < 0;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.h
deleted file mode 100644
index 694296f7..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Cpu.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// NES 6502 CPU emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef NES_CPU_H
-#define NES_CPU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long nes_time_t; // clock cycle count
-typedef unsigned nes_addr_t; // 16-bit address
-enum { future_nes_time = INT_MAX / 2 + 1 };
-
-class Nes_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear registers, map low memory and its three mirrors to address 0,
- // and mirror unmapped_page in remaining memory
- void reset( void const* unmapped_page = 0 );
-
- // Map code memory (memory accessed via the program counter). Start and size
- // must be multiple of page_size. If mirror is true, repeats code page
- // throughout address range.
- enum { page_size = 0x800 };
- void map_code( nes_addr_t start, unsigned size, void const* code, bool mirror = false );
-
- // Access emulated memory as CPU does
- uint8_t const* get_code( nes_addr_t );
-
- // 2KB of RAM at address 0
- uint8_t low_mem [0x800];
-
- // NES 6502 registers. Not kept updated during a call to run().
- struct registers_t {
- BOOST::uint16_t pc;
- BOOST::uint8_t a;
- BOOST::uint8_t x;
- BOOST::uint8_t y;
- BOOST::uint8_t status;
- BOOST::uint8_t sp;
- };
- registers_t r;
-
- // Set end_time and run CPU from current time. Returns true if execution
- // stopped due to encountering bad_opcode.
- bool run( nes_time_t end_time );
-
- // Time of beginning of next instruction to be executed
- nes_time_t time() const { return state->time + state->base; }
- void set_time( nes_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- nes_time_t irq_time() const { return irq_time_; }
- void set_irq_time( nes_time_t );
-
- nes_time_t end_time() const { return end_time_; }
- void set_end_time( nes_time_t );
-
- // Number of undefined instructions encountered and skipped
- void clear_error_count() { error_count_ = 0; }
- unsigned long error_count() const { return error_count_; }
-
- // CPU invokes bad opcode handler if it encounters this
- enum { bad_opcode = 0xF2 };
-
-public:
- Nes_Cpu() { state = &state_; }
- enum { page_bits = 11 };
- enum { page_count = 0x10000 >> page_bits };
- enum { irq_inhibit = 0x04 };
-private:
- struct state_t {
- uint8_t const* code_map [page_count + 1];
- nes_time_t base;
- int time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- nes_time_t irq_time_;
- nes_time_t end_time_;
- unsigned long error_count_;
-
- void set_code_page( int, void const* );
- inline int update_end_time( nes_time_t end, nes_time_t irq );
-};
-
-inline BOOST::uint8_t const* Nes_Cpu::get_code( nes_addr_t addr )
-{
- return state->code_map [addr >> page_bits] + addr
- #if !BLARGG_NONPORTABLE
- % (unsigned) page_size
- #endif
- ;
-}
-
-inline int Nes_Cpu::update_end_time( nes_time_t t, nes_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- int delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Nes_Cpu::set_irq_time( nes_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Nes_Cpu::set_end_time( nes_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.cpp
deleted file mode 100644
index 62594fc2..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nes_Fme7_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-void Nes_Fme7_Apu::reset()
-{
- last_time = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- oscs [i].last_amp = 0;
-
- fme7_apu_state_t* state = this;
- memset( state, 0, sizeof *state );
-}
-
-unsigned char const Nes_Fme7_Apu::amp_table [16] =
-{
- #define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
- ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
- ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
- ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
- ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
- #undef ENTRY
-};
-
-void Nes_Fme7_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time );
-
- for ( int index = 0; index < osc_count; index++ )
- {
- int mode = regs [7] >> index;
- int vol_mode = regs [010 + index];
- int volume = amp_table [vol_mode & 0x0F];
-
- Blip_Buffer* const osc_output = oscs [index].output;
- if ( !osc_output )
- continue;
- osc_output->set_modified();
-
- // check for unsupported mode
- #ifndef NDEBUG
- if ( (mode & 011) <= 001 && vol_mode & 0x1F )
- debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
- mode, vol_mode & 0x1F );
- #endif
-
- if ( (mode & 001) | (vol_mode & 0x10) )
- volume = 0; // noise and envelope aren't supported
-
- // period
- int const period_factor = 16;
- unsigned period = (regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
- regs [index * 2] * period_factor;
- if ( period < 50 ) // around 22 kHz
- {
- volume = 0;
- if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
- period = period_factor;
- }
-
- // current amplitude
- int amp = volume;
- if ( !phases [index] )
- amp = 0;
- {
- int delta = amp - oscs [index].last_amp;
- if ( delta )
- {
- oscs [index].last_amp = amp;
- synth.offset( last_time, delta, osc_output );
- }
- }
-
- blip_time_t time = last_time + delays [index];
- if ( time < end_time )
- {
- int delta = amp * 2 - volume;
- if ( volume )
- {
- do
- {
- delta = -delta;
- synth.offset_inline( time, delta, osc_output );
- time += period;
- }
- while ( time < end_time );
-
- oscs [index].last_amp = (delta + volume) >> 1;
- phases [index] = (delta > 0);
- }
- else
- {
- // maintain phase when silent
- int count = (end_time - time + period - 1) / period;
- phases [index] ^= count & 1;
- time += (blargg_long) count * period;
- }
- }
-
- delays [index] = time - end_time;
- }
-
- last_time = end_time;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.h
deleted file mode 100644
index 97094897..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Fme7_Apu.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Sunsoft FME-7 sound emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef NES_FME7_APU_H
-#define NES_FME7_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct fme7_apu_state_t
-{
- enum { reg_count = 14 };
- BOOST::uint8_t regs [reg_count];
- BOOST::uint8_t phases [3]; // 0 or 1
- BOOST::uint8_t latch;
- BOOST::uint16_t delays [3]; // a, b, c
-};
-
-class Nes_Fme7_Apu : private fme7_apu_state_t {
-public:
- // See Nes_Apu.h for reference
- void reset();
- void volume( double );
- void treble_eq( blip_eq_t const& );
- void output( Blip_Buffer* );
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
- void end_frame( blip_time_t );
- void save_state( fme7_apu_state_t* ) const;
- void load_state( fme7_apu_state_t const& );
-
- // Mask and addresses of registers
- enum { addr_mask = 0xE000 };
- enum { data_addr = 0xE000 };
- enum { latch_addr = 0xC000 };
-
- // (addr & addr_mask) == latch_addr
- void write_latch( int );
-
- // (addr & addr_mask) == data_addr
- void write_data( blip_time_t, int data );
-
-public:
- Nes_Fme7_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Fme7_Apu( const Nes_Fme7_Apu& );
- Nes_Fme7_Apu& operator = ( const Nes_Fme7_Apu& );
-
- static unsigned char const amp_table [16];
-
- struct {
- Blip_Buffer* output;
- int last_amp;
- } oscs [osc_count];
- blip_time_t last_time;
-
- enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff
- Blip_Synth<blip_good_quality,1> synth;
-
- void run_until( blip_time_t );
-};
-
-inline void Nes_Fme7_Apu::volume( double v )
-{
- synth.volume( 0.38 / amp_range * v ); // to do: fine-tune
-}
-
-inline void Nes_Fme7_Apu::treble_eq( blip_eq_t const& eq )
-{
- synth.treble_eq( eq );
-}
-
-inline void Nes_Fme7_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Fme7_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-inline Nes_Fme7_Apu::Nes_Fme7_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-inline void Nes_Fme7_Apu::write_latch( int data ) { latch = data; }
-
-inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data )
-{
- if ( (unsigned) latch >= reg_count )
- {
- #ifdef debug_printf
- debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
- #endif
- return;
- }
-
- run_until( time );
- regs [latch] = data;
-}
-
-inline void Nes_Fme7_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-inline void Nes_Fme7_Apu::save_state( fme7_apu_state_t* out ) const
-{
- *out = *this;
-}
-
-inline void Nes_Fme7_Apu::load_state( fme7_apu_state_t const& in )
-{
- reset();
- fme7_apu_state_t* state = this;
- *state = in;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.cpp
deleted file mode 100644
index f3235b38..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Namco_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Namco_Apu::Nes_Namco_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-void Nes_Namco_Apu::reset()
-{
- last_time = 0;
- addr_reg = 0;
-
- int i;
- for ( i = 0; i < reg_count; i++ )
- reg [i] = 0;
-
- for ( i = 0; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- osc.delay = 0;
- osc.last_amp = 0;
- osc.wave_pos = 0;
- }
-}
-
-void Nes_Namco_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-/*
-void Nes_Namco_Apu::reflect_state( Tagged_Data& data )
-{
- reflect_int16( data, BLARGG_4CHAR('A','D','D','R'), &addr_reg );
-
- static const char hex [17] = "0123456789ABCDEF";
- int i;
- for ( i = 0; i < reg_count; i++ )
- reflect_int16( data, 'RG\0\0' + hex [i >> 4] * 0x100 + hex [i & 15], &reg [i] );
-
- for ( i = 0; i < osc_count; i++ )
- {
- reflect_int32( data, BLARGG_4CHAR('D','L','Y','0') + i, &oscs [i].delay );
- reflect_int16( data, BLARGG_4CHAR('P','O','S','0') + i, &oscs [i].wave_pos );
- }
-}
-*/
-
-void Nes_Namco_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
-{
- int active_oscs = (reg [0x7F] >> 4 & 7) + 1;
- for ( int i = osc_count - active_oscs; i < osc_count; i++ )
- {
- Namco_Osc& osc = oscs [i];
- Blip_Buffer* output = osc.output;
- if ( !output )
- continue;
- output->set_modified();
-
- blip_resampled_time_t time =
- output->resampled_time( last_time ) + osc.delay;
- blip_resampled_time_t end_time = output->resampled_time( nes_end_time );
- osc.delay = 0;
- if ( time < end_time )
- {
- const BOOST::uint8_t* osc_reg = &reg [i * 8 + 0x40];
- if ( !(osc_reg [4] & 0xE0) )
- continue;
-
- int volume = osc_reg [7] & 15;
- if ( !volume )
- continue;
-
- blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
- if ( freq < 64 * active_oscs )
- continue; // prevent low frequencies from excessively delaying freq changes
- blip_resampled_time_t period =
- output->resampled_duration( 983040 ) / freq * active_oscs;
-
- int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
- if ( !wave_size )
- continue;
-
- int last_amp = osc.last_amp;
- int wave_pos = osc.wave_pos;
-
- do
- {
- // read wave sample
- int addr = wave_pos + osc_reg [6];
- int sample = reg [addr >> 1] >> (addr << 2 & 4);
- wave_pos++;
- sample = (sample & 15) * volume;
-
- // output impulse if amplitude changed
- int delta = sample - last_amp;
- if ( delta )
- {
- last_amp = sample;
- synth.offset_resampled( time, delta, output );
- }
-
- // next sample
- time += period;
- if ( wave_pos >= wave_size )
- wave_pos = 0;
- }
- while ( time < end_time );
-
- osc.wave_pos = wave_pos;
- osc.last_amp = last_amp;
- }
- osc.delay = time - end_time;
- }
-
- last_time = nes_end_time;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.h
deleted file mode 100644
index db5fea4b..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Namco_Apu.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Namco 106 sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_NAMCO_APU_H
-#define NES_NAMCO_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct namco_state_t;
-
-class Nes_Namco_Apu {
-public:
- // See Nes_Apu.h for reference.
- void volume( double );
- void treble_eq( const blip_eq_t& );
- void output( Blip_Buffer* );
- enum { osc_count = 8 };
- void osc_output( int index, Blip_Buffer* );
- void reset();
- void end_frame( blip_time_t );
-
- // Read/write data register is at 0x4800
- enum { data_reg_addr = 0x4800 };
- void write_data( blip_time_t, int );
- int read_data();
-
- // Write-only address register is at 0xF800
- enum { addr_reg_addr = 0xF800 };
- void write_addr( int );
-
- // to do: implement save/restore
- void save_state( namco_state_t* out ) const;
- void load_state( namco_state_t const& );
-
-public:
- Nes_Namco_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Namco_Apu( const Nes_Namco_Apu& );
- Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& );
-
- struct Namco_Osc {
- blargg_long delay;
- Blip_Buffer* output;
- short last_amp;
- short wave_pos;
- };
-
- Namco_Osc oscs [osc_count];
-
- blip_time_t last_time;
- int addr_reg;
-
- enum { reg_count = 0x80 };
- BOOST::uint8_t reg [reg_count];
- Blip_Synth<blip_good_quality,15> synth;
-
- BOOST::uint8_t& access();
- void run_until( blip_time_t );
-};
-/*
-struct namco_state_t
-{
- BOOST::uint8_t regs [0x80];
- BOOST::uint8_t addr;
- BOOST::uint8_t unused;
- BOOST::uint8_t positions [8];
- BOOST::uint32_t delays [8];
-};
-*/
-
-inline BOOST::uint8_t& Nes_Namco_Apu::access()
-{
- int addr = addr_reg & 0x7F;
- if ( addr_reg & 0x80 )
- addr_reg = (addr + 1) | 0x80;
- return reg [addr];
-}
-
-inline void Nes_Namco_Apu::volume( double v ) { synth.volume( 0.10 / osc_count * v ); }
-
-inline void Nes_Namco_Apu::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); }
-
-inline void Nes_Namco_Apu::write_addr( int v ) { addr_reg = v; }
-
-inline int Nes_Namco_Apu::read_data() { return access(); }
-
-inline void Nes_Namco_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Namco_Apu::write_data( blip_time_t time, int data )
-{
- run_until( time );
- access() = data;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.cpp
deleted file mode 100644
index 1ad3f59c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Nes_Osc
-
-void Nes_Osc::clock_length( int halt_mask )
-{
- if ( length_counter && !(regs [0] & halt_mask) )
- length_counter--;
-}
-
-void Nes_Envelope::clock_envelope()
-{
- int period = regs [0] & 15;
- if ( reg_written [3] ) {
- reg_written [3] = false;
- env_delay = period;
- envelope = 15;
- }
- else if ( --env_delay < 0 ) {
- env_delay = period;
- if ( envelope | (regs [0] & 0x20) )
- envelope = (envelope - 1) & 15;
- }
-}
-
-int Nes_Envelope::volume() const
-{
- return length_counter == 0 ? 0 : (regs [0] & 0x10) ? (regs [0] & 15) : envelope;
-}
-
-// Nes_Square
-
-void Nes_Square::clock_sweep( int negative_adjust )
-{
- int sweep = regs [1];
-
- if ( --sweep_delay < 0 )
- {
- reg_written [1] = true;
-
- int period = this->period();
- int shift = sweep & shift_mask;
- if ( shift && (sweep & 0x80) && period >= 8 )
- {
- int offset = period >> shift;
-
- if ( sweep & negate_flag )
- offset = negative_adjust - offset;
-
- if ( period + offset < 0x800 )
- {
- period += offset;
- // rewrite period
- regs [2] = period & 0xFF;
- regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
- }
- }
- }
-
- if ( reg_written [1] ) {
- reg_written [1] = false;
- sweep_delay = (sweep >> 4) & 7;
- }
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period )
-{
- nes_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- int count = (remain + timer_period - 1) / timer_period;
- phase = (phase + count) & (phase_range - 1);
- time += (blargg_long) count * timer_period;
- }
- return time;
-}
-
-void Nes_Square::run( nes_time_t time, nes_time_t end_time )
-{
- const int period = this->period();
- const int timer_period = (period + 1) * 2;
-
- if ( !output )
- {
- delay = maintain_phase( time + delay, end_time, timer_period ) - end_time;
- return;
- }
-
- output->set_modified();
-
- int offset = period >> (regs [1] & shift_mask);
- if ( regs [1] & negate_flag )
- offset = 0;
-
- const int volume = this->volume();
- if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
- {
- if ( last_amp ) {
- synth.offset( time, -last_amp, output );
- last_amp = 0;
- }
-
- time += delay;
- time = maintain_phase( time, end_time, timer_period );
- }
- else
- {
- // handle duty select
- int duty_select = (regs [0] >> 6) & 3;
- int duty = 1 << duty_select; // 1, 2, 4, 2
- int amp = 0;
- if ( duty_select == 3 ) {
- duty = 2; // negated 25%
- amp = volume;
- }
- if ( phase < duty )
- amp ^= volume;
-
- {
- int delta = update_amp( amp );
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- const Synth& synth = this->synth;
- int delta = amp * 2 - volume;
- int phase = this->phase;
-
- do {
- phase = (phase + 1) & (phase_range - 1);
- if ( phase == 0 || phase == duty ) {
- delta = -delta;
- synth.offset_inline( time, delta, output );
- }
- time += timer_period;
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->phase = phase;
- }
- }
-
- delay = time - end_time;
-}
-
-// Nes_Triangle
-
-void Nes_Triangle::clock_linear_counter()
-{
- if ( reg_written [3] )
- linear_counter = regs [0] & 0x7F;
- else if ( linear_counter )
- linear_counter--;
-
- if ( !(regs [0] & 0x80) )
- reg_written [3] = false;
-}
-
-inline int Nes_Triangle::calc_amp() const
-{
- int amp = phase_range - phase;
- if ( amp < 0 )
- amp = phase - (phase_range + 1);
- return amp;
-}
-
-// TODO: clean up
-inline nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period )
-{
- nes_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- int count = (remain + timer_period - 1) / timer_period;
- phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
- phase++;
- time += (blargg_long) count * timer_period;
- }
- return time;
-}
-
-void Nes_Triangle::run( nes_time_t time, nes_time_t end_time )
-{
- const int timer_period = period() + 1;
- if ( !output )
- {
- time += delay;
- delay = 0;
- if ( length_counter && linear_counter && timer_period >= 3 )
- delay = maintain_phase( time, end_time, timer_period ) - end_time;
- return;
- }
-
- output->set_modified();
-
- // to do: track phase when period < 3
- // to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
-
- int delta = update_amp( calc_amp() );
- if ( delta )
- synth.offset( time, delta, output );
-
- time += delay;
- if ( length_counter == 0 || linear_counter == 0 || timer_period < 3 )
- {
- time = end_time;
- }
- else if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
-
- int phase = this->phase;
- int volume = 1;
- if ( phase > phase_range ) {
- phase -= phase_range;
- volume = -volume;
- }
-
- do {
- if ( --phase == 0 ) {
- phase = phase_range;
- volume = -volume;
- }
- else {
- synth.offset_inline( time, volume, output );
- }
-
- time += timer_period;
- }
- while ( time < end_time );
-
- if ( volume < 0 )
- phase += phase_range;
- this->phase = phase;
- last_amp = calc_amp();
- }
- delay = time - end_time;
-}
-
-// Nes_Dmc
-
-void Nes_Dmc::reset()
-{
- address = 0;
- dac = 0;
- buf = 0;
- bits_remain = 1;
- bits = 0;
- buf_full = false;
- silence = true;
- next_irq = Nes_Apu::no_irq;
- irq_flag = false;
- irq_enabled = false;
-
- Nes_Osc::reset();
- period = 0x1AC;
-}
-
-void Nes_Dmc::recalc_irq()
-{
- nes_time_t irq = Nes_Apu::no_irq;
- if ( irq_enabled && length_counter )
- irq = apu->last_dmc_time + delay +
- ((length_counter - 1) * 8 + bits_remain - 1) * nes_time_t (period) + 1;
- if ( irq != next_irq ) {
- next_irq = irq;
- apu->irq_changed();
- }
-}
-
-int Nes_Dmc::count_reads( nes_time_t time, nes_time_t* last_read ) const
-{
- if ( last_read )
- *last_read = time;
-
- if ( length_counter == 0 )
- return 0; // not reading
-
- nes_time_t first_read = next_read_time();
- nes_time_t avail = time - first_read;
- if ( avail <= 0 )
- return 0;
-
- int count = (avail - 1) / (period * 8) + 1;
- if ( !(regs [0] & loop_flag) && count > length_counter )
- count = length_counter;
-
- if ( last_read )
- {
- *last_read = first_read + (count - 1) * (period * 8) + 1;
- check( *last_read <= time );
- check( count == count_reads( *last_read, NULL ) );
- check( count - 1 == count_reads( *last_read - 1, NULL ) );
- }
-
- return count;
-}
-
-static short const dmc_period_table [2] [16] = {
- {428, 380, 340, 320, 286, 254, 226, 214, // NTSC
- 190, 160, 142, 128, 106, 84, 72, 54},
-
- {398, 354, 316, 298, 276, 236, 210, 198, // PAL
- 176, 148, 132, 118, 98, 78, 66, 50}
-};
-
-inline void Nes_Dmc::reload_sample()
-{
- address = 0x4000 + regs [2] * 0x40;
- length_counter = regs [3] * 0x10 + 1;
-}
-
-static byte const dac_table [128] =
-{
- 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
- 15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
- 27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
- 39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
- 50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
- 59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
- 68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
- 76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
-};
-
-void Nes_Dmc::write_register( int addr, int data )
-{
- if ( addr == 0 )
- {
- period = dmc_period_table [pal_mode] [data & 15];
- irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
- irq_flag &= irq_enabled;
- recalc_irq();
- }
- else if ( addr == 1 )
- {
- int old_dac = dac;
- dac = data & 0x7F;
-
- // adjust last_amp so that "pop" amplitude will be properly non-linear
- // with respect to change in dac
- int faked_nonlinear = dac - (dac_table [dac] - dac_table [old_dac]);
- if ( !nonlinear )
- last_amp = faked_nonlinear;
- }
-}
-
-void Nes_Dmc::start()
-{
- reload_sample();
- fill_buffer();
- recalc_irq();
-}
-
-void Nes_Dmc::fill_buffer()
-{
- if ( !buf_full && length_counter )
- {
- require( prg_reader ); // prg_reader must be set
- buf = prg_reader( prg_reader_data, 0x8000u + address );
- address = (address + 1) & 0x7FFF;
- buf_full = true;
- if ( --length_counter == 0 )
- {
- if ( regs [0] & loop_flag ) {
- reload_sample();
- }
- else {
- apu->osc_enables &= ~0x10;
- irq_flag = irq_enabled;
- next_irq = Nes_Apu::no_irq;
- apu->irq_changed();
- }
- }
- }
-}
-
-void Nes_Dmc::run( nes_time_t time, nes_time_t end_time )
-{
- int delta = update_amp( dac );
- if ( !output )
- {
- silence = true;
- }
- else
- {
- output->set_modified();
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- int bits_remain = this->bits_remain;
- if ( silence && !buf_full )
- {
- int count = (end_time - time + period - 1) / period;
- bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
- time += count * period;
- }
- else
- {
- Blip_Buffer* const output = this->output;
- const int period = this->period;
- int bits = this->bits;
- int dac = this->dac;
-
- do
- {
- if ( !silence )
- {
- int step = (bits & 1) * 4 - 2;
- bits >>= 1;
- if ( unsigned (dac + step) <= 0x7F ) {
- dac += step;
- synth.offset_inline( time, step, output );
- }
- }
-
- time += period;
-
- if ( --bits_remain == 0 )
- {
- bits_remain = 8;
- if ( !buf_full ) {
- silence = true;
- }
- else {
- silence = false;
- bits = buf;
- buf_full = false;
- if ( !output )
- silence = true;
- fill_buffer();
- }
- }
- }
- while ( time < end_time );
-
- this->dac = dac;
- this->last_amp = dac;
- this->bits = bits;
- }
- this->bits_remain = bits_remain;
- }
- delay = time - end_time;
-}
-
-// Nes_Noise
-
-static short const noise_period_table [16] = {
- 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
- 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
-};
-
-void Nes_Noise::run( nes_time_t time, nes_time_t end_time )
-{
- int period = noise_period_table [regs [2] & 15];
-
- if ( !output )
- {
- // TODO: clean up
- time += delay;
- delay = time + (end_time - time + period - 1) / period * period - end_time;
- return;
- }
-
- output->set_modified();
-
- const int volume = this->volume();
- int amp = (noise & 1) ? volume : 0;
- {
- int delta = update_amp( amp );
- if ( delta )
- synth.offset( time, delta, output );
- }
-
- time += delay;
- if ( time < end_time )
- {
- const int mode_flag = 0x80;
-
- if ( !volume )
- {
- // round to next multiple of period
- time += (end_time - time + period - 1) / period * period;
-
- // approximate noise cycling while muted, by shuffling up noise register
- // to do: precise muted noise cycling?
- if ( !(regs [2] & mode_flag) ) {
- int feedback = (noise << 13) ^ (noise << 14);
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- }
- else
- {
- Blip_Buffer* const output = this->output;
-
- // using resampled time avoids conversion in synth.offset()
- blip_resampled_time_t rperiod = output->resampled_duration( period );
- blip_resampled_time_t rtime = output->resampled_time( time );
-
- int noise = this->noise;
- int delta = amp * 2 - volume;
- const int tap = (regs [2] & mode_flag ? 8 : 13);
-
- do {
- int feedback = (noise << tap) ^ (noise << 14);
- time += period;
-
- if ( (noise + 1) & 2 ) {
- // bits 0 and 1 of noise differ
- delta = -delta;
- synth.offset_resampled( rtime, delta, output );
- }
-
- rtime += rperiod;
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- while ( time < end_time );
-
- last_amp = (delta + volume) >> 1;
- this->noise = noise;
- }
- }
-
- delay = time - end_time;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.h
deleted file mode 100644
index b675bfb4..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Oscs.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Private oscillators used by Nes_Apu
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_OSCS_H
-#define NES_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Nes_Apu;
-
-struct Nes_Osc
-{
- unsigned char regs [4];
- bool reg_written [4];
- Blip_Buffer* output;
- int length_counter;// length counter (0 if unused by oscillator)
- int delay; // delay until next (potential) transition
- int last_amp; // last amplitude oscillator was outputting
-
- void clock_length( int halt_mask );
- int period() const {
- return (regs [3] & 7) * 0x100 + (regs [2] & 0xFF);
- }
- void reset() {
- delay = 0;
- last_amp = 0;
- }
- int update_amp( int amp ) {
- int delta = amp - last_amp;
- last_amp = amp;
- return delta;
- }
-};
-
-struct Nes_Envelope : Nes_Osc
-{
- int envelope;
- int env_delay;
-
- void clock_envelope();
- int volume() const;
- void reset() {
- envelope = 0;
- env_delay = 0;
- Nes_Osc::reset();
- }
-};
-
-// Nes_Square
-struct Nes_Square : Nes_Envelope
-{
- enum { negate_flag = 0x08 };
- enum { shift_mask = 0x07 };
- enum { phase_range = 8 };
- int phase;
- int sweep_delay;
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- Synth const& synth; // shared between squares
-
- Nes_Square( Synth const* s ) : synth( *s ) { }
-
- void clock_sweep( int adjust );
- void run( nes_time_t, nes_time_t );
- void reset() {
- sweep_delay = 0;
- Nes_Envelope::reset();
- }
- nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period );
-};
-
-// Nes_Triangle
-struct Nes_Triangle : Nes_Osc
-{
- enum { phase_range = 16 };
- int phase;
- int linear_counter;
- Blip_Synth<blip_med_quality,1> synth;
-
- int calc_amp() const;
- void run( nes_time_t, nes_time_t );
- void clock_linear_counter();
- void reset() {
- linear_counter = 0;
- phase = 1;
- Nes_Osc::reset();
- }
- nes_time_t maintain_phase( nes_time_t time, nes_time_t end_time,
- nes_time_t timer_period );
-};
-
-// Nes_Noise
-struct Nes_Noise : Nes_Envelope
-{
- int noise;
- Blip_Synth<blip_med_quality,1> synth;
-
- void run( nes_time_t, nes_time_t );
- void reset() {
- noise = 1 << 14;
- Nes_Envelope::reset();
- }
-};
-
-// Nes_Dmc
-struct Nes_Dmc : Nes_Osc
-{
- int address; // address of next byte to read
- int period;
- //int length_counter; // bytes remaining to play (already defined in Nes_Osc)
- int buf;
- int bits_remain;
- int bits;
- bool buf_full;
- bool silence;
-
- enum { loop_flag = 0x40 };
-
- int dac;
-
- nes_time_t next_irq;
- bool irq_enabled;
- bool irq_flag;
- bool pal_mode;
- bool nonlinear;
-
- int (*prg_reader)( void*, nes_addr_t ); // needs to be initialized to prg read function
- void* prg_reader_data;
-
- Nes_Apu* apu;
-
- Blip_Synth<blip_med_quality,1> synth;
-
- void start();
- void write_register( int, int );
- void run( nes_time_t, nes_time_t );
- void recalc_irq();
- void fill_buffer();
- void reload_sample();
- void reset();
- int count_reads( nes_time_t, nes_time_t* ) const;
- nes_time_t next_read_time() const;
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.cpp
deleted file mode 100644
index d178407c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
-
-#include "Nes_Vrc6_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nes_Vrc6_Apu::Nes_Vrc6_Apu()
-{
- output( NULL );
- volume( 1.0 );
- reset();
-}
-
-void Nes_Vrc6_Apu::reset()
-{
- last_time = 0;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc& osc = oscs [i];
- for ( int j = 0; j < reg_count; j++ )
- osc.regs [j] = 0;
- osc.delay = 0;
- osc.last_amp = 0;
- osc.phase = 1;
- osc.amp = 0;
- }
-}
-
-void Nes_Vrc6_Apu::output( Blip_Buffer* buf )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, buf );
-}
-
-void Nes_Vrc6_Apu::run_until( blip_time_t time )
-{
- require( time >= last_time );
- run_square( oscs [0], time );
- run_square( oscs [1], time );
- run_saw( time );
- last_time = time;
-}
-
-void Nes_Vrc6_Apu::write_osc( blip_time_t time, int osc_index, int reg, int data )
-{
- require( (unsigned) osc_index < osc_count );
- require( (unsigned) reg < reg_count );
-
- run_until( time );
- oscs [osc_index].regs [reg] = data;
-}
-
-void Nes_Vrc6_Apu::end_frame( blip_time_t time )
-{
- if ( time > last_time )
- run_until( time );
-
- assert( last_time >= time );
- last_time -= time;
-}
-
-void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const
-{
- assert( sizeof (vrc6_apu_state_t) == 20 );
- out->saw_amp = oscs [2].amp;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc const& osc = oscs [i];
- for ( int r = 0; r < reg_count; r++ )
- out->regs [i] [r] = osc.regs [r];
-
- out->delays [i] = osc.delay;
- out->phases [i] = osc.phase;
- }
-}
-
-void Nes_Vrc6_Apu::load_state( vrc6_apu_state_t const& in )
-{
- reset();
- oscs [2].amp = in.saw_amp;
- for ( int i = 0; i < osc_count; i++ )
- {
- Vrc6_Osc& osc = oscs [i];
- for ( int r = 0; r < reg_count; r++ )
- osc.regs [r] = in.regs [i] [r];
-
- osc.delay = in.delays [i];
- osc.phase = in.phases [i];
- }
- if ( !oscs [2].phase )
- oscs [2].phase = 1;
-}
-
-void Nes_Vrc6_Apu::run_square( Vrc6_Osc& osc, blip_time_t end_time )
-{
- Blip_Buffer* output = osc.output;
- if ( !output )
- return;
- output->set_modified();
-
- int volume = osc.regs [0] & 15;
- if ( !(osc.regs [2] & 0x80) )
- volume = 0;
-
- int gate = osc.regs [0] & 0x80;
- int duty = ((osc.regs [0] >> 4) & 7) + 1;
- int delta = ((gate || osc.phase < duty) ? volume : 0) - osc.last_amp;
- blip_time_t time = last_time;
- if ( delta )
- {
- osc.last_amp += delta;
- square_synth.offset( time, delta, output );
- }
-
- time += osc.delay;
- osc.delay = 0;
- int period = osc.period();
- if ( volume && !gate && period > 4 )
- {
- if ( time < end_time )
- {
- int phase = osc.phase;
-
- do
- {
- phase++;
- if ( phase == 16 )
- {
- phase = 0;
- osc.last_amp = volume;
- square_synth.offset( time, volume, output );
- }
- if ( phase == duty )
- {
- osc.last_amp = 0;
- square_synth.offset( time, -volume, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- osc.phase = phase;
- }
- osc.delay = time - end_time;
- }
-}
-
-void Nes_Vrc6_Apu::run_saw( blip_time_t end_time )
-{
- Vrc6_Osc& osc = oscs [2];
- Blip_Buffer* output = osc.output;
- if ( !output )
- return;
- output->set_modified();
-
- int amp = osc.amp;
- int amp_step = osc.regs [0] & 0x3F;
- blip_time_t time = last_time;
- int last_amp = osc.last_amp;
- if ( !(osc.regs [2] & 0x80) || !(amp_step | amp) )
- {
- osc.delay = 0;
- int delta = (amp >> 3) - last_amp;
- last_amp = amp >> 3;
- saw_synth.offset( time, delta, output );
- }
- else
- {
- time += osc.delay;
- if ( time < end_time )
- {
- int period = osc.period() * 2;
- int phase = osc.phase;
-
- do
- {
- if ( --phase == 0 )
- {
- phase = 7;
- amp = 0;
- }
-
- int delta = (amp >> 3) - last_amp;
- if ( delta )
- {
- last_amp = amp >> 3;
- saw_synth.offset( time, delta, output );
- }
-
- time += period;
- amp = (amp + amp_step) & 0xFF;
- }
- while ( time < end_time );
-
- osc.phase = phase;
- osc.amp = amp;
- }
-
- osc.delay = time - end_time;
- }
-
- osc.last_amp = last_amp;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.h
deleted file mode 100644
index 18722233..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nes_Vrc6_Apu.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Konami VRC6 sound chip emulator
-
-// Nes_Snd_Emu 0.1.8
-#ifndef NES_VRC6_APU_H
-#define NES_VRC6_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct vrc6_apu_state_t;
-
-class Nes_Vrc6_Apu {
-public:
- // See Nes_Apu.h for reference
- void reset();
- void volume( double );
- void treble_eq( blip_eq_t const& );
- void output( Blip_Buffer* );
- enum { osc_count = 3 };
- void osc_output( int index, Blip_Buffer* );
- void end_frame( blip_time_t );
- void save_state( vrc6_apu_state_t* ) const;
- void load_state( vrc6_apu_state_t const& );
-
- // Oscillator 0 write-only registers are at $9000-$9002
- // Oscillator 1 write-only registers are at $A000-$A002
- // Oscillator 2 write-only registers are at $B000-$B002
- enum { reg_count = 3 };
- enum { base_addr = 0x9000 };
- enum { addr_step = 0x1000 };
- void write_osc( blip_time_t, int osc, int reg, int data );
-
-public:
- Nes_Vrc6_Apu();
- BLARGG_DISABLE_NOTHROW
-private:
- // noncopyable
- Nes_Vrc6_Apu( const Nes_Vrc6_Apu& );
- Nes_Vrc6_Apu& operator = ( const Nes_Vrc6_Apu& );
-
- struct Vrc6_Osc
- {
- BOOST::uint8_t regs [3];
- Blip_Buffer* output;
- int delay;
- int last_amp;
- int phase;
- int amp; // only used by saw
-
- int period() const
- {
- return (regs [2] & 0x0F) * 0x100L + regs [1] + 1;
- }
- };
-
- Vrc6_Osc oscs [osc_count];
- blip_time_t last_time;
-
- Blip_Synth<blip_med_quality,1> saw_synth;
- Blip_Synth<blip_good_quality,1> square_synth;
-
- void run_until( blip_time_t );
- void run_square( Vrc6_Osc& osc, blip_time_t );
- void run_saw( blip_time_t );
-};
-
-struct vrc6_apu_state_t
-{
- BOOST::uint8_t regs [3] [3];
- BOOST::uint8_t saw_amp;
- BOOST::uint16_t delays [3];
- BOOST::uint8_t phases [3];
- BOOST::uint8_t unused;
-};
-
-inline void Nes_Vrc6_Apu::osc_output( int i, Blip_Buffer* buf )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = buf;
-}
-
-inline void Nes_Vrc6_Apu::volume( double v )
-{
- double const factor = 0.0967 * 2;
- saw_synth.volume( factor / 31 * v );
- square_synth.volume( factor * 0.5 / 15 * v );
-}
-
-inline void Nes_Vrc6_Apu::treble_eq( blip_eq_t const& eq )
-{
- saw_synth.treble_eq( eq );
- square_synth.treble_eq( eq );
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.cpp
deleted file mode 100644
index 6e58164c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nsf_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <stdio.h>
-
-#if !NSF_EMU_APU_ONLY
- #include "Nes_Namco_Apu.h"
- #include "Nes_Vrc6_Apu.h"
- #include "Nes_Fme7_Apu.h"
-#endif
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const vrc6_flag = 0x01;
-int const namco_flag = 0x10;
-int const fme7_flag = 0x20;
-
-long const clock_divisor = 12;
-
-Nsf_Emu::equalizer_t const Nsf_Emu::nes_eq = { -1.0, 80 };
-Nsf_Emu::equalizer_t const Nsf_Emu::famicom_eq = { -15.0, 80 };
-
-int Nsf_Emu::pcm_read( void* emu, nes_addr_t addr )
-{
- return *((Nsf_Emu*) emu)->cpu::get_code( addr );
-}
-
-Nsf_Emu::Nsf_Emu()
-{
- vrc6 = 0;
- namco = 0;
- fme7 = 0;
-
- set_type( gme_nsf_type );
- set_silence_lookahead( 6 );
- apu.dmc_reader( pcm_read, this );
- Music_Emu::set_equalizer( nes_eq );
- set_gain( 1.4 );
- memset( unmapped_code, Nes_Cpu::bad_opcode, sizeof unmapped_code );
-}
-
-Nsf_Emu::~Nsf_Emu() { unload(); }
-
-void Nsf_Emu::unload()
-{
- #if !NSF_EMU_APU_ONLY
- {
- delete vrc6;
- vrc6 = 0;
-
- delete namco;
- namco = 0;
-
- delete fme7;
- fme7 = 0;
- }
- #endif
-
- rom.clear();
- Music_Emu::unload();
-}
-
-// Track info
-
-static void copy_nsf_fields( Nsf_Emu::header_t const& h, track_info_t* out )
-{
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, author );
- GME_COPY_FIELD( h, out, copyright );
- if ( h.chip_flags )
- Gme_File::copy_field_( out->system, "Famicom" );
-}
-
-blargg_err_t Nsf_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_nsf_fields( header_, out );
- return 0;
-}
-
-static blargg_err_t check_nsf_header( void const* header )
-{
- if ( memcmp( header, "NESM\x1A", 5 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Nsf_File : Gme_Info_
-{
- Nsf_Emu::header_t h;
-
- Nsf_File() { set_type( gme_nsf_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- blargg_err_t err = in.read( &h, Nsf_Emu::header_size );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
-
- if ( h.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
- set_warning( "Uses unsupported audio expansion hardware" );
-
- set_track_count( h.track_count );
- return check_nsf_header( &h );
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_nsf_fields( h, out );
- return 0;
- }
-};
-
-static Music_Emu* new_nsf_emu () { return BLARGG_NEW Nsf_Emu ; }
-static Music_Emu* new_nsf_file() { return BLARGG_NEW Nsf_File; }
-
-static gme_type_t_ const gme_nsf_type_ = { "Nintendo NES", 0, &new_nsf_emu, &new_nsf_file, "NSF", 1 };
-gme_type_t const gme_nsf_type = &gme_nsf_type_;
-
-
-// Setup
-
-void Nsf_Emu::set_tempo_( double t )
-{
- unsigned playback_rate = get_le16( header_.ntsc_speed );
- unsigned standard_rate = 0x411A;
- clock_rate_ = 1789772.72727;
- play_period = 262 * 341L * 4 - 2; // two fewer PPU clocks every four frames
-
- if ( pal_only )
- {
- play_period = 33247 * clock_divisor;
- clock_rate_ = 1662607.125;
- standard_rate = 0x4E20;
- playback_rate = get_le16( header_.pal_speed );
- }
-
- if ( !playback_rate )
- playback_rate = standard_rate;
-
- if ( playback_rate != standard_rate || t != 1.0 )
- play_period = long (playback_rate * clock_rate_ / (1000000.0 / clock_divisor * t));
-
- apu.set_tempo( t );
-}
-
-blargg_err_t Nsf_Emu::init_sound()
-{
- if ( header_.chip_flags & ~(namco_flag | vrc6_flag | fme7_flag) )
- set_warning( "Uses unsupported audio expansion hardware" );
-
- {
- #define APU_NAMES "Square 1", "Square 2", "Triangle", "Noise", "DMC"
-
- int const count = Nes_Apu::osc_count;
- static const char* const apu_names [count] = { APU_NAMES };
- set_voice_count( count );
- set_voice_names( apu_names );
-
- }
-
- static int const types [] = {
- wave_type | 1, wave_type | 2, wave_type | 0,
- noise_type | 0, mixed_type | 1,
- wave_type | 3, wave_type | 4, wave_type | 5,
- wave_type | 6, wave_type | 7, wave_type | 8, wave_type | 9,
- wave_type |10, wave_type |11, wave_type |12, wave_type |13
- };
- set_voice_types( types ); // common to all sound chip configurations
-
- double adjusted_gain = gain();
-
- #if NSF_EMU_APU_ONLY
- {
- if ( header_.chip_flags )
- set_warning( "Uses unsupported audio expansion hardware" );
- }
- #else
- {
- if ( header_.chip_flags & (namco_flag | vrc6_flag | fme7_flag) )
- set_voice_count( Nes_Apu::osc_count + 3 );
-
- if ( header_.chip_flags & namco_flag )
- {
- namco = BLARGG_NEW Nes_Namco_Apu;
- CHECK_ALLOC( namco );
- adjusted_gain *= 0.75;
-
- int const count = Nes_Apu::osc_count + Nes_Namco_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( header_.chip_flags & vrc6_flag )
- {
- vrc6 = BLARGG_NEW Nes_Vrc6_Apu;
- CHECK_ALLOC( vrc6 );
- adjusted_gain *= 0.75;
-
- {
- int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Saw Wave", "Square 3", "Square 4"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( header_.chip_flags & namco_flag )
- {
- int const count = Nes_Apu::osc_count + Nes_Vrc6_Apu::osc_count +
- Nes_Namco_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Saw Wave", "Square 3", "Square 4",
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
- }
-
- if ( header_.chip_flags & fme7_flag )
- {
- fme7 = BLARGG_NEW Nes_Fme7_Apu;
- CHECK_ALLOC( fme7 );
- adjusted_gain *= 0.75;
-
- int const count = Nes_Apu::osc_count + Nes_Fme7_Apu::osc_count;
- static const char* const names [count] = {
- APU_NAMES,
- "Square 3", "Square 4", "Square 5"
- };
- set_voice_count( count );
- set_voice_names( names );
- }
-
- if ( namco ) namco->volume( adjusted_gain );
- if ( vrc6 ) vrc6 ->volume( adjusted_gain );
- if ( fme7 ) fme7 ->volume( adjusted_gain );
- }
- #endif
-
- apu.volume( adjusted_gain );
-
- return 0;
-}
-
-blargg_err_t Nsf_Emu::load_( Data_Reader& in )
-{
- assert( offsetof (header_t,unused [4]) == header_size );
- RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
-
- set_track_count( header_.track_count );
- RETURN_ERR( check_nsf_header( &header_ ) );
-
- if ( header_.vers != 1 )
- set_warning( "Unknown file version" );
-
- // sound and memory
- blargg_err_t err = init_sound();
- if ( err )
- return err;
-
- // set up data
- nes_addr_t load_addr = get_le16( header_.load_addr );
- init_addr = get_le16( header_.init_addr );
- play_addr = get_le16( header_.play_addr );
- if ( !load_addr ) load_addr = rom_begin;
- if ( !init_addr ) init_addr = rom_begin;
- if ( !play_addr ) play_addr = rom_begin;
- if ( load_addr < rom_begin || init_addr < rom_begin )
- {
- const char* w = warning();
- if ( !w )
- w = "Corrupt file (invalid load/init/play address)";
- return w;
- }
-
- rom.set_addr( load_addr % bank_size );
- int total_banks = rom.size() / bank_size;
-
- // bank switching
- int first_bank = (load_addr - rom_begin) / bank_size;
- for ( int i = 0; i < bank_count; i++ )
- {
- unsigned bank = i - first_bank;
- if ( bank >= (unsigned) total_banks )
- bank = 0;
- initial_banks [i] = bank;
-
- if ( header_.banks [i] )
- {
- // bank-switched
- memcpy( initial_banks, header_.banks, sizeof initial_banks );
- break;
- }
- }
-
- pal_only = (header_.speed_flags & 3) == 1;
-
- #if !NSF_EMU_EXTRA_FLAGS
- header_.speed_flags = 0;
- #endif
-
- set_tempo( tempo() );
-
- return setup_buffer( (long) (clock_rate_ + 0.5) );
-}
-
-void Nsf_Emu::update_eq( blip_eq_t const& eq )
-{
- apu.treble_eq( eq );
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->treble_eq( eq );
- if ( vrc6 ) vrc6 ->treble_eq( eq );
- if ( fme7 ) fme7 ->treble_eq( eq );
- }
- #endif
-}
-
-void Nsf_Emu::set_voice( int i, Blip_Buffer* buf, Blip_Buffer*, Blip_Buffer* )
-{
- if ( i < Nes_Apu::osc_count )
- {
- apu.osc_output( i, buf );
- return;
- }
- i -= Nes_Apu::osc_count;
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( fme7 && i < Nes_Fme7_Apu::osc_count )
- {
- fme7->osc_output( i, buf );
- return;
- }
-
- if ( vrc6 )
- {
- if ( i < Nes_Vrc6_Apu::osc_count )
- {
- // put saw first
- if ( --i < 0 )
- i = 2;
- vrc6->osc_output( i, buf );
- return;
- }
- i -= Nes_Vrc6_Apu::osc_count;
- }
-
- if ( namco && i < Nes_Namco_Apu::osc_count )
- {
- namco->osc_output( i, buf );
- return;
- }
- }
- #endif
-}
-
-// Emulation
-
-// see nes_cpu_io.h for read/write functions
-
-void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
-{
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco )
- {
- switch ( addr )
- {
- case Nes_Namco_Apu::data_reg_addr:
- namco->write_data( time(), data );
- return;
-
- case Nes_Namco_Apu::addr_reg_addr:
- namco->write_addr( data );
- return;
- }
- }
-
- if ( addr >= Nes_Fme7_Apu::latch_addr && fme7 )
- {
- switch ( addr & Nes_Fme7_Apu::addr_mask )
- {
- case Nes_Fme7_Apu::latch_addr:
- fme7->write_latch( data );
- return;
-
- case Nes_Fme7_Apu::data_addr:
- fme7->write_data( time(), data );
- return;
- }
- }
-
- if ( vrc6 )
- {
- unsigned reg = addr & (Nes_Vrc6_Apu::addr_step - 1);
- unsigned osc = unsigned (addr - Nes_Vrc6_Apu::base_addr) / Nes_Vrc6_Apu::addr_step;
- if ( osc < Nes_Vrc6_Apu::osc_count && reg < Nes_Vrc6_Apu::reg_count )
- {
- vrc6->write_osc( time(), osc, reg, data );
- return;
- }
- }
- }
- #endif
-
- // unmapped write
-
- #ifndef NDEBUG
- {
- // some games write to $8000 and $8001 repeatedly
- if ( addr == 0x8000 || addr == 0x8001 ) return;
-
- // probably namco sound mistakenly turned on in mck
- if ( addr == 0x4800 || addr == 0xF800 ) return;
-
- // memory mapper?
- if ( addr == 0xFFF8 ) return;
-
- debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
- }
- #endif
-}
-
-blargg_err_t Nsf_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( low_mem, 0, sizeof low_mem );
- memset( sram, 0, sizeof sram );
-
- cpu::reset( unmapped_code ); // also maps low_mem
- cpu::map_code( sram_addr, sizeof sram, sram );
- for ( int i = 0; i < bank_count; ++i )
- cpu_write( bank_select_addr + i, initial_banks [i] );
-
- apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
- apu.write_register( 0, 0x4015, 0x0F );
- apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->reset();
- if ( vrc6 ) vrc6 ->reset();
- if ( fme7 ) fme7 ->reset();
- }
- #endif
-
- play_ready = 4;
- play_extra = 0;
- next_play = play_period / clock_divisor;
-
- saved_state.pc = badop_addr;
- low_mem [0x1FF] = (badop_addr - 1) >> 8;
- low_mem [0x1FE] = (badop_addr - 1) & 0xFF;
- r.sp = 0xFD;
- r.pc = init_addr;
- r.a = track;
- r.x = pal_only;
-
- return 0;
-}
-
-blargg_err_t Nsf_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- while ( time() < duration )
- {
- nes_time_t end = min( (blip_time_t) next_play, duration );
- end = min( end, time() + 32767 ); // allows CPU to use 16-bit time delta
- if ( cpu::run( end ) )
- {
- if ( r.pc != badop_addr )
- {
- set_warning( "Emulation error (illegal instruction)" );
- r.pc++;
- }
- else
- {
- play_ready = 1;
- if ( saved_state.pc != badop_addr )
- {
- cpu::r = saved_state;
- saved_state.pc = badop_addr;
- }
- else
- {
- set_time( end );
- }
- }
- }
-
- if ( time() >= next_play )
- {
- nes_time_t period = (play_period + play_extra) / clock_divisor;
- play_extra = play_period - period * clock_divisor;
- next_play += period;
- if ( play_ready && !--play_ready )
- {
- check( saved_state.pc == badop_addr );
- if ( r.pc != badop_addr )
- saved_state = cpu::r;
-
- r.pc = play_addr;
- low_mem [0x100 + r.sp--] = (badop_addr - 1) >> 8;
- low_mem [0x100 + r.sp--] = (badop_addr - 1) & 0xFF;
- GME_FRAME_HOOK( this );
- }
- }
- }
-
- if ( cpu::error_count() )
- {
- cpu::clear_error_count();
- set_warning( "Emulation error (illegal instruction)" );
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- if ( next_play < 0 )
- next_play = 0;
-
- apu.end_frame( duration );
-
- #if !NSF_EMU_APU_ONLY
- {
- if ( namco ) namco->end_frame( duration );
- if ( vrc6 ) vrc6 ->end_frame( duration );
- if ( fme7 ) fme7 ->end_frame( duration );
- }
- #endif
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.h
deleted file mode 100644
index 6b213529..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nsf_Emu.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Nintendo NES/Famicom NSF music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef NSF_EMU_H
-#define NSF_EMU_H
-
-#include "Classic_Emu.h"
-#include "Nes_Apu.h"
-#include "Nes_Cpu.h"
-
-class Nsf_Emu : private Nes_Cpu, public Classic_Emu {
- typedef Nes_Cpu cpu;
-public:
- // Equalizer profiles for US NES and Japanese Famicom
- static equalizer_t const nes_eq;
- static equalizer_t const famicom_eq;
-
- // NSF file header
- enum { header_size = 0x80 };
- struct header_t
- {
- char tag [5];
- byte vers;
- byte track_count;
- byte first_track;
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- char game [32];
- char author [32];
- char copyright [32];
- byte ntsc_speed [2];
- byte banks [8];
- byte pal_speed [2];
- byte speed_flags;
- byte chip_flags;
- byte unused [4];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return header_; }
-
- static gme_type_t static_type() { return gme_nsf_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
-
-public:
- Nsf_Emu();
- ~Nsf_Emu();
- Nes_Apu* apu_() { return &apu; }
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_( Data_Reader& );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
- void unload();
-protected:
- enum { bank_count = 8 };
- byte initial_banks [bank_count];
- nes_addr_t init_addr;
- nes_addr_t play_addr;
- double clock_rate_;
- bool pal_only;
-
- // timing
- Nes_Cpu::registers_t saved_state;
- nes_time_t next_play;
- nes_time_t play_period;
- int play_extra;
- int play_ready;
-
- enum { rom_begin = 0x8000 };
- enum { bank_select_addr = 0x5FF8 };
- enum { bank_size = 0x1000 };
- Rom_Data<bank_size> rom;
-
-public: private: friend class Nes_Cpu;
- void cpu_jsr( nes_addr_t );
- int cpu_read( nes_addr_t );
- void cpu_write( nes_addr_t, int );
- void cpu_write_misc( nes_addr_t, int );
- enum { badop_addr = bank_select_addr };
-
-private:
- class Nes_Namco_Apu* namco;
- class Nes_Vrc6_Apu* vrc6;
- class Nes_Fme7_Apu* fme7;
- Nes_Apu apu;
- static int pcm_read( void*, nes_addr_t );
- blargg_err_t init_sound();
-
- header_t header_;
-
- enum { sram_addr = 0x6000 };
- byte sram [0x2000];
- byte unmapped_code [Nes_Cpu::page_size + 8];
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.cpp
deleted file mode 100644
index eb8cdadf..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Nsfe_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Nsfe_Info::Nsfe_Info() { playlist_disabled = false; }
-
-Nsfe_Info::~Nsfe_Info() { }
-
-inline void Nsfe_Info::unload()
-{
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-}
-
-// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
-void Nsfe_Info::disable_playlist( bool b )
-{
- playlist_disabled = b;
- info.track_count = playlist.size();
- if ( !info.track_count || playlist_disabled )
- info.track_count = actual_track_count_;
-}
-
-int Nsfe_Info::remap_track( int track ) const
-{
- if ( !playlist_disabled && (unsigned) track < playlist.size() )
- track = playlist [track];
- return track;
-}
-
-// Read multiple strings and separate into individual strings
-static blargg_err_t read_strs( Data_Reader& in, long size, blargg_vector<char>& chars,
- blargg_vector<const char*>& strs )
-{
- RETURN_ERR( chars.resize( size + 1 ) );
- chars [size] = 0; // in case last string doesn't have terminator
- RETURN_ERR( in.read( &chars [0], size ) );
-
- RETURN_ERR( strs.resize( 128 ) );
- int count = 0;
- for ( int i = 0; i < size; i++ )
- {
- if ( (int) strs.size() <= count )
- RETURN_ERR( strs.resize( count * 2 ) );
- strs [count++] = &chars [i];
- while ( i < size && chars [i] )
- i++;
- }
-
- return strs.resize( count );
-}
-
-// Copy in to out, where out has out_max characters allocated. Truncate to
-// out_max - 1 characters.
-static void copy_str( const char* in, char* out, int out_max )
-{
- out [out_max - 1] = 0;
- strncpy( out, in, out_max - 1 );
-}
-
-struct nsfe_info_t
-{
- byte load_addr [2];
- byte init_addr [2];
- byte play_addr [2];
- byte speed_flags;
- byte chip_flags;
- byte track_count;
- byte first_track;
- byte unused [6];
-};
-
-blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
-{
- int const nsfe_info_size = 16;
- assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size );
-
- // check header
- byte signature [4];
- blargg_err_t err = in.read( signature, sizeof signature );
- if ( err )
- return (err == in.eof_error ? gme_wrong_file_type : err);
- if ( memcmp( signature, "NSFE", 4 ) )
- return gme_wrong_file_type;
-
- // free previous info
- track_name_data.clear();
- track_names.clear();
- playlist.clear();
- track_times.clear();
-
- // default nsf header
- static const Nsf_Emu::header_t base_header =
- {
- {'N','E','S','M','\x1A'},// tag
- 1, // version
- 1, 1, // track count, first track
- {0,0},{0,0},{0,0}, // addresses
- "","","", // strings
- {0x1A, 0x41}, // NTSC rate
- {0,0,0,0,0,0,0,0}, // banks
- {0x20, 0x4E}, // PAL rate
- 0, 0, // flags
- {0,0,0,0} // unused
- };
- Nsf_Emu::header_t& header = info;
- header = base_header;
-
- // parse tags
- int phase = 0;
- while ( phase != 3 )
- {
- // read size and tag
- byte block_header [2] [4];
- RETURN_ERR( in.read( block_header, sizeof block_header ) );
- blargg_long size = get_le32( block_header [0] );
- blargg_long tag = get_le32( block_header [1] );
-
- //debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
-
- switch ( tag )
- {
- case BLARGG_4CHAR('O','F','N','I'): {
- check( phase == 0 );
- if ( size < 8 )
- return "Corrupt file";
-
- nsfe_info_t finfo;
- finfo.track_count = 1;
- finfo.first_track = 0;
-
- RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) );
- if ( size > nsfe_info_size )
- RETURN_ERR( in.skip( size - nsfe_info_size ) );
- phase = 1;
- info.speed_flags = finfo.speed_flags;
- info.chip_flags = finfo.chip_flags;
- info.track_count = finfo.track_count;
- this->actual_track_count_ = finfo.track_count;
- info.first_track = finfo.first_track;
- memcpy( info.load_addr, finfo.load_addr, 2 * 3 );
- break;
- }
-
- case BLARGG_4CHAR('K','N','A','B'):
- if ( size > (int) sizeof info.banks )
- return "Corrupt file";
- RETURN_ERR( in.read( info.banks, size ) );
- break;
-
- case BLARGG_4CHAR('h','t','u','a'): {
- blargg_vector<char> chars;
- blargg_vector<const char*> strs;
- RETURN_ERR( read_strs( in, size, chars, strs ) );
- int n = strs.size();
-
- if ( n > 3 )
- copy_str( strs [3], info.dumper, sizeof info.dumper );
-
- if ( n > 2 )
- copy_str( strs [2], info.copyright, sizeof info.copyright );
-
- if ( n > 1 )
- copy_str( strs [1], info.author, sizeof info.author );
-
- if ( n > 0 )
- copy_str( strs [0], info.game, sizeof info.game );
-
- break;
- }
-
- case BLARGG_4CHAR('e','m','i','t'):
- RETURN_ERR( track_times.resize( size / 4 ) );
- RETURN_ERR( in.read( track_times.begin(), track_times.size() * 4 ) );
- break;
-
- case BLARGG_4CHAR('l','b','l','t'):
- RETURN_ERR( read_strs( in, size, track_name_data, track_names ) );
- break;
-
- case BLARGG_4CHAR('t','s','l','p'):
- RETURN_ERR( playlist.resize( size ) );
- RETURN_ERR( in.read( &playlist [0], size ) );
- break;
-
- case BLARGG_4CHAR('A','T','A','D'): {
- check( phase == 1 );
- phase = 2;
- if ( !nsf_emu )
- {
- RETURN_ERR( in.skip( size ) );
- }
- else
- {
- Subset_Reader sub( &in, size ); // limit emu to nsf data
- Remaining_Reader rem( &header, Nsf_Emu::header_size, &sub );
- RETURN_ERR( nsf_emu->load( rem ) );
- check( rem.remain() == 0 );
- }
- break;
- }
-
- case BLARGG_4CHAR('D','N','E','N'):
- check( phase == 2 );
- phase = 3;
- break;
-
- default:
- // tags that can be skipped start with a lowercase character
- check( islower( (tag >> 24) & 0xFF ) );
- RETURN_ERR( in.skip( size ) );
- break;
- }
- }
-
- return 0;
-}
-
-blargg_err_t Nsfe_Info::track_info_( track_info_t* out, int track ) const
-{
- int remapped = remap_track( track );
- if ( (unsigned) remapped < track_times.size() )
- {
- long length = (BOOST::int32_t) get_le32( track_times [remapped] );
- if ( length > 0 )
- out->length = length;
- }
- if ( (unsigned) remapped < track_names.size() )
- Gme_File::copy_field_( out->song, track_names [remapped] );
-
- GME_COPY_FIELD( info, out, game );
- GME_COPY_FIELD( info, out, author );
- GME_COPY_FIELD( info, out, copyright );
- GME_COPY_FIELD( info, out, dumper );
- return 0;
-}
-
-Nsfe_Emu::Nsfe_Emu()
-{
- loading = false;
- set_type( gme_nsfe_type );
-}
-
-Nsfe_Emu::~Nsfe_Emu() { }
-
-void Nsfe_Emu::unload()
-{
- if ( !loading )
- info.unload(); // TODO: extremely hacky!
- Nsf_Emu::unload();
-}
-
-blargg_err_t Nsfe_Emu::track_info_( track_info_t* out, int track ) const
-{
- return info.track_info_( out, track );
-}
-
-struct Nsfe_File : Gme_Info_
-{
- Nsfe_Info info;
-
- Nsfe_File() { set_type( gme_nsfe_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- RETURN_ERR( info.load( in, 0 ) );
- info.disable_playlist( false );
- set_track_count( info.info.track_count );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int track ) const
- {
- return info.track_info_( out, track );
- }
-};
-
-static Music_Emu* new_nsfe_emu () { return BLARGG_NEW Nsfe_Emu ; }
-static Music_Emu* new_nsfe_file() { return BLARGG_NEW Nsfe_File; }
-
-static gme_type_t_ const gme_nsfe_type_ = { "Nintendo NES", 0, &new_nsfe_emu, &new_nsfe_file, "NSFE", 1 };
-gme_type_t const gme_nsfe_type = &gme_nsfe_type_;
-
-
-blargg_err_t Nsfe_Emu::load_( Data_Reader& in )
-{
- if ( loading )
- return Nsf_Emu::load_( in );
-
- // TODO: this hacky recursion-avoidance could have subtle problems
- loading = true;
- blargg_err_t err = info.load( in, this );
- loading = false;
- disable_playlist( false );
- return err;
-}
-
-void Nsfe_Emu::disable_playlist( bool b )
-{
- info.disable_playlist( b );
- set_track_count( info.info.track_count );
-}
-
-void Nsfe_Emu::clear_playlist_()
-{
- disable_playlist();
- Nsf_Emu::clear_playlist_();
-}
-
-blargg_err_t Nsfe_Emu::start_track_( int track )
-{
- return Nsf_Emu::start_track_( info.remap_track( track ) );
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.h
deleted file mode 100644
index 7971e47b..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Nsfe_Emu.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Nintendo NES/Famicom NSFE music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef NSFE_EMU_H
-#define NSFE_EMU_H
-
-#include "blargg_common.h"
-#include "Nsf_Emu.h"
-
-// Allows reading info from NSFE file without creating emulator
-class Nsfe_Info {
-public:
- blargg_err_t load( Data_Reader&, Nsf_Emu* );
-
- struct info_t : Nsf_Emu::header_t
- {
- char game [256];
- char author [256];
- char copyright [256];
- char dumper [256];
- } info;
-
- void disable_playlist( bool = true );
-
- blargg_err_t track_info_( track_info_t* out, int track ) const;
-
- int remap_track( int i ) const;
-
- void unload();
-
- Nsfe_Info();
- ~Nsfe_Info();
-private:
- blargg_vector<char> track_name_data;
- blargg_vector<const char*> track_names;
- blargg_vector<unsigned char> playlist;
- blargg_vector<char [4]> track_times;
- int actual_track_count_;
- bool playlist_disabled;
-};
-
-class Nsfe_Emu : public Nsf_Emu {
-public:
- static gme_type_t static_type() { return gme_nsfe_type; }
-
-public:
- // deprecated
- struct header_t { char tag [4]; };
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- void disable_playlist( bool = true ); // use clear_playlist()
-
-public:
- Nsfe_Emu();
- ~Nsfe_Emu();
-protected:
- blargg_err_t load_( Data_Reader& );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t start_track_( int );
- void unload();
- void clear_playlist_();
-private:
- Nsfe_Info info;
- bool loading;
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.cpp
deleted file mode 100644
index fb56f5dc..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.cpp
+++ /dev/null
@@ -1,334 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Apu.h"
-
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-int const max_frequency = 12000; // pure waves above this frequency are silenced
-
-static void gen_poly( blargg_ulong mask, int count, byte* out )
-{
- blargg_ulong n = 1;
- do
- {
- int bits = 0;
- int b = 0;
- do
- {
- // implemented using "Galios configuration"
- bits |= (n & 1) << b;
- n = (n >> 1) ^ (mask & -(n & 1));
- }
- while ( b++ < 7 );
- *out++ = bits;
- }
- while ( --count );
-}
-
-// poly5
-int const poly5_len = (1 << 5) - 1;
-blargg_ulong const poly5_mask = (1UL << poly5_len) - 1;
-blargg_ulong const poly5 = 0x167C6EA1;
-
-inline blargg_ulong run_poly5( blargg_ulong in, int shift )
-{
- return (in << shift & poly5_mask) | (in >> (poly5_len - shift));
-}
-
-#define POLY_MASK( width, tap1, tap2 ) \
- ((1UL << (width - 1 - tap1)) | (1UL << (width - 1 - tap2)))
-
-Sap_Apu_Impl::Sap_Apu_Impl()
-{
- gen_poly( POLY_MASK( 4, 1, 0 ), sizeof poly4, poly4 );
- gen_poly( POLY_MASK( 9, 5, 0 ), sizeof poly9, poly9 );
- gen_poly( POLY_MASK( 17, 5, 0 ), sizeof poly17, poly17 );
-
- if ( 0 ) // comment out to recauculate poly5 constant
- {
- byte poly5 [4];
- gen_poly( POLY_MASK( 5, 2, 0 ), sizeof poly5, poly5 );
- blargg_ulong n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L +
- poly5 [1] * 0x100L + poly5 [0];
- blargg_ulong rev = n & 1;
- for ( int i = 1; i < poly5_len; i++ )
- rev |= (n >> i & 1) << (poly5_len - i);
- debug_printf( "poly5: 0x%08lX\n", rev );
- }
-}
-
-Sap_Apu::Sap_Apu()
-{
- impl = 0;
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, 0 );
-}
-
-void Sap_Apu::reset( Sap_Apu_Impl* new_impl )
-{
- impl = new_impl;
- last_time = 0;
- poly5_pos = 0;
- poly4_pos = 0;
- polym_pos = 0;
- control = 0;
-
- for ( int i = 0; i < osc_count; i++ )
- memset( &oscs [i], 0, offsetof (osc_t,output) );
-}
-
-void Sap_Apu::calc_periods()
-{
- // 15/64 kHz clock
- int divider = 28;
- if ( this->control & 1 )
- divider = 114;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- osc_t* const osc = &oscs [i];
-
- int const osc_reload = osc->regs [0]; // cache
- blargg_long period = (osc_reload + 1) * divider;
- static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 };
- if ( this->control & fast_bits [i] )
- {
- period = osc_reload + 4;
- if ( i & 1 )
- {
- period = osc_reload * 0x100L + osc [-1].regs [0] + 7;
- if ( !(this->control & fast_bits [i - 1]) )
- period = (period - 6) * divider;
-
- if ( (osc [-1].regs [1] & 0x1F) > 0x10 )
- debug_printf( "Use of slave channel in 16-bit mode not supported\n" );
- }
- }
- osc->period = period;
- }
-}
-
-void Sap_Apu::run_until( blip_time_t end_time )
-{
- calc_periods();
- Sap_Apu_Impl* const impl = this->impl; // cache
-
- // 17/9-bit poly selection
- byte const* polym = impl->poly17;
- int polym_len = poly17_len;
- if ( this->control & 0x80 )
- {
- polym_len = poly9_len;
- polym = impl->poly9;
- }
- polym_pos %= polym_len;
-
- for ( int i = 0; i < osc_count; i++ )
- {
- osc_t* const osc = &oscs [i];
- blip_time_t time = last_time + osc->delay;
- blip_time_t const period = osc->period;
-
- // output
- Blip_Buffer* output = osc->output;
- if ( output )
- {
- output->set_modified();
-
- int const osc_control = osc->regs [1]; // cache
- int volume = (osc_control & 0x0F) * 2;
- if ( !volume || osc_control & 0x10 || // silent, DAC mode, or inaudible frequency
- ((osc_control & 0xA0) == 0xA0 && period < 1789773 / 2 / max_frequency) )
- {
- if ( !(osc_control & 0x10) )
- volume >>= 1; // inaudible frequency = half volume
-
- int delta = volume - osc->last_amp;
- if ( delta )
- {
- osc->last_amp = volume;
- impl->synth.offset( last_time, delta, output );
- }
-
- // TODO: doesn't maintain high pass flip-flop (very minor issue)
- }
- else
- {
- // high pass
- static byte const hipass_bits [osc_count] = { 1 << 2, 1 << 1, 0, 0 };
- blip_time_t period2 = 0; // unused if no high pass
- blip_time_t time2 = end_time;
- if ( this->control & hipass_bits [i] )
- {
- period2 = osc [2].period;
- time2 = last_time + osc [2].delay;
- if ( osc->invert )
- {
- // trick inner wave loop into inverting output
- osc->last_amp -= volume;
- volume = -volume;
- }
- }
-
- if ( time < end_time || time2 < end_time )
- {
- // poly source
- static byte const poly1 [] = { 0x55, 0x55 }; // square wave
- byte const* poly = poly1;
- int poly_len = 8 * sizeof poly1; // can be just 2 bits, but this is faster
- int poly_pos = osc->phase & 1;
- int poly_inc = 1;
- if ( !(osc_control & 0x20) )
- {
- poly = polym;
- poly_len = polym_len;
- poly_pos = polym_pos;
- if ( osc_control & 0x40 )
- {
- poly = impl->poly4;
- poly_len = poly4_len;
- poly_pos = poly4_pos;
- }
- poly_inc = period % poly_len;
- poly_pos = (poly_pos + osc->delay) % poly_len;
- }
- poly_inc -= poly_len; // allows more optimized inner loop below
-
- // square/poly5 wave
- blargg_ulong wave = poly5;
- check( poly5 & 1 ); // low bit is set for pure wave
- int poly5_inc = 0;
- if ( !(osc_control & 0x80) )
- {
- wave = run_poly5( wave, (osc->delay + poly5_pos) % poly5_len );
- poly5_inc = period % poly5_len;
- }
-
- // Run wave and high pass interleved with each catching up to the other.
- // Disabled high pass has no performance effect since inner wave loop
- // makes no compromise for high pass, and only runs once in that case.
- int osc_last_amp = osc->last_amp;
- do
- {
- // run high pass
- if ( time2 < time )
- {
- int delta = -osc_last_amp;
- if ( volume < 0 )
- delta += volume;
- if ( delta )
- {
- osc_last_amp += delta - volume;
- volume = -volume;
- impl->synth.offset( time2, delta, output );
- }
- }
- while ( time2 <= time ) // must advance *past* time to avoid hang
- time2 += period2;
-
- // run wave
- blip_time_t end = end_time;
- if ( end > time2 )
- end = time2;
- while ( time < end )
- {
- if ( wave & 1 )
- {
- int amp = volume & -(poly [poly_pos >> 3] >> (poly_pos & 7) & 1);
- if ( (poly_pos += poly_inc) < 0 )
- poly_pos += poly_len;
- int delta = amp - osc_last_amp;
- if ( delta )
- {
- osc_last_amp = amp;
- impl->synth.offset( time, delta, output );
- }
- }
- wave = run_poly5( wave, poly5_inc );
- time += period;
- }
- }
- while ( time < end_time || time2 < end_time );
-
- osc->phase = poly_pos;
- osc->last_amp = osc_last_amp;
- }
-
- osc->invert = 0;
- if ( volume < 0 )
- {
- // undo inversion trickery
- osc->last_amp -= volume;
- osc->invert = 1;
- }
- }
- }
-
- // maintain divider
- blip_time_t remain = end_time - time;
- if ( remain > 0 )
- {
- blargg_long count = (remain + period - 1) / period;
- osc->phase ^= count;
- time += count * period;
- }
- osc->delay = time - end_time;
- }
-
- // advance polies
- blip_time_t duration = end_time - last_time;
- last_time = end_time;
- poly4_pos = (poly4_pos + duration) % poly4_len;
- poly5_pos = (poly5_pos + duration) % poly5_len;
- polym_pos += duration; // will get %'d on next call
-}
-
-void Sap_Apu::write_data( blip_time_t time, unsigned addr, int data )
-{
- run_until( time );
- int i = (addr ^ 0xD200) >> 1;
- if ( i < osc_count )
- {
- oscs [i].regs [addr & 1] = data;
- }
- else if ( addr == 0xD208 )
- {
- control = data;
- }
- else if ( addr == 0xD209 )
- {
- oscs [0].delay = 0;
- oscs [1].delay = 0;
- oscs [2].delay = 0;
- oscs [3].delay = 0;
- }
- /*
- // TODO: are polynomials reset in this case?
- else if ( addr == 0xD20F )
- {
- if ( (data & 3) == 0 )
- polym_pos = 0;
- }
- */
-}
-
-void Sap_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- last_time -= end_time;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.h
deleted file mode 100644
index a573499c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Apu.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Atari POKEY sound chip emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SAP_APU_H
-#define SAP_APU_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-class Sap_Apu_Impl;
-
-class Sap_Apu {
-public:
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* );
-
- void reset( Sap_Apu_Impl* );
-
- enum { start_addr = 0xD200 };
- enum { end_addr = 0xD209 };
- void write_data( blip_time_t, unsigned addr, int data );
-
- void end_frame( blip_time_t );
-
-public:
- Sap_Apu();
-private:
- struct osc_t
- {
- unsigned char regs [2];
- unsigned char phase;
- unsigned char invert;
- int last_amp;
- blip_time_t delay;
- blip_time_t period; // always recalculated before use; here for convenience
- Blip_Buffer* output;
- };
- osc_t oscs [osc_count];
- Sap_Apu_Impl* impl;
- blip_time_t last_time;
- int poly5_pos;
- int poly4_pos;
- int polym_pos;
- int control;
-
- void calc_periods();
- void run_until( blip_time_t );
-
- enum { poly4_len = (1L << 4) - 1 };
- enum { poly9_len = (1L << 9) - 1 };
- enum { poly17_len = (1L << 17) - 1 };
- friend class Sap_Apu_Impl;
-};
-
-// Common tables and Blip_Synth that can be shared among multiple Sap_Apu objects
-class Sap_Apu_Impl {
-public:
- Blip_Synth<blip_good_quality,1> synth;
-
- Sap_Apu_Impl();
- void volume( double d ) { synth.volume( 1.0 / Sap_Apu::osc_count / 30 * d ); }
-
-private:
- typedef unsigned char byte;
- byte poly4 [Sap_Apu::poly4_len / 8 + 1];
- byte poly9 [Sap_Apu::poly9_len / 8 + 1];
- byte poly17 [Sap_Apu::poly17_len / 8 + 1];
- friend class Sap_Apu;
-};
-
-inline void Sap_Apu::osc_output( int i, Blip_Buffer* b )
-{
- assert( (unsigned) i < osc_count );
- oscs [i].output = b;
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.cpp
deleted file mode 100644
index 35e1b511..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.cpp
+++ /dev/null
@@ -1,1011 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Cpu.h"
-
-#include <limits.h>
-#include "blargg_endian.h"
-
-//#include "nes_cpu_log.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#define FLUSH_TIME() (void) (s.time = s_time)
-#define CACHE_TIME() (void) (s_time = s.time)
-
-#include "sap_cpu_io.h"
-
-#ifndef CPU_DONE
- #define CPU_DONE( cpu, time, result_out ) { result_out = -1; }
-#endif
-
-#include "blargg_source.h"
-
-int const st_n = 0x80;
-int const st_v = 0x40;
-int const st_r = 0x20;
-int const st_b = 0x10;
-int const st_d = 0x08;
-int const st_i = 0x04;
-int const st_z = 0x02;
-int const st_c = 0x01;
-
-void Sap_Cpu::reset( void* new_mem )
-{
- check( state == &state_ );
- state = &state_;
- mem = (uint8_t*) new_mem;
- r.status = st_i;
- r.sp = 0xFF;
- r.pc = 0;
- r.a = 0;
- r.x = 0;
- r.y = 0;
- state_.time = 0;
- state_.base = 0;
- irq_time_ = future_sap_time;
- end_time_ = future_sap_time;
-
- blargg_verify_byte_order();
-}
-
-#define TIME (s_time + s.base)
-#define READ( addr ) CPU_READ( this, (addr), TIME )
-#define WRITE( addr, data ) {CPU_WRITE( this, (addr), (data), TIME );}
-#define READ_LOW( addr ) (mem [int (addr)])
-#define WRITE_LOW( addr, data ) (void) (READ_LOW( addr ) = (data))
-#define READ_PROG( addr ) (READ_LOW( addr ))
-
-#define SET_SP( v ) (sp = ((v) + 1) | 0x100)
-#define GET_SP() ((sp - 1) & 0xFF)
-#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
-
-// even on x86, using short and unsigned char was slower
-typedef int fint16;
-typedef unsigned fuint16;
-typedef unsigned fuint8;
-typedef blargg_long fint32;
-
-bool Sap_Cpu::run( sap_time_t end_time )
-{
- bool illegal_encountered = false;
- set_end_time( end_time );
- state_t s = this->state_;
- this->state = &s;
- fint32 s_time = s.time;
- uint8_t* const mem = this->mem; // cache
-
- // registers
- fuint16 pc = r.pc;
- fuint8 a = r.a;
- fuint8 x = r.x;
- fuint8 y = r.y;
- fuint16 sp;
- SET_SP( r.sp );
-
- // status flags
- #define IS_NEG (nz & 0x8080)
-
- #define CALC_STATUS( out ) do {\
- out = status & (st_v | st_d | st_i);\
- out |= ((nz >> 8) | nz) & st_n;\
- out |= c >> 8 & st_c;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & (st_v | st_d | st_i);\
- nz = in << 8;\
- c = nz;\
- nz |= ~in & st_z;\
- } while ( 0 )
-
- fuint8 status;
- fuint16 c; // carry set if (c & 0x100) != 0
- fuint16 nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x8080) != 0
- {
- fuint8 temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-dec_clock_loop:
- s_time--;
-loop:
-
- #ifndef NDEBUG
- {
- sap_time_t correct = end_time_;
- if ( !(status & st_i) && correct > irq_time_ )
- correct = irq_time_;
- check( s.base == correct );
- }
- #endif
-
- check( (unsigned) GET_SP() < 0x100 );
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- fuint8 opcode = mem [pc];
- pc++;
- uint8_t const* instr = mem + pc;
-
- static uint8_t const clock_table [256] =
- {// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,// 0
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 1
- 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,// 2
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 3
- 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,// 4
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 5
- 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,// 6
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// 7
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// 8
- 3,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,// 9
- 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,// A
- 3,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,// B
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// C
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,// D
- 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,// E
- 3,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7 // F
- }; // 0x00 was 7
-
- fuint16 data;
- data = clock_table [opcode];
- if ( (s_time += data) >= 0 )
- goto possibly_out_of_time;
-almost_out_of_time:
-
- data = *instr;
-
- #ifdef NES_CPU_LOG_H
- nes_cpu_log( "cpu_log", pc - 1, opcode, instr [0], instr [1] );
- #endif
-
- switch ( opcode )
- {
-possibly_out_of_time:
- if ( s_time < (int) data )
- goto almost_out_of_time;
- s_time -= data;
- goto out_of_time;
-
-// Macros
-
-#define GET_MSB() (instr [1])
-#define ADD_PAGE() (pc++, data += 0x100 * GET_MSB())
-#define GET_ADDR() GET_LE16( instr )
-
-#define NO_PAGE_CROSSING( lsb )
-#define HANDLE_PAGE_CROSSING( lsb ) s_time += (lsb) >> 8;
-
-#define INC_DEC_XY( reg, n ) reg = uint8_t (nz = reg + n); goto loop;
-
-#define IND_Y( cross, out ) {\
- fuint16 temp = READ_LOW( data ) + y;\
- out = temp + 0x100 * READ_LOW( uint8_t (data + 1) );\
- cross( temp );\
- }
-
-#define IND_X( out ) {\
- fuint16 temp = data + x;\
- out = 0x100 * READ_LOW( uint8_t (temp + 1) ) + READ_LOW( uint8_t (temp) );\
- }
-
-#define ARITH_ADDR_MODES( op )\
-case op - 0x04: /* (ind,x) */\
- IND_X( data )\
- goto ptr##op;\
-case op + 0x0C: /* (ind),y */\
- IND_Y( HANDLE_PAGE_CROSSING, data )\
- goto ptr##op;\
-case op + 0x10: /* zp,X */\
- data = uint8_t (data + x);\
-case op + 0x00: /* zp */\
- data = READ_LOW( data );\
- goto imm##op;\
-case op + 0x14: /* abs,Y */\
- data += y;\
- goto ind##op;\
-case op + 0x18: /* abs,X */\
- data += x;\
-ind##op:\
- HANDLE_PAGE_CROSSING( data );\
-case op + 0x08: /* abs */\
- ADD_PAGE();\
-ptr##op:\
- FLUSH_TIME();\
- data = READ( data );\
- CACHE_TIME();\
-case op + 0x04: /* imm */\
-imm##op:
-
-// TODO: more efficient way to handle negative branch that wraps PC around
-#define BRANCH( cond )\
-{\
- fint16 offset = (BOOST::int8_t) data;\
- fuint16 extra_clock = (++pc & 0xFF) + offset;\
- if ( !(cond) ) goto dec_clock_loop;\
- pc += offset;\
- s_time += extra_clock >> 8 & 1;\
- goto loop;\
-}
-
-// Often-Used
-
- case 0xB5: // LDA zp,x
- a = nz = READ_LOW( uint8_t (data + x) );
- pc++;
- goto loop;
-
- case 0xA5: // LDA zp
- a = nz = READ_LOW( data );
- pc++;
- goto loop;
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz );
-
- case 0x20: { // JSR
- fuint16 temp = pc + 1;
- pc = GET_ADDR();
- WRITE_LOW( 0x100 | (sp - 1), temp >> 8 );
- sp = (sp - 2) | 0x100;
- WRITE_LOW( sp, temp );
- goto loop;
- }
-
- case 0x4C: // JMP abs
- pc = GET_ADDR();
- goto loop;
-
- case 0xE8: // INX
- INC_DEC_XY( x, 1 )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- ARITH_ADDR_MODES( 0xC5 ) // CMP
- nz = a - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0xF0: // BEQ
- BRANCH( !(uint8_t) nz );
-
- case 0x95: // STA zp,x
- data = uint8_t (data + x);
- case 0x85: // STA zp
- pc++;
- WRITE_LOW( data, a );
- goto loop;
-
- case 0xC8: // INY
- INC_DEC_XY( y, 1 )
-
- case 0xA8: // TAY
- y = a;
- nz = a;
- goto loop;
-
- case 0x98: // TYA
- a = y;
- nz = y;
- goto loop;
-
- case 0xAD:{// LDA abs
- unsigned addr = GET_ADDR();
- pc += 2;
- nz = READ( addr );
- a = nz;
- goto loop;
- }
-
- case 0x60: // RTS
- pc = 1 + READ_LOW( sp );
- pc += 0x100 * READ_LOW( 0x100 | (sp - 0xFF) );
- sp = (sp - 0xFE) | 0x100;
- goto loop;
-
- {
- fuint16 addr;
-
- case 0x99: // STA abs,Y
- addr = y + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x8D: // STA abs
- addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- goto sta_ptr;
-
- case 0x9D: // STA abs,X (slightly more common than STA abs)
- addr = x + GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, a );
- goto loop;
- }
- sta_ptr:
- FLUSH_TIME();
- WRITE( addr, a );
- CACHE_TIME();
- goto loop;
-
- case 0x91: // STA (ind),Y
- IND_Y( NO_PAGE_CROSSING, addr )
- pc++;
- goto sta_ptr;
-
- case 0x81: // STA (ind,X)
- IND_X( addr )
- pc++;
- goto sta_ptr;
-
- }
-
- case 0xA9: // LDA #imm
- pc++;
- a = data;
- nz = data;
- goto loop;
-
- // common read instructions
- {
- fuint16 addr;
-
- case 0xA1: // LDA (ind,X)
- IND_X( addr )
- pc++;
- goto a_nz_read_addr;
-
- case 0xB1:// LDA (ind),Y
- addr = READ_LOW( data ) + y;
- HANDLE_PAGE_CROSSING( addr );
- addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
- pc++;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xB9: // LDA abs,Y
- HANDLE_PAGE_CROSSING( data + y );
- addr = GET_ADDR() + y;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- goto a_nz_read_addr;
-
- case 0xBD: // LDA abs,X
- HANDLE_PAGE_CROSSING( data + x );
- addr = GET_ADDR() + x;
- pc += 2;
- a = nz = READ_PROG( addr );
- if ( (addr ^ 0x8000) <= 0x9FFF )
- goto loop;
- a_nz_read_addr:
- FLUSH_TIME();
- a = nz = READ( addr );
- CACHE_TIME();
- goto loop;
-
- }
-
-// Branch
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
-// Load/store
-
- case 0x94: // STY zp,x
- data = uint8_t (data + x);
- case 0x84: // STY zp
- pc++;
- WRITE_LOW( data, y );
- goto loop;
-
- case 0x96: // STX zp,y
- data = uint8_t (data + y);
- case 0x86: // STX zp
- pc++;
- WRITE_LOW( data, x );
- goto loop;
-
- case 0xB6: // LDX zp,y
- data = uint8_t (data + y);
- case 0xA6: // LDX zp
- data = READ_LOW( data );
- case 0xA2: // LDX #imm
- pc++;
- x = data;
- nz = data;
- goto loop;
-
- case 0xB4: // LDY zp,x
- data = uint8_t (data + x);
- case 0xA4: // LDY zp
- data = READ_LOW( data );
- case 0xA0: // LDY #imm
- pc++;
- y = data;
- nz = data;
- goto loop;
-
- case 0xBC: // LDY abs,X
- data += x;
- HANDLE_PAGE_CROSSING( data );
- case 0xAC:{// LDY abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- y = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- case 0xBE: // LDX abs,y
- data += y;
- HANDLE_PAGE_CROSSING( data );
- case 0xAE:{// LDX abs
- unsigned addr = data + 0x100 * GET_MSB();
- pc += 2;
- FLUSH_TIME();
- x = nz = READ( addr );
- CACHE_TIME();
- goto loop;
- }
-
- {
- fuint8 temp;
- case 0x8C: // STY abs
- temp = y;
- goto store_abs;
-
- case 0x8E: // STX abs
- temp = x;
- store_abs:
- unsigned addr = GET_ADDR();
- pc += 2;
- if ( addr <= 0x7FF )
- {
- WRITE_LOW( addr, temp );
- goto loop;
- }
- FLUSH_TIME();
- WRITE( addr, temp );
- CACHE_TIME();
- goto loop;
- }
-
-// Compare
-
- case 0xEC:{// CPX abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpx_data;
- }
-
- case 0xE4: // CPX zp
- data = READ_LOW( data );
- case 0xE0: // CPX #imm
- cpx_data:
- nz = x - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0xCC:{// CPY abs
- unsigned addr = GET_ADDR();
- pc++;
- FLUSH_TIME();
- data = READ( addr );
- CACHE_TIME();
- goto cpy_data;
- }
-
- case 0xC4: // CPY zp
- data = READ_LOW( data );
- case 0xC0: // CPY #imm
- cpy_data:
- nz = y - data;
- pc++;
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
-// Logical
-
- ARITH_ADDR_MODES( 0x25 ) // AND
- nz = (a &= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x45 ) // EOR
- nz = (a ^= data);
- pc++;
- goto loop;
-
- ARITH_ADDR_MODES( 0x05 ) // ORA
- nz = (a |= data);
- pc++;
- goto loop;
-
- case 0x2C:{// BIT abs
- unsigned addr = GET_ADDR();
- pc += 2;
- status &= ~st_v;
- nz = READ( addr );
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
- }
-
- case 0x24: // BIT zp
- nz = READ_LOW( data );
- pc++;
- status &= ~st_v;
- status |= nz & st_v;
- if ( a & nz )
- goto loop;
- nz <<= 8; // result must be zero, even if N bit is set
- goto loop;
-
-// Add/subtract
-
- ARITH_ADDR_MODES( 0xE5 ) // SBC
- case 0xEB: // unofficial equivalent
- data ^= 0xFF;
- goto adc_imm;
-
- ARITH_ADDR_MODES( 0x65 ) // ADC
- adc_imm: {
- check( !(status & st_d) );
- fint16 carry = c >> 8 & 1;
- fint16 ov = (a ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- status &= ~st_v;
- status |= ov >> 2 & 0x40;
- c = nz = a + data + carry;
- pc++;
- a = (uint8_t) nz;
- goto loop;
- }
-
-// Shift/rotate
-
- case 0x4A: // LSR A
- c = 0;
- case 0x6A: // ROR A
- nz = c >> 1 & 0x80;
- c = a << 8;
- nz |= a >> 1;
- a = nz;
- goto loop;
-
- case 0x0A: // ASL A
- nz = a << 1;
- c = nz;
- a = (uint8_t) nz;
- goto loop;
-
- case 0x2A: { // ROL A
- nz = a << 1;
- fint16 temp = c >> 8 & 1;
- c = nz;
- nz |= temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x5E: // LSR abs,X
- data += x;
- case 0x4E: // LSR abs
- c = 0;
- case 0x6E: // ROR abs
- ror_abs: {
- ADD_PAGE();
- FLUSH_TIME();
- int temp = READ( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto rotate_common;
- }
-
- case 0x3E: // ROL abs,X
- data += x;
- goto rol_abs;
-
- case 0x1E: // ASL abs,X
- data += x;
- case 0x0E: // ASL abs
- c = 0;
- case 0x2E: // ROL abs
- rol_abs:
- ADD_PAGE();
- nz = c >> 8 & 1;
- FLUSH_TIME();
- nz |= (c = READ( data ) << 1);
- rotate_common:
- pc++;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
- case 0x7E: // ROR abs,X
- data += x;
- goto ror_abs;
-
- case 0x76: // ROR zp,x
- data = uint8_t (data + x);
- goto ror_zp;
-
- case 0x56: // LSR zp,x
- data = uint8_t (data + x);
- case 0x46: // LSR zp
- c = 0;
- case 0x66: // ROR zp
- ror_zp: {
- int temp = READ_LOW( data );
- nz = (c >> 1 & 0x80) | (temp >> 1);
- c = temp << 8;
- goto write_nz_zp;
- }
-
- case 0x36: // ROL zp,x
- data = uint8_t (data + x);
- goto rol_zp;
-
- case 0x16: // ASL zp,x
- data = uint8_t (data + x);
- case 0x06: // ASL zp
- c = 0;
- case 0x26: // ROL zp
- rol_zp:
- nz = c >> 8 & 1;
- nz |= (c = READ_LOW( data ) << 1);
- goto write_nz_zp;
-
-// Increment/decrement
-
- case 0xCA: // DEX
- INC_DEC_XY( x, -1 )
-
- case 0x88: // DEY
- INC_DEC_XY( y, -1 )
-
- case 0xF6: // INC zp,x
- data = uint8_t (data + x);
- case 0xE6: // INC zp
- nz = 1;
- goto add_nz_zp;
-
- case 0xD6: // DEC zp,x
- data = uint8_t (data + x);
- case 0xC6: // DEC zp
- nz = (unsigned) -1;
- add_nz_zp:
- nz += READ_LOW( data );
- write_nz_zp:
- pc++;
- WRITE_LOW( data, nz );
- goto loop;
-
- case 0xFE: // INC abs,x
- data = x + GET_ADDR();
- goto inc_ptr;
-
- case 0xEE: // INC abs
- data = GET_ADDR();
- inc_ptr:
- nz = 1;
- goto inc_common;
-
- case 0xDE: // DEC abs,x
- data = x + GET_ADDR();
- goto dec_ptr;
-
- case 0xCE: // DEC abs
- data = GET_ADDR();
- dec_ptr:
- nz = (unsigned) -1;
- inc_common:
- FLUSH_TIME();
- nz += READ( data );
- pc += 2;
- WRITE( data, (uint8_t) nz );
- CACHE_TIME();
- goto loop;
-
-// Transfer
-
- case 0xAA: // TAX
- x = a;
- nz = a;
- goto loop;
-
- case 0x8A: // TXA
- a = x;
- nz = x;
- goto loop;
-
- case 0x9A: // TXS
- SET_SP( x ); // verified (no flag change)
- goto loop;
-
- case 0xBA: // TSX
- x = nz = GET_SP();
- goto loop;
-
-// Stack
-
- case 0x48: // PHA
- PUSH( a ); // verified
- goto loop;
-
- case 0x68: // PLA
- a = nz = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- goto loop;
-
- case 0x40:{// RTI
- fuint8 temp = READ_LOW( sp );
- pc = READ_LOW( 0x100 | (sp - 0xFF) );
- pc |= READ_LOW( 0x100 | (sp - 0xFE) ) * 0x100;
- sp = (sp - 0xFD) | 0x100;
- data = status;
- SET_STATUS( temp );
- this->r.status = status; // update externally-visible I flag
- if ( (data ^ status) & st_i )
- {
- sap_time_t new_time = end_time_;
- if ( !(status & st_i) && new_time > irq_time_ )
- new_time = irq_time_;
- blargg_long delta = s.base - new_time;
- s.base = new_time;
- s_time += delta;
- }
- goto loop;
- }
-
- case 0x28:{// PLP
- fuint8 temp = READ_LOW( sp );
- sp = (sp - 0xFF) | 0x100;
- fuint8 changed = status ^ temp;
- SET_STATUS( temp );
- if ( !(changed & st_i) )
- goto loop; // I flag didn't change
- if ( status & st_i )
- goto handle_sei;
- goto handle_cli;
- }
-
- case 0x08: { // PHP
- fuint8 temp;
- CALC_STATUS( temp );
- PUSH( temp | (st_b | st_r) );
- goto loop;
- }
-
- case 0x6C:{// JMP (ind)
- data = GET_ADDR();
- pc = READ_PROG( data );
- data = (data & 0xFF00) | ((data + 1) & 0xFF);
- pc |= 0x100 * READ_PROG( data );
- goto loop;
- }
-
- case 0x00: // BRK
- goto handle_brk;
-
-// Flags
-
- case 0x38: // SEC
- c = (unsigned) ~0;
- goto loop;
-
- case 0x18: // CLC
- c = 0;
- goto loop;
-
- case 0xB8: // CLV
- status &= ~st_v;
- goto loop;
-
- case 0xD8: // CLD
- status &= ~st_d;
- goto loop;
-
- case 0xF8: // SED
- status |= st_d;
- goto loop;
-
- case 0x58: // CLI
- if ( !(status & st_i) )
- goto loop;
- status &= ~st_i;
- handle_cli: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - irq_time_;
- if ( delta <= 0 )
- {
- if ( TIME < irq_time_ )
- goto loop;
- goto delayed_cli;
- }
- s.base = irq_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
-
- if ( delta >= s_time + 1 )
- {
- // delayed irq until after next instruction
- s.base += s_time + 1;
- s_time = -1;
- irq_time_ = s.base; // TODO: remove, as only to satisfy debug check in loop
- goto loop;
- }
- delayed_cli:
- debug_printf( "Delayed CLI not emulated\n" );
- goto loop;
- }
-
- case 0x78: // SEI
- if ( status & st_i )
- goto loop;
- status |= st_i;
- handle_sei: {
- this->r.status = status; // update externally-visible I flag
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- if ( s_time < 0 )
- goto loop;
- debug_printf( "Delayed SEI not emulated\n" );
- goto loop;
- }
-
-// Unofficial
-
- // SKW - Skip word
- case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
- HANDLE_PAGE_CROSSING( data + x );
- case 0x0C:
- pc++;
- // SKB - Skip byte
- case 0x74: case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
- case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2: case 0xF4:
- pc++;
- goto loop;
-
- // NOP
- case 0xEA: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA:
- goto loop;
-
-// Unimplemented
-
- // halt
- //case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- //case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
-
- default:
- assert( (unsigned) opcode <= 0xFF );
- illegal_encountered = true;
- pc--;
- goto stop;
- }
- assert( false );
-
- int result_;
-handle_brk:
- if ( (pc - 1) >= idle_addr )
- goto idle_done;
- pc++;
- result_ = 4;
- debug_printf( "BRK executed\n" );
-
-interrupt:
- {
- s_time += 7;
-
- WRITE_LOW( 0x100 | (sp - 1), pc >> 8 );
- WRITE_LOW( 0x100 | (sp - 2), pc );
- pc = GET_LE16( &READ_PROG( 0xFFFA ) + result_ );
-
- sp = (sp - 3) | 0x100;
- fuint8 temp;
- CALC_STATUS( temp );
- temp |= st_r;
- if ( result_ )
- temp |= st_b; // TODO: incorrectly sets B flag for IRQ
- WRITE_LOW( sp, temp );
-
- status &= ~st_d;
- status |= st_i;
- this->r.status = status; // update externally-visible I flag
-
- blargg_long delta = s.base - end_time_;
- s.base = end_time_;
- s_time += delta;
- goto loop;
- }
-
-idle_done:
- //s_time = 0;
- pc--;
- goto stop;
-out_of_time:
- pc--;
- FLUSH_TIME();
- CPU_DONE( this, TIME, result_ );
- CACHE_TIME();
- if ( result_ >= 0 )
- goto interrupt;
- if ( s_time < 0 )
- goto loop;
-
-stop:
-
- s.time = s_time;
-
- r.pc = pc;
- r.sp = GET_SP();
- r.a = a;
- r.x = x;
- r.y = y;
-
- {
- fuint8 temp;
- CALC_STATUS( temp );
- r.status = temp;
- }
-
- this->state_ = s;
- this->state = &this->state_;
-
- return illegal_encountered;
-}
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.h
deleted file mode 100644
index bde219f6..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Cpu.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Atari 6502 CPU emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SAP_CPU_H
-#define SAP_CPU_H
-
-#include "blargg_common.h"
-
-typedef blargg_long sap_time_t; // clock cycle count
-typedef unsigned sap_addr_t; // 16-bit address
-enum { future_sap_time = INT_MAX / 2 + 1 };
-
-class Sap_Cpu {
-public:
- typedef BOOST::uint8_t uint8_t;
-
- // Clear all registers and keep pointer to 64K memory passed in
- void reset( void* mem_64k );
-
- // Run until specified time is reached. Returns true if suspicious/unsupported
- // instruction was encountered at any point during run.
- bool run( sap_time_t end_time );
-
- // Registers are not updated until run() returns (except I flag in status)
- struct registers_t {
- BOOST::uint16_t pc;
- BOOST::uint8_t a;
- BOOST::uint8_t x;
- BOOST::uint8_t y;
- BOOST::uint8_t status;
- BOOST::uint8_t sp;
- };
- registers_t r;
-
- enum { idle_addr = 0xFEFF };
-
- // Time of beginning of next instruction to be executed
- sap_time_t time() const { return state->time + state->base; }
- void set_time( sap_time_t t ) { state->time = t - state->base; }
- void adjust_time( int delta ) { state->time += delta; }
-
- sap_time_t irq_time() const { return irq_time_; }
- void set_irq_time( sap_time_t );
-
- sap_time_t end_time() const { return end_time_; }
- void set_end_time( sap_time_t );
-
-public:
- Sap_Cpu() { state = &state_; }
- enum { irq_inhibit = 0x04 };
-private:
- struct state_t {
- sap_time_t base;
- sap_time_t time;
- };
- state_t* state; // points to state_ or a local copy within run()
- state_t state_;
- sap_time_t irq_time_;
- sap_time_t end_time_;
- uint8_t* mem;
-
- inline sap_time_t update_end_time( sap_time_t end, sap_time_t irq );
-};
-
-inline sap_time_t Sap_Cpu::update_end_time( sap_time_t t, sap_time_t irq )
-{
- if ( irq < t && !(r.status & irq_inhibit) ) t = irq;
- sap_time_t delta = state->base - t;
- state->base = t;
- return delta;
-}
-
-inline void Sap_Cpu::set_irq_time( sap_time_t t )
-{
- state->time += update_end_time( end_time_, (irq_time_ = t) );
-}
-
-inline void Sap_Cpu::set_end_time( sap_time_t t )
-{
- state->time += update_end_time( (end_time_ = t), irq_time_ );
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.cpp
deleted file mode 100644
index aa4ce948..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.cpp
+++ /dev/null
@@ -1,444 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Sap_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-long const base_scanline_period = 114;
-
-Sap_Emu::Sap_Emu()
-{
- set_type( gme_sap_type );
-
- static const char* const names [Sap_Apu::osc_count * 2] = {
- "Wave 1", "Wave 2", "Wave 3", "Wave 4",
- "Wave 5", "Wave 6", "Wave 7", "Wave 8",
- };
- set_voice_names( names );
-
- static int const types [Sap_Apu::osc_count * 2] = {
- wave_type | 1, wave_type | 2, wave_type | 3, wave_type | 0,
- wave_type | 5, wave_type | 6, wave_type | 7, wave_type | 4,
- };
- set_voice_types( types );
- set_silence_lookahead( 6 );
-}
-
-Sap_Emu::~Sap_Emu() { }
-
-// Track info
-
-// Returns 16 or greater if not hex
-inline int from_hex_char( int h )
-{
- h -= 0x30;
- if ( (unsigned) h > 9 )
- h = ((h - 0x11) & 0xDF) + 10;
- return h;
-}
-
-static long from_hex( byte const* in )
-{
- unsigned result = 0;
- for ( int n = 4; n--; )
- {
- int h = from_hex_char( *in++ );
- if ( h > 15 )
- return -1;
- result = result * 0x10 + h;
- }
- return result;
-}
-
-static int from_dec( byte const* in, byte const* end )
-{
- if ( in >= end )
- return -1;
-
- int n = 0;
- while ( in < end )
- {
- int dig = *in++ - '0';
- if ( (unsigned) dig > 9 )
- return -1;
- n = n * 10 + dig;
- }
- return n;
-}
-
-static void parse_string( byte const* in, byte const* end, int len, char* out )
-{
- byte const* start = in;
- if ( *in++ == '\"' )
- {
- start++;
- while ( in < end && *in != '\"' )
- in++;
- }
- else
- {
- in = end;
- }
- len = min( len - 1, int (in - start) );
- out [len] = 0;
- memcpy( out, start, len );
-}
-
-static blargg_err_t parse_info( byte const* in, long size, Sap_Emu::info_t* out )
-{
- out->track_count = 1;
- out->author [0] = 0;
- out->name [0] = 0;
- out->copyright [0] = 0;
-
- if ( size < 16 || memcmp( in, "SAP\x0D\x0A", 5 ) )
- return gme_wrong_file_type;
-
- byte const* file_end = in + size - 5;
- in += 5;
- while ( in < file_end && (in [0] != 0xFF || in [1] != 0xFF) )
- {
- byte const* line_end = in;
- while ( line_end < file_end && *line_end != 0x0D )
- line_end++;
-
- char const* tag = (char const*) in;
- while ( in < line_end && *in > ' ' )
- in++;
- int tag_len = (char const*) in - tag;
-
- while ( in < line_end && *in <= ' ' ) in++;
-
- if ( tag_len <= 0 )
- {
- // skip line
- }
- else if ( !strncmp( "INIT", tag, tag_len ) )
- {
- out->init_addr = from_hex( in );
- if ( (unsigned long) out->init_addr > 0xFFFF )
- return "Invalid init address";
- }
- else if ( !strncmp( "PLAYER", tag, tag_len ) )
- {
- out->play_addr = from_hex( in );
- if ( (unsigned long) out->play_addr > 0xFFFF )
- return "Invalid play address";
- }
- else if ( !strncmp( "MUSIC", tag, tag_len ) )
- {
- out->music_addr = from_hex( in );
- if ( (unsigned long) out->music_addr > 0xFFFF )
- return "Invalid music address";
- }
- else if ( !strncmp( "SONGS", tag, tag_len ) )
- {
- out->track_count = from_dec( in, line_end );
- if ( out->track_count <= 0 )
- return "Invalid track count";
- }
- else if ( !strncmp( "TYPE", tag, tag_len ) )
- {
- switch ( out->type = *in )
- {
- case 'C':
- case 'B':
- break;
-
- case 'D':
- return "Digimusic not supported";
-
- default:
- return "Unsupported player type";
- }
- }
- else if ( !strncmp( "STEREO", tag, tag_len ) )
- {
- out->stereo = true;
- }
- else if ( !strncmp( "FASTPLAY", tag, tag_len ) )
- {
- out->fastplay = from_dec( in, line_end );
- if ( out->fastplay <= 0 )
- return "Invalid fastplay value";
- }
- else if ( !strncmp( "AUTHOR", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->author, out->author );
- }
- else if ( !strncmp( "NAME", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->name, out->name );
- }
- else if ( !strncmp( "DATE", tag, tag_len ) )
- {
- parse_string( in, line_end, sizeof out->copyright, out->copyright );
- }
-
- in = line_end + 2;
- }
-
- if ( in [0] != 0xFF || in [1] != 0xFF )
- return "ROM data missing";
- out->rom_data = in + 2;
-
- return 0;
-}
-
-static void copy_sap_fields( Sap_Emu::info_t const& in, track_info_t* out )
-{
- Gme_File::copy_field_( out->game, in.name );
- Gme_File::copy_field_( out->author, in.author );
- Gme_File::copy_field_( out->copyright, in.copyright );
-}
-
-blargg_err_t Sap_Emu::track_info_( track_info_t* out, int ) const
-{
- copy_sap_fields( info, out );
- return 0;
-}
-
-struct Sap_File : Gme_Info_
-{
- Sap_Emu::info_t info;
-
- Sap_File() { set_type( gme_sap_type ); }
-
- blargg_err_t load_mem_( byte const* begin, long size )
- {
- RETURN_ERR( parse_info( begin, size, &info ) );
- set_track_count( info.track_count );
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- copy_sap_fields( info, out );
- return 0;
- }
-};
-
-static Music_Emu* new_sap_emu () { return BLARGG_NEW Sap_Emu ; }
-static Music_Emu* new_sap_file() { return BLARGG_NEW Sap_File; }
-
-static gme_type_t_ const gme_sap_type_ = { "Atari XL", 0, &new_sap_emu, &new_sap_file, "SAP", 1 };
-gme_type_t const gme_sap_type = &gme_sap_type_;
-
-
-// Setup
-
-blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
-{
- file_end = in + size;
-
- info.warning = 0;
- info.type = 'B';
- info.stereo = false;
- info.init_addr = -1;
- info.play_addr = -1;
- info.music_addr = -1;
- info.fastplay = 312;
- RETURN_ERR( parse_info( in, size, &info ) );
-
- set_warning( info.warning );
- set_track_count( info.track_count );
- set_voice_count( Sap_Apu::osc_count << info.stereo );
- apu_impl.volume( gain() );
-
- return setup_buffer( 1773447 );
-}
-
-void Sap_Emu::update_eq( blip_eq_t const& eq )
-{
- apu_impl.synth.treble_eq( eq );
-}
-
-void Sap_Emu::set_voice( int i, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- int i2 = i - Sap_Apu::osc_count;
- if ( i2 >= 0 )
- apu2.osc_output( i2, right );
- else
- apu.osc_output( i, (info.stereo ? left : center) );
-}
-
-// Emulation
-
-void Sap_Emu::set_tempo_( double t )
-{
- scanline_period = sap_time_t (base_scanline_period / t);
-}
-
-inline sap_time_t Sap_Emu::play_period() const { return info.fastplay * scanline_period; }
-
-void Sap_Emu::cpu_jsr( sap_addr_t addr )
-{
- check( r.sp >= 0xFE ); // catch anything trying to leave data on stack
- r.pc = addr;
- int high_byte = (idle_addr - 1) >> 8;
- if ( r.sp == 0xFE && mem.ram [0x1FF] == high_byte )
- r.sp = 0xFF; // pop extra byte off
- mem.ram [0x100 + r.sp--] = high_byte; // some routines use RTI to return
- mem.ram [0x100 + r.sp--] = high_byte;
- mem.ram [0x100 + r.sp--] = (idle_addr - 1) & 0xFF;
-}
-
-void Sap_Emu::run_routine( sap_addr_t addr )
-{
- cpu_jsr( addr );
- cpu::run( 312 * base_scanline_period * 60 );
- check( r.pc == idle_addr );
-}
-
-inline void Sap_Emu::call_init( int track )
-{
- switch ( info.type )
- {
- case 'B':
- r.a = track;
- run_routine( info.init_addr );
- break;
-
- case 'C':
- r.a = 0x70;
- r.x = info.music_addr&0xFF;
- r.y = info.music_addr >> 8;
- run_routine( info.play_addr + 3 );
- r.a = 0;
- r.x = track;
- run_routine( info.play_addr + 3 );
- break;
- }
-}
-
-blargg_err_t Sap_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
-
- memset( &mem, 0, sizeof mem );
-
- byte const* in = info.rom_data;
- while ( file_end - in >= 5 )
- {
- unsigned start = get_le16( in );
- unsigned end = get_le16( in + 2 );
- //debug_printf( "Block $%04X-$%04X\n", start, end );
- in += 4;
- if ( end < start )
- {
- set_warning( "Invalid file data block" );
- break;
- }
- long len = end - start + 1;
- if ( len > file_end - in )
- {
- set_warning( "Invalid file data block" );
- break;
- }
-
- memcpy( mem.ram + start, in, len );
- in += len;
- if ( file_end - in >= 2 && in [0] == 0xFF && in [1] == 0xFF )
- in += 2;
- }
-
- apu.reset( &apu_impl );
- apu2.reset( &apu_impl );
- cpu::reset( mem.ram );
- time_mask = 0; // disables sound during init
- call_init( track );
- time_mask = -1;
-
- next_play = play_period();
-
- return 0;
-}
-
-// Emulation
-
-// see sap_cpu_io.h for read/write functions
-
-void Sap_Emu::cpu_write_( sap_addr_t addr, int data )
-{
- if ( (addr ^ Sap_Apu::start_addr) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) )
- {
- GME_APU_HOOK( this, addr - Sap_Apu::start_addr, data );
- apu.write_data( time() & time_mask, addr, data );
- return;
- }
-
- if ( (addr ^ (Sap_Apu::start_addr + 0x10)) <= (Sap_Apu::end_addr - Sap_Apu::start_addr) &&
- info.stereo )
- {
- GME_APU_HOOK( this, addr - 0x10 - Sap_Apu::start_addr + 10, data );
- apu2.write_data( time() & time_mask, addr ^ 0x10, data );
- return;
- }
-
- if ( (addr & ~0x0010) != 0xD20F || data != 0x03 )
- debug_printf( "Unmapped write $%04X <- $%02X\n", addr, data );
-}
-
-inline void Sap_Emu::call_play()
-{
- switch ( info.type )
- {
- case 'B':
- cpu_jsr( info.play_addr );
- break;
-
- case 'C':
- cpu_jsr( info.play_addr + 6 );
- break;
- }
-}
-
-blargg_err_t Sap_Emu::run_clocks( blip_time_t& duration, int )
-{
- set_time( 0 );
- while ( time() < duration )
- {
- if ( cpu::run( duration ) || r.pc > idle_addr )
- return "Emulation error (illegal instruction)";
-
- if ( r.pc == idle_addr )
- {
- if ( next_play <= duration )
- {
- set_time( next_play );
- next_play += play_period();
- call_play();
- GME_FRAME_HOOK( this );
- }
- else
- {
- set_time( duration );
- }
- }
- }
-
- duration = time();
- next_play -= duration;
- check( next_play >= 0 );
- if ( next_play < 0 )
- next_play = 0;
- apu.end_frame( duration );
- if ( info.stereo )
- apu2.end_frame( duration );
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.h
deleted file mode 100644
index 21879447..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sap_Emu.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Atari XL/XE SAP music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SAP_EMU_H
-#define SAP_EMU_H
-
-#include "Classic_Emu.h"
-#include "Sap_Apu.h"
-#include "Sap_Cpu.h"
-
-class Sap_Emu : private Sap_Cpu, public Classic_Emu {
- typedef Sap_Cpu cpu;
-public:
- static gme_type_t static_type() { return gme_sap_type; }
-public:
- Sap_Emu();
- ~Sap_Emu();
- struct info_t {
- byte const* rom_data;
- const char* warning;
- long init_addr;
- long play_addr;
- long music_addr;
- int type;
- int track_count;
- int fastplay;
- bool stereo;
- char author [256];
- char name [256];
- char copyright [ 32];
- };
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t start_track_( int );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-public: private: friend class Sap_Cpu;
- int cpu_read( sap_addr_t );
- void cpu_write( sap_addr_t, int );
- void cpu_write_( sap_addr_t, int );
-private:
- info_t info;
-
- byte const* file_end;
- sap_time_t scanline_period;
- sap_time_t next_play;
- sap_time_t time_mask;
- Sap_Apu apu;
- Sap_Apu apu2;
-
- // large items
- struct {
- byte padding1 [0x100];
- byte ram [0x10000];
- byte padding2 [0x100];
- } mem;
- Sap_Apu_Impl apu_impl;
-
- sap_time_t play_period() const;
- void call_play();
- void cpu_jsr( sap_addr_t );
- void call_init( int track );
- void run_routine( sap_addr_t );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.cpp
deleted file mode 100644
index b41fdec4..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.cpp
+++ /dev/null
@@ -1,330 +0,0 @@
-// Sms_Snd_Emu 0.1.4. http://www.slack.net/~ant/
-
-#include "Sms_Apu.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Sms_Osc
-
-Sms_Osc::Sms_Osc()
-{
- output = 0;
- outputs [0] = 0; // always stays NULL
- outputs [1] = 0;
- outputs [2] = 0;
- outputs [3] = 0;
-}
-
-void Sms_Osc::reset()
-{
- delay = 0;
- last_amp = 0;
- volume = 0;
- output_select = 3;
- output = outputs [3];
-}
-
-// Sms_Square
-
-inline void Sms_Square::reset()
-{
- period = 0;
- phase = 0;
- Sms_Osc::reset();
-}
-
-void Sms_Square::run( blip_time_t time, blip_time_t end_time )
-{
- if ( !volume || period <= 128 )
- {
- // ignore 16kHz and higher
- if ( last_amp )
- {
- synth->offset( time, -last_amp, output );
- last_amp = 0;
- }
- time += delay;
- if ( !period )
- {
- time = end_time;
- }
- else if ( time < end_time )
- {
- // keep calculating phase
- int count = (end_time - time + period - 1) / period;
- phase = (phase + count) & 1;
- time += count * period;
- }
- }
- else
- {
- int amp = phase ? volume : -volume;
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth->offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- int delta = amp * 2;
- do
- {
- delta = -delta;
- synth->offset_inline( time, delta, output );
- time += period;
- phase ^= 1;
- }
- while ( time < end_time );
- this->last_amp = phase ? volume : -volume;
- }
- }
- delay = time - end_time;
-}
-
-// Sms_Noise
-
-static int const noise_periods [3] = { 0x100, 0x200, 0x400 };
-
-inline void Sms_Noise::reset()
-{
- period = &noise_periods [0];
- shifter = 0x8000;
- feedback = 0x9000;
- Sms_Osc::reset();
-}
-
-void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
-{
- int amp = volume;
- if ( shifter & 1 )
- amp = -amp;
-
- {
- int delta = amp - last_amp;
- if ( delta )
- {
- last_amp = amp;
- synth.offset( time, delta, output );
- }
- }
-
- time += delay;
- if ( !volume )
- time = end_time;
-
- if ( time < end_time )
- {
- Blip_Buffer* const output = this->output;
- unsigned shifter = this->shifter;
- int delta = amp * 2;
- int period = *this->period * 2;
- if ( !period )
- period = 16;
-
- do
- {
- int changed = shifter + 1;
- shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1);
- if ( changed & 2 ) // true if bits 0 and 1 differ
- {
- delta = -delta;
- synth.offset_inline( time, delta, output );
- }
- time += period;
- }
- while ( time < end_time );
-
- this->shifter = shifter;
- this->last_amp = delta >> 1;
- }
- delay = time - end_time;
-}
-
-// Sms_Apu
-
-Sms_Apu::Sms_Apu()
-{
- for ( int i = 0; i < 3; i++ )
- {
- squares [i].synth = &square_synth;
- oscs [i] = &squares [i];
- }
- oscs [3] = &noise;
-
- volume( 1.0 );
- reset();
-}
-
-Sms_Apu::~Sms_Apu()
-{
-}
-
-void Sms_Apu::volume( double vol )
-{
- vol *= 0.85 / (osc_count * 64 * 2);
- square_synth.volume( vol );
- noise.synth.volume( vol );
-}
-
-void Sms_Apu::treble_eq( const blip_eq_t& eq )
-{
- square_synth.treble_eq( eq );
- noise.synth.treble_eq( eq );
-}
-
-void Sms_Apu::osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- require( (unsigned) index < osc_count );
- require( (center && left && right) || (!center && !left && !right) );
- Sms_Osc& osc = *oscs [index];
- osc.outputs [1] = right;
- osc.outputs [2] = left;
- osc.outputs [3] = center;
- osc.output = osc.outputs [osc.output_select];
-}
-
-void Sms_Apu::output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right )
-{
- for ( int i = 0; i < osc_count; i++ )
- osc_output( i, center, left, right );
-}
-
-void Sms_Apu::reset( unsigned feedback, int noise_width )
-{
- last_time = 0;
- latch = 0;
-
- if ( !feedback || !noise_width )
- {
- feedback = 0x0009;
- noise_width = 16;
- }
- // convert to "Galios configuration"
- looped_feedback = 1 << (noise_width - 1);
- noise_feedback = 0;
- while ( noise_width-- )
- {
- noise_feedback = (noise_feedback << 1) | (feedback & 1);
- feedback >>= 1;
- }
-
- squares [0].reset();
- squares [1].reset();
- squares [2].reset();
- noise.reset();
-}
-
-void Sms_Apu::run_until( blip_time_t end_time )
-{
- require( end_time >= last_time ); // end_time must not be before previous time
-
- if ( end_time > last_time )
- {
- // run oscillators
- for ( int i = 0; i < osc_count; ++i )
- {
- Sms_Osc& osc = *oscs [i];
- if ( osc.output )
- {
- osc.output->set_modified();
- if ( i < 3 )
- squares [i].run( last_time, end_time );
- else
- noise.run( last_time, end_time );
- }
- }
-
- last_time = end_time;
- }
-}
-
-void Sms_Apu::end_frame( blip_time_t end_time )
-{
- if ( end_time > last_time )
- run_until( end_time );
-
- assert( last_time >= end_time );
- last_time -= end_time;
-}
-
-void Sms_Apu::write_ggstereo( blip_time_t time, int data )
-{
- require( (unsigned) data <= 0xFF );
-
- run_until( time );
-
- for ( int i = 0; i < osc_count; i++ )
- {
- Sms_Osc& osc = *oscs [i];
- int flags = data >> i;
- Blip_Buffer* old_output = osc.output;
- osc.output_select = (flags >> 3 & 2) | (flags & 1);
- osc.output = osc.outputs [osc.output_select];
- if ( osc.output != old_output && osc.last_amp )
- {
- if ( old_output )
- {
- old_output->set_modified();
- square_synth.offset( time, -osc.last_amp, old_output );
- }
- osc.last_amp = 0;
- }
- }
-}
-
-// volumes [i] = 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
-static unsigned char const volumes [16] = {
- 64, 50, 39, 31, 24, 19, 15, 12, 9, 7, 5, 4, 3, 2, 1, 0
-};
-
-void Sms_Apu::write_data( blip_time_t time, int data )
-{
- require( (unsigned) data <= 0xFF );
-
- run_until( time );
-
- if ( data & 0x80 )
- latch = data;
-
- int index = (latch >> 5) & 3;
- if ( latch & 0x10 )
- {
- oscs [index]->volume = volumes [data & 15];
- }
- else if ( index < 3 )
- {
- Sms_Square& sq = squares [index];
- if ( data & 0x80 )
- sq.period = (sq.period & 0xFF00) | (data << 4 & 0x00FF);
- else
- sq.period = (sq.period & 0x00FF) | (data << 8 & 0x3F00);
- }
- else
- {
- int select = data & 3;
- if ( select < 3 )
- noise.period = &noise_periods [select];
- else
- noise.period = &squares [2].period;
-
- noise.feedback = (data & 0x04) ? noise_feedback : looped_feedback;
- noise.shifter = 0x8000;
- }
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.h b/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.h
deleted file mode 100644
index 3c11a9c3..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Apu.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Sega Master System SN76489 PSG sound chip emulator
-
-// Sms_Snd_Emu 0.1.4
-#ifndef SMS_APU_H
-#define SMS_APU_H
-
-#include "Sms_Oscs.h"
-
-class Sms_Apu {
-public:
- // Set overall volume of all oscillators, where 1.0 is full volume
- void volume( double );
-
- // Set treble equalization
- void treble_eq( const blip_eq_t& );
-
- // Outputs can be assigned to a single buffer for mono output, or to three
- // buffers for stereo output (using Stereo_Buffer to do the mixing).
-
- // Assign all oscillator outputs to specified buffer(s). If buffer
- // is NULL, silences all oscillators.
- void output( Blip_Buffer* mono );
- void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
- // which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL,
- // silences oscillator.
- enum { osc_count = 4 };
- void osc_output( int index, Blip_Buffer* mono );
- void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
-
- // Reset oscillators and internal state
- void reset( unsigned noise_feedback = 0, int noise_width = 0 );
-
- // Write GameGear left/right assignment byte
- void write_ggstereo( blip_time_t, int );
-
- // Write to data port
- void write_data( blip_time_t, int );
-
- // Run all oscillators up to specified time, end current frame, then
- // start a new frame at time 0.
- void end_frame( blip_time_t );
-
-public:
- Sms_Apu();
- ~Sms_Apu();
-private:
- // noncopyable
- Sms_Apu( const Sms_Apu& );
- Sms_Apu& operator = ( const Sms_Apu& );
-
- Sms_Osc* oscs [osc_count];
- Sms_Square squares [3];
- Sms_Square::Synth square_synth; // used by squares
- blip_time_t last_time;
- int latch;
- Sms_Noise noise;
- unsigned noise_feedback;
- unsigned looped_feedback;
-
- void run_until( blip_time_t );
-};
-
-struct sms_apu_state_t
-{
- unsigned char regs [8] [2];
- unsigned char latch;
-};
-
-inline void Sms_Apu::output( Blip_Buffer* b ) { output( b, b, b ); }
-
-inline void Sms_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Oscs.h b/plugins/gme/game-music-emu-0.5.5/gme/Sms_Oscs.h
deleted file mode 100644
index 2a896fef..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Sms_Oscs.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Private oscillators used by Sms_Apu
-
-// Sms_Snd_Emu 0.1.4
-#ifndef SMS_OSCS_H
-#define SMS_OSCS_H
-
-#include "blargg_common.h"
-#include "Blip_Buffer.h"
-
-struct Sms_Osc
-{
- Blip_Buffer* outputs [4]; // NULL, right, left, center
- Blip_Buffer* output;
- int output_select;
-
- int delay;
- int last_amp;
- int volume;
-
- Sms_Osc();
- void reset();
-};
-
-struct Sms_Square : Sms_Osc
-{
- int period;
- int phase;
-
- typedef Blip_Synth<blip_good_quality,1> Synth;
- const Synth* synth;
-
- void reset();
- void run( blip_time_t, blip_time_t );
-};
-
-struct Sms_Noise : Sms_Osc
-{
- const int* period;
- unsigned shifter;
- unsigned feedback;
-
- typedef Blip_Synth<blip_med_quality,1> Synth;
- Synth synth;
-
- void reset();
- void run( blip_time_t, blip_time_t );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.cpp
deleted file mode 100644
index d169b388..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.cpp
+++ /dev/null
@@ -1,489 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Snes_Spc.h"
-
-#include <string.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// always in the future (CPU time can go over 0, but not by this much)
-int const timer_disabled_time = 127;
-
-Snes_Spc::Snes_Spc() : dsp( mem.ram ), cpu( this, mem.ram )
-{
- set_tempo( 1.0 );
-
- // Put STOP instruction around memory to catch PC underflow/overflow.
- memset( mem.padding1, 0xFF, sizeof mem.padding1 );
- memset( mem.padding2, 0xFF, sizeof mem.padding2 );
-
- // A few tracks read from the last four bytes of IPL ROM
- boot_rom [sizeof boot_rom - 2] = 0xC0;
- boot_rom [sizeof boot_rom - 1] = 0xFF;
- memset( boot_rom, 0, sizeof boot_rom - 2 );
-}
-
-void Snes_Spc::set_tempo( double t )
-{
- int unit = (int) (16.0 / t + 0.5);
-
- timer [0].divisor = unit * 8; // 8 kHz
- timer [1].divisor = unit * 8; // 8 kHz
- timer [2].divisor = unit; // 64 kHz
-}
-
-// Load
-
-void Snes_Spc::set_ipl_rom( void const* in )
-{
- memcpy( boot_rom, in, sizeof boot_rom );
-}
-
-blargg_err_t Snes_Spc::load_spc( const void* data, long size )
-{
- struct spc_file_t {
- char signature [27];
- char unused [10];
- uint8_t pc [2];
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- char unused2 [212];
- uint8_t ram [0x10000];
- uint8_t dsp [128];
- uint8_t ipl_rom [128];
- };
- assert( offsetof (spc_file_t,ipl_rom) == spc_file_size );
-
- const spc_file_t* spc = (spc_file_t const*) data;
-
- if ( size < spc_file_size )
- return "Not an SPC file";
-
- if ( strncmp( spc->signature, "SNES-SPC700 Sound File Data", 27 ) != 0 )
- return "Not an SPC file";
-
- registers_t regs;
- regs.pc = spc->pc [1] * 0x100 + spc->pc [0];
- regs.a = spc->a;
- regs.x = spc->x;
- regs.y = spc->y;
- regs.status = spc->status;
- regs.sp = spc->sp;
-
- if ( (unsigned long) size >= sizeof *spc )
- set_ipl_rom( spc->ipl_rom );
-
- const char* error = load_state( regs, spc->ram, spc->dsp );
-
- echo_accessed = false;
-
- return error;
-}
-
-void Snes_Spc::clear_echo()
-{
- if ( !(dsp.read( 0x6C ) & 0x20) )
- {
- unsigned addr = 0x100 * dsp.read( 0x6D );
- size_t size = 0x800 * dsp.read( 0x7D );
- memset( mem.ram + addr, 0xFF, min( size, sizeof mem.ram - addr ) );
- }
-}
-
-// Handle other file formats (emulator save states) in user code, not here.
-
-blargg_err_t Snes_Spc::load_state( const registers_t& cpu_state, const void* new_ram,
- const void* dsp_state )
-{
- // cpu
- cpu.r = cpu_state;
-
- // Allow DSP to generate one sample before code starts
- // (Tengai Makyo Zero, Tenjin's Table Toss first notes are lost since it
- // clears KON 31 cycles from starting execution. It works on the SNES
- // since the SPC player adds a few extra cycles delay after restoring
- // KON from the DSP registers at the end of an SPC file).
- extra_cycles = 32;
-
- // ram
- memcpy( mem.ram, new_ram, sizeof mem.ram );
- memcpy( extra_ram, mem.ram + rom_addr, sizeof extra_ram );
-
- // boot rom (have to force enable_rom() to update it)
- rom_enabled = !(mem.ram [0xF1] & 0x80);
- enable_rom( !rom_enabled );
-
- // dsp
- dsp.reset();
- int i;
- for ( i = 0; i < Spc_Dsp::register_count; i++ )
- dsp.write( i, ((uint8_t const*) dsp_state) [i] );
-
- // timers
- for ( i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
-
- t.next_tick = 0;
- t.enabled = (mem.ram [0xF1] >> i) & 1;
- if ( !t.enabled )
- t.next_tick = timer_disabled_time;
- t.count = 0;
- t.counter = mem.ram [0xFD + i] & 15;
-
- int p = mem.ram [0xFA + i];
- t.period = p ? p : 0x100;
- }
-
- // Handle registers which already give 0 when read by setting RAM and not changing it.
- // Put STOP instruction in registers which can be read, to catch attempted CPU execution.
- mem.ram [0xF0] = 0;
- mem.ram [0xF1] = 0;
- mem.ram [0xF3] = 0xFF;
- mem.ram [0xFA] = 0;
- mem.ram [0xFB] = 0;
- mem.ram [0xFC] = 0;
- mem.ram [0xFD] = 0xFF;
- mem.ram [0xFE] = 0xFF;
- mem.ram [0xFF] = 0xFF;
-
- return 0; // success
-}
-
-// Hardware
-
-// Current time starts negative and ends at 0
-inline spc_time_t Snes_Spc::time() const
-{
- return -cpu.remain();
-}
-
-// Keep track of next time to run and avoid a function call if it hasn't been reached.
-
-// Timers
-
-void Snes_Spc::Timer::run_until_( spc_time_t time )
-{
- if ( !enabled )
- debug_printf( "next_tick: %ld, time: %ld", (long) next_tick, (long) time );
- assert( enabled ); // when disabled, next_tick should always be in the future
-
- int elapsed = ((time - next_tick) / divisor) + 1;
- next_tick += elapsed * divisor;
-
- elapsed += count;
- if ( elapsed >= period ) // avoid unnecessary division
- {
- int n = elapsed / period;
- elapsed -= n * period;
- counter = (counter + n) & 15;
- }
- count = elapsed;
-}
-
-// DSP
-
-const int clocks_per_sample = 32; // 1.024 MHz CPU clock / 32000 samples per second
-
-void Snes_Spc::run_dsp_( spc_time_t time )
-{
- int count = ((time - next_dsp) >> 5) + 1; // divide by clocks_per_sample
- sample_t* buf = sample_buf;
- if ( buf ) {
- sample_buf = buf + count * 2; // stereo
- assert( sample_buf <= buf_end );
- }
- next_dsp += count * clocks_per_sample;
- dsp.run( count, buf );
-}
-
-inline void Snes_Spc::run_dsp( spc_time_t time )
-{
- if ( time >= next_dsp )
- run_dsp_( time );
-}
-
-// Debug-only check for read/write within echo buffer, since this might result in
-// inaccurate emulation due to the DSP not being caught up to the present.
-inline void Snes_Spc::check_for_echo_access( spc_addr_t addr )
-{
- if ( !echo_accessed && !(dsp.read( 0x6C ) & 0x20) )
- {
- // ** If echo accesses are found that require running the DSP, cache
- // the start and end address on DSP writes to speed up checking.
-
- unsigned start = 0x100 * dsp.read( 0x6D );
- unsigned end = start + 0x800 * dsp.read( 0x7D );
- if ( start <= addr && addr < end ) {
- echo_accessed = true;
- debug_printf( "Read/write at $%04X within echo buffer\n", (unsigned) addr );
- }
- }
-}
-
-// Read
-
-int Snes_Spc::read( spc_addr_t addr )
-{
- int result = mem.ram [addr];
-
- if ( (rom_addr <= addr && addr < 0xFFFC || addr >= 0xFFFE) && rom_enabled )
- debug_printf( "Read from ROM: %04X -> %02X\n", addr, result );
-
- if ( unsigned (addr - 0xF0) < 0x10 )
- {
- assert( 0xF0 <= addr && addr <= 0xFF );
-
- // counters
- int i = addr - 0xFD;
- if ( i >= 0 )
- {
- Timer& t = timer [i];
- t.run_until( time() );
- int old = t.counter;
- t.counter = 0;
- return old;
- }
-
- // dsp
- if ( addr == 0xF3 )
- {
- run_dsp( time() );
- if ( mem.ram [0xF2] >= Spc_Dsp::register_count )
- debug_printf( "DSP read from $%02X\n", (int) mem.ram [0xF2] );
- return dsp.read( mem.ram [0xF2] & 0x7F );
- }
-
- if ( addr == 0xF0 || addr == 0xF1 || addr == 0xF8 ||
- addr == 0xF9 || addr == 0xFA )
- debug_printf( "Read from register $%02X\n", (int) addr );
-
- // Registers which always read as 0 are handled by setting mem.ram [reg] to 0
- // at startup then never changing that value.
-
- check(( check_for_echo_access( addr ), true ));
- }
-
- return result;
-}
-
-
-// Write
-
-void Snes_Spc::enable_rom( bool enable )
-{
- if ( rom_enabled != enable )
- {
- rom_enabled = enable;
- memcpy( mem.ram + rom_addr, (enable ? boot_rom : extra_ram), rom_size );
- // TODO: ROM can still get overwritten when DSP writes to echo buffer
- }
-}
-
-void Snes_Spc::write( spc_addr_t addr, int data )
-{
- // first page is very common
- if ( addr < 0xF0 ) {
- mem.ram [addr] = (uint8_t) data;
- }
- else switch ( addr )
- {
- // RAM
- default:
- check(( check_for_echo_access( addr ), true ));
- if ( addr < rom_addr ) {
- mem.ram [addr] = (uint8_t) data;
- }
- else {
- extra_ram [addr - rom_addr] = (uint8_t) data;
- if ( !rom_enabled )
- mem.ram [addr] = (uint8_t) data;
- }
- break;
-
- // DSP
- //case 0xF2: // mapped to RAM
- case 0xF3: {
- run_dsp( time() );
- int reg = mem.ram [0xF2];
- if ( next_dsp > 0 ) {
- // skip mode
-
- // key press
- if ( reg == 0x4C )
- keys_pressed |= data & ~dsp.read( 0x5C );
-
- // key release
- if ( reg == 0x5C ) {
- keys_released |= data;
- keys_pressed &= ~data;
- }
- }
- if ( reg < Spc_Dsp::register_count ) {
- dsp.write( reg, data );
- }
- else {
- debug_printf( "DSP write to $%02X\n", (int) reg );
- }
- break;
- }
-
- case 0xF0: // Test register
- debug_printf( "Wrote $%02X to $F0\n", (int) data );
- break;
-
- // Config
- case 0xF1:
- {
- // timers
- for ( int i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
- if ( !(data & (1 << i)) ) {
- t.enabled = 0;
- t.next_tick = timer_disabled_time;
- }
- else if ( !t.enabled ) {
- // just enabled
- t.enabled = 1;
- t.counter = 0;
- t.count = 0;
- t.next_tick = time();
- }
- }
-
- // port clears
- if ( data & 0x10 ) {
- mem.ram [0xF4] = 0;
- mem.ram [0xF5] = 0;
- }
- if ( data & 0x20 ) {
- mem.ram [0xF6] = 0;
- mem.ram [0xF7] = 0;
- }
-
- enable_rom( (data & 0x80) != 0 );
-
- break;
- }
-
- // Ports
- case 0xF4:
- case 0xF5:
- case 0xF6:
- case 0xF7:
- // to do: handle output ports
- break;
-
- //case 0xF8: // verified on SNES that these are read/write (RAM)
- //case 0xF9:
-
- // Timers
- case 0xFA:
- case 0xFB:
- case 0xFC: {
- Timer& t = timer [addr - 0xFA];
- if ( (t.period & 0xFF) != data ) {
- t.run_until( time() );
- t.period = data ? data : 0x100;
- }
- break;
- }
-
- // Counters (cleared on write)
- case 0xFD:
- case 0xFE:
- case 0xFF:
- debug_printf( "Wrote to counter $%02X\n", (int) addr );
- timer [addr - 0xFD].counter = 0;
- break;
- }
-}
-
-// Play
-
-blargg_err_t Snes_Spc::skip( long count )
-{
- if ( count > 4 * 32000L )
- {
- // don't run DSP for long durations (2-3 times faster)
-
- const long sync_count = 32000L * 2;
-
- // keep track of any keys pressed/released (and not subsequently released)
- keys_pressed = 0;
- keys_released = 0;
- // sentinel tells play to ignore DSP
- RETURN_ERR( play( count - sync_count, skip_sentinel ) );
-
- // press/release keys now
- dsp.write( 0x5C, keys_released & ~keys_pressed );
- dsp.write( 0x4C, keys_pressed );
-
- clear_echo();
-
- // play the last few seconds normally to help synchronize DSP
- count = sync_count;
- }
-
- return play( count );
-}
-
-blargg_err_t Snes_Spc::play( long count, sample_t* out )
-{
- require( count % 2 == 0 ); // output is always in pairs of samples
-
- // CPU time() runs from -duration to 0
- spc_time_t duration = (count / 2) * clocks_per_sample;
-
- // DSP output is made on-the-fly when the CPU reads/writes DSP registers
- sample_buf = out;
- buf_end = out + (out && out != skip_sentinel ? count : 0);
- next_dsp = (out == skip_sentinel) ? clocks_per_sample : -duration + clocks_per_sample;
-
- // Localize timer next_tick times and run them to the present to prevent a running
- // but ignored timer's next_tick from getting too far behind and overflowing.
- for ( int i = 0; i < timer_count; i++ )
- {
- Timer& t = timer [i];
- if ( t.enabled )
- {
- t.next_tick -= duration;
- t.run_until( -duration );
- }
- }
-
- // Run CPU for duration, reduced by any extra cycles from previous run
- int elapsed = cpu.run( duration - extra_cycles );
- if ( elapsed > 0 )
- {
- debug_printf( "Unhandled instruction $%02X, pc = $%04X\n",
- (int) cpu.read( cpu.r.pc ), (unsigned) cpu.r.pc );
- return "Emulation error (illegal/unsupported instruction)";
- }
- extra_cycles = -elapsed;
-
- // Catch DSP up to present.
- run_dsp( 0 );
- if ( out ) {
- assert( next_dsp == clocks_per_sample );
- assert( out == skip_sentinel || sample_buf - out == count );
- }
- buf_end = 0;
-
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.h b/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.h
deleted file mode 100644
index 1df51613..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Snes_Spc.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Super Nintendo (SNES) SPC-700 APU Emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SNES_SPC_H
-#define SNES_SPC_H
-
-#include "blargg_common.h"
-#include "Spc_Cpu.h"
-#include "Spc_Dsp.h"
-
-class Snes_Spc {
-public:
-
- // Load copy of SPC data into emulator. Clear echo buffer if 'clear_echo' is true.
- enum { spc_file_size = 0x10180 };
- blargg_err_t load_spc( const void* spc, long spc_size );
-
- // Generate 'count' samples and optionally write to 'buf'. Count must be even.
- // Sample output is 16-bit 32kHz, signed stereo pairs with the left channel first.
- typedef short sample_t;
- blargg_err_t play( long count, sample_t* buf = NULL );
-
-// Optional functionality
-
- // Load copy of state into emulator.
- typedef Spc_Cpu::registers_t registers_t;
- blargg_err_t load_state( const registers_t& cpu_state, const void* ram_64k,
- const void* dsp_regs_128 );
-
- // Clear echo buffer, useful because many tracks have junk in the buffer.
- void clear_echo();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { voice_count = Spc_Dsp::voice_count };
- void mute_voices( int mask );
-
- // Skip forward by the specified number of samples (64000 samples = 1 second)
- blargg_err_t skip( long count );
-
- // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped the
- // 16-bit sample range.
- void set_gain( double );
-
- // If true, prevent channels and global volumes from being phase-negated
- void disable_surround( bool disable = true );
-
- // Set 128 bytes to use for IPL boot ROM. Makes copy. Default is zero filled,
- // to avoid including copyrighted code from the SPC-700.
- void set_ipl_rom( const void* );
-
- void set_tempo( double );
-
-public:
- Snes_Spc();
- typedef BOOST::uint8_t uint8_t;
-private:
- // timers
- struct Timer
- {
- spc_time_t next_tick;
- int period;
- int count;
- int divisor;
- int enabled;
- int counter;
-
- void run_until_( spc_time_t );
- void run_until( spc_time_t time )
- {
- if ( time >= next_tick )
- run_until_( time );
- }
- };
- enum { timer_count = 3 };
- Timer timer [timer_count];
-
- // hardware
- int extra_cycles;
- spc_time_t time() const;
- int read( spc_addr_t );
- void write( spc_addr_t, int );
- friend class Spc_Cpu;
-
- // dsp
- sample_t* sample_buf;
- sample_t* buf_end; // to do: remove this once possible bug resolved
- spc_time_t next_dsp;
- Spc_Dsp dsp;
- int keys_pressed;
- int keys_released;
- sample_t skip_sentinel [1]; // special value for play() passed by skip()
- void run_dsp( spc_time_t );
- void run_dsp_( spc_time_t );
- bool echo_accessed;
- void check_for_echo_access( spc_addr_t );
-
- // boot rom
- enum { rom_size = 64 };
- enum { rom_addr = 0xFFC0 };
- bool rom_enabled;
- void enable_rom( bool );
-
- // CPU and RAM (at end because it's large)
- Spc_Cpu cpu;
- uint8_t extra_ram [rom_size];
- struct {
- // padding to catch jumps before beginning or past end
- uint8_t padding1 [0x100];
- uint8_t ram [0x10000];
- uint8_t padding2 [0x100];
- } mem;
- uint8_t boot_rom [rom_size];
-};
-
-inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
-
-inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
-
-inline void Snes_Spc::set_gain( double v ) { dsp.set_gain( v ); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.cpp
deleted file mode 100644
index 8b61a455..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.cpp
+++ /dev/null
@@ -1,1062 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Spc_Cpu.h"
-
-#include "blargg_endian.h"
-#include "Snes_Spc.h"
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-// Several instructions are commented out (or not even implemented). These aren't
-// used by the SPC files tested.
-
-// Optimize performance for the most common instructions, and size for the rest:
-//
-// 15% 0xF0 BEQ rel
-// 8% 0xE4 MOV A,dp
-// 4% 0xF5 MOV A,abs+X
-// 4% 0xD0 BNE rel
-// 4% 0x6F RET
-// 4% 0x3F CALL addr
-// 4% 0xF4 MOV A,dp+X
-// 3% 0xC4 MOV dp,A
-// 2% 0xEB MOV Y,dp
-// 2% 0x3D INC X
-// 2% 0xF6 MOV A,abs+Y
-// (1% and below not shown)
-
-Spc_Cpu::Spc_Cpu( Snes_Spc* e, uint8_t* ram_in ) : ram( ram_in ), emu( *e )
-{
- remain_ = 0;
- assert( INT_MAX >= 0x7FFFFFFF ); // requires 32-bit int
- blargg_verify_byte_order();
-}
-
-#define READ( addr ) (emu.read( addr ))
-#define WRITE( addr, value ) (emu.write( addr, value ))
-
-#define READ_DP( addr ) READ( (addr) + dp )
-#define WRITE_DP( addr, value ) WRITE( (addr) + dp, value )
-
-#define READ_PROG( addr ) (ram [addr])
-#define READ_PROG16( addr ) GET_LE16( &READ_PROG( addr ) )
-
-int Spc_Cpu::read( spc_addr_t addr )
-{
- return READ( addr );
-}
-
-void Spc_Cpu::write( spc_addr_t addr, int data )
-{
- WRITE( addr, data );
-}
-
-// Cycle table derived from text copy of SPC-700 manual (using regular expressions)
-static unsigned char const cycle_table [0x100] = {
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,6,8, // 0
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,4,6, // 1
- 2,8,4,5,3,4,3,6,2,6,5,4,5,4,5,4, // 2
- 2,8,4,5,4,5,5,6,5,5,6,5,2,2,3,8, // 3
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,6,6, // 4
- 2,8,4,5,4,5,5,6,5,5,4,5,2,2,4,3, // 5
- 2,8,4,5,3,4,3,6,2,6,4,4,5,4,5,5, // 6
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,6, // 7
- 2,8,4,5,3,4,3,6,2,6,5,4,5,2,4,5, // 8
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,12,5,// 9
- 3,8,4,5,3,4,3,6,2,6,4,4,5,2,4,4, // A
- 2,8,4,5,4,5,5,6,5,5,5,5,2,2,3,4, // B
- 3,8,4,5,4,5,4,7,2,5,6,4,5,2,4,9, // C
- 2,8,4,5,5,6,6,7,4,5,4,5,2,2,6,3, // D
- 2,8,4,5,3,4,3,6,2,4,5,3,4,3,4,3, // E
- 2,8,4,5,4,5,5,6,3,4,5,4,2,2,4,3 // F
-};
-
-// The C,mem instructions are hardly used, so a non-inline function is used for
-// the common access code.
-unsigned Spc_Cpu::mem_bit( spc_addr_t pc )
-{
- unsigned addr = READ_PROG16( pc );
- unsigned t = READ( addr & 0x1FFF ) >> (addr >> 13);
- return (t << 8) & 0x100;
-}
-
-spc_time_t Spc_Cpu::run( spc_time_t cycle_count )
-{
- remain_ = cycle_count;
-
- uint8_t* const ram = this->ram; // cache
-
- // Stack pointer is kept one greater than usual SPC stack pointer to allow
- // common pre-decrement and post-increment memory instructions that some
- // processors have. Address wrap-around isn't supported.
- #define PUSH( v ) (*--sp = uint8_t (v))
- #define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
- #define POP() (*sp++)
- #define SET_SP( v ) (sp = ram + 0x101 + (v))
- #define GET_SP() (sp - 0x101 - ram)
-
- uint8_t* sp;
- SET_SP( r.sp );
-
- // registers
- unsigned pc = (unsigned) r.pc;
- int a = r.a;
- int x = r.x;
- int y = r.y;
-
- // status flags
-
- const int st_n = 0x80;
- const int st_v = 0x40;
- const int st_p = 0x20;
- const int st_b = 0x10;
- const int st_h = 0x08;
- const int st_i = 0x04;
- const int st_z = 0x02;
- const int st_c = 0x01;
-
- #define IS_NEG (nz & 0x880)
-
- #define CALC_STATUS( out ) do {\
- out = status & ~(st_n | st_z | st_c);\
- out |= (c >> 8) & st_c;\
- out |= (dp >> 3) & st_p;\
- if ( IS_NEG ) out |= st_n;\
- if ( !(nz & 0xFF) ) out |= st_z;\
- } while ( 0 )
-
- #define SET_STATUS( in ) do {\
- status = in & ~(st_n | st_z | st_c | st_p);\
- c = in << 8;\
- nz = (in << 4) & 0x800;\
- nz |= ~in & st_z;\
- dp = (in << 3) & 0x100;\
- } while ( 0 )
-
- int status;
- int c; // store C as 'c' & 0x100.
- int nz; // Z set if (nz & 0xFF) == 0, N set if (nz & 0x880) != 0
- unsigned dp; // direct page base
- {
- int temp = r.status;
- SET_STATUS( temp );
- }
-
- goto loop;
-
- unsigned data; // first operand of instruction and temporary across function calls
-
- // Common endings for instructions
-cbranch_taken_loop: // compare and branch
- pc += (BOOST::int8_t) READ_PROG( pc );
- remain_ -= 2;
-inc_pc_loop: // end of instruction with an operand
- pc++;
-loop:
-
- check( (unsigned) pc < 0x10000 );
- check( (unsigned) GET_SP() < 0x100 );
-
- check( (unsigned) a < 0x100 );
- check( (unsigned) x < 0x100 );
- check( (unsigned) y < 0x100 );
-
- unsigned opcode = READ_PROG( pc );
- pc++;
- // to do: if pc is at end of memory, this will get wrong byte
- data = READ_PROG( pc );
-
- if ( remain_ <= 0 )
- goto stop;
-
- remain_ -= cycle_table [opcode];
-
- // Use 'data' for temporaries whose lifetime crosses read/write calls, otherwise
- // use a local temporary.
- switch ( opcode )
- {
-
- #define BRANCH( cond ) {\
- pc++;\
- int offset = (BOOST::int8_t) data;\
- if ( cond ) {\
- pc += offset;\
- remain_ -= 2;\
- }\
- goto loop;\
- }
-
-// Most-Common
-
- case 0xF0: // BEQ (most common)
- BRANCH( !(uint8_t) nz )
-
- case 0xD0: // BNE
- BRANCH( (uint8_t) nz )
-
- case 0x3F: // CALL
- PUSH16( pc + 2 );
- pc = READ_PROG16( pc );
- goto loop;
-
- case 0x6F: // RET
- pc = POP();
- pc += POP() * 0x100;
- goto loop;
-
-#define CASE( n ) case n:
-
-// Define common address modes based on opcode for immediate mode. Execution
-// ends with data set to the address of the operand.
-#define ADDR_MODES( op )\
- CASE( op - 0x02 ) /* (X) */\
- data = x + dp;\
- pc--;\
- goto end_##op;\
- CASE( op + 0x0F ) /* (dp)+Y */\
- data = READ_PROG16( data + dp ) + y;\
- goto end_##op;\
- CASE( op - 0x01 ) /* (dp+X) */\
- data = READ_PROG16( uint8_t (data + x) + dp );\
- goto end_##op;\
- CASE( op + 0x0E ) /* abs+Y */\
- data += y;\
- goto abs_##op;\
- CASE( op + 0x0D ) /* abs+X */\
- data += x;\
- CASE( op - 0x03 ) /* abs */\
- abs_##op:\
- pc++;\
- data += 0x100 * READ_PROG( pc );\
- goto end_##op;\
- CASE( op + 0x0C ) /* dp+X */\
- data = uint8_t (data + x);\
- CASE( op - 0x04 ) /* dp */\
- data += dp;\
- end_##op:
-
-// 1. 8-bit Data Transmission Commands. Group I
-
- ADDR_MODES( 0xE8 ) // MOV A,addr
- // case 0xE4: // MOV a,dp (most common)
- mov_a_addr:
- a = nz = READ( data );
- goto inc_pc_loop;
- case 0xBF: // MOV A,(X)+
- data = x + dp;
- x = uint8_t (x + 1);
- pc--;
- goto mov_a_addr;
-
- case 0xE8: // MOV A,imm
- a = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xF9: // MOV X,dp+Y
- data = uint8_t (data + y);
- case 0xF8: // MOV X,dp
- data += dp;
- goto mov_x_addr;
- case 0xE9: // MOV X,abs
- data = READ_PROG16( pc );
- pc++;
- mov_x_addr:
- data = READ( data );
- case 0xCD: // MOV X,imm
- x = data;
- nz = data;
- goto inc_pc_loop;
-
- case 0xFB: // MOV Y,dp+X
- data = uint8_t (data + x);
- case 0xEB: // MOV Y,dp
- data += dp;
- goto mov_y_addr;
- case 0xEC: // MOV Y,abs
- data = READ_PROG16( pc );
- pc++;
- mov_y_addr:
- data = READ( data );
- case 0x8D: // MOV Y,imm
- y = data;
- nz = data;
- goto inc_pc_loop;
-
-// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
-
- ADDR_MODES( 0xC8 ) // MOV addr,A
- WRITE( data, a );
- goto inc_pc_loop;
-
- {
- int temp;
- case 0xCC: // MOV abs,Y
- temp = y;
- goto mov_abs_temp;
- case 0xC9: // MOV abs,X
- temp = x;
- mov_abs_temp:
- WRITE( READ_PROG16( pc ), temp );
- pc += 2;
- goto loop;
- }
-
- case 0xD9: // MOV dp+Y,X
- data = uint8_t (data + y);
- case 0xD8: // MOV dp,X
- WRITE( data + dp, x );
- goto inc_pc_loop;
-
- case 0xDB: // MOV dp+X,Y
- data = uint8_t (data + x);
- case 0xCB: // MOV dp,Y
- WRITE( data + dp, y );
- goto inc_pc_loop;
-
- case 0xFA: // MOV dp,dp
- data = READ( data + dp );
- case 0x8F: // MOV dp,#imm
- pc++;
- WRITE_DP( READ_PROG( pc ), data );
- goto inc_pc_loop;
-
-// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
-
- case 0x7D: // MOV A,X
- a = x;
- nz = x;
- goto loop;
-
- case 0xDD: // MOV A,Y
- a = y;
- nz = y;
- goto loop;
-
- case 0x5D: // MOV X,A
- x = a;
- nz = a;
- goto loop;
-
- case 0xFD: // MOV Y,A
- y = a;
- nz = a;
- goto loop;
-
- case 0x9D: // MOV X,SP
- x = nz = GET_SP();
- goto loop;
-
- case 0xBD: // MOV SP,X
- SET_SP( x );
- goto loop;
-
- //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
-
- case 0xAF: // MOV (X)+,A
- WRITE_DP( x, a );
- x++;
- goto loop;
-
-// 5. 8-BIT LOGIC OPERATION COMMANDS
-
-#define LOGICAL_OP( op, func )\
- ADDR_MODES( op ) /* addr */\
- data = READ( data );\
- case op: /* imm */\
- nz = a func##= data;\
- goto inc_pc_loop;\
- { unsigned addr;\
- case op + 0x11: /* X,Y */\
- data = READ_DP( y );\
- addr = x + dp;\
- pc--;\
- goto addr_##op;\
- case op + 0x01: /* dp,dp */\
- data = READ_DP( data );\
- case op + 0x10: /*dp,imm*/\
- pc++;\
- addr = READ_PROG( pc ) + dp;\
- addr_##op:\
- nz = data func READ( addr );\
- WRITE( addr, nz );\
- goto inc_pc_loop;\
- }
-
- LOGICAL_OP( 0x28, & ); // AND
-
- LOGICAL_OP( 0x08, | ); // OR
-
- LOGICAL_OP( 0x48, ^ ); // EOR
-
-// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
-
- ADDR_MODES( 0x68 ) // CMP addr
- data = READ( data );
- case 0x68: // CMP imm
- nz = a - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x79: // CMP (X),(Y)
- data = READ_DP( x );
- nz = data - READ_DP( y );
- c = ~nz;
- nz &= 0xFF;
- goto loop;
-
- case 0x69: // CMP (dp),(dp)
- data = READ_DP( data );
- case 0x78: // CMP dp,imm
- pc++;
- nz = READ_DP( READ_PROG( pc ) ) - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x3E: // CMP X,dp
- data += dp;
- goto cmp_x_addr;
- case 0x1E: // CMP X,abs
- data = READ_PROG16( pc );
- pc++;
- cmp_x_addr:
- data = READ( data );
- case 0xC8: // CMP X,imm
- nz = x - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- case 0x7E: // CMP Y,dp
- data += dp;
- goto cmp_y_addr;
- case 0x5E: // CMP Y,abs
- data = READ_PROG16( pc );
- pc++;
- cmp_y_addr:
- data = READ( data );
- case 0xAD: // CMP Y,imm
- nz = y - data;
- c = ~nz;
- nz &= 0xFF;
- goto inc_pc_loop;
-
- {
- int addr;
- case 0xB9: // SBC (x),(y)
- case 0x99: // ADC (x),(y)
- pc--; // compensate for inc later
- data = READ_DP( x );
- addr = y + dp;
- goto adc_addr;
- case 0xA9: // SBC dp,dp
- case 0x89: // ADC dp,dp
- data = READ_DP( data );
- case 0xB8: // SBC dp,imm
- case 0x98: // ADC dp,imm
- pc++;
- addr = READ_PROG( pc ) + dp;
- adc_addr:
- nz = READ( addr );
- goto adc_data;
-
-// catch ADC and SBC together, then decode later based on operand
-#undef CASE
-#define CASE( n ) case n: case (n) + 0x20:
- ADDR_MODES( 0x88 ) // ADC/SBC addr
- data = READ( data );
- case 0xA8: // SBC imm
- case 0x88: // ADC imm
- addr = -1; // A
- nz = a;
- adc_data: {
- if ( opcode & 0x20 )
- data ^= 0xFF; // SBC
- int carry = (c >> 8) & 1;
- int ov = (nz ^ 0x80) + carry + (BOOST::int8_t) data; // sign-extend
- int hc = (nz & 15) + carry;
- c = nz += data + carry;
- hc = (nz & 15) - hc;
- status = (status & ~(st_v | st_h)) | ((ov >> 2) & st_v) | ((hc >> 1) & st_h);
- if ( addr < 0 ) {
- a = (uint8_t) nz;
- goto inc_pc_loop;
- }
- WRITE( addr, (uint8_t) nz );
- goto inc_pc_loop;
- }
-
- }
-
-// 6. ADDITION & SUBTRACTION COMMANDS
-
-#define INC_DEC_REG( reg, n )\
- nz = reg + n;\
- reg = (uint8_t) nz;\
- goto loop;
-
- case 0xBC: INC_DEC_REG( a, 1 ) // INC A
- case 0x3D: INC_DEC_REG( x, 1 ) // INC X
- case 0xFC: INC_DEC_REG( y, 1 ) // INC Y
-
- case 0x9C: INC_DEC_REG( a, -1 ) // DEC A
- case 0x1D: INC_DEC_REG( x, -1 ) // DEC X
- case 0xDC: INC_DEC_REG( y, -1 ) // DEC Y
-
- case 0x9B: // DEC dp+X
- case 0xBB: // INC dp+X
- data = uint8_t (data + x);
- case 0x8B: // DEC dp
- case 0xAB: // INC dp
- data += dp;
- goto inc_abs;
- case 0x8C: // DEC abs
- case 0xAC: // INC abs
- data = READ_PROG16( pc );
- pc++;
- inc_abs:
- nz = ((opcode >> 4) & 2) - 1;
- nz += READ( data );
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
-// 7. SHIFT, ROTATION COMMANDS
-
- case 0x5C: // LSR A
- c = 0;
- case 0x7C:{// ROR A
- nz = ((c >> 1) & 0x80) | (a >> 1);
- c = a << 8;
- a = nz;
- goto loop;
- }
-
- case 0x1C: // ASL A
- c = 0;
- case 0x3C:{// ROL A
- int temp = (c >> 8) & 1;
- c = a << 1;
- nz = c | temp;
- a = (uint8_t) nz;
- goto loop;
- }
-
- case 0x0B: // ASL dp
- c = 0;
- data += dp;
- goto rol_mem;
- case 0x1B: // ASL dp+X
- c = 0;
- case 0x3B: // ROL dp+X
- data = uint8_t (data + x);
- case 0x2B: // ROL dp
- data += dp;
- goto rol_mem;
- case 0x0C: // ASL abs
- c = 0;
- case 0x2C: // ROL abs
- data = READ_PROG16( pc );
- pc++;
- rol_mem:
- nz = (c >> 8) & 1;
- nz |= (c = READ( data ) << 1);
- WRITE( data, (uint8_t) nz );
- goto inc_pc_loop;
-
- case 0x4B: // LSR dp
- c = 0;
- data += dp;
- goto ror_mem;
- case 0x5B: // LSR dp+X
- c = 0;
- case 0x7B: // ROR dp+X
- data = uint8_t (data + x);
- case 0x6B: // ROR dp
- data += dp;
- goto ror_mem;
- case 0x4C: // LSR abs
- c = 0;
- case 0x6C: // ROR abs
- data = READ_PROG16( pc );
- pc++;
- ror_mem: {
- int temp = READ( data );
- nz = ((c >> 1) & 0x80) | (temp >> 1);
- c = temp << 8;
- WRITE( data, nz );
- goto inc_pc_loop;
- }
-
- case 0x9F: // XCN
- nz = a = (a >> 4) | uint8_t (a << 4);
- goto loop;
-
-// 8. 16-BIT TRANSMISION COMMANDS
-
- case 0xBA: // MOVW YA,dp
- a = READ_DP( data );
- nz = (a & 0x7F) | (a >> 1);
- y = READ_DP( uint8_t (data + 1) );
- nz |= y;
- goto inc_pc_loop;
-
- case 0xDA: // MOVW dp,YA
- WRITE_DP( data, a );
- WRITE_DP( uint8_t (data + 1), y );
- goto inc_pc_loop;
-
-// 9. 16-BIT OPERATION COMMANDS
-
- case 0x3A: // INCW dp
- case 0x1A:{// DECW dp
- data += dp;
-
- // low byte
- int temp = READ( data );
- temp += ((opcode >> 4) & 2) - 1; // +1 for INCW, -1 for DECW
- nz = ((temp >> 1) | temp) & 0x7F;
- WRITE( data, (uint8_t) temp );
-
- // high byte
- data = uint8_t (data + 1) + dp;
- temp >>= 8;
- temp = uint8_t (temp + READ( data ));
- nz |= temp;
- WRITE( data, temp );
-
- goto inc_pc_loop;
- }
-
- case 0x9A: // SUBW YA,dp
- case 0x7A: // ADDW YA,dp
- {
- // read 16-bit addend
- int temp = READ_DP( data );
- int sign = READ_DP( uint8_t (data + 1) );
- temp += 0x100 * sign;
- status &= ~(st_v | st_h);
-
- // to do: fix half-carry for SUBW (it's probably wrong)
-
- // for SUBW, negate and truncate to 16 bits
- if ( opcode & 0x80 ) {
- temp = (temp ^ 0xFFFF) + 1;
- sign = temp >> 8;
- }
-
- // add low byte (A)
- temp += a;
- a = (uint8_t) temp;
- nz = (temp | (temp >> 1)) & 0x7F;
-
- // add high byte (Y)
- temp >>= 8;
- c = y + temp;
- nz = (nz | c) & 0xFF;
-
- // half-carry (temporary avoids CodeWarrior optimizer bug)
- unsigned hc = (c & 15) - (y & 15);
- status |= (hc >> 4) & st_h;
-
- // overflow if sign of YA changed when previous sign and addend sign were same
- status |= (((c ^ y) & ~(y ^ sign)) >> 1) & st_v;
-
- y = (uint8_t) c;
-
- goto inc_pc_loop;
- }
-
- case 0x5A: { // CMPW YA,dp
- int temp = a - READ_DP( data );
- nz = ((temp >> 1) | temp) & 0x7F;
- temp = y + (temp >> 8);
- temp -= READ_DP( uint8_t (data + 1) );
- nz |= temp;
- c = ~temp;
- nz &= 0xFF;
- goto inc_pc_loop;
- }
-
-// 10. MULTIPLICATION & DIVISON COMMANDS
-
- case 0xCF: { // MUL YA
- unsigned temp = y * a;
- a = (uint8_t) temp;
- nz = ((temp >> 1) | temp) & 0x7F;
- y = temp >> 8;
- nz |= y;
- goto loop;
- }
-
- case 0x9E: // DIV YA,X
- {
- // behavior based on SPC CPU tests
-
- status &= ~(st_h | st_v);
-
- if ( (y & 15) >= (x & 15) )
- status |= st_h;
-
- if ( y >= x )
- status |= st_v;
-
- unsigned ya = y * 0x100 + a;
- if ( y < x * 2 )
- {
- a = ya / x;
- y = ya - a * x;
- }
- else
- {
- a = 255 - (ya - x * 0x200) / (256 - x);
- y = x + (ya - x * 0x200) % (256 - x);
- }
-
- nz = (uint8_t) a;
- a = (uint8_t) a;
-
- goto loop;
- }
-
-// 11. DECIMAL COMPENSATION COMMANDS
-
- // seem unused
- // case 0xDF: // DAA
- // case 0xBE: // DAS
-
-// 12. BRANCHING COMMANDS
-
- case 0x2F: // BRA rel
- pc += (BOOST::int8_t) data;
- goto inc_pc_loop;
-
- case 0x30: // BMI
- BRANCH( IS_NEG )
-
- case 0x10: // BPL
- BRANCH( !IS_NEG )
-
- case 0xB0: // BCS
- BRANCH( c & 0x100 )
-
- case 0x90: // BCC
- BRANCH( !(c & 0x100) )
-
- case 0x70: // BVS
- BRANCH( status & st_v )
-
- case 0x50: // BVC
- BRANCH( !(status & st_v) )
-
- case 0x03: // BBS dp.bit,rel
- case 0x23:
- case 0x43:
- case 0x63:
- case 0x83:
- case 0xA3:
- case 0xC3:
- case 0xE3:
- pc++;
- if ( (READ_DP( data ) >> (opcode >> 5)) & 1 )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0x13: // BBC dp.bit,rel
- case 0x33:
- case 0x53:
- case 0x73:
- case 0x93:
- case 0xB3:
- case 0xD3:
- case 0xF3:
- pc++;
- if ( !((READ_DP( data ) >> (opcode >> 5)) & 1) )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xDE: // CBNE dp+X,rel
- data = uint8_t (data + x);
- // fall through
- case 0x2E: // CBNE dp,rel
- pc++;
- if ( READ_DP( data ) != a )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
-
- case 0xFE: // DBNZ Y,rel
- y = uint8_t (y - 1);
- BRANCH( y )
-
- case 0x6E: { // DBNZ dp,rel
- pc++;
- unsigned temp = READ_DP( data ) - 1;
- WRITE_DP( (uint8_t) data, (uint8_t) temp );
- if ( temp )
- goto cbranch_taken_loop;
- goto inc_pc_loop;
- }
-
- case 0x1F: // JMP (abs+X)
- pc = READ_PROG16( pc ) + x;
- // fall through
- case 0x5F: // JMP abs
- pc = READ_PROG16( pc );
- goto loop;
-
-// 13. SUB-ROUTINE CALL RETURN COMMANDS
-
- case 0x0F:{// BRK
- check( false ); // untested
- PUSH16( pc + 1 );
- pc = READ_PROG16( 0xFFDE ); // vector address verified
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- status = (status | st_b) & ~st_i;
- goto loop;
- }
-
- case 0x4F: // PCALL offset
- pc++;
- PUSH16( pc );
- pc = 0xFF00 + data;
- goto loop;
-
- case 0x01: // TCALL n
- case 0x11:
- case 0x21:
- case 0x31:
- case 0x41:
- case 0x51:
- case 0x61:
- case 0x71:
- case 0x81:
- case 0x91:
- case 0xA1:
- case 0xB1:
- case 0xC1:
- case 0xD1:
- case 0xE1:
- case 0xF1:
- PUSH16( pc );
- pc = READ_PROG16( 0xFFDE - (opcode >> 3) );
- goto loop;
-
-// 14. STACK OPERATION COMMANDS
-
- {
- int temp;
- case 0x7F: // RET1
- temp = POP();
- pc = POP();
- pc |= POP() << 8;
- goto set_status;
- case 0x8E: // POP PSW
- temp = POP();
- set_status:
- SET_STATUS( temp );
- goto loop;
- }
-
- case 0x0D: { // PUSH PSW
- int temp;
- CALC_STATUS( temp );
- PUSH( temp );
- goto loop;
- }
-
- case 0x2D: // PUSH A
- PUSH( a );
- goto loop;
-
- case 0x4D: // PUSH X
- PUSH( x );
- goto loop;
-
- case 0x6D: // PUSH Y
- PUSH( y );
- goto loop;
-
- case 0xAE: // POP A
- a = POP();
- goto loop;
-
- case 0xCE: // POP X
- x = POP();
- goto loop;
-
- case 0xEE: // POP Y
- y = POP();
- goto loop;
-
-// 15. BIT OPERATION COMMANDS
-
- case 0x02: // SET1
- case 0x22:
- case 0x42:
- case 0x62:
- case 0x82:
- case 0xA2:
- case 0xC2:
- case 0xE2:
- case 0x12: // CLR1
- case 0x32:
- case 0x52:
- case 0x72:
- case 0x92:
- case 0xB2:
- case 0xD2:
- case 0xF2: {
- data += dp;
- int bit = 1 << (opcode >> 5);
- int mask = ~bit;
- if ( opcode & 0x10 )
- bit = 0;
- WRITE( data, (READ( data ) & mask) | bit );
- goto inc_pc_loop;
- }
-
- case 0x0E: // TSET1 abs
- case 0x4E:{// TCLR1 abs
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data );
- nz = temp & a;
- temp &= ~a;
- if ( !(opcode & 0x40) )
- temp |= a;
- WRITE( data, temp );
- goto loop;
- }
-
- case 0x4A: // AND1 C,mem.bit
- c &= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x6A: // AND1 C,/mem.bit
- check( false ); // untested
- c &= ~mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x0A: // OR1 C,mem.bit
- check( false ); // untested
- c |= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x2A: // OR1 C,/mem.bit
- check( false ); // untested
- c |= ~mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0x8A: // EOR1 C,mem.bit
- c ^= mem_bit( pc );
- pc += 2;
- goto loop;
-
- case 0xEA: { // NOT1 mem.bit
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- temp ^= 1 << (data >> 13);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xCA: { // MOV1 mem.bit,C
- data = READ_PROG16( pc );
- pc += 2;
- unsigned temp = READ( data & 0x1FFF );
- unsigned bit = data >> 13;
- temp = (temp & ~(1 << bit)) | (((c >> 8) & 1) << bit);
- WRITE( data & 0x1FFF, temp );
- goto loop;
- }
-
- case 0xAA: // MOV1 C,mem.bit
- c = mem_bit( pc );
- pc += 2;
- goto loop;
-
-// 16. PROGRAM STATUS FLAG OPERATION COMMANDS
-
- case 0x60: // CLRC
- c = 0;
- goto loop;
-
- case 0x80: // SETC
- c = ~0;
- goto loop;
-
- case 0xED: // NOTC
- c ^= 0x100;
- goto loop;
-
- case 0xE0: // CLRV
- status &= ~(st_v | st_h);
- goto loop;
-
- case 0x20: // CLRP
- dp = 0;
- goto loop;
-
- case 0x40: // SETP
- dp = 0x100;
- goto loop;
-
- case 0xA0: // EI
- check( false ); // untested
- status |= st_i;
- goto loop;
-
- case 0xC0: // DI
- check( false ); // untested
- status &= ~st_i;
- goto loop;
-
-// 17. OTHER COMMANDS
-
- case 0x00: // NOP
- goto loop;
-
- //case 0xEF: // SLEEP
- //case 0xFF: // STOP
-
- } // switch
-
- // unhandled instructions fall out of switch so emulator can catch them
-
-stop:
- pc--;
-
- {
- int temp;
- CALC_STATUS( temp );
- r.status = (uint8_t) temp;
- }
-
- r.pc = pc;
- r.sp = (uint8_t) GET_SP();
- r.a = (uint8_t) a;
- r.x = (uint8_t) x;
- r.y = (uint8_t) y;
-
- return remain_;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.h b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.h
deleted file mode 100644
index 40f55aea..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Cpu.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Super Nintendo (SNES) SPC-700 CPU emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SPC_CPU_H
-#define SPC_CPU_H
-
-#include "blargg_common.h"
-
-typedef unsigned spc_addr_t;
-typedef blargg_long spc_time_t;
-
-class Snes_Spc;
-
-class Spc_Cpu {
- typedef BOOST::uint8_t uint8_t;
- uint8_t* const ram;
-public:
- // Keeps pointer to 64K RAM
- Spc_Cpu( Snes_Spc* spc, uint8_t* ram );
-
- // SPC-700 registers. *Not* kept updated during a call to run().
- struct registers_t {
- long pc; // more than 16 bits to allow overflow detection
- uint8_t a;
- uint8_t x;
- uint8_t y;
- uint8_t status;
- uint8_t sp;
- } r;
-
- // Run CPU for at least 'count' cycles. Return the number of cycles remaining
- // when emulation stopped (negative if extra cycles were emulated). Emulation
- // stops when there are no more remaining cycles or an unhandled instruction
- // is encountered (STOP, SLEEP, and any others not yet implemented). In the
- // latter case, the return value is greater than zero.
- spc_time_t run( spc_time_t count );
-
- // Number of clock cycles remaining for current run() call
- spc_time_t remain() const;
-
- // Access memory as the emulated CPU does
- int read ( spc_addr_t );
- void write( spc_addr_t, int );
-
-private:
- // noncopyable
- Spc_Cpu( const Spc_Cpu& );
- Spc_Cpu& operator = ( const Spc_Cpu& );
- unsigned mem_bit( spc_addr_t );
-
- spc_time_t remain_;
- Snes_Spc& emu;
-};
-
-inline spc_time_t Spc_Cpu::remain() const { return remain_; }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.cpp
deleted file mode 100644
index 814ff2bd..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.cpp
+++ /dev/null
@@ -1,666 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-// Based on Brad Martin's OpenSPC DSP emulator
-
-#include "Spc_Dsp.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-
-/* Copyright (C) 2002 Brad Martin */
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-Spc_Dsp::Spc_Dsp( uint8_t* ram_ ) : ram( ram_ )
-{
- set_gain( 1.0 );
- mute_voices( 0 );
- disable_surround( false );
-
- assert( offsetof (globals_t,unused9 [2]) == register_count );
- assert( sizeof (voice) == register_count );
- blargg_verify_byte_order();
-}
-
-void Spc_Dsp::mute_voices( int mask )
-{
- for ( int i = 0; i < voice_count; i++ )
- voice_state [i].enabled = (mask >> i & 1) ? 31 : 7;
-}
-
-void Spc_Dsp::reset()
-{
- keys = 0;
- echo_ptr = 0;
- noise_count = 0;
- noise = 1;
- fir_offset = 0;
-
- g.flags = 0xE0; // reset, mute, echo off
- g.key_ons = 0;
-
- for ( int i = 0; i < voice_count; i++ )
- {
- voice_t& v = voice_state [i];
- v.on_cnt = 0;
- v.volume [0] = 0;
- v.volume [1] = 0;
- v.envstate = state_release;
- }
-
- memset( fir_buf, 0, sizeof fir_buf );
-}
-
-void Spc_Dsp::write( int i, int data )
-{
- require( (unsigned) i < register_count );
-
- reg [i] = data;
- int high = i >> 4;
- switch ( i & 0x0F )
- {
- // voice volume
- case 0:
- case 1: {
- short* volume = voice_state [high].volume;
- int left = (int8_t) reg [i & ~1];
- int right = (int8_t) reg [i | 1];
- volume [0] = left;
- volume [1] = right;
- // kill surround only if enabled and signs of volumes differ
- if ( left * right < surround_threshold )
- {
- if ( left < 0 )
- volume [0] = -left;
- else
- volume [1] = -right;
- }
- break;
- }
-
- // fir coefficients
- case 0x0F:
- fir_coeff [high] = (int8_t) data; // sign-extend
- break;
- }
-}
-
-// This table is for envelope timing. It represents the number of counts
-// that should be subtracted from the counter each sample period (32kHz).
-// The counter starts at 30720 (0x7800). Each count divides exactly into
-// 0x7800 without remainder.
-const int env_rate_init = 0x7800;
-static short const env_rates [0x20] =
-{
- 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
- 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
- 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
- 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
-};
-
-const int env_range = 0x800;
-
-inline int Spc_Dsp::clock_envelope( int v )
-{ /* Return value is current
- * ENVX */
- raw_voice_t& raw_voice = this->voice [v];
- voice_t& voice = voice_state [v];
-
- int envx = voice.envx;
- if ( voice.envstate == state_release )
- {
- /*
- * Docs: "When in the state of "key off". the "click" sound is
- * prevented by the addition of the fixed value 1/256" WTF???
- * Alright, I'm going to choose to interpret that this way:
- * When a note is keyed off, start the RELEASE state, which
- * subtracts 1/256th each sample period (32kHz). Note there's
- * no need for a count because it always happens every update.
- */
- envx -= env_range / 256;
- if ( envx <= 0 )
- {
- envx = 0;
- keys &= ~(1 << v);
- return -1;
- }
- voice.envx = envx;
- raw_voice.envx = envx >> 8;
- return envx;
- }
-
- int cnt = voice.envcnt;
- int adsr1 = raw_voice.adsr [0];
- if ( adsr1 & 0x80 )
- {
- switch ( voice.envstate )
- {
- case state_attack: {
- // increase envelope by 1/64 each step
- int t = adsr1 & 15;
- if ( t == 15 )
- {
- envx += env_range / 2;
- }
- else
- {
- cnt -= env_rates [t * 2 + 1];
- if ( cnt > 0 )
- break;
- envx += env_range / 64;
- cnt = env_rate_init;
- }
- if ( envx >= env_range )
- {
- envx = env_range - 1;
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- }
-
- case state_decay: {
- // Docs: "DR... [is multiplied] by the fixed value
- // 1-1/256." Well, at least that makes some sense.
- // Multiplying ENVX by 255/256 every time DECAY is
- // updated.
- cnt -= env_rates [((adsr1 >> 3) & 0xE) + 0x10];
- if ( cnt <= 0 )
- {
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- voice.envx = envx;
- }
- int sustain_level = raw_voice.adsr [1] >> 5;
-
- if ( envx <= (sustain_level + 1) * 0x100 )
- voice.envstate = state_sustain;
- break;
- }
-
- case state_sustain:
- // Docs: "SR [is multiplied] by the fixed value 1-1/256."
- // Multiplying ENVX by 255/256 every time SUSTAIN is
- // updated.
- cnt -= env_rates [raw_voice.adsr [1] & 0x1F];
- if ( cnt <= 0 )
- {
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- voice.envx = envx;
- }
- break;
-
- case state_release:
- // handled above
- break;
- }
- }
- else
- { /* GAIN mode is set */
- /*
- * Note: if the game switches between ADSR and GAIN modes
- * partway through, should the count be reset, or should it
- * continue from where it was? Does the DSP actually watch for
- * that bit to change, or does it just go along with whatever
- * it sees when it performs the update? I'm going to assume
- * the latter and not update the count, unless I see a game
- * that obviously wants the other behavior. The effect would
- * be pretty subtle, in any case.
- */
- int t = raw_voice.gain;
- if (t < 0x80)
- {
- envx = voice.envx = t << 4;
- }
- else switch (t >> 5)
- {
- case 4: /* Docs: "Decrease (linear): Subtraction
- * of the fixed value 1/64." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx -= env_range / 64;
- if ( envx < 0 )
- {
- envx = 0;
- if ( voice.envstate == state_attack )
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- case 5: /* Docs: "Drecrease <sic> (exponential):
- * Multiplication by the fixed value
- * 1-1/256." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx -= ((envx - 1) >> 8) + 1;
- if ( envx < 0 )
- {
- envx = 0;
- if ( voice.envstate == state_attack )
- voice.envstate = state_decay;
- }
- voice.envx = envx;
- break;
- case 6: /* Docs: "Increase (linear): Addition of
- * the fixed value 1/64." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- envx += env_range / 64;
- if ( envx >= env_range )
- envx = env_range - 1;
- voice.envx = envx;
- break;
- case 7: /* Docs: "Increase (bent line): Addition
- * of the constant 1/64 up to .75 of the
- * constaint <sic> 1/256 from .75 to 1." */
- cnt -= env_rates [t & 0x1F];
- if (cnt > 0)
- break;
- cnt = env_rate_init;
- if ( envx < env_range * 3 / 4 )
- envx += env_range / 64;
- else
- envx += env_range / 256;
- if ( envx >= env_range )
- envx = env_range - 1;
- voice.envx = envx;
- break;
- }
- }
- voice.envcnt = cnt;
- raw_voice.envx = envx >> 4;
- return envx;
-}
-
-// Clamp n into range -32768 <= n <= 32767
-inline int clamp_16( int n )
-{
- if ( (BOOST::int16_t) n != n )
- n = BOOST::int16_t (0x7FFF - (n >> 31));
- return n;
-}
-
-void Spc_Dsp::run( long count, short* out_buf )
-{
- // to do: make clock_envelope() inline so that this becomes a leaf function?
-
- // Should we just fill the buffer with silence? Flags won't be cleared
- // during this run so it seems it should keep resetting every sample.
- if ( g.flags & 0x80 )
- reset();
-
- struct src_dir {
- char start [2];
- char loop [2];
- };
-
- const src_dir* const sd = (src_dir*) &ram [g.wave_page * 0x100];
-
- int left_volume = g.left_volume;
- int right_volume = g.right_volume;
- if ( left_volume * right_volume < surround_threshold )
- right_volume = -right_volume; // kill global surround
- left_volume *= emu_gain;
- right_volume *= emu_gain;
-
- while ( --count >= 0 )
- {
- // Here we check for keys on/off. Docs say that successive writes
- // to KON/KOF must be separated by at least 2 Ts periods or risk
- // being neglected. Therefore DSP only looks at these during an
- // update, and not at the time of the write. Only need to do this
- // once however, since the regs haven't changed over the whole
- // period we need to catch up with.
-
- g.wave_ended &= ~g.key_ons; // Keying on a voice resets that bit in ENDX.
-
- if ( g.noise_enables )
- {
- noise_count -= env_rates [g.flags & 0x1F];
- if ( noise_count <= 0 )
- {
- noise_count = env_rate_init;
-
- noise_amp = BOOST::int16_t (noise * 2);
-
- // TODO: switch to Galios style
- int feedback = (noise << 13) ^ (noise << 14);
- noise = (feedback & 0x4000) | (noise >> 1);
- }
- }
-
- // What is the expected behavior when pitch modulation is enabled on
- // voice 0? Jurassic Park 2 does this. Assume 0 for now.
- blargg_long prev_outx = 0;
-
- int echol = 0;
- int echor = 0;
- int left = 0;
- int right = 0;
- for ( int vidx = 0; vidx < voice_count; vidx++ )
- {
- const int vbit = 1 << vidx;
- raw_voice_t& raw_voice = voice [vidx];
- voice_t& voice = voice_state [vidx];
-
- if ( voice.on_cnt && !--voice.on_cnt )
- {
- // key on
- keys |= vbit;
- voice.addr = GET_LE16( sd [raw_voice.waveform].start );
- voice.block_remain = 1;
- voice.envx = 0;
- voice.block_header = 0;
- voice.fraction = 0x3FFF; // decode three samples immediately
- voice.interp0 = 0; // BRR decoder filter uses previous two samples
- voice.interp1 = 0;
-
- // NOTE: Real SNES does *not* appear to initialize the
- // envelope counter to anything in particular. The first
- // cycle always seems to come at a random time sooner than
- // expected; as yet, I have been unable to find any
- // pattern. I doubt it will matter though, so we'll go
- // ahead and do the full time for now.
- voice.envcnt = env_rate_init;
- voice.envstate = state_attack;
- }
-
- if ( g.key_ons & vbit & ~g.key_offs )
- {
- // voice doesn't come on if key off is set
- g.key_ons &= ~vbit;
- voice.on_cnt = 8;
- }
-
- if ( keys & g.key_offs & vbit )
- {
- // key off
- voice.envstate = state_release;
- voice.on_cnt = 0;
- }
-
- int envx;
- if ( !(keys & vbit) || (envx = clock_envelope( vidx )) < 0 )
- {
- raw_voice.envx = 0;
- raw_voice.outx = 0;
- prev_outx = 0;
- continue;
- }
-
- // Decode samples when fraction >= 1.0 (0x1000)
- for ( int n = voice.fraction >> 12; --n >= 0; )
- {
- if ( !--voice.block_remain )
- {
- if ( voice.block_header & 1 )
- {
- g.wave_ended |= vbit;
-
- if ( voice.block_header & 2 )
- {
- // verified (played endless looping sample and ENDX was set)
- voice.addr = GET_LE16( sd [raw_voice.waveform].loop );
- }
- else
- {
- // first block was end block; don't play anything (verified)
- goto sample_ended; // to do: find alternative to goto
- }
- }
-
- voice.block_header = ram [voice.addr++];
- voice.block_remain = 16; // nybbles
- }
-
- // if next block has end flag set, *this* block ends *early* (verified)
- if ( voice.block_remain == 9 && (ram [voice.addr + 5] & 3) == 1 &&
- (voice.block_header & 3) != 3 )
- {
- sample_ended:
- g.wave_ended |= vbit;
- keys &= ~vbit;
- raw_voice.envx = 0;
- voice.envx = 0;
- // add silence samples to interpolation buffer
- do
- {
- voice.interp3 = voice.interp2;
- voice.interp2 = voice.interp1;
- voice.interp1 = voice.interp0;
- voice.interp0 = 0;
- }
- while ( --n >= 0 );
- break;
- }
-
- int delta = ram [voice.addr];
- if ( voice.block_remain & 1 )
- {
- delta <<= 4; // use lower nybble
- voice.addr++;
- }
-
- // Use sign-extended upper nybble
- delta = int8_t (delta) >> 4;
-
- // For invalid ranges (D,E,F): if the nybble is negative,
- // the result is F000. If positive, 0000. Nothing else
- // like previous range, etc seems to have any effect. If
- // range is valid, do the shift normally. Note these are
- // both shifted right once to do the filters properly, but
- // the output will be shifted back again at the end.
- int shift = voice.block_header >> 4;
- delta = (delta << shift) >> 1;
- if ( shift > 0x0C )
- delta = (delta >> 14) & ~0x7FF;
-
- // One, two and three point IIR filters
- int smp1 = voice.interp0;
- int smp2 = voice.interp1;
- if ( voice.block_header & 8 )
- {
- delta += smp1;
- delta -= smp2 >> 1;
- if ( !(voice.block_header & 4) )
- {
- delta += (-smp1 - (smp1 >> 1)) >> 5;
- delta += smp2 >> 5;
- }
- else
- {
- delta += (-smp1 * 13) >> 7;
- delta += (smp2 + (smp2 >> 1)) >> 4;
- }
- }
- else if ( voice.block_header & 4 )
- {
- delta += smp1 >> 1;
- delta += (-smp1) >> 5;
- }
-
- voice.interp3 = voice.interp2;
- voice.interp2 = smp2;
- voice.interp1 = smp1;
- voice.interp0 = BOOST::int16_t (clamp_16( delta ) * 2); // sign-extend
- }
-
- // rate (with possible modulation)
- int rate = GET_LE16( raw_voice.rate ) & 0x3FFF;
- if ( g.pitch_mods & vbit )
- rate = (rate * (prev_outx + 32768)) >> 15;
-
- // Gaussian interpolation using most recent 4 samples
- int index = voice.fraction >> 2 & 0x3FC;
- voice.fraction = (voice.fraction & 0x0FFF) + rate;
- const BOOST::int16_t* table = (BOOST::int16_t const*) ((char const*) gauss + index);
- const BOOST::int16_t* table2 = (BOOST::int16_t const*) ((char const*) gauss + (255*4 - index));
- int s = ((table [0] * voice.interp3) >> 12) +
- ((table [1] * voice.interp2) >> 12) +
- ((table2 [1] * voice.interp1) >> 12);
- s = (BOOST::int16_t) (s * 2);
- s += (table2 [0] * voice.interp0) >> 11 & ~1;
- int output = clamp_16( s );
- if ( g.noise_enables & vbit )
- output = noise_amp;
-
- // scale output and set outx values
- output = (output * envx) >> 11 & ~1;
-
- // output and apply muting (by setting voice.enabled to 31)
- // if voice is externally disabled (not a SNES feature)
- int l = (voice.volume [0] * output) >> voice.enabled;
- int r = (voice.volume [1] * output) >> voice.enabled;
- prev_outx = output;
- raw_voice.outx = int8_t (output >> 8);
- if ( g.echo_ons & vbit )
- {
- echol += l;
- echor += r;
- }
- left += l;
- right += r;
- }
- // end of channel loop
-
- // main volume control
- left = (left * left_volume ) >> (7 + emu_gain_bits);
- right = (right * right_volume) >> (7 + emu_gain_bits);
-
- // Echo FIR filter
-
- // read feedback from echo buffer
- int echo_ptr = this->echo_ptr;
- uint8_t* echo_buf = &ram [(g.echo_page * 0x100 + echo_ptr) & 0xFFFF];
- echo_ptr += 4;
- if ( echo_ptr >= (g.echo_delay & 15) * 0x800 )
- echo_ptr = 0;
- int fb_left = (BOOST::int16_t) GET_LE16( echo_buf ); // sign-extend
- int fb_right = (BOOST::int16_t) GET_LE16( echo_buf + 2 ); // sign-extend
- this->echo_ptr = echo_ptr;
-
- // put samples in history ring buffer
- const int fir_offset = this->fir_offset;
- short (*fir_pos) [2] = &fir_buf [fir_offset];
- this->fir_offset = (fir_offset + 7) & 7; // move backwards one step
- fir_pos [0] [0] = (short) fb_left;
- fir_pos [0] [1] = (short) fb_right;
- fir_pos [8] [0] = (short) fb_left; // duplicate at +8 eliminates wrap checking below
- fir_pos [8] [1] = (short) fb_right;
-
- // FIR
- fb_left = fb_left * fir_coeff [7] +
- fir_pos [1] [0] * fir_coeff [6] +
- fir_pos [2] [0] * fir_coeff [5] +
- fir_pos [3] [0] * fir_coeff [4] +
- fir_pos [4] [0] * fir_coeff [3] +
- fir_pos [5] [0] * fir_coeff [2] +
- fir_pos [6] [0] * fir_coeff [1] +
- fir_pos [7] [0] * fir_coeff [0];
-
- fb_right = fb_right * fir_coeff [7] +
- fir_pos [1] [1] * fir_coeff [6] +
- fir_pos [2] [1] * fir_coeff [5] +
- fir_pos [3] [1] * fir_coeff [4] +
- fir_pos [4] [1] * fir_coeff [3] +
- fir_pos [5] [1] * fir_coeff [2] +
- fir_pos [6] [1] * fir_coeff [1] +
- fir_pos [7] [1] * fir_coeff [0];
-
- left += (fb_left * g.left_echo_volume ) >> 14;
- right += (fb_right * g.right_echo_volume) >> 14;
-
- // echo buffer feedback
- if ( !(g.flags & 0x20) )
- {
- echol += (fb_left * g.echo_feedback) >> 14;
- echor += (fb_right * g.echo_feedback) >> 14;
- SET_LE16( echo_buf , clamp_16( echol ) );
- SET_LE16( echo_buf + 2, clamp_16( echor ) );
- }
-
- if ( out_buf )
- {
- // write final samples
-
- left = clamp_16( left );
- right = clamp_16( right );
-
- int mute = g.flags & 0x40;
-
- out_buf [0] = (short) left;
- out_buf [1] = (short) right;
- out_buf += 2;
-
- // muting
- if ( mute )
- {
- out_buf [-2] = 0;
- out_buf [-1] = 0;
- }
- }
- }
-}
-
-// Base normal_gauss table is almost exactly (with an error of 0 or -1 for each entry):
-// int normal_gauss [512];
-// normal_gauss [i] = exp((i-511)*(i-511)*-9.975e-6)*pow(sin(0.00307096*i),1.7358)*1304.45
-
-// Interleved gauss table (to improve cache coherency).
-// gauss [i * 2 + j] = normal_gauss [(1 - j) * 256 + i]
-const BOOST::int16_t Spc_Dsp::gauss [512] =
-{
- 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
- 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
- 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
- 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
- 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
- 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
- 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
- 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
- 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
- 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
- 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
- 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
- 102,1102, 100,1098, 99,1094, 97,1090, 95,1086, 94,1082, 92,1078, 90,1074,
- 89,1070, 87,1066, 86,1061, 84,1057, 83,1053, 81,1049, 80,1045, 78,1040,
- 77,1036, 76,1032, 74,1027, 73,1023, 71,1019, 70,1014, 69,1010, 67,1005,
- 66,1001, 65, 997, 64, 992, 62, 988, 61, 983, 60, 978, 59, 974, 58, 969,
- 56, 965, 55, 960, 54, 955, 53, 951, 52, 946, 51, 941, 50, 937, 49, 932,
- 48, 927, 47, 923, 46, 918, 45, 913, 44, 908, 43, 904, 42, 899, 41, 894,
- 40, 889, 39, 884, 38, 880, 37, 875, 36, 870, 36, 865, 35, 860, 34, 855,
- 33, 851, 32, 846, 32, 841, 31, 836, 30, 831, 29, 826, 29, 821, 28, 816,
- 27, 811, 27, 806, 26, 802, 25, 797, 24, 792, 24, 787, 23, 782, 23, 777,
- 22, 772, 21, 767, 21, 762, 20, 757, 20, 752, 19, 747, 19, 742, 18, 737,
- 17, 732, 17, 728, 16, 723, 16, 718, 15, 713, 15, 708, 15, 703, 14, 698,
- 14, 693, 13, 688, 13, 683, 12, 678, 12, 674, 11, 669, 11, 664, 11, 659,
- 10, 654, 10, 649, 10, 644, 9, 640, 9, 635, 9, 630, 8, 625, 8, 620,
- 8, 615, 7, 611, 7, 606, 7, 601, 6, 596, 6, 592, 6, 587, 6, 582,
- 5, 577, 5, 573, 5, 568, 5, 563, 4, 559, 4, 554, 4, 550, 4, 545,
- 4, 540, 3, 536, 3, 531, 3, 527, 3, 522, 3, 517, 2, 513, 2, 508,
- 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
- 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
- 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
- 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
-};
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.h b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.h
deleted file mode 100644
index 1e79870a..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Dsp.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Super Nintendo (SNES) SPC DSP emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SPC_DSP_H
-#define SPC_DSP_H
-
-#include "blargg_common.h"
-
-class Spc_Dsp {
- typedef BOOST::int8_t int8_t;
- typedef BOOST::uint8_t uint8_t;
-public:
-
- // Keeps pointer to 64K ram
- Spc_Dsp( uint8_t* ram );
-
- // Mute voice n if bit n (1 << n) of mask is clear.
- enum { voice_count = 8 };
- void mute_voices( int mask );
-
- // Clear state and silence everything.
- void reset();
-
- // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped to
- // the 16-bit sample range.
- void set_gain( double );
-
- // If true, prevent channels and global volumes from being phase-negated
- void disable_surround( bool disable );
-
- // Read/write register 'n', where n ranges from 0 to register_count - 1.
- enum { register_count = 128 };
- int read ( int n );
- void write( int n, int );
-
- // Run DSP for 'count' samples. Write resulting samples to 'buf' if not NULL.
- void run( long count, short* buf = NULL );
-
-
-// End of public interface
-private:
-
- struct raw_voice_t {
- int8_t left_vol;
- int8_t right_vol;
- uint8_t rate [2];
- uint8_t waveform;
- uint8_t adsr [2]; // envelope rates for attack, decay, and sustain
- uint8_t gain; // envelope gain (if not using ADSR)
- int8_t envx; // current envelope level
- int8_t outx; // current sample
- int8_t unused [6];
- };
-
- struct globals_t {
- int8_t unused1 [12];
- int8_t left_volume; // 0C Main Volume Left (-.7)
- int8_t echo_feedback; // 0D Echo Feedback (-.7)
- int8_t unused2 [14];
- int8_t right_volume; // 1C Main Volume Right (-.7)
- int8_t unused3 [15];
- int8_t left_echo_volume; // 2C Echo Volume Left (-.7)
- uint8_t pitch_mods; // 2D Pitch Modulation on/off for each voice
- int8_t unused4 [14];
- int8_t right_echo_volume; // 3C Echo Volume Right (-.7)
- uint8_t noise_enables; // 3D Noise output on/off for each voice
- int8_t unused5 [14];
- uint8_t key_ons; // 4C Key On for each voice
- uint8_t echo_ons; // 4D Echo on/off for each voice
- int8_t unused6 [14];
- uint8_t key_offs; // 5C key off for each voice (instantiates release mode)
- uint8_t wave_page; // 5D source directory (wave table offsets)
- int8_t unused7 [14];
- uint8_t flags; // 6C flags and noise freq
- uint8_t echo_page; // 6D
- int8_t unused8 [14];
- uint8_t wave_ended; // 7C
- uint8_t echo_delay; // 7D ms >> 4
- char unused9 [2];
- };
-
- union {
- raw_voice_t voice [voice_count];
- uint8_t reg [register_count];
- globals_t g;
- };
-
- uint8_t* const ram;
-
- // Cache of echo FIR values for faster access
- short fir_coeff [voice_count];
-
- // fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code
- short fir_buf [16] [2];
- int fir_offset; // (0 to 7)
-
- enum { emu_gain_bits = 8 };
- int emu_gain;
-
- int keyed_on; // 8-bits for 8 voices
- int keys;
-
- int echo_ptr;
- int noise_amp;
- int noise;
- int noise_count;
-
- int surround_threshold;
-
- static BOOST::int16_t const gauss [];
-
- enum state_t {
- state_attack,
- state_decay,
- state_sustain,
- state_release
- };
-
- struct voice_t {
- short volume [2];
- short fraction;// 12-bit fractional position
- short interp3; // most recent four decoded samples
- short interp2;
- short interp1;
- short interp0;
- short block_remain; // number of nybbles remaining in current block
- unsigned short addr;
- short block_header; // header byte from current block
- short envcnt;
- short envx;
- short on_cnt;
- short enabled; // 7 if enabled, 31 if disabled
- short envstate;
- short unused; // pad to power of 2
- };
-
- voice_t voice_state [voice_count];
-
- int clock_envelope( int );
-};
-
-inline void Spc_Dsp::disable_surround( bool disable ) { surround_threshold = disable ? 0 : -0x7FFF; }
-
-inline void Spc_Dsp::set_gain( double v ) { emu_gain = (int) (v * (1 << emu_gain_bits)); }
-
-inline int Spc_Dsp::read( int i )
-{
- assert( (unsigned) i < register_count );
- return reg [i];
-}
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.cpp
deleted file mode 100644
index a5002bf7..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.cpp
+++ /dev/null
@@ -1,328 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Spc_Emu.h"
-
-#include "blargg_endian.h"
-#include <stdlib.h>
-#include <string.h>
-
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-Spc_Emu::Spc_Emu()
-{
- set_type( gme_spc_type );
-
- static const char* const names [Snes_Spc::voice_count] = {
- "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
- };
- set_voice_names( names );
-
- set_gain( 1.4 );
-}
-
-Spc_Emu::~Spc_Emu() { }
-
-// Track info
-
-long const trailer_offset = 0x10200;
-
-byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, trailer_offset )]; }
-
-long Spc_Emu::trailer_size() const { return max( 0L, file_size - trailer_offset ); }
-
-static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
-{
- // header
- byte const* end = begin + size;
- if ( size < 8 || memcmp( begin, "xid6", 4 ) )
- {
- check( false );
- return;
- }
- long info_size = get_le32( begin + 4 );
- byte const* in = begin + 8;
- if ( end - in > info_size )
- {
- debug_printf( "Extra data after SPC xid6 info\n" );
- end = in + info_size;
- }
-
- int year = 0;
- char copyright [256 + 5];
- int copyright_len = 0;
- int const year_len = 5;
-
- while ( end - in >= 4 )
- {
- // header
- int id = in [0];
- int data = in [3] * 0x100 + in [2];
- int type = in [1];
- int len = type ? data : 0;
- in += 4;
- if ( len > end - in )
- {
- check( false );
- break; // block goes past end of data
- }
-
- // handle specific block types
- char* field = 0;
- switch ( id )
- {
- case 0x01: field = out->song; break;
- case 0x02: field = out->game; break;
- case 0x03: field = out->author; break;
- case 0x04: field = out->dumper; break;
- case 0x07: field = out->comment; break;
- case 0x14: year = data; break;
-
- //case 0x30: // intro length
- // Many SPCs have intro length set wrong for looped tracks, making it useless
- /*
- case 0x30:
- check( len == 4 );
- if ( len >= 4 )
- {
- out->intro_length = get_le32( in ) / 64;
- if ( out->length > 0 )
- {
- long loop = out->length - out->intro_length;
- if ( loop >= 2000 )
- out->loop_length = loop;
- }
- }
- break;
- */
-
- case 0x13:
- copyright_len = min( len, (int) sizeof copyright - year_len );
- memcpy( &copyright [year_len], in, copyright_len );
- break;
-
- default:
- if ( id < 0x01 || (id > 0x07 && id < 0x10) ||
- (id > 0x14 && id < 0x30) || id > 0x36 )
- debug_printf( "Unknown SPC xid6 block: %X\n", (int) id );
- break;
- }
- if ( field )
- {
- check( type == 1 );
- Gme_File::copy_field_( field, (char const*) in, len );
- }
-
- // skip to next block
- in += len;
-
- // blocks are supposed to be 4-byte aligned with zero-padding...
- byte const* unaligned = in;
- while ( (in - begin) & 3 && in < end )
- {
- if ( *in++ != 0 )
- {
- // ...but some files have no padding
- in = unaligned;
- debug_printf( "SPC info tag wasn't properly padded to align\n" );
- break;
- }
- }
- }
-
- char* p = &copyright [year_len];
- if ( year )
- {
- *--p = ' ';
- for ( int n = 4; n--; )
- {
- *--p = char (year % 10 + '0');
- year /= 10;
- }
- copyright_len += year_len;
- }
- if ( copyright_len )
- Gme_File::copy_field_( out->copyright, p, copyright_len );
-
- check( in == end );
-}
-
-static void get_spc_info( Spc_Emu::header_t const& h, byte const* xid6, long xid6_size,
- track_info_t* out )
-{
- // decode length (can be in text or binary format, sometimes ambiguous ugh)
- long len_secs = 0;
- for ( int i = 0; i < 3; i++ )
- {
- unsigned n = h.len_secs [i] - '0';
- if ( n > 9 )
- {
- // ignore single-digit text lengths
- // (except if author field is present and begins at offset 1, ugh)
- if ( i == 1 && (h.author [0] || !h.author [1]) )
- len_secs = 0;
- break;
- }
- len_secs *= 10;
- len_secs += n;
- }
- if ( !len_secs || len_secs > 0x1FFF )
- len_secs = get_le16( h.len_secs );
- if ( len_secs < 0x1FFF )
- out->length = len_secs * 1000;
-
- int offset = (h.author [0] < ' ' || unsigned (h.author [0] - '0') <= 9);
- Gme_File::copy_field_( out->author, &h.author [offset], sizeof h.author - offset );
-
- GME_COPY_FIELD( h, out, song );
- GME_COPY_FIELD( h, out, game );
- GME_COPY_FIELD( h, out, dumper );
- GME_COPY_FIELD( h, out, comment );
-
- if ( xid6_size )
- get_spc_xid6( xid6, xid6_size, out );
-}
-
-blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
-{
- get_spc_info( header(), trailer(), trailer_size(), out );
- return 0;
-}
-
-static blargg_err_t check_spc_header( void const* header )
-{
- if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Spc_File : Gme_Info_
-{
- Spc_Emu::header_t header;
- blargg_vector<byte> xid6;
-
- Spc_File() { set_type( gme_spc_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- long file_size = in.remain();
- if ( file_size < Snes_Spc::spc_file_size )
- return gme_wrong_file_type;
- RETURN_ERR( in.read( &header, Spc_Emu::header_size ) );
- RETURN_ERR( check_spc_header( header.tag ) );
- long const xid6_offset = 0x10200;
- long xid6_size = file_size - xid6_offset;
- if ( xid6_size > 0 )
- {
- RETURN_ERR( xid6.resize( xid6_size ) );
- RETURN_ERR( in.skip( xid6_offset - Spc_Emu::header_size ) );
- RETURN_ERR( in.read( xid6.begin(), xid6.size() ) );
- }
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- get_spc_info( header, xid6.begin(), xid6.size(), out );
- return 0;
- }
-};
-
-static Music_Emu* new_spc_emu () { return BLARGG_NEW Spc_Emu ; }
-static Music_Emu* new_spc_file() { return BLARGG_NEW Spc_File; }
-
-static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &new_spc_file, "SPC", 0 };
-gme_type_t const gme_spc_type = &gme_spc_type_;
-
-
-// Setup
-
-blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
-{
- apu.set_gain( gain() );
- if ( sample_rate != native_sample_rate )
- {
- RETURN_ERR( resampler.buffer_size( native_sample_rate / 20 * 2 ) );
- resampler.time_ratio( (double) native_sample_rate / sample_rate, 0.9965 );
- }
- return 0;
-}
-
-void Spc_Emu::mute_voices_( int m )
-{
- Music_Emu::mute_voices_( m );
- apu.mute_voices( m );
-}
-
-blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
-{
- assert( offsetof (header_t,unused2 [46]) == header_size );
- file_data = in;
- file_size = size;
- set_voice_count( Snes_Spc::voice_count );
- if ( size < Snes_Spc::spc_file_size )
- return gme_wrong_file_type;
- return check_spc_header( in );
-}
-
-// Emulation
-
-void Spc_Emu::set_tempo_( double t ) { apu.set_tempo( t ); }
-
-blargg_err_t Spc_Emu::start_track_( int track )
-{
- RETURN_ERR( Music_Emu::start_track_( track ) );
- resampler.clear();
- RETURN_ERR( apu.load_spc( file_data, file_size ) );
- apu.clear_echo();
- return 0;
-}
-
-blargg_err_t Spc_Emu::skip_( long count )
-{
- if ( sample_rate() != native_sample_rate )
- {
- count = long (count * resampler.ratio()) & ~1;
- count -= resampler.skip_input( count );
- }
-
- // TODO: shouldn't skip be adjusted for the 64 samples read afterwards?
-
- if ( count > 0 )
- RETURN_ERR( apu.skip( count ) );
-
- // eliminate pop due to resampler
- const int resampler_latency = 64;
- sample_t buf [resampler_latency];
- return play_( resampler_latency, buf );
-}
-
-blargg_err_t Spc_Emu::play_( long count, sample_t* out )
-{
- if ( sample_rate() == native_sample_rate )
- return apu.play( count, out );
-
- long remain = count;
- while ( remain > 0 )
- {
- remain -= resampler.read( &out [count - remain], remain );
- if ( remain > 0 )
- {
- long n = resampler.max_write();
- RETURN_ERR( apu.play( n, resampler.buffer() ) );
- resampler.write( n );
- }
- }
- check( remain == 0 );
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.h
deleted file mode 100644
index ab35649c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Spc_Emu.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Super Nintendo SPC music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef SPC_EMU_H
-#define SPC_EMU_H
-
-#include "Fir_Resampler.h"
-#include "Music_Emu.h"
-#include "Snes_Spc.h"
-
-class Spc_Emu : public Music_Emu {
-public:
- // The Super Nintendo hardware samples at 32kHz. Other sample rates are
- // handled by resampling the 32kHz output; emulation accuracy is not affected.
- enum { native_sample_rate = 32000 };
-
- // SPC file header
- enum { header_size = 0x100 };
- struct header_t
- {
- char tag [35];
- byte format;
- byte version;
- byte pc [2];
- byte a, x, y, psw, sp;
- byte unused [2];
- char song [32];
- char game [32];
- char dumper [16];
- char comment [32];
- byte date [11];
- byte len_secs [3];
- byte fade_msec [4];
- char author [32]; // sometimes first char should be skipped (see official SPC spec)
- byte mute_mask;
- byte emulator;
- byte unused2 [46];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return *(header_t const*) file_data; }
-
- // Prevents channels and global volumes from being phase-negated
- void disable_surround( bool disable = true );
-
- static gme_type_t static_type() { return gme_spc_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- byte const* trailer() const; // use track_info()
- long trailer_size() const;
-
-public:
- Spc_Emu();
- ~Spc_Emu();
-protected:
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t set_sample_rate_( long );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long, sample_t* );
- blargg_err_t skip_( long );
- void mute_voices_( int );
- void set_tempo_( double );
-private:
- byte const* file_data;
- long file_size;
- Fir_Resampler<24> resampler;
- Snes_Spc apu;
-};
-
-inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.cpp
deleted file mode 100644
index 6a7cb98a..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include "blargg_endian.h"
-#include <string.h>
-#include <math.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
-double const rolloff = 0.990;
-double const oversample_factor = 1.5;
-
-Vgm_Emu::Vgm_Emu()
-{
- disable_oversampling_ = false;
- psg_rate = 0;
- set_type( gme_vgm_type );
-
- static int const types [8] = {
- wave_type | 1, wave_type | 0, wave_type | 2, noise_type | 0
- };
- set_voice_types( types );
-
- set_silence_lookahead( 1 ); // tracks should already be trimmed
-
- static equalizer_t const eq = { -14.0, 80 };
- set_equalizer( eq );
-}
-
-Vgm_Emu::~Vgm_Emu() { }
-
-// Track info
-
-static byte const* skip_gd3_str( byte const* in, byte const* end )
-{
- while ( end - in >= 2 )
- {
- in += 2;
- if ( !(in [-2] | in [-1]) )
- break;
- }
- return in;
-}
-
-static byte const* get_gd3_str( byte const* in, byte const* end, char* field )
-{
- byte const* mid = skip_gd3_str( in, end );
- int len = (mid - in) / 2 - 1;
- if ( len > 0 )
- {
- len = min( len, (int) Gme_File::max_field_ );
- field [len] = 0;
- for ( int i = 0; i < len; i++ )
- field [i] = (in [i * 2 + 1] ? '?' : in [i * 2]); // TODO: convert to utf-8
- }
- return mid;
-}
-
-static byte const* get_gd3_pair( byte const* in, byte const* end, char* field )
-{
- return skip_gd3_str( get_gd3_str( in, end, field ), end );
-}
-
-static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
-{
- in = get_gd3_pair( in, end, out->song );
- in = get_gd3_pair( in, end, out->game );
- in = get_gd3_pair( in, end, out->system );
- in = get_gd3_pair( in, end, out->author );
- in = get_gd3_str ( in, end, out->copyright );
- in = get_gd3_pair( in, end, out->dumper );
- in = get_gd3_str ( in, end, out->comment );
-}
-
-int const gd3_header_size = 12;
-
-static long check_gd3_header( byte const* h, long remain )
-{
- if ( remain < gd3_header_size ) return 0;
- if ( memcmp( h, "Gd3 ", 4 ) ) return 0;
- if ( get_le32( h + 4 ) >= 0x200 ) return 0;
-
- long gd3_size = get_le32( h + 8 );
- if ( gd3_size > remain - gd3_header_size ) return 0;
-
- return gd3_size;
-}
-
-byte const* Vgm_Emu::gd3_data( int* size ) const
-{
- if ( size )
- *size = 0;
-
- long gd3_offset = get_le32( header().gd3_offset ) - 0x2C;
- if ( gd3_offset < 0 )
- return 0;
-
- byte const* gd3 = data + header_size + gd3_offset;
- long gd3_size = check_gd3_header( gd3, data_end - gd3 );
- if ( !gd3_size )
- return 0;
-
- if ( size )
- *size = gd3_size + gd3_header_size;
-
- return gd3;
-}
-
-static void get_vgm_length( Vgm_Emu::header_t const& h, track_info_t* out )
-{
- long length = get_le32( h.track_duration ) * 10 / 441;
- if ( length > 0 )
- {
- long loop = get_le32( h.loop_duration );
- if ( loop > 0 && get_le32( h.loop_offset ) )
- {
- out->loop_length = loop * 10 / 441;
- out->intro_length = length - out->loop_length;
- }
- else
- {
- out->length = length; // 1000 / 44100 (VGM files used 44100 as timebase)
- out->intro_length = length; // make it clear that track is no longer than length
- out->loop_length = 0;
- }
- }
-}
-
-blargg_err_t Vgm_Emu::track_info_( track_info_t* out, int ) const
-{
- get_vgm_length( header(), out );
-
- int size;
- byte const* gd3 = gd3_data( &size );
- if ( gd3 )
- parse_gd3( gd3 + gd3_header_size, gd3 + size, out );
-
- return 0;
-}
-
-static blargg_err_t check_vgm_header( Vgm_Emu::header_t const& h )
-{
- if ( memcmp( h.tag, "Vgm ", 4 ) )
- return gme_wrong_file_type;
- return 0;
-}
-
-struct Vgm_File : Gme_Info_
-{
- Vgm_Emu::header_t h;
- blargg_vector<byte> gd3;
-
- Vgm_File() { set_type( gme_vgm_type ); }
-
- blargg_err_t load_( Data_Reader& in )
- {
- long file_size = in.remain();
- if ( file_size <= Vgm_Emu::header_size )
- return gme_wrong_file_type;
-
- RETURN_ERR( in.read( &h, Vgm_Emu::header_size ) );
- RETURN_ERR( check_vgm_header( h ) );
-
- long gd3_offset = get_le32( h.gd3_offset ) - 0x2C;
- long remain = file_size - Vgm_Emu::header_size - gd3_offset;
- byte gd3_h [gd3_header_size];
- if ( gd3_offset > 0 && remain >= gd3_header_size )
- {
- RETURN_ERR( in.skip( gd3_offset ) );
- RETURN_ERR( in.read( gd3_h, sizeof gd3_h ) );
- long gd3_size = check_gd3_header( gd3_h, remain );
- if ( gd3_size )
- {
- RETURN_ERR( gd3.resize( gd3_size ) );
- RETURN_ERR( in.read( gd3.begin(), gd3.size() ) );
- }
- }
- return 0;
- }
-
- blargg_err_t track_info_( track_info_t* out, int ) const
- {
- get_vgm_length( h, out );
- if ( gd3.size() )
- parse_gd3( gd3.begin(), gd3.end(), out );
- return 0;
- }
-};
-
-static Music_Emu* new_vgm_emu () { return BLARGG_NEW Vgm_Emu ; }
-static Music_Emu* new_vgm_file() { return BLARGG_NEW Vgm_File; }
-
-static gme_type_t_ const gme_vgm_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGM", 1 };
-gme_type_t const gme_vgm_type = &gme_vgm_type_;
-
-static gme_type_t_ const gme_vgz_type_ = { "Sega SMS/Genesis", 1, &new_vgm_emu, &new_vgm_file, "VGZ", 1 };
-gme_type_t const gme_vgz_type = &gme_vgz_type_;
-
-
-// Setup
-
-void Vgm_Emu::set_tempo_( double t )
-{
- if ( psg_rate )
- {
- vgm_rate = (long) (44100 * t + 0.5);
- blip_time_factor = (long) floor( double (1L << blip_time_bits) / vgm_rate * psg_rate + 0.5 );
- //debug_printf( "blip_time_factor: %ld\n", blip_time_factor );
- //debug_printf( "vgm_rate: %ld\n", vgm_rate );
- // TODO: remove? calculates vgm_rate more accurately (above differs at most by one Hz only)
- //blip_time_factor = (long) floor( double (1L << blip_time_bits) * psg_rate / 44100 / t + 0.5 );
- //vgm_rate = (long) floor( double (1L << blip_time_bits) * psg_rate / blip_time_factor + 0.5 );
-
- fm_time_factor = 2 + (long) floor( fm_rate * (1L << fm_time_bits) / vgm_rate + 0.5 );
- }
-}
-
-blargg_err_t Vgm_Emu::set_sample_rate_( long sample_rate )
-{
- RETURN_ERR( blip_buf.set_sample_rate( sample_rate, 1000 / 30 ) );
- return Classic_Emu::set_sample_rate_( sample_rate );
-}
-
-void Vgm_Emu::update_eq( blip_eq_t const& eq )
-{
- psg.treble_eq( eq );
- dac_synth.treble_eq( eq );
-}
-
-void Vgm_Emu::set_voice( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r )
-{
- if ( i < psg.osc_count )
- psg.osc_output( i, c, l, r );
-}
-
-void Vgm_Emu::mute_voices_( int mask )
-{
- Classic_Emu::mute_voices_( mask );
- dac_synth.output( &blip_buf );
- if ( uses_fm )
- {
- psg.output( (mask & 0x80) ? 0 : &blip_buf );
- if ( ym2612.enabled() )
- {
- dac_synth.volume( (mask & 0x40) ? 0.0 : 0.1115 / 256 * fm_gain * gain() );
- ym2612.mute_voices( mask );
- }
-
- if ( ym2413.enabled() )
- {
- int m = mask & 0x3F;
- if ( mask & 0x20 )
- m |= 0x01E0; // channels 5-8
- if ( mask & 0x40 )
- m |= 0x3E00;
- ym2413.mute_voices( m );
- }
- }
-}
-
-blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
-{
- assert( offsetof (header_t,unused2 [8]) == header_size );
-
- if ( new_size <= header_size )
- return gme_wrong_file_type;
-
- header_t const& h = *(header_t const*) new_data;
-
- RETURN_ERR( check_vgm_header( h ) );
-
- check( get_le32( h.version ) <= 0x150 );
-
- // psg rate
- psg_rate = get_le32( h.psg_rate );
- if ( !psg_rate )
- psg_rate = 3579545;
- blip_buf.clock_rate( psg_rate );
-
- data = new_data;
- data_end = new_data + new_size;
-
- // get loop
- loop_begin = data_end;
- if ( get_le32( h.loop_offset ) )
- loop_begin = &data [get_le32( h.loop_offset ) + offsetof (header_t,loop_offset)];
-
- set_voice_count( psg.osc_count );
-
- RETURN_ERR( setup_fm() );
-
- static const char* const fm_names [] = {
- "FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PCM", "PSG"
- };
- static const char* const psg_names [] = { "Square 1", "Square 2", "Square 3", "Noise" };
- set_voice_names( uses_fm ? fm_names : psg_names );
-
- // do after FM in case output buffer is changed
- return Classic_Emu::setup_buffer( psg_rate );
-}
-
-blargg_err_t Vgm_Emu::setup_fm()
-{
- long ym2612_rate = get_le32( header().ym2612_rate );
- long ym2413_rate = get_le32( header().ym2413_rate );
- if ( ym2413_rate && get_le32( header().version ) < 0x110 )
- update_fm_rates( &ym2413_rate, &ym2612_rate );
-
- uses_fm = false;
-
- fm_rate = blip_buf.sample_rate() * oversample_factor;
-
- if ( ym2612_rate )
- {
- uses_fm = true;
- if ( disable_oversampling_ )
- fm_rate = ym2612_rate / 144.0;
- Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
- RETURN_ERR( ym2612.set_rate( fm_rate, ym2612_rate ) );
- ym2612.enable( true );
- set_voice_count( 8 );
- }
-
- if ( !uses_fm && ym2413_rate )
- {
- uses_fm = true;
- if ( disable_oversampling_ )
- fm_rate = ym2413_rate / 72.0;
- Dual_Resampler::setup( fm_rate / blip_buf.sample_rate(), rolloff, fm_gain * gain() );
- int result = ym2413.set_rate( fm_rate, ym2413_rate );
- if ( result == 2 )
- return "YM2413 FM sound isn't supported";
- CHECK_ALLOC( !result );
- ym2413.enable( true );
- set_voice_count( 8 );
- }
-
- if ( uses_fm )
- {
- RETURN_ERR( Dual_Resampler::reset( blip_buf.length() * blip_buf.sample_rate() / 1000 ) );
- psg.volume( 0.135 * fm_gain * gain() );
- }
- else
- {
- ym2612.enable( false );
- ym2413.enable( false );
- psg.volume( gain() );
- }
-
- return 0;
-}
-
-// Emulation
-
-blargg_err_t Vgm_Emu::start_track_( int track )
-{
- RETURN_ERR( Classic_Emu::start_track_( track ) );
- psg.reset( get_le16( header().noise_feedback ), header().noise_width );
-
- dac_disabled = -1;
- pos = data + header_size;
- pcm_data = pos;
- pcm_pos = pos;
- dac_amp = -1;
- vgm_time = 0;
- if ( get_le32( header().version ) >= 0x150 )
- {
- long data_offset = get_le32( header().data_offset );
- check( data_offset );
- if ( data_offset )
- pos += data_offset + offsetof (header_t,data_offset) - 0x40;
- }
-
- if ( uses_fm )
- {
- if ( ym2413.enabled() )
- ym2413.reset();
-
- if ( ym2612.enabled() )
- ym2612.reset();
-
- fm_time_offset = 0;
- blip_buf.clear();
- Dual_Resampler::clear();
- }
- return 0;
-}
-
-blargg_err_t Vgm_Emu::run_clocks( blip_time_t& time_io, int msec )
-{
- time_io = run_commands( msec * vgm_rate / 1000 );
- psg.end_frame( time_io );
- return 0;
-}
-
-blargg_err_t Vgm_Emu::play_( long count, sample_t* out )
-{
- if ( !uses_fm )
- return Classic_Emu::play_( count, out );
-
- Dual_Resampler::dual_play( count, out, blip_buf );
- return 0;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.h
deleted file mode 100644
index bcfa506b..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Sega Master System/Mark III, Sega Genesis/Mega Drive, BBC Micro VGM music file emulator
-
-// Game_Music_Emu 0.5.5
-#ifndef VGM_EMU_H
-#define VGM_EMU_H
-
-#include "Vgm_Emu_Impl.h"
-
-// Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips.
-// Supports custom sound buffer and frequency equalization when VGM uses just the PSG.
-// FM sound chips can be run at their proper rates, or slightly higher to reduce
-// aliasing on high notes. Currently YM2413 support requires that you supply a
-// YM2413 sound chip emulator. I can provide one I've modified to work with the library.
-class Vgm_Emu : public Vgm_Emu_Impl {
-public:
- // True if custom buffer and custom equalization are supported
- // TODO: move into Music_Emu and rename to something like supports_custom_buffer()
- bool is_classic_emu() const { return !uses_fm; }
-
- // Disable running FM chips at higher than normal rate. Will result in slightly
- // more aliasing of high notes.
- void disable_oversampling( bool disable = true ) { disable_oversampling_ = disable; }
-
- // VGM header format
- enum { header_size = 0x40 };
- struct header_t
- {
- char tag [4];
- byte data_size [4];
- byte version [4];
- byte psg_rate [4];
- byte ym2413_rate [4];
- byte gd3_offset [4];
- byte track_duration [4];
- byte loop_offset [4];
- byte loop_duration [4];
- byte frame_rate [4];
- byte noise_feedback [2];
- byte noise_width;
- byte unused1;
- byte ym2612_rate [4];
- byte ym2151_rate [4];
- byte data_offset [4];
- byte unused2 [8];
- };
-
- // Header for currently loaded file
- header_t const& header() const { return *(header_t const*) data; }
-
- static gme_type_t static_type() { return gme_vgm_type; }
-
-public:
- // deprecated
- Music_Emu::load;
- blargg_err_t load( header_t const& h, Data_Reader& in ) // use Remaining_Reader
- { return load_remaining_( &h, sizeof h, in ); }
- byte const* gd3_data( int* size_out = 0 ) const; // use track_info()
-
-public:
- Vgm_Emu();
- ~Vgm_Emu();
-protected:
- blargg_err_t track_info_( track_info_t*, int track ) const;
- blargg_err_t load_mem_( byte const*, long );
- blargg_err_t set_sample_rate_( long sample_rate );
- blargg_err_t start_track_( int );
- blargg_err_t play_( long count, sample_t* );
- blargg_err_t run_clocks( blip_time_t&, int );
- void set_tempo_( double );
- void mute_voices_( int mask );
- void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* );
- void update_eq( blip_eq_t const& );
-private:
- // removed; use disable_oversampling() and set_tempo() instead
- Vgm_Emu( bool oversample, double tempo = 1.0 );
- double fm_rate;
- long psg_rate;
- long vgm_rate;
- bool disable_oversampling_;
- bool uses_fm;
- blargg_err_t setup_fm();
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.cpp
deleted file mode 100644
index 5a9b724a..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Vgm_Emu.h"
-
-#include <math.h>
-#include <string.h>
-#include "blargg_endian.h"
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-enum {
- cmd_gg_stereo = 0x4F,
- cmd_psg = 0x50,
- cmd_ym2413 = 0x51,
- cmd_ym2612_port0 = 0x52,
- cmd_ym2612_port1 = 0x53,
- cmd_ym2151 = 0x54,
- cmd_delay = 0x61,
- cmd_delay_735 = 0x62,
- cmd_delay_882 = 0x63,
- cmd_byte_delay = 0x64,
- cmd_end = 0x66,
- cmd_data_block = 0x67,
- cmd_short_delay = 0x70,
- cmd_pcm_delay = 0x80,
- cmd_pcm_seek = 0xE0,
-
- pcm_block_type = 0x00,
- ym2612_dac_port = 0x2A
-};
-
-inline int command_len( int command )
-{
- switch ( command >> 4 )
- {
- case 0x03:
- case 0x04:
- return 2;
-
- case 0x05:
- case 0x0A:
- case 0x0B:
- return 3;
-
- case 0x0C:
- case 0x0D:
- return 4;
-
- case 0x0E:
- case 0x0F:
- return 5;
- }
-
- check( false );
- return 1;
-}
-
-template<class Emu>
-inline void Ym_Emu<Emu>::begin_frame( short* p )
-{
- require( enabled() );
- out = p;
- last_time = 0;
-}
-
-template<class Emu>
-inline int Ym_Emu<Emu>::run_until( int time )
-{
- int count = time - last_time;
- if ( count > 0 )
- {
- if ( last_time < 0 )
- return false;
- last_time = time;
- short* p = out;
- out += count * Emu::out_chan_count;
- Emu::run( count, p );
- }
- return true;
-}
-
-inline Vgm_Emu_Impl::fm_time_t Vgm_Emu_Impl::to_fm_time( vgm_time_t t ) const
-{
- return (t * fm_time_factor + fm_time_offset) >> fm_time_bits;
-}
-
-inline blip_time_t Vgm_Emu_Impl::to_blip_time( vgm_time_t t ) const
-{
- return (t * blip_time_factor) >> blip_time_bits;
-}
-
-void Vgm_Emu_Impl::write_pcm( vgm_time_t vgm_time, int amp )
-{
- blip_time_t blip_time = to_blip_time( vgm_time );
- int old = dac_amp;
- int delta = amp - old;
- dac_amp = amp;
- if ( old >= 0 )
- dac_synth.offset_inline( blip_time, delta, &blip_buf );
- else
- dac_amp |= dac_disabled;
-}
-
-blip_time_t Vgm_Emu_Impl::run_commands( vgm_time_t end_time )
-{
- vgm_time_t vgm_time = this->vgm_time;
- byte const* pos = this->pos;
- if ( pos >= data_end )
- {
- set_track_ended();
- if ( pos > data_end )
- set_warning( "Stream lacked end event" );
- }
-
- while ( vgm_time < end_time && pos < data_end )
- {
- // TODO: be sure there are enough bytes left in stream for particular command
- // so we don't read past end
- switch ( *pos++ )
- {
- case cmd_end:
- pos = loop_begin; // if not looped, loop_begin == data_end
- break;
-
- case cmd_delay_735:
- vgm_time += 735;
- break;
-
- case cmd_delay_882:
- vgm_time += 882;
- break;
-
- case cmd_gg_stereo:
- psg.write_ggstereo( to_blip_time( vgm_time ), *pos++ );
- break;
-
- case cmd_psg:
- psg.write_data( to_blip_time( vgm_time ), *pos++ );
- break;
-
- case cmd_delay:
- vgm_time += pos [1] * 0x100L + pos [0];
- pos += 2;
- break;
-
- case cmd_byte_delay:
- vgm_time += *pos++;
- break;
-
- case cmd_ym2413:
- if ( ym2413.run_until( to_fm_time( vgm_time ) ) )
- ym2413.write( pos [0], pos [1] );
- pos += 2;
- break;
-
- case cmd_ym2612_port0:
- if ( pos [0] == ym2612_dac_port )
- {
- write_pcm( vgm_time, pos [1] );
- }
- else if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
- {
- if ( pos [0] == 0x2B )
- {
- dac_disabled = (pos [1] >> 7 & 1) - 1;
- dac_amp |= dac_disabled;
- }
- ym2612.write0( pos [0], pos [1] );
- }
- pos += 2;
- break;
-
- case cmd_ym2612_port1:
- if ( ym2612.run_until( to_fm_time( vgm_time ) ) )
- ym2612.write1( pos [0], pos [1] );
- pos += 2;
- break;
-
- case cmd_data_block: {
- check( *pos == cmd_end );
- int type = pos [1];
- long size = get_le32( pos + 2 );
- pos += 6;
- if ( type == pcm_block_type )
- pcm_data = pos;
- pos += size;
- break;
- }
-
- case cmd_pcm_seek:
- pcm_pos = pcm_data + pos [3] * 0x1000000L + pos [2] * 0x10000L +
- pos [1] * 0x100L + pos [0];
- pos += 4;
- break;
-
- default:
- int cmd = pos [-1];
- switch ( cmd & 0xF0 )
- {
- case cmd_pcm_delay:
- write_pcm( vgm_time, *pcm_pos++ );
- vgm_time += cmd & 0x0F;
- break;
-
- case cmd_short_delay:
- vgm_time += (cmd & 0x0F) + 1;
- break;
-
- case 0x50:
- pos += 2;
- break;
-
- default:
- pos += command_len( cmd ) - 1;
- set_warning( "Unknown stream event" );
- }
- }
- }
- vgm_time -= end_time;
- this->pos = pos;
- this->vgm_time = vgm_time;
-
- return to_blip_time( end_time );
-}
-
-int Vgm_Emu_Impl::play_frame( blip_time_t blip_time, int sample_count, sample_t* buf )
-{
- // to do: timing is working mostly by luck
-
- int min_pairs = sample_count >> 1;
- int vgm_time = ((long) min_pairs << fm_time_bits) / fm_time_factor - 1;
- assert( to_fm_time( vgm_time ) <= min_pairs );
- int pairs = min_pairs;
- while ( (pairs = to_fm_time( vgm_time )) < min_pairs )
- vgm_time++;
- //debug_printf( "pairs: %d, min_pairs: %d\n", pairs, min_pairs );
-
- if ( ym2612.enabled() )
- {
- ym2612.begin_frame( buf );
- memset( buf, 0, pairs * stereo * sizeof *buf );
- }
- else if ( ym2413.enabled() )
- {
- ym2413.begin_frame( buf );
- }
-
- run_commands( vgm_time );
- ym2612.run_until( pairs );
- ym2413.run_until( pairs );
-
- fm_time_offset = (vgm_time * fm_time_factor + fm_time_offset) -
- ((long) pairs << fm_time_bits);
-
- psg.end_frame( blip_time );
-
- return pairs * stereo;
-}
-
-// Update pre-1.10 header FM rates by scanning commands
-void Vgm_Emu_Impl::update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const
-{
- byte const* p = data + 0x40;
- while ( p < data_end )
- {
- switch ( *p )
- {
- case cmd_end:
- return;
-
- case cmd_psg:
- case cmd_byte_delay:
- p += 2;
- break;
-
- case cmd_delay:
- p += 3;
- break;
-
- case cmd_data_block:
- p += 7 + get_le32( p + 3 );
- break;
-
- case cmd_ym2413:
- *ym2612_rate = 0;
- return;
-
- case cmd_ym2612_port0:
- case cmd_ym2612_port1:
- *ym2612_rate = *ym2413_rate;
- *ym2413_rate = 0;
- return;
-
- case cmd_ym2151:
- *ym2413_rate = 0;
- *ym2612_rate = 0;
- return;
-
- default:
- p += command_len( *p );
- }
- }
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.h b/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.h
deleted file mode 100644
index 8a73c328..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Vgm_Emu_Impl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Low-level parts of Vgm_Emu
-
-// Game_Music_Emu 0.5.5
-#ifndef VGM_EMU_IMPL_H
-#define VGM_EMU_IMPL_H
-
-#include "Dual_Resampler.h"
-#include "Classic_Emu.h"
-#include "Ym2413_Emu.h"
-#include "Ym2612_Emu.h"
-#include "Sms_Apu.h"
-
-template<class Emu>
-class Ym_Emu : public Emu {
-protected:
- int last_time;
- short* out;
- enum { disabled_time = -1 };
-public:
- Ym_Emu() : last_time( disabled_time ), out( NULL ) { }
- void enable( bool b ) { last_time = b ? 0 : disabled_time; }
- bool enabled() const { return last_time != disabled_time; }
- void begin_frame( short* p );
- int run_until( int time );
-};
-
-class Vgm_Emu_Impl : public Classic_Emu, private Dual_Resampler {
-public:
- typedef Classic_Emu::sample_t sample_t;
-protected:
- enum { stereo = 2 };
-
- typedef int vgm_time_t;
-
- enum { fm_time_bits = 12 };
- typedef int fm_time_t;
- long fm_time_offset;
- int fm_time_factor;
- fm_time_t to_fm_time( vgm_time_t ) const;
-
- enum { blip_time_bits = 12 };
- int blip_time_factor;
- blip_time_t to_blip_time( vgm_time_t ) const;
-
- byte const* data;
- byte const* loop_begin;
- byte const* data_end;
- void update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const;
-
- vgm_time_t vgm_time;
- byte const* pos;
- blip_time_t run_commands( vgm_time_t );
- int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf );
-
- byte const* pcm_data;
- byte const* pcm_pos;
- int dac_amp;
- int dac_disabled; // -1 if disabled
- void write_pcm( vgm_time_t, int amp );
-
- Ym_Emu<Ym2612_Emu> ym2612;
- Ym_Emu<Ym2413_Emu> ym2413;
-
- Blip_Buffer blip_buf;
- Sms_Apu psg;
- Blip_Synth<blip_med_quality,1> dac_synth;
-
- friend class Vgm_Emu;
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.cpp
deleted file mode 100644
index be5b2d8c..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-
-// Use in place of Ym2413_Emu.cpp and ym2413.c to disable support for this chip
-
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Ym2413_Emu.h"
-
-Ym2413_Emu::Ym2413_Emu() { }
-
-Ym2413_Emu::~Ym2413_Emu() { }
-
-int Ym2413_Emu::set_rate( double, double ) { return 2; }
-
-void Ym2413_Emu::reset() { }
-
-void Ym2413_Emu::write( int, int ) { }
-
-void Ym2413_Emu::mute_voices( int ) { }
-
-void Ym2413_Emu::run( int, sample_t* ) { }
-
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.h
deleted file mode 100644
index 42314435..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ym2413_Emu.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// YM2413 FM sound chip emulator interface
-
-// Game_Music_Emu 0.5.5
-#ifndef YM2413_EMU_H
-#define YM2413_EMU_H
-
-class Ym2413_Emu {
- struct OPLL* opll;
-public:
- Ym2413_Emu();
- ~Ym2413_Emu();
-
- // Set output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- int set_rate( double sample_rate, double clock_rate );
-
- // Reset to power-up state
- void reset();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { channel_count = 14 };
- void mute_voices( int mask );
-
- // Write 'data' to 'addr'
- void write( int addr, int data );
-
- // Run and write pair_count samples to output
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.cpp b/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.cpp
deleted file mode 100644
index 390fdfce..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.cpp
+++ /dev/null
@@ -1,1319 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-// Based on Gens 2.10 ym2612.c
-
-#include "Ym2612_Emu.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <stdio.h>
-#include <math.h>
-
-/* Copyright (C) 2002 Stphane Dallongeville (gens AT consolemul.com) */
-/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-// This is mostly the original source in its C style and all.
-//
-// Somewhat optimized and simplified. Uses a template to generate the many
-// variants of Update_Chan. Rewrote header file. In need of full rewrite by
-// someone more familiar with FM sound and the YM2612. Has some inaccuracies
-// compared to the Sega Genesis sound, particularly being mixed at such a
-// high sample accuracy (the Genesis sounds like it has only 8 bit samples).
-// - Shay
-
-#ifdef BLARGG_ENABLE_OPTIMIZER
- #include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-const int output_bits = 14;
-
-struct slot_t
-{
- const int *DT; // parametre detune
- int MUL; // parametre "multiple de frequence"
- int TL; // Total Level = volume lorsque l'enveloppe est au plus haut
- int TLL; // Total Level ajusted
- int SLL; // Sustin Level (ajusted) = volume o l'enveloppe termine sa premiere phase de regression
- int KSR_S; // Key Scale Rate Shift = facteur de prise en compte du KSL dans la variations de l'enveloppe
- int KSR; // Key Scale Rate = cette valeur est calculee par rapport la frequence actuelle, elle va influer
- // sur les differents parametres de l'enveloppe comme l'attaque, le decay ... comme dans la realite !
- int SEG; // Type enveloppe SSG
- int env_xor;
- int env_max;
-
- const int *AR; // Attack Rate (table pointeur) = Taux d'attaque (AR[KSR])
- const int *DR; // Decay Rate (table pointeur) = Taux pour la regression (DR[KSR])
- const int *SR; // Sustin Rate (table pointeur) = Taux pour le maintien (SR[KSR])
- const int *RR; // Release Rate (table pointeur) = Taux pour le rel'chement (RR[KSR])
- int Fcnt; // Frequency Count = compteur-frequence pour determiner l'amplitude actuelle (SIN[Finc >> 16])
- int Finc; // frequency step = pas d'incrementation du compteur-frequence
- // plus le pas est grand, plus la frequence est agu (ou haute)
- int Ecurp; // Envelope current phase = cette variable permet de savoir dans quelle phase
- // de l'enveloppe on se trouve, par exemple phase d'attaque ou phase de maintenue ...
- // en fonction de la valeur de cette variable, on va appeler une fonction permettant
- // de mettre jour l'enveloppe courante.
- int Ecnt; // Envelope counter = le compteur-enveloppe permet de savoir o l'on se trouve dans l'enveloppe
- int Einc; // Envelope step courant
- int Ecmp; // Envelope counter limite pour la prochaine phase
- int EincA; // Envelope step for Attack = pas d'incrementation du compteur durant la phase d'attaque
- // cette valeur est egal AR[KSR]
- int EincD; // Envelope step for Decay = pas d'incrementation du compteur durant la phase de regression
- // cette valeur est egal DR[KSR]
- int EincS; // Envelope step for Sustain = pas d'incrementation du compteur durant la phase de maintenue
- // cette valeur est egal SR[KSR]
- int EincR; // Envelope step for Release = pas d'incrementation du compteur durant la phase de rel'chement
- // cette valeur est egal RR[KSR]
- int *OUTp; // pointeur of SLOT output = pointeur permettant de connecter la sortie de ce slot l'entree
- // d'un autre ou carrement la sortie de la voie
- int INd; // input data of the slot = donnees en entree du slot
- int ChgEnM; // Change envelop mask.
- int AMS; // AMS depth level of this SLOT = degre de modulation de l'amplitude par le LFO
- int AMSon; // AMS enable flag = drapeau d'activation de l'AMS
-};
-
-struct channel_t
-{
- int S0_OUT[4]; // anciennes sorties slot 0 (pour le feed back)
- int LEFT; // LEFT enable flag
- int RIGHT; // RIGHT enable flag
- int ALGO; // Algorythm = determine les connections entre les operateurs
- int FB; // shift count of self feed back = degre de "Feed-Back" du SLOT 1 (il est son unique entree)
- int FMS; // Frequency Modulation Sensitivity of channel = degre de modulation de la frequence sur la voie par le LFO
- int AMS; // Amplitude Modulation Sensitivity of channel = degre de modulation de l'amplitude sur la voie par le LFO
- int FNUM[4]; // hauteur frequence de la voie (+ 3 pour le mode special)
- int FOCT[4]; // octave de la voie (+ 3 pour le mode special)
- int KC[4]; // Key Code = valeur fonction de la frequence (voir KSR pour les slots, KSR = KC >> KSR_S)
- slot_t SLOT[4]; // four slot.operators = les 4 slots de la voie
- int FFlag; // Frequency step recalculation flag
-};
-
-struct state_t
-{
- int TimerBase; // TimerBase calculation
- int Status; // YM2612 Status (timer overflow)
- int TimerA; // timerA limit = valeur jusqu' laquelle le timer A doit compter
- int TimerAL;
- int TimerAcnt; // timerA counter = valeur courante du Timer A
- int TimerB; // timerB limit = valeur jusqu' laquelle le timer B doit compter
- int TimerBL;
- int TimerBcnt; // timerB counter = valeur courante du Timer B
- int Mode; // Mode actuel des voie 3 et 6 (normal / special)
- int DAC; // DAC enabled flag
- channel_t CHANNEL[Ym2612_Emu::channel_count]; // Les 6 voies du YM2612
- int REG[2][0x100]; // Sauvegardes des valeurs de tout les registres, c'est facultatif
- // cela nous rend le debuggage plus facile
-};
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-#define ATTACK 0
-#define DECAY 1
-#define SUBSTAIN 2
-#define RELEASE 3
-
-// SIN_LBITS <= 16
-// LFO_HBITS <= 16
-// (SIN_LBITS + SIN_HBITS) <= 26
-// (ENV_LBITS + ENV_HBITS) <= 28
-// (LFO_LBITS + LFO_HBITS) <= 28
-
-#define SIN_HBITS 12 // Sinus phase counter int part
-#define SIN_LBITS (26 - SIN_HBITS) // Sinus phase counter float part (best setting)
-
-#if (SIN_LBITS > 16)
-#define SIN_LBITS 16 // Can't be greater than 16 bits
-#endif
-
-#define ENV_HBITS 12 // Env phase counter int part
-#define ENV_LBITS (28 - ENV_HBITS) // Env phase counter float part (best setting)
-
-#define LFO_HBITS 10 // LFO phase counter int part
-#define LFO_LBITS (28 - LFO_HBITS) // LFO phase counter float part (best setting)
-
-#define SIN_LENGHT (1 << SIN_HBITS)
-#define ENV_LENGHT (1 << ENV_HBITS)
-#define LFO_LENGHT (1 << LFO_HBITS)
-
-#define TL_LENGHT (ENV_LENGHT * 3) // Env + TL scaling + LFO
-
-#define SIN_MASK (SIN_LENGHT - 1)
-#define ENV_MASK (ENV_LENGHT - 1)
-#define LFO_MASK (LFO_LENGHT - 1)
-
-#define ENV_STEP (96.0 / ENV_LENGHT) // ENV_MAX = 96 dB
-
-#define ENV_ATTACK ((ENV_LENGHT * 0) << ENV_LBITS)
-#define ENV_DECAY ((ENV_LENGHT * 1) << ENV_LBITS)
-#define ENV_END ((ENV_LENGHT * 2) << ENV_LBITS)
-
-#define MAX_OUT_BITS (SIN_HBITS + SIN_LBITS + 2) // Modulation = -4 <--> +4
-#define MAX_OUT ((1 << MAX_OUT_BITS) - 1)
-
-#define PG_CUT_OFF ((int) (78.0 / ENV_STEP))
-#define ENV_CUT_OFF ((int) (68.0 / ENV_STEP))
-
-#define AR_RATE 399128
-#define DR_RATE 5514396
-
-//#define AR_RATE 426136
-//#define DR_RATE (AR_RATE * 12)
-
-#define LFO_FMS_LBITS 9 // FIXED (LFO_FMS_BASE gives somethink as 1)
-#define LFO_FMS_BASE ((int) (0.05946309436 * 0.0338 * (double) (1 << LFO_FMS_LBITS)))
-
-#define S0 0 // Stupid typo of the YM2612
-#define S1 2
-#define S2 1
-#define S3 3
-
-inline void set_seg( slot_t& s, int seg )
-{
- s.env_xor = 0;
- s.env_max = INT_MAX;
- s.SEG = seg;
- if ( seg & 4 )
- {
- s.env_xor = ENV_MASK;
- s.env_max = ENV_MASK;
- }
-}
-
-struct tables_t
-{
- short SIN_TAB [SIN_LENGHT]; // SINUS TABLE (offset into TL TABLE)
- int LFOcnt; // LFO counter = compteur-frequence pour le LFO
- int LFOinc; // LFO step counter = pas d'incrementation du compteur-frequence du LFO
- // plus le pas est grand, plus la frequence est grande
- unsigned int AR_TAB [128]; // Attack rate table
- unsigned int DR_TAB [96]; // Decay rate table
- unsigned int DT_TAB [8] [32]; // Detune table
- unsigned int SL_TAB [16]; // Substain level table
- unsigned int NULL_RATE [32]; // Table for NULL rate
- int LFO_INC_TAB [8]; // LFO step table
-
- short ENV_TAB [2 * ENV_LENGHT + 8]; // ENV CURVE TABLE (attack & decay)
-
- short LFO_ENV_TAB [LFO_LENGHT]; // LFO AMS TABLE (adjusted for 11.8 dB)
- short LFO_FREQ_TAB [LFO_LENGHT]; // LFO FMS TABLE
- int TL_TAB [TL_LENGHT * 2]; // TOTAL LEVEL TABLE (positif and minus)
- unsigned int DECAY_TO_ATTACK [ENV_LENGHT]; // Conversion from decay to attack phase
- unsigned int FINC_TAB [2048]; // Frequency step table
-};
-
-static const unsigned char DT_DEF_TAB [4 * 32] =
-{
-// FD = 0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-
-// FD = 1
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
- 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8,
-
-// FD = 2
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
- 5, 6, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 16, 16, 16, 16,
-
-// FD = 3
- 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
- 8 , 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 20, 22, 22, 22, 22
-};
-
-static const unsigned char FKEY_TAB [16] =
-{
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 2, 3, 3, 3,
- 3, 3, 3, 3
-};
-
-static const unsigned char LFO_AMS_TAB [4] =
-{
- 31, 4, 1, 0
-};
-
-static const unsigned char LFO_FMS_TAB [8] =
-{
- LFO_FMS_BASE * 0, LFO_FMS_BASE * 1,
- LFO_FMS_BASE * 2, LFO_FMS_BASE * 3,
- LFO_FMS_BASE * 4, LFO_FMS_BASE * 6,
- LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
-};
-
-inline void YM2612_Special_Update() { }
-
-struct Ym2612_Impl
-{
- enum { channel_count = Ym2612_Emu::channel_count };
-
- state_t YM2612;
- int mute_mask;
- tables_t g;
-
- void KEY_ON( channel_t&, int );
- void KEY_OFF( channel_t&, int );
- int SLOT_SET( int, int );
- int CHANNEL_SET( int, int );
- int YM_SET( int, int );
-
- void set_rate( double sample_rate, double clock_factor );
- void reset();
- void write0( int addr, int data );
- void write1( int addr, int data );
- void run_timer( int );
- void run( int pair_count, Ym2612_Emu::sample_t* );
-};
-
-void Ym2612_Impl::KEY_ON( channel_t& ch, int nsl)
-{
- slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
-
- if (SL->Ecurp == RELEASE) // la touche est-elle rel'chee ?
- {
- SL->Fcnt = 0;
-
- // Fix Ecco 2 splash sound
-
- SL->Ecnt = (g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK) & SL->ChgEnM;
- SL->ChgEnM = ~0;
-
-// SL->Ecnt = g.DECAY_TO_ATTACK [g.ENV_TAB [SL->Ecnt >> ENV_LBITS]] + ENV_ATTACK;
-// SL->Ecnt = 0;
-
- SL->Einc = SL->EincA;
- SL->Ecmp = ENV_DECAY;
- SL->Ecurp = ATTACK;
- }
-}
-
-
-void Ym2612_Impl::KEY_OFF(channel_t& ch, int nsl)
-{
- slot_t *SL = &(ch.SLOT [nsl]); // on recupere le bon pointeur de slot
-
- if (SL->Ecurp != RELEASE) // la touche est-elle appuyee ?
- {
- if (SL->Ecnt < ENV_DECAY) // attack phase ?
- {
- SL->Ecnt = (g.ENV_TAB [SL->Ecnt >> ENV_LBITS] << ENV_LBITS) + ENV_DECAY;
- }
-
- SL->Einc = SL->EincR;
- SL->Ecmp = ENV_END;
- SL->Ecurp = RELEASE;
- }
-}
-
-
-int Ym2612_Impl::SLOT_SET( int Adr, int data )
-{
- int nch = Adr & 3;
- if ( nch == 3 )
- return 1;
-
- channel_t& ch = YM2612.CHANNEL [nch + (Adr & 0x100 ? 3 : 0)];
- slot_t& sl = ch.SLOT [(Adr >> 2) & 3];
-
- switch ( Adr & 0xF0 )
- {
- case 0x30:
- if ( (sl.MUL = (data & 0x0F)) != 0 ) sl.MUL <<= 1;
- else sl.MUL = 1;
-
- sl.DT = (int*) g.DT_TAB [(data >> 4) & 7];
-
- ch.SLOT [0].Finc = -1;
-
- break;
-
- case 0x40:
- sl.TL = data & 0x7F;
-
- // SOR2 do a lot of TL adjustement and this fix R.Shinobi jump sound...
- YM2612_Special_Update();
-
-#if ((ENV_HBITS - 7) < 0)
- sl.TLL = sl.TL >> (7 - ENV_HBITS);
-#else
- sl.TLL = sl.TL << (ENV_HBITS - 7);
-#endif
-
- break;
-
- case 0x50:
- sl.KSR_S = 3 - (data >> 6);
-
- ch.SLOT [0].Finc = -1;
-
- if (data &= 0x1F) sl.AR = (int*) &g.AR_TAB [data << 1];
- else sl.AR = (int*) &g.NULL_RATE [0];
-
- sl.EincA = sl.AR [sl.KSR];
- if (sl.Ecurp == ATTACK) sl.Einc = sl.EincA;
- break;
-
- case 0x60:
- if ( (sl.AMSon = (data & 0x80)) != 0 ) sl.AMS = ch.AMS;
- else sl.AMS = 31;
-
- if (data &= 0x1F) sl.DR = (int*) &g.DR_TAB [data << 1];
- else sl.DR = (int*) &g.NULL_RATE [0];
-
- sl.EincD = sl.DR [sl.KSR];
- if (sl.Ecurp == DECAY) sl.Einc = sl.EincD;
- break;
-
- case 0x70:
- if (data &= 0x1F) sl.SR = (int*) &g.DR_TAB [data << 1];
- else sl.SR = (int*) &g.NULL_RATE [0];
-
- sl.EincS = sl.SR [sl.KSR];
- if ((sl.Ecurp == SUBSTAIN) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincS;
- break;
-
- case 0x80:
- sl.SLL = g.SL_TAB [data >> 4];
-
- sl.RR = (int*) &g.DR_TAB [((data & 0xF) << 2) + 2];
-
- sl.EincR = sl.RR [sl.KSR];
- if ((sl.Ecurp == RELEASE) && (sl.Ecnt < ENV_END)) sl.Einc = sl.EincR;
- break;
-
- case 0x90:
- // SSG-EG envelope shapes :
- /*
- E At Al H
-
- 1 0 0 0 \\\\
- 1 0 0 1 \___
- 1 0 1 0 \/\/
- 1 0 1 1 \
- 1 1 0 0 ////
- 1 1 0 1 /
- 1 1 1 0 /\/\
- 1 1 1 1 /___
-
- E = SSG-EG enable
- At = Start negate
- Al = Altern
- H = Hold */
-
- set_seg( sl, (data & 8) ? (data & 0x0F) : 0 );
- break;
- }
-
- return 0;
-}
-
-
-int Ym2612_Impl::CHANNEL_SET( int Adr, int data )
-{
- int num = Adr & 3;
- if ( num == 3 )
- return 1;
-
- channel_t& ch = YM2612.CHANNEL [num + (Adr & 0x100 ? 3 : 0)];
-
- switch ( Adr & 0xFC )
- {
- case 0xA0:
- YM2612_Special_Update();
-
- ch.FNUM [0] = (ch.FNUM [0] & 0x700) + data;
- ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
- ch.SLOT [0].Finc = -1;
- break;
-
- case 0xA4:
- YM2612_Special_Update();
-
- ch.FNUM [0] = (ch.FNUM [0] & 0x0FF) + ((data & 0x07) << 8);
- ch.FOCT [0] = (data & 0x38) >> 3;
- ch.KC [0] = (ch.FOCT [0] << 2) | FKEY_TAB [ch.FNUM [0] >> 7];
-
- ch.SLOT [0].Finc = -1;
- break;
-
- case 0xA8:
- if ( Adr < 0x100 )
- {
- num++;
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x700) + data;
- YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
- FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1;
- }
- break;
-
- case 0xAC:
- if ( Adr < 0x100 )
- {
- num++;
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].FNUM [num] = (YM2612.CHANNEL [2].FNUM [num] & 0x0FF) + ((data & 0x07) << 8);
- YM2612.CHANNEL [2].FOCT [num] = (data & 0x38) >> 3;
- YM2612.CHANNEL [2].KC [num] = (YM2612.CHANNEL [2].FOCT [num] << 2) |
- FKEY_TAB [YM2612.CHANNEL [2].FNUM [num] >> 7];
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1;
- }
- break;
-
- case 0xB0:
- if ( ch.ALGO != (data & 7) )
- {
- // Fix VectorMan 2 heli sound (level 1)
- YM2612_Special_Update();
-
- ch.ALGO = data & 7;
-
- ch.SLOT [0].ChgEnM = 0;
- ch.SLOT [1].ChgEnM = 0;
- ch.SLOT [2].ChgEnM = 0;
- ch.SLOT [3].ChgEnM = 0;
- }
-
- ch.FB = 9 - ((data >> 3) & 7); // Real thing ?
-
-// if (ch.FB = ((data >> 3) & 7)) ch.FB = 9 - ch.FB; // Thunder force 4 (music stage 8), Gynoug, Aladdin bug sound...
-// else ch.FB = 31;
- break;
-
- case 0xB4: {
- YM2612_Special_Update();
-
- ch.LEFT = 0 - ((data >> 7) & 1);
- ch.RIGHT = 0 - ((data >> 6) & 1);
-
- ch.AMS = LFO_AMS_TAB [(data >> 4) & 3];
- ch.FMS = LFO_FMS_TAB [data & 7];
-
- for ( int i = 0; i < 4; i++ )
- {
- slot_t& sl = ch.SLOT [i];
- sl.AMS = (sl.AMSon ? ch.AMS : 31);
- }
- break;
- }
- }
-
- return 0;
-}
-
-
-int Ym2612_Impl::YM_SET(int Adr, int data)
-{
- switch ( Adr )
- {
- case 0x22:
- if (data & 8) // LFO enable
- {
- // Cool Spot music 1, LFO modified severals time which
- // distord the sound, have to check that on a real genesis...
-
- g.LFOinc = g.LFO_INC_TAB [data & 7];
- }
- else
- {
- g.LFOinc = g.LFOcnt = 0;
- }
- break;
-
- case 0x24:
- YM2612.TimerA = (YM2612.TimerA & 0x003) | (((int) data) << 2);
-
- if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
- {
- YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
- }
- break;
-
- case 0x25:
- YM2612.TimerA = (YM2612.TimerA & 0x3FC) | (data & 3);
-
- if (YM2612.TimerAL != (1024 - YM2612.TimerA) << 12)
- {
- YM2612.TimerAcnt = YM2612.TimerAL = (1024 - YM2612.TimerA) << 12;
- }
- break;
-
- case 0x26:
- YM2612.TimerB = data;
-
- if (YM2612.TimerBL != (256 - YM2612.TimerB) << (4 + 12))
- {
- YM2612.TimerBcnt = YM2612.TimerBL = (256 - YM2612.TimerB) << (4 + 12);
- }
- break;
-
- case 0x27:
- // Parametre divers
- // b7 = CSM MODE
- // b6 = 3 slot mode
- // b5 = reset b
- // b4 = reset a
- // b3 = timer enable b
- // b2 = timer enable a
- // b1 = load b
- // b0 = load a
-
- if ((data ^ YM2612.Mode) & 0x40)
- {
- // We changed the channel 2 mode, so recalculate phase step
- // This fix the punch sound in Street of Rage 2
-
- YM2612_Special_Update();
-
- YM2612.CHANNEL [2].SLOT [0].Finc = -1; // recalculate phase step
- }
-
-// if ((data & 2) && (YM2612.Status & 2)) YM2612.TimerBcnt = YM2612.TimerBL;
-// if ((data & 1) && (YM2612.Status & 1)) YM2612.TimerAcnt = YM2612.TimerAL;
-
-// YM2612.Status &= (~data >> 4); // Reset du Status au cas ou c'est demande
- YM2612.Status &= (~data >> 4) & (data >> 2); // Reset Status
-
- YM2612.Mode = data;
- break;
-
- case 0x28: {
- int nch = data & 3;
- if ( nch == 3 )
- return 1;
- if ( data & 4 )
- nch += 3;
- channel_t& ch = YM2612.CHANNEL [nch];
-
- YM2612_Special_Update();
-
- if (data & 0x10) KEY_ON(ch, S0); // On appuie sur la touche pour le slot 1
- else KEY_OFF(ch, S0); // On rel'che la touche pour le slot 1
- if (data & 0x20) KEY_ON(ch, S1); // On appuie sur la touche pour le slot 3
- else KEY_OFF(ch, S1); // On rel'che la touche pour le slot 3
- if (data & 0x40) KEY_ON(ch, S2); // On appuie sur la touche pour le slot 2
- else KEY_OFF(ch, S2); // On rel'che la touche pour le slot 2
- if (data & 0x80) KEY_ON(ch, S3); // On appuie sur la touche pour le slot 4
- else KEY_OFF(ch, S3); // On rel'che la touche pour le slot 4
- break;
- }
-
- case 0x2B:
- if (YM2612.DAC ^ (data & 0x80)) YM2612_Special_Update();
-
- YM2612.DAC = data & 0x80; // activation/desactivation du DAC
- break;
- }
-
- return 0;
-}
-
-void Ym2612_Impl::set_rate( double sample_rate, double clock_rate )
-{
- assert( sample_rate );
- assert( clock_rate > sample_rate );
-
- int i;
-
- // 144 = 12 * (prescale * 2) = 12 * 6 * 2
- // prescale set to 6 by default
-
- double Frequence = clock_rate / sample_rate / 144.0;
- if ( fabs( Frequence - 1.0 ) < 0.0000001 )
- Frequence = 1.0;
- YM2612.TimerBase = int (Frequence * 4096.0);
-
- // Tableau TL :
- // [0 - 4095] = +output [4095 - ...] = +output overflow (fill with 0)
- // [12288 - 16383] = -output [16384 - ...] = -output overflow (fill with 0)
-
- for(i = 0; i < TL_LENGHT; i++)
- {
- if (i >= PG_CUT_OFF) // YM2612 cut off sound after 78 dB (14 bits output ?)
- {
- g.TL_TAB [TL_LENGHT + i] = g.TL_TAB [i] = 0;
- }
- else
- {
- double x = MAX_OUT; // Max output
- x /= pow( 10.0, (ENV_STEP * i) / 20.0 ); // Decibel -> Voltage
-
- g.TL_TAB [i] = (int) x;
- g.TL_TAB [TL_LENGHT + i] = -g.TL_TAB [i];
- }
- }
-
- // Tableau SIN :
- // g.SIN_TAB [x] [y] = sin(x) * y;
- // x = phase and y = volume
-
- g.SIN_TAB [0] = g.SIN_TAB [SIN_LENGHT / 2] = PG_CUT_OFF;
-
- for(i = 1; i <= SIN_LENGHT / 4; i++)
- {
- double x = sin(2.0 * PI * (double) (i) / (double) (SIN_LENGHT)); // Sinus
- x = 20 * log10(1 / x); // convert to dB
-
- int j = (int) (x / ENV_STEP); // Get TL range
-
- if (j > PG_CUT_OFF) j = (int) PG_CUT_OFF;
-
- g.SIN_TAB [i] = g.SIN_TAB [(SIN_LENGHT / 2) - i] = j;
- g.SIN_TAB [(SIN_LENGHT / 2) + i] = g.SIN_TAB [SIN_LENGHT - i] = TL_LENGHT + j;
- }
-
- // Tableau LFO (LFO wav) :
-
- for(i = 0; i < LFO_LENGHT; i++)
- {
- double x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
- x += 1.0;
- x /= 2.0; // positive only
- x *= 11.8 / ENV_STEP; // ajusted to MAX enveloppe modulation
-
- g.LFO_ENV_TAB [i] = (int) x;
-
- x = sin(2.0 * PI * (double) (i) / (double) (LFO_LENGHT)); // Sinus
- x *= (double) ((1 << (LFO_HBITS - 1)) - 1);
-
- g.LFO_FREQ_TAB [i] = (int) x;
-
- }
-
- // Tableau Enveloppe :
- // g.ENV_TAB [0] -> g.ENV_TAB [ENV_LENGHT - 1] = attack curve
- // g.ENV_TAB [ENV_LENGHT] -> g.ENV_TAB [2 * ENV_LENGHT - 1] = decay curve
-
- for(i = 0; i < ENV_LENGHT; i++)
- {
- // Attack curve (x^8 - music level 2 Vectorman 2)
- double x = pow(((double) ((ENV_LENGHT - 1) - i) / (double) (ENV_LENGHT)), 8);
- x *= ENV_LENGHT;
-
- g.ENV_TAB [i] = (int) x;
-
- // Decay curve (just linear)
- x = pow(((double) (i) / (double) (ENV_LENGHT)), 1);
- x *= ENV_LENGHT;
-
- g.ENV_TAB [ENV_LENGHT + i] = (int) x;
- }
- for ( i = 0; i < 8; i++ )
- g.ENV_TAB [i + ENV_LENGHT * 2] = 0;
-
- g.ENV_TAB [ENV_END >> ENV_LBITS] = ENV_LENGHT - 1; // for the stopped state
-
- // Tableau pour la conversion Attack -> Decay and Decay -> Attack
-
- int j = ENV_LENGHT - 1;
- for ( i = 0; i < ENV_LENGHT; i++ )
- {
- while ( j && g.ENV_TAB [j] < i )
- j--;
-
- g.DECAY_TO_ATTACK [i] = j << ENV_LBITS;
- }
-
- // Tableau pour le Substain Level
-
- for(i = 0; i < 15; i++)
- {
- double x = i * 3; // 3 and not 6 (Mickey Mania first music for test)
- x /= ENV_STEP;
-
- g.SL_TAB [i] = ((int) x << ENV_LBITS) + ENV_DECAY;
- }
-
- g.SL_TAB [15] = ((ENV_LENGHT - 1) << ENV_LBITS) + ENV_DECAY; // special case : volume off
-
- // Tableau Frequency Step
-
- for(i = 0; i < 2048; i++)
- {
- double x = (double) (i) * Frequence;
-
-#if ((SIN_LBITS + SIN_HBITS - (21 - 7)) < 0)
- x /= (double) (1 << ((21 - 7) - SIN_LBITS - SIN_HBITS));
-#else
- x *= (double) (1 << (SIN_LBITS + SIN_HBITS - (21 - 7)));
-#endif
-
- x /= 2.0; // because MUL = value * 2
-
- g.FINC_TAB [i] = (unsigned int) x;
- }
-
- // Tableaux Attack & Decay Rate
-
- for(i = 0; i < 4; i++)
- {
- g.AR_TAB [i] = 0;
- g.DR_TAB [i] = 0;
- }
-
- for(i = 0; i < 60; i++)
- {
- double x = Frequence;
-
- x *= 1.0 + ((i & 3) * 0.25); // bits 0-1 : x1.00, x1.25, x1.50, x1.75
- x *= (double) (1 << ((i >> 2))); // bits 2-5 : shift bits (x2^0 - x2^15)
- x *= (double) (ENV_LENGHT << ENV_LBITS); // on ajuste pour le tableau g.ENV_TAB
-
- g.AR_TAB [i + 4] = (unsigned int) (x / AR_RATE);
- g.DR_TAB [i + 4] = (unsigned int) (x / DR_RATE);
- }
-
- for(i = 64; i < 96; i++)
- {
- g.AR_TAB [i] = g.AR_TAB [63];
- g.DR_TAB [i] = g.DR_TAB [63];
-
- g.NULL_RATE [i - 64] = 0;
- }
-
- for ( i = 96; i < 128; i++ )
- g.AR_TAB [i] = 0;
-
- // Tableau Detune
-
- for(i = 0; i < 4; i++)
- {
- for (int j = 0; j < 32; j++)
- {
-#if ((SIN_LBITS + SIN_HBITS - 21) < 0)
- double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence / (double) (1 << (21 - SIN_LBITS - SIN_HBITS));
-#else
- double y = (double) DT_DEF_TAB [(i << 5) + j] * Frequence * (double) (1 << (SIN_LBITS + SIN_HBITS - 21));
-#endif
-
- g.DT_TAB [i + 0] [j] = (int) y;
- g.DT_TAB [i + 4] [j] = (int) -y;
- }
- }
-
- // Tableau LFO
- g.LFO_INC_TAB [0] = (unsigned int) (3.98 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [1] = (unsigned int) (5.56 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [2] = (unsigned int) (6.02 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [3] = (unsigned int) (6.37 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [4] = (unsigned int) (6.88 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [5] = (unsigned int) (9.63 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [6] = (unsigned int) (48.1 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
- g.LFO_INC_TAB [7] = (unsigned int) (72.2 * (double) (1 << (LFO_HBITS + LFO_LBITS)) / sample_rate);
-
- reset();
-}
-
-const char* Ym2612_Emu::set_rate( double sample_rate, double clock_rate )
-{
- if ( !impl )
- {
- impl = (Ym2612_Impl*) malloc( sizeof *impl );
- if ( !impl )
- return "Out of memory";
- impl->mute_mask = 0;
- }
- memset( &impl->YM2612, 0, sizeof impl->YM2612 );
-
- impl->set_rate( sample_rate, clock_rate );
-
- return 0;
-}
-
-Ym2612_Emu::~Ym2612_Emu()
-{
- free( impl );
-}
-
-inline void Ym2612_Impl::write0( int opn_addr, int data )
-{
- assert( (unsigned) data <= 0xFF );
-
- if ( opn_addr < 0x30 )
- {
- YM2612.REG [0] [opn_addr] = data;
- YM_SET( opn_addr, data );
- }
- else if ( YM2612.REG [0] [opn_addr] != data )
- {
- YM2612.REG [0] [opn_addr] = data;
-
- if ( opn_addr < 0xA0 )
- SLOT_SET( opn_addr, data );
- else
- CHANNEL_SET( opn_addr, data );
- }
-}
-
-inline void Ym2612_Impl::write1( int opn_addr, int data )
-{
- assert( (unsigned) data <= 0xFF );
-
- if ( opn_addr >= 0x30 && YM2612.REG [1] [opn_addr] != data )
- {
- YM2612.REG [1] [opn_addr] = data;
-
- if ( opn_addr < 0xA0 )
- SLOT_SET( opn_addr + 0x100, data );
- else
- CHANNEL_SET( opn_addr + 0x100, data );
- }
-}
-
-void Ym2612_Emu::reset()
-{
- impl->reset();
-}
-
-void Ym2612_Impl::reset()
-{
- g.LFOcnt = 0;
- YM2612.TimerA = 0;
- YM2612.TimerAL = 0;
- YM2612.TimerAcnt = 0;
- YM2612.TimerB = 0;
- YM2612.TimerBL = 0;
- YM2612.TimerBcnt = 0;
- YM2612.DAC = 0;
-
- YM2612.Status = 0;
-
- int i;
- for ( i = 0; i < channel_count; i++ )
- {
- channel_t& ch = YM2612.CHANNEL [i];
-
- ch.LEFT = ~0;
- ch.RIGHT = ~0;
- ch.ALGO = 0;
- ch.FB = 31;
- ch.FMS = 0;
- ch.AMS = 0;
-
- for ( int j = 0 ;j < 4 ; j++ )
- {
- ch.S0_OUT [j] = 0;
- ch.FNUM [j] = 0;
- ch.FOCT [j] = 0;
- ch.KC [j] = 0;
-
- ch.SLOT [j].Fcnt = 0;
- ch.SLOT [j].Finc = 0;
- ch.SLOT [j].Ecnt = ENV_END; // Put it at the end of Decay phase...
- ch.SLOT [j].Einc = 0;
- ch.SLOT [j].Ecmp = 0;
- ch.SLOT [j].Ecurp = RELEASE;
-
- ch.SLOT [j].ChgEnM = 0;
- }
- }
-
- for ( i = 0; i < 0x100; i++ )
- {
- YM2612.REG [0] [i] = -1;
- YM2612.REG [1] [i] = -1;
- }
-
- for ( i = 0xB6; i >= 0xB4; i-- )
- {
- write0( i, 0xC0 );
- write1( i, 0xC0 );
- }
-
- for ( i = 0xB2; i >= 0x22; i-- )
- {
- write0( i, 0 );
- write1( i, 0 );
- }
-
- write0( 0x2A, 0x80 );
-}
-
-void Ym2612_Emu::write0( int addr, int data )
-{
- impl->write0( addr, data );
-}
-
-void Ym2612_Emu::write1( int addr, int data )
-{
- impl->write1( addr, data );
-}
-
-void Ym2612_Emu::mute_voices( int mask ) { impl->mute_mask = mask; }
-
-static void update_envelope_( slot_t* sl )
-{
- switch ( sl->Ecurp )
- {
- case 0:
- // Env_Attack_Next
-
- // Verified with Gynoug even in HQ (explode SFX)
- sl->Ecnt = ENV_DECAY;
-
- sl->Einc = sl->EincD;
- sl->Ecmp = sl->SLL;
- sl->Ecurp = DECAY;
- break;
-
- case 1:
- // Env_Decay_Next
-
- // Verified with Gynoug even in HQ (explode SFX)
- sl->Ecnt = sl->SLL;
-
- sl->Einc = sl->EincS;
- sl->Ecmp = ENV_END;
- sl->Ecurp = SUBSTAIN;
- break;
-
- case 2:
- // Env_Substain_Next(slot_t *SL)
- if (sl->SEG & 8) // SSG envelope type
- {
- int release = sl->SEG & 1;
-
- if ( !release )
- {
- // re KEY ON
-
- // sl->Fcnt = 0;
- // sl->ChgEnM = ~0;
-
- sl->Ecnt = 0;
- sl->Einc = sl->EincA;
- sl->Ecmp = ENV_DECAY;
- sl->Ecurp = ATTACK;
- }
-
- set_seg( *sl, (sl->SEG << 1) & 4 );
-
- if ( !release )
- break;
- }
- // fall through
-
- case 3:
- // Env_Release_Next
- sl->Ecnt = ENV_END;
- sl->Einc = 0;
- sl->Ecmp = ENV_END + 1;
- break;
-
- // default: no op
- }
-}
-
-inline void update_envelope( slot_t& sl )
-{
- int ecmp = sl.Ecmp;
- if ( (sl.Ecnt += sl.Einc) >= ecmp )
- update_envelope_( &sl );
-}
-
-template<int algo>
-struct ym2612_update_chan {
- static void func( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-};
-
-typedef void (*ym2612_update_chan_t)( tables_t&, channel_t&, Ym2612_Emu::sample_t*, int );
-
-template<int algo>
-void ym2612_update_chan<algo>::func( tables_t& g, channel_t& ch,
- Ym2612_Emu::sample_t* buf, int length )
-{
- int not_end = ch.SLOT [S3].Ecnt - ENV_END;
-
- // algo is a compile-time constant, so all conditions based on it are resolved
- // during compilation
-
- // special cases
- if ( algo == 7 )
- not_end |= ch.SLOT [S0].Ecnt - ENV_END;
-
- if ( algo >= 5 )
- not_end |= ch.SLOT [S2].Ecnt - ENV_END;
-
- if ( algo >= 4 )
- not_end |= ch.SLOT [S1].Ecnt - ENV_END;
-
- int CH_S0_OUT_1 = ch.S0_OUT [1];
-
- int in0 = ch.SLOT [S0].Fcnt;
- int in1 = ch.SLOT [S1].Fcnt;
- int in2 = ch.SLOT [S2].Fcnt;
- int in3 = ch.SLOT [S3].Fcnt;
-
- int YM2612_LFOinc = g.LFOinc;
- int YM2612_LFOcnt = g.LFOcnt + YM2612_LFOinc;
-
- if ( !not_end )
- return;
-
- do
- {
- // envelope
- int const env_LFO = g.LFO_ENV_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK];
-
- short const* const ENV_TAB = g.ENV_TAB;
-
- #define CALC_EN( x ) \
- int temp##x = ENV_TAB [ch.SLOT [S##x].Ecnt >> ENV_LBITS] + ch.SLOT [S##x].TLL; \
- int en##x = ((temp##x ^ ch.SLOT [S##x].env_xor) + (env_LFO >> ch.SLOT [S##x].AMS)) & \
- ((temp##x - ch.SLOT [S##x].env_max) >> 31);
-
- CALC_EN( 0 )
- CALC_EN( 1 )
- CALC_EN( 2 )
- CALC_EN( 3 )
-
- int const* const TL_TAB = g.TL_TAB;
-
- #define SINT( i, o ) (TL_TAB [g.SIN_TAB [(i)] + (o)])
-
- // feedback
- int CH_S0_OUT_0 = ch.S0_OUT [0];
- {
- int temp = in0 + ((CH_S0_OUT_0 + CH_S0_OUT_1) >> ch.FB);
- CH_S0_OUT_1 = CH_S0_OUT_0;
- CH_S0_OUT_0 = SINT( (temp >> SIN_LBITS) & SIN_MASK, en0 );
- }
-
- int CH_OUTd;
- if ( algo == 0 )
- {
- int temp = in1 + CH_S0_OUT_1;
- temp = in2 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 1 )
- {
- int temp = in2 + CH_S0_OUT_1 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 2 )
- {
- int temp = in2 + SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 );
- temp = in3 + CH_S0_OUT_1 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 3 )
- {
- int temp = in1 + CH_S0_OUT_1;
- temp = in3 + SINT( (temp >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 );
- }
- else if ( algo == 4 )
- {
- int temp = in3 + SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- CH_OUTd = SINT( (temp >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 );
- //DO_LIMIT
- }
- else if ( algo == 5 )
- {
- int temp = CH_S0_OUT_1;
- CH_OUTd = SINT( ((in3 + temp) >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + temp) >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( ((in2 + temp) >> SIN_LBITS) & SIN_MASK, en2 );
- //DO_LIMIT
- }
- else if ( algo == 6 )
- {
- CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( ((in1 + CH_S0_OUT_1) >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 );
- //DO_LIMIT
- }
- else if ( algo == 7 )
- {
- CH_OUTd = SINT( (in3 >> SIN_LBITS) & SIN_MASK, en3 ) +
- SINT( (in1 >> SIN_LBITS) & SIN_MASK, en1 ) +
- SINT( (in2 >> SIN_LBITS) & SIN_MASK, en2 ) + CH_S0_OUT_1;
- //DO_LIMIT
- }
-
- CH_OUTd >>= MAX_OUT_BITS - output_bits + 2;
-
- // update phase
- unsigned freq_LFO = ((g.LFO_FREQ_TAB [YM2612_LFOcnt >> LFO_LBITS & LFO_MASK] *
- ch.FMS) >> (LFO_HBITS - 1 + 1)) + (1L << (LFO_FMS_LBITS - 1));
- YM2612_LFOcnt += YM2612_LFOinc;
- in0 += (ch.SLOT [S0].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in1 += (ch.SLOT [S1].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in2 += (ch.SLOT [S2].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
- in3 += (ch.SLOT [S3].Finc * freq_LFO) >> (LFO_FMS_LBITS - 1);
-
- int t0 = buf [0] + (CH_OUTd & ch.LEFT);
- int t1 = buf [1] + (CH_OUTd & ch.RIGHT);
-
- update_envelope( ch.SLOT [0] );
- update_envelope( ch.SLOT [1] );
- update_envelope( ch.SLOT [2] );
- update_envelope( ch.SLOT [3] );
-
- ch.S0_OUT [0] = CH_S0_OUT_0;
- buf [0] = t0;
- buf [1] = t1;
- buf += 2;
- }
- while ( --length );
-
- ch.S0_OUT [1] = CH_S0_OUT_1;
-
- ch.SLOT [S0].Fcnt = in0;
- ch.SLOT [S1].Fcnt = in1;
- ch.SLOT [S2].Fcnt = in2;
- ch.SLOT [S3].Fcnt = in3;
-}
-
-static const ym2612_update_chan_t UPDATE_CHAN [8] = {
- &ym2612_update_chan<0>::func,
- &ym2612_update_chan<1>::func,
- &ym2612_update_chan<2>::func,
- &ym2612_update_chan<3>::func,
- &ym2612_update_chan<4>::func,
- &ym2612_update_chan<5>::func,
- &ym2612_update_chan<6>::func,
- &ym2612_update_chan<7>::func
-};
-
-void Ym2612_Impl::run_timer( int length )
-{
- int const step = 6;
- int remain = length;
- do
- {
- int n = step;
- if ( n > remain )
- n = remain;
- remain -= n;
-
- long i = n * YM2612.TimerBase;
- if (YM2612.Mode & 1) // Timer A ON ?
- {
- // if ((YM2612.TimerAcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
- if ((YM2612.TimerAcnt -= i) <= 0)
- {
- // timer a overflow
-
- YM2612.Status |= (YM2612.Mode & 0x04) >> 2;
- YM2612.TimerAcnt += YM2612.TimerAL;
-
- if (YM2612.Mode & 0x80)
- {
- KEY_ON( YM2612.CHANNEL [2], 0 );
- KEY_ON( YM2612.CHANNEL [2], 1 );
- KEY_ON( YM2612.CHANNEL [2], 2 );
- KEY_ON( YM2612.CHANNEL [2], 3 );
- }
- }
- }
-
- if (YM2612.Mode & 2) // Timer B ON ?
- {
- // if ((YM2612.TimerBcnt -= 14073) <= 0) // 13879=NTSC (old: 14475=NTSC 14586=PAL)
- if ((YM2612.TimerBcnt -= i) <= 0)
- {
- // timer b overflow
- YM2612.Status |= (YM2612.Mode & 0x08) >> 2;
- YM2612.TimerBcnt += YM2612.TimerBL;
- }
- }
- }
- while ( remain > 0 );
-}
-
-void Ym2612_Impl::run( int pair_count, Ym2612_Emu::sample_t* out )
-{
- if ( pair_count <= 0 )
- return;
-
- if ( YM2612.Mode & 3 )
- run_timer( pair_count );
-
- // Mise jour des pas des compteurs-frequences s'ils ont ete modifies
-
- for ( int chi = 0; chi < channel_count; chi++ )
- {
- channel_t& ch = YM2612.CHANNEL [chi];
- if ( ch.SLOT [0].Finc != -1 )
- continue;
-
- int i2 = 0;
- if ( chi == 2 && (YM2612.Mode & 0x40) )
- i2 = 2;
-
- for ( int i = 0; i < 4; i++ )
- {
- // static int seq [4] = { 2, 1, 3, 0 };
- // if ( i2 ) i2 = seq [i];
-
- slot_t& sl = ch.SLOT [i];
- int finc = g.FINC_TAB [ch.FNUM [i2]] >> (7 - ch.FOCT [i2]);
- int ksr = ch.KC [i2] >> sl.KSR_S; // keycode attenuation
- sl.Finc = (finc + sl.DT [ch.KC [i2]]) * sl.MUL;
- if (sl.KSR != ksr) // si le KSR a change alors
- { // les differents taux pour l'enveloppe sont mis jour
- sl.KSR = ksr;
-
- sl.EincA = sl.AR [ksr];
- sl.EincD = sl.DR [ksr];
- sl.EincS = sl.SR [ksr];
- sl.EincR = sl.RR [ksr];
-
- if (sl.Ecurp == ATTACK)
- {
- sl.Einc = sl.EincA;
- }
- else if (sl.Ecurp == DECAY)
- {
- sl.Einc = sl.EincD;
- }
- else if (sl.Ecnt < ENV_END)
- {
- if (sl.Ecurp == SUBSTAIN)
- sl.Einc = sl.EincS;
- else if (sl.Ecurp == RELEASE)
- sl.Einc = sl.EincR;
- }
- }
-
- if ( i2 )
- i2 = (i2 ^ 2) ^ (i2 >> 1);
- }
- }
-
- for ( int i = 0; i < channel_count; i++ )
- {
- if ( !(mute_mask & (1 << i)) && (i != 5 || !YM2612.DAC) )
- UPDATE_CHAN [YM2612.CHANNEL [i].ALGO]( g, YM2612.CHANNEL [i], out, pair_count );
- }
-
- g.LFOcnt += g.LFOinc * pair_count;
-}
-
-void Ym2612_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.h b/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.h
deleted file mode 100644
index 314b3399..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/Ym2612_Emu.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// YM2612 FM sound chip emulator interface
-
-// Game_Music_Emu 0.5.5
-#ifndef YM2612_EMU_H
-#define YM2612_EMU_H
-
-struct Ym2612_Impl;
-
-class Ym2612_Emu {
- Ym2612_Impl* impl;
-public:
- Ym2612_Emu() { impl = 0; }
- ~Ym2612_Emu();
-
- // Set output sample rate and chip clock rates, in Hz. Returns non-zero
- // if error.
- const char* set_rate( double sample_rate, double clock_rate );
-
- // Reset to power-up state
- void reset();
-
- // Mute voice n if bit n (1 << n) of mask is set
- enum { channel_count = 6 };
- void mute_voices( int mask );
-
- // Write addr to register 0 then data to register 1
- void write0( int addr, int data );
-
- // Write addr to register 2 then data to register 3
- void write1( int addr, int data );
-
- // Run and add pair_count samples into current output buffer contents
- typedef short sample_t;
- enum { out_chan_count = 2 }; // stereo
- void run( int pair_count, sample_t* out );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/blargg_common.h b/plugins/gme/game-music-emu-0.5.5/gme/blargg_common.h
deleted file mode 100644
index e48d6469..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/blargg_common.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Sets up common environment for Shay Green's libraries.
-// To change configuration options, modify blargg_config.h, not this file.
-
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
-
-#undef BLARGG_COMMON_H
-// allow blargg_config.h to #include blargg_common.h
-#include "blargg_config.h"
-#ifndef BLARGG_COMMON_H
-#define BLARGG_COMMON_H
-
-// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
-#ifndef STATIC_CAST
- #define STATIC_CAST(T,expr) ((T) (expr))
-#endif
-
-// blargg_err_t (0 on success, otherwise error string)
-#ifndef blargg_err_t
- typedef const char* blargg_err_t;
-#endif
-
-// blargg_vector - very lightweight vector of POD types (no constructor/destructor)
-template<class T>
-class blargg_vector {
- T* begin_;
- size_t size_;
-public:
- blargg_vector() : begin_( 0 ), size_( 0 ) { }
- ~blargg_vector() { free( begin_ ); }
- size_t size() const { return size_; }
- T* begin() const { return begin_; }
- T* end() const { return begin_ + size_; }
- blargg_err_t resize( size_t n )
- {
- void* p = realloc( begin_, n * sizeof (T) );
- if ( !p && n )
- return "Out of memory";
- begin_ = (T*) p;
- size_ = n;
- return 0;
- }
- void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); }
- T& operator [] ( size_t n ) const
- {
- assert( n <= size_ ); // <= to allow past-the-end value
- return begin_ [n];
- }
-};
-
-#ifndef BLARGG_DISABLE_NOTHROW
- #if __cplusplus < 199711
- #define BLARGG_THROWS( spec )
- #else
- #define BLARGG_THROWS( spec ) throw spec
- #endif
- #define BLARGG_DISABLE_NOTHROW \
- void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
- void operator delete ( void* p ) { free( p ); }
- #define BLARGG_NEW new
-#else
- #include <new>
- #define BLARGG_NEW new (std::nothrow)
-#endif
-
-#define BLARGG_4CHAR( a, b, c, d ) \
- ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
-
-// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
-#ifndef BOOST_STATIC_ASSERT
- #ifdef _MSC_VER
- // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
- #else
- // Some other compilers fail when declaring same function multiple times in class,
- // so differentiate them by line
- #define BOOST_STATIC_ASSERT( expr ) \
- void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
- #endif
-#endif
-
-// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
-// compiler is assumed to support bool. If undefined, availability is determined.
-#ifndef BLARGG_COMPILER_HAS_BOOL
- #if defined (__MWERKS__)
- #if !__option(bool)
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (_MSC_VER)
- #if _MSC_VER < 1100
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
- #elif defined (__GNUC__)
- // supports bool
- #elif __cplusplus < 199711
- #define BLARGG_COMPILER_HAS_BOOL 0
- #endif
-#endif
-#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
- // If you get errors here, modify your blargg_config.h file
- typedef int bool;
- const bool true = 1;
- const bool false = 0;
-#endif
-
-// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
-#include <limits.h>
-
-#if INT_MAX >= 0x7FFFFFFF
- typedef int blargg_long;
-#else
- typedef long blargg_long;
-#endif
-
-#if UINT_MAX >= 0xFFFFFFFF
- typedef unsigned blargg_ulong;
-#else
- typedef unsigned long blargg_ulong;
-#endif
-
-// BOOST::int8_t etc.
-
-// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
-#if defined (HAVE_STDINT_H)
- #include <stdint.h>
- #define BOOST
-
-// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
-#elif defined (HAVE_INTTYPES_H)
- #include <inttypes.h>
- #define BOOST
-
-#else
- struct BOOST
- {
- #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
- typedef signed char int8_t;
- typedef unsigned char uint8_t;
- #else
- // No suitable 8-bit type available
- typedef struct see_blargg_common_h int8_t;
- typedef struct see_blargg_common_h uint8_t;
- #endif
-
- #if USHRT_MAX == 0xFFFF
- typedef short int16_t;
- typedef unsigned short uint16_t;
- #else
- // No suitable 16-bit type available
- typedef struct see_blargg_common_h int16_t;
- typedef struct see_blargg_common_h uint16_t;
- #endif
-
- #if ULONG_MAX == 0xFFFFFFFF
- typedef long int32_t;
- typedef unsigned long uint32_t;
- #elif UINT_MAX == 0xFFFFFFFF
- typedef int int32_t;
- typedef unsigned int uint32_t;
- #else
- // No suitable 32-bit type available
- typedef struct see_blargg_common_h int32_t;
- typedef struct see_blargg_common_h uint32_t;
- #endif
- };
-#endif
-
-#endif
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/blargg_config.h b/plugins/gme/game-music-emu-0.5.5/gme/blargg_config.h
deleted file mode 100644
index 9bdbeb57..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/blargg_config.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Library configuration. Modify this file as necessary.
-
-#ifndef BLARGG_CONFIG_H
-#define BLARGG_CONFIG_H
-
-// Uncomment to use zlib for transparent decompression of gzipped files
-//#define HAVE_ZLIB_H
-
-// Uncomment to enable platform-specific optimizations
-#define BLARGG_NONPORTABLE 1
-
-// Uncomment to use faster, lower quality sound synthesis
-//#define BLIP_BUFFER_FAST 1
-
-// Uncomment if automatic byte-order determination doesn't work
-//#define BLARGG_BIG_ENDIAN 1
-
-// Uncomment if you get errors in the bool section of blargg_common.h
-//#define BLARGG_COMPILER_HAS_BOOL 1
-
-// Use standard config.h if present
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-// Add supported emulator types
-#include "gme_types.h"
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/blargg_endian.h b/plugins/gme/game-music-emu-0.5.5/gme/blargg_endian.h
deleted file mode 100644
index 4d160d2f..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/blargg_endian.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// CPU Byte Order Utilities
-
-// Game_Music_Emu 0.5.5
-#ifndef BLARGG_ENDIAN
-#define BLARGG_ENDIAN
-
-#include "blargg_common.h"
-
-// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
-#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
- defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
- #define BLARGG_CPU_X86 1
- #define BLARGG_CPU_CISC 1
-#endif
-
-#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
- #define BLARGG_CPU_POWERPC 1
-#endif
-
-// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
-// one may be #defined to 1. Only needed if something actually depends on byte order.
-#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
-#ifdef __GLIBC__
- // GCC handles this for us
- #include <endian.h>
- #if __BYTE_ORDER == __LITTLE_ENDIAN
- #define BLARGG_LITTLE_ENDIAN 1
- #elif __BYTE_ORDER == __BIG_ENDIAN
- #define BLARGG_BIG_ENDIAN 1
- #endif
-#else
-
-#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
- (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-
-#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
- defined (__mips__) || defined (__sparc__) || BLARGG_CPU_POWERPC || \
- (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
- #define BLARGG_BIG_ENDIAN 1
-#else
- // No endian specified; assume little-endian, since it's most common
- #define BLARGG_LITTLE_ENDIAN 1
-#endif
-#endif
-#endif
-
-#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
- #undef BLARGG_LITTLE_ENDIAN
- #undef BLARGG_BIG_ENDIAN
-#endif
-
-inline void blargg_verify_byte_order()
-{
- #ifndef NDEBUG
- #if BLARGG_BIG_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i == 0 );
- #elif BLARGG_LITTLE_ENDIAN
- volatile int i = 1;
- assert( *(volatile char*) &i != 0 );
- #endif
- #endif
-}
-
-inline unsigned get_le16( void const* p ) {
- return ((unsigned char const*) p) [1] * 0x100u +
- ((unsigned char const*) p) [0];
-}
-inline unsigned get_be16( void const* p ) {
- return ((unsigned char const*) p) [0] * 0x100u +
- ((unsigned char const*) p) [1];
-}
-inline blargg_ulong get_le32( void const* p ) {
- return ((unsigned char const*) p) [3] * 0x01000000u +
- ((unsigned char const*) p) [2] * 0x00010000u +
- ((unsigned char const*) p) [1] * 0x00000100u +
- ((unsigned char const*) p) [0];
-}
-inline blargg_ulong get_be32( void const* p ) {
- return ((unsigned char const*) p) [0] * 0x01000000u +
- ((unsigned char const*) p) [1] * 0x00010000u +
- ((unsigned char const*) p) [2] * 0x00000100u +
- ((unsigned char const*) p) [3];
-}
-inline void set_le16( void* p, unsigned n ) {
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [0] = (unsigned char) n;
-}
-inline void set_be16( void* p, unsigned n ) {
- ((unsigned char*) p) [0] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [1] = (unsigned char) n;
-}
-inline void set_le32( void* p, blargg_ulong n ) {
- ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [0] = (unsigned char) n;
-}
-inline void set_be32( void* p, blargg_ulong n ) {
- ((unsigned char*) p) [0] = (unsigned char) (n >> 24);
- ((unsigned char*) p) [1] = (unsigned char) (n >> 16);
- ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
- ((unsigned char*) p) [3] = (unsigned char) n;
-}
-
-#if BLARGG_NONPORTABLE
- // Optimized implementation if byte order is known
- #if BLARGG_LITTLE_ENDIAN
- #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr))
- #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr))
- #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
- #elif BLARGG_BIG_ENDIAN
- #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr))
- #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr))
- #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
- #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
- #endif
-
- #if BLARGG_CPU_POWERPC && defined (__MWERKS__)
- // PowerPC has special byte-reversed instructions
- // to do: assumes that PowerPC is running in big-endian mode
- // to do: implement for other compilers which don't support these macros
- #define GET_LE16( addr ) (__lhbrx( (addr), 0 ))
- #define GET_LE32( addr ) (__lwbrx( (addr), 0 ))
- #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 ))
- #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 ))
- #endif
-#endif
-
-#ifndef GET_LE16
- #define GET_LE16( addr ) get_le16( addr )
- #define GET_LE32( addr ) get_le32( addr )
- #define SET_LE16( addr, data ) set_le16( addr, data )
- #define SET_LE32( addr, data ) set_le32( addr, data )
-#endif
-
-#ifndef GET_BE16
- #define GET_BE16( addr ) get_be16( addr )
- #define GET_BE32( addr ) get_be32( addr )
- #define SET_BE16( addr, data ) set_be16( addr, data )
- #define SET_BE32( addr, data ) set_be32( addr, data )
-#endif
-
-// auto-selecting versions
-
-inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
-inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); }
-inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
-inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); }
-inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); }
-inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); }
-inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); }
-inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); }
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/blargg_source.h b/plugins/gme/game-music-emu-0.5.5/gme/blargg_source.h
deleted file mode 100644
index 2b568d19..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/blargg_source.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Included at the beginning of library source files, after all other #include lines
-#ifndef BLARGG_SOURCE_H
-#define BLARGG_SOURCE_H
-
-// If debugging is enabled, abort program if expr is false. Meant for checking
-// internal state and consistency. A failed assertion indicates a bug in the module.
-// void assert( bool expr );
-#include <assert.h>
-
-// If debugging is enabled and expr is false, abort program. Meant for checking
-// caller-supplied parameters and operations that are outside the control of the
-// module. A failed requirement indicates a bug outside the module.
-// void require( bool expr );
-#undef require
-#define require( expr ) assert( expr )
-
-// Like printf() except output goes to debug log file. Might be defined to do
-// nothing (not even evaluate its arguments).
-// void debug_printf( const char* format, ... );
-inline void blargg_dprintf_( const char*, ... ) { }
-#undef debug_printf
-#define debug_printf (1) ? (void) 0 : blargg_dprintf_
-
-// If enabled, evaluate expr and if false, make debug log entry with source file
-// and line. Meant for finding situations that should be examined further, but that
-// don't indicate a problem. In all cases, execution continues normally.
-#undef check
-#define check( expr ) ((void) 0)
-
-// If expr yields error string, return it from current function, otherwise continue.
-#undef RETURN_ERR
-#define RETURN_ERR( expr ) do { \
- blargg_err_t blargg_return_err_ = (expr); \
- if ( blargg_return_err_ ) return blargg_return_err_; \
- } while ( 0 )
-
-// If ptr is 0, return out of memory error string.
-#undef CHECK_ALLOC
-#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
-
-// Avoid any macros which evaluate their arguments multiple times
-#undef min
-#undef max
-
-// using const references generates crappy code, and I am currenly only using these
-// for built-in types, so they take arguments by value
-
-template<class T>
-inline T min( T x, T y )
-{
- if ( x < y )
- return x;
- return y;
-}
-
-template<class T>
-inline T max( T x, T y )
-{
- if ( x < y )
- return y;
- return x;
-}
-
-// TODO: good idea? bad idea?
-#undef byte
-#define byte byte_
-typedef unsigned char byte;
-
-// deprecated
-#define BLARGG_CHECK_ALLOC CHECK_ALLOC
-#define BLARGG_RETURN_ERR RETURN_ERR
-
-// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check
-#ifdef BLARGG_SOURCE_BEGIN
- #include BLARGG_SOURCE_BEGIN
-#endif
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/gb_cpu_io.h b/plugins/gme/game-music-emu-0.5.5/gme/gb_cpu_io.h
deleted file mode 100644
index cd98ffd5..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/gb_cpu_io.h
+++ /dev/null
@@ -1,72 +0,0 @@
-
-#include "Gbs_Emu.h"
-
-#include "blargg_source.h"
-
-int Gbs_Emu::cpu_read( gb_addr_t addr )
-{
- int result = *cpu::get_code( addr );
- if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )
- result = apu.read_register( clock(), addr );
-#ifndef NDEBUG
- else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
- debug_printf( "Read from unmapped memory $%.4x\n", (unsigned) addr );
- else if ( unsigned (addr - 0xFF01) < 0xFF80 - 0xFF01 )
- debug_printf( "Unhandled I/O read 0x%4X\n", (unsigned) addr );
-#endif
- return result;
-}
-
-void Gbs_Emu::cpu_write( gb_addr_t addr, int data )
-{
- unsigned offset = addr - ram_addr;
- if ( offset <= 0xFFFF - ram_addr )
- {
- ram [offset] = data;
- if ( (addr ^ 0xE000) <= 0x1F80 - 1 )
- {
- if ( unsigned (addr - Gb_Apu::start_addr) < Gb_Apu::register_count )
- {
- GME_APU_HOOK( this, addr - Gb_Apu::start_addr, data );
- apu.write_register( clock(), addr, data );
- }
- else if ( (addr ^ 0xFF06) < 2 )
- update_timer();
- else if ( addr == joypad_addr )
- ram [offset] = 0; // keep joypad return value 0
- else
- ram [offset] = 0xFF;
-
- //if ( addr == 0xFFFF )
- // debug_printf( "Wrote interrupt mask\n" );
- }
- }
- else if ( (addr ^ 0x2000) <= 0x2000 - 1 )
- {
- set_bank( data );
- }
-#ifndef NDEBUG
- else if ( unsigned (addr - 0x8000) < 0x2000 || unsigned (addr - 0xE000) < 0x1F00 )
- {
- debug_printf( "Wrote to unmapped memory $%.4x\n", (unsigned) addr );
- }
-#endif
-}
-
-#define CPU_READ_FAST( cpu, addr, time, out ) \
- CPU_READ_FAST_( STATIC_CAST(Gbs_Emu*,cpu), addr, time, out )
-
-#define CPU_READ_FAST_( emu, addr, time, out ) \
-{\
- out = READ_PROG( addr );\
- if ( unsigned (addr - Gb_Apu::start_addr) <= Gb_Apu::register_count )\
- out = emu->apu.read_register( emu->cpu_time - time * clocks_per_instr, addr );\
- else\
- check( out == emu->cpu_read( addr ) );\
-}
-
-#define CPU_READ( cpu, addr, time ) \
- STATIC_CAST(Gbs_Emu*,cpu)->cpu_read( addr )
-
-#define CPU_WRITE( cpu, addr, data, time ) \
- STATIC_CAST(Gbs_Emu*,cpu)->cpu_write( addr, data )
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/gme.cpp b/plugins/gme/game-music-emu-0.5.5/gme/gme.cpp
deleted file mode 100644
index 6b9dc0b8..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/gme.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Music_Emu.h"
-
-#if !GME_DISABLE_STEREO_DEPTH
-#include "Effects_Buffer.h"
-#endif
-#include "blargg_endian.h"
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
-can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-module is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "blargg_source.h"
-
-gme_type_t const* gme_type_list()
-{
- static gme_type_t const gme_type_list_ [] = {
-#ifdef USE_GME_AY
- gme_ay_type,
-#endif
-#ifdef USE_GME_GBS
- gme_gbs_type,
-#endif
-#ifdef USE_GME_GYM
- gme_gym_type,
-#endif
-#ifdef USE_GME_HES
- gme_hes_type,
-#endif
-#ifdef USE_GME_KSS
- gme_kss_type,
-#endif
-#if defined(USE_GME_NSF) || defined(USE_GME_NSFE)
- gme_nsf_type,
-#endif
-#ifdef USE_GME_NSFE
- gme_nsfe_type,
-#endif
-#ifdef USE_GME_SAP
- gme_sap_type,
-#endif
-#ifdef USE_GME_SPC
- gme_spc_type,
-#endif
-#ifdef USE_GME_VGM
- gme_vgm_type,
- gme_vgz_type,
-#endif
- 0 };
-
- return gme_type_list_;
-}
-
-const char* gme_identify_header( void const* header )
-{
- switch ( get_be32( header ) )
- {
- case BLARGG_4CHAR('Z','X','A','Y'): return "AY";
- case BLARGG_4CHAR('G','B','S',0x01): return "GBS";
- case BLARGG_4CHAR('G','Y','M','X'): return "GYM";
- case BLARGG_4CHAR('H','E','S','M'): return "HES";
- case BLARGG_4CHAR('K','S','C','C'):
- case BLARGG_4CHAR('K','S','S','X'): return "KSS";
- case BLARGG_4CHAR('N','E','S','M'): return "NSF";
- case BLARGG_4CHAR('N','S','F','E'): return "NSFE";
- case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
- case BLARGG_4CHAR('S','N','E','S'): return "SPC";
- case BLARGG_4CHAR('V','g','m',' '): return "VGM";
- }
- return "";
-}
-
-static void to_uppercase( const char* in, int len, char* out )
-{
- for ( int i = 0; i < len; i++ )
- {
- if ( !(out [i] = toupper( in [i] )) )
- return;
- }
- *out = 0; // extension too long
-}
-
-gme_type_t gme_identify_extension( const char* extension_ )
-{
- char const* end = strrchr( extension_, '.' );
- if ( end )
- extension_ = end + 1;
-
- char extension [6];
- to_uppercase( extension_, sizeof extension, extension );
-
- for ( gme_type_t const* types = gme_type_list(); *types; types++ )
- if ( !strcmp( extension, (*types)->extension_ ) )
- return *types;
- return 0;
-}
-
-gme_err_t gme_identify_file( const char* path, gme_type_t* type_out )
-{
- *type_out = gme_identify_extension( path );
- // TODO: don't examine header if file has extension?
- if ( !*type_out )
- {
- char header [4];
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
- RETURN_ERR( in.read( header, sizeof header ) );
- *type_out = gme_identify_extension( gme_identify_header( header ) );
- }
- return 0;
-}
-
-gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate )
-{
- require( (data || !size) && out );
- *out = 0;
-
- gme_type_t file_type = 0;
- if ( size >= 4 )
- file_type = gme_identify_extension( gme_identify_header( data ) );
- if ( !file_type )
- return gme_wrong_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- gme_err_t err = gme_load_data( emu, data, size );
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
-{
- require( path && out );
- *out = 0;
-
- GME_FILE_READER in;
- RETURN_ERR( in.open( path ) );
-
- char header [4];
- int header_size = 0;
-
- gme_type_t file_type = gme_identify_extension( path );
- if ( !file_type )
- {
- header_size = sizeof header;
- RETURN_ERR( in.read( header, sizeof header ) );
- file_type = gme_identify_extension( gme_identify_header( header ) );
- }
- if ( !file_type )
- return gme_wrong_file_type;
-
- Music_Emu* emu = gme_new_emu( file_type, sample_rate );
- CHECK_ALLOC( emu );
-
- // optimization: avoids seeking/re-reading header
- Remaining_Reader rem( header, header_size, &in );
- gme_err_t err = emu->load( rem );
- in.close();
-
- if ( err )
- delete emu;
- else
- *out = emu;
-
- return err;
-}
-
-Music_Emu* gme_new_emu( gme_type_t type, int rate )
-{
- if ( type )
- {
- if ( rate == gme_info_only )
- return type->new_info();
-
- Music_Emu* me = type->new_emu();
- if ( me )
- {
- #if !GME_DISABLE_STEREO_DEPTH
- if ( type->flags_ & 1 )
- {
- me->effects_buffer = BLARGG_NEW Effects_Buffer;
- if ( me->effects_buffer )
- me->set_buffer( me->effects_buffer );
- }
-
- if ( !(type->flags_ & 1) || me->effects_buffer )
- #endif
- {
- if ( !me->set_sample_rate( rate ) )
- {
- check( me->type() == type );
- return me;
- }
- }
- delete me;
- }
- }
- return 0;
-}
-
-gme_err_t gme_load_file( Music_Emu* me, const char* path ) { return me->load_file( path ); }
-
-gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
-{
- Mem_File_Reader in( data, size );
- return me->load( in );
-}
-
-gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
-{
- Callback_Reader in( func, size, data );
- return me->load( in );
-}
-
-void gme_delete( Music_Emu* me ) { delete me; }
-
-gme_type_t gme_type( Music_Emu const* me ) { return me->type(); }
-
-const char* gme_warning( Music_Emu* me ) { return me->warning(); }
-
-int gme_track_count( Music_Emu const* me ) { return me->track_count(); }
-
-struct gme_info_t_ : gme_info_t
-{
- track_info_t info;
-
- BLARGG_DISABLE_NOTHROW
-};
-
-gme_err_t gme_track_info( Music_Emu const* me, gme_info_t** out, int track )
-{
- *out = NULL;
-
- gme_info_t_* info = BLARGG_NEW gme_info_t_;
- CHECK_ALLOC( info );
-
- gme_err_t err = me->track_info( &info->info, track );
- if ( err )
- {
- gme_free_info( info );
- return err;
- }
-
- #define COPY(name) info->name = info->info.name;
-
- COPY( length );
- COPY( intro_length );
- COPY( loop_length );
-
- info->i4 = -1;
- info->i5 = -1;
- info->i6 = -1;
- info->i7 = -1;
- info->i8 = -1;
- info->i9 = -1;
- info->i10 = -1;
- info->i11 = -1;
- info->i12 = -1;
- info->i13 = -1;
- info->i14 = -1;
- info->i15 = -1;
-
- info->s7 = "";
- info->s8 = "";
- info->s9 = "";
- info->s10 = "";
- info->s11 = "";
- info->s12 = "";
- info->s13 = "";
- info->s14 = "";
- info->s15 = "";
-
- COPY( system );
- COPY( game );
- COPY( song );
- COPY( author );
- COPY( copyright );
- COPY( comment );
- COPY( dumper );
-
- #undef COPY
-
- info->play_length = info->length;
- if ( info->play_length <= 0 )
- {
- info->play_length = info->intro_length + 2 * info->loop_length; // intro + 2 loops
- if ( info->play_length <= 0 )
- info->play_length = 150 * 1000; // 2.5 minutes
- }
-
- *out = info;
-
- return 0;
-}
-
-void gme_free_info( gme_info_t* info )
-{
- delete STATIC_CAST(gme_info_t_*,info);
-}
-
-void gme_set_stereo_depth( Music_Emu* me, double depth )
-{
-#if !GME_DISABLE_STEREO_DEPTH
- if ( me->effects_buffer )
- STATIC_CAST(Effects_Buffer*,me->effects_buffer)->set_depth( depth );
-#endif
-}
-
-void* gme_user_data ( Music_Emu const* me ) { return me->user_data(); }
-void gme_set_user_data ( Music_Emu* me, void* new_user_data ) { me->set_user_data( new_user_data ); }
-void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->set_user_cleanup( func ); }
-
-gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); }
-gme_err_t gme_play ( Music_Emu* me, int n, short* p ) { return me->play( n, p ); }
-void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
-int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
-int gme_tell ( Music_Emu const* me ) { return me->tell(); }
-gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
-int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
-void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
-void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
-void gme_mute_voice ( Music_Emu* me, int index, int mute ) { me->mute_voice( index, mute != 0 ); }
-void gme_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
-
-void gme_set_equalizer ( Music_Emu* me, gme_equalizer_t const* eq )
-{
- Music_Emu::equalizer_t e = me->equalizer();
- e.treble = eq->treble;
- e.bass = eq->bass;
- me->set_equalizer( e );
-}
-
-void gme_equalizer( Music_Emu const* me, gme_equalizer_t* out )
-{
- gme_equalizer_t e = { };
- e.treble = me->equalizer().treble;
- e.bass = me->equalizer().bass;
- *out = e;
-}
-
-const char* gme_voice_name( Music_Emu const* me, int i )
-{
- assert( (unsigned) i < (unsigned) me->voice_count() );
- return me->voice_names() [i];
-}
-
-const char* gme_type_system( gme_type_t type )
-{
- assert( type );
- return type->system;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/gme.h b/plugins/gme/game-music-emu-0.5.5/gme/gme.h
deleted file mode 100644
index 5b9039c4..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/gme.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/* Game music emulator library C interface (also usable from C++) */
-
-/* Game_Music_Emu 0.5.5 */
-#ifndef GME_H
-#define GME_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/* Error string returned by library functions, or NULL if no error (success) */
-typedef const char* gme_err_t;
-
-/* First parameter of most gme_ functions is a pointer to the Music_Emu */
-typedef struct Music_Emu Music_Emu;
-
-
-/******** Basic operations ********/
-
-/* Create emulator and load game music file/data into it. Sets *out to new emulator. */
-gme_err_t gme_open_file( const char path [], Music_Emu** out, int sample_rate );
-
-/* Number of tracks available */
-int gme_track_count( Music_Emu const* );
-
-/* Start a track, where 0 is the first track */
-gme_err_t gme_start_track( Music_Emu*, int index );
-
-/* Generate 'count' 16-bit signed samples info 'out'. Output is in stereo. */
-gme_err_t gme_play( Music_Emu*, int count, short out [] );
-
-/* Finish using emulator and free memory */
-void gme_delete( Music_Emu* );
-
-
-/******** Track position/length ********/
-
-/* Set time to start fading track out. Once fade ends track_ended() returns true.
-Fade time can be changed while track is playing. */
-void gme_set_fade( Music_Emu*, int start_msec );
-
-/* True if a track has reached its end */
-int gme_track_ended( Music_Emu const* );
-
-/* Number of milliseconds (1000 = one second) played since beginning of track */
-int gme_tell( Music_Emu const* );
-
-/* Seek to new time in track. Seeking backwards or far forward can take a while. */
-gme_err_t gme_seek( Music_Emu*, int msec );
-
-
-/******** Informational ********/
-
-/* If you only need track information from a music file, pass gme_info_only for
-sample_rate to open/load. */
-enum { gme_info_only = -1 };
-
-/* Most recent warning string, or NULL if none. Clears current warning after returning.
-Warning is also cleared when loading a file and starting a track. */
-const char* gme_warning( Music_Emu* );
-
-/* Load m3u playlist file (must be done after loading music) */
-gme_err_t gme_load_m3u( Music_Emu*, const char path [] );
-
-/* Clear any loaded m3u playlist and any internal playlist that the music format
-supports (NSFE for example). */
-void gme_clear_playlist( Music_Emu* );
-
-/* Gets information for a particular track (length, name, author, etc.).
-Must be freed after use. */
-typedef struct gme_info_t gme_info_t;
-gme_err_t gme_track_info( Music_Emu const*, gme_info_t** out, int track );
-
-/* Frees track information */
-void gme_free_info( gme_info_t* );
-
-struct gme_info_t
-{
- /* times in milliseconds; -1 if unknown */
- int length; /* total length, if file specifies it */
- int intro_length; /* length of song up to looping section */
- int loop_length; /* length of looping section */
-
- /* Length if available, otherwise intro_length+loop_length*2 if available,
- otherwise a default of 150000 (2.5 minutes). */
- int play_length;
-
- int i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15; /* reserved */
-
- /* empty string ("") if not available */
- const char* system;
- const char* game;
- const char* song;
- const char* author;
- const char* copyright;
- const char* comment;
- const char* dumper;
-
- const char *s7,*s8,*s9,*s10,*s11,*s12,*s13,*s14,*s15; /* reserved */
-};
-
-
-/******** Advanced playback ********/
-
-/* Adjust stereo echo depth, where 0.0 = off and 1.0 = maximum. Has no effect for
-GYM, SPC, and Sega Genesis VGM music */
-void gme_set_stereo_depth( Music_Emu*, double depth );
-
-/* Disable automatic end-of-track detection and skipping of silence at beginning
-if ignore is true */
-void gme_ignore_silence( Music_Emu*, int ignore );
-
-/* Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
-Track length as returned by track_info() assumes a tempo of 1.0. */
-void gme_set_tempo( Music_Emu*, double tempo );
-
-/* Number of voices used by currently loaded file */
-int gme_voice_count( Music_Emu const* );
-
-/* Name of voice i, from 0 to gme_voice_count() - 1 */
-const char* gme_voice_name( Music_Emu const*, int i );
-
-/* Mute/unmute voice i, where voice 0 is first voice */
-void gme_mute_voice( Music_Emu*, int index, int mute );
-
-/* Set muting state of all voices at once using a bit mask, where -1 mutes all
-voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
-void gme_mute_voices( Music_Emu*, int muting_mask );
-
-/* Frequency equalizer parameters (see gme.txt) */
-typedef struct gme_equalizer_t
-{
- double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
- double bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */
-
- double d2,d3,d4,d5,d6,d7,d8,d9; /* reserved */
-} gme_equalizer_t;
-
-/* Get current frequency equalizater parameters */
-void gme_equalizer( Music_Emu const*, gme_equalizer_t* out );
-
-/* Change frequency equalizer parameters */
-void gme_set_equalizer( Music_Emu*, gme_equalizer_t const* eq );
-
-
-
-/******** Game music types ********/
-
-/* Music file type identifier. Can also hold NULL. */
-typedef const struct gme_type_t_* gme_type_t;
-
-/* Emulator type constants for each supported file type */
-extern const gme_type_t
- gme_ay_type,
- gme_gbs_type,
- gme_gym_type,
- gme_hes_type,
- gme_kss_type,
- gme_nsf_type,
- gme_nsfe_type,
- gme_sap_type,
- gme_spc_type,
- gme_vgm_type,
- gme_vgz_type;
-
-/* Type of this emulator */
-gme_type_t gme_type( Music_Emu const* );
-
-/* Pointer to array of all music types, with NULL entry at end. Allows a player linked
-to this library to support new music types without having to be updated. */
-gme_type_t const* gme_type_list();
-
-/* Name of game system for this music file type */
-const char* gme_type_system( gme_type_t );
-
-/* True if this music file type supports multiple tracks */
-int gme_type_multitrack( gme_type_t );
-
-
-/******** Advanced file loading ********/
-
-/* Error returned if file type is not supported */
-extern const char* const gme_wrong_file_type;
-
-/* Same as gme_open_file(), but uses file data already in memory. Makes copy of data. */
-gme_err_t gme_open_data( void const* data, long size, Music_Emu** out, int sample_rate );
-
-/* Determine likely game music type based on first four bytes of file. Returns
-string containing proper file suffix (i.e. "NSF", "SPC", etc.) or "" if
-file header is not recognized. */
-const char* gme_identify_header( void const* header );
-
-/* Get corresponding music type for file path or extension passed in. */
-gme_type_t gme_identify_extension( const char path_or_extension [] );
-
-/* Determine file type based on file's extension or header (if extension isn't recognized).
-Sets *type_out to type, or 0 if unrecognized or error. */
-gme_err_t gme_identify_file( const char path [], gme_type_t* type_out );
-
-/* Create new emulator and set sample rate. Returns NULL if out of memory. If you only need
-track information, pass gme_info_only for sample_rate. */
-Music_Emu* gme_new_emu( gme_type_t, int sample_rate );
-
-/* Load music file into emulator */
-gme_err_t gme_load_file( Music_Emu*, const char path [] );
-
-/* Load music file from memory into emulator. Makes a copy of data passed. */
-gme_err_t gme_load_data( Music_Emu*, void const* data, long size );
-
-/* Load music file using custom data reader function that will be called to
-read file data. Most emulators load the entire file in one read call. */
-typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );
-gme_err_t gme_load_custom( Music_Emu*, gme_reader_t, long file_size, void* your_data );
-
-/* Load m3u playlist file from memory (must be done after loading music) */
-gme_err_t gme_load_m3u_data( Music_Emu*, void const* data, long size );
-
-
-/******** User data ********/
-
-/* Set/get pointer to data you want to associate with this emulator.
-You can use this for whatever you want. */
-void gme_set_user_data( Music_Emu*, void* new_user_data );
-void* gme_user_data( Music_Emu const* );
-
-/* Register cleanup function to be called when deleting emulator, or NULL to
-clear it. Passes user_data to cleanup function. */
-typedef void (*gme_user_cleanup_t)( void* user_data );
-void gme_set_user_cleanup( Music_Emu*, gme_user_cleanup_t func );
-
-typedef struct
-{
- long track_count;
-
- /* times in milliseconds; -1 if unknown */
- long length;
- long intro_length;
- long loop_length;
-
- /* empty string if not available */
- char system [256];
- char game [256];
- char song [256];
- char author [256];
- char copyright [256];
- char comment [256];
- char dumper [256];
-} track_info_t;
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h b/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h
deleted file mode 100644
index 915b87a0..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef GME_TYPES_H
-#define GME_TYPES_H
-
-#define USE_GME_AY 1
-#define USE_GME_GBS 1
-#define USE_GME_GYM 1
-#define USE_GME_HES 1
-#define USE_GME_KSS 1
-#define USE_GME_NSF 1
-#define USE_GME_NSFE 1
-#define USE_GME_SAP 1
-#define USE_GME_SPC 1
-#define USE_GME_VGM 1
-
-#endif /* GME_TYPES_H */
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h.in b/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h.in
deleted file mode 100644
index 4829b3e1..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/gme_types.h.in
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GME_TYPES_H
-#define GME_TYPES_H
-
-/* CMake will either define the following to 1, or #undef it,
- * depending on the options passed to CMake. This is used to
- * conditionally compile in the various emulator types.
- *
- * See gme_type_list() in gme.cpp
- */
-
-#cmakedefine USE_GME_AY
-#cmakedefine USE_GME_GBS
-#cmakedefine USE_GME_GYM
-#cmakedefine USE_GME_HES
-#cmakedefine USE_GME_KSS
-#cmakedefine USE_GME_NSF
-#cmakedefine USE_GME_NSFE
-#cmakedefine USE_GME_SAP
-#cmakedefine USE_GME_SPC
-/* VGM and VGZ are a package deal */
-#cmakedefine USE_GME_VGM
-
-#endif /* GME_TYPES_H */
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/hes_cpu_io.h b/plugins/gme/game-music-emu-0.5.5/gme/hes_cpu_io.h
deleted file mode 100644
index ce60ce8e..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/hes_cpu_io.h
+++ /dev/null
@@ -1,101 +0,0 @@
-
-#include "Hes_Emu.h"
-
-#include "blargg_source.h"
-
-int Hes_Emu::cpu_read( hes_addr_t addr )
-{
- check( addr <= 0xFFFF );
- int result = *cpu::get_code( addr );
- if ( mmr [addr >> page_shift] == 0xFF )
- result = cpu_read_( addr );
- return result;
-}
-
-void Hes_Emu::cpu_write( hes_addr_t addr, int data )
-{
- check( addr <= 0xFFFF );
- byte* out = write_pages [addr >> page_shift];
- addr &= page_size - 1;
- if ( out )
- out [addr] = data;
- else if ( mmr [addr >> page_shift] == 0xFF )
- cpu_write_( addr, data );
-}
-
-inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank )
-{
- write_pages [page] = 0;
- if ( bank < 0x80 )
- return rom.at_addr( bank * (blargg_long) page_size );
-
- byte* data = 0;
- switch ( bank )
- {
- case 0xF8:
- data = cpu::ram;
- break;
-
- case 0xF9:
- case 0xFA:
- case 0xFB:
- data = &sgx [(bank - 0xF9) * page_size];
- break;
-
- default:
- if ( bank != 0xFF )
- debug_printf( "Unmapped bank $%02X\n", bank );
- return rom.unmapped();
- }
-
- write_pages [page] = data;
- return data;
-}
-
-#define CPU_READ_FAST( cpu, addr, time, out ) \
- CPU_READ_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, time, out )
-
-#define CPU_READ_FAST_( cpu, addr, time, out ) \
-{\
- out = READ_PROG( addr );\
- if ( mmr [addr >> page_shift] == 0xFF )\
- {\
- FLUSH_TIME();\
- out = cpu->cpu_read_( addr );\
- CACHE_TIME();\
- }\
-}
-
-#define CPU_WRITE_FAST( cpu, addr, data, time ) \
- CPU_WRITE_FAST_( STATIC_CAST(Hes_Emu*,cpu), addr, data, time )
-
-#define CPU_WRITE_FAST_( cpu, addr, data, time ) \
-{\
- byte* out = cpu->write_pages [addr >> page_shift];\
- addr &= page_size - 1;\
- if ( out )\
- {\
- out [addr] = data;\
- }\
- else if ( mmr [addr >> page_shift] == 0xFF )\
- {\
- FLUSH_TIME();\
- cpu->cpu_write_( addr, data );\
- CACHE_TIME();\
- }\
-}
-
-#define CPU_READ( cpu, addr, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_read( addr )
-
-#define CPU_WRITE( cpu, addr, data, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_write( addr, data )
-
-#define CPU_WRITE_VDP( cpu, addr, data, time ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_write_vdp( addr, data )
-
-#define CPU_SET_MMR( cpu, page, bank ) \
- STATIC_CAST(Hes_Emu*,cpu)->cpu_set_mmr( page, bank )
-
-#define CPU_DONE( cpu, time, result_out ) \
- result_out = STATIC_CAST(Hes_Emu*,cpu)->cpu_done()
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/nes_cpu_io.h b/plugins/gme/game-music-emu-0.5.5/gme/nes_cpu_io.h
deleted file mode 100644
index 68ce9b6f..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/nes_cpu_io.h
+++ /dev/null
@@ -1,83 +0,0 @@
-
-#include "Nsf_Emu.h"
-
-#if !NSF_EMU_APU_ONLY
- #include "Nes_Namco_Apu.h"
-#endif
-
-#include "blargg_source.h"
-
-int Nsf_Emu::cpu_read( nes_addr_t addr )
-{
- int result;
-
- result = cpu::low_mem [addr & 0x7FF];
- if ( !(addr & 0xE000) )
- goto exit;
-
- result = *cpu::get_code( addr );
- if ( addr > 0x7FFF )
- goto exit;
-
- result = sram [addr & (sizeof sram - 1)];
- if ( addr > 0x5FFF )
- goto exit;
-
- if ( addr == Nes_Apu::status_addr )
- return apu.read_status( cpu::time() );
-
- #if !NSF_EMU_APU_ONLY
- if ( addr == Nes_Namco_Apu::data_reg_addr && namco )
- return namco->read_data();
- #endif
-
- result = addr >> 8; // simulate open bus
-
- if ( addr != 0x2002 )
- debug_printf( "Read unmapped $%.4X\n", (unsigned) addr );
-
-exit:
- return result;
-}
-
-void Nsf_Emu::cpu_write( nes_addr_t addr, int data )
-{
- {
- nes_addr_t offset = addr ^ sram_addr;
- if ( offset < sizeof sram )
- {
- sram [offset] = data;
- return;
- }
- }
- {
- int temp = addr & 0x7FF;
- if ( !(addr & 0xE000) )
- {
- cpu::low_mem [temp] = data;
- return;
- }
- }
-
- if ( unsigned (addr - Nes_Apu::start_addr) <= Nes_Apu::end_addr - Nes_Apu::start_addr )
- {
- GME_APU_HOOK( this, addr - Nes_Apu::start_addr, data );
- apu.write_register( cpu::time(), addr, data );
- return;
- }
-
- unsigned bank = addr - bank_select_addr;
- if ( bank < bank_count )
- {
- blargg_long offset = rom.mask_addr( data * (blargg_long) bank_size );
- if ( offset >= rom.size() )
- set_warning( "Invalid bank" );
- cpu::map_code( (bank + 8) * bank_size, bank_size, rom.at_addr( offset ) );
- return;
- }
-
- cpu_write_misc( addr, data );
-}
-
-#define CPU_READ( cpu, addr, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_read( addr )
-#define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Nsf_Emu&,*cpu).cpu_write( addr, data )
diff --git a/plugins/gme/game-music-emu-0.5.5/gme/sap_cpu_io.h b/plugins/gme/game-music-emu-0.5.5/gme/sap_cpu_io.h
deleted file mode 100644
index d009d0d9..00000000
--- a/plugins/gme/game-music-emu-0.5.5/gme/sap_cpu_io.h
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include "Sap_Emu.h"
-
-#include "blargg_source.h"
-
-#define CPU_WRITE( cpu, addr, data, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_write( addr, data )
-
-void Sap_Emu::cpu_write( sap_addr_t addr, int data )
-{
- mem.ram [addr] = data;
- if ( (addr >> 8) == 0xD2 )
- cpu_write_( addr, data );
-}
-
-#ifdef NDEBUG
- #define CPU_READ( cpu, addr, time ) READ_LOW( addr )
-#else
- #define CPU_READ( cpu, addr, time ) STATIC_CAST(Sap_Emu&,*cpu).cpu_read( addr )
-
- int Sap_Emu::cpu_read( sap_addr_t addr )
- {
- if ( (addr & 0xF900) == 0xD000 )
- debug_printf( "Unmapped read $%04X\n", addr );
- return mem.ram [addr];
- }
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/license.txt b/plugins/gme/game-music-emu-0.5.5/license.txt
deleted file mode 100644
index 5faba9d4..00000000
--- a/plugins/gme/game-music-emu-0.5.5/license.txt
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.cpp b/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.cpp
deleted file mode 100644
index 464392d5..00000000
--- a/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Audio_Scope.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-/* Copyright (C) 2005-2006 by Shay Green. Permission is hereby granted, free of
-charge, to any person obtaining a copy of this software module and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-int const step_bits = 8;
-int const step_unit = 1 << step_bits;
-int const erase_color = 1;
-int const draw_color = 2;
-
-Audio_Scope::Audio_Scope()
-{
- surface = 0;
- buf = 0;
-}
-
-Audio_Scope::~Audio_Scope()
-{
- free( buf );
-
- if ( surface )
- SDL_FreeSurface( surface );
-}
-
-const char* Audio_Scope::init( int width, int height )
-{
- assert( height <= 256 );
- assert( !buf ); // can only call init() once
-
- buf = (byte*) calloc( width * sizeof *buf, 1 );
- if ( !buf )
- return "Out of memory";
-
- low_y = 0;
- high_y = height;
- buf_size = width;
-
- for ( sample_shift = 6; sample_shift < 14; )
- if ( ((0x7FFFL * 2) >> sample_shift++) < height )
- break;
-
- v_offset = height / 2 - (0x10000 >> sample_shift);
-
- screen = SDL_SetVideoMode( width, height, 0, 0 );
- if ( !screen )
- return "Couldn't set video mode";
-
- surface = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0 );
- if ( !screen )
- return "Couldn't create surface";
-
- static SDL_Color palette [2] = { {0, 0, 0}, {0, 255, 0} };
- SDL_SetColors( surface, palette, 1, 2 );
-
- return 0; // success
-}
-
-const char* Audio_Scope::draw( const short* in, long count, double step )
-{
- int low = low_y;
- int high = high_y;
-
- if ( count >= buf_size )
- {
- count = buf_size;
- low_y = 0x7FFF;
- high_y = 0;
- }
-
- if ( SDL_LockSurface( surface ) < 0 )
- return "Couldn't lock surface";
- render( in, count, (long) (step * step_unit) );
- SDL_UnlockSurface( surface );
-
- if ( low > low_y )
- low = low_y;
-
- if ( high < high_y )
- high = high_y;
-
- SDL_Rect r;
- r.x = 0;
- r.w = buf_size;
- r.y = low + v_offset;
- r.h = high - low + 1;
-
- if ( SDL_BlitSurface( surface, &r, screen, &r ) < 0 )
- return "Blit to screen failed";
-
- if ( SDL_Flip( screen ) < 0 )
- return "Couldn't flip screen";
-
- return 0; // success
-}
-
-void Audio_Scope::render( short const* in, long count, long step )
-{
- byte* old_pos = buf;
- long surface_pitch = surface->pitch;
- byte* out = (byte*) surface->pixels + v_offset * surface_pitch;
- int old_erase = *old_pos;
- int old_draw = 0;
- long in_pos = 0;
-
- int low_y = this->low_y;
- int high_y = this->high_y;
- int half_step = (step + step_unit / 2) >> (step_bits + 1);
-
- while ( count-- )
- {
- // Line drawing/erasing starts at previous sample and ends one short of
- // current sample, except when previous and current are the same.
-
- // Extra read on the last iteration of line loops will always be at the
- // height of the next sample, and thus within the gworld bounds.
-
- // Erase old line
- {
- int delta = *old_pos - old_erase;
- int offset = old_erase * surface_pitch;
- old_erase += delta;
-
- int next_line = surface_pitch;
- if ( delta < 0 )
- {
- delta = -delta;
- next_line = -surface_pitch;
- }
-
- do
- {
- out [offset] = erase_color;
- offset += next_line;
- }
- while ( delta-- > 1 );
- }
-
- // Draw new line and put in old_buf
- {
-
- int in_whole = in_pos >> step_bits;
- int sample = (0x7FFF * 2 - in [in_whole] - in [in_whole + half_step]) >> sample_shift;
- if ( !in_pos )
- old_draw = sample;
- in_pos += step;
-
- int delta = sample - old_draw;
- int offset = old_draw * surface_pitch;
- old_draw += delta;
-
- int next_line = surface_pitch;
- if ( delta < 0 )
- {
- delta = -delta;
- next_line = -surface_pitch;
- }
-
- *old_pos++ = sample;
-
- // min/max updating can be interleved anywhere
-
- if ( low_y > sample )
- low_y = sample;
-
- do
- {
- out [offset] = draw_color;
- offset += next_line;
- }
- while ( delta-- > 1 );
-
- if ( high_y < sample )
- high_y = sample;
- }
-
- out++;
- }
-
- this->low_y = low_y;
- this->high_y = high_y;
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.h b/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.h
deleted file mode 100644
index 75334676..00000000
--- a/plugins/gme/game-music-emu-0.5.5/player/Audio_Scope.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Simple audio waveform scope in a window, using SDL multimedia library
-
-#ifndef AUDIO_SCOPE_H
-#define AUDIO_SCOPE_H
-
-#include "SDL.h"
-
-class Audio_Scope {
-public:
- typedef const char* error_t;
-
- // Initialize scope window of specified size. Height must be 256 or less.
- error_t init( int width, int height );
-
- // Draw at most 'count' samples from 'in', skipping 'step' samples after
- // each sample drawn. Step can be less than 1.0.
- error_t draw( const short* in, long count, double step = 1.0 );
-
- Audio_Scope();
- ~Audio_Scope();
-
-private:
- typedef unsigned char byte;
- SDL_Surface* screen;
- SDL_Surface* surface;
- byte* buf;
- int buf_size;
- int sample_shift;
- int low_y;
- int high_y;
- int v_offset;
-
- void render( short const* in, long count, long step );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/player/Music_Player.cpp b/plugins/gme/game-music-emu-0.5.5/player/Music_Player.cpp
deleted file mode 100644
index e73261fb..00000000
--- a/plugins/gme/game-music-emu-0.5.5/player/Music_Player.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
-
-#include "Music_Player.h"
-
-#include "gme/Music_Emu.h"
-
-#include <string.h>
-#include <ctype.h>
-
-/* Copyright (C) 2005-2006 by Shay Green. Permission is hereby granted, free of
-charge, to any person obtaining a copy of this software module and associated
-documentation files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and
-to permit persons to whom the Software is furnished to do so, subject to the
-following conditions: The above copyright notice and this permission notice
-shall be included in all copies or substantial portions of the Software. THE
-SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#include "blargg_source.h"
-
-// Number of audio buffers per second. Adjust if you encounter audio skipping.
-const int fill_rate = 45;
-
-// Simple sound driver using SDL
-typedef void (*sound_callback_t)( void* data, short* out, int count );
-static const char* sound_init( long sample_rate, int buf_size, sound_callback_t, void* data );
-static void sound_start();
-static void sound_stop();
-static void sound_cleanup();
-
-Music_Player::Music_Player()
-{
- emu_ = 0;
- scope_buf = 0;
- paused = false;
-}
-
-blargg_err_t Music_Player::init( long rate )
-{
- sample_rate = rate;
-
- int min_size = sample_rate * 2 / fill_rate;
- int buf_size = 512;
- while ( buf_size < min_size )
- buf_size *= 2;
-
- return sound_init( sample_rate, buf_size, fill_buffer, this );
-}
-
-void Music_Player::stop()
-{
- sound_stop();
- delete emu_;
- emu_ = 0;
-}
-
-Music_Player::~Music_Player()
-{
- stop();
- sound_cleanup();
-}
-
-blargg_err_t Music_Player::load_file( const char* path )
-{
- stop();
-
- RETURN_ERR( gme_open_file( path, &emu_, sample_rate ) );
-
- char m3u_path [256 + 5];
- strncpy( m3u_path, path, 256 );
- m3u_path [256] = 0;
- char* p = strrchr( m3u_path, '.' );
- if ( !p )
- p = m3u_path + strlen( m3u_path );
- strcpy( p, ".m3u" );
- if ( emu_->load_m3u( m3u_path ) ) { } // ignore error
-
- return 0;
-}
-
-int Music_Player::track_count() const
-{
- return emu_ ? emu_->track_count() : false;
-}
-
-blargg_err_t Music_Player::start_track( int track )
-{
- if ( emu_ )
- {
- // Sound must not be running when operating on emulator
- sound_stop();
- RETURN_ERR( emu_->start_track( track ) );
-
- // Calculate track length
- if ( !emu_->track_info( &track_info_ ) )
- {
- if ( track_info_.length <= 0 )
- track_info_.length = track_info_.intro_length +
- track_info_.loop_length * 2;
- }
- if ( track_info_.length <= 0 )
- track_info_.length = (long) (2.5 * 60 * 1000);
- emu_->set_fade( track_info_.length );
-
- paused = false;
- sound_start();
- }
- return 0;
-}
-
-void Music_Player::pause( int b )
-{
- paused = b;
- if ( b )
- sound_stop();
- else
- sound_start();
-}
-
-void Music_Player::suspend()
-{
- if ( !paused )
- sound_stop();
-}
-
-void Music_Player::resume()
-{
- if ( !paused )
- sound_start();
-}
-
-bool Music_Player::track_ended() const
-{
- return emu_ ? emu_->track_ended() : false;
-}
-
-void Music_Player::set_stereo_depth( double tempo )
-{
- suspend();
- gme_set_stereo_depth( emu_, tempo );
- resume();
-}
-
-void Music_Player::set_tempo( double tempo )
-{
- suspend();
- emu_->set_tempo( tempo );
- resume();
-}
-
-void Music_Player::mute_voices( int mask )
-{
- suspend();
- emu_->mute_voices( mask );
- emu_->ignore_silence( mask != 0 );
- resume();
-}
-
-void Music_Player::fill_buffer( void* data, sample_t* out, int count )
-{
- Music_Player* self = (Music_Player*) data;
- if ( self->emu_ )
- {
- if ( self->emu_->play( count, out ) ) { } // ignore error
-
- if ( self->scope_buf )
- memcpy( self->scope_buf, out, self->scope_buf_size * sizeof *self->scope_buf );
- }
-}
-
-// Sound output driver using SDL
-
-#include "SDL.h"
-
-static sound_callback_t sound_callback;
-static void* sound_callback_data;
-
-static void sdl_callback( void* data, Uint8* out, int count )
-{
- if ( sound_callback )
- sound_callback( sound_callback_data, (short*) out, count / 2 );
-}
-
-static const char* sound_init( long sample_rate, int buf_size,
- sound_callback_t cb, void* data )
-{
- sound_callback = cb;
- sound_callback_data = data;
-
- static SDL_AudioSpec as; // making static clears all fields to 0
- as.freq = sample_rate;
- as.format = AUDIO_S16SYS;
- as.channels = 2;
- as.callback = sdl_callback;
- as.samples = buf_size;
- if ( SDL_OpenAudio( &as, 0 ) < 0 )
- {
- const char* err = SDL_GetError();
- if ( !err )
- err = "Couldn't open SDL audio";
- return err;
- }
-
- return 0;
-}
-
-static void sound_start()
-{
- SDL_PauseAudio( false );
-}
-
-static void sound_stop()
-{
- SDL_PauseAudio( true );
-
- // be sure audio thread is not active
- SDL_LockAudio();
- SDL_UnlockAudio();
-}
-
-static void sound_cleanup()
-{
- sound_stop();
- SDL_CloseAudio();
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/player/Music_Player.h b/plugins/gme/game-music-emu-0.5.5/player/Music_Player.h
deleted file mode 100644
index 82115fc6..00000000
--- a/plugins/gme/game-music-emu-0.5.5/player/Music_Player.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Simple game music file player
-
-// Game_Music_Emu 0.5.5
-#ifndef MUSIC_PLAYER_H
-#define MUSIC_PLAYER_H
-
-#include "gme/Music_Emu.h"
-
-class Music_Player {
-public:
- // Initialize player and set sample rate
- blargg_err_t init( long sample_rate = 44100 );
-
- // Load game music file. NULL on success, otherwise error string.
- blargg_err_t load_file( const char* path );
-
- // (Re)start playing track. Tracks are numbered from 0 to track_count() - 1.
- blargg_err_t start_track( int track );
-
- // Stop playing current file
- void stop();
-
-// Optional functions
-
- // Number of tracks in current file, or 0 if no file loaded.
- int track_count() const;
-
- // Info for current track
- track_info_t const& track_info() const { return track_info_; }
-
- // Pause/resume playing current track.
- void pause( int );
-
- // True if track ended
- bool track_ended() const;
-
- // Pointer to emulator
- Music_Emu* emu() const { return emu_; }
-
- // Set stereo depth, where 0.0 = none and 1.0 = maximum
- void set_stereo_depth( double );
-
- // Set tempo, where 0.5 = half speed, 1.0 = normal, 2.0 = double speed
- void set_tempo( double );
-
- // Set voice muting bitmask
- void mute_voices( int );
-
- // Set buffer to copy samples from each buffer into, or NULL to disable
- typedef short sample_t;
- void set_scope_buffer( sample_t* buf, int size ) { scope_buf = buf; scope_buf_size = size; }
-
-public:
- Music_Player();
- ~Music_Player();
-private:
- Music_Emu* emu_;
- sample_t* scope_buf;
- long sample_rate;
- int scope_buf_size;
- bool paused;
- track_info_t track_info_;
-
- void suspend();
- void resume();
- static void fill_buffer( void*, sample_t*, int );
-};
-
-#endif
diff --git a/plugins/gme/game-music-emu-0.5.5/player/player.cpp b/plugins/gme/game-music-emu-0.5.5/player/player.cpp
deleted file mode 100644
index 59d66729..00000000
--- a/plugins/gme/game-music-emu-0.5.5/player/player.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* How to play game music files with Music_Player (requires SDL library)
-
-Run program with path to a game music file.
-
-Left/Right Change track
-Space Pause/unpause
-E Normal/slight stereo echo/more stereo echo
--/= Adjust tempo
-1-9 Toggle channel on/off
-0 Reset tempo and turn channels back on */
-
-int const scope_width = 512;
-
-#include "Music_Player.h"
-#include "Audio_Scope.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include "SDL.h"
-
-void handle_error( const char* );
-
-static bool paused;
-static Audio_Scope* scope;
-static Music_Player* player;
-static short scope_buf [scope_width * 2];
-
-static void init()
-{
- // Start SDL
- if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO ) < 0 )
- exit( EXIT_FAILURE );
- atexit( SDL_Quit );
- SDL_EnableKeyRepeat( 500, 80 );
-
- // Init scope
- scope = new Audio_Scope;
- if ( !scope )
- handle_error( "Out of memory" );
- if ( scope->init( scope_width, 256 ) )
- handle_error( "Couldn't initialize scope" );
- memset( scope_buf, 0, sizeof scope_buf );
-
- // Create player
- player = new Music_Player;
- if ( !player )
- handle_error( "Out of memory" );
- handle_error( player->init() );
- player->set_scope_buffer( scope_buf, scope_width * 2 );
-}
-
-static void start_track( int track, const char* path )
-{
- paused = false;
- handle_error( player->start_track( track - 1 ) );
-
- // update window title with track info
-
- long seconds = player->track_info().length / 1000;
- const char* game = player->track_info().game;
- if ( !*game )
- {
- // extract filename
- game = strrchr( path, '\\' ); // DOS
- if ( !game )
- game = strrchr( path, '/' ); // UNIX
- if ( !game )
- game = path;
- else
- game++; // skip path separator
- }
-
- char title [512];
- sprintf( title, "%s: %d/%d %s (%ld:%02ld)",
- game, track, player->track_count(), player->track_info().song,
- seconds / 60, seconds % 60 );
- SDL_WM_SetCaption( title, title );
-}
-
-int main( int argc, char** argv )
-{
- init();
-
- // Load file
- const char* path = (argc > 1 ? argv [argc - 1] : "test.nsf");
- handle_error( player->load_file( path ) );
- start_track( 1, path );
-
- // Main loop
- int track = 1;
- double tempo = 1.0;
- bool running = true;
- double stereo_depth = 0.0;
- int muting_mask = 0;
- while ( running )
- {
- SDL_Delay( 1000 / 100 );
-
- // Update scope
- scope->draw( scope_buf, scope_width, 2 );
-
- // Automatically go to next track when current one ends
- if ( player->track_ended() )
- {
- if ( track < player->track_count() )
- start_track( ++track, path );
- else
- player->pause( paused = true );
- }
-
- // Handle keyboard input
- SDL_Event e;
- while ( SDL_PollEvent( &e ) )
- {
- switch ( e.type )
- {
- case SDL_QUIT:
- running = false;
- break;
-
- case SDL_KEYDOWN:
- int key = e.key.keysym.sym;
- switch ( key )
- {
- case SDLK_q:
- case SDLK_ESCAPE: // quit
- running = false;
- break;
-
- case SDLK_LEFT: // prev track
- if ( !paused && !--track )
- track = 1;
- start_track( track, path );
- break;
-
- case SDLK_RIGHT: // next track
- if ( track < player->track_count() )
- start_track( ++track, path );
- break;
-
- case SDLK_MINUS: // reduce tempo
- tempo -= 0.1;
- if ( tempo < 0.1 )
- tempo = 0.1;
- player->set_tempo( tempo );
- break;
-
- case SDLK_EQUALS: // increase tempo
- tempo += 0.1;
- if ( tempo > 2.0 )
- tempo = 2.0;
- player->set_tempo( tempo );
- break;
-
- case SDLK_SPACE: // toggle pause
- paused = !paused;
- player->pause( paused );
- break;
-
- case SDLK_e: // toggle echo
- stereo_depth += 0.2;
- if ( stereo_depth > 0.5 )
- stereo_depth = 0;
- player->set_stereo_depth( stereo_depth );
- break;
-
- case SDLK_0: // reset tempo and muting
- tempo = 1.0;
- muting_mask = 0;
- player->set_tempo( tempo );
- player->mute_voices( muting_mask );
- break;
-
- default:
- if ( SDLK_1 <= key && key <= SDLK_9 ) // toggle muting
- {
- muting_mask ^= 1 << (key - SDLK_1);
- player->mute_voices( muting_mask );
- }
- }
- }
- }
- }
-
- // Cleanup
- delete player;
- delete scope;
-
- return 0;
-}
-
-void handle_error( const char* error )
-{
- if ( error )
- {
- // put error in window title
- char str [256];
- sprintf( str, "Error: %s", error );
- fprintf( stderr, "%s\n", str );
- SDL_WM_SetCaption( str, str );
-
- // wait for keyboard or mouse activity
- SDL_Event e;
- do
- {
- while ( !SDL_PollEvent( &e ) ) { }
- }
- while ( e.type != SDL_QUIT && e.type != SDL_KEYDOWN && e.type != SDL_MOUSEBUTTONDOWN );
-
- exit( EXIT_FAILURE );
- }
-}
diff --git a/plugins/gme/game-music-emu-0.5.5/readme.txt b/plugins/gme/game-music-emu-0.5.5/readme.txt
deleted file mode 100644
index 36213f6b..00000000
--- a/plugins/gme/game-music-emu-0.5.5/readme.txt
+++ /dev/null
@@ -1,218 +0,0 @@
-Game_Music_Emu 0.5.5: Game Music Emulators
-------------------------------------------
-Game_Music_Emu is a collection of video game music file emulators that
-support the following formats and systems:
-
-AY ZX Spectrum/Amstrad CPC
-GBS Nintendo Game Boy
-GYM Sega Genesis/Mega Drive
-HES NEC TurboGrafx-16/PC Engine
-KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
-NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
-SAP Atari systems using POKEY sound chip
-SPC Super Nintendo/Super Famicom
-VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
-
-Features:
-* Can be used in C and C++ code
-* High emphasis has been placed on making the library very easy to use
-* One set of common functions work with all emulators the same way
-* Several code examples, including music player using SDL
-* Portable code for use on any system with modern or older C++ compilers
-* Adjustable output sample rate using quality band-limited resampling
-* Uniform access to text information fields and track timing information
-* End-of-track fading and automatic look ahead silence detection
-* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
-* Tempo can be adjusted and individual voices can be muted while playing
-* Can read music data from file, memory, or custom reader function/class
-* Can access track information without having to load into full emulator
-* M3U track listing support for multi-track formats
-* Modular design allows elimination of unneeded emulators/features
-
-This library has been used in game music players for Windows, Linux on
-several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
-GP2X, and Nintendo DS.
-
-Author : Shay Green <gblargg@gmail.com>
-Website: http://www.slack.net/~ant/
-Forum : http://groups.google.com/group/blargg-sound-libs
-License: GNU Lesser General Public License (LGPL)
-
-
-Getting Started
----------------
-Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
-all source files in gme/.
-
-If you have CMake 2.6 or higher you can use CMake to perform the build for
-you using standard CMake technique (i.e. cd to the source directory, run
-cmake, cd demo, run make)
-
-Be sure "test.nsf" is in the same directory.
-Running the program should generate the recording "out.wav".
-
-A slightly more extensive demo application is available in the player/
-directory. It requires SDL to build.
-
-Read gme.txt for more information. Post to the discussion forum for
-assistance.
-
-
-Files
------
-gme.txt General notes about the library
-changes.txt Changes made since previous releases
-design.txt Library design notes
-license.txt GNU Lesser General Public License
-CMakeLists.txt CMake build rules
-
-test.nsf Test file for NSF emulator
-test.m3u Test m3u playlist for features.c demo
-
-demo/
- basics.c Records NSF file to wave sound file
- cpp_basics.cpp C++ version of basics.c
- features.c Demonstrates many additional features
- Wave_Writer.h WAVE sound file writer used for demo output
- Wave_Writer.cpp
- CMakeLists.txt CMake build rules
-
-player/ Player using the SDL multimedia library
- player.cpp Simple music player with waveform display
- Music_Player.cpp Stand alone player for background music
- Music_Player.h
- Audio_Scope.cpp Audio waveform scope
- Audio_Scope.h
- CMakeLists.txt CMake build rules
-
-gme/
- blargg_config.h Library configuration (modify this file as needed)
-
- gme.h C interface (also usable in C++, and simpler too)
- gme.cpp
-
- Gme_File.h File loading and track information
- Music_Emu.h Track playback and adjustments
- Data_Reader.h Custom data readers
-
- Effects_Buffer.h Sound buffer with stereo echo and panning
- Effects_Buffer.cpp
-
- M3u_Playlist.h M3U playlist support
- M3u_Playlist.cpp
-
- Ay_Emu.h ZX Spectrum AY emulator
- Ay_Emu.cpp
- Ay_Apu.cpp
- Ay_Apu.h
- Ay_Cpu.cpp
- Ay_Cpu.h
-
- Gbs_Emu.h Nintendo Game Boy GBS emulator
- Gbs_Emu.cpp
- Gb_Apu.cpp
- Gb_Apu.h
- Gb_Cpu.cpp
- Gb_Cpu.h
- gb_cpu_io.h
- Gb_Oscs.cpp
- Gb_Oscs.h
-
- Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
- Hes_Apu.cpp
- Hes_Apu.h
- Hes_Cpu.cpp
- Hes_Cpu.h
- hes_cpu_io.h
- Hes_Emu.cpp
-
- Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
- Kss_Emu.cpp
- Kss_Cpu.cpp
- Kss_Cpu.h
- Kss_Scc_Apu.cpp
- Kss_Scc_Apu.h
- Ay_Apu.h
- Ay_Apu.cpp
- Sms_Apu.h
- Sms_Apu.cpp
- Sms_Oscs.h
-
- Nsf_Emu.h Nintendo NES NSF/NSFE emulator
- Nsf_Emu.cpp
- Nes_Apu.cpp
- Nes_Apu.h
- Nes_Cpu.cpp
- Nes_Cpu.h
- nes_cpu_io.h
- Nes_Oscs.cpp
- Nes_Oscs.h
- Nes_Fme7_Apu.cpp
- Nes_Fme7_Apu.h
- Nes_Namco_Apu.cpp
- Nes_Namco_Apu.h
- Nes_Vrc6_Apu.cpp
- Nes_Vrc6_Apu.h
- Nsfe_Emu.h NSFE support
- Nsfe_Emu.cpp
-
- Spc_Emu.h Super Nintendo SPC emulator
- Spc_Emu.cpp
- Snes_Spc.cpp
- Snes_Spc.h
- Spc_Cpu.cpp
- Spc_Cpu.h
- Spc_Dsp.cpp
- Spc_Dsp.h
- Fir_Resampler.cpp
- Fir_Resampler.h
-
- Sap_Emu.h Atari SAP emulator
- Sap_Emu.cpp
- Sap_Apu.cpp
- Sap_Apu.h
- Sap_Cpu.cpp
- Sap_Cpu.h
- sap_cpu_io.h
-
- Vgm_Emu.h Sega VGM emulator
- Vgm_Emu_Impl.cpp
- Vgm_Emu_Impl.h
- Vgm_Emu.cpp
- Ym2413_Emu.cpp
- Ym2413_Emu.h
- Gym_Emu.h Sega Genesis GYM emulator
- Gym_Emu.cpp
- Sms_Apu.cpp Common Sega emulator files
- Sms_Apu.h
- Sms_Oscs.h
- Ym2612_Emu.cpp
- Ym2612_Emu.h
- Dual_Resampler.cpp
- Dual_Resampler.h
- Fir_Resampler.cpp
- Fir_Resampler.h
-
- blargg_common.h Common files needed by all emulators
- blargg_endian.h
- blargg_source.h
- Blip_Buffer.cpp
- Blip_Buffer.h
- Gme_File.cpp
- Music_Emu.cpp
- Classic_Emu.h
- Classic_Emu.cpp
- Multi_Buffer.h
- Multi_Buffer.cpp
- Data_Reader.cpp
- CMakeLists.txt CMake build rules
-
-
-Legal
------
-Game_Music_Emu library copyright (C) 2003-2006 Shay Green.
-SNES SPC DSP emulator based on OpenSPC, copyright (C) 2002 Brad Martin.
-Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
-
---
-Shay Green <gblargg@gmail.com>
diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am
index 74889110..d87d1221 100644
--- a/plugins/gtkui/Makefile.am
+++ b/plugins/gtkui/Makefile.am
@@ -1,6 +1,18 @@
if HAVE_GTKUI
gtkuidir = $(libdir)/$(PACKAGE)
+if HAVE_SM
+if HAVE_ICE
+SM_SOURCES = smclient/eggdesktopfile.h\
+ smclient/eggsmclient-private.h\
+ smclient/eggsmclient.h\
+ smclient/eggdesktopfile.c\
+ smclient/eggsmclient-xsmp.c\
+ smclient/eggsmclient.c
+SM_LIBADD = $(SM_LIBS) $(ICE_LIBS)
+endif
+endif
+
GTKUI_SOURCES = gtkui.c gtkui.h\
callbacks.c interface.c support.c callbacks.h interface.h support.h\
ddblistview.c ddblistview.h\
@@ -24,7 +36,10 @@ GTKUI_SOURCES = gtkui.c gtkui.h\
wingeom.c wingeom.h\
pluginconf.h\
ddbseekbar.h ddbequalizer.h ddbcellrenderertextmultiline.h\
- ddbseekbar.c ddbequalizer.c ddbcellrenderertextmultiline.c
+ ddbseekbar.c ddbequalizer.c ddbcellrenderertextmultiline.c\
+ $(SM_SOURCES)
+
+
sdkdir = $(pkgincludedir)
sdk_HEADERS = gtkui_api.h
@@ -51,14 +66,14 @@ endif
if HAVE_GTK2
ddb_gui_GTK2_la_SOURCES = $(GTKUI_SOURCES)
ddb_gui_GTK2_la_LDFLAGS = -module
-ddb_gui_GTK2_la_LIBADD = $(LDADD) $(GTK2_DEPS_LIBS)
-ddb_gui_GTK2_la_CFLAGS = -std=c99 $(GTK2_DEPS_CFLAGS)
+ddb_gui_GTK2_la_LIBADD = $(LDADD) $(GTK2_DEPS_LIBS) $(SM_LIBADD)
+ddb_gui_GTK2_la_CFLAGS = -std=c99 $(GTK2_DEPS_CFLAGS) -DEGG_SM_CLIENT_BACKEND_XSMP -DG_LOG_DOMAIN=\""deadbeef"\"
endif
if HAVE_GTK3
ddb_gui_GTK3_la_SOURCES = $(GTKUI_SOURCES)
ddb_gui_GTK3_la_LDFLAGS = -module
-ddb_gui_GTK3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS)
-ddb_gui_GTK3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS)
+ddb_gui_GTK3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS) $(SM_LIBADD)
+ddb_gui_GTK3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS) -DEGG_SM_CLIENT_BACKEND_XSMP -DG_LOG_DOMAIN=\""deadbeef"\"
endif
# fallback lib
@@ -68,7 +83,7 @@ GTK_ROOT=@top_srcdir@/$(LIB)/gtk-2.12.12/usr
ddb_gui_GTK2_fallback_la_SOURCES = $(GTKUI_SOURCES)
ddb_gui_GTK2_fallback_la_LDFLAGS = -module
-ddb_gui_GTK2_fallback_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la
+ddb_gui_GTK2_fallback_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la $(SM_LIBADD)
ddb_gui_GTK2_fallback_la_CFLAGS = -std=c99 -I $(GTK_ROOT)/include -I $(GTK_ROOT)/lib/gtk-2.0/include -I $(GTK_ROOT)/include/glib-2.0 -I $(GTK_ROOT)/include/gtk-2.0 -I $(GTK_ROOT)/include/cairo -I $(GTK_ROOT)/lib/glib-2.0/include/ -I $(GTK_ROOT)/include/pango-1.0 -I $(GTK_ROOT)/include/atk-1.0 -DULTRA_COMPATIBLE=1
diff --git a/plugins/gtkui/ddbcellrenderertextmultiline.c b/plugins/gtkui/ddbcellrenderertextmultiline.c
index 3b1ac61b..a79d3154 100644
--- a/plugins/gtkui/ddbcellrenderertextmultiline.c
+++ b/plugins/gtkui/ddbcellrenderertextmultiline.c
@@ -27,58 +27,22 @@
#include <string.h>
#include <gdk/gdk.h>
#include "support.h"
+#include "ddbcellrenderertextmultiline.h"
-#define DDB_TYPE_CELL_EDITABLE_TEXT_VIEW (ddb_cell_editable_text_view_get_type ())
-#define DDB_CELL_EDITABLE_TEXT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW, DdbCellEditableTextView))
-#define DDB_CELL_EDITABLE_TEXT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW, DdbCellEditableTextViewClass))
-#define DDB_IS_CELL_EDITABLE_TEXT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW))
-#define DDB_IS_CELL_EDITABLE_TEXT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW))
-#define DDB_CELL_EDITABLE_TEXT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW, DdbCellEditableTextViewClass))
-
-typedef struct _DdbCellEditableTextView DdbCellEditableTextView;
-typedef struct _DdbCellEditableTextViewClass DdbCellEditableTextViewClass;
-typedef struct _DdbCellEditableTextViewPrivate DdbCellEditableTextViewPrivate;
#define _g_free0(var) (var = (g_free (var), NULL))
-#define DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE (ddb_cell_renderer_text_multiline_get_type ())
-#define DDB_CELL_RENDERER_TEXT_MULTILINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE, DdbCellRendererTextMultiline))
-#define DDB_CELL_RENDERER_TEXT_MULTILINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE, DdbCellRendererTextMultilineClass))
-#define DDB_IS_CELL_RENDERER_TEXT_MULTILINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE))
-#define DDB_IS_CELL_RENDERER_TEXT_MULTILINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE))
-#define DDB_CELL_RENDERER_TEXT_MULTILINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE, DdbCellRendererTextMultilineClass))
-
-typedef struct _DdbCellRendererTextMultiline DdbCellRendererTextMultiline;
-typedef struct _DdbCellRendererTextMultilineClass DdbCellRendererTextMultilineClass;
-typedef struct _DdbCellRendererTextMultilinePrivate DdbCellRendererTextMultilinePrivate;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _gtk_tree_path_free0(var) ((var == NULL) ? NULL : (var = (gtk_tree_path_free (var), NULL)))
-struct _DdbCellEditableTextView {
- GtkTextView parent_instance;
- DdbCellEditableTextViewPrivate * priv;
- gboolean editing_canceled;
- gchar* tree_path;
-};
-
-struct _DdbCellEditableTextViewClass {
- GtkTextViewClass parent_class;
-};
-
-struct _DdbCellRendererTextMultiline {
- GtkCellRendererText parent_instance;
- DdbCellRendererTextMultilinePrivate * priv;
-};
-
-struct _DdbCellRendererTextMultilineClass {
- GtkCellRendererTextClass parent_class;
-};
-
struct _DdbCellRendererTextMultilinePrivate {
DdbCellEditableTextView* entry;
gulong focus_out_id;
};
+struct _DdbCellEditableTextViewPrivate {
+ gboolean editing_canceled;
+};
static gpointer ddb_cell_editable_text_view_parent_class = NULL;
static GtkCellEditableIface* ddb_cell_editable_text_view_gtk_cell_editable_parent_iface = NULL;
@@ -90,14 +54,12 @@ enum {
};
static gboolean ddb_cell_editable_text_view_real_key_press_event (GtkWidget* base, GdkEventKey* event);
static void ddb_cell_editable_text_view_real_start_editing (GtkCellEditable* base, GdkEvent* event);
-#if GTK_CHECK_VERSION(2,20,0)
-static void ddb_cell_editable_text_view_real_editing_canceled (GtkCellRenderer*);
-#endif
DdbCellEditableTextView* ddb_cell_editable_text_view_new (void);
DdbCellEditableTextView* ddb_cell_editable_text_view_construct (GType object_type);
static void ddb_cell_editable_text_view_finalize (GObject* obj);
GType ddb_cell_renderer_text_multiline_get_type (void) G_GNUC_CONST;
#define DDB_CELL_RENDERER_TEXT_MULTILINE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DDB_TYPE_CELL_RENDERER_TEXT_MULTILINE, DdbCellRendererTextMultilinePrivate))
+#define DDB_CELL_EDITABLE_TEXT_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DDB_TYPE_CELL_EDITABLE_TEXT_VIEW, DdbCellEditableTextViewPrivate))
enum {
DDB_CELL_RENDERER_TEXT_MULTILINE_DUMMY_PROPERTY
};
@@ -143,7 +105,7 @@ static gboolean ddb_cell_editable_text_view_real_key_press_event (GtkWidget* bas
_tmp6_ = *event;
_tmp7_ = _tmp6_.keyval;
if (_tmp7_ == ((guint) GDK_Escape)) {
- self->editing_canceled = TRUE;
+ self->priv->editing_canceled = TRUE;
gtk_cell_editable_editing_done ((GtkCellEditable*) self);
gtk_cell_editable_remove_widget ((GtkCellEditable*) self);
result = TRUE;
@@ -173,8 +135,8 @@ static void ddb_cell_editable_text_view_real_editing_canceled (GtkCellRenderer*
#endif
DdbCellEditableTextView* ddb_cell_editable_text_view_construct (GType object_type) {
- DdbCellEditableTextView * self = NULL;
- self = (DdbCellEditableTextView*) g_object_new (object_type, NULL);
+ DdbCellEditableTextView * self;
+ self = g_object_newv (object_type, 0, NULL);
return self;
}
@@ -183,22 +145,89 @@ DdbCellEditableTextView* ddb_cell_editable_text_view_new (void) {
return ddb_cell_editable_text_view_construct (DDB_TYPE_CELL_EDITABLE_TEXT_VIEW);
}
+enum
+{
+ PROP_0,
+
+ PROP_EDITING_canceled,
+
+ N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+static void
+ddb_cell_editable_text_view_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ DdbCellEditableTextView *self = DDB_CELL_EDITABLE_TEXT_VIEW (object);
+
+ switch (property_id)
+ {
+ case PROP_EDITING_canceled:
+ self->priv->editing_canceled = g_value_get_boolean (value);
+ break;
+
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+ddb_cell_editable_text_view_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ DdbCellEditableTextView *self = DDB_CELL_EDITABLE_TEXT_VIEW (object);
+
+ switch (property_id)
+ {
+ case PROP_EDITING_canceled:
+ g_value_set_boolean (value, self->priv->editing_canceled);
+ break;
+
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
static void ddb_cell_editable_text_view_class_init (DdbCellEditableTextViewClass * klass) {
+ g_type_class_add_private (klass, sizeof (DdbCellEditableTextViewPrivate));
ddb_cell_editable_text_view_parent_class = g_type_class_peek_parent (klass);
GTK_WIDGET_CLASS (klass)->key_press_event = ddb_cell_editable_text_view_real_key_press_event;
G_OBJECT_CLASS (klass)->finalize = ddb_cell_editable_text_view_finalize;
+
+ G_OBJECT_CLASS (klass)->set_property = ddb_cell_editable_text_view_set_property;
+ G_OBJECT_CLASS (klass)->get_property = ddb_cell_editable_text_view_get_property;
+
+ obj_properties[PROP_EDITING_canceled] =
+ g_param_spec_boolean ("editing-canceled",
+ "Editing canceled",
+ "Indicates whether editing on the cell has been canceled",
+ FALSE,
+ G_PARAM_READWRITE);
+
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ g_object_class_install_properties (gobject_class, N_PROPERTIES, obj_properties);
}
static void ddb_cell_editable_text_view_gtk_cell_editable_interface_init (GtkCellEditableIface * iface) {
ddb_cell_editable_text_view_gtk_cell_editable_parent_iface = g_type_interface_peek_parent (iface);
- iface->start_editing = (void (*)(GtkCellEditable*, GdkEvent*)) ddb_cell_editable_text_view_real_start_editing;
+ iface->start_editing = ddb_cell_editable_text_view_real_start_editing;
}
static void ddb_cell_editable_text_view_instance_init (DdbCellEditableTextView * self) {
- self->editing_canceled = FALSE;
+ self->priv = DDB_CELL_EDITABLE_TEXT_VIEW_GET_PRIVATE (self);
+ self->priv->editing_canceled = FALSE;
}
@@ -259,7 +288,7 @@ static void ddb_cell_renderer_text_multiline_gtk_cell_renderer_text_editing_done
g_signal_handler_disconnect ((GObject*) _tmp0_, _tmp2_);
_tmp3_ = _self_;
_tmp4_ = entry;
- _tmp5_ = _tmp4_->editing_canceled;
+ _tmp5_ = _tmp4_->priv->editing_canceled;
gtk_cell_renderer_stop_editing ((GtkCellRenderer*) _tmp3_, _tmp5_);
_tmp6_ = entry;
_tmp7_ = gtk_text_view_get_buffer ((GtkTextView*) _tmp6_);
@@ -284,15 +313,11 @@ static void ddb_cell_renderer_text_multiline_gtk_cell_renderer_text_editing_done
static gboolean ddb_cell_renderer_text_multiline_gtk_cell_renderer_focus_out_event (DdbCellEditableTextView* entry, GdkEvent* event, DdbCellRendererTextMultiline* _self_) {
gboolean result = FALSE;
- DdbCellEditableTextView* _tmp0_;
- DdbCellEditableTextView* _tmp1_;
g_return_val_if_fail (entry != NULL, FALSE);
g_return_val_if_fail (event != NULL, FALSE);
g_return_val_if_fail (_self_ != NULL, FALSE);
- _tmp0_ = entry;
- _tmp0_->editing_canceled = TRUE;
- _tmp1_ = entry;
- gtk_cell_editable_remove_widget ((GtkCellEditable*) _tmp1_);
+ entry->priv->editing_canceled = TRUE;
+ gtk_cell_editable_remove_widget ((GtkCellEditable*) entry);
result = FALSE;
return result;
}
@@ -440,8 +465,8 @@ static GtkCellEditable* ddb_cell_renderer_text_multiline_real_start_editing (Gtk
DdbCellRendererTextMultiline* ddb_cell_renderer_text_multiline_construct (GType object_type) {
- DdbCellRendererTextMultiline * self = NULL;
- self = (DdbCellRendererTextMultiline*) g_object_new (object_type, NULL);
+ DdbCellRendererTextMultiline * self;
+ self = g_object_newv (object_type, 0, NULL);
return self;
}
@@ -454,15 +479,14 @@ DdbCellRendererTextMultiline* ddb_cell_renderer_text_multiline_new (void) {
static void ddb_cell_renderer_text_multiline_class_init (DdbCellRendererTextMultilineClass * klass) {
ddb_cell_renderer_text_multiline_parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (DdbCellRendererTextMultilinePrivate));
+ GTK_CELL_RENDERER_CLASS (klass)->start_editing = ddb_cell_renderer_text_multiline_real_start_editing;
G_OBJECT_CLASS (klass)->finalize = ddb_cell_renderer_text_multiline_finalize;
-#if GTK_CHECK_VERSION(2,20,0)
- GTK_CELL_RENDERER_CLASS (klass)->editing_canceled = (void (*)(GtkCellRenderer*)) ddb_cell_editable_text_view_real_editing_canceled;
-#endif
}
static void ddb_cell_renderer_text_multiline_instance_init (DdbCellRendererTextMultiline * self) {
self->priv = DDB_CELL_RENDERER_TEXT_MULTILINE_GET_PRIVATE (self);
+ printf ("alloc priv %p %p\n", self, self->priv);
}
diff --git a/plugins/gtkui/ddbcellrenderertextmultiline.h b/plugins/gtkui/ddbcellrenderertextmultiline.h
index b464472a..bdfec5ec 100644
--- a/plugins/gtkui/ddbcellrenderertextmultiline.h
+++ b/plugins/gtkui/ddbcellrenderertextmultiline.h
@@ -37,7 +37,6 @@ typedef struct _DdbCellRendererTextMultilinePrivate DdbCellRendererTextMultiline
struct _DdbCellEditableTextView {
GtkTextView parent_instance;
DdbCellEditableTextViewPrivate * priv;
- gboolean editing_canceled;
gchar* tree_path;
};
diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade
index 184b66fd..e369d119 100644
--- a/plugins/gtkui/deadbeef.glade
+++ b/plugins/gtkui/deadbeef.glade
@@ -788,6 +788,7 @@
<signal name="clicked" handler="on_playbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:48:53 GMT"/>
<accelerator key="x" modifiers="0" signal="activate"/>
<accelerator key="Return" modifiers="0" signal="activate"/>
+ <accelerator key="KP_Enter" modifiers="0" signal="activate"/>
<child>
<widget class="GtkImage" id="image2">
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index d18b120e..7ded4f6d 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -47,6 +47,7 @@
#include "pluginconf.h"
#include "gtkui_api.h"
#include "wingeom.h"
+#include "smclient/eggsmclient.h"
#define trace(...) { fprintf(stderr, __VA_ARGS__); }
//#define trace(fmt,...)
@@ -1037,15 +1038,26 @@ gtkui_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
return 0;
}
+static void
+smclient_quit_requested (EggSMClient *client, gpointer user_data) {
+ egg_sm_client_will_quit (client, TRUE);
+}
+
+static void
+smclient_quit_cancelled (EggSMClient *client, gpointer user_data) {
+}
+
+static void
+smclient_quit (EggSMClient *client, gpointer user_data) {
+ deadbeef->sendmessage (DB_EV_TERMINATE, 0, 0, 0);
+}
+
+static void
+smclient_save_state (EggSMClient *client, const char *state_dir, gpointer user_data) {
+}
+
void
gtkui_thread (void *ctx) {
- // let's start some gtk
- g_thread_init (NULL);
-// add_pixmap_directory (PREFIX "/share/deadbeef/pixmaps");
- add_pixmap_directory (deadbeef->get_pixmap_dir ());
- gdk_threads_init ();
- gdk_threads_enter ();
-
int argc = 2;
const char **argv = alloca (sizeof (char *) * argc);
argv[0] = "deadbeef";
@@ -1054,6 +1066,34 @@ gtkui_thread (void *ctx) {
if (!deadbeef->conf_get_int ("gtkui.sync", 0)) {
argc = 1;
}
+
+ g_type_init ();
+ GOptionContext *goption_context;
+ GError *err = NULL;
+ goption_context = g_option_context_new (_("- Test logout functionality"));
+ g_option_context_add_group (goption_context, gtk_get_option_group (TRUE));
+ g_option_context_add_group (goption_context, egg_sm_client_get_option_group ());
+
+ if (!g_option_context_parse (goption_context, &argc, (char ***)&argv, &err))
+ {
+ g_printerr ("Could not parse arguments: %s\n", err->message);
+ g_error_free (err);
+ }
+ else {
+ EggSMClient *client = egg_sm_client_get ();
+ g_signal_connect (client, "quit-requested", G_CALLBACK (smclient_quit_requested), NULL);
+ g_signal_connect (client, "quit-cancelled", G_CALLBACK (smclient_quit_cancelled), NULL);
+ g_signal_connect (client, "quit", G_CALLBACK (smclient_quit), NULL);
+ g_signal_connect (client, "save-state", G_CALLBACK (smclient_save_state), NULL);
+ }
+
+ // let's start some gtk
+ g_thread_init (NULL);
+// add_pixmap_directory (PREFIX "/share/deadbeef/pixmaps");
+ add_pixmap_directory (deadbeef->get_pixmap_dir ());
+ gdk_threads_init ();
+ gdk_threads_enter ();
+
gtk_disable_setlocale ();
gtk_init (&argc, (char ***)&argv);
diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c
index 84649092..7c79079a 100644
--- a/plugins/gtkui/interface.c
+++ b/plugins/gtkui/interface.c
@@ -523,6 +523,9 @@ create_mainwin (void)
gtk_widget_add_accelerator (playbtn, "activate", accel_group,
GDK_Return, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
+ gtk_widget_add_accelerator (playbtn, "activate", accel_group,
+ GDK_KP_Enter, (GdkModifierType) 0,
+ GTK_ACCEL_VISIBLE);
gtk_button_set_relief (GTK_BUTTON (playbtn), GTK_RELIEF_NONE);
image2 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_BUTTON);
diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c
index 6f447792..ddf9e395 100644
--- a/plugins/gtkui/prefwin.c
+++ b/plugins/gtkui/prefwin.c
@@ -197,6 +197,37 @@ on_hk_binding_edited (GtkCellRendererAccel *accel, gchar *path, guint accel_key,
strcat (new_value, "Alt ");
}
+ // translate numlock keycodes into non-numlock codes
+ switch (accel_key) {
+ case GDK_KP_0:
+ accel_key = GDK_KP_Insert;
+ break;
+ case GDK_KP_1:
+ accel_key = GDK_KP_End;
+ break;
+ case GDK_KP_2:
+ accel_key = GDK_KP_Down;
+ break;
+ case GDK_KP_3:
+ accel_key = GDK_KP_Page_Down;
+ break;
+ case GDK_KP_4:
+ accel_key = GDK_KP_Left;
+ break;
+ case GDK_KP_6:
+ accel_key = GDK_KP_Right;
+ break;
+ case GDK_KP_7:
+ accel_key = GDK_KP_Home;
+ break;
+ case GDK_KP_8:
+ accel_key = GDK_KP_Up;
+ break;
+ case GDK_KP_9:
+ accel_key = GDK_KP_Page_Up;
+ break;
+ }
+
// find key name from hotkeys plugin
DB_plugin_t *hotkeys = deadbeef->plug_get_for_id ("hotkeys");
if (hotkeys) {
diff --git a/plugins/gtkui/smclient/eggdesktopfile.c b/plugins/gtkui/smclient/eggdesktopfile.c
new file mode 100644
index 00000000..443d5ec6
--- /dev/null
+++ b/plugins/gtkui/smclient/eggdesktopfile.c
@@ -0,0 +1,1528 @@
+/* eggdesktopfile.c - Freedesktop.Org Desktop Files
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Based on gnome-desktop-item.c
+ * Copyright (C) 1999, 2000 Red Hat Inc.
+ * Copyright (C) 2001 George Lebl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place -
+ * Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "eggdesktopfile.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include <glib/gi18n.h>
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+
+struct EggDesktopFile {
+ GKeyFile *key_file;
+ char *source;
+
+ char *name, *icon;
+ EggDesktopFileType type;
+ char document_code;
+};
+
+/**
+ * egg_desktop_file_new:
+ * @desktop_file_path: path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @desktop_file.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new (const char *desktop_file_path, GError **error)
+{
+ GKeyFile *key_file;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (key_file, desktop_file_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ return egg_desktop_file_new_from_key_file (key_file, desktop_file_path,
+ error);
+}
+
+/**
+ * egg_desktop_file_new_from_data_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ GKeyFile *key_file;
+ char *full_path;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_data_dirs (key_file, desktop_file_path,
+ &full_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ desktop_file = egg_desktop_file_new_from_key_file (key_file,
+ full_path,
+ error);
+ g_free (full_path);
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_dirs:
+ * @desktop_file_path: relative path to a Freedesktop-style Desktop file
+ * @search_dirs: NULL-terminated array of directories to search
+ * @error: error pointer
+ *
+ * Looks for @desktop_file_path in the paths returned from
+ * g_get_user_data_dir() and g_get_system_data_dirs(), and creates
+ * a new #EggDesktopFile from it.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_dirs (const char *desktop_file_path,
+ const char **search_dirs,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ GKeyFile *key_file;
+ char *full_path;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_dirs (key_file, desktop_file_path, search_dirs,
+ &full_path, 0, error))
+ {
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ desktop_file = egg_desktop_file_new_from_key_file (key_file,
+ full_path,
+ error);
+ g_free (full_path);
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_new_from_key_file:
+ * @key_file: a #GKeyFile representing a desktop file
+ * @source: the path or URI that @key_file was loaded from, or %NULL
+ * @error: error pointer
+ *
+ * Creates a new #EggDesktopFile for @key_file. Assumes ownership of
+ * @key_file (on success or failure); you should consider @key_file to
+ * be freed after calling this function.
+ *
+ * Return value: the new #EggDesktopFile, or %NULL on error.
+ **/
+EggDesktopFile *
+egg_desktop_file_new_from_key_file (GKeyFile *key_file,
+ const char *source,
+ GError **error)
+{
+ EggDesktopFile *desktop_file;
+ char *version, *type;
+
+ if (!g_key_file_has_group (key_file, EGG_DESKTOP_FILE_GROUP))
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ _("File is not a valid .desktop file"));
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ version = g_key_file_get_value (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_VERSION,
+ NULL);
+ if (version)
+ {
+ double version_num;
+ char *end;
+
+ version_num = g_ascii_strtod (version, &end);
+ if (*end)
+ {
+ g_warning ("Invalid Version string '%s' in %s",
+ version, source ? source : "(unknown)");
+ }
+ else if (version_num > 1.0)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ /* translators: 'Version' is from a desktop file, and
+ * should not be translated. '%s' would probably be a
+ * version number. */
+ _("Unrecognized desktop file Version '%s'"), version);
+ g_free (version);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+ g_free (version);
+ }
+
+ desktop_file = g_new0 (EggDesktopFile, 1);
+ desktop_file->key_file = key_file;
+
+ if (g_path_is_absolute (source))
+ desktop_file->source = g_filename_to_uri (source, NULL, NULL);
+ else
+ desktop_file->source = g_strdup (source);
+
+ desktop_file->name = g_key_file_get_locale_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NAME,
+ NULL,
+ error);
+ if (!desktop_file->name)
+ {
+ egg_desktop_file_free (desktop_file);
+ return NULL;
+ }
+
+ type = g_key_file_get_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TYPE, error);
+ if (!type)
+ {
+ egg_desktop_file_free (desktop_file);
+ return NULL;
+ }
+
+ if (!strcmp (type, "Application"))
+ {
+ char *exec, *p;
+
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_APPLICATION;
+
+ exec = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ error);
+ if (!exec)
+ {
+ egg_desktop_file_free (desktop_file);
+ g_free (type);
+ return NULL;
+ }
+
+ /* See if it takes paths or URIs or neither */
+ for (p = exec; *p; p++)
+ {
+ if (*p == '%')
+ {
+ if (p[1] == '\0' || strchr ("FfUu", p[1]))
+ {
+ desktop_file->document_code = p[1];
+ break;
+ }
+ p++;
+ }
+ }
+
+ g_free (exec);
+ }
+ else if (!strcmp (type, "Link"))
+ {
+ char *url;
+
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_LINK;
+
+ url = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_URL,
+ error);
+ if (!url)
+ {
+ egg_desktop_file_free (desktop_file);
+ g_free (type);
+ return NULL;
+ }
+ g_free (url);
+ }
+ else if (!strcmp (type, "Directory"))
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_DIRECTORY;
+ else
+ desktop_file->type = EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED;
+
+ g_free (type);
+
+ /* Check the Icon key */
+ desktop_file->icon = g_key_file_get_string (key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_ICON,
+ NULL);
+ if (desktop_file->icon && !g_path_is_absolute (desktop_file->icon))
+ {
+ char *ext;
+
+ /* Lots of .desktop files still get this wrong */
+ ext = strrchr (desktop_file->icon, '.');
+ if (ext && (!strcmp (ext, ".png") ||
+ !strcmp (ext, ".xpm") ||
+ !strcmp (ext, ".svg")))
+ {
+ g_warning ("Desktop file '%s' has malformed Icon key '%s'"
+ "(should not include extension)",
+ source ? source : "(unknown)",
+ desktop_file->icon);
+ *ext = '\0';
+ }
+ }
+
+ return desktop_file;
+}
+
+/**
+ * egg_desktop_file_free:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Frees @desktop_file.
+ **/
+void
+egg_desktop_file_free (EggDesktopFile *desktop_file)
+{
+ g_key_file_free (desktop_file->key_file);
+ g_free (desktop_file->source);
+ g_free (desktop_file->name);
+ g_free (desktop_file->icon);
+ g_free (desktop_file);
+}
+
+/**
+ * egg_desktop_file_get_source:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the URI that @desktop_file was loaded from.
+ *
+ * Return value: @desktop_file's source URI
+ **/
+const char *
+egg_desktop_file_get_source (EggDesktopFile *desktop_file)
+{
+ return desktop_file->source;
+}
+
+/**
+ * egg_desktop_file_get_desktop_file_type:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the desktop file type of @desktop_file.
+ *
+ * Return value: @desktop_file's type
+ **/
+EggDesktopFileType
+egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file)
+{
+ return desktop_file->type;
+}
+
+/**
+ * egg_desktop_file_get_name:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the (localized) value of @desktop_file's "Name" key.
+ *
+ * Return value: the application/link name
+ **/
+const char *
+egg_desktop_file_get_name (EggDesktopFile *desktop_file)
+{
+ return desktop_file->name;
+}
+
+/**
+ * egg_desktop_file_get_icon:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Gets the value of @desktop_file's "Icon" key.
+ *
+ * If the icon string is a full path (that is, if g_path_is_absolute()
+ * returns %TRUE when called on it), it points to a file containing an
+ * unthemed icon. If the icon string is not a full path, it is the
+ * name of a themed icon, which can be looked up with %GtkIconTheme,
+ * or passed directly to a theme-aware widget like %GtkImage or
+ * %GtkCellRendererPixbuf.
+ *
+ * Return value: the icon path or name
+ **/
+const char *
+egg_desktop_file_get_icon (EggDesktopFile *desktop_file)
+{
+ return desktop_file->icon;
+}
+
+gboolean
+egg_desktop_file_has_key (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char *
+egg_desktop_file_get_string (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char *
+egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ GError **error)
+{
+ return g_key_file_get_locale_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key, locale,
+ error);
+}
+
+gboolean
+egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+double
+egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_double (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+int
+egg_desktop_file_get_integer (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error)
+{
+ return g_key_file_get_integer (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ error);
+}
+
+char **
+egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ gsize *length,
+ GError **error)
+{
+ return g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key, length,
+ error);
+}
+
+char **
+egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ gsize *length,
+ GError **error)
+{
+ return g_key_file_get_locale_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP, key,
+ locale, length,
+ error);
+}
+
+/**
+ * egg_desktop_file_can_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @desktop_environment: the name of the running desktop environment,
+ * or %NULL
+ *
+ * Tests if @desktop_file can/should be launched in the current
+ * environment. If @desktop_environment is non-%NULL, @desktop_file's
+ * "OnlyShowIn" and "NotShowIn" keys are checked to make sure that
+ * this desktop_file is appropriate for the named environment.
+ *
+ * Furthermore, if @desktop_file has type
+ * %EGG_DESKTOP_FILE_TYPE_APPLICATION, its "TryExec" key (if any) is
+ * also checked, to make sure the binary it points to exists.
+ *
+ * egg_desktop_file_can_launch() does NOT check the value of the
+ * "Hidden" key.
+ *
+ * Return value: %TRUE if @desktop_file can be launched
+ **/
+gboolean
+egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
+ const char *desktop_environment)
+{
+ char *try_exec, *found_program;
+ char **only_show_in, **not_show_in;
+ gboolean found;
+ int i;
+
+ if (desktop_file->type != EGG_DESKTOP_FILE_TYPE_APPLICATION &&
+ desktop_file->type != EGG_DESKTOP_FILE_TYPE_LINK)
+ return FALSE;
+
+ if (desktop_environment)
+ {
+ only_show_in = g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN,
+ NULL, NULL);
+ if (only_show_in)
+ {
+ for (i = 0, found = FALSE; only_show_in[i] && !found; i++)
+ {
+ if (!strcmp (only_show_in[i], desktop_environment))
+ found = TRUE;
+ }
+
+ g_strfreev (only_show_in);
+
+ if (!found)
+ return FALSE;
+ }
+
+ not_show_in = g_key_file_get_string_list (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN,
+ NULL, NULL);
+ if (not_show_in)
+ {
+ for (i = 0, found = FALSE; not_show_in[i] && !found; i++)
+ {
+ if (!strcmp (not_show_in[i], desktop_environment))
+ found = TRUE;
+ }
+
+ g_strfreev (not_show_in);
+
+ if (found)
+ return FALSE;
+ }
+ }
+
+ if (desktop_file->type == EGG_DESKTOP_FILE_TYPE_APPLICATION)
+ {
+ try_exec = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TRY_EXEC,
+ NULL);
+ if (try_exec)
+ {
+ found_program = g_find_program_in_path (try_exec);
+ g_free (try_exec);
+
+ if (!found_program)
+ return FALSE;
+ g_free (found_program);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * egg_desktop_file_accepts_documents:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file represents an application that can accept
+ * documents on the command line.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file)
+{
+ return desktop_file->document_code != 0;
+}
+
+/**
+ * egg_desktop_file_accepts_multiple:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept multiple documents at once.
+ *
+ * If this returns %FALSE, you can still pass multiple documents to
+ * egg_desktop_file_launch(), but that will result in multiple copies
+ * of the application being launched. See egg_desktop_file_launch()
+ * for more details.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file)
+{
+ return (desktop_file->document_code == 'F' ||
+ desktop_file->document_code == 'U');
+}
+
+/**
+ * egg_desktop_file_accepts_uris:
+ * @desktop_file: an #EggDesktopFile
+ *
+ * Tests if @desktop_file can accept (non-"file:") URIs as documents to
+ * open.
+ *
+ * Return value: %TRUE or %FALSE
+ **/
+gboolean
+egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file)
+{
+ return (desktop_file->document_code == 'U' ||
+ desktop_file->document_code == 'u');
+}
+
+static void
+append_quoted_word (GString *str,
+ const char *s,
+ gboolean in_single_quotes,
+ gboolean in_double_quotes)
+{
+ const char *p;
+
+ if (!in_single_quotes && !in_double_quotes)
+ g_string_append_c (str, '\'');
+ else if (!in_single_quotes && in_double_quotes)
+ g_string_append (str, "\"'");
+
+ if (!strchr (s, '\''))
+ g_string_append (str, s);
+ else
+ {
+ for (p = s; *p != '\0'; p++)
+ {
+ if (*p == '\'')
+ g_string_append (str, "'\\''");
+ else
+ g_string_append_c (str, *p);
+ }
+ }
+
+ if (!in_single_quotes && !in_double_quotes)
+ g_string_append_c (str, '\'');
+ else if (!in_single_quotes && in_double_quotes)
+ g_string_append (str, "'\"");
+}
+
+static void
+do_percent_subst (EggDesktopFile *desktop_file,
+ char code,
+ GString *str,
+ GSList **documents,
+ gboolean in_single_quotes,
+ gboolean in_double_quotes)
+{
+ GSList *d;
+ char *doc;
+
+ switch (code)
+ {
+ case '%':
+ g_string_append_c (str, '%');
+ break;
+
+ case 'F':
+ case 'U':
+ for (d = *documents; d; d = d->next)
+ {
+ doc = d->data;
+ g_string_append (str, " ");
+ append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+ }
+ *documents = NULL;
+ break;
+
+ case 'f':
+ case 'u':
+ if (*documents)
+ {
+ doc = (*documents)->data;
+ g_string_append (str, " ");
+ append_quoted_word (str, doc, in_single_quotes, in_double_quotes);
+ *documents = (*documents)->next;
+ }
+ break;
+
+ case 'i':
+ if (desktop_file->icon)
+ {
+ g_string_append (str, "--icon ");
+ append_quoted_word (str, desktop_file->icon,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'c':
+ if (desktop_file->name)
+ {
+ append_quoted_word (str, desktop_file->name,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'k':
+ if (desktop_file->source)
+ {
+ append_quoted_word (str, desktop_file->source,
+ in_single_quotes, in_double_quotes);
+ }
+ break;
+
+ case 'D':
+ case 'N':
+ case 'd':
+ case 'n':
+ case 'v':
+ case 'm':
+ /* Deprecated; skip */
+ break;
+
+ default:
+ g_warning ("Unrecognized %%-code '%%%c' in Exec", code);
+ break;
+ }
+}
+
+static char *
+parse_exec (EggDesktopFile *desktop_file,
+ GSList **documents,
+ GError **error)
+{
+ char *exec, *p, *command;
+ gboolean escape, single_quot, double_quot;
+ GString *gs;
+
+ exec = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ error);
+ if (!exec)
+ return NULL;
+
+ /* Build the command */
+ gs = g_string_new (NULL);
+ escape = single_quot = double_quot = FALSE;
+
+ for (p = exec; *p != '\0'; p++)
+ {
+ if (escape)
+ {
+ escape = FALSE;
+ g_string_append_c (gs, *p);
+ }
+ else if (*p == '\\')
+ {
+ if (!single_quot)
+ escape = TRUE;
+ g_string_append_c (gs, *p);
+ }
+ else if (*p == '\'')
+ {
+ g_string_append_c (gs, *p);
+ if (!single_quot && !double_quot)
+ single_quot = TRUE;
+ else if (single_quot)
+ single_quot = FALSE;
+ }
+ else if (*p == '"')
+ {
+ g_string_append_c (gs, *p);
+ if (!single_quot && !double_quot)
+ double_quot = TRUE;
+ else if (double_quot)
+ double_quot = FALSE;
+ }
+ else if (*p == '%' && p[1])
+ {
+ do_percent_subst (desktop_file, p[1], gs, documents,
+ single_quot, double_quot);
+ p++;
+ }
+ else
+ g_string_append_c (gs, *p);
+ }
+
+ g_free (exec);
+ command = g_string_free (gs, FALSE);
+
+ /* Prepend "xdg-terminal " if needed (FIXME: use gvfs) */
+ if (g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TERMINAL,
+ NULL))
+ {
+ GError *terminal_error = NULL;
+ gboolean use_terminal =
+ g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TERMINAL,
+ &terminal_error);
+ if (terminal_error)
+ {
+ g_free (command);
+ g_propagate_error (error, terminal_error);
+ return NULL;
+ }
+
+ if (use_terminal)
+ {
+ gs = g_string_new ("xdg-terminal ");
+ append_quoted_word (gs, command, FALSE, FALSE);
+ g_free (command);
+ command = g_string_free (gs, FALSE);
+ }
+ }
+
+ return command;
+}
+
+static GSList *
+translate_document_list (EggDesktopFile *desktop_file, GSList *documents)
+{
+ gboolean accepts_uris = egg_desktop_file_accepts_uris (desktop_file);
+ GSList *ret, *d;
+
+ for (d = documents, ret = NULL; d; d = d->next)
+ {
+ const char *document = d->data;
+ gboolean is_uri = !g_path_is_absolute (document);
+ char *translated;
+
+ if (accepts_uris)
+ {
+ if (is_uri)
+ translated = g_strdup (document);
+ else
+ translated = g_filename_to_uri (document, NULL, NULL);
+ }
+ else
+ {
+ if (is_uri)
+ translated = g_filename_from_uri (document, NULL, NULL);
+ else
+ translated = g_strdup (document);
+ }
+
+ if (translated)
+ ret = g_slist_prepend (ret, translated);
+ }
+
+ return g_slist_reverse (ret);
+}
+
+static void
+free_document_list (GSList *documents)
+{
+ GSList *d;
+
+ for (d = documents; d; d = d->next)
+ g_free (d->data);
+ g_slist_free (documents);
+}
+
+/**
+ * egg_desktop_file_parse_exec:
+ * @desktop_file: a #EggDesktopFile
+ * @documents: a list of document paths or URIs
+ * @error: error pointer
+ *
+ * Parses @desktop_file's Exec key, inserting @documents into it, and
+ * returns the result.
+ *
+ * If @documents contains non-file: URIs and @desktop_file does not
+ * accept URIs, those URIs will be ignored. Likewise, if @documents
+ * contains more elements than @desktop_file accepts, the extra
+ * documents will be ignored.
+ *
+ * Return value: the parsed Exec string
+ **/
+char *
+egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error)
+{
+ GSList *translated, *docs;
+ char *command;
+
+ docs = translated = translate_document_list (desktop_file, documents);
+ command = parse_exec (desktop_file, &docs, error);
+ free_document_list (translated);
+
+ return command;
+}
+
+static gboolean
+parse_link (EggDesktopFile *desktop_file,
+ EggDesktopFile **app_desktop_file,
+ GSList **documents,
+ GError **error)
+{
+ char *url;
+ GKeyFile *key_file;
+
+ url = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_URL,
+ error);
+ if (!url)
+ return FALSE;
+ *documents = g_slist_prepend (NULL, url);
+
+ /* FIXME: use gvfs */
+ key_file = g_key_file_new ();
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_NAME,
+ "xdg-open");
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_TYPE,
+ "Application");
+ g_key_file_set_string (key_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ "xdg-open %u");
+ *app_desktop_file = egg_desktop_file_new_from_key_file (key_file, NULL, NULL);
+ return TRUE;
+}
+
+#if GTK_CHECK_VERSION (2, 12, 0)
+static char *
+start_startup_notification (GdkDisplay *display,
+ EggDesktopFile *desktop_file,
+ const char *argv0,
+ int screen,
+ int workspace,
+ guint32 launch_time)
+{
+ static int sequence = 0;
+ char *startup_id;
+ char *description, *wmclass;
+ char *screen_str, *workspace_str;
+
+ if (g_key_file_has_key (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+ NULL))
+ {
+ if (!g_key_file_get_boolean (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY,
+ NULL))
+ return NULL;
+ wmclass = NULL;
+ }
+ else
+ {
+ wmclass = g_key_file_get_string (desktop_file->key_file,
+ EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS,
+ NULL);
+ if (!wmclass)
+ return NULL;
+ }
+
+ if (launch_time == (guint32)-1)
+ launch_time = gdk_x11_display_get_user_time (display);
+ startup_id = g_strdup_printf ("%s-%lu-%s-%s-%d_TIME%lu",
+ g_get_prgname (),
+ (unsigned long)getpid (),
+ g_get_host_name (),
+ argv0,
+ sequence++,
+ (unsigned long)launch_time);
+
+ description = g_strdup_printf (_("Starting %s"), desktop_file->name);
+ screen_str = g_strdup_printf ("%d", screen);
+ workspace_str = workspace == -1 ? NULL : g_strdup_printf ("%d", workspace);
+
+ gdk_x11_display_broadcast_startup_message (display, "new",
+ "ID", startup_id,
+ "NAME", desktop_file->name,
+ "SCREEN", screen_str,
+ "BIN", argv0,
+ "ICON", desktop_file->icon,
+ "DESKTOP", workspace_str,
+ "DESCRIPTION", description,
+ "WMCLASS", wmclass,
+ NULL);
+
+ g_free (description);
+ g_free (wmclass);
+ g_free (screen_str);
+ g_free (workspace_str);
+
+ return startup_id;
+}
+
+static void
+end_startup_notification (GdkDisplay *display,
+ const char *startup_id)
+{
+ gdk_x11_display_broadcast_startup_message (display, "remove",
+ "ID", startup_id,
+ NULL);
+}
+
+#define EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH (30 /* seconds */)
+
+typedef struct {
+ GdkDisplay *display;
+ char *startup_id;
+} StartupNotificationData;
+
+static gboolean
+startup_notification_timeout (gpointer data)
+{
+ StartupNotificationData *sn_data = data;
+
+ end_startup_notification (sn_data->display, sn_data->startup_id);
+ g_object_unref (sn_data->display);
+ g_free (sn_data->startup_id);
+ g_free (sn_data);
+
+ return FALSE;
+}
+
+static void
+set_startup_notification_timeout (GdkDisplay *display,
+ const char *startup_id)
+{
+ StartupNotificationData *sn_data;
+
+ sn_data = g_new (StartupNotificationData, 1);
+ sn_data->display = g_object_ref (display);
+ sn_data->startup_id = g_strdup (startup_id);
+
+ g_timeout_add_seconds (EGG_DESKTOP_FILE_SN_TIMEOUT_LENGTH,
+ startup_notification_timeout, sn_data);
+}
+#endif /* GTK 2.12 */
+
+static GPtrArray *
+array_putenv (GPtrArray *env, char *variable)
+{
+ guint i, keylen;
+
+ if (!env)
+ {
+ char **envp;
+
+ env = g_ptr_array_new ();
+
+ envp = g_listenv ();
+ for (i = 0; envp[i]; i++)
+ {
+ const char *value;
+
+ value = g_getenv (envp[i]);
+ g_ptr_array_add (env, g_strdup_printf ("%s=%s", envp[i],
+ value ? value : ""));
+ }
+ g_strfreev (envp);
+ }
+
+ keylen = strcspn (variable, "=");
+
+ /* Remove old value of key */
+ for (i = 0; i < env->len; i++)
+ {
+ char *envvar = env->pdata[i];
+
+ if (!strncmp (envvar, variable, keylen) && envvar[keylen] == '=')
+ {
+ g_free (envvar);
+ g_ptr_array_remove_index_fast (env, i);
+ break;
+ }
+ }
+
+ /* Add new value */
+ g_ptr_array_add (env, g_strdup (variable));
+
+ return env;
+}
+
+static gboolean
+egg_desktop_file_launchv (EggDesktopFile *desktop_file,
+ GSList *documents, va_list args,
+ GError **error)
+{
+ EggDesktopFileLaunchOption option;
+ GSList *translated_documents = NULL, *docs = NULL;
+ char *command, **argv;
+ int argc, i, screen_num;
+ gboolean success, current_success;
+ GdkDisplay *display;
+ char *startup_id;
+
+ GPtrArray *env = NULL;
+ char **variables = NULL;
+ GdkScreen *screen = NULL;
+ int workspace = -1;
+ const char *directory = NULL;
+ guint32 launch_time = (guint32)-1;
+ GSpawnFlags flags = G_SPAWN_SEARCH_PATH;
+ GSpawnChildSetupFunc setup_func = NULL;
+ gpointer setup_data = NULL;
+
+ GPid *ret_pid = NULL;
+ int *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL;
+ char **ret_startup_id = NULL;
+
+ if (documents && desktop_file->document_code == 0)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ _("Application does not accept documents on command line"));
+ return FALSE;
+ }
+
+ /* Read the options: technically it's incorrect for the caller to
+ * NULL-terminate the list of options (rather than 0-terminating
+ * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED,
+ * it's more consistent with other glib/gtk methods, and it will
+ * work as long as sizeof (int) <= sizeof (NULL), and NULL is
+ * represented as 0. (Which is true everywhere we care about.)
+ */
+ while ((option = va_arg (args, EggDesktopFileLaunchOption)))
+ {
+ switch (option)
+ {
+ case EGG_DESKTOP_FILE_LAUNCH_CLEARENV:
+ if (env)
+ g_ptr_array_free (env, TRUE);
+ env = g_ptr_array_new ();
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_PUTENV:
+ variables = va_arg (args, char **);
+ for (i = 0; variables[i]; i++)
+ env = array_putenv (env, variables[i]);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_SCREEN:
+ screen = va_arg (args, GdkScreen *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE:
+ workspace = va_arg (args, int);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY:
+ directory = va_arg (args, const char *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_TIME:
+ launch_time = va_arg (args, guint32);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_FLAGS:
+ flags |= va_arg (args, GSpawnFlags);
+ /* Make sure they didn't set any flags that don't make sense. */
+ flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO;
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC:
+ setup_func = va_arg (args, GSpawnChildSetupFunc);
+ setup_data = va_arg (args, gpointer);
+ break;
+
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID:
+ ret_pid = va_arg (args, GPid *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE:
+ ret_stdin = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE:
+ ret_stdout = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE:
+ ret_stderr = va_arg (args, int *);
+ break;
+ case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID:
+ ret_startup_id = va_arg (args, char **);
+ break;
+
+ default:
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION,
+ _("Unrecognized launch option: %d"),
+ GPOINTER_TO_INT (option));
+ success = FALSE;
+ goto out;
+ }
+ }
+
+ if (screen)
+ {
+ char *display_name = gdk_screen_make_display_name (screen);
+ char *display_env = g_strdup_printf ("DISPLAY=%s", display_name);
+ env = array_putenv (env, display_env);
+ g_free (display_name);
+ g_free (display_env);
+
+ display = gdk_screen_get_display (screen);
+ }
+ else
+ {
+ display = gdk_display_get_default ();
+ screen = gdk_display_get_default_screen (display);
+ }
+ screen_num = gdk_screen_get_number (screen);
+
+ translated_documents = translate_document_list (desktop_file, documents);
+ docs = translated_documents;
+
+ success = FALSE;
+
+ do
+ {
+ command = parse_exec (desktop_file, &docs, error);
+ if (!command)
+ goto out;
+
+ if (!g_shell_parse_argv (command, &argc, &argv, error))
+ {
+ g_free (command);
+ goto out;
+ }
+ g_free (command);
+
+#if GTK_CHECK_VERSION (2, 12, 0)
+ startup_id = start_startup_notification (display, desktop_file,
+ argv[0], screen_num,
+ workspace, launch_time);
+ if (startup_id)
+ {
+ char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s",
+ startup_id);
+ env = array_putenv (env, startup_id_env);
+ g_free (startup_id_env);
+ }
+#else
+ startup_id = NULL;
+#endif /* GTK 2.12 */
+
+ if (env != NULL)
+ g_ptr_array_add (env, NULL);
+
+ current_success =
+ g_spawn_async_with_pipes (directory,
+ argv,
+ env ? (char **)(env->pdata) : NULL,
+ flags,
+ setup_func, setup_data,
+ ret_pid,
+ ret_stdin, ret_stdout, ret_stderr,
+ error);
+ g_strfreev (argv);
+
+ if (startup_id)
+ {
+#if GTK_CHECK_VERSION (2, 12, 0)
+ if (current_success)
+ {
+ set_startup_notification_timeout (display, startup_id);
+
+ if (ret_startup_id)
+ *ret_startup_id = startup_id;
+ else
+ g_free (startup_id);
+ }
+ else
+#endif /* GTK 2.12 */
+ g_free (startup_id);
+ }
+ else if (ret_startup_id)
+ *ret_startup_id = NULL;
+
+ if (current_success)
+ {
+ /* If we successfully launch any instances of the app, make
+ * sure we return TRUE and don't set @error.
+ */
+ success = TRUE;
+ error = NULL;
+
+ /* Also, only set the output params on the first one */
+ ret_pid = NULL;
+ ret_stdin = ret_stdout = ret_stderr = NULL;
+ ret_startup_id = NULL;
+ }
+ }
+ while (docs && current_success);
+
+ out:
+ if (env)
+ {
+ g_ptr_array_foreach (env, (GFunc)g_free, NULL);
+ g_ptr_array_free (env, TRUE);
+ }
+ free_document_list (translated_documents);
+
+ return success;
+}
+
+/**
+ * egg_desktop_file_launch:
+ * @desktop_file: an #EggDesktopFile
+ * @documents: a list of URIs or paths to documents to open
+ * @error: error pointer
+ * @...: additional options
+ *
+ * Launches @desktop_file with the given arguments. Additional options
+ * can be specified as follows:
+ *
+ * %EGG_DESKTOP_FILE_LAUNCH_CLEARENV: (no arguments)
+ * clears the environment in the child process
+ * %EGG_DESKTOP_FILE_LAUNCH_PUTENV: (char **variables)
+ * adds the NAME=VALUE strings in the given %NULL-terminated
+ * array to the child process's environment
+ * %EGG_DESKTOP_FILE_LAUNCH_SCREEN: (GdkScreen *screen)
+ * causes the application to be launched on the given screen
+ * %EGG_DESKTOP_FILE_LAUNCH_WORKSPACE: (int workspace)
+ * causes the application to be launched on the given workspace
+ * %EGG_DESKTOP_FILE_LAUNCH_DIRECTORY: (char *dir)
+ * causes the application to be launched in the given directory
+ * %EGG_DESKTOP_FILE_LAUNCH_TIME: (guint32 launch_time)
+ * sets the "launch time" for the application. If the user
+ * interacts with another window after @launch_time but before
+ * the launched application creates its first window, the window
+ * manager may choose to not give focus to the new application.
+ * Passing 0 for @launch_time will explicitly request that the
+ * application not receive focus.
+ * %EGG_DESKTOP_FILE_LAUNCH_FLAGS (GSpawnFlags flags)
+ * Sets additional #GSpawnFlags to use. See g_spawn_async() for
+ * more details.
+ * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC (GSpawnChildSetupFunc, gpointer)
+ * Sets the child setup callback and the data to pass to it.
+ * (See g_spawn_async() for more details.)
+ *
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID (GPid **pid)
+ * On a successful launch, sets *@pid to the PID of the launched
+ * application.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID (char **startup_id)
+ * On a successful launch, sets *@startup_id to the Startup
+ * Notification "startup id" of the launched application.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stdin.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stdout.
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE (int *fd)
+ * On a successful launch, sets *@fd to the file descriptor of
+ * a pipe connected to the application's stderr.
+ *
+ * The options should be terminated with a single %NULL.
+ *
+ * If @documents contains multiple documents, but
+ * egg_desktop_file_accepts_multiple() returns %FALSE for
+ * @desktop_file, then egg_desktop_file_launch() will actually launch
+ * multiple instances of the application. In that case, the return
+ * value (as well as any values passed via
+ * %EGG_DESKTOP_FILE_LAUNCH_RETURN_PID, etc) will only reflect the
+ * first instance of the application that was launched (but the
+ * %EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC will be called for each
+ * instance).
+ *
+ * Return value: %TRUE if the application was successfully launched.
+ **/
+gboolean
+egg_desktop_file_launch (EggDesktopFile *desktop_file,
+ GSList *documents, GError **error,
+ ...)
+{
+ va_list args;
+ gboolean success;
+ EggDesktopFile *app_desktop_file;
+
+ switch (desktop_file->type)
+ {
+ case EGG_DESKTOP_FILE_TYPE_APPLICATION:
+ va_start (args, error);
+ success = egg_desktop_file_launchv (desktop_file, documents,
+ args, error);
+ va_end (args);
+ break;
+
+ case EGG_DESKTOP_FILE_TYPE_LINK:
+ if (documents)
+ {
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ /* translators: The 'Type=Link' string is found in a
+ * desktop file, and should not be translated. */
+ _("Can't pass document URIs to a 'Type=Link' desktop entry"));
+ return FALSE;
+ }
+
+ if (!parse_link (desktop_file, &app_desktop_file, &documents, error))
+ return FALSE;
+
+ va_start (args, error);
+ success = egg_desktop_file_launchv (app_desktop_file, documents,
+ args, error);
+ va_end (args);
+
+ egg_desktop_file_free (app_desktop_file);
+ free_document_list (documents);
+ break;
+
+ case EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED:
+ case EGG_DESKTOP_FILE_TYPE_DIRECTORY:
+ default:
+ g_set_error (error, EGG_DESKTOP_FILE_ERROR,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ _("Not a launchable item"));
+ success = FALSE;
+ break;
+ }
+
+ return success;
+}
+
+
+GQuark
+egg_desktop_file_error_quark (void)
+{
+ return g_quark_from_static_string ("egg-desktop_file-error-quark");
+}
+
+
+G_LOCK_DEFINE_STATIC (egg_desktop_file);
+static EggDesktopFile *egg_desktop_file;
+
+static void
+egg_set_desktop_file_internal (const char *desktop_file_path,
+ gboolean set_defaults)
+{
+ GError *error = NULL;
+
+ G_LOCK (egg_desktop_file);
+ if (egg_desktop_file)
+ egg_desktop_file_free (egg_desktop_file);
+
+ egg_desktop_file = egg_desktop_file_new (desktop_file_path, &error);
+ if (error)
+ {
+ g_warning ("Could not load desktop file '%s': %s",
+ desktop_file_path, error->message);
+ g_error_free (error);
+ }
+
+ if (set_defaults && egg_desktop_file != NULL) {
+ /* Set localized application name and default window icon */
+ if (egg_desktop_file->name)
+ g_set_application_name (egg_desktop_file->name);
+ if (egg_desktop_file->icon)
+ {
+ if (g_path_is_absolute (egg_desktop_file->icon))
+ gtk_window_set_default_icon_from_file (egg_desktop_file->icon, NULL);
+ else
+ gtk_window_set_default_icon_name (egg_desktop_file->icon);
+ }
+ }
+
+ G_UNLOCK (egg_desktop_file);
+}
+
+/**
+ * egg_set_desktop_file:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path. This will also call g_set_application_name()
+ * with the localized application name from the desktop file, and
+ * gtk_window_set_default_icon_name() or
+ * gtk_window_set_default_icon_from_file() with the application's
+ * icon. Other code may use additional information from the desktop
+ * file.
+ * See egg_set_desktop_file_without_defaults() for a variant of this
+ * function that does not set the application name and default window
+ * icon.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file_without_defaults().
+ **/
+void
+egg_set_desktop_file (const char *desktop_file_path)
+{
+ egg_set_desktop_file_internal (desktop_file_path, TRUE);
+}
+
+/**
+ * egg_set_desktop_file_without_defaults:
+ * @desktop_file_path: path to the application's desktop file
+ *
+ * Creates an #EggDesktopFile for the application from the data at
+ * @desktop_file_path.
+ * See egg_set_desktop_file() for a variant of this function that
+ * sets the application name and default window icon from the information
+ * in the desktop file.
+ *
+ * Note that for thread safety reasons, this function can only
+ * be called once, and is mutually exclusive with calling
+ * egg_set_desktop_file().
+ **/
+void
+egg_set_desktop_file_without_defaults (const char *desktop_file_path)
+{
+ egg_set_desktop_file_internal (desktop_file_path, FALSE);
+}
+
+/**
+ * egg_get_desktop_file:
+ *
+ * Gets the application's #EggDesktopFile, as set by
+ * egg_set_desktop_file().
+ *
+ * Return value: the #EggDesktopFile, or %NULL if it hasn't been set.
+ **/
+EggDesktopFile *
+egg_get_desktop_file (void)
+{
+ EggDesktopFile *retval;
+
+ G_LOCK (egg_desktop_file);
+ retval = egg_desktop_file;
+ G_UNLOCK (egg_desktop_file);
+
+ return retval;
+}
diff --git a/plugins/gtkui/smclient/eggdesktopfile.h b/plugins/gtkui/smclient/eggdesktopfile.h
new file mode 100644
index 00000000..16c5426c
--- /dev/null
+++ b/plugins/gtkui/smclient/eggdesktopfile.h
@@ -0,0 +1,163 @@
+/* eggdesktopfile.h - Freedesktop.Org Desktop Files
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place -
+ * Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_DESKTOP_FILE_H__
+#define __EGG_DESKTOP_FILE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct EggDesktopFile EggDesktopFile;
+
+typedef enum {
+ EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
+
+ EGG_DESKTOP_FILE_TYPE_APPLICATION,
+ EGG_DESKTOP_FILE_TYPE_LINK,
+ EGG_DESKTOP_FILE_TYPE_DIRECTORY
+} EggDesktopFileType;
+
+EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
+ GError **error);
+
+EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
+ GError **error);
+EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
+ const char **search_dirs,
+ GError **error);
+EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
+ const char *source,
+ GError **error);
+
+void egg_desktop_file_free (EggDesktopFile *desktop_file);
+
+const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);
+
+EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);
+
+const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
+const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);
+
+gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
+ const char *desktop_environment);
+
+gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
+gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
+gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
+
+char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error);
+
+gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
+ GSList *documents,
+ GError **error,
+ ...) G_GNUC_NULL_TERMINATED;
+
+typedef enum {
+ EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
+ EGG_DESKTOP_FILE_LAUNCH_PUTENV,
+ EGG_DESKTOP_FILE_LAUNCH_SCREEN,
+ EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
+ EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
+ EGG_DESKTOP_FILE_LAUNCH_TIME,
+ EGG_DESKTOP_FILE_LAUNCH_FLAGS,
+ EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
+ EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
+} EggDesktopFileLaunchOption;
+
+/* Standard Keys */
+#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
+
+#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
+#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
+#define EGG_DESKTOP_FILE_KEY_NAME "Name"
+#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
+#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
+#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
+#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
+#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
+#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
+#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
+#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
+#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
+#define EGG_DESKTOP_FILE_KEY_PATH "Path"
+#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
+#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
+#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
+#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
+#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
+#define EGG_DESKTOP_FILE_KEY_URL "URL"
+
+/* Accessors */
+gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error) G_GNUC_MALLOC;
+char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ GError **error) G_GNUC_MALLOC;
+gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+int egg_desktop_file_get_integer (EggDesktopFile *desktop_file,
+ const char *key,
+ GError **error);
+char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ gsize *length,
+ GError **error) G_GNUC_MALLOC;
+char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
+ const char *key,
+ const char *locale,
+ gsize *length,
+ GError **error) G_GNUC_MALLOC;
+
+
+/* Errors */
+#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
+
+GQuark egg_desktop_file_error_quark (void);
+
+typedef enum {
+ EGG_DESKTOP_FILE_ERROR_INVALID,
+ EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
+ EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
+} EggDesktopFileError;
+
+/* Global application desktop file */
+void egg_set_desktop_file (const char *desktop_file_path);
+void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
+EggDesktopFile *egg_get_desktop_file (void);
+
+
+G_END_DECLS
+
+#endif /* __EGG_DESKTOP_FILE_H__ */
diff --git a/plugins/gtkui/smclient/eggsmclient-private.h b/plugins/gtkui/smclient/eggsmclient-private.h
new file mode 100644
index 00000000..0c98eeed
--- /dev/null
+++ b/plugins/gtkui/smclient/eggsmclient-private.h
@@ -0,0 +1,59 @@
+/* eggsmclient-private.h
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_SM_CLIENT_PRIVATE_H__
+#define __EGG_SM_CLIENT_PRIVATE_H__
+
+#include <gtk/gtk.h>
+
+#if !GTK_CHECK_VERSION(2,91,7) && !GTK_CHECK_VERSION(3,0,0)
+/* GTK+ 3 includes this automatically */
+#include <gdkconfig.h>
+#endif
+
+#include "eggsmclient.h"
+
+G_BEGIN_DECLS
+
+GKeyFile *egg_sm_client_save_state (EggSMClient *client);
+void egg_sm_client_quit_requested (EggSMClient *client);
+void egg_sm_client_quit_cancelled (EggSMClient *client);
+void egg_sm_client_quit (EggSMClient *client);
+
+#if defined (GDK_WINDOWING_X11)
+# ifdef EGG_SM_CLIENT_BACKEND_XSMP
+GType egg_sm_client_xsmp_get_type (void);
+EggSMClient *egg_sm_client_xsmp_new (void);
+# endif
+# ifdef EGG_SM_CLIENT_BACKEND_DBUS
+GType egg_sm_client_dbus_get_type (void);
+EggSMClient *egg_sm_client_dbus_new (void);
+# endif
+#elif defined (GDK_WINDOWING_WIN32)
+GType egg_sm_client_win32_get_type (void);
+EggSMClient *egg_sm_client_win32_new (void);
+#elif defined (GDK_WINDOWING_QUARTZ)
+GType egg_sm_client_osx_get_type (void);
+EggSMClient *egg_sm_client_osx_new (void);
+#endif
+
+G_END_DECLS
+
+
+#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */
diff --git a/plugins/gtkui/smclient/eggsmclient-xsmp.c b/plugins/gtkui/smclient/eggsmclient-xsmp.c
new file mode 100644
index 00000000..2c65de7c
--- /dev/null
+++ b/plugins/gtkui/smclient/eggsmclient-xsmp.c
@@ -0,0 +1,1381 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * Inspired by various other pieces of code including GsmClient (C)
+ * 2001 Havoc Pennington, GnomeClient (C) 1998 Carsten Schaar, and twm
+ * session code (C) 1998 The Open Group.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+#include "eggdesktopfile.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/SM/SMlib.h>
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#define EGG_TYPE_SM_CLIENT_XSMP (egg_sm_client_xsmp_get_type ())
+#define EGG_SM_CLIENT_XSMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMP))
+#define EGG_SM_CLIENT_XSMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+#define EGG_IS_SM_CLIENT_XSMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_IS_SM_CLIENT_XSMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_XSMP))
+#define EGG_SM_CLIENT_XSMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass))
+
+typedef struct _EggSMClientXSMP EggSMClientXSMP;
+typedef struct _EggSMClientXSMPClass EggSMClientXSMPClass;
+
+/* These mostly correspond to the similarly-named states in section
+ * 9.1 of the XSMP spec. Some of the states there aren't represented
+ * here, because we don't need them. SHUTDOWN_CANCELLED is slightly
+ * different from the spec; we use it when the client is IDLE after a
+ * ShutdownCancelled message, but the application is still interacting
+ * and doesn't know the shutdown has been cancelled yet.
+ */
+typedef enum
+{
+ XSMP_STATE_IDLE,
+ XSMP_STATE_SAVE_YOURSELF,
+ XSMP_STATE_INTERACT_REQUEST,
+ XSMP_STATE_INTERACT,
+ XSMP_STATE_SAVE_YOURSELF_DONE,
+ XSMP_STATE_SHUTDOWN_CANCELLED,
+ XSMP_STATE_CONNECTION_CLOSED
+} EggSMClientXSMPState;
+
+static const char *state_names[] = {
+ "idle",
+ "save-yourself",
+ "interact-request",
+ "interact",
+ "save-yourself-done",
+ "shutdown-cancelled",
+ "connection-closed"
+};
+
+#define EGG_SM_CLIENT_XSMP_STATE(xsmp) (state_names[(xsmp)->state])
+
+struct _EggSMClientXSMP
+{
+ EggSMClient parent;
+
+ SmcConn connection;
+ char *client_id;
+
+ EggSMClientXSMPState state;
+ char **restart_command;
+ gboolean set_restart_command;
+ int restart_style;
+
+ guint idle;
+
+ /* Current SaveYourself state */
+ guint expecting_initial_save_yourself : 1;
+ guint need_save_state : 1;
+ guint need_quit_requested : 1;
+ guint interact_errors : 1;
+ guint shutting_down : 1;
+
+ /* Todo list */
+ guint waiting_to_set_initial_properties : 1;
+ guint waiting_to_emit_quit : 1;
+ guint waiting_to_emit_quit_cancelled : 1;
+ guint waiting_to_save_myself : 1;
+
+};
+
+struct _EggSMClientXSMPClass
+{
+ EggSMClientClass parent_class;
+
+};
+
+static void sm_client_xsmp_startup (EggSMClient *client,
+ const char *client_id);
+static void sm_client_xsmp_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv);
+static void sm_client_xsmp_will_quit (EggSMClient *client,
+ gboolean will_quit);
+static gboolean sm_client_xsmp_end_session (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+static void xsmp_save_yourself (SmcConn smc_conn,
+ SmPointer client_data,
+ int save_style,
+ Bool shutdown,
+ int interact_style,
+ Bool fast);
+static void xsmp_die (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_save_complete (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_shutdown_cancelled (SmcConn smc_conn,
+ SmPointer client_data);
+static void xsmp_interact (SmcConn smc_conn,
+ SmPointer client_data);
+
+static SmProp *array_prop (const char *name,
+ ...);
+static SmProp *ptrarray_prop (const char *name,
+ GPtrArray *values);
+static SmProp *string_prop (const char *name,
+ const char *value);
+static SmProp *card8_prop (const char *name,
+ unsigned char value);
+
+static void set_properties (EggSMClientXSMP *xsmp, ...);
+static void delete_properties (EggSMClientXSMP *xsmp, ...);
+
+static GPtrArray *generate_command (char **restart_command,
+ const char *client_id,
+ const char *state_file);
+
+static void save_state (EggSMClientXSMP *xsmp);
+static void do_save_yourself (EggSMClientXSMP *xsmp);
+static void update_pending_events (EggSMClientXSMP *xsmp);
+
+static void ice_init (void);
+static gboolean process_ice_messages (IceConn ice_conn);
+static void smc_error_handler (SmcConn smc_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ SmPointer values);
+
+G_DEFINE_TYPE (EggSMClientXSMP, egg_sm_client_xsmp, EGG_TYPE_SM_CLIENT)
+
+static void
+egg_sm_client_xsmp_init (EggSMClientXSMP *xsmp)
+{
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+ xsmp->connection = NULL;
+ xsmp->restart_style = SmRestartIfRunning;
+}
+
+static void
+egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass)
+{
+ EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
+
+ sm_client_class->startup = sm_client_xsmp_startup;
+ sm_client_class->set_restart_command = sm_client_xsmp_set_restart_command;
+ sm_client_class->will_quit = sm_client_xsmp_will_quit;
+ sm_client_class->end_session = sm_client_xsmp_end_session;
+}
+
+EggSMClient *
+egg_sm_client_xsmp_new (void)
+{
+#if GTK_CHECK_VERSION(3,0,0)
+ if (!GDK_IS_X11_DISPLAY_MANAGER (gdk_display_manager_get ()))
+ return NULL;
+#endif
+
+ if (!g_getenv ("SESSION_MANAGER"))
+ return NULL;
+
+ return g_object_new (EGG_TYPE_SM_CLIENT_XSMP, NULL);
+}
+
+static gboolean
+sm_client_xsmp_set_initial_properties (gpointer user_data)
+{
+ EggSMClientXSMP *xsmp = user_data;
+ EggDesktopFile *desktop_file;
+ GPtrArray *clone, *restart;
+ char pid_str[64];
+
+ if (xsmp->idle)
+ {
+ g_source_remove (xsmp->idle);
+ xsmp->idle = 0;
+ }
+ xsmp->waiting_to_set_initial_properties = FALSE;
+
+ if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
+ xsmp->restart_style = SmRestartNever;
+
+ /* Parse info out of desktop file */
+ desktop_file = egg_get_desktop_file ();
+ if (desktop_file)
+ {
+ GError *err = NULL;
+ char *cmdline, **argv;
+ int argc;
+
+ if (xsmp->restart_style == SmRestartIfRunning)
+ {
+ if (egg_desktop_file_get_boolean (desktop_file,
+ "X-GNOME-AutoRestart", NULL))
+ xsmp->restart_style = SmRestartImmediately;
+ }
+
+ if (!xsmp->set_restart_command)
+ {
+ cmdline = egg_desktop_file_parse_exec (desktop_file, NULL, &err);
+ if (cmdline && g_shell_parse_argv (cmdline, &argc, &argv, &err))
+ {
+ egg_sm_client_set_restart_command (EGG_SM_CLIENT (xsmp),
+ argc, (const char **)argv);
+ g_strfreev (argv);
+ }
+ else
+ {
+ g_warning ("Could not parse Exec line in desktop file: %s",
+ err->message);
+ g_error_free (err);
+ }
+ g_free (cmdline);
+ }
+ }
+
+ if (!xsmp->set_restart_command)
+ xsmp->restart_command = g_strsplit (g_get_prgname (), " ", -1);
+
+ clone = generate_command (xsmp->restart_command, NULL, NULL);
+ restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+
+ g_debug ("Setting initial properties");
+
+ /* Program, CloneCommand, RestartCommand, and UserID are required.
+ * ProcessID isn't required, but the SM may be able to do something
+ * useful with it.
+ */
+ g_snprintf (pid_str, sizeof (pid_str), "%lu", (gulong) getpid ());
+ set_properties (xsmp,
+ string_prop (SmProgram, g_get_prgname ()),
+ ptrarray_prop (SmCloneCommand, clone),
+ ptrarray_prop (SmRestartCommand, restart),
+ string_prop (SmUserID, g_get_user_name ()),
+ string_prop (SmProcessID, pid_str),
+ card8_prop (SmRestartStyleHint, xsmp->restart_style),
+ NULL);
+ g_ptr_array_free (clone, TRUE);
+ g_ptr_array_free (restart, TRUE);
+
+ if (desktop_file)
+ {
+ set_properties (xsmp,
+ string_prop ("_GSM_DesktopFile", egg_desktop_file_get_source (desktop_file)),
+ NULL);
+ }
+
+ update_pending_events (xsmp);
+ return FALSE;
+}
+
+/* This gets called from two different places: xsmp_die() (when the
+ * server asks us to disconnect) and process_ice_messages() (when the
+ * server disconnects unexpectedly).
+ */
+static void
+sm_client_xsmp_disconnect (EggSMClientXSMP *xsmp)
+{
+ SmcConn connection;
+
+ if (!xsmp->connection)
+ return;
+
+ g_debug ("Disconnecting");
+
+ connection = xsmp->connection;
+ xsmp->connection = NULL;
+ SmcCloseConnection (connection, 0, NULL);
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+}
+
+static void
+sm_client_xsmp_startup (EggSMClient *client,
+ const char *client_id)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ SmcCallbacks callbacks;
+ char *ret_client_id;
+ char error_string_ret[256];
+
+ xsmp->client_id = g_strdup (client_id);
+
+ ice_init ();
+ SmcSetErrorHandler (smc_error_handler);
+
+ callbacks.save_yourself.callback = xsmp_save_yourself;
+ callbacks.die.callback = xsmp_die;
+ callbacks.save_complete.callback = xsmp_save_complete;
+ callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
+
+ callbacks.save_yourself.client_data = xsmp;
+ callbacks.die.client_data = xsmp;
+ callbacks.save_complete.client_data = xsmp;
+ callbacks.shutdown_cancelled.client_data = xsmp;
+
+ client_id = NULL;
+ error_string_ret[0] = '\0';
+ xsmp->connection =
+ SmcOpenConnection (NULL, xsmp, SmProtoMajor, SmProtoMinor,
+ SmcSaveYourselfProcMask | SmcDieProcMask |
+ SmcSaveCompleteProcMask |
+ SmcShutdownCancelledProcMask,
+ &callbacks,
+ xsmp->client_id, &ret_client_id,
+ sizeof (error_string_ret), error_string_ret);
+
+ if (!xsmp->connection)
+ {
+ g_warning ("Failed to connect to the session manager: %s\n",
+ error_string_ret[0] ?
+ error_string_ret : "no error message given");
+ xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
+ return;
+ }
+
+ /* We expect a pointless initial SaveYourself if either (a) we
+ * didn't have an initial client ID, or (b) we DID have an initial
+ * client ID, but the server rejected it and gave us a new one.
+ */
+ if (!xsmp->client_id ||
+ (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
+ xsmp->expecting_initial_save_yourself = TRUE;
+
+ if (ret_client_id)
+ {
+ g_free (xsmp->client_id);
+ xsmp->client_id = g_strdup (ret_client_id);
+ free (ret_client_id);
+
+ gdk_threads_enter ();
+#if !GTK_CHECK_VERSION(2,23,3) && !GTK_CHECK_VERSION(3,0,0)
+ gdk_set_sm_client_id (xsmp->client_id);
+#else
+ gdk_x11_set_sm_client_id (xsmp->client_id);
+#endif
+ gdk_threads_leave ();
+
+ g_debug ("Got client ID \"%s\"", xsmp->client_id);
+ }
+
+ xsmp->state = XSMP_STATE_IDLE;
+
+ /* Do not set the initial properties until we reach the main loop,
+ * so that the application has a chance to call
+ * egg_set_desktop_file(). (This may also help the session manager
+ * have a better idea of when the application is fully up and
+ * running.)
+ */
+ xsmp->waiting_to_set_initial_properties = TRUE;
+ xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
+}
+
+static void
+sm_client_xsmp_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ int i;
+
+ g_strfreev (xsmp->restart_command);
+
+ xsmp->restart_command = g_new (char *, argc + 1);
+ for (i = 0; i < argc; i++)
+ xsmp->restart_command[i] = g_strdup (argv[i]);
+ xsmp->restart_command[i] = NULL;
+
+ xsmp->set_restart_command = TRUE;
+}
+
+static void
+sm_client_xsmp_will_quit (EggSMClient *client,
+ gboolean will_quit)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+
+ if (xsmp->state == XSMP_STATE_CONNECTION_CLOSED)
+ {
+ /* The session manager has already exited! Schedule a quit
+ * signal.
+ */
+ xsmp->waiting_to_emit_quit = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+ else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* We received a ShutdownCancelled message while the application
+ * was interacting; Schedule a quit_cancelled signal.
+ */
+ xsmp->waiting_to_emit_quit_cancelled = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+
+ g_return_if_fail (xsmp->state == XSMP_STATE_INTERACT);
+
+ g_debug ("Sending InteractDone(%s)", will_quit ? "False" : "True");
+ SmcInteractDone (xsmp->connection, !will_quit);
+
+ if (will_quit && xsmp->need_save_state)
+ save_state (xsmp);
+
+ g_debug ("Sending SaveYourselfDone(%s)", will_quit ? "True" : "False");
+ SmcSaveYourselfDone (xsmp->connection, will_quit);
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static gboolean
+sm_client_xsmp_end_session (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation)
+{
+ EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
+ int save_type;
+
+ /* To end the session via XSMP, we have to send a
+ * SaveYourselfRequest. We aren't allowed to do that if anything
+ * else is going on, but we don't want to expose this fact to the
+ * application. So we do our best to patch things up here...
+ *
+ * In the worst case, this method might block for some length of
+ * time in process_ice_messages, but the only time that code path is
+ * honestly likely to get hit is if the application tries to end the
+ * session as the very first thing it does, in which case it
+ * probably won't actually block anyway. It's not worth gunking up
+ * the API to try to deal nicely with the other 0.01% of cases where
+ * this happens.
+ */
+
+ while (xsmp->state != XSMP_STATE_IDLE ||
+ xsmp->expecting_initial_save_yourself)
+ {
+ /* If we're already shutting down, we don't need to do anything. */
+ if (xsmp->shutting_down)
+ return TRUE;
+
+ switch (xsmp->state)
+ {
+ case XSMP_STATE_CONNECTION_CLOSED:
+ return FALSE;
+
+ case XSMP_STATE_SAVE_YOURSELF:
+ /* Trying to log out from the save_state callback? Whatever.
+ * Abort the save_state.
+ */
+ SmcSaveYourselfDone (xsmp->connection, FALSE);
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+ break;
+
+ case XSMP_STATE_INTERACT_REQUEST:
+ case XSMP_STATE_INTERACT:
+ case XSMP_STATE_SHUTDOWN_CANCELLED:
+ /* Already in a shutdown-related state, just ignore
+ * the new shutdown request...
+ */
+ return TRUE;
+
+ case XSMP_STATE_IDLE:
+ if (xsmp->waiting_to_set_initial_properties)
+ sm_client_xsmp_set_initial_properties (xsmp);
+
+ if (!xsmp->expecting_initial_save_yourself)
+ break;
+ /* else fall through */
+
+ case XSMP_STATE_SAVE_YOURSELF_DONE:
+ /* We need to wait for some response from the server.*/
+ process_ice_messages (SmcGetIceConnection (xsmp->connection));
+ break;
+
+ default:
+ /* Hm... shouldn't happen */
+ return FALSE;
+ }
+ }
+
+ /* xfce4-session will do the wrong thing if we pass SmSaveGlobal and
+ * the user chooses to save the session. But gnome-session will do
+ * the wrong thing if we pass SmSaveBoth and the user chooses NOT to
+ * save the session... Sigh.
+ */
+ if (!strcmp (SmcVendor (xsmp->connection), "xfce4-session"))
+ save_type = SmSaveBoth;
+ else
+ save_type = SmSaveGlobal;
+
+ g_debug ("Sending SaveYourselfRequest(SmSaveGlobal, Shutdown, SmInteractStyleAny, %sFast)", request_confirmation ? "!" : "");
+ SmcRequestSaveYourself (xsmp->connection,
+ save_type,
+ True, /* shutdown */
+ SmInteractStyleAny,
+ !request_confirmation, /* fast */
+ True /* global */);
+ return TRUE;
+}
+
+static gboolean
+idle_do_pending_events (gpointer data)
+{
+ EggSMClientXSMP *xsmp = data;
+ EggSMClient *client = data;
+
+ gdk_threads_enter ();
+
+ xsmp->idle = 0;
+
+ if (xsmp->waiting_to_emit_quit)
+ {
+ fprintf (stderr, "deadbeef: egg_sm_client_quit\n");
+ xsmp->waiting_to_emit_quit = FALSE;
+ egg_sm_client_quit (client);
+ goto out;
+ }
+
+ if (xsmp->waiting_to_emit_quit_cancelled)
+ {
+ xsmp->waiting_to_emit_quit_cancelled = FALSE;
+ egg_sm_client_quit_cancelled (client);
+ xsmp->state = XSMP_STATE_IDLE;
+ }
+
+ if (xsmp->waiting_to_save_myself)
+ {
+ xsmp->waiting_to_save_myself = FALSE;
+ do_save_yourself (xsmp);
+ }
+
+ out:
+ gdk_threads_leave ();
+ return FALSE;
+}
+
+static void
+update_pending_events (EggSMClientXSMP *xsmp)
+{
+ gboolean want_idle =
+ xsmp->waiting_to_emit_quit ||
+ xsmp->waiting_to_emit_quit_cancelled ||
+ xsmp->waiting_to_save_myself;
+
+ if (want_idle)
+ {
+ if (xsmp->idle == 0)
+ xsmp->idle = g_idle_add (idle_do_pending_events, xsmp);
+ }
+ else
+ {
+ if (xsmp->idle != 0)
+ g_source_remove (xsmp->idle);
+ xsmp->idle = 0;
+ }
+}
+
+static void
+fix_broken_state (EggSMClientXSMP *xsmp, const char *message,
+ gboolean send_interact_done,
+ gboolean send_save_yourself_done)
+{
+ g_warning ("Received XSMP %s message in state %s: client or server error",
+ message, EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ /* Forget any pending SaveYourself plans we had */
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+
+ if (send_interact_done)
+ SmcInteractDone (xsmp->connection, False);
+ if (send_save_yourself_done)
+ SmcSaveYourselfDone (xsmp->connection, True);
+
+ xsmp->state = send_save_yourself_done ? XSMP_STATE_SAVE_YOURSELF_DONE : XSMP_STATE_IDLE;
+}
+
+/* SM callbacks */
+
+static void
+xsmp_save_yourself (SmcConn smc_conn,
+ SmPointer client_data,
+ int save_type,
+ Bool shutdown,
+ int interact_style,
+ Bool fast)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ gboolean wants_quit_requested;
+
+ g_debug ("Received SaveYourself(%s, %s, %s, %s) in state %s",
+ save_type == SmSaveLocal ? "SmSaveLocal" :
+ save_type == SmSaveGlobal ? "SmSaveGlobal" : "SmSaveBoth",
+ shutdown ? "Shutdown" : "!Shutdown",
+ interact_style == SmInteractStyleAny ? "SmInteractStyleAny" :
+ interact_style == SmInteractStyleErrors ? "SmInteractStyleErrors" :
+ "SmInteractStyleNone", fast ? "Fast" : "!Fast",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state != XSMP_STATE_IDLE &&
+ xsmp->state != XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ fix_broken_state (xsmp, "SaveYourself", FALSE, TRUE);
+ return;
+ }
+
+ if (xsmp->waiting_to_set_initial_properties)
+ sm_client_xsmp_set_initial_properties (xsmp);
+
+ /* If this is the initial SaveYourself, ignore it; we've already set
+ * properties and there's no reason to actually save state too.
+ */
+ if (xsmp->expecting_initial_save_yourself)
+ {
+ xsmp->expecting_initial_save_yourself = FALSE;
+
+ if (save_type == SmSaveLocal &&
+ interact_style == SmInteractStyleNone &&
+ !shutdown && !fast)
+ {
+ g_debug ("Sending SaveYourselfDone(True) for initial SaveYourself");
+ SmcSaveYourselfDone (xsmp->connection, True);
+ /* As explained in the comment at the end of
+ * do_save_yourself(), SAVE_YOURSELF_DONE is the correct
+ * state here, not IDLE.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+ return;
+ }
+ else
+ g_warning ("First SaveYourself was not the expected one!");
+ }
+
+ /* Even ignoring the "fast" flag completely, there are still 18
+ * different combinations of save_type, shutdown and interact_style.
+ * We interpret them as follows:
+ *
+ * Type Shutdown Interact Interpretation
+ * G F A/E/N do nothing (1)
+ * G T N do nothing (1)*
+ * G T A/E quit_requested (2)
+ * L/B F A/E/N save_state (3)
+ * L/B T N save_state (3)*
+ * L/B T A/E quit_requested, then save_state (4)
+ *
+ * 1. Do nothing, because the SM asked us to do something
+ * uninteresting (save open files, but then don't quit
+ * afterward) or rude (save open files without asking the user
+ * for confirmation).
+ *
+ * 2. Request interaction and then emit ::quit_requested. This
+ * perhaps isn't quite correct for the SmInteractStyleErrors
+ * case, but we don't care.
+ *
+ * 3. Emit ::save_state. The SmSaveBoth SaveYourselfs in these
+ * rows essentially get demoted to SmSaveLocal, because their
+ * Global halves correspond to "do nothing".
+ *
+ * 4. Request interaction, emit ::quit_requested, and then emit
+ * ::save_state after interacting. This is the SmSaveBoth
+ * equivalent of #2, but we also promote SmSaveLocal shutdown
+ * SaveYourselfs to SmSaveBoth here, because we want to give
+ * the user a chance to save open files before quitting.
+ *
+ * (* It would be nice if we could do something useful when the
+ * session manager sends a SaveYourself with shutdown True and
+ * SmInteractStyleNone. But we can't, so we just pretend it didn't
+ * even tell us it was shutting down. The docs for ::quit mention
+ * that it might not always be preceded by ::quit_requested.)
+ */
+
+ /* As an optimization, we don't actually request interaction and
+ * emit ::quit_requested if the application isn't listening to the
+ * signal.
+ */
+ wants_quit_requested = g_signal_has_handler_pending (xsmp, g_signal_lookup ("quit_requested", EGG_TYPE_SM_CLIENT), 0, FALSE);
+
+ xsmp->need_save_state = (save_type != SmSaveGlobal);
+ xsmp->need_quit_requested = (shutdown && wants_quit_requested &&
+ interact_style != SmInteractStyleNone);
+ xsmp->interact_errors = (interact_style == SmInteractStyleErrors);
+
+ xsmp->shutting_down = shutdown;
+
+ do_save_yourself (xsmp);
+}
+
+static void
+do_save_yourself (EggSMClientXSMP *xsmp)
+{
+ if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* The SM cancelled a previous SaveYourself, but we haven't yet
+ * had a chance to tell the application, so we can't start
+ * processing this SaveYourself yet.
+ */
+ xsmp->waiting_to_save_myself = TRUE;
+ update_pending_events (xsmp);
+ return;
+ }
+
+ if (xsmp->need_quit_requested)
+ {
+ xsmp->state = XSMP_STATE_INTERACT_REQUEST;
+
+ g_debug ("Sending InteractRequest(%s)",
+ xsmp->interact_errors ? "Error" : "Normal");
+ SmcInteractRequest (xsmp->connection,
+ xsmp->interact_errors ? SmDialogError : SmDialogNormal,
+ xsmp_interact,
+ xsmp);
+ return;
+ }
+
+ if (xsmp->need_save_state)
+ {
+ save_state (xsmp);
+
+ /* Though unlikely, the client could have been disconnected
+ * while the application was saving its state.
+ */
+ if (!xsmp->connection)
+ return;
+ }
+
+ g_debug ("Sending SaveYourselfDone(True)");
+ SmcSaveYourselfDone (xsmp->connection, True);
+
+ /* The client state diagram in the XSMP spec says that after a
+ * non-shutdown SaveYourself, we go directly back to "idle". But
+ * everything else in both the XSMP spec and the libSM docs
+ * disagrees.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
+}
+
+static void
+save_state (EggSMClientXSMP *xsmp)
+{
+ GKeyFile *state_file;
+ char *state_file_path, *data;
+ EggDesktopFile *desktop_file;
+ GPtrArray *restart;
+ int offset, fd;
+
+ /* We set xsmp->state before emitting save_state, but our caller is
+ * responsible for setting it back afterward.
+ */
+ xsmp->state = XSMP_STATE_SAVE_YOURSELF;
+
+ state_file = egg_sm_client_save_state ((EggSMClient *)xsmp);
+ if (!state_file)
+ {
+ restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL);
+ set_properties (xsmp,
+ ptrarray_prop (SmRestartCommand, restart),
+ NULL);
+ g_ptr_array_free (restart, TRUE);
+ delete_properties (xsmp, SmDiscardCommand, NULL);
+ return;
+ }
+
+ desktop_file = egg_get_desktop_file ();
+ if (desktop_file)
+ {
+ GKeyFile *merged_file;
+ char *desktop_file_path;
+
+ merged_file = g_key_file_new ();
+ desktop_file_path =
+ g_filename_from_uri (egg_desktop_file_get_source (desktop_file),
+ NULL, NULL);
+ if (desktop_file_path &&
+ g_key_file_load_from_file (merged_file, desktop_file_path,
+ G_KEY_FILE_KEEP_COMMENTS |
+ G_KEY_FILE_KEEP_TRANSLATIONS, NULL))
+ {
+ guint g, k, i;
+ char **groups, **keys, *value, *exec;
+
+ groups = g_key_file_get_groups (state_file, NULL);
+ for (g = 0; groups[g]; g++)
+ {
+ keys = g_key_file_get_keys (state_file, groups[g], NULL, NULL);
+ for (k = 0; keys[k]; k++)
+ {
+ value = g_key_file_get_value (state_file, groups[g],
+ keys[k], NULL);
+ if (value)
+ {
+ g_key_file_set_value (merged_file, groups[g],
+ keys[k], value);
+ g_free (value);
+ }
+ }
+ g_strfreev (keys);
+ }
+ g_strfreev (groups);
+
+ g_key_file_free (state_file);
+ state_file = merged_file;
+
+ /* Update Exec key using "--sm-client-state-file %k" */
+ restart = generate_command (xsmp->restart_command,
+ NULL, "%k");
+ for (i = 0; i < restart->len; i++)
+ restart->pdata[i] = g_shell_quote (restart->pdata[i]);
+ g_ptr_array_add (restart, NULL);
+ exec = g_strjoinv (" ", (char **)restart->pdata);
+ g_strfreev ((char **)restart->pdata);
+ g_ptr_array_free (restart, FALSE);
+
+ g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP,
+ EGG_DESKTOP_FILE_KEY_EXEC,
+ exec);
+ g_free (exec);
+ }
+ else
+ desktop_file = NULL;
+
+ g_free (desktop_file_path);
+ }
+
+ /* Now write state_file to disk. (We can't use mktemp(), because
+ * that requires the filename to end with "XXXXXX", and we want
+ * it to end with ".desktop".)
+ */
+
+ data = g_key_file_to_data (state_file, NULL, NULL);
+ g_key_file_free (state_file);
+
+ offset = 0;
+ while (1)
+ {
+ state_file_path = g_strdup_printf ("%s%csession-state%c%s-%ld.%s",
+ g_get_user_config_dir (),
+ G_DIR_SEPARATOR, G_DIR_SEPARATOR,
+ g_get_prgname (),
+ (long)time (NULL) + offset,
+ desktop_file ? "desktop" : "state");
+
+ fd = open (state_file_path, O_WRONLY | O_CREAT | O_EXCL, 0644);
+ if (fd == -1)
+ {
+ if (errno == EEXIST)
+ {
+ offset++;
+ g_free (state_file_path);
+ continue;
+ }
+ else if (errno == ENOTDIR || errno == ENOENT)
+ {
+ char *sep = strrchr (state_file_path, G_DIR_SEPARATOR);
+
+ *sep = '\0';
+ if (g_mkdir_with_parents (state_file_path, 0755) != 0)
+ {
+ g_warning ("Could not create directory '%s'",
+ state_file_path);
+ g_free (state_file_path);
+ state_file_path = NULL;
+ break;
+ }
+
+ continue;
+ }
+
+ g_warning ("Could not create file '%s': %s",
+ state_file_path, g_strerror (errno));
+ g_free (state_file_path);
+ state_file_path = NULL;
+ break;
+ }
+
+ close (fd);
+ g_file_set_contents (state_file_path, data, -1, NULL);
+ break;
+ }
+ g_free (data);
+
+ restart = generate_command (xsmp->restart_command, xsmp->client_id,
+ state_file_path);
+ set_properties (xsmp,
+ ptrarray_prop (SmRestartCommand, restart),
+ NULL);
+ g_ptr_array_free (restart, TRUE);
+
+ if (state_file_path)
+ {
+ set_properties (xsmp,
+ array_prop (SmDiscardCommand,
+ "/bin/rm", "-rf", state_file_path,
+ NULL),
+ NULL);
+ g_free (state_file_path);
+ }
+}
+
+static void
+xsmp_interact (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received Interact message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state != XSMP_STATE_INTERACT_REQUEST)
+ {
+ fix_broken_state (xsmp, "Interact", TRUE, TRUE);
+ return;
+ }
+
+ xsmp->state = XSMP_STATE_INTERACT;
+ egg_sm_client_quit_requested (client);
+}
+
+static void
+xsmp_die (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received Die message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ sm_client_xsmp_disconnect (xsmp);
+ egg_sm_client_quit (client);
+}
+
+static void
+xsmp_save_complete (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+
+ g_debug ("Received SaveComplete message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+ xsmp->state = XSMP_STATE_IDLE;
+ else
+ fix_broken_state (xsmp, "SaveComplete", FALSE, FALSE);
+}
+
+static void
+xsmp_shutdown_cancelled (SmcConn smc_conn,
+ SmPointer client_data)
+{
+ EggSMClientXSMP *xsmp = client_data;
+ EggSMClient *client = client_data;
+
+ g_debug ("Received ShutdownCancelled message in state %s",
+ EGG_SM_CLIENT_XSMP_STATE (xsmp));
+
+ xsmp->shutting_down = FALSE;
+
+ if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
+ {
+ /* We've finished interacting and now the SM has agreed to
+ * cancel the shutdown.
+ */
+ xsmp->state = XSMP_STATE_IDLE;
+ egg_sm_client_quit_cancelled (client);
+ }
+ else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
+ {
+ /* Hm... ok, so we got a shutdown SaveYourself, which got
+ * cancelled, but the application was still interacting, so we
+ * didn't tell it yet, and then *another* SaveYourself arrived,
+ * which we must still be waiting to tell the app about, except
+ * that now that SaveYourself has been cancelled too! Dizzy yet?
+ */
+ xsmp->waiting_to_save_myself = FALSE;
+ update_pending_events (xsmp);
+ }
+ else
+ {
+ g_debug ("Sending SaveYourselfDone(False)");
+ SmcSaveYourselfDone (xsmp->connection, False);
+
+ if (xsmp->state == XSMP_STATE_INTERACT)
+ {
+ /* The application is currently interacting, so we can't
+ * tell it about the cancellation yet; we will wait until
+ * after it calls egg_sm_client_will_quit().
+ */
+ xsmp->state = XSMP_STATE_SHUTDOWN_CANCELLED;
+ }
+ else
+ {
+ /* The shutdown was cancelled before the application got a
+ * chance to interact.
+ */
+ xsmp->state = XSMP_STATE_IDLE;
+ }
+ }
+}
+
+/* Utilities */
+
+/* Create a restart/clone/Exec command based on @restart_command.
+ * If @client_id is non-%NULL, add "--sm-client-id @client_id".
+ * If @state_file is non-%NULL, add "--sm-client-state-file @state_file".
+ *
+ * None of the input strings are g_strdup()ed; the caller must keep
+ * them around until it is done with the returned GPtrArray, and must
+ * then free the array, but not its contents.
+ */
+static GPtrArray *
+generate_command (char **restart_command, const char *client_id,
+ const char *state_file)
+{
+ GPtrArray *cmd;
+ int i;
+
+ cmd = g_ptr_array_new ();
+ g_ptr_array_add (cmd, restart_command[0]);
+
+ if (client_id)
+ {
+ g_ptr_array_add (cmd, (char *)"--sm-client-id");
+ g_ptr_array_add (cmd, (char *)client_id);
+ }
+
+ if (state_file)
+ {
+ g_ptr_array_add (cmd, (char *)"--sm-client-state-file");
+ g_ptr_array_add (cmd, (char *)state_file);
+ }
+
+ for (i = 1; restart_command[i]; i++)
+ g_ptr_array_add (cmd, restart_command[i]);
+
+ return cmd;
+}
+
+/* Takes a NULL-terminated list of SmProp * values, created by
+ * array_prop, ptrarray_prop, string_prop, card8_prop, sets them, and
+ * frees them.
+ */
+static void
+set_properties (EggSMClientXSMP *xsmp, ...)
+{
+ GPtrArray *props;
+ SmProp *prop;
+ va_list ap;
+ guint i;
+
+ props = g_ptr_array_new ();
+
+ va_start (ap, xsmp);
+ while ((prop = va_arg (ap, SmProp *)))
+ g_ptr_array_add (props, prop);
+ va_end (ap);
+
+ if (xsmp->connection)
+ {
+ SmcSetProperties (xsmp->connection, props->len,
+ (SmProp **)props->pdata);
+ }
+
+ for (i = 0; i < props->len; i++)
+ {
+ prop = props->pdata[i];
+ g_free (prop->vals);
+ g_free (prop);
+ }
+ g_ptr_array_free (props, TRUE);
+}
+
+/* Takes a NULL-terminated list of property names and deletes them. */
+static void
+delete_properties (EggSMClientXSMP *xsmp, ...)
+{
+ GPtrArray *props;
+ char *prop;
+ va_list ap;
+
+ if (!xsmp->connection)
+ return;
+
+ props = g_ptr_array_new ();
+
+ va_start (ap, xsmp);
+ while ((prop = va_arg (ap, char *)))
+ g_ptr_array_add (props, prop);
+ va_end (ap);
+
+ SmcDeleteProperties (xsmp->connection, props->len,
+ (char **)props->pdata);
+
+ g_ptr_array_free (props, TRUE);
+}
+
+/* Takes an array of strings and creates a LISTofARRAY8 property. The
+ * strings are neither dupped nor freed; they need to remain valid
+ * until you're done with the SmProp.
+ */
+static SmProp *
+array_prop (const char *name, ...)
+{
+ SmProp *prop;
+ SmPropValue pv;
+ GArray *vals;
+ char *value;
+ va_list ap;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmLISTofARRAY8;
+
+ vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+ va_start (ap, name);
+ while ((value = va_arg (ap, char *)))
+ {
+ pv.length = strlen (value);
+ pv.value = value;
+ g_array_append_val (vals, pv);
+ }
+
+ prop->num_vals = vals->len;
+ prop->vals = (SmPropValue *)vals->data;
+
+ g_array_free (vals, FALSE);
+
+ return prop;
+}
+
+/* Takes a GPtrArray of strings and creates a LISTofARRAY8 property.
+ * The array contents are neither dupped nor freed; they need to
+ * remain valid until you're done with the SmProp.
+ */
+static SmProp *
+ptrarray_prop (const char *name, GPtrArray *values)
+{
+ SmProp *prop;
+ SmPropValue pv;
+ GArray *vals;
+ guint i;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmLISTofARRAY8;
+
+ vals = g_array_new (FALSE, FALSE, sizeof (SmPropValue));
+
+ for (i = 0; i < values->len; i++)
+ {
+ pv.length = strlen (values->pdata[i]);
+ pv.value = values->pdata[i];
+ g_array_append_val (vals, pv);
+ }
+
+ prop->num_vals = vals->len;
+ prop->vals = (SmPropValue *)vals->data;
+
+ g_array_free (vals, FALSE);
+
+ return prop;
+}
+
+/* Takes a string and creates an ARRAY8 property. The string is
+ * neither dupped nor freed; it needs to remain valid until you're
+ * done with the SmProp.
+ */
+static SmProp *
+string_prop (const char *name, const char *value)
+{
+ SmProp *prop;
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmARRAY8;
+
+ prop->num_vals = 1;
+ prop->vals = g_new (SmPropValue, 1);
+
+ prop->vals[0].length = strlen (value);
+ prop->vals[0].value = (char *)value;
+
+ return prop;
+}
+
+/* Takes a char and creates a CARD8 property. */
+static SmProp *
+card8_prop (const char *name, unsigned char value)
+{
+ SmProp *prop;
+ char *card8val;
+
+ /* To avoid having to allocate and free prop->vals[0], we cheat and
+ * make vals a 2-element-long array and then use the second element
+ * to store value.
+ */
+
+ prop = g_new (SmProp, 1);
+ prop->name = (char *)name;
+ prop->type = (char *)SmCARD8;
+
+ prop->num_vals = 1;
+ prop->vals = g_new (SmPropValue, 2);
+ card8val = (char *)(&prop->vals[1]);
+ card8val[0] = value;
+
+ prop->vals[0].length = 1;
+ prop->vals[0].value = card8val;
+
+ return prop;
+}
+
+/* ICE code. This makes no effort to play nice with anyone else trying
+ * to use libICE. Fortunately, no one uses libICE for anything other
+ * than SM. (DCOP uses ICE, but it has its own private copy of
+ * libICE.)
+ *
+ * When this moves to gtk, it will need to be cleverer, to avoid
+ * tripping over old apps that use GnomeClient or that use libSM
+ * directly.
+ */
+
+#include <X11/ICE/ICElib.h>
+#include <fcntl.h>
+
+static void ice_error_handler (IceConn ice_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ IcePointer values);
+static void ice_io_error_handler (IceConn ice_conn);
+static void ice_connection_watch (IceConn ice_conn,
+ IcePointer client_data,
+ Bool opening,
+ IcePointer *watch_data);
+
+static void
+ice_init (void)
+{
+ IceSetIOErrorHandler (ice_io_error_handler);
+ IceSetErrorHandler (ice_error_handler);
+ IceAddConnectionWatch (ice_connection_watch, NULL);
+}
+
+static gboolean
+process_ice_messages (IceConn ice_conn)
+{
+ IceProcessMessagesStatus status;
+
+ gdk_threads_enter ();
+ status = IceProcessMessages (ice_conn, NULL, NULL);
+ gdk_threads_leave ();
+
+ switch (status)
+ {
+ case IceProcessMessagesSuccess:
+ return TRUE;
+
+ case IceProcessMessagesIOError:
+ sm_client_xsmp_disconnect (IceGetConnectionContext (ice_conn));
+ return FALSE;
+
+ case IceProcessMessagesConnectionClosed:
+ return FALSE;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean
+ice_iochannel_watch (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer client_data)
+{
+ return process_ice_messages (client_data);
+}
+
+static void
+ice_connection_watch (IceConn ice_conn,
+ IcePointer client_data,
+ Bool opening,
+ IcePointer *watch_data)
+{
+ guint watch_id;
+
+ if (opening)
+ {
+ GIOChannel *channel;
+ int fd = IceConnectionNumber (ice_conn);
+
+ fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
+ channel = g_io_channel_unix_new (fd);
+ watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
+ ice_iochannel_watch, ice_conn);
+ g_io_channel_unref (channel);
+
+ *watch_data = GUINT_TO_POINTER (watch_id);
+ }
+ else
+ {
+ watch_id = GPOINTER_TO_UINT (*watch_data);
+ g_source_remove (watch_id);
+ }
+}
+
+static void
+ice_error_handler (IceConn ice_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ IcePointer values)
+{
+ /* Do nothing */
+}
+
+static void
+ice_io_error_handler (IceConn ice_conn)
+{
+ /* Do nothing */
+}
+
+static void
+smc_error_handler (SmcConn smc_conn,
+ Bool swap,
+ int offending_minor_opcode,
+ unsigned long offending_sequence,
+ int error_class,
+ int severity,
+ SmPointer values)
+{
+ /* Do nothing */
+}
diff --git a/plugins/gtkui/smclient/eggsmclient.c b/plugins/gtkui/smclient/eggsmclient.c
new file mode 100644
index 00000000..92be8a7e
--- /dev/null
+++ b/plugins/gtkui/smclient/eggsmclient.c
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "eggsmclient.h"
+#include "eggsmclient-private.h"
+
+static void egg_sm_client_debug_handler (const char *log_domain,
+ GLogLevelFlags log_level,
+ const char *message,
+ gpointer user_data);
+
+enum {
+ SAVE_STATE,
+ QUIT_REQUESTED,
+ QUIT_CANCELLED,
+ QUIT,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+struct _EggSMClientPrivate {
+ GKeyFile *state_file;
+};
+
+#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
+
+G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
+
+static EggSMClient *global_client;
+static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
+
+static void
+egg_sm_client_init (EggSMClient *client)
+{
+ ;
+}
+
+static void
+egg_sm_client_class_init (EggSMClientClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
+
+ /**
+ * EggSMClient::save_state:
+ * @client: the client
+ * @state_file: a #GKeyFile to save state information into
+ *
+ * Emitted when the session manager has requested that the
+ * application save information about its current state. The
+ * application should save its state into @state_file, and then the
+ * session manager may then restart the application in a future
+ * session and tell it to initialize itself from that state.
+ *
+ * You should not save any data into @state_file's "start group"
+ * (ie, the %NULL group). Instead, applications should save their
+ * data into groups with names that start with the application name,
+ * and libraries that connect to this signal should save their data
+ * into groups with names that start with the library name.
+ *
+ * Alternatively, rather than (or in addition to) using @state_file,
+ * the application can save its state by calling
+ * egg_sm_client_set_restart_command() during the processing of this
+ * signal (eg, to include a list of files to open).
+ **/
+ signals[SAVE_STATE] =
+ g_signal_new ("save_state",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, save_state),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ /**
+ * EggSMClient::quit_requested:
+ * @client: the client
+ *
+ * Emitted when the session manager requests that the application
+ * exit (generally because the user is logging out). The application
+ * should decide whether or not it is willing to quit (perhaps after
+ * asking the user what to do with documents that have unsaved
+ * changes) and then call egg_sm_client_will_quit(), passing %TRUE
+ * or %FALSE to give its answer to the session manager. (It does not
+ * need to give an answer before returning from the signal handler;
+ * it can interact with the user asynchronously and then give its
+ * answer later on.) If the application does not connect to this
+ * signal, then #EggSMClient will automatically return %TRUE on its
+ * behalf.
+ *
+ * The application should not save its session state as part of
+ * handling this signal; if the user has requested that the session
+ * be saved when logging out, then ::save_state will be emitted
+ * separately.
+ *
+ * If the application agrees to quit, it should then wait for either
+ * the ::quit_cancelled or ::quit signals to be emitted.
+ **/
+ signals[QUIT_REQUESTED] =
+ g_signal_new ("quit_requested",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * EggSMClient::quit_cancelled:
+ * @client: the client
+ *
+ * Emitted when the session manager decides to cancel a logout after
+ * the application has already agreed to quit. After receiving this
+ * signal, the application can go back to what it was doing before
+ * receiving the ::quit_requested signal.
+ **/
+ signals[QUIT_CANCELLED] =
+ g_signal_new ("quit_cancelled",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * EggSMClient::quit:
+ * @client: the client
+ *
+ * Emitted when the session manager wants the application to quit
+ * (generally because the user is logging out). The application
+ * should exit as soon as possible after receiving this signal; if
+ * it does not, the session manager may choose to forcibly kill it.
+ *
+ * Normally a GUI application would only be sent a ::quit if it
+ * agreed to quit in response to a ::quit_requested signal. However,
+ * this is not guaranteed; in some situations the session manager
+ * may decide to end the session without giving applications a
+ * chance to object.
+ **/
+ signals[QUIT] =
+ g_signal_new ("quit",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSMClientClass, quit),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+static gboolean sm_client_disable = FALSE;
+static char *sm_client_state_file = NULL;
+static char *sm_client_id = NULL;
+static char *sm_config_prefix = NULL;
+
+static gboolean
+sm_client_post_parse_func (GOptionContext *context,
+ GOptionGroup *group,
+ gpointer data,
+ GError **error)
+{
+ EggSMClient *client = egg_sm_client_get ();
+
+ if (sm_client_id == NULL)
+ {
+ const gchar *desktop_autostart_id;
+
+ desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+
+ if (desktop_autostart_id != NULL)
+ sm_client_id = g_strdup (desktop_autostart_id);
+ }
+
+ /* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
+ * use the same client id. */
+ g_unsetenv ("DESKTOP_AUTOSTART_ID");
+
+ if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
+ EGG_SM_CLIENT_GET_CLASS (client)->startup)
+ EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
+ return TRUE;
+}
+
+/**
+ * egg_sm_client_get_option_group:
+ *
+ * Creates a %GOptionGroup containing the session-management-related
+ * options. You should add this group to the application's
+ * %GOptionContext if you want to use #EggSMClient.
+ *
+ * Return value: the %GOptionGroup
+ **/
+GOptionGroup *
+egg_sm_client_get_option_group (void)
+{
+ const GOptionEntry entries[] = {
+ { "sm-client-disable", 0, 0,
+ G_OPTION_ARG_NONE, &sm_client_disable,
+ N_("Disable connection to session manager"), NULL },
+ { "sm-client-state-file", 0, 0,
+ G_OPTION_ARG_FILENAME, &sm_client_state_file,
+ N_("Specify file containing saved configuration"), N_("FILE") },
+ { "sm-client-id", 0, 0,
+ G_OPTION_ARG_STRING, &sm_client_id,
+ N_("Specify session management ID"), N_("ID") },
+ /* GnomeClient compatibility option */
+ { "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_NONE, &sm_client_disable,
+ NULL, NULL },
+ /* GnomeClient compatibility option. This is a dummy option that only
+ * exists so that sessions saved by apps with GnomeClient can be restored
+ * later when they've switched to EggSMClient. See bug #575308.
+ */
+ { "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_STRING, &sm_config_prefix,
+ NULL, NULL },
+ { NULL }
+ };
+ GOptionGroup *group;
+
+ /* Use our own debug handler for the "EggSMClient" domain. */
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ egg_sm_client_debug_handler, NULL);
+
+ group = g_option_group_new ("sm-client",
+ _("Session management options:"),
+ _("Show session management options"),
+ NULL, NULL);
+ g_option_group_add_entries (group, entries);
+ g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
+
+ return group;
+}
+
+/**
+ * egg_sm_client_set_mode:
+ * @mode: an #EggSMClient mode
+ *
+ * Sets the "mode" of #EggSMClient as follows:
+ *
+ * %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
+ * disabled, until the mode is changed again. The application will
+ * not even connect to the session manager. (egg_sm_client_get()
+ * will still return an #EggSMClient object.)
+ *
+ * %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
+ * the session manager (and thus will receive notification when the
+ * user is logging out, etc), but will request to not be
+ * automatically restarted with saved state in future sessions.
+ *
+ * %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
+ * function normally.
+ *
+ * This must be called before the application's main loop begins and
+ * before any call to egg_sm_client_get(), unless the mode was set
+ * earlier to %EGG_SM_CLIENT_MODE_DISABLED and this call enables
+ * session management. Note that option parsing will call
+ * egg_sm_client_get().
+ **/
+void
+egg_sm_client_set_mode (EggSMClientMode mode)
+{
+ EggSMClientMode old_mode = global_client_mode;
+
+ g_return_if_fail (global_client == NULL || global_client_mode == EGG_SM_CLIENT_MODE_DISABLED);
+ g_return_if_fail (!(global_client != NULL && mode == EGG_SM_CLIENT_MODE_DISABLED));
+
+ global_client_mode = mode;
+
+ if (global_client != NULL && old_mode == EGG_SM_CLIENT_MODE_DISABLED)
+ {
+ if (EGG_SM_CLIENT_GET_CLASS (global_client)->startup)
+ EGG_SM_CLIENT_GET_CLASS (global_client)->startup (global_client, sm_client_id);
+ }
+}
+
+/**
+ * egg_sm_client_get_mode:
+ *
+ * Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
+ * for details.
+ *
+ * Return value: the global #EggSMClientMode
+ **/
+EggSMClientMode
+egg_sm_client_get_mode (void)
+{
+ return global_client_mode;
+}
+
+/**
+ * egg_sm_client_get:
+ *
+ * Returns the master #EggSMClient for the application.
+ *
+ * On platforms that support saved sessions (ie, POSIX/X11), the
+ * application will only request to be restarted by the session
+ * manager if you call egg_set_desktop_file() to set an application
+ * desktop file. In particular, if the desktop file contains the key
+ * "X
+ *
+ * Return value: the master #EggSMClient.
+ **/
+EggSMClient *
+egg_sm_client_get (void)
+{
+ if (!global_client)
+ {
+ if (!sm_client_disable)
+ {
+#if defined (GDK_WINDOWING_WIN32)
+ global_client = egg_sm_client_win32_new ();
+#elif defined (GDK_WINDOWING_QUARTZ)
+ global_client = egg_sm_client_osx_new ();
+#else
+ /* If both D-Bus and XSMP are compiled in, try XSMP first
+ * (since it supports state saving) and fall back to D-Bus
+ * if XSMP isn't available.
+ */
+# ifdef EGG_SM_CLIENT_BACKEND_XSMP
+ global_client = egg_sm_client_xsmp_new ();
+# endif
+# ifdef EGG_SM_CLIENT_BACKEND_DBUS
+ if (!global_client)
+ global_client = egg_sm_client_dbus_new ();
+# endif
+#endif
+ }
+
+ /* Fallback: create a dummy client, so that callers don't have
+ * to worry about a %NULL return value.
+ */
+ if (!global_client)
+ global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
+ }
+
+ return global_client;
+}
+
+/**
+ * egg_sm_client_is_resumed:
+ * @client: the client
+ *
+ * Checks whether or not the current session has been resumed from
+ * a previous saved session. If so, the application should call
+ * egg_sm_client_get_state_file() and restore its state from the
+ * returned #GKeyFile.
+ *
+ * Return value: %TRUE if the session has been resumed
+ **/
+gboolean
+egg_sm_client_is_resumed (EggSMClient *client)
+{
+ g_return_val_if_fail (client == global_client, FALSE);
+
+ return sm_client_state_file != NULL;
+}
+
+/**
+ * egg_sm_client_get_state_file:
+ * @client: the client
+ *
+ * If the application was resumed by the session manager, this will
+ * return the #GKeyFile containing its state from the previous
+ * session.
+ *
+ * Note that other libraries and #EggSMClient itself may also store
+ * state in the key file, so if you call egg_sm_client_get_groups(),
+ * on it, the return value will likely include groups that you did not
+ * put there yourself. (It is also not guaranteed that the first
+ * group created by the application will still be the "start group"
+ * when it is resumed.)
+ *
+ * Return value: the #GKeyFile containing the application's earlier
+ * state, or %NULL on error. You should not free this key file; it
+ * is owned by @client.
+ **/
+GKeyFile *
+egg_sm_client_get_state_file (EggSMClient *client)
+{
+ EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
+ char *state_file_path;
+ GError *err = NULL;
+
+ g_return_val_if_fail (client == global_client, NULL);
+
+ if (!sm_client_state_file)
+ return NULL;
+ if (priv->state_file)
+ return priv->state_file;
+
+ if (!strncmp (sm_client_state_file, "file://", 7))
+ state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
+ else
+ state_file_path = g_strdup (sm_client_state_file);
+
+ priv->state_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
+ {
+ g_warning ("Could not load SM state file '%s': %s",
+ sm_client_state_file, err->message);
+ g_clear_error (&err);
+ g_key_file_free (priv->state_file);
+ priv->state_file = NULL;
+ }
+
+ g_free (state_file_path);
+ return priv->state_file;
+}
+
+/**
+ * egg_sm_client_set_restart_command:
+ * @client: the client
+ * @argc: the length of @argv
+ * @argv: argument vector
+ *
+ * Sets the command used to restart @client if it does not have a
+ * .desktop file that can be used to find its restart command.
+ *
+ * This can also be used when handling the ::save_state signal, to
+ * save the current state via an updated command line. (Eg, providing
+ * a list of filenames to open when the application is resumed.)
+ **/
+void
+egg_sm_client_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv)
+{
+ g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
+ EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
+}
+
+/**
+ * egg_sm_client_will_quit:
+ * @client: the client
+ * @will_quit: whether or not the application is willing to quit
+ *
+ * This MUST be called in response to the ::quit_requested signal, to
+ * indicate whether or not the application is willing to quit. The
+ * application may call it either directly from the signal handler, or
+ * at some later point (eg, after asynchronously interacting with the
+ * user).
+ *
+ * If the application does not connect to ::quit_requested,
+ * #EggSMClient will call this method on its behalf (passing %TRUE
+ * for @will_quit).
+ *
+ * After calling this method, the application should wait to receive
+ * either ::quit_cancelled or ::quit.
+ **/
+void
+egg_sm_client_will_quit (EggSMClient *client,
+ gboolean will_quit)
+{
+ g_return_if_fail (EGG_IS_SM_CLIENT (client));
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
+ EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
+}
+
+/**
+ * egg_sm_client_end_session:
+ * @style: a hint at how to end the session
+ * @request_confirmation: whether or not the user should get a chance
+ * to confirm the action
+ *
+ * Requests that the session manager end the current session. @style
+ * indicates how the session should be ended, and
+ * @request_confirmation indicates whether or not the user should be
+ * given a chance to confirm the logout/reboot/shutdown. Both of these
+ * flags are merely hints though; the session manager may choose to
+ * ignore them.
+ *
+ * Return value: %TRUE if the request was sent; %FALSE if it could not
+ * be (eg, because it could not connect to the session manager).
+ **/
+gboolean
+egg_sm_client_end_session (EggSMClientEndStyle style,
+ gboolean request_confirmation)
+{
+ EggSMClient *client = egg_sm_client_get ();
+
+ g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
+
+ if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
+ {
+ return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
+ request_confirmation);
+ }
+ else
+ return FALSE;
+}
+
+/* Signal-emitting callbacks from platform-specific code */
+
+GKeyFile *
+egg_sm_client_save_state (EggSMClient *client)
+{
+ GKeyFile *state_file;
+ char *group;
+
+ g_return_val_if_fail (client == global_client, NULL);
+
+ state_file = g_key_file_new ();
+
+ g_debug ("Emitting save_state");
+ g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
+ g_debug ("Done emitting save_state");
+
+ group = g_key_file_get_start_group (state_file);
+ if (group)
+ {
+ g_free (group);
+ return state_file;
+ }
+ else
+ {
+ g_key_file_free (state_file);
+ return NULL;
+ }
+}
+
+void
+egg_sm_client_quit_requested (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
+ {
+ g_debug ("Not emitting quit_requested because no one is listening");
+ egg_sm_client_will_quit (client, TRUE);
+ return;
+ }
+
+ g_debug ("Emitting quit_requested");
+ g_signal_emit (client, signals[QUIT_REQUESTED], 0);
+ g_debug ("Done emitting quit_requested");
+}
+
+void
+egg_sm_client_quit_cancelled (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ g_debug ("Emitting quit_cancelled");
+ g_signal_emit (client, signals[QUIT_CANCELLED], 0);
+ g_debug ("Done emitting quit_cancelled");
+}
+
+void
+egg_sm_client_quit (EggSMClient *client)
+{
+ g_return_if_fail (client == global_client);
+
+ g_debug ("Emitting quit");
+ g_signal_emit (client, signals[QUIT], 0);
+ g_debug ("Done emitting quit");
+
+ /* FIXME: should we just call gtk_main_quit() here? */
+}
+
+static void
+egg_sm_client_debug_handler (const char *log_domain,
+ GLogLevelFlags log_level,
+ const char *message,
+ gpointer user_data)
+{
+ static int debug = -1;
+
+ if (debug < 0)
+ debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
+
+ if (debug)
+ g_log_default_handler (log_domain, log_level, message, NULL);
+}
diff --git a/plugins/gtkui/smclient/eggsmclient.h b/plugins/gtkui/smclient/eggsmclient.h
new file mode 100644
index 00000000..e620b754
--- /dev/null
+++ b/plugins/gtkui/smclient/eggsmclient.h
@@ -0,0 +1,117 @@
+/* eggsmclient.h
+ * Copyright (C) 2007 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_SM_CLIENT_H__
+#define __EGG_SM_CLIENT_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
+#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
+#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
+#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
+#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
+#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
+
+typedef struct _EggSMClient EggSMClient;
+typedef struct _EggSMClientClass EggSMClientClass;
+typedef struct _EggSMClientPrivate EggSMClientPrivate;
+
+typedef enum {
+ EGG_SM_CLIENT_END_SESSION_DEFAULT,
+ EGG_SM_CLIENT_LOGOUT,
+ EGG_SM_CLIENT_REBOOT,
+ EGG_SM_CLIENT_SHUTDOWN
+} EggSMClientEndStyle;
+
+typedef enum {
+ EGG_SM_CLIENT_MODE_DISABLED,
+ EGG_SM_CLIENT_MODE_NO_RESTART,
+ EGG_SM_CLIENT_MODE_NORMAL
+} EggSMClientMode;
+
+struct _EggSMClient
+{
+ GObject parent;
+
+};
+
+struct _EggSMClientClass
+{
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*save_state) (EggSMClient *client,
+ GKeyFile *state_file);
+
+ void (*quit_requested) (EggSMClient *client);
+ void (*quit_cancelled) (EggSMClient *client);
+ void (*quit) (EggSMClient *client);
+
+ /* virtual methods */
+ void (*startup) (EggSMClient *client,
+ const char *client_id);
+ void (*set_restart_command) (EggSMClient *client,
+ int argc,
+ const char **argv);
+ void (*will_quit) (EggSMClient *client,
+ gboolean will_quit);
+ gboolean (*end_session) (EggSMClient *client,
+ EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+ /* Padding for future expansion */
+ void (*_egg_reserved1) (void);
+ void (*_egg_reserved2) (void);
+ void (*_egg_reserved3) (void);
+ void (*_egg_reserved4) (void);
+};
+
+GType egg_sm_client_get_type (void) G_GNUC_CONST;
+
+GOptionGroup *egg_sm_client_get_option_group (void);
+
+/* Initialization */
+void egg_sm_client_set_mode (EggSMClientMode mode);
+EggSMClientMode egg_sm_client_get_mode (void);
+EggSMClient *egg_sm_client_get (void);
+
+/* Resuming a saved session */
+gboolean egg_sm_client_is_resumed (EggSMClient *client);
+GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
+
+/* Alternate means of saving state */
+void egg_sm_client_set_restart_command (EggSMClient *client,
+ int argc,
+ const char **argv);
+
+/* Handling "quit_requested" signal */
+void egg_sm_client_will_quit (EggSMClient *client,
+ gboolean will_quit);
+
+/* Initiate a logout/reboot/shutdown */
+gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
+ gboolean request_confirmation);
+
+G_END_DECLS
+
+
+#endif /* __EGG_SM_CLIENT_H__ */
diff --git a/plugins/hotkeys/hotkeys.c b/plugins/hotkeys/hotkeys.c
index c7c1c1f3..9c317120 100644
--- a/plugins/hotkeys/hotkeys.c
+++ b/plugins/hotkeys/hotkeys.c
@@ -95,8 +95,23 @@ cmd_invoke_plugin_command (DB_plugin_action_t *action)
{
trace ("We're here to invoke action %s / %s\n", action->title, action->name);
- DB_plugin_t **plugins = deadbeef->plug_get_list();
- int i;
+ // common action
+ if (action->flags & DB_ACTION_COMMON)
+ {
+ action->callback (action, NULL);
+ return;
+ }
+
+ // playlist action
+ if (action->flags & DB_ACTION_PLAYLIST)
+ {
+ ddb_playlist_t *plt = deadbeef->plt_get_curr ();
+ if (plt) {
+ action->callback (action, plt);
+ deadbeef->plt_unref (plt);
+ }
+ return;
+ }
int selected_count = 0;
DB_playItem_t *pit = deadbeef->pl_get_first (PL_MAIN);
@@ -113,13 +128,6 @@ cmd_invoke_plugin_command (DB_plugin_action_t *action)
pit = next;
}
-
- if (action->flags & DB_ACTION_COMMON)
- {
- //Simply call common action
- action->callback (action, NULL);
- return;
- }
//Now we're checking if action is applicable:
if (selected_count == 0)
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index 487219e2..32f4022f 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -807,7 +807,7 @@ cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
trace ("mpgmad: skipping %d(%xH) bytes of junk\n", skip, skip);
deadbeef->fseek (info->buffer.file, skip, SEEK_SET);
}
- int res = cmp3_scan_stream (&info->buffer, -1);
+ int res = cmp3_scan_stream (&info->buffer, deadbeef->conf_get_int ("mp3.disable_gapless", 0) ? 0 : -1);
if (res < 0) {
trace ("mpgmad: cmp3_init: initial cmp3_scan_stream failed\n");
return -1;
@@ -1440,6 +1440,10 @@ static const char *exts[] = {
"mp1", "mp2", "mp3", NULL
};
+static const char settings_dlg[] =
+ "property \"Disable gapless playback (faster scanning)\" checkbox mp3.disable_gapless 0;\n"
+;
+
// define plugin interface
static DB_decoder_t plugin = {
.plugin.api_vmajor = 1,
@@ -1468,6 +1472,7 @@ static DB_decoder_t plugin = {
"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
,
.plugin.website = "http://deadbeef.sf.net",
+ .plugin.configdialog = settings_dlg,
.open = cmp3_open,
.init = cmp3_init,
.free = cmp3_free,
diff --git a/plugins/shellexecui/shellexecui.c b/plugins/shellexecui/shellexecui.c
index 0898d4aa..b2a60230 100644
--- a/plugins/shellexecui/shellexecui.c
+++ b/plugins/shellexecui/shellexecui.c
@@ -348,15 +348,22 @@ init_treeview() {
g_object_unref(liststore);
}
-static int
-shellexecui_action_callback(DB_plugin_action_t *action,
- void *user_data) {
+static gboolean
+shellexecui_action_gtk (void *data)
+{
conf_dlg = create_shellexec_conf_dialog();
gtk_widget_set_size_request (conf_dlg, 400, 400);
gtk_window_set_transient_for(GTK_WINDOW(conf_dlg),
GTK_WINDOW(gtkui_plugin->get_mainwin()));
init_treeview();
gtk_widget_show(conf_dlg);
+ return FALSE;
+}
+
+static int
+shellexecui_action_callback(DB_plugin_action_t *action,
+ void *user_data) {
+ g_idle_add (shellexecui_action_gtk, NULL);
return 0;
}
@@ -397,11 +404,12 @@ static DB_misc_t plugin = {
.plugin.version_major = 1,
.plugin.version_minor = 0,
#if GTK_CHECK_VERSION(3,0,0)
- .plugin.id = "shellexecui_gtk2",
-#else
.plugin.id = "shellexecui_gtk3",
+ .plugin.name = "Shellexec GTK3 UI",
+#else
+ .plugin.id = "shellexecui_gtk2",
+ .plugin.name = "Shellexec GTK2 UI",
#endif
- .plugin.name = "Shellexec GTK UI",
.plugin.descr = "A GTK UI for the Shellexec plugin",
.plugin.copyright =
"Copyright (C) 2012 Azeem Arshad <kr00r4n@gmail.com>\n"
diff --git a/plugins/sndfile/sndfile.c b/plugins/sndfile/sndfile.c
index 071dffdb..e10979be 100644
--- a/plugins/sndfile/sndfile.c
+++ b/plugins/sndfile/sndfile.c
@@ -47,6 +47,7 @@ typedef struct {
int bitrate;
int sf_format;
int read_as_short;
+ int sf_need_endswap;
} sndfile_info_t;
// vfs wrapper for sf
@@ -176,6 +177,7 @@ sndfile_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
}
_info->plugin = &plugin;
info->sf_format = inf.format&0x000f;
+ info->sf_need_endswap = sf_command (info->ctx, SFC_RAW_DATA_NEEDS_ENDSWAP, NULL, 0);
switch (inf.format&0x000f) {
case SF_FORMAT_PCM_S8:
@@ -279,6 +281,36 @@ sndfile_read (DB_fileinfo_t *_info, char *bytes, int size) {
((int8_t *)bytes)[i] = sample-0x80;
}
}
+ else if (info->sf_need_endswap) {
+ switch (info->info.fmt.bps) {
+ case 16:
+ {
+ uint16_t *data = (uint16_t *)bytes;
+ for (int i = 0; i < n; i++, data++) {
+ *data = ((*data & 0xff) << 8) | ((*data & 0xff00) >> 8);
+ }
+ }
+ break;
+ case 24:
+ {
+ uint8_t *data = bytes;
+ for (int i = 0; i < n; i++, data += 3) {
+ uint8_t temp = data[0];
+ data[0] = data[2];
+ data[2] = temp;
+ }
+ }
+ break;
+ case 32:
+ {
+ uint32_t *data = (uint32_t *)bytes;
+ for (int i = 0; i < n; i++, data++) {
+ *data = ((*data & 0xff) << 24) | ((*data & 0xff00) << 8) | ((*data & 0xff0000) >> 8) | ((*data & 0xff0000) >> 24);
+ }
+ }
+ break;
+ }
+ }
n /= samplesize;
}
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index b0779da7..bf35b7f4 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -652,6 +652,7 @@ http_thread_func (void *ctx) {
trace ("curl error:\n%s\n", fp->http_err);
}
deadbeef->mutex_lock (fp->mutex);
+#if 0
if (status == 0 && fp->length < 0 && fp->status != STATUS_ABORTED && fp->status != STATUS_SEEK) {
trace ("vfs_curl: restarting stream\n");
// NOTE: don't do http_stream_reset here - we don't want to cut the ending
@@ -669,6 +670,7 @@ http_thread_func (void *ctx) {
deadbeef->mutex_unlock (fp->mutex);
continue;
}
+#endif
if (fp->status != STATUS_SEEK) {
trace ("vfs_curl: break loop\n");
deadbeef->mutex_unlock (fp->mutex);
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index cbc23a62..335e73d0 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -222,7 +222,7 @@ cvorbis_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
if (plt) {
deadbeef->plt_unref (plt);
}
- deadbeef->pl_replace_meta (it, ":FILETYPE", "OggVorbis");
+ deadbeef->pl_replace_meta (it, "!FILETYPE", "OggVorbis");
}
else
{
@@ -463,7 +463,7 @@ cvorbis_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
int64_t fsize = deadbeef->fgetlength (fp);
if (fp->vfs->is_streaming ()) {
DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
- deadbeef->pl_add_meta (it, ":FILETYPE", "OggVorbis");
+ deadbeef->pl_add_meta (it, "!FILETYPE", "OggVorbis");
deadbeef->plt_set_item_duration (plt, it, -1);
deadbeef->pl_add_meta (it, "title", NULL);
after = deadbeef->plt_insert_item (plt, after, it);
diff --git a/po/zh_TW.po b/po/zh_TW.po
index c12a33d2..429d48eb 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -1138,8 +1138,8 @@ msgid ""
" copy[r]ight, [e]lapsed\n"
msgstr ""
" FMT %%-句法: [a]藝人, [t]歌名, [b]專輯,\n"
-" [l]長度, [n]歌曲編號, [y]年份, [c]評語, "
-"[r]版權, [e]已過時間"
+" [l]長度, [n]歌曲編號, [y]年份, [c]評語,\n"
+" [r]版權, [e]已過時間\n"
#: ../main.c:109
#, c-format
diff --git a/scripts/portable_build.sh b/scripts/portable_build.sh
index 89f2d1ca..3a11ea99 100755
--- a/scripts/portable_build.sh
+++ b/scripts/portable_build.sh
@@ -9,7 +9,7 @@ export APBUILD_STATIC_LIBGCC=1
./autogen.sh
-./configure --enable-staticlink=yes --enable-portable=yes --disable-artwork-imlib2
+./configure --enable-staticlink --enable-portable --disable-artwork-imlib2
sed -i 's/-lstdc++ -lm -lgcc_s -lc -lgcc_s/-lm -lc/g' libtool
make clean
make -j9
@@ -23,5 +23,3 @@ cd tools/pluginfo
make
cd ../../
-./scripts/portable_postbuild.sh
-
diff --git a/scripts/portable_package_static.sh b/scripts/portable_package_static.sh
index 26fa6051..1ad0c076 100755
--- a/scripts/portable_package_static.sh
+++ b/scripts/portable_package_static.sh
@@ -1,23 +1,28 @@
#!/bin/sh
+./scripts/portable_postbuild.sh
+
# package for distribution
VERSION=`cat PORTABLE_VERSION | perl -ne 'chomp and print'`
BUILD=`cat PORTABLE_BUILD | perl -ne 'chomp and print'`
+ARCH=`uname -m | perl -ne 'chomp and print'`
# main distro
SRCDIR=deadbeef-$VERSION
PLUGDIR=$SRCDIR/plugins
DOCDIR=$SRCDIR/doc
PIXMAPDIR=$SRCDIR/pixmaps
+OUTNAME=deadbeef-static_${VERSION}-${BUILD}_${ARCH}.tar.bz2
ARCH=`uname -m | perl -ne 'chomp and print'`
-rm portable_out/build/deadbeef-$VERSION-static-$ARCH.tar.bz2
+rm portable_out/build/$OUTNAME
cd portable/$ARCH
-tar jcvf ../..//portable_out/build/deadbeef-$VERSION-static-$ARCH.tar.bz2\
+tar jcvf ../../portable_out/build/$OUTNAME\
$SRCDIR/deadbeef\
$SRCDIR/deadbeef.png\
+ $SRCDIR/.ddb_portable\
$DOCDIR\
$PLUGDIR/aac.so\
$PLUGDIR/adplug.so\
diff --git a/scripts/portable_postbuild.sh b/scripts/portable_postbuild.sh
index 9a82c216..45db6740 100755
--- a/scripts/portable_postbuild.sh
+++ b/scripts/portable_postbuild.sh
@@ -6,6 +6,7 @@ OUTDIR=portable/$ARCH/deadbeef-$VERSION
PLUGDIR=$OUTDIR/plugins
DOCDIR=$OUTDIR/doc
PIXMAPDIR=$OUTDIR/pixmaps
+echo OUTDIR=$OUTDIR
rm -rf $OUTDIR
@@ -54,7 +55,7 @@ fi
#pixmaps
-for i in pause_16.png play_16.png noartwork.jpg buffering_16.png; do
+for i in pause_16.png play_16.png noartwork.png buffering_16.png; do
cp ./pixmaps/$i $PIXMAPDIR/
done
@@ -78,6 +79,7 @@ for i in po/*.gmo ; do
done
cp translation/help.pt_BR.txt $OUTDIR/doc/
cp translation/help.ru.txt $OUTDIR/doc/
+touch $OUTDIR/.ddb_portable
# strip
if [ $OSTYPE != 'Darwin' ];then
diff --git a/scripts/static_build.sh b/scripts/static_build.sh
index 7ebc85ca..250b29e8 100755
--- a/scripts/static_build.sh
+++ b/scripts/static_build.sh
@@ -2,27 +2,21 @@
VERSION=`cat PORTABLE_VERSION | perl -ne 'chomp and print'`
ORIGIN=`pwd | perl -ne 'chomp and print'`
AP=$ORIGIN/tools/apbuild
-export CC=$AP/apgcc
-export CXX=$AP/apgcc
+ARCH=`uname -m | perl -ne 'chomp and print'`
-export APBUILD_STATIC_LIBGCC=1
+cd tools/apbuild
+./apinit
+cd ../../
./autogen.sh
-./configure --enable-staticlink --disable-artwork-imlib2 --prefix=/opt/deadbeef
+export APBUILD_STATIC_LIBGCC=1
+CC=$AP/apgcc CXX=$AP/apgcc ./configure --enable-staticlink --disable-artwork-imlib2 --prefix=/opt/deadbeef
sed -i 's/-lstdc++ -lm -lgcc_s -lc -lgcc_s/-lm -lc/g' libtool
make clean
-make -j9
-
-#./scripts/portable_extraplugs.sh
-
-cd $ORIGIN
+make DESTDIR=`pwd`/static/$ARCH/deadbeef-$VERSION -j8 install
echo "building pluginfo tool..."
cd tools/pluginfo
make
cd ../../
-
-#./scripts/portable_postbuild.sh
-fakeroot -- ./scripts/static_install.sh
-
diff --git a/streamer.c b/streamer.c
index ce381dee..2a5d22bc 100644
--- a/streamer.c
+++ b/streamer.c
@@ -755,8 +755,9 @@ streamer_set_current (playItem_t *it) {
trace ("failed to alloc %d bytes for playlist buffer\n");
goto m3u_error;
}
+ trace ("reading %d bytes\n", size);
int rd = vfs_fread (buf, 1, size, fp);
- if (rd != size) {
+ if (rd <= 0) {
trace ("failed to download %d bytes (got %d bytes)\n", size, rd);
goto m3u_error;
}
@@ -772,13 +773,14 @@ streamer_set_current (playItem_t *it) {
trace ("failed to open temp file %s\n", tempfile);
goto m3u_error;
}
+ trace ("writing to %s\n", tempfile);
out = fdopen (fd, "w+b");
if (!out) {
trace ("fdopen failed for %s\n", tempfile);
goto m3u_error;
}
- int rw = fwrite (buf, 1, size, out);
- if (rw != size) {
+ int rw = fwrite (buf, 1, rd, out);
+ if (rw != rd) {
trace ("failed to write %d bytes into file %s\n", size, tempfile);
goto m3u_error;
}
@@ -786,6 +788,7 @@ streamer_set_current (playItem_t *it) {
fd = -1;
out = NULL;
+ trace ("loading playlist from %s\n", tempfile);
// load playlist
playlist_t *plt = plt_alloc ("temp");
DB_playlist_t **plug = plug_get_playlist_list ();
@@ -1196,7 +1199,9 @@ streamer_thread (void *ctx) {
bytes_until_next_song = -1;
trace ("nextsong=-2\n");
nextsong = -1;
+ streamer_unlock ();
output->stop ();
+ streamer_lock ();
if (playing_track) {
trace ("sending songfinished to plugins [1]\n");
send_songfinished (playing_track);
diff --git a/tools/apbuild/apgcc b/tools/apbuild/apgcc
index 8b81686c..ddda846b 100755
--- a/tools/apbuild/apgcc
+++ b/tools/apbuild/apgcc
@@ -74,14 +74,10 @@ if (!defined $appath) {
$appath =~ s/\/*$//g;
$appath =~ s/^(.*)\/.*?$/$1/;
$appath .= '/include/apbuild';
- if (! -f "$appath/apsymbols.h" && -f "$FindBin::Bin/apsymbols.h") {
+ if (! -f "$appath/apsymbols.h.i686" && -f "$FindBin::Bin/apsymbols.h.i686") {
$appath = $FindBin::Bin;
}
}
-my $arch=`uname -m`;
-chomp $arch;
-`cp $appath/apsymbols.h.$arch $appath/apsymbols.h`;
-
# Special constants
our @linking = ('-Wl,--enable-new-dtags,--rpath,${ORIGIN}/../lib,--rpath,${ORIGIN}/../lib/autopackage');
diff --git a/tools/apbuild/apinit b/tools/apbuild/apinit
new file mode 100755
index 00000000..37892303
--- /dev/null
+++ b/tools/apbuild/apinit
@@ -0,0 +1,9 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+my $arch=`uname -m`;
+chomp $arch;
+`cp apsymbols.h.$arch apsymbols.h`;
+
+
diff --git a/tools/packages/arch.sh b/tools/packages/arch.sh
index 8e22176e..ce171a67 100755
--- a/tools/packages/arch.sh
+++ b/tools/packages/arch.sh
@@ -2,6 +2,7 @@
PWD=`pwd`
VERSION=`cat PORTABLE_VERSION | perl -ne 'chomp and print'`
+ARCH_VERSION=`cat PORTABLE_VERSION | perl -ne 'chomp and print' | sed 's/-//'`
BUILD=`cat PORTABLE_BUILD | perl -ne 'chomp and print'`
ARCH=`uname -m | perl -ne 'chomp and print'`
INDIR=$PWD/static/$ARCH/deadbeef-$VERSION
@@ -19,7 +20,9 @@ cp -r $INDIR/* $TEMPDIR/
# rm unneeded files
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.la
for i in $TEMPDIR/opt/deadbeef/lib/deadbeef/*.so.0.0.0; do
- mv $i $TEMPDIR/opt/deadbeef/lib/deadbeef/`basename $i .0.0.0`
+ n=$TEMPDIR/opt/deadbeef/lib/deadbeef/`basename $i .0.0.0`
+ mv $i $n
+ strip --strip-unneeded $n
done
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.so.*
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.a
@@ -32,7 +35,7 @@ mv $TEMPDIR/opt/deadbeef/share/icons $TEMPDIR/usr/share/
# generate .PKGINFO
echo "# `date -u`" >$PKGINFO
-echo "pkgver = $VERSION-$BUILD" >>$PKGINFO
+echo "pkgver = $ARCH_VERSION-$BUILD" >>$PKGINFO
echo "builddate = `date --utc +%s`" >>$PKGINFO
echo "size = `du -sb $TEMPDIR | awk '{print $1}'`" >>$PKGINFO
echo "arch = $ARCH" >>$PKGINFO
@@ -43,4 +46,4 @@ cp tools/packages/arch_install $INSTALL
# archive
cd $TEMPDIR
-fakeroot -- tar Jcvf $OUTDIR/deadbeef-$VERSION-$BUILD-$ARCH.pkg.tar.xz * .PKGINFO .INSTALL
+fakeroot -- tar Jcvf $OUTDIR/deadbeef-static-$ARCH_VERSION-$BUILD-$ARCH.pkg.tar.xz * .PKGINFO .INSTALL
diff --git a/tools/packages/arch_install b/tools/packages/arch_install
index eaf1b9a6..2c5696c8 100644
--- a/tools/packages/arch_install
+++ b/tools/packages/arch_install
@@ -1,4 +1,4 @@
-pkgname=deadbeef
+pkgname=deadbeef-static
post_install() {
gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
diff --git a/tools/packages/arch_pkginfo b/tools/packages/arch_pkginfo
index e58eee9e..17d1c0f9 100644
--- a/tools/packages/arch_pkginfo
+++ b/tools/packages/arch_pkginfo
@@ -1,4 +1,4 @@
-pkgname = deadbeef
+pkgname = deadbeef-static
pkgdesc = An audio player for GNU/Linux based on GTK2.
url = http://deadbeef.sourceforge.net
packager = Alexey Yakovenko <waker@users.sf.net>
diff --git a/tools/packages/debian.sh b/tools/packages/debian.sh
index 985dca28..90d8acdd 100755
--- a/tools/packages/debian.sh
+++ b/tools/packages/debian.sh
@@ -27,8 +27,12 @@ cp -r $INDIR/* $TEMPDIR/
# rm unneeded files
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.la
for i in $TEMPDIR/opt/deadbeef/lib/deadbeef/*.so.0.0.0; do
- mv $i $TEMPDIR/opt/deadbeef/lib/deadbeef/`basename $i .0.0.0`
+ n=$TEMPDIR/opt/deadbeef/lib/deadbeef/`basename $i .0.0.0`
+ mv $i $n
+ strip --strip-unneeded $n
done
+strip --strip-unneeded $TEMPDIR/opt/deadbeef/bin/deadbeef
+
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.so.*
rm $TEMPDIR/opt/deadbeef/lib/deadbeef/*.a
@@ -43,7 +47,7 @@ echo "2.0" >$TEMPDIR/debian-binary
# generate control
echo "Version: $VERSION-$BUILD" >$TEMPDIR/control
-echo "Installed-Size: `du -sb $TEMPDIR | awk '{print $1}'`" >>$TEMPDIR/control
+echo "Installed-Size: `du -sb $TEMPDIR | awk '{print int($1/1024)}'`" >>$TEMPDIR/control
echo "Architecture: $DEB_ARCH" >>$TEMPDIR/control
cat $PWD/tools/packages/deb_control >>$TEMPDIR/control
diff --git a/translation/extra.c b/translation/extra.c
index fe0552cb..7a0ddb5d 100644
--- a/translation/extra.c
+++ b/translation/extra.c
@@ -13,6 +13,7 @@ _("Disable nowplaying")
_("Username")
_("Password")
_("Scrobble URL")
+_("Prefer Album Artist over Artist field")
// OSS output plugin
_("Device file")
_("OSS4 samplerate bug workaround")
@@ -33,8 +34,11 @@ _("Prefer CDDB protocol over HTTP")
_("Enable NRG image support")
// DUMB module player plugin
_("Resampling quality (0..2, higher is better)")
+_("8-bit output (default is 16)")
// Game_Music_Emu decoder plugin
_("Max song length (in minutes)")
+_("Fadeout length (seconds)")
+_("Play loops nr. of times (if available)")
// Standard GTK2 user interface plugin
_("Ask confirmation to delete files from disk")
_("Status icon volume control sensitivity")
@@ -89,5 +93,11 @@ _("Convert")
_("Target Samplerate")
_("Quality / Algorythm")
_("Automatic Samplerate (overrides Target Samplerate)")
+// shellexecui
// please note: do NOT translate the Edit/ part
_("Edit/Configure custom shell commands")
+// mpgmad
+_("Disable gapless playback (faster scanning)")
+// adplug
+_("Prefer Ken emu over Satoh (surround won't work)")
+_("Enable surround")