213 lines
15 KiB
HTML
213 lines
15 KiB
HTML
|
<html>
|
|||
|
|
|||
|
<head>
|
|||
|
<title>Savestate (.fcs)</title>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|||
|
<meta name="generator" content="HelpNDoc">
|
|||
|
<link type="text/css" rel="stylesheet" media="all" href="css/reset.css" />
|
|||
|
<link type="text/css" rel="stylesheet" media="all" href="css/base.css" />
|
|||
|
<link type="text/css" rel="stylesheet" media="all" href="css/hnd.css" />
|
|||
|
<!--[if lte IE 8]>
|
|||
|
<link type="text/css" rel="stylesheet" media="all" href="css/ielte8.css" />
|
|||
|
<![endif]-->
|
|||
|
<script type="text/javascript" src="js/jquery.min.js"></script>
|
|||
|
<script type="text/javascript" src="js/hnd.js"></script>
|
|||
|
<script type="text/javascript"><!--
|
|||
|
var sTopicId = top.location.href.substring(top.location.href.lastIndexOf("/") + 1, top.location.href.length);
|
|||
|
if (top.frames.length == 0)
|
|||
|
top.location.href = "fceux.html?" + sTopicId
|
|||
|
else if (top && top.FrameTOC && top.FrameTOC.SelectTocItem)
|
|||
|
top.FrameTOC.SelectTocItem(sTopicId);
|
|||
|
</script>
|
|||
|
</head>
|
|||
|
|
|||
|
<body>
|
|||
|
|
|||
|
<div id="topic_header">
|
|||
|
<div id="topic_header_content">
|
|||
|
<h1>Savestate (.fcs)</h1>
|
|||
|
|
|||
|
<div id="topic_breadcrumb">
|
|||
|
<a href="Technicalinformation.html">Technical Information</a> ›› <a href="Movieformats.html">Movie & Savestate formats</a> ›› </div>
|
|||
|
</div>
|
|||
|
<div id="topic_header_nav">
|
|||
|
<a href="Movieformats.html"><img src="img/arrow_up.png" alt="Parent"/></a>
|
|||
|
|
|||
|
<a href="fcm.html"><img src="img/arrow_left.png" alt="Previous"/></a>
|
|||
|
|
|||
|
<a href="Sound.html"><img src="img/arrow_right.png" alt="Next"/></a>
|
|||
|
|
|||
|
</div>
|
|||
|
<div class="clear"></div>
|
|||
|
</div>
|
|||
|
<div id="topic_content">
|
|||
|
|
|||
|
<p>FCE Ultra Save State Format</p>
|
|||
|
<p> Updated: Mar 9, 2003</p>
|
|||
|
<p>---------------------------------------</p>
|
|||
|
<p><br></p>
|
|||
|
<p>FCE Ultra's save state format is now designed to be as forward and backwards</p>
|
|||
|
<p>compatible as possible. This is achieved through the (over)use of chunks.</p>
|
|||
|
<p>All multiple-byte variables are stored LSB(least significant byte)-first.</p>
|
|||
|
<p>Data types:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> (u)int8 - (un)signed 8 bit variable(also referred to as "byte")</p>
|
|||
|
<p> (u)int16 - (un)signed 16 bit variable</p>
|
|||
|
<p> (u)int32 - (un)signed 32 bit variable</p>
|
|||
|
<p><br></p>
|
|||
|
<p>-- Main File Header:</p>
|
|||
|
<p><br></p>
|
|||
|
<p>The main file header is 16-bytes in length. The first three bytes contain</p>
|
|||
|
<p>the string "FCS". The next byte contains the version of FCE Ultra that saved</p>
|
|||
|
<p>this save state. This document only applies to version "53"(.53) and higher.</p>
|
|||
|
<p>After the version byte, the size of the entire file in bytes(minus the 16 byte</p>
|
|||
|
<p>main file header) is stored. If oldversion is set to 255, the 32-bit version</p>
|
|||
|
<p>field will be used. In this field, a version such as 0.98.10 is stored as "9810"(decimal).</p>
|
|||
|
<p>The rest of the header is currently unused and should be nulled out. </p>
|
|||
|
<p>Example of relevant parts:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> FCS <uint8 oldversion> <uint32 totalsize> <uint32 version></p>
|
|||
|
<p><br></p>
|
|||
|
<p>-- Section Chunks:</p>
|
|||
|
<p><br></p>
|
|||
|
<p>Sections chunk headers are 5-bytes in length. The first byte defines what </p>
|
|||
|
<p>section it is, the next four bytes define the total size of the section</p>
|
|||
|
<p>(including the section chunk header).</p>
|
|||
|
<p><br></p>
|
|||
|
<p> <uint8 section> <uint32 size></p>
|
|||
|
<p><br></p>
|
|||
|
<p>Section definitions:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> 1 - "CPU"</p>
|
|||
|
<p> 2 - "CPUC"</p>
|
|||
|
<p> 3 - "PPU"</p>
|
|||
|
<p> 4 - "CTLR"</p>
|
|||
|
<p> 5 - "SND"</p>
|
|||
|
<p> 16 - "EXTRA"</p>
|
|||
|
<p><br></p>
|
|||
|
<p>-- Subsection Chunks</p>
|
|||
|
<p><br></p>
|
|||
|
<p>Subsection chunks are stored within section chunks. They contain the actual</p>
|
|||
|
<p>state data. Each subsection chunk is composed of an 8-byte header and the data.</p>
|
|||
|
<p>The header contains a description(a name) and the size of the data contained </p>
|
|||
|
<p>in the chunk:</p>
|
|||
|
<p> <uint8 description[4]> <uint32 size></p>
|
|||
|
<p><br></p>
|
|||
|
<p>The name is a four-byte string. It does not need to be null-terminated.</p>
|
|||
|
<p>If the string is less than four bytes in length, the remaining unused bytes</p>
|
|||
|
<p>must be null.</p>
|
|||
|
<p><br></p>
|
|||
|
<p>-- Subsection Chunk Description Definitions</p>
|
|||
|
<p><br></p>
|
|||
|
<p>Note that not all subsection chunk description definitions listed below</p>
|
|||
|
<p>are guaranteed to be in the section chunk. It's just a list of what CAN</p>
|
|||
|
<p>be in a section chunk. This especially applies to the "EXTRA" subsection.</p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "CPU"</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p> </p>
|
|||
|
<p> PC uint16 Program Counter</p>
|
|||
|
<p> A uint8 Accumulator</p>
|
|||
|
<p> P uint8 Processor status register</p>
|
|||
|
<p> X uint8 X register</p>
|
|||
|
<p> Y uint8 Y register</p>
|
|||
|
<p> S uint8 Stack pointer</p>
|
|||
|
<p> RAM uint8[0x800] 2KB work RAM</p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "CPUC" (emulator specific)</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> JAMM uint8 Non-zero value if CPU in a "jammed" state</p>
|
|||
|
<p> IRQL uint8 Non-zero value if IRQs are to be generated constantly</p>
|
|||
|
<p> ICoa int32 Temporary cycle counter</p>
|
|||
|
<p> ICou int32 Cycle counter</p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "PPU"</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> NTAR uint8[0x800] 2 KB of name/attribute table RAM</p>
|
|||
|
<p> PRAM uint8[32] 32 bytes of palette index RAM</p>
|
|||
|
<p> SPRA uint8[0x100] 256 bytes of sprite RAM</p>
|
|||
|
<p> PPU uint8[4] Last values written to $2000 and $2001, the PPU</p>
|
|||
|
<p> status register, and the last value written to</p>
|
|||
|
<p> $2003.</p>
|
|||
|
<p> XOFF uint8 Tile X-offset.</p>
|
|||
|
<p> VTOG uint8 Toggle used by $2005 and $2006.</p>
|
|||
|
<p> RADD uint16 PPU Address Register(address written to/read from</p>
|
|||
|
<p> when $2007 is accessed).</p>
|
|||
|
<p> TADD uint16 PPU Address Register</p>
|
|||
|
<p> VBUF uint8 VRAM Read Buffer</p>
|
|||
|
<p> PGEN uint8 PPU "general" latch. See Ki's document.</p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "CTLR" (somewhat emulator specific)</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> J1RB uint8 Bit to be returned when first joystick is read.</p>
|
|||
|
<p> J2RB uint8 Bit to be returned when second joystick is read.</p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "SND" (somewhat emulator specific)</p>
|
|||
|
<p><br></p>
|
|||
|
<p> NREG uint16 Noise LFSR.</p>
|
|||
|
<p> P17 uint8 Last byte written to $4017.</p>
|
|||
|
<p> PBIN uint8 DMC bit index.</p>
|
|||
|
<p> PAIN uint32 DMC address index(from $8000).</p>
|
|||
|
<p> PSIN uint32 DMC length counter(how many bytes left </p>
|
|||
|
<p> to fetch).</p>
|
|||
|
<p><br></p>
|
|||
|
<p> <to be finished></p>
|
|||
|
<p><br></p>
|
|||
|
<p>---- Section "EXTRA" (varying emulator specificness)</p>
|
|||
|
<p><br></p>
|
|||
|
<p> For iNES-format games(incomplete, and doesn't apply to every game):</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> WRAM uint8[0x2000] 8KB of WRAM at $6000-$7fff</p>
|
|||
|
<p> MEXR uint8[0x8000] (very emulator specific)</p>
|
|||
|
<p> CHRR uint8[0x2000] 8KB of CHR RAM at $0000-$1fff(in PPU address space).</p>
|
|||
|
<p> EXNR uint8[0x800] Extra 2KB of name/attribute table RAM.</p>
|
|||
|
<p> MPBY uint8[32] (very emulator specific)</p>
|
|||
|
<p> MIRR uint8 Current mirroring:</p>
|
|||
|
<p> 0 = "Horizontal"</p>
|
|||
|
<p> 1 = "Vertical"</p>
|
|||
|
<p> $10 = Mirror from $2000</p>
|
|||
|
<p> $11 = Mirror from $2400</p>
|
|||
|
<p> IRQC uint32 Generic IRQ counter</p>
|
|||
|
<p> IQL1 uint32 Generic IRQ latch</p>
|
|||
|
<p> IQL2 uint32 Generic IRQ latch</p>
|
|||
|
<p> IRQA uint8 Generic IRQ on/off register.</p>
|
|||
|
<p> PBL uint8[4] List of 4 8KB ROM banks paged in at $8000-$FFFF</p>
|
|||
|
<p> CBL uint8[8] List of 8 1KB VROM banks page in at $0000-$1FFF(PPU).</p>
|
|||
|
<p><br></p>
|
|||
|
<p> For FDS games(incomplete):</p>
|
|||
|
<p><br></p>
|
|||
|
<p> Name: Type: Description:</p>
|
|||
|
<p><br></p>
|
|||
|
<p> DDT<x> uint8[65500] Disk data for side x(0-3).</p>
|
|||
|
<p> FDSR uint8[0x8000] 32 KB of work RAM</p>
|
|||
|
<p> CHRR uint8[0x2000] 8 KB of CHR RAM</p>
|
|||
|
<p> IRQC uint32 IRQ counter</p>
|
|||
|
<p> IQL1 uint32 IRQ latch</p>
|
|||
|
<p> IRQA uint8 IRQ on/off.</p>
|
|||
|
<p><br></p>
|
|||
|
<p> WAVE uint8[64] Carrier waveform data.</p>
|
|||
|
<p> MWAV uint8[32] Modulator waveform data.</p>
|
|||
|
<p> AMPL uint8[2] Amplitude data.</p>
|
|||
|
<p><br></p>
|
|||
|
<p class="rvps2"><span class="rvts13">Created with the Personal Edition of HelpNDoc: </span><a class="rvts14" href="http://www.helpndoc.com/feature-tour">Easily create HTML Help documents</a></p>
|
|||
|
</div>
|
|||
|
|
|||
|
<div id="topic_footer">
|
|||
|
|
|||
|
<div id="topic_footer_content">
|
|||
|
2012</div>
|
|||
|
</div>
|
|||
|
</body>
|
|||
|
|
|||
|
</html>
|
|||
|
|