cargador.cpp 15.8 KB
Newer Older
Sergio Costas's avatar
Sergio Costas committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright 2003-2009 (C) Raster Software Vigo (Sergio Costas)
 * This file is part of FBZX
 *
 * FBZX is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * FBZX is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 *
Sergio Costas's avatar
Sergio Costas committed
18 19
 */

Sergio Costas's avatar
Sergio Costas committed
20 21
#include "cargador.hh"

Sergio Costas's avatar
Sergio Costas committed
22 23 24
#include "z80free/Z80free.h"
#include <stdio.h>
#include <string.h>
Sergio Costas's avatar
Sergio Costas committed
25 26
#include "computer.hh"
#include "emulator.hh"
27
#include "keyboard.hh"
28
#include "spk_ay.hh"
Sergio Costas's avatar
Sergio Costas committed
29

30
void uncompress_z80(FILE *fichero, int length, unsigned char *memo) {
Sergio Costas's avatar
Sergio Costas committed
31

32
	unsigned char byte_loaded, EDfound, counter;
Sergio Costas's avatar
Sergio Costas committed
33
	int position;
Sergio Costas's avatar
Sergio Costas committed
34

35 36 37 38 39 40 41
	counter = 0;
	byte_loaded = 0;
	EDfound = 0;
	position = 0;

	printf("Descomprimo de longitud %d\n", length);

Sergio Costas's avatar
Sergio Costas committed
42
	do {
43 44
		if (counter) {
			memo[position++] = byte_loaded;
Sergio Costas's avatar
Sergio Costas committed
45 46 47
			counter--;
			continue;
		} else
48 49 50 51 52 53
			fread(&byte_loaded, 1, 1, fichero);

		if (EDfound == 2) { // we have two EDs
			counter = byte_loaded;
			fread(&byte_loaded, 1, 1, fichero);
			EDfound = 0;
Sergio Costas's avatar
Sergio Costas committed
54 55
			continue;
		}
56 57 58

		if (byte_loaded == 0xED) {
			EDfound++;
Sergio Costas's avatar
Sergio Costas committed
59
		} else {
60 61 62
			if (EDfound == 1) { // we found ED xx. We write ED and xx
				memo[position++] = 0xED;
				EDfound = 0;
Sergio Costas's avatar
Sergio Costas committed
63
			}
64
			if (position >= length) {
Sergio Costas's avatar
Sergio Costas committed
65 66
				break;
			}
67
			memo[position++] = byte_loaded;
Sergio Costas's avatar
Sergio Costas committed
68
		}
69
	} while (position < length);
Sergio Costas's avatar
Sergio Costas committed
70 71 72 73 74

}

int save_z80(char *filename) {

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	FILE *fichero;
	unsigned char value, bucle;

	fichero = fopen(filename, "r");
	if (fichero != NULL) {
		fclose(fichero);
		return -1; // file already exists
	}

	fichero = fopen(filename, "w");

	if (fichero == NULL)
		return -2; // can't create file

	fprintf(fichero, "%c%c%c%c%c%c", procesador.Rm.br.A, procesador.Rm.br.F,
			procesador.Rm.br.C, procesador.Rm.br.B, procesador.Rm.br.L,
			procesador.Rm.br.H); // AF, BC and HL

	if (ordenador->mode128k == 0) // 48K
		fprintf(fichero, "%c%c", (byte) (procesador.PC & 0x0FF),
				(byte) ((procesador.PC >> 8) & 0xFF)); // PC
	else
		fprintf(fichero, "%c%c", 0, 0); // 128K

	fprintf(fichero, "%c%c", procesador.Rm.br.P, procesador.Rm.br.S); // SP
	fprintf(fichero, "%c%c%c", procesador.I, procesador.R,
			(((procesador.R2 >> 7) & 0x01) | ((screen->border << 1) & 0x0E))); // I, R and border color

	fprintf(fichero, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c", procesador.Rm.br.E,
			procesador.Rm.br.D, procesador.Ra.br.C, procesador.Ra.br.B,
			procesador.Ra.br.E, procesador.Ra.br.D, procesador.Ra.br.L,
			procesador.Ra.br.H, procesador.Ra.br.A, procesador.Ra.br.F,
			procesador.Rm.br.IYl, procesador.Rm.br.IYh, procesador.Rm.br.IXl,
			procesador.Rm.br.IXh);

	if (procesador.IFF1)
		value = 1;
	else
		value = 0;
	fprintf(fichero, "%c", value);
	if (procesador.IFF2)
		value = 1;
	else
		value = 0;
	fprintf(fichero, "%c", value);
	value = procesador.IM;
	if (ordenador->issue == 2)
		value |= 4;
	switch (keyboard->joystick) {
124
	case JOYSTICK_KEMPSTON:
125 126
		value |= 64;
		break;
127
	case JOYSTICK_SINCLAIR1:
128 129
		value |= 128;
		break;
130
	case JOYSTICK_SINCLAIR2:
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
		value |= 192;
		break;
	}
	fprintf(fichero, "%c", value);

	if (ordenador->mode128k == 0) { // 48K
		fwrite((ordenador->memoria + 147456), 16384, 1, fichero); // video memory
		fwrite((ordenador->memoria + 98304), 32768, 1, fichero); // memory pages 2 & 3
		fclose(fichero);
		return 0;
	}

	// 128K

	fprintf(fichero, "%c%c", 23, 0); // Z80 file v2.01
	fprintf(fichero, "%c%c", (byte) (procesador.PC & 0x0FF),
			(byte) ((procesador.PC >> 8) & 0x0FF)); // PC
	fprintf(fichero, "%c", 3); // hardware mode=3
	fprintf(fichero, "%c", ordenador->mport1); // content of 0x7FFD latch
	fprintf(fichero, "%c%c", 0, 0); // no If1, no emulation of any kind
	fprintf(fichero, "%c", spk_ay->get_latch()); // last selected AY register
	for (bucle = 0; bucle < 16; bucle++)
		fprintf(fichero, "%c", spk_ay->get_value(bucle)); // AY registers
	for (bucle = 0; bucle < 8; bucle++) {
		fprintf(fichero, "%c%c", 0xFF, 0xFF); // length=0xFFFF (uncompressed)
		fprintf(fichero, "%c", bucle + 3); // page number
		fwrite(ordenador->memoria + (16384 * bucle) + 65536, 16384, 1, fichero); // store page
	}
	fclose(fichero);
	return 0;
Sergio Costas's avatar
Sergio Costas committed
161 162
}

163
int load_z80(const char *filename) {
Sergio Costas's avatar
Sergio Costas committed
164

165
	struct z80snapshot *snap;
166
	unsigned char tempo[30], tempo2[56], type, compressed, page, byte_read[3];
167
	unsigned char *memo;
Sergio Costas's avatar
Sergio Costas committed
168
	FILE *fichero;
169
	int longitud = 0, longitud2, bucle;
Sergio Costas's avatar
Sergio Costas committed
170

171 172
	memo = (unsigned char *) malloc(49152);
	snap = (struct z80snapshot *) malloc(sizeof(struct z80snapshot));
173

174 175 176
	longitud = strlen(filename);
	if ((longitud > 4)
			&& (0 == strcasecmp(".sna", filename + (longitud - 4)))) {
Sergio Costas's avatar
Sergio Costas committed
177
		printf("Read SNA file\n");
178 179
		free(memo);
		free(snap);
Sergio Costas's avatar
Sergio Costas committed
180 181 182 183 184
		return load_sna(filename);
	}

	printf("Read Z80 file\n");

185 186
	for (bucle = 0; bucle < 16; bucle++)
		snap->ay_regs[bucle] = 0;
Sergio Costas's avatar
Sergio Costas committed
187

188 189
	fichero = fopen(filename, "r");
	if (fichero == NULL) {
190 191
		free(memo);
		free(snap);
Sergio Costas's avatar
Sergio Costas committed
192
		return -1; // error
193
	}
Sergio Costas's avatar
Sergio Costas committed
194 195

	printf("Read header (first 30 bytes)\n");
196
	fread(tempo, 1, 30, fichero);
Sergio Costas's avatar
Sergio Costas committed
197

198
	if ((tempo[6] == 0) && (tempo[7] == 0)) { // extended Z80
Sergio Costas's avatar
Sergio Costas committed
199
		printf("It's an extended Z80 file\n");
200
		type = 1; // new type
Sergio Costas's avatar
Sergio Costas committed
201

202 203 204 205
		fread(tempo2, 1, 2, fichero); // read the length of the extension

		longitud = ((int) tempo2[0]) + 256 * ((int) tempo2[1]);
		if (longitud > 54) {
Sergio Costas's avatar
Sergio Costas committed
206 207
			fclose(fichero);
			printf("Not suported Z80 file\n");
208 209
			free(memo);
			free(snap);
Sergio Costas's avatar
Sergio Costas committed
210 211
			return -3; // not a supported Z80 file
		}
212 213
		printf("Length: %d\n", longitud);
		fread(tempo2 + 2, 1, longitud, fichero);
Sergio Costas's avatar
Sergio Costas committed
214

215 216
		if (longitud == 23) // z80 ver 2.01
			switch (tempo2[4]) {
Sergio Costas's avatar
Sergio Costas committed
217 218
			case 0:
			case 1:
219
				snap->type = 0; // 48K
Sergio Costas's avatar
Sergio Costas committed
220 221 222
				break;
			case 3:
			case 4:
223 224
				snap->type = 1; // 128K
				break;
Sergio Costas's avatar
Sergio Costas committed
225 226 227
			default:
				fclose(fichero);
				printf("Again not suported Z80 file\n");
228 229
				free(memo);
				free(snap);
Sergio Costas's avatar
Sergio Costas committed
230
				return -3; // not a supported Z80 file
231
				break;
Sergio Costas's avatar
Sergio Costas committed
232
			}
233 234 235
		else
			// z80 ver 3.0x
			switch (tempo2[4]) {
Sergio Costas's avatar
Sergio Costas committed
236 237 238
			case 0:
			case 1:
			case 3:
239
				snap->type = 0; // 48K
Sergio Costas's avatar
Sergio Costas committed
240 241 242 243
				break;
			case 4:
			case 5:
			case 6:
244
				snap->type = 1; // 128K
Sergio Costas's avatar
Sergio Costas committed
245 246 247
				break;
			default:
				fclose(fichero);
248 249
				free(memo);
				free(snap);
Sergio Costas's avatar
Sergio Costas committed
250 251
				return -3; // not a supported Z80 file
				break;
252
			}
Sergio Costas's avatar
Sergio Costas committed
253 254
	} else {
		printf("Old type z80\n");
255 256
		type = 0; // old type
		snap->type = 0; // 48k
Sergio Costas's avatar
Sergio Costas committed
257 258
	}

259
	if (tempo[29] & 0x04) {
Sergio Costas's avatar
Sergio Costas committed
260
		printf("Issue 2\n");
261
		snap->issue = 2; // issue2
Sergio Costas's avatar
Sergio Costas committed
262 263
	} else {
		printf("Issue 3\n");
264
		snap->issue = 3; // issue3
Sergio Costas's avatar
Sergio Costas committed
265 266
	}

267 268 269 270 271 272 273 274 275 276 277
	snap->A = tempo[0];
	snap->F = tempo[1];
	snap->C = tempo[2];
	snap->B = tempo[3];
	snap->L = tempo[4];
	snap->H = tempo[5];
	if (type) {
		snap->PC = ((word) tempo2[2]) + 256 * ((word) tempo2[3]);
		for (bucle = 0; bucle < 16; bucle++)
			snap->ay_regs[bucle] = tempo2[9 + bucle];
		snap->ay_latch = tempo2[8];
Sergio Costas's avatar
Sergio Costas committed
278
	} else {
279
		snap->PC = ((word) tempo[6]) + 256 * ((word) tempo[7]);
Sergio Costas's avatar
Sergio Costas committed
280 281
	}

282 283 284
	snap->SP = ((word) tempo[8]) + 256 * ((word) tempo[9]);
	snap->I = tempo[10];
	snap->R = (tempo[11] & 0x7F);
Sergio Costas's avatar
Sergio Costas committed
285

286
	if (tempo[12] == 255) {
Sergio Costas's avatar
Sergio Costas committed
287
		printf("Byte 12 is 255! doing 1\n");
288
		tempo[12] = 1;
Sergio Costas's avatar
Sergio Costas committed
289 290
	}

291 292
	if (tempo[12] & 0x01)
		snap->R |= 0x80;
Sergio Costas's avatar
Sergio Costas committed
293

294
	snap->border = (tempo[12] >> 1) & 0x07;
Sergio Costas's avatar
Sergio Costas committed
295

296 297
	if (tempo[12] & 32)
		compressed = 1;
Sergio Costas's avatar
Sergio Costas committed
298
	else
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
		compressed = 0;

	snap->E = tempo[13];
	snap->D = tempo[14];
	snap->CC = tempo[15];
	snap->BB = tempo[16];
	snap->EE = tempo[17];
	snap->DD = tempo[18];
	snap->LL = tempo[19];
	snap->HH = tempo[20];
	snap->AA = tempo[21];
	snap->FF = tempo[22];
	snap->IY = ((word) tempo[23]) + 256 * ((word) tempo[24]);
	snap->IX = ((word) tempo[25]) + 256 * ((word) tempo[26]);

	if (tempo[27] != 0)
		snap->IFF1 = 1;
Sergio Costas's avatar
Sergio Costas committed
316
	else
317
		snap->IFF1 = 0;
Sergio Costas's avatar
Sergio Costas committed
318

319 320
	if (tempo[28] != 0)
		snap->IFF2 = 1;
Sergio Costas's avatar
Sergio Costas committed
321
	else
322 323 324
		snap->IFF2 = 0;

	switch (tempo[29] & 0x03) {
Sergio Costas's avatar
Sergio Costas committed
325
	case 0:
326
		snap->Imode = 0;
Sergio Costas's avatar
Sergio Costas committed
327 328
		break;
	case 1:
329
		snap->Imode = 1;
Sergio Costas's avatar
Sergio Costas committed
330 331
		break;
	case 2:
332
		snap->Imode = 2;
Sergio Costas's avatar
Sergio Costas committed
333 334 335
		break;
	}

336
	snap->joystick = ((tempo[29] >> 6) & 0x03);
Sergio Costas's avatar
Sergio Costas committed
337

338 339
	if (type)
		snap->pager = tempo2[5];
Sergio Costas's avatar
Sergio Costas committed
340

341 342
	if (type) { // extended z80
		if (snap->type == 1) { // 128K snapshot
Sergio Costas's avatar
Sergio Costas committed
343

344 345 346 347 348
			/*			 fclose(fichero);
			 return -3;*/	// z80 file not yet supported
			while (!feof(fichero)) {
				fread(byte_read, 3, 1, fichero);
				if (feof(fichero))
Sergio Costas's avatar
Sergio Costas committed
349
					break;
350 351
				longitud2 = ((int) byte_read[0]) + 256 * ((int) byte_read[1]);
				switch (byte_read[2]) {
Sergio Costas's avatar
Sergio Costas committed
352
				case 3:
353
					page = 0;
Sergio Costas's avatar
Sergio Costas committed
354 355
					break;
				case 4:
356
					page = 1;
Sergio Costas's avatar
Sergio Costas committed
357 358
					break;
				case 5:
359
					page = 2;
Sergio Costas's avatar
Sergio Costas committed
360 361
					break;
				case 6:
362
					page = 3;
Sergio Costas's avatar
Sergio Costas committed
363 364
					break;
				case 7:
365
					page = 4;
Sergio Costas's avatar
Sergio Costas committed
366 367
					break;
				case 8:
368
					page = 5;
Sergio Costas's avatar
Sergio Costas committed
369 370
					break;
				case 9:
371
					page = 6;
Sergio Costas's avatar
Sergio Costas committed
372 373
					break;
				case 10:
374
					page = 7;
Sergio Costas's avatar
Sergio Costas committed
375 376
					break;
				default:
377
					page = 11;
Sergio Costas's avatar
Sergio Costas committed
378 379
					break;
				}
380 381 382
				printf("Loading page %d of length %d\n", page, longitud);
				if (longitud2 == 0xFFFF) // uncompressed raw data
					fread(snap->page[page], 16384, 1, fichero);
Sergio Costas's avatar
Sergio Costas committed
383
				else
384
					uncompress_z80(fichero, 16384, snap->page[page]);
Sergio Costas's avatar
Sergio Costas committed
385 386 387
			}

		} else {
388 389 390
			while (!feof(fichero)) {
				fread(byte_read, 3, 1, fichero);
				if (feof(fichero))
Sergio Costas's avatar
Sergio Costas committed
391
					break;
392 393
				longitud2 = ((int) byte_read[0]) + 256 * ((int) byte_read[1]);
				switch (byte_read[2]) {
Sergio Costas's avatar
Sergio Costas committed
394
				case 8:
395
					page = 0;
Sergio Costas's avatar
Sergio Costas committed
396 397
					break;
				case 4:
398
					page = 1;
Sergio Costas's avatar
Sergio Costas committed
399 400
					break;
				case 5:
401
					page = 2;
Sergio Costas's avatar
Sergio Costas committed
402 403
					break;
				default:
404
					page = 11;
Sergio Costas's avatar
Sergio Costas committed
405 406
					break;
				}
407 408
				if (longitud2 == 0xFFFF) // uncompressed raw data
					fread(snap->page[page], 16384, 1, fichero);
Sergio Costas's avatar
Sergio Costas committed
409
				else
410
					uncompress_z80(fichero, 16384, snap->page[page]);
Sergio Costas's avatar
Sergio Costas committed
411 412 413 414
			}
		}
	} else {

415
		if (compressed) {
Sergio Costas's avatar
Sergio Costas committed
416
			// 48k compressed z80 loader
417

Sergio Costas's avatar
Sergio Costas committed
418
			// we uncompress first the data
419 420 421 422 423 424 425

			uncompress_z80(fichero, 49152, memo);

			memcpy(snap->page[0], memo, 16384);
			memcpy(snap->page[1], memo + 16384, 16384);
			memcpy(snap->page[2], memo + 32768, 16384);

Sergio Costas's avatar
Sergio Costas committed
426 427
		} else {
			// 48k uncompressed z80 loader
428 429 430 431

			fread(snap->page[0], 16384, 1, fichero);
			fread(snap->page[1], 16384, 1, fichero);
			fread(snap->page[2], 16384, 1, fichero);
Sergio Costas's avatar
Sergio Costas committed
432
		}
433

Sergio Costas's avatar
Sergio Costas committed
434 435
	}

436
	load_snap(snap);
Sergio Costas's avatar
Sergio Costas committed
437
	fclose(fichero);
438 439
	free(memo);
	free(snap);
Sergio Costas's avatar
Sergio Costas committed
440 441 442
	return 0; // all right
}

443
int load_sna(const char *filename) {
Sergio Costas's avatar
Sergio Costas committed
444

445 446
	unsigned char *tempo;
	unsigned char *tempo2;
447
	unsigned char type = 0;
Sergio Costas's avatar
Sergio Costas committed
448
	FILE *fichero;
449
	struct z80snapshot *snap;
450 451 452 453 454 455
	unsigned char v1, v2;
	int addr, loop;

	tempo = (unsigned char *) malloc(49179);
	tempo2 = (unsigned char *) malloc(98308);
	snap = (struct z80snapshot *) malloc(sizeof(struct z80snapshot));
Sergio Costas's avatar
Sergio Costas committed
456 457

	printf("Loading SNA file\n");
458 459 460

	fichero = fopen(filename, "r");
	if (fichero == NULL) {
461 462 463
		free(tempo);
		free(tempo2);
		free(snap);
Sergio Costas's avatar
Sergio Costas committed
464
		return -1; // error
465
	}
Sergio Costas's avatar
Sergio Costas committed
466

467
	if (1 != fread(tempo, 49179, 1, fichero)) {
468 469 470
		free(tempo);
		free(tempo2);
		free(snap);
Sergio Costas's avatar
Sergio Costas committed
471
		fclose(fichero);
Sergio Costas's avatar
Sergio Costas committed
472 473
		return -1;
	}
474 475

	if (0 == fread(tempo2, 1, 98308, fichero)) {
Sergio Costas's avatar
Sergio Costas committed
476
		printf("48K SNA\n");
477
		type = 0;
Sergio Costas's avatar
Sergio Costas committed
478 479
	} else {
		printf("128K SNA\n");
480
		type = 1;
Sergio Costas's avatar
Sergio Costas committed
481
	}
482 483

	snap->type = type;
484 485

	//Some inits
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
	for (loop = 0; loop < 16; loop++)
		snap->ay_regs[loop] = 0;
	snap->ay_latch = 0;
	snap->issue = 3;
	snap->joystick = 1; //kempston

	snap->I = tempo[0];
	snap->LL = tempo[1];
	snap->HH = tempo[2];
	snap->EE = tempo[3];
	snap->DD = tempo[4];
	snap->CC = tempo[5];
	snap->BB = tempo[6];
	snap->FF = tempo[7];
	snap->AA = tempo[8];

	snap->L = tempo[9];
	snap->H = tempo[10];
	snap->E = tempo[11];
	snap->D = tempo[12];
	snap->C = tempo[13];
	snap->B = tempo[14];

	snap->IY = ((word) tempo[15]) + 256 * ((word) tempo[16]);
	snap->IX = ((word) tempo[17]) + 256 * ((word) tempo[18]);

	if (tempo[19] & 0x01) {
		snap->IFF1 = 1;
Sergio Costas's avatar
Sergio Costas committed
514
	} else {
515
		snap->IFF1 = 0;
Sergio Costas's avatar
Sergio Costas committed
516
	}
517 518 519

	if (tempo[19] & 0x02) {
		snap->IFF2 = 1;
Sergio Costas's avatar
Sergio Costas committed
520
	} else {
521
		snap->IFF2 = 0;
Sergio Costas's avatar
Sergio Costas committed
522
	}
523 524 525 526 527 528 529 530 531 532 533 534 535 536

	snap->R = tempo[20];
	snap->F = tempo[21];
	snap->A = tempo[22];
	snap->SP = ((word) tempo[23]) + 256 * ((word) tempo[24]);
	snap->Imode = tempo[25];
	snap->border = tempo[26];

	if (type == 0) {

		v1 = tempo[23];
		v2 = tempo[24];
		addr = ((int) v1) + 256 * ((int) v2);
		if ((addr < 16384) || (addr >= 65534)) {
537 538 539
			free(tempo);
			free(tempo2);
			free(snap);
Sergio Costas's avatar
Sergio Costas committed
540
			fclose(fichero);
Sergio Costas's avatar
Sergio Costas committed
541 542 543
			printf("Error loading SNA file. Return address in ROM.\n");
			return -1;
		}
544 545 546 547 548 549 550 551 552 553
		addr -= 16384;
		addr += 27;
		snap->PC = ((word) tempo[addr]) + 256 * ((word) tempo[addr + 1]);
		tempo[addr] = 0;
		tempo[addr + 1] = 0;
		snap->SP += 2;
		snap->IFF1 = snap->IFF2;
		memcpy(snap->page[0], tempo + 27, 16384);
		memcpy(snap->page[1], tempo + 16411, 16384);
		memcpy(snap->page[2], tempo + 32795, 16384);
Sergio Costas's avatar
Sergio Costas committed
554
	} else {
555 556 557 558 559 560 561 562 563 564
		snap->PC = ((word) tempo2[0]) + 256 * ((word) tempo2[1]);
		memcpy(snap->page[5], tempo + 27, 16384);
		memcpy(snap->page[2], tempo + 16411, 16384);
		v1 = tempo[2];
		snap->pager = v1;
		v1 &= 0x07;
		memcpy(snap->page[v1], tempo + 32795, 16384);
		addr = 4;
		for (loop = 0; loop < 7; loop++) {
			if ((loop == 2) || (loop == 5) || (loop == ((int) v1))) {
Sergio Costas's avatar
Sergio Costas committed
565 566
				continue;
			}
567 568
			memcpy(snap->page[loop], tempo2 + addr, 16384);
			addr += 16384;
Sergio Costas's avatar
Sergio Costas committed
569 570
		}
	}
571

572 573 574 575
	load_snap(snap);
	free(tempo);
	free(tempo2);
	free(snap);
Sergio Costas's avatar
Sergio Costas committed
576
	fclose(fichero);
Sergio Costas's avatar
Sergio Costas committed
577
	return 0;
578

Sergio Costas's avatar
Sergio Costas committed
579 580 581 582
}

void load_snap(struct z80snapshot *snap) {

583
	int bucle;
Sergio Costas's avatar
Sergio Costas committed
584 585 586

	printf("Loading SnapShot\n");

587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
	switch (snap->type) {
	case 0: // 48k
		printf("Mode 48K\n");
		ordenador->mode128k = 0; // 48K mode
		ordenador->issue = snap->issue;
		ResetComputer();
		break;
	case 1: // 128k
		printf("Mode 128K\n");
		ordenador->mode128k = 2; // +2 mode
		ordenador->issue = 3;
		ResetComputer();
		printf("Pager: %X\n", snap->pager);
		Z80free_Out(0x7FFD, snap->pager);
		break;
	default:
		break;
	}

606 607 608 609 610 611 612 613 614 615 616 617 618 619
	switch (snap->joystick) {
	case 0:
		keyboard->joystick = JOYSTICK_CURSOR;
	break;
	case 1:
		keyboard->joystick = JOYSTICK_KEMPSTON;
	break;
	case 2:
		keyboard->joystick = JOYSTICK_SINCLAIR1;
	break;
	case 3:
		keyboard->joystick = JOYSTICK_SINCLAIR2;
	break;
	}
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697

	procesador.Rm.br.A = snap->A;
	procesador.Rm.br.F = snap->F;
	procesador.Rm.br.B = snap->B;
	procesador.Rm.br.C = snap->C;
	procesador.Rm.br.D = snap->D;
	procesador.Rm.br.E = snap->E;
	procesador.Rm.br.H = snap->H;
	procesador.Rm.br.L = snap->L;
	printf("A:%d F:%d B:%d C:%d D:%d E:%d H:%d L:%d\n", snap->A, snap->F,
			snap->B, snap->C, snap->D, snap->E, snap->H, snap->L);
	procesador.Ra.br.A = snap->AA;
	procesador.Ra.br.F = snap->FF;
	procesador.Ra.br.B = snap->BB;
	procesador.Ra.br.C = snap->CC;
	procesador.Ra.br.D = snap->DD;
	procesador.Ra.br.E = snap->EE;
	procesador.Ra.br.H = snap->HH;
	procesador.Ra.br.L = snap->LL;
	printf("A:%d F:%d B:%d C:%d D:%d E:%d H:%d L:%d\n", snap->AA, snap->FF,
			snap->BB, snap->CC, snap->DD, snap->EE, snap->HH, snap->LL);
	procesador.Rm.wr.IX = snap->IX;
	procesador.Rm.wr.IY = snap->IY;
	procesador.Rm.wr.SP = snap->SP;
	procesador.PC = snap->PC;
	printf("IX:%d IY:%d SP:%d PC:%d\n", snap->IX, snap->IY, snap->SP, snap->PC);
	procesador.I = snap->I;
	procesador.R = snap->R;
	procesador.R2 = snap->R;
	printf("I:%d R:%d\n", snap->I, snap->R);

	if (snap->IFF1) {
		procesador.IFF1 = 1;
	} else {
		procesador.IFF1 = 0;
	}
	if (snap->IFF2) {
		procesador.IFF2 = 1;
	} else {
		procesador.IFF2 = 0;
	}

	procesador.IM = snap->Imode;
	Z80free_Out(0xFFFE, ((snap->border & 0x07) | 0x10));

	switch (snap->type) {
	case 0: // 48K

		for (bucle = 0; bucle < 16384; bucle++) {
			ordenador->memoria[bucle + 147456] = snap->page[0][bucle];
			ordenador->memoria[bucle + 98304] = snap->page[1][bucle];
			ordenador->memoria[bucle + 114688] = snap->page[2][bucle];
		}

		spk_ay->ay_emul = 0;
		break;
	case 1: // 128K

		for (bucle = 0; bucle < 16384; bucle++) {
			ordenador->memoria[bucle + 65536] = snap->page[0][bucle];
			ordenador->memoria[bucle + 81920] = snap->page[1][bucle];
			ordenador->memoria[bucle + 98304] = snap->page[2][bucle];
			ordenador->memoria[bucle + 114688] = snap->page[3][bucle];
			ordenador->memoria[bucle + 131072] = snap->page[4][bucle];
			ordenador->memoria[bucle + 147456] = snap->page[5][bucle];
			ordenador->memoria[bucle + 163840] = snap->page[6][bucle];
			ordenador->memoria[bucle + 180224] = snap->page[7][bucle];
		}
		spk_ay->ay_emul = 1;
		for (bucle = 0; bucle < 16; bucle++) {
			spk_ay->set_latch(bucle);
			spk_ay->set_value(snap->ay_regs[bucle]);
		}
		spk_ay->set_latch(snap->ay_latch);
		break;
	default:
		break;
	}
Sergio Costas's avatar
Sergio Costas committed
698
}