VOGONS

Common searches


Save States - Proof of concept

Topic actions

Reply 100 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Have another patch for cdrom cdda.

Ex. Play Gobliiins 1/2 CD. Hit dosbox load state while intro playing. Wrong cdda track keeps playing as BGM in normal game.

(ykhwong svn-daum 2012-02-20)

dos/dos_mscdex.cpp



(add to end of file)
#include "../save_state.h"

//save state support
namespace
{
class SerializeCdrom : public SerializeGlobalPOD
{
public:
SerializeCdrom() : SerializeGlobalPOD("Cdrom")
{
}

private:
virtual void getBytes(std::ostream& stream)
{
//writePOD(stream, xms_callback);

SerializeGlobalPOD::getBytes(stream);


for (Bit8u drive_unit=0; drive_unit<mscdex->GetNumDrives(); drive_unit++) {
TMSF pos, start, end;
bool playing, pause;

mscdex->GetAudioStatus(drive_unit, playing, pause, start, end);
mscdex->GetCurrentPos(drive_unit,pos);

stream.write(reinterpret_cast<const char*>( &playing ), sizeof(playing) );
stream.write(reinterpret_cast<const char*>( &pause ), sizeof(pause) );
stream.write(reinterpret_cast<const char*>( &pos ), sizeof(pos) );
stream.write(reinterpret_cast<const char*>( &start ), sizeof(start) );
stream.write(reinterpret_cast<const char*>( &end ), sizeof(end) );
}
}


virtual void setBytes(std::istream& stream)
{
//readPOD(stream, xms_callback);


SerializeGlobalPOD::setBytes(stream);


for (Bit8u drive_unit=0; drive_unit<mscdex->GetNumDrives(); drive_unit++) {
TMSF pos, start, end;
Bit32u msf_time, play_len;
bool playing, pause;



mscdex->StopAudio(drive_unit);

Show last 25 lines

stream.read(reinterpret_cast<char*>( &playing ), sizeof(playing) );
stream.read(reinterpret_cast<char*>( &pause ), sizeof(pause) );
stream.read(reinterpret_cast<char*>( &pos ), sizeof(pos) );
stream.read(reinterpret_cast<char*>( &start ), sizeof(start) );
stream.read(reinterpret_cast<char*>( &end ), sizeof(end) );


msf_time = ( pos.min << 16 ) + ( pos.sec << 8 ) + ( pos.fr );

// end = total play time (GetAudioStatus adds +150)
// pos = current play cursor
// start = start play cursor
play_len = end.min * 75 * 60 + ( end.sec * 75 ) + end.fr - 150;
play_len -= ( pos.min - start.min ) * 75 * 60 + ( pos.sec - start.sec ) * 75 + ( pos.fr - start.fr );


// first play, then simulate pause
if( playing ) mscdex->PlayAudioMSF(drive_unit, msf_time, play_len);
if( pause ) mscdex->PlayAudioMSF(drive_unit, msf_time, 0);
}
}
} dummy;
}

===============================
===============================
===============================

Thanks for the feedback. 😀

Currently I have this change for vga mode switching:

vga_memory.cpp

private:
virtual void getBytes(std::ostream& stream)
{
SerializeGlobalPOD::getBytes(stream);

stream.write(reinterpret_cast<const char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
stream.write(reinterpret_cast<const char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));


stream.write(reinterpret_cast<const char*>( &vga.mode ), sizeof(vga.mode) );
stream.write(reinterpret_cast<const char*>( &vga.draw.height ), sizeof(vga.draw.height) );
stream.write(reinterpret_cast<const char*>( &vga.draw.width ), sizeof(vga.draw.width) );

stream.write(reinterpret_cast<const char*>( &vga.misc_output ), sizeof(vga.misc_output) );
stream.write(reinterpret_cast<const char*>( &vga.crtc.maximum_scan_line ), sizeof(vga.crtc.maximum_scan_line) );
stream.write(reinterpret_cast<const char*>( &vga.config.scan_len ), sizeof(vga.config.scan_len) );
}

virtual void setBytes(std::istream& stream)
{
SerializeGlobalPOD::setBytes(stream);

stream.read(reinterpret_cast<char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
stream.read(reinterpret_cast<char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));


stream.read(reinterpret_cast<char*>( &vga.mode ), sizeof(vga.mode) );
stream.read(reinterpret_cast<char*>( &vga.draw.height ), sizeof(vga.draw.height) );
stream.read(reinterpret_cast<char*>( &vga.draw.width ), sizeof(vga.draw.width) );

stream.read(reinterpret_cast<char*>( &vga.misc_output ), sizeof(vga.misc_output) );
stream.read(reinterpret_cast<char*>( &vga.crtc.maximum_scan_line ), sizeof(vga.crtc.maximum_scan_line) );
stream.read(reinterpret_cast<char*>( &vga.config.scan_len ), sizeof(vga.config.scan_len) );


extern void VGA_SetupDrawing(Bitu /*val*/);
VGA_SetupDrawing(0);
}

It's not done yet because it doesn't fully work with Lemmings 2 - menus vs in-game modes not totally restored. But much better than what it used to display (no weird stripes).

Probably missing another state POD somewhere.

If you have an example game with palette load corruption, please mention the specifics. Maybe I can assist in sorting it out. 😉
(I've only tested palette with Gobliiins / Lemmings mostly)

I also have a WIP patch for dos_files (ex. saving in the middle of Syndicate Wars streaming smk movies). Need to diff it out and clean it up first though.

Attachments

  • Filename
    dos_mscdex_savestate.diff
    File size
    2.32 KiB
    Downloads
    213 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 101 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie

Cool, that is awesome. I will take a look and check sooner or later. 😀 I need to start a new build environment as I've recently formatted my hard disk.

There may be also still missing PODs to be saved, especially, sound. SB and MIDI parts are important for some games like MegaMan X.

Reply 102 of 227, by tikalat

User metadata
Rank Member
Rank
Member

This addition is for basic dos file handling (streaming problems). More spread out changes this time since a new function is needed for drive handlers.

Example game would be Syndicate Wars. Make a save state at intro movie (streaming content). You can reload the state later in the movie to replay certain parts again (without Dosbox crashing). Or it even works while playing an in-game mission and loadstate back to the intro movie.

ykhwong svn-daum 2012-02-20

#1
include/dos_system.h

class DOS_File
----> add this line
virtual Bit32u GetSeekPos() { return 0xffffffff; }


#2
dos/drives/drive_fat.cpp

class fatFile : public DOS_File {
----> add this line
Bit32u GetSeekPos(void);


---> add this elsewhere in file (like end-of-file)
Bit32u fatFile::GetSeekPos() {
return seekpos;
}


#3
dos/drives/drive_iso.cpp

class isoFile : public DOS_File {
----> add this line
Bit32u GetSeekPos(void);

---> add this elsewhere in file (like at end)
Bit32u isoFile::GetSeekPos() {
return filePos - fileBegin;
}


#4
class localFile : public DOS_File {

---> add this line
Bit32u GetSeekPos(void);

---> add this elsewhere in file (like at end)
Bit32u localFile::GetSeekPos() {
return ftell( fhandle );
}


#5
dos/dos_files.cpp

(replace SerializeDosFiles at end-of-file with this new one)
//save state support
namespace
{
class SerializeDosFiles : public SerializeGlobalPOD
{
public:
SerializeDosFiles() : SerializeGlobalPOD("Dos Files")
Show last 116 lines
    {
}

private:
virtual void getBytes(std::ostream& stream)
{
//writePOD(stream, xms_callback);

SerializeGlobalPOD::getBytes(stream);


for( int handle = 0; handle < DOS_FILES; handle++ ) {
Bit32u str_len, seek_pos;


// skip entry
if( Files[handle] == 0 ||
strcmp( Files[handle]->GetName(), "CON" ) == 0 ||
strcmp( Files[handle]->GetName(), "PRN" ) == 0 ||
strcmp( Files[handle]->GetName(), "AUX" ) == 0 ) {
str_len = 0;
stream.write(reinterpret_cast<const char*>( &str_len ), 4 );
continue;
}


str_len = strlen( Files[handle]->GetName() );
stream.write(reinterpret_cast<const char*>( &str_len ), 4 );
stream.write(reinterpret_cast<const char*>( Files[handle]->GetName() ), str_len );

stream.write(reinterpret_cast<const char*>( &Files[handle]->flags ), sizeof( Files[handle]->flags ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->drive ), sizeof( Files[handle]->drive ) );

stream.write(reinterpret_cast<const char*>( &Files[handle]->time ), sizeof( Files[handle]->time ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->date ), sizeof( Files[handle]->date ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->attr ), sizeof( Files[handle]->attr ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->newtime ), sizeof( Files[handle]->newtime ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->open ), sizeof( Files[handle]->open ) );
stream.write(reinterpret_cast<const char*>( &Files[handle]->refCtr ), sizeof( Files[handle]->refCtr ) );


seek_pos = Files[handle]->GetSeekPos();
stream.write(reinterpret_cast<const char*>( &seek_pos ), 4 );
}
}


virtual void setBytes(std::istream& stream)
{
//readPOD(stream, xms_callback);


SerializeGlobalPOD::setBytes(stream);

// shutdown old files
for( int handle = 0; handle < DOS_FILES; handle++ ) {
if( Files[handle] == 0 ) continue;

if( strcmp( Files[handle]->GetName(), "CON" ) == 0 ) continue;
if( strcmp( Files[handle]->GetName(), "PRN" ) == 0 ) continue;
if( strcmp( Files[handle]->GetName(), "AUX" ) == 0 ) continue;


if (Files[handle]->IsOpen()) {
Files[handle]->Close();
}
delete Files[handle];
Files[handle]=0;
}


for( int handle = 0; handle < DOS_FILES; handle++ ) {
Bit32u temp_val, flags_val, seek_pos;
char *file_name;
bool exists;
Bit8u drive_num;


// find old handle to restore
stream.read(reinterpret_cast<char*>( &temp_val ), 4 );
if( temp_val == 0 ) continue;


// restore file info - name + flags + drive
file_name = (char*)_alloca( (temp_val+1) * sizeof(char));
stream.read(reinterpret_cast<char*>( file_name ), temp_val );
stream.read(reinterpret_cast<char*>( &flags_val ), sizeof( Files[handle]->flags ) );
stream.read(reinterpret_cast<char*>( &drive_num ), sizeof( Files[handle]->drive ) );
file_name[ temp_val ] = 0;


exists = Drives[drive_num]->FileOpen(&Files[handle],file_name,flags_val);
if (exists) {
Files[handle]->SetDrive(drive_num);
Files[handle]->drive = drive_num;
}


stream.read(reinterpret_cast<char*>( &Files[handle]->time ), sizeof( Files[handle]->time ) );
stream.read(reinterpret_cast<char*>( &Files[handle]->date ), sizeof( Files[handle]->date ) );
stream.read(reinterpret_cast<char*>( &Files[handle]->attr ), sizeof( Files[handle]->attr ) );
stream.read(reinterpret_cast<char*>( &Files[handle]->newtime ), sizeof( Files[handle]->newtime ) );
stream.read(reinterpret_cast<char*>( &Files[handle]->open ), sizeof( Files[handle]->open ) );
stream.read(reinterpret_cast<char*>( &Files[handle]->refCtr ), sizeof( Files[handle]->refCtr ) );


stream.read(reinterpret_cast<char*>( &seek_pos ), 4 );
Files[handle]->Seek( &seek_pos, DOS_SEEK_SET );


if( !Files[handle]->IsOpen() ) Files[handle]->Close();
}
}
} dummy;
}

#1-4 is about recording seek cursors.
#5 is about writing seek cursors. And closing / reopening files as they were at the time of savestate.

==================================
==================================
==================================

This new vga_memory.cpp savestate version fixes my Lemmings 2 problems (menu <---> in-game drawing routines).

There seems to be a Syndicate Wars problem from intro -> main menu (original loadstate bug). May commit this code later as a testbase though. Unsure.

//save state support
namespace {
class SerializeVgaMemory : public SerializeGlobalPOD {
public:
SerializeVgaMemory() : SerializeGlobalPOD("Vga Memory")
{
/*
registerPOD(vgapages.base);
registerPOD(vgapages.mask);
registerPOD(svga);
registerPOD(vga.mode);
registerPOD(vga.lastmode);
registerPOD(vga.misc_output);
registerPOD(vga.draw);
registerPOD(vga.config);
registerPOD(vga.internal);
registerPOD(vga.seq);
registerPOD(vga.attr);
registerPOD(vga.gfx);
registerPOD(vga.dac);
registerPOD(vga.latch);
registerPOD(vga.lfb);
registerPOD(vga.s3);
registerPOD(vga.other);
registerPOD(vga.crtc);
*/


// VGASetupDrawing
registerPOD(vga.mode);
registerPOD(vga.misc_output);

// VGASetupDrawing - many vars used
registerPOD(vga.config);
registerPOD(vga.crtc);
registerPOD(vga.other);

// VGA_SetupHandlers (?)
registerPOD(vga.gfx.miscellaneous);
registerPOD(vga.s3.ext_mem_ctrl);
}

private:
virtual void getBytes(std::ostream& stream)
{
SerializeGlobalPOD::getBytes(stream);

stream.write(reinterpret_cast<const char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
stream.write(reinterpret_cast<const char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));
}

virtual void setBytes(std::istream& stream)
{
SerializeGlobalPOD::setBytes(stream);

stream.read(reinterpret_cast<char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
stream.read(reinterpret_cast<char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));



Show last 8 lines
				// force redraw
vga.draw.width = vga.draw.height = 1;
VGA_SetupDrawing(0);
VGA_SetupHandlers();
}
} dummy;
}

Sound PODs are new to me. Maybe I'll track down Megaman X floppy sometime and give it a whirl. 😉

Attachments

  • Filename
    dos_files_savestate_diff.7z
    File size
    1.42 KiB
    Downloads
    231 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 103 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Syndicate Wars seems to switch between vga (movies, in-game) vs s3 svga (menus). Still glitchy but better so only save/load state between vga-only states (or during svga only).

Otherwise it works out with other games so far. Going to WIP1 commit this since it generally works (minus svga <--> vga mode switches).

hardware/vga/vga_memory.cpp


(change at end of file)
//save state support
namespace {
class SerializeVgaMemory : public SerializeGlobalPOD {
public:
SerializeVgaMemory() : SerializeGlobalPOD("Vga Memory")
{
/*
registerPOD(vgapages.base);
registerPOD(vgapages.mask);
registerPOD(svga);
registerPOD(vga.mode);
registerPOD(vga.lastmode);
registerPOD(vga.misc_output);
registerPOD(vga.draw);
registerPOD(vga.config);
registerPOD(vga.internal);
registerPOD(vga.seq);
registerPOD(vga.attr);
registerPOD(vga.gfx);
registerPOD(vga.dac);
registerPOD(vga.latch);
registerPOD(vga.lfb);
registerPOD(vga.s3);
registerPOD(vga.other);
registerPOD(vga.crtc);
*/

// VGASetupDrawing
registerPOD(vga.mode);
registerPOD(vga.misc_output);

// VGASetupDrawing - many vars used
registerPOD(vga.config);
registerPOD(vga.crtc);
registerPOD(vga.other);
registerPOD(vga.s3); // (vga.s3.reg_3a)

// VGA_SetupHandlers (?)
registerPOD(vga.gfx.miscellaneous);
//registerPOD(vga.s3.ext_mem_ctrl);
}

private:
virtual void getBytes(std::ostream& stream)
{
SerializeGlobalPOD::getBytes(stream);

stream.write(reinterpret_cast<const char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
stream.write(reinterpret_cast<const char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));
}

virtual void setBytes(std::istream& stream)
{
SerializeGlobalPOD::setBytes(stream);

stream.read(reinterpret_cast<char*>(vga.mem.linear_orgptr), sizeof(Bit8u) * (std::max<Bit32u>(vga.vmemsize, 512 * 1024U) + 2048 + 16));
Show last 12 lines
        stream.read(reinterpret_cast<char*>(vga.fastmem_orgptr), sizeof(Bit8u) * ((vga.vmemsize << 1) + 4096 + 16));



// force redraw
vga.draw.width = vga.draw.height = 0;
VGA_SetupDrawing(0);
VGA_SetupHandlers();
}
} dummy;
}

===========================
===========================
===========================

Studied up on MPU-401 (General Midi) conventions. Practically speaking, I think it would be a burden to keep track of all the SysEx patches as they are uploaded - making a large memory list since we can't just poll the sound device for params, times.

Having tried Blackthorne with MT-32 MIDI (Emu), quite a change over Win32 Soft GS.

It looks that the MUNT version can be save state'd (on paper). Looks cleaner than the video mode switching + video handlers.

I may give this one a try over the days / weeks. Since it's important enough to me and seems doable.

Attachments

  • Filename
    vga_memory_savestate_wip1.diff
    File size
    3.96 KiB
    Downloads
    205 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 104 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie

Thanks. I am going to use the MUNT as an external library in my next release. Here is a link to a new munt patch for DOSBox from sergm.
https://github.com/sergm/munt_devel/tree/mast … SBox-mt32-patch

Reply 105 of 227, by tikalat

User metadata
Rank Member
Rank
Member

I'll check out the mt32 patch sometime. Going to work off the svn-daum 2012-02-20 build first.

Taking much longer than I wanted to map out how the MUNT ptr structures work (complex beast). I think it's about 85% done and I've finally got a feel how this system works.

Save states are about 40% there (roughly working over short midi stretches). Quite a lot of changes (mostly adding saveState / loadState functions) with some extra constructor variable passing additions to handle this new feature.

Debugging bad ptrs is the hard part, leading to some nasty crashes when not caught.

And have to add MIDI SysEx save states on the dosbox end (avoid other hangs there).

Hopefully it'll be done by week's end. And I may take a healthy break before tackling SB PODs.

Reply 106 of 227, by tikalat

User metadata
Rank Member
Rank
Member

This is a rather large diff that spreads across most of the MUNT files (ykhwong svn-daum 2012-02-20 build).

Most of the changes are 'non-intrusive' and don't change the MUNT core. A few dangling pointers / values are now (de-)init'd for savestate compatibility.

Hopefully this diff patches correctly.

Savestate will only correctly work with internal MT-32 emulation. No other MIDI device can be fully restored.

Tested with Blackthorne (General Midi) and Space Quest 1 (VGA) + 3. Music normally gets restored without problems. Other than the random odd Dosbox emulation hangs - maybe missing PIC events or something related when loadstating.

Only spent some time actually playing each title (~5 min worth from intro).

So there could a be a load bug but big steps were taken to catch and minimize any such events.

I should look at that new dosbox patch too. But that'd also require making a MUNT lib. xx(

Attachments

  • Filename
    midi_mt32_savestates.zip
    File size
    11.57 KiB
    Downloads
    211 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 107 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Small change to gui/vga_draw.cpp

Sometimes it's fun to know what game resolution you're running at

void VGA_SetupDrawing(Bitu /*val*/ ) {
..
..
// (end of function)
{
char *str;

const char* const mode_texts[] = {
"M_CGA2", "M_CGA4",
"M_EGA", "M_VGA",
"M_LIN4", "M_LIN8", "M_LIN15", "M_LIN16", "M_LIN32",
"M_TEXT",
"M_HERC_GFX", "M_HERC_TEXT",
"M_CGA16", "M_TANDY2", "M_TANDY4", "M_TANDY16", "M_TANDY_TEXT",
"M_ERROR"
};

str = (char *) _alloca(512);
sprintf( str, "Mode switch = [%s] %dx%dx%d", mode_texts[vga.mode], vga.draw.width, vga.draw.height, vga.draw.bpp );
LOG_MSG(str);
}

/////////////////////////////////////////////
/////////////////////////////////////////////
/////////////////////////////////////////////

Now the more important patch. This simulates savestates for external MIDI devices.

Based off General Midi 1.0 (1992-1993'ish specs) + Roland GS (lightweight version).

Some GS controls are missing (all NRPN + SysEx). And GM 1.0 (Master Volume SysEx).

It's been briefly tested using MS Soft GS. Restores the GM patches + notes. It's not a full recreation like the internal MT32 savestates but should be acceptable for normal gaming.

This new file will also replace - update the last MT32 MUNT savestate code to handle multithreading cores better (clear queued msg buffers safely).

I'll be passing on writing PODs for Adlib/Soundblaster for awhile. Until I greatly need them. The previous patches were all pretty exhausting. 😉

Attachments

  • Filename
    gui_midi_external_savestate.diff
    File size
    14.9 KiB
    Downloads
    204 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 108 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie

I appreciate what you have done for the graphics, input, and several sound parts, etc. I will also take some time to look through the basic structure of the adlib/sb later.

Meanwhile, your changes on hardware/vga_draw.cpp for showing resolution could be useful to some but this is already provided in debugger-enabled build AFAIK.

Reply 109 of 227, by tikalat

User metadata
Rank Member
Rank
Member

I tried the debugger but those messages fly by so~ fast. Console did mention something about resolution switch. Then it gets spammed with loads of PIC events. 🤣

I find the patch more convenient. Mainly intended just for me but decided to share anyway. 😀

Normally I'd expect Adlib / SBlaster states to be not that problematic. But most of the patches so far involve saving a selective # of vars (not the whole struct). So I'm wary of tinkering with PODs atm.

My brain keeps telling me to make a PIC POD though. Always thinking there's some event that doesn't get re-queued on loadstate causing fatal hangs. Sometime this year perhaps.

Reply 110 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie

PIC logging can be disabled in [log] section from dosbox.conf newly refreshed by the debugger. However, the patch that you provided above also should work.

tikalat wrote:

My brain keeps telling me to make a PIC POD though. Always thinking there's some event that doesn't get re-queued on loadstate causing fatal hangs. Sometime this year perhaps.

I remember that I remarked every PIC pods used in the original version of save states. (hardware/pic.cpp)

Reply 111 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Since I may not have time to work on Dosbox states for some time, decided to patch up PIC states (full restore).

Because VGA POD changes around PICs (+ Render POD indirectly), two hacks are used to work around this. Until VGA POD is fully restored and corrected.

1) PIC POD --> ZZZ__PIC (loaded after VGA)
2) Render POD --> redraw hack (at VStart, refresh for 2 frames) to recover black screens

Fatal hangs have shrunk again.

BTW: Thanks for the debugger tip!
NOTE: Diff file manually edited to remove some misc debugging junk

Attachments

  • Filename
    pic_savestate.diff
    File size
    21.6 KiB
    Downloads
    196 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 112 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Squeezed this in. Restructured VGA POD saving. All modes now saved (CGA - EGA - VGA - S3 - S3 other - misc). PIC POD hack removed. Render POD hack removed and rewritten. VGA Memory POD changed around (no POD conflicts).

On a good note, Syndicate Wars handles VGA -> SVGA loadstates okay now. But not SVGA -> VGA yet.

Guess I'll do the sound PODs too sometime (next). Which would then leave CPU paging, IO handlers, Mem pagehandlers. And maybe DMA controllers. Although I now wonder if XMS is burning SWars above problem.

So much to do. Must find the time. 😀

Attachments

  • Filename
    vga_full_savestate.diff
    File size
    57.23 KiB
    Downloads
    201 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 113 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Mixer savestates (Sblaster - Tandy - Gameblaster - Disney - PS1Sound - GUS - MPU401 - PC Speaker). No innova (couldn't compile yet) or Adlib (complicated). + DMA (full) POD

Sblaster seems okay from small testing.

Attachments

  • Filename
    mixer_wip1_savestate.diff
    File size
    32.63 KiB
    Downloads
    185 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 114 of 227, by tikalat

User metadata
Rank Member
Rank
Member

minor goof to gus - null ptr check

Attachments

  • Filename
    mixer_wip1_patch1_savestate.diff
    File size
    4.39 KiB
    Downloads
    203 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 115 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Patch does not handle paging - too complicated for me to piece together as a POD.

But it does the basic stuff for CPU. Minus special vars each core may use.

And resets Dosbox performance timer on load state.

Result: Games like 'Another World' go from 30% load failure hangs -> <1% atm. But this game likes to init / de-init the SB late in-game (past the codewheel protection). So load state can't produce sound until SB is officially on.

Maybe this can be patched later.

Attachments

  • Filename
    cpu_wip1_savestate.diff
    File size
    12.91 KiB
    Downloads
    180 downloads
    File comment
    ykhwong svn-daum 2012-02-20
    File license
    Fair use/fair dealing exception

Reply 116 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie

Thanks for the diffs, tikalat.
Did you compile with gcc (mingw/msys) or msvc? Visual Studio does not seem to work with the changes you have done. As it just stops working when loading from the beginning (CMOS part), testing each part may be required. Simple debugging did not help that much to me.

Also, it was hard to analyze the difference when looking through the diffs because they look too complicated. For parsing, "diff -urN" could be much better than just doing "diff -r".

I tried to collect every patch you provided here in order to merge them to a single patch against 2012-02-20 source. I am not sure if I did it correctly. (See the attachment)

Attachments

Reply 117 of 227, by Gamecollector

User metadata
Rank Oldbie
Rank
Oldbie

Well, the savestates are broken in the 20 Feb 2012 build.

Asus P4P800 SE/Pentium4 3.2E/2 Gb DDR400B,
Radeon HD3850 Agp (Sapphire), Catalyst 14.4 (XpProSp3).
Voodoo2 12 MB SLI, Win2k drivers 1.02.00 (XpProSp3).

Reply 118 of 227, by ykhwong

User metadata
Rank Oldbie
Rank
Oldbie
Gamecollector wrote:

Well, the savestates are broken in the 20 Feb 2012 build.

Yes, I know that it was unstable. I had to disable some more cpu pods when building it in visual studio. I think CPU_Core_Dyn_X86_Cache_Reset() also had to be set in the end.

Reply 119 of 227, by tikalat

User metadata
Rank Member
Rank
Member

Patches were made with vc express 2008 + gnu-win32 'diff -r'. Didn't know about '-urN'

Sadly, quite a lot of things were changed around with the new state PODs.

I could go over all the patches again from the merged diff one-by-one and see what flubbed up.