menu_pico.c 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699
  1. /*
  2. * PicoDrive
  3. * (C) notaz, 2010,2011
  4. *
  5. * This work is licensed under the terms of MAME license.
  6. * See COPYING file in the top-level directory.
  7. */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <SDL/SDL_ttf.h>
  14. #include <SDL/SDL_image.h>
  15. #include "emu.h"
  16. #include "configfile_fk.h"
  17. #include "menu_pico.h"
  18. #include "input_pico.h"
  19. #include "../libpicofe/input.h"
  20. #include "version.h"
  21. #include <pico/pico_int.h>
  22. #include <pico/patch.h>
  23. #ifdef PANDORA
  24. #define MENU_X2 1
  25. #else
  26. #define MENU_X2 0
  27. #endif
  28. #if defined USE_BGR555
  29. #define COL_ROM 0x5eff
  30. #define COL_OTH 0x5ff5
  31. #elif defined USE_BGR565
  32. #define COL_ROM 0xfdf7
  33. #define COL_OTH 0xaff5
  34. #else
  35. #define COL_ROM 0xbdff
  36. #define COL_OTH 0xaff5
  37. #endif
  38. // FIXME
  39. #define REVISION "0"
  40. static const char *rom_exts[] = {
  41. "zip",
  42. "bin", "smd", "gen", "md",
  43. "iso", "cso", "cue", "chd",
  44. "32x",
  45. "sms", "gg",
  46. NULL
  47. };
  48. // rrrr rggg gggb bbbb
  49. static unsigned short fname2color(const char *fname)
  50. {
  51. static const char *other_exts[] = { "gmv", "pat" };
  52. const char *ext;
  53. int i;
  54. ext = strrchr(fname, '.');
  55. if (ext++ == NULL) {
  56. ext = fname + strlen(fname) - 3;
  57. if (ext < fname) ext = fname;
  58. }
  59. for (i = 0; rom_exts[i] != NULL; i++)
  60. if (strcasecmp(ext, rom_exts[i]) == 0) return COL_ROM;
  61. for (i = 0; i < array_size(other_exts); i++)
  62. if (strcasecmp(ext, other_exts[i]) == 0) return COL_OTH;
  63. return 0xffff;
  64. }
  65. #include <platform/libpicofe/menu.c>
  66. static const char *men_dummy[] = { NULL };
  67. /* platform specific options and handlers */
  68. #if defined(__GP2X__)
  69. #include <platform/gp2x/menu.c>
  70. #elif defined(__PSP__)
  71. #include <platform/psp/menu.c>
  72. #elif defined(PANDORA)
  73. #include <platform/pandora/menu.c>
  74. #else
  75. #define MENU_OPTIONS_GFX
  76. #define MENU_OPTIONS_ADV
  77. #endif
  78. /// -------------- DEFINES --------------
  79. #define MIN(a,b) (((a)<(b))?(a):(b))
  80. #define MAX(a,b) (((a)>(b))?(a):(b))
  81. #define ABS(x) (((x) < 0) ? (-x) : (x))
  82. //#define MENU_DEBUG
  83. #define MENU_ERROR
  84. #ifdef MENU_DEBUG
  85. #define MENU_DEBUG_PRINTF(...) printf(__VA_ARGS__);
  86. #else
  87. #define MENU_DEBUG_PRINTF(...)
  88. #endif //MENU_DEBUG
  89. #ifdef MENU_ERROR
  90. #define MENU_ERROR_PRINTF(...) printf(__VA_ARGS__);
  91. #else
  92. #define MENU_ERROR_PRINTF(...)
  93. #endif //MENU_ERROR
  94. #define RES_HW_SCREEN_HORIZONTAL 240
  95. #define RES_HW_SCREEN_VERTICAL 240
  96. #define SCREEN_HORIZONTAL_SIZE 240
  97. #define SCREEN_VERTICAL_SIZE 240
  98. #define SCROLL_SPEED_PX 30
  99. #define FPS_MENU 50
  100. #define ARROWS_PADDING 8
  101. #define MENU_ZONE_WIDTH SCREEN_HORIZONTAL_SIZE
  102. #define MENU_ZONE_HEIGHT SCREEN_VERTICAL_SIZE
  103. #define MENU_BG_SQUARE_WIDTH 180
  104. #define MENU_BG_SQUARE_HEIGHT 140
  105. #define MENU_FONT_NAME_TITLE "/usr/games/menu_resources/OpenSans-Bold.ttf"
  106. #define MENU_FONT_SIZE_TITLE 22
  107. #define MENU_FONT_NAME_INFO "/usr/games/menu_resources/OpenSans-Bold.ttf"
  108. #define MENU_FONT_SIZE_INFO 16
  109. #define MENU_FONT_NAME_SMALL_INFO "/usr/games/menu_resources/OpenSans-Regular.ttf"
  110. #define MENU_FONT_SIZE_SMALL_INFO 13
  111. #define MENU_PNG_BG_PATH "/usr/games/menu_resources/zone_bg.png"
  112. #define MENU_PNG_ARROW_TOP_PATH "/usr/games/menu_resources/arrow_top.png"
  113. #define MENU_PNG_ARROW_BOTTOM_PATH "/usr/games/menu_resources/arrow_bottom.png"
  114. #define GRAY_MAIN_R 85
  115. #define GRAY_MAIN_G 85
  116. #define GRAY_MAIN_B 85
  117. #define WHITE_MAIN_R 236
  118. #define WHITE_MAIN_G 236
  119. #define WHITE_MAIN_B 236
  120. #define MAX_SAVE_SLOTS 9
  121. #define MAXPATHLEN 512
  122. /// -------------- STATIC VARIABLES --------------
  123. extern SDL_Surface * hw_screen;
  124. extern SDL_Surface * virtual_hw_screen;
  125. SDL_Surface * draw_screen;
  126. static int backup_key_repeat_delay, backup_key_repeat_interval;
  127. static SDL_Surface * backup_hw_screen = NULL;
  128. static TTF_Font *menu_title_font = NULL;
  129. static TTF_Font *menu_info_font = NULL;
  130. static TTF_Font *menu_small_info_font = NULL;
  131. static SDL_Surface *img_arrow_top = NULL;
  132. static SDL_Surface *img_arrow_bottom = NULL;
  133. static SDL_Surface ** menu_zone_surfaces = NULL;
  134. static int * idx_menus = NULL;
  135. static int nb_menu_zones = 0;
  136. static int menuItem = 0;
  137. int stop_menu_loop = 0;
  138. static SDL_Color text_color = {GRAY_MAIN_R, GRAY_MAIN_G, GRAY_MAIN_B};
  139. static int padding_y_from_center_menu_zone = 18;
  140. static uint16_t width_progress_bar = 100;
  141. static uint16_t height_progress_bar = 20;
  142. static uint16_t x_volume_bar = 0;
  143. static uint16_t y_volume_bar = 0;
  144. static uint16_t x_brightness_bar = 0;
  145. static uint16_t y_brightness_bar = 0;
  146. int volume_percentage = 0;
  147. int brightness_percentage = 0;
  148. static int quick_load_slot_chosen = 0;
  149. #undef X
  150. #define X(a, b) b,
  151. const char *resume_options_str[] = {RESUME_OPTIONS};
  152. /// -------------- FUNCTIONS IMPLEMENTATION --------------
  153. void init_menu_SDL(){
  154. /// ----- Loading the fonts -----
  155. menu_title_font = TTF_OpenFont(MENU_FONT_NAME_TITLE, MENU_FONT_SIZE_TITLE);
  156. if(!menu_title_font){
  157. MENU_ERROR_PRINTF("ERROR in init_menu_SDL: Could not open menu font %s, %s\n", MENU_FONT_NAME_TITLE, SDL_GetError());
  158. }
  159. menu_info_font = TTF_OpenFont(MENU_FONT_NAME_INFO, MENU_FONT_SIZE_INFO);
  160. if(!menu_info_font){
  161. MENU_ERROR_PRINTF("ERROR in init_menu_SDL: Could not open menu font %s, %s\n", MENU_FONT_NAME_INFO, SDL_GetError());
  162. }
  163. menu_small_info_font = TTF_OpenFont(MENU_FONT_NAME_SMALL_INFO, MENU_FONT_SIZE_SMALL_INFO);
  164. if(!menu_small_info_font){
  165. MENU_ERROR_PRINTF("ERROR in init_menu_SDL: Could not open menu font %s, %s\n", MENU_FONT_NAME_SMALL_INFO, SDL_GetError());
  166. }
  167. /// ----- Copy draw_screen at init ------
  168. backup_hw_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
  169. virtual_hw_screen->w, virtual_hw_screen->h, 16, 0, 0, 0, 0);
  170. if(backup_hw_screen == NULL){
  171. MENU_ERROR_PRINTF("ERROR in init_menu_SDL: Could not create backup_hw_screen: %s\n", SDL_GetError());
  172. }
  173. draw_screen = SDL_CreateRGBSurface(SDL_SWSURFACE,
  174. virtual_hw_screen->w, virtual_hw_screen->h, 16, 0, 0, 0, 0);
  175. if(draw_screen == NULL){
  176. MENU_ERROR_PRINTF("ERROR in init_menu_SDL: Could not create draw_screen: %s\n", SDL_GetError());
  177. }
  178. /// ------ Load arrows imgs -------
  179. img_arrow_top = IMG_Load(MENU_PNG_ARROW_TOP_PATH);
  180. if(!img_arrow_top) {
  181. MENU_ERROR_PRINTF("ERROR IMG_Load: %s\n", IMG_GetError());
  182. }
  183. img_arrow_bottom = IMG_Load(MENU_PNG_ARROW_BOTTOM_PATH);
  184. if(!img_arrow_bottom) {
  185. MENU_ERROR_PRINTF("ERROR IMG_Load: %s\n", IMG_GetError());
  186. }
  187. /// ------ Init menu zones ------
  188. init_menu_zones();
  189. }
  190. void deinit_menu_SDL(){
  191. /// ------ Close font -------
  192. TTF_CloseFont(menu_title_font);
  193. TTF_CloseFont(menu_info_font);
  194. TTF_CloseFont(menu_small_info_font);
  195. /// ------ Free Surfaces -------
  196. for(int i=0; i < nb_menu_zones; i++){
  197. SDL_FreeSurface(menu_zone_surfaces[i]);
  198. }
  199. SDL_FreeSurface(backup_hw_screen);
  200. SDL_FreeSurface(draw_screen);
  201. SDL_FreeSurface(img_arrow_top);
  202. SDL_FreeSurface(img_arrow_bottom);
  203. /// ------ Free Menu memory and reset vars -----
  204. if(idx_menus){
  205. free(idx_menus);
  206. }
  207. idx_menus=NULL;
  208. nb_menu_zones = 0;
  209. }
  210. void draw_progress_bar(SDL_Surface * surface, uint16_t x, uint16_t y, uint16_t width,
  211. uint16_t height, uint8_t percentage, uint16_t nb_bars){
  212. /// ------ Init Variables ------
  213. uint16_t line_width = 1; //px
  214. uint16_t padding_bars_ratio = 3;
  215. uint16_t nb_full_bars = 0;
  216. /// ------ Check values ------
  217. percentage = (percentage > 100)?100:percentage;
  218. x = (x > (surface->w-1))?(surface->w-1):x;
  219. y = (y > surface->h-1)?(surface->h-1):y;
  220. width = (width < line_width*2+1)?(line_width*2+1):width;
  221. width = (width > surface->w-x-1)?(surface->w-x-1):width;
  222. height = (height < line_width*2+1)?(line_width*2+1):height;
  223. height = (height > surface->h-y-1)?(surface->h-y-1):height;
  224. uint16_t nb_bars_max = ( width * padding_bars_ratio / (line_width*2+1) + 1 ) / (padding_bars_ratio+1);
  225. nb_bars = (nb_bars > nb_bars_max)?nb_bars_max:nb_bars;
  226. uint16_t bar_width = (width / nb_bars)*padding_bars_ratio/(padding_bars_ratio+1)+1;
  227. uint16_t bar_padding_x = bar_width/padding_bars_ratio;
  228. nb_full_bars = nb_bars*percentage/100;
  229. /// ------ draw full bars ------
  230. for (int i = 0; i < nb_full_bars; ++i)
  231. {
  232. /// ---- draw one bar ----
  233. //MENU_DEBUG_PRINTF("Drawing filled bar %d\n", i);
  234. SDL_Rect rect = {x+ i*(bar_width +bar_padding_x),
  235. y, bar_width, height};
  236. SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, GRAY_MAIN_R, GRAY_MAIN_G, GRAY_MAIN_B));
  237. }
  238. /// ------ draw full bars ------
  239. for (int i = 0; i < (nb_bars-nb_full_bars); ++i)
  240. {
  241. /// ---- draw one bar ----
  242. //MENU_DEBUG_PRINTF("Drawing empty bar %d\n", i);
  243. SDL_Rect rect = {x+ i*(bar_width +bar_padding_x) + nb_full_bars*(bar_width +bar_padding_x),
  244. y, bar_width, height};
  245. SDL_FillRect(surface, &rect, SDL_MapRGB(surface->format, GRAY_MAIN_R, GRAY_MAIN_G, GRAY_MAIN_B));
  246. SDL_Rect rect2 = {x+ i*(bar_width +bar_padding_x) + line_width + nb_full_bars*(bar_width +bar_padding_x),
  247. y + line_width, bar_width - line_width*2, height - line_width*2};
  248. SDL_FillRect(surface, &rect2, SDL_MapRGB(surface->format, WHITE_MAIN_R, WHITE_MAIN_R, WHITE_MAIN_R));
  249. }
  250. }
  251. void add_menu_zone(ENUM_MENU_TYPE menu_type){
  252. /// ------ Increase nb of menu zones -------
  253. nb_menu_zones++;
  254. /// ------ Realoc idx Menus array -------
  255. if(!idx_menus){
  256. idx_menus = malloc(nb_menu_zones*sizeof(int));
  257. menu_zone_surfaces = malloc(nb_menu_zones*sizeof(SDL_Surface*));
  258. }
  259. else{
  260. int *temp = realloc(idx_menus, nb_menu_zones*sizeof(int));
  261. idx_menus = temp;
  262. menu_zone_surfaces = realloc(menu_zone_surfaces, nb_menu_zones*sizeof(SDL_Surface*));
  263. }
  264. idx_menus[nb_menu_zones-1] = menu_type;
  265. /// ------ Reinit menu surface with height increased -------
  266. menu_zone_surfaces[nb_menu_zones-1] = IMG_Load(MENU_PNG_BG_PATH);
  267. if(!menu_zone_surfaces[nb_menu_zones-1]) {
  268. MENU_ERROR_PRINTF("ERROR IMG_Load: %s\n", IMG_GetError());
  269. }
  270. /// --------- Init Common Variables --------
  271. SDL_Surface *text_surface = NULL;
  272. SDL_Surface *surface = menu_zone_surfaces[nb_menu_zones-1];
  273. SDL_Rect text_pos;
  274. /// --------- Add new zone ---------
  275. switch(menu_type){
  276. case MENU_TYPE_VOLUME:
  277. MENU_DEBUG_PRINTF("Init MENU_TYPE_VOLUME\n");
  278. /// ------ Text ------
  279. text_surface = TTF_RenderText_Blended(menu_title_font, "VOLUME", text_color);
  280. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  281. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 - padding_y_from_center_menu_zone;
  282. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  283. x_volume_bar = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - width_progress_bar)/2;
  284. y_volume_bar = surface->h - MENU_ZONE_HEIGHT/2 - height_progress_bar/2 + padding_y_from_center_menu_zone;
  285. draw_progress_bar(surface, x_volume_bar, y_volume_bar,
  286. width_progress_bar, height_progress_bar, 0, 100/STEP_CHANGE_VOLUME);
  287. break;
  288. case MENU_TYPE_BRIGHTNESS:
  289. MENU_DEBUG_PRINTF("Init MENU_TYPE_BRIGHTNESS\n");
  290. /// ------ Text ------
  291. text_surface = TTF_RenderText_Blended(menu_title_font, "BRIGHTNESS", text_color);
  292. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  293. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 - padding_y_from_center_menu_zone;
  294. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  295. x_brightness_bar = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - width_progress_bar)/2;
  296. y_brightness_bar = surface->h - MENU_ZONE_HEIGHT/2 - height_progress_bar/2 + padding_y_from_center_menu_zone;
  297. draw_progress_bar(surface, x_brightness_bar, y_brightness_bar,
  298. width_progress_bar, height_progress_bar, 0, 100/STEP_CHANGE_BRIGHTNESS);
  299. break;
  300. case MENU_TYPE_SAVE:
  301. MENU_DEBUG_PRINTF("Init MENU_TYPE_SAVE\n");
  302. /// ------ Text ------
  303. text_surface = TTF_RenderText_Blended(menu_title_font, "SAVE", text_color);
  304. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  305. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 - padding_y_from_center_menu_zone*2;
  306. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  307. break;
  308. case MENU_TYPE_LOAD:
  309. MENU_DEBUG_PRINTF("Init MENU_TYPE_LOAD\n");
  310. /// ------ Text ------
  311. text_surface = TTF_RenderText_Blended(menu_title_font, "LOAD", text_color);
  312. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  313. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 - padding_y_from_center_menu_zone*2;
  314. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  315. break;
  316. case MENU_TYPE_ASPECT_RATIO:
  317. MENU_DEBUG_PRINTF("Init MENU_TYPE_ASPECT_RATIO\n");
  318. /// ------ Text ------
  319. text_surface = TTF_RenderText_Blended(menu_title_font, "ASPECT RATIO", text_color);
  320. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  321. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 - padding_y_from_center_menu_zone;
  322. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  323. break;
  324. case MENU_TYPE_EXIT:
  325. MENU_DEBUG_PRINTF("Init MENU_TYPE_EXIT\n");
  326. /// ------ Text ------
  327. text_surface = TTF_RenderText_Blended(menu_title_font, "EXIT GAME", text_color);
  328. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  329. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2;
  330. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  331. break;
  332. case MENU_TYPE_POWERDOWN:
  333. MENU_DEBUG_PRINTF("Init MENU_TYPE_POWERDOWN\n");
  334. /// ------ Text ------
  335. text_surface = TTF_RenderText_Blended(menu_title_font, "POWERDOWN", text_color);
  336. text_pos.x = (surface->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  337. text_pos.y = surface->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2;
  338. SDL_BlitSurface(text_surface, NULL, surface, &text_pos);
  339. break;
  340. default:
  341. MENU_DEBUG_PRINTF("Warning - In add_menu_zone, unknown MENU_TYPE: %d\n", menu_type);
  342. break;
  343. }
  344. /// ------ Free Surfaces -------
  345. SDL_FreeSurface(text_surface);
  346. }
  347. void init_menu_zones(){
  348. /// Init Volume Menu
  349. add_menu_zone(MENU_TYPE_VOLUME);
  350. /// Init Brightness Menu
  351. add_menu_zone(MENU_TYPE_BRIGHTNESS);
  352. /// Init Save Menu
  353. add_menu_zone(MENU_TYPE_SAVE);
  354. /// Init Load Menu
  355. add_menu_zone(MENU_TYPE_LOAD);
  356. /// Init Aspect Ratio Menu
  357. add_menu_zone(MENU_TYPE_ASPECT_RATIO);
  358. /// Init Exit Menu
  359. add_menu_zone(MENU_TYPE_EXIT);
  360. /// Init Powerdown Menu
  361. //add_menu_zone(MENU_TYPE_POWERDOWN);
  362. }
  363. void init_menu_system_values(){
  364. FILE *fp;
  365. char res[100];
  366. /// ------- Get system volume percentage --------
  367. fp = popen(SHELL_CMD_VOLUME_GET, "r");
  368. if (fp == NULL) {
  369. MENU_ERROR_PRINTF("Failed to run command %s\n", SHELL_CMD_VOLUME_GET );
  370. volume_percentage = 50; ///wrong value: setting default to 50
  371. }
  372. else{
  373. fgets(res, sizeof(res)-1, fp);
  374. pclose(fp);
  375. /// Check if Volume is a number (at least the first char)
  376. if(res[0] < '0' || res[0] > '9'){
  377. MENU_ERROR_PRINTF("Wrong return value: %s for volume cmd: %s\n",res, SHELL_CMD_VOLUME_GET);
  378. volume_percentage = 50; ///wrong value: setting default to 50
  379. }
  380. else{
  381. volume_percentage = atoi(res);
  382. MENU_DEBUG_PRINTF("System volume = %d%%\n", volume_percentage);
  383. }
  384. }
  385. /// ------- Get system brightness percentage -------
  386. fp = popen(SHELL_CMD_BRIGHTNESS_GET, "r");
  387. if (fp == NULL) {
  388. MENU_ERROR_PRINTF("Failed to run command %s\n", SHELL_CMD_BRIGHTNESS_GET );
  389. brightness_percentage = 50; ///wrong value: setting default to 50
  390. }
  391. else{
  392. fgets(res, sizeof(res)-1, fp);
  393. pclose(fp);
  394. /// Check if brightness is a number (at least the first char)
  395. if(res[0] < '0' || res[0] > '9'){
  396. MENU_ERROR_PRINTF("Wrong return value: %s for volume cmd: %s\n",res, SHELL_CMD_BRIGHTNESS_GET);
  397. brightness_percentage = 50; ///wrong value: setting default to 50
  398. }
  399. else{
  400. brightness_percentage = atoi(res);
  401. MENU_DEBUG_PRINTF("System brightness = %d%%\n", brightness_percentage);
  402. }
  403. }
  404. /// ------ Save prev key repeat params and set new Key repeat -------
  405. SDL_GetKeyRepeat(&backup_key_repeat_delay, &backup_key_repeat_interval);
  406. if(SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL)){
  407. MENU_ERROR_PRINTF("ERROR with SDL_EnableKeyRepeat: %s\n", SDL_GetError());
  408. }
  409. /// Get save slot from game
  410. state_slot = (state_slot%MAX_SAVE_SLOTS); // security
  411. }
  412. void menu_screen_refresh(int menuItem, int prevItem, int scroll, uint8_t menu_confirmation, uint8_t menu_action){
  413. /// --------- Vars ---------
  414. int print_arrows = (scroll==0)?1:0;
  415. /// --------- Clear HW screen ----------
  416. //SDL_FillRect(draw_screen, NULL, SDL_MapRGB(draw_screen->format, 255, 0, 0));
  417. if(SDL_BlitSurface(backup_hw_screen, NULL, draw_screen, NULL)){
  418. MENU_ERROR_PRINTF("ERROR Could not Clear draw_screen: %s\n", SDL_GetError());
  419. }
  420. /// --------- Setup Blit Window ----------
  421. SDL_Rect menu_blit_window;
  422. menu_blit_window.x = 0;
  423. menu_blit_window.w = SCREEN_HORIZONTAL_SIZE;
  424. /// --------- Blit prev menu Zone going away ----------
  425. menu_blit_window.y = scroll;
  426. menu_blit_window.h = SCREEN_VERTICAL_SIZE;
  427. if(SDL_BlitSurface(menu_zone_surfaces[prevItem], &menu_blit_window, draw_screen, NULL)){
  428. MENU_ERROR_PRINTF("ERROR Could not Blit surface on draw_screen: %s\n", SDL_GetError());
  429. }
  430. /// --------- Blit new menu Zone going in (only during animations) ----------
  431. if(scroll>0){
  432. menu_blit_window.y = SCREEN_VERTICAL_SIZE-scroll;
  433. menu_blit_window.h = SCREEN_VERTICAL_SIZE;
  434. if(SDL_BlitSurface(menu_zone_surfaces[menuItem], NULL, draw_screen, &menu_blit_window)){
  435. MENU_ERROR_PRINTF("ERROR Could not Blit surface on draw_screen: %s\n", SDL_GetError());
  436. }
  437. }
  438. else if(scroll<0){
  439. menu_blit_window.y = SCREEN_VERTICAL_SIZE+scroll;
  440. menu_blit_window.h = SCREEN_VERTICAL_SIZE;
  441. if(SDL_BlitSurface(menu_zone_surfaces[menuItem], &menu_blit_window, draw_screen, NULL)){
  442. MENU_ERROR_PRINTF("ERROR Could not Blit surface on draw_screen: %s\n", SDL_GetError());
  443. }
  444. }
  445. /// --------- No Scroll ? Blitting menu-specific info
  446. else{
  447. SDL_Surface * text_surface = NULL;
  448. char text_tmp[40];
  449. SDL_Rect text_pos;
  450. /*char fname[MAXPATHLEN];
  451. memset(fname, 0, MAXPATHLEN);*/
  452. char *fname = NULL;
  453. uint16_t limit_filename_size = 24;
  454. switch(idx_menus[menuItem]){
  455. case MENU_TYPE_VOLUME:
  456. draw_progress_bar(draw_screen, x_volume_bar, y_volume_bar,
  457. width_progress_bar, height_progress_bar, volume_percentage, 100/STEP_CHANGE_VOLUME);
  458. break;
  459. case MENU_TYPE_BRIGHTNESS:
  460. draw_progress_bar(draw_screen, x_volume_bar, y_volume_bar,
  461. width_progress_bar, height_progress_bar, brightness_percentage, 100/STEP_CHANGE_BRIGHTNESS);
  462. break;
  463. case MENU_TYPE_SAVE:
  464. /// ---- Write slot -----
  465. sprintf(text_tmp, "IN SLOT < %d >", state_slot+1);
  466. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  467. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  468. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2;
  469. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  470. if(menu_action){
  471. sprintf(text_tmp, "Saving...");
  472. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  473. }
  474. else{
  475. if(menu_confirmation){
  476. sprintf(text_tmp, "Are you sure ?");
  477. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  478. }
  479. else{
  480. fname = emu_get_save_fname(1, 0, state_slot, NULL);
  481. if (fname == NULL) {
  482. text_surface = TTF_RenderText_Blended(menu_info_font, "Free", text_color);
  483. }
  484. else{
  485. printf("Found saved file: %s\n", fname);
  486. char *p = strrchr (fname, '/');
  487. char *basename = p ? p + 1 : (char *) fname;
  488. if(strlen(basename) > limit_filename_size){basename[limit_filename_size]=0;} //limiting size
  489. text_surface = TTF_RenderText_Blended(menu_small_info_font, basename, text_color);
  490. }
  491. }
  492. }
  493. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  494. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 + 2*padding_y_from_center_menu_zone;
  495. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  496. break;
  497. case MENU_TYPE_LOAD:
  498. /// ---- Write slot -----
  499. if(quick_load_slot_chosen){
  500. sprintf(text_tmp, "FROM AUTO SAVE");
  501. }
  502. else{
  503. sprintf(text_tmp, "FROM SLOT < %d >", state_slot+1);
  504. }
  505. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  506. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  507. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2;
  508. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  509. if(menu_action){
  510. sprintf(text_tmp, "Loading...");
  511. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  512. }
  513. else{
  514. if(menu_confirmation){
  515. sprintf(text_tmp, "Are you sure ?");
  516. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  517. }
  518. else{
  519. if(quick_load_slot_chosen){
  520. text_surface = TTF_RenderText_Blended(menu_info_font, " ", text_color);
  521. }
  522. else{
  523. fname = emu_get_save_fname(1, 0, state_slot, NULL);
  524. if (fname == NULL) {
  525. text_surface = TTF_RenderText_Blended(menu_info_font, "Free", text_color);
  526. }
  527. else{
  528. printf("Found saved file: %s\n", fname);
  529. char *p = strrchr (fname, '/');
  530. char *basename = p ? p + 1 : (char *) fname;
  531. if(strlen(basename) > limit_filename_size){basename[limit_filename_size]=0;} //limiting size
  532. text_surface = TTF_RenderText_Blended(menu_small_info_font, basename, text_color);
  533. }
  534. }
  535. }
  536. }
  537. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  538. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 + 2*padding_y_from_center_menu_zone;
  539. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  540. break;
  541. case MENU_TYPE_ASPECT_RATIO:
  542. sprintf(text_tmp, "< %s >", aspect_ratio_name[aspect_ratio]);
  543. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  544. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  545. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 + padding_y_from_center_menu_zone;
  546. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  547. break;
  548. case MENU_TYPE_EXIT:
  549. case MENU_TYPE_POWERDOWN:
  550. if(menu_confirmation){
  551. sprintf(text_tmp, "Are you sure ?");
  552. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  553. text_pos.x = (draw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  554. text_pos.y = draw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 + 2*padding_y_from_center_menu_zone;
  555. SDL_BlitSurface(text_surface, NULL, draw_screen, &text_pos);
  556. }
  557. break;
  558. default:
  559. break;
  560. }
  561. /// ------ Free Surfaces -------
  562. if(text_surface)
  563. SDL_FreeSurface(text_surface);
  564. }
  565. /// --------- Print arrows --------
  566. if(print_arrows){
  567. /// Top arrow
  568. SDL_Rect pos_arrow_top;
  569. pos_arrow_top.x = (draw_screen->w - img_arrow_top->w)/2;
  570. pos_arrow_top.y = (draw_screen->h - MENU_BG_SQUARE_HEIGHT)/4 - img_arrow_top->h/2;
  571. SDL_BlitSurface(img_arrow_top, NULL, draw_screen, &pos_arrow_top);
  572. /// Bottom arrow
  573. SDL_Rect pos_arrow_bottom;
  574. pos_arrow_bottom.x = (draw_screen->w - img_arrow_bottom->w)/2;
  575. pos_arrow_bottom.y = draw_screen->h -
  576. (draw_screen->h - MENU_BG_SQUARE_HEIGHT)/4 - img_arrow_bottom->h/2;
  577. SDL_BlitSurface(img_arrow_bottom, NULL, draw_screen, &pos_arrow_bottom);
  578. }
  579. // Rotate
  580. //SDL_Rotate_270(hw_screen, virtual_hw_screen);
  581. SDL_BlitSurface(draw_screen, NULL, hw_screen, NULL);
  582. /// --- Real Flip ---
  583. SDL_Flip(hw_screen);
  584. }
  585. void run_menu_loop()
  586. {
  587. MENU_DEBUG_PRINTF("Launch Menu\n");
  588. SDL_Event event;
  589. uint32_t prev_ms = SDL_GetTicks();
  590. uint32_t cur_ms = SDL_GetTicks();
  591. int scroll=0;
  592. int start_scroll=0;
  593. uint8_t screen_refresh = 1;
  594. char shell_cmd[100];
  595. uint8_t menu_confirmation = 0;
  596. stop_menu_loop = 0;
  597. char fname[MAXPATHLEN];
  598. /// ------ Load default keymap ------
  599. system(SHELL_CMD_KEYMAP_DEFAULT);
  600. /// ------ Get init values -------
  601. init_menu_system_values();
  602. int prevItem=menuItem;
  603. /// ------ Copy currently displayed screen -------
  604. /* if(SDL_BlitSurface(virtual_hw_screen, NULL, backup_hw_screen, NULL)){
  605. MENU_ERROR_PRINTF("ERROR Could not copy draw_screen: %s\n", SDL_GetError());
  606. }*/
  607. memcpy(backup_hw_screen->pixels, (uint16_t*) virtual_hw_screen->pixels,
  608. RES_HW_SCREEN_HORIZONTAL * RES_HW_SCREEN_VERTICAL * sizeof(uint16_t));
  609. /* Stop Ampli */
  610. system(SHELL_CMD_AUDIO_AMP_OFF);
  611. /// ------ Wait for menu UP key event ------
  612. int actions[IN_BINDTYPE_COUNT] = { 0, };
  613. while(event.type != SDL_KEYUP || event.key.keysym.sym != SDLK_q){
  614. while (SDL_PollEvent(&event)){
  615. SDL_PushEvent(&event);
  616. in_update(actions);
  617. }
  618. /* 500ms timeout */
  619. if(SDL_GetTicks() - cur_ms > 500){
  620. MENU_ERROR_PRINTF("Timeout waiting for SDLK_q UP\n");
  621. break;
  622. }
  623. }
  624. /// -------- Main loop ---------
  625. while (!stop_menu_loop)
  626. {
  627. /// -------- Handle Keyboard Events ---------
  628. if(!scroll){
  629. while (SDL_PollEvent(&event))
  630. switch(event.type)
  631. {
  632. case SDL_QUIT:
  633. engineState = PGS_Quit;
  634. stop_menu_loop = 1;
  635. break;
  636. case SDL_KEYDOWN:
  637. switch (event.key.keysym.sym)
  638. {
  639. case SDLK_b:
  640. if(menu_confirmation){
  641. /// ------ Reset menu confirmation ------
  642. menu_confirmation = 0;
  643. /// ------ Refresh screen ------
  644. screen_refresh = 1;
  645. }
  646. /*else{
  647. stop_menu_loop = 1;
  648. }*/
  649. break;
  650. case SDLK_q:
  651. case SDLK_ESCAPE:
  652. stop_menu_loop = 1;
  653. break;
  654. case SDLK_d:
  655. case SDLK_DOWN:
  656. MENU_DEBUG_PRINTF("DOWN\n");
  657. /// ------ Start scrolling to new menu -------
  658. menuItem++;
  659. if (menuItem>=nb_menu_zones) menuItem=0;
  660. scroll=1;
  661. /// ------ Reset menu confirmation ------
  662. menu_confirmation = 0;
  663. /// ------ Refresh screen ------
  664. screen_refresh = 1;
  665. break;
  666. case SDLK_u:
  667. case SDLK_UP:
  668. MENU_DEBUG_PRINTF("UP\n");
  669. /// ------ Start scrolling to new menu -------
  670. menuItem--;
  671. if (menuItem<0) menuItem=nb_menu_zones-1;
  672. scroll=-1;
  673. /// ------ Reset menu confirmation ------
  674. menu_confirmation = 0;
  675. /// ------ Refresh screen ------
  676. screen_refresh = 1;
  677. break;
  678. case SDLK_l:
  679. case SDLK_LEFT:
  680. //MENU_DEBUG_PRINTF("LEFT\n");
  681. if(idx_menus[menuItem] == MENU_TYPE_VOLUME){
  682. MENU_DEBUG_PRINTF("Volume DOWN\n");
  683. /// ----- Compute new value -----
  684. volume_percentage = (volume_percentage < STEP_CHANGE_VOLUME)?
  685. 0:(volume_percentage-STEP_CHANGE_VOLUME);
  686. /// ----- Shell cmd ----
  687. sprintf(shell_cmd, "%s %d", SHELL_CMD_VOLUME_SET, volume_percentage);
  688. system(shell_cmd);
  689. /// ------ Refresh screen ------
  690. screen_refresh = 1;
  691. }
  692. else if(idx_menus[menuItem] == MENU_TYPE_BRIGHTNESS){
  693. MENU_DEBUG_PRINTF("Brightness DOWN\n");
  694. /// ----- Compute new value -----
  695. brightness_percentage = (brightness_percentage < STEP_CHANGE_BRIGHTNESS)?
  696. 0:(brightness_percentage-STEP_CHANGE_BRIGHTNESS);
  697. /// ----- Shell cmd ----
  698. sprintf(shell_cmd, "%s %d", SHELL_CMD_BRIGHTNESS_SET, brightness_percentage);
  699. system(shell_cmd);
  700. /// ------ Refresh screen ------
  701. screen_refresh = 1;
  702. }
  703. else if(idx_menus[menuItem] == MENU_TYPE_SAVE){
  704. MENU_DEBUG_PRINTF("Save Slot DOWN\n");
  705. state_slot = (!state_slot)?(MAX_SAVE_SLOTS-1):(state_slot-1);
  706. /// ------ Refresh screen ------
  707. screen_refresh = 1;
  708. }
  709. else if(idx_menus[menuItem] == MENU_TYPE_LOAD){
  710. MENU_DEBUG_PRINTF("Load Slot DOWN\n");
  711. /** Choose quick save file or standard saveslot for loading */
  712. if(!quick_load_slot_chosen &&
  713. state_slot == 0 &&
  714. access(quick_save_file, F_OK ) != -1){
  715. quick_load_slot_chosen = 1;
  716. }
  717. else if(quick_load_slot_chosen){
  718. quick_load_slot_chosen = 0;
  719. state_slot = MAX_SAVE_SLOTS-1;
  720. }
  721. else{
  722. state_slot = (!state_slot)?(MAX_SAVE_SLOTS-1):(state_slot-1);
  723. }
  724. /// ------ Refresh screen ------
  725. screen_refresh = 1;
  726. }
  727. else if(idx_menus[menuItem] == MENU_TYPE_ASPECT_RATIO){
  728. MENU_DEBUG_PRINTF("Aspect Ratio DOWN\n");
  729. aspect_ratio = (!aspect_ratio)?(NB_ASPECT_RATIOS_TYPES-1):(aspect_ratio-1);
  730. /// ------ Refresh screen ------
  731. screen_refresh = 1;
  732. // Save config file
  733. configfile_save(cfg_file_rom);
  734. }
  735. break;
  736. case SDLK_r:
  737. case SDLK_RIGHT:
  738. //MENU_DEBUG_PRINTF("RIGHT\n");
  739. if(idx_menus[menuItem] == MENU_TYPE_VOLUME){
  740. MENU_DEBUG_PRINTF("Volume UP\n");
  741. /// ----- Compute new value -----
  742. volume_percentage = (volume_percentage > 100 - STEP_CHANGE_VOLUME)?
  743. 100:(volume_percentage+STEP_CHANGE_VOLUME);
  744. /// ----- Shell cmd ----
  745. sprintf(shell_cmd, "%s %d", SHELL_CMD_VOLUME_SET, volume_percentage);
  746. system(shell_cmd);
  747. /// ------ Refresh screen ------
  748. screen_refresh = 1;
  749. }
  750. else if(idx_menus[menuItem] == MENU_TYPE_BRIGHTNESS){
  751. MENU_DEBUG_PRINTF("Brightness UP\n");
  752. /// ----- Compute new value -----
  753. brightness_percentage = (brightness_percentage > 100 - STEP_CHANGE_BRIGHTNESS)?
  754. 100:(brightness_percentage+STEP_CHANGE_BRIGHTNESS);
  755. /// ----- Shell cmd ----
  756. sprintf(shell_cmd, "%s %d", SHELL_CMD_BRIGHTNESS_SET, brightness_percentage);
  757. system(shell_cmd);
  758. /// ------ Refresh screen ------
  759. screen_refresh = 1;
  760. }
  761. else if(idx_menus[menuItem] == MENU_TYPE_SAVE){
  762. MENU_DEBUG_PRINTF("Save Slot UP\n");
  763. state_slot = (state_slot+1)%MAX_SAVE_SLOTS;
  764. /// ------ Refresh screen ------
  765. screen_refresh = 1;
  766. }
  767. else if(idx_menus[menuItem] == MENU_TYPE_LOAD){
  768. MENU_DEBUG_PRINTF("Load Slot UP\n");
  769. /** Choose quick save file or standard saveslot for loading */
  770. if(!quick_load_slot_chosen &&
  771. state_slot == MAX_SAVE_SLOTS-1 &&
  772. access(quick_save_file, F_OK ) != -1){
  773. quick_load_slot_chosen = 1;
  774. }
  775. else if(quick_load_slot_chosen){
  776. quick_load_slot_chosen = 0;
  777. state_slot = 0;
  778. }
  779. else{
  780. state_slot = (state_slot+1)%MAX_SAVE_SLOTS;
  781. }
  782. /// ------ Refresh screen ------
  783. screen_refresh = 1;
  784. }
  785. else if(idx_menus[menuItem] == MENU_TYPE_ASPECT_RATIO){
  786. MENU_DEBUG_PRINTF("Aspect Ratio UP\n");
  787. aspect_ratio = (aspect_ratio+1)%NB_ASPECT_RATIOS_TYPES;
  788. /// ------ Refresh screen ------
  789. screen_refresh = 1;
  790. // Save config file
  791. configfile_save(cfg_file_rom);
  792. }
  793. break;
  794. case SDLK_a:
  795. case SDLK_RETURN:
  796. if(idx_menus[menuItem] == MENU_TYPE_SAVE){
  797. if(menu_confirmation){
  798. MENU_DEBUG_PRINTF("Saving in slot %d\n", state_slot);
  799. /// ------ Refresh Screen -------
  800. menu_screen_refresh(menuItem, prevItem, scroll, menu_confirmation, 1);
  801. /// ------ Save game ------
  802. int ret = emu_save_load_game(0, 0);
  803. /// ----- Hud Msg -----
  804. if(ret){
  805. MENU_ERROR_PRINTF("Save Failed\n");
  806. sprintf(shell_cmd, "%s %d \" SAVE FAILED\"",
  807. SHELL_CMD_NOTIF_SET, NOTIF_SECONDS_DISP);
  808. }
  809. else{
  810. sprintf(shell_cmd, "%s %d \" SAVED IN SLOT %d\"",
  811. SHELL_CMD_NOTIF_SET, NOTIF_SECONDS_DISP, state_slot+1);
  812. }
  813. system(shell_cmd);
  814. stop_menu_loop = 1;
  815. }
  816. else{
  817. MENU_DEBUG_PRINTF("Save game - asking confirmation\n");
  818. menu_confirmation = 1;
  819. /// ------ Refresh screen ------
  820. screen_refresh = 1;
  821. }
  822. }
  823. else if(idx_menus[menuItem] == MENU_TYPE_LOAD){
  824. if(menu_confirmation){
  825. MENU_DEBUG_PRINTF("Loading in slot %d\n", state_slot);
  826. /// ------ Refresh Screen -------
  827. menu_screen_refresh(menuItem, prevItem, scroll, menu_confirmation, 1);
  828. /// ------ Load game ------
  829. int ret;
  830. if(quick_load_slot_chosen){
  831. ret = emu_save_load_game_from_file(1, quick_save_file);
  832. }
  833. else{
  834. ret = emu_save_load_game(1, 0);
  835. }
  836. /// ----- Hud Msg -----
  837. if(ret){
  838. MENU_ERROR_PRINTF("Load Failed\n");
  839. sprintf(shell_cmd, "%s %d \" LOAD FAILED\"",
  840. SHELL_CMD_NOTIF_SET, NOTIF_SECONDS_DISP);
  841. }
  842. else{
  843. if(quick_load_slot_chosen){
  844. sprintf(shell_cmd, "%s %d \" LOADED FROM AUTO SAVE\"",
  845. SHELL_CMD_NOTIF_SET, NOTIF_SECONDS_DISP);
  846. }
  847. else{
  848. sprintf(shell_cmd, "%s %d \" LOADED FROM SLOT %d\"",
  849. SHELL_CMD_NOTIF_SET, NOTIF_SECONDS_DISP, state_slot+1);
  850. }
  851. }
  852. system(shell_cmd);
  853. /*snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "LOADED" : "FAIL!");
  854. hud_new_msg = 3;*/
  855. stop_menu_loop = 1;
  856. }
  857. else{
  858. MENU_DEBUG_PRINTF("Save game - asking confirmation\n");
  859. menu_confirmation = 1;
  860. /// ------ Refresh screen ------
  861. screen_refresh = 1;
  862. }
  863. }
  864. else if(idx_menus[menuItem] == MENU_TYPE_EXIT){
  865. MENU_DEBUG_PRINTF("Exit game\n");
  866. if(menu_confirmation){
  867. MENU_DEBUG_PRINTF("Exit game - confirmed\n");
  868. /// ----- The game should be saved here ----
  869. int ret = emu_save_load_game_from_file(0, quick_save_file);
  870. /// ----- Exit game and back to launcher ----
  871. engineState = PGS_Quit;
  872. stop_menu_loop = 1;
  873. }
  874. else{
  875. MENU_DEBUG_PRINTF("Exit game - asking confirmation\n");
  876. menu_confirmation = 1;
  877. /// ------ Refresh screen ------
  878. screen_refresh = 1;
  879. }
  880. }
  881. else if(idx_menus[menuItem] == MENU_TYPE_POWERDOWN){
  882. if(menu_confirmation){
  883. MENU_DEBUG_PRINTF("Powerdown - confirmed\n");
  884. /// ----- Shell cmd ----
  885. execlp(SHELL_CMD_POWERDOWN, SHELL_CMD_POWERDOWN, NULL);
  886. MENU_ERROR_PRINTF("Failed to run command %s\n", SHELL_CMD_POWERDOWN);
  887. exit(0);
  888. }
  889. else{
  890. MENU_DEBUG_PRINTF("Powerdown - asking confirmation\n");
  891. menu_confirmation = 1;
  892. /// ------ Refresh screen ------
  893. screen_refresh = 1;
  894. }
  895. }
  896. break;
  897. default:
  898. //MENU_DEBUG_PRINTF("Keydown: %d\n", event.key.keysym.sym);
  899. break;
  900. }
  901. break;
  902. }
  903. }
  904. /// --------- Handle Scroll effect ---------
  905. if ((scroll>0) || (start_scroll>0)){
  906. scroll+=MIN(SCROLL_SPEED_PX, MENU_ZONE_HEIGHT-scroll);
  907. start_scroll = 0;
  908. screen_refresh = 1;
  909. }
  910. else if ((scroll<0) || (start_scroll<0)){
  911. scroll-=MIN(SCROLL_SPEED_PX, MENU_ZONE_HEIGHT+scroll);
  912. start_scroll = 0;
  913. screen_refresh = 1;
  914. }
  915. if (scroll>=MENU_ZONE_HEIGHT || scroll<=-MENU_ZONE_HEIGHT) {
  916. prevItem=menuItem;
  917. scroll=0;
  918. screen_refresh = 1;
  919. }
  920. /// --------- Handle FPS ---------
  921. cur_ms = SDL_GetTicks();
  922. if(cur_ms-prev_ms < 1000/FPS_MENU){
  923. SDL_Delay(1000/FPS_MENU - (cur_ms-prev_ms));
  924. }
  925. prev_ms = SDL_GetTicks();
  926. /// --------- Refresh screen
  927. if(screen_refresh){
  928. menu_screen_refresh(menuItem, prevItem, scroll, menu_confirmation, 0);
  929. }
  930. /// --------- reset screen refresh ---------
  931. screen_refresh = 0;
  932. }
  933. /// ------ Restore last keymap ------
  934. system(SHELL_CMD_KEYMAP_RESUME);
  935. /// ------ Reset prev key repeat params -------
  936. if(SDL_EnableKeyRepeat(backup_key_repeat_delay, backup_key_repeat_interval)){
  937. MENU_ERROR_PRINTF("ERROR with SDL_EnableKeyRepeat: %s\n", SDL_GetError());
  938. }
  939. /* Start Ampli */
  940. system(SHELL_CMD_AUDIO_AMP_ON);
  941. /// ------ Reset last screen ------
  942. SDL_BlitSurface(backup_hw_screen, NULL, hw_screen, NULL);
  943. SDL_Flip(hw_screen);
  944. }
  945. /****************************/
  946. /* Quick Resume Menu */
  947. /****************************/
  948. int launch_resume_menu_loop()
  949. {
  950. MENU_DEBUG_PRINTF("Init resume menu\n");
  951. /* Decare vars */
  952. SDL_Surface *text_surface = NULL;
  953. char text_tmp[40];
  954. SDL_Rect text_pos;
  955. SDL_Event event;
  956. uint32_t prev_ms = SDL_GetTicks();
  957. uint32_t cur_ms = SDL_GetTicks();
  958. stop_menu_loop = 0;
  959. uint8_t screen_refresh = 1;
  960. uint8_t menu_confirmation = 0;
  961. int option_idx=RESUME_YES;
  962. /* Stop Ampli */
  963. system(SHELL_CMD_AUDIO_AMP_OFF);
  964. /* Save prev key repeat params and set new Key repeat */
  965. SDL_GetKeyRepeat(&backup_key_repeat_delay, &backup_key_repeat_interval);
  966. if(SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL)){
  967. MENU_ERROR_PRINTF("ERROR with SDL_EnableKeyRepeat: %s\n", SDL_GetError());
  968. }
  969. /* Load BG */
  970. SDL_Surface *img_square_bg = IMG_Load(MENU_PNG_BG_PATH);
  971. if(!img_square_bg) {
  972. MENU_ERROR_PRINTF("ERROR IMG_Load: %s\n", IMG_GetError());
  973. }
  974. SDL_Surface *bg_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, hw_screen->w, hw_screen->h, 16, 0, 0, 0, 0);
  975. SDL_BlitSurface(img_square_bg, NULL, bg_surface, NULL);
  976. SDL_FreeSurface(img_square_bg);
  977. /* Print top arrow */
  978. SDL_Rect pos_arrow_top;
  979. pos_arrow_top.x = (bg_surface->w - img_arrow_top->w)/2;
  980. pos_arrow_top.y = (bg_surface->h - MENU_BG_SQUARE_HEIGHT)/4 - img_arrow_top->h/2;
  981. SDL_BlitSurface(img_arrow_top, NULL, bg_surface, &pos_arrow_top);
  982. /* Print bottom arrow */
  983. SDL_Rect pos_arrow_bottom;
  984. pos_arrow_bottom.x = (bg_surface->w - img_arrow_bottom->w)/2;
  985. pos_arrow_bottom.y = bg_surface->h -
  986. (bg_surface->h - MENU_BG_SQUARE_HEIGHT)/4 - img_arrow_bottom->h/2;
  987. SDL_BlitSurface(img_arrow_bottom, NULL, bg_surface, &pos_arrow_bottom);
  988. if (text_surface)
  989. SDL_FreeSurface(text_surface);
  990. /* Main loop */
  991. while (!stop_menu_loop)
  992. {
  993. /* Handle keyboard events */
  994. while (SDL_PollEvent(&event))
  995. switch(event.type)
  996. {
  997. case SDL_QUIT:
  998. engineState = PGS_Quit;
  999. stop_menu_loop = 1;
  1000. break;
  1001. case SDL_KEYDOWN:
  1002. switch (event.key.keysym.sym)
  1003. {
  1004. case SDLK_b:
  1005. if(menu_confirmation){
  1006. /// ------ Reset menu confirmation ------
  1007. menu_confirmation = 0;
  1008. /// ------ Refresh screen ------
  1009. screen_refresh = 1;
  1010. }
  1011. /*else{
  1012. stop_menu_loop = 1;
  1013. }*/
  1014. break;
  1015. case SDLK_q:
  1016. case SDLK_ESCAPE:
  1017. /*stop_menu_loop = 1;*/
  1018. break;
  1019. case SDLK_u:
  1020. case SDLK_UP:
  1021. MENU_DEBUG_PRINTF("Option UP\n");
  1022. option_idx = (!option_idx)?(NB_RESUME_OPTIONS-1):(option_idx-1);
  1023. /// ------ Reset menu confirmation ------
  1024. menu_confirmation = 0;
  1025. /// ------ Refresh screen ------
  1026. screen_refresh = 1;
  1027. break;
  1028. case SDLK_d:
  1029. case SDLK_DOWN:
  1030. MENU_DEBUG_PRINTF("Option DWON\n");
  1031. option_idx = (option_idx+1)%NB_RESUME_OPTIONS;
  1032. /// ------ Reset menu confirmation ------
  1033. menu_confirmation = 0;
  1034. /// ------ Refresh screen ------
  1035. screen_refresh = 1;
  1036. break;
  1037. case SDLK_a:
  1038. case SDLK_RETURN:
  1039. MENU_DEBUG_PRINTF("Pressed A\n");
  1040. if(menu_confirmation){
  1041. MENU_DEBUG_PRINTF("Confirmed\n");
  1042. /// ----- exit menu ----
  1043. stop_menu_loop = 1;
  1044. }
  1045. else{
  1046. MENU_DEBUG_PRINTF("Asking confirmation\n");
  1047. menu_confirmation = 1;
  1048. /// ------ Refresh screen ------
  1049. screen_refresh = 1;
  1050. }
  1051. break;
  1052. default:
  1053. //MENU_DEBUG_PRINTF("Keydown: %d\n", event.key.keysym.sym);
  1054. break;
  1055. }
  1056. break;
  1057. }
  1058. /* Handle FPS */
  1059. cur_ms = SDL_GetTicks();
  1060. if(cur_ms-prev_ms < 1000/FPS_MENU){
  1061. SDL_Delay(1000/FPS_MENU - (cur_ms-prev_ms));
  1062. }
  1063. prev_ms = SDL_GetTicks();
  1064. /* Refresh screen */
  1065. if(screen_refresh){
  1066. /* Clear and draw BG */
  1067. SDL_FillRect(hw_screen, NULL, 0);
  1068. if(SDL_BlitSurface(bg_surface, NULL, hw_screen, NULL)){
  1069. MENU_ERROR_PRINTF("ERROR Could not draw background: %s\n", SDL_GetError());
  1070. }
  1071. /* Draw resume or reset option */
  1072. text_surface = TTF_RenderText_Blended(menu_title_font, resume_options_str[option_idx], text_color);
  1073. text_pos.x = (hw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  1074. text_pos.y = hw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2;
  1075. SDL_BlitSurface(text_surface, NULL, hw_screen, &text_pos);
  1076. /* Draw confirmation */
  1077. if(menu_confirmation){
  1078. sprintf(text_tmp, "Are you sure ?");
  1079. text_surface = TTF_RenderText_Blended(menu_info_font, text_tmp, text_color);
  1080. text_pos.x = (hw_screen->w - MENU_ZONE_WIDTH)/2 + (MENU_ZONE_WIDTH - text_surface->w)/2;
  1081. text_pos.y = hw_screen->h - MENU_ZONE_HEIGHT/2 - text_surface->h/2 + 2*padding_y_from_center_menu_zone;
  1082. SDL_BlitSurface(text_surface, NULL, hw_screen, &text_pos);
  1083. }
  1084. /* Flip Screen */
  1085. SDL_Flip(hw_screen);
  1086. }
  1087. /* reset screen refresh */
  1088. screen_refresh = 0;
  1089. }
  1090. /// ----- Clear screen -----
  1091. SDL_FillRect(hw_screen, NULL, 0);
  1092. SDL_Flip(hw_screen);
  1093. /* Free SDL Surfaces */
  1094. if(bg_surface)
  1095. SDL_FreeSurface(bg_surface);
  1096. if(text_surface)
  1097. SDL_FreeSurface(text_surface);
  1098. /* Reset prev key repeat params */
  1099. if(SDL_EnableKeyRepeat(backup_key_repeat_delay, backup_key_repeat_interval)){
  1100. MENU_ERROR_PRINTF("ERROR with SDL_EnableKeyRepeat: %s\n", SDL_GetError());
  1101. }
  1102. /* Start Ampli */
  1103. system(SHELL_CMD_AUDIO_AMP_ON);
  1104. return option_idx;
  1105. }
  1106. static void make_bg(int no_scale, int from_screen)
  1107. {
  1108. unsigned short *src = (void *)g_menubg_src_ptr;
  1109. int w = g_menubg_src_w ? g_menubg_src_w : g_screen_width;
  1110. int h = g_menubg_src_h ? g_menubg_src_h : g_screen_height;
  1111. int pp = g_menubg_src_pp ? g_menubg_src_pp : g_screen_ppitch;
  1112. short *dst;
  1113. int x, y;
  1114. if (from_screen) {
  1115. src = g_screen_ptr;
  1116. w = g_screen_width;
  1117. h = g_screen_height;
  1118. pp = g_screen_ppitch;
  1119. }
  1120. if (src == NULL) {
  1121. memset(g_menubg_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
  1122. return;
  1123. }
  1124. if (!no_scale && g_menuscreen_w / w >= 2 && g_menuscreen_h / h >= 2)
  1125. {
  1126. u32 t, *d = g_menubg_ptr;
  1127. d += (g_menuscreen_h / 2 - h * 2 / 2)
  1128. * g_menuscreen_w / 2;
  1129. d += (g_menuscreen_w / 2 - w * 2 / 2) / 2;
  1130. for (y = 0; y < h; y++, src += pp, d += g_menuscreen_w*2/2) {
  1131. for (x = 0; x < w; x++) {
  1132. t = src[x];
  1133. t = ((t & 0xf79e)>>1) - ((t & 0xc618)>>3);
  1134. t |= t << 16;
  1135. d[x] = d[x + g_menuscreen_w / 2] = t;
  1136. }
  1137. }
  1138. return;
  1139. }
  1140. if (w > g_menuscreen_w)
  1141. w = g_menuscreen_w;
  1142. if (h > g_menuscreen_h)
  1143. h = g_menuscreen_h;
  1144. dst = (short *)g_menubg_ptr +
  1145. (g_menuscreen_h / 2 - h / 2) * g_menuscreen_w +
  1146. (g_menuscreen_w / 2 - w / 2);
  1147. // darken the active framebuffer
  1148. for (; h > 0; dst += g_menuscreen_w, src += pp, h--)
  1149. menu_darken_bg(dst, src, w, 1);
  1150. }
  1151. static void copy_bg(int dir)
  1152. {
  1153. unsigned short *bg = (void *)g_menubg_ptr;
  1154. unsigned short *sc = (void *)g_menuscreen_ptr;
  1155. int h = g_menuscreen_h;
  1156. for (; h > 0; sc += g_menuscreen_pp, bg += g_menuscreen_w, h--) {
  1157. if (dir)
  1158. memcpy(bg, sc, g_menuscreen_w * 2);
  1159. else
  1160. memcpy(sc, bg, g_menuscreen_w * 2);
  1161. }
  1162. }
  1163. static void menu_enter(int is_rom_loaded)
  1164. {
  1165. if (is_rom_loaded)
  1166. {
  1167. make_bg(0, 0);
  1168. }
  1169. else
  1170. {
  1171. int pos;
  1172. char buff[256];
  1173. pos = plat_get_skin_dir(buff, 256);
  1174. strcpy(buff + pos, "background.png");
  1175. // should really only happen once, on startup..
  1176. if (readpng(g_menubg_ptr, buff, READPNG_BG,
  1177. g_menuscreen_w, g_menuscreen_h) < 0)
  1178. memset(g_menubg_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);
  1179. }
  1180. plat_video_menu_enter(is_rom_loaded);
  1181. }
  1182. static void draw_savestate_bg(int slot)
  1183. {
  1184. const char *fname;
  1185. void *tmp_state;
  1186. fname = emu_get_save_fname(1, 0, slot, NULL);
  1187. if (!fname)
  1188. return;
  1189. tmp_state = PicoTmpStateSave();
  1190. PicoStateLoadGfx(fname);
  1191. /* do a frame and fetch menu bg */
  1192. pemu_forced_frame(0, 0);
  1193. make_bg(0, 1);
  1194. PicoTmpStateRestore(tmp_state);
  1195. }
  1196. // --------- loading ROM screen ----------
  1197. static int cdload_called = 0;
  1198. static void load_progress_cb(int percent)
  1199. {
  1200. int ln, len = percent * g_menuscreen_w / 100;
  1201. unsigned short *dst;
  1202. if (len > g_menuscreen_w)
  1203. len = g_menuscreen_w;
  1204. menu_draw_begin(0, 1);
  1205. copy_bg(0);
  1206. dst = (unsigned short *)g_menuscreen_ptr + g_menuscreen_pp * me_sfont_h * 2;
  1207. for (ln = me_sfont_h - 2; ln > 0; ln--, dst += g_menuscreen_pp)
  1208. memset(dst, 0xff, len * 2);
  1209. menu_draw_end();
  1210. }
  1211. static void cdload_progress_cb(const char *fname, int percent)
  1212. {
  1213. int ln, len = percent * g_menuscreen_w / 100;
  1214. unsigned short *dst;
  1215. menu_draw_begin(0, 1);
  1216. dst = (unsigned short *)g_menuscreen_ptr + g_menuscreen_pp * me_sfont_h * 2;
  1217. copy_bg(0);
  1218. menuscreen_memset_lines(dst, 0xff, me_sfont_h - 2);
  1219. smalltext_out16(1, 3 * me_sfont_h, "Processing CD image / MP3s", 0xffff);
  1220. smalltext_out16(1, 4 * me_sfont_h, fname, 0xffff);
  1221. dst += g_menuscreen_pp * me_sfont_h * 3;
  1222. if (len > g_menuscreen_w)
  1223. len = g_menuscreen_w;
  1224. for (ln = (me_sfont_h - 2); ln > 0; ln--, dst += g_menuscreen_pp)
  1225. memset(dst, 0xff, len * 2);
  1226. menu_draw_end();
  1227. cdload_called = 1;
  1228. }
  1229. void menu_romload_prepare(const char *rom_name)
  1230. {
  1231. #ifndef ALLOW_TEXT_OUT
  1232. return;
  1233. #endif //ALLOW_TEXT_OUT
  1234. const char *p = rom_name + strlen(rom_name);
  1235. while (p > rom_name && *p != '/')
  1236. p--;
  1237. menu_draw_begin(1, 1);
  1238. smalltext_out16(1, 1, "Loading", 0xffff);
  1239. smalltext_out16(1, me_sfont_h, p, 0xffff);
  1240. /* copy menu to bg for callbacks. OK since we are not in menu_loop here */
  1241. copy_bg(1);
  1242. menu_draw_end();
  1243. PicoCartLoadProgressCB = load_progress_cb;
  1244. PicoCDLoadProgressCB = cdload_progress_cb;
  1245. cdload_called = 0;
  1246. }
  1247. void menu_romload_end(void)
  1248. {
  1249. #ifndef ALLOW_TEXT_OUT
  1250. return;
  1251. #endif //ALLOW_TEXT_OUT
  1252. PicoCartLoadProgressCB = NULL;
  1253. PicoCDLoadProgressCB = NULL;
  1254. menu_draw_begin(0, 1);
  1255. copy_bg(0);
  1256. smalltext_out16(1, (cdload_called ? 6 : 3) * me_sfont_h,
  1257. "Starting emulation...", 0xffff);
  1258. menu_draw_end();
  1259. }
  1260. // ------------ patch/gg menu ------------
  1261. static void draw_patchlist(int sel)
  1262. {
  1263. int max_cnt, start, i, pos, active;
  1264. max_cnt = g_menuscreen_h / me_sfont_h;
  1265. start = max_cnt / 2 - sel;
  1266. menu_draw_begin(1, 0);
  1267. for (i = 0; i < PicoPatchCount; i++) {
  1268. pos = start + i;
  1269. if (pos < 0) continue;
  1270. if (pos >= max_cnt) break;
  1271. active = PicoPatches[i].active;
  1272. smalltext_out16(14, pos * me_sfont_h, active ? "ON " : "OFF", active ? 0xfff6 : 0xffff);
  1273. smalltext_out16(14 + me_sfont_w*4, pos * me_sfont_h, PicoPatches[i].name, active ? 0xfff6 : 0xffff);
  1274. }
  1275. pos = start + i;
  1276. if (pos < max_cnt)
  1277. smalltext_out16(14, pos * me_sfont_h, "done", 0xffff);
  1278. text_out16(5, max_cnt / 2 * me_sfont_h, ">");
  1279. menu_draw_end();
  1280. }
  1281. static void menu_loop_patches(void)
  1282. {
  1283. static int menu_sel = 0;
  1284. int inp;
  1285. for (;;)
  1286. {
  1287. draw_patchlist(menu_sel);
  1288. inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_L|PBTN_R
  1289. |PBTN_MOK|PBTN_MBACK, NULL, 33);
  1290. if (inp & PBTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = PicoPatchCount; }
  1291. if (inp & PBTN_DOWN) { menu_sel++; if (menu_sel > PicoPatchCount) menu_sel = 0; }
  1292. if (inp &(PBTN_LEFT|PBTN_L)) { menu_sel-=10; if (menu_sel < 0) menu_sel = 0; }
  1293. if (inp &(PBTN_RIGHT|PBTN_R)) { menu_sel+=10; if (menu_sel > PicoPatchCount) menu_sel = PicoPatchCount; }
  1294. if (inp & PBTN_MOK) { // action
  1295. if (menu_sel < PicoPatchCount)
  1296. PicoPatches[menu_sel].active = !PicoPatches[menu_sel].active;
  1297. else break;
  1298. }
  1299. if (inp & PBTN_MBACK)
  1300. break;
  1301. }
  1302. }
  1303. // -------------- key config --------------
  1304. // PicoIn.pad[] format: MXYZ SACB RLDU
  1305. me_bind_action me_ctrl_actions[] =
  1306. {
  1307. { "UP ", 0x0001 },
  1308. { "DOWN ", 0x0002 },
  1309. { "LEFT ", 0x0004 },
  1310. { "RIGHT ", 0x0008 },
  1311. { "A ", 0x0040 },
  1312. { "B ", 0x0010 },
  1313. { "C ", 0x0020 },
  1314. { "A turbo", 0x4000 },
  1315. { "B turbo", 0x1000 },
  1316. { "C turbo", 0x2000 },
  1317. { "START ", 0x0080 },
  1318. { "MODE ", 0x0800 },
  1319. { "X ", 0x0400 },
  1320. { "Y ", 0x0200 },
  1321. { "Z ", 0x0100 },
  1322. { NULL, 0 },
  1323. };
  1324. me_bind_action emuctrl_actions[] =
  1325. {
  1326. { "Load State ", PEV_STATE_LOAD },
  1327. { "Save State ", PEV_STATE_SAVE },
  1328. { "Prev Save Slot ", PEV_SSLOT_PREV },
  1329. { "Next Save Slot ", PEV_SSLOT_NEXT },
  1330. { "Switch Renderer ", PEV_SWITCH_RND },
  1331. { "Volume Down ", PEV_VOL_DOWN },
  1332. { "Volume Up ", PEV_VOL_UP },
  1333. { "Fast forward ", PEV_FF },
  1334. { "Reset Game ", PEV_RESET },
  1335. { "Enter Menu ", PEV_MENU },
  1336. { "Pico Next page ", PEV_PICO_PNEXT },
  1337. { "Pico Prev page ", PEV_PICO_PPREV },
  1338. { "Pico Switch input", PEV_PICO_SWINP },
  1339. { NULL, 0 }
  1340. };
  1341. static int key_config_loop_wrap(int id, int keys)
  1342. {
  1343. switch (id) {
  1344. case MA_CTRL_PLAYER1:
  1345. key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 0);
  1346. break;
  1347. case MA_CTRL_PLAYER2:
  1348. key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1);
  1349. break;
  1350. case MA_CTRL_EMU:
  1351. key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1);
  1352. break;
  1353. default:
  1354. break;
  1355. }
  1356. return 0;
  1357. }
  1358. static const char *mgn_dev_name(int id, int *offs)
  1359. {
  1360. const char *name = NULL;
  1361. static int it = 0;
  1362. if (id == MA_CTRL_DEV_FIRST)
  1363. it = 0;
  1364. for (; it < IN_MAX_DEVS; it++) {
  1365. name = in_get_dev_name(it, 1, 1);
  1366. if (name != NULL)
  1367. break;
  1368. }
  1369. it++;
  1370. return name;
  1371. }
  1372. static int mh_saveloadcfg(int id, int keys);
  1373. static const char *mgn_saveloadcfg(int id, int *offs);
  1374. const char *indev_names[] = { "none", "3 button pad", "6 button pad", NULL };
  1375. static menu_entry e_menu_keyconfig[] =
  1376. {
  1377. mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
  1378. mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
  1379. mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap),
  1380. mee_enum ("Input device 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev_names),
  1381. mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev_names),
  1382. mee_range ("Turbo rate", MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30),
  1383. mee_range ("Analog deadzone", MA_CTRL_DEADZONE, currentConfig.analog_deadzone, 1, 99),
  1384. mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg),
  1385. mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg),
  1386. mee_label (""),
  1387. mee_label ("Input devices:"),
  1388. mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name),
  1389. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1390. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1391. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1392. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1393. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1394. mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
  1395. mee_end,
  1396. };
  1397. static int menu_loop_keyconfig(int id, int keys)
  1398. {
  1399. static int sel = 0;
  1400. me_enable(e_menu_keyconfig, MA_OPT_SAVECFG_GAME, PicoGameLoaded);
  1401. me_loop(e_menu_keyconfig, &sel);
  1402. PicoSetInputDevice(0, currentConfig.input_dev0);
  1403. PicoSetInputDevice(1, currentConfig.input_dev1);
  1404. return 0;
  1405. }
  1406. // ------------ SCD options menu ------------
  1407. static const char h_cdleds[] = "Show power/CD LEDs of emulated console";
  1408. static const char h_cdda[] = "Play audio tracks from mp3s/wavs/bins";
  1409. static const char h_cdpcm[] = "Emulate PCM audio chip for effects/voices/music";
  1410. static const char h_srcart[] = "Emulate the save RAM cartridge accessory\n"
  1411. "most games don't need this";
  1412. static const char h_scfx[] = "Emulate scale/rotate ASIC chip for graphics effects\n"
  1413. "disable to improve performance";
  1414. static menu_entry e_menu_cd_options[] =
  1415. {
  1416. mee_onoff_h("CD LEDs", MA_CDOPT_LEDS, currentConfig.EmuOpt, EOPT_EN_CD_LEDS, h_cdleds),
  1417. mee_onoff_h("CDDA audio", MA_CDOPT_CDDA, PicoIn.opt, POPT_EN_MCD_CDDA, h_cdda),
  1418. mee_onoff_h("PCM audio", MA_CDOPT_PCM, PicoIn.opt, POPT_EN_MCD_PCM, h_cdpcm),
  1419. mee_onoff_h("SaveRAM cart", MA_CDOPT_SAVERAM, PicoIn.opt, POPT_EN_MCD_RAMCART, h_srcart),
  1420. mee_onoff_h("Scale/Rot. fx", MA_CDOPT_SCALEROT_CHIP, PicoIn.opt, POPT_EN_MCD_GFX, h_scfx),
  1421. mee_end,
  1422. };
  1423. static int menu_loop_cd_options(int id, int keys)
  1424. {
  1425. static int sel = 0;
  1426. me_loop(e_menu_cd_options, &sel);
  1427. return 0;
  1428. }
  1429. // ------------ 32X options menu ------------
  1430. #ifndef NO_32X
  1431. // convert from multiplier of VClk
  1432. static int mh_opt_sh2cycles(int id, int keys)
  1433. {
  1434. int *khz = (id == MA_32XOPT_MSH2_CYCLES) ?
  1435. &currentConfig.msh2_khz : &currentConfig.ssh2_khz;
  1436. if (keys & (PBTN_LEFT|PBTN_RIGHT))
  1437. *khz += (keys & PBTN_LEFT) ? -50 : 50;
  1438. if (keys & (PBTN_L|PBTN_R))
  1439. *khz += (keys & PBTN_L) ? -500 : 500;
  1440. if (*khz < 1)
  1441. *khz = 1;
  1442. else if (*khz > 0x7fffffff / 1000)
  1443. *khz = 0x7fffffff / 1000;
  1444. return 0;
  1445. }
  1446. static const char *mgn_opt_sh2cycles(int id, int *offs)
  1447. {
  1448. int khz = (id == MA_32XOPT_MSH2_CYCLES) ?
  1449. currentConfig.msh2_khz : currentConfig.ssh2_khz;
  1450. sprintf(static_buff, "%d", khz);
  1451. return static_buff;
  1452. }
  1453. static const char h_32x_enable[] = "Enable emulation of the 32X addon";
  1454. static const char h_pwm[] = "Disabling may improve performance, but break sound";
  1455. static const char h_sh2cycles[] = "Cycles/millisecond (similar to DOSBox)\n"
  1456. "lower values speed up emulation but break games\n"
  1457. "at least 11000 recommended for compatibility";
  1458. static menu_entry e_menu_32x_options[] =
  1459. {
  1460. mee_onoff_h ("32X enabled", MA_32XOPT_ENABLE_32X, PicoIn.opt, POPT_EN_32X, h_32x_enable),
  1461. mee_enum ("32X renderer", MA_32XOPT_RENDERER, currentConfig.renderer32x, renderer_names32x),
  1462. mee_onoff_h ("PWM sound", MA_32XOPT_PWM, PicoIn.opt, POPT_EN_PWM, h_pwm),
  1463. mee_cust_h ("Master SH2 cycles", MA_32XOPT_MSH2_CYCLES, mh_opt_sh2cycles, mgn_opt_sh2cycles, h_sh2cycles),
  1464. mee_cust_h ("Slave SH2 cycles", MA_32XOPT_SSH2_CYCLES, mh_opt_sh2cycles, mgn_opt_sh2cycles, h_sh2cycles),
  1465. mee_end,
  1466. };
  1467. static int menu_loop_32x_options(int id, int keys)
  1468. {
  1469. static int sel = 0;
  1470. me_enable(e_menu_32x_options, MA_32XOPT_RENDERER, renderer_names32x[0] != NULL);
  1471. me_loop(e_menu_32x_options, &sel);
  1472. Pico32xSetClocks(currentConfig.msh2_khz * 1000, currentConfig.msh2_khz * 1000);
  1473. return 0;
  1474. }
  1475. #endif
  1476. // ------------ SMS options menu ------------
  1477. #ifndef NO_SMS
  1478. static const char *sms_hardwares[] = { "auto", "Game Gear", "Master System", NULL };
  1479. static const char *sms_mappers[] = { "auto", "Sega", "Codemasters", "Korea", "Korea MSX", "Korea X-in-1", "Korea 4-Pak", "Korea Janggun", "Korea Nemesis", NULL };
  1480. static const char h_smsfm[] = "FM sound is only supported by few games\nOther games may crash with FM enabled";
  1481. static menu_entry e_menu_sms_options[] =
  1482. {
  1483. mee_enum ("System", MA_SMSOPT_HARDWARE, PicoIn.hwSelect, sms_hardwares),
  1484. mee_onoff_h ("FM Sound Unit", MA_OPT2_ENABLE_YM2413, PicoIn.opt, POPT_EN_YM2413, h_smsfm),
  1485. mee_enum ("Cartridge mapping", MA_SMSOPT_MAPPER, PicoIn.mapper, sms_mappers),
  1486. mee_end,
  1487. };
  1488. static int menu_loop_sms_options(int id, int keys)
  1489. {
  1490. static int sel = 0;
  1491. me_loop(e_menu_sms_options, &sel);
  1492. return 0;
  1493. }
  1494. #endif
  1495. // ------------ adv options menu ------------
  1496. static const char h_ovrclk[] = "Will break some games, keep at 0";
  1497. static menu_entry e_menu_adv_options[] =
  1498. {
  1499. mee_onoff ("Disable sprite limit", MA_OPT2_NO_SPRITE_LIM, PicoIn.opt, POPT_DIS_SPRITE_LIM),
  1500. mee_range_h ("Overclock M68k (%)", MA_OPT2_OVERCLOCK_M68K,currentConfig.overclock_68k, 0, 1000, h_ovrclk),
  1501. mee_onoff ("Emulate Z80", MA_OPT2_ENABLE_Z80, PicoIn.opt, POPT_EN_Z80),
  1502. mee_onoff ("Emulate YM2612 (FM)", MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM),
  1503. mee_onoff ("Disable YM2612 SSG-EG", MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG),
  1504. mee_onoff ("Enable YM2612 DAC noise", MA_OPT2_ENABLE_YM_DAC, PicoIn.opt, POPT_EN_FM_DAC),
  1505. mee_onoff ("Emulate SN76496 (PSG)", MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG),
  1506. mee_onoff ("Emulate Game Gear LCD", MA_OPT2_ENABLE_GGLCD ,PicoIn.opt, POPT_EN_GG_LCD),
  1507. mee_onoff ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoIn.opt, POPT_DIS_IDLE_DET),
  1508. mee_onoff ("Disable frame limiter", MA_OPT2_NO_FRAME_LIMIT,currentConfig.EmuOpt, EOPT_NO_FRMLIMIT),
  1509. mee_onoff ("Enable dynarecs", MA_OPT2_DYNARECS, PicoIn.opt, POPT_EN_DRC),
  1510. mee_range ("Max auto frameskip", MA_OPT2_MAX_FRAMESKIP, currentConfig.max_skip, 1, 10),
  1511. mee_onoff ("PWM IRQ optimization", MA_OPT2_PWM_IRQ_OPT, PicoIn.opt, POPT_PWM_IRQ_OPT),
  1512. MENU_OPTIONS_ADV
  1513. mee_end,
  1514. };
  1515. static int menu_loop_adv_options(int id, int keys)
  1516. {
  1517. static int sel = 0;
  1518. me_loop(e_menu_adv_options, &sel);
  1519. PicoIn.overclockM68k = currentConfig.overclock_68k; // int vs short
  1520. return 0;
  1521. }
  1522. // ------------ sound options menu ------------
  1523. static int sndrate_prevnext(int rate, int dir)
  1524. {
  1525. static const int rates[] = { 8000, 11025, 16000, 22050, 44100 };
  1526. int i;
  1527. for (i = 0; i < 5; i++)
  1528. if (rates[i] == rate) break;
  1529. i += dir ? 1 : -1;
  1530. if (i > 4) {
  1531. if (!(PicoIn.opt & POPT_EN_STEREO)) {
  1532. PicoIn.opt |= POPT_EN_STEREO;
  1533. return rates[0];
  1534. }
  1535. return rates[4];
  1536. }
  1537. if (i < 0) {
  1538. if (PicoIn.opt & POPT_EN_STEREO) {
  1539. PicoIn.opt &= ~POPT_EN_STEREO;
  1540. return rates[4];
  1541. }
  1542. return rates[0];
  1543. }
  1544. return rates[i];
  1545. }
  1546. static int mh_opt_snd(int id, int keys)
  1547. {
  1548. PicoIn.sndRate = sndrate_prevnext(PicoIn.sndRate, keys & PBTN_RIGHT);
  1549. return 0;
  1550. }
  1551. static const char *mgn_opt_sound(int id, int *offs)
  1552. {
  1553. const char *str2;
  1554. *offs = -8;
  1555. str2 = (PicoIn.opt & POPT_EN_STEREO) ? "stereo" : "mono";
  1556. sprintf(static_buff, "%5iHz %s", PicoIn.sndRate, str2);
  1557. return static_buff;
  1558. }
  1559. static int mh_opt_alpha(int id, int keys)
  1560. {
  1561. int val = (PicoIn.sndFilterAlpha * 100 + 0x08000) / 0x10000;
  1562. if (keys & PBTN_LEFT) val--;
  1563. if (keys & PBTN_RIGHT) val++;
  1564. if (val < 1) val = 1;
  1565. if (val > 99) val = 99;
  1566. PicoIn.sndFilterAlpha = val * 0x10000 / 100;
  1567. return 0;
  1568. }
  1569. static const char *mgn_opt_alpha(int id, int *offs)
  1570. {
  1571. int val = (PicoIn.sndFilterAlpha * 100 + 0x08000) / 0x10000;
  1572. sprintf(static_buff, "0.%02d", val);
  1573. return static_buff;
  1574. }
  1575. static const char h_lowpass[] = "Low pass filter for sound closer to real hardware";
  1576. static menu_entry e_menu_snd_options[] =
  1577. {
  1578. mee_onoff ("Enable sound", MA_OPT_ENABLE_SOUND, currentConfig.EmuOpt, EOPT_EN_SOUND),
  1579. mee_cust ("Sound Quality", MA_OPT_SOUND_QUALITY, mh_opt_snd, mgn_opt_sound),
  1580. mee_onoff_h ("Sound filter", MA_OPT_SOUND_FILTER, PicoIn.opt, POPT_EN_SNDFILTER, h_lowpass),
  1581. mee_cust ("Filter strength", MA_OPT_SOUND_ALPHA, mh_opt_alpha, mgn_opt_alpha),
  1582. mee_end,
  1583. };
  1584. static int menu_loop_snd_options(int id, int keys)
  1585. {
  1586. static int sel = 0;
  1587. me_loop(e_menu_snd_options, &sel);
  1588. return 0;
  1589. }
  1590. // ------------ gfx options menu ------------
  1591. static const char h_gamma[] = "Gamma/brightness adjustment (default 1.00)";
  1592. static const char *mgn_opt_fskip(int id, int *offs)
  1593. {
  1594. if (currentConfig.Frameskip < 0)
  1595. return "Auto";
  1596. sprintf(static_buff, "%d", currentConfig.Frameskip);
  1597. return static_buff;
  1598. }
  1599. static const char *mgn_aopt_gamma(int id, int *offs)
  1600. {
  1601. sprintf(static_buff, "%i.%02i", currentConfig.gamma / 100, currentConfig.gamma % 100);
  1602. return static_buff;
  1603. }
  1604. static menu_entry e_menu_gfx_options[] =
  1605. {
  1606. mee_enum ("Video output mode", MA_OPT_VOUT_MODE, plat_target.vout_method, men_dummy),
  1607. mee_enum ("Renderer", MA_OPT_RENDERER, currentConfig.renderer, renderer_names),
  1608. mee_range_cust("Frameskip", MA_OPT_FRAMESKIP, currentConfig.Frameskip, -1, 16, mgn_opt_fskip),
  1609. mee_enum ("Filter", MA_OPT3_FILTERING, currentConfig.filter, men_dummy),
  1610. mee_range_cust_h("Gamma correction", MA_OPT2_GAMMA, currentConfig.gamma, 1, 300, mgn_aopt_gamma, h_gamma),
  1611. MENU_OPTIONS_GFX
  1612. mee_end,
  1613. };
  1614. static int menu_loop_gfx_options(int id, int keys)
  1615. {
  1616. static int sel = 0;
  1617. me_enable(e_menu_gfx_options, MA_OPT_RENDERER, renderer_names[0] != NULL);
  1618. me_loop(e_menu_gfx_options, &sel);
  1619. return 0;
  1620. }
  1621. // ------------ UI options menu ------------
  1622. static const char *men_confirm_save[] = { "OFF", "writes", "loads", "both", NULL };
  1623. static const char h_confirm_save[] = "Ask for confirmation when overwriting save,\n"
  1624. "loading state or both";
  1625. static menu_entry e_menu_ui_options[] =
  1626. {
  1627. mee_onoff ("Show FPS", MA_OPT_SHOW_FPS, currentConfig.EmuOpt, EOPT_SHOW_FPS),
  1628. mee_enum_h ("Confirm savestate", MA_OPT_CONFIRM_STATES, currentConfig.confirm_save, men_confirm_save, h_confirm_save),
  1629. mee_onoff ("Don't save last used ROM", MA_OPT2_NO_LAST_ROM, currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG),
  1630. mee_end,
  1631. };
  1632. static int menu_loop_ui_options(int id, int keys)
  1633. {
  1634. static int sel = 0;
  1635. me_loop(e_menu_ui_options, &sel);
  1636. return 0;
  1637. }
  1638. // ------------ options menu ------------
  1639. static menu_entry e_menu_options[];
  1640. static void region_prevnext(int right)
  1641. {
  1642. // jp_ntsc=1, jp_pal=2, usa=4, eu=8
  1643. static const int rgn_orders[] = { 0x148, 0x184, 0x814, 0x418, 0x841, 0x481 };
  1644. int i;
  1645. if (right) {
  1646. if (!PicoIn.regionOverride) {
  1647. for (i = 0; i < 6; i++)
  1648. if (rgn_orders[i] == PicoIn.autoRgnOrder) break;
  1649. if (i < 5) PicoIn.autoRgnOrder = rgn_orders[i+1];
  1650. else PicoIn.regionOverride=1;
  1651. }
  1652. else
  1653. PicoIn.regionOverride <<= 1;
  1654. if (PicoIn.regionOverride > 8)
  1655. PicoIn.regionOverride = 8;
  1656. } else {
  1657. if (!PicoIn.regionOverride) {
  1658. for (i = 0; i < 6; i++)
  1659. if (rgn_orders[i] == PicoIn.autoRgnOrder) break;
  1660. if (i > 0) PicoIn.autoRgnOrder = rgn_orders[i-1];
  1661. }
  1662. else
  1663. PicoIn.regionOverride >>= 1;
  1664. }
  1665. }
  1666. static int mh_opt_misc(int id, int keys)
  1667. {
  1668. switch (id) {
  1669. case MA_OPT_REGION:
  1670. region_prevnext(keys & PBTN_RIGHT);
  1671. break;
  1672. default:
  1673. break;
  1674. }
  1675. return 0;
  1676. }
  1677. static int mh_saveloadcfg(int id, int keys)
  1678. {
  1679. int ret;
  1680. if (keys & (PBTN_LEFT|PBTN_RIGHT)) { // multi choice
  1681. config_slot += (keys & PBTN_LEFT) ? -1 : 1;
  1682. if (config_slot < 0) config_slot = 9;
  1683. else if (config_slot > 9) config_slot = 0;
  1684. me_enable(e_menu_options, MA_OPT_LOADCFG, config_slot != config_slot_current);
  1685. return 0;
  1686. }
  1687. switch (id) {
  1688. case MA_OPT_SAVECFG:
  1689. case MA_OPT_SAVECFG_GAME:
  1690. if (emu_write_config(id == MA_OPT_SAVECFG_GAME ? 1 : 0))
  1691. menu_update_msg("config saved");
  1692. else
  1693. menu_update_msg("failed to write config");
  1694. break;
  1695. case MA_OPT_LOADCFG:
  1696. ret = emu_read_config(rom_fname_loaded, 1);
  1697. if (!ret) ret = emu_read_config(NULL, 1);
  1698. if (ret) menu_update_msg("config loaded");
  1699. else menu_update_msg("failed to load config");
  1700. break;
  1701. default:
  1702. return 0;
  1703. }
  1704. return 1;
  1705. }
  1706. static int mh_restore_defaults(int id, int keys)
  1707. {
  1708. emu_set_defconfig();
  1709. menu_update_msg("defaults restored");
  1710. return 1;
  1711. }
  1712. static const char *mgn_opt_region(int id, int *offs)
  1713. {
  1714. static const char *names[] = { "Auto", " Japan NTSC", " Japan PAL", " USA", " Europe" };
  1715. static const char *names_short[] = { "", " JP", " JP", " US", " EU" };
  1716. int code = PicoIn.regionOverride;
  1717. int u, i = 0;
  1718. *offs = -6;
  1719. if (code) {
  1720. code <<= 1;
  1721. while ((code >>= 1)) i++;
  1722. if (i > 4)
  1723. return "unknown";
  1724. return names[i];
  1725. } else {
  1726. strcpy(static_buff, "Auto:");
  1727. for (u = 0; u < 3; u++) {
  1728. code = (PicoIn.autoRgnOrder >> u*4) & 0xf;
  1729. for (i = 0; code; code >>= 1, i++)
  1730. ;
  1731. strcat(static_buff, names_short[i]);
  1732. }
  1733. return static_buff;
  1734. }
  1735. }
  1736. static const char *mgn_saveloadcfg(int id, int *offs)
  1737. {
  1738. static_buff[0] = 0;
  1739. if (config_slot != 0)
  1740. sprintf(static_buff, "[%i]", config_slot);
  1741. return static_buff;
  1742. }
  1743. static menu_entry e_menu_options[] =
  1744. {
  1745. mee_range ("Save slot", MA_OPT_SAVE_SLOT, state_slot, 0, 9),
  1746. mee_cust ("Region", MA_OPT_REGION, mh_opt_misc, mgn_opt_region),
  1747. mee_range ("", MA_OPT_CPU_CLOCKS, currentConfig.CPUclock, 20, 3200),
  1748. mee_handler ("[Interface options]", menu_loop_ui_options),
  1749. mee_handler ("[Display options]", menu_loop_gfx_options),
  1750. mee_handler ("[Sound options]", menu_loop_snd_options),
  1751. mee_handler ("[Sega/Mega CD options]", menu_loop_cd_options),
  1752. #ifndef NO_32X
  1753. mee_handler ("[32X options]", menu_loop_32x_options),
  1754. #endif
  1755. #ifndef NO_SMS
  1756. mee_handler ("[SMS options]", menu_loop_sms_options),
  1757. #endif
  1758. mee_handler ("[Advanced options]", menu_loop_adv_options),
  1759. mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg),
  1760. mee_cust_nosave("Save cfg for loaded game",MA_OPT_SAVECFG_GAME, mh_saveloadcfg, mgn_saveloadcfg),
  1761. mee_cust_nosave("Load cfg from profile", MA_OPT_LOADCFG, mh_saveloadcfg, mgn_saveloadcfg),
  1762. mee_handler ("Restore defaults", mh_restore_defaults),
  1763. mee_end,
  1764. };
  1765. static int menu_loop_options(int id, int keys)
  1766. {
  1767. static int sel = 0;
  1768. me_enable(e_menu_options, MA_OPT_SAVECFG_GAME, PicoGameLoaded);
  1769. me_enable(e_menu_options, MA_OPT_LOADCFG, config_slot != config_slot_current);
  1770. me_loop(e_menu_options, &sel);
  1771. return 0;
  1772. }
  1773. // ------------ debug menu ------------
  1774. #include <pico/debug.h>
  1775. extern void SekStepM68k(void);
  1776. static void mplayer_loop(void)
  1777. {
  1778. pemu_sound_start();
  1779. while (1)
  1780. {
  1781. PDebugZ80Frame();
  1782. if (in_menu_wait_any(NULL, 0) & PBTN_MA3)
  1783. break;
  1784. emu_sound_wait();
  1785. }
  1786. emu_sound_stop();
  1787. }
  1788. static void draw_text_debug(const char *str, int skip, int from)
  1789. {
  1790. const char *p;
  1791. int line;
  1792. p = str;
  1793. while (skip-- > 0)
  1794. {
  1795. while (*p && *p != '\n')
  1796. p++;
  1797. if (*p == 0 || p[1] == 0)
  1798. return;
  1799. p++;
  1800. }
  1801. str = p;
  1802. for (line = from; line < g_menuscreen_h / me_sfont_h; line++)
  1803. {
  1804. smalltext_out16(1, line * me_sfont_h, str, 0xffff);
  1805. while (*p && *p != '\n')
  1806. p++;
  1807. if (*p == 0)
  1808. break;
  1809. p++; str = p;
  1810. }
  1811. }
  1812. #ifdef __GNUC__
  1813. #define COMPILER "gcc " __VERSION__
  1814. #else
  1815. #define COMPILER
  1816. #endif
  1817. static void draw_frame_debug(void)
  1818. {
  1819. char layer_str[48] = "layers: ";
  1820. struct PicoVideo *pv = &Pico.video;
  1821. if (!(pv->debug_p & PVD_KILL_B)) memcpy(layer_str + 8, "B", 1);
  1822. if (!(pv->debug_p & PVD_KILL_A)) memcpy(layer_str + 10, "A", 1);
  1823. if (!(pv->debug_p & PVD_KILL_S_LO)) memcpy(layer_str + 12, "spr_lo", 6);
  1824. if (!(pv->debug_p & PVD_KILL_S_HI)) memcpy(layer_str + 19, "spr_hi", 6);
  1825. if (!(pv->debug_p & PVD_KILL_32X)) memcpy(layer_str + 26, "32x", 4);
  1826. pemu_forced_frame(1, 0);
  1827. make_bg(1, 1);
  1828. smalltext_out16(4, 1, "build: r" REVISION " "__DATE__ " " __TIME__ " " COMPILER, 0xffff);
  1829. smalltext_out16(4, g_menuscreen_h - me_sfont_h, layer_str, 0xffff);
  1830. }
  1831. static void debug_menu_loop(void)
  1832. {
  1833. struct PicoVideo *pv = &Pico.video;
  1834. int inp, mode = 0;
  1835. int spr_offs = 0, dumped = 0;
  1836. char *tmp;
  1837. while (1)
  1838. {
  1839. menu_draw_begin(1, 0);
  1840. switch (mode)
  1841. {
  1842. case 0: tmp = PDebugMain();
  1843. plat_debug_cat(tmp);
  1844. draw_text_debug(tmp, 0, 0);
  1845. if (dumped) {
  1846. smalltext_out16(g_menuscreen_w - 6 * me_sfont_h,
  1847. g_menuscreen_h - me_mfont_h, "dumped", 0xffff);
  1848. dumped = 0;
  1849. }
  1850. break;
  1851. case 1: draw_frame_debug();
  1852. break;
  1853. case 2: pemu_forced_frame(1, 0);
  1854. make_bg(1, 1);
  1855. PDebugShowSpriteStats((unsigned short *)g_menuscreen_ptr
  1856. + (g_menuscreen_h/2 - 240/2) * g_menuscreen_pp
  1857. + g_menuscreen_w/2 - 320/2, g_menuscreen_pp);
  1858. break;
  1859. case 3: menuscreen_memset_lines(g_menuscreen_ptr, 0, g_menuscreen_h);
  1860. PDebugShowPalette(g_menuscreen_ptr, g_menuscreen_pp);
  1861. PDebugShowSprite((unsigned short *)g_menuscreen_ptr
  1862. + g_menuscreen_pp * 120 + g_menuscreen_w / 2 + 16,
  1863. g_menuscreen_pp, spr_offs);
  1864. draw_text_debug(PDebugSpriteList(), spr_offs, 6);
  1865. break;
  1866. case 4: tmp = PDebug32x();
  1867. draw_text_debug(tmp, 0, 0);
  1868. break;
  1869. }
  1870. menu_draw_end();
  1871. inp = in_menu_wait(PBTN_MOK|PBTN_MBACK|PBTN_MA2|PBTN_MA3|PBTN_L|PBTN_R |
  1872. PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT, NULL, 70);
  1873. if (inp & PBTN_MBACK) return;
  1874. if (inp & PBTN_L) { mode--; if (mode < 0) mode = 4; }
  1875. if (inp & PBTN_R) { mode++; if (mode > 4) mode = 0; }
  1876. switch (mode)
  1877. {
  1878. case 0:
  1879. if (inp & PBTN_MOK)
  1880. PDebugCPUStep();
  1881. if (inp & PBTN_MA3) {
  1882. while (inp & PBTN_MA3)
  1883. inp = in_menu_wait_any(NULL, -1);
  1884. mplayer_loop();
  1885. }
  1886. if ((inp & (PBTN_MA2|PBTN_LEFT)) == (PBTN_MA2|PBTN_LEFT)) {
  1887. mkdir("dumps", 0777);
  1888. PDebugDumpMem();
  1889. while (inp & PBTN_MA2) inp = in_menu_wait_any(NULL, -1);
  1890. dumped = 1;
  1891. }
  1892. break;
  1893. case 1:
  1894. if (inp & PBTN_LEFT) pv->debug_p ^= PVD_KILL_B;
  1895. if (inp & PBTN_RIGHT) pv->debug_p ^= PVD_KILL_A;
  1896. if (inp & PBTN_DOWN) pv->debug_p ^= PVD_KILL_S_LO;
  1897. if (inp & PBTN_UP) pv->debug_p ^= PVD_KILL_S_HI;
  1898. if (inp & PBTN_MA2) pv->debug_p ^= PVD_KILL_32X;
  1899. if (inp & PBTN_MOK) {
  1900. PicoIn.sndOut = NULL; // just in case
  1901. PicoIn.skipFrame = 1;
  1902. PicoFrame();
  1903. PicoIn.skipFrame = 0;
  1904. while (inp & PBTN_MOK) inp = in_menu_wait_any(NULL, -1);
  1905. }
  1906. break;
  1907. case 3:
  1908. if (inp & PBTN_DOWN) spr_offs++;
  1909. if (inp & PBTN_UP) spr_offs--;
  1910. if (spr_offs < 0) spr_offs = 0;
  1911. break;
  1912. }
  1913. }
  1914. }
  1915. // ------------ main menu ------------
  1916. static void draw_frame_credits(void)
  1917. {
  1918. smalltext_out16(4, 1, "build: " __DATE__ " " __TIME__, 0xe7fc);
  1919. }
  1920. static const char credits[] =
  1921. "PicoDrive v" VERSION "\n"
  1922. "(c) notaz, 2006-2013; irixxxx, 2018-2021\n\n"
  1923. "Credits:\n"
  1924. "fDave: initial code\n"
  1925. #ifdef EMU_C68K
  1926. " Cyclone 68000 core\n"
  1927. #else
  1928. "Stef, Chui: FAME/C 68k core\n"
  1929. #endif
  1930. #ifdef _USE_DRZ80
  1931. "Reesy & FluBBa: DrZ80 core\n"
  1932. #else
  1933. "Stef, NJ: CZ80 core\n"
  1934. #endif
  1935. "MAME devs: SH2, YM2612 and SN76496 cores\n"
  1936. "Eke, Stef: some Sega CD code\n"
  1937. "Inder, ketchupgun: graphics\n"
  1938. #ifdef __GP2X__
  1939. "Squidge: mmuhack\n"
  1940. "Dzz: ARM940 sample\n"
  1941. #endif
  1942. "\n"
  1943. "special thanks (for docs, ideas):\n"
  1944. " Charles MacDonald, Haze,\n"
  1945. " Stephane Dallongeville,\n"
  1946. " Lordus, Exophase, Rokas,\n"
  1947. " Eke, Nemesis, Tasco Deluxe";
  1948. static void menu_main_draw_status(void)
  1949. {
  1950. static time_t last_bat_read = 0;
  1951. static int last_bat_val = -1;
  1952. unsigned short *bp = g_menuscreen_ptr;
  1953. int bat_h = me_mfont_h * 2 / 3;
  1954. int i, u, w, wfill, batt_val;
  1955. struct tm *tmp;
  1956. time_t ltime;
  1957. char time_s[16];
  1958. if (!(currentConfig.EmuOpt & EOPT_SHOW_RTC))
  1959. return;
  1960. ltime = time(NULL);
  1961. tmp = gmtime(&ltime);
  1962. strftime(time_s, sizeof(time_s), "%H:%M", tmp);
  1963. text_out16(g_menuscreen_w - me_mfont_w * 6, me_mfont_h + 2, time_s);
  1964. if (ltime - last_bat_read > 10) {
  1965. last_bat_read = ltime;
  1966. last_bat_val = batt_val = plat_target_bat_capacity_get();
  1967. }
  1968. else
  1969. batt_val = last_bat_val;
  1970. if (batt_val < 0 || batt_val > 100)
  1971. return;
  1972. /* battery info */
  1973. bp += (me_mfont_h * 2 + 2) * g_menuscreen_pp + g_menuscreen_w - me_mfont_w * 3 - 3;
  1974. for (i = 0; i < me_mfont_w * 2; i++)
  1975. bp[i] = menu_text_color;
  1976. for (i = 0; i < me_mfont_w * 2; i++)
  1977. bp[i + g_menuscreen_pp * bat_h] = menu_text_color;
  1978. for (i = 0; i <= bat_h; i++)
  1979. bp[i * g_menuscreen_pp] =
  1980. bp[i * g_menuscreen_pp + me_mfont_w * 2] = menu_text_color;
  1981. for (i = 2; i < bat_h - 1; i++)
  1982. bp[i * g_menuscreen_pp - 1] =
  1983. bp[i * g_menuscreen_pp - 2] = menu_text_color;
  1984. w = me_mfont_w * 2 - 1;
  1985. wfill = batt_val * w / 100;
  1986. for (u = 1; u < bat_h; u++)
  1987. for (i = 0; i < wfill; i++)
  1988. bp[(w - i) + g_menuscreen_pp * u] = menu_text_color;
  1989. }
  1990. static int main_menu_handler(int id, int keys)
  1991. {
  1992. const char *ret_name;
  1993. switch (id)
  1994. {
  1995. case MA_MAIN_RESUME_GAME:
  1996. if (PicoGameLoaded)
  1997. return 1;
  1998. break;
  1999. case MA_MAIN_SAVE_STATE:
  2000. if (PicoGameLoaded)
  2001. return menu_loop_savestate(0);
  2002. break;
  2003. case MA_MAIN_LOAD_STATE:
  2004. if (PicoGameLoaded)
  2005. return menu_loop_savestate(1);
  2006. break;
  2007. case MA_MAIN_RESET_GAME:
  2008. if (PicoGameLoaded) {
  2009. emu_reset_game();
  2010. return 1;
  2011. }
  2012. break;
  2013. case MA_MAIN_LOAD_ROM:
  2014. rom_fname_reload = NULL;
  2015. ret_name = menu_loop_romsel(rom_fname_loaded,
  2016. sizeof(rom_fname_loaded), rom_exts, NULL);
  2017. if (ret_name != NULL) {
  2018. lprintf("selected file: %s\n", ret_name);
  2019. rom_fname_reload = ret_name;
  2020. engineState = PGS_ReloadRom;
  2021. return 1;
  2022. }
  2023. break;
  2024. case MA_MAIN_CHANGE_CD:
  2025. if (PicoIn.AHW & PAHW_MCD) {
  2026. // if cd is loaded, cdd_unload() triggers eject and
  2027. // returns 1, else we'll select and load new CD here
  2028. if (!cdd_unload())
  2029. menu_loop_tray();
  2030. return 1;
  2031. }
  2032. break;
  2033. case MA_MAIN_CREDITS:
  2034. draw_menu_message(credits, draw_frame_credits);
  2035. in_menu_wait(PBTN_MOK|PBTN_MBACK, NULL, 70);
  2036. break;
  2037. case MA_MAIN_EXIT:
  2038. engineState = PGS_Quit;
  2039. return 1;
  2040. case MA_MAIN_PATCHES:
  2041. if (PicoGameLoaded && PicoPatches) {
  2042. menu_loop_patches();
  2043. PicoPatchApply();
  2044. menu_update_msg("Patches applied");
  2045. }
  2046. break;
  2047. default:
  2048. lprintf("%s: something unknown selected\n", __FUNCTION__);
  2049. break;
  2050. }
  2051. return 0;
  2052. }
  2053. static menu_entry e_menu_main[] =
  2054. {
  2055. mee_label ("PicoDrive " VERSION),
  2056. mee_label (""),
  2057. mee_label (""),
  2058. mee_label (""),
  2059. mee_handler_id("Resume game", MA_MAIN_RESUME_GAME, main_menu_handler),
  2060. mee_handler_id("Save State", MA_MAIN_SAVE_STATE, main_menu_handler),
  2061. mee_handler_id("Load State", MA_MAIN_LOAD_STATE, main_menu_handler),
  2062. mee_handler_id("Reset game", MA_MAIN_RESET_GAME, main_menu_handler),
  2063. mee_handler_id("Load new ROM/ISO", MA_MAIN_LOAD_ROM, main_menu_handler),
  2064. mee_handler_id("Change CD/ISO", MA_MAIN_CHANGE_CD, main_menu_handler),
  2065. mee_handler ("Change options", menu_loop_options),
  2066. mee_handler ("Configure controls", menu_loop_keyconfig),
  2067. mee_handler_id("Credits", MA_MAIN_CREDITS, main_menu_handler),
  2068. mee_handler_id("Patches / GameGenie",MA_MAIN_PATCHES, main_menu_handler),
  2069. mee_handler_id("Exit", MA_MAIN_EXIT, main_menu_handler),
  2070. mee_end,
  2071. };
  2072. void menu_loop(void)
  2073. {
  2074. static int sel = 0;
  2075. me_enable(e_menu_main, MA_MAIN_RESUME_GAME, PicoGameLoaded);
  2076. me_enable(e_menu_main, MA_MAIN_SAVE_STATE, PicoGameLoaded);
  2077. me_enable(e_menu_main, MA_MAIN_LOAD_STATE, PicoGameLoaded);
  2078. me_enable(e_menu_main, MA_MAIN_RESET_GAME, PicoGameLoaded);
  2079. me_enable(e_menu_main, MA_MAIN_CHANGE_CD, PicoIn.AHW & PAHW_MCD);
  2080. me_enable(e_menu_main, MA_MAIN_PATCHES, PicoPatches != NULL);
  2081. menu_enter(PicoGameLoaded);
  2082. in_set_config_int(0, IN_CFG_BLOCKING, 1);
  2083. me_loop_d(e_menu_main, &sel, NULL, menu_main_draw_status);
  2084. if (PicoGameLoaded) {
  2085. if (engineState == PGS_Menu)
  2086. engineState = PGS_Running;
  2087. /* wait until menu, ok, back is released */
  2088. while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
  2089. ;
  2090. }
  2091. in_set_config_int(0, IN_CFG_BLOCKING, 0);
  2092. plat_video_menu_leave();
  2093. }
  2094. void menu_loop_funkey(void)
  2095. {
  2096. in_set_config_int(0, IN_CFG_BLOCKING, 1);
  2097. run_menu_loop();
  2098. if (PicoGameLoaded) {
  2099. if (engineState == PGS_Menu)
  2100. engineState = PGS_Running;
  2101. /* wait until menu, ok, back is released */
  2102. /*while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
  2103. ;*/
  2104. }
  2105. in_set_config_int(0, IN_CFG_BLOCKING, 0);
  2106. plat_video_menu_leave();
  2107. }
  2108. // --------- CD tray close menu ----------
  2109. static int mh_tray_load_cd(int id, int keys)
  2110. {
  2111. const char *ret_name;
  2112. rom_fname_reload = NULL;
  2113. ret_name = menu_loop_romsel(rom_fname_loaded,
  2114. sizeof(rom_fname_loaded), rom_exts, NULL);
  2115. if (ret_name == NULL)
  2116. return 0;
  2117. rom_fname_reload = ret_name;
  2118. engineState = PGS_RestartRun;
  2119. return emu_swap_cd(ret_name);
  2120. }
  2121. static int mh_tray_nothing(int id, int keys)
  2122. {
  2123. return 1;
  2124. }
  2125. static menu_entry e_menu_tray[] =
  2126. {
  2127. mee_label ("The CD tray has opened."),
  2128. mee_label (""),
  2129. mee_label (""),
  2130. mee_handler("Load CD image", mh_tray_load_cd),
  2131. mee_handler("Insert nothing", mh_tray_nothing),
  2132. mee_end,
  2133. };
  2134. int menu_loop_tray(void)
  2135. {
  2136. int ret = 1, sel = 0;
  2137. menu_enter(PicoGameLoaded);
  2138. in_set_config_int(0, IN_CFG_BLOCKING, 1);
  2139. me_loop(e_menu_tray, &sel);
  2140. if (engineState != PGS_RestartRun) {
  2141. engineState = PGS_RestartRun;
  2142. ret = 0; /* no CD inserted */
  2143. }
  2144. while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
  2145. ;
  2146. in_set_config_int(0, IN_CFG_BLOCKING, 0);
  2147. plat_video_menu_leave();
  2148. return ret;
  2149. }
  2150. void menu_update_msg(const char *msg)
  2151. {
  2152. strncpy(menu_error_msg, msg, sizeof(menu_error_msg));
  2153. menu_error_msg[sizeof(menu_error_msg) - 1] = 0;
  2154. menu_error_time = plat_get_ticks_ms();
  2155. lprintf("msg: %s\n", menu_error_msg);
  2156. }
  2157. // ------------ util ------------
  2158. /* hidden options for config engine only */
  2159. static menu_entry e_menu_hidden[] =
  2160. {
  2161. mee_onoff("Accurate sprites", MA_OPT_ACC_SPRITES, PicoIn.opt, POPT_ACC_SPRITES),
  2162. mee_onoff("autoload savestates", MA_OPT_AUTOLOAD_SAVE, g_autostateld_opt, 1),
  2163. mee_end,
  2164. };
  2165. static menu_entry *e_menu_table[] =
  2166. {
  2167. e_menu_options,
  2168. e_menu_ui_options,
  2169. e_menu_snd_options,
  2170. e_menu_gfx_options,
  2171. e_menu_adv_options,
  2172. e_menu_cd_options,
  2173. #ifndef NO_32X
  2174. e_menu_32x_options,
  2175. #endif
  2176. #ifndef NO_SMS
  2177. e_menu_sms_options,
  2178. #endif
  2179. e_menu_keyconfig,
  2180. e_menu_hidden,
  2181. };
  2182. static menu_entry *me_list_table = NULL;
  2183. static menu_entry *me_list_i = NULL;
  2184. menu_entry *me_list_get_first(void)
  2185. {
  2186. me_list_table = me_list_i = e_menu_table[0];
  2187. return me_list_i;
  2188. }
  2189. menu_entry *me_list_get_next(void)
  2190. {
  2191. int i;
  2192. me_list_i++;
  2193. if (me_list_i->name != NULL)
  2194. return me_list_i;
  2195. for (i = 0; i < array_size(e_menu_table); i++)
  2196. if (me_list_table == e_menu_table[i])
  2197. break;
  2198. if (i + 1 < array_size(e_menu_table))
  2199. me_list_table = me_list_i = e_menu_table[i + 1];
  2200. else
  2201. me_list_table = me_list_i = NULL;
  2202. return me_list_i;
  2203. }
  2204. void menu_init(void)
  2205. {
  2206. int i;
  2207. menu_init_base();
  2208. i = 0;
  2209. #if defined(_SVP_DRC) || defined(DRC_SH2)
  2210. i = 1;
  2211. #endif
  2212. me_enable(e_menu_adv_options, MA_OPT2_DYNARECS, i);
  2213. i = me_id2offset(e_menu_gfx_options, MA_OPT_VOUT_MODE);
  2214. e_menu_gfx_options[i].data = plat_target.vout_methods;
  2215. me_enable(e_menu_gfx_options, MA_OPT_VOUT_MODE,
  2216. plat_target.vout_methods != NULL);
  2217. i = me_id2offset(e_menu_gfx_options, MA_OPT3_FILTERING);
  2218. e_menu_gfx_options[i].data = plat_target.hwfilters;
  2219. me_enable(e_menu_gfx_options, MA_OPT3_FILTERING,
  2220. plat_target.hwfilters != NULL);
  2221. me_enable(e_menu_gfx_options, MA_OPT2_GAMMA,
  2222. plat_target.gamma_set != NULL);
  2223. i = me_id2offset(e_menu_options, MA_OPT_CPU_CLOCKS);
  2224. e_menu_options[i].enabled = 0;
  2225. if (plat_target.cpu_clock_set != NULL) {
  2226. e_menu_options[i].name = "CPU clock";
  2227. e_menu_options[i].enabled = 1;
  2228. }
  2229. }