pizza progress: it runs
This commit is contained in:
parent
0d7116ef06
commit
8fa903c004
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -362,7 +362,7 @@
|
|||
<Compile Include="Consoles\Atari\A7800Hawk\A7800Hawk.ISaveRam.cs">
|
||||
<DependentUpon>A7800Hawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\A7800Hawk\A7800Hawk.ISettable.cs">
|
||||
<Compile Include="Consoles\Atari\A7800Hawk\A7800Hawk.ISettable.cs">
|
||||
<DependentUpon>A7800Hawk.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\A7800Hawk\A7800HawkControllerDeck.cs" />
|
||||
|
@ -539,7 +539,10 @@
|
|||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\GBColors.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\GBDisassembler.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\IGameboyCommon.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\LibGambatte.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\LibPizza.cs" />
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\Pizza.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBA\ArmV4Disassembler.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBA\GBA.cs" />
|
||||
<Compile Include="Consoles\Nintendo\GBA\IGBAGPUViewable.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<Gameboy.GambatteSettings, Gameboy.GambatteSyncSettings>
|
||||
IBoardInfo, IDebuggable, ISettable<Gameboy.GambatteSettings, Gameboy.GambatteSyncSettings>,
|
||||
IGameboyCommon
|
||||
{
|
||||
[CoreConstructor("GB", "GBC")]
|
||||
public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings, bool deterministic)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<LibPizza>(_exe, _exe);
|
||||
using (_exe.EnterExit())
|
||||
{
|
||||
if (!_pizza.Init(rom, rom.Length))
|
||||
{
|
||||
throw new InvalidOperationException("Core rejected the rom!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// the nominal length of one frame
|
||||
/// </summary>
|
||||
private const int TICKSPERFRAME = 35112;
|
||||
|
||||
/// <summary>
|
||||
/// number of ticks per second (GB, CGB)
|
||||
/// </summary>
|
||||
private const int TICKSPERSECOND = 2097152;
|
||||
|
||||
/// <summary>
|
||||
/// number of ticks per second (SGB)
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
/* prototypes */
|
||||
char cartridge_load(char *file_nm);
|
||||
char cartridge_load(const void* data, size_t sz);
|
||||
void cartridge_term();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,29 +24,7 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "sound.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -17,13 +17,9 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#else
|
||||
#include <emulibc.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <emulibc.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 (; px<magnify_rate; px++)
|
||||
line[(int) (px + (x * magnify_rate))] =
|
||||
fb[x + (y * 160)];
|
||||
|
||||
px -= magnify_rate;
|
||||
}
|
||||
|
||||
for (; py<magnify_rate; py++)
|
||||
memcpy(&pixel[(int) (((y * magnify_rate) + py) *
|
||||
160 * magnify_rate)],
|
||||
line, sizeof(uint16_t) * 160 * magnify_rate);
|
||||
|
||||
py -= magnify_rate;
|
||||
}
|
||||
|
||||
free(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* just copy GPU frame buffer into SDL frame buffer */
|
||||
memcpy(pixel, fb, 160 * 144 * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
SDL_ConvertPixels(screenSurface->w, 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");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue