pizza progress: it runs

This commit is contained in:
nattthebear 2017-06-15 19:00:41 -04:00
parent 0d7116ef06
commit 8fa903c004
27 changed files with 295 additions and 372 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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" />

View File

@ -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)

View File

@ -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();
}
}

View File

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

View File

@ -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
}
}

6
waterbox/pizza/.vscode/settings.json vendored Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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

View File

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

View File

@ -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];

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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 */

View File

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

View File

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