plat.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Platform interface functions for PSP picodrive frontend
  3. *
  4. * (C) 2020 kub
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <dirent.h>
  10. #include "../common/emu.h"
  11. #include "../libpicofe/menu.h"
  12. #include "../libpicofe/plat.h"
  13. #include <pspiofilemgr.h>
  14. #include <pspthreadman.h>
  15. #include <pspdisplay.h>
  16. #include <psputils.h>
  17. #include <psppower.h>
  18. #include <pspgu.h>
  19. #include <pspaudio.h>
  20. #include "psp.h"
  21. #include "emu.h"
  22. #include "asm_utils.h"
  23. #include <pico/pico_int.h>
  24. /* graphics buffer management in VRAM:
  25. * - VRAM_FB0, VRAM_FB1 frame buffers
  26. * - VRAM_DEPTH Z buffer (unused)
  27. * - VRAM_BUF0, VRAM_BUF1 emulator render buffers
  28. * Emulator screen output is using the MD screen resolutions and is rendered
  29. * to VRAM_BUFx and subsequently projected (that is, scaled and blitted) into
  30. * the associated frame buffer (in PSP output resolution). Additional emulator
  31. * output is then directly rendered to that frame buffer.
  32. * The emulator menu is rendered directly into the frame buffers, using the
  33. * native PSP resolution.
  34. * Menu background uses native resolution and is copied and shaded from a frame
  35. * buffer, or read in from a file if no emulator screen output is present.
  36. */
  37. /* System level intialization */
  38. int plat_target_init(void)
  39. {
  40. psp_init();
  41. /* buffer resolutions */
  42. g_menuscreen_w = 480, g_menuscreen_h = 272, g_menuscreen_pp = 512;
  43. g_screen_width = 328, g_screen_height = 256, g_screen_ppitch = 512;
  44. g_menubg_src_w = 480, g_menubg_src_h = 272, g_menubg_src_pp = 512;
  45. /* buffer settings for menu display on startup */
  46. g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0);
  47. g_menuscreen_ptr = psp_screen;
  48. g_menubg_ptr = malloc(512*272*2);
  49. return 0;
  50. }
  51. /* System level deinitialization */
  52. void plat_target_finish(void)
  53. {
  54. psp_finish();
  55. }
  56. /* display a completed frame buffer and prepare a new render buffer */
  57. void plat_video_flip(void)
  58. {
  59. g_menubg_src_ptr = psp_screen;
  60. psp_video_flip(currentConfig.EmuOpt & EOPT_VSYNC);
  61. g_screen_ptr = VRAM_CACHED_STUFF + (psp_screen - VRAM_FB0);
  62. plat_video_set_buffer(g_screen_ptr);
  63. }
  64. /* wait for start of vertical blanking */
  65. void plat_video_wait_vsync(void)
  66. {
  67. sceDisplayWaitVblankStart();
  68. }
  69. /* switch from emulation display to menu display */
  70. void plat_video_menu_enter(int is_rom_loaded)
  71. {
  72. }
  73. /* start rendering a menu screen */
  74. void plat_video_menu_begin(void)
  75. {
  76. g_menuscreen_ptr = psp_screen;
  77. }
  78. /* display a completed menu screen */
  79. void plat_video_menu_end(void)
  80. {
  81. plat_video_wait_vsync();
  82. plat_video_flip();
  83. }
  84. /* terminate menu display */
  85. void plat_video_menu_leave(void)
  86. {
  87. }
  88. /* Preliminary initialization needed at program start */
  89. void plat_early_init(void)
  90. {
  91. }
  92. /* base directory for configuration and save files */
  93. int plat_get_root_dir(char *dst, int len)
  94. {
  95. if (len > 0) *dst = 0;
  96. return 0;
  97. }
  98. /* base directory for emulator resources */
  99. int plat_get_skin_dir(char *dst, int len)
  100. {
  101. if (len > 4)
  102. strcpy(dst, "skin/");
  103. else if (len > 0)
  104. *dst = 0;
  105. return strlen(dst);
  106. }
  107. /* top directory for rom images */
  108. int plat_get_data_dir(char *dst, int len)
  109. {
  110. if (len > 4)
  111. strcpy(dst, "ms0:/");
  112. else if (len > 0)
  113. *dst = 0;
  114. return strlen(dst);
  115. }
  116. /* check if path is a directory */
  117. int plat_is_dir(const char *path)
  118. {
  119. SceIoStat st;
  120. int ret = sceIoGetstat(path, &st);
  121. return (ret >= 0 && (st.st_mode & FIO_S_IFDIR));
  122. }
  123. /* current time in ms */
  124. unsigned int plat_get_ticks_ms(void)
  125. {
  126. /* approximate /= 1000 */
  127. unsigned long long v64;
  128. v64 = (unsigned long long)plat_get_ticks_us() * 4294968;
  129. return v64 >> 32;
  130. }
  131. /* current time in us */
  132. unsigned int plat_get_ticks_us(void)
  133. {
  134. return sceKernelGetSystemTimeLow();
  135. }
  136. /* sleep for some time in ms */
  137. void plat_sleep_ms(int ms)
  138. {
  139. psp_msleep(ms);
  140. }
  141. /* sleep for some time in us */
  142. void plat_wait_till_us(unsigned int us_to)
  143. {
  144. unsigned int tval;
  145. int diff;
  146. tval = sceKernelGetSystemTimeLow();
  147. diff = (int)us_to - (int)tval;
  148. if (diff >= 512 && diff < 100*1024)
  149. sceKernelDelayThread(diff);
  150. }
  151. /* wait until some event occurs, or timeout */
  152. int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
  153. {
  154. return 0; // unused
  155. }
  156. /* memory mapping functions */
  157. void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
  158. {
  159. return malloc(size);
  160. }
  161. void *plat_mremap(void *ptr, size_t oldsize, size_t newsize)
  162. {
  163. return realloc(ptr, newsize);
  164. }
  165. void plat_munmap(void *ptr, size_t size)
  166. {
  167. free(ptr);
  168. }
  169. void *plat_mem_get_for_drc(size_t size)
  170. {
  171. return NULL;
  172. }
  173. int plat_mem_set_exec(void *ptr, size_t size)
  174. {
  175. return 0;
  176. }
  177. /* get current CPU clock */
  178. static int plat_cpu_clock_get(void)
  179. {
  180. return scePowerGetCpuClockFrequencyInt();
  181. }
  182. /* set CPU clock */
  183. static int plat_cpu_clock_set(int clock)
  184. {
  185. if (clock < 33) clock = 33;
  186. if (clock > 333) clock = 333;
  187. return scePowerSetClockFrequency(clock, clock, clock/2);
  188. }
  189. /* get battery state in percent */
  190. static int plat_bat_capacity_get(void)
  191. {
  192. return scePowerGetBatteryLifePercent();
  193. }
  194. struct plat_target plat_target = {
  195. .cpu_clock_get = plat_cpu_clock_get,
  196. .cpu_clock_set = plat_cpu_clock_set,
  197. .bat_capacity_get = plat_bat_capacity_get,
  198. // .gamma_set = plat_gamma_set,
  199. // .hwfilter_set = plat_hwfilter_set,
  200. // .hwfilters = plat_hwfilters,
  201. };
  202. /* replacement libc stuff */
  203. int alphasort(const struct dirent **a, const struct dirent **b)
  204. {
  205. return strcoll ((*a)->d_name, (*b)->d_name);
  206. }
  207. int scandir(const char *dir, struct dirent ***namelist_out,
  208. int(*filter)(const struct dirent *),
  209. int(*compar)(const struct dirent **, const struct dirent **))
  210. {
  211. int ret = -1, dir_uid = -1, name_alloc = 4, name_count = 0;
  212. struct dirent **namelist = NULL, *ent;
  213. SceIoDirent sce_ent;
  214. namelist = malloc(sizeof(*namelist) * name_alloc);
  215. if (namelist == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; }
  216. // try to read first..
  217. dir_uid = sceIoDopen(dir);
  218. if (dir_uid >= 0)
  219. {
  220. /* it is very important to clear SceIoDirent to be passed to sceIoDread(), */
  221. /* or else it may crash, probably misinterpreting something in it. */
  222. memset(&sce_ent, 0, sizeof(sce_ent));
  223. ret = sceIoDread(dir_uid, &sce_ent);
  224. if (ret < 0)
  225. {
  226. lprintf("sceIoDread(\"%s\") failed with %i\n", dir, ret);
  227. goto fail;
  228. }
  229. }
  230. else
  231. lprintf("sceIoDopen(\"%s\") failed with %i\n", dir, dir_uid);
  232. while (ret > 0)
  233. {
  234. ent = malloc(sizeof(*ent));
  235. if (ent == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; }
  236. ent->d_stat = sce_ent.d_stat;
  237. ent->d_stat.st_attr &= FIO_SO_IFMT; // serves as d_type
  238. strncpy(ent->d_name, sce_ent.d_name, sizeof(ent->d_name));
  239. ent->d_name[sizeof(ent->d_name)-1] = 0;
  240. if (filter == NULL || filter(ent))
  241. namelist[name_count++] = ent;
  242. else free(ent);
  243. if (name_count >= name_alloc)
  244. {
  245. void *tmp;
  246. name_alloc *= 2;
  247. tmp = realloc(namelist, sizeof(*namelist) * name_alloc);
  248. if (tmp == NULL) { lprintf("%s:%i: OOM\n", __FILE__, __LINE__); goto fail; }
  249. namelist = tmp;
  250. }
  251. memset(&sce_ent, 0, sizeof(sce_ent));
  252. ret = sceIoDread(dir_uid, &sce_ent);
  253. }
  254. // sort
  255. if (compar != NULL && name_count > 3)
  256. qsort(&namelist[2], name_count - 2, sizeof(namelist[0]), (int (*)()) compar);
  257. // all done.
  258. ret = name_count;
  259. *namelist_out = namelist;
  260. goto end;
  261. fail:
  262. if (namelist != NULL)
  263. {
  264. while (name_count--)
  265. free(namelist[name_count]);
  266. free(namelist);
  267. }
  268. end:
  269. if (dir_uid >= 0) sceIoDclose(dir_uid);
  270. return ret;
  271. }
  272. int _flush_cache (char *addr, const int size, const int op)
  273. {
  274. //sceKernelDcacheWritebackAll();
  275. sceKernelDcacheWritebackRange(addr, size);
  276. sceKernelIcacheInvalidateRange(addr, size);
  277. return 0;
  278. }