Ejemplo n.º 1
0
//=============================================================================
//	eTape::ParseCSW
//-----------------------------------------------------------------------------
bool eTape::ParseCSW(const void* data, size_t data_size)
{
	const byte* buf = (const byte*)data;
	const dword Z80FQ = 3500000;
	CloseTape();
	NamedCell("CSW tape image");
	if(buf[0x1B] != 1)
		return false; // unknown compression type
	dword rate = Z80FQ / Word(buf + 0x19); // usually 3.5mhz / 44khz
	if(!rate)
		return false;
	Reserve(data_size - 0x18);
	if(!(buf[0x1C] & 1))
		tape_image[tape_imagesize++] = FindPulse(1);
	for(const byte* ptr = (const byte*)data + 0x20; ptr < (const byte*)data + data_size;)
	{
		dword len = *ptr++ * rate;
		if(!len)
		{
			len = Dword(ptr) / rate;
			ptr += 4;
		}
		tape_image[tape_imagesize++] = FindPulse(len);
	}
	tape_image[tape_imagesize++] = FindPulse(Z80FQ / 10);
	FindTapeSizes();
	return true;
}
Ejemplo n.º 2
0
/*
 * Subroutine to do actual fixing after state initialization.
 */
static void
Dfix2(Char **v)
{
    ginit();			/* Initialize glob's area pointers */
    Dvp = v;
    Dcp = STRNULL;		/* Setup input vector for Dreadc */
    unDgetC(0);
    unDredc(0);			/* Clear out any old peeks (at error) */
    dolp = 0;
    dolcnt = 0;			/* Clear out residual $ expands (...) */
    while (Dword())
	continue;
}
Ejemplo n.º 3
0
/*
=============
  CheckSizeToWrite
=============
*/
void MemoryWriter::CheckSizeToWrite( Dword sizeToWrite )
{
    if( this->pos + sizeToWrite > this->buffer.getLength() )
    {
      Dword toAdd = Dword( Math::Ceil( float( sizeToWrite - ( this->buffer.getLength() - this->pos ) ) / float( this->blockSize ) ) ) * this->blockSize;
      if( this->buffer.getLength() )
      {
        memory temp( this->buffer );
        this->buffer.realloc( this->buffer.getLength() + toAdd );
        memcpy( this->buffer.getData(), temp.getData(), temp.getLength() );
      }
      else
        this->buffer.alloc( toAdd );
    }
}//CheckSizeToWrite
Ejemplo n.º 4
0
/*
 * Subroutine to do actual fixing after state initialization.
 */
void
Dfix2(tchar **v)
{
	tchar *agargv[GAVSIZ];

#ifdef TRACE
	tprintf("TRACE- Dfix2()\n");
#endif
	ginit(agargv);			/* Initialize glob's area pointers */
	Dvp = v; Dcp = S_ /* "" */;	/* Setup input vector for Dreadc */
	unDgetC(0); unDredc(0);		/* Clear out any old peeks (at error) */
	dolp = 0; dolcnt = 0;		/* Clear out residual $ expands (...) */
	while (Dword())
		continue;
	gargv = copyblk(gargv);
}
Ejemplo n.º 5
0
//=============================================================================
//	eFdd::ReadFdi
//-----------------------------------------------------------------------------
bool eFdd::ReadFdi(const void* _data, size_t data_size)
{
	const byte* buf = (const byte*)_data;
	SAFE_DELETE(disk);
	disk = new eUdi(buf[4], buf[6]);

	const byte* trk = buf + 0x0E + Word(buf + 0x0C);
	const byte* dat = buf + Word(buf + 0x0A);

	for(int i = 0; i < disk->Cyls(); ++i)
	{
		for(int j = 0; j < disk->Sides(); ++j)
		{
			Seek(i, j);

			int id_len = Track().data_len / 8 + ((Track().data_len & 7) ? 1 : 0);
			memset(Track().data, 0, Track().data_len + id_len);

			int pos = 0;
			WriteBlock(pos, 0x4e, 80);		//gap4a
			WriteBlock(pos, 0, 12);			//sync
			WriteBlock(pos, 0xc2, 3, true);	//iam
			Write(pos++, 0xfc);

			const byte* t0 = dat + Dword(trk);
			int ns = trk[6];
			Track().sectors_amount = ns;
			trk += 7;
			for(int i = 0; i < ns; ++i)
			{
				WriteBlock(pos, 0x4e, 40);		//gap1 50 fixme: recalculate gap1 only for non standard formats
				WriteBlock(pos, 0, 12);			//sync
				WriteBlock(pos, 0xa1, 3, true);	//id am
				Write(pos++, 0xfe);
				eUdi::eTrack::eSector& sec = Sector(i);
				sec.id = Track().data + pos;
				Write(pos++, trk[0]);
				Write(pos++, trk[1]);
				Write(pos++, trk[2]);
				Write(pos++, trk[3]);
				word crc = Crc(Track().data + pos - 5, 5);
				Write(pos++, crc >> 8);
				Write(pos++, (byte)crc);

				if(trk[4] & 0x40)
				{
					sec.data = NULL;
				}
				else
				{
					const byte* data = t0 + Word(trk+5);
					if(data + 128 > buf + data_size)
						return false;
					WriteBlock(pos, 0x4e, 22);		//gap2
					WriteBlock(pos, 0, 12);			//sync
					WriteBlock(pos, 0xa1, 3, true);	//data am
					Write(pos++, 0xfb);
					sec.data = Track().data + pos;
					int len = sec.Len();
					memcpy(sec.data, data, len);
					crc = Crc(Track().data + pos - 1, len + 1);
					if(!(trk[4] & (1<<(trk[3] & 3))))
						crc ^= 0xffff;
					pos += len;
					Write(pos++, crc >> 8);
					Write(pos++, (byte)crc);
				}
				trk += 7;
			}
			if(pos > Track().data_len)
			{
				assert(0); //track too long
			}
			WriteBlock(pos, 0x4e, Track().data_len - pos - 1); //gap3
		}
	}
	return true;
}
Ejemplo n.º 6
0
bool eZ80AccessorSZX::SetState(xIo::eStreamMemory& is)
{
	ZXSTHEADER header;
	if(is.Read(&header, sizeof(header)) != sizeof(header))
		return false;
	if(header.dwMagic != FOURCC('Z', 'X', 'S', 'T'))
		return false;
	bool model48k = false;
	switch(header.chMachineId)
	{
	case ZXSTMID_16K:
	case ZXSTMID_48K:
	case ZXSTMID_NTSC48K:
		model48k = true;
		break;
	case ZXSTMID_128K:
	case ZXSTMID_PENTAGON128:
		break;
	default:
		return false;
	}
	SetupDevices(model48k);
	ZXSTBLOCK block;
	while(is.Read(&block, sizeof(block)) == sizeof(block))
	{
		switch(block.dwId)
		{
		case FOURCC('Z', '8', '0', 'R'):
			{
				ZXSTZ80REGS regs;
				if(!ReadBlock(is, &regs, block))
					return false;
				af = SwapWord(regs.AF);
				bc = SwapWord(regs.BC);
				de = SwapWord(regs.DE);
				hl = SwapWord(regs.HL);
				alt.af = SwapWord(regs.AF1);
				alt.bc = SwapWord(regs.BC1);
				alt.de = SwapWord(regs.DE1);
				alt.hl = SwapWord(regs.HL1);

				ix = SwapWord(regs.IX);
				iy = SwapWord(regs.IY);
				sp = SwapWord(regs.SP);
				pc = SwapWord(regs.PC);
				i = regs.I;
				r_low = regs.R;
				r_hi = regs.R & 0x80;
				im = regs.IM;
				iff1 = regs.IFF1;
				iff2 = regs.IFF2;
				t = Dword((const byte*)&regs.dwCyclesStart) % frame_tacts;
				if(regs.wMemPtr)
					memptr = SwapWord(regs.wMemPtr);
			}
			break;
		case FOURCC('S', 'P', 'C', 'R'):
			{
				ZXSTSPECREGS regs;
				if(!ReadBlock(is, &regs, block))
					return false;
				devices->IoWrite(0xfe, (regs.chFe&0x18) | regs.chBorder, t);
				devices->IoWrite(0x7ffd, model48k ? 0x30 : regs.ch7ffd, t);
				if(model48k)
					devices->Get<eMemory>()->SetRomPage(eMemory::P_ROM_48);
				else
					devices->Get<eMemory>()->SetRomPage((regs.ch7ffd & 0x10) ? eMemory::P_ROM_128_0 : eMemory::P_ROM_128_1);
			}
			break;
		case FOURCC('R', 'A', 'M', 'P'):
			{
				ZXSTRAMPAGE ram_page;
				if(!ReadBlock(is, &ram_page, block, sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1))
					return false;
				byte* buf = new byte[eMemory::PAGE_SIZE];
				bool ok = false;
				if(SwapWord(ram_page.wFlags)&ZXSTRF_COMPRESSED)
				{
#ifdef USE_ZIP
					size_t size = ram_page.blk.dwSize - (sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1);
					byte* buf_compr = new byte[size];
					ok = is.Read(buf_compr, size) == size;
					if(ok)
					{
						z_stream zs;
						memset(&zs, 0, sizeof(zs));
						zs.next_in = buf_compr;
						zs.avail_in = size;
						zs.next_out = buf;
						zs.avail_out = eMemory::PAGE_SIZE;
						ok = inflateInit2(&zs, 15) == Z_OK;
						if(ok)
							ok = inflate(&zs, Z_NO_FLUSH) == Z_STREAM_END;
						inflateEnd(&zs);
					}
					SAFE_DELETE_ARRAY(buf_compr);
#endif//USE_ZIP
				}
				else
				{
					size_t size = ram_page.blk.dwSize - (sizeof(ZXSTRAMPAGE) - sizeof(ZXSTBLOCK) - 1);
					ok = size == eMemory::PAGE_SIZE;
					if(ok)
					{
						ok = is.Read(buf, size) == size;
					}
				}
				if(ok && ram_page.chPageNo <= 7)
				{
					memcpy(memory->Get(eMemory::P_RAM0 + ram_page.chPageNo), buf, eMemory::PAGE_SIZE);
				}
				SAFE_DELETE(buf);
				if(!ok)
					return false;
			}
			break;
		case FOURCC('A', 'Y', '\0', '\0'):
			{
				ZXSTAYBLOCK ay_state;
				if(!ReadBlock(is, &ay_state, block))
					return false;
				devices->Get<eAY>()->SetRegs(ay_state.chAyRegs);
				devices->Get<eAY>()->Select(ay_state.chCurrentRegister);
			}
			break;
		default:
			if(is.Seek(block.dwSize, xIo::eStreamMemory::S_CUR) != 0)
				return false;
		}
		if(is.Pos() == is.Size())
			return true;
	}
	return false;
}
Ejemplo n.º 7
0
//=============================================================================
//	eTape::ParseTZX
//-----------------------------------------------------------------------------
bool eTape::ParseTZX(const void* data, size_t data_size)
{
	byte* ptr = (byte*)data;
	CloseTape();
	dword size, pause, i, j, n, t, t0;
	byte pl, last, *end;
	byte* p;
	dword loop_n = 0, loop_p = 0;
	char nm[512];
	while(ptr < (const byte*)data + data_size)
	{
		switch(*ptr++)
		{
		case 0x10: // normal block
			AllocInfocell();
			size = Word(ptr + 2);
			pause = Word(ptr);
			ptr += 4;
			Desc(ptr, size, tapeinfo[tape_infosize].desc);
			tape_infosize++;
			MakeBlock(ptr, size, 2168, 667, 735, 855, 1710, (*ptr < 4) ? 8064
					: 3220, pause);
			ptr += size;
			break;
		case 0x11: // turbo block
			AllocInfocell();
			size = 0xFFFFFF & Dword(ptr + 0x0F);
			Desc(ptr + 0x12, size, tapeinfo[tape_infosize].desc);
			tape_infosize++;
			MakeBlock(ptr + 0x12, size, Word(ptr), Word(ptr + 2),
					Word(ptr + 4), Word(ptr + 6), Word(ptr + 8),
					Word(ptr + 10), Word(ptr + 13), ptr[12]);
			// todo: test used bits - ptr+12
			ptr += size + 0x12;
			break;
		case 0x12: // pure tone
			CreateAppendableBlock();
			pl = FindPulse(Word(ptr));
			n = Word(ptr + 2);
			Reserve(n);
			for(i = 0; i < n; i++)
				tape_image[tape_imagesize++] = pl;
			ptr += 4;
			break;
		case 0x13: // sequence of pulses of different lengths
			CreateAppendableBlock();
			n = *ptr++;
			Reserve(n);
			for(i = 0; i < n; i++, ptr += 2)
				tape_image[tape_imagesize++] = FindPulse(Word(ptr));
			break;
		case 0x14: // pure data block
			CreateAppendableBlock();
			size = 0xFFFFFF & Dword(ptr + 7);
			MakeBlock(ptr + 0x0A, size, 0, 0, 0, Word(ptr),
					Word(ptr + 2), -1, Word(ptr + 5), ptr[4]);
			ptr += size + 0x0A;
			break;
		case 0x15: // direct recording
			size = 0xFFFFFF & Dword(ptr + 5);
			t0 = Word(ptr);
			pause = Word(ptr + 2);
			last = ptr[4];
			NamedCell("direct recording");
			ptr += 8;
			pl = 0;
			n = 0;
			for(i = 0; i < size; i++) // count number of pulses
				for(j = 0x80; j; j >>= 1)
					if((ptr[i] ^ pl) & j)
						n++, pl ^= -1;
			t = 0;
			pl = 0;
			Reserve(n + 2);
			for(i = 1; i < size; i++, ptr++) // find pulses
				for(j = 0x80; j; j >>= 1)
				{
					t += t0;
					if((*ptr ^ pl) & j)
					{
						tape_image[tape_imagesize++] = FindPulse(t);
						pl ^= -1;
						t = 0;
					}
				}
			// find pulses - last byte
			for(j = 0x80; j != (byte)(0x80 >> last); j >>= 1)
			{
				t += t0;
				if((*ptr ^ pl) & j)
				{
					tape_image[tape_imagesize++] = FindPulse(t);
					pl ^= -1;
					t = 0;
				}
			}
			ptr++;
			tape_image[tape_imagesize++] = FindPulse(t); // last pulse ???
			if(pause)
				tape_image[tape_imagesize++] = FindPulse(pause * 3500);
			break;
		case 0x20: // pause (silence) or 'stop the tape' command
			pause = Word(ptr);
			sprintf(nm, pause ? "pause %d ms" : "stop the tape", pause);
			NamedCell(nm);
			Reserve(2);
			ptr += 2;
			if(!pause)
			{ // at least 1ms pulse as specified in TZX 1.13
				tape_image[tape_imagesize++] = FindPulse(3500);
				pause = -1;
			}
			else
				pause *= 3500;
			tape_image[tape_imagesize++] = FindPulse(pause);
			break;
		case 0x21: // group start
			n = *ptr++;
			NamedCell(ptr, n);
			ptr += n;
			appendable = 1;
			break;
		case 0x22: // group end
			break;
		case 0x23: // jump to block
			NamedCell("* jump");
			ptr += 2;
			break;
		case 0x24: // loop start
			loop_n = Word(ptr);
			loop_p = tape_imagesize;
			ptr += 2;
			break;
		case 0x25: // loop end
			if(!loop_n)
				break;
			size = tape_imagesize - loop_p;
			Reserve((loop_n - 1) * size);
			for(i = 1; i < loop_n; i++)
				memcpy(tape_image + loop_p + i * size, tape_image + loop_p,
						size);
			tape_imagesize += (loop_n - 1) * size;
			loop_n = 0;
			break;
		case 0x26: // call
			NamedCell("* call");
			ptr += 2 + 2 * Word(ptr);
			break;
		case 0x27: // ret
			NamedCell("* return");
			break;
		case 0x28: // select block
			sprintf(nm, "* choice: ");
			n = ptr[2];
			p = ptr + 3;
			for(i = 0; i < n; i++)
			{
				if(i)
					strcat(nm, " / ");
				char *q = nm + strlen(nm);
				size = *(p + 2);
				memcpy(q, p + 3, size);
				q[size] = 0;
				p += size + 3;
			}
			NamedCell(nm);
			ptr += 2 + Word(ptr);
			break;
		case 0x2A: // stop if 48k
			NamedCell("* stop if 48K");
			ptr += 4 + Dword(ptr);
			break;
		case 0x30: // text description
			n = *ptr++;
			NamedCell(ptr, n);
			ptr += n;
			appendable = 1;
			break;
		case 0x31: // message block
			NamedCell("- MESSAGE BLOCK ");
			end = ptr + 2 + ptr[1];
			pl = *end;
			*end = 0;
			for(p = ptr + 2; p < end; p++)
				if(*p == 0x0D)
					*p = 0;
			for(p = ptr + 2; p < end; p += strlen((char*)p) + 1)
				NamedCell(p);
			*end = pl;
			ptr = end;
			NamedCell("-");
			break;
		case 0x32: // archive info
			NamedCell("- ARCHIVE INFO ");
			p = ptr + 3;
			for(i = 0; i < ptr[2]; i++)
			{
				const char *info;
				switch(*p++)
				{
				case 0:
					info = "Title";
					break;
				case 1:
					info = "Publisher";
					break;
				case 2:
					info = "Author";
					break;
				case 3:
					info = "Year";
					break;
				case 4:
					info = "Language";
					break;
				case 5:
					info = "Type";
					break;
				case 6:
					info = "Price";
					break;
				case 7:
					info = "Protection";
					break;
				case 8:
					info = "Origin";
					break;
				case 0xFF:
					info = "Comment";
					break;
				default:
					info = "info";
					break;
				}
				dword size = *p + 1;
				char tmp = p[size];
				p[size] = 0;
				sprintf(nm, "%s: %s", info, p + 1);
				p[size] = tmp;
				p += size;
				NamedCell(nm);
			}
			NamedCell("-");
			ptr += 2 + Word(ptr);
			break;
		case 0x33: // hardware type
			ParseHardware(ptr);
			ptr += 1 + 3 * *ptr;
			break;
		case 0x34: // emulation info
			NamedCell("* emulation info");
			ptr += 8;
			break;
		case 0x35: // custom info
			if(!memcmp(ptr, "POKEs           ", 16))
			{
				NamedCell("- POKEs block ");
				NamedCell(ptr + 0x15, ptr[0x14]);
				p = ptr + 0x15 + ptr[0x14];
				n = *p++;
				for(i = 0; i < n; i++)
				{
					NamedCell(p + 1, *p);
					p += *p + 1;
					t = *p++;
					strcpy(nm, "POKE ");
					for(j = 0; j < t; j++)
					{
						sprintf(nm + strlen(nm), "%d,", Word(p + 1));
						sprintf(nm + strlen(nm), *p & 0x10 ? "nn" : "%d",
								*(byte*)(p + 3));
						if(!(*p & 0x08))
							sprintf(nm + strlen(nm), "(page %d)", *p & 7);
						strcat(nm, "; ");
						p += 5;
					}
					NamedCell(nm);
				}
				nm[0] = '-';
				nm[1] = 0;
				nm[2] = 0;
				nm[3] = 0;
			}
			else
				sprintf(nm, "* custom info: %s", ptr), nm[15 + 16] = 0;
			NamedCell(nm);
			ptr += 0x14 + Dword(ptr + 0x10);
			break;
		case 0x40: // snapshot
			NamedCell("* snapshot");
			ptr += 4 + (0xFFFFFF & Dword(ptr + 1));
			break;
		case 0x5A: // 'Z'
			ptr += 9;
			break;
		default:
			ptr += data_size;
		}
	}
	for(i = 0; i < tape_infosize; i++)
	{
		if(tapeinfo[i].desc[0] == '*' && tapeinfo[i].desc[1] == ' ')
			strcat(tapeinfo[i].desc, " [UNSUPPORTED]");
		if(*tapeinfo[i].desc == '-')
			while(strlen(tapeinfo[i].desc) < sizeof(tapeinfo[i].desc) - 1)
				strcat(tapeinfo[i].desc, "-");
	}
	if(tape_imagesize && tape_pulse[tape_image[tape_imagesize - 1]] < 350000)
		Reserve(1), tape_image[tape_imagesize++] = FindPulse(350000); // small pause [rqd for 3ddeathchase]
	FindTapeSizes();
	return (ptr == (const byte*)data + data_size);
}