src/platform/psp2/main.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 "psp2-context.h"
7
8#include <mgba/internal/gba/gba.h>
9#include "feature/gui/gui-runner.h"
10#include <mgba-util/gui.h>
11#include <mgba-util/gui/font.h>
12#include <mgba-util/gui/file-select.h>
13#include <mgba-util/gui/menu.h>
14
15#include <psp2/apputil.h>
16#include <psp2/ctrl.h>
17#include <psp2/display.h>
18#include <psp2/kernel/processmgr.h>
19#include <psp2/kernel/threadmgr.h>
20#include <psp2/power.h>
21#include <psp2/sysmodule.h>
22#include <psp2/system_param.h>
23#include <psp2/touch.h>
24
25#include <vita2d.h>
26
27static void _drawStart(void) {
28 vita2d_set_vblank_wait(false);
29 vita2d_start_drawing();
30 vita2d_clear_screen();
31}
32
33static void _drawEnd(void) {
34 static int vcount = 0;
35 extern bool frameLimiter;
36 int oldVCount = vcount;
37 vita2d_end_drawing();
38 vcount = sceDisplayGetVcount();
39 vita2d_set_vblank_wait(frameLimiter && vcount + 1 >= oldVCount);
40 vita2d_swap_buffers();
41}
42
43static uint32_t _pollInput(const struct mInputMap* map) {
44 SceCtrlData pad;
45 sceCtrlPeekBufferPositive(0, &pad, 1);
46 int input = mInputMapKeyBits(map, PSP2_INPUT, pad.buttons, 0);
47
48 if (pad.buttons & SCE_CTRL_UP || pad.ly < 64) {
49 input |= 1 << GUI_INPUT_UP;
50 }
51 if (pad.buttons & SCE_CTRL_DOWN || pad.ly >= 192) {
52 input |= 1 << GUI_INPUT_DOWN;
53 }
54 if (pad.buttons & SCE_CTRL_LEFT || pad.lx < 64) {
55 input |= 1 << GUI_INPUT_LEFT;
56 }
57 if (pad.buttons & SCE_CTRL_RIGHT || pad.lx >= 192) {
58 input |= 1 << GUI_INPUT_RIGHT;
59 }
60
61 return input;
62}
63
64static enum GUICursorState _pollCursor(unsigned* x, unsigned* y) {
65 SceTouchData touch;
66 sceTouchPeek(SCE_TOUCH_PORT_FRONT, &touch, 1);
67 if (touch.reportNum < 1) {
68 return GUI_CURSOR_NOT_PRESENT;
69 }
70 *x = touch.report[0].x / 2;
71 *y = touch.report[0].y / 2;
72 return GUI_CURSOR_DOWN;
73}
74
75static int _batteryState(void) {
76 int charge = scePowerGetBatteryLifePercent();
77 int adapter = scePowerIsPowerOnline();
78 int state = 0;
79 if (adapter) {
80 state |= BATTERY_CHARGING;
81 }
82 charge /= 25;
83 return state | charge;
84}
85
86int main() {
87 vita2d_init();
88 struct GUIFont* font = GUIFontCreate();
89 struct mGUIRunner runner = {
90 .params = {
91 PSP2_HORIZONTAL_PIXELS, PSP2_VERTICAL_PIXELS,
92 font, "ux0:data", _drawStart, _drawEnd,
93 _pollInput, _pollCursor,
94 _batteryState,
95 0, 0,
96 },
97 .configExtra = (struct GUIMenuItem[]) {
98 {
99 .title = "Screen mode",
100 .data = "screenMode",
101 .submenu = 0,
102 .state = 0,
103 .validStates = (const char*[]) {
104 "With Background",
105 "Without Background",
106 "Stretched",
107 "Fit Aspect Ratio",
108 },
109 .nStates = 4
110 },
111 {
112 .title = "Camera",
113 .data = "camera",
114 .submenu = 0,
115 .state = 1,
116 .validStates = (const char*[]) {
117 "None",
118 "Front",
119 "Back",
120 },
121 .nStates = 3
122 }
123 },
124 .keySources = (struct GUIInputKeys[]) {
125 {
126 .name = "Vita Input",
127 .id = PSP2_INPUT,
128 .keyNames = (const char*[]) {
129 "Select",
130 0,
131 0,
132 "Start",
133 "Up",
134 "Right",
135 "Down",
136 "Left",
137 "L",
138 "R",
139 0, // L2?
140 0, // R2?
141 "\1\xC",
142 "\1\xA",
143 "\1\xB",
144 "\1\xD"
145 },
146 .nKeys = 16
147 },
148 { .id = 0 }
149 },
150 .nConfigExtra = 2,
151 .setup = mPSP2Setup,
152 .teardown = mPSP2Teardown,
153 .gameLoaded = mPSP2LoadROM,
154 .gameUnloaded = mPSP2UnloadROM,
155 .prepareForFrame = mPSP2PrepareForFrame,
156 .drawFrame = mPSP2Draw,
157 .drawScreenshot = mPSP2DrawScreenshot,
158 .paused = mPSP2Paused,
159 .unpaused = mPSP2Unpaused,
160 .incrementScreenMode = mPSP2IncrementScreenMode,
161 .setFrameLimiter = mPSP2SetFrameLimiter,
162 .pollGameInput = mPSP2PollInput
163 };
164
165 sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START);
166 sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG_WIDE);
167 sceSysmoduleLoadModule(SCE_SYSMODULE_PHOTO_EXPORT);
168 sceSysmoduleLoadModule(SCE_SYSMODULE_APPUTIL);
169
170 mGUIInit(&runner, "psvita");
171
172 int enterButton;
173 SceAppUtilInitParam initParam;
174 SceAppUtilBootParam bootParam;
175 memset(&initParam, 0, sizeof(SceAppUtilInitParam));
176 memset(&bootParam, 0, sizeof(SceAppUtilBootParam));
177 sceAppUtilInit(&initParam, &bootParam);
178 sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_ENTER_BUTTON, &enterButton);
179 sceAppUtilShutdown();
180
181 if (enterButton == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE) {
182 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_CROSS, GUI_INPUT_BACK);
183 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_CIRCLE, GUI_INPUT_SELECT);
184 } else {
185 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_CROSS, GUI_INPUT_SELECT);
186 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_CIRCLE, GUI_INPUT_BACK);
187 }
188 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_TRIANGLE, GUI_INPUT_CANCEL);
189 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_UP, GUI_INPUT_UP);
190 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_DOWN, GUI_INPUT_DOWN);
191 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_LEFT, GUI_INPUT_LEFT);
192 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_RIGHT, GUI_INPUT_RIGHT);
193 mPSP2MapKey(&runner.params.keyMap, SCE_CTRL_SQUARE, mGUI_INPUT_SCREEN_MODE);
194
195 scePowerSetArmClockFrequency(444);
196 mGUIRunloop(&runner);
197
198 vita2d_fini();
199 mGUIDeinit(&runner);
200
201 int pgfLoaded = sceSysmoduleIsLoaded(SCE_SYSMODULE_PGF);
202 if (pgfLoaded != SCE_SYSMODULE_LOADED) {
203 sceSysmoduleLoadModule(SCE_SYSMODULE_PGF);
204 }
205 GUIFontDestroy(font);
206 sceSysmoduleUnloadModule(SCE_SYSMODULE_PGF);
207
208 sceKernelExitProcess(0);
209 return 0;
210}