https://github.com/x213212/LLD_gbemu_wasm/

enable SharedArrayBuffer

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!

來處理記憶體洩漏 於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大家一起玩,畫面顯示也不會一幀一幀的跳