From 8fa903c004fd10e82b01b085a5b92b8c9f88bfe8 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Thu, 15 Jun 2017 19:00:41 -0400 Subject: [PATCH] pizza progress: it runs --- BizHawk.Client.Common/Global.cs | 4 +- BizHawk.Client.Common/RomLoader.cs | 1 + .../BizHawk.Emulation.Cores.csproj | 5 +- .../Consoles/Nintendo/Gameboy/Gambatte.cs | 4 +- .../Nintendo/Gameboy/IGameboyCommon.cs | 13 + .../Consoles/Nintendo/Gameboy/LibPizza.cs | 26 ++ .../Consoles/Nintendo/Gameboy/Pizza.cs | 130 ++++++++ waterbox/pizza/.vscode/settings.json | 6 + waterbox/pizza/Makefile | 4 +- waterbox/pizza/lib/cartridge.c | 4 +- waterbox/pizza/lib/cartridge.h | 2 +- waterbox/pizza/lib/cycles.c | 1 + waterbox/pizza/lib/cycles.h | 14 +- waterbox/pizza/lib/gameboy.c | 12 +- waterbox/pizza/lib/gameboy.h | 3 +- waterbox/pizza/lib/global.c | 8 +- waterbox/pizza/lib/global.h | 2 - waterbox/pizza/lib/gpu.c | 10 +- waterbox/pizza/lib/gpu.h | 8 +- waterbox/pizza/lib/mmu.h | 34 +-- waterbox/pizza/lib/serial.c | 23 +- waterbox/pizza/lib/serial.h | 6 +- waterbox/pizza/lib/sound.c | 2 - waterbox/pizza/lib/sound.h | 10 +- waterbox/pizza/lib/timer.h | 4 +- waterbox/pizza/lib/utils.c | 51 +--- waterbox/pizza/pizza.c | 280 ++++-------------- 27 files changed, 295 insertions(+), 372 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs create mode 100644 waterbox/pizza/.vscode/settings.json diff --git a/BizHawk.Client.Common/Global.cs b/BizHawk.Client.Common/Global.cs index 896a2c5567..42e9a75a89 100644 --- a/BizHawk.Client.Common/Global.cs +++ b/BizHawk.Client.Common/Global.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Nintendo.Gameboy; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; using BizHawk.Emulation.Cores.Sega.MasterSystem; // ReSharper disable StyleCop.SA1401 @@ -112,7 +112,7 @@ namespace BizHawk.Client.Common case "SNES": return SystemInfo.SNES; case "GB": - if ((Emulator as Gameboy).IsCGBMode()) + if ((Emulator as IGameboyCommon).IsCGBMode()) { return SystemInfo.GBC; } diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index aaf4251a7b..d046d3c3a4 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -817,6 +817,7 @@ namespace BizHawk.Client.Common case "GBC": if (!Global.Config.GB_AsSGB) { + //core = CoreInventory.Instance["GB", "Pizza Boy"]; core = CoreInventory.Instance["GB", "Gambatte"]; } else diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 5e7140d435..38b5b350a9 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -362,7 +362,7 @@ A7800Hawk.cs - + A7800Hawk.cs @@ -539,7 +539,10 @@ + + + diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs index bdc3932729..e2e3f6b4ea 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.cs @@ -2,6 +2,7 @@ using BizHawk.Common.BufferExtensions; using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; namespace BizHawk.Emulation.Cores.Nintendo.Gameboy { @@ -17,7 +18,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy portedUrl: "http://gambatte.sourceforge.net/")] [ServiceNotApplicable(typeof(IDriveLight), typeof(IDriveLight))] public partial class Gameboy : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable, ICodeDataLogger, - IBoardInfo, IDebuggable, ISettable + IBoardInfo, IDebuggable, ISettable, + IGameboyCommon { [CoreConstructor("GB", "GBC")] public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings, bool deterministic) diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs new file mode 100644 index 0000000000..fa236b8f47 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/IGameboyCommon.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy +{ + public interface IGameboyCommon + { + bool IsCGBMode(); + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs new file mode 100644 index 0000000000..503f1e4b9d --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/LibPizza.cs @@ -0,0 +1,26 @@ +using BizHawk.Common.BizInvoke; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy +{ + public abstract class LibPizza + { + private const CallingConvention CC = CallingConvention.Cdecl; + [StructLayout(LayoutKind.Sequential)] + public class FrameInfo + { + public IntPtr VideoBuffer; + public int Clocks; + } + + [BizImport(CC)] + public abstract bool Init(byte[] rom, int romlen); + [BizImport(CC)] + public abstract void FrameAdvance([In,Out] FrameInfo frame); + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs new file mode 100644 index 0000000000..b72da3f7b1 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Pizza.cs @@ -0,0 +1,130 @@ +using BizHawk.Common; +using BizHawk.Common.BizInvoke; +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy +{ + [CoreAttributes("Pizza Boy", "Davide Berra", true, false, "c7bc6ee376028b3766de8d7a02e60ab794841f45", + "https://github.com/davideberra/emu-pizza/", false)] + public class Pizza : IEmulator, IInputPollable, IVideoProvider, IGameboyCommon + { + private LibPizza _pizza; + private PeRunner _exe; + private bool _disposed; + + [CoreConstructor("GB")] + public Pizza(byte[] rom, CoreComm comm) + { + CoreComm = comm; + ServiceProvider = new BasicServiceProvider(this); + + _exe = new PeRunner(new PeRunnerOptions + { + Filename = "pizza.wbx", + Path = comm.CoreFileProvider.DllPath(), + SbrkHeapSizeKB = 2 * 1024, + InvisibleHeapSizeKB = 16 * 1024, + SealedHeapSizeKB = 16 * 1024, + PlainHeapSizeKB = 16 * 1024, + MmapHeapSizeKB = 32 * 1024 + }); + _pizza = BizInvoker.GetInvoker(_exe, _exe); + using (_exe.EnterExit()) + { + if (!_pizza.Init(rom, rom.Length)) + { + throw new InvalidOperationException("Core rejected the rom!"); + } + } + } + + /// + /// the nominal length of one frame + /// + private const int TICKSPERFRAME = 35112; + + /// + /// number of ticks per second (GB, CGB) + /// + private const int TICKSPERSECOND = 2097152; + + /// + /// number of ticks per second (SGB) + /// + private const int TICKSPERSECOND_SGB = 2147727; + + private int _tickOverflow = 0; + + + public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true) + { + fixed (int* vp = _videoBuffer) + { + var targetClocks = TICKSPERFRAME - _tickOverflow; + + var frame = new LibPizza.FrameInfo + { + VideoBuffer = (IntPtr)vp, + Clocks = targetClocks + }; + + _pizza.FrameAdvance(frame); + _tickOverflow = frame.Clocks - targetClocks; + } + } + + public void Dispose() + { + if (!_disposed) + { + _exe.Dispose(); + _exe = null; + _pizza = null; + _disposed = true; + } + } + + public bool IsCGBMode() { return false; } // TODO + public ControllerDefinition ControllerDefinition => NullController.Instance.Definition; + public int Frame { get; private set; } + public int LagCount { get; set; } + public bool IsLagFrame { get; set; } + public IInputCallbackSystem InputCallbacks { get; } = new InputCallbackSystem(); + + public void ResetCounters() + { + Frame = 0; + } + + public IEmulatorServiceProvider ServiceProvider { get; private set; } + public string SystemId { get { return "GB"; } } + public bool DeterministicEmulation { get; private set; } + public CoreComm CoreComm { get; } + + #region IVideoProvider + + private int[] _videoBuffer = new int[160 * 144]; + + public int[] GetVideoBuffer() + { + return _videoBuffer; + } + + public int VirtualWidth => 160; + public int VirtualHeight => 144; + public int BufferWidth => 160; + public int BufferHeight => 144; + public int VsyncNumerator { get; private set; } = TICKSPERSECOND; + public int VsyncDenominator { get; private set; } = TICKSPERFRAME; + public int BackgroundColor => unchecked((int)0xff000000); + + #endregion + + } +} diff --git a/waterbox/pizza/.vscode/settings.json b/waterbox/pizza/.vscode/settings.json new file mode 100644 index 0000000000..d5073385ae --- /dev/null +++ b/waterbox/pizza/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "editor.insertSpaces": false, + "editor.tabSize": 4, + "editor.detectIndentation": false +} \ No newline at end of file diff --git a/waterbox/pizza/Makefile b/waterbox/pizza/Makefile index 2cde9bdea9..3e44a58fa8 100644 --- a/waterbox/pizza/Makefile +++ b/waterbox/pizza/Makefile @@ -4,8 +4,8 @@ CCFLAGS:=-Ilib \ -I../emulibc \ -Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \ -std=c99 -fomit-frame-pointer -fvisibility=hidden \ - -DLSB_FIRST -DUSE_32BPP_RENDERING -DINLINE=static\ __inline__ \ - -O0 -flto + -DLSB_FIRST -D_GNU_SOURCE \ + -O0 -g TARGET = pizza.wbx diff --git a/waterbox/pizza/lib/cartridge.c b/waterbox/pizza/lib/cartridge.c index 75fbb219db..bd894a112d 100644 --- a/waterbox/pizza/lib/cartridge.c +++ b/waterbox/pizza/lib/cartridge.c @@ -19,8 +19,6 @@ #include #include -#include -#include #include #include @@ -48,6 +46,8 @@ char cartridge_load(const void* data, size_t sz) if (sz < 1 || sz > 2 << 24) return 1; + memcpy(rom, data, sz); + /* gameboy color? */ if (rom[0x143] == 0xC0 || rom[0x143] == 0x80) { diff --git a/waterbox/pizza/lib/cartridge.h b/waterbox/pizza/lib/cartridge.h index e8781c5f8c..4c6c372ad6 100644 --- a/waterbox/pizza/lib/cartridge.h +++ b/waterbox/pizza/lib/cartridge.h @@ -23,7 +23,7 @@ #include /* prototypes */ -char cartridge_load(char *file_nm); +char cartridge_load(const void* data, size_t sz); void cartridge_term(); #endif diff --git a/waterbox/pizza/lib/cycles.c b/waterbox/pizza/lib/cycles.c index ea2f79f0fe..dd3b31271a 100644 --- a/waterbox/pizza/lib/cycles.c +++ b/waterbox/pizza/lib/cycles.c @@ -115,6 +115,7 @@ void cycles_closest_next() void cycles_step() { cycles.cnt += 4; + cycles.sampleclock += 2 >> global_cpu_double_speed; /* while (cycles.cnt >= cycles_very_next) diff --git a/waterbox/pizza/lib/cycles.h b/waterbox/pizza/lib/cycles.h index a3f8b64940..39cf216552 100644 --- a/waterbox/pizza/lib/cycles.h +++ b/waterbox/pizza/lib/cycles.h @@ -29,13 +29,13 @@ typedef struct cycles_s uint_fast32_t inited; /* ticks counter */ - uint_fast32_t cnt; + uint64_t cnt; - /* CPU clock */ + // CPU clock. advances at 4MHz or 8MHz depending on current cgb setting uint_fast32_t clock; /* handy for calculation */ - uint_fast32_t next; + uint64_t next; /* step varying on cpu and emulation speed */ uint_fast32_t step; @@ -44,11 +44,10 @@ typedef struct cycles_s uint_fast32_t seconds; /* 2 spares */ - uint_fast32_t hs_next; - - - uint_fast32_t spare2; + uint64_t hs_next; + // reference clock. advances at 2MHz always + uint64_t sampleclock; } cycles_t; extern cycles_t cycles; @@ -67,7 +66,6 @@ void cycles_set_speed(char dbl); void cycles_start_hs(); void cycles_step(); void cycles_stop_hs(); -void cycles_term(); void cycles_vblank(); #endif diff --git a/waterbox/pizza/lib/gameboy.c b/waterbox/pizza/lib/gameboy.c index 4ac0f850fe..7e54f4e7fc 100644 --- a/waterbox/pizza/lib/gameboy.c +++ b/waterbox/pizza/lib/gameboy.c @@ -130,9 +130,9 @@ void gameboy_init() gameboy_inited = 1; return; -} +} -void gameboy_run() +void gameboy_run(uint64_t target) { uint8_t op; @@ -148,14 +148,8 @@ void gameboy_run() /* mechanism is simple. */ /* 1) execute instruction 2) update cycles counter 3) check interrupts */ /* and repeat forever */ - while (!global_quit) + while (cycles.sampleclock < target) { - /*if (global_slow_down) - { - usleep(100000); - global_slow_down = 0; - }*/ - /* get op */ op = mmu_read(state.pc); diff --git a/waterbox/pizza/lib/gameboy.h b/waterbox/pizza/lib/gameboy.h index e2094ce4eb..06efa026a8 100644 --- a/waterbox/pizza/lib/gameboy.h +++ b/waterbox/pizza/lib/gameboy.h @@ -22,8 +22,7 @@ /* prototypes */ void gameboy_init(); -void gameboy_run(); -void gameboy_set_pause(char pause); +void gameboy_run(uint64_t target); void gameboy_stop(); #endif diff --git a/waterbox/pizza/lib/global.c b/waterbox/pizza/lib/global.c index f13119b5fb..d6a04f80d8 100644 --- a/waterbox/pizza/lib/global.c +++ b/waterbox/pizza/lib/global.c @@ -23,13 +23,11 @@ #include "global.h" char global_cart_name[256]; -char global_cgb; +char global_cgb; // if true, in CGB mode char global_cpu_double_speed; char global_debug; -char global_next_frame; char global_rumble; -char global_slow_down; -char global_window; +char global_window; // if true, show window void global_init() { @@ -37,8 +35,6 @@ void global_init() global_debug = 0; global_cgb = 0; global_cpu_double_speed = 0; - global_slow_down = 0; - global_next_frame = 0; global_rumble = 0; sprintf(global_cart_name, "NOCARTIRDGE"); } diff --git a/waterbox/pizza/lib/global.h b/waterbox/pizza/lib/global.h index 4f80496223..0833156835 100644 --- a/waterbox/pizza/lib/global.h +++ b/waterbox/pizza/lib/global.h @@ -23,10 +23,8 @@ extern char global_window; extern char global_debug; extern char global_cgb; -extern char global_next_frame; // extern char global_started; extern char global_cpu_double_speed; -extern char global_slow_down; extern char global_rumble; extern char global_cart_name[256]; diff --git a/waterbox/pizza/lib/gpu.c b/waterbox/pizza/lib/gpu.c index 3b7f2d7650..f987e15a60 100644 --- a/waterbox/pizza/lib/gpu.c +++ b/waterbox/pizza/lib/gpu.c @@ -17,8 +17,6 @@ */ -#include -#include #include #include #include @@ -234,12 +232,6 @@ void gpu_draw_frame() bzero(gpu.priority, 160 * 144); bzero(gpu.palette_idx, 160 * 144); - if (global_next_frame) - { - global_next_frame = 0; - gameboy_set_pause(1); - } - return; } @@ -865,7 +857,7 @@ void gpu_step() gpu_if->lcd_vblank = 1; /* apply gameshark patches */ - mmu_apply_gs(); + //mmu_apply_gs(); /* and finally push it on screen! */ gpu_draw_frame(); diff --git a/waterbox/pizza/lib/gpu.h b/waterbox/pizza/lib/gpu.h index 52dabbe8eb..d983f5ef82 100644 --- a/waterbox/pizza/lib/gpu.h +++ b/waterbox/pizza/lib/gpu.h @@ -91,7 +91,7 @@ typedef struct gpu_s uint8_t *lyc; /* clocks counter */ - uint_fast32_t next; + uint64_t next; /* gpu step span */ uint_fast32_t step; @@ -116,24 +116,18 @@ typedef struct gpu_s uint16_t cgb_palette_bg[0x20]; uint8_t cgb_palette_bg_idx; uint8_t cgb_palette_bg_autoinc; - uint16_t spare2; /* CGB palette for sprites */ uint16_t cgb_palette_oam_rgb565[0x20]; uint16_t cgb_palette_oam[0x20]; uint8_t cgb_palette_oam_idx; uint8_t cgb_palette_oam_autoinc; - uint16_t spare3; /* frame buffer */ uint16_t frame_buffer_prev[160 * 144]; uint16_t frame_buffer[160 * 144]; uint8_t priority[160 * 144]; uint8_t palette_idx[160 * 144]; - - uint_fast32_t spare4; - uint_fast32_t spare5; - } gpu_t; extern gpu_t gpu; diff --git a/waterbox/pizza/lib/mmu.h b/waterbox/pizza/lib/mmu.h index 35ded2a477..010d5d4825 100644 --- a/waterbox/pizza/lib/mmu.h +++ b/waterbox/pizza/lib/mmu.h @@ -24,29 +24,7 @@ #include #include -typedef struct mmu_gamegenie_s { - - /* data necessary */ - uint16_t address; - uint8_t old_value; - uint8_t new_value; - -} mmu_gamegenie_t; - -typedef struct mmu_gameshark_s { - - /* data necessary */ - uint16_t address; - uint8_t ram_bank; - uint8_t new_value; - -} mmu_gameshark_t; - -#define MMU_GAMEGENIE_MAX 4 -#define MMU_GAMESHARK_MAX 32 - typedef struct mmu_s { - /* main 64K of memory */ uint8_t memory[65536]; @@ -101,18 +79,8 @@ typedef struct mmu_s { uint16_t spare6; time_t rtc_time; time_t rtc_latch_time; - - /* Gamegenie */ - uint8_t gg_count; - mmu_gamegenie_t gg_array[MMU_GAMEGENIE_MAX]; - - /* Gameshark */ - uint8_t gs_count; - mmu_gameshark_t gs_array[MMU_GAMESHARK_MAX]; - - uint_fast32_t dma_next; - uint_fast32_t spare8; + uint64_t dma_next; } mmu_t; extern mmu_t mmu; diff --git a/waterbox/pizza/lib/serial.c b/waterbox/pizza/lib/serial.c index f48cc690e7..497d8a65c1 100644 --- a/waterbox/pizza/lib/serial.c +++ b/waterbox/pizza/lib/serial.c @@ -87,7 +87,8 @@ void serial_write_reg(uint16_t a, uint8_t v) switch (a) { case 0xFF01: - serial.data = v; goto end; + serial.data = v; + return; case 0xFF02: serial.clock = v & 0x01; serial.speed = (v & 0x02) ? 0x01 : 0x00; @@ -96,6 +97,7 @@ void serial_write_reg(uint16_t a, uint8_t v) /* reset? */ serial.data_sent = 0; + break; } if (serial.transfer_start && @@ -106,9 +108,7 @@ void serial_write_reg(uint16_t a, uint8_t v) serial.next = cycles.cnt + 8 * 8; else serial.next = cycles.cnt + 256 * 8; - } - -end: + } } uint8_t serial_read_reg(uint16_t a) @@ -137,8 +137,7 @@ void serial_recv_byte(uint8_t v, uint8_t clock, uint8_t transfer_start) serial_second_data = v; serial_second_clock = clock; serial_second_transfer_start = transfer_start; - - goto end; + return; } /* received side OK */ @@ -150,8 +149,6 @@ void serial_recv_byte(uint8_t v, uint8_t clock, uint8_t transfer_start) /* notify main thread in case it's waiting */ //if (serial_waiting_data) //pthread_cond_signal(&serial_cond); - -end: } void serial_send_byte() @@ -176,20 +173,20 @@ void serial_wait_data() if (serial.data_sent && serial.data_recv == 0) { /* wait max 3 seconds */ - struct timespec wait; + //struct timespec wait; - wait.tv_sec = time(NULL) + 3; + //wait.tv_sec = time(NULL) + 3; /* this is very important to avoid EINVAL return! */ - wait.tv_nsec = 0; + //wait.tv_nsec = 0; /* declare i'm waiting for data */ - serial_waiting_data = 1; + //serial_waiting_data = 1; /* notify something has arrived */ // pthread_cond_timedwait(&serial_cond, &serial_mutex, &wait); /* not waiting anymore */ - serial_waiting_data = 0; + //serial_waiting_data = 0; } } diff --git a/waterbox/pizza/lib/serial.h b/waterbox/pizza/lib/serial.h index 40b36bbf19..d4cfb918eb 100644 --- a/waterbox/pizza/lib/serial.h +++ b/waterbox/pizza/lib/serial.h @@ -54,7 +54,7 @@ typedef struct serial_s { uint8_t data_to_recv; /* counter */ - uint_fast32_t next; + uint64_t next; /* peer connected? */ uint8_t peer_connected:1; @@ -66,10 +66,6 @@ typedef struct serial_s { uint8_t data_recv_transfer_start:1; uint8_t spare10:1; - uint8_t spare2; - uint8_t spare3; - uint8_t spare4; - uint_fast32_t last_send_cnt; } serial_t; diff --git a/waterbox/pizza/lib/sound.c b/waterbox/pizza/lib/sound.c index d6d350dc00..c6d09a3e79 100644 --- a/waterbox/pizza/lib/sound.c +++ b/waterbox/pizza/lib/sound.c @@ -24,7 +24,6 @@ #include "sound.h" #include "utils.h" -#include #include #include #include @@ -45,7 +44,6 @@ void sound_push_sample(int16_t s); void sound_read_samples(int len, int16_t *buf); void sound_rebuild_wave(); void sound_sweep_step(); -void sound_term(); void sound_write_wave(uint16_t a, uint8_t v); int sound_get_samples() diff --git a/waterbox/pizza/lib/sound.h b/waterbox/pizza/lib/sound.h index 8840c0a066..27a4887107 100644 --- a/waterbox/pizza/lib/sound.h +++ b/waterbox/pizza/lib/sound.h @@ -195,7 +195,7 @@ typedef struct channel_square_s uint8_t duty_idx; uint8_t envelope_cnt; uint_fast16_t duty_cycles; - uint_fast16_t duty_cycles_next; + uint64_t duty_cycles_next; uint_fast32_t length; uint_fast32_t frequency; int16_t sample; @@ -219,7 +219,7 @@ typedef struct channel_wave_s int16_t spare; int16_t wave[32]; uint_fast32_t cycles; - uint_fast32_t cycles_next; + uint64_t cycles_next; uint_fast32_t ram_access_next; uint_fast32_t length; @@ -232,7 +232,7 @@ typedef struct channel_noise_s uint16_t spare; uint_fast32_t length; uint_fast16_t period_lfsr; - uint_fast32_t cycles_next; + uint64_t cycles_next; int16_t volume; int16_t sample; uint16_t reg; @@ -294,11 +294,11 @@ typedef struct sound_s /* CPU cycles to internal cycles counters */ uint_fast32_t fs_cycles; uint_fast32_t fs_cycles_idx; - uint_fast32_t fs_cycles_next; + uint64_t fs_cycles_next; uint_fast32_t sample_cycles; uint_fast32_t sample_cycles_remainder; uint_fast32_t sample_cycles_next; - uint_fast32_t sample_cycles_next_rounded; + uint64_t sample_cycles_next_rounded; /* steps length */ uint_fast32_t step_int; diff --git a/waterbox/pizza/lib/timer.h b/waterbox/pizza/lib/timer.h index acdf8561c8..531116121b 100644 --- a/waterbox/pizza/lib/timer.h +++ b/waterbox/pizza/lib/timer.h @@ -45,12 +45,10 @@ typedef struct timer_gb_s /* current value */ uint_fast32_t sub; - uint_fast32_t next; + uint64_t next; /* spare */ uint_fast32_t sub_next; - uint_fast32_t spare2; - } timer_gb_t; /* global status of timer */ diff --git a/waterbox/pizza/lib/utils.c b/waterbox/pizza/lib/utils.c index 3800a82e4b..dff5dd1d79 100644 --- a/waterbox/pizza/lib/utils.c +++ b/waterbox/pizza/lib/utils.c @@ -17,13 +17,9 @@ */ -#ifdef __ANDROID__ -#include -#else +#include #include -#endif -#include #include #include @@ -31,7 +27,7 @@ #include "gpu.h" #include "utils.h" -uint32_t prev_cycles = 0; +uint64_t prev_cycles = 0; void utils_log(const char *format, ...) { @@ -39,19 +35,8 @@ void utils_log(const char *format, ...) va_list args; va_start(args, format); - -#ifdef __ANDROID__ - vsnprintf(buf, 256, format, args); - __android_log_write(ANDROID_LOG_INFO, "Pizza", buf); - -#else - - vsnprintf(buf, 256, format, args); - printf(buf); - -#endif - + _debug_puts(buf); va_end(args); } @@ -62,19 +47,8 @@ void utils_log_urgent(const char *format, ...) va_list args; va_start(args, format); - -#ifdef __ANDROID__ - vsnprintf(buf, 256, format, args); - __android_log_write(ANDROID_LOG_INFO, "Pizza", buf); - -#else - - vsnprintf(buf, 256, format, args); - printf(buf); - -#endif - + _debug_puts(buf); va_end(args); } @@ -84,25 +58,18 @@ void utils_ts_log(const char *format, ...) va_start(args, format); char buf[256]; + char buf2[512]; struct timeval tv; -#ifdef __ANDROID__ - - vsnprintf(buf, 256, format, args); - __android_log_write(ANDROID_LOG_INFO, "Pizza", buf); - -#else vsprintf(buf, format, args); - gettimeofday(&tv, NULL); + //gettimeofday(&tv, NULL); // printf("%ld - %s\n", tv.tv_sec, buf); - printf("LINE %u - CYCLES %u - DIFF %u - %ld:%06ld - %s", - *(gpu.ly), cycles.cnt, cycles.cnt - prev_cycles, + sprintf(buf2, "LINE %u - CYCLES %lu - DIFF %lu - %ld:%06ld - %s", + *(gpu.ly), cycles.cnt, cycles.cnt - prev_cycles, tv.tv_sec, tv.tv_usec, buf); - + _debug_puts(buf2); prev_cycles = cycles.cnt; -#endif - va_end(args); } diff --git a/waterbox/pizza/pizza.c b/waterbox/pizza/pizza.c index b92e82c14f..1f158d6689 100644 --- a/waterbox/pizza/pizza.c +++ b/waterbox/pizza/pizza.c @@ -17,12 +17,13 @@ */ -#include -#include #include #include -#include #include +#include +#include + +#define EXPORT ECL_EXPORT #include "cartridge.h" #include "cycles.h" @@ -30,9 +31,10 @@ #include "global.h" #include "gpu.h" #include "input.h" -#include "network.h" #include "sound.h" #include "serial.h" +#include "utils.h" +#include "mmu.h" /* proto */ void cb(); @@ -49,177 +51,50 @@ uint16_t *fb; /* magnify rate */ float magnify_rate = 1.f; -/* emulator thread */ -pthread_t thread; - -/* SDL video stuff */ -SDL_Window *window; -SDL_Surface *screenSurface; -SDL_Surface *windowSurface; - /* cartridge name */ char cart_name[64]; - -int main(int argc, char **argv) +int main(void) { - /* SDL variables */ - SDL_Event e; - SDL_AudioSpec desired; - SDL_AudioSpec obtained; +} - /* init global variables */ - global_init(); +EXPORT int Init(const void *rom, int romlen) +{ + /* init global variables */ + global_init(); - /* set global folder */ - snprintf(global_save_folder, sizeof(global_save_folder), "/tmp/str/save/"); - __mkdirp(global_save_folder, S_IRWXU); + /* first, load cartridge */ + char ret = cartridge_load(rom, romlen); - /* first, load cartridge */ - char ret = cartridge_load(argv[1]); + if (ret != 0) + return 0; // failure - if (ret != 0) - return 1; + gameboy_init(); - /* apply cheat */ + /* init GPU */ + gpu_init(&cb); - /* tetris */ -/* mmu_set_cheat("00063D6E9"); - mmu_set_cheat("3E064D5D0"); - mmu_set_cheat("04065D087"); */ + /* set sound output rate */ + sound_set_output_rate(44100); - /* samurai shodown */ - // mmu_set_cheat("11F86E3B6"); - //) - // mmu_set_cheat("3EB60D7F1"); - // + /* set rumble cb */ + mmu_set_rumble_cb(&rumble_cb); - /* gameshark aladdin */ - // mmu_set_cheat("01100ADC"); + /* get frame buffer reference */ + fb = gpu_get_frame_buffer(); - /* gameshark wario land */ - // mmu_set_cheat("809965A9"); + return 1; +} - // mmu_apply_gg(); +static uint32_t fb32[160 * 144]; - /* initialize SDL video */ - if (SDL_Init(SDL_INIT_VIDEO) < 0 ) - { - printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); - return 1; - } +//case (SDLK_d): global_debug ^= 0x01; break; +//case (SDLK_s): global_slow_down = 1; break; +//case (SDLK_w): global_window ^= 0x01; break; +//case (SDLK_n): gameboy_set_pause(0); +// global_next_frame = 1; break; - window = SDL_CreateWindow("Emu Pizza - Gameboy", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - 160 * magnify_rate, 144 * magnify_rate, - SDL_WINDOW_SHOWN); - - /* get window surface */ - windowSurface = SDL_GetWindowSurface(window); - screenSurface = SDL_ConvertSurfaceFormat(windowSurface, - SDL_PIXELFORMAT_RGB565, - 0); - - gameboy_init(); - - /* initialize SDL audio */ - SDL_Init(SDL_INIT_AUDIO); - desired.freq = 44100; - desired.samples = SOUND_SAMPLES / 2; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - desired.callback = sound_read_buffer; - desired.userdata = NULL; - - /* Open audio */ - if (SDL_OpenAudio(&desired, &obtained) == 0) - SDL_PauseAudio(0); - else - { - printf("Cannot open audio device!!\n"); - return 1; - } - - /* init GPU */ - gpu_init(&cb); - - /* set sound output rate */ - sound_set_output_rate(44100); - - /* set rumble cb */ - mmu_set_rumble_cb(&rumble_cb); - - /* get frame buffer reference */ - fb = gpu_get_frame_buffer(); - - /* start thread! */ - pthread_create(&thread, NULL, start_thread, NULL); - - /* start network thread! */ - network_start(&connected_cb, &disconnected_cb, "192.168.100.255"); - - /* loop forever */ - while (!global_quit) - { - /* aaaaaaaaaaaaaand finally, check for SDL events */ - - /* SDL_WaitEvent should be better but somehow, */ - /* it interfer with my cycles timer */ - if (SDL_PollEvent(&e) == 0) - { - usleep(100000); - continue; - } - - switch (e.type) - { - case SDL_QUIT: - global_quit = 1; - break; - - case SDL_KEYDOWN: - switch (e.key.keysym.sym) - { - case (SDLK_1): gameboy_set_pause(1); - gameboy_save_stat(0); - gameboy_set_pause(0); - break; - case (SDLK_2): gameboy_set_pause(1); - gameboy_restore_stat(0); - gameboy_set_pause(0); - break; - case (SDLK_9): network_start(&connected_cb, - &disconnected_cb, - "192.168.100.255"); break; - case (SDLK_0): network_stop(); break; - case (SDLK_q): global_quit = 1; break; - case (SDLK_d): global_debug ^= 0x01; break; - case (SDLK_s): global_slow_down = 1; break; - case (SDLK_w): global_window ^= 0x01; break; - case (SDLK_n): gameboy_set_pause(0); - global_next_frame = 1; break; - case (SDLK_PLUS): - if (global_emulation_speed != - GLOBAL_EMULATION_SPEED_4X) - { - global_emulation_speed++; - cycles_change_emulation_speed(); - sound_change_emulation_speed(); - } - - break; - case (SDLK_MINUS): - if (global_emulation_speed != - GLOBAL_EMULATION_SPEED_QUARTER) - { - global_emulation_speed--; - cycles_change_emulation_speed(); - sound_change_emulation_speed(); - } - - break; - case (SDLK_p): gameboy_set_pause(global_pause ^ 0x01); +/* case (SDLK_p): gameboy_set_pause(global_pause ^ 0x01); break; case (SDLK_m): mmu_dump_all(); break; case (SDLK_SPACE): input_set_key_select(1); break; @@ -249,90 +124,61 @@ int main(int argc, char **argv) } } - /* join emulation thread */ + // join emulation thread pthread_join(thread, NULL); - /* stop network thread! */ + // stop network thread! network_stop(); utils_log("Total cycles %d\n", cycles.cnt); utils_log("Total running seconds %d\n", cycles.seconds); return 0; -} +}*/ -void *start_thread(void *args) +typedef struct { - /* run until break or global_quit is set */ - gameboy_run(); + uint32_t* vbuff; + int32_t clocks; // desired(in) actual(out) time to run; 2MHZ +} frameinfo_t; - /* tell main thread it's over */ - global_quit = 1; + +EXPORT void FrameAdvance(frameinfo_t* frame) +{ + uint64_t current = cycles.sampleclock; + gameboy_run(current + frame->clocks); + frame->clocks = cycles.sampleclock - current; + memcpy(frame->vbuff, fb32, 160 * 144 * sizeof(uint32_t)); } void cb() { - uint16_t *pixel = screenSurface->pixels; + // frame received into fb + uint16_t *src = fb; + uint8_t *dst = (uint8_t *)fb32; - /* magnify! */ - if (magnify_rate > 1) - { - int x,y,p; - float px, py = 0; - - uint16_t *line = malloc(sizeof(uint16_t) * 160 * magnify_rate); - - for (y=0; y<144; y++) - { - px = 0; - - for (x=0; x<160; x++) - { - for (; pxw, screenSurface->h, - screenSurface->format->format, - screenSurface->pixels, screenSurface->pitch, - SDL_PIXELFORMAT_ARGB8888, - windowSurface->pixels, windowSurface->pitch); - - /* Update the surface */ - SDL_UpdateWindowSurface(window); + for (int i = 0; i < 160 * 144; i++) + { + uint16_t c = *src++; + *dst++ = c << 3 & 0xf8 | c >> 2 & 7; + *dst++ = c >> 3 & 0xfa | c >> 9 & 3; + *dst++ = c >> 8 & 0xf8 | c >> 13 & 7; + *dst++ = 0xff; + } } void connected_cb() { - utils_log("Connected\n"); + utils_log("Connected\n"); } void disconnected_cb() { - utils_log("Disconnected\n"); + utils_log("Disconnected\n"); } void rumble_cb(uint8_t rumble) { - if (rumble) - printf("RUMBLE\n"); + if (rumble) + printf("RUMBLE\n"); }