1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 // Disable printf override in common/forbidden.h to avoid
24 // clashes with pspdebug.h from the PSP SDK.
25 // That header file uses
26 //   __attribute__((format(printf,1,2)));
27 // which gets messed up by our override mechanism; this could
28 // be avoided by either changing the PSP SDK to use the equally
29 // legal and valid
30 //   __attribute__((format(__printf__,1,2)));
31 // or by refining our printf override to use a varadic macro
32 // (which then wouldn't be portable, though).
33 // Anyway, for now we just disable the printf override globally
34 // for the PSP port
35 #define FORBIDDEN_SYMBOL_EXCEPTION_printf
36 
37 #define	USERSPACE_ONLY	//don't use kernel mode features
38 
39 #ifndef USERSPACE_ONLY
40 #include <pspkernel.h>
41 #include <pspdebug.h>
42 #else
43 #include <pspuser.h>
44 #endif
45 
46 #include <psppower.h>
47 
48 #include <common/system.h>
49 #include <engines/engine.h>
50 #include <base/main.h>
51 #include <base/plugins.h>
52 #include "backends/platform/psp/powerman.h"
53 #include "backends/platform/psp/thread.h"
54 
55 #include "backends/plugins/psp/psp-provider.h"
56 #include "backends/platform/psp/psppixelformat.h"
57 #include "backends/platform/psp/osys_psp.h"
58 #include "backends/platform/psp/tests.h"	/* for unit/speed tests */
59 #include "backends/platform/psp/trace.h"
60 
61 #ifdef ENABLE_PROFILING
62 	#include <pspprof.h>
63 #endif
64 
65 /**
66  * Define the module info section
67  *
68  * 2nd arg must 0x1000 so __init is executed in
69  * kernelmode for our loaderInit function
70  */
71 #ifndef USERSPACE_ONLY
72 PSP_MODULE_INFO("SCUMMVM-PSP", 0x1000, 1, 1);
73 #else
74 PSP_MODULE_INFO("SCUMMVM-PSP", 0, 1, 1);
75 #endif
76 
77 /**
78  * THREAD_ATTR_USER causes the thread that the startup
79  * code (crt0.c) starts this program in to be in usermode
80  * even though the module was started in kernelmode
81  */
82 PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
83 PSP_HEAP_SIZE_KB(-128);	//Leave 128kb for thread stacks, etc.
84 
85 
86 #ifndef USERSPACE_ONLY
MyExceptionHandler(PspDebugRegBlock * regs)87 void MyExceptionHandler(PspDebugRegBlock *regs) {
88 	/* Do normal initial dump, setup screen etc */
89 
90 	pspDebugScreenInit();
91 
92 	pspDebugScreenSetBackColor(0x00FF0000);
93 	pspDebugScreenSetTextColor(0xFFFFFFFF);
94 	pspDebugScreenClear();
95 
96 	pspDebugScreenPrintf("Exception Details:\n");
97 	pspDebugDumpException(regs);
98 
99 	while (1) ;
100 }
101 
102 /**
103  * Function that is called from _init in kernelmode before the
104  * main thread is started in usermode.
105  */
106 __attribute__((constructor))
loaderInit()107 void loaderInit() {
108 	pspKernelSetKernelPC();
109 	pspDebugInstallErrorHandler(MyExceptionHandler);
110 }
111 #endif
112 
113 /* Exit callback */
exit_callback(void)114 int exit_callback(void) {
115 
116 #ifdef ENABLE_PROFILING
117 	gprof_cleanup();
118 #endif
119 
120 	sceKernelExitGame();
121 	return 0;
122 }
123 
124 /* Function for handling suspend/resume */
power_callback(int,int powerinfo,void *)125 int power_callback(int , int powerinfo, void *) {
126 	if (powerinfo & PSP_POWER_CB_POWER_SWITCH || powerinfo & PSP_POWER_CB_SUSPENDING) {
127 		PowerMan.suspend();
128 	} else if (powerinfo & PSP_POWER_CB_RESUME_COMPLETE) {
129 		PowerMan.resume();
130 	}
131 	return 0;
132 }
133 
134 /* Callback thread */
CallbackThread(SceSize,void * arg)135 int CallbackThread(SceSize /*size*/, void *arg) {
136 	int cbid;
137 
138 	cbid = sceKernelCreateCallback("Exit Callback", (SceKernelCallbackFunction)exit_callback, NULL);
139 	sceKernelRegisterExitCallback(cbid);
140 	/* Set up callbacks for PSPIoStream */
141 
142 	cbid = sceKernelCreateCallback("Power Callback", (SceKernelCallbackFunction)power_callback, 0);
143 	if (cbid >= 0) {
144 		if (scePowerRegisterCallback(-1, cbid) < 0) {
145 			PSP_ERROR("Couldn't register callback for power_callback\n");
146 		}
147 	} else {
148 		PSP_ERROR("Couldn't create a callback for power_callback\n");
149 	}
150 
151 	sceKernelSleepThreadCB();
152 	return 0;
153 }
154 
155 /* Sets up the callback thread and returns its thread id */
SetupCallbacks(void)156 int SetupCallbacks(void) {
157 	int thid = sceKernelCreateThread("power_thread", CallbackThread, PRIORITY_POWER_THREAD, STACK_POWER_THREAD, THREAD_ATTR_USER, 0);
158 	if (thid >= 0) {
159 		sceKernelStartThread(thid, 0, 0);
160 	}
161 
162 	return thid;
163 }
164 
165 #undef main
main(void)166 int main(void) {
167 	//change clock rate to 333mhz
168 	scePowerSetClockFrequency(333, 333, 166);
169 
170 	PowerManager::instance();	// Setup power manager
171 
172 	SetupCallbacks();
173 
174 	static const char *argv[] = { "scummvm", NULL };
175 	static int argc = sizeof(argv) / sizeof(char *) - 1;
176 
177 	g_system = new OSystem_PSP();
178 	assert(g_system);
179 
180 #ifdef DYNAMIC_MODULES
181 	PluginManager::instance().addPluginProvider(new PSPPluginProvider());
182 #endif
183 
184 /* unit/speed tests */
185 #if defined(PSP_ENABLE_UNIT_TESTS) || defined(PSP_ENABLE_SPEED_TESTS)
186 	PSP_INFO_PRINT("running tests\n");
187 	psp_tests();
188 	sceKernelSleepThread();	// that's it. That's all we're doing
189 #endif
190 
191 	int res = scummvm_main(argc, argv);
192 
193 	g_system->quit();	// TODO: Consider removing / replacing this!
194 
195 	PowerManager::destroy();	// get rid of PowerManager
196 
197 	sceKernelSleepThread();
198 
199 	return res;
200 }
201