OGFILEA.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OGFILEA.CPP
  21. //Description : Game File Array
  22. #include <io.h>
  23. #include <KEY.h>
  24. #include <ODIR.h>
  25. #include <OSYS.h>
  26. #include <ODATE.h>
  27. #include <OMOUSE.h>
  28. #include <OMOUSECR.h>
  29. #include <OPOWER.h>
  30. #include <ORACERES.h>
  31. #include <OUNITRES.h>
  32. #include <OIMGRES.h>
  33. #include <OVGA.h>
  34. #include <OBOX.h>
  35. #include <OFONT.h>
  36. #include <OINFO.h>
  37. #include <OGAME.h>
  38. #include <OGAMESET.h>
  39. #include <OGFILE.h>
  40. #include <OBUTT3D.h>
  41. #include <OSLIDCUS.h>
  42. #include <OBLOB.h>
  43. //--------- Define constant ---------//
  44. enum { FILE_MENU_WIDTH = 638,
  45. FILE_MENU_HEIGHT = 398 };
  46. enum { FILE_MAIN_MENU_X1 = 80,
  47. FILE_MAIN_MENU_Y1 = 175 };
  48. enum { FILE_IN_GAME_MENU_X1 = 80,
  49. FILE_IN_GAME_MENU_Y1 = 115 };
  50. enum { BROWSE_X1 = 34,
  51. BROWSE_Y1 = 31,
  52. BROWSE_REC_WIDTH = 538,
  53. BROWSE_REC_HEIGHT = 62,
  54. BROWSE_X2 = BROWSE_X1 + BROWSE_REC_WIDTH - 1 };
  55. enum { SCROLL_X1 = 595,
  56. SCROLL_Y1 = 47,
  57. SCROLL_X2 = 609,
  58. SCROLL_Y2 = 324,
  59. SCROLL_WIDTH = SCROLL_X2 - SCROLL_X1 + 1,
  60. SCROLL_HEIGHT = SCROLL_Y2 - SCROLL_Y1 + 1 };
  61. //----- File name of the game file array --------//
  62. #define MAX_BROWSE_DISP_REC 5 // max. no. of records can be displayed in the saved game browser
  63. #define HALL_OF_FAME_FILE_NAME "HALLFAME.DAT"
  64. //------- Declare static vars & functions ----------//
  65. static char action_mode;
  66. static short browse_recno;
  67. static short browse_top_recno;
  68. static short menu_x1, menu_y1;
  69. static int sort_game_file_function( const void *a, const void *b );
  70. static int last_game_recno();
  71. static void key_search();
  72. static void disp_scroll_bar_func(SlideVBar *scroll, int);
  73. //------ Begin of function GameFileArray constuctor ------//
  74. GameFileArray::GameFileArray() : DynArray( sizeof(GameFile), 10 )
  75. {
  76. demo_format = 0;
  77. #ifdef DEMO
  78. demo_format = 1;
  79. #endif
  80. #ifdef DEMO_DESIGN
  81. demo_format = 1;
  82. #endif
  83. last_file_name[0] = NULL;
  84. has_read_hall_of_fame = 0;
  85. memset( hall_fame_array, 0, sizeof(HallFame)*HALL_FAME_NUM );
  86. }
  87. //-------- End of function GameFileArray constuctor ------//
  88. //------ Begin of function GameFileArray::init ------//
  89. void GameFileArray::init(char *extStr)
  90. {
  91. //------------- Read Hall of Fame ------------//
  92. if( !has_read_hall_of_fame ) // only read once, GameFileArray::init() is called every time the load/save game menu is brought up.
  93. {
  94. read_hall_of_fame();
  95. has_read_hall_of_fame = 1;
  96. }
  97. //-- Load all headers of all saved game files in current directory --//
  98. load_all_game_header(extStr);
  99. }
  100. //-------- End of function GameFileArray::init ------//
  101. //------ Begin of function GameFileArray::deinit ------//
  102. void GameFileArray::deinit()
  103. {
  104. }
  105. //-------- End of function GameFileArray::deinit ------//
  106. #define LSOPTION_SLOT(n) (1 << (n))
  107. #define LSOPTION_ALL_SLOTS 0x0000ffff
  108. #define LSOPTION_PAGE 0x00010000
  109. #define LSOPTION_SCROLL 0x00020000
  110. #define LSOPTION_ALL 0xffffffff
  111. //-------- Begin of function GameFileArray::menu --------//
  112. //
  113. // <int> actionMode = -2 - save screen to back buffer
  114. // -1 - restore screen to back buffer
  115. // 1 - save game
  116. // 2 - load game
  117. //
  118. // <int *> recno = if overwritting save game or load game acion
  119. // is succcessful, return the recno of GameFile
  120. //
  121. // return : <int> 1 - game loaded/saved
  122. // 0 - user cancel loading/saving
  123. // -1 - loading/saving error
  124. //
  125. int GameFileArray::menu(int actionMode, int *recno)
  126. {
  127. if( actionMode == -2 || actionMode == -1)
  128. {
  129. // copy or restore screen to back buffer
  130. int scrnX1, scrnY1, scrnX2, scrnY2;
  131. if( game.game_mode==GAME_PREGAME ) // called from the main menu, not in the game
  132. {
  133. scrnX1 = FILE_MAIN_MENU_X1;
  134. scrnY1 = FILE_MAIN_MENU_Y1;
  135. }
  136. else
  137. {
  138. scrnX1 = FILE_IN_GAME_MENU_X1;
  139. scrnY1 = FILE_IN_GAME_MENU_Y1;
  140. }
  141. scrnX2 = scrnX1 + FILE_MENU_WIDTH-1;
  142. scrnY2 = scrnY1 + FILE_MENU_HEIGHT-1;
  143. mouse.hide_area( scrnX1, scrnY1, scrnX2, scrnY2);
  144. if( actionMode == -2 )
  145. // save to back buffer
  146. IMGcopy(vga_back.buf_ptr(), vga_back.buf_pitch(),
  147. vga_front.buf_ptr(), vga_front.buf_pitch(),
  148. scrnX1, scrnY1, scrnX2, scrnY2);
  149. else
  150. // restore from back buffer
  151. IMGcopy(vga_front.buf_ptr(), vga_front.buf_pitch(),
  152. vga_back.buf_ptr(), vga_back.buf_pitch(),
  153. scrnX1, scrnY1, scrnX2, scrnY2);
  154. mouse.show_area();
  155. return 1;
  156. }
  157. // #### begin Gilbert 25/9 ########//
  158. //#ifdef DEMO // No game saving in demo version
  159. // box.msg( "Sorry, you cannot load/save game in the demo version." );
  160. // return -1;
  161. //#endif
  162. // #### end Gilbert 25/9 ########//
  163. action_mode = actionMode;
  164. if( action_mode==2 && size()==0 )
  165. {
  166. box.msg( "You haven't saved any games yet." );
  167. return 0;
  168. }
  169. // load race icon
  170. char deinitGameSet=0;
  171. char deinitUnitRes=0;
  172. char deinitRaceRes=0;
  173. if( !game_set.set_opened_flag )
  174. {
  175. game_set.open_set(1);
  176. deinitGameSet = 1;
  177. }
  178. if( !unit_res.init_flag )
  179. {
  180. unit_res.init();
  181. deinitUnitRes = 1;
  182. }
  183. if( !race_res.init_flag )
  184. {
  185. race_res.init();
  186. deinitRaceRes = 1;
  187. }
  188. //-------------------------------------//
  189. if( game.game_mode==GAME_PREGAME ) // called from the main menu, not in the game
  190. {
  191. menu_x1 = FILE_MAIN_MENU_X1;
  192. menu_y1 = FILE_MAIN_MENU_Y1;
  193. }
  194. else
  195. {
  196. menu_x1 = FILE_IN_GAME_MENU_X1;
  197. menu_y1 = FILE_IN_GAME_MENU_Y1;
  198. }
  199. int x=menu_x1, y=menu_y1+17;
  200. // vga_back.adjust_brightness( x, y, x+menu_x1-1, y+menu_y1-1, -6 );
  201. vga.blt_buf( x, y, x+menu_x1-1, y+menu_y1-1, 0 );
  202. mouse_cursor.set_icon(CURSOR_NORMAL);
  203. power.win_opened = 1;
  204. int minRecno = action_mode == 1 ? 0 : 1;
  205. //------ set current record no. -------//
  206. for( int i=1 ; i<=size() ; i++ )
  207. {
  208. if( strcmp(last_file_name, game_file_array[i]->file_name)==0 )
  209. {
  210. browse_recno = i;
  211. break;
  212. }
  213. }
  214. //---------------------------------//
  215. browse_top_recno = minRecno;
  216. // in save game mode, browse_recno = 0 means selecting empty slot
  217. // in load game mode, browse_recno = 0 means nonthing is selected
  218. // browse_top_recno = browse_recno ? browse_recno : minRecno;
  219. //--------------------------------------//
  220. Button3D scrollUp, scrollDown, saveButton, saveNewButton, delButton, cancelButton;
  221. int retFlag = 0;
  222. int refreshFlag = LSOPTION_ALL;
  223. //int scrollButtonY1 = menu_y1+SCROLL_Y1, scrollButtonY2 = menu_y1+SCROLL_Y2;
  224. //int dragingScrollBar = 0;
  225. //int dragScrollYDiff; // when draging begins, mouse.cur_y - scrollButtonY1
  226. SlideVBar scrollBar;
  227. scrollBar.init_scroll(menu_x1+SCROLL_X1, menu_y1+SCROLL_Y1, menu_x1+SCROLL_X2, menu_y1+SCROLL_Y2,
  228. MAX_BROWSE_DISP_REC, disp_scroll_bar_func);
  229. scrollBar.set(minRecno, size(), browse_top_recno);
  230. // try to centre the selected record on the browser
  231. //browse_top_recno = browse_recno - MAX_BROWSE_DISP_REC /2;
  232. //if( browse_top_recno > size()-MAX_BROWSE_DISP_REC+1)
  233. // browse_top_recno = size()-MAX_BROWSE_DISP_REC+1;
  234. //if( browse_top_recno < minRecno )
  235. // browse_top_recno = minRecno;
  236. browse_top_recno = scrollBar.set_view_recno(browse_recno - MAX_BROWSE_DISP_REC /2);
  237. Blob browseArea[MAX_BROWSE_DISP_REC];
  238. Blob scrollArea;
  239. while(1)
  240. {
  241. //---------- yield --------//
  242. sys.yield();
  243. mouse.get_event();
  244. // --------- display ----------//
  245. if( refreshFlag )
  246. {
  247. if( refreshFlag & LSOPTION_PAGE )
  248. {
  249. mouse.hide_area(menu_x1, menu_y1, menu_x1+FILE_MENU_WIDTH, menu_y1+FILE_MENU_HEIGHT);
  250. image_interface.put_front( menu_x1, menu_y1, actionMode==1 ? (char*)"SAVEGAME" : (char*)"LOADGAME" );
  251. scrollUp.paint(menu_x1+SCROLL_X1+1,menu_y1+SCROLL_Y1-17, "SV-UP-U", "SV-UP-D");
  252. scrollDown.paint(menu_x1+SCROLL_X1+1,menu_y1+SCROLL_Y2+1, "SV-DW-U", "SV-DW-D");
  253. if( action_mode == 1)
  254. {
  255. saveButton.paint(menu_x1+34, menu_y1+354, "SAVE", "CANCEL1D");
  256. saveNewButton.paint(menu_x1+147, menu_y1+354, "SAVE-NEW", "CANCEL1D");
  257. delButton.paint(menu_x1+260, menu_y1+354, "DELETE", "CANCEL1D");
  258. }
  259. else if( action_mode == 2)
  260. {
  261. saveButton.paint(menu_x1+34, menu_y1+354, "LOAD", "CANCEL1D");
  262. }
  263. cancelButton.paint(menu_x1+473, menu_y1+354, "CANCEL1", "CANCEL1D");
  264. // capture browseArea, scrollArea
  265. for( int j = 0; j < MAX_BROWSE_DISP_REC; ++j)
  266. {
  267. browseArea[j].resize(2*sizeof(short)+BROWSE_REC_WIDTH*BROWSE_REC_HEIGHT);
  268. vga_front.read_bitmap(
  269. menu_x1+BROWSE_X1, menu_y1+BROWSE_Y1+j*BROWSE_REC_HEIGHT,
  270. menu_x1+BROWSE_X2, menu_y1+BROWSE_Y1+j*BROWSE_REC_HEIGHT+BROWSE_REC_HEIGHT-1,
  271. browseArea[j].ptr);
  272. }
  273. scrollArea.resize(2*sizeof(short)+SCROLL_WIDTH*SCROLL_HEIGHT);
  274. vga_front.read_bitmap( menu_x1+SCROLL_X1, menu_y1+SCROLL_Y1,
  275. menu_x1+SCROLL_X2, menu_y1+SCROLL_Y2, scrollArea.ptr);
  276. mouse.show_area();
  277. }
  278. if( scrollBar.max_recno != size() )
  279. {
  280. scrollBar.set_max_recno(size());
  281. if( scrollBar.view_recno > scrollBar.max_view_recno() )
  282. {
  283. scrollBar.view_recno = scrollBar.max_view_recno();
  284. }
  285. refreshFlag |= LSOPTION_SCROLL;
  286. }
  287. if( refreshFlag & LSOPTION_SCROLL )
  288. {
  289. vga_front.put_bitmap( menu_x1+SCROLL_X1, menu_y1+SCROLL_Y1,
  290. scrollArea.ptr);
  291. scrollBar.paint();
  292. }
  293. if( refreshFlag & LSOPTION_ALL_SLOTS )
  294. {
  295. for(int slot = 0; slot < MAX_BROWSE_DISP_REC; ++slot)
  296. {
  297. int rec = slot + scrollBar.view_recno;
  298. if( refreshFlag & LSOPTION_SLOT(slot) )
  299. {
  300. int browseSlotX1 = menu_x1+BROWSE_X1;
  301. int browseSlotY1 = menu_y1+BROWSE_Y1+slot*BROWSE_REC_HEIGHT;
  302. int browseSlotX2 = menu_x1+BROWSE_X2;
  303. int browseSlotY2 = menu_y1+BROWSE_Y1+(slot+1)*BROWSE_REC_HEIGHT-1;
  304. mouse.hide_area(browseSlotX1, browseSlotY1,
  305. browseSlotX2, browseSlotY2);
  306. vga_front.put_bitmap( browseSlotX1, browseSlotY1,
  307. browseArea[rec%MAX_BROWSE_DISP_REC].ptr);
  308. if( rec == 0 )
  309. {
  310. err_when( action_mode!=1 );
  311. font_bible.center_put( browseSlotX1, browseSlotY1,
  312. browseSlotX2, browseSlotY2, "Empty Game Slot" );
  313. }
  314. else if( rec <= size() )
  315. {
  316. game_file_array[rec]->disp_info(browseSlotX1, browseSlotY1);
  317. }
  318. if( rec == browse_recno )
  319. {
  320. vga_front.adjust_brightness( browseSlotX1, browseSlotY1,
  321. browseSlotX2, browseSlotY2, -2);
  322. vga_front.put_bitmap_trans_decompress(browseSlotX1, browseSlotY1,
  323. image_button.read("LS-DWN"));
  324. }
  325. mouse.show_area();
  326. }
  327. }
  328. // disp_browse();
  329. }
  330. refreshFlag = 0;
  331. }
  332. sys.blt_virtual_buf();
  333. if( scrollBar.detect() == 1 )
  334. {
  335. browse_top_recno = scrollBar.view_recno;
  336. refreshFlag |= LSOPTION_SCROLL | LSOPTION_ALL_SLOTS;
  337. }
  338. else if( scrollUp.detect() )
  339. {
  340. // click on scroll up
  341. int oldValue = scrollBar.view_recno;
  342. if( oldValue != scrollBar.set_view_recno(oldValue-1) )
  343. refreshFlag |= LSOPTION_SCROLL | LSOPTION_ALL_SLOTS;
  344. browse_top_recno = scrollBar.view_recno;
  345. }
  346. else if( scrollDown.detect() )
  347. {
  348. // click on scroll down
  349. // click on scroll up
  350. int oldValue = scrollBar.view_recno;
  351. if( oldValue != scrollBar.set_view_recno(oldValue+1) )
  352. refreshFlag |= LSOPTION_SCROLL | LSOPTION_ALL_SLOTS;
  353. browse_top_recno = scrollBar.view_recno;
  354. }
  355. else if( mouse.double_click( menu_x1+BROWSE_X1, menu_y1+BROWSE_Y1,
  356. menu_x1+BROWSE_X1+BROWSE_REC_WIDTH-1,
  357. menu_y1+BROWSE_Y1+ BROWSE_REC_HEIGHT*MAX_BROWSE_DISP_REC -1) )
  358. {
  359. // double click on game slot
  360. int oldValue = browse_recno;
  361. int newValue = scrollBar.view_recno + (mouse.click_y(0) - BROWSE_Y1 - menu_y1) / BROWSE_REC_HEIGHT;
  362. if( newValue <= size())
  363. {
  364. // ######## begin Gilbert 31/10 ########//
  365. if( newValue == oldValue )
  366. {
  367. browse_recno = newValue;
  368. refreshFlag |= LSOPTION_SLOT(newValue-scrollBar.view_recno);
  369. if( oldValue-scrollBar.view_recno >= 0 && oldValue-scrollBar.view_recno < MAX_BROWSE_DISP_REC )
  370. refreshFlag |= LSOPTION_SLOT(oldValue-scrollBar.view_recno);
  371. if( recno )
  372. *recno = browse_recno;
  373. retFlag = process_action(0);
  374. // if( retFlag < 0 )
  375. // box.msg("Error");
  376. break;
  377. }
  378. // ######## end Gilbert 31/10 ########//
  379. }
  380. }
  381. else if( mouse.single_click( menu_x1+BROWSE_X1, menu_y1+BROWSE_Y1,
  382. menu_x1+BROWSE_X1+BROWSE_REC_WIDTH-1,
  383. menu_y1+BROWSE_Y1+ BROWSE_REC_HEIGHT*MAX_BROWSE_DISP_REC -1) )
  384. {
  385. // click on game slot
  386. int oldValue = browse_recno;
  387. int newValue = scrollBar.view_recno + (mouse.click_y(0) - BROWSE_Y1 - menu_y1) / BROWSE_REC_HEIGHT;
  388. if( newValue <= size())
  389. {
  390. // ##### begin Gilbert 31/10 #######//
  391. //if( oldValue == browse_recno )
  392. //{
  393. // browse_recno = newValue;
  394. // refreshFlag |= LSOPTION_SLOT(oldValue-scrollBar.view_recno)
  395. // | LSOPTION_SLOT(newValue-scrollBar.view_recno);
  396. //}
  397. if( newValue != oldValue )
  398. {
  399. browse_recno = newValue;
  400. refreshFlag |= LSOPTION_SLOT(newValue-scrollBar.view_recno);
  401. if( oldValue-scrollBar.view_recno >= 0 && oldValue-scrollBar.view_recno < MAX_BROWSE_DISP_REC )
  402. refreshFlag |= LSOPTION_SLOT(oldValue-scrollBar.view_recno);
  403. }
  404. // ##### end Gilbert 31/10 #######//
  405. }
  406. }
  407. else if( cancelButton.detect(KEY_ESC) || mouse.any_click(RIGHT_BUTTON) > 0) // also when ESC key is pressed or right button
  408. {
  409. // cancel button or escape key
  410. refreshFlag = LSOPTION_ALL;
  411. retFlag = 0;
  412. break; // break while(1)
  413. }
  414. else if( (action_mode == 1 || (action_mode == 2 && browse_recno))
  415. && saveButton.detect() )
  416. {
  417. // save / load button
  418. refreshFlag = LSOPTION_ALL;
  419. if( recno )
  420. *recno = browse_recno;
  421. retFlag = process_action(0);
  422. // ##### begin Gilbert 15/10 #####//
  423. if( retFlag != 0 )
  424. {
  425. // if( retFlag < 0 )
  426. // box.msg("Error");
  427. break;
  428. }
  429. // ##### end Gilbert 15/10 #####//
  430. }
  431. else if( action_mode == 1 && saveNewButton.detect() )
  432. {
  433. // save new button
  434. refreshFlag = LSOPTION_ALL;
  435. retFlag = process_action(1);
  436. // if( retFlag < 0 )
  437. // box.msg("Error");
  438. break;
  439. }
  440. else if( action_mode == 1 && browse_recno && delButton.detect() )
  441. {
  442. // delete save game button
  443. if( browse_recno != 0 ) // cannot del save game slot
  444. {
  445. del_game();
  446. if( browse_recno > size() )
  447. {
  448. browse_recno = size();
  449. }
  450. if( browse_top_recno > size()-MAX_BROWSE_DISP_REC+1)
  451. browse_top_recno = size()-MAX_BROWSE_DISP_REC+1;
  452. if( browse_top_recno < minRecno )
  453. browse_top_recno = minRecno;
  454. scrollBar.set_view_recno(browse_top_recno);
  455. refreshFlag |= LSOPTION_ALL_SLOTS | LSOPTION_SCROLL;
  456. }
  457. else
  458. {
  459. box.msg("Cannot delete this slot");
  460. }
  461. refreshFlag = LSOPTION_ALL;
  462. }
  463. }
  464. power.win_opened = 0;
  465. if( retFlag <= 0 )
  466. {
  467. // if load game is successful, no need to deinit resource
  468. if( deinitGameSet )
  469. game_set.close_set();
  470. if( deinitUnitRes )
  471. unit_res.deinit();
  472. if( deinitRaceRes )
  473. race_res.deinit();
  474. }
  475. mouse.reset_click();
  476. return retFlag;
  477. }
  478. //---------- End of function GameFileArray::menu --------//
  479. //-------- Begin of function GameFileArray::disp_browse --------//
  480. //
  481. // Display saved game info on the browser.
  482. //
  483. void GameFileArray::disp_browse()
  484. {
  485. int lastRec = min(browse_top_recno+MAX_BROWSE_DISP_REC-1, size());
  486. int x = menu_x1 + BROWSE_X1;
  487. int y = menu_y1 + BROWSE_Y1;
  488. for( int i=browse_top_recno ; i<=lastRec ; i++, y+=BROWSE_REC_HEIGHT )
  489. {
  490. if( i==0 )
  491. {
  492. err_when( action_mode!=1 );
  493. font_bible.center_put( x, y, x+BROWSE_REC_WIDTH-1, y+BROWSE_REC_HEIGHT-1, "Empty Game Slot" );
  494. }
  495. else
  496. {
  497. game_file_array[i]->disp_info(x, y);
  498. }
  499. if( i == browse_recno )
  500. {
  501. vga_front.adjust_brightness(x,y,x+BROWSE_REC_WIDTH-1,y+BROWSE_REC_HEIGHT-1,-2);
  502. vga_front.put_bitmap_trans_decompress( x, y, image_button.read("LS-DWN"));
  503. }
  504. }
  505. }
  506. //--------- End of function GameFileArray::disp_browse --------//
  507. //-------- Begin of function GameFile::disp_info --------//
  508. //
  509. void GameFile::disp_info(int x, int y)
  510. {
  511. vga_front.put_bitmap(x+10, y+10, unit_res[ race_res[race_id]->basic_unit_id ]->king_icon_ptr);
  512. x+=60;
  513. //------ display player color -----//
  514. nation_array.disp_nation_color( x+1, y+13, nation_color );
  515. //-------- display king name ------//
  516. String str;
  517. str = translate.process("King ");
  518. str += player_name;
  519. font_bible.put( x+18, y+8, str );
  520. //------- display game date --------//
  521. str = translate.process("Game Date: ");
  522. str += date.date_str(game_date);
  523. font_bible.put( x, y+30, str );
  524. //---------------------------------//
  525. str = translate.process("File Name: ");
  526. str += file_name;
  527. #if(defined(FRENCH))
  528. font_small.put( x+320, y+16, str );
  529. #elif(defined(GERMAN))
  530. font_small.put( x+320, y+16, str );
  531. #else
  532. font_small.put( x+335, y+16, str );
  533. #endif
  534. SYSTEMTIME sysTime;
  535. FILETIME localFileTime;
  536. FileTimeToLocalFileTime( &file_date, &localFileTime );
  537. FileTimeToSystemTime( &localFileTime, &sysTime );
  538. str = translate.process("File Date: ");
  539. str += date.date_str(date.julian(sysTime.wYear, sysTime.wMonth,sysTime.wDay), 1);
  540. str += " ";
  541. str += date.time_str( sysTime.wHour * 100 + sysTime.wMinute );
  542. #if(defined(FRENCH))
  543. font_small.put( x+318, y+34, str );
  544. #elif(defined(GERMAN))
  545. font_small.put( x+320, y+34, str );
  546. #else
  547. font_small.put( x+335, y+34, str );
  548. #endif
  549. }
  550. //--------- End of function GameFile::disp_info --------//
  551. //------- Begin of function GameFileArray::process_action ------//
  552. //
  553. // [int] saveNew - save on a new game file
  554. // (default : 0)
  555. //
  556. // return : <int> 1 - process ok
  557. // 0 - process cancelled
  558. // -1 - save/load failed
  559. //
  560. int GameFileArray::process_action(int saveNew)
  561. {
  562. //------------ save game --------------//
  563. if( action_mode == 1 )
  564. {
  565. if( saveNew || browse_recno==0 ) // save on empty slot
  566. {
  567. save_new_game();
  568. }
  569. else // save on existing slot
  570. {
  571. if( !box.ask( "It will overwrite the existing saved game, proceed ?" ) )
  572. return 0;
  573. GameFile* gameFile = game_file_array[browse_recno];
  574. if( !gameFile->save_game())
  575. return -1;
  576. strcpy( last_file_name, gameFile->file_name );
  577. }
  578. return 1;
  579. }
  580. //----------- load game -------------//
  581. else
  582. {
  583. GameFile* gameFile = game_file_array[browse_recno];
  584. int rc = gameFile->load_game();
  585. if( rc > 0 )
  586. strcpy( last_file_name, gameFile->file_name );
  587. return rc;
  588. }
  589. return 0;
  590. }
  591. //--------- End of function GameFileArray::process_action ------//
  592. //-------- Begin of function GameFileArray::save_new_game -----//
  593. //
  594. // Save current game to a new saved game file immediately without
  595. // prompting menu.
  596. //
  597. // Called by GameFileArray::process_action() and error handler.
  598. //
  599. // [char*] fileName - file name of the saved game
  600. //
  601. void GameFileArray::save_new_game(char* fileName)
  602. {
  603. GameFile gameFile;
  604. GameFile* gameFilePtr;
  605. int addFlag=1;
  606. int gameFileRecno;
  607. memset( &gameFile, 0, sizeof(GameFile) );
  608. if( fileName )
  609. {
  610. //----- check for overwriting an existing file ----//
  611. for( gameFileRecno=1 ; gameFileRecno<=game_file_array.size() ; gameFileRecno++ )
  612. {
  613. gameFilePtr = game_file_array[gameFileRecno];
  614. if( strcmp(gameFilePtr->file_name, fileName)==0 ) // if this file name already exist
  615. {
  616. addFlag=0;
  617. break;
  618. }
  619. }
  620. strcpy( gameFile.file_name, fileName );
  621. }
  622. else
  623. {
  624. gameFile.set_file_name(); // give it a new game_file_name based on current group name
  625. }
  626. //----------- save game now ------------//
  627. if( gameFile.save_game(fileName) )
  628. {
  629. strcpy( last_file_name, gameFile.file_name );
  630. if( addFlag )
  631. {
  632. linkin(&gameFile);
  633. quick_sort( sort_game_file_function );
  634. }
  635. else
  636. {
  637. game_file_array.update(&gameFile, gameFileRecno);
  638. }
  639. }
  640. }
  641. //-------- End of function GameFileArray::save_new_game -------//
  642. //------- Begin of function GameFileArray::del_game ------//
  643. void GameFileArray::del_game()
  644. {
  645. int recNo = browse_recno;
  646. if( !box.ask( "This saved game will be deleted, proceed ?" ) )
  647. return;
  648. //---------------------------------------------------//
  649. unlink(game_file_array[recNo]->file_name); // unlink() is a C standard function in io.h, for delete file
  650. go(recNo);
  651. linkout();
  652. go(recNo-1); // skip back one record
  653. }
  654. //--------- End of function GameFileArray::del_game ------//
  655. //------- Begin of function GameFileArray::write_hall_of_fame ------//
  656. //
  657. int GameFileArray::write_hall_of_fame()
  658. {
  659. int rc;
  660. File file;
  661. rc = file.file_create( HALL_OF_FAME_FILE_NAME, 0, 1 ); // 0=don't handle error itself
  662. if( !rc )
  663. return 0;
  664. // 1=allow the writing size and the read size to be different
  665. //--------- Write Hall of Fame ----------//
  666. if( rc )
  667. rc = file.file_write( hall_fame_array, sizeof(HallFame) * HALL_FAME_NUM );
  668. //------ write last saved game file name ------//
  669. if( rc )
  670. rc = file.file_write( last_file_name, MAX_PATH+1 );
  671. file.file_close();
  672. return rc;
  673. }
  674. //--------- End of function GameFileArray::write_hall_of_fame ------//
  675. //------- Begin of function GameFileArray::read_hall_of_fame ------//
  676. //
  677. int GameFileArray::read_hall_of_fame()
  678. {
  679. if( !m.is_file_exist(HALL_OF_FAME_FILE_NAME) )
  680. return 0;
  681. int rc;
  682. File file;
  683. rc = file.file_open( HALL_OF_FAME_FILE_NAME, 0, 1 ); // 0=don't handle error itself
  684. // 1=allow the writing size and the read size to be different
  685. if( !rc )
  686. return 0;
  687. // 1=allow the writing size and the read size to be different
  688. //--------- Read Hall of Fame ----------//
  689. if( rc )
  690. rc = file.file_read( hall_fame_array, sizeof(HallFame) * HALL_FAME_NUM );
  691. //------ read last saved game file name ------//
  692. if( rc )
  693. rc = file.file_read( last_file_name, MAX_PATH+1);
  694. file.file_close();
  695. return rc;
  696. }
  697. //--------- End of function GameFileArray::read_hall_of_fame ------//
  698. //-------- Begin of function GameFileArray::load_all_game_header --------//
  699. //
  700. // Load all headers of all saved game files in current directory.
  701. //
  702. void GameFileArray::load_all_game_header(char *extStr)
  703. {
  704. int i;
  705. Directory gameDir;
  706. GameFile gameFile;
  707. File file;
  708. gameDir.read( extStr, 1 ); // 1-Sort file names
  709. //-------- read in the headers of all game sets -------//
  710. zap();
  711. for( i=1 ; i<=gameDir.size() ; i++ )
  712. {
  713. if( file.file_open( gameDir[i]->name, 1, 1 ) // last 1=allow varying read & write size
  714. && file.file_read(&gameFile, sizeof(GameFile))
  715. && gameFile.validate_header() )
  716. {
  717. strcpy( gameFile.file_name, gameDir[i]->name ); // in case that the name may be different
  718. gameFile.file_date = gameDir[i]->time;
  719. linkin(&gameFile);
  720. }
  721. file.file_close();
  722. }
  723. }
  724. //------ End of function GameFileArray::load_all_game_header --------//
  725. //------ Begin of function sort_game_file_function ------//
  726. //
  727. static int sort_game_file_function( const void *a, const void *b )
  728. {
  729. return strcmp( ((GameFile*)a)->file_name, ((GameFile*)b)->file_name );
  730. }
  731. //------- End of function sort_game_file_function ------//
  732. //------ Begin of function last_game_recno ------//
  733. //
  734. static int last_game_recno()
  735. {
  736. int i;
  737. for( i=game_file_array.size() ; i>0 ; i-- )
  738. {
  739. if( strcmp(game_file_array[i]->file_name, game_file_array.last_file_name)==0 )
  740. return i;
  741. }
  742. return 0; // if none of them match, return 1 as the first record
  743. }
  744. //------- End of function last_game_recno ------//
  745. //------- Begin of function GameFileArray::operator[] -----//
  746. GameFile* GameFileArray::operator[](int recNo)
  747. {
  748. GameFile* gameFile = (GameFile*) get(recNo);
  749. return gameFile;
  750. }
  751. //--------- End of function GameFileArray::operator[] ----//
  752. //------- Begin of static function key_search --------//
  753. static void key_search()
  754. {
  755. int i;
  756. int searchKey = m.upper(mouse.key_code);
  757. if( searchKey < '0' || searchKey > 'Z' )
  758. return;
  759. for( i=1 ; i<=game_file_array.size() ; i++ )
  760. {
  761. if( m.upper(game_file_array[i]->file_name[0]) >= searchKey )
  762. {
  763. browse_recno = i+(action_mode==1);
  764. return;
  765. }
  766. }
  767. }
  768. //------- End of static function key_search --------//
  769. //------- Begin of static function disp_scroll_bar_func --------//
  770. static void disp_scroll_bar_func(SlideVBar *scroll, int)
  771. {
  772. short rectTop = scroll->rect_top();
  773. short rectBottom = scroll->rect_bottom();
  774. vga_front.bar( scroll->scrn_x1, rectTop, scroll->scrn_x2, rectBottom, VGA_YELLOW+1);
  775. if( rectBottom - rectTop > 6 )
  776. {
  777. vga_front.d3_panel_up(scroll->scrn_x1, rectTop, scroll->scrn_x2, rectBottom,2,0);
  778. }
  779. }
  780. //------- End of static function disp_scroll_bar_func --------//