1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17 #include "cheat.h"
18
19 #if !defined(ALLEGRO)
20
file_size(char * file_name)21 long file_size (char* file_name)
22 {
23 FILE* f = fopen(file_name,"rb");
24 long position;
25 if (f == NULL)
26 return 0;
27 fseek(f,0,SEEK_END);
28 position = ftell(f);
29 fclose(f);
30 return position;
31 }
32 #endif
33
fputw(UInt16 value,FILE * F)34 inline void fputw (UInt16 value, FILE* F)
35 {
36 fputc((int)(value & 0xFF), F);
37 fputc((int)(value >> 8), F);
38 }
39
fgetw(FILE * F)40 inline UInt16 fgetw (FILE* F)
41 {
42 return (UInt16)(fgetc(F) + (fgetc(F) << 8));
43 }
44
45 freezed_value list_to_freeze[MAX_FREEZED_VALUE];
46 // List of all the value to freeze
47
48 unsigned char current_freezed_values;
49 // Current number of values to freeze
50
51 static UChar
bigindextobank(UInt32 index)52 bigindextobank (UInt32 index)
53 {
54 if (index<0x8000)
55 return 0;
56 if (index<0x18000)
57 return ((index-0x8000) >> 13) + 1;
58 if (index<0x48000)
59 return ((index-0x18000) >> 13) + 10;
60 // FIXME: what to return here?
61 }
62
63 UInt16
bigtosmallindex(UInt32 index)64 bigtosmallindex(UInt32 index)
65 {
66 if (index<0x8000)
67 return (UInt16)index;
68 return (UInt16)(index & 0x1FFF);
69 }
70
71 UChar
readindexedram(UInt32 index)72 readindexedram (UInt32 index)
73 {
74 if (index<0x8000)
75 return RAM[index];
76 if (index<0x18000)
77 return cd_extra_mem[index-0x8000];
78 if (index<0x48000)
79 return cd_extra_super_mem[index-0x18000];
80
81 return 0;
82
83 }
84
85 void
writeindexedram(UInt32 index,UChar value)86 writeindexedram (UInt32 index, UChar value)
87 {
88 if (index<0x8000)
89 RAM[index] = value;
90 else
91 if (index<0x18000)
92 cd_extra_mem[index-0x8000] = value;
93 else
94 if (index<0x48000)
95 cd_extra_super_mem[index-0x18000] = value;
96
97 }
98
99
100 /*****************************************************************************
101
102 Function: pokebyte
103
104 Description: set a value in the ram to a specified value
105 Parameters: none
106 Return: 0
107
108 *****************************************************************************/
109
110 char
pokebyte()111 pokebyte ()
112 {
113 char tmp_str[10], new_val;
114 unsigned char index = 0;
115 unsigned addr;
116
117 while (osd_keypressed())
118 /*@-retvalother*/
119 osd_readkey (); // Flushing keys
120 /*@=retvalother*/
121 while ((index < 10) && ((tmp_str[index++] = (char)(osd_readkey () & 0xFF)) != 13));
122 tmp_str[index - 1] = 0;
123 addr = (unsigned) atoi (tmp_str);
124
125 while (osd_keypressed ())
126 /*@-retvalother*/
127 osd_readkey (); // Flushing keys
128 /*@=retvalother*/
129 index = 0;
130 while ((index < 10) && ((tmp_str[index++] = (char)(osd_readkey () & 0xFF)) != 13));
131 tmp_str[index - 1] = 0;
132 new_val = atoi (tmp_str);
133
134 writeindexedram(addr, (UChar)new_val);
135
136 {
137 char *tmp_buf = (char *) malloc (100);
138 snprintf (tmp_buf, 100, MESSAGE[language][byte_set], addr, new_val);
139 osd_gfx_set_message (tmp_buf);
140 message_delay = 180;
141 free(tmp_buf);
142 }
143
144
145 return 0;
146 }
147
148 /*****************************************************************************
149
150 Function: searchbyte
151
152 Description: search the ram for a particuliar value
153 Parameters: none
154 Return: 1 on error
155
156 *****************************************************************************/
157 char
searchbyte()158 searchbyte ()
159 {
160 UInt32 MAX_INDEX;
161 char tmp_str[10];
162 UInt32 index = 0, tmp_word, last_index;
163 UChar bank;
164 char data_filename[80], old_filename[80];
165 char first_research = 1;
166 FILE *D, *O;
167 SInt16 to_search;
168
169 MAX_INDEX = (UInt16)( CD_emulation ? 0x48000 : 0x8000);
170
171 while (osd_keypressed ())
172 /*@-retvalother*/
173 osd_readkey (); // Flushing keys
174 /*@=retvalother*/
175
176 while ((index < 10) && ((tmp_str[index++] = (char)(osd_readkey () & 0xFF)) != 13));
177 tmp_str[index - 1] = 0;
178
179 to_search = atoi (tmp_str);
180
181 strcpy (old_filename, short_cart_name);
182 strcpy (data_filename, short_cart_name);
183 strcat (data_filename, "FP1");
184
185 O = fopen ((char *) strcat (old_filename, "FP0"), "rb");
186 if (O == NULL)
187 first_research = 1;
188 /*
189 if (exists ((char *) strcat (old_filename, "FP0")))
190 {
191 if (!(O = fopen (old_filename, "rb")))
192 return 1;
193 first_research = 0;
194 }
195 */
196 if (!(D = fopen (data_filename, "wb")))
197 return 1;
198 tmp_str[9] = 0;
199
200
201 if ((tmp_str[0] != '-')
202 &&(tmp_str[0] != '+'))
203 { /* non relative research */
204
205 for (index = 0; index < MAX_INDEX; index++)
206 {
207 if (readindexedram(index) == (UChar)to_search)
208 {
209
210 if (first_research)
211 {
212 fputc (readindexedram(index), D);
213 fputc (bigindextobank(index), D);
214 fputw (bigtosmallindex(index), D);
215 }
216 else
217 {
218 while (!(feof (O)))
219 {
220 fgetc (O);
221 bank = (UChar)fgetc(O);
222 tmp_word = fgetw(O);
223
224 if ((bank > bigindextobank(index))
225 ||
226 ((bank == bigindextobank(index)) && (tmp_word >= bigtosmallindex(index))))
227 {
228 fseek (O, -4, SEEK_CUR);
229 break;
230 }
231 }
232
233 if ((bigtosmallindex(index) == (UInt16)tmp_word) &&
234 (bigindextobank(index) == bank))
235 {
236 fputc (to_search, D);
237 fputc (bigindextobank(index), D);
238 fputw (bigtosmallindex(index), D);
239 last_index = index;
240 }
241 } //search for old occurences
242 }
243 }
244 }
245 else
246 { /* relative research */
247 for (index = 0; index < MAX_INDEX; index++)
248 {
249
250 if (first_research)
251 {
252 fputc (readindexedram(index), D);
253 fputc (bigindextobank(index), D);
254 fputw (bigtosmallindex(index), D);
255 }
256 else
257 {
258 UChar old_value;
259
260 {
261 while (!(feof (O)))
262 {
263 fgetc (O);
264 bank = (UChar)fgetc(O);
265 tmp_word = fgetw(O);
266
267 if ((bank > bigindextobank(index))
268 ||
269 ((bank == bigindextobank(index)) && (tmp_word >= bigtosmallindex(index))))
270 {
271 fseek (O, -4, SEEK_CUR);
272 break;
273 }
274 }
275
276 if ((bigindextobank(index) == bank) &&
277 (bigtosmallindex(index) == (UInt16)tmp_word) &&
278 (readindexedram(index) == old_value + to_search))
279 {
280 fputc (readindexedram(index), D);
281 fputc (bigindextobank(index), D);
282 fputw (bigtosmallindex(index), D);
283 last_index = index;
284 }
285 } //search for old occurences
286 }
287 }
288
289 }
290
291 if (!first_research)
292 fclose (O);
293 fclose (D);
294
295 rename (data_filename, old_filename);
296 if (!file_size (old_filename))
297 {
298 osd_gfx_set_message (MESSAGE[language][search_failed]);
299 message_delay = 180;
300 unlink (old_filename);
301 return 1;
302 }
303
304 if (file_size (old_filename) == 4)
305 {
306 char *tmp_buf = (char *) malloc (100);
307 snprintf (tmp_buf, 100, MESSAGE[language][found_at], last_index);
308 osd_gfx_set_message (tmp_buf);
309 message_delay = 60 * 5;
310 free(tmp_buf);
311 }
312 else
313 {
314 osd_gfx_set_message (MESSAGE[language][still_need_search]);
315 message_delay = 60 * 3;
316 }
317
318 while (osd_keypressed ())
319 /*@-retvalother*/
320 osd_readkey (); // Flushing keys
321 /*@=retvalother*/
322
323 return 0;
324 }
325
326 /*****************************************************************************
327
328 Function: loadgame
329
330 Description: load a saved game using allegro packing functions
331 Parameters: none
332 Return: 1 on error, else 0
333
334 *****************************************************************************/
335 int
loadgame()336 loadgame ()
337 {
338
339 #ifndef KERNEL_DS
340
341 /* TODO: add support for plain file when allegro isn't present */
342
343 #ifdef ALLEGRO
344 PACKFILE *fp;
345 UInt32 tmp = 0;
346 char *tmp_buf = (char *) alloca (100);
347 UChar version = 0;
348
349 if (!exists (sav_path))
350 return 1;
351
352 if (!(fp = pack_fopen (sav_path, F_READ_PACKED)))
353 return 1;
354
355 pack_fread (tmp_buf, 18, fp);
356 if (!strncmp (tmp_buf, "Hu-Go! state file", 17))
357 {
358 version = tmp_buf[17];
359 }
360 else
361 {
362 version = 0;
363 pack_fclose (fp);
364 if (!(fp = pack_fopen (sav_path, F_READ_PACKED)))
365 return 1;
366
367 }
368
369 pack_fread (RAM, 0x8000, fp);
370 pack_fread (VRAM, VRAMSIZE, fp);
371 pack_fread (SPRAM, 64 * 4 * sizeof (short), fp);
372 pack_fread (Pal, 512, fp);
373 pack_fread (&scanline, sizeof (int), fp);
374
375 if (version == 0x11)
376 pack_fread (&io, sizeof (IO), fp);
377 else
378 pack_fread (&io, 1420, fp);
379
380 pack_fread (&M, sizeof (M6502), fp);
381
382 if (populus)
383 pack_fread (PopRAM, PopRAMsize, fp);
384
385 if (CD_emulation)
386 {
387 pack_fread (cd_extra_mem, 0x10000, fp);
388 pack_fread (cd_extra_super_mem, 0x30000, fp);
389 pack_fread (cd_sector_buffer, 0x2000, fp);
390 pack_fread (&tmp, 2, fp);
391 if (tmp != 0xFFFF)
392 cd_read_buffer = cd_sector_buffer + tmp;
393 else
394 cd_read_buffer = 0;
395 }
396
397 for (tmp = 0; tmp < 8; tmp++)
398 bank_set (tmp, M.MPR[tmp]);
399 memset (vchange, 1, VRAMSIZE / 32);
400 memset (vchanges, 1, VRAMSIZE / 128);
401
402 CycleOld = (UInt32) M.User;
403
404 pack_fclose (fp);
405
406 #endif
407
408 #else // KERNEL_DS defined
409
410 #ifdef ALLEGRO
411 PACKFILE *fp;
412 UInt32 tmp = 0;
413 char *tmp_buf = (char *) alloca (100);
414 UChar version = 0;
415
416 if (!exists (sav_path))
417 return 1;
418
419 if (!(fp = pack_fopen (sav_path, F_READ_PACKED)))
420 return 1;
421
422 pack_fread (tmp_buf, 18, fp);
423 if (!strncmp (tmp_buf, "Hu-Go! state file", 17))
424 {
425 version = tmp_buf[17];
426 }
427 else
428 {
429 version = 0;
430 pack_fclose (fp);
431 if (!(fp = pack_fopen (sav_path, F_READ_PACKED)))
432 return 1;
433
434 }
435
436 pack_fread (RAM, 0x8000, fp);
437 pack_fread (VRAM, VRAMSIZE, fp);
438 pack_fread (SPRAM, 64 * 4 * sizeof (short), fp);
439 pack_fread (Pal, 512, fp);
440 pack_fread (&scanline, sizeof (int), fp);
441
442 if ((version == 0x11) || (version == 0x20))
443 pack_fread (&io, sizeof (IO), fp);
444 else
445 pack_fread (&io, 1420, fp);
446
447 {
448
449 pack_fread (mmr, sizeof(mmr[0])*8, fp);
450 pack_fread (&cyclecount, sizeof(cyclecount), fp);
451 pack_fread (&cyclecountold, sizeof(cyclecountold), fp);
452
453 // registers
454
455 pack_fread (®_pc, sizeof(reg_pc), fp);
456 pack_fread (®_a, sizeof(reg_a), fp);
457 pack_fread (®_x, sizeof(reg_x), fp);
458 pack_fread (®_y, sizeof(reg_y), fp);
459 pack_fread (®_p, sizeof(reg_p), fp);
460 pack_fread (®_s, sizeof(reg_s), fp);
461
462 pack_fread (&halt_flag, sizeof(halt_flag), fp);
463 pack_fread (&cycles, sizeof(cycles), fp);
464
465 }
466
467 if (populus)
468 pack_fread (PopRAM, PopRAMsize, fp);
469
470 if (CD_emulation)
471 {
472 pack_fread (cd_extra_mem, 0x10000, fp);
473 pack_fread (cd_extra_super_mem, 0x30000, fp);
474 pack_fread (cd_sector_buffer, 0x2000, fp);
475 pack_fread (&tmp, 2, fp);
476 if (tmp != 0xFFFF)
477 cd_read_buffer = cd_sector_buffer + tmp;
478 else
479 cd_read_buffer = 0;
480 pack_fread (&cd_port_1800, sizeof(cd_port_1800), fp);
481 pack_fread (&cd_port_1801, sizeof(cd_port_1801), fp);
482 pack_fread (&cd_port_1802, sizeof(cd_port_1802), fp);
483 pack_fread (&cd_port_1804, sizeof(cd_port_1804), fp);
484 pack_fread (&pce_cd_read_datacnt, sizeof(pce_cd_read_datacnt), fp);
485 pack_fread (&pce_cd_curcmd, sizeof(pce_cd_curcmd), fp);
486
487 }
488
489 for (tmp = 0; tmp < 8; tmp++)
490 bank_set (tmp, mmr[tmp]);
491 memset (vchange, 1, VRAMSIZE / 32);
492 memset (vchanges, 1, VRAMSIZE / 128);
493
494 // CycleOld = (UInt32) M.User;
495
496 zp_base = RAM;
497 sp_base = RAM + 0x100;
498
499 pack_fclose (fp);
500
501 #else
502
503 FILE* saved_file;
504
505 saved_file = fopen(sav_path, "rb");
506
507 if (saved_file == NULL)
508 return 1;
509
510 if (fread(hard_pce, 1, sizeof(struct_hard_pce), saved_file) != sizeof(struct_hard_pce))
511 {
512 fclose(saved_file);
513 return 1;
514 }
515
516 {
517 int mmr_index;
518
519 for (mmr_index = 0; mmr_index < 8; mmr_index++)
520 {
521 bank_set((UChar)mmr_index, mmr[mmr_index]);
522 printf("Setting bank %d to 0x%02x\n", mmr_index, mmr[mmr_index]);
523 }
524 }
525
526 fclose(saved_file);
527
528 #endif
529
530
531
532 #endif
533
534 return 0;
535 }
536
537 /*****************************************************************************
538
539 Function: savegame
540
541 Description: save a game using allegro packing functions
542 Parameters: none
543 Return: 1 on error, else 0
544
545 *****************************************************************************/
546
547
548 int
savegame()549 savegame ()
550 {
551
552 #ifndef KERNEL_DS
553
554 #ifdef ALLEGRO
555
556 PACKFILE *fp;
557 UInt32 tmp;
558
559 if (!(fp = pack_fopen (sav_path, F_WRITE_PACKED)))
560 return 1;
561
562 pack_fwrite ("Hu-Go! state file\21", 18, fp);
563
564 pack_fwrite (RAM, 0x8000, fp);
565 pack_fwrite (VRAM, VRAMSIZE, fp);
566 pack_fwrite (SPRAM, 64 * 4 * sizeof (short), fp);
567 pack_fwrite (Pal, 512, fp);
568 pack_fwrite (&scanline, sizeof (int), fp);
569 pack_fwrite (&io, sizeof (IO), fp);
570 pack_fwrite (&M, sizeof (M6502), fp);
571 if (populus)
572 pack_fwrite (PopRAM, PopRAMsize, fp);
573 if (CD_emulation)
574 {
575 pack_fwrite (cd_extra_mem, 0x10000, fp);
576 pack_fwrite (cd_extra_super_mem, 0x30000, fp);
577 pack_fwrite (cd_sector_buffer, 0x2000, fp);
578 if (cd_read_buffer)
579 {
580 tmp = cd_read_buffer - cd_sector_buffer;
581 pack_fwrite (&tmp, 2, fp);
582 }
583 else
584 {
585 tmp = 0xFFFF;
586 pack_fwrite (&tmp, 2, fp);
587 }
588 }
589
590 return pack_fclose (fp);
591 #else
592
593 return 0;
594
595 #endif
596
597 #else // KERNEL_DS defined
598
599 #ifdef ALLEGRO
600
601 PACKFILE *fp;
602 UInt32 tmp;
603
604 if (!(fp = pack_fopen (sav_path, F_WRITE_PACKED)))
605 return 1;
606
607 pack_fwrite ("Hu-Go! state file\40", 18, fp);
608
609 pack_fwrite (RAM, 0x8000, fp);
610 pack_fwrite (VRAM, VRAMSIZE, fp);
611 pack_fwrite (SPRAM, 64 * 4 * sizeof (short), fp);
612 pack_fwrite (Pal, 512, fp);
613 pack_fwrite (&scanline, sizeof (int), fp);
614 pack_fwrite (&io, sizeof (IO), fp);
615
616 // pack_fwrite (&M, sizeof (M6502), fp);
617 pack_fwrite (mmr, sizeof(mmr[0])*8, fp);
618 pack_fwrite (&cyclecount, sizeof(cyclecount), fp);
619 pack_fwrite (&cyclecountold, sizeof(cyclecountold), fp);
620
621 // registers
622
623 pack_fwrite (®_pc, sizeof(reg_pc), fp);
624 pack_fwrite (®_a, sizeof(reg_a), fp);
625 pack_fwrite (®_x, sizeof(reg_x), fp);
626 pack_fwrite (®_y, sizeof(reg_y), fp);
627 pack_fwrite (®_p, sizeof(reg_p), fp);
628 pack_fwrite (®_s, sizeof(reg_s), fp);
629
630 pack_fwrite (&halt_flag, sizeof(halt_flag), fp);
631 pack_fwrite (&cycles, sizeof(cycles), fp);
632
633 if (populus)
634 pack_fwrite (PopRAM, PopRAMsize, fp);
635
636 if (CD_emulation)
637 {
638 pack_fwrite (cd_extra_mem, 0x10000, fp);
639 pack_fwrite (cd_extra_super_mem, 0x30000, fp);
640 pack_fwrite (cd_sector_buffer, 0x2000, fp);
641 if (cd_read_buffer)
642 {
643 tmp = cd_read_buffer - cd_sector_buffer;
644 pack_fwrite (&tmp, 2, fp);
645 }
646 else
647 {
648 tmp = 0xFFFF;
649 pack_fwrite (&tmp, 2, fp);
650 }
651
652 pack_fwrite (&cd_port_1800, sizeof(cd_port_1800), fp);
653 pack_fwrite (&cd_port_1801, sizeof(cd_port_1801), fp);
654 pack_fwrite (&cd_port_1802, sizeof(cd_port_1802), fp);
655 pack_fwrite (&cd_port_1804, sizeof(cd_port_1804), fp);
656 pack_fwrite (&pce_cd_read_datacnt, sizeof(pce_cd_read_datacnt), fp);
657 pack_fwrite (&pce_cd_curcmd, sizeof(pce_cd_curcmd), fp);
658
659 }
660
661 return pack_fclose (fp);
662 #else // ALLEGRO not defined
663
664 FILE* saved_file;
665
666 saved_file = fopen(sav_path, "wb");
667
668 if (saved_file == NULL)
669 return 1;
670
671 if (fwrite(hard_pce, 1, sizeof(struct_hard_pce), saved_file) != sizeof(struct_hard_pce))
672 {
673 fclose(saved_file);
674 return 1;
675 }
676
677 fclose(saved_file);
678
679 #endif
680
681 #endif
682
683 return 0;
684
685 }
686
687 /*****************************************************************************
688
689 Function: freeze_value
690
691 Description: set or unset a value to freeze
692 Parameters:none
693 Return: 0 if unset an old freezed value or can't set a value anymore
694 1 if new was created,
695 may modify 'list_freezed_value'
696
697 *****************************************************************************/
698 int
freeze_value(void)699 freeze_value (void)
700 {
701 char tmp_str[10];
702 unsigned char index = 0;
703 unsigned where;
704
705 while (osd_keypressed ())
706 /*@-retvalother*/
707 osd_readkey (); // Flushing keys
708 /*@=retvalother*/
709
710 while ((index < 10) && ((tmp_str[index++] = (char)(osd_readkey () & 0xFF)) != 13));
711 tmp_str[index - 1] = 0;
712
713 where = (unsigned)atoi (tmp_str);
714
715 for (index = 0; index < current_freezed_values; index++)
716 if (list_to_freeze[index].position == (unsigned short)where)
717 {
718 // We entered an already freezed offset
719
720 memcpy (&list_to_freeze[index], &list_to_freeze[index + 1],
721 (current_freezed_values - index +
722 1) * sizeof (freezed_value));
723 // We erase the current struct letting no hole...
724
725 current_freezed_values--;
726 // And we got one less value
727
728 return 0;
729 }
730
731 if (current_freezed_values < MAX_FREEZED_VALUE)
732 {
733 list_to_freeze[current_freezed_values].position = (unsigned short)where;
734
735 while ((index < 10) && ((tmp_str[index++] = (char)(osd_readkey () & 0xFF)) != 13));
736 tmp_str[index - 1] = 0;
737
738 list_to_freeze[current_freezed_values++].value = (unsigned) atoi (tmp_str);
739
740 return 1;
741 }
742 else
743 return 0;
744 }
745