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");
}