GME: Updated libgme to 0.6.4-13-ga32f34a

Also applied PR !134

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-08-04 19:59:52 -07:00
parent e0be2497c0
commit 81df9c8282
124 changed files with 4005 additions and 3722 deletions

View file

@ -82,7 +82,6 @@
17C8F2470CBED286008D969D /* Sms_Apu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F1DE0CBED286008D969D /* Sms_Apu.h */; }; 17C8F2470CBED286008D969D /* Sms_Apu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F1DE0CBED286008D969D /* Sms_Apu.h */; };
17C8F24F0CBED286008D969D /* Spc_Emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F1E60CBED286008D969D /* Spc_Emu.cpp */; }; 17C8F24F0CBED286008D969D /* Spc_Emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 17C8F1E60CBED286008D969D /* Spc_Emu.cpp */; };
17C8F2500CBED286008D969D /* Spc_Emu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F1E70CBED286008D969D /* Spc_Emu.h */; }; 17C8F2500CBED286008D969D /* Spc_Emu.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C8F1E70CBED286008D969D /* Spc_Emu.h */; };
8302AF4F2784668C0066143E /* vrc7tone.h in Headers */ = {isa = PBXBuildFile; fileRef = 8302AF4E2784668C0066143E /* vrc7tone.h */; };
83489CBB2783015300BDCEA2 /* gme_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB12783015200BDCEA2 /* gme_types.h */; }; 83489CBB2783015300BDCEA2 /* gme_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB12783015200BDCEA2 /* gme_types.h */; };
83489CBC2783015300BDCEA2 /* nes_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB22783015300BDCEA2 /* nes_cpu_io.h */; }; 83489CBC2783015300BDCEA2 /* nes_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB22783015300BDCEA2 /* nes_cpu_io.h */; };
83489CBD2783015300BDCEA2 /* hes_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB32783015300BDCEA2 /* hes_cpu_io.h */; }; 83489CBD2783015300BDCEA2 /* hes_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CB32783015300BDCEA2 /* hes_cpu_io.h */; };
@ -100,17 +99,21 @@
83489CD82783C98600BDCEA2 /* Nes_Vrc7_Apu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CD62783C98600BDCEA2 /* Nes_Vrc7_Apu.h */; }; 83489CD82783C98600BDCEA2 /* Nes_Vrc7_Apu.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CD62783C98600BDCEA2 /* Nes_Vrc7_Apu.h */; };
83489CD92783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83489CD72783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp */; }; 83489CD92783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83489CD72783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp */; };
83489CE02783CAC100BDCEA2 /* gb_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CDA2783CAC000BDCEA2 /* gb_cpu_io.h */; }; 83489CE02783CAC100BDCEA2 /* gb_cpu_io.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CDA2783CAC000BDCEA2 /* gb_cpu_io.h */; };
83489CE12783CAC100BDCEA2 /* 2413tone.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CDB2783CAC000BDCEA2 /* 2413tone.h */; };
83489CE32783CAC100BDCEA2 /* emu2413.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CDD2783CAC100BDCEA2 /* emu2413.h */; };
83489CE52783CAC100BDCEA2 /* emu2413.c in Sources */ = {isa = PBXBuildFile; fileRef = 83489CDF2783CAC100BDCEA2 /* emu2413.c */; };
83489CEA2783CADC00BDCEA2 /* panning.c in Sources */ = {isa = PBXBuildFile; fileRef = 83489CE72783CADC00BDCEA2 /* panning.c */; };
83489CEB2783CADC00BDCEA2 /* panning.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CE82783CADC00BDCEA2 /* panning.h */; };
83489CED2783D86700BDCEA2 /* mamedef.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CEC2783D86700BDCEA2 /* mamedef.h */; };
83489CEF2783D89300BDCEA2 /* emutypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 83489CEE2783D89300BDCEA2 /* emutypes.h */; };
8370B7AD17F615FE001A4D7A /* Spc_Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8370B70A17F615FE001A4D7A /* Spc_Filter.cpp */; }; 8370B7AD17F615FE001A4D7A /* Spc_Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8370B70A17F615FE001A4D7A /* Spc_Filter.cpp */; };
8370B7AE17F615FE001A4D7A /* Spc_Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B70B17F615FE001A4D7A /* Spc_Filter.h */; }; 8370B7AE17F615FE001A4D7A /* Spc_Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B70B17F615FE001A4D7A /* Spc_Filter.h */; };
8370B7AF17F615FE001A4D7A /* Spc_Sfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8370B70C17F615FE001A4D7A /* Spc_Sfm.cpp */; }; 8370B7AF17F615FE001A4D7A /* Spc_Sfm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8370B70C17F615FE001A4D7A /* Spc_Sfm.cpp */; };
8370B7B017F615FE001A4D7A /* Spc_Sfm.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B70D17F615FE001A4D7A /* Spc_Sfm.h */; }; 8370B7B017F615FE001A4D7A /* Spc_Sfm.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B70D17F615FE001A4D7A /* Spc_Sfm.h */; };
83BDCDD02E41A269003FC007 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 83BDCDC92E41A269003FC007 /* LICENSE */; };
83BDCDD12E41A269003FC007 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 83BDCDCD2E41A269003FC007 /* README.md */; };
83BDCDD22E41A269003FC007 /* emu2413_NESpatches.txt in Resources */ = {isa = PBXBuildFile; fileRef = 83BDCDC72E41A269003FC007 /* emu2413_NESpatches.txt */; };
83BDCDD32E41A269003FC007 /* panning.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDCB2E41A269003FC007 /* panning.h */; };
83BDCDD42E41A269003FC007 /* 2413tone.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDC42E41A269003FC007 /* 2413tone.h */; };
83BDCDD52E41A269003FC007 /* emutypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDC82E41A269003FC007 /* emutypes.h */; };
83BDCDD62E41A269003FC007 /* mamedef.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDCA2E41A269003FC007 /* mamedef.h */; };
83BDCDD72E41A269003FC007 /* emu2413.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDC52E41A269003FC007 /* emu2413.h */; };
83BDCDD82E41A269003FC007 /* vrc7tone.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCDCE2E41A269003FC007 /* vrc7tone.h */; };
83BDCDD92E41A269003FC007 /* emu2413.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BDCDC62E41A269003FC007 /* emu2413.c */; };
83BDCDDA2E41A269003FC007 /* panning.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BDCDCC2E41A269003FC007 /* panning.c */; };
83FC5D5E181B47FB00B917E5 /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83FC5D3B181B47FB00B917E5 /* dsp.cpp */; }; 83FC5D5E181B47FB00B917E5 /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83FC5D3B181B47FB00B917E5 /* dsp.cpp */; };
83FC5D5F181B47FB00B917E5 /* dsp.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83FC5D3C181B47FB00B917E5 /* dsp.hpp */; }; 83FC5D5F181B47FB00B917E5 /* dsp.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83FC5D3C181B47FB00B917E5 /* dsp.hpp */; };
83FC5D78181B47FB00B917E5 /* smp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83FC5D57181B47FB00B917E5 /* smp.cpp */; }; 83FC5D78181B47FB00B917E5 /* smp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83FC5D57181B47FB00B917E5 /* smp.cpp */; };
@ -203,7 +206,6 @@
17C8F1DE0CBED286008D969D /* Sms_Apu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sms_Apu.h; path = gme/Sms_Apu.h; sourceTree = "<group>"; }; 17C8F1DE0CBED286008D969D /* Sms_Apu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Sms_Apu.h; path = gme/Sms_Apu.h; sourceTree = "<group>"; };
17C8F1E60CBED286008D969D /* Spc_Emu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Spc_Emu.cpp; path = gme/Spc_Emu.cpp; sourceTree = "<group>"; }; 17C8F1E60CBED286008D969D /* Spc_Emu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Spc_Emu.cpp; path = gme/Spc_Emu.cpp; sourceTree = "<group>"; };
17C8F1E70CBED286008D969D /* Spc_Emu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Spc_Emu.h; path = gme/Spc_Emu.h; sourceTree = "<group>"; }; 17C8F1E70CBED286008D969D /* Spc_Emu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Spc_Emu.h; path = gme/Spc_Emu.h; sourceTree = "<group>"; };
8302AF4E2784668C0066143E /* vrc7tone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vrc7tone.h; sourceTree = "<group>"; };
833F68361CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 833F68361CDBCAB200AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
83489CB12783015200BDCEA2 /* gme_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gme_types.h; path = gme/gme_types.h; sourceTree = "<group>"; }; 83489CB12783015200BDCEA2 /* gme_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gme_types.h; path = gme/gme_types.h; sourceTree = "<group>"; };
83489CB22783015300BDCEA2 /* nes_cpu_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nes_cpu_io.h; path = gme/nes_cpu_io.h; sourceTree = "<group>"; }; 83489CB22783015300BDCEA2 /* nes_cpu_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nes_cpu_io.h; path = gme/nes_cpu_io.h; sourceTree = "<group>"; };
@ -222,14 +224,6 @@
83489CD62783C98600BDCEA2 /* Nes_Vrc7_Apu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Nes_Vrc7_Apu.h; path = gme/Nes_Vrc7_Apu.h; sourceTree = SOURCE_ROOT; }; 83489CD62783C98600BDCEA2 /* Nes_Vrc7_Apu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Nes_Vrc7_Apu.h; path = gme/Nes_Vrc7_Apu.h; sourceTree = SOURCE_ROOT; };
83489CD72783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Nes_Vrc7_Apu.cpp; path = gme/Nes_Vrc7_Apu.cpp; sourceTree = SOURCE_ROOT; }; 83489CD72783C98600BDCEA2 /* Nes_Vrc7_Apu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Nes_Vrc7_Apu.cpp; path = gme/Nes_Vrc7_Apu.cpp; sourceTree = SOURCE_ROOT; };
83489CDA2783CAC000BDCEA2 /* gb_cpu_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gb_cpu_io.h; path = gme/gb_cpu_io.h; sourceTree = "<group>"; }; 83489CDA2783CAC000BDCEA2 /* gb_cpu_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gb_cpu_io.h; path = gme/gb_cpu_io.h; sourceTree = "<group>"; };
83489CDB2783CAC000BDCEA2 /* 2413tone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 2413tone.h; sourceTree = "<group>"; };
83489CDC2783CAC100BDCEA2 /* emu2413_NESpatches.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = emu2413_NESpatches.txt; sourceTree = "<group>"; };
83489CDD2783CAC100BDCEA2 /* emu2413.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emu2413.h; sourceTree = "<group>"; };
83489CDF2783CAC100BDCEA2 /* emu2413.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emu2413.c; sourceTree = "<group>"; };
83489CE72783CADC00BDCEA2 /* panning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = panning.c; sourceTree = "<group>"; };
83489CE82783CADC00BDCEA2 /* panning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = panning.h; sourceTree = "<group>"; };
83489CEC2783D86700BDCEA2 /* mamedef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mamedef.h; sourceTree = "<group>"; };
83489CEE2783D89300BDCEA2 /* emutypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = emutypes.h; sourceTree = "<group>"; };
835C889022CC1884001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 835C889022CC1884001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
8370B70A17F615FE001A4D7A /* Spc_Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Spc_Filter.cpp; path = gme/Spc_Filter.cpp; sourceTree = "<group>"; }; 8370B70A17F615FE001A4D7A /* Spc_Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Spc_Filter.cpp; path = gme/Spc_Filter.cpp; sourceTree = "<group>"; };
8370B70B17F615FE001A4D7A /* Spc_Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Spc_Filter.h; path = gme/Spc_Filter.h; sourceTree = "<group>"; }; 8370B70B17F615FE001A4D7A /* Spc_Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Spc_Filter.h; path = gme/Spc_Filter.h; sourceTree = "<group>"; };
@ -237,6 +231,17 @@
8370B70D17F615FE001A4D7A /* Spc_Sfm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Spc_Sfm.h; path = gme/Spc_Sfm.h; sourceTree = "<group>"; }; 8370B70D17F615FE001A4D7A /* Spc_Sfm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Spc_Sfm.h; path = gme/Spc_Sfm.h; sourceTree = "<group>"; };
83747B7F2862D4DB0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; }; 83747B7F2862D4DB0021245F /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
838EE8BD29A8600A00CD0580 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 838EE8BD29A8600A00CD0580 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
83BDCDC42E41A269003FC007 /* 2413tone.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = 2413tone.h; sourceTree = "<group>"; };
83BDCDC52E41A269003FC007 /* emu2413.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = emu2413.h; sourceTree = "<group>"; };
83BDCDC62E41A269003FC007 /* emu2413.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = emu2413.c; sourceTree = "<group>"; };
83BDCDC72E41A269003FC007 /* emu2413_NESpatches.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = emu2413_NESpatches.txt; sourceTree = "<group>"; };
83BDCDC82E41A269003FC007 /* emutypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = emutypes.h; sourceTree = "<group>"; };
83BDCDC92E41A269003FC007 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
83BDCDCA2E41A269003FC007 /* mamedef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mamedef.h; sourceTree = "<group>"; };
83BDCDCB2E41A269003FC007 /* panning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = panning.h; sourceTree = "<group>"; };
83BDCDCC2E41A269003FC007 /* panning.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = panning.c; sourceTree = "<group>"; };
83BDCDCD2E41A269003FC007 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
83BDCDCE2E41A269003FC007 /* vrc7tone.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vrc7tone.h; sourceTree = "<group>"; };
83F0E6B7287CAB4100D84594 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 83F0E6B7287CAB4100D84594 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
83FC5D3B181B47FB00B917E5 /* dsp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp.cpp; sourceTree = "<group>"; }; 83FC5D3B181B47FB00B917E5 /* dsp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp.cpp; sourceTree = "<group>"; };
83FC5D3C181B47FB00B917E5 /* dsp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = dsp.hpp; sourceTree = "<group>"; }; 83FC5D3C181B47FB00B917E5 /* dsp.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = dsp.hpp; sourceTree = "<group>"; };
@ -339,7 +344,7 @@
17C8F1860CBED26C008D969D /* Source */ = { 17C8F1860CBED26C008D969D /* Source */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
83489CF02783DC4F00BDCEA2 /* ext */, 83BDCDCF2E41A269003FC007 /* ext */,
83FC5D35181B47FB00B917E5 /* higan */, 83FC5D35181B47FB00B917E5 /* higan */,
17C8F18B0CBED286008D969D /* Ay_Apu.cpp */, 17C8F18B0CBED286008D969D /* Ay_Apu.cpp */,
17C8F18C0CBED286008D969D /* Ay_Apu.h */, 17C8F18C0CBED286008D969D /* Ay_Apu.h */,
@ -447,22 +452,6 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
83489CF02783DC4F00BDCEA2 /* ext */ = {
isa = PBXGroup;
children = (
83489CDB2783CAC000BDCEA2 /* 2413tone.h */,
83489CDC2783CAC100BDCEA2 /* emu2413_NESpatches.txt */,
83489CDF2783CAC100BDCEA2 /* emu2413.c */,
83489CDD2783CAC100BDCEA2 /* emu2413.h */,
83489CEE2783D89300BDCEA2 /* emutypes.h */,
83489CEC2783D86700BDCEA2 /* mamedef.h */,
83489CE72783CADC00BDCEA2 /* panning.c */,
83489CE82783CADC00BDCEA2 /* panning.h */,
8302AF4E2784668C0066143E /* vrc7tone.h */,
);
path = ext;
sourceTree = "<group>";
};
83747B7E2862D4DB0021245F /* Xcode-config */ = { 83747B7E2862D4DB0021245F /* Xcode-config */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -472,6 +461,25 @@
path = "../../Xcode-config"; path = "../../Xcode-config";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
83BDCDCF2E41A269003FC007 /* ext */ = {
isa = PBXGroup;
children = (
83BDCDC42E41A269003FC007 /* 2413tone.h */,
83BDCDC52E41A269003FC007 /* emu2413.h */,
83BDCDC62E41A269003FC007 /* emu2413.c */,
83BDCDC72E41A269003FC007 /* emu2413_NESpatches.txt */,
83BDCDC82E41A269003FC007 /* emutypes.h */,
83BDCDC92E41A269003FC007 /* LICENSE */,
83BDCDCA2E41A269003FC007 /* mamedef.h */,
83BDCDCB2E41A269003FC007 /* panning.h */,
83BDCDCC2E41A269003FC007 /* panning.c */,
83BDCDCD2E41A269003FC007 /* README.md */,
83BDCDCE2E41A269003FC007 /* vrc7tone.h */,
);
name = ext;
path = gme/ext;
sourceTree = "<group>";
};
83FC5D35181B47FB00B917E5 /* higan */ = { 83FC5D35181B47FB00B917E5 /* higan */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -546,22 +554,25 @@
17C8F1FF0CBED286008D969D /* Blip_Buffer.h in Headers */, 17C8F1FF0CBED286008D969D /* Blip_Buffer.h in Headers */,
17C8F2010CBED286008D969D /* Classic_Emu.h in Headers */, 17C8F2010CBED286008D969D /* Classic_Emu.h in Headers */,
17C8F2030CBED286008D969D /* Data_Reader.h in Headers */, 17C8F2030CBED286008D969D /* Data_Reader.h in Headers */,
83BDCDD32E41A269003FC007 /* panning.h in Headers */,
83BDCDD42E41A269003FC007 /* 2413tone.h in Headers */,
83BDCDD52E41A269003FC007 /* emutypes.h in Headers */,
83BDCDD62E41A269003FC007 /* mamedef.h in Headers */,
83BDCDD72E41A269003FC007 /* emu2413.h in Headers */,
83BDCDD82E41A269003FC007 /* vrc7tone.h in Headers */,
17C8F2050CBED286008D969D /* Dual_Resampler.h in Headers */, 17C8F2050CBED286008D969D /* Dual_Resampler.h in Headers */,
17C8F2070CBED286008D969D /* Effects_Buffer.h in Headers */, 17C8F2070CBED286008D969D /* Effects_Buffer.h in Headers */,
17C8F2090CBED286008D969D /* Fir_Resampler.h in Headers */, 17C8F2090CBED286008D969D /* Fir_Resampler.h in Headers */,
83489CD82783C98600BDCEA2 /* Nes_Vrc7_Apu.h in Headers */, 83489CD82783C98600BDCEA2 /* Nes_Vrc7_Apu.h in Headers */,
83489CEB2783CADC00BDCEA2 /* panning.h in Headers */,
83FC5DAE181B8B1900B917E5 /* spc700.hpp in Headers */, 83FC5DAE181B8B1900B917E5 /* spc700.hpp in Headers */,
17C8F20B0CBED286008D969D /* Gb_Apu.h in Headers */, 17C8F20B0CBED286008D969D /* Gb_Apu.h in Headers */,
83FC5DAB181B8B1900B917E5 /* registers.hpp in Headers */, 83FC5DAB181B8B1900B917E5 /* registers.hpp in Headers */,
17C8F20E0CBED286008D969D /* Gb_Cpu.h in Headers */, 17C8F20E0CBED286008D969D /* Gb_Cpu.h in Headers */,
83489CC22783015300BDCEA2 /* sap_cpu_io.h in Headers */, 83489CC22783015300BDCEA2 /* sap_cpu_io.h in Headers */,
8302AF4F2784668C0066143E /* vrc7tone.h in Headers */,
83489CBD2783015300BDCEA2 /* hes_cpu_io.h in Headers */, 83489CBD2783015300BDCEA2 /* hes_cpu_io.h in Headers */,
17C8F2100CBED286008D969D /* Gb_Oscs.h in Headers */, 17C8F2100CBED286008D969D /* Gb_Oscs.h in Headers */,
17C8F2120CBED286008D969D /* Gbs_Emu.h in Headers */, 17C8F2120CBED286008D969D /* Gbs_Emu.h in Headers */,
83489CE02783CAC100BDCEA2 /* gb_cpu_io.h in Headers */, 83489CE02783CAC100BDCEA2 /* gb_cpu_io.h in Headers */,
83489CEF2783D89300BDCEA2 /* emutypes.h in Headers */,
83489CD12783BF6D00BDCEA2 /* Nes_Mmc5_Apu.h in Headers */, 83489CD12783BF6D00BDCEA2 /* Nes_Mmc5_Apu.h in Headers */,
83489CC02783015300BDCEA2 /* Ay_Cpu.h in Headers */, 83489CC02783015300BDCEA2 /* Ay_Cpu.h in Headers */,
83FC5D9A181B675900B917E5 /* SPC_DSP.h in Headers */, 83FC5D9A181B675900B917E5 /* SPC_DSP.h in Headers */,
@ -578,9 +589,7 @@
17C8F2290CBED286008D969D /* M3u_Playlist.h in Headers */, 17C8F2290CBED286008D969D /* M3u_Playlist.h in Headers */,
17C8F22B0CBED286008D969D /* Multi_Buffer.h in Headers */, 17C8F22B0CBED286008D969D /* Multi_Buffer.h in Headers */,
17C8F22D0CBED286008D969D /* Music_Emu.h in Headers */, 17C8F22D0CBED286008D969D /* Music_Emu.h in Headers */,
83489CED2783D86700BDCEA2 /* mamedef.h in Headers */,
17C8F22F0CBED286008D969D /* Nes_Apu.h in Headers */, 17C8F22F0CBED286008D969D /* Nes_Apu.h in Headers */,
83489CE32783CAC100BDCEA2 /* emu2413.h in Headers */,
17C8F2320CBED286008D969D /* Nes_Cpu.h in Headers */, 17C8F2320CBED286008D969D /* Nes_Cpu.h in Headers */,
17C8F2340CBED286008D969D /* Nes_Fme7_Apu.h in Headers */, 17C8F2340CBED286008D969D /* Nes_Fme7_Apu.h in Headers */,
17C8F2360CBED286008D969D /* Nes_Namco_Apu.h in Headers */, 17C8F2360CBED286008D969D /* Nes_Namco_Apu.h in Headers */,
@ -595,7 +604,6 @@
8370B7AE17F615FE001A4D7A /* Spc_Filter.h in Headers */, 8370B7AE17F615FE001A4D7A /* Spc_Filter.h in Headers */,
17C8F2500CBED286008D969D /* Spc_Emu.h in Headers */, 17C8F2500CBED286008D969D /* Spc_Emu.h in Headers */,
83489CC12783015300BDCEA2 /* Sms_Oscs.h in Headers */, 83489CC12783015300BDCEA2 /* Sms_Oscs.h in Headers */,
83489CE12783CAC100BDCEA2 /* 2413tone.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -656,6 +664,9 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
83BDCDD02E41A269003FC007 /* LICENSE in Resources */,
83BDCDD12E41A269003FC007 /* README.md in Resources */,
83BDCDD22E41A269003FC007 /* emu2413_NESpatches.txt in Resources */,
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */, 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -672,14 +683,14 @@
17C8F1F80CBED286008D969D /* Ay_Emu.cpp in Sources */, 17C8F1F80CBED286008D969D /* Ay_Emu.cpp in Sources */,
17C8F1FE0CBED286008D969D /* Blip_Buffer.cpp in Sources */, 17C8F1FE0CBED286008D969D /* Blip_Buffer.cpp in Sources */,
17C8F2000CBED286008D969D /* Classic_Emu.cpp in Sources */, 17C8F2000CBED286008D969D /* Classic_Emu.cpp in Sources */,
83489CEA2783CADC00BDCEA2 /* panning.c in Sources */,
8370B7AF17F615FE001A4D7A /* Spc_Sfm.cpp in Sources */, 8370B7AF17F615FE001A4D7A /* Spc_Sfm.cpp in Sources */,
17C8F2020CBED286008D969D /* Data_Reader.cpp in Sources */, 17C8F2020CBED286008D969D /* Data_Reader.cpp in Sources */,
83FC5D78181B47FB00B917E5 /* smp.cpp in Sources */, 83FC5D78181B47FB00B917E5 /* smp.cpp in Sources */,
17C8F2040CBED286008D969D /* Dual_Resampler.cpp in Sources */, 17C8F2040CBED286008D969D /* Dual_Resampler.cpp in Sources */,
17C8F2060CBED286008D969D /* Effects_Buffer.cpp in Sources */, 17C8F2060CBED286008D969D /* Effects_Buffer.cpp in Sources */,
17C8F2080CBED286008D969D /* Fir_Resampler.cpp in Sources */, 17C8F2080CBED286008D969D /* Fir_Resampler.cpp in Sources */,
83489CE52783CAC100BDCEA2 /* emu2413.c in Sources */, 83BDCDD92E41A269003FC007 /* emu2413.c in Sources */,
83BDCDDA2E41A269003FC007 /* panning.c in Sources */,
17C8F20A0CBED286008D969D /* Gb_Apu.cpp in Sources */, 17C8F20A0CBED286008D969D /* Gb_Apu.cpp in Sources */,
17C8F20D0CBED286008D969D /* Gb_Cpu.cpp in Sources */, 17C8F20D0CBED286008D969D /* Gb_Cpu.cpp in Sources */,
17C8F20F0CBED286008D969D /* Gb_Oscs.cpp in Sources */, 17C8F20F0CBED286008D969D /* Gb_Oscs.cpp in Sources */,
@ -756,6 +767,7 @@
HAVE_STDINT_H, HAVE_STDINT_H,
"DEBUG=1", "DEBUG=1",
"VGM_YM2612_NUKED=1", "VGM_YM2612_NUKED=1",
"BLARGG_LITTLE_ENDIAN=1",
); );
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks"; INSTALL_PATH = "@loader_path/../Frameworks";
@ -789,6 +801,7 @@
HAVE_STDINT_H, HAVE_STDINT_H,
NDEBUG, NDEBUG,
"VGM_YM2612_NUKED=1", "VGM_YM2612_NUKED=1",
"BLARGG_LITTLE_ENDIAN=1",
); );
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "@loader_path/../Frameworks"; INSTALL_PATH = "@loader_path/../Frameworks";

View file

@ -1,62 +0,0 @@
#ifndef __MAMEDEF_H__
#define __MAMEDEF_H__
// typedefs to use MAME's (U)INTxx types (copied from MAME\src\ods\odscomm.h)
/* 8-bit values */
typedef unsigned char UINT8;
typedef signed char INT8;
/* 16-bit values */
typedef unsigned short UINT16;
typedef signed short INT16;
/* 32-bit values */
#ifndef _WINDOWS_H
typedef unsigned int UINT32;
typedef signed int INT32;
#endif
/* 64-bit values */
#ifndef _WINDOWS_H
#ifdef _MSC_VER
typedef signed __int64 INT64;
typedef unsigned __int64 UINT64;
#else
__extension__ typedef unsigned long long UINT64;
__extension__ typedef signed long long INT64;
#endif
#endif
/* offsets and addresses are 32-bit (for now...) */
typedef UINT32 offs_t;
/* stream_sample_t is used to represent a single sample in a sound stream */
typedef INT32 stream_sample_t;
#ifdef VGM_BIG_ENDIAN
#define BYTE_XOR_BE(x) (x)
#else
#define BYTE_XOR_BE(x) ((x) ^ 0x01)
#endif
#if defined(_MSC_VER)
//#define INLINE static __forceinline
#define INLINE static __inline
#elif defined(__GNUC__)
#define INLINE static __inline__
#else
#define INLINE static inline
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef _DEBUG
#define logerror printf
#else
#define logerror
#endif
typedef void (*SRATE_CALLBACK)(void*, UINT32);
#endif // __MAMEDEF_H__

View file

@ -22,9 +22,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// Tones above this frequency are treated as disabled tone at half volume. // Tones above this frequency are treated as disabled tone at half volume.
// Power of two is more efficient (avoids division). // Power of two is more efficient (avoids division).
unsigned const inaudible_freq = 16384; static unsigned const inaudible_freq = 16384;
int const period_factor = 16; static int const period_factor = 16;
static byte const amp_table [16] = static byte const amp_table [16] =
{ {
@ -158,8 +158,8 @@ void Ay_Apu::write_data_( int addr, int data )
// TODO: same as above for envelope timer, and it also has a divide by two after it // TODO: same as above for envelope timer, and it also has a divide by two after it
} }
int const noise_off = 0x08; static int const noise_off = 0x08;
int const tone_off = 0x01; static int const tone_off = 0x01;
void Ay_Apu::run_until( blip_time_t final_end_time ) void Ay_Apu::run_until( blip_time_t final_end_time )
{ {
@ -171,7 +171,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
if ( !noise_period ) if ( !noise_period )
noise_period = noise_period_factor; noise_period = noise_period_factor;
blip_time_t const old_noise_delay = noise.delay; blip_time_t const old_noise_delay = noise.delay;
blargg_ulong const old_noise_lfsr = noise.lfsr; uint32_t const old_noise_lfsr = noise.lfsr;
// envelope period // envelope period
blip_time_t const env_period_factor = period_factor * 2; // verified blip_time_t const env_period_factor = period_factor * 2; // verified
@ -195,7 +195,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
// period // period
int half_vol = 0; int half_vol = 0;
blip_time_t inaudible_period = (blargg_ulong) (osc_output->clock_rate() + blip_time_t inaudible_period = (uint32_t) (osc_output->clock_rate() +
inaudible_freq) / (inaudible_freq * 2); inaudible_freq) / (inaudible_freq * 2);
if ( osc->period <= inaudible_period && !(osc_mode & tone_off) ) if ( osc->period <= inaudible_period && !(osc_mode & tone_off) )
{ {
@ -237,14 +237,14 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
blip_time_t time = start_time + osc->delay; blip_time_t time = start_time + osc->delay;
if ( osc_mode & tone_off ) // maintain tone's phase when off if ( osc_mode & tone_off ) // maintain tone's phase when off
{ {
blargg_long count = (final_end_time - time + period - 1) / period; int32_t count = (final_end_time - time + period - 1) / period;
time += count * period; time += count * period;
osc->phase ^= count & 1; osc->phase ^= count & 1;
} }
// noise time // noise time
blip_time_t ntime = final_end_time; blip_time_t ntime = final_end_time;
blargg_ulong noise_lfsr = 1; uint32_t noise_lfsr = 1;
if ( !(osc_mode & noise_off) ) if ( !(osc_mode & noise_off) )
{ {
ntime = start_time + old_noise_delay; ntime = start_time + old_noise_delay;
@ -299,7 +299,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
while ( ntime <= end ) // must advance *past* time to avoid hang while ( ntime <= end ) // must advance *past* time to avoid hang
{ {
int changed = noise_lfsr + 1; int changed = noise_lfsr + 1;
noise_lfsr = (-(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1); noise_lfsr = (uMinus(noise_lfsr & 1) & 0x12000) ^ (noise_lfsr >> 1);
if ( changed & 2 ) if ( changed & 2 )
{ {
delta = -delta; delta = -delta;
@ -311,8 +311,8 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
else else
{ {
// 20 or more noise periods on average for some music // 20 or more noise periods on average for some music
blargg_long remain = end - ntime; int32_t remain = end - ntime;
blargg_long count = remain / noise_period; int32_t count = remain / noise_period;
if ( remain >= 0 ) if ( remain >= 0 )
ntime += noise_period + count * noise_period; ntime += noise_period + count * noise_period;
} }
@ -380,7 +380,7 @@ void Ay_Apu::run_until( blip_time_t final_end_time )
blip_time_t remain = final_end_time - last_time - env.delay; blip_time_t remain = final_end_time - last_time - env.delay;
if ( remain >= 0 ) if ( remain >= 0 )
{ {
blargg_long count = (remain + env_period) / env_period; int32_t count = (remain + env_period) / env_period;
env.pos += count; env.pos += count;
if ( env.pos >= 0 ) if ( env.pos >= 0 )
env.pos = (env.pos & 31) - 32; env.pos = (env.pos & 31) - 32;

View file

@ -16,7 +16,7 @@ public:
void reset(); void reset();
// Write to register at specified time // Write to register at specified time
enum { reg_count = 16 }; static const unsigned int reg_count = 16;
void write( blip_time_t time, int addr, int data ); void write( blip_time_t time, int addr, int data );
// Run sound to specified time, end current time frame, then start a new // Run sound to specified time, end current time frame, then start a new
@ -28,7 +28,7 @@ public:
// Set sound output of specific oscillator to buffer, where index is // Set sound output of specific oscillator to buffer, where index is
// 0, 1, or 2. If buffer is NULL, the specified oscillator is muted. // 0, 1, or 2. If buffer is NULL, the specified oscillator is muted.
enum { osc_count = 3 }; static const int osc_count = 3;
void osc_output( int index, Blip_Buffer* ); void osc_output( int index, Blip_Buffer* );
// Set overall volume (default is 1.0) // Set overall volume (default is 1.0)
@ -54,7 +54,7 @@ private:
struct { struct {
blip_time_t delay; blip_time_t delay;
blargg_ulong lfsr; uint32_t lfsr;
} noise; } noise;
struct { struct {
@ -67,7 +67,7 @@ private:
void run_until( blip_time_t ); void run_until( blip_time_t );
void write_data_( int addr, int data ); void write_data_( int addr, int data );
public: public:
enum { amp_range = 255 }; static const int amp_range = 255;
Blip_Synth<blip_good_quality,1> synth_; Blip_Synth<blip_good_quality,1> synth_;
}; };

View file

@ -38,15 +38,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
// flags, named with hex value for clarity // flags, named with hex value for clarity
int const S80 = 0x80; enum {
int const Z40 = 0x40; S80 = 0x80,
int const F20 = 0x20; Z40 = 0x40,
int const H10 = 0x10; F20 = 0x20,
int const F08 = 0x08; H10 = 0x10,
int const V04 = 0x04; F08 = 0x08,
int const P04 = 0x04; V04 = 0x04,
int const N02 = 0x02; P04 = 0x04,
int const C01 = 0x01; N02 = 0x02,
C01 = 0x01
};
#define SZ28P( n ) szpc [n] #define SZ28P( n ) szpc [n]
#define SZ28PC( n ) szpc [n] #define SZ28PC( n ) szpc [n]
@ -460,7 +462,7 @@ possibly_out_of_time:
case 0x29: // ADD HL,HL case 0x29: // ADD HL,HL
data = R16( opcode, 4, 0x09 ); data = R16( opcode, 4, 0x09 );
add_hl_data: { add_hl_data: {
blargg_ulong sum = rp.hl + data; uint32_t sum = rp.hl + data;
data ^= rp.hl; data ^= rp.hl;
rp.hl = sum; rp.hl = sum;
flags = (flags & (S80 | Z40 | V04)) | flags = (flags & (S80 | Z40 | V04)) |
@ -708,7 +710,7 @@ possibly_out_of_time:
} }
case 0x17:{// RLA case 0x17:{// RLA
blargg_ulong temp = (rg.a << 1) | (flags & C01); uint32_t temp = (rg.a << 1) | (flags & C01);
flags = (flags & (S80 | Z40 | P04)) | flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) | (temp & (F20 | F08)) |
(temp >> 8); (temp >> 8);
@ -1026,7 +1028,7 @@ possibly_out_of_time:
switch ( data ) switch ( data )
{ {
{ {
blargg_ulong temp; uint32_t temp;
case 0x72: // SBC HL,SP case 0x72: // SBC HL,SP
case 0x7A: // ADC HL,SP case 0x7A: // ADC HL,SP
temp = sp; temp = sp;
@ -1038,10 +1040,10 @@ possibly_out_of_time:
case 0x5A: // ADC HL,DE case 0x5A: // ADC HL,DE
case 0x6A: // ADC HL,HL case 0x6A: // ADC HL,HL
temp = R16( data >> 3 & 6, 1, 0 ); temp = R16( data >> 3 & 6, 1, 0 );
blargg_ulong sum = temp + (flags & C01); uint32_t sum = temp + (flags & C01);
flags = ~data >> 2 & N02; flags = ~data >> 2 & N02;
if ( flags ) if ( flags )
sum = -sum; sum = uMinus(sum);
sum += rp.hl; sum += rp.hl;
temp ^= rp.hl; temp ^= rp.hl;
temp ^= sum; temp ^= sum;
@ -1349,7 +1351,7 @@ possibly_out_of_time:
case 0x19: // ADD IXY,DE case 0x19: // ADD IXY,DE
temp = R16( data, 4, 0x09 ); temp = R16( data, 4, 0x09 );
add_ixy_data: { add_ixy_data: {
blargg_ulong sum = ixy + temp; uint32_t sum = ixy + temp;
temp ^= ixy; temp ^= ixy;
ixy = (uint16_t) sum; ixy = (uint16_t) sum;
flags = (flags & (S80 | Z40 | V04)) | flags = (flags & (S80 | Z40 | V04)) |

View file

@ -6,7 +6,7 @@
#include "blargg_endian.h" #include "blargg_endian.h"
typedef blargg_long cpu_time_t; typedef int32_t cpu_time_t;
// must be defined by caller // must be defined by caller
void ay_cpu_out( class Ay_Cpu*, cpu_time_t, unsigned addr, int data ); void ay_cpu_out( class Ay_Cpu*, cpu_time_t, unsigned addr, int data );

View file

@ -20,11 +20,11 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
long const spectrum_clock = 3546900; static long const spectrum_clock = 3546900;
long const cpc_clock = 2000000; static long const cpc_clock = 2000000;
unsigned const ram_start = 0x4000; static unsigned const ram_start = 0x4000;
int const osc_count = Ay_Apu::osc_count + 1; static int const osc_count = Ay_Apu::osc_count + 1;
using std::min; using std::min;
using std::max; using std::max;
@ -56,7 +56,7 @@ static byte const* get_data( Ay_Emu::file_t const& file, byte const* ptr, int mi
long file_size = file.end - (byte const*) file.header; long file_size = file.end - (byte const*) file.header;
assert( (unsigned long) pos <= (unsigned long) file_size - 2 ); assert( (unsigned long) pos <= (unsigned long) file_size - 2 );
int offset = (int16_t) get_be16( ptr ); int offset = (int16_t) get_be16( ptr );
if ( !offset || blargg_ulong (pos + offset) > blargg_ulong (file_size - min_size) ) if ( !offset || uint32_t (pos + offset) > uint32_t (file_size - min_size) )
return 0; return 0;
return ptr + offset; return ptr + offset;
} }
@ -128,7 +128,7 @@ extern gme_type_t const gme_ay_type = &gme_ay_type_;
blargg_err_t Ay_Emu::load_mem_( byte const* in, long size ) blargg_err_t Ay_Emu::load_mem_( byte const* in, long size )
{ {
assert( offsetof (header_t,track_info [2]) == header_size ); blaarg_static_assert( offsetof (header_t,track_info [2]) == header_size, "AY Header layout incorrect!" );
RETURN_ERR( parse_header( in, size, &file ) ); RETURN_ERR( parse_header( in, size, &file ) );
set_track_count( file.header->max_track + 1 ); set_track_count( file.header->max_track + 1 );
@ -209,7 +209,7 @@ blargg_err_t Ay_Emu::start_track_( int track )
} }
check( len ); check( len );
byte const* in = get_data( file, blocks, 0 ); blocks += 2; byte const* in = get_data( file, blocks, 0 ); blocks += 2;
if ( len > blargg_ulong (file.end - in) ) if ( len > uint32_t (file.end - in) )
{ {
set_warning( "Missing file data" ); set_warning( "Missing file data" );
len = file.end - in; len = file.end - in;

View file

@ -23,7 +23,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include BLARGG_ENABLE_OPTIMIZER #include BLARGG_ENABLE_OPTIMIZER
#endif #endif
int const silent_buf_size = 1; // size used for Silent_Blip_Buffer static int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
Blip_Buffer::Blip_Buffer() Blip_Buffer::Blip_Buffer()
{ {
@ -144,7 +144,6 @@ void Blip_Buffer::bass_freq( int freq )
void Blip_Buffer::end_frame( blip_time_t t ) void Blip_Buffer::end_frame( blip_time_t t )
{ {
offset_ += t * factor_; offset_ += t * factor_;
assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
} }
void Blip_Buffer::remove_silence( long count ) void Blip_Buffer::remove_silence( long count )

View file

@ -1,6 +1,7 @@
// Band-limited sound synthesis buffer // Band-limited sound synthesis buffer
// Blip_Buffer 0.4.1 // Blip_Buffer 0.4.1
#ifndef BLIP_BUFFER_H #ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H #define BLIP_BUFFER_H
@ -120,9 +121,7 @@ private:
friend class Blip_Reader; friend class Blip_Reader;
}; };
#ifdef HAVE_CONFIG_H #include "blargg_config.h"
#include "config.h"
#endif
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio // Number of bits in resample ratio fraction. Higher values give a more accurate ratio
// but reduce maximum buffer size. // but reduce maximum buffer size.
@ -233,9 +232,9 @@ public:
#endif #endif
// disable broken defaulted constructors, Blip_Synth_ isn't safe to move/copy // disable broken defaulted constructors, Blip_Synth_ isn't safe to move/copy
Blip_Synth<quality, range> (const Blip_Synth<quality, range> &) = delete; Blip_Synth (const Blip_Synth &) = delete;
Blip_Synth<quality, range> ( Blip_Synth<quality, range> &&) = delete; Blip_Synth ( Blip_Synth &&) = delete;
Blip_Synth<quality, range>& operator=(const Blip_Synth<quality, range> &) = delete; Blip_Synth& operator=(const Blip_Synth &) = delete;
}; };
// Low-pass equalization parameters // Low-pass equalization parameters
@ -272,11 +271,12 @@ public:
Silent_Blip_Buffer(); Silent_Blip_Buffer();
}; };
#if defined (__GNUC__) || _MSC_VER >= 1100 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || \
#define BLIP_RESTRICT __restrict (defined(_MSC_VER) && (_MSC_VER >= 1100))
#else #define BLIP_RESTRICT __restrict
#define BLIP_RESTRICT #else
#endif #define BLIP_RESTRICT
#endif
// Optimized reading from Blip_Buffer, for use in custom sample output // Optimized reading from Blip_Buffer, for use in custom sample output
@ -474,7 +474,11 @@ 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 ) { } treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
inline int Blip_Buffer::length() const { return length_; } 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::samples_avail() const
{
long samples = (long) (offset_ >> BLIP_BUFFER_ACCURACY);
return samples <= (long) buffer_size_ ? samples : 0;
}
inline long Blip_Buffer::sample_rate() const { return sample_rate_; } inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
inline long Blip_Buffer::clock_rate() const { return clock_rate_; } inline long Blip_Buffer::clock_rate() const { return clock_rate_; }

View file

@ -1,120 +1,178 @@
if(NOT GME_BUILD_SHARED AND NOT GME_BUILD_STATIC)
message(FATAL_ERROR "Both shared and static builds disabled. Please enable build of shared and/or static build of the GME.")
endif()
if(GME_ZLIB)
find_package(ZLIB QUIET)
endif()
# List of source files required by libgme and any emulators # List of source files required by libgme and any emulators
# This is not 100% accurate (Fir_Resampler for instance) but # This is not 100% accurate (Fir_Resampler for instance) but
# you'll be OK. # you'll be OK.
set(libgme_SRCS Blip_Buffer.cpp set(libgme_SRCS Blip_Buffer.cpp
Blip_Buffer.h
Classic_Emu.cpp Classic_Emu.cpp
Classic_Emu.h
Data_Reader.cpp Data_Reader.cpp
Data_Reader.h
Dual_Resampler.cpp Dual_Resampler.cpp
Dual_Resampler.h
Effects_Buffer.cpp Effects_Buffer.cpp
Effects_Buffer.h
Fir_Resampler.cpp Fir_Resampler.cpp
Fir_Resampler.h
gme.cpp gme.cpp
gme.h
gme_types.h
Gme_File.cpp Gme_File.cpp
Gme_File.h
M3u_Playlist.cpp M3u_Playlist.cpp
M3u_Playlist.h
Multi_Buffer.cpp Multi_Buffer.cpp
Multi_Buffer.h
Music_Emu.cpp Music_Emu.cpp
Music_Emu.h
blargg_common.h
blargg_config.h
blargg_endian.h
blargg_source.h
) )
find_package(ZLIB QUIET)
# Ay_Apu is very popular around here # Ay_Apu is very popular around here
if (USE_GME_AY OR USE_GME_KSS) if(USE_GME_AY OR USE_GME_KSS)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Ay_Apu.cpp Ay_Apu.cpp
Ay_Apu.h
) )
endif() endif()
# so is Ym2612_Emu # so is Ym2612_Emu
if (USE_GME_VGM OR USE_GME_GYM) if(USE_GME_VGM OR USE_GME_GYM)
if(GME_YM2612_EMU STREQUAL "Nuked") if(GME_YM2612_EMU STREQUAL "Nuked")
add_definitions(-DVGM_YM2612_NUKED) add_definitions(-DVGM_YM2612_NUKED)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Ym2612_Nuked.cpp Ym2612_Nuked.cpp
Ym2612_Nuked.h
) )
message("VGM/GYM: Nuked OPN2 emulator will be used") message(STATUS "VGM/GYM: Nuked OPN2 emulator will be used")
elseif(GME_YM2612_EMU STREQUAL "MAME") elseif(GME_YM2612_EMU STREQUAL "MAME")
add_definitions(-DVGM_YM2612_MAME) add_definitions(-DVGM_YM2612_MAME)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Ym2612_MAME.cpp Ym2612_MAME.cpp
Ym2612_MAME.h
) )
message("VGM/GYM: MAME YM2612 emulator will be used") message(STATUS "VGM/GYM: MAME YM2612 emulator will be used")
else() else()
add_definitions(-DVGM_YM2612_GENS) add_definitions(-DVGM_YM2612_GENS)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Ym2612_GENS.cpp Ym2612_GENS.cpp
Ym2612_GENS.h
) )
message("VGM/GYM: GENS 2.10 emulator will be used") message(STATUS "VGM/GYM: GENS 2.10 emulator will be used")
endif() endif()
endif() endif()
# But none are as popular as Sms_Apu # But none are as popular as Sms_Apu
if (USE_GME_VGM OR USE_GME_GYM OR USE_GME_KSS) if(USE_GME_VGM OR USE_GME_GYM OR USE_GME_KSS)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Sms_Apu.cpp Sms_Apu.cpp
Sms_Apu.h
) )
endif() endif()
if (USE_GME_AY) if(USE_GME_AY)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
# Ay_Apu.cpp included earlier # Ay_Apu.cpp included earlier
Ay_Cpu.cpp Ay_Cpu.cpp
Ay_Cpu.h
Ay_Emu.cpp Ay_Emu.cpp
Ay_Emu.h
) )
endif() endif()
if (USE_GME_GBS) if(USE_GME_GBS)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Gb_Apu.cpp Gb_Apu.cpp
Gb_Apu.h
Gb_Cpu.cpp Gb_Cpu.cpp
Gb_Cpu.h
Gb_Oscs.cpp Gb_Oscs.cpp
Gb_Oscs.h
Gbs_Emu.cpp Gbs_Emu.cpp
Gbs_Emu.h
gb_cpu_io.h
) )
endif() endif()
if (USE_GME_GYM) if(USE_GME_GYM)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
# Sms_Apu.cpp included earlier # Sms_Apu.cpp included earlier
# Ym2612_Emu.cpp included earlier # Ym2612_Emu.cpp included earlier
Gym_Emu.cpp Gym_Emu.cpp
Gym_Emu.h
) )
endif() endif()
if (USE_GME_HES) if(USE_GME_HES)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Hes_Apu.cpp Hes_Apu.cpp
Hes_Apu.h
Hes_Cpu.cpp Hes_Cpu.cpp
Hes_Cpu.h
Hes_Emu.cpp Hes_Emu.cpp
Hes_Emu.h
hes_cpu_io.h
) )
endif() endif()
if (USE_GME_KSS) if(USE_GME_KSS)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
# Ay_Apu.cpp included earlier # Ay_Apu.cpp included earlier
# Sms_Apu.cpp included earlier # Sms_Apu.cpp included earlier
Kss_Cpu.cpp Kss_Cpu.cpp
Kss_Cpu.h
Kss_Emu.cpp Kss_Emu.cpp
Kss_Emu.h
Kss_Scc_Apu.cpp Kss_Scc_Apu.cpp
Kss_Scc_Apu.h
) )
endif() endif()
if (USE_GME_NSF OR USE_GME_NSFE) if(USE_GME_NSF OR USE_GME_NSFE)
set(libgme_SRCS ${libgme_SRCS} list(APPEND libgme_SRCS
Nes_Apu.cpp Nes_Apu.cpp
Nes_Apu.h
Nes_Cpu.cpp Nes_Cpu.cpp
Nes_Cpu.h
Nes_Fme7_Apu.cpp Nes_Fme7_Apu.cpp
Nes_Fme7_Apu.h
Nes_Namco_Apu.cpp Nes_Namco_Apu.cpp
Nes_Namco_Apu.h
Nes_Oscs.cpp Nes_Oscs.cpp
Nes_Oscs.h
Nes_Vrc6_Apu.cpp Nes_Vrc6_Apu.cpp
Nes_Vrc6_Apu.h
Nes_Fds_Apu.cpp Nes_Fds_Apu.cpp
Nes_Fds_Apu.h
Nes_Vrc7_Apu.cpp Nes_Vrc7_Apu.cpp
../ext/emu2413.c Nes_Vrc7_Apu.h
../ext/panning.c ext/emu2413.c
ext/emu2413.h
ext/panning.c
ext/panning.h
ext/emutypes.h
ext/2413tone.h
ext/vrc7tone.h
Nsf_Emu.cpp Nsf_Emu.cpp
Nsf_Emu.h
) )
endif() endif()
if (USE_GME_NSFE) if (USE_GME_NSFE)
set(libgme_SRCS ${libgme_SRCS} set(libgme_SRCS ${libgme_SRCS}
Nsfe_Emu.cpp Nsfe_Emu.cpp
Nsfe_Emu.h
) )
endif() endif()
@ -123,6 +181,7 @@ if (USE_GME_SAP)
Sap_Apu.cpp Sap_Apu.cpp
Sap_Cpu.cpp Sap_Cpu.cpp
Sap_Emu.cpp Sap_Emu.cpp
sap_cpu_io.h
) )
endif() endif()
@ -135,12 +194,19 @@ if (USE_GME_SPC)
../higan/dsp/dsp.cpp ../higan/dsp/dsp.cpp
../higan/dsp/SPC_DSP.cpp ../higan/dsp/SPC_DSP.cpp
Snes_Spc.cpp Snes_Spc.cpp
Snes_Spc.h
Spc_Cpu.cpp Spc_Cpu.cpp
Spc_Cpu.h
Spc_Dsp.cpp Spc_Dsp.cpp
Spc_Dsp.h
Spc_Emu.cpp Spc_Emu.cpp
Spc_Emu.h
Spc_Filter.cpp Spc_Filter.cpp
Spc_Filter.h
Bml_Parser.cpp Bml_Parser.cpp
Bml_Parser.h
Spc_Sfm.cpp Spc_Sfm.cpp
Spc_Sfm.h
) )
if (GME_SPC_ISOLATED_ECHO_BUFFER) if (GME_SPC_ISOLATED_ECHO_BUFFER)
add_definitions(-DSPC_ISOLATED_ECHO_BUFFER) add_definitions(-DSPC_ISOLATED_ECHO_BUFFER)
@ -152,88 +218,265 @@ if (USE_GME_VGM)
# Sms_Apu.cpp included earlier # Sms_Apu.cpp included earlier
# Ym2612_Emu.cpp included earlier # Ym2612_Emu.cpp included earlier
Vgm_Emu.cpp Vgm_Emu.cpp
Vgm_Emu.h
Vgm_Emu_Impl.cpp Vgm_Emu_Impl.cpp
Vgm_Emu_Impl.h
Ym2413_Emu.cpp Ym2413_Emu.cpp
Ym2413_Emu.h
) )
endif() endif()
# These headers are part of the generic gme interface. # These headers are part of the generic gme interface.
set (EXPORTED_HEADERS gme.h blargg_source.h) set (EXPORTED_HEADERS gme.h)
# while building a macOS framework, exported headers must be in the source # while building a macOS framework, exported headers must be in the source
# list, or the header files aren't copied to the bundle. # list, or the header files aren't copied to the bundle.
if (BUILD_FRAMEWORK) if(GME_BUILD_FRAMEWORK)
set(libgme_SRCS ${libgme_SRCS} ${EXPORTED_HEADERS}) set(libgme_SRCS ${libgme_SRCS} ${EXPORTED_HEADERS})
endif() endif()
# On some platforms we may need to change headers or whatnot based on whether # Extract symbols from gme.exports
# we're building the library or merely using the library. The following is file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/gme.exports" gme_exports_strings)
# only defined when building the library to allow us to tell which is which. set(gme_exports)
add_definitions(-DBLARGG_BUILD_DLL) foreach(gme_export_string ${gme_exports_strings})
string(STRIP "${gme_export_string}" gme_export_string)
string(SUBSTRING "${gme_export_string}" 0 1 gme_export_first_char)
if(gme_export_string AND NOT gme_export_first_char STREQUAL "#")
list(APPEND gme_exports ${gme_export_string})
endif()
endforeach()
# For the gme_types.h
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Add library to be compiled. add_library(gme_deps INTERFACE)
add_library(gme ${libgme_SRCS})
if(ZLIB_FOUND) ## FIXME: Properly find the C++ library !!!
message(" ** ZLib library located, compressed file formats will be supported") set(PC_LIBS -lstdc++)
target_compile_definitions(gme PRIVATE -DHAVE_ZLIB_H)
target_include_directories(gme PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(gme ${ZLIB_LIBRARIES})
# Is not to be installed though
set(PKG_CONFIG_ZLIB -lz) # evaluated in libgme.pc.in if(GME_ZLIB)
if(ZLIB_FOUND)
message(STATUS "ZLib library located, compressed file formats will be supported")
target_compile_definitions(gme_deps INTERFACE HAVE_ZLIB_H)
target_link_libraries(gme_deps INTERFACE ZLIB::ZLIB)
# Is not to be installed though
list(APPEND PC_LIBS -lz) # for libgme.pc
else()
message(STATUS "** ZLib library not found, disabling support for compressed formats such as VGZ")
endif()
else() else()
message("ZLib library not found, disabling support for compressed formats such as VGZ") message(STATUS "Zlib-Compressed formats excluded")
endif() endif()
if(USE_GME_SPC) if(NOT MSVC)
if(UNRAR_FOUND) # Link with -no-undefined, if available
message(" ** unRAR library located, the RSN file format will be supported") if(NOT APPLE AND NOT CMAKE_SYSTEM_NAME MATCHES ".*OpenBSD.*")
target_compile_definitions(gme PRIVATE -DRARDLL) cmake_push_check_state()
target_include_directories(gme PRIVATE ${UNRAR_INCLUDE_DIRS}) set(CMAKE_REQUIRED_FLAGS "-Wl,-no-undefined")
target_link_libraries(gme ${UNRAR_LIBRARIES}) check_cxx_source_compiles("int main(void) { return 0;}" LINKER_SUPPORTS_NO_UNDEFINED)
# Is not to be installed though cmake_pop_check_state()
endif()
set(PKG_CONFIG_UNRAR -lunrar) # evaluated in libgme.pc.in # Link to libm, if necessary
else() check_cxx_source_compiles("
message("unRAR library not found, disabling support for the RSN file format") #include <math.h>
int main(int argc, char** argv) {
return (int) pow(argc, 2.5);
}" LIBM_NOT_NEEDED)
if(NOT LIBM_NOT_NEEDED)
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES "-lm")
check_cxx_source_compiles("
#include <math.h>
int main(int argc, char** argv) {
return (int) pow(argc, 2.5);
}" HAVE_LIBM)
cmake_pop_check_state()
if(HAVE_LIBM)
list(APPEND PC_LIBS -lm) # for libgme.pc
endif()
endif() endif()
endif() endif()
# The version is the release. The "soversion" is the API version. As long
# as only build fixes are performed (i.e. no backwards-incompatible changes
# to the API), the SOVERSION should be the same even when bumping up VERSION.
# The way gme.h is designed, SOVERSION should very rarely be bumped, if ever.
# Hopefully the API can stay compatible with old versions.
set_target_properties(gme
PROPERTIES VERSION ${GME_VERSION}
SOVERSION 1)
# macOS framework build # Add a version script to hide the c++ STL
if(BUILD_FRAMEWORK) if(APPLE)
set_target_properties(gme set(gme_syms "")
PROPERTIES FRAMEWORK TRUE foreach(gme_export ${gme_exports})
FRAMEWORK_VERSION A set(gme_syms "${gme_syms}_${gme_export}\n")
MACOSX_FRAMEWORK_IDENTIFIER net.mpyne.gme endforeach()
VERSION ${GME_VERSION}
SOVERSION 0 # Use an intermediate 'gme_generated.sym' file to avoid a relink every time CMake runs
PUBLIC_HEADER "${EXPORTED_HEADERS}") set(temporary_sym_file "${CMAKE_CURRENT_BINARY_DIR}/gme_generated.sym")
set(generated_sym_file "${CMAKE_CURRENT_BINARY_DIR}/gme.sym")
file(WRITE "${temporary_sym_file}" "${gme_syms}")
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${temporary_sym_file}" "${generated_sym_file}")
elseif(UNIX)
set(gme_syms "{\n global:\n")
foreach(gme_export ${gme_exports})
set(gme_syms "${gme_syms} ${gme_export};\n")
endforeach()
set(gme_syms "${gme_syms} local: *;\n};\n")
# Use an intermediate 'gme_generated.sym' file to avoid a relink every time CMake runs
set(temporary_sym_file "${CMAKE_CURRENT_BINARY_DIR}/gme_generated.sym")
set(generated_sym_file "${CMAKE_CURRENT_BINARY_DIR}/gme.sym")
file(WRITE "${temporary_sym_file}" "${gme_syms}")
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${temporary_sym_file}" "${generated_sym_file}")
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Wl,-version-script='${generated_sym_file}'")
check_cxx_source_compiles("int main() { return 0;}" LINKER_SUPPORTS_VERSION_SCRIPT)
cmake_pop_check_state()
endif() endif()
install(TARGETS gme LIBRARY DESTINATION lib${LIB_SUFFIX}
RUNTIME DESTINATION bin # DLL platforms set(INSTALL_TARGETS)
ARCHIVE DESTINATION lib # DLL platforms
FRAMEWORK DESTINATION /Library/Frameworks) # macOS framework # Shared properties for shared and static builds of libGME
macro(set_gme_props gme_target)
list(APPEND INSTALL_TARGETS ${gme_target})
set_property(TARGET ${gme_target} PROPERTY C_VISIBILITY_PRESET "hidden")
set_property(TARGET ${gme_target} PROPERTY VISIBILITY_INLINES_HIDDEN TRUE)
set_property(TARGET ${gme_target} PROPERTY CXX_VISIBILITY_PRESET "hidden")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_definitions(${gme_target} PRIVATE LIBGME_VISIBILITY)
endif()
target_compile_definitions(${gme_target} PRIVATE GEN_TYPES_H)
if(WORDS_BIGENDIAN)
target_compile_definitions(${gme_target} PRIVATE BLARGG_BIG_ENDIAN=1)
else()
target_compile_definitions(${gme_target} PRIVATE BLARGG_LITTLE_ENDIAN=1)
endif()
# Try to protect against undefined behavior from signed integer overflow
# This has caused miscompilation of code already and there are other
# potential uses; see https://bitbucket.org/mpyne/game-music-emu/issues/18/
# (https://github.com/libgme/game-music-emu/issues/20 )
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(${gme_target} PRIVATE -fwrapv)
endif()
target_include_directories(${gme_target}
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>" # For gen_types.h
INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>"
INTERFACE "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
if(NOT MSVC)
# Link with -no-undefined, if available
if(APPLE)
set_property(TARGET ${gme_target} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-undefined,error")
elseif(NOT CMAKE_SYSTEM_NAME MATCHES ".*OpenBSD.*" AND LINKER_SUPPORTS_NO_UNDEFINED)
set_property(TARGET ${gme_target} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-no-undefined")
endif()
endif()
endmacro()
# Building the Shared version of GME
if(GME_BUILD_SHARED)
add_library(gme_shared SHARED ${libgme_SRCS})
set_target_properties(gme_shared PROPERTIES OUTPUT_NAME gme)
if(WIN32)
set_property(TARGET gme_shared PROPERTY DEFINE_SYMBOL BLARGG_BUILD_DLL)
endif()
set_gme_props(gme_shared)
# Add a version script to hide the c++ STL
if(APPLE)
set_property(TARGET gme_shared APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-exported_symbols_list,'${generated_sym_file}'")
set_property(TARGET gme_shared APPEND PROPERTY LINK_DEPENDS "${generated_sym_file}")
elseif(UNIX AND LINKER_SUPPORTS_VERSION_SCRIPT)
set_property(TARGET gme_shared APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-version-script='${generated_sym_file}'")
set_property(TARGET gme_shared APPEND PROPERTY LINK_DEPENDS "${generated_sym_file}")
endif()
target_link_libraries(gme_shared PRIVATE gme_deps)
if(HAVE_LIBM)
target_link_libraries(gme_shared PRIVATE -lm)
endif()
# The version is the release. The "soversion" is the API version. As long
# as only build fixes are performed (i.e. no backwards-incompatible changes
# to the API), the SOVERSION should be the same even when bumping up VERSION.
# The way gme.h is designed, SOVERSION should very rarely be bumped, if ever.
# Hopefully the API can stay compatible with old versions.
set_target_properties(gme_shared PROPERTIES VERSION ${GME_VERSION} SOVERSION 0)
# macOS framework build
if(GME_BUILD_FRAMEWORK)
set_target_properties(gme_shared
PROPERTIES FRAMEWORK TRUE
FRAMEWORK_VERSION A
MACOSX_FRAMEWORK_IDENTIFIER net.mpyne.gme
VERSION ${GME_VERSION}
SOVERSION 0
PUBLIC_HEADER "${EXPORTED_HEADERS}")
endif()
endif()
# Building the Static version of GME
if(GME_BUILD_STATIC)
# Static build.
add_library(gme_static STATIC ${libgme_SRCS})
# Static builds need to find static zlib (and static forms of other needed
# libraries. Ensure CMake looks only for static libs if we're doing a static
# build. See https://stackoverflow.com/a/44738756
if(MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
if(MSVC AND GME_BUILD_SHARED)
set_target_properties(gme_static PROPERTIES OUTPUT_NAME gme-static)
else()
set_target_properties(gme_static PROPERTIES OUTPUT_NAME gme)
endif()
set_gme_props(gme_static)
target_link_libraries(gme_static PUBLIC gme_deps)
if(HAVE_LIBM)
target_link_libraries(gme_static PUBLIC -lm)
endif()
endif()
if(GME_BUILD_SHARED)
add_library(gme::gme ALIAS gme_shared)
else()
add_library(gme::gme ALIAS gme_static)
endif()
install(TARGETS ${INSTALL_TARGETS}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # DLL platforms
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # DLL platforms
FRAMEWORK DESTINATION /Library/Frameworks) # macOS framework
# Run during cmake phase, so this is available during make # Run during cmake phase, so this is available during make
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gme_types.h.in configure_file(gme_types.h.in gen_types.h @ONLY)
${CMAKE_CURRENT_BINARY_DIR}/gme_types.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libgme.pc.in set(TMP_PC_LIBS "")
${CMAKE_CURRENT_BINARY_DIR}/libgme.pc @ONLY) foreach(PC_LIB ${PC_LIBS})
if(NOT "${TMP_PC_LIBS}" STREQUAL "")
set(TMP_PC_LIBS "${TMP_PC_LIBS} ${PC_LIB}")
else()
set(TMP_PC_LIBS "${PC_LIB}")
endif()
endforeach()
set(PC_LIBS "${TMP_PC_LIBS}")
unset(TMP_PC_LIBS)
install(FILES ${EXPORTED_HEADERS} DESTINATION include/gme) configure_file(libgme.pc.in libgme.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
install(FILES ${EXPORTED_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gme)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

View file

@ -25,9 +25,9 @@ Classic_Emu::Classic_Emu()
voice_types = 0; voice_types = 0;
// avoid inconsistency in our duplicated constants // avoid inconsistency in our duplicated constants
assert( (int) wave_type == (int) Multi_Buffer::wave_type ); blaarg_static_assert( (int) wave_type == (int) Multi_Buffer::wave_type, "wave_type inconsistent across two classes using it" );
assert( (int) noise_type == (int) Multi_Buffer::noise_type ); blaarg_static_assert( (int) noise_type == (int) Multi_Buffer::noise_type, "noise_type inconsistent across two classes using it" );
assert( (int) mixed_type == (int) Multi_Buffer::mixed_type ); blaarg_static_assert( (int) mixed_type == (int) Multi_Buffer::mixed_type, "mixed_type inconsistent across two classes using it" );
} }
Classic_Emu::~Classic_Emu() Classic_Emu::~Classic_Emu()
@ -115,7 +115,7 @@ blargg_err_t Classic_Emu::play_( long count, sample_t* out )
remute_voices(); remute_voices();
} }
int msec = buf->length(); int msec = buf->length();
blip_time_t clocks_emulated = (blargg_long) msec * clock_rate_ / 1000; blip_time_t clocks_emulated = (int32_t) msec * clock_rate_ / 1000;
RETURN_ERR( run_clocks( clocks_emulated, msec ) ); RETURN_ERR( run_clocks( clocks_emulated, msec ) );
assert( clocks_emulated ); assert( clocks_emulated );
buf->end_frame( clocks_emulated ); buf->end_frame( clocks_emulated );
@ -182,9 +182,9 @@ void Rom_Data_::set_addr_( long addr, int unit )
if ( 0 ) if ( 0 )
{ {
debug_printf( "addr: %X\n", addr ); debug_printf( "addr: %X\n", (int)addr );
debug_printf( "file_size: %d\n", file_size_ ); debug_printf( "file_size: %ld\n", file_size_ );
debug_printf( "rounded: %d\n", rounded ); debug_printf( "rounded: %ld\n", rounded );
debug_printf( "mask: $%X\n", mask ); debug_printf( "mask: $%X\n", mask );
} }
} }

View file

@ -58,9 +58,9 @@ protected:
enum { pad_extra = 8 }; enum { pad_extra = 8 };
blargg_vector<byte> rom; blargg_vector<byte> rom;
long file_size_; long file_size_;
blargg_long rom_addr; int32_t rom_addr;
blargg_long mask; int32_t mask;
blargg_long size_; // TODO: eliminate int32_t size_; // TODO: eliminate
blargg_err_t load_rom_data_( Data_Reader& in, int header_size, void* header_out, blargg_err_t load_rom_data_( Data_Reader& in, int header_size, void* header_out,
int fill, long pad_size ); int fill, long pad_size );
@ -97,7 +97,7 @@ public:
byte* unmapped() { return rom.begin(); } byte* unmapped() { return rom.begin(); }
// Mask address to nearest power of two greater than size() // Mask address to nearest power of two greater than size()
blargg_long mask_addr( blargg_long addr ) const int32_t mask_addr( int32_t addr ) const
{ {
#ifdef check #ifdef check
check( addr <= mask ); check( addr <= mask );
@ -106,10 +106,10 @@ public:
} }
// Pointer to page starting at addr. Returns unmapped() if outside data. // Pointer to page starting at addr. Returns unmapped() if outside data.
byte* at_addr( blargg_long addr ) byte* at_addr( int32_t addr )
{ {
blargg_ulong offset = mask_addr( addr ) - rom_addr; uint32_t offset = mask_addr( addr ) - rom_addr;
if ( offset > blargg_ulong (rom.size() - pad_size) ) if ( offset > uint32_t (rom.size() - pad_size) )
offset = 0; // unmapped offset = 0; // unmapped
return &rom [offset]; return &rom [offset];
} }

View file

@ -362,15 +362,17 @@ blargg_err_t Std_File_Reader::open( const char* path )
long Std_File_Reader::size() const long Std_File_Reader::size() const
{ {
if ( !file_ )
return -1L;
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
if ( file_ ) return size_; // Set for both compressed and uncompressed modes
return size_; // Set for both compressed and uncompressed modes #else
#endif
long pos = tell(); long pos = tell();
fseek( (FILE*) file_, 0, SEEK_END ); fseek( (FILE*) file_, 0, SEEK_END );
long result = tell(); long result = tell();
fseek( (FILE*) file_, pos, SEEK_SET ); fseek( (FILE*) file_, pos, SEEK_SET );
return result; return result;
#endif
} }
long Std_File_Reader::read_avail( void* p, long s ) long Std_File_Reader::read_avail( void* p, long s )
@ -390,52 +392,55 @@ long Std_File_Reader::read_avail( void* p, long s )
blargg_err_t Std_File_Reader::read( void* p, long s ) blargg_err_t Std_File_Reader::read( void* p, long s )
{ {
if ( !file_ )
return "NULL FILE pointer";
RETURN_VALIDITY_CHECK( s > 0 && static_cast<unsigned long>(s) <= UINT_MAX ); RETURN_VALIDITY_CHECK( s > 0 && static_cast<unsigned long>(s) <= UINT_MAX );
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
if ( file_ ) const auto &gzfile = reinterpret_cast<gzFile>( file_ );
{ if ( s == gzread( gzfile, p, static_cast<unsigned>( s ) ) )
const auto &gzfile = reinterpret_cast<gzFile>( file_ ); return nullptr;
if ( s == gzread( gzfile, p, static_cast<unsigned>( s ) ) ) if ( gzeof( gzfile ) )
return nullptr; return eof_error;
if ( gzeof( gzfile ) ) return "Couldn't read from GZ file";
return eof_error; #else
return "Couldn't read from GZ file";
}
#endif
const auto &file = reinterpret_cast<FILE*>( file_ ); const auto &file = reinterpret_cast<FILE*>( file_ );
if ( s == static_cast<long>( fread( p, 1, static_cast<size_t>(s), file ) ) ) if ( s == static_cast<long>( fread( p, 1, static_cast<size_t>(s), file ) ) )
return 0; return 0;
if ( feof( file ) ) if ( feof( file ) )
return eof_error; return eof_error;
return "Couldn't read from file"; return "Couldn't read from file";
#endif
} }
long Std_File_Reader::tell() const long Std_File_Reader::tell() const
{ {
if ( !file_ )
return -1L;
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
if ( file_ ) return gztell( reinterpret_cast<gzFile>( file_ ) );
return gztell( reinterpret_cast<gzFile>( file_ ) ); #else
#endif
return ftell( reinterpret_cast<FILE*>( file_ ) ); return ftell( reinterpret_cast<FILE*>( file_ ) );
#endif
} }
blargg_err_t Std_File_Reader::seek( long n ) blargg_err_t Std_File_Reader::seek( long n )
{ {
if ( !file_ )
return "NULL FILE pointer";
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
if ( file_ ) if ( gzseek( reinterpret_cast<gzFile>( file_ ), n, SEEK_SET ) >= 0 )
{ return nullptr;
if ( gzseek( reinterpret_cast<gzFile>( file_ ), n, SEEK_SET ) >= 0 ) if ( n > size_ )
return nullptr; return eof_error;
if ( n > size_ ) return "Error seeking in GZ file";
return eof_error; #else
return "Error seeking in GZ file";
}
#endif
if ( !fseek( reinterpret_cast<FILE*>( file_ ), n, SEEK_SET ) ) if ( !fseek( reinterpret_cast<FILE*>( file_ ), n, SEEK_SET ) )
return nullptr; return nullptr;
if ( n > size() ) if ( n > size() )
return eof_error; return eof_error;
return "Error seeking in file"; return "Error seeking in file";
#endif
} }
void Std_File_Reader::close() void Std_File_Reader::close()
@ -450,4 +455,3 @@ void Std_File_Reader::close()
file_ = nullptr; file_ = nullptr;
} }
} }

View file

@ -119,12 +119,12 @@ void Dual_Resampler::mix_samples( Blip_Buffer& blip_buf, dsample_t* out )
for ( int n = sample_buf_size >> 1; n--; ) for ( int n = sample_buf_size >> 1; n--; )
{ {
int s = sn.read(); int s = sn.read();
blargg_long l = (blargg_long) in [0] * 2 + s; int32_t l = (int32_t) in [0] * 2 + s;
if ( (int16_t) l != l ) if ( (int16_t) l != l )
l = 0x7FFF - (l >> 24); l = 0x7FFF - (l >> 24);
sn.next( bass ); sn.next( bass );
blargg_long r = (blargg_long) in [1] * 2 + s; int32_t r = (int32_t) in [1] * 2 + s;
if ( (int16_t) r != r ) if ( (int16_t) r != r )
r = 0x7FFF - (r >> 24); r = 0x7FFF - (r >> 24);

View file

@ -22,7 +22,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include BLARGG_ENABLE_OPTIMIZER #include BLARGG_ENABLE_OPTIMIZER
#endif #endif
typedef blargg_long fixed_t; typedef int32_t fixed_t;
using std::min; using std::min;
using std::max; using std::max;
@ -30,12 +30,12 @@ using std::max;
#define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5) #define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5)
#define FMUL( x, y ) (((x) * (y)) >> 15) #define FMUL( x, y ) (((x) * (y)) >> 15)
const unsigned echo_size = 4096; static const unsigned echo_size = 4096;
const unsigned echo_mask = echo_size - 1; static const unsigned echo_mask = echo_size - 1;
static_assert( (echo_size & echo_mask) == 0, "echo_size must be a power of 2" ); static_assert( (echo_size & echo_mask) == 0, "echo_size must be a power of 2" );
const unsigned reverb_size = 8192 * 2; static const unsigned reverb_size = 8192 * 2;
const unsigned reverb_mask = reverb_size - 1; static const unsigned reverb_mask = reverb_size - 1;
static_assert( (reverb_size & reverb_mask) == 0, "reverb_size must be a power of 2" ); static_assert( (reverb_size & reverb_mask) == 0, "reverb_size must be a power of 2" );
Effects_Buffer::config_t::config_t() Effects_Buffer::config_t::config_t()
@ -88,26 +88,24 @@ Effects_Buffer::Effects_Buffer( int num_voices, bool center_only )
Effects_Buffer::~Effects_Buffer() Effects_Buffer::~Effects_Buffer()
{} {}
blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec ) blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec ) noexcept
{ {
try for(int i=0; i<max_voices; i++)
{ {
for(int i=0; i<max_voices; i++) if ( !echo_buf[i].size() )
{ {
if ( !echo_buf[i].size() ) echo_buf[i].resize( echo_size );
{ }
echo_buf[i].resize( echo_size );
} if ( !reverb_buf[i].size() )
{
if ( !reverb_buf[i].size() ) reverb_buf[i].resize( reverb_size );
{ }
reverb_buf[i].resize( reverb_size );
} if ( !echo_buf[i].size() || !reverb_buf[i].size() )
{
return "Out of memory";
} }
}
catch(std::bad_alloc& ba)
{
return "Out of memory";
} }
for ( int i = 0; i < buf_count; i++ ) for ( int i = 0; i < buf_count; i++ )
@ -217,7 +215,7 @@ void Effects_Buffer::config( const config_t& cfg )
chan_types [i*chan_types_count+2].left = &bufs [i*max_buf_count+5]; chan_types [i*chan_types_count+2].left = &bufs [i*max_buf_count+5];
chan_types [i*chan_types_count+2].right = &bufs [i*max_buf_count+6]; chan_types [i*chan_types_count+2].right = &bufs [i*max_buf_count+6];
} }
assert( 2 < chan_types_count ); blaarg_static_assert( chan_types_count >= 3, "Need at least three audio channels for effects processing" );
} }
else else
{ {
@ -364,7 +362,7 @@ long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples )
return total_samples * n_channels; return total_samples * n_channels;
} }
void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count ) void Effects_Buffer::mix_mono( blip_sample_t* out_, int32_t count )
{ {
for(int i=0; i<max_voices; i++) for(int i=0; i<max_voices; i++)
{ {
@ -373,21 +371,21 @@ void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
BLIP_READER_BEGIN( c, bufs [i*max_buf_count+0] ); BLIP_READER_BEGIN( c, bufs [i*max_buf_count+0] );
// unrolled loop // unrolled loop
for ( blargg_long n = count >> 1; n; --n ) for ( int32_t n = count >> 1; n; --n )
{ {
blargg_long cs0 = BLIP_READER_READ( c ); int32_t cs0 = BLIP_READER_READ( c );
BLIP_READER_NEXT( c, bass ); BLIP_READER_NEXT( c, bass );
blargg_long cs1 = BLIP_READER_READ( c ); int32_t cs1 = BLIP_READER_READ( c );
BLIP_READER_NEXT( c, bass ); BLIP_READER_NEXT( c, bass );
if ( (int16_t) cs0 != cs0 ) if ( (int16_t) cs0 != cs0 )
cs0 = 0x7FFF - (cs0 >> 24); cs0 = 0x7FFF - (cs0 >> 24);
((uint32_t*) out) [i*2+0] = ((uint16_t) cs0) | (uint16_t(cs0) << 16); ((uint32_t*) out) [i] = ((uint16_t) cs0) | (uint16_t(cs0) << 16);
if ( (int16_t) cs1 != cs1 ) if ( (int16_t) cs1 != cs1 )
cs1 = 0x7FFF - (cs1 >> 24); cs1 = 0x7FFF - (cs1 >> 24);
((uint32_t*) out) [i*2+1] = ((uint16_t) cs1) | (uint16_t(cs1) << 16); ((uint32_t*) out) [i+max_voices] = ((uint16_t) cs1) | (uint16_t(cs1) << 16);
out += max_voices*4; out += max_voices*4;
} }
@ -395,21 +393,17 @@ void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
{ {
int s = BLIP_READER_READ( c ); int s = BLIP_READER_READ( c );
BLIP_READER_NEXT( c, bass ); BLIP_READER_NEXT( c, bass );
if ( (int16_t) s != s )
s = 0x7FFF - (s >> 24);
out [i*2+0] = s; out [i*2+0] = s;
out [i*2+1] = s; out [i*2+1] = s;
if ( (int16_t) s != s )
{
s = 0x7FFF - (s >> 24);
out [i*2+0] = s;
out [i*2+1] = s;
}
} }
BLIP_READER_END( c, bufs [i*max_buf_count+0] ); BLIP_READER_END( c, bufs [i*max_buf_count+0] );
} }
} }
void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long frames ) void Effects_Buffer::mix_stereo( blip_sample_t* out_, int32_t frames )
{ {
for(int i=0; i<max_voices; i++) for(int i=0; i<max_voices; i++)
{ {
@ -448,7 +442,7 @@ void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long frames )
} }
} }
void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long frames ) void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, int32_t frames )
{ {
for(int i=0; i<max_voices; i++) for(int i=0; i<max_voices; i++)
{ {
@ -515,7 +509,7 @@ void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long frames
} }
} }
void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long frames ) void Effects_Buffer::mix_enhanced( blip_sample_t* out_, int32_t frames )
{ {
for(int i=0; i<max_voices; i++) for(int i=0; i<max_voices; i++)
{ {

View file

@ -44,7 +44,7 @@ public:
public: public:
~Effects_Buffer(); ~Effects_Buffer();
blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length ); blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length ) noexcept;
void clock_rate( long ); void clock_rate( long );
void bass_freq( int ); void bass_freq( int );
void clear(); void clear();
@ -81,10 +81,10 @@ private:
fixed_t reverb_level; fixed_t reverb_level;
} chans; } chans;
void mix_mono( blip_sample_t*, blargg_long ); void mix_mono( blip_sample_t*, int32_t );
void mix_stereo( blip_sample_t*, blargg_long ); void mix_stereo( blip_sample_t*, int32_t );
void mix_enhanced( blip_sample_t*, blargg_long ); void mix_enhanced( blip_sample_t*, int32_t );
void mix_mono_enhanced( blip_sample_t*, blargg_long ); void mix_mono_enhanced( blip_sample_t*, int32_t );
}; };
#endif #endif

View file

@ -138,9 +138,9 @@ double Fir_Resampler_::time_ratio( double new_factor, double rolloff, double gai
return ratio_; return ratio_;
} }
int Fir_Resampler_::input_needed( blargg_long output_count ) const int Fir_Resampler_::input_needed( int32_t output_count ) const
{ {
blargg_long input_count = 0; int32_t input_count = 0;
unsigned long skip = skip_bits >> imp_phase; unsigned long skip = skip_bits >> imp_phase;
int remain = res - imp_phase; int remain = res - imp_phase;
@ -162,13 +162,13 @@ int Fir_Resampler_::input_needed( blargg_long output_count ) const
return input_extra; return input_extra;
} }
int Fir_Resampler_::avail_( blargg_long input_count ) const int Fir_Resampler_::avail_( int32_t input_count ) const
{ {
int cycle_count = input_count / input_per_cycle; int cycle_count = input_count / input_per_cycle;
int output_count = cycle_count * res * stereo; int output_count = cycle_count * res * stereo;
input_count -= cycle_count * input_per_cycle; input_count -= cycle_count * input_per_cycle;
blargg_ulong skip = skip_bits >> imp_phase; uint32_t skip = skip_bits >> imp_phase;
int remain = res - imp_phase; int remain = res - imp_phase;
while ( input_count >= 0 ) while ( input_count >= 0 )
{ {
@ -188,6 +188,8 @@ int Fir_Resampler_::skip_input( long count )
{ {
int remain = write_pos - buf.begin(); int remain = write_pos - buf.begin();
int max_count = remain - width_ * stereo; int max_count = remain - width_ * stereo;
if ( max_count < 0 )
max_count = 0;
if ( count > max_count ) if ( count > max_count )
count = max_count; count = max_count;

View file

@ -48,7 +48,7 @@ public:
// Output // Output
// Number of extra input samples needed until 'count' output samples are available // Number of extra input samples needed until 'count' output samples are available
int input_needed( blargg_long count ) const; int input_needed( int32_t count ) const;
// Number of output samples available // Number of output samples available
int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); } int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); }
@ -64,14 +64,14 @@ protected:
int imp_phase; int imp_phase;
int const width_; int const width_;
int const write_offset; int const write_offset;
blargg_ulong skip_bits; uint32_t skip_bits;
int step; int step;
int input_per_cycle; int input_per_cycle;
double ratio_; double ratio_;
sample_t* impulses; sample_t* impulses;
Fir_Resampler_( int width, sample_t* ); Fir_Resampler_( int width, sample_t* );
int avail_( blargg_long input_count ) const; int avail_( int32_t input_count ) const;
}; };
// Width is number of points in FIR. Must be even and 4 or more. More points give // Width is number of points in FIR. Must be even and 4 or more. More points give
@ -85,7 +85,7 @@ public:
// Read at most 'count' samples. Returns number of samples actually read. // Read at most 'count' samples. Returns number of samples actually read.
typedef short sample_t; typedef short sample_t;
int read( sample_t* out, blargg_long count ); int read( sample_t* out, int32_t count );
}; };
// End of public interface // End of public interface
@ -97,12 +97,12 @@ inline void Fir_Resampler_::write( long count )
} }
template<int width> template<int width>
int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count ) int Fir_Resampler<width>::read( sample_t* out_begin, int32_t count )
{ {
sample_t* out = out_begin; sample_t* out = out_begin;
const sample_t* in = buf.begin(); const sample_t* in = buf.begin();
sample_t* end_pos = write_pos; sample_t* end_pos = write_pos;
blargg_ulong skip = skip_bits >> imp_phase; uint32_t skip = skip_bits >> imp_phase;
sample_t const* imp = impulses [imp_phase]; sample_t const* imp = impulses [imp_phase];
int remain = res - imp_phase; int remain = res - imp_phase;
int const step = this->step; int const step = this->step;
@ -132,8 +132,8 @@ int Fir_Resampler<width>::read( sample_t* out_begin, blargg_long count )
else else
{ {
// accumulate in extended precision // accumulate in extended precision
blargg_long l = 0; int32_t l = 0;
blargg_long r = 0; int32_t r = 0;
const sample_t* i = in; const sample_t* i = in;

View file

@ -18,14 +18,16 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
unsigned const vol_reg = 0xFF24; static unsigned const vol_reg = 0xFF24;
unsigned const status_reg = 0xFF26; static unsigned const status_reg = 0xFF26;
using std::min; using std::min;
using std::max; using std::max;
Gb_Apu::Gb_Apu() Gb_Apu::Gb_Apu()
{ {
memset(regs, 0, sizeof(regs));
square1.synth = &square_synth; square1.synth = &square_synth;
square2.synth = &square_synth; square2.synth = &square_synth;
wave.synth = &other_synth; wave.synth = &other_synth;

View file

@ -26,7 +26,7 @@ public:
// Assign single oscillator output to buffer(s). Valid indicies are 0 to 3, // 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, // which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL,
// silences oscillator. // silences oscillator.
enum { osc_count = 4 }; static const int osc_count = 4;
void osc_output( int index, Blip_Buffer* mono ); void osc_output( int index, Blip_Buffer* mono );
void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
@ -34,9 +34,9 @@ public:
void reset(); void reset();
// Reads and writes at addr must satisfy start_addr <= addr <= end_addr // Reads and writes at addr must satisfy start_addr <= addr <= end_addr
enum { start_addr = 0xFF10 }; static const unsigned int start_addr = 0xFF10;
enum { end_addr = 0xFF3F }; static const unsigned int end_addr = 0xFF3F;
enum { register_count = end_addr - start_addr + 1 }; static const unsigned int register_count = end_addr - start_addr + 1;
// Write 'data' to address at specified time // Write 'data' to address at specified time
void write_register( blip_time_t, unsigned addr, int data ); void write_register( blip_time_t, unsigned addr, int data );

View file

@ -49,7 +49,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
inline void Gb_Cpu::set_code_page( int i, uint8_t* p ) inline void Gb_Cpu::set_code_page( int i, uint8_t* p )
{ {
state->code_map [i] = p - PAGE_OFFSET( i * (blargg_long) page_size ); state->code_map [i] = p - PAGE_OFFSET( i * (int32_t) page_size );
} }
void Gb_Cpu::reset( void* unmapped ) void Gb_Cpu::reset( void* unmapped )
@ -84,14 +84,15 @@ void Gb_Cpu::map_code( gb_addr_t start, unsigned size, void* data )
#define READ_FAST( addr, out ) CPU_READ_FAST( this, (addr), s.remain, out ) #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 )]) #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 ) static unsigned const z_flag = 0x80;
static unsigned const n_flag = 0x40;
static unsigned const h_flag = 0x20;
static unsigned const c_flag = 0x10;
bool Gb_Cpu::run( int32_t cycle_count )
{ {
state_.remain = blargg_ulong (cycle_count + clocks_per_instr) / clocks_per_instr; state_.remain = uint32_t (cycle_count + clocks_per_instr) / clocks_per_instr;
state_t s; state_t s;
this->state = &s; this->state = &s;
memcpy( &s, &this->state_, sizeof s ); memcpy( &s, &this->state_, sizeof s );
@ -678,7 +679,7 @@ loop:
// Add 16-bit // Add 16-bit
{ {
blargg_ulong temp; // need more than 16 bits for carry uint32_t temp; // need more than 16 bits for carry
unsigned prev; unsigned prev;
case 0xF8: // LD HL,SP+imm case 0xF8: // LD HL,SP+imm

View file

@ -52,10 +52,10 @@ public:
// Run CPU for at least 'count' cycles and return false, or return true if // Run CPU for at least 'count' cycles and return false, or return true if
// illegal instruction is encountered. // illegal instruction is encountered.
bool run( blargg_long count ); bool run( int32_t count );
// Number of clock cycles remaining for most recent run() call // Number of clock cycles remaining for most recent run() call
blargg_long remain() const { return state->remain * clocks_per_instr; } int32_t remain() const { return state->remain * clocks_per_instr; }
// Can read this many bytes past end of a page // Can read this many bytes past end of a page
enum { cpu_padding = 8 }; enum { cpu_padding = 8 };
@ -71,7 +71,7 @@ private:
struct state_t { struct state_t {
uint8_t* code_map [page_count + 1]; uint8_t* code_map [page_count + 1];
blargg_long remain; int32_t remain;
}; };
state_t* state; // points to state_ or a local copy within run() state_t* state; // points to state_ or a local copy within run()
state_t state_; state_t state_;

View file

@ -107,7 +107,7 @@ extern gme_type_t const gme_gbs_type = &gme_gbs_type_;
blargg_err_t Gbs_Emu::load_( Data_Reader& in ) blargg_err_t Gbs_Emu::load_( Data_Reader& in )
{ {
assert( offsetof (header_t,copyright [32]) == header_size ); blaarg_static_assert( offsetof (header_t,copyright [32]) == header_size, "GBS Header layout incorrect!" );
RETURN_ERR( rom.load( in, header_size, &header_, 0 ) ); RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
set_track_count( header_.track_count ); set_track_count( header_.track_count );
@ -154,7 +154,7 @@ void Gbs_Emu::set_bank( int n )
n = 1; n = 1;
} }
blargg_long addr = n * (blargg_long) bank_size; int32_t addr = n * (int32_t) bank_size;
if (addr > rom.size()) if (addr > rom.size())
{ {
return; return;

View file

@ -61,6 +61,11 @@ blargg_err_t Gme_File::load_( Data_Reader& in )
{ {
RETURN_ERR( file_data.resize( in.remain() ) ); RETURN_ERR( file_data.resize( in.remain() ) );
RETURN_ERR( in.read( file_data.begin(), file_data.size() ) ); RETURN_ERR( in.read( file_data.begin(), file_data.size() ) );
if ( type()->track_count == 1 )
{
RETURN_ERR( tracks.resize( 2 ) );
tracks[0] = 0, tracks[1] = file_data.size();
}
return load_mem_( file_data.begin(), file_data.size() ); return load_mem_( file_data.begin(), file_data.size() );
} }
@ -90,6 +95,22 @@ blargg_err_t Gme_File::load_mem( void const* in, long size )
return post_load( load_mem_( (byte const*) in, size ) ); return post_load( load_mem_( (byte const*) in, size ) );
} }
blargg_err_t Gme_File::load_tracks( void const* in, long* sizes, int count )
{
pre_load();
if ( type()->track_count != 1 )
return "File type must have a fixed track count of 1";
set_track_count( count );
RETURN_ERR( tracks.resize( count + 1 ) );
long size = 0;
for ( int i = 0; i < count; size += sizes[i++] )
tracks[i] = size;
tracks[count] = size;
RETURN_ERR( file_data.resize( size ) );
memcpy( file_data.begin(), in, size );
return post_load( load_mem_( file_data.begin(), tracks[1] ) );
}
blargg_err_t Gme_File::load( Data_Reader& in ) blargg_err_t Gme_File::load( Data_Reader& in )
{ {
pre_load(); pre_load();

View file

@ -76,6 +76,10 @@ public:
// must not free it until you're done with the file. // must not free it until you're done with the file.
blargg_err_t load_mem( void const* data, long size ); blargg_err_t load_mem( void const* data, long size );
// Load from multiple files already read into memory.
// Should only be used for file types with a fixed track count of 1.
blargg_err_t load_tracks( void const* in, long* sizes, int count );
// Load an m3u playlist. Must be done after loading main music file. // 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( const char* path );
blargg_err_t load_m3u( Data_Reader& in ); blargg_err_t load_m3u( Data_Reader& in );
@ -112,9 +116,6 @@ public:
// clear it. Passes user_data to cleanup function. // clear it. Passes user_data to cleanup function.
void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; } void set_user_cleanup( gme_user_cleanup_t func ) { user_cleanup_ = func; }
bool is_archive = false;
virtual blargg_err_t load_archive( const char* ) { return gme_wrong_file_type; }
public: public:
// deprecated // deprecated
int error_count() const; // use warning() int error_count() const; // use warning()
@ -130,6 +131,9 @@ protected:
void set_type( gme_type_t t ) { type_ = t; } void set_type( gme_type_t t ) { type_ = t; }
blargg_err_t load_remaining_( void const* header, long header_size, Data_Reader& remaining ); blargg_err_t load_remaining_( void const* header, long header_size, Data_Reader& remaining );
const byte* track_pos( int i ) { return &file_data[tracks[i]]; }
long track_size( int i ) { return tracks[i + 1] - tracks[i]; }
// Overridable // Overridable
virtual void unload(); // called before loading file and if loading fails 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_( Data_Reader& ); // default loads then calls load_mem_()
@ -155,6 +159,7 @@ private:
M3u_Playlist playlist; M3u_Playlist playlist;
char playlist_warning [64]; char playlist_warning [64];
blargg_vector<byte> file_data; // only if loaded into memory using default load blargg_vector<byte> file_data; // only if loaded into memory using default load
blargg_vector<long> tracks; // file start indexes of `file_data`
blargg_err_t load_m3u_( blargg_err_t ); blargg_err_t load_m3u_( blargg_err_t );
blargg_err_t post_load( blargg_err_t err ); blargg_err_t post_load( blargg_err_t err );

View file

@ -18,12 +18,12 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
double const min_tempo = 0.25; static double const min_tempo = 0.25;
double const oversample_factor = 5 / 3.0; static double const oversample_factor = 5 / 3.0;
double const fm_gain = 3.0; static double const fm_gain = 3.0;
const long base_clock = 53700300; static const long base_clock = 53700300;
const long clock_rate = base_clock / 15; static const long clock_rate = base_clock / 15;
Gym_Emu::Gym_Emu() Gym_Emu::Gym_Emu()
{ {
@ -210,7 +210,7 @@ void Gym_Emu::mute_voices_( int mask )
blargg_err_t Gym_Emu::load_mem_( byte const* in, long size ) blargg_err_t Gym_Emu::load_mem_( byte const* in, long size )
{ {
assert( offsetof (header_t,packed [4]) == header_size ); blaarg_static_assert( offsetof (header_t,packed [4]) == header_size, "GYM Header layout incorrect!" );
int offset = 0; int offset = 0;
RETURN_ERR( check_header( in, size, &offset ) ); RETURN_ERR( check_header( in, size, &offset ) );
set_voice_count( 8 ); set_voice_count( 8 );

View file

@ -58,10 +58,10 @@ private:
const byte* loop_begin; const byte* loop_begin;
const byte* pos; const byte* pos;
const byte* data_end; const byte* data_end;
blargg_long loop_remain; // frames remaining until loop beginning has been located int32_t loop_remain; // frames remaining until loop beginning has been located
header_t header_; header_t header_;
double fm_sample_rate; double fm_sample_rate;
blargg_long clocks_per_frame; int32_t clocks_per_frame;
void parse_frame(); void parse_frame();
// dac (pcm) // dac (pcm)

View file

@ -17,7 +17,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
bool const center_waves = true; // reduces asymmetry and clamping when starting notes static bool const center_waves = true; // reduces asymmetry and clamping when starting notes
Hes_Apu::Hes_Apu() Hes_Apu::Hes_Apu()
{ {
@ -106,10 +106,10 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
unsigned noise_lfsr = this->noise_lfsr; unsigned noise_lfsr = this->noise_lfsr;
do do
{ {
int new_dac = 0x1F & -(noise_lfsr >> 1 & 1); int new_dac = 0x1F & uMinus(noise_lfsr >> 1 & 1);
// Implemented using "Galios configuration" // Implemented using "Galios configuration"
// TODO: find correct LFSR algorithm // TODO: find correct LFSR algorithm
noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & -(noise_lfsr & 1)); noise_lfsr = (noise_lfsr >> 1) ^ (0xE008 & uMinus(noise_lfsr & 1));
//noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1)); //noise_lfsr = (noise_lfsr >> 1) ^ (0x6000 & -(noise_lfsr & 1));
int delta = new_dac - dac; int delta = new_dac - dac;
if ( delta ) if ( delta )
@ -160,9 +160,8 @@ void Hes_Osc::run_until( synth_t& synth_, blip_time_t end_time )
//if ( !(volume_0 | volume_1) ) //if ( !(volume_0 | volume_1) )
// debug_printf( "Used period 0\n" ); // debug_printf( "Used period 0\n" );
} }
// maintain phase when silent // maintain phase when silent
blargg_long count = (end_time - time + period - 1) / period; int32_t count = (end_time - time + period - 1) / period;
phase += count; // phase will be masked below phase += count; // phase will be masked below
time += count * period; time += count * period;
} }
@ -288,14 +287,14 @@ void Hes_Apu::write_data( blip_time_t time, int addr, int data )
} }
break; break;
case 0x807: case 0x807:
if ( &osc >= &oscs [4] ) if ( &osc >= &oscs [4] )
osc.noise = data; osc.noise = data;
break; break;
case 0x809: case 0x809:
if ( !(data & 0x80) && (data & 0x03) != 0 ) if ( !(data & 0x80) && (data & 0x03) != 0 )
debug_printf( "HES LFO not supported\n" ); debug_printf( "HES LFO not supported\n" );
} }
} }
} }

View file

@ -25,7 +25,7 @@ struct Hes_Osc
unsigned noise_lfsr; unsigned noise_lfsr;
unsigned char control; unsigned char control;
enum { amp_range = 0x8000 }; static const unsigned int amp_range = 0x8000;
typedef Blip_Synth<blip_med_quality,1> synth_t; typedef Blip_Synth<blip_med_quality,1> synth_t;
void run_until( synth_t& synth, blip_time_t ); void run_until( synth_t& synth, blip_time_t );
@ -36,13 +36,13 @@ public:
void treble_eq( blip_eq_t const& ); void treble_eq( blip_eq_t const& );
void volume( double ); void volume( double );
enum { osc_count = 6 }; static const int osc_count = 6;
void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
void reset(); void reset();
enum { start_addr = 0x0800 }; static const unsigned int start_addr = 0x0800;
enum { end_addr = 0x0809 }; static const unsigned int end_addr = 0x0809;
void write_data( blip_time_t, int addr, int data ); void write_data( blip_time_t, int addr, int data );
void end_frame( blip_time_t ); void end_frame( blip_time_t );

View file

@ -37,14 +37,16 @@ int const ram_addr = 0x2000;
#endif #endif
// status flags // status flags
BLARGG_MAYBE_UNUSED int const st_n = 0x80; enum {
BLARGG_MAYBE_UNUSED int const st_v = 0x40; st_n = 0x80,
BLARGG_MAYBE_UNUSED int const st_t = 0x20; st_v = 0x40,
BLARGG_MAYBE_UNUSED int const st_b = 0x10; st_t = 0x20,
BLARGG_MAYBE_UNUSED int const st_d = 0x08; st_b = 0x10,
BLARGG_MAYBE_UNUSED int const st_i = 0x04; st_d = 0x08,
BLARGG_MAYBE_UNUSED int const st_z = 0x02; st_i = 0x04,
BLARGG_MAYBE_UNUSED int const st_c = 0x01; st_z = 0x02,
st_c = 0x01
};
void Hes_Cpu::reset() void Hes_Cpu::reset()
{ {
@ -94,7 +96,7 @@ bool Hes_Cpu::run( hes_time_t end_time )
state_t s = this->state_; state_t s = this->state_;
this->state = &s; this->state = &s;
// even on x86, using s.time in place of s_time was slower // even on x86, using s.time in place of s_time was slower
blargg_long s_time = s.time; int32_t s_time = s.time;
// registers // registers
uint_fast16_t pc = r.pc; uint_fast16_t pc = r.pc;
@ -994,7 +996,7 @@ possibly_out_of_time:
hes_time_t new_time = end_time_; hes_time_t new_time = end_time_;
if ( !(status & st_i) && new_time > irq_time_ ) if ( !(status & st_i) && new_time > irq_time_ )
new_time = irq_time_; new_time = irq_time_;
blargg_long delta = s.base - new_time; int32_t delta = s.base - new_time;
s.base = new_time; s.base = new_time;
s_time += delta; s_time += delta;
} }
@ -1062,7 +1064,7 @@ possibly_out_of_time:
status &= ~st_i; status &= ~st_i;
handle_cli: { handle_cli: {
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - irq_time_; int32_t delta = s.base - irq_time_;
if ( delta <= 0 ) if ( delta <= 0 )
{ {
if ( TIME < irq_time_ ) if ( TIME < irq_time_ )
@ -1093,7 +1095,7 @@ possibly_out_of_time:
status |= st_i; status |= st_i;
handle_sei: { handle_sei: {
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
s.base = end_time_; s.base = end_time_;
s_time += delta; s_time += delta;
if ( s_time < 0 ) if ( s_time < 0 )
@ -1260,7 +1262,7 @@ interrupt:
status |= st_i; status |= st_i;
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
s.base = end_time_; s.base = end_time_;
s_time += delta; s_time += delta;
goto loop; goto loop;

View file

@ -6,7 +6,7 @@
#include "blargg_common.h" #include "blargg_common.h"
typedef blargg_long hes_time_t; // clock cycle count typedef int32_t hes_time_t; // clock cycle count
typedef unsigned hes_addr_t; // 16-bit address typedef unsigned hes_addr_t; // 16-bit address
enum { future_hes_time = INT_MAX / 2 + 1 }; enum { future_hes_time = INT_MAX / 2 + 1 };
@ -73,7 +73,7 @@ private:
struct state_t { struct state_t {
uint8_t const* code_map [page_count + 1]; uint8_t const* code_map [page_count + 1];
hes_time_t base; hes_time_t base;
blargg_long time; int32_t time;
}; };
state_t* state; // points to state_ or a local copy within run() state_t* state; // points to state_ or a local copy within run()
state_t state_; state_t state_;

View file

@ -19,12 +19,12 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const timer_mask = 0x04; static int const timer_mask = 0x04;
int const vdp_mask = 0x02; static int const vdp_mask = 0x02;
int const i_flag_mask = 0x04; static int const i_flag_mask = 0x04;
int const unmapped = 0xFF; static int const unmapped = 0xFF;
long const period_60hz = 262 * 455L; // scanlines * clocks per scanline static long const period_60hz = 262 * 455L; // scanlines * clocks per scanline
using std::min; using std::min;
using std::max; using std::max;
@ -119,7 +119,7 @@ struct Hes_File : Gme_Info_
blargg_err_t load_( Data_Reader& in ) blargg_err_t load_( Data_Reader& in )
{ {
assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20 ); blaarg_static_assert( offsetof (header_t,fields) == Hes_Emu::header_size + 0x20, "HES header layout is incorrect!" );
blargg_err_t err = in.read( &h, sizeof h ); blargg_err_t err = in.read( &h, sizeof h );
if ( err ) if ( err )
return (err == in.eof_error ? gme_wrong_file_type : err); return (err == in.eof_error ? gme_wrong_file_type : err);
@ -144,7 +144,7 @@ extern gme_type_t const gme_hes_type = &gme_hes_type_;
blargg_err_t Hes_Emu::load_( Data_Reader& in ) blargg_err_t Hes_Emu::load_( Data_Reader& in )
{ {
assert( offsetof (header_t,unused [4]) == header_size ); blaarg_static_assert( offsetof (header_t,unused [4]) == header_size, "HES header layout is incorrect!" );
RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) ); RETURN_ERR( rom.load( in, header_size, &header_, unmapped ) );
RETURN_ERR( check_hes_header( header_.tag ) ); RETURN_ERR( check_hes_header( header_.tag ) );
@ -498,7 +498,7 @@ int Hes_Emu::cpu_done()
return 0; return 0;
} }
static void adjust_time( blargg_long& time, hes_time_t delta ) static void adjust_time( int32_t& time, hes_time_t delta )
{ {
if ( time < future_hes_time ) if ( time < future_hes_time )
{ {

View file

@ -62,8 +62,8 @@ private:
struct { struct {
hes_time_t last_time; hes_time_t last_time;
blargg_long count; int32_t count;
blargg_long load; int32_t load;
int raw_load; int raw_load;
byte enabled; byte enabled;
byte fired; byte fired;

View file

@ -41,15 +41,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
// flags, named with hex value for clarity // flags, named with hex value for clarity
int const S80 = 0x80; enum {
int const Z40 = 0x40; S80 = 0x80,
int const F20 = 0x20; Z40 = 0x40,
int const H10 = 0x10; F20 = 0x20,
int const F08 = 0x08; H10 = 0x10,
int const V04 = 0x04; F08 = 0x08,
int const P04 = 0x04; V04 = 0x04,
int const N02 = 0x02; P04 = 0x04,
int const C01 = 0x01; N02 = 0x02,
C01 = 0x01
};
#define SZ28P( n ) szpc [n] #define SZ28P( n ) szpc [n]
#define SZ28PC( n ) szpc [n] #define SZ28PC( n ) szpc [n]
@ -78,7 +80,7 @@ Kss_Cpu::Kss_Cpu()
inline void Kss_Cpu::set_page( int i, void* write, void const* read ) 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 ); int32_t offset = KSS_CPU_PAGE_OFFSET( i * (int32_t) page_size );
state->write [i] = (byte *) write - offset; state->write [i] = (byte *) write - offset;
state->read [i] = (byte const*) read - offset; state->read [i] = (byte const*) read - offset;
} }
@ -97,7 +99,7 @@ void Kss_Cpu::reset( void* unmapped_write, void const* unmapped_read )
memset( &r, 0, sizeof r ); memset( &r, 0, sizeof r );
} }
void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const* read ) void Kss_Cpu::map_mem( unsigned addr, uint32_t size, void* write, void const* read )
{ {
// address range must begin and end on page boundaries // address range must begin and end on page boundaries
require( addr % page_size == 0 ); require( addr % page_size == 0 );
@ -106,7 +108,7 @@ void Kss_Cpu::map_mem( unsigned addr, blargg_ulong size, void* write, void const
unsigned first_page = addr / page_size; unsigned first_page = addr / page_size;
for ( unsigned i = size / page_size; i--; ) for ( unsigned i = size / page_size; i--; )
{ {
blargg_long offset = i * (blargg_long) page_size; int32_t offset = i * (int32_t) page_size;
set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset ); set_page( first_page + i, (byte*) write + offset, (byte const*) read + offset );
} }
} }
@ -485,7 +487,6 @@ possibly_out_of_time:
} }
// ADD HL,rp // ADD HL,rp
case 0x39: // ADD HL,SP case 0x39: // ADD HL,SP
data = sp; data = sp;
goto add_hl_data; goto add_hl_data;
@ -495,7 +496,7 @@ possibly_out_of_time:
case 0x29: // ADD HL,HL case 0x29: // ADD HL,HL
data = R16( opcode, 4, 0x09 ); data = R16( opcode, 4, 0x09 );
add_hl_data: { add_hl_data: {
blargg_ulong sum = rp.hl + data; uint32_t sum = rp.hl + data;
data ^= rp.hl; data ^= rp.hl;
rp.hl = sum; rp.hl = sum;
flags = (flags & (S80 | Z40 | V04)) | flags = (flags & (S80 | Z40 | V04)) |
@ -743,7 +744,7 @@ possibly_out_of_time:
} }
case 0x17:{// RLA case 0x17:{// RLA
blargg_ulong temp = (rg.a << 1) | (flags & C01); uint32_t temp = (rg.a << 1) | (flags & C01);
flags = (flags & (S80 | Z40 | P04)) | flags = (flags & (S80 | Z40 | P04)) |
(temp & (F20 | F08)) | (temp & (F20 | F08)) |
(temp >> 8); (temp >> 8);
@ -1064,7 +1065,7 @@ possibly_out_of_time:
switch ( data ) switch ( data )
{ {
{ {
blargg_ulong temp; uint32_t temp;
case 0x72: // SBC HL,SP case 0x72: // SBC HL,SP
case 0x7A: // ADC HL,SP case 0x7A: // ADC HL,SP
temp = sp; temp = sp;
@ -1076,10 +1077,10 @@ possibly_out_of_time:
case 0x5A: // ADC HL,DE case 0x5A: // ADC HL,DE
case 0x6A: // ADC HL,HL case 0x6A: // ADC HL,HL
temp = R16( data >> 3 & 6, 1, 0 ); temp = R16( data >> 3 & 6, 1, 0 );
blargg_ulong sum = temp + (flags & C01); uint32_t sum = temp + (flags & C01);
flags = ~data >> 2 & N02; flags = ~data >> 2 & N02;
if ( flags ) if ( flags )
sum = -sum; sum = uMinus(sum);
sum += rp.hl; sum += rp.hl;
temp ^= rp.hl; temp ^= rp.hl;
temp ^= sum; temp ^= sum;
@ -1317,7 +1318,7 @@ possibly_out_of_time:
goto loop; goto loop;
default: default:
debug_printf( "Opcode $ED $%02X not supported\n", data ); debug_printf( "Opcode $ED $%02X not supported\n", (unsigned int)data );
warning = true; warning = true;
goto loop; goto loop;
} }
@ -1345,7 +1346,6 @@ possibly_out_of_time:
#define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in; #define SET_IXY( in ) if ( opcode == 0xDD ) ix = in; else iy = in;
// ADD/ADC/SUB/SBC // ADD/ADC/SUB/SBC
case 0x96: // SUB (IXY+disp) case 0x96: // SUB (IXY+disp)
case 0x86: // ADD (IXY+disp) case 0x86: // ADD (IXY+disp)
flags &= ~C01; // FALLTHRU flags &= ~C01; // FALLTHRU
@ -1387,8 +1387,8 @@ possibly_out_of_time:
case 0x09: // ADD IXY,BC case 0x09: // ADD IXY,BC
case 0x19: // ADD IXY,DE case 0x19: // ADD IXY,DE
temp = R16( data, 4, 0x09 ); temp = R16( data, 4, 0x09 );
add_ixy_data: { add_ixy_data: {
blargg_ulong sum = ixy + temp; uint32_t sum = ixy + temp;
temp ^= ixy; temp ^= ixy;
ixy = (uint16_t) sum; ixy = (uint16_t) sum;
flags = (flags & (S80 | Z40 | V04)) | flags = (flags & (S80 | Z40 | V04)) |
@ -1396,7 +1396,7 @@ possibly_out_of_time:
(sum >> 8 & (F20 | F08)) | (sum >> 8 & (F20 | F08)) |
((temp ^ sum) >> 8 & H10); ((temp ^ sum) >> 8 & H10);
goto set_ixy; goto set_ixy;
} }
} }
// AND // AND
@ -1654,7 +1654,6 @@ possibly_out_of_time:
} }
// Misc // Misc
case 0xE9: // JP (IXY) case 0xE9: // JP (IXY)
pc = ixy; pc = ixy;
goto loop; goto loop;

View file

@ -6,7 +6,7 @@
#include "blargg_endian.h" #include "blargg_endian.h"
typedef blargg_long cpu_time_t; typedef int32_t cpu_time_t;
// must be defined by caller // must be defined by caller
void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data ); void kss_cpu_out( class Kss_Cpu*, cpu_time_t, unsigned addr, int data );
@ -19,8 +19,8 @@ public:
void reset( void* unmapped_write, void const* unmapped_read ); void reset( void* unmapped_write, void const* unmapped_read );
// Map memory. Start and size must be multiple of page_size. // Map memory. Start and size must be multiple of page_size.
enum { page_size = 0x2000 }; static const unsigned int page_size = 0x2000;
void map_mem( unsigned addr, blargg_ulong size, void* write, void const* read ); void map_mem( unsigned addr, uint32_t size, void* write, void const* read );
// Map address to page // Map address to page
uint8_t* write( unsigned addr ); uint8_t* write( unsigned addr );
@ -68,15 +68,15 @@ public:
}; };
//registers_t r; (below for efficiency) //registers_t r; (below for efficiency)
enum { idle_addr = 0xFFFF }; static const unsigned int idle_addr = 0xFFFF;
// can read this far past end of a page // can read this far past end of a page
enum { cpu_padding = 0x100 }; static const unsigned int cpu_padding = 0x100;
public: public:
Kss_Cpu(); Kss_Cpu();
enum { page_shift = 13 }; static const unsigned int page_shift = 13;
enum { page_count = 0x10000 >> page_shift }; static const int page_count = 0x10000 >> page_shift;
private: private:
uint8_t szpc [0x200]; uint8_t szpc [0x200];
cpu_time_t end_time_; cpu_time_t end_time_;

View file

@ -19,8 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
long const clock_rate = 3579545; static long const clock_rate = 3579545;
int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count; static int const osc_count = Ay_Apu::osc_count + Scc_Apu::osc_count;
using std::min; using std::min;
using std::max; using std::max;
@ -125,8 +125,8 @@ void Kss_Emu::update_gain()
blargg_err_t Kss_Emu::load_( Data_Reader& in ) blargg_err_t Kss_Emu::load_( Data_Reader& in )
{ {
memset( &header_, 0, sizeof header_ ); memset( &header_, 0, sizeof header_ );
assert( offsetof (header_t,device_flags) == header_size - 1 ); blaarg_static_assert( offsetof (header_t,device_flags) == header_size - 1, "KSS Header layout incorrect!" );
assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1 ); blaarg_static_assert( offsetof (ext_header_t,msx_audio_vol) == ext_header_size - 1, "KSS Extended Header layout incorrect!" );
RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) ); RETURN_ERR( rom.load( in, header_size, STATIC_CAST(header_t*,&header_), 0 ) );
RETURN_ERR( check_kss_header( header_.tag ) ); RETURN_ERR( check_kss_header( header_.tag ) );
@ -226,7 +226,7 @@ blargg_err_t Kss_Emu::start_track_( int track )
rom.set_addr( -load_size - header_.extra_header ); rom.set_addr( -load_size - header_.extra_header );
// check available bank data // check available bank data
blargg_long const bank_size = this->bank_size(); int32_t const bank_size = this->bank_size();
int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size; int max_banks = (rom.file_size() - load_size + bank_size - 1) / bank_size;
bank_count = header_.bank_mode & 0x7F; bank_count = header_.bank_mode & 0x7F;
if ( bank_count > max_banks ) if ( bank_count > max_banks )
@ -276,7 +276,7 @@ void Kss_Emu::set_bank( int logical, int physical )
} }
else else
{ {
long phys = physical * (blargg_long) bank_size; long phys = physical * (int32_t) bank_size;
for ( unsigned offset = 0; offset < bank_size; offset += page_size ) for ( unsigned offset = 0; offset < bank_size; offset += page_size )
cpu::map_mem( addr + offset, page_size, cpu::map_mem( addr + offset, page_size,
unmapped_write, rom.at_addr( phys + offset ) ); unmapped_write, rom.at_addr( phys + offset ) );

View file

@ -70,7 +70,7 @@ private:
unsigned scc_enabled; // 0 or 0xC000 unsigned scc_enabled; // 0 or 0xC000
int bank_count; int bank_count;
void set_bank( int logical, int physical ); void set_bank( int logical, int physical );
blargg_long bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); } int32_t bank_size() const { return (16 * 1024L) >> (header_.bank_mode >> 7 & 1); }
blip_time_t play_period; blip_time_t play_period;
blip_time_t next_play; blip_time_t next_play;
@ -82,7 +82,7 @@ private:
friend void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data ); friend void kss_cpu_write( class Kss_Cpu*, unsigned addr, int data );
// large items // large items
enum { mem_size = 0x10000 }; static const unsigned int mem_size = 0x10000;
byte ram [mem_size + cpu_padding]; byte ram [mem_size + cpu_padding];
Ay_Apu ay; Ay_Apu ay;

View file

@ -17,9 +17,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// Tones above this frequency are treated as disabled tone at half volume. // Tones above this frequency are treated as disabled tone at half volume.
// Power of two is more efficient (avoids division). // Power of two is more efficient (avoids division).
unsigned const inaudible_freq = 16384; static unsigned const inaudible_freq = 16384;
int const wave_size = 0x20; static int const wave_size = 0x20;
void Scc_Apu::run_until( blip_time_t end_time ) void Scc_Apu::run_until( blip_time_t end_time )
{ {
@ -37,7 +37,7 @@ void Scc_Apu::run_until( blip_time_t end_time )
int volume = 0; int volume = 0;
if ( regs [0x8F] & (1 << index) ) if ( regs [0x8F] & (1 << index) )
{ {
blip_time_t inaudible_period = (blargg_ulong) (output->clock_rate() + blip_time_t inaudible_period = (uint32_t) (output->clock_rate() +
inaudible_freq * 32) / (inaudible_freq * 16); inaudible_freq * 32) / (inaudible_freq * 16);
if ( period > inaudible_period ) if ( period > inaudible_period )
volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15); volume = (regs [0x8A + index] & 0x0F) * (amp_range / 256 / 15);
@ -62,7 +62,7 @@ void Scc_Apu::run_until( blip_time_t end_time )
if ( !volume ) if ( !volume )
{ {
// maintain phase // maintain phase
blargg_long count = (end_time - time + period - 1) / period; int32_t count = (end_time - time + period - 1) / period;
osc.phase = (osc.phase + count) & (wave_size - 1); osc.phase = (osc.phase + count) & (wave_size - 1);
time += count * period; time += count * period;
} }

View file

@ -17,7 +17,7 @@ public:
void reset(); void reset();
// Write to register at specified time // Write to register at specified time
enum { reg_count = 0x90 }; static const int reg_count = 0x90;
void write( blip_time_t time, int reg, int data ); void write( blip_time_t time, int reg, int data );
// Run sound to specified time, end current time frame, then start a new // Run sound to specified time, end current time frame, then start a new
@ -29,7 +29,7 @@ public:
// Set sound output of specific oscillator to buffer, where index is // Set sound output of specific oscillator to buffer, where index is
// 0 to 4. If buffer is NULL, the specified oscillator is muted. // 0 to 4. If buffer is NULL, the specified oscillator is muted.
enum { osc_count = 5 }; static const int osc_count = 5;
void osc_output( int index, Blip_Buffer* ); void osc_output( int index, Blip_Buffer* );
// Set overall volume (default is 1.0) // Set overall volume (default is 1.0)
@ -41,7 +41,7 @@ public:
public: public:
Scc_Apu(); Scc_Apu();
private: private:
enum { amp_range = 0x8000 }; static const unsigned int amp_range = 0x8000;
struct osc_t struct osc_t
{ {
int delay; int delay;

View file

@ -60,8 +60,6 @@ gme_err_t gme_load_m3u_data( Music_Emu* me, const void* data, long size )
return me->load_m3u( in ); return me->load_m3u( in );
} }
static char* skip_white( char* in ) static char* skip_white( char* in )
{ {
while ( *in == ' ' ) while ( *in == ' ' )
@ -69,7 +67,7 @@ static char* skip_white( char* in )
return in; return in;
} }
inline unsigned from_dec( unsigned n ) { return n - '0'; } static inline unsigned from_dec( unsigned n ) { return n - '0'; }
static char* parse_filename( char* in, M3u_Playlist::entry_t& entry ) static char* parse_filename( char* in, M3u_Playlist::entry_t& entry )
{ {
@ -176,7 +174,7 @@ static char* parse_int( char* in, int* out, int* result )
} }
// Returns 16 or greater if not hex // Returns 16 or greater if not hex
inline int from_hex_char( int h ) static inline int from_hex_char( int h )
{ {
h -= 0x30; h -= 0x30;
if ( (unsigned) h > 9 ) if ( (unsigned) h > 9 )

View file

@ -148,7 +148,7 @@ long Stereo_Buffer::read_samples( blip_sample_t* out, long count )
return count * 2; return count * 2;
} }
void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count ) void Stereo_Buffer::mix_stereo( blip_sample_t* out_, int32_t count )
{ {
blip_sample_t* BLIP_RESTRICT out = out_; blip_sample_t* BLIP_RESTRICT out = out_;
int const bass = BLIP_READER_BASS( bufs [1] ); int const bass = BLIP_READER_BASS( bufs [1] );
@ -159,8 +159,8 @@ void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
for ( ; count; --count ) for ( ; count; --count )
{ {
int c = BLIP_READER_READ( center ); int c = BLIP_READER_READ( center );
blargg_long l = c + BLIP_READER_READ( left ); int32_t l = c + BLIP_READER_READ( left );
blargg_long r = c + BLIP_READER_READ( right ); int32_t r = c + BLIP_READER_READ( right );
if ( (int16_t) l != l ) if ( (int16_t) l != l )
l = 0x7FFF - (l >> 24); l = 0x7FFF - (l >> 24);
@ -181,7 +181,7 @@ void Stereo_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count )
BLIP_READER_END( left, bufs [1] ); BLIP_READER_END( left, bufs [1] );
} }
void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count ) void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, int32_t count )
{ {
blip_sample_t* BLIP_RESTRICT out = out_; blip_sample_t* BLIP_RESTRICT out = out_;
int const bass = BLIP_READER_BASS( bufs [1] ); int const bass = BLIP_READER_BASS( bufs [1] );
@ -190,11 +190,11 @@ void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count
for ( ; count; --count ) for ( ; count; --count )
{ {
blargg_long l = BLIP_READER_READ( left ); int32_t l = BLIP_READER_READ( left );
if ( (int16_t) l != l ) if ( (int16_t) l != l )
l = 0x7FFF - (l >> 24); l = 0x7FFF - (l >> 24);
blargg_long r = BLIP_READER_READ( right ); int32_t r = BLIP_READER_READ( right );
if ( (int16_t) r != r ) if ( (int16_t) r != r )
r = 0x7FFF - (r >> 24); r = 0x7FFF - (r >> 24);
@ -210,7 +210,7 @@ void Stereo_Buffer::mix_stereo_no_center( blip_sample_t* out_, blargg_long count
BLIP_READER_END( left, bufs [1] ); BLIP_READER_END( left, bufs [1] );
} }
void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count ) void Stereo_Buffer::mix_mono( blip_sample_t* out_, int32_t count )
{ {
blip_sample_t* BLIP_RESTRICT out = out_; blip_sample_t* BLIP_RESTRICT out = out_;
int const bass = BLIP_READER_BASS( bufs [0] ); int const bass = BLIP_READER_BASS( bufs [0] );
@ -218,7 +218,7 @@ void Stereo_Buffer::mix_mono( blip_sample_t* out_, blargg_long count )
for ( ; count; --count ) for ( ; count; --count )
{ {
blargg_long s = BLIP_READER_READ( center ); int32_t s = BLIP_READER_READ( center );
if ( (int16_t) s != s ) if ( (int16_t) s != s )
s = 0x7FFF - (s >> 24); s = 0x7FFF - (s >> 24);

View file

@ -116,9 +116,9 @@ private:
int stereo_added; int stereo_added;
int was_stereo; int was_stereo;
void mix_stereo_no_center( blip_sample_t*, blargg_long ); void mix_stereo_no_center( blip_sample_t*, int32_t );
void mix_stereo( blip_sample_t*, blargg_long ); void mix_stereo( blip_sample_t*, int32_t );
void mix_mono( blip_sample_t*, blargg_long ); void mix_mono( blip_sample_t*, int32_t );
}; };
// Silent_Buffer generates no samples, useful where no sound is wanted // Silent_Buffer generates no samples, useful where no sound is wanted

View file

@ -19,10 +19,10 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const silence_max = 6; // seconds static int const silence_max = 6; // seconds
int const silence_threshold = 0x10; static int const silence_threshold = 0x10;
long const fade_block_size = 512; static long const fade_block_size = 512;
int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift) static int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
using std::min; using std::min;
using std::max; using std::max;
@ -34,6 +34,7 @@ void Music_Emu::clear_track_vars()
{ {
current_track_ = -1; current_track_ = -1;
out_time = 0; out_time = 0;
out_time_scaled = 0;
emu_time = 0; emu_time = 0;
emu_track_ended_ = true; emu_track_ended_ = true;
track_ended_ = true; track_ended_ = true;
@ -137,6 +138,11 @@ void Music_Emu::mute_voices( int mask )
mute_voices_( mask ); mute_voices_( mask );
} }
void Music_Emu::disable_echo( bool disable )
{
disable_echo_( disable );
}
void Music_Emu::set_tempo( double t ) void Music_Emu::set_tempo( double t )
{ {
require( sample_rate() ); // sample rate must be set first require( sample_rate() ); // sample rate must be set first
@ -176,10 +182,11 @@ blargg_err_t Music_Emu::start_track( int track )
break; break;
} }
emu_time = buf_remain; emu_time = buf_remain;
out_time = 0; out_time = 0;
silence_time = 0; out_time_scaled = 0;
silence_count = 0; silence_time = 0;
silence_count = 0;
} }
return track_ended() ? warning() : 0; return track_ended() ? warning() : 0;
} }
@ -205,9 +212,9 @@ void Music_Emu::set_autoload_playback_limit( bool do_autoload_limit )
// Tell/Seek // Tell/Seek
blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const int32_t Music_Emu::msec_to_samples( int32_t msec ) const
{ {
blargg_long sec = msec / 1000; int32_t sec = msec / 1000;
msec -= sec * 1000; msec -= sec * 1000;
return (sec * sample_rate() + msec * sample_rate() / 1000) * out_channels(); return (sec * sample_rate() + msec * sample_rate() / 1000) * out_channels();
} }
@ -219,11 +226,16 @@ long Music_Emu::tell_samples() const
long Music_Emu::tell() const long Music_Emu::tell() const
{ {
blargg_long rate = sample_rate() * out_channels(); int32_t rate = sample_rate() * out_channels();
blargg_long sec = out_time / rate; int32_t sec = out_time / rate;
return sec * 1000 + (out_time - sec * rate) * 1000 / rate; return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
} }
long Music_Emu::tell_scaled() const
{
return out_time_scaled / (sample_rate() / 1000.0);
}
blargg_err_t Music_Emu::seek_samples( long time ) blargg_err_t Music_Emu::seek_samples( long time )
{ {
if ( time < out_time ) if ( time < out_time )
@ -236,10 +248,22 @@ blargg_err_t Music_Emu::seek( long msec )
return seek_samples( msec_to_samples( msec ) ); return seek_samples( msec_to_samples( msec ) );
} }
blargg_err_t Music_Emu::seek_scaled( long msec )
{
require( tempo_ > 0 );
int32_t frames = (msec / 1000.0) * sample_rate();
if ( frames < out_time_scaled )
RETURN_ERR( start_track( current_track_ ) );
int samples_to_skip = (frames - out_time_scaled) * out_channels() / tempo_;
samples_to_skip += samples_to_skip % out_channels();
return skip( samples_to_skip );
}
blargg_err_t Music_Emu::skip( long count ) blargg_err_t Music_Emu::skip( long count )
{ {
require( current_track() >= 0 ); // start_track() must have been called already require( current_track() >= 0 ); // start_track() must have been called already
out_time += count; out_time += count;
out_time_scaled += count * tempo_ / out_channels();
// remove from silence and buf first // remove from silence and buf first
{ {
@ -302,7 +326,7 @@ void Music_Emu::set_fade( long start_msec, long length_msec )
} }
// unit / pow( 2.0, (double) x / step ) // unit / pow( 2.0, (double) x / step )
static int int_log( blargg_long x, int step, int unit ) static int int_log( int32_t x, int step, int unit )
{ {
int shift = x / step; int shift = x / step;
int fraction = (x - shift * step) * unit / step; int fraction = (x - shift * step) * unit / step;
@ -397,7 +421,7 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out )
{ {
// during a run of silence, run emulator at >=2x speed so it gets ahead // 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; long ahead_time = silence_lookahead * (out_time + out_count - silence_time) + silence_time;
while ( emu_time < ahead_time && !(buf_remain | emu_track_ended_) ) while ( emu_time < ahead_time && !(buf_remain | static_cast<long>(emu_track_ended_)) )
fill_buf(); fill_buf();
// fill with silence // fill with silence
@ -405,7 +429,7 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out )
memset( out, 0, pos * sizeof *out ); memset( out, 0, pos * sizeof *out );
silence_count -= pos; silence_count -= pos;
if ( emu_time - silence_time > silence_max * out_channels() * sample_rate() ) if ( !ignore_silence_ && emu_time - silence_time > silence_max * out_channels() * sample_rate() )
{ {
track_ended_ = emu_track_ended_ = true; track_ended_ = emu_track_ended_ = true;
silence_count = 0; silence_count = 0;
@ -445,6 +469,7 @@ blargg_err_t Music_Emu::play( long out_count, sample_t* out )
handle_fade( out_count, out ); handle_fade( out_count, out );
} }
out_time += out_count; out_time += out_count;
out_time_scaled += out_count * tempo_ / out_channels();
return 0; return 0;
} }
@ -459,3 +484,4 @@ void Gme_Info_::mute_voices_( int ) { check( false ); }
void Gme_Info_::set_tempo_( double ) { } 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_::start_track_( int ) { return "Use full emulator for playback"; }
blargg_err_t Gme_Info_::play_( long, sample_t* ) { return "Use full emulator for playback"; } blargg_err_t Gme_Info_::play_( long, sample_t* ) { return "Use full emulator for playback"; }

View file

@ -51,12 +51,18 @@ public:
// Number of samples generated since beginning of track // Number of samples generated since beginning of track
long tell_samples() const; long tell_samples() const;
// Number of milliseconds played since beginning of track (scaled with tempo).
long tell_scaled() const;
// Seek to new time in track. Seeking backwards or far forward can take a while. // Seek to new time in track. Seeking backwards or far forward can take a while.
blargg_err_t seek( long msec ); blargg_err_t seek( long msec );
// Equivalent to restarting track then skipping n samples // Equivalent to restarting track then skipping n samples
blargg_err_t seek_samples( long n ); blargg_err_t seek_samples( long n );
// Seek to new time in track (scaled with tempo).
blargg_err_t seek_scaled( long msec );
// Skip n samples // Skip n samples
blargg_err_t skip( long n ); blargg_err_t skip( long n );
@ -94,6 +100,9 @@ public:
// 0 unmutes them all, 0x01 mutes just the first voice, etc. // 0 unmutes them all, 0x01 mutes just the first voice, etc.
void mute_voices( int mask ); void mute_voices( int mask );
// Disables echo effect at SPC files
void disable_echo( bool disable );
// Change overall output amplitude, where 1.0 results in minimal clamping. // Change overall output amplitude, where 1.0 results in minimal clamping.
// Must be called before set_sample_rate(). // Must be called before set_sample_rate().
void set_gain( double ); void set_gain( double );
@ -146,9 +155,10 @@ protected:
virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0; virtual blargg_err_t set_sample_rate_( long sample_rate ) = 0;
virtual void set_equalizer_( equalizer_t const& ) { } virtual void set_equalizer_( equalizer_t const& ) { }
virtual void enable_accuracy_( bool /* enable */ ) { } virtual void enable_accuracy_( bool /* enable */ ) { }
virtual void mute_voices_( int mask ) = 0; virtual void mute_voices_( int mask );
virtual void set_tempo_( double ) = 0; virtual void disable_echo_( bool /* disable */);
virtual blargg_err_t start_track_( int ) = 0; // tempo is set before this virtual void set_tempo_( double );
virtual blargg_err_t start_track_( int ); // tempo is set before this
virtual blargg_err_t play_( long count, sample_t* out ) = 0; virtual blargg_err_t play_( long count, sample_t* out ) = 0;
virtual blargg_err_t skip_( long count ); virtual blargg_err_t skip_( long count );
protected: protected:
@ -170,20 +180,21 @@ private:
int out_channels() const { return this->multi_channel() ? 2*8 : 2; } int out_channels() const { return this->multi_channel() ? 2*8 : 2; }
long sample_rate_; long sample_rate_;
blargg_long msec_to_samples( blargg_long msec ) const; int32_t msec_to_samples( int32_t msec ) const;
// track-specific // track-specific
int current_track_; int current_track_;
blargg_long out_time; // number of samples played since start of track int32_t out_time; // number of samples played since start of track
blargg_long emu_time; // number of samples emulator has generated since start of track int32_t out_time_scaled; // number of samples played since start of track (scaled with tempo)
bool emu_track_ended_; // emulator has reached end of track int32_t emu_time; // number of samples emulator has generated since start of track
bool emu_track_ended_; // emulator has reached end of track
bool emu_autoload_playback_limit_; // whether to load and obey track length by default bool emu_autoload_playback_limit_; // whether to load and obey track length by default
volatile bool track_ended_; volatile bool track_ended_;
void clear_track_vars(); void clear_track_vars();
void end_track_if_error( blargg_err_t ); void end_track_if_error( blargg_err_t );
// fading // fading
blargg_long fade_start; int32_t fade_start;
int fade_step; int fade_step;
void handle_fade( long count, sample_t* out ); void handle_fade( long count, sample_t* out );
@ -233,7 +244,12 @@ inline void Music_Emu::enable_accuracy( bool b ) { enable_accuracy_( b ); }
inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; } inline void Music_Emu::set_tempo_( double t ) { tempo_ = t; }
inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); } inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); }
inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; } inline void Music_Emu::ignore_silence( bool b ) { ignore_silence_ = b; }
inline blargg_err_t Music_Emu::start_track_( int ) { return 0; } inline blargg_err_t Music_Emu::start_track_( int track )
{
if ( type()->track_count == 1 )
return load_mem_( track_pos( track ), track_size( track ) );
return 0;
}
inline void Music_Emu::set_voice_names( const char* const* names ) inline void Music_Emu::set_voice_names( const char* const* names )
{ {
@ -243,6 +259,8 @@ inline void Music_Emu::set_voice_names( const char* const* names )
inline void Music_Emu::mute_voices_( int ) { } inline void Music_Emu::mute_voices_( int ) { }
inline void Music_Emu::disable_echo_( bool ) { }
inline void Music_Emu::set_gain( double g ) inline void Music_Emu::set_gain( double g )
{ {
assert( !sample_rate() ); // you must set gain before setting sample rate assert( !sample_rate() ); // you must set gain before setting sample rate

View file

@ -15,7 +15,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const amp_range = 15; static int const amp_range = 15;
Nes_Apu::Nes_Apu() : Nes_Apu::Nes_Apu() :
square1( &square_synth ), square1( &square_synth ),

View file

@ -6,7 +6,7 @@
#include "blargg_common.h" #include "blargg_common.h"
typedef blargg_long nes_time_t; // CPU clock cycle count typedef int32_t nes_time_t; // CPU clock cycle count
typedef unsigned nes_addr_t; // 16-bit memory address typedef unsigned nes_addr_t; // 16-bit memory address
#include "Nes_Oscs.h" #include "Nes_Oscs.h"
@ -29,12 +29,12 @@ public:
// count, call end_frame( last_cpu_time ). // count, call end_frame( last_cpu_time ).
// Write to register (0x4000-0x4017, except 0x4014 and 0x4016) // Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
enum { start_addr = 0x4000 }; static const unsigned int start_addr = 0x4000;
enum { end_addr = 0x4017 }; static const unsigned int end_addr = 0x4017;
void write_register( nes_time_t, nes_addr_t, int data ); void write_register( nes_time_t, nes_addr_t, int data );
// Read from status register at 0x4015 // Read from status register at 0x4015
enum { status_addr = 0x4015 }; static const unsigned int status_addr = 0x4015;
int read_status( nes_time_t ); int read_status( nes_time_t );
// Run all oscillators up to specified time, end current time frame, then // Run all oscillators up to specified time, end current time frame, then
@ -67,7 +67,7 @@ public:
// the specified oscillator is muted and emulation accuracy is reduced. // the specified oscillator is muted and emulation accuracy is reduced.
// The oscillators are indexed as follows: 0) Square 1, 1) Square 2, // The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
// 2) Triangle, 3) Noise, 4) DMC. // 2) Triangle, 3) Noise, 4) DMC.
enum { osc_count = 5 }; static const int osc_count = 5;
void osc_output( int index, Blip_Buffer* buffer ); void osc_output( int index, Blip_Buffer* buffer );
// Set IRQ time callback that is invoked when the time of earliest IRQ // Set IRQ time callback that is invoked when the time of earliest IRQ
@ -78,8 +78,8 @@ public:
// Get time that APU-generated IRQ will occur if no further register reads // 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 // or writes occur. If IRQ is already pending, returns irq_waiting. If no
// IRQ will occur, returns no_irq. // IRQ will occur, returns no_irq.
enum { no_irq = INT_MAX / 2 + 1 }; static const unsigned int no_irq = INT_MAX / 2 + 1;
enum { irq_waiting = 0 }; static const unsigned int irq_waiting = 0;
nes_time_t earliest_irq( nes_time_t ) const; nes_time_t earliest_irq( nes_time_t ) const;
// Count number of DMC reads that would occur if 'run_until( t )' were executed. // Count number of DMC reads that would occur if 'run_until( t )' were executed.

View file

@ -53,14 +53,16 @@ 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 ); state->code_map [i] = (uint8_t const*) p - PAGE_OFFSET( i * page_size );
} }
int const st_n = 0x80; enum {
int const st_v = 0x40; st_n = 0x80,
int const st_r = 0x20; st_v = 0x40,
int const st_b = 0x10; st_r = 0x20,
int const st_d = 0x08; st_b = 0x10,
int const st_i = 0x04; st_d = 0x08,
int const st_z = 0x02; st_i = 0x04,
int const st_c = 0x01; st_z = 0x02,
st_c = 0x01
};
void Nes_Cpu::reset( void const* unmapped_page ) void Nes_Cpu::reset( void const* unmapped_page )
{ {
@ -78,7 +80,7 @@ void Nes_Cpu::reset( void const* unmapped_page )
end_time_ = future_nes_time; end_time_ = future_nes_time;
error_count_ = 0; error_count_ = 0;
assert( page_size == 0x800 ); // assumes this blaarg_static_assert( page_size == 0x800, "NES set to use unhandled page size" ); // assumes this
set_code_page( page_count, unmapped_page ); set_code_page( page_count, unmapped_page );
map_code( 0x2000, 0xE000, unmapped_page, true ); map_code( 0x2000, 0xE000, unmapped_page, true );
map_code( 0x0000, 0x2000, low_mem, true ); map_code( 0x0000, 0x2000, low_mem, true );
@ -849,7 +851,7 @@ imm##op:
SET_STATUS( temp ); SET_STATUS( temp );
if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change if ( !((data ^ status) & st_i) ) goto loop; // I flag didn't change
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - irq_time_; int32_t delta = s.base - irq_time_;
if ( delta <= 0 ) goto loop; if ( delta <= 0 ) goto loop;
if ( status & st_i ) goto loop; if ( status & st_i ) goto loop;
s_time += delta; s_time += delta;
@ -918,7 +920,7 @@ imm##op:
handle_cli: { handle_cli: {
//debug_printf( "CLI at %d\n", TIME ); //debug_printf( "CLI at %d\n", TIME );
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - irq_time_; int32_t delta = s.base - irq_time_;
if ( delta <= 0 ) if ( delta <= 0 )
{ {
if ( TIME < irq_time_ ) if ( TIME < irq_time_ )
@ -949,7 +951,7 @@ imm##op:
status |= st_i; status |= st_i;
handle_sei: { handle_sei: {
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
s.base = end_time_; s.base = end_time_;
s_time += delta; s_time += delta;
if ( s_time < 0 ) if ( s_time < 0 )
@ -961,6 +963,42 @@ imm##op:
// Unofficial // Unofficial
case 0xB3: { // LAX (ind),Y
uint16_t addr = READ_LOW( data ) + y;
HANDLE_PAGE_CROSSING( addr );
addr += 0x100 * READ_LOW( (uint8_t) (data + 1) );
pc++;
a = x = nz = READ_PROG( addr );
if ( (addr ^ 0x8000) <= 0x9FFF )
goto loop;
FLUSH_TIME();
a = x = nz = READ( addr );
CACHE_TIME();
goto loop;
}
case 0x8F: { // SAX abs
uint16_t addr = GET_ADDR();
uint8_t temp = a & x;
pc += 2;
if ( addr <= 0x7FF )
{
WRITE_LOW( addr, temp );
goto loop;
}
FLUSH_TIME();
WRITE( addr, temp );
CACHE_TIME();
goto loop;
}
case 0xCB: // SBX #imm
x = nz = (a & x) - data;
pc++;
c = ~nz;
nz &= 0xFF;
goto loop;
// SKW - Skip word // SKW - Skip word
case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC: case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
HANDLE_PAGE_CROSSING( data + x );/*FALLTHRU*/ HANDLE_PAGE_CROSSING( data + x );/*FALLTHRU*/
@ -1001,8 +1039,6 @@ imm##op:
if ( (opcode >> 4) == 0x0B ) if ( (opcode >> 4) == 0x0B )
{ {
if ( opcode == 0xB3 )
data = READ_LOW( data );
if ( opcode != 0xB7 ) if ( opcode != 0xB7 )
HANDLE_PAGE_CROSSING( data + y ); HANDLE_PAGE_CROSSING( data + y );
} }
@ -1032,7 +1068,7 @@ interrupt:
WRITE_LOW( sp, temp ); WRITE_LOW( sp, temp );
this->r.status = status |= st_i; this->r.status = status |= st_i;
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
if ( delta >= 0 ) goto loop; if ( delta >= 0 ) goto loop;
s_time += delta; s_time += delta;
s.base = end_time_; s.base = end_time_;

View file

@ -6,7 +6,7 @@
#include "blargg_common.h" #include "blargg_common.h"
typedef blargg_long nes_time_t; // clock cycle count typedef int32_t nes_time_t; // clock cycle count
typedef unsigned nes_addr_t; // 16-bit address typedef unsigned nes_addr_t; // 16-bit address
enum { future_nes_time = INT_MAX / 2 + 1 }; enum { future_nes_time = INT_MAX / 2 + 1 };

View file

@ -17,7 +17,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include <string.h> #include <string.h>
int const fract_range = 65536; static int const fract_range = 65536;
void Nes_Fds_Apu::reset() void Nes_Fds_Apu::reset()
{ {

View file

@ -6,24 +6,28 @@
#define NES_FDS_APU_H #define NES_FDS_APU_H
#include "blargg_common.h" #include "blargg_common.h"
#include "blargg_source.h"
#include "Blip_Buffer.h" #include "Blip_Buffer.h"
class Nes_Fds_Apu { class Nes_Fds_Apu {
public: public:
// setup // setup
void set_tempo( double ); void set_tempo( double );
enum { osc_count = 1 }; static const int osc_count = 1;
void volume( double ); void volume( double );
void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); } void treble_eq( blip_eq_t const& eq ) { synth.treble_eq( eq ); }
// emulation // emulation
void reset(); void reset();
enum { io_addr = 0x4040 }; static const unsigned int io_addr = 0x4040;
enum { io_size = 0x53 }; static const unsigned int io_size = 0x53;
void write( blip_time_t time, unsigned addr, int data ); void write( blip_time_t time, unsigned addr, int data );
int read( blip_time_t time, unsigned addr ); int read( blip_time_t time, unsigned addr );
void end_frame( blip_time_t ); void end_frame( blip_time_t );
// FDS has a RAM area at $8000-DFFF
enum { sram_addr = 0x8000 };
byte sram [0x6000];
public: public:
Nes_Fds_Apu(); Nes_Fds_Apu();
void write_( unsigned addr, int data ); void write_( unsigned addr, int data );
@ -31,14 +35,14 @@ public:
void osc_output( int, Blip_Buffer* ); void osc_output( int, Blip_Buffer* );
private: private:
enum { wave_size = 0x40 }; static const unsigned int wave_size = 0x40;
enum { master_vol_max = 10 }; static const unsigned int master_vol_max = 10;
enum { vol_max = 0x20 }; static const int vol_max = 0x20;
enum { wave_sample_max = 0x3F }; static const unsigned int wave_sample_max = 0x3F;
unsigned char regs_ [io_size];// last written value to registers unsigned char regs_ [io_size];// last written value to registers
enum { lfo_base_tempo = 8 }; static const unsigned int lfo_base_tempo = 8;
int lfo_tempo; // normally 8; adjusted by set_tempo() int lfo_tempo; // normally 8; adjusted by set_tempo()
int env_delay; int env_delay;
@ -76,6 +80,9 @@ inline void Nes_Fds_Apu::volume( double v )
inline void Nes_Fds_Apu::osc_output( int i, Blip_Buffer* buf ) inline void Nes_Fds_Apu::osc_output( int i, Blip_Buffer* buf )
{ {
#ifdef NDEBUG
(void) i;
#endif
assert( (unsigned) i < osc_count ); assert( (unsigned) i < osc_count );
output_ = buf; output_ = buf;
} }

View file

@ -109,7 +109,7 @@ void Nes_Fme7_Apu::run_until( blip_time_t end_time )
// maintain phase when silent // maintain phase when silent
int count = (end_time - time + period - 1) / period; int count = (end_time - time + period - 1) / period;
phases [index] ^= count & 1; phases [index] ^= count & 1;
time += (blargg_long) count * period; time += (int32_t) count * period;
} }
} }

View file

@ -9,7 +9,7 @@
struct fme7_apu_state_t struct fme7_apu_state_t
{ {
enum { reg_count = 14 }; static const unsigned int reg_count = 14;
uint8_t regs [reg_count]; uint8_t regs [reg_count];
uint8_t phases [3]; // 0 or 1 uint8_t phases [3]; // 0 or 1
uint8_t latch; uint8_t latch;
@ -23,16 +23,16 @@ public:
void volume( double ); void volume( double );
void treble_eq( blip_eq_t const& ); void treble_eq( blip_eq_t const& );
void output( Blip_Buffer* ); void output( Blip_Buffer* );
enum { osc_count = 3 }; static const int osc_count = 3;
void osc_output( int index, Blip_Buffer* ); void osc_output( int index, Blip_Buffer* );
void end_frame( blip_time_t ); void end_frame( blip_time_t );
void save_state( fme7_apu_state_t* ) const; void save_state( fme7_apu_state_t* ) const;
void load_state( fme7_apu_state_t const& ); void load_state( fme7_apu_state_t const& );
// Mask and addresses of registers // Mask and addresses of registers
enum { addr_mask = 0xE000 }; static const unsigned int addr_mask = 0xE000;
enum { data_addr = 0xE000 }; static const unsigned int data_addr = 0xE000;
enum { latch_addr = 0xC000 }; static const unsigned int latch_addr = 0xC000;
// (addr & addr_mask) == latch_addr // (addr & addr_mask) == latch_addr
void write_latch( int ); void write_latch( int );
@ -56,7 +56,7 @@ private:
} oscs [osc_count]; } oscs [osc_count];
blip_time_t last_time; blip_time_t last_time;
enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff static const unsigned int amp_range = 192; // can be any value; this gives best error/quality tradeoff
Blip_Synth<blip_good_quality,1> synth; Blip_Synth<blip_good_quality,1> synth;
void run_until( blip_time_t ); void run_until( blip_time_t );

View file

@ -98,7 +98,7 @@ void Nes_Namco_Apu::run_until( blip_time_t nes_end_time )
if ( !volume ) if ( !volume )
continue; continue;
blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0]; int32_t freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
if ( freq < 64 * active_oscs ) if ( freq < 64 * active_oscs )
continue; // prevent low frequencies from excessively delaying freq changes continue; // prevent low frequencies from excessively delaying freq changes
blip_resampled_time_t period = blip_resampled_time_t period =

View file

@ -15,18 +15,18 @@ public:
void volume( double ); void volume( double );
void treble_eq( const blip_eq_t& ); void treble_eq( const blip_eq_t& );
void output( Blip_Buffer* ); void output( Blip_Buffer* );
enum { osc_count = 8 }; static const int osc_count = 8;
void osc_output( int index, Blip_Buffer* ); void osc_output( int index, Blip_Buffer* );
void reset(); void reset();
void end_frame( blip_time_t ); void end_frame( blip_time_t );
// Read/write data register is at 0x4800 // Read/write data register is at 0x4800
enum { data_reg_addr = 0x4800 }; static const unsigned int data_reg_addr = 0x4800;
void write_data( blip_time_t, int ); void write_data( blip_time_t, int );
int read_data(); int read_data();
// Write-only address register is at 0xF800 // Write-only address register is at 0xF800
enum { addr_reg_addr = 0xF800 }; static const unsigned int addr_reg_addr = 0xF800;
void write_addr( int ); void write_addr( int );
// to do: implement save/restore // to do: implement save/restore
@ -42,7 +42,7 @@ private:
Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& ); Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& );
struct Namco_Osc { struct Namco_Osc {
blargg_long delay; int32_t delay;
Blip_Buffer* output; Blip_Buffer* output;
short last_amp; short last_amp;
short wave_pos; short wave_pos;
@ -53,7 +53,7 @@ private:
blip_time_t last_time; blip_time_t last_time;
int addr_reg; int addr_reg;
enum { reg_count = 0x80 }; static const int reg_count = 0x80;
uint8_t reg [reg_count]; uint8_t reg [reg_count];
Blip_Synth<blip_good_quality,15> synth; Blip_Synth<blip_good_quality,15> synth;

View file

@ -87,7 +87,7 @@ inline nes_time_t Nes_Square::maintain_phase( nes_time_t time, nes_time_t end_ti
{ {
int count = (remain + timer_period - 1) / timer_period; int count = (remain + timer_period - 1) / timer_period;
phase = (phase + count) & (phase_range - 1); phase = (phase + count) & (phase_range - 1);
time += (blargg_long) count * timer_period; time += (int32_t) count * timer_period;
} }
return time; return time;
} }
@ -196,7 +196,7 @@ inline nes_time_t Nes_Triangle::maintain_phase( nes_time_t time, nes_time_t end_
int count = (remain + timer_period - 1) / timer_period; int count = (remain + timer_period - 1) / timer_period;
phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1); phase = ((unsigned) phase + 1 - count) & (phase_range * 2 - 1);
phase++; phase++;
time += (blargg_long) count * timer_period; time += (int32_t) count * timer_period;
} }
return time; return time;
} }

View file

@ -72,7 +72,7 @@ void Nes_Vrc6_Apu::end_frame( blip_time_t time )
void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const void Nes_Vrc6_Apu::save_state( vrc6_apu_state_t* out ) const
{ {
assert( sizeof (vrc6_apu_state_t) == 20 ); blaarg_static_assert( sizeof (vrc6_apu_state_t) == 20, "VRC APU State layout incorrect!" );
out->saw_amp = oscs [2].amp; out->saw_amp = oscs [2].amp;
for ( int i = 0; i < osc_count; i++ ) for ( int i = 0; i < osc_count; i++ )
{ {

View file

@ -1,7 +1,7 @@
#include "Nes_Vrc7_Apu.h" #include "Nes_Vrc7_Apu.h"
extern "C" { extern "C" {
#include "../ext/emu2413.h" #include "ext/emu2413.h"
} }
#include <string.h> #include <string.h>
@ -10,10 +10,10 @@ extern "C" {
static unsigned char vrc7_inst[(16 + 3) * 8] = static unsigned char vrc7_inst[(16 + 3) * 8] =
{ {
#include "../ext/vrc7tone.h" #include "ext/vrc7tone.h"
}; };
int const period = 36; // NES CPU clocks per FM clock static int const period = 36; // NES CPU clocks per FM clock
Nes_Vrc7_Apu::Nes_Vrc7_Apu() Nes_Vrc7_Apu::Nes_Vrc7_Apu()
{ {

View file

@ -29,14 +29,14 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const vrc6_flag = 0x01; static int const vrc6_flag = 0x01;
int const vrc7_flag = 0x02; static int const vrc7_flag = 0x02;
int const fds_flag = 0x04; static int const fds_flag = 0x04;
int const mmc5_flag = 0x08; static int const mmc5_flag = 0x08;
int const namco_flag = 0x10; static int const namco_flag = 0x10;
int const fme7_flag = 0x20; static int const fme7_flag = 0x20;
long const clock_divisor = 12; static long const clock_divisor = 12;
using std::min; using std::min;
using std::max; using std::max;
@ -205,6 +205,7 @@ blargg_err_t Nsf_Emu::init_sound()
apu_names[count + 2] = "Triangle"; apu_names[count + 2] = "Triangle";
apu_names[count + 3] = "Noise"; apu_names[count + 3] = "Noise";
apu_names[count + 4] = "DMC"; apu_names[count + 4] = "DMC";
apu_names[count + 5] = "FM";
count += Nes_Apu::osc_count; count += Nes_Apu::osc_count;
} }
@ -311,9 +312,6 @@ blargg_err_t Nsf_Emu::init_sound()
count += Nes_Vrc7_Apu::osc_count; count += Nes_Vrc7_Apu::osc_count;
} }
set_voice_count( count );
set_voice_names( &apu_names[0] );
if ( namco ) namco->volume( adjusted_gain ); if ( namco ) namco->volume( adjusted_gain );
if ( vrc6 ) vrc6 ->volume( adjusted_gain ); if ( vrc6 ) vrc6 ->volume( adjusted_gain );
if ( fme7 ) fme7 ->volume( adjusted_gain ); if ( fme7 ) fme7 ->volume( adjusted_gain );
@ -323,6 +321,9 @@ blargg_err_t Nsf_Emu::init_sound()
} }
#endif #endif
set_voice_count( count );
set_voice_names( &apu_names[0] );
apu.volume( adjusted_gain ); apu.volume( adjusted_gain );
return 0; return 0;
@ -330,7 +331,7 @@ blargg_err_t Nsf_Emu::init_sound()
blargg_err_t Nsf_Emu::load_( Data_Reader& in ) blargg_err_t Nsf_Emu::load_( Data_Reader& in )
{ {
assert( offsetof (header_t,unused [4]) == header_size ); blaarg_static_assert( offsetof (header_t,unused [4]) == header_size, "NSF Header layout incorrect!" );
RETURN_ERR( rom.load( in, header_size, &header_, 0 ) ); RETURN_ERR( rom.load( in, header_size, &header_, 0 ) );
set_track_count( header_.track_count ); set_track_count( header_.track_count );
@ -561,6 +562,9 @@ void Nsf_Emu::cpu_write_misc( nes_addr_t addr, int data )
// memory mapper? // memory mapper?
if ( addr == 0xFFF8 ) return; if ( addr == 0xFFF8 ) return;
// FDS memory
if ( fds && (unsigned) (addr - 0x8000) < 0x6000 ) return;
debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data ); debug_printf( "write_unmapped( 0x%04X, 0x%02X )\n", (unsigned) addr, (unsigned) data );
} }
#endif #endif
@ -578,6 +582,30 @@ blargg_err_t Nsf_Emu::start_track_( int track )
for ( int i = 0; i < bank_count; ++i ) for ( int i = 0; i < bank_count; ++i )
cpu_write( bank_select_addr + i, initial_banks [i] ); cpu_write( bank_select_addr + i, initial_banks [i] );
if (fds)
{
memset( fds->sram, 0, sizeof fds->sram );
// For FDS the initial load values at $076 and $077
// specify the banks used for $6000-7FFF as well as $E000-FFFF
cpu_write( bank_select_addr - 2, initial_banks [bank_count - 2] );
cpu_write( bank_select_addr - 1, initial_banks [bank_count - 1] );
for ( int i = 0; i < bank_count; ++i )
{
byte* out = fds->sram;
unsigned bank = i;
if ( bank >= 6 )
{
out = sram;
bank -= 6;
}
int32_t offset = rom.mask_addr( initial_banks [i] * (int32_t) bank_size );
if ( offset >= rom.size() )
set_warning( "Invalid bank" );
memcpy( &out [bank * bank_size], rom.at_addr( offset ), bank_size );
}
cpu::map_code( fds->sram_addr, sizeof fds->sram, fds->sram );
}
apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 ); apu.reset( pal_only, (header_.speed_flags & 0x20) ? 0x3F : 0 );
apu.write_register( 0, 0x4015, 0x0F ); apu.write_register( 0, 0x4015, 0x0F );
apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 ); apu.write_register( 0, 0x4017, (header_.speed_flags & 0x10) ? 0x80 : 0 );

View file

@ -96,7 +96,7 @@ struct nsfe_info_t
blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu ) blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
{ {
int const nsfe_info_size = 16; int const nsfe_info_size = 16;
assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size ); blaarg_static_assert( offsetof (nsfe_info_t,unused [6]) == nsfe_info_size, "NSFE Info header layout incorrect!" );
// check header // check header
byte signature [4]; byte signature [4];
@ -136,8 +136,8 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
// read size and tag // read size and tag
byte block_header [2] [4]; byte block_header [2] [4];
RETURN_ERR( in.read( block_header, sizeof block_header ) ); RETURN_ERR( in.read( block_header, sizeof block_header ) );
blargg_long size = get_le32( block_header [0] ); int32_t size = get_le32( block_header [0] );
blargg_long tag = get_le32( block_header [1] ); int32_t tag = get_le32( block_header [1] );
if ( size < 0 ) if ( size < 0 )
return "Corrupt file"; return "Corrupt file";
@ -155,7 +155,7 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
finfo.track_count = 1; finfo.track_count = 1;
finfo.first_track = 0; finfo.first_track = 0;
RETURN_ERR( in.read( &finfo, min( size, (blargg_long) nsfe_info_size ) ) ); RETURN_ERR( in.read( &finfo, min( size, (int32_t) nsfe_info_size ) ) );
if ( size > nsfe_info_size ) if ( size > nsfe_info_size )
RETURN_ERR( in.skip( size - nsfe_info_size ) ); RETURN_ERR( in.skip( size - nsfe_info_size ) );
phase = 1; phase = 1;

View file

@ -17,11 +17,11 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const max_frequency = 12000; // pure waves above this frequency are silenced static int const max_frequency = 12000; // pure waves above this frequency are silenced
static void gen_poly( blargg_ulong mask, int count, byte* out ) static void gen_poly( uint32_t mask, int count, byte* out )
{ {
blargg_ulong n = 1; uint32_t n = 1;
do do
{ {
int bits = 0; int bits = 0;
@ -30,7 +30,7 @@ static void gen_poly( blargg_ulong mask, int count, byte* out )
{ {
// implemented using "Galios configuration" // implemented using "Galios configuration"
bits |= (n & 1) << b; bits |= (n & 1) << b;
n = (n >> 1) ^ (mask & -(n & 1)); n = (n >> 1) ^ (mask & uMinus(n & 1));
} }
while ( b++ < 7 ); while ( b++ < 7 );
*out++ = bits; *out++ = bits;
@ -39,11 +39,11 @@ static void gen_poly( blargg_ulong mask, int count, byte* out )
} }
// poly5 // poly5
int const poly5_len = (1 << 5) - 1; static int const poly5_len = (1 << 5) - 1;
blargg_ulong const poly5_mask = (1UL << poly5_len) - 1; static uint32_t const poly5_mask = (1UL << poly5_len) - 1;
blargg_ulong const poly5 = 0x167C6EA1; static uint32_t const poly5 = 0x167C6EA1;
inline blargg_ulong run_poly5( blargg_ulong in, int shift ) static inline uint32_t run_poly5( uint32_t in, int shift )
{ {
return (in << shift & poly5_mask) | (in >> (poly5_len - shift)); return (in << shift & poly5_mask) | (in >> (poly5_len - shift));
} }
@ -61,12 +61,12 @@ Sap_Apu_Impl::Sap_Apu_Impl()
{ {
byte poly5 [4]; byte poly5 [4];
gen_poly( POLY_MASK( 5, 2, 0 ), sizeof poly5, poly5 ); gen_poly( POLY_MASK( 5, 2, 0 ), sizeof poly5, poly5 );
blargg_ulong n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L + uint32_t n = poly5 [3] * 0x1000000L + poly5 [2] * 0x10000L +
poly5 [1] * 0x100L + poly5 [0]; poly5 [1] * 0x100L + poly5 [0];
blargg_ulong rev = n & 1; uint32_t rev = n & 1;
for ( int i = 1; i < poly5_len; i++ ) for ( int i = 1; i < poly5_len; i++ )
rev |= (n >> i & 1) << (poly5_len - i); rev |= (n >> i & 1) << (poly5_len - i);
debug_printf( "poly5: 0x%08lX\n", rev ); debug_printf( "poly5: 0x%08lX\n", (long unsigned int)rev );
} }
} }
@ -102,7 +102,7 @@ inline void Sap_Apu::calc_periods()
osc_t* const osc = &oscs [i]; osc_t* const osc = &oscs [i];
int const osc_reload = osc->regs [0]; // cache int const osc_reload = osc->regs [0]; // cache
blargg_long period = (osc_reload + 1) * divider; int32_t period = (osc_reload + 1) * divider;
static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 }; static byte const fast_bits [osc_count] = { 1 << 6, 1 << 4, 1 << 5, 1 << 3 };
if ( this->control & fast_bits [i] ) if ( this->control & fast_bits [i] )
{ {
@ -208,7 +208,7 @@ void Sap_Apu::run_until( blip_time_t end_time )
poly_inc -= poly_len; // allows more optimized inner loop below poly_inc -= poly_len; // allows more optimized inner loop below
// square/poly5 wave // square/poly5 wave
blargg_ulong wave = poly5; uint32_t wave = poly5;
check( poly5 & 1 ); // low bit is set for pure wave check( poly5 & 1 ); // low bit is set for pure wave
int poly5_inc = 0; int poly5_inc = 0;
if ( !(osc_control & 0x80) ) if ( !(osc_control & 0x80) )
@ -281,7 +281,7 @@ void Sap_Apu::run_until( blip_time_t end_time )
blip_time_t remain = end_time - time; blip_time_t remain = end_time - time;
if ( remain > 0 ) if ( remain > 0 )
{ {
blargg_long count = (remain + period - 1) / period; int32_t count = (remain + period - 1) / period;
osc->phase ^= count; osc->phase ^= count;
time += count * period; time += count * period;
} }

View file

@ -11,13 +11,13 @@ class Sap_Apu_Impl;
class Sap_Apu { class Sap_Apu {
public: public:
enum { osc_count = 4 }; static const int osc_count = 4;
void osc_output( int index, Blip_Buffer* ); void osc_output( int index, Blip_Buffer* );
void reset( Sap_Apu_Impl* ); void reset( Sap_Apu_Impl* );
enum { start_addr = 0xD200 }; static const unsigned int start_addr = 0xD200;
enum { end_addr = 0xD209 }; static const unsigned int end_addr = 0xD209;
void write_data( blip_time_t, unsigned addr, int data ); void write_data( blip_time_t, unsigned addr, int data );
void end_frame( blip_time_t ); void end_frame( blip_time_t );
@ -46,9 +46,9 @@ private:
void calc_periods(); void calc_periods();
void run_until( blip_time_t ); void run_until( blip_time_t );
enum { poly4_len = (1L << 4) - 1 }; static const unsigned int poly4_len = (1L << 4) - 1;
enum { poly9_len = (1L << 9) - 1 }; static const unsigned int poly9_len = (1L << 9) - 1;
enum { poly17_len = (1L << 17) - 1 }; static const unsigned int poly17_len = (1L << 17) - 1;
friend class Sap_Apu_Impl; friend class Sap_Apu_Impl;
}; };

View file

@ -29,14 +29,16 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
int const st_n = 0x80; enum {
int const st_v = 0x40; st_n = 0x80,
int const st_r = 0x20; st_v = 0x40,
int const st_b = 0x10; st_r = 0x20,
int const st_d = 0x08; st_b = 0x10,
int const st_i = 0x04; st_d = 0x08,
int const st_z = 0x02; st_i = 0x04,
int const st_c = 0x01; st_z = 0x02,
st_c = 0x01
};
void Sap_Cpu::reset( void* new_mem ) void Sap_Cpu::reset( void* new_mem )
{ {
@ -797,7 +799,7 @@ imm##op:
sap_time_t new_time = end_time_; sap_time_t new_time = end_time_;
if ( !(status & st_i) && new_time > irq_time_ ) if ( !(status & st_i) && new_time > irq_time_ )
new_time = irq_time_; new_time = irq_time_;
blargg_long delta = s.base - new_time; int32_t delta = s.base - new_time;
s.base = new_time; s.base = new_time;
s_time += delta; s_time += delta;
} }
@ -862,7 +864,7 @@ imm##op:
status &= ~st_i; status &= ~st_i;
handle_cli: { handle_cli: {
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - irq_time_; int32_t delta = s.base - irq_time_;
if ( delta <= 0 ) if ( delta <= 0 )
{ {
if ( TIME < irq_time_ ) if ( TIME < irq_time_ )
@ -893,7 +895,7 @@ imm##op:
status |= st_i; status |= st_i;
handle_sei: { handle_sei: {
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
s.base = end_time_; s.base = end_time_;
s_time += delta; s_time += delta;
if ( s_time < 0 ) if ( s_time < 0 )
@ -960,7 +962,7 @@ interrupt:
status |= st_i; status |= st_i;
this->r.status = status; // update externally-visible I flag this->r.status = status; // update externally-visible I flag
blargg_long delta = s.base - end_time_; int32_t delta = s.base - end_time_;
s.base = end_time_; s.base = end_time_;
s_time += delta; s_time += delta;
goto loop; goto loop;

View file

@ -6,7 +6,7 @@
#include "blargg_common.h" #include "blargg_common.h"
typedef blargg_long sap_time_t; // clock cycle count typedef int32_t sap_time_t; // clock cycle count
typedef unsigned sap_addr_t; // 16-bit address typedef unsigned sap_addr_t; // 16-bit address
enum { future_sap_time = INT_MAX / 2 + 1 }; enum { future_sap_time = INT_MAX / 2 + 1 };

View file

@ -19,7 +19,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
long const base_scanline_period = 114; static long const base_scanline_period = 114;
using std::min; using std::min;
using std::max; using std::max;
@ -259,7 +259,7 @@ blargg_err_t Sap_Emu::load_mem_( byte const* in, long size )
set_warning( info.warning ); set_warning( info.warning );
set_track_count( info.track_count ); set_track_count( info.track_count );
set_voice_count( Sap_Apu::osc_count << info.stereo ); set_voice_count( Sap_Apu::osc_count << static_cast<int>(info.stereo) );
apu_impl.volume( gain() ); apu_impl.volume( gain() );
return setup_buffer( 1773447 ); return setup_buffer( 1773447 );

View file

@ -141,7 +141,7 @@ void Sms_Noise::run( blip_time_t time, blip_time_t end_time )
do do
{ {
int changed = shifter + 1; int changed = shifter + 1;
shifter = (feedback & -(shifter & 1)) ^ (shifter >> 1); shifter = (feedback & uMinus(shifter & 1)) ^ (shifter >> 1);
if ( changed & 2 ) // true if bits 0 and 1 differ if ( changed & 2 ) // true if bits 0 and 1 differ
{ {
delta = -delta; delta = -delta;

View file

@ -217,7 +217,7 @@ blargg_err_t Snes_Spc::load_spc( void const* data, long size )
spc_file_t const* const spc = (spc_file_t const*) data; spc_file_t const* const spc = (spc_file_t const*) data;
// be sure compiler didn't insert any padding into fle_t // be sure compiler didn't insert any padding into fle_t
assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); blaarg_static_assert( sizeof (spc_file_t) == spc_min_file_size + 0x80, "SPC File header layout incorrect!" );
// Check signature and file size // Check signature and file size
if ( size < signature_size || memcmp( spc, signature, 27 ) ) if ( size < signature_size || memcmp( spc, signature, 27 ) )

View file

@ -63,8 +63,10 @@ public:
// Only supported by fast DSP. // Only supported by fast DSP.
void disable_surround( bool disable = true ); void disable_surround( bool disable = true );
void disable_echo( bool disable = true );
// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
enum { tempo_unit = 0x100 }; static const unsigned int tempo_unit = 0x100;
void set_tempo( int ); void set_tempo( int );
// SPC music files // SPC music files
@ -276,6 +278,8 @@ inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); }
inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); } inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
inline void Snes_Spc::disable_echo( bool disable ) { dsp.disable_echo( disable ); }
#if !SPC_NO_COPY_STATE_FUNCS #if !SPC_NO_COPY_STATE_FUNCS
inline bool Snes_Spc::check_kon() { return dsp.check_kon(); } inline bool Snes_Spc::check_kon() { return dsp.check_kon(); }
#endif #endif

View file

@ -94,7 +94,7 @@ void Snes_Spc::enable_rom( int enable )
//// DSP //// DSP
#if SPC_LESS_ACCURATE #if SPC_LESS_ACCURATE
int const max_reg_time = 29; static int const max_reg_time = 29;
signed char const Snes_Spc::reg_times_ [256] = signed char const Snes_Spc::reg_times_ [256] =
{ {
@ -224,56 +224,62 @@ inline void Snes_Spc::dsp_write( int data, rel_time_t time )
#if SPC_MORE_ACCURACY #if SPC_MORE_ACCURACY
static unsigned char const glitch_probs [3] [256] = static unsigned char const glitch_probs [3] [256] =
{ {
0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, {
0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B,
0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08,
0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09,
0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01,
0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05,
0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07,
0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07,
0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01,
0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09,
0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08,
0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03,
0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03,
0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07,
0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02,
0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02,
0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01
},
0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, {
0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07,
0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06,
0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09,
0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03,
0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07,
0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03,
0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06,
0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03,
0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05,
0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04,
0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05,
0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01,
0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05,
0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01,
0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03,
0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01
},
0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, {
0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A,
0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A,
0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A,
0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09,
0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09,
0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02,
0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07,
0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04,
0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A,
0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07,
0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04,
0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02,
0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06,
0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03,
0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02,
0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03
}
}; };
#endif #endif
@ -282,7 +288,7 @@ static unsigned char const glitch_probs [3] [256] =
// by compiler. // by compiler.
// If write isn't preceded by read, data has this added to it // If write isn't preceded by read, data has this added to it
int const no_read_before_write = 0x2000; static int const no_read_before_write = 0x2000;
void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, uint16_t addr ) void Snes_Spc::cpu_write_smp_reg_( int data, rel_time_t time, uint16_t addr )
{ {
@ -516,7 +522,7 @@ uint8_t* Snes_Spc::run_until_( time_t end_time )\
#ifndef NDEBUG #ifndef NDEBUG
// Used only for assert // Used only for assert
int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks static int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
#endif #endif

View file

@ -155,7 +155,7 @@ inline void Spc_Dsp::init_counter()
// counters start out with this synchronization // counters start out with this synchronization
m.counters [0] = 1; m.counters [0] = 1;
m.counters [1] = 0; m.counters [1] = 0;
m.counters [2] = -0x20u; m.counters [2] = uMinus(0x20u);
m.counters [3] = 0x0B; m.counters [3] = 0x0B;
int n = 2; int n = 2;
@ -202,6 +202,17 @@ void Spc_Dsp::run( int clock_count )
// Global volume // Global volume
int mvoll = (int8_t) REG(mvoll); int mvoll = (int8_t) REG(mvoll);
int mvolr = (int8_t) REG(mvolr); int mvolr = (int8_t) REG(mvolr);
int evoll = (int8_t) REG(evoll);
int evolr = (int8_t) REG(evolr);
if ( !m.echo_enable)
{
mvoll = 127;
mvolr = 127;
evoll = 0;
evolr = 0;
}
if ( mvoll * mvolr < m.surround_threshold ) if ( mvoll * mvolr < m.surround_threshold )
mvoll = -mvoll; // eliminate surround mvoll = -mvoll; // eliminate surround
@ -615,8 +626,8 @@ skip_brr:
} }
// Sound out // Sound out
int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14; int l = (main_out_l * mvoll + echo_in_l * evoll) >> 14;
int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14; int r = (main_out_r * mvolr + echo_in_r * evolr) >> 14;
CLAMP16( l ); CLAMP16( l );
CLAMP16( r ); CLAMP16( r );
@ -647,21 +658,27 @@ void Spc_Dsp::mute_voices( int mask )
} }
} }
Spc_Dsp::Spc_Dsp()
{
memset(&m, 0, sizeof(state_t));
}
void Spc_Dsp::init( void* ram_64k ) void Spc_Dsp::init( void* ram_64k )
{ {
m.ram = (uint8_t*) ram_64k; m.ram = (uint8_t*) ram_64k;
mute_voices( 0 ); mute_voices( 0 );
disable_surround( false ); disable_surround( false );
disable_echo( false );
set_output( 0, 0 ); set_output( 0, 0 );
reset(); reset();
// be sure this sign-extends
blaarg_static_assert( (int16_t) 0x8000 == -0x8000, "This compiler doesn't sign-extend during integer promotion" );
// be sure right shift preserves sign
blaarg_static_assert( (-1 >> 1) == -1, "This compiler doesn't preserve sign on right-shift" );
#ifndef NDEBUG #ifndef NDEBUG
// be sure this sign-extends
assert( (int16_t) 0x8000 == -0x8000 );
// be sure right shift preserves sign
assert( (-1 >> 1) == -1 );
// check clamp macro // check clamp macro
int i; int i;
i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );

View file

@ -8,6 +8,7 @@
struct Spc_Dsp { struct Spc_Dsp {
public: public:
Spc_Dsp();
// Setup // Setup
// Initializes DSP and has it use the 64K RAM provided // Initializes DSP and has it use the 64K RAM provided
@ -50,6 +51,8 @@ public:
// If true, prevents channels and global volumes from being phase-negated // If true, prevents channels and global volumes from being phase-negated
void disable_surround( bool disable = true ); void disable_surround( bool disable = true );
void disable_echo( bool disable = true );
// State // State
// Resets DSP and uses supplied values to initialize registers // Resets DSP and uses supplied values to initialize registers
@ -138,6 +141,7 @@ private:
uint8_t* ram; // 64K shared RAM between DSP and SMP uint8_t* ram; // 64K shared RAM between DSP and SMP
int mute_mask; int mute_mask;
int surround_threshold; int surround_threshold;
int echo_enable;
sample_t* out; sample_t* out;
sample_t* out_end; sample_t* out_end;
sample_t* out_begin; sample_t* out_begin;
@ -205,6 +209,11 @@ inline void Spc_Dsp::disable_surround( bool disable )
m.surround_threshold = disable ? 0 : -0x4000; m.surround_threshold = disable ? 0 : -0x4000;
} }
inline void Spc_Dsp::disable_echo( bool disable )
{
m.echo_enable = !disable;
}
#define SPC_NO_COPY_STATE_FUNCS 1 #define SPC_NO_COPY_STATE_FUNCS 1
#define SPC_LESS_ACCURATE 1 #define SPC_LESS_ACCURATE 1

View file

@ -7,16 +7,6 @@
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#ifdef RARDLL
#define PASCAL
#define CALLBACK
#define LONG long
#define HANDLE void *
#define LPARAM intptr_t
#define UINT __attribute__((unused)) unsigned int
#include <dll.hpp>
#endif
/* Copyright (C) 2004-2009 Shay Green. This module is free software; you /* Copyright (C) 2004-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser 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 General Public License as published by the Free Software Foundation; either
@ -35,9 +25,9 @@ using std::max;
// TODO: support Spc_Filter's bass // TODO: support Spc_Filter's bass
Spc_Emu::Spc_Emu( gme_type_t type ) Spc_Emu::Spc_Emu()
{ {
set_type( type ); set_type( gme_spc_type );
static const char* const names [SuperFamicom::SPC_DSP::voice_count] = { static const char* const names [SuperFamicom::SPC_DSP::voice_count] = {
"DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8" "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", "DSP 8"
@ -60,19 +50,6 @@ byte const* Spc_Emu::trailer() const { return &file_data [min( file_size, spc_si
long Spc_Emu::trailer_size() const { return max( 0L, file_size - spc_size ); } long Spc_Emu::trailer_size() const { return max( 0L, file_size - spc_size ); }
byte const* Rsn_Emu::trailer( int track ) const
{
const byte *track_data = spc[track];
long track_size = spc[track + 1] - spc[track];
return &track_data [min( track_size, spc_size )];
}
long Rsn_Emu::trailer_size( int track ) const
{
long track_size = spc[track + 1] - spc[track];
return max( 0L, track_size - spc_size );
}
static void get_spc_xid6( byte const* begin, long size, track_info_t* out ) static void get_spc_xid6( byte const* begin, long size, track_info_t* out )
{ {
// header // header
@ -284,12 +261,6 @@ blargg_err_t Spc_Emu::track_info_( track_info_t* out, int ) const
return 0; return 0;
} }
blargg_err_t Rsn_Emu::track_info_( track_info_t* out, int track ) const
{
get_spc_info( header( track ), trailer( track ), trailer_size( track ), out );
return 0;
}
static blargg_err_t check_spc_header( void const* header ) static blargg_err_t check_spc_header( void const* header )
{ {
if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) ) if ( memcmp( header, "SNES-SPC700 Sound File Data", 27 ) )
@ -302,14 +273,11 @@ struct Spc_File : Gme_Info_
Spc_Emu::header_t header; Spc_Emu::header_t header;
blargg_vector<byte> xid6; blargg_vector<byte> xid6;
Spc_File( gme_type_t type ) { set_type( type ); } Spc_File() { set_type( gme_spc_type ); }
Spc_File() : Spc_File( gme_spc_type ) {}
blargg_err_t load_( Data_Reader& in ) blargg_err_t load_( Data_Reader& in )
{ {
long file_size = in.remain(); long file_size = in.remain();
if ( is_archive )
return 0;
if ( file_size < 0x10180 ) if ( file_size < 0x10180 )
return gme_wrong_file_type; return gme_wrong_file_type;
RETURN_ERR( in.read( &header, head_size ) ); RETURN_ERR( in.read( &header, head_size ) );
@ -338,106 +306,6 @@ static gme_type_t_ const gme_spc_type_ = { "Super Nintendo", 1, &new_spc_emu, &n
extern gme_type_t const gme_spc_type = &gme_spc_type_; extern gme_type_t const gme_spc_type = &gme_spc_type_;
#ifdef RARDLL
static int CALLBACK call_rsn(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2)
{
byte **bp = (byte **)UserData;
unsigned char *addr = (unsigned char *)P1;
memcpy( *bp, addr, P2 );
*bp += P2;
return 0;
}
#endif
struct Rsn_File : Spc_File
{
blargg_vector<byte*> spc;
Rsn_File() : Spc_File( gme_rsn_type ) { is_archive = true; }
blargg_err_t load_archive( const char* path )
{
#ifdef RARDLL
struct RAROpenArchiveData data = {
.ArcName = (char *)path,
.OpenMode = RAR_OM_LIST, .OpenResult = 0,
.CmtBuf = 0, .CmtBufSize = 0, .CmtSize = 0, .CmtState = 0
};
// get the size of all unpacked headers combined
long pos = 0;
int count = 0;
unsigned biggest = 0;
blargg_vector<byte> temp;
HANDLE PASCAL rar = RAROpenArchive( &data );
struct RARHeaderData head;
for ( ; RARReadHeader( rar, &head ) == ERAR_SUCCESS; count++ )
{
RARProcessFile( rar, RAR_SKIP, 0, 0 );
long xid6_size = head.UnpSize - spc_size;
if ( xid6_size > 0 )
pos += xid6_size;
pos += head_size;
biggest = max( biggest, head.UnpSize );
}
xid6.resize( pos );
spc.resize( count + 1 );
temp.resize( biggest );
RARCloseArchive( rar );
// copy the headers/xid6 and index them
byte *bp;
data.OpenMode = RAR_OM_EXTRACT;
rar = RAROpenArchive( &data );
RARSetCallback( rar, call_rsn, (intptr_t)&bp );
for ( count = 0, pos = 0; RARReadHeader( rar, &head ) == ERAR_SUCCESS; )
{
bp = &temp[0];
RARProcessFile( rar, RAR_TEST, 0, 0 );
if ( !check_spc_header( bp - head.UnpSize ) )
{
spc[count++] = &xid6[pos];
memcpy( &xid6[pos], &temp[0], head_size );
pos += head_size;
long xid6_size = head.UnpSize - spc_size;
if ( xid6_size > 0 )
{
memcpy( &xid6[pos], &temp[spc_size], xid6_size );
pos += xid6_size;
}
}
}
spc[count] = &xid6[pos];
set_track_count( count );
RARCloseArchive( rar );
return 0;
#else
(void) path;
return gme_wrong_file_type;
#endif
}
blargg_err_t track_info_( track_info_t* out, int track ) const
{
if ( static_cast<size_t>(track) >= spc.size() )
return "Invalid track";
long xid6_size = spc[track + 1] - ( spc[track] + head_size );
get_spc_info(
*(Spc_Emu::header_t const*) spc[track],
spc[track] + head_size, xid6_size, out
);
return 0;
}
};
static Music_Emu* new_rsn_emu () { return BLARGG_NEW Rsn_Emu ; }
static Music_Emu* new_rsn_file() { return BLARGG_NEW Rsn_File; }
static gme_type_t_ const gme_rsn_type_ = { "Super Nintendo", 0, &new_rsn_emu, &new_rsn_file, "RSN", 0 };
extern gme_type_t const gme_rsn_type = &gme_rsn_type_;
// Setup // Setup
blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate ) blargg_err_t Spc_Emu::set_sample_rate_( long sample_rate )
@ -466,14 +334,17 @@ void Spc_Emu::mute_voices_( int m )
smp.dsp.channel_enable( i, !( m & j ) ); smp.dsp.channel_enable( i, !( m & j ) );
} }
void Spc_Emu::disable_echo_( bool disable )
{
smp.dsp.spc_dsp.enable_echo( !disable );
}
blargg_err_t Spc_Emu::load_mem_( byte const* in, long size ) blargg_err_t Spc_Emu::load_mem_( byte const* in, long size )
{ {
assert( offsetof (header_t,unused2 [46]) == header_size ); blaarg_static_assert( offsetof (header_t,unused2 [46]) == header_size, "SPC Header layout incorrect!" );
file_data = in; file_data = in;
file_size = size; file_size = size;
set_voice_count( SuperFamicom::SPC_DSP::voice_count ); set_voice_count( SuperFamicom::SPC_DSP::voice_count );
if ( is_archive )
return 0;
if ( size < 0x10180 ) if ( size < 0x10180 )
return gme_wrong_file_type; return gme_wrong_file_type;
return check_spc_header( in ); return check_spc_header( in );
@ -602,60 +473,3 @@ blargg_err_t Spc_Emu::play_( long count, sample_t* out )
check( remain == 0 ); check( remain == 0 );
return 0; return 0;
} }
blargg_err_t Rsn_Emu::load_archive( const char* path )
{
#ifdef RARDLL
struct RAROpenArchiveData data = {
.ArcName = (char *)path,
.OpenMode = RAR_OM_LIST, .OpenResult = 0,
.CmtBuf = 0, .CmtBufSize = 0, .CmtSize = 0, .CmtState = 0
};
// get the file count and unpacked size
long pos = 0;
int count = 0;
HANDLE PASCAL rar = RAROpenArchive( &data );
struct RARHeaderData head;
for ( ; RARReadHeader( rar, &head ) == ERAR_SUCCESS; count++ )
{
RARProcessFile( rar, RAR_SKIP, 0, 0 );
pos += head.UnpSize;
}
rsn.resize( pos );
spc.resize( count + 1 );
RARCloseArchive( rar );
// copy the stream and index the tracks
byte *bp = &rsn[0];
data.OpenMode = RAR_OM_EXTRACT;
rar = RAROpenArchive( &data );
RARSetCallback( rar, call_rsn, (intptr_t)&bp );
for ( count = 0, pos = 0; RARReadHeader( rar, &head ) == ERAR_SUCCESS; )
{
RARProcessFile( rar, RAR_TEST, 0, 0 );
if ( !check_spc_header( bp - head.UnpSize ) )
spc[count++] = &rsn[pos];
pos += head.UnpSize;
}
spc[count] = &rsn[pos];
set_track_count( count );
RARCloseArchive( rar );
return 0;
#else
(void) path;
return gme_wrong_file_type;
#endif
}
blargg_err_t Rsn_Emu::start_track_( int track )
{
if ( static_cast<size_t>(track) >= spc.size() )
return "Invalid track requested";
file_data = spc[track];
file_size = spc[track + 1] - spc[track];
return Spc_Emu::start_track_( track );
}
Rsn_Emu::~Rsn_Emu() { }

View file

@ -66,8 +66,7 @@ public:
long trailer_size() const; long trailer_size() const;
public: public:
Spc_Emu( gme_type_t ); Spc_Emu();
Spc_Emu() : Spc_Emu( gme_spc_type ) {}
~Spc_Emu(); ~Spc_Emu();
protected: protected:
blargg_err_t load_mem_( byte const*, long ); blargg_err_t load_mem_( byte const*, long );
@ -77,11 +76,12 @@ protected:
blargg_err_t play_( long, sample_t* ); blargg_err_t play_( long, sample_t* );
blargg_err_t skip_( long ); blargg_err_t skip_( long );
void mute_voices_( int ); void mute_voices_( int );
void disable_echo_( bool disable );
void set_tempo_( double ); void set_tempo_( double );
void enable_accuracy_( bool ); void enable_accuracy_( bool );
private:
byte const* file_data; byte const* file_data;
long file_size; long file_size;
private:
Fir_Resampler<24> resampler; Fir_Resampler<24> resampler;
SPC_Filter filter; SPC_Filter filter;
SuperFamicom::SMP smp; SuperFamicom::SMP smp;
@ -96,20 +96,4 @@ inline void Spc_Emu::mute_effects( bool mute ) { enable_echo(!mute); }
inline SuperFamicom::SMP const* Spc_Emu::get_smp() const { return &smp; } inline SuperFamicom::SMP const* Spc_Emu::get_smp() const { return &smp; }
inline SuperFamicom::SMP * Spc_Emu::get_smp() { return &smp; } inline SuperFamicom::SMP * Spc_Emu::get_smp() { return &smp; }
class Rsn_Emu : public Spc_Emu {
public:
Rsn_Emu() : Spc_Emu( gme_rsn_type ) { is_archive = true; }
~Rsn_Emu();
blargg_err_t load_archive( const char* );
header_t const& header( int track ) const { return *(header_t const*) spc[track]; }
byte const* trailer( int ) const; // use track_info()
long trailer_size( int ) const;
protected:
blargg_err_t track_info_( track_info_t*, int ) const;
blargg_err_t start_track_( int );
private:
blargg_vector<byte> rsn;
blargg_vector<byte*> spc;
};
#endif #endif

View file

@ -20,23 +20,23 @@ public:
// Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit
// are fine, since output is clamped to 16-bit sample range. // are fine, since output is clamped to 16-bit sample range.
enum { gain_unit = 0x100 }; static const unsigned int gain_unit = 0x100;
void set_gain( int gain ); void set_gain( int gain );
// Enables/disables filtering (when disabled, gain is still applied) // Enables/disables filtering (when disabled, gain is still applied)
void enable( bool b ); void enable( bool b );
// Sets amount of bass (logarithmic scale) // Sets amount of bass (logarithmic scale)
enum { bass_none = 0 }; static const unsigned int bass_none = 0;
enum { bass_norm = 8 }; // normal amount static const unsigned int bass_norm = 8; // normal amount
enum { bass_max = 31 }; static const unsigned int bass_max = 31;
void set_bass( int bass ); void set_bass( int bass );
public: public:
SPC_Filter(); SPC_Filter();
BLARGG_DISABLE_NOTHROW BLARGG_DISABLE_NOTHROW
private: private:
enum { gain_bits = 8 }; static const unsigned int gain_bits = 8;
int gain; int gain;
int bass; int bass;
bool enabled; bool enabled;

View file

@ -20,9 +20,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h" #include "blargg_source.h"
double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow static double const fm_gain = 3.0; // FM emulators are internally quieter to avoid 16-bit overflow
double const rolloff = 0.990; static double const rolloff = 0.990;
double const oversample_factor = 1.0; static double const oversample_factor = 1.0;
using std::min; using std::min;
using std::max; using std::max;
@ -30,6 +30,8 @@ using std::max;
Vgm_Emu::Vgm_Emu() Vgm_Emu::Vgm_Emu()
{ {
disable_oversampling_ = false; disable_oversampling_ = false;
psg_dual = false;
psg_t6w28 = false;
psg_rate = 0; psg_rate = 0;
set_type( gme_vgm_type ); set_type( gme_vgm_type );
@ -88,7 +90,7 @@ static void parse_gd3( byte const* in, byte const* end, track_info_t* out )
in = get_gd3_str ( in, end, out->comment ); in = get_gd3_str ( in, end, out->comment );
} }
int const gd3_header_size = 12; static int const gd3_header_size = 12;
static long check_gd3_header( byte const* h, long remain ) static long check_gd3_header( byte const* h, long remain )
{ {
@ -324,7 +326,7 @@ void Vgm_Emu::mute_voices_( int mask )
blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size ) blargg_err_t Vgm_Emu::load_mem_( byte const* new_data, long new_size )
{ {
assert( offsetof (header_t,unused2 [8]) == header_size ); blaarg_static_assert( offsetof (header_t,unused2 [8]) == header_size, "VGM Header layout incorrect!" );
if ( new_size <= header_size ) if ( new_size <= header_size )
return gme_wrong_file_type; return gme_wrong_file_type;

View file

@ -46,7 +46,7 @@ enum {
ym2612_dac_port = 0x2A ym2612_dac_port = 0x2A
}; };
inline int command_len( int command ) static inline int command_len( int command )
{ {
switch ( command >> 4 ) switch ( command >> 4 )
{ {

View file

@ -2,17 +2,30 @@
// Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/ // Game_Music_Emu https://bitbucket.org/mpyne/game-music-emu/
#if !defined(VGM_YM2612_GENS) && !defined(VGM_YM2612_NUKED) && !defined(VGM_YM2612_MAME)
#define VGM_YM2612_NUKED
#endif
#ifdef VGM_YM2612_GENS // LGPL v2.1+ license #ifdef VGM_YM2612_GENS // LGPL v2.1+ license
# if defined(VGM_YM2612_NUKED) || defined(VGM_YM2612_MAME)
# error Only one of VGM_YM2612_GENS, VGM_YM2612_NUKED or VGM_YM2612_MAME can be defined
# endif
#include "Ym2612_GENS.h" #include "Ym2612_GENS.h"
typedef Ym2612_GENS_Emu Ym2612_Emu; typedef Ym2612_GENS_Emu Ym2612_Emu;
#endif #endif
#ifdef VGM_YM2612_NUKED // LGPL v2.1+ license #ifdef VGM_YM2612_NUKED // LGPL v2.1+ license
# if defined(VGM_YM2612_GENS) || defined(VGM_YM2612_MAME)
# error Only one of VGM_YM2612_GENS, VGM_YM2612_NUKED or VGM_YM2612_MAME can be defined
# endif
#include "Ym2612_Nuked.h" #include "Ym2612_Nuked.h"
typedef Ym2612_Nuked_Emu Ym2612_Emu; typedef Ym2612_Nuked_Emu Ym2612_Emu;
#endif #endif
#ifdef VGM_YM2612_MAME // GPL v2+ license #ifdef VGM_YM2612_MAME // GPL v2+ license
# if defined(VGM_YM2612_GENS) || defined(VGM_YM2612_NUKED)
# error Only one of VGM_YM2612_GENS, VGM_YM2612_NUKED or VGM_YM2612_MAME can be defined
# endif
#include "Ym2612_MAME.h" #include "Ym2612_MAME.h"
typedef Ym2612_MAME_Emu Ym2612_Emu; typedef Ym2612_MAME_Emu Ym2612_Emu;
#endif #endif

View file

@ -2,6 +2,8 @@
// Based on Gens 2.10 ym2612.c // Based on Gens 2.10 ym2612.c
#ifdef VGM_YM2612_GENS
#include "Ym2612_GENS.h" #include "Ym2612_GENS.h"
#include <assert.h> #include <assert.h>
@ -36,7 +38,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include BLARGG_ENABLE_OPTIMIZER #include BLARGG_ENABLE_OPTIMIZER
#endif #endif
const int output_bits = 14; static const int output_bits = 14;
struct slot_t struct slot_t
{ {
@ -179,7 +181,7 @@ struct state_t
#define S2 1 #define S2 1
#define S3 3 #define S3 3
inline void set_seg( slot_t& s, int seg ) static inline void set_seg( slot_t& s, int seg )
{ {
s.env_xor = 0; s.env_xor = 0;
s.env_max = INT_MAX; s.env_max = INT_MAX;
@ -253,7 +255,7 @@ static const unsigned char LFO_FMS_TAB [8] =
LFO_FMS_BASE * 12, LFO_FMS_BASE * 24 LFO_FMS_BASE * 12, LFO_FMS_BASE * 24
}; };
inline void YM2612_Special_Update() { } static inline void YM2612_Special_Update() { }
struct Ym2612_GENS_Impl struct Ym2612_GENS_Impl
{ {
@ -1024,7 +1026,7 @@ static void update_envelope_( slot_t* sl )
} }
} }
inline void update_envelope( slot_t& sl ) static inline void update_envelope( slot_t& sl )
{ {
int ecmp = sl.Ecmp; int ecmp = sl.Ecmp;
if ( (sl.Ecnt += sl.Einc) >= ecmp ) if ( (sl.Ecnt += sl.Einc) >= ecmp )
@ -1317,3 +1319,5 @@ void Ym2612_GENS_Impl::run( int pair_count, Ym2612_GENS_Emu::sample_t* out )
} }
void Ym2612_GENS_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); } void Ym2612_GENS_Emu::run( int pair_count, sample_t* out ) { impl->run( pair_count, out ); }
#endif /* VGM_YM2612_GENS */

View file

@ -2,6 +2,8 @@
// Based on Mame YM2612 ym2612.c // Based on Mame YM2612 ym2612.c
#ifdef VGM_YM2612_MAME
#include "Ym2612_MAME.h" #include "Ym2612_MAME.h"
/* /*
@ -2578,7 +2580,7 @@ void ym2612_pre_generate(void *chip)
refresh_fc_eg_chan( OPN, &cch[5] ); refresh_fc_eg_chan( OPN, &cch[5] );
} }
void ym2612_generate_one_native(void *chip, FMSAMPLE buffer[]) void ym2612_generate_one_native(void *chip, FMSAMPLE buffer[2])
{ {
YM2612 *F2612 = (YM2612 *)chip; YM2612 *F2612 = (YM2612 *)chip;
FM_OPN *OPN = &F2612->OPN; FM_OPN *OPN = &F2612->OPN;
@ -2819,7 +2821,7 @@ static void * ym2612_init(void *param, int clock, int rate,
F2612->OPN.ST.clock = clock; F2612->OPN.ST.clock = clock;
#if RSM_ENABLE #if RSM_ENABLE
F2612->OPN.ST.rate = 53267; F2612->OPN.ST.rate = 53267;
F2612->OPN.ST.rateratio = (INT32)(UINT32)((((UINT64)144 * rate) << RSM_FRAC) / clock); F2612->OPN.ST.rateratio = (INT32)(UINT32)((((UINT64)144 * rate) << RSM_FRAC) / 7670454);
F2612->OPN.ST.framecnt = 1 << RSM_FRAC; F2612->OPN.ST.framecnt = 1 << RSM_FRAC;
memset(&(F2612->OPN.ST.cur_sample), 0x00, sizeof(FMSAMPLE) * 2); memset(&(F2612->OPN.ST.cur_sample), 0x00, sizeof(FMSAMPLE) * 2);
memset(&(F2612->OPN.ST.prev_sample), 0x00, sizeof(FMSAMPLE) * 2); memset(&(F2612->OPN.ST.prev_sample), 0x00, sizeof(FMSAMPLE) * 2);
@ -3107,3 +3109,5 @@ void Ym2612_MAME_Emu::run(int pair_count, Ym2612_MAME_Emu::sample_t *out)
(void) &Ym2612_MameImpl::TimerBOver; // squelch clang warning, which appears to be from a config choice (void) &Ym2612_MameImpl::TimerBOver; // squelch clang warning, which appears to be from a config choice
if ( impl ) Ym2612_MameImpl::ym2612_generate( impl, out, pair_count, 1); if ( impl ) Ym2612_MameImpl::ym2612_generate( impl, out, pair_count, 1);
} }
#endif /* VGM_YM2612_MAME */

View file

@ -2,6 +2,8 @@
// Based on Nuked OPN2 ym3438.c and ym3438.h // Based on Nuked OPN2 ym3438.c and ym3438.h
#ifdef VGM_YM2612_NUKED
#include "Ym2612_Nuked.h" #include "Ym2612_Nuked.h"
/* /*
@ -1839,7 +1841,7 @@ const char *Ym2612_Nuked_Emu::set_rate(double sample_rate, double clock_rate)
void Ym2612_Nuked_Emu::reset() void Ym2612_Nuked_Emu::reset()
{ {
Ym2612_NukedImpl::ym3438_t *chip_r = reinterpret_cast<Ym2612_NukedImpl::ym3438_t*>(impl); Ym2612_NukedImpl::ym3438_t *chip_r = reinterpret_cast<Ym2612_NukedImpl::ym3438_t*>(impl);
if ( !chip_r ) Ym2612_NukedImpl::OPN2_Reset( chip_r, static_cast<Bit32u>(prev_sample_rate), static_cast<Bit32u>(prev_clock_rate) ); if ( chip_r ) Ym2612_NukedImpl::OPN2_Reset( chip_r, static_cast<Bit32u>(prev_sample_rate), static_cast<Bit32u>(prev_clock_rate) );
} }
void Ym2612_Nuked_Emu::mute_voices(int mask) void Ym2612_Nuked_Emu::mute_voices(int mask)
@ -1870,3 +1872,5 @@ void Ym2612_Nuked_Emu::run(int pair_count, Ym2612_Nuked_Emu::sample_t *out)
if ( !chip_r ) return; if ( !chip_r ) return;
Ym2612_NukedImpl::OPN2_GenerateStreamMix(chip_r, out, pair_count); Ym2612_NukedImpl::OPN2_GenerateStreamMix(chip_r, out, pair_count);
} }
#endif /* VGM_YM2612_NUKED */

View file

@ -4,19 +4,22 @@
#ifndef BLARGG_COMMON_H #ifndef BLARGG_COMMON_H
#define BLARGG_COMMON_H #define BLARGG_COMMON_H
#include "blargg_config.h"
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#undef BLARGG_COMMON_H #if defined(__GNUC__)
// allow blargg_config.h to #include blargg_common.h #define BLARGG_PRINTFN(x,y) __attribute__((__format__(__printf__,x,y)))
#include "blargg_config.h" #else
#ifndef BLARGG_COMMON_H #define BLARGG_PRINTFN(x,y)
#define BLARGG_COMMON_H #endif
// BLARGG_RESTRICT: equivalent to restrict, where supported // BLARGG_RESTRICT: equivalent to restrict, where supported
#if __GNUC__ >= 3 || _MSC_VER >= 1100 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || \
(defined(_MSC_VER) && (_MSC_VER >= 1100))
#define BLARGG_RESTRICT __restrict #define BLARGG_RESTRICT __restrict
#else #else
#define BLARGG_RESTRICT #define BLARGG_RESTRICT
@ -27,11 +30,24 @@
#define STATIC_CAST(T,expr) ((T) (expr)) #define STATIC_CAST(T,expr) ((T) (expr))
#endif #endif
#if !defined(_MSC_VER) || _MSC_VER >= 1910
#define blaarg_static_assert(cond, msg) static_assert(cond, msg)
#else
#define blaarg_static_assert(cond, msg) assert(cond)
#endif
// blargg_err_t (0 on success, otherwise error string) // blargg_err_t (0 on success, otherwise error string)
#ifndef blargg_err_t #ifndef blargg_err_t
typedef const char* blargg_err_t; typedef const char* blargg_err_t;
#endif #endif
// Apply minus sign to unsigned type and prevent the warning being shown
template<typename T>
inline T uMinus(T in)
{
return ~(in - 1);
}
// blargg_vector - very lightweight vector of POD types (no constructor/destructor) // blargg_vector - very lightweight vector of POD types (no constructor/destructor)
template<class T> template<class T>
class blargg_vector { class blargg_vector {
@ -66,7 +82,8 @@ public:
#define BLARGG_DISABLE_NOTHROW \ #define BLARGG_DISABLE_NOTHROW \
void* operator new ( size_t s ) noexcept { return malloc( s ); }\ void* operator new ( size_t s ) noexcept { return malloc( s ); }\
void* operator new ( size_t s, const std::nothrow_t& ) noexcept { return malloc( s ); }\ void* operator new ( size_t s, const std::nothrow_t& ) noexcept { return malloc( s ); }\
void operator delete ( void* p ) noexcept { free( p ); } void operator delete ( void* p ) noexcept { free( p ); }\
void operator delete ( void* p, const std::nothrow_t&) noexcept { free( p ); }
#endif #endif
// Use to force disable exceptions for a specific allocation no matter what class // Use to force disable exceptions for a specific allocation no matter what class
@ -79,74 +96,7 @@ public:
#define BLARGG_2CHAR( a, b ) \ #define BLARGG_2CHAR( a, b ) \
((a&0xFF)*0x100L + (b&0xFF)) ((a&0xFF)*0x100L + (b&0xFF))
// 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
#if defined(__has_cpp_attribute)
# if __has_cpp_attribute(maybe_unused)
# define BLARGG_MAYBE_UNUSED [[maybe_unused]]
# endif
#endif
#ifndef BLARGG_MAYBE_UNUSED
# define BLARGG_MAYBE_UNUSED
#endif
// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
typedef long blargg_long;
#else
typedef int blargg_long;
#endif
#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
typedef unsigned long blargg_ulong;
#else
typedef unsigned blargg_ulong;
#endif
// int8_t etc. // int8_t etc.
#include <stdint.h>
// TODO: Add CMake check for this, although I'd likely just point affected
// persons to a real compiler...
#if 1 || defined (HAVE_STDINT_H)
#include <stdint.h>
#endif
#if __GNUC__ >= 3
#define BLARGG_DEPRECATED __attribute__ ((deprecated))
#else
#define BLARGG_DEPRECATED
#endif
// Use in place of "= 0;" for a pure virtual, since these cause calls to std C++ lib.
// During development, BLARGG_PURE( x ) expands to = 0;
// virtual int func() BLARGG_PURE( { return 0; } )
#ifndef BLARGG_PURE
#define BLARGG_PURE( def ) def
#endif
#endif #endif
#endif

View file

@ -29,11 +29,9 @@
// Uncomment to use faster, lower quality sound synthesis // Uncomment to use faster, lower quality sound synthesis
//#define BLIP_BUFFER_FAST 1 //#define BLIP_BUFFER_FAST 1
// Uncomment if automatic byte-order determination doesn't work // Uncomment one of the following two if automatic byte-order determination doesn't work
//#define BLARGG_BIG_ENDIAN 1 //#define BLARGG_BIG_ENDIAN 1
//#define BLARGG_LITTLE_ENDIAN 1
// Uncomment if you get errors in the bool section of blargg_common.h
//#define BLARGG_COMPILER_HAS_BOOL 1
#define debug_printf(a, ...) #define debug_printf(a, ...)

View file

@ -19,36 +19,12 @@
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only // 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. // one may be #defined to 1. Only needed if something actually depends on byte order.
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) // BLARGG_BIG_ENDIAN or BLARGG_LITTLE_ENDIAN must be defined by the build system.
#ifdef __GLIBC__ #if !defined(BLARGG_BIG_ENDIAN) && !defined(BLARGG_LITTLE_ENDIAN)
// GCC handles this for us #error Unspecified endianness.
#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 #endif
#if defined(BLARGG_BIG_ENDIAN) && defined(BLARGG_LITTLE_ENDIAN)
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ #error BLARGG_LITTLE_ENDIAN and BLARGG_BIG_ENDIAN are both defined.
defined (__sparc__) || BLARGG_CPU_POWERPC || \
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
#define BLARGG_BIG_ENDIAN 1
#elif !defined (__mips__)
// No endian specified; assume little-endian, since it's most common
#define BLARGG_LITTLE_ENDIAN 1
#endif
#endif
#endif
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
#undef BLARGG_LITTLE_ENDIAN
#undef BLARGG_BIG_ENDIAN
#endif #endif
inline void blargg_verify_byte_order() inline void blargg_verify_byte_order()
@ -76,20 +52,20 @@ inline unsigned get_be16( void const* p )
(unsigned) ((unsigned char const*) p) [1]; (unsigned) ((unsigned char const*) p) [1];
} }
inline blargg_ulong get_le32( void const* p ) inline uint32_t get_le32( void const* p )
{ {
return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | return (uint32_t) ((unsigned char const*) p) [3] << 24 |
(blargg_ulong) ((unsigned char const*) p) [2] << 16 | (uint32_t) ((unsigned char const*) p) [2] << 16 |
(blargg_ulong) ((unsigned char const*) p) [1] << 8 | (uint32_t) ((unsigned char const*) p) [1] << 8 |
(blargg_ulong) ((unsigned char const*) p) [0]; (uint32_t) ((unsigned char const*) p) [0];
} }
inline blargg_ulong get_be32( void const* p ) inline uint32_t get_be32( void const* p )
{ {
return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | return (uint32_t) ((unsigned char const*) p) [0] << 24 |
(blargg_ulong) ((unsigned char const*) p) [1] << 16 | (uint32_t) ((unsigned char const*) p) [1] << 16 |
(blargg_ulong) ((unsigned char const*) p) [2] << 8 | (uint32_t) ((unsigned char const*) p) [2] << 8 |
(blargg_ulong) ((unsigned char const*) p) [3]; (uint32_t) ((unsigned char const*) p) [3];
} }
inline void set_le16( void* p, unsigned n ) inline void set_le16( void* p, unsigned n )
@ -104,7 +80,7 @@ inline void set_be16( void* p, unsigned n )
((unsigned char*) p) [1] = (unsigned char) n; ((unsigned char*) p) [1] = (unsigned char) n;
} }
inline void set_le32( void* p, blargg_ulong n ) inline void set_le32( void* p, uint32_t n )
{ {
((unsigned char*) p) [0] = (unsigned char) n; ((unsigned char*) p) [0] = (unsigned char) n;
((unsigned char*) p) [1] = (unsigned char) (n >> 8); ((unsigned char*) p) [1] = (unsigned char) (n >> 8);
@ -112,7 +88,7 @@ inline void set_le32( void* p, blargg_ulong n )
((unsigned char*) p) [3] = (unsigned char) (n >> 24); ((unsigned char*) p) [3] = (unsigned char) (n >> 24);
} }
inline void set_be32( void* p, blargg_ulong n ) inline void set_be32( void* p, uint32_t n )
{ {
((unsigned char*) p) [3] = (unsigned char) n; ((unsigned char*) p) [3] = (unsigned char) n;
((unsigned char*) p) [2] = (unsigned char) (n >> 8); ((unsigned char*) p) [2] = (unsigned char) (n >> 8);
@ -142,7 +118,7 @@ inline void set_be32( void* p, blargg_ulong n )
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
#elif defined (__GNUC__) #elif defined (__GNUC__)
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;}) #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;}) #define GET_LE32( addr ) ({unsigned int ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
#endif #endif
@ -172,13 +148,13 @@ inline void set_be32( void* p, blargg_ulong n )
// auto-selecting versions // auto-selecting versions
inline void set_le( uint16_t* p, unsigned n ) { SET_LE16( p, n ); } inline void set_le( uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
inline void set_le( uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } inline void set_le( uint32_t* p, uint32_t n ) { SET_LE32( p, n ); }
inline void set_be( uint16_t* p, unsigned n ) { SET_BE16( p, n ); } inline void set_be( uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
inline void set_be( uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } inline void set_be( uint32_t* p, uint32_t n ) { SET_BE32( p, n ); }
inline unsigned get_le( uint16_t* p ) { return GET_LE16( p ); } inline unsigned get_le( uint16_t* p ) { return GET_LE16( p ); }
inline blargg_ulong get_le( uint32_t* p ) { return GET_LE32( p ); } inline uint32_t get_le( uint32_t* p ) { return GET_LE32( p ); }
inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); } inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); }
inline blargg_ulong get_be( uint32_t* p ) { return GET_BE32( p ); } inline uint32_t get_be( uint32_t* p ) { return GET_BE32( p ); }
#endif #endif

View file

@ -34,11 +34,10 @@
/* Like printf() except output goes to debug log file. Might be defined to do /* Like printf() except output goes to debug log file. Might be defined to do
* nothing (not even evaluate its arguments). * nothing (not even evaluate its arguments).
* void debug_printf( const char* format, ... ); */ * void debug_printf( const char* format, ... ); */
#if defined(__cplusplus) && defined(BLARGG_BUILD_DLL) static inline void BLARGG_PRINTFN(1,2)
static inline void blargg_dprintf_( const char* fmt_str, ... ) { (void) fmt_str; } blargg_dprintf_( const char* fmt_str, ... ) { (void) fmt_str; }
#undef debug_printf #undef debug_printf
#define debug_printf (1) ? (void) 0 : blargg_dprintf_ #define debug_printf (1) ? (void) 0 : blargg_dprintf_
#endif
/* If enabled, evaluate expr and if false, make debug log entry with source file /* 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 * and line. Meant for finding situations that should be examined further, but that
@ -62,21 +61,6 @@
#define byte byte_ #define byte byte_
typedef unsigned char byte; typedef unsigned char byte;
/* Setup compiler defines useful for exporting required public API symbols in gme.cpp */
#ifndef BLARGG_EXPORT
#if defined (_WIN32)
#if defined(BLARGG_BUILD_DLL)
#define BLARGG_EXPORT __declspec(dllexport)
#else
#define BLARGG_EXPORT /* Leave blank: friendly with both static and shared linking */
#endif
#elif defined (LIBGME_VISIBILITY) && defined(__cplusplus)
#define BLARGG_EXPORT __attribute__((visibility ("default")))
#else
#define BLARGG_EXPORT
#endif
#endif
/* deprecated */ /* deprecated */
#define BLARGG_CHECK_ALLOC CHECK_ALLOC #define BLARGG_CHECK_ALLOC CHECK_ALLOC
#define BLARGG_RETURN_ERR RETURN_ERR #define BLARGG_RETURN_ERR RETURN_ERR

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2001-2019 Mitsutaka Okazaki
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.

View file

@ -0,0 +1,8 @@
# emu2413
A YM2413 emulator written in C by Mitsutaka Okazaki.
This is the version 0.61, tweaked by Chrosipher Snowhill (@kode54).
If you looking latest version of this module, please visit this repository:
https://github.com/digital-sound-antiques/emu2413

View file

@ -55,8 +55,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "mamedef.h"
#undef INLINE
#include "emu2413.h" #include "emu2413.h"
#include "panning.h" // Maxim #include "panning.h" // Maxim
@ -169,7 +167,7 @@ static unsigned char default_inst[OPLL_TONE_NUM][(16 + 3) * 8] = {
#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1)) #define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1))
/* Adjust envelope speed which depends on sampling rate. */ /* Adjust envelope speed which depends on sampling rate. */
#define RATE_ADJUST(x) (rate==49716?x:(e_uint32)((double)(x)*clk/72/rate + 0.5)) /* added 0.5 to round the value*/ #define RATE_ADJUST(x) (rate==49716?(x):(e_uint32)((double)(x)*clk/72/rate + 0.5)) /* added 0.5 to round the value*/
#define MOD(o,x) (&(o)->slot[(x)<<1]) #define MOD(o,x) (&(o)->slot[(x)<<1])
#define CAR(o,x) (&(o)->slot[((x)<<1)|1]) #define CAR(o,x) (&(o)->slot[((x)<<1)|1])
@ -424,7 +422,8 @@ static double decaytime[16][4] = {
static void static void
makeDphaseARTable (void) makeDphaseARTable (void)
{ {
e_int32 AR, Rks, RM, RL; e_int32 AR, Rks, RM;
e_uint32 RL;
#ifdef USE_SPEC_ENV_SPEED #ifdef USE_SPEC_ENV_SPEED
e_uint32 attacktable[16][4]; e_uint32 attacktable[16][4];
@ -472,7 +471,8 @@ makeDphaseARTable (void)
static void static void
makeDphaseDRTable (void) makeDphaseDRTable (void)
{ {
e_int32 DR, Rks, RM, RL; e_int32 DR, Rks, RM;
e_uint32 RL;
#ifdef USE_SPEC_ENV_SPEED #ifdef USE_SPEC_ENV_SPEED
e_uint32 decaytable[16][4]; e_uint32 decaytable[16][4];
@ -1000,7 +1000,7 @@ OPLL_new (e_uint32 clk, e_uint32 rate)
maketables (clk, rate); maketables (clk, rate);
opll = (OPLL *) calloc (sizeof (OPLL), 1); opll = (OPLL *) calloc (1, sizeof (OPLL));
if (opll == NULL) if (opll == NULL)
return NULL; return NULL;

View file

View file

@ -2,7 +2,11 @@
#include "Music_Emu.h" #include "Music_Emu.h"
#ifdef GEN_TYPES_H
#include "gen_types.h" /* same as gme_types.h but generated by build system */
#else
#include "gme_types.h" #include "gme_types.h"
#endif
#if !GME_DISABLE_STEREO_DEPTH #if !GME_DISABLE_STEREO_DEPTH
#include "Effects_Buffer.h" #include "Effects_Buffer.h"
#endif #endif
@ -55,7 +59,6 @@ gme_type_t const* gme_type_list()
#endif #endif
#ifdef USE_GME_SPC #ifdef USE_GME_SPC
gme_spc_type, gme_spc_type,
gme_rsn_type,
gme_sfm_type, gme_sfm_type,
#endif #endif
#ifdef USE_GME_VGM #ifdef USE_GME_VGM
@ -83,7 +86,6 @@ const char* gme_identify_header( void const* header )
case BLARGG_4CHAR('N','S','F','E'): return "NSFE"; case BLARGG_4CHAR('N','S','F','E'): return "NSFE";
case BLARGG_4CHAR('S','A','P',0x0D): return "SAP"; case BLARGG_4CHAR('S','A','P',0x0D): return "SAP";
case BLARGG_4CHAR('S','N','E','S'): return "SPC"; case BLARGG_4CHAR('S','N','E','S'): return "SPC";
case BLARGG_4CHAR('R','a','r','!'): return "RSN";
case BLARGG_4CHAR('V','g','m',' '): return "VGM"; case BLARGG_4CHAR('V','g','m',' '): return "VGM";
} }
if (get_be16(header) == BLARGG_2CHAR(0x1F, 0x8B)) if (get_be16(header) == BLARGG_2CHAR(0x1F, 0x8B))
@ -180,9 +182,9 @@ gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
header_size = sizeof header; header_size = sizeof header;
RETURN_ERR( in.read( header, sizeof header ) ); RETURN_ERR( in.read( header, sizeof header ) );
file_type = gme_identify_extension( gme_identify_header( header ) ); file_type = gme_identify_extension( gme_identify_header( header ) );
if ( !file_type )
return gme_wrong_file_type;
} }
if ( !file_type )
return gme_wrong_file_type;
Music_Emu* emu = gme_new_emu( file_type, sample_rate ); Music_Emu* emu = gme_new_emu( file_type, sample_rate );
CHECK_ALLOC( emu ); CHECK_ALLOC( emu );
@ -192,9 +194,6 @@ gme_err_t gme_open_file( const char* path, Music_Emu** out, int sample_rate )
gme_err_t err = emu->load( rem ); gme_err_t err = emu->load( rem );
in.close(); in.close();
if ( emu->is_archive )
err = emu->load_archive( path );
if ( err ) if ( err )
delete emu; delete emu;
else else
@ -208,7 +207,7 @@ void gme_set_autoload_playback_limit( Music_Emu *emu, int do_autoload_limit )
emu->set_autoload_playback_limit( do_autoload_limit != 0 ); emu->set_autoload_playback_limit( do_autoload_limit != 0 );
} }
int gme_autoload_playback_limit( Music_Emu *const emu ) int gme_autoload_playback_limit( Music_Emu const* emu )
{ {
return emu->autoload_playback_limit(); return emu->autoload_playback_limit();
} }
@ -275,6 +274,17 @@ gme_err_t gme_load_data( Music_Emu* me, void const* data, long size )
return me->load( in ); return me->load( in );
} }
gme_err_t gme_load_tracks( Music_Emu* me, void const* data, long* sizes, int count )
{
return me->load_tracks( data, sizes, count );
}
int gme_fixed_track_count( gme_type_t t )
{
assert( t );
return t->track_count;
}
gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data ) gme_err_t gme_load_custom( Music_Emu* me, gme_reader_t func, long size, void* data )
{ {
Callback_Reader in( func, size, data ); Callback_Reader in( func, size, data );
@ -381,17 +391,21 @@ void gme_set_user_cleanup(Music_Emu* me, gme_user_cleanup_t func ) { me->se
gme_err_t gme_start_track ( Music_Emu* me, int index ) { return me->start_track( index ); } 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 ); } 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, int fade_msec ) { me->set_fade( start_msec, fade_msec ); } void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
void gme_set_fade_msecs ( Music_Emu* me, int start_msec, int fade_msec ) { me->set_fade( start_msec, fade_msec ); }
int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
int gme_tell ( Music_Emu const* me ) { return me->tell(); } int gme_tell ( Music_Emu const* me ) { return me->tell(); }
int gme_tell_samples ( Music_Emu const* me ) { return me->tell_samples(); } int gme_tell_samples ( Music_Emu const* me ) { return me->tell_samples(); }
int gme_tell_scaled ( Music_Emu const* me ) { return me->tell_scaled(); }
gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
gme_err_t gme_seek_samples ( Music_Emu* me, int n ) { return me->seek_samples( n ); } gme_err_t gme_seek_samples ( Music_Emu* me, int n ) { return me->seek_samples( n ); }
gme_err_t gme_seek_scaled ( Music_Emu* me, int msec ) { return me->seek_scaled( msec ); }
int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } 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_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_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_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_mute_voices ( Music_Emu* me, int mask ) { me->mute_voices( mask ); }
void gme_disable_echo ( Music_Emu* me, int disable ) { me->disable_echo( disable ); }
void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( enabled ); } void gme_enable_accuracy( Music_Emu* me, int enabled ) { me->enable_accuracy( enabled ); }
void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); } void gme_clear_playlist ( Music_Emu* me ) { me->clear_playlist(); }
int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; } int gme_type_multitrack( gme_type_t t ) { return t->track_count != 1; }

View file

@ -0,0 +1,68 @@
# List of all exported symbols
gme_autoload_playback_limit
gme_clear_playlist
gme_delete
gme_enable_accuracy
gme_equalizer
gme_free_info
gme_identify_extension
gme_identify_file
gme_identify_header
gme_ignore_silence
gme_load_custom
gme_load_data
gme_load_file
gme_load_m3u
gme_load_m3u_data
gme_multi_channel
gme_mute_voice
gme_mute_voices
gme_new_emu
gme_new_emu_multi_channel
gme_open_data
gme_open_file
gme_play
gme_seek
gme_seek_samples
gme_set_autoload_playback_limit
gme_set_equalizer
gme_set_fade
gme_set_stereo_depth
gme_set_tempo
gme_set_user_cleanup
gme_set_user_data
gme_start_track
gme_tell
gme_tell_samples
gme_track_count
gme_track_ended
gme_track_info
gme_type
gme_type_extension
gme_type_list
gme_type_multitrack
gme_type_system
gme_user_data
gme_voice_count
gme_voice_name
gme_warning
gme_wrong_file_type
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
gme_disable_echo
gme_set_fade_msecs
gme_load_tracks
gme_fixed_track_count
# Since 0.6.5
gme_seek_scaled
gme_tell_scaled

View file

@ -1,16 +1,14 @@
/* Game music emulator library C interface (also usable from C++) */ /* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.7.0 */ /* Game_Music_Emu 0.6.4 */
#ifndef GME_H #ifndef GME_H
#define GME_H #define GME_H
#include "blargg_source.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define GME_VERSION 0x000700 /* 1 byte major, 1 byte minor, 1 byte patch-level */ #define GME_VERSION 0x000604 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */ /* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t; typedef const char* gme_err_t;
@ -19,6 +17,22 @@ typedef const char* gme_err_t;
typedef struct Music_Emu Music_Emu; typedef struct Music_Emu Music_Emu;
/* Setup compiler defines useful for exporting required public API symbols in gme.cpp */
#ifndef BLARGG_EXPORT
#if defined (_WIN32)
#if defined(BLARGG_BUILD_DLL)
#define BLARGG_EXPORT __declspec(dllexport)
#else
#define BLARGG_EXPORT /* Leave blank: friendly with both static and shared linking. */
#endif
#elif defined (LIBGME_VISIBILITY)
#define BLARGG_EXPORT __attribute__((visibility ("default")))
#else
#define BLARGG_EXPORT
#endif
#endif
/******** Basic operations ********/ /******** Basic operations ********/
/* Create emulator and load game music file/data into it. Sets *out to new emulator. */ /* Create emulator and load game music file/data into it. Sets *out to new emulator. */
@ -41,7 +55,12 @@ BLARGG_EXPORT void gme_delete( Music_Emu* );
/* Set time to start fading track out. Once fade ends track_ended() returns true. /* Set time to start fading track out. Once fade ends track_ended() returns true.
Fade time can be changed while track is playing. */ Fade time can be changed while track is playing. */
BLARGG_EXPORT void gme_set_fade( Music_Emu*, int start_msec, int length_msec ); BLARGG_EXPORT void gme_set_fade( Music_Emu*, int start_msec );
/** See gme_set_fade.
* @since 0.6.4
*/
BLARGG_EXPORT void gme_set_fade_msecs( Music_Emu*, int start_msec, int length_msecs );
/** /**
* If do_autoload_limit is nonzero, then automatically load track length * If do_autoload_limit is nonzero, then automatically load track length
@ -53,12 +72,13 @@ BLARGG_EXPORT void gme_set_fade( Music_Emu*, int start_msec, int length_msec );
* *
* By default, playback limits are loaded and applied. * By default, playback limits are loaded and applied.
* *
* @since 0.6.2 * @since 0.6.3
*/ */
BLARGG_EXPORT void gme_set_autoload_playback_limit( Music_Emu *, int do_autoload_limit ); BLARGG_EXPORT void gme_set_autoload_playback_limit( Music_Emu *, int do_autoload_limit );
/** See gme_set_autoload_playback_limit. /** See gme_set_autoload_playback_limit.
* @since 0.6.2 * (This was actually added in 0.6.3, but wasn't exported because of a typo.)
* @since 0.6.4
*/ */
BLARGG_EXPORT int gme_autoload_playback_limit( Music_Emu const* ); BLARGG_EXPORT int gme_autoload_playback_limit( Music_Emu const* );
@ -71,12 +91,20 @@ BLARGG_EXPORT int gme_tell( Music_Emu const* );
/* Number of samples generated since beginning of track */ /* Number of samples generated since beginning of track */
BLARGG_EXPORT int gme_tell_samples( Music_Emu const* ); BLARGG_EXPORT int gme_tell_samples( Music_Emu const* );
/* Number of milliseconds played since beginning of track (scaled with tempo).
* @since 0.6.5 */
BLARGG_EXPORT int gme_tell_scaled( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */ /* Seek to new time in track. Seeking backwards or far forward can take a while. */
BLARGG_EXPORT gme_err_t gme_seek( Music_Emu*, int msec ); BLARGG_EXPORT gme_err_t gme_seek( Music_Emu*, int msec );
/* Equivalent to restarting track then skipping n samples */ /* Equivalent to restarting track then skipping n samples */
BLARGG_EXPORT gme_err_t gme_seek_samples( Music_Emu*, int n ); BLARGG_EXPORT gme_err_t gme_seek_samples( Music_Emu*, int n );
/* Seek to new time in track (scaled with tempo).
* @since 0.6.5 */
BLARGG_EXPORT gme_err_t gme_seek_scaled( Music_Emu*, int msec );
/******** Informational ********/ /******** Informational ********/
@ -103,7 +131,7 @@ BLARGG_EXPORT gme_err_t gme_track_info( Music_Emu const*, gme_info_t** out, int
/* Frees track information */ /* Frees track information */
BLARGG_EXPORT void gme_free_info( gme_info_t* ); BLARGG_EXPORT void gme_free_info( gme_info_t* );
struct BLARGG_EXPORT gme_info_t struct gme_info_t
{ {
/* times in milliseconds; -1 if unknown */ /* times in milliseconds; -1 if unknown */
int length; /* total length, if file specifies it */ int length; /* total length, if file specifies it */
@ -159,9 +187,13 @@ BLARGG_EXPORT void gme_mute_voice( Music_Emu*, int index, int mute );
voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */ voices, 0 unmutes them all, 0x01 mutes just the first voice, etc. */
BLARGG_EXPORT void gme_mute_voices( Music_Emu*, int muting_mask ); BLARGG_EXPORT void gme_mute_voices( Music_Emu*, int muting_mask );
/* Disable/Enable echo effect for SPC files */
/* Available since 0.6.4 */
BLARGG_EXPORT void gme_disable_echo( Music_Emu*, int disable );
/* Frequency equalizer parameters (see gme.txt) */ /* Frequency equalizer parameters (see gme.txt) */
/* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */ /* Implementers: If modified, also adjust Music_Emu::make_equalizer as needed */
typedef struct BLARGG_EXPORT gme_equalizer_t typedef struct gme_equalizer_t
{ {
double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */ double treble; /* -50.0 = muffled, 0 = flat, +5.0 = extra-crisp */
double bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */ double bass; /* 1 = full bass, 90 = average, 16000 = almost no bass */
@ -195,7 +227,6 @@ extern BLARGG_EXPORT const gme_type_t
gme_nsfe_type, gme_nsfe_type,
gme_sap_type, gme_sap_type,
gme_spc_type, gme_spc_type,
gme_rsn_type,
gme_sfm_type, gme_sfm_type,
gme_vgm_type, gme_vgm_type,
gme_vgz_type; gme_vgz_type;
@ -215,7 +246,7 @@ BLARGG_EXPORT int gme_type_multitrack( gme_type_t );
/* whether the pcm output retrieved by gme_play() will have all 8 voices rendered to their /* whether the pcm output retrieved by gme_play() will have all 8 voices rendered to their
* individual stereo channel or (if false) these voices get mixed into one single stereo channel * individual stereo channel or (if false) these voices get mixed into one single stereo channel
* @since 0.6.2 */ * @since 0.6.3 */
BLARGG_EXPORT int gme_multi_channel( Music_Emu const* ); BLARGG_EXPORT int gme_multi_channel( Music_Emu const* );
/******** Advanced file loading ********/ /******** Advanced file loading ********/
@ -239,7 +270,7 @@ BLARGG_EXPORT gme_type_t gme_identify_extension( const char path_or_extension []
* Get typical file extension for a given music type. This is not a replacement * Get typical file extension for a given music type. This is not a replacement
* for a file content identification library (but see gme_identify_header). * for a file content identification library (but see gme_identify_header).
* *
* @since 0.6.2 * @since 0.6.3
*/ */
BLARGG_EXPORT const char* gme_type_extension( gme_type_t music_type ); BLARGG_EXPORT const char* gme_type_extension( gme_type_t music_type );
@ -254,7 +285,7 @@ BLARGG_EXPORT Music_Emu* gme_new_emu( gme_type_t, int sample_rate );
/* Create new multichannel emulator and set sample rate. Returns NULL if out of memory. /* Create new multichannel emulator and set sample rate. Returns NULL if out of memory.
* If you only need track information, pass gme_info_only for sample_rate. * If you only need track information, pass gme_info_only for sample_rate.
* (see gme_multi_channel for more information on multichannel support) * (see gme_multi_channel for more information on multichannel support)
* @since 0.6.2 * @since 0.6.3
*/ */
BLARGG_EXPORT Music_Emu* gme_new_emu_multi_channel( gme_type_t, int sample_rate ); BLARGG_EXPORT Music_Emu* gme_new_emu_multi_channel( gme_type_t, int sample_rate );
@ -264,6 +295,17 @@ BLARGG_EXPORT gme_err_t gme_load_file( Music_Emu*, const char path [] );
/* Load music file from memory into emulator. Makes a copy of data passed. */ /* Load music file from memory into emulator. Makes a copy of data passed. */
BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu*, void const* data, long size ); BLARGG_EXPORT gme_err_t gme_load_data( Music_Emu*, void const* data, long size );
/* Load multiple single-track music files from memory into emulator.
* @since 0.6.4
*/
BLARGG_EXPORT gme_err_t gme_load_tracks( Music_Emu* me,
void const* data, long* sizes, int count );
/* Return the fixed track count of an emu file type
* @since 0.6.4
*/
BLARGG_EXPORT int gme_fixed_track_count( gme_type_t );
/* Load music file using custom data reader function that will be called to /* 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. */ 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 ); typedef gme_err_t (*gme_reader_t)( void* your_data, void* out, int count );

View file

@ -27,7 +27,7 @@ inline byte const* Hes_Emu::cpu_set_mmr( int page, int bank )
{ {
write_pages [page] = 0; write_pages [page] = 0;
if ( bank < 0x80 ) if ( bank < 0x80 )
return rom.at_addr( bank * (blargg_long) page_size ); return rom.at_addr( bank * (int32_t) page_size );
byte* data = 0; byte* data = 0;
switch ( bank ) switch ( bank )

View file

@ -13,4 +13,4 @@ URL: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
Version: @GME_VERSION@ Version: @GME_VERSION@
Cflags: -I${includedir} Cflags: -I${includedir}
Libs: -L${libdir} -lgme Libs: -L${libdir} -lgme
Libs.private: -lstdc++ @PKG_CONFIG_ZLIB@ @PKG_CONFIG_UNRAR@ Libs.private: @PC_LIBS@

View file

@ -9,6 +9,8 @@
#include "blargg_source.h" #include "blargg_source.h"
#include <cstring>
int Nsf_Emu::cpu_read( nes_addr_t addr ) int Nsf_Emu::cpu_read( nes_addr_t addr )
{ {
int result, i; int result, i;
@ -79,10 +81,26 @@ void Nsf_Emu::cpu_write( nes_addr_t addr, int data )
return; return;
} }
if ( fds && ( addr >= 0x5FF6 && addr <= 0x5FFD ) )
{
int32_t offset = rom.mask_addr( data * (int32_t) bank_size );
if ( offset >= rom.size() )
set_warning( "Invalid bank" );
unsigned bank = addr - 0x5FF6;
byte* out = sram;
if ( bank >= 2 )
{
out = fds->sram;
bank -= 2;
}
memcpy( &out [bank * bank_size], rom.at_addr( offset ), bank_size );
return;
}
unsigned bank = addr - bank_select_addr; unsigned bank = addr - bank_select_addr;
if ( bank < bank_count ) if ( bank < bank_count )
{ {
blargg_long offset = rom.mask_addr( data * (blargg_long) bank_size ); int32_t offset = rom.mask_addr( data * (int32_t) bank_size );
if ( offset >= rom.size() ) if ( offset >= rom.size() )
set_warning( "Invalid bank" ); set_warning( "Invalid bank" );
cpu::map_code( (bank + 8) * bank_size, bank_size, rom.at_addr( offset ) ); cpu::map_code( (bank + 8) * bank_size, bank_size, rom.at_addr( offset ) );

Some files were not shown because too many files have changed in this diff Show more