jamieduk / mupen64plus

Automatically exported from code.google.com/p/mupen64plus
1 stars 0 forks source link

Support for pj64 statesaves #52

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Add support for PJ64 statesave format (if it's not already supported)

Original issue reported on code.google.com by ebenbl...@gmail.com on 14 Apr 2008 at 6:52

GoogleCodeExporter commented 9 years ago
Note, whether this feature gets implemented or not depends on if any developers 
are
interested in doing it and how similar the formats of the PJ64 and mupen64 
statesaves
are.

Original comment by ebenbl...@gmail.com on 14 Apr 2008 at 7:10

GoogleCodeExporter commented 9 years ago

Original comment by ebenbl...@gmail.com on 14 Apr 2008 at 7:11

GoogleCodeExporter commented 9 years ago
Which 'save files' are wanted?  It seems that PJ64 has several different save 
files -
.SRA, .EEP, and .PJ.  Since PJ64 is closed source it's going to be difficult to
implement this feature.

Original comment by richard...@gmail.com on 14 Apr 2008 at 7:17

GoogleCodeExporter commented 9 years ago
SRA and EEP files are generic as they are fit to the Nintendo64 standard, the 
.pj
files can possibly be ported by looking at the source from 1.4.

Original comment by sgorman07@gmail.com on 17 Apr 2008 at 6:33

GoogleCodeExporter commented 9 years ago
Aren't PJ64 .pj savestates just byteswapped copies of the RAM?

Original comment by Wareya@gmail.com on 7 Jul 2008 at 8:01

GoogleCodeExporter commented 9 years ago
I'm fairly sure its just that, the registers, and some header info, sometimes 
zipped. 1964 can also use Project64 saves, and Zilmar told me they haven't 
changed 
from 1.0 so its in the open source 1.4 code.

EDITTED (basically the first time I went looking I couldn't find the Project64 
savestate code, its not in a neat savestate.c like ours ;)) Well... you got me 
to 
do some work. The Project64 code is in the
BOOL Machine_LoadState(void) / BOOL Machine_SaveState(void) functions in cpu.c. 
The 
difference is mupen states are gzipped instead of zipped (and we don't have 
uncompressed fallback) and the registers / memories are in a different order. 
Project64 also has slightly different header info, they save the full header, 
we 
just save the MD5. 

It shouldn't take too much time to port those functions over. Sadly between the 
netplay code / bug hunting / Input and RCS issues I don't think any devs have 
had 
time. At least with this info. anyone can do it now. 

Original comment by sknau...@wesleyan.edu on 8 Jul 2008 at 2:26

GoogleCodeExporter commented 9 years ago
One potential problem is that Mupen64plus also loads/saves a list of pending
interrupts and the 'virtual clock cycle' when these interrupts will fire.  Even 
if
PJ64 saves the same kind of data, since the cores are different the timing will 
not
be the same.  It is possible that the game will not run properly without this 
state
information, and if we cannot do some kind of translation into our own timing 
units
it might not work.

Original comment by richard...@gmail.com on 8 Jul 2008 at 5:56

GoogleCodeExporter commented 9 years ago
I would like to give this one a shot.

Original comment by olejl77@gmail.com on 22 Dec 2008 at 11:00

GoogleCodeExporter commented 9 years ago
I have done some initial work on this. It is not working yet (and I don't know 
if it
ever will).

I think that I'm now reading all the information correct from the pj64 
savestate (it
is difficult to verify since I don't know what it is supposed to be). Most of 
the
changes has been implemented in savestate.c, and all my current 
questions/issues has
been marked with 'TODO' in this file.

I have also done some minor changes around to be able to test it.

When I try to load a pj64 savestate, m64p is stuck in an endless loop, and 
nothing
happens (I didn't expect it to work). The most likely problem is the TLB and
vi_interupt which I am not sure how to convert between pj64 and m64p.

Anyone able to shed some light on the issues?

(A patch file is attached. Highly experimental!!!)

Original comment by olejl77@gmail.com on 23 Dec 2008 at 9:57

Attachments:

GoogleCodeExporter commented 9 years ago
Wow. I was quite surprised, but I actually made a one time load of a PJ64 
savestate.
I have not been able to reproduce the "accident". All the other tries seems to 
end in
some sort of "audio loop".

Patch is attached. Did some fixes on the vi_interupt handling.

Original comment by olejl77@gmail.com on 1 Jan 2009 at 4:48

Attachments:

GoogleCodeExporter commented 9 years ago
Ok now I have the first beta version available for testing. Any feedback / 
testing is
welcomed.

I have successfully loaded PJ64 savestates from the following games:
- Legend of Zelda, The - Ocarina of Time (U) (V1.0) [!]
- Super Mario 64 (U) [!]
- Perfect Dark (U) (V1.0) [!]
- Mario Kart 64 (U) [!]
- GoldenEye 007 (U) [!]

Almost working
- Paper Mario (U) [!] (some graphic gliches after load)
- Banjo-Tooie (U) [!] (freezes short after loading)

There are still issues, but maybe it is easier to do them on a case by case 
basis?

Original comment by olejl77@gmail.com on 6 Jan 2009 at 1:26

Attachments:

GoogleCodeExporter commented 9 years ago
Same as above only that I removed all the core and gui changes I made. Now it 
simply
try to load the savestate as a PJ64 savestate if the initial mupen one fails. 
Changes
only to savestates.c, savestates.h, memory.c, memory.h (last two only makes some
internal functions available from savestates.c)

Original comment by olejl77@gmail.com on 12 Jan 2009 at 5:07

Attachments:

GoogleCodeExporter commented 9 years ago
The patch from comment #12 was committed to the trunk in rev 1295, with a few 
small
changes.

Original comment by richard...@gmail.com on 25 Jan 2009 at 1:12

GoogleCodeExporter commented 9 years ago
attached is a patch for 'savestates_save_pj64'. It currently is not hooked up in
core. This is what I did to test it:

Index: r4300/interupt.c
===================================================================
--- r4300/interupt.c    (revision 1321)
+++ r4300/interupt.c    (working copy)
@@ -610,8 +617,8 @@

     if (savestates_job & SAVESTATE) 
     {
-        savestates_save();
-        savestates_job &= ~SAVESTATE;
+        if (savestates_save_pj64() != -1)
+            savestates_job &= ~SAVESTATE;
     }
 }

Somebody should find a nice way to do this...

Original comment by olejl77@gmail.com on 16 Feb 2009 at 3:27

Attachments:

GoogleCodeExporter commented 9 years ago
As of r1336 Project64 savestates should be fully supported, besides some minor 
timestamp variables that do not seem to be used by Project64.

Original comment by sknau...@wesleyan.edu on 22 Feb 2009 at 12:08

GoogleCodeExporter commented 9 years ago
Re-opened, there appears to be some issue in the load code, Olejl found this 
patch 
helps:

Index: main/savestates.c
===================================================================
--- main/savestates.c   (revision 1331)
+++ main/savestates.c   (working copy)
@@ -605,33 +605,98 @@
     unzReadCurrentFile(zipstatefile, &sp_register.sp_dram_addr_reg, 4);
     unzReadCurrentFile(zipstatefile, &sp_register.sp_rd_len_reg, 4);
     unzReadCurrentFile(zipstatefile, &sp_register.sp_wr_len_reg, 4);
-    unzReadCurrentFile(zipstatefile, &sp_register.w_sp_status_reg, 4);
+    unzReadCurrentFile(zipstatefile, &sp_register.sp_status_reg, 4);
     unzReadCurrentFile(zipstatefile, &sp_register.sp_dma_full_reg, 4);
     unzReadCurrentFile(zipstatefile, &sp_register.sp_dma_busy_reg, 4);
     unzReadCurrentFile(zipstatefile, &sp_register.sp_semaphore_reg, 4);
     unzReadCurrentFile(zipstatefile, &value, 4); // SP_PC_REG -> Not part of mupen 
savestate. Dummy read.
     unzReadCurrentFile(zipstatefile, &value, 4); // SP_IBIST_REG -> Not part of 
mupen savestate. Dummy read.
+
+    unsigned int *w_sp = &sp_register.w_sp_status_reg; // Only done to reduce 
the 
amount
+    unsigned int *sp = &sp_register.sp_status_reg;     // of character in the 
below ifs / elses
+    *w_sp = 0;
+    if ((*sp & 0x0001) == 0) { *w_sp |= 0x0000001; }
+    else                     { *w_sp |= 0x0000002; }
+    if ((*sp & 0x0002) == 0) { *w_sp |= 0x0000004; }
+    if ((*sp & 0x001c) == 0) { *w_sp |= 0x0000008; } // TODO: Unsecure if this 
is 
correct
+    else                     { *w_sp |= 0x0000010; } // TODO:  --- " ---
+    if ((*sp & 0x0020) == 0) { *w_sp |= 0x0000020; }
+    else                     { *w_sp |= 0x0000040; }
+    if ((*sp & 0x0040) == 0) { *w_sp |= 0x0000080; }
+    else                     { *w_sp |= 0x0000100; }
+    if ((*sp & 0x0080) == 0) { *w_sp |= 0x0000200; }
+    else                     { *w_sp |= 0x0000400; }
+    if ((*sp & 0x0100) == 0) { *w_sp |= 0x0000800; }
+    else                     { *w_sp |= 0x0001000; }
+    if ((*sp & 0x0200) == 0) { *w_sp |= 0x0002000; }
+    else                     { *w_sp |= 0x0004000; }
+    if ((*sp & 0x0400) == 0) { *w_sp |= 0x0008000; }
+    else                     { *w_sp |= 0x0010000; }
+    if ((*sp & 0x0800) == 0) { *w_sp |= 0x0020000; }
+    else                     { *w_sp |= 0x0040000; }
+    if ((*sp & 0x1000) == 0) { *w_sp |= 0x0080000; }
+    else                     { *w_sp |= 0x0100000; }
+    if ((*sp & 0x2000) == 0) { *w_sp |= 0x0200000; }
+    else                     { *w_sp |= 0x0400000; }
+    if ((*sp & 0x4000) == 0) { *w_sp |= 0x0800000; }
+    else                     { *w_sp |= 0x1000000; }
     update_SP();

     // dpc_register
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_start, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_end, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_current, 4);
-    unzReadCurrentFile(zipstatefile, &dpc_register.w_dpc_status, 4);
+    unzReadCurrentFile(zipstatefile, &dpc_register.dpc_status, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_clock, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_bufbusy, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_pipebusy, 4);
     unzReadCurrentFile(zipstatefile, &dpc_register.dpc_tmem, 4);
     unzReadCurrentFile(zipstatefile, &value, 4); // Dummy read
     unzReadCurrentFile(zipstatefile, &value, 4); // Dummy read
+    unsigned int *w_dpc = &dpc_register.w_dpc_status;
+    unsigned int *dpc = &dpc_register.dpc_status;
+    *w_dpc = 0;
+    if ((*dpc & 0x0001) == 0) { *w_dpc |= 0x0000001; }
+    else                      { *w_dpc |= 0x0000002; }
+    if ((*dpc & 0x0002) == 0) { *w_dpc |= 0x0000004; }
+    else                      { *w_dpc |= 0x0000008; }
+    if ((*dpc & 0x0004) == 0) { *w_dpc |= 0x0000010; }
+    else                      { *w_dpc |= 0x0000020; }
     update_DPC();

     // mi_register
-    unzReadCurrentFile(zipstatefile, &MI_register.w_mi_init_mode_reg, 4);
+    unzReadCurrentFile(zipstatefile, &MI_register.mi_init_mode_reg, 4);
     unzReadCurrentFile(zipstatefile, &MI_register.mi_version_reg, 4);
     unzReadCurrentFile(zipstatefile, &MI_register.mi_intr_reg, 4);
-    unzReadCurrentFile(zipstatefile, &MI_register.w_mi_intr_mask_reg, 4);
+    unzReadCurrentFile(zipstatefile, &MI_register.mi_intr_mask_reg, 4);
+    MI_register.w_mi_init_mode_reg = MI_register.mi_init_mode_reg & 0x7F;
+    if ((MI_register.mi_init_mode_reg & 0x080) == 0)
+        { MI_register.w_mi_init_mode_reg |= 0x0000080;
+    } else {
+        MI_register.w_mi_init_mode_reg |= 0x0000100;
+    }
+    if ((MI_register.mi_init_mode_reg & 0x200) == 0) {
+        MI_register.w_mi_init_mode_reg |= 0x0001000;
+    } else {
+        MI_register.w_mi_init_mode_reg |= 0x0002000;
+    }
+    // TODO: Unsecure about 'clear DP interrupt' 
(MI_register.w_mi_init_mode_reg[11])
     update_MI_intr_mask_reg();
+    unsigned int *w_mi = (unsigned int *) &MI_register.w_mi_intr_mask_reg;
+    unsigned int *mi = (unsigned int *) &MI_register.mi_intr_mask_reg;
+    *w_mi = 0;
+    if ((*mi & 0x01) == 0) { *w_mi |= 0x0000001; }
+    else                   { *w_mi |= 0x0000002; }
+    if ((*mi & 0x02) == 0) { *w_mi |= 0x0000004; }
+    else                   { *w_mi |= 0x0000008; }
+    if ((*mi & 0x04) == 0) { *w_mi |= 0x0000010; }
+    else                   { *w_mi |= 0x0000020; }
+    if ((*mi & 0x08) == 0) { *w_mi |= 0x0000040; }
+    else                   { *w_mi |= 0x0000080; }
+    if ((*mi & 0x10) == 0) { *w_mi |= 0x0000100; }
+    else                   { *w_mi |= 0x0000200; }
+    if ((*mi & 0x20) == 0) { *w_mi |= 0x0000400; }
+    else                   { *w_mi |= 0x0000800; }
     update_MI_init_mode_reg();

     // vi_register 
@@ -640,9 +705,9 @@
     // ai_register
     unzReadCurrentFile(zipstatefile, &ai_register, 4*6);

-    // TODO: Not avialable in PJ64 savestate
+    // TODO: Not avialable in PJ64 savestate. Leave it as is.
     // ai_register.next_delay = 0; ai_register.next_len = 0;
-    // ai_register.current_delay = 0;//804629; ai_register.current_len = 0;
+    // ai_register.current_delay = 0; ai_register.current_len = 0;

     // pi_register
     unzReadCurrentFile(zipstatefile, &pi_register, sizeof(PI_register));

I think there needs to be a better way.

Original comment by sknau...@wesleyan.edu on 22 Feb 2009 at 4:42

GoogleCodeExporter commented 9 years ago
Here is one savestate that fail without the above patch

Original comment by olejl77@gmail.com on 22 Feb 2009 at 5:06

Attachments:

GoogleCodeExporter commented 9 years ago
patch committed in rev 1416, the SM64 state file loads now.  Thanks olejl77 and
sknauert, sorry it took so long to get it in SVN

Original comment by richard...@gmail.com on 2 Oct 2009 at 3:23

GoogleCodeExporter commented 9 years ago
Wow. I am looking to implement an USF audio player plugin using Mupen64Plus as 
a base
— and for this I need a PJ64 savestate loader. October 01, you say ? I'm 
lucky :)
Hurray, one less thing to do !

Original comment by kemenaran on 16 Oct 2009 at 3:04

GoogleCodeExporter commented 9 years ago
Hello, I can not seem to get mupen64plus to load Zelda Majoras Mask savestate. 
Is there any thing that may possibly be done?

Original comment by kno0...@gmail.com on 1 Oct 2010 at 1:44

GoogleCodeExporter commented 9 years ago
HI !! I'm sure your patch's awesome ! But I can't understand how to use it....

Do you have to say "open *.pj0" "open *.pj0.zip", or is it something else than 
open ???

Original comment by pere.so...@gmail.com on 18 Oct 2010 at 5:41