/* 3dsspec - Nintendo 3DS Sinclair Spectrum 48K emulator. Copyright (C) 2021 Ian Cowburn 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; either version 2 of the License, or (at your option) any later version. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. $Id: snap.c 4 2006-09-15 00:30:18Z ianc $ */ #include #include #include "snap.h" #include "debug.h" /* ---------------------------------------- MACROS */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define ROMLEN 0x4000 /* ---------------------------------------- PRIVATE DATA */ static FILE *tapfile; /* ---------------------------------------- PRIVATE FUNCTIONS */ static Z80Byte GetTAPByte(void) { int ret=0; if (tapfile) { ret = fgetc(tapfile); if (ret == EOF) { ret = 0; fclose(tapfile); tapfile = NULL; } } return (Z80Byte)ret; } static Z80Word GetTAPLSBWord(void) { int c1,c2; c1=GetTAPByte(); c2=GetTAPByte(); return (Z80Word)(c1+(c2<<8)); } /* ---------------------------------------- INTERFACES */ void TAPOpenTape(const char *path) { tapfile = fopen(path, "rb"); } void TAPCloseTape(void) { if (tapfile) { fclose(tapfile); tapfile = NULL; } } int TAPLoad(Z80Byte id, Z80Word *addr, Z80Word *len, SNAP_Poke poke) { Z80Word blen; Z80Byte type,b,csum,tape_csum; b = 0; blen = GetTAPLSBWord(); type = GetTAPByte(); csum = type; if (!tapfile) { SPEC_DEBUG("Tape not open, returning FALSE\n"); return FALSE; } SPEC_DEBUG("Read block. len=%u type=%u\n", (unsigned)blen, (unsigned)type); SPEC_DEBUG("Requested block len=%u type=%u addr=%u\n", (unsigned)*len, (unsigned)id, (unsigned)*addr); /* Have we found the requested block? */ if (id == type) { /* Knock off block type */ blen--; while(blen && *len) { b = GetTAPByte(); if (blen > 1) { csum ^= b; poke(*addr,b); } (*addr)++; (*len)--; blen--; } SPEC_DEBUG("Finished block. Remaining blen=%u len=%u addr=%u\n", (unsigned)blen, (unsigned)*len, (unsigned)*addr); /* Get the checksum. If the length was correct there should be just byte left in blen, but decrement it in a loop to skip to the end. */ if (blen) { while(blen--) { tape_csum=GetTAPByte(); if (blen) { csum ^= tape_csum; } } } else { tape_csum=b; } /* Check the checksum */ if (csum == tape_csum) { SPEC_DEBUG("Checksum %u (calc) and %u (tape) match\n", (unsigned)csum, (unsigned)tape_csum); return TRUE; } else { SPEC_DEBUG("Checksum %u (calc) and %u (tape) DON'T match\n", (unsigned)csum, (unsigned)tape_csum); return FALSE; } } else { /* If it's the wrong type, skip it */ while(blen--) { GetTAPByte(); } return FALSE; } } /* END OF FILE */