1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 
5 #include <pspkernel.h>
6 #include <psppower.h>
7 #include <pspdisplay.h>
8 #include <pspctrl.h>
9 #include <psprtc.h>
10 #include <pspaudiolib.h>
11 #include <pspaudio.h>
12 
13 PSP_MODULE_INFO("OpenLara", 0, 1, 1);
14 PSP_HEAP_SIZE_KB(20480);
15 PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU | PSP_THREAD_ATTR_NO_FILLSTACK);
16 
17 #include "game.h"
18 
19 #define BUF_WIDTH   (512)
20 #define SCR_WIDTH   (480)
21 #define SCR_HEIGHT  (272)
22 
exitCallback(int arg1,int arg2,void * common)23 int exitCallback(int arg1, int arg2, void *common) {
24     Core::quit();
25     return 0;
26 }
27 
callbackThread(SceSize args,void * argp)28 int callbackThread(SceSize args, void *argp) {
29     int cbid = sceKernelCreateCallback("Exit Callback", exitCallback, NULL);
30     sceKernelRegisterExitCallback(cbid);
31     sceKernelSleepThreadCB();
32     return 0;
33 }
34 
setupCallbacks(void)35 int setupCallbacks(void) {
36     int thid = sceKernelCreateThread("update_thread", callbackThread, 0x11, 0xFA0, 0, 0);
37     sceKernelStartThread(thid, 0, 0);
38     return thid;
39 }
40 
41 
42 // multi-threading
osMutexInit()43 void* osMutexInit() {
44     SceUID *mutex = new SceUID();
45     *mutex = sceKernelCreateSema(NULL, 0, 1, 1, 0);
46     return mutex;
47 }
48 
osMutexFree(void * obj)49 void osMutexFree(void *obj) {
50     sceKernelDeleteSema(*(SceUID*)obj);
51     delete (SceUID*)obj;
52 }
53 
osMutexLock(void * obj)54 void osMutexLock(void *obj) {
55     sceKernelWaitSema(*(SceUID*)obj, 1, NULL);
56 }
57 
osMutexUnlock(void * obj)58 void osMutexUnlock(void *obj) {
59     sceKernelSignalSema(*(SceUID*)obj, 1);
60 }
61 
osRWLockInit()62 void* osRWLockInit() {
63     return osMutexInit();
64 }
65 
osRWLockFree(void * obj)66 void osRWLockFree(void *obj) {
67     osMutexFree(obj);
68 }
69 
osRWLockRead(void * obj)70 void osRWLockRead(void *obj) {
71     osMutexLock(obj);
72 }
73 
osRWUnlockRead(void * obj)74 void osRWUnlockRead(void *obj) {
75     osMutexUnlock(obj);
76 }
77 
osRWLockWrite(void * obj)78 void osRWLockWrite(void *obj) {
79     osMutexLock(obj);
80 }
81 
osRWUnlockWrite(void * obj)82 void osRWUnlockWrite(void *obj) {
83     osMutexUnlock(obj);
84 }
85 
86 // timing
87 int osStartTime = 0;
88 int osTimerFreq;
89 
osGetTimeMS()90 int osGetTimeMS() {
91     u64 time;
92     sceRtcGetCurrentTick(&time);
93     return int(time * 1000 / osTimerFreq - osStartTime);
94 }
95 
96 // input
osJoyReady(int index)97 bool osJoyReady(int index) {
98     return index == 0;
99 }
100 
osJoyVibrate(int index,float L,float R)101 void osJoyVibrate(int index, float L, float R) {
102     //
103 }
104 
joyInit()105 void joyInit() {
106     sceCtrlSetSamplingCycle(0);
107     sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
108 }
109 
joyUpdate()110 void joyUpdate() {
111     SceCtrlData pad;
112     sceCtrlReadBufferPositive(&pad, 1);
113 
114     Input::setJoyDown(0, jkUp,     (pad.Buttons & PSP_CTRL_UP));
115     Input::setJoyDown(0, jkDown,   (pad.Buttons & PSP_CTRL_DOWN));
116     Input::setJoyDown(0, jkLeft,   (pad.Buttons & PSP_CTRL_LEFT));
117     Input::setJoyDown(0, jkRight,  (pad.Buttons & PSP_CTRL_RIGHT));
118     Input::setJoyDown(0, jkA,      (pad.Buttons & PSP_CTRL_CROSS));
119     Input::setJoyDown(0, jkB,      (pad.Buttons & PSP_CTRL_CIRCLE));
120     Input::setJoyDown(0, jkX,      (pad.Buttons & PSP_CTRL_SQUARE));
121     Input::setJoyDown(0, jkY,      (pad.Buttons & PSP_CTRL_TRIANGLE));
122     Input::setJoyDown(0, jkLB,     (pad.Buttons & PSP_CTRL_LTRIGGER));
123     Input::setJoyDown(0, jkRB,     (pad.Buttons & PSP_CTRL_RTRIGGER));
124     Input::setJoyDown(0, jkStart,  (pad.Buttons & PSP_CTRL_START));
125     Input::setJoyDown(0, jkSelect, (pad.Buttons & PSP_CTRL_SELECT));
126 
127     vec2 stick = vec2(float(pad.Lx), float(pad.Ly)) / 128.0f - 1.0f;
128     if (fabsf(stick.x) < 0.2f && fabsf(stick.y) < 0.2f)
129         stick = vec2(0.0f);
130     Input::setJoyPos(0, jkL, stick);
131 }
132 
sndFill(void * buf,unsigned int length,void * userdata)133 void sndFill(void* buf, unsigned int length, void *userdata) {
134     Sound::fill((Sound::Frame*)buf, length);
135 }
136 
sndInit()137 void sndInit() {
138     pspAudioInit();
139     pspAudioSetChannelCallback(0, sndFill, NULL);
140 }
141 
main()142 int main() {
143     cacheDir[0] = saveDir[0] = contentDir[0] = 0;
144 
145     scePowerSetClockFrequency(333, 333, 166);
146     setupCallbacks();
147 
148     sceGuInit();
149 
150     GAPI::beginCmdBuf();
151 
152     sceGuDrawBuffer(GU_PSM_5650, (void*)0, BUF_WIDTH);
153     sceGuDispBuffer(SCR_WIDTH, SCR_HEIGHT, (void*)(BUF_WIDTH * SCR_HEIGHT * 2), BUF_WIDTH);
154     sceGuDepthBuffer((void*)(BUF_WIDTH * SCR_HEIGHT * 2 * 2), BUF_WIDTH);
155 
156     sceGuScissor(0, 0, SCR_WIDTH, SCR_HEIGHT);
157     sceGuEnable(GU_SCISSOR_TEST);
158 
159     sndInit();
160     joyInit();
161 
162     osTimerFreq = sceRtcGetTickResolution();
163     osStartTime = Core::getTime();
164 
165     Game::init();
166 
167     GAPI::submitCmdBuf();
168 
169     sceDisplayWaitVblankStart();
170     sceGuDisplay(GU_TRUE);
171 
172     GAPI::curBackBuffer = 0;
173 
174     while (!Core::isQuit) {
175         GAPI::beginCmdBuf();
176 
177         joyUpdate();
178         Game::update();
179         Game::render();
180         GAPI::submitCmdBuf();
181         Core::waitVBlank();
182         GAPI::curBackBuffer = sceGuSwapBuffers();
183     }
184 
185     Game::deinit();
186 
187     sceGuTerm();
188     sceKernelExitGame();
189 
190     return 0;
191 }