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 (&reg_pc, sizeof(reg_pc), fp);
456       pack_fread (&reg_a, sizeof(reg_a), fp);
457       pack_fread (&reg_x, sizeof(reg_x), fp);
458       pack_fread (&reg_y, sizeof(reg_y), fp);
459       pack_fread (&reg_p, sizeof(reg_p), fp);
460       pack_fread (&reg_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 (&reg_pc, sizeof(reg_pc), fp);
624   pack_fwrite (&reg_a, sizeof(reg_a), fp);
625   pack_fwrite (&reg_x, sizeof(reg_x), fp);
626   pack_fwrite (&reg_y, sizeof(reg_y), fp);
627   pack_fwrite (&reg_p, sizeof(reg_p), fp);
628   pack_fwrite (&reg_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