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