Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1541 lines (1367 sloc)
42.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| ** Oricutron | |
| ** Copyright (C) 2009-2014 Peter Gordon | |
| ** | |
| ** This program 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, version 2 | |
| ** of the License. | |
| ** | |
| ** This program 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, write to the Free Software | |
| ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| ** | |
| ** Snapshot saving & loading | |
| ** | |
| */ | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include "system.h" | |
| #include "6502.h" | |
| #include "via.h" | |
| #include "8912.h" | |
| #include "gui.h" | |
| #include "disk.h" | |
| #include "monitor.h" | |
| #include "6551.h" | |
| #include "machine.h" | |
| #include "avi.h" | |
| #include "filereq.h" | |
| #include "main.h" | |
| #include "ula.h" | |
| #include "joystick.h" | |
| #include "tape.h" | |
| #include "msgbox.h" | |
| extern char diskpath[]; | |
| #define MAX_BLOCK (262144) | |
| static unsigned char *buf; | |
| static int offs = 0; | |
| #define PUTU32(val) ok=putu32(ok, (Uint32)val) | |
| static SDL_bool putu32(SDL_bool stillok, Uint32 val) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| if ((offs+4) > MAX_BLOCK) return SDL_FALSE; | |
| buf[offs++] = (val>>24)&0xff; | |
| buf[offs++] = (val>>16)&0xff; | |
| buf[offs++] = (val>>8)&0xff; | |
| buf[offs++] = val&0xff; | |
| return SDL_TRUE; | |
| } | |
| #define PUTU16(val) ok=putu16(ok, (Uint16)val) | |
| static SDL_bool putu16(SDL_bool stillok, Uint16 val) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| if ((offs+2) > MAX_BLOCK) return SDL_FALSE; | |
| buf[offs++] = (val>>8)&0xff; | |
| buf[offs++] = val&0xff; | |
| return SDL_TRUE; | |
| } | |
| #define PUTU8(val) ok=putu8(ok, (Uint8)val) | |
| static SDL_bool putu8(SDL_bool stillok, Uint8 val) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| if (offs >= MAX_BLOCK) return SDL_FALSE; | |
| buf[offs++] = val&0xff; | |
| return SDL_TRUE; | |
| } | |
| #define PUTDATA(data, size) ok=putdata(ok, data, size) | |
| static SDL_bool putdata(SDL_bool stillok, unsigned char *data, Uint32 size) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| if ((offs+size) > MAX_BLOCK) return SDL_FALSE; | |
| memcpy( &buf[offs], data, size ); | |
| offs += size; | |
| return SDL_TRUE; | |
| } | |
| #define PUTSTR(str) ok=putstr(ok, str) | |
| static SDL_bool putstr(SDL_bool stillok, char *str) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| stillok = putu32(stillok, (int)strlen(str)+1); | |
| return putdata(stillok, (unsigned char *)str, (int)strlen(str)+1); | |
| } | |
| #define WRITEBLOCK() ok=writeblock(ok, f) | |
| static SDL_bool writeblock(SDL_bool stillok, FILE *f) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| if (offs <= 8) return SDL_TRUE; // No block to write | |
| buf[4] = ((offs-8)>>24)&0xff; | |
| buf[5] = ((offs-8)>>16)&0xff; | |
| buf[6] = ((offs-8)>>8)&0xff; | |
| buf[7] = (offs-8)&0xff; | |
| stillok = (fwrite(buf, offs, 1, f) == 1); | |
| offs = 0; | |
| return stillok; | |
| } | |
| // ID must be 4 bytes long! | |
| #define NEWBLOCK(id) ok=newblock(ok, id, f) | |
| static SDL_bool newblock(SDL_bool stillok, char *id, FILE *f) | |
| { | |
| if (!stillok) return SDL_FALSE; | |
| // Got an old block? | |
| if (!writeblock(stillok, f)) return SDL_FALSE; | |
| // Start a new one! | |
| memcpy(buf, id, 4); | |
| offs = 8; | |
| return SDL_TRUE; | |
| } | |
| #define DATABLOCK(data, len) ok = datablock(ok, data, len, f) | |
| static SDL_bool datablock(SDL_bool stillok, unsigned char *data, Uint32 len, FILE *f) | |
| { | |
| Uint32 lenbe = _BE32(len); | |
| if (!stillok) return SDL_FALSE; | |
| // Anything to write? | |
| if (len == 0) return SDL_TRUE; | |
| // Got an old block? | |
| if (!writeblock(stillok, f)) return SDL_FALSE; | |
| stillok = (fwrite("DATA", 4, 1, f) == 1); | |
| stillok &= (fwrite(&lenbe, 4, 1, f) == 1); | |
| stillok &= (fwrite(data, len, 1, f) == 1); | |
| offs = 0; | |
| return stillok; | |
| } | |
| SDL_bool save_snapshot(struct machine *oric, char *filename) | |
| { | |
| SDL_bool ok = SDL_TRUE; | |
| struct m6502 *cpu = &oric->cpu; | |
| SDL_bool do_wd17xx = SDL_FALSE; | |
| int i, j; | |
| FILE *f = NULL; | |
| buf = malloc(MAX_BLOCK); | |
| if (!buf) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot failed: out of memory (1)\n"); | |
| return SDL_FALSE; | |
| } | |
| f = fopen(filename, "wb"); | |
| if (!f) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Unable to create snapshot file (2)"); | |
| free(buf); | |
| return SDL_FALSE; | |
| } | |
| NEWBLOCK("OSN\x00"); | |
| PUTU8(oric->type); // 0 | |
| PUTU32(oric->overclockmult); // 1 | |
| PUTU32(oric->overclockshift); // 5 | |
| PUTU16(oric->vsync); // 9 | |
| PUTU8(oric->romdis); // 11 | |
| PUTU8(oric->romon); // 12 | |
| PUTU8(oric->vsynchack); // 13 | |
| PUTU8(oric->drivetype); // 14 | |
| PUTU8(oric->tapeturbo); // 15 | |
| PUTU8(oric->vid_mode); // 16 | |
| PUTU32(oric->keymap); // 17 = 21 | |
| DATABLOCK(oric->mem, oric->memsize); | |
| NEWBLOCK("TAP\x00"); | |
| PUTU8(oric->tapebit); | |
| PUTU8(oric->tapeout); | |
| PUTU8(oric->tapeparity); | |
| PUTU32(oric->tapelen); | |
| PUTU32(oric->tapeoffs); | |
| PUTU32(oric->tapecount); | |
| PUTU32(oric->tapetime); | |
| PUTU32(oric->tapedupbytes); | |
| PUTU32(oric->tapehdrend); | |
| PUTU32(oric->tapedelay); | |
| PUTU8(oric->tapemotor); | |
| PUTU8(oric->tapeturbo_forceoff); | |
| PUTU8(oric->rawtape); | |
| PUTU32(oric->nonrawend); | |
| PUTU32(oric->tapehitend); | |
| PUTU32(oric->tapeturbo_syncstack); | |
| DATABLOCK(oric->tapebuf, oric->tapelen); | |
| // Patches | |
| NEWBLOCK("PCH\0x00"); | |
| PUTU32(oric->pch_fd_cload_getname_pc); | |
| PUTU32(oric->pch_fd_csave_getname_pc); | |
| PUTU32(oric->pch_fd_store_getname_pc); | |
| PUTU32(oric->pch_fd_recall_getname_pc); | |
| PUTU32(oric->pch_fd_getname_addr); | |
| PUTU8(oric->pch_fd_available); | |
| PUTU32(oric->pch_tt_getsync_pc); | |
| PUTU32(oric->pch_tt_getsync_end_pc); | |
| PUTU32(oric->pch_tt_getsync_loop_pc); | |
| PUTU32(oric->pch_tt_readbyte_pc); | |
| PUTU32(oric->pch_tt_readbyte_end_pc); | |
| PUTU32(oric->pch_tt_readbyte_storebyte_addr); | |
| PUTU32(oric->pch_tt_readbyte_storezero_addr); | |
| PUTU32(oric->pch_tt_putbyte_pc); | |
| PUTU32(oric->pch_tt_putbyte_end_pc); | |
| PUTU32(oric->pch_tt_csave_end_pc); | |
| PUTU32(oric->pch_tt_store_end_pc); | |
| PUTU32(oric->pch_tt_writeleader_pc); | |
| PUTU32(oric->pch_tt_writeleader_end_pc); | |
| PUTU8(oric->pch_tt_readbyte_setcarry); | |
| PUTU8(oric->pch_tt_available); | |
| PUTU8(oric->pch_tt_save_available); | |
| // CPU | |
| NEWBLOCK("CPU\x00"); | |
| PUTU32(cpu->cycles); | |
| PUTU16(cpu->pc); | |
| PUTU16(cpu->lastpc); | |
| PUTU16(cpu->calcpc); | |
| PUTU16(cpu->calcint); | |
| PUTU8(cpu->nmi); | |
| PUTU8(cpu->a); | |
| PUTU8(cpu->x); | |
| PUTU8(cpu->y); | |
| PUTU8(cpu->sp); | |
| PUTU8(MAKEFLAGS); | |
| PUTU8(cpu->irq); | |
| PUTU8(cpu->nmicount); | |
| PUTU8(cpu->calcop); | |
| // AY | |
| NEWBLOCK("AY\x00\x00"); | |
| PUTU8(oric->ay.bmode); | |
| PUTU8(oric->ay.creg); | |
| PUTDATA(&oric->ay.eregs[0], NUM_AY_REGS); | |
| for (i=0; i<8; i++) | |
| PUTU8(oric->ay.keystates[i]); | |
| for (i=0; i<3; i++) | |
| PUTU32(oric->ay.toneper[i]); | |
| PUTU32(oric->ay.noiseper); | |
| PUTU32(oric->ay.envper); | |
| for (i=0; i<3; i++) | |
| { | |
| PUTU16(oric->ay.tonebit[i]); | |
| PUTU16(oric->ay.noisebit[i]); | |
| PUTU16(oric->ay.vol[i]); | |
| } | |
| PUTU16(oric->ay.newout); | |
| for (i=0; i<3; i++) | |
| PUTU32(oric->ay.ct[i]); | |
| PUTU32(oric->ay.ctn); | |
| PUTU32(oric->ay.cte); | |
| for (i=0; i<3; i++) | |
| { | |
| PUTU32(oric->ay.tonepos[i]); | |
| PUTU32(oric->ay.tonestep[i]); | |
| PUTU32(oric->ay.sign[i]); | |
| PUTU32(oric->ay.out[i]); | |
| } | |
| PUTU32(oric->ay.envpos); | |
| PUTU32(oric->ay.currnoise); | |
| PUTU32(oric->ay.rndrack); | |
| PUTU32(oric->ay.keybitdelay); | |
| PUTU32(oric->ay.currkeyoffs); | |
| // VIA | |
| NEWBLOCK("VIA\x00"); | |
| PUTU8(oric->via.ifr); | |
| PUTU8(oric->via.irb); | |
| PUTU8(oric->via.orb); | |
| PUTU8(oric->via.irbl); | |
| PUTU8(oric->via.ira); | |
| PUTU8(oric->via.ora); | |
| PUTU8(oric->via.iral); | |
| PUTU8(oric->via.ddra); | |
| PUTU8(oric->via.ddrb); | |
| PUTU8(oric->via.t1l_l); | |
| PUTU8(oric->via.t1l_h); | |
| PUTU16(oric->via.t1c); | |
| PUTU8(oric->via.t2l_l); | |
| PUTU8(oric->via.t2l_h); | |
| PUTU16(oric->via.t2c); | |
| PUTU8(oric->via.sr); | |
| PUTU8(oric->via.acr); | |
| PUTU8(oric->via.pcr); | |
| PUTU8(oric->via.ier); | |
| PUTU8(oric->via.ca1); | |
| PUTU8(oric->via.ca2); | |
| PUTU8(oric->via.cb1); | |
| PUTU8(oric->via.cb2); | |
| PUTU8(oric->via.srcount); | |
| PUTU8(oric->via.t1reload); | |
| PUTU8(oric->via.t2reload); | |
| PUTU16(oric->via.srtime); | |
| PUTU8(oric->via.t1run); | |
| PUTU8(oric->via.t2run); | |
| PUTU8(oric->via.ca2pulse); | |
| PUTU8(oric->via.cb2pulse); | |
| PUTU8(oric->via.srtrigger); | |
| PUTU32(oric->via.irqbit); | |
| switch (oric->drivetype) | |
| { | |
| case DRV_JASMIN: | |
| NEWBLOCK("JSM\x00"); | |
| PUTU8(oric->jasmin.olay); | |
| PUTU8(oric->jasmin.romdis); | |
| do_wd17xx = SDL_TRUE; | |
| break; | |
| case DRV_MICRODISC: | |
| NEWBLOCK("MDC\x00"); | |
| PUTU8(oric->md.status); | |
| PUTU8(oric->md.intrq); | |
| PUTU8(oric->md.drq); | |
| PUTU8(oric->md.diskrom); | |
| do_wd17xx = SDL_TRUE; | |
| break; | |
| case DRV_PRAVETZ: | |
| { | |
| Uint8 tmp[PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE*2]; | |
| NEWBLOCK("PRV\x00"); | |
| PUTU8(oric->pravetz.olay); // 1 | |
| PUTU8(oric->pravetz.romdis); // 2 | |
| PUTU16(oric->pravetz.extension); // 4 | |
| PUTU8(oric->wddisk.c_drive); // 5 | |
| PUTU32(oric->wddisk.currentop); // 9 | |
| for (i=0; i<2; i++) | |
| { | |
| PUTU8(oric->pravetz.drv[i].volume); // +1 | |
| PUTU8(oric->pravetz.drv[i].select); // +2 | |
| PUTU8(oric->pravetz.drv[i].motor_on); // +3 | |
| PUTU8(oric->pravetz.drv[i].write_ready); // +4 | |
| PUTU16(oric->pravetz.drv[i].byte); // +6 | |
| PUTU16(oric->pravetz.drv[i].half_track); // +8 | |
| PUTU8(oric->pravetz.drv[i].dirty); // +9 | |
| PUTU8(oric->pravetz.drv[i].prot); // +10 | |
| } | |
| /* Snapshot format is limited to one datablock per block, */ | |
| /* concatenate these into a temporary one... */ | |
| memcpy(tmp, &oric->pravetz.drv[0].image[0][0], PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE); | |
| memcpy(&tmp[PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE], &oric->pravetz.drv[1].image[0][0], PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE); | |
| DATABLOCK(tmp, PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE*2); | |
| for (i=0; i<2; i++) | |
| { | |
| if ((oric->pravetz.drv[i].pimg == NULL) || | |
| (oric->pravetz.drv[i].pimg->rawimage == NULL)) | |
| break; | |
| NEWBLOCK("PVD\x00"); | |
| PUTU16(i); | |
| PUTU32(oric->wddisk.disk[i]->rawimagelen); | |
| /* Convert sector_ptr to an offset */ | |
| if ((oric->pravetz.drv[i].sector_ptr == NULL) || | |
| (oric->pravetz.drv[i].pimg == NULL) || | |
| (oric->pravetz.drv[i].pimg->rawimage == NULL)) | |
| PUTU32(0xffffffff); | |
| else | |
| PUTU32((Uint32)(oric->pravetz.drv[i].sector_ptr - oric->pravetz.drv[i].pimg->rawimage)); | |
| DATABLOCK(oric->wddisk.disk[i]->rawimage, oric->wddisk.disk[i]->rawimagelen); | |
| } | |
| } | |
| } | |
| if( do_wd17xx ) | |
| { | |
| NEWBLOCK("WDD\x00"); | |
| PUTU8(oric->wddisk.r_status); | |
| PUTU8(oric->wddisk.r_track); | |
| PUTU8(oric->wddisk.r_sector); | |
| PUTU8(oric->wddisk.r_data); | |
| PUTU8(oric->wddisk.c_drive); | |
| PUTU8(oric->wddisk.c_side); | |
| PUTU8(oric->wddisk.c_track); | |
| PUTU8(oric->wddisk.c_sector); | |
| PUTU8(oric->wddisk.sectype); | |
| PUTU8(oric->wddisk.last_step_in); | |
| PUTU32(oric->wddisk.currentop); | |
| PUTU32(oric->wddisk.curroffs); | |
| PUTU32(oric->wddisk.delayedint); | |
| PUTU32(oric->wddisk.delayeddrq); | |
| PUTU32(oric->wddisk.distatus); | |
| PUTU32(oric->wddisk.ddstatus); | |
| PUTU32(oric->wddisk.crc); | |
| for (i=0; i<4; i++) | |
| { | |
| if( oric->wddisk.disk[i] ) | |
| { | |
| NEWBLOCK("DSK\x00"); | |
| PUTU16(oric->wddisk.disk[i]->drivenum); | |
| PUTU16(oric->wddisk.disk[i]->numtracks); | |
| PUTU16(oric->wddisk.disk[i]->numsides); | |
| PUTU16(oric->wddisk.disk[i]->geometry); | |
| PUTU16(oric->wddisk.disk[i]->cachedtrack); | |
| PUTU16(oric->wddisk.disk[i]->cachedside); | |
| PUTU32(oric->wddisk.disk[i]->rawimagelen); | |
| DATABLOCK(oric->wddisk.disk[i]->rawimage, oric->wddisk.disk[i]->rawimagelen); | |
| } | |
| } | |
| } | |
| if (oric->type == MACH_TELESTRAT) | |
| { | |
| // Bank info | |
| NEWBLOCK("BNK\x00"); | |
| for (i=0; i<8; i++) | |
| PUTU8(oric->tele_bank[i].type); | |
| PUTU8(oric->tele_currbank); | |
| // ACIA | |
| NEWBLOCK("ACI\x00"); | |
| PUTDATA(&oric->tele_acia.regs[0], ACIA_LAST); | |
| // VIA | |
| NEWBLOCK("TVA\x00"); | |
| PUTU8(oric->tele_via.ifr); | |
| PUTU8(oric->tele_via.irb); | |
| PUTU8(oric->tele_via.orb); | |
| PUTU8(oric->tele_via.irbl); | |
| PUTU8(oric->tele_via.ira); | |
| PUTU8(oric->tele_via.ora); | |
| PUTU8(oric->tele_via.iral); | |
| PUTU8(oric->tele_via.ddra); | |
| PUTU8(oric->tele_via.ddrb); | |
| PUTU8(oric->tele_via.t1l_l); | |
| PUTU8(oric->tele_via.t1l_h); | |
| PUTU16(oric->tele_via.t1c); | |
| PUTU8(oric->tele_via.t2l_l); | |
| PUTU8(oric->tele_via.t2l_h); | |
| PUTU16(oric->tele_via.t2c); | |
| PUTU8(oric->tele_via.sr); | |
| PUTU8(oric->tele_via.acr); | |
| PUTU8(oric->tele_via.pcr); | |
| PUTU8(oric->tele_via.ier); | |
| PUTU8(oric->tele_via.ca1); | |
| PUTU8(oric->tele_via.ca2); | |
| PUTU8(oric->tele_via.cb1); | |
| PUTU8(oric->tele_via.cb2); | |
| PUTU8(oric->tele_via.srcount); | |
| PUTU8(oric->tele_via.t1reload); | |
| PUTU8(oric->tele_via.t2reload); | |
| PUTU16(oric->tele_via.srtime); | |
| PUTU8(oric->tele_via.t1run); | |
| PUTU8(oric->tele_via.t2run); | |
| PUTU8(oric->tele_via.ca2pulse); | |
| PUTU8(oric->tele_via.cb2pulse); | |
| PUTU8(oric->tele_via.srtrigger); | |
| PUTU32(oric->tele_via.irqbit); | |
| } | |
| // Symbols | |
| if (oric->romsyms.numsyms) | |
| { | |
| NEWBLOCK("SYR\x00"); | |
| for (i=0; i<oric->romsyms.numsyms; i++) | |
| { | |
| PUTSTR(oric->romsyms.syms[i].name); | |
| PUTU16(oric->romsyms.syms[i].addr); | |
| PUTU16(oric->romsyms.syms[i].flags); | |
| } | |
| } | |
| if (oric->usersyms.numsyms) | |
| { | |
| NEWBLOCK("SYU\x00"); | |
| for (i=0; i<oric->usersyms.numsyms; i++) | |
| { | |
| PUTSTR(oric->usersyms.syms[i].name); | |
| PUTU16(oric->usersyms.syms[i].addr); | |
| PUTU16(oric->usersyms.syms[i].flags); | |
| } | |
| } | |
| if (oric->type == MACH_TELESTRAT) | |
| { | |
| for (j=0; j<8; j++) | |
| { | |
| if (oric->tele_banksyms[j].numsyms) | |
| { | |
| char name[8]; | |
| sprintf(name, "SY%d%c", j, 0); | |
| NEWBLOCK(name); | |
| for (i=0; i<oric->tele_banksyms[j].numsyms; i++) | |
| { | |
| PUTSTR(oric->tele_banksyms[j].syms[i].name); | |
| PUTU16(oric->romsyms.syms[i].addr); | |
| PUTU16(oric->romsyms.syms[i].flags); | |
| } | |
| } | |
| } | |
| } | |
| // Breakpoints | |
| if ((cpu->anybp) || (cpu->anymbp)) | |
| { | |
| NEWBLOCK("BKP\x00"); | |
| for (i=0; i<16; i++) | |
| PUTU32(cpu->breakpoints[i]); | |
| for (i=0; i<16; i++) | |
| { | |
| PUTU8(cpu->membreakpoints[i].flags); | |
| PUTU8(cpu->membreakpoints[i].lastval); | |
| PUTU16(cpu->membreakpoints[i].addr); | |
| } | |
| } | |
| WRITEBLOCK(); | |
| fclose(f); | |
| free(buf); | |
| if (!ok) | |
| msgbox(oric, MSGBOX_OK, "Snapshot failed! (3)"); | |
| return ok; | |
| } | |
| struct blockheader | |
| { | |
| unsigned char id[4]; | |
| unsigned int offset; | |
| unsigned int size; | |
| unsigned char *buf; | |
| struct blockheader *datablock; | |
| int offs; | |
| }; | |
| int numhdrs = 0; | |
| static struct blockheader *bkh = NULL; | |
| static SDL_bool getheaders(struct machine *oric, FILE *f) | |
| { | |
| int i; | |
| unsigned int size, offset, filesize; | |
| unsigned char hdr[8]; | |
| fseek(f, 0, SEEK_END); | |
| filesize = (int)ftell(f); | |
| fseek(f, 0, SEEK_SET); | |
| /* First, find all the blocks in the file */ | |
| /* and make sure the file structure is sane. */ | |
| offset = 0; | |
| numhdrs = 0; | |
| while (offset < filesize) | |
| { | |
| if (fread(hdr, 8, 1, f) != 1) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Read error (4)"); | |
| numhdrs = 0; | |
| return SDL_FALSE; | |
| } | |
| size = (hdr[4]<<24)|(hdr[5]<<16)|(hdr[6]<<8)|hdr[7]; | |
| if ((size == 0) || ((offset+size) > filesize)) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file structure (5)"); | |
| numhdrs = 0; | |
| return SDL_FALSE; | |
| } | |
| numhdrs++; | |
| fseek(f, size, SEEK_CUR); | |
| offset += size+8; | |
| } | |
| /* Allocate memory to store all the block headers */ | |
| bkh = (struct blockheader *)malloc(numhdrs*sizeof(struct blockheader)); | |
| if (!bkh) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (6)"); | |
| numhdrs = 0; | |
| return SDL_FALSE; | |
| } | |
| memset(bkh, 0, numhdrs*sizeof(struct blockheader)); | |
| /* Now read in all the block headers */ | |
| fseek(f, 0, SEEK_SET); | |
| offset = 0; | |
| i = 0; | |
| while (offset < filesize) | |
| { | |
| if (fread(hdr, 8, 1, f) != 1) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Read error (7)"); | |
| free(bkh); | |
| bkh = NULL; | |
| numhdrs = 0; | |
| return SDL_FALSE; | |
| } | |
| size = (hdr[4]<<24)|(hdr[5]<<16)|(hdr[6]<<8)|hdr[7]; | |
| if ((size == 0) || ((offset+size) > filesize)) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file structure (8)"); | |
| free(bkh); | |
| bkh = NULL; | |
| numhdrs = 0; | |
| return SDL_FALSE; | |
| } | |
| offset+=8; | |
| memcpy(bkh[i].id, hdr, 4); | |
| bkh[i].offset = offset; | |
| bkh[i].size = size; | |
| //printf("Block: %c%c%c%c (@ %d, size %d)\n", bkh[i].id[0], bkh[i].id[1], (bkh[i].id[2]>31)?bkh[i].id[2]:'.', (bkh[i].id[3]>31)?bkh[i].id[3]:'.', bkh[i].offset, bkh[i].size); | |
| if ((i>0) && (memcmp(bkh[i].id, "DATA", 4)==0)) | |
| { | |
| bkh[i-1].datablock = &bkh[i]; | |
| } | |
| fseek(f, size, SEEK_CUR); | |
| offset += size; | |
| i++; | |
| } | |
| return SDL_TRUE; | |
| } | |
| static void free_block(struct blockheader *blk) | |
| { | |
| if ((!blk)||(!blk->buf)) return; | |
| free(blk->buf); | |
| blk->buf = NULL; | |
| } | |
| static void free_blockheaders(void) | |
| { | |
| int i; | |
| if (!bkh) return; | |
| for (i=0; i<numhdrs; i++) | |
| { | |
| if (bkh[i].buf) free(bkh[i].buf); | |
| } | |
| free(bkh); | |
| } | |
| static struct blockheader *load_block(struct machine *oric, char *id, FILE *f, SDL_bool required, int expectedsize, SDL_bool datarequired) | |
| { | |
| int i; | |
| for (i=0; i<numhdrs; i++) | |
| { | |
| if (memcmp(bkh[i].id, id, 4) == 0) | |
| break; | |
| } | |
| if (i==numhdrs) | |
| { | |
| //printf("Unable to find %c%c%c%c\n", id[0], id[1], (id[2]>31)?id[2]:'.', (id[3]>31)?id[3]:'.'); | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (9)"); | |
| return NULL; | |
| } | |
| if ((datarequired) && (bkh[i].datablock == NULL)) | |
| { | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (10)"); | |
| return NULL; | |
| } | |
| if ((expectedsize != -1) && (bkh[i].size != expectedsize)) | |
| { | |
| //printf("Size for %c%c%c%c is %d, expected %d\n", id[0], id[1], (id[2]>31)?id[2]:'.', (id[3]>31)?id[3]:'.', bkh[i].size, expectedsize); | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (11)"); | |
| return NULL; | |
| } | |
| /* Already loaded it?! */ | |
| if (bkh[i].buf) | |
| { | |
| bkh[i].offs = 0; | |
| return &bkh[i]; | |
| } | |
| bkh[i].buf = malloc(bkh[i].size); | |
| if (!bkh[i].buf) | |
| { | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (12)"); | |
| return NULL; | |
| } | |
| fseek(f, bkh[i].offset, SEEK_SET); | |
| if (fread(bkh[i].buf, bkh[i].size, 1, f) != 1) | |
| { | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Read error (13)"); | |
| return NULL; | |
| } | |
| bkh[i].offs = 0; | |
| return &bkh[i]; | |
| } | |
| static SDL_bool read_block(struct machine *oric, struct blockheader *blk, FILE *f, SDL_bool required, unsigned char *destbuf) | |
| { | |
| if (!blk) | |
| { | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Internal error (14)"); | |
| return SDL_FALSE; | |
| } | |
| if (blk->buf) | |
| { | |
| memcpy(destbuf, blk->buf, blk->size); | |
| return SDL_TRUE; | |
| } | |
| fseek(f, blk->offset, SEEK_SET); | |
| if (fread(destbuf, blk->size, 1, f) != 1) | |
| { | |
| if (required) msgbox(oric, MSGBOX_OK, "Snapshot load failed: Read error (15)"); | |
| return SDL_FALSE; | |
| } | |
| return SDL_TRUE; | |
| } | |
| static Uint32 getu32(struct blockheader *blk) | |
| { | |
| Uint32 val = (blk->buf[blk->offs]<<24)|(blk->buf[blk->offs+1]<<16)|(blk->buf[blk->offs+2]<<8)|blk->buf[blk->offs+3]; | |
| blk->offs+=4; | |
| return val; | |
| } | |
| static Sint32 gets32(struct blockheader *blk) | |
| { | |
| Sint32 val = (blk->buf[blk->offs]<<24)|(blk->buf[blk->offs+1]<<16)|(blk->buf[blk->offs+2]<<8)|blk->buf[blk->offs+3]; | |
| blk->offs+=4; | |
| return val; | |
| } | |
| static Uint16 getu16(struct blockheader *blk) | |
| { | |
| Uint16 val = (blk->buf[blk->offs]<<8)|blk->buf[blk->offs+1]; | |
| blk->offs+=2; | |
| return val; | |
| } | |
| static Sint16 gets16(struct blockheader *blk) | |
| { | |
| Sint16 val = (blk->buf[blk->offs]<<8)|blk->buf[blk->offs+1]; | |
| blk->offs+=2; | |
| return val; | |
| } | |
| static Uint8 getu8(struct blockheader *blk) | |
| { | |
| return blk->buf[blk->offs++]; | |
| } | |
| static void getdata(struct blockheader *blk, unsigned char *dest, unsigned int size) | |
| { | |
| memcpy(dest, &blk->buf[blk->offs], size); | |
| blk->offs += size; | |
| } | |
| SDL_bool load_snapshot(struct machine *oric, char *filename) | |
| { | |
| struct m6502 *cpu = &oric->cpu; | |
| int i; | |
| SDL_bool do_wd17xx = SDL_FALSE, back2mon = oric->emu_mode == EM_DEBUG; | |
| unsigned int type, drivetype; | |
| FILE *f = NULL; | |
| struct blockheader *blk = NULL; | |
| f = fopen(filename, "rb"); | |
| if (!f) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Unable to open snapshot file (16)"); | |
| return SDL_FALSE; | |
| } | |
| if(!getheaders(oric, f)) | |
| { | |
| fclose(f); | |
| return SDL_FALSE; | |
| } | |
| /* Get the main block */ | |
| blk = load_block(oric, "OSN\x00", f, SDL_TRUE, 21, SDL_TRUE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| return SDL_FALSE; | |
| } | |
| /* Set up the emulation for the required machine type */ | |
| type = blk->buf[0]; | |
| drivetype = blk->buf[14]; | |
| if (type >= MACH_LAST) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (17)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| return SDL_FALSE; | |
| } | |
| swapmach(oric, NULL, (drivetype<<16)|type); | |
| /* Perform some validation */ | |
| if((oric->drivetype != drivetype) || // Unrecognised or invalid drive type | |
| (oric->memsize != blk->datablock->size)) // Memsize incorrect for type | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (18)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| /* Read in the memory */ | |
| if (!read_block(oric, blk->datablock, f, SDL_TRUE, oric->mem)) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| /* Clear things that will get replaced */ | |
| clear_patches( oric ); | |
| if (oric->tapebuf) | |
| { | |
| free(oric->tapebuf); | |
| oric->tapebuf = NULL; | |
| oric->tapelen = 0; | |
| } | |
| blk->offs = 1; | |
| oric->overclockmult = getu32(blk); | |
| oric->overclockshift = getu32(blk); | |
| oric->vsync = getu16(blk); | |
| oric->romdis = getu8 (blk); | |
| oric->romon = getu8 (blk); | |
| oric->vsynchack = getu8 (blk); | |
| blk->offs++; // Skip drivetype (already got it) | |
| oric->tapeturbo = getu8 (blk); | |
| oric->vid_mode = getu8 (blk); | |
| oric->keymap = getu32(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| oric->vid_freq = oric->vid_mode&2; | |
| if( oric->vid_mode & 4 ) | |
| { | |
| oric->vid_addr = oric->vidbases[0]; | |
| oric->vid_ch_base = &oric->mem[oric->vidbases[1]]; | |
| } else { | |
| oric->vid_addr = oric->vidbases[2]; | |
| oric->vid_ch_base = &oric->mem[oric->vidbases[3]]; | |
| } | |
| /* Get the CPU block */ | |
| blk = load_block(oric, "CPU\x00", f, SDL_TRUE, 21, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| cpu->cycles = getu32(blk); | |
| cpu->pc = getu16(blk); | |
| cpu->lastpc = getu16(blk); | |
| cpu->calcpc = getu16(blk); | |
| cpu->calcint = getu16(blk); | |
| cpu->nmi = getu8 (blk); | |
| cpu->a = getu8 (blk); | |
| cpu->x = getu8 (blk); | |
| cpu->y = getu8 (blk); | |
| cpu->sp = getu8 (blk); | |
| i = getu8 (blk); | |
| SETFLAGS(i); | |
| cpu->irq = getu8 (blk); | |
| cpu->nmicount = getu8 (blk); | |
| cpu->calcop = getu8 (blk); | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the AY block */ | |
| blk = load_block(oric, "AY\x00\x00", f, SDL_TRUE, 153, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->ay.bmode = getu8(blk); | |
| oric->ay.creg = getu8(blk); | |
| getdata(blk, &oric->ay.eregs[0], NUM_AY_REGS); | |
| memcpy(&oric->ay.regs[0], &oric->ay.eregs[0], NUM_AY_REGS); | |
| for (i=0; i<8; i++) | |
| oric->ay.keystates[i] = getu8(blk); | |
| for (i=0; i<3; i++) | |
| oric->ay.toneper[i] = getu32(blk); | |
| oric->ay.noiseper = getu32(blk); | |
| oric->ay.envper = getu32(blk); | |
| for (i=0; i<3; i++) | |
| { | |
| oric->ay.tonebit[i] = getu16(blk); | |
| oric->ay.noisebit[i] = getu16(blk); | |
| oric->ay.vol[i] = getu16(blk); | |
| } | |
| oric->ay.newout = getu16(blk); | |
| for (i=0; i<3; i++) | |
| oric->ay.ct[i] = getu32(blk); | |
| oric->ay.ctn = getu32(blk); | |
| oric->ay.cte = getu32(blk); | |
| for (i=0; i<3; i++) | |
| { | |
| oric->ay.tonepos[i] = getu32(blk); | |
| oric->ay.tonestep[i] = getu32(blk); | |
| oric->ay.sign[i] = getu32(blk); | |
| oric->ay.out[i] = getu32(blk); | |
| } | |
| oric->ay.envpos = getu32(blk); | |
| oric->ay.currnoise = getu32(blk); | |
| oric->ay.rndrack = getu32(blk); | |
| oric->ay.keybitdelay = getu32(blk); | |
| oric->ay.currkeyoffs = getu32(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the VIA block */ | |
| blk = load_block(oric, "VIA\x00", f, SDL_TRUE, 39, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->via.ifr = getu8 (blk); | |
| oric->via.irb = getu8 (blk); | |
| oric->via.orb = getu8 (blk); | |
| oric->via.irbl = getu8 (blk); | |
| oric->via.ira = getu8 (blk); | |
| oric->via.ora = getu8 (blk); | |
| oric->via.iral = getu8 (blk); | |
| oric->via.ddra = getu8 (blk); | |
| oric->via.ddrb = getu8 (blk); | |
| oric->via.t1l_l = getu8 (blk); | |
| oric->via.t1l_h = getu8 (blk); | |
| oric->via.t1c = getu16(blk); | |
| oric->via.t2l_l = getu8 (blk); | |
| oric->via.t2l_h = getu8 (blk); | |
| oric->via.t2c = getu16(blk); | |
| oric->via.sr = getu8 (blk); | |
| oric->via.acr = getu8 (blk); | |
| oric->via.pcr = getu8 (blk); | |
| oric->via.ier = getu8 (blk); | |
| oric->via.ca1 = getu8 (blk); | |
| oric->via.ca2 = getu8 (blk); | |
| oric->via.cb1 = getu8 (blk); | |
| oric->via.cb2 = getu8 (blk); | |
| oric->via.srcount = getu8 (blk); | |
| oric->via.t1reload = getu8 (blk); | |
| oric->via.t2reload = getu8 (blk); | |
| oric->via.srtime = getu16(blk); | |
| oric->via.t1run = getu8 (blk); | |
| oric->via.t2run = getu8 (blk); | |
| oric->via.ca2pulse = getu8 (blk); | |
| oric->via.cb2pulse = getu8 (blk); | |
| oric->via.srtrigger= getu8 (blk); | |
| oric->via.irqbit = getu32(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the tape block */ | |
| blk = load_block(oric, "TAP\x00", f, SDL_TRUE, 46, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->tapebit = getu8 (blk); | |
| oric->tapeout = getu8 (blk); | |
| oric->tapeparity = getu8 (blk); | |
| oric->tapelen = getu32(blk); | |
| oric->tapeoffs = getu32(blk); | |
| oric->tapecount = getu32(blk); | |
| oric->tapetime = getu32(blk); | |
| oric->tapedupbytes= getu32(blk); | |
| oric->tapehdrend = getu32(blk); | |
| oric->tapedelay = getu32(blk); | |
| oric->tapemotor = getu8 (blk); | |
| oric->tapeturbo_forceoff= getu8(blk); | |
| oric->rawtape = getu8 (blk); | |
| oric->nonrawend = getu32(blk); | |
| oric->tapehitend = getu32(blk); | |
| oric->tapeturbo_syncstack = getu32(blk); | |
| if (!blk->datablock) | |
| { | |
| oric->tapelen = 0; | |
| oric->tapeoffs = 0; | |
| } | |
| else | |
| { | |
| oric->tapebuf = malloc(blk->datablock->size); | |
| if (!oric->tapebuf) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (19)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| if (!read_block(oric, blk->datablock, f, SDL_TRUE, oric->tapebuf)) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| } | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the patch block */ | |
| if ((blk = load_block(oric, "PCH\x00", f, SDL_FALSE, 76, SDL_FALSE))) | |
| { | |
| oric->pch_fd_cload_getname_pc = getu32(blk); | |
| oric->pch_fd_csave_getname_pc = getu32(blk); | |
| oric->pch_fd_store_getname_pc = getu32(blk); | |
| oric->pch_fd_recall_getname_pc = getu32(blk); | |
| oric->pch_fd_getname_addr = getu32(blk); | |
| oric->pch_fd_available = getu8(blk); | |
| oric->pch_tt_getsync_pc = getu32(blk); | |
| oric->pch_tt_getsync_end_pc = getu32(blk); | |
| oric->pch_tt_getsync_loop_pc = getu32(blk); | |
| oric->pch_tt_readbyte_pc = getu32(blk); | |
| oric->pch_tt_readbyte_end_pc = getu32(blk); | |
| oric->pch_tt_readbyte_storebyte_addr = getu32(blk); | |
| oric->pch_tt_readbyte_storezero_addr = getu32(blk); | |
| oric->pch_tt_putbyte_pc = getu32(blk); | |
| oric->pch_tt_putbyte_end_pc = getu32(blk); | |
| oric->pch_tt_csave_end_pc = getu32(blk); | |
| oric->pch_tt_store_end_pc = getu32(blk); | |
| oric->pch_tt_writeleader_pc = getu32(blk); | |
| oric->pch_tt_writeleader_end_pc = getu32(blk); | |
| oric->pch_tt_readbyte_setcarry = getu8 (blk); | |
| oric->pch_tt_available = getu8 (blk); | |
| oric->pch_tt_save_available = getu8 (blk); | |
| // Finished with this one | |
| free_block(blk); | |
| } | |
| switch (oric->drivetype) | |
| { | |
| case DRV_JASMIN: | |
| /* Get the jasmin block */ | |
| blk = load_block(oric, "JSM\x00", f, SDL_TRUE, 2, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->jasmin.olay = getu8(blk); | |
| oric->jasmin.romdis = getu8(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| do_wd17xx = SDL_TRUE; | |
| break; | |
| case DRV_MICRODISC: | |
| /* Get the microdisc block */ | |
| blk = load_block(oric, "MDC\x00", f, SDL_TRUE, 4, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->md.status = getu8(blk); | |
| oric->md.intrq = getu8(blk); | |
| oric->md.drq = getu8(blk); | |
| oric->md.diskrom = getu8(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| do_wd17xx = SDL_TRUE; | |
| break; | |
| case DRV_PRAVETZ: | |
| { | |
| Uint8 tmp[PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE*2]; | |
| Uint32 offs_; | |
| /* Get the pravetz block */ | |
| blk = load_block(oric, "PRV\x00", f, SDL_TRUE, 9+2*10, SDL_TRUE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->pravetz.olay = getu8(blk); | |
| oric->pravetz.romdis = getu8(blk); | |
| oric->pravetz.extension = getu16(blk); | |
| oric->wddisk.c_drive = getu8(blk); | |
| oric->wddisk.currentop = getu32(blk); | |
| for (i=0; i<2; i++) | |
| { | |
| oric->pravetz.drv[i].volume = getu8(blk); | |
| oric->pravetz.drv[i].select = getu8(blk); | |
| oric->pravetz.drv[i].motor_on = getu8(blk); | |
| oric->pravetz.drv[i].write_ready = getu8(blk); | |
| oric->pravetz.drv[i].byte = getu16(blk); | |
| oric->pravetz.drv[i].half_track = getu16(blk); | |
| oric->pravetz.drv[i].dirty = getu8(blk); | |
| oric->pravetz.drv[i].prot = getu8(blk); | |
| } | |
| if (!read_block(oric, blk->datablock, f, SDL_TRUE, tmp)) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| memcpy(&oric->pravetz.drv[0].image[0][0], tmp, PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE); | |
| memcpy(&oric->pravetz.drv[1].image[0][0], &tmp[PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE], PRAV_TRACKS_PER_DISK*PRAV_RAW_TRACK_SIZE); | |
| free_block(blk); | |
| // Get the disk images | |
| while ((blk = load_block(oric, "PVD\x00", f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| // Get the drive associated with this disk image | |
| i = getu16(blk); | |
| if ((i<0) || (i>1) || (oric->wddisk.disk[i] != NULL) || (!blk->datablock) || (blk->size != 10)) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (PVD1)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| // Allocate a diskimage header | |
| oric->wddisk.disk[i] = (struct diskimage *)malloc(sizeof(struct diskimage)); | |
| if (!oric->wddisk.disk[i]) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (PVD2)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| memset(oric->wddisk.disk[i], 0, sizeof(struct diskimage)); | |
| // Allocate space for the disk image | |
| oric->wddisk.disk[i]->rawimage = malloc(blk->datablock->size); | |
| if (!oric->wddisk.disk[i]) | |
| { | |
| free(oric->wddisk.disk[i]); | |
| oric->wddisk.disk[i] = NULL; | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (PVD3)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| // Read in the disk image | |
| if (!read_block(oric, blk->datablock, f, SDL_TRUE, oric->wddisk.disk[i]->rawimage)) | |
| { | |
| free(oric->wddisk.disk[i]->rawimage); | |
| free(oric->wddisk.disk[i]); | |
| oric->wddisk.disk[i] = NULL; | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->wddisk.disk[i]->cachedtrack = -1; | |
| oric->wddisk.disk[i]->cachedside = -1; | |
| // Fill out the disk image header | |
| oric->wddisk.disk[i]->drivenum = i; | |
| oric->wddisk.disk[i]->rawimagelen = getu32(blk); | |
| sprintf(oric->wddisk.disk[i]->filename, "%s%cSNAPDISK%d.DSK", diskpath, PATHSEP, i); | |
| offs_ = getu32(blk); | |
| oric->pravetz.drv[i].pimg = oric->wddisk.disk[i]; | |
| if (offs_ == 0xffffffff) | |
| oric->pravetz.drv[i].sector_ptr = NULL; | |
| else | |
| oric->pravetz.drv[i].sector_ptr = &oric->pravetz.drv[i].pimg->rawimage[offs_]; | |
| blk->id[0] = 0; // Don't find this one again | |
| free_block(blk); | |
| } | |
| } | |
| } | |
| if (do_wd17xx) | |
| { | |
| Uint8 disks[4]; | |
| /* Get the wd17xx block */ | |
| blk = load_block(oric, "WDD\x00", f, SDL_TRUE, 38, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->wddisk.r_status = getu8 (blk); | |
| oric->wddisk.r_track = getu8 (blk); | |
| oric->wddisk.r_sector = getu8 (blk); | |
| oric->wddisk.r_data = getu8 (blk); | |
| oric->wddisk.c_drive = getu8 (blk); | |
| oric->wddisk.c_side = getu8 (blk); | |
| oric->wddisk.c_track = getu8 (blk); | |
| oric->wddisk.c_sector = getu8 (blk); | |
| oric->wddisk.sectype = getu8 (blk); | |
| oric->wddisk.last_step_in = getu8 (blk); | |
| getdata(blk, disks, 4); | |
| oric->wddisk.currentop = getu32(blk); | |
| oric->wddisk.curroffs = getu32(blk); | |
| oric->wddisk.delayedint = getu32(blk); | |
| oric->wddisk.delayeddrq = getu32(blk); | |
| oric->wddisk.distatus = getu32(blk); | |
| oric->wddisk.ddstatus = getu32(blk); | |
| oric->wddisk.crc = getu32(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| // Get the disk images | |
| while ((blk = load_block(oric, "DSK\x00", f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| int track_to_cache=-1, side_to_cache=-1; | |
| // Get the drive associated with this disk image | |
| i = getu16(blk); | |
| if ((i<0) || (i>3) || (oric->wddisk.disk[i] != NULL) || (!blk->datablock) || (blk->size != 16)) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Invalid file (20)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| // Allocate a diskimage header | |
| oric->wddisk.disk[i] = (struct diskimage *)malloc(sizeof(struct diskimage)); | |
| if (!oric->wddisk.disk[i]) | |
| { | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (21)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| memset(oric->wddisk.disk[i], 0, sizeof(struct diskimage)); | |
| // Allocate space for the disk image | |
| oric->wddisk.disk[i]->rawimage = malloc(blk->datablock->size); | |
| if (!oric->wddisk.disk[i]) | |
| { | |
| free(oric->wddisk.disk[i]); | |
| oric->wddisk.disk[i] = NULL; | |
| msgbox(oric, MSGBOX_OK, "Snapshot load failed: Out of memory (22)"); | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| // Read in the disk image | |
| if (!read_block(oric, blk->datablock, f, SDL_TRUE, oric->wddisk.disk[i]->rawimage)) | |
| { | |
| free(oric->wddisk.disk[i]->rawimage); | |
| free(oric->wddisk.disk[i]); | |
| oric->wddisk.disk[i] = NULL; | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->wddisk.disk[i]->cachedtrack = -1; | |
| oric->wddisk.disk[i]->cachedside = -1; | |
| // Fill out the disk image header | |
| oric->wddisk.disk[i]->drivenum = i; | |
| oric->wddisk.disk[i]->numtracks = getu16(blk); | |
| oric->wddisk.disk[i]->numsides = getu16(blk); | |
| oric->wddisk.disk[i]->geometry = getu16(blk); | |
| track_to_cache = gets16(blk); | |
| side_to_cache = gets16(blk); | |
| oric->wddisk.disk[i]->rawimagelen = getu32(blk); | |
| if ((track_to_cache != -1) && (side_to_cache != -1)) | |
| diskimage_cachetrack(oric->wddisk.disk[i], track_to_cache, side_to_cache); | |
| if (oric->wddisk.c_drive == i) | |
| oric->wddisk.currsector = wd17xx_find_sector(&oric->wddisk, oric->wddisk.r_sector); | |
| sprintf(oric->wddisk.disk[i]->filename, "%s%cSNAPDISK%d.DSK", diskpath, PATHSEP, i); | |
| blk->id[0] = 0; // Don't find this one again | |
| free_block(blk); | |
| } | |
| } | |
| if (oric->type == MACH_TELESTRAT) | |
| { | |
| /* Get the bank information block */ | |
| blk = load_block(oric, "BNK\x00", f, SDL_TRUE, 9, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| for (i=0; i<8; i++) | |
| oric->tele_bank[i].type = getu8(blk); | |
| oric->tele_currbank = getu8(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the ACIA block */ | |
| blk = load_block(oric, "ACI\x00", f, SDL_TRUE, ACIA_LAST, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| getdata(blk, &oric->tele_acia.regs[0], ACIA_LAST); | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the AUX ACIA block */ | |
| blk = load_block(oric, "AUX\x00", f, SDL_TRUE, ACIA_LAST, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| // Finished with this one | |
| free_block(blk); | |
| /* Get the VIA block */ | |
| blk = load_block(oric, "TVA\x00", f, SDL_TRUE, 39, SDL_FALSE); | |
| if (!blk) | |
| { | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_FALSE; | |
| } | |
| oric->tele_via.ifr = getu8 (blk); | |
| oric->tele_via.irb = getu8 (blk); | |
| oric->tele_via.orb = getu8 (blk); | |
| oric->tele_via.irbl = getu8 (blk); | |
| oric->tele_via.ira = getu8 (blk); | |
| oric->tele_via.ora = getu8 (blk); | |
| oric->tele_via.iral = getu8 (blk); | |
| oric->tele_via.ddra = getu8 (blk); | |
| oric->tele_via.ddrb = getu8 (blk); | |
| oric->tele_via.t1l_l = getu8 (blk); | |
| oric->tele_via.t1l_h = getu8 (blk); | |
| oric->tele_via.t1c = getu16(blk); | |
| oric->tele_via.t2l_l = getu8 (blk); | |
| oric->tele_via.t2l_h = getu8 (blk); | |
| oric->tele_via.t2c = getu16(blk); | |
| oric->tele_via.sr = getu8 (blk); | |
| oric->tele_via.acr = getu8 (blk); | |
| oric->tele_via.pcr = getu8 (blk); | |
| oric->tele_via.ier = getu8 (blk); | |
| oric->tele_via.ca1 = getu8 (blk); | |
| oric->tele_via.ca2 = getu8 (blk); | |
| oric->tele_via.cb1 = getu8 (blk); | |
| oric->tele_via.cb2 = getu8 (blk); | |
| oric->tele_via.srcount = getu8 (blk); | |
| oric->tele_via.t1reload = getu8 (blk); | |
| oric->tele_via.t2reload = getu8 (blk); | |
| oric->tele_via.srtime = getu16(blk); | |
| oric->tele_via.t1run = getu8 (blk); | |
| oric->tele_via.t2run = getu8 (blk); | |
| oric->tele_via.ca2pulse = getu8 (blk); | |
| oric->tele_via.cb2pulse = getu8 (blk); | |
| oric->tele_via.srtrigger= getu8 (blk); | |
| oric->tele_via.irqbit = getu32(blk); | |
| // Finished with this one | |
| free_block(blk); | |
| } | |
| /* Get the rom symbols block */ | |
| if ((blk = load_block(oric, "SYR\x00", f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| mon_symsfromsnapshot(&oric->romsyms, blk->buf, blk->size); | |
| free_block(blk); | |
| } | |
| /* Get the user symbols block */ | |
| if ((blk = load_block(oric, "SYU\x00", f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| mon_symsfromsnapshot(&oric->usersyms, blk->buf, blk->size); | |
| free_block(blk); | |
| } | |
| if (oric->type == MACH_TELESTRAT) | |
| { | |
| for (i=0; i<8; i++) | |
| { | |
| char name[8]; | |
| sprintf(name, "SY%d%c", i, 0); | |
| if ((blk = load_block(oric, name, f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| mon_symsfromsnapshot(&oric->tele_banksyms[i], blk->buf, blk->size); | |
| free_block(blk); | |
| } | |
| } | |
| } | |
| /* ... and finally, breakpoints! */ | |
| if ((blk = load_block(oric, "BKP\x00", f, SDL_FALSE, -1, SDL_FALSE))) | |
| { | |
| cpu->anybp = SDL_FALSE; | |
| cpu->anymbp = SDL_FALSE; | |
| for (i=0; i<16; i++) | |
| { | |
| cpu->breakpoints[i] = gets32(blk); | |
| if (cpu->breakpoints[i] != -1) cpu->anybp = SDL_TRUE; | |
| } | |
| for (i=0; i<16; i++) | |
| { | |
| cpu->membreakpoints[i].flags = getu8(blk); | |
| cpu->membreakpoints[i].lastval = getu8(blk); | |
| cpu->membreakpoints[i].addr = getu16(blk); | |
| if (cpu->membreakpoints[i].flags) cpu->anymbp = SDL_TRUE; | |
| } | |
| free_block(blk); | |
| } | |
| free_blockheaders(); | |
| fclose(f); | |
| setmenutoggles( oric ); | |
| if (back2mon) setemumode(oric, NULL, EM_DEBUG); | |
| return SDL_TRUE; | |
| } | |