#include #include #include #include #include #include #include #include #include "lodepng.h" #include "gb.h" #define NUM_FRAMES 600 // #define SKIP_STEPS 1000000 #define NUM_STEPS 200000 static uint32_t file_size( const char * const path ) { struct stat st; if (stat(path, &st)) { perror("stat():"); exit(EXIT_FAILURE); } return st.st_size; } static const uint8_t * load( const char * const path, uint32_t * const r_file_size ) { const uint32_t rom_size = file_size(path); uint8_t *rom_data = malloc(rom_size); if (!rom_data) { perror("malloc():"); exit(EXIT_FAILURE); } FILE *fh = fopen(path, "rb"); if (!fh) { perror("fopen():"); exit(EXIT_FAILURE); } if (!fread(rom_data, rom_size, 1, fh)) { perror("fread():"); exit(EXIT_FAILURE); } fclose(fh); if (r_file_size) { *r_file_size = (uint32_t) rom_size; } return rom_data; } // buffer for rendered frames static uint8_t frames[NUM_FRAMES * GB_FRAME_SIZE]; static void test_render_frames( const char * const png_path, const char * const rom_path ) { // load rom data uint32_t rom_size = 0; const uint8_t *rom_data = load(rom_path, &rom_size); fprintf(stderr, "loaded \"%s\" (%u bytes)\n", rom_path, rom_size); // init context gb_t ctx; gb_init(&ctx, rom_data, rom_size); fprintf(stderr, "gb context initialized\n"); // render frames for (size_t j = 0; j < NUM_FRAMES; j++) { // render frame gb_frame(&ctx); // copy frame to buffer memcpy(frames + GB_FRAME_SIZE * j, gb_get_rgb_frame(&ctx), GB_FRAME_SIZE); } // save png if (lodepng_encode24_file(png_path, frames, 160, 144 * NUM_FRAMES)) { fprintf(stderr, "lode_png_encode24_file() failed\n"); exit(EXIT_FAILURE); } fprintf(stderr, "%d frames rendered\n", NUM_FRAMES); // free rom data free((void*) rom_data); } const char * const RWS[] = { "AF", "BC", "DE", "HL", "SP", "PC", NULL }; static void gb_dump_context( const gb_t * const ctx ) { for (int i = 0; RWS[i]; i++) { printf("%s%s: 0x%04X", (!i) ? "" : ", ", RWS[i], ctx->cpu.rs[i]); } printf("\n"); } static void test_execute_steps( const char * const rom_path ) { // load rom data uint32_t rom_size = 0; const uint8_t *rom_data = load(rom_path, &rom_size); fprintf(stderr, "loaded \"%s\" (%u bytes)\n", rom_path, rom_size); // init context gb_t ctx; gb_init(&ctx, rom_data, rom_size); fprintf(stderr, "gb context initialized\n"); #ifdef SKIP_STEPS for (size_t i = 0; i < SKIP_STEPS; i++) { // step cpu gb_step(&ctx); } #endif /* SKIP_STEPS */ // run cpu for (size_t i = 0; i < NUM_STEPS; i++) { // print context gb_dump_context(&ctx); // step cpu gb_step(&ctx); } // free rom data free((void*) rom_data); } int main(int argc, char *argv[]) { // render 600 frames for (int i = 2; i < argc; i++) { if (argv[1][0] == 'f') { test_render_frames("out.png", argv[i]); } else if (argv[1][0] == 'e') { test_execute_steps(argv[i]); } else { fprintf(stderr, "unknown test: %s\n", argv[i]); exit(EXIT_FAILURE); } } // return success return 0; }