https://github.com/x213212/LLD_gbemu_wasm/
# enable SharedArrayBuffer
![](https://i.imgur.com/qALQRCJ.png)
# enable pthread
```c=
#include "../include/common.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
// TODO Add Windows Alternative...
/*
Emu components:
|Cart|
|CPU|
|Address Bus|
|PPU|
|Timer|
*/
static emu_context ctx;
u32 prev_frame = 0;
int count2 = 0;
// EMSCRIPTEN_KEEPALIVE
void handle_events()
{
usleep(100);
ui_handle_events();
ui_update();
}
void run_main_loop()
{
#ifdef __EMSCRIPTEN__
printf("Cart loaded..\n");
emscripten_set_main_loop(handle_events, 60, true);
#else
printf("Cart loaded2..\n");
while (ctx.running)
{
handle_events();
}
#endif
}
emu_context *emu_get_context()
{
return &ctx;
}
void *cpu_run(void *p)
{
timer_init();
cpu_init();
ppu_init();
ctx.running = true;
ctx.paused = false;
ctx.too = false;
ctx.ticks = 0;
// cpu_set_flags(ctx, ctx.regs.a, 1, (val & 0x0F) == 0x0F, -1);
// fp = fopen("regist.txt", "w");
while (ctx.running)
{
if (ctx.too)
break;
if (ctx.paused)
{
delay(10);
continue;
}
if (!cpu_step())
{
printf("CPU Stopped\n");
return 0;
}
// if (count2 >= 2000000 && count2 <= 4000000)
// continue;
}
return 0;
}
int emu_run()
{
// if (argc < 2)
// {
// printf("Usage: emu <rom_file>\n");
// return -1;
// }
if (!cart_load("LG.gb"))
// if (!cart_load(argv[1]))
{
printf("Failed to load ROM file: %s\n", "LG.gb");
return -2;
}
printf("Cart loaded..\n");
ui_init();
timer_init();
cpu_init();
ppu_init();
ctx.running = true;
ctx.paused = false;
ctx.too = false;
ctx.ticks = 0;
// u32 prev_frame = 0;
// int count2 = 0;
// cpu_set_flags(ctx, ctx.regs.a, 1, (val & 0x0F) == 0x0F, -1);
// fp = fopen("regist.txt", "w");
pthread_t t1;
if (pthread_create(&t1, NULL, cpu_run, NULL))
{
fprintf(stderr, "FAILED TO START MAIN CPU THREAD!\n");
return -1;
}
u32 prev_frame = 0;
run_main_loop();
return 0;
}
void emu_cycles(int cpu_cycles)
{
for (int i = 0; i < cpu_cycles; i++)
{
for (int n = 0; n < 4; n++)
{
ctx.ticks++;
timer_tick();
ppu_tick();
}
dma_tick();
}
}
```
注意要加這個
-s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4
```bash=
emcc --bind main.c ./lib/cpu_fetch.c ./lib/interrupts.c ./lib/ppu_pipeline.c ./lib/timer.c ./lib/dma.c ./lib/bus.c ./lib/cart.c ./lib/cpu_proc.c ./lib/emu.c ./lib/io.c ./lib/ppu_sm.c ./lib/ui.c ./lib/cpu_util.c ./lib/gamepad.c ./lib/lcd.c ./lib/ram.c ./lib/cpu.c ./lib/dbg.c ./lib/instructions.c ./lib/ppu.c ./lib/stack.c -I ./include -o foo.html -s USE_SDL=2 -s USE_SDL_GFX=2 --preload-file LG.gb -sALLOW_MEMORY_GROWTH -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4
```
現在我們的fps也可以到達快60幀,我們的按鍵全部都可以work!
![](https://i.imgur.com/EFwQoz4.png)
來處理記憶體洩漏
![](https://i.imgur.com/qkG3Qcp.png)
於pixel_fifo_pop()
```c=
u32 pixel_fifo_pop() {
if (ppu_get_context()->pfc.pixel_fifo.size <= 0) {
fprintf(stderr, "ERR IN PIXEL FIFO!\n");
exit(-8);
}
fifo_entry *popped = ppu_get_context()->pfc.pixel_fifo.head;
ppu_get_context()->pfc.pixel_fifo.head = popped->next;
ppu_get_context()->pfc.pixel_fifo.size--;
u32 val = popped->value;
free(popped); <==作者忘記補
return val;
}
```
現在wasm 就可以全速運行我們的gb_emu,也不會有記憶體洩漏的問題,加上個存檔讀檔就可以像上次提到的專案進行cloud大家一起玩,畫面顯示也不會一幀一幀的跳
![](https://imgur.com/LApSnni.gif)