Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
snapshot.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2015,2016 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #include "xep128.h"
20 #include "snapshot.h"
21 #include "configuration.h"
22 #include "cpu.h"
23 #include "roms.h"
24 
25 
26 
27 static const Uint8 ep128emu_snapshot_marker[] = {
28  0x5D, 0x12, 0xE4, 0xF4, 0xC9, 0xDA, 0xB6, 0x42, 0x01, 0x33, 0xDE, 0x07, 0xD2, 0x34, 0xF2, 0x22
29 };
30 
31 #define BLOCK_Z80 0
32 #define BLOCK_MEM 1
33 #define BLOCK_IO 2
34 #define BLOCK_DAVE 3
35 #define BLOCK_NICK 4
36 #define BLOCK_MACH 5
37 #define BLOCK_TYPES 6
38 
39 #ifndef DISABLE_DEBUG
40 // <Z80>0 <MEM>1 <IO>2 <DAVE>3 <NICK>4 <MACHINE>5
41 static const char *block_names[BLOCK_TYPES] = { "Z80", "MEM", "IO", "DAVE", "NICK", "MACHINE" };
42 #endif
43 static const Uint32 block_types[BLOCK_TYPES] = { 0x45508001, 0x45508002, 0x45508003, 0x45508004, 0x45508005, 0x45508009 };
44 static const int block_versions[BLOCK_TYPES] = { 0x1000002, 0x1000000, 0x1000000, 0x1000000, 0x4000000, -1 };
45 
46 static int block_offsets[BLOCK_TYPES];
47 static int block_sizes[BLOCK_TYPES];
48 static Uint8 *snap = NULL;
49 
50 
51 
52 
53 
54 
55 static inline Uint32 getSnapDword ( const Uint8 *stream, int pos ) {
56  return (stream[pos] << 24) | (stream[pos + 1] << 16) | (stream[pos + 2] << 8) | stream[pos + 3];
57 }
58 
59 
60 static inline Uint16 getSnapWord ( const Uint8 *stream, int pos ) {
61  return (stream[pos] << 8) | stream[pos + 1];
62 }
63 
64 
65 int ep128snap_load ( const char *fn )
66 {
67  long snapsize;
68  int pos;
69  char pathbuffer[PATH_MAX + 1];
70  FILE *f = open_emu_file(fn, "rb", pathbuffer);
71  if (!f) {
72  ERROR_WINDOW("Cannot open requestes snapshot file: %s", fn);
73  return 1;
74  }
75  if (fseek(f, 0, SEEK_END)) {
76  ERROR_WINDOW("Cannot seek snapshot file: %s", pathbuffer);
77  goto error;
78  }
79  snapsize = ftell(f);
80  DEBUGPRINT("SNAPSHOT: LOAD: %s (%ld bytes)" NL, fn, snapsize);
81  if (snapsize < 16 || snapsize >= 0x500000) {
82  ERROR_WINDOW("Too short or long snapshot file: %s", pathbuffer);
83  goto error;
84  }
85  rewind(f);
86  snap = malloc(snapsize);
87  if (!snap) {
88  ERROR_WINDOW("Not enough memory for loading snapshot");
89  goto error;
90  }
91  if (fread(snap, snapsize, 1, f) != 1) {
92  ERROR_WINDOW("Cannot read snapshot file");
93  goto error;
94  }
95  fclose(f);
96  f = NULL;
97  if (memcmp(snap, ep128emu_snapshot_marker, sizeof ep128emu_snapshot_marker)) {
98  ERROR_WINDOW("Invalid ep128emu snapshot (identifier not found)");
99  goto error;
100  }
101  for (pos = 0; pos < BLOCK_TYPES; pos++)
102  block_offsets[pos] = 0;
103  pos = 16;
104  for (;;) {
105  Uint32 btype, bsize;
106  int bindex;
107  if (pos + 8 >= snapsize) {
108  ERROR_WINDOW("Invalid snapshot file: truncated (during block header)");
109  goto error;
110  }
111  btype = getSnapDword(snap, pos);
112  if (!btype)
113  break;
114  bsize = getSnapDword(snap, pos + 4);
115  pos += 8;
116  if (pos + bsize + 4 >= snapsize) {
117  ERROR_WINDOW("Invalid snapshot file: truncated (during block data)");
118  goto error;
119  }
120  for (bindex = 0 ;; bindex++)
121  if (bindex == BLOCK_TYPES) {
122  ERROR_WINDOW("Invalid snapshot file: Unknown block type: %Xh", btype);
123  goto error;
124  } else if (btype == block_types[bindex])
125  break;
126  if (block_offsets[bindex]) {
127  ERROR_WINDOW("Invalid snapshot file: duplicated block %Xh", block_types[bindex]);
128  goto error;
129  }
130  if (block_versions[bindex] != -1) {
131  Uint32 bver = getSnapDword(snap, pos);
132  if (bver != block_versions[bindex]) {
133  ERROR_WINDOW("Invalid snapshot file: bad block version %Xh (should be %Xh) for block %Xh",
134  bver, block_versions[bindex], block_types[bindex]
135  );
136  goto error;
137  }
138  pos += 4;
139  bsize -= 4;
140  }
141  block_offsets[bindex] = pos;
142  block_sizes[bindex] = bsize;
143  DEBUG("SNAPSHOT: block #%d %Xh(%s) @%06Xh" NL, bindex, block_types[bindex], block_names[bindex], block_offsets[bindex]);
144  pos += bsize + 4;
145  }
146  /* Check all needed blocks, if exists in the snapshot */
147  for (pos = 0; pos < BLOCK_TYPES; pos++)
148  if (block_versions[pos] != -1 && !block_offsets[pos]) {
149  ERROR_WINDOW("Invalid snapshot file: missing block %Xh", block_types[pos]);
150  goto error;
151  }
152  /* Populate memory */
153  if ((block_sizes[BLOCK_MEM] - 4) % 0x4002) {
154  ERROR_WINDOW("Invalid snapshot file: memory dump size is not multiple of 16Ks");
155  goto error;
156  }
157 
158 
159  //printf("Memory = %Xh %f" NL, block_sizes[BLOCK_MEM], (block_sizes[BLOCK_MEM] - 4) / (float)0x4002);
160 
161  xep_rom_seg = -1; // with snapshots, no XEP rom is possible :( [at least not with ep128emu snapshots too much ...]
162 
163  memset(memory, 0xFF, 0x400000);
164  for (pos = 0; pos < 0x100; pos++) {
165  rom_name_tab[pos] = NULL;
166  memory_segment_map[pos] = (pos >= 0xFC) ? VRAM_SEGMENT : UNUSED_SEGMENT;
167  }
168 
169 
170  for (pos = block_offsets[BLOCK_MEM] + 4; pos < block_offsets[BLOCK_MEM] + block_sizes[BLOCK_MEM]; pos += 0x4002) {
171  //printf("SEG %02X %02X" NL, snap[pos], snap[pos + 1]);
172  if (snap[pos] < 0xFC)
173  memory_segment_map[snap[pos]] = snap[pos + 1] ? ROM_SEGMENT : RAM_SEGMENT;
174  //rom_name_tab[snap[pos]] = strdup(pathbuffer);
175  }
176  ep_init_ram();
177  for (pos = block_offsets[BLOCK_MEM] + 4; pos < block_offsets[BLOCK_MEM] + block_sizes[BLOCK_MEM]; pos += 0x4002)
178  memcpy(memory + (snap[pos] << 14), snap + pos + 2, 0x4000);
179  return 0;
180 error:
181  if (f)
182  fclose(f);
183  if (snap) {
184  free(snap);
185  snap = NULL;
186  }
187  return 1;
188 }
189 
190 
191 
193 {
194  int pos;
195  /* Z80 */
196  pos = block_offsets[BLOCK_Z80];
197  Z80_PC = getSnapWord(snap, pos);
198  DEBUG("SNAPSHOT: Z80: PC is %04Xh" NL, Z80_PC);
199  Z80_A = snap[pos + 2]; Z80_F = snap[pos + 3];
200  Z80_B = snap[pos + 4]; Z80_C = snap[pos + 5];
201  Z80_D = snap[pos + 6]; Z80_E = snap[pos + 7];
202  Z80_H = snap[pos + 8]; Z80_L = snap[pos + 9];
203  Z80_SP = getSnapWord(snap, pos + 10);
204  Z80_IXH = snap[pos + 12]; Z80_IXL = snap[pos + 13];
205  Z80_IYH = snap[pos + 14]; Z80_IYL = snap[pos + 15];
206  Z80_A_ = snap[pos + 16]; Z80_F_ = snap[pos + 17];
207  Z80_B_ = snap[pos + 18]; Z80_C_ = snap[pos + 19];
208  Z80_D_ = snap[pos + 20]; Z80_E_ = snap[pos + 21];
209  Z80_H_ = snap[pos + 22]; Z80_L_ = snap[pos + 23];
210  Z80_I = snap[pos + 24];
211  Z80_R = snap[pos + 25] & 127;
212  // 26 27 28 29 -> internal reg
213  Z80_IFF1 = snap[pos + 30] & 1;
214  Z80_IFF2 = snap[pos + 31] & 1;
215  Z80_R7 = snap[pos + 32] & 128;
216  Z80_IM = snap[pos + 33];
217  /* I/O ports */
218  for (pos = 0; pos < 256; pos++)
219  ports[pos] = snap[block_offsets[BLOCK_IO] + pos];
220  for (pos = 0xA0; pos <= 0xBF; pos++)
221  z80ex_pwrite_cb(pos, snap[block_offsets[BLOCK_IO] + pos]);
222  for (pos = 0; pos < 4; pos++) {
223  z80ex_pwrite_cb(0xB0 | pos, snap[block_offsets[BLOCK_MEM] + pos]);
224  z80ex_pwrite_cb(0x80 | pos, snap[block_offsets[BLOCK_IO] + 0x80 + pos]);
225  }
226  z80ex_pwrite_cb(0x83, snap[block_offsets[BLOCK_IO] + 0x83] & 127 );
227  z80ex_pwrite_cb(0x83, snap[block_offsets[BLOCK_IO] + 0x83] | 128 | 64);
228  /* END */
229  free(snap);
230  snap = NULL;
231 }
Z80_B_
#define Z80_B_
Definition: z80ex.h:95
Z80_L_
#define Z80_L_
Definition: z80ex.h:104
BLOCK_TYPES
#define BLOCK_TYPES
Definition: snapshot.c:37
Z80_IYL
#define Z80_IYL
Definition: z80ex.h:112
rom_name_tab
const char * rom_name_tab[0x100]
Definition: roms.c:36
xep_rom_seg
int xep_rom_seg
Definition: roms.c:33
Z80_D
#define Z80_D
Definition: z80ex.h:83
BLOCK_Z80
#define BLOCK_Z80
Definition: snapshot.c:31
UNUSED_SEGMENT
const char UNUSED_SEGMENT[]
Definition: cpu.c:56
ep128snap_set_cpu_and_io
void ep128snap_set_cpu_and_io(void)
Definition: snapshot.c:203
Z80_A
#define Z80_A
Definition: z80ex.h:75
z80ex_pwrite_cb
void z80ex_pwrite_cb(Z80EX_WORD port16, Z80EX_BYTE value)
Definition: cpu.c:396
Z80_F_
#define Z80_F_
Definition: z80ex.h:92
Z80_SP
#define Z80_SP
Definition: z80ex.h:117
Z80_R7
#define Z80_R7
Definition: z80ex.h:125
BLOCK_MEM
#define BLOCK_MEM
Definition: snapshot.c:32
Z80_I
#define Z80_I
Definition: z80ex.h:123
Z80_IYH
#define Z80_IYH
Definition: z80ex.h:111
roms.h
Z80_H_
#define Z80_H_
Definition: z80ex.h:103
fn
const char * fn
Definition: roms.c:42
ep_init_ram
int ep_init_ram(void)
Definition: cpu.c:194
Z80_L
#define Z80_L
Definition: z80ex.h:88
BLOCK_IO
#define BLOCK_IO
Definition: snapshot.c:33
Uint32
uint32_t Uint32
Definition: fat32.c:49
Z80_IFF1
#define Z80_IFF1
Definition: z80ex.h:127
Uint8
uint8_t Uint8
Definition: fat32.c:51
open_emu_file
FILE * open_emu_file(const char *name, const char *mode, char *pathbuffer)
Definition: configuration.c:109
cpu.h
Z80_IXL
#define Z80_IXL
Definition: z80ex.h:108
Z80_IFF2
#define Z80_IFF2
Definition: z80ex.h:128
Z80_C_
#define Z80_C_
Definition: z80ex.h:96
memory_segment_map
const char * memory_segment_map[0x100]
Definition: cpu.c:44
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
ep128snap_load
int ep128snap_load(const char *fn)
Definition: snapshot.c:68
Z80_H
#define Z80_H
Definition: z80ex.h:87
Z80_F
#define Z80_F
Definition: z80ex.h:76
NL
#define NL
Definition: fat32.c:37
Z80_E
#define Z80_E
Definition: z80ex.h:84
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
Z80_IXH
#define Z80_IXH
Definition: z80ex.h:107
VRAM_SEGMENT
const char VRAM_SEGMENT[]
Definition: cpu.c:54
Z80_IM
#define Z80_IM
Definition: z80ex.h:129
Z80_A_
#define Z80_A_
Definition: z80ex.h:91
Z80_R
#define Z80_R
Definition: z80ex.h:124
snapshot.h
xep128.h
Z80_C
#define Z80_C
Definition: z80ex.h:80
Z80_PC
#define Z80_PC
Definition: z80ex.h:121
Z80_D_
#define Z80_D_
Definition: z80ex.h:99
Z80_B
#define Z80_B
Definition: z80ex.h:79
configuration.h
stream
Uint8 * stream
Definition: inject.c:36
Uint16
uint16_t Uint16
Definition: fat32.c:50
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
RAM_SEGMENT
const char RAM_SEGMENT[]
Definition: cpu.c:53
Z80_E_
#define Z80_E_
Definition: z80ex.h:100
ROM_SEGMENT
const char ROM_SEGMENT[]
Definition: cpu.c:51