diff options
| author | Louis Burda <quent.burda@gmail.com> | 2022-06-02 15:28:40 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2022-06-02 15:28:40 +0200 |
| commit | 5bc16063c29aa4d3d287ebd163ccdbcbf54c4f9f (patch) | |
| tree | c131f947a37b3af2d14d41e9eda098bdec2d061c /gearboy/platforms/raspberrypi/main.cpp | |
| parent | 78a5f810b22f0d8cafa05f638b0cb2e889824859 (diff) | |
| download | cscg2022-gearboy-master.tar.gz cscg2022-gearboy-master.zip | |
Diffstat (limited to 'gearboy/platforms/raspberrypi/main.cpp')
| -rw-r--r-- | gearboy/platforms/raspberrypi/main.cpp | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/gearboy/platforms/raspberrypi/main.cpp b/gearboy/platforms/raspberrypi/main.cpp new file mode 100644 index 00000000..746277c3 --- /dev/null +++ b/gearboy/platforms/raspberrypi/main.cpp @@ -0,0 +1,633 @@ +/* + * Gearboy - Nintendo Game Boy Emulator + * Copyright (C) 2012 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> +#include <unistd.h> +#include <iostream> +#include <iomanip> +#include <stdlib.h> +#include <sys/time.h> +#include <SDL2/SDL.h> +#include <libconfig.h++> +#include "bcm_host.h" +#include "GLES/gl.h" +#include "EGL/egl.h" +#include "EGL/eglext.h" + +#include "gearboy.h" +#include "../audio-shared/Sound_Queue.h" + +using namespace std; +using namespace libconfig; + +bool running = true; +bool paused = false; + +EGLDisplay display; +EGLSurface surface; +EGLContext context; + +static const char *output_file = "gearboy.cfg"; + +const float kGB_Width = 160.0f; +const float kGB_Height = 144.0f; +const float kGB_TexWidth = kGB_Width / 256.0f; +const float kGB_TexHeight = kGB_Height / 256.0f; +const GLfloat kQuadTex[8] = { 0, 0, kGB_TexWidth, 0, kGB_TexWidth, kGB_TexHeight, 0, kGB_TexHeight}; +GLshort quadVerts[8]; + +GearboyCore* theGearboyCore; +Sound_Queue* theSoundQueue; +u16* theFrameBuffer; +GLuint theGBTexture; +s16 theSampleBufffer[AUDIO_BUFFER_SIZE]; + +bool audioEnabled = true; + +struct palette_color +{ + int red; + int green; + int blue; + int alpha; +}; + +palette_color dmg_palette[4]; + +SDL_Joystick* game_pad = NULL; +SDL_Keycode kc_keypad_left, kc_keypad_right, kc_keypad_up, kc_keypad_down, kc_keypad_a, kc_keypad_b, kc_keypad_start, kc_keypad_select, kc_emulator_pause, kc_emulator_quit; +bool jg_x_axis_invert, jg_y_axis_invert; +int jg_a, jg_b, jg_start, jg_select, jg_x_axis, jg_y_axis; + +uint32_t screen_width, screen_height; + +SDL_Window* theWindow; + +void update(void) +{ + SDL_Event keyevent; + + while (SDL_PollEvent(&keyevent)) + { + switch(keyevent.type) + { + case SDL_QUIT: + running = false; + break; + + case SDL_JOYBUTTONDOWN: + { + if (keyevent.jbutton.button == jg_b) + theGearboyCore->KeyPressed(B_Key); + else if (keyevent.jbutton.button == jg_a) + theGearboyCore->KeyPressed(A_Key); + else if (keyevent.jbutton.button == jg_select) + theGearboyCore->KeyPressed(Select_Key); + else if (keyevent.jbutton.button == jg_start) + theGearboyCore->KeyPressed(Start_Key); + } + break; + + case SDL_JOYBUTTONUP: + { + if (keyevent.jbutton.button == jg_b) + theGearboyCore->KeyReleased(B_Key); + else if (keyevent.jbutton.button == jg_a) + theGearboyCore->KeyReleased(A_Key); + else if (keyevent.jbutton.button == jg_select) + theGearboyCore->KeyReleased(Select_Key); + else if (keyevent.jbutton.button == jg_start) + theGearboyCore->KeyReleased(Start_Key); + } + break; + + case SDL_JOYAXISMOTION: + { + if(keyevent.jaxis.axis == jg_x_axis) + { + int x_motion = keyevent.jaxis.value * (jg_x_axis_invert ? -1 : 1); + if (x_motion < 0) + theGearboyCore->KeyPressed(Left_Key); + else if (x_motion > 0) + theGearboyCore->KeyPressed(Right_Key); + else + { + theGearboyCore->KeyReleased(Left_Key); + theGearboyCore->KeyReleased(Right_Key); + } + } + else if(keyevent.jaxis.axis == jg_y_axis) + { + int y_motion = keyevent.jaxis.value * (jg_y_axis_invert ? -1 : 1); + if (y_motion < 0) + theGearboyCore->KeyPressed(Up_Key); + else if (y_motion > 0) + theGearboyCore->KeyPressed(Down_Key); + else + { + theGearboyCore->KeyReleased(Up_Key); + theGearboyCore->KeyReleased(Down_Key); + } + } + } + break; + + case SDL_KEYDOWN: + { + if (keyevent.key.keysym.sym == kc_keypad_left) + theGearboyCore->KeyPressed(Left_Key); + else if (keyevent.key.keysym.sym == kc_keypad_right) + theGearboyCore->KeyPressed(Right_Key); + else if (keyevent.key.keysym.sym == kc_keypad_up) + theGearboyCore->KeyPressed(Up_Key); + else if (keyevent.key.keysym.sym == kc_keypad_down) + theGearboyCore->KeyPressed(Down_Key); + else if (keyevent.key.keysym.sym == kc_keypad_b) + theGearboyCore->KeyPressed(B_Key); + else if (keyevent.key.keysym.sym == kc_keypad_a) + theGearboyCore->KeyPressed(A_Key); + else if (keyevent.key.keysym.sym == kc_keypad_select) + theGearboyCore->KeyPressed(Select_Key); + else if (keyevent.key.keysym.sym == kc_keypad_start) + theGearboyCore->KeyPressed(Start_Key); + + if (keyevent.key.keysym.sym == kc_emulator_quit) + running = false; + else if (keyevent.key.keysym.sym == kc_emulator_pause) + { + paused = !paused; + theGearboyCore->Pause(paused); + } + } + break; + + case SDL_KEYUP: + { + if (keyevent.key.keysym.sym == kc_keypad_left) + theGearboyCore->KeyReleased(Left_Key); + else if (keyevent.key.keysym.sym == kc_keypad_right) + theGearboyCore->KeyReleased(Right_Key); + else if (keyevent.key.keysym.sym == kc_keypad_up) + theGearboyCore->KeyReleased(Up_Key); + else if (keyevent.key.keysym.sym == kc_keypad_down) + theGearboyCore->KeyReleased(Down_Key); + else if (keyevent.key.keysym.sym == kc_keypad_b) + theGearboyCore->KeyReleased(B_Key); + else if (keyevent.key.keysym.sym == kc_keypad_a) + theGearboyCore->KeyReleased(A_Key); + else if (keyevent.key.keysym.sym == kc_keypad_select) + theGearboyCore->KeyReleased(Select_Key); + else if (keyevent.key.keysym.sym == kc_keypad_start) + theGearboyCore->KeyReleased(Start_Key); + } + break; + } + } + + int sampleCount = 0; + + theGearboyCore->RunToVBlank(theFrameBuffer, theSampleBufffer, &sampleCount); + + if (audioEnabled && (sampleCount > 0)) + { + theSoundQueue->write(theSampleBufffer, sampleCount); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 160, 144, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (GLvoid*) theFrameBuffer); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + eglSwapBuffers(display, surface); +} + +void init_sdl(void) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) + { + Log("SDL Error Init: %s", SDL_GetError()); + } + + theWindow = SDL_CreateWindow(GEARBOY_TITLE, 0, 0, 0, 0, 0); + + if (theWindow == NULL) + { + Log("SDL Error Video: %s", SDL_GetError()); + } + + SDL_ShowCursor(SDL_DISABLE); + + game_pad = SDL_JoystickOpen(0); + + if(game_pad == NULL) + { + Log("Warning: Unable to open game controller! SDL Error: %s\n", SDL_GetError()); + } + + kc_keypad_left = SDLK_LEFT; + kc_keypad_right = SDLK_RIGHT; + kc_keypad_up = SDLK_UP; + kc_keypad_down = SDLK_DOWN; + kc_keypad_a = SDLK_a; + kc_keypad_b = SDLK_s; + kc_keypad_start = SDLK_RETURN; + kc_keypad_select = SDLK_SPACE; + kc_emulator_pause = SDLK_p; + kc_emulator_quit = SDLK_ESCAPE; + + jg_x_axis_invert = false; + jg_y_axis_invert = false; + jg_a = 1; + jg_b = 2; + jg_start = 9; + jg_select = 8; + jg_x_axis = 0; + jg_y_axis = 1; + + dmg_palette[0].red = 0xEF; + dmg_palette[0].green = 0xF3; + dmg_palette[0].blue = 0xD5; + dmg_palette[0].alpha = 0xFF; + + dmg_palette[1].red = 0xA3; + dmg_palette[1].green = 0xB6; + dmg_palette[1].blue = 0x7A; + dmg_palette[1].alpha = 0xFF; + + dmg_palette[2].red = 0x37; + dmg_palette[2].green = 0x61; + dmg_palette[2].blue = 0x3B; + dmg_palette[2].alpha = 0xFF; + + dmg_palette[3].red = 0x04; + dmg_palette[3].green = 0x1C; + dmg_palette[3].blue = 0x16; + dmg_palette[3].alpha = 0xFF; + + Config cfg; + + try + { + cfg.readFile(output_file); + + try + { + const Setting& root = cfg.getRoot(); + const Setting &gearboy = root[GEARBOY_TITLE]; + + string keypad_left, keypad_right, keypad_up, keypad_down, keypad_a, keypad_b, + keypad_start, keypad_select, emulator_pause, emulator_quit; + gearboy.lookupValue("keypad_left", keypad_left); + gearboy.lookupValue("keypad_right", keypad_right); + gearboy.lookupValue("keypad_up", keypad_up); + gearboy.lookupValue("keypad_down", keypad_down); + gearboy.lookupValue("keypad_a", keypad_a); + gearboy.lookupValue("keypad_b", keypad_b); + gearboy.lookupValue("keypad_start", keypad_start); + gearboy.lookupValue("keypad_select", keypad_select); + + gearboy.lookupValue("joystick_gamepad_a", jg_a); + gearboy.lookupValue("joystick_gamepad_b", jg_b); + gearboy.lookupValue("joystick_gamepad_start", jg_start); + gearboy.lookupValue("joystick_gamepad_select", jg_select); + gearboy.lookupValue("joystick_gamepad_x_axis", jg_x_axis); + gearboy.lookupValue("joystick_gamepad_y_axis", jg_y_axis); + gearboy.lookupValue("joystick_gamepad_x_axis_invert", jg_x_axis_invert); + gearboy.lookupValue("joystick_gamepad_y_axis_invert", jg_y_axis_invert); + + gearboy.lookupValue("emulator_pause", emulator_pause); + gearboy.lookupValue("emulator_quit", emulator_quit); + + gearboy.lookupValue("emulator_pal0_red", dmg_palette[0].red); + gearboy.lookupValue("emulator_pal0_green", dmg_palette[0].green); + gearboy.lookupValue("emulator_pal0_blue", dmg_palette[0].blue); + gearboy.lookupValue("emulator_pal1_red", dmg_palette[1].red); + gearboy.lookupValue("emulator_pal1_green", dmg_palette[1].green); + gearboy.lookupValue("emulator_pal1_blue", dmg_palette[1].blue); + gearboy.lookupValue("emulator_pal2_red", dmg_palette[2].red); + gearboy.lookupValue("emulator_pal2_green", dmg_palette[2].green); + gearboy.lookupValue("emulator_pal2_blue", dmg_palette[2].blue); + gearboy.lookupValue("emulator_pal3_red", dmg_palette[3].red); + gearboy.lookupValue("emulator_pal3_green", dmg_palette[3].green); + gearboy.lookupValue("emulator_pal3_blue", dmg_palette[3].blue); + + kc_keypad_left = SDL_GetKeyFromName(keypad_left.c_str()); + kc_keypad_right = SDL_GetKeyFromName(keypad_right.c_str()); + kc_keypad_up = SDL_GetKeyFromName(keypad_up.c_str()); + kc_keypad_down = SDL_GetKeyFromName(keypad_down.c_str()); + kc_keypad_a = SDL_GetKeyFromName(keypad_a.c_str()); + kc_keypad_b = SDL_GetKeyFromName(keypad_b.c_str()); + kc_keypad_start = SDL_GetKeyFromName(keypad_start.c_str()); + kc_keypad_select = SDL_GetKeyFromName(keypad_select.c_str()); + + kc_emulator_pause = SDL_GetKeyFromName(emulator_pause.c_str()); + kc_emulator_quit = SDL_GetKeyFromName(emulator_quit.c_str()); + } + catch(const SettingNotFoundException &nfex) + { + std::cerr << "Setting not found" << std::endl; + } + } + catch(const FileIOException &fioex) + { + Log("I/O error while reading file: %s", output_file); + } + catch(const ParseException &pex) + { + std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() + << " - " << pex.getError() << std::endl; + } +} + +void init_ogl(void) +{ + int32_t success = 0; + EGLBoolean result; + EGLint num_config; + + static EGL_DISPMANX_WINDOW_T nativewindow; + + DISPMANX_ELEMENT_HANDLE_T dispman_element; + DISPMANX_DISPLAY_HANDLE_T dispman_display; + DISPMANX_UPDATE_HANDLE_T dispman_update; + VC_DISPMANX_ALPHA_T alpha; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + + static const EGLint attribute_list[] = + { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + + EGLConfig config; + + // Get an EGL display connection + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + assert(display!=EGL_NO_DISPLAY); + + // Initialize the EGL display connection + result = eglInitialize(display, NULL, NULL); + assert(EGL_FALSE != result); + + // Get an appropriate EGL frame buffer configuration + result = eglChooseConfig(display, attribute_list, &config, 1, &num_config); + assert(EGL_FALSE != result); + + // Create an EGL rendering context + context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); + assert(context!=EGL_NO_CONTEXT); + + // Create an EGL window surface + success = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height); + assert( success >= 0 ); + + int32_t zoom = screen_width / GAMEBOY_WIDTH; + int32_t zoom2 = screen_height / GAMEBOY_HEIGHT; + + if (zoom2 < zoom) + zoom = zoom2; + + int32_t display_width = GAMEBOY_WIDTH * zoom; + int32_t display_height = GAMEBOY_HEIGHT * zoom; + int32_t display_offset_x = (screen_width / 2) - (display_width / 2); + int32_t display_offset_y = (screen_height / 2) - (display_height / 2); + + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = screen_width; + dst_rect.height = screen_height; + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = screen_width << 16; + src_rect.height = screen_height << 16; + + dispman_display = vc_dispmanx_display_open( 0 /* LCD */); + dispman_update = vc_dispmanx_update_start( 0 ); + + alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; + alpha.opacity = 255; + alpha.mask = 0; + + dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, + 0/*layer*/, &dst_rect, 0/*src*/, + &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, DISPMANX_NO_ROTATE/*transform*/); + + nativewindow.element = dispman_element; + nativewindow.width = screen_width; + nativewindow.height = screen_height; + vc_dispmanx_update_submit_sync( dispman_update ); + + surface = eglCreateWindowSurface( display, config, &nativewindow, NULL ); + assert(surface != EGL_NO_SURFACE); + + // Connect the context to the surface + result = eglMakeCurrent(display, surface, surface, context); + assert(EGL_FALSE != result); + + eglSwapInterval(display, 1); + + glGenTextures(1, &theGBTexture); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, theGBTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (GLvoid*) NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrthof(0.0f, screen_width, screen_height, 0.0f, -1.0f, 1.0f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glViewport(0.0f, 0.0f, screen_width, screen_height); + + quadVerts[0] = display_offset_x; + quadVerts[1] = display_offset_y; + quadVerts[2] = display_offset_x + display_width; + quadVerts[3] = display_offset_y; + quadVerts[4] = display_offset_x + display_width; + quadVerts[5] = display_offset_y + display_height; + quadVerts[6] = display_offset_x; + quadVerts[7] = display_offset_y + display_height; + + glVertexPointer(2, GL_SHORT, 0, quadVerts); + glEnableClientState(GL_VERTEX_ARRAY); + + glTexCoordPointer(2, GL_FLOAT, 0, kQuadTex); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glClear(GL_COLOR_BUFFER_BIT); +} + +void init(void) +{ + + bcm_host_init(); + init_ogl(); + init_sdl(); + + theGearboyCore = new GearboyCore(); + theGearboyCore->Init(); + + theSoundQueue = new Sound_Queue(); + theSoundQueue->start(44100, 2); + + theFrameBuffer = new u16[GAMEBOY_WIDTH * GAMEBOY_HEIGHT]; + + for (int i = 0; i < (GAMEBOY_WIDTH * GAMEBOY_HEIGHT); ++i) + { + theFrameBuffer[i] = 0; + } +} + +void end(void) +{ + Config cfg; + + Setting &root = cfg.getRoot(); + Setting &address = root.add(GEARBOY_TITLE, Setting::TypeGroup); + + address.add("keypad_left", Setting::TypeString) = SDL_GetKeyName(kc_keypad_left); + address.add("keypad_right", Setting::TypeString) = SDL_GetKeyName(kc_keypad_right); + address.add("keypad_up", Setting::TypeString) = SDL_GetKeyName(kc_keypad_up); + address.add("keypad_down", Setting::TypeString) = SDL_GetKeyName(kc_keypad_down); + address.add("keypad_a", Setting::TypeString) = SDL_GetKeyName(kc_keypad_a); + address.add("keypad_b", Setting::TypeString) = SDL_GetKeyName(kc_keypad_b); + address.add("keypad_start", Setting::TypeString) = SDL_GetKeyName(kc_keypad_start); + address.add("keypad_select", Setting::TypeString) = SDL_GetKeyName(kc_keypad_select); + + address.add("joystick_gamepad_a", Setting::TypeInt) = jg_a; + address.add("joystick_gamepad_b", Setting::TypeInt) = jg_b; + address.add("joystick_gamepad_start", Setting::TypeInt) = jg_start; + address.add("joystick_gamepad_select", Setting::TypeInt) = jg_select; + address.add("joystick_gamepad_x_axis", Setting::TypeInt) = jg_x_axis; + address.add("joystick_gamepad_y_axis", Setting::TypeInt) = jg_y_axis; + address.add("joystick_gamepad_x_axis_invert", Setting::TypeBoolean) = jg_x_axis_invert; + address.add("joystick_gamepad_y_axis_invert", Setting::TypeBoolean) = jg_y_axis_invert; + + address.add("emulator_pause", Setting::TypeString) = SDL_GetKeyName(kc_emulator_pause); + address.add("emulator_quit", Setting::TypeString) = SDL_GetKeyName(kc_emulator_quit); + + address.add("emulator_pal0_red", Setting::TypeInt) = dmg_palette[0].red; + address.add("emulator_pal0_green", Setting::TypeInt) = dmg_palette[0].green; + address.add("emulator_pal0_blue", Setting::TypeInt) = dmg_palette[0].blue; + address.add("emulator_pal1_red", Setting::TypeInt) = dmg_palette[1].red; + address.add("emulator_pal1_green", Setting::TypeInt) = dmg_palette[1].green; + address.add("emulator_pal1_blue", Setting::TypeInt) = dmg_palette[1].blue; + address.add("emulator_pal2_red", Setting::TypeInt) = dmg_palette[2].red; + address.add("emulator_pal2_green", Setting::TypeInt) = dmg_palette[2].green; + address.add("emulator_pal2_blue", Setting::TypeInt) = dmg_palette[2].blue; + address.add("emulator_pal3_red", Setting::TypeInt) = dmg_palette[3].red; + address.add("emulator_pal3_green", Setting::TypeInt) = dmg_palette[3].green; + address.add("emulator_pal3_blue", Setting::TypeInt) = dmg_palette[3].blue; + + try + { + cfg.writeFile(output_file); + } + catch(const FileIOException &fioex) + { + Log("I/O error while writing file: %s", output_file); + } + + SDL_JoystickClose(game_pad); + + SafeDeleteArray(theFrameBuffer); + SafeDelete(theSoundQueue); + SafeDelete(theGearboyCore); + SDL_DestroyWindow(theWindow); + SDL_Quit(); + bcm_host_deinit(); +} + +int main(int argc, char** argv) +{ + init(); + + if (argc < 2 || argc > 4) + { + end(); + printf("usage: %s rom_path [options]\n", argv[0]); + printf("options:\n-nosound\n-forcedmg\n"); + return -1; + } + + bool forcedmg = false; + + if (argc > 2) + { + for (int i = 2; i < argc; i++) + { + if (strcmp("-nosound", argv[i]) == 0) + audioEnabled = false; + else if (strcmp("-forcedmg", argv[i]) == 0) + forcedmg = true; + else + { + end(); + printf("invalid option: %s\n", argv[i]); + return -1; + } + } + } + + if (theGearboyCore->LoadROM(argv[1], forcedmg)) + { + GB_Color color1; + GB_Color color2; + GB_Color color3; + GB_Color color4; + + color1.red = dmg_palette[0].red; + color1.green = dmg_palette[0].green; + color1.blue = dmg_palette[0].blue; + color2.red = dmg_palette[1].red; + color2.green = dmg_palette[1].green; + color2.blue = dmg_palette[1].blue; + color3.red = dmg_palette[2].red; + color3.green = dmg_palette[2].green; + color3.blue = dmg_palette[2].blue; + color4.red = dmg_palette[3].red; + color4.green = dmg_palette[3].green; + color4.blue = dmg_palette[3].blue; + + theGearboyCore->SetDMGPalette(color1, color2, color3, color4); + theGearboyCore->LoadRam(); + + while (running) + { + update(); + } + + theGearboyCore->SaveRam(); + } + + end(); + + return 0; +} |
