Any docs about this format?
Would be cool to know how it works...
Err... Not really complete. There is a document on the initial SNA Version 3 format
hereAnd then the format is very similar to the SNP format but with some extras. I'll have to hunt for any documentation, or failing that analyse the source code to create it.
Here's the headers from WinAPE which define the SNA V3 format:
{ TODO: Save Disc Image names, active ROMs, CPC Plus Raster Int flag }
{ TODO: PS2 Mouse X/Y and Button states in SNR }
const
HeaderSNA: String = 'MV - SNA';
HeaderSNP: String = 'MV - SNP';
HeaderSNR: String = 'RW - SNR';
CRTC_FLAG_VSYNC_ACTIVE = $01;
CRTC_FLAG_HSYNC_ACTIVE = $02;
CRTC_FLAG_HDISP_INACTIVE = $04;
CRTC_FLAG_VDISP_INACTIVE = $08;
CRTC_FLAG_HTOT_REACHED = $10;
CRTC_FLAG_VTOT_REACHED = $20;
CRTC_FLAG_MAXIMUM_RASTER_COUNT_REACHED = $40;
CRTC_FLAG_REG8_BLANKING = $80;
CRTC_FLAG_VTA_ACTIVE = $100;
CRTC_FLAG_WINAPE_ICSR = $8000;
SFormatInvalid: String = 'Snapshot format invalid';
type
TSnapshotType = (SNA, SNR, SNP);
TBankFlag = (c0, c4c7, cccf, d4d7, dcdf, e4e7, ecef, f4f7, fcff);
TBankFlags = set of TBankFlag;
TChunkFlag = ( cfROMs, cfDSCA, cfDSCB, cfBreaks, cfDataAreas );
TChunkFlags = set of TChunkFlag;
TSnapshotHeader = packed record
SnapshotID: packed array[0..7] of char;
pad0 : packed array[0..7] of char;
Version: Byte;
{Registers}
REG_AF,REG_BC,REG_DE,REG_HL: word;
REG_R,REG_I,REG_IFF0,REG_IFF1: byte;
REG_IX,REG_IY,REG_SP,REG_PC: word;
REG_IM: byte;
REG_AF1,REG_BC1,REG_DE1,REG_HL1: word;
GA_Pen: byte;
GA_Inks: packed array[0..16] of byte;
GA_ROM, GA_RAM: byte;
CRTC_Reg: byte;
CRTC_Regs: packed array [0..17] of byte;
UpperRom: byte;
PIO_A,PIO_B,PIO_C,PIO_Control: byte;
PSG_Reg: byte;
PSG_Regs: packed array[0..15] of byte;
MemSize: word;
CPCType: byte;
InterruptNo: byte; // CPCEMU only
MultiMode: packed array[0..5] of byte; // CPCEMU only
// Version 3 only
Empty1: packed array[$75..$9a] of byte;
FDD_Fast: Boolean;
FDD_Motor: Boolean;
FDD_Cyl: packed array[0..3] of byte;
Printer_Data: byte;
Monitor_Line: SmallInt;
CRTC_Type: byte;
Empty3: packed array [$a5..$a8] of byte;
CRTC_HCC: byte;
Empty4: byte;
CRTC_VCC: byte;
CRTC_VLC: byte;
CRTC_VTAC: byte;
CRTC_HSYNC: byte;
CRTC_VSYNC: byte;
CRTC_Flags: word;
GA_DelayCount: byte;
GA_ScanCount: byte;
Z80_IntStat: byte;
Z80_ICSR: byte;
DisablePlus: Boolean;
PlusPPI: Boolean;
Empty5: packed array [$b8..$df] of byte;
EmulatorID: packed array [$e0..$ff] of char;
end;
TDMARegs = packed record
Loop: Word;
Addr: Word;
Pause: Word;
PreScale: byte;
end;
TPlusChunk = packed record
SpriteData: packed array [0..$7ff] of byte;
SpriteAtts: packed array [0..$7f] of byte;
Palette: packed array [0..$3f] of byte;
Regs: packed array [0..5] of byte;
SecROM: Word;
Analogue: packed array [$08..$0f] of byte;
DMA: packed array [0..$f] of byte;
DMARegs: packed array [0..2] of TDMARegs;
GA_Last: byte;
GA_UnLocked: byte;
GA_Sequence: byte;
end;
The SNR file can contain RIFF sections defining the Disk images and ROM images active at the time of recording.
The SNR file ends with an SNR RIFF chunk (ID: 'SNR '). This contains all the keystrokes and timing information as well as Symbiface Mouse and RTC information. The following constants are used to define the ID's of these:
{ Mouse Bits for SNR recording }
SNR_MOUSE = $80;
SNR_MB = $01;
SNR_MX = $60;
SNR_MX_B = $20;
SNR_MX_W = $40;
SNR_MY = $18;
SNR_MY_B = $08;
SNR_MY_W = $10;
SNR_MW = $06;
SNR_MW_B = $02;
SNR_MW_W = $04;
{ Real-Time Clock IDs }
SNR_RTC = $E0;
SNR_MIN = $E1;
SNR_HR = $E2;
SNR_DAY = $E3;
SNR_MTH = $E4;
SNR_YR = $E5;
SNR_MIL = $E6;
The actual SNR format is quite complicated due to limitations of the original SNP format and the work-arounds to get it accurate. This is by no means complete, but I think it's something along the lines of:
Count (Byte) - Number of frames until next change or 00. If 00, then a further word is used to indicate the number of frames. For example:
05 = 5 frames.
00 01 02 = 513 frames.
After that number of frames has passed, the next byte is read (the block length specifier (BLS)). Bit 7 (and #80) determines if there is a synchronisation block. If this is set, the following data (bytes) are contained in the synch block:
+0: Least significant byte of current Z80 PC (Program Counter)
+1: Vertical Line Count of CRTC.
+2: Horizontal Character Count of CRTC.
+3: Least significant byte of the TotalCycles counter (always reset to zero at the start of the SNR file snapshot).
The following 7 bits of the BLS define the number of bytes that follow unless they are all 1 (ie. BLS and #7f == #7f). This has a special meaning, which is to repeat the same changes as the last frame.
Each byte following for (BLS and #7f bytes) represents either a key number or a Mouse or RTC update.
If the byte (call it CHG) is E0..FF it is treated as an RTC update. The number of following bytes is (CHG and #1F) + 1, so, if CHG is SNR_RTC (#E0) only the RTC second is updated (1 following byte), if CHG is SNR_DAY (#E4), the RTC second, minute, hour, day and day of week is updated. The Day of Week is the fourth byte and #07, the Day (1..31) is the same byte SHL 3 (div

.
If the CHG is #80 .. #df it is treated as a Mouse Update.
- If (CHG and SNR_MB) <> 0 the Mouse Button byte is read.
- If (CHG and SNR_MX) <> 0 the Mouse X position is updated (if (CHG and SNR_MX_W) then it's a word else a byte).
- If (CHG and SNR_MY) <> 0 the Mouse Y position is updated (if (CHG and SNR_MY_W) then it's a word else a byte).
- If (CHG and SNR_MW) <> 0 the Mouse Wheel position is updated. (if (CHG and SNR_MW_W) then it's a word else a byte).
...
And that's all there is to it. Really simple eh !
Cheers,
Richard
P.S. I would make a Wiki page about the SNR format from this post but I'm useless at Wiki code and I don't have much time. Anyone else feel free to do so.