public D64Drive(IEC iec, string filepath) : base(iec) { the_file = null; ram = null; Ready = false; orig_d64_name = filepath; for (int i = 0; i < chan_mode.Length - 1; i++) { chan_mode[i] = ChannelMode.CHMOD_FREE; } chan_mode[15] = ChannelMode.CHMOD_COMMAND; // Open .d64 file open_close_d64_file(filepath); if (the_file != null) { // Allocate 1541 RAM ram = new BytePtr(0x800); unsafe { bam = (BAM *)(ram.Pointer + 0x700); } Reset(); Ready = true; } }
protected void set_error(ErrorCode1541 error) { if (error_ptr_buf != null) { error_ptr_buf.Dispose(); } unsafe { error_ptr_buf = Errors_1541[(int)error]; error_ptr = error_ptr_buf; error_len = Errors_1541[(int)error].Length; } // Set drive condition if (error != ErrorCode1541.ERR_OK) if (error == ErrorCode1541.ERR_STARTUP) LED = DriveLEDState.DRVLED_OFF; else LED = DriveLEDState.DRVLED_ERROR; else if (LED == DriveLEDState.DRVLED_ERROR) LED = DriveLEDState.DRVLED_OFF; the_iec.UpdateLEDs(); }
unsafe void chd64_cmd(byte *d64name) { using (BytePtr str = new BytePtr(IEC.NAMEBUF_LENGTH)) { byte *p = str; // Convert .d64 file name for (int i = 0; i < IEC.NAMEBUF_LENGTH && (*p++ = conv_from_64(*d64name++, false)) != 0; i++) { ; } close_all_channels(); // G:. resets the .d64 file name to its original setting if (str[0] == '.' && str[1] == 0) { open_close_d64_file(orig_d64_name); } else { open_close_d64_file(str.ToString()); } // Read BAM read_sector(18, 0, (byte *)bam); } }
void find_first_file(BytePtr aName) { DirectoryInfo dir = new DirectoryInfo(dir_path); if (!dir.Exists) { return; } FileInfo[] files = dir.GetFiles(); string name = aName.ToString(); IEnumerator fenum = files.GetEnumerator(); while (fenum.MoveNext() && (((FileInfo)fenum.Current).Name == "." || ((FileInfo)fenum.Current).Name == "..")) { ; } do { FileInfo fi = (FileInfo)fenum.Current; // Match found? Then copy real file name if (match(name, fi.Name)) { CharFunctions.strncpy(aName, fi.Name); return; } } while (fenum.MoveNext()); }
byte open_direct(int channel, BytePtr filename) { int buf = -1; if (filename[1] == 0) { buf = alloc_buffer(-1); } else if ((filename[1] >= '0') && (filename[1] <= '3') && (filename[2] == 0)) { buf = alloc_buffer(filename[1] - '0'); } if (buf == -1) { set_error(ErrorCode1541.ERR_NOCHANNEL); return((byte)C64StatusCode.ST_OK); } unsafe { // The buffers are in the 1541 RAM at $300 and are 256 bytes each chan_buf[channel] = buf_ptr[channel] = (byte *)ram + 0x300 + (buf << 8); chan_mode[channel] = ChannelMode.CHMOD_DIRECT; chan_buf_num[channel] = buf; // Store actual buffer number in buffer *chan_buf[channel] = (byte)(buf + '0'); buf_len[channel] = 1; } return((byte)C64StatusCode.ST_OK); }
public override byte Open(int channel, byte[] aFilename) { using (BytePtr filename = new BytePtr(aFilename)) { set_error(ErrorCode1541.ERR_OK); // Channel 15: Execute file name as command if (channel == 15) { execute_command(filename); return (byte)C64StatusCode.ST_OK; } // Close previous file if still open if (file[channel] != null) { file[channel].Dispose(); file[channel] = null; } if (filename[0] == '$') unsafe { return open_directory(channel, filename.Pointer + 1); } if (filename[0] == '#') { set_error(ErrorCode1541.ERR_NOCHANNEL); return (byte)C64StatusCode.ST_OK; } return open_file(channel, filename); } }
unsafe void convert_filename(BytePtr srcname, BytePtr destname, ref FileAccessMode filemode, ref FileType filetype) { byte *p; // Search for ':', p points to first character after ':' if ((p = CharFunctions.strchr(srcname, ':')) != null) { p++; } else { p = srcname; } // Remaining string -> destname CharFunctions.strncpy(destname, srcname, p); // Look for mode parameters seperated by ',' p = destname; while ((p = CharFunctions.strchr(p, ',')) != null) { // Cut string after the first ',' *p++ = 0; switch ((Char)(*p)) { case 'P': filetype = FileType.FTYPE_PRG; break; case 'S': filetype = FileType.FTYPE_SEQ; break; case 'U': filetype = FileType.FTYPE_USR; break; case 'L': filetype = FileType.FTYPE_REL; break; case 'R': filemode = FileAccessMode.FMODE_READ; break; case 'W': filemode = FileAccessMode.FMODE_WRITE; break; case 'A': filemode = FileAccessMode.FMODE_APPEND; break; } } }
public static void strncpy(BytePtr dest, string src) { int i = 0; for (; i < dest.Length && i < src.Length; i++) { dest[i] = (byte)src[i]; } dest[i] = 0x00; }
public static void strncpy(BytePtr dest, BytePtr src, long start) { long i = start, j = 0; for (; i < dest.Length && src[i] != 0x00; i++, j++) { dest[j] = src[i]; } dest[j] = 0x00; }
unsafe public static byte *strchr(BytePtr src, byte c) { for (int i = 0; i < src.Length; i++) { if (src[i] == c) { return(src.Pointer + i); } } return(null); }
unsafe byte open_file(int channel, BytePtr filename) { using (BytePtr plainname = new BytePtr(256)) { FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; int track = -1, sector = -1; convert_filename(filename, plainname, ref filemode, ref filetype); // Channel 0 is READ PRG, channel 1 is WRITE PRG if (channel == 0) { filemode = FileAccessMode.FMODE_READ; filetype = FileType.FTYPE_PRG; } if (channel == 1) { filemode = FileAccessMode.FMODE_WRITE; filetype = FileType.FTYPE_PRG; } // Allow only read accesses if (filemode != FileAccessMode.FMODE_READ) { set_error(ErrorCode1541.ERR_WRITEPROTECT); return((byte)C64StatusCode.ST_OK); } // Find file in directory and open it if (find_file(plainname, ref track, ref sector)) { return(open_file_ts(channel, track, sector)); } else { set_error(ErrorCode1541.ERR_FILENOTFOUND); } return((byte)C64StatusCode.ST_OK); } }
public override byte Open(int channel, byte[] afilename) { using (BytePtr filename = new BytePtr(afilename)) { set_error(ErrorCode1541.ERR_OK); // Channel 15: execute file name as command if (channel == 15) { execute_command(filename); return((byte)C64StatusCode.ST_OK); } if (chan_mode[channel] != ChannelMode.CHMOD_FREE) { set_error(ErrorCode1541.ERR_NOCHANNEL); return((byte)C64StatusCode.ST_OK); } if (filename[0] == '$') { if (channel != 0) { return(open_file_ts(channel, 18, 0)); } else { unsafe { return(open_directory(filename.Pointer + 1)); } } } if (filename[0] == '#') { return(open_direct(channel, filename)); } return(open_file(channel, filename)); } }
void execute_command(BytePtr command) { switch ((char)command[0]) { case 'I': close_all_channels(); set_error(ErrorCode1541.ERR_OK); break; case 'U': if ((command[1] & 0x0f) == 0x0a) { Reset(); } else { set_error(ErrorCode1541.ERR_SYNTAX30); } break; case 'G': if ((char)command[1] != ':') { set_error(ErrorCode1541.ERR_SYNTAX30); } else { unsafe { string dir = new string((sbyte *)(command.Pointer + 2)); chdir_cmd(dir); } } break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } }
public override byte Open(int channel, byte[] aFilename) { using (BytePtr filename = new BytePtr(aFilename)) { set_error(ErrorCode1541.ERR_OK); // Channel 15: Execute file name as command if (channel == 15) { execute_command(filename); return((byte)C64StatusCode.ST_OK); } // Close previous file if still open if (file[channel] != null) { file[channel].Dispose(); file[channel] = null; } if (filename[0] == '$') { unsafe { return(open_directory(channel, filename.Pointer + 1)); } } if (filename[0] == '#') { set_error(ErrorCode1541.ERR_NOCHANNEL); return((byte)C64StatusCode.ST_OK); } return(open_file(channel, filename)); } }
unsafe void chd64_cmd(byte* d64name) { using (BytePtr str = new BytePtr(IEC.NAMEBUF_LENGTH)) { byte* p = str; // Convert .d64 file name for (int i = 0; i < IEC.NAMEBUF_LENGTH && (*p++ = conv_from_64(*d64name++, false)) != 0; i++) ; close_all_channels(); // G:. resets the .d64 file name to its original setting if (str[0] == '.' && str[1] == 0) open_close_d64_file(orig_d64_name); else open_close_d64_file(str.ToString()); // Read BAM read_sector(18, 0, (byte*)bam); } }
unsafe void convert_filename(BytePtr srcname, BytePtr destname, ref FileAccessMode filemode, ref FileType filetype) { byte* p; // Search for ':', p points to first character after ':' if ((p = CharFunctions.strchr(srcname, ':')) != null) p++; else p = srcname; // Remaining string -> destname CharFunctions.strncpy(destname, srcname, p); // Look for mode parameters seperated by ',' p = destname; while ((p = CharFunctions.strchr(p, ',')) != null) { // Cut string after the first ',' *p++ = 0; switch ((Char)(*p)) { case 'P': filetype = FileType.FTYPE_PRG; break; case 'S': filetype = FileType.FTYPE_SEQ; break; case 'U': filetype = FileType.FTYPE_USR; break; case 'L': filetype = FileType.FTYPE_REL; break; case 'R': filemode = FileAccessMode.FMODE_READ; break; case 'W': filemode = FileAccessMode.FMODE_WRITE; break; case 'A': filemode = FileAccessMode.FMODE_APPEND; break; } } }
public override byte Open(int channel, byte[] afilename) { using (BytePtr filename = new BytePtr(afilename)) { set_error(ErrorCode1541.ERR_OK); // Channel 15: execute file name as command if (channel == 15) { execute_command(filename); return (byte)C64StatusCode.ST_OK; } if (chan_mode[channel] != ChannelMode.CHMOD_FREE) { set_error(ErrorCode1541.ERR_NOCHANNEL); return (byte)C64StatusCode.ST_OK; } if (filename[0] == '$') if (channel != 0) return open_file_ts(channel, 18, 0); else { unsafe { return open_directory(filename.Pointer + 1); } } if (filename[0] == '#') return open_direct(channel, filename); return open_file(channel, filename); } }
private unsafe void AllocateChannelBuffer(int channel, int size) { chan_buf_alloc[channel] = new BytePtr(size); chan_buf[channel] = chan_buf_alloc[channel]; }
byte open_file(int channel, BytePtr filename) { using (BytePtr plainname = new BytePtr(256)) { FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; bool wildflag = false; FileMode fmode = FileMode.Open; FileAccess faccess = FileAccess.Read; unsafe { convert_filename(filename, plainname, ref filemode, ref filetype, ref wildflag); } // Channel 0 is READ PRG, channel 1 is WRITE PRG if (channel == 0) { filemode = FileAccessMode.FMODE_READ; filetype = FileType.FTYPE_PRG; } else if (channel == 1) { filemode = FileAccessMode.FMODE_WRITE; filetype = FileType.FTYPE_PRG; } // Wildcards are only allowed on reading if (wildflag) { if (filemode != FileAccessMode.FMODE_READ) { set_error(ErrorCode1541.ERR_SYNTAX33); return((byte)C64StatusCode.ST_OK); } find_first_file(plainname); } // Select fopen() mode according to file mode switch (filemode) { case FileAccessMode.FMODE_READ: fmode = FileMode.Open; faccess = FileAccess.Read; break; case FileAccessMode.FMODE_WRITE: fmode = FileMode.OpenOrCreate; faccess = FileAccess.ReadWrite; break; case FileAccessMode.FMODE_APPEND: fmode = FileMode.Append; faccess = FileAccess.ReadWrite; break; } try { string fullpath = Path.Combine(dir_path, plainname.ToString()); file[channel] = new FileStream(fullpath, fmode, faccess); if (filemode == FileAccessMode.FMODE_READ) // Read and buffer first byte { read_char[channel] = (byte)file[channel].ReadByte(); } else { Environment.CurrentDirectory = Assembly.GetExecutingAssembly().Location; } } catch (DirectoryNotFoundException) { set_error(ErrorCode1541.ERR_NOTREADY); } catch (FileNotFoundException) { set_error(ErrorCode1541.ERR_FILENOTFOUND); } } return((byte)C64StatusCode.ST_OK); }
Stream the_file; // File pointer for .d64 file #endregion Fields #region Constructors public D64Drive(IEC iec, string filepath) : base(iec) { the_file = null; ram = null; Ready = false; orig_d64_name = filepath; for (int i = 0; i < chan_mode.Length - 1; i++) { chan_mode[i] = ChannelMode.CHMOD_FREE; } chan_mode[15] = ChannelMode.CHMOD_COMMAND; // Open .d64 file open_close_d64_file(filepath); if (the_file != null) { // Allocate 1541 RAM ram = new BytePtr(0x800); unsafe { bam = (BAM*)(ram.Pointer + 0x700); } Reset(); Ready = true; } }
unsafe private void AllocateChannelBuffer(int channel, int size) { chan_buf_alloc[channel] = new BytePtr(size); chan_buf[channel] = chan_buf_alloc[channel]; }
byte open_direct(int channel, BytePtr filename) { int buf = -1; if (filename[1] == 0) buf = alloc_buffer(-1); else if ((filename[1] >= '0') && (filename[1] <= '3') && (filename[2] == 0)) buf = alloc_buffer(filename[1] - '0'); if (buf == -1) { set_error(ErrorCode1541.ERR_NOCHANNEL); return (byte)C64StatusCode.ST_OK; } unsafe { // The buffers are in the 1541 RAM at $300 and are 256 bytes each chan_buf[channel] = buf_ptr[channel] = (byte*)ram + 0x300 + (buf << 8); chan_mode[channel] = ChannelMode.CHMOD_DIRECT; chan_buf_num[channel] = buf; // Store actual buffer number in buffer *chan_buf[channel] = (byte)(buf + '0'); buf_len[channel] = 1; } return (byte)C64StatusCode.ST_OK; }
public static void strncpy(BytePtr dest, string src) { int i = 0; for (; i < dest.Length && i < src.Length; i++) dest[i] = (byte)src[i]; dest[i] = 0x00; }
unsafe byte open_directory(int channel, byte *filename) { using (BytePtr buf = new BytePtr(Encoding.ASCII.GetBytes("\u0001\u0004\u0001\u0001\u0000\u0000\u0012\u0022 \u0022 00 2A\0")), pattern = new BytePtr(IEC.NAMEBUF_LENGTH)) { //char str[NAMEBUF_LENGTH]; byte * p, q; int i; FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; bool wildflag = false; string str; // Special treatment for "$0" if (filename[0] == '0' && filename[1] == 0) { filename += 1; } // Convert filename ('$' already stripped), filemode/type are ignored convert_filename(filename, pattern, ref filemode, ref filetype, ref wildflag); DirectoryInfo dir = new DirectoryInfo(dir_path); if (!dir.Exists) { set_error(ErrorCode1541.ERR_NOTREADY); return((byte)C64StatusCode.ST_OK); } FileSystemInfo[] files = dir.GetFileSystemInfos(); file[channel] = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite); p = (byte *)buf.Pointer + 8; for (i = 0; i < 16 & i < dir_title.Length; i++) { *p++ = conv_to_64((byte)dir_title[i], false); } file[channel].Write(buf, 0, 32); IEnumerator fenum = files.GetEnumerator(); while (fenum.MoveNext() && (((FileSystemInfo)fenum.Current).Name == "." || ((FileSystemInfo)fenum.Current).Name == "..")) { ; } do { FileSystemInfo fsi = (FileSystemInfo)fenum.Current; if (match(pattern.ToString(), fsi.Name)) { // Clear line with spaces and terminate with null byte for (i = 0; i < buf.Length; i++) { buf[i] = (byte)' '; } buf[31] = 0; p = buf; *p++ = 0x01; // Dummy line link *p++ = 0x01; if (fsi is FileInfo) { FileInfo fi = (FileInfo)fsi; // Calculate size in blocks (254 bytes each) i = (int)((fi.Length + 254) / 254); *p++ = (byte)(i & 0xff); *p++ = (byte)((i >> 8) & 0xff); p++; if (i < 10) { p++; // Less than 10: add one space } if (i < 100) { p++; // Less than 100: add another space } str = fi.Name; // Convert and insert file name *p++ = (byte)'\"'; q = p; for (i = 0; i < 16 && i < str.Length; i++) { *q++ = conv_to_64((byte)str[i], true); } *q++ = (byte)'\"'; p += 18; } // File type if (fsi is DirectoryInfo) { *p++ = (byte)'D'; *p++ = (byte)'I'; *p++ = (byte)'R'; } else { *p++ = (byte)'P'; *p++ = (byte)'R'; *p++ = (byte)'G'; } // Write line file[channel].Write(buf, 0, 32); } } while (fenum.MoveNext()); } // Final line file[channel].Write(Encoding.ASCII.GetBytes("\u0001\u0001\0\0BLOCKS FREE. \0\0\0"), 0, 32); file[channel].Position = 0; read_char[channel] = (byte)file[channel].ReadByte(); return((byte)C64StatusCode.ST_OK); }
unsafe byte open_directory(int channel, byte* filename) { using (BytePtr buf = new BytePtr(Encoding.ASCII.GetBytes("\u0001\u0004\u0001\u0001\u0000\u0000\u0012\u0022 \u0022 00 2A\0")), pattern = new BytePtr(IEC.NAMEBUF_LENGTH)) { //char str[NAMEBUF_LENGTH]; byte* p, q; int i; FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; bool wildflag = false; string str; // Special treatment for "$0" if (filename[0] == '0' && filename[1] == 0) filename += 1; // Convert filename ('$' already stripped), filemode/type are ignored convert_filename(filename, pattern, ref filemode, ref filetype, ref wildflag); DirectoryInfo dir = new DirectoryInfo(dir_path); if (!dir.Exists) { set_error(ErrorCode1541.ERR_NOTREADY); return (byte)C64StatusCode.ST_OK; } FileSystemInfo[] files = dir.GetFileSystemInfos(); file[channel] = new FileStream(Path.GetTempFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite); p = (byte*)buf.Pointer + 8; for (i = 0; i < 16 & i < dir_title.Length; i++) { *p++ = conv_to_64((byte)dir_title[i], false); } file[channel].Write(buf, 0, 32); IEnumerator fenum = files.GetEnumerator(); while (fenum.MoveNext() && (((FileSystemInfo)fenum.Current).Name == "." || ((FileSystemInfo)fenum.Current).Name == "..")) ; do { FileSystemInfo fsi = (FileSystemInfo)fenum.Current; if (match(pattern.ToString(), fsi.Name)) { // Clear line with spaces and terminate with null byte for (i = 0; i < buf.Length; i++) buf[i] = (byte)' '; buf[31] = 0; p = buf; *p++ = 0x01; // Dummy line link *p++ = 0x01; if (fsi is FileInfo) { FileInfo fi = (FileInfo)fsi; // Calculate size in blocks (254 bytes each) i = (int)((fi.Length + 254) / 254); *p++ = (byte)(i & 0xff); *p++ = (byte)((i >> 8) & 0xff); p++; if (i < 10) p++; // Less than 10: add one space if (i < 100) p++; // Less than 100: add another space str = fi.Name; // Convert and insert file name *p++ = (byte)'\"'; q = p; for (i = 0; i < 16 && i < str.Length; i++) *q++ = conv_to_64((byte)str[i], true); *q++ = (byte)'\"'; p += 18; } // File type if (fsi is DirectoryInfo) { *p++ = (byte)'D'; *p++ = (byte)'I'; *p++ = (byte)'R'; } else { *p++ = (byte)'P'; *p++ = (byte)'R'; *p++ = (byte)'G'; } // Write line file[channel].Write(buf, 0, 32); } } while (fenum.MoveNext()); } // Final line file[channel].Write(Encoding.ASCII.GetBytes("\u0001\u0001\0\0BLOCKS FREE. \0\0\0"), 0, 32); file[channel].Position = 0; read_char[channel] = (byte)file[channel].ReadByte(); return (byte)C64StatusCode.ST_OK; }
void execute_command(BytePtr command) { switch ((char)command[0]) { case 'I': close_all_channels(); set_error(ErrorCode1541.ERR_OK); break; case 'U': if ((command[1] & 0x0f) == 0x0a) { Reset(); } else set_error(ErrorCode1541.ERR_SYNTAX30); break; case 'G': if ((char)command[1] != ':') set_error(ErrorCode1541.ERR_SYNTAX30); else { unsafe { string dir = new string((sbyte*)(command.Pointer + 2)); chdir_cmd(dir); } } break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } }
unsafe public static byte *strchr(BytePtr src, Char c) { return(strchr(src, (byte)c)); }
unsafe void execute_command(BytePtr command) { UInt16 adr; int len; switch ((char)command[0]) { case 'B': if (command[1] != '-') set_error(ErrorCode1541.ERR_SYNTAX30); else switch ((char)command[2]) { case 'R': block_read_cmd(command.Pointer + 3); break; case 'P': buffer_ptr_cmd(command.Pointer + 3); break; case 'A': case 'F': case 'W': set_error(ErrorCode1541.ERR_WRITEPROTECT); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } break; case 'M': if (command[1] != '-') set_error(ErrorCode1541.ERR_SYNTAX30); else switch ((char)command[2]) { case 'R': adr = (UInt16)(((byte)command[4] << 8) | ((byte)command[3])); error_ptr = (byte*)((byte*)ram + (adr & 0x07ff)); if ((error_len = (byte)command[5]) == 0) error_len = 1; break; case 'W': adr = (UInt16)(((byte)command[4] << 8) | ((byte)command[3])); len = (byte)command[5]; for (int i = 0; i < len; i++) ram[adr + i] = (byte)command[i + 6]; break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } break; case 'I': close_all_channels(); read_sector(18, 0, (byte*)bam); set_error(ErrorCode1541.ERR_OK); break; case 'U': switch (command[1] & 0x0f) { case 1: // U1/UA: Block-Read block_read_cmd(command.Pointer + 2); break; case 2: // U2/UB: Block-Write set_error(ErrorCode1541.ERR_WRITEPROTECT); break; case 10: // U:/UJ: Reset Reset(); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } break; case 'G': if (command[1] != ':') set_error(ErrorCode1541.ERR_SYNTAX30); else chd64_cmd(command.Pointer + 2); break; case 'C': case 'N': case 'R': case 'S': case 'V': set_error(ErrorCode1541.ERR_WRITEPROTECT); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } }
public static unsafe void strncpy(BytePtr dest, BytePtr src, byte* start) { strncpy(dest, src, start - src.Pointer); }
unsafe bool find_file(BytePtr filename, ref int track, ref int sector) { int i, j; byte* p, q; DirEntry* de; fixed (Directory* dd = &dir) { // Scan all directory blocks dir.next_track = bam->dir_track; dir.next_sector = bam->dir_sector; while (dir.next_track != 0) { if (!read_sector(dir.next_track, dir.next_sector, &dd->next_track)) return false; DirEntry* ade = (DirEntry*)dd->entry; // Scan all 8 entries of a block for (j = 0; j < 8; j++) { de = &ade[j]; track = de->track; sector = de->sector; if (de->type != 0) { p = (byte*)filename; q = de->name; for (i = 0; i < 16 && (*p != 0); i++, p++, q++) { if (*p == '*') // Wildcard '*' matches all following characters return true; if (*p != *q) { if (*p != '?') goto next_entry; // Wildcard '?' matches single character if (*q == 0xa0) goto next_entry; } } if (i == 16 || *q == 0xa0) return true; } next_entry: ; } } } return false; }
unsafe void execute_command(BytePtr command) { UInt16 adr; int len; switch ((char)command[0]) { case 'B': if (command[1] != '-') { set_error(ErrorCode1541.ERR_SYNTAX30); } else { switch ((char)command[2]) { case 'R': block_read_cmd(command.Pointer + 3); break; case 'P': buffer_ptr_cmd(command.Pointer + 3); break; case 'A': case 'F': case 'W': set_error(ErrorCode1541.ERR_WRITEPROTECT); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } } break; case 'M': if (command[1] != '-') { set_error(ErrorCode1541.ERR_SYNTAX30); } else { switch ((char)command[2]) { case 'R': adr = (UInt16)(((byte)command[4] << 8) | ((byte)command[3])); error_ptr = (byte *)((byte *)ram + (adr & 0x07ff)); if ((error_len = (byte)command[5]) == 0) { error_len = 1; } break; case 'W': adr = (UInt16)(((byte)command[4] << 8) | ((byte)command[3])); len = (byte)command[5]; for (int i = 0; i < len; i++) { ram[adr + i] = (byte)command[i + 6]; } break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } } break; case 'I': close_all_channels(); read_sector(18, 0, (byte *)bam); set_error(ErrorCode1541.ERR_OK); break; case 'U': switch (command[1] & 0x0f) { case 1: // U1/UA: Block-Read block_read_cmd(command.Pointer + 2); break; case 2: // U2/UB: Block-Write set_error(ErrorCode1541.ERR_WRITEPROTECT); break; case 10: // U:/UJ: Reset Reset(); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } break; case 'G': if (command[1] != ':') { set_error(ErrorCode1541.ERR_SYNTAX30); } else { chd64_cmd(command.Pointer + 2); } break; case 'C': case 'N': case 'R': case 'S': case 'V': set_error(ErrorCode1541.ERR_WRITEPROTECT); break; default: set_error(ErrorCode1541.ERR_SYNTAX30); break; } }
unsafe byte open_file(int channel, BytePtr filename) { using (BytePtr plainname = new BytePtr(256)) { FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; int track = -1, sector = -1; convert_filename(filename, plainname, ref filemode, ref filetype); // Channel 0 is READ PRG, channel 1 is WRITE PRG if (channel == 0) { filemode = FileAccessMode.FMODE_READ; filetype = FileType.FTYPE_PRG; } if (channel == 1) { filemode = FileAccessMode.FMODE_WRITE; filetype = FileType.FTYPE_PRG; } // Allow only read accesses if (filemode != FileAccessMode.FMODE_READ) { set_error(ErrorCode1541.ERR_WRITEPROTECT); return (byte)C64StatusCode.ST_OK; } // Find file in directory and open it if (find_file(plainname, ref track, ref sector)) return open_file_ts(channel, track, sector); else set_error(ErrorCode1541.ERR_FILENOTFOUND); return (byte)C64StatusCode.ST_OK; } }
unsafe public static void strncpy(BytePtr dest, BytePtr src, byte *start) { strncpy(dest, src, start - src.Pointer); }
void find_first_file(BytePtr aName) { DirectoryInfo dir = new DirectoryInfo(dir_path); if (!dir.Exists) return; FileInfo[] files = dir.GetFiles(); string name = aName.ToString(); IEnumerator fenum = files.GetEnumerator(); while (fenum.MoveNext() && (((FileInfo)fenum.Current).Name == "." || ((FileInfo)fenum.Current).Name == "..")) ; do { FileInfo fi = (FileInfo)fenum.Current; // Match found? Then copy real file name if (match(name, fi.Name)) { CharFunctions.strncpy(aName, fi.Name); return; } } while (fenum.MoveNext()); }
public static unsafe byte* strchr(BytePtr src, Char c) { return strchr(src, (byte)c); }
byte open_file(int channel, BytePtr filename) { using (BytePtr plainname = new BytePtr(256)) { FileAccessMode filemode = FileAccessMode.FMODE_READ; FileType filetype = FileType.FTYPE_PRG; bool wildflag = false; FileMode fmode = FileMode.Open; FileAccess faccess = FileAccess.Read; unsafe { convert_filename(filename, plainname, ref filemode, ref filetype, ref wildflag); } // Channel 0 is READ PRG, channel 1 is WRITE PRG if (channel == 0) { filemode = FileAccessMode.FMODE_READ; filetype = FileType.FTYPE_PRG; } else if (channel == 1) { filemode = FileAccessMode.FMODE_WRITE; filetype = FileType.FTYPE_PRG; } // Wildcards are only allowed on reading if (wildflag) { if (filemode != FileAccessMode.FMODE_READ) { set_error(ErrorCode1541.ERR_SYNTAX33); return (byte)C64StatusCode.ST_OK; } find_first_file(plainname); } // Select fopen() mode according to file mode switch (filemode) { case FileAccessMode.FMODE_READ: fmode = FileMode.Open; faccess = FileAccess.Read; break; case FileAccessMode.FMODE_WRITE: fmode = FileMode.OpenOrCreate; faccess = FileAccess.ReadWrite; break; case FileAccessMode.FMODE_APPEND: fmode = FileMode.Append; faccess = FileAccess.ReadWrite; break; } try { string fullpath = Path.Combine(dir_path, plainname.ToString()); file[channel] = new FileStream(fullpath, fmode, faccess); if (filemode == FileAccessMode.FMODE_READ) // Read and buffer first byte read_char[channel] = (byte)file[channel].ReadByte(); else Environment.CurrentDirectory = Assembly.GetExecutingAssembly().Location; } catch (DirectoryNotFoundException) { set_error(ErrorCode1541.ERR_NOTREADY); } catch (FileNotFoundException) { set_error(ErrorCode1541.ERR_FILENOTFOUND); } } return (byte)C64StatusCode.ST_OK; }
public static void strncpy(BytePtr dest, BytePtr src, long start) { long i = start, j = 0; for (; i < dest.Length && src[i] != 0x00; i++, j++) dest[j] = src[i]; dest[j] = 0x00; }
unsafe bool find_file(BytePtr filename, ref int track, ref int sector) { int i, j; byte * p, q; DirEntry *de; fixed(Directory *dd = &dir) { // Scan all directory blocks dir.next_track = bam->dir_track; dir.next_sector = bam->dir_sector; while (dir.next_track != 0) { if (!read_sector(dir.next_track, dir.next_sector, &dd->next_track)) { return(false); } DirEntry *ade = (DirEntry *)dd->entry; // Scan all 8 entries of a block for (j = 0; j < 8; j++) { de = &ade[j]; track = de->track; sector = de->sector; if (de->type != 0) { p = (byte *)filename; q = de->name; for (i = 0; i < 16 && (*p != 0); i++, p++, q++) { if (*p == '*') // Wildcard '*' matches all following characters { return(true); } if (*p != *q) { if (*p != '?') { goto next_entry; // Wildcard '?' matches single character } if (*q == 0xa0) { goto next_entry; } } } if (i == 16 || *q == 0xa0) { return(true); } } next_entry :; } } } return(false); }
public static unsafe byte* strchr(BytePtr src, byte c) { for (int i = 0; i < src.Length; i++) if (src[i] == c) return src.Pointer + i; return null; }