Added support for loading T64 files.
All the PRG files contained inside a T64 image are transfered over to a in memory D64 image. This in turn is converted to the low level G64 like image that the emulator uses.
This commit is contained in:
parent
9c75e0bb97
commit
14452da320
8 changed files with 543 additions and 82 deletions
|
@ -163,6 +163,9 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
||||||
case DiskImage::D81:
|
case DiskImage::D81:
|
||||||
success = InsertD81(fileInfo, (unsigned char*)DiskImage::readBuffer, bytesRead, readOnly);
|
success = InsertD81(fileInfo, (unsigned char*)DiskImage::readBuffer, bytesRead, readOnly);
|
||||||
break;
|
break;
|
||||||
|
case DiskImage::T64:
|
||||||
|
success = InsertT64(fileInfo, (unsigned char*)DiskImage::readBuffer, bytesRead, readOnly);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
|
@ -251,6 +254,19 @@ bool DiskCaddy::InsertD81(const FILINFO* fileInfo, unsigned char* diskImageData,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DiskCaddy::InsertT64(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly)
|
||||||
|
{
|
||||||
|
DiskImage diskImage;
|
||||||
|
if (diskImage.OpenT64(fileInfo, diskImageData, size))
|
||||||
|
{
|
||||||
|
diskImage.SetReadOnly(readOnly);
|
||||||
|
disks.push_back(diskImage);
|
||||||
|
selectedIndex = disks.size() - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void DiskCaddy::Display()
|
void DiskCaddy::Display()
|
||||||
{
|
{
|
||||||
unsigned numberOfImages = GetNumberOfImages();
|
unsigned numberOfImages = GetNumberOfImages();
|
||||||
|
|
|
@ -106,6 +106,7 @@ private:
|
||||||
bool InsertNIB(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
bool InsertNIB(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
||||||
bool InsertNBZ(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
bool InsertNBZ(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
||||||
bool InsertD81(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
bool InsertD81(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
||||||
|
bool InsertT64(const FILINFO* fileInfo, unsigned char* diskImageData, unsigned size, bool readOnly);
|
||||||
|
|
||||||
void ShowSelectedImage(u32 index);
|
void ShowSelectedImage(u32 index);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "lz.h"
|
#include "lz.h"
|
||||||
|
#include "Petscii.h"
|
||||||
|
#include <malloc.h>
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "rpi-gpio.h"
|
#include "rpi-gpio.h"
|
||||||
|
@ -32,6 +34,35 @@ extern "C"
|
||||||
|
|
||||||
extern u32 HashBuffer(const void* pBuffer, u32 length);
|
extern u32 HashBuffer(const void* pBuffer, u32 length);
|
||||||
|
|
||||||
|
#define MAX_DIRECTORY_SECTORS 18
|
||||||
|
#define DIRECTORY_SIZE 32
|
||||||
|
#define DISK_SECTOR_OFFSET_FIRST_DIRECTORY_SECTOR 357
|
||||||
|
#define DISKNAME_OFFSET_IN_DIR_BLOCK 144
|
||||||
|
#define DISKID_OFFSET_IN_DIR_BLOCK 162
|
||||||
|
|
||||||
|
#define DIRECTRY_ENTRY_FILE_TYPE_PRG 0x82
|
||||||
|
|
||||||
|
static u8 blankD64DIRBAM[] =
|
||||||
|
{
|
||||||
|
0x12, 0x01, 0x41, 0x00, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
||||||
|
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
||||||
|
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
||||||
|
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
||||||
|
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x11, 0xfc, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07,
|
||||||
|
0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07,
|
||||||
|
0x13, 0xff, 0xff, 0x07, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03,
|
||||||
|
0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x11, 0xff, 0xff, 0x01,
|
||||||
|
0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01,
|
||||||
|
0x42, 0x4c, 0x41, 0x4e, 0x4b, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||||
|
0xa0, 0xa0, 0x31, 0x41, 0xa0, 0x32, 0x41, 0xa0, 0xa0, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
unsigned char DiskImage::readBuffer[READBUFFER_SIZE];
|
unsigned char DiskImage::readBuffer[READBUFFER_SIZE];
|
||||||
|
|
||||||
static unsigned char compressionBuffer[HALF_TRACK_COUNT * MAX_TRACK_LENGTH];
|
static unsigned char compressionBuffer[HALF_TRACK_COUNT * MAX_TRACK_LENGTH];
|
||||||
|
@ -140,6 +171,10 @@ void DiskImage::Close()
|
||||||
CloseD81();
|
CloseD81();
|
||||||
memset(tracksD81, 0, sizeof(tracksD81));
|
memset(tracksD81, 0, sizeof(tracksD81));
|
||||||
break;
|
break;
|
||||||
|
case T64:
|
||||||
|
CloseT64();
|
||||||
|
memset(tracks, 0x55, sizeof(tracks));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1164,6 +1199,102 @@ void DiskImage::CloseNBZ()
|
||||||
attachedImageSize = 0;
|
attachedImageSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DiskImage::OpenT64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
Close();
|
||||||
|
|
||||||
|
this->fileInfo = fileInfo;
|
||||||
|
|
||||||
|
attachedImageSize = size;
|
||||||
|
|
||||||
|
if ((memcmp(diskImage, "C64 tape image file", 20) == 0) || (memcmp(diskImage, "C64s tape image file", 21) == 0))
|
||||||
|
{
|
||||||
|
u16 version = diskImage[0x20] | (diskImage[0x21] << 8);
|
||||||
|
u16 entries = diskImage[0x22] | (diskImage[0x23] << 8);
|
||||||
|
u16 entriesUsed = diskImage[0x24] | (diskImage[0x25] << 8);
|
||||||
|
char name[25] = { 0 };
|
||||||
|
for (int i = 0; i < 24; ++i)
|
||||||
|
{
|
||||||
|
name[i] = tolower(diskImage[i + 0x28]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* newDiskImage = (unsigned char*)malloc(READBUFFER_SIZE);
|
||||||
|
|
||||||
|
if (newDiskImage)
|
||||||
|
{
|
||||||
|
unsigned length = DiskImage::CreateNewDiskInRAM(name, "00", newDiskImage);
|
||||||
|
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
|
||||||
|
u16 entryIndex;
|
||||||
|
|
||||||
|
for (entryIndex = 0; entryIndex < entriesUsed; ++entryIndex)
|
||||||
|
{
|
||||||
|
char nameEntry[17] = { 0 };
|
||||||
|
int offset = 0x40 + entryIndex * 32;
|
||||||
|
u8 type = diskImage[offset];
|
||||||
|
u8 fileType = diskImage[offset + 1];
|
||||||
|
if (fileType == DIRECTRY_ENTRY_FILE_TYPE_PRG)
|
||||||
|
{
|
||||||
|
u16 startAddress = diskImage[offset + 2] | (diskImage[offset + 3] << 8);
|
||||||
|
u16 endAddress = diskImage[offset + 4] | (diskImage[offset + 5] << 8);
|
||||||
|
unsigned length = endAddress - startAddress;
|
||||||
|
|
||||||
|
u32 fileOffset = diskImage[offset + 8] | (diskImage[offset + 9] << 8) | (diskImage[offset + 10] << 16) | (diskImage[offset + 11] << 24);
|
||||||
|
strncpy(nameEntry, (const char*)(diskImage + offset + 0x10), 16);
|
||||||
|
|
||||||
|
unsigned char* data = (unsigned char*)malloc(length + 2);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
data[0] = startAddress & 0xff;
|
||||||
|
data[1] = (startAddress >> 8) & 0xff;
|
||||||
|
|
||||||
|
memcpy(data + 2, diskImage + fileOffset, length);
|
||||||
|
length += 2;
|
||||||
|
bool addFileSuccess = AddFileToRAMD64(newDiskImage, nameEntry, data, length);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OpenD64(fileInfo, newDiskImage, length))
|
||||||
|
{
|
||||||
|
success = true;
|
||||||
|
diskType = T64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(newDiskImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskImage::WriteT64(char* name)
|
||||||
|
{
|
||||||
|
if (readOnly)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiskImage::CloseT64()
|
||||||
|
{
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
|
WriteT64();
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
attachedImageSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool DiskImage::GetDecodedSector(u32 track, u32 sector, u8* buffer)
|
bool DiskImage::GetDecodedSector(u32 track, u32 sector, u8* buffer)
|
||||||
{
|
{
|
||||||
if (track > 0)
|
if (track > 0)
|
||||||
|
@ -1190,6 +1321,8 @@ DiskImage::DiskType DiskImage::GetDiskImageTypeViaExtention(const char* diskImag
|
||||||
return NBZ;
|
return NBZ;
|
||||||
else if (toupper((char)ext[1]) == 'D' && ext[2] == '6' && ext[3] == '4')
|
else if (toupper((char)ext[1]) == 'D' && ext[2] == '6' && ext[3] == '4')
|
||||||
return D64;
|
return D64;
|
||||||
|
else if (toupper((char)ext[1]) == 'T' && ext[2] == '6' && ext[3] == '4')
|
||||||
|
return T64;
|
||||||
else if (IsLSTExtention(diskImageName))
|
else if (IsLSTExtention(diskImageName))
|
||||||
return LST;
|
return LST;
|
||||||
else if (toupper((char)ext[1]) == 'D' && ext[2] == '8' && ext[3] == '1')
|
else if (toupper((char)ext[1]) == 'D' && ext[2] == '8' && ext[3] == '1')
|
||||||
|
@ -1418,3 +1551,358 @@ unsigned DiskImage::LastTrackUsed()
|
||||||
}
|
}
|
||||||
return lastTrackUsed;
|
return lastTrackUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned DiskImage::CreateNewDiskInRAM(const char* filenameNew, const char* ID, unsigned char* destBuffer)
|
||||||
|
{
|
||||||
|
unsigned char* dest;
|
||||||
|
unsigned char* ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
DEBUG_LOG("CreateNewDiskInRAM %s\r\n", filenameNew);
|
||||||
|
|
||||||
|
unsigned char buffer[256];
|
||||||
|
u32 bytes;
|
||||||
|
u32 blocks;
|
||||||
|
|
||||||
|
if (destBuffer == 0)
|
||||||
|
destBuffer = DiskImage::readBuffer;
|
||||||
|
|
||||||
|
dest = destBuffer;
|
||||||
|
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
|
||||||
|
for (blocks = 0; blocks < DISK_SECTOR_OFFSET_FIRST_DIRECTORY_SECTOR; ++blocks)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
*dest++ = buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = (unsigned char*)&blankD64DIRBAM[DISKNAME_OFFSET_IN_DIR_BLOCK];
|
||||||
|
int len = strlen(filenameNew);
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
*ptr++ = ascii2petscii(filenameNew[i]);
|
||||||
|
}
|
||||||
|
for (; i < 18; ++i)
|
||||||
|
{
|
||||||
|
*ptr++ = 0xa0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
*ptr++ = ascii2petscii(ID[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
*dest++ = blankD64DIRBAM[i];
|
||||||
|
}
|
||||||
|
buffer[1] = 0xff;
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
*dest++ = buffer[i];
|
||||||
|
}
|
||||||
|
buffer[1] = 0;
|
||||||
|
for (blocks = 0; blocks < 324; ++blocks)
|
||||||
|
{
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
*dest++ = buffer[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned)(dest - destBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DiskImage::RAMD64GetSectorOffset(int track, int sector)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int sectorOffset = 0;
|
||||||
|
|
||||||
|
for (index = 0; index < (track - 1); ++index)
|
||||||
|
{
|
||||||
|
sectorOffset += SectorsPerTrack[index];
|
||||||
|
}
|
||||||
|
sectorOffset += sector;
|
||||||
|
return sectorOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* DiskImage::RAMD64AddDirectoryEntry(unsigned char* ramD64, const char* name, const unsigned char* data, unsigned length)
|
||||||
|
{
|
||||||
|
unsigned char* ptrTrackSector = 0;
|
||||||
|
unsigned char* ptr;
|
||||||
|
int directorySector;
|
||||||
|
int track = 18;
|
||||||
|
int i;
|
||||||
|
int numberOfBlocks = length / (256 - 2) + ((length % (256 - 2)) ? 1 : 0);
|
||||||
|
|
||||||
|
int sectorOffset = RAMD64GetSectorOffset(18, 0);
|
||||||
|
ptr = ramD64 + sectorOffset * 256;
|
||||||
|
|
||||||
|
track = ptr[0];
|
||||||
|
|
||||||
|
for (directorySector = 1; directorySector < 19; ++directorySector)
|
||||||
|
{
|
||||||
|
int entryIndex;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
sectorOffset = RAMD64GetSectorOffset(track, directorySector);
|
||||||
|
|
||||||
|
DEBUG_LOG("directory sector offset = %d\r\n", sectorOffset);
|
||||||
|
ptr = ramD64 + sectorOffset * 256;
|
||||||
|
|
||||||
|
entryIndex = 0;
|
||||||
|
while (!found && entryIndex < 8)
|
||||||
|
{
|
||||||
|
unsigned char* ptrEntry = ptr + 2 + entryIndex * DIRECTORY_SIZE;
|
||||||
|
|
||||||
|
if (*ptrEntry == 0)
|
||||||
|
{
|
||||||
|
*ptrEntry++ = DIRECTRY_ENTRY_FILE_TYPE_PRG;
|
||||||
|
|
||||||
|
ptrTrackSector = ptrEntry;
|
||||||
|
|
||||||
|
ptrEntry++; // track data start
|
||||||
|
ptrEntry++; // sector data start
|
||||||
|
|
||||||
|
int len = strlen(name);
|
||||||
|
len = Min(len, 16);
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
*ptrEntry++ = ascii2petscii(tolower(name[i]));
|
||||||
|
}
|
||||||
|
for (; i < 16; ++i)
|
||||||
|
{
|
||||||
|
*ptrEntry++ = 0xa0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrEntry++; // track and sector of the first side sector block
|
||||||
|
ptrEntry++;
|
||||||
|
|
||||||
|
ptrEntry++; // record length
|
||||||
|
|
||||||
|
ptrEntry++; // not used
|
||||||
|
ptrEntry++;
|
||||||
|
ptrEntry++;
|
||||||
|
ptrEntry++;
|
||||||
|
|
||||||
|
ptrEntry++; // Track and sector of the new file when overwrtiting with the at sign
|
||||||
|
ptrEntry++;
|
||||||
|
|
||||||
|
*ptrEntry++ = (unsigned char)(numberOfBlocks & 0xff);
|
||||||
|
*ptrEntry++ = (unsigned char)(numberOfBlocks >> 8);
|
||||||
|
ptrEntry++; // not used
|
||||||
|
ptrEntry++;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++entryIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entryIndex < 8)
|
||||||
|
{
|
||||||
|
ptr[0] = 0;
|
||||||
|
ptr[1] = 0xff;
|
||||||
|
|
||||||
|
if (directorySector > 1)
|
||||||
|
{
|
||||||
|
unsigned char* ptrPrevSector = ramD64 + RAMD64GetSectorOffset(track, directorySector - 1) * 256;
|
||||||
|
|
||||||
|
ptrPrevSector[0] = track;
|
||||||
|
ptrPrevSector[1] = directorySector - 1;
|
||||||
|
// Allocate directory sector in the BAM
|
||||||
|
RAMD64AllocateSector(ramD64, track, directorySector);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptrTrackSector;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DiskImage::RAMD64FreeSectors(unsigned char* ramD64)
|
||||||
|
{
|
||||||
|
int freeSectors = 0;
|
||||||
|
unsigned char* ptr;
|
||||||
|
int sectorOffset = RAMD64GetSectorOffset(18, 0);
|
||||||
|
|
||||||
|
DEBUG_LOG("sectorOffset bam = %d\r\n", sectorOffset);
|
||||||
|
|
||||||
|
ptr = ramD64 + sectorOffset * 256;
|
||||||
|
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
int trackIndex;
|
||||||
|
for (trackIndex = 0; trackIndex < 35; ++trackIndex)
|
||||||
|
{
|
||||||
|
freeSectors += *ptr;
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
return freeSectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskImage::RAMD64AllocateSector(unsigned char* ramD64, int track, int sector)
|
||||||
|
{
|
||||||
|
int sectorOffset = RAMD64GetSectorOffset(18, 0);
|
||||||
|
unsigned bits;
|
||||||
|
unsigned char* ptr = 4 + ramD64 + sectorOffset * 256 + 4 * (track - 1);
|
||||||
|
unsigned bitMap = 1 << sector;
|
||||||
|
bits = ptr[1];
|
||||||
|
bits |= ptr[2] << 8;
|
||||||
|
bits |= ptr[3] << 16;
|
||||||
|
if (bits & bitMap)
|
||||||
|
{
|
||||||
|
ptr[0]--;
|
||||||
|
bits &= ~bitMap;
|
||||||
|
ptr[1] = (unsigned char)(bits & 0xff);
|
||||||
|
ptr[2] = (unsigned char)((bits >> 8) & 0xff);
|
||||||
|
ptr[3] = (unsigned char)((bits >> 16) & 0xff);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, int lastTrackUsed, int lastSectorUsed, int& track, int& sector)
|
||||||
|
{
|
||||||
|
unsigned char* ptr;
|
||||||
|
int sectorOffset = RAMD64GetSectorOffset(18, 0);
|
||||||
|
int trackIndex;
|
||||||
|
int sectorIndex;
|
||||||
|
int stripAmount = 10;
|
||||||
|
|
||||||
|
track = 0;
|
||||||
|
sector = -1;
|
||||||
|
if (searchForwards)
|
||||||
|
{
|
||||||
|
if (lastTrackUsed == -1)
|
||||||
|
trackIndex = 18;
|
||||||
|
else
|
||||||
|
trackIndex = lastTrackUsed - 1;
|
||||||
|
|
||||||
|
for (; trackIndex < 35; ++trackIndex)
|
||||||
|
{
|
||||||
|
if (lastTrackUsed != (trackIndex + 1))
|
||||||
|
{
|
||||||
|
lastSectorUsed = 0;
|
||||||
|
stripAmount = 0;
|
||||||
|
}
|
||||||
|
if (lastSectorUsed < 0)
|
||||||
|
{
|
||||||
|
lastSectorUsed = 0;
|
||||||
|
stripAmount = 0;
|
||||||
|
}
|
||||||
|
ptr = 4 + ramD64 + sectorOffset * 256 + 4 * trackIndex;
|
||||||
|
if (*ptr != 0)
|
||||||
|
{
|
||||||
|
for (sectorIndex = 0; sectorIndex < SectorsPerTrack[trackIndex]; ++sectorIndex)
|
||||||
|
{
|
||||||
|
int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % SectorsPerTrack[trackIndex];
|
||||||
|
if (RAMD64AllocateSector(ramD64, trackIndex + 1, sectorStripped))
|
||||||
|
{
|
||||||
|
track = trackIndex + 1;
|
||||||
|
sector = sectorStripped;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (lastTrackUsed == -1)
|
||||||
|
trackIndex = 16;
|
||||||
|
else
|
||||||
|
trackIndex = lastTrackUsed - 1;
|
||||||
|
for (; trackIndex >= 0; --trackIndex)
|
||||||
|
{
|
||||||
|
if (lastTrackUsed != (trackIndex + 1))
|
||||||
|
{
|
||||||
|
lastSectorUsed = 0;
|
||||||
|
stripAmount = 0;
|
||||||
|
}
|
||||||
|
if (lastSectorUsed < 0)
|
||||||
|
{
|
||||||
|
lastSectorUsed = 0;
|
||||||
|
stripAmount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = 4 + ramD64 + sectorOffset * 256 + 4 * trackIndex;
|
||||||
|
if (*ptr != 0)
|
||||||
|
{
|
||||||
|
for (sectorIndex = 0; sectorIndex < SectorsPerTrack[trackIndex]; ++sectorIndex)
|
||||||
|
{
|
||||||
|
int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % SectorsPerTrack[trackIndex];
|
||||||
|
if (RAMD64AllocateSector(ramD64, trackIndex + 1, sectorStripped))
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
track = trackIndex + 1;
|
||||||
|
sector = sectorStripped;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiskImage::AddFileToRAMD64(unsigned char* ramD64, const char* name, const unsigned char* data, unsigned length)
|
||||||
|
{
|
||||||
|
int numberOfSectorsRequired = length / (256 - 2) + ((length % (256 - 2)) ? 1 : 0);
|
||||||
|
int freeSectors = RAMD64FreeSectors(ramD64);
|
||||||
|
int bytesRemaining = length;
|
||||||
|
bool success = false;
|
||||||
|
int lastTrackUsed = -1;
|
||||||
|
int lastSectorUsed = -1;
|
||||||
|
|
||||||
|
if (freeSectors >= numberOfSectorsRequired)
|
||||||
|
{
|
||||||
|
unsigned char* ptrTrackSector = RAMD64AddDirectoryEntry(ramD64, name, data, length);
|
||||||
|
if (ptrTrackSector)
|
||||||
|
{
|
||||||
|
int blocks;
|
||||||
|
|
||||||
|
for (blocks = 0; blocks < numberOfSectorsRequired; ++blocks)
|
||||||
|
{
|
||||||
|
int track;
|
||||||
|
int sector;
|
||||||
|
|
||||||
|
bool found = RAMD64FindFreeSector(true, ramD64, lastTrackUsed, lastSectorUsed, track, sector);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
if (lastTrackUsed >= 18)
|
||||||
|
lastTrackUsed = -1;
|
||||||
|
found = RAMD64FindFreeSector(false, ramD64, lastTrackUsed, lastSectorUsed, track, sector);
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
lastTrackUsed = track;
|
||||||
|
lastSectorUsed = sector;
|
||||||
|
ptrTrackSector[0] = track;
|
||||||
|
ptrTrackSector[1] = sector;
|
||||||
|
ptrTrackSector = ramD64 + RAMD64GetSectorOffset(track, sector) * 256;
|
||||||
|
|
||||||
|
int bytesToCopy = (256 - 2);
|
||||||
|
|
||||||
|
if (bytesRemaining < (256 - 2))
|
||||||
|
{
|
||||||
|
bytesToCopy = bytesRemaining + 1;
|
||||||
|
ptrTrackSector[0] = 0;
|
||||||
|
ptrTrackSector[1] = bytesToCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesRemaining -= bytesToCopy;
|
||||||
|
|
||||||
|
memcpy(ptrTrackSector + 2, data, bytesToCopy);
|
||||||
|
}
|
||||||
|
data += (256 - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
|
@ -62,17 +62,21 @@ public:
|
||||||
LST,
|
LST,
|
||||||
D71,
|
D71,
|
||||||
D81,
|
D81,
|
||||||
|
T64,
|
||||||
RAW
|
RAW
|
||||||
};
|
};
|
||||||
|
|
||||||
DiskImage();
|
DiskImage();
|
||||||
|
|
||||||
|
static unsigned CreateNewDiskInRAM(const char* filenameNew, const char* ID, unsigned char* destBuffer = 0);
|
||||||
|
|
||||||
bool OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
bool OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenG64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
bool OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenNIB(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
bool OpenNBZ(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenNBZ(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
bool OpenD71(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenD71(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
bool OpenD81(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
bool OpenD81(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
|
bool OpenT64(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
@ -210,11 +214,13 @@ private:
|
||||||
void CloseNBZ();
|
void CloseNBZ();
|
||||||
void CloseD71();
|
void CloseD71();
|
||||||
void CloseD81();
|
void CloseD81();
|
||||||
|
void CloseT64();
|
||||||
|
|
||||||
bool WriteNIB();
|
bool WriteNIB();
|
||||||
bool WriteNBZ();
|
bool WriteNBZ();
|
||||||
bool WriteD71();
|
bool WriteD71();
|
||||||
bool WriteD81();
|
bool WriteD81();
|
||||||
|
bool WriteT64(char* name = 0);
|
||||||
|
|
||||||
inline void TestDirty(u32 track, bool isDirty)
|
inline void TestDirty(u32 track, bool isDirty)
|
||||||
{
|
{
|
||||||
|
@ -235,6 +241,14 @@ private:
|
||||||
void OutputD81HeaderByte(unsigned char*& dest, unsigned char byte);
|
void OutputD81HeaderByte(unsigned char*& dest, unsigned char byte);
|
||||||
void OutputD81DataByte(unsigned char*& src, unsigned char*& dest);
|
void OutputD81DataByte(unsigned char*& src, unsigned char*& dest);
|
||||||
|
|
||||||
|
static bool AddFileToRAMD64(unsigned char* ramD64, const char* name, const unsigned char* data, unsigned length);
|
||||||
|
static unsigned char* RAMD64AddDirectoryEntry(unsigned char* ramD64, const char* name, const unsigned char* data, unsigned length);
|
||||||
|
static int RAMD64GetSectorOffset(int track, int sector);
|
||||||
|
static int RAMD64FreeSectors(unsigned char* ramD64);
|
||||||
|
static bool RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, int lastTrackUsed, int lastSectorUsed, int& track, int& sector);
|
||||||
|
static bool RAMD64AllocateSector(unsigned char* ramD64, int track, int sector);
|
||||||
|
static bool WriteRAMD64(unsigned char* diskImage, unsigned size);
|
||||||
|
|
||||||
bool readOnly;
|
bool readOnly;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
unsigned attachedImageSize;
|
unsigned attachedImageSize;
|
||||||
|
|
|
@ -1332,7 +1332,7 @@ bool FileBrowser::SelectLST(const char* filenameLST)
|
||||||
{
|
{
|
||||||
//DEBUG_LOG("LST token = %s\r\n", token);
|
//DEBUG_LOG("LST token = %s\r\n", token);
|
||||||
diskType = DiskImage::GetDiskImageTypeViaExtention(token);
|
diskType = DiskImage::GetDiskImageTypeViaExtention(token);
|
||||||
if (diskType == DiskImage::D64 || diskType == DiskImage::G64 || diskType == DiskImage::NIB || diskType == DiskImage::NBZ)
|
if (diskType == DiskImage::D64 || diskType == DiskImage::G64 || diskType == DiskImage::NIB || diskType == DiskImage::NBZ || diskType == DiskImage::T64)
|
||||||
{
|
{
|
||||||
FileBrowser::BrowsableList::Entry* entry = folder.FindEntry(token);
|
FileBrowser::BrowsableList::Entry* entry = folder.FindEntry(token);
|
||||||
if (entry && !(entry->filImage.fattrib & AM_DIR))
|
if (entry && !(entry->filImage.fattrib & AM_DIR))
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "DiskImage.h"
|
#include "DiskImage.h"
|
||||||
#include "Petscii.h"
|
#include "Petscii.h"
|
||||||
#include "FileBrowser.h"
|
#include "FileBrowser.h"
|
||||||
|
#include "DiskImage.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -93,29 +94,6 @@ static const u8 filetypes[] = {
|
||||||
'D', 'I', 'R', // 6
|
'D', 'I', 'R', // 6
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DISKNAME_OFFSET_IN_DIR_BLOCK 144
|
|
||||||
#define DISKID_OFFSET_IN_DIR_BLOCK 162
|
|
||||||
static u8 blankD64DIRBAM[] =
|
|
||||||
{
|
|
||||||
0x12, 0x01, 0x41, 0x00, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
|
||||||
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
|
||||||
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
|
||||||
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f,
|
|
||||||
0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x11, 0xfc, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07,
|
|
||||||
0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07, 0x13, 0xff, 0xff, 0x07,
|
|
||||||
0x13, 0xff, 0xff, 0x07, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03,
|
|
||||||
0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x12, 0xff, 0xff, 0x03, 0x11, 0xff, 0xff, 0x01,
|
|
||||||
0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01, 0x11, 0xff, 0xff, 0x01,
|
|
||||||
0x42, 0x4c, 0x41, 0x4e, 0x4b, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
|
||||||
0xa0, 0xa0, 0x31, 0x41, 0xa0, 0x32, 0x41, 0xa0, 0xa0, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
// 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static char ErrorMessage[64];
|
static char ErrorMessage[64];
|
||||||
|
|
||||||
static u8* InsertNumber(u8* msg, u8 value)
|
static u8* InsertNumber(u8* msg, u8 value)
|
||||||
|
@ -2136,11 +2114,6 @@ void IEC_Commands::CloseFile(u8 secondary)
|
||||||
|
|
||||||
int IEC_Commands::CreateNewDisk(char* filenameNew, char* ID, bool automount)
|
int IEC_Commands::CreateNewDisk(char* filenameNew, char* ID, bool automount)
|
||||||
{
|
{
|
||||||
FILINFO filInfo;
|
|
||||||
FRESULT res;
|
|
||||||
char* ptr;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
DisplayMessage(240, 280, false, "Creating new disk", RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0, 0, 0xff));
|
DisplayMessage(240, 280, false, "Creating new disk", RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0, 0, 0xff));
|
||||||
DisplayMessage(0, 0, true, "Creating new disk", RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0, 0, 0xff));
|
DisplayMessage(0, 0, true, "Creating new disk", RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0, 0, 0xff));
|
||||||
|
|
||||||
|
@ -2159,63 +2132,22 @@ int IEC_Commands::CreateNewDisk(char* filenameNew, char* ID, bool automount)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned length = DiskImage::CreateNewDiskInRAM(filenameNew, ID);
|
||||||
|
|
||||||
|
return WriteNewDiskInRAM(filenameNew, automount, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int IEC_Commands::WriteNewDiskInRAM(char* filenameNew, bool automount, unsigned length)
|
||||||
|
{
|
||||||
|
FILINFO filInfo;
|
||||||
|
FRESULT res;
|
||||||
|
|
||||||
res = f_stat(filenameNew, &filInfo);
|
res = f_stat(filenameNew, &filInfo);
|
||||||
if (res == FR_NO_FILE)
|
if (res == FR_NO_FILE)
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned char* dest = DiskImage::readBuffer;
|
|
||||||
|
|
||||||
char buffer[256];
|
|
||||||
u32 bytes;
|
|
||||||
u32 blocks;
|
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
|
||||||
// TODO: Should check for disk full.
|
|
||||||
for (blocks = 0; blocks < 357; ++blocks)
|
|
||||||
{
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
*dest++ = buffer[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ptr = (char*)&blankD64DIRBAM[DISKNAME_OFFSET_IN_DIR_BLOCK];
|
|
||||||
int len = strlen(filenameNew);
|
|
||||||
for (i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
*ptr++ = ascii2petscii(filenameNew[i]);
|
|
||||||
}
|
|
||||||
for (; i < 18; ++i)
|
|
||||||
{
|
|
||||||
*ptr++ = 0xa0;
|
|
||||||
}
|
|
||||||
for (i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
*ptr++ = ascii2petscii(ID[i]);
|
|
||||||
}
|
|
||||||
//f_write(&fpOut, blankD64DIRBAM, 256, &bytes);
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
*dest++ = blankD64DIRBAM[i];
|
|
||||||
}
|
|
||||||
buffer[1] = 0xff;
|
|
||||||
//f_write(&fpOut, buffer, 256, &bytes);
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
*dest++ = buffer[i];
|
|
||||||
}
|
|
||||||
buffer[1] = 0;
|
|
||||||
for (blocks = 0; blocks < 324; ++blocks)
|
|
||||||
{
|
|
||||||
//if (f_write(&fpOut, buffer, 256, &bytes) != FR_OK)
|
|
||||||
// break;
|
|
||||||
for (i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
*dest++ = buffer[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DiskImage diskImage;
|
DiskImage diskImage;
|
||||||
diskImage.OpenD64((const FILINFO*)0, (unsigned char*)DiskImage::readBuffer, dest - (unsigned char*)DiskImage::readBuffer);
|
diskImage.OpenD64((const FILINFO*)0, (unsigned char*)DiskImage::readBuffer, length);
|
||||||
|
|
||||||
switch (newDiskType)
|
switch (newDiskType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -172,6 +172,8 @@ protected:
|
||||||
|
|
||||||
u8 GetFilenameCharacter(u8 value);
|
u8 GetFilenameCharacter(u8 value);
|
||||||
|
|
||||||
|
int WriteNewDiskInRAM(char* filenameNew, bool automount, unsigned length);
|
||||||
|
|
||||||
UpdateAction updateAction;
|
UpdateAction updateAction;
|
||||||
u8 commandCode;
|
u8 commandCode;
|
||||||
bool receivedCommand : 1;
|
bool receivedCommand : 1;
|
||||||
|
|
|
@ -24,4 +24,12 @@ typedef enum {
|
||||||
EXIT_AUTOLOAD
|
EXIT_AUTOLOAD
|
||||||
} EXIT_TYPE;
|
} EXIT_TYPE;
|
||||||
|
|
||||||
|
#ifndef Max
|
||||||
|
#define Max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Min
|
||||||
|
#define Min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue