| @@ -62,9 +62,16 @@ entirely with `--no-save`. | |||
| Add `--debug` (`-g`) to show logging information while running. Pass it twice | |||
| (`-gg`) to show more detailed logs, including an emulator trace. | |||
| crater tries to reproduce the Game Gear's native display resolution, which had | |||
| a pixel aspect ratio (PAR) of [8:7][par]; this means the pixels were slightly | |||
| wider than square, unlike modern LCD displays with a 1:1 PAR. Add `--square` | |||
| (`-q`) to force square pixels. | |||
| `./crater -h` gives (fairly basic) command-line usage, and `./crater -v` gives | |||
| the current version. | |||
| [par]: https://pineight.com/mw/index.php?title=Dot_clock_rates | |||
| ### Input | |||
| crater supports keyboard and joystick/controller input. | |||
| @@ -44,6 +44,8 @@ static void print_help(const char *arg1) | |||
| " the Game Gear does not usually require BIOS)\n" | |||
| " -x, --scale <n> scale the game screen by an integer factor\n" | |||
| " (applies to windowed mode only; defaults to 4)\n" | |||
| " -q, --square force a square pixel aspect ratio instead of the more\n" | |||
| " faithful 8:7 PAR\n" | |||
| " -a, --assemble <in> [<out>]\n" | |||
| " convert z80 assembly source code into a binary file that\n" | |||
| " can be run by crater\n" | |||
| @@ -269,6 +271,9 @@ static int parse_opt_arg(Config *config, Arguments *args, const char *arg) | |||
| } | |||
| config->scale = scale; | |||
| } | |||
| else if (arg_check(arg, "q", "square")) { | |||
| config->square_par = true; | |||
| } | |||
| else if (arg_check(arg, "a", "assemble")) { | |||
| if (args->paths_read >= 1) { | |||
| config->src_path = config->rom_path; | |||
| @@ -367,7 +372,8 @@ static bool sanity_check(Config *config) | |||
| } else if (config->assemble && config->disassemble) { | |||
| ERROR("cannot assemble and disassemble at the same time") | |||
| return false; | |||
| } else if (assembler && (config->fullscreen || config->scale)) { | |||
| } else if (assembler && (config->fullscreen || config->scale || | |||
| config->square_par)) { | |||
| ERROR("cannot specify emulator options in assembler mode") | |||
| return false; | |||
| } else if (assembler && !config->src_path) { | |||
| @@ -424,6 +430,7 @@ int config_create(Config** config_ptr, int argc, char* argv[]) | |||
| config->fullscreen = false; | |||
| config->no_saving = false; | |||
| config->scale = 0; | |||
| config->square_par = false; | |||
| config->rom_path = NULL; | |||
| config->sav_path = NULL; | |||
| config->bios_path = NULL; | |||
| @@ -469,6 +476,7 @@ void config_dump_args(const Config* config) | |||
| DEBUG("- fullscreen: %s", config->fullscreen ? "true" : "false") | |||
| DEBUG("- no_saving: %s", config->no_saving ? "true" : "false") | |||
| DEBUG("- scale: %d", config->scale) | |||
| DEBUG("- square_par: %s", config->square_par ? "true" : "false") | |||
| DEBUG("- rom_path: %s", config->rom_path ? config->rom_path : "(null)") | |||
| DEBUG("- sav_path: %s", config->sav_path ? config->sav_path : "(null)") | |||
| DEBUG("- bios_path: %s", config->bios_path ? config->bios_path : "(null)") | |||
| @@ -14,10 +14,9 @@ | |||
| /* | |||
| We need some sort of maximum scale - with a native resolution of 160 x 144, | |||
| a scale factor of 1024 will let us go up to 163,840 x 147,456 pixels. | |||
| No one has a screen this large. | |||
| a scale factor of 128 will let us go up to 20,480 x 18,432 pixels. | |||
| */ | |||
| #define SCALE_MAX 1024 | |||
| #define SCALE_MAX 128 | |||
| /* Structs */ | |||
| @@ -28,6 +27,7 @@ typedef struct { | |||
| bool fullscreen; | |||
| bool no_saving; | |||
| unsigned scale; | |||
| bool square_par; | |||
| char *rom_path; | |||
| char *sav_path; | |||
| char *bios_path; | |||
| @@ -88,19 +88,22 @@ static void setup_input() | |||
| /* | |||
| Set up SDL for drawing the game. | |||
| */ | |||
| static void setup_graphics(bool fullscreen, unsigned scale) | |||
| static void setup_graphics(Config *config) | |||
| { | |||
| SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); | |||
| uint32_t flags; | |||
| if (fullscreen) | |||
| if (config->fullscreen) | |||
| flags = SDL_WINDOW_FULLSCREEN_DESKTOP; | |||
| else | |||
| flags = SDL_WINDOW_RESIZABLE; | |||
| SDL_CreateWindowAndRenderer( | |||
| scale * GG_SCREEN_WIDTH, scale * GG_SCREEN_HEIGHT, | |||
| flags, &emu.window, &emu.renderer); | |||
| int width = config->scale * GG_SCREEN_WIDTH; | |||
| int height = config->scale * GG_SCREEN_HEIGHT; | |||
| if (!config->square_par) | |||
| height = height * GG_PIXEL_HEIGHT / GG_PIXEL_WIDTH; | |||
| SDL_CreateWindowAndRenderer(width, height, flags, | |||
| &emu.window, &emu.renderer); | |||
| if (!emu.window) | |||
| FATAL("SDL failed to create a window: %s", SDL_GetError()); | |||
| @@ -116,7 +119,9 @@ static void setup_graphics(bool fullscreen, unsigned scale) | |||
| emu.pixels = cr_malloc( | |||
| sizeof(uint32_t) * GG_SCREEN_WIDTH * GG_SCREEN_HEIGHT); | |||
| SDL_RenderSetLogicalSize(emu.renderer, GG_SCREEN_WIDTH, GG_SCREEN_HEIGHT); | |||
| SDL_RenderSetLogicalSize(emu.renderer, | |||
| config->square_par ? GG_SCREEN_WIDTH : GG_LOGICAL_WIDTH, | |||
| config->square_par ? GG_SCREEN_HEIGHT : GG_LOGICAL_HEIGHT); | |||
| SDL_SetTextureBlendMode(emu.texture, SDL_BLENDMODE_BLEND); | |||
| SDL_SetWindowTitle(emu.window, "crater"); | |||
| SDL_ShowCursor(SDL_DISABLE); | |||
| @@ -130,13 +135,13 @@ static void setup_graphics(bool fullscreen, unsigned scale) | |||
| /* | |||
| Set up SDL. | |||
| */ | |||
| static void setup_sdl(bool fullscreen, unsigned scale) | |||
| static void setup_sdl(Config *config) | |||
| { | |||
| if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER) < 0) | |||
| FATAL("SDL failed to initialize: %s", SDL_GetError()); | |||
| setup_input(); | |||
| setup_graphics(fullscreen, scale); | |||
| setup_graphics(config); | |||
| } | |||
| /* | |||
| @@ -370,7 +375,7 @@ void emulate(ROM *rom, Config *config) | |||
| emu.gg = gamegear_create(); | |||
| signal(SIGINT, handle_sigint); | |||
| setup_sdl(config->fullscreen, config->scale); | |||
| setup_sdl(config); | |||
| gamegear_attach_callback(emu.gg, frame_callback); | |||
| gamegear_attach_display(emu.gg, emu.pixels); | |||
| @@ -15,6 +15,10 @@ | |||
| #define GG_SCREEN_WIDTH 160 | |||
| #define GG_SCREEN_HEIGHT 144 | |||
| #define GG_PIXEL_WIDTH 8 | |||
| #define GG_PIXEL_HEIGHT 7 | |||
| #define GG_LOGICAL_WIDTH (GG_SCREEN_WIDTH * GG_PIXEL_WIDTH) | |||
| #define GG_LOGICAL_HEIGHT (GG_SCREEN_HEIGHT * GG_PIXEL_HEIGHT) | |||
| #define GG_FPS 60 | |||
| #define GG_EXC_BUFF_SIZE 128 | |||