public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, Types.FileType Type) { _LastError = ""; if ((Data.Length > 0) || (Type != Types.FileType.PRG)) { _LastError = "invalid file type"; return(false); } Data = new GR.Memory.ByteBuffer(Content); this.Filename = Filename; return(true); }
public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, Types.FileType Type) { _LastError = ""; int fileIndex = 0; foreach (FileRecord file in FileRecords) { if (file.EntryType == 0) { // free slot found file.EntryType = 1; file.C64FileType = Type; if (Type == Types.FileType.PRG) { file.StartAddress = Content.UInt16At(0); if (Content.Length < 2) { FileDatas[fileIndex] = new GR.Memory.ByteBuffer(); } else { FileDatas[fileIndex] = Content.SubBuffer(2); } } else { file.StartAddress = 0x0801; FileDatas[fileIndex] = new GR.Memory.ByteBuffer(Content); } file.EndAddress = (ushort)(file.StartAddress + Content.Length); file.FileOffset = 0; file.Filename = Filename; return(true); } ++fileIndex; } _LastError = "tape image is full"; return(false); }
public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, Types.FileType Type) { _LastError = ""; GR.Memory.ByteBuffer dataToWrite = new GR.Memory.ByteBuffer(Content); if (dataToWrite.Length > FreeBytes()) { _LastError = "file too large"; return(false); } Sector bam = Tracks[TRACK_BAM - 1].Sectors[SECTOR_BAM]; int trackIndex = 1; int prevSector = 0; int interleave = 10; int bytesToWrite = (int)dataToWrite.Length; int writeOffset = 0; Sector previousSector = null; int searchSector = -1; int startSector = -1; int startTrack = -1; int sectorsWritten = 0; write_next_sector :; trackIndex = 1; foreach (Track track in Tracks) { if (trackIndex == TRACK_DIRECTORY) { // directory track ++trackIndex; continue; } if (track.FreeSectors == 0) { ++trackIndex; continue; } int sectorsPerTrack = track.Sectors.Count; searchSector = (prevSector + interleave) % sectorsPerTrack; while (true) { if (track.Sectors[searchSector].Free) { AllocSector(trackIndex, searchSector); if (previousSector != null) { previousSector.Data.SetU8At(0, (byte)trackIndex); previousSector.Data.SetU8At(1, (byte)searchSector); } else { // first sector, add directory entry startSector = searchSector; startTrack = trackIndex; } previousSector = track.Sectors[searchSector]; if (bytesToWrite > 254) { //Debug.Log( "Write to T/S " + trackIndex + "," + searchSector ); dataToWrite.CopyTo(previousSector.Data, writeOffset, 254, 2); previousSector.Free = false; writeOffset += 254; bytesToWrite -= 254; ++sectorsWritten; prevSector = searchSector; goto write_next_sector; } // last sector //Debug.Log( "Write to T/S " + trackIndex + "," + searchSector ); previousSector.Free = false; previousSector.Data.SetU8At(0, 0); previousSector.Data.SetU8At(1, (byte)(1 + bytesToWrite)); dataToWrite.CopyTo(previousSector.Data, writeOffset, bytesToWrite, 2); writeOffset += bytesToWrite; bytesToWrite = 0; ++sectorsWritten; AddDirectoryEntry(Filename, startTrack, startSector, sectorsWritten, Type); return(true); } else { ++searchSector; if (searchSector >= sectorsPerTrack) { searchSector = 0; } } } } _LastError = "disk is full"; return(false); }
bool AddDirectoryEntry(GR.Memory.ByteBuffer Filename, int StartTrack, int StartSector, int SectorsWritten, Types.FileType Type) { _LastError = ""; Track dirTrack = Tracks[TRACK_DIRECTORY - 1]; byte dirTrackIndex = (byte)TRACK_DIRECTORY; for (int sector = SECTOR_DIRECTORY; sector < dirTrack.Sectors.Count; ++sector) { Sector sect = dirTrack.Sectors[sector]; for (int i = 0; i < 8; ++i) { if (sect.Data.ByteAt(BYTES_PER_DIR_ENTRY * i + 2) == 0) { // scratched (empty) entry // default set PRG sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 2, (byte)Type); sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 3, (byte)StartTrack); sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 4, (byte)StartSector); for (int j = 0; j < 16; ++j) { sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 5 + j, Filename.ByteAt(j)); } sect.Data.SetU16At(BYTES_PER_DIR_ENTRY * i + 30, (UInt16)SectorsWritten); return(true); } } // do we need to alloc next dir sector? if (sector + 1 == dirTrack.Sectors.Count) { // disk full!! (or continue on next track?) _LastError = "disk is full"; return(false); } if (sect.Data.ByteAt(0) == 0) { // current sector was last dir sector sect.Data.SetU8At(0, dirTrackIndex); sect.Data.SetU8At(1, (byte)(sector + 1)); AllocSector(dirTrackIndex, sector + 1); dirTrack.Sectors[sector + 1].Data.SetU8At(0, 0); dirTrack.Sectors[sector + 1].Data.SetU8At(1, 0xff); } } _LastError = "disk is full"; return(false); }
bool AddDirectoryEntry(GR.Memory.ByteBuffer Filename, int StartTrack, int StartSector, int SectorsWritten, Types.FileType Type) { _LastError = ""; Track dirTrack = Tracks[TRACK_DIRECTORY - 1]; byte dirTrackIndex = (byte)TRACK_DIRECTORY; int directoryInterleave = 3; int sector = 1; do { Sector sect = dirTrack.Sectors[sector]; for (int i = 0; i < 8; ++i) { if (sect.Data.ByteAt(BYTES_PER_DIR_ENTRY * i + 2) == 0) { // scratched (empty) entry // default set PRG sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 2, (byte)Type); sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 3, (byte)StartTrack); sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 4, (byte)StartSector); for (int j = 0; j < 16; ++j) { sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 5 + j, Filename.ByteAt(j)); } sect.Data.SetU16At(BYTES_PER_DIR_ENTRY * i + 30, (UInt16)SectorsWritten); return(true); } } // do we need to alloc next dir sector? do { sector = (sector + directoryInterleave) % dirTrack.Sectors.Count; // do NOT write into BAM }while (sector == SECTOR_BAM); if (sector == 1) { // arrived at starting sector, disk full! break; } if (sect.Data.ByteAt(0) == 0) { // current sector was last dir sector sect.Data.SetU8At(0, dirTrackIndex); sect.Data.SetU8At(1, (byte)(sector)); AllocSector(dirTrackIndex, sector); dirTrack.Sectors[sector].Data.SetU8At(0, 0); dirTrack.Sectors[sector].Data.SetU8At(1, 0xff); } }while (true); _LastError = "disk is full"; return(false); }
public override bool WriteFile(GR.Memory.ByteBuffer Filename, GR.Memory.ByteBuffer Content, Types.FileType Type) { _LastError = ""; FileEntry file = new FileEntry(); file.Filename = new GR.Memory.ByteBuffer(Filename); file.Data = new GR.Memory.ByteBuffer(Content); if (Type == Types.FileType.PRG) { if (Content.Length >= 2) { file.StartAddress = Content.UInt16At(0); file.Data = Content.SubBuffer(2); } } file.EndAddress = (ushort)(file.StartAddress + file.Data.Length - 1); if (file.StartAddress + file.Data.Length >= 65536) { _LastError = "file size too large"; return(false); } TapFiles.Add(file); return(true); }