src/gba/gui/gui-runner.c (view raw)
1/* Copyright (c) 2013-2015 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "gui-runner.h"
7
8#include "gba/serialize.h"
9#include "util/gui/file-select.h"
10#include "util/gui/font.h"
11#include "util/gui/menu.h"
12#include "util/vfs.h"
13
14enum {
15 RUNNER_CONTINUE,
16 RUNNER_EXIT,
17 RUNNER_SAVE_STATE,
18 RUNNER_LOAD_STATE,
19};
20
21void GBAGUIInit(struct GBAGUIRunner* runner, const char* port) {
22 GUIInit(&runner->params);
23 GBAContextInit(&runner->context, port);
24 if (runner->setup) {
25 runner->setup(runner);
26 }
27}
28
29void GBAGUIDeinit(struct GBAGUIRunner* runner) {
30 if (runner->teardown) {
31 runner->teardown(runner);
32 }
33 GBAContextDeinit(&runner->context);
34}
35
36void GBAGUIRunloop(struct GBAGUIRunner* runner) {
37 struct GUIMenu pauseMenu = {
38 .title = "Game Paused",
39 .index = 0,
40 };
41 GUIMenuItemListInit(&pauseMenu.items, 0);
42 *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Unpause", .data = (void*) RUNNER_CONTINUE };
43#if !(defined(__POWERPC__) || defined(__PPC__))
44 // PPC doesn't have working savestates yet
45 *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Save state", .data = (void*) RUNNER_SAVE_STATE };
46 *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Load state", .data = (void*) RUNNER_LOAD_STATE };
47#endif
48 *GUIMenuItemListAppend(&pauseMenu.items) = (struct GUIMenuItem) { .title = "Exit game", .data = (void*) RUNNER_EXIT };
49
50 while (true) {
51 if (runner->params.guiPrepare) {
52 runner->params.guiPrepare();
53 }
54 char path[256];
55 if (!GUISelectFile(&runner->params, path, sizeof(path), GBAIsROM)) {
56 if (runner->params.guiFinish) {
57 runner->params.guiFinish();
58 }
59 GUIMenuItemListDeinit(&pauseMenu.items);
60 return;
61 }
62
63 // TODO: Message box API
64 runner->params.drawStart();
65 GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
66 runner->params.drawEnd();
67 runner->params.drawStart();
68 GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Loading...");
69 runner->params.drawEnd();
70
71 if (!GBAContextLoadROM(&runner->context, path, true)) {
72 int i;
73 for (i = 0; i < 300; ++i) {
74 runner->params.drawStart();
75 GUIFontPrint(runner->params.font, runner->params.width / 2, (GUIFontHeight(runner->params.font) + runner->params.height) / 2, GUI_TEXT_CENTER, 0xFFFFFFFF, "Load failed!");
76 runner->params.drawEnd();
77 }
78 }
79 if (runner->params.guiFinish) {
80 runner->params.guiFinish();
81 }
82 GBAContextStart(&runner->context);
83 if (runner->gameLoaded) {
84 runner->gameLoaded(runner);
85 }
86 bool running = true;
87 while (running) {
88 while (true) {
89 int guiKeys = runner->params.pollInput();
90 if (guiKeys & (1 << GUI_INPUT_CANCEL)) {
91 break;
92 }
93 uint16_t keys = runner->pollGameInput(runner);
94 if (runner->prepareForFrame) {
95 runner->prepareForFrame(runner);
96 }
97 GBAContextFrame(&runner->context, keys);
98 if (runner->drawFrame) {
99 runner->drawFrame(runner, false);
100 }
101 }
102
103 if (runner->params.guiPrepare) {
104 runner->params.guiPrepare();
105 }
106 GUIInvalidateKeys(&runner->params);
107 int keys = -1; // Huge hack to avoid an extra variable!
108 struct GUIMenuItem item;
109 enum GUIMenuExitReason reason = GUIShowMenu(&runner->params, &pauseMenu, &item);
110 if (reason == GUI_MENU_EXIT_ACCEPT) {
111 struct VFile* vf;
112 switch ((int) item.data) {
113 case RUNNER_EXIT:
114 running = false;
115 keys = 0;
116 break;
117 case RUNNER_SAVE_STATE:
118 vf = GBAGetState(runner->context.gba, 0, 1, true);
119 if (vf) {
120 GBASaveStateNamed(runner->context.gba, vf, true);
121 vf->close(vf);
122 }
123 break;
124 case RUNNER_LOAD_STATE:
125 vf = GBAGetState(runner->context.gba, 0, 1, false);
126 if (vf) {
127 GBALoadStateNamed(runner->context.gba, vf);
128 vf->close(vf);
129 }
130 break;
131 case RUNNER_CONTINUE:
132 break;
133 }
134 }
135 while (keys) {
136 GUIPollInput(&runner->params, 0, &keys);
137 }
138 if (runner->params.guiFinish) {
139 runner->params.guiFinish();
140 }
141 }
142 GBAContextStop(&runner->context);
143 if (runner->gameUnloaded) {
144 runner->gameUnloaded(runner);
145 }
146 GBAContextUnloadROM(&runner->context);
147 }
148 GUIMenuItemListDeinit(&pauseMenu.items);
149}