diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs index 2ccc8e37a3..1ff94aca08 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs @@ -9,6 +9,33 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES { public class QuickNES : IEmulator, IVideoProvider, ISyncSoundProvider { + private class FPCtrl : IDisposable + { + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern uint _control87(uint @new, uint mask); + + public static void PrintCurrentFP() + { + uint curr = _control87(0, 0); + Console.WriteLine("Current FP word: 0x{0:x8}", curr); + } + + uint cw; + + public IDisposable Save() + { + cw = _control87(0, 0); + _control87(0x00000, 0x30000); + return this; + } + public void Dispose() + { + _control87(cw, 0x30000); + } + } + + FPCtrl FP = new FPCtrl(); + static QuickNES() { LibQuickNES.qn_setup_mappers(); @@ -16,24 +43,27 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES public QuickNES(CoreComm nextComm, byte[] Rom) { - CoreComm = nextComm; - - Context = LibQuickNES.qn_new(); - if (Context == IntPtr.Zero) - throw new InvalidOperationException("qn_new() returned NULL"); - try + using (FP.Save()) { - LibQuickNES.ThrowStringError(LibQuickNES.qn_loadines(Context, Rom, Rom.Length)); + CoreComm = nextComm; - InitSaveRamBuff(); - InitSaveStateBuff(); - InitVideo(); - InitAudio(); - } - catch - { - Dispose(); - throw; + Context = LibQuickNES.qn_new(); + if (Context == IntPtr.Zero) + throw new InvalidOperationException("qn_new() returned NULL"); + try + { + LibQuickNES.ThrowStringError(LibQuickNES.qn_loadines(Context, Rom, Rom.Length)); + + InitSaveRamBuff(); + InitSaveStateBuff(); + InitVideo(); + InitAudio(); + } + catch + { + Dispose(); + throw; + } } } @@ -84,22 +114,25 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES public void FrameAdvance(bool render, bool rendersound = true) { - if (Controller["Power"]) - LibQuickNES.qn_reset(Context, true); - if (Controller["Reset"]) - LibQuickNES.qn_reset(Context, false); + using (FP.Save()) + { + if (Controller["Power"]) + LibQuickNES.qn_reset(Context, true); + if (Controller["Reset"]) + LibQuickNES.qn_reset(Context, false); - int j1, j2; - SetPads(out j1, out j2); + int j1, j2; + SetPads(out j1, out j2); - Frame++; - LibQuickNES.ThrowStringError(LibQuickNES.qn_emulate_frame(Context, j1, j2)); - IsLagFrame = LibQuickNES.qn_get_joypad_read_count(Context) == 0; - if (IsLagFrame) - LagCount++; + Frame++; + LibQuickNES.ThrowStringError(LibQuickNES.qn_emulate_frame(Context, j1, j2)); + IsLagFrame = LibQuickNES.qn_get_joypad_read_count(Context) == 0; + if (IsLagFrame) + LagCount++; - Blit(); - DrainAudio(); + Blit(); + DrainAudio(); + } } #region state @@ -332,7 +365,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES void DrainAudio() { - NumSamples = LibQuickNES.qn_read_audio(Context, MonoBuff, 1024); + NumSamples = LibQuickNES.qn_read_audio(Context, MonoBuff, MonoBuff.Length); unsafe { fixed (short *_src = &MonoBuff[0], _dst = &StereoBuff[0]) diff --git a/output/dll/libquicknes.dll b/output/dll/libquicknes.dll index 45183ad77c..05a9485860 100644 Binary files a/output/dll/libquicknes.dll and b/output/dll/libquicknes.dll differ diff --git a/quicknes/bizinterface.cpp b/quicknes/bizinterface.cpp index 36d430e25d..5cfa683fcd 100644 --- a/quicknes/bizinterface.cpp +++ b/quicknes/bizinterface.cpp @@ -36,14 +36,17 @@ EXPORT void qn_delete(Nes_Emu *e) EXPORT const char *qn_loadines(Nes_Emu *e, const void *data, int length) { - Mem_File_Reader r = Mem_File_Reader(data, length); - Auto_File_Reader a = Auto_File_Reader(r); + Mem_File_Reader r(data, length); + Auto_File_Reader a(r); return e->load_ines(a); } EXPORT const char *qn_set_sample_rate(Nes_Emu *e, int rate) { - return e->set_sample_rate(rate); + const char *ret = e->set_sample_rate(rate); + if (!ret) + e->set_equalizer(Nes_Emu::nes_eq); + return ret; } EXPORT void qn_get_image_dimensions(Nes_Emu *e, int *width, int *height) @@ -69,9 +72,9 @@ EXPORT void qn_blit(Nes_Emu *e, char *dest) // what is the point of the 256 color bitmap and the dynamic color allocation to it? // why not just render directly to a 512 color bitmap with static palette positions? - const char *src = (const char *)e->frame().pixels; + const unsigned char *src = e->frame().pixels; const int srcpitch = e->frame().pitch; - const char *srcend = src + e->image_height * srcpitch; + const unsigned char *srcend = src + e->image_height * srcpitch; const short *lut = e->frame().palette; const Nes_Emu::rgb_t *colors = e->nes_colors; @@ -114,8 +117,8 @@ EXPORT void qn_reset(Nes_Emu *e, int hard) EXPORT const char *qn_state_size(Nes_Emu *e, int *size) { - Sim_Writer w = Sim_Writer(); - Auto_File_Writer a = Auto_File_Writer(w); + Sim_Writer w; + Auto_File_Writer a(w); const char *ret = e->save_state(a); if (size) *size = w.size(); @@ -124,8 +127,8 @@ EXPORT const char *qn_state_size(Nes_Emu *e, int *size) EXPORT const char *qn_state_save(Nes_Emu *e, void *dest, int size) { - Mem_Writer w = Mem_Writer(dest, size, 0); - Auto_File_Writer a = Auto_File_Writer(w); + Mem_Writer w(dest, size, 0); + Auto_File_Writer a(w); const char *ret = e->save_state(a); if (!ret && w.size() != size) return "Buffer Underrun!"; @@ -134,8 +137,8 @@ EXPORT const char *qn_state_save(Nes_Emu *e, void *dest, int size) EXPORT const char *qn_state_load(Nes_Emu *e, const void *src, int size) { - Mem_File_Reader r = Mem_File_Reader(src, size); - Auto_File_Reader a = Auto_File_Reader(r); + Mem_File_Reader r(src, size); + Auto_File_Reader a(r); return e->load_state(a); } @@ -146,8 +149,8 @@ EXPORT int qn_has_battery_ram(Nes_Emu *e) EXPORT const char *qn_battery_ram_size(Nes_Emu *e, int *size) { - Sim_Writer w = Sim_Writer(); - Auto_File_Writer a = Auto_File_Writer(w); + Sim_Writer w; + Auto_File_Writer a(w); const char *ret = e->save_battery_ram(a); if (size) *size = w.size(); @@ -156,8 +159,8 @@ EXPORT const char *qn_battery_ram_size(Nes_Emu *e, int *size) EXPORT const char *qn_battery_ram_save(Nes_Emu *e, void *dest, int size) { - Mem_Writer w = Mem_Writer(dest, size, 0); - Auto_File_Writer a = Auto_File_Writer(w); + Mem_Writer w(dest, size, 0); + Auto_File_Writer a(w); const char *ret = e->save_battery_ram(a); if (!ret && w.size() != size) return "Buffer Underrun!"; @@ -166,8 +169,8 @@ EXPORT const char *qn_battery_ram_save(Nes_Emu *e, void *dest, int size) EXPORT const char *qn_battery_ram_load(Nes_Emu *e, const void *src, int size) { - Mem_File_Reader r = Mem_File_Reader(src, size); - Auto_File_Reader a = Auto_File_Reader(r); + Mem_File_Reader r(src, size); + Auto_File_Reader a(r); return e->load_battery_ram(a); } diff --git a/quicknes/mingw/Makefile b/quicknes/mingw/Makefile new file mode 100644 index 0000000000..5f9700683c --- /dev/null +++ b/quicknes/mingw/Makefile @@ -0,0 +1,65 @@ +CXX = g++ +CXXFLAGS = -Wall -DDISABLE_AUTO_FILE -D__LIBRETRO__ -I.. -Wno-multichar -O3 +TARGET = libquicknes.dll +LDFLAGS = -shared -static-libgcc -static-libstdc++ +RM = rm +CP = cp + +SRCS = \ + ../nes_emu/abstract_file.cpp \ + ../nes_emu/apu_state.cpp \ + ../nes_emu/Blip_Buffer.cpp \ + ../nes_emu/Effects_Buffer.cpp \ + ../nes_emu/Mapper_Fme7.cpp \ + ../nes_emu/Mapper_Mmc5.cpp \ + ../nes_emu/Mapper_Namco106.cpp \ + ../nes_emu/Mapper_Vrc6.cpp \ + ../nes_emu/misc_mappers.cpp \ + ../nes_emu/Multi_Buffer.cpp \ + ../nes_emu/Nes_Apu.cpp \ + ../nes_emu/Nes_Buffer.cpp \ + ../nes_emu/Nes_Cart.cpp \ + ../nes_emu/Nes_Core.cpp \ + ../nes_emu/Nes_Cpu.cpp \ + ../nes_emu/nes_data.cpp \ + ../nes_emu/Nes_Effects_Buffer.cpp \ + ../nes_emu/Nes_Emu.cpp \ + ../nes_emu/Nes_File.cpp \ + ../nes_emu/Nes_Film.cpp \ + ../nes_emu/Nes_Film_Data.cpp \ + ../nes_emu/Nes_Film_Packer.cpp \ + ../nes_emu/Nes_Fme7_Apu.cpp \ + ../nes_emu/Nes_Mapper.cpp \ + ../nes_emu/nes_mappers.cpp \ + ../nes_emu/Nes_Mmc1.cpp \ + ../nes_emu/Nes_Mmc3.cpp \ + ../nes_emu/Nes_Namco_Apu.cpp \ + ../nes_emu/Nes_Oscs.cpp \ + ../nes_emu/Nes_Ppu.cpp \ + ../nes_emu/Nes_Ppu_Impl.cpp \ + ../nes_emu/Nes_Ppu_Rendering.cpp \ + ../nes_emu/Nes_Recorder.cpp \ + ../nes_emu/Nes_State.cpp \ + ../nes_emu/nes_util.cpp \ + ../nes_emu/Nes_Vrc6_Apu.cpp \ + ../bizinterface.cpp \ + ../fex/Data_Reader.cpp \ + ../fex/blargg_errors.cpp \ + ../fex/blargg_common.cpp + +OBJS = $(SRCS:.cpp=.o) + +all: $(TARGET) + +%.o: %.cpp + $(CXX) -c -o $@ $< $(CXXFLAGS) + +$(TARGET) : $(OBJS) + $(CXX) -o $@ $(LDFLAGS) $(OBJS) + +clean: + $(RM) $(OBJS) + $(RM) $(TARGET) + +install: + $(CP) $(TARGET) ../../output/dll