/* * IEC.h - IEC bus routines, 1541 emulation (DOS level) * * Frodo (C) 1994-1997,2002-2004 Christian Bauer * * 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 */ #ifndef _IEC_H #define _IEC_H /* * Definitions */ // Maximum length of file names const int NAMEBUF_LENGTH = 256; // C64 status codes enum { ST_OK = 0, // No error ST_READ_TIMEOUT = 0x02, // Timeout on reading ST_TIMEOUT = 0x03, // Timeout ST_EOF = 0x40, // End of file ST_NOTPRESENT = 0x80 // Device not present }; // 1541 error codes enum { ERR_OK, // 00 OK ERR_SCRATCHED, // 01 FILES SCRATCHED ERR_UNIMPLEMENTED, // 03 UNIMPLEMENTED ERR_READ20, // 20 READ ERROR (block header not found) ERR_READ21, // 21 READ ERROR (no sync character) ERR_READ22, // 22 READ ERROR (data block not present) ERR_READ23, // 23 READ ERROR (checksum error in data block) ERR_READ24, // 24 READ ERROR (byte decoding error) ERR_WRITE25, // 25 WRITE ERROR (write-verify error) ERR_WRITEPROTECT, // 26 WRITE PROTECT ON ERR_READ27, // 27 READ ERROR (checksum error in header) ERR_WRITE28, // 28 WRITE ERROR (long data block) ERR_DISKID, // 29 DISK ID MISMATCH ERR_SYNTAX30, // 30 SYNTAX ERROR (general syntax) ERR_SYNTAX31, // 31 SYNTAX ERROR (invalid command) ERR_SYNTAX32, // 32 SYNTAX ERROR (command too long) ERR_SYNTAX33, // 33 SYNTAX ERROR (wildcards on writing) ERR_SYNTAX34, // 34 SYNTAX ERROR (missing file name) ERR_WRITEFILEOPEN, // 60 WRITE FILE OPEN ERR_FILENOTOPEN, // 61 FILE NOT OPEN ERR_FILENOTFOUND, // 62 FILE NOT FOUND ERR_FILEEXISTS, // 63 FILE EXISTS ERR_FILETYPE, // 64 FILE TYPE MISMATCH ERR_NOBLOCK, // 65 NO BLOCK ERR_ILLEGALTS, // 66 ILLEGAL TRACK OR SECTOR ERR_NOCHANNEL, // 70 NO CHANNEL ERR_DIRERROR, // 71 DIR ERROR ERR_DISKFULL, // 72 DISK FULL ERR_STARTUP, // 73 Power-up message ERR_NOTREADY // 74 DRIVE NOT READY }; // Mountable file types enum { FILE_IMAGE, // Disk image, handled by ImageDrive FILE_ARCH // Archive file, handled by ArchDrive }; // 1541 file types enum { FTYPE_DEL, // Deleted FTYPE_SEQ, // Sequential FTYPE_PRG, // Program FTYPE_USR, // User FTYPE_REL, // Relative FTYPE_UNKNOWN }; static const char ftype_char[9] = "DSPUL "; // 1541 file access modes enum { FMODE_READ, // Read FMODE_WRITE, // Write FMODE_APPEND, // Append FMODE_M // Read open file }; // Drive LED states enum { DRVLED_OFF, // Inactive, LED off DRVLED_ON, // Active, LED on DRVLED_ERROR // Error, blink LED }; // Information about file in disk image/archive file struct c64_dir_entry { c64_dir_entry(const uint8 *n, int t, bool o, bool p, size_t s, off_t ofs = 0, uint8 sal = 0, uint8 sah = 0) : type(t), is_open(o), is_protected(p), size(s), offset(ofs), sa_lo(sal), sa_hi(sah) { strncpy((char *)name, (const char *)n, 17); name[16] = 0; } // Basic information uint8 name[17]; // File name (C64 charset, null-terminated) int type; // File type (see defines above) bool is_open; // Flag: file open bool is_protected; // Flag: file protected size_t size; // File size (may be approximated) // Special information off_t offset; // Offset of file in archive file uint8 sa_lo, sa_hi; // C64 start address }; class Drive; class C64Display; class Prefs; // Class for complete IEC bus system with drives 8..11 class IEC { public: IEC(C64Display *display); ~IEC(); void Reset(void); void NewPrefs(Prefs *prefs); void UpdateLEDs(void); uint8 Out(uint8 byte, bool eoi); uint8 OutATN(uint8 byte); uint8 OutSec(uint8 byte); uint8 In(uint8 &byte); void SetATN(void); void RelATN(void); void Turnaround(void); void Release(void); private: Drive *create_drive(const char *path); uint8 listen(int device); uint8 talk(int device); uint8 unlisten(void); uint8 untalk(void); uint8 sec_listen(void); uint8 sec_talk(void); uint8 open_out(uint8 byte, bool eoi); uint8 data_out(uint8 byte, bool eoi); uint8 data_in(uint8 &byte); C64Display *the_display; // Pointer to display object (for drive LEDs) uint8 name_buf[NAMEBUF_LENGTH]; // Buffer for file names and command strings uint8 *name_ptr; // Pointer for reception of file name int name_len; // Received length of file name Drive *drive[4]; // 4 drives (8..11) Drive *listener; // Pointer to active listener Drive *talker; // Pointer to active talker bool listener_active; // Listener selected, listener_data is valid bool talker_active; // Talker selected, talker_data is valid bool listening; // Last ATN was listen (to decide between sec_listen/sec_talk) uint8 received_cmd; // Received command code ($x0) uint8 sec_addr; // Received secondary address ($0x) }; // Abstract superclass for individual drives class Drive { public: Drive(IEC *iec); virtual ~Drive() {} virtual uint8 Open(int channel, const uint8 *name, int name_len)=0; virtual uint8 Close(int channel)=0; virtual uint8 Read(int channel, uint8 &byte)=0; virtual uint8 Write(int channel, uint8 byte, bool eoi)=0; virtual void Reset(void)=0; int LED; // Drive LED state bool Ready; // Drive is ready for operation protected: void set_error(int error, int track = 0, int sector = 0); void parse_file_name(const uint8 *src, int src_len, uint8 *dest, int &dest_len, int &mode, int &type, int &rec_len, bool convert_charset = false); void execute_cmd(const uint8 *cmd, int cmd_len); virtual void block_read_cmd(int channel, int track, int sector, bool user_cmd = false); virtual void block_write_cmd(int channel, int track, int sector, bool user_cmd = false); virtual void block_execute_cmd(int channel, int track, int sector); virtual void block_allocate_cmd(int track, int sector); virtual void block_free_cmd(int track, int sector); virtual void buffer_pointer_cmd(int channel, int pos); virtual void mem_read_cmd(uint16 adr, uint8 len); virtual void mem_write_cmd(uint16 adr, uint8 len, uint8 *p); virtual void mem_execute_cmd(uint16 adr); virtual void copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len); virtual void rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len); virtual void scratch_cmd(const uint8 *files, int files_len); virtual void position_cmd(const uint8 *cmd, int cmd_len); virtual void initialize_cmd(void); virtual void new_cmd(const uint8 *name, int name_len, const uint8 *comma); virtual void validate_cmd(void); void unsupp_cmd(void); char error_buf[256]; // Buffer with current error message char *error_ptr; // Pointer within error message int error_len; // Remaining length of error message int current_error; // Number of current error uint8 cmd_buf[64]; // Buffer for incoming command strings int cmd_len; // Length of received command private: IEC *the_iec; // Pointer to IEC object }; /* * Functions */ // Convert ASCII character to PETSCII character extern uint8 ascii2petscii(char c); // Convert ASCII string to PETSCII string extern void ascii2petscii(uint8 *dest, const char *src, int max); // Convert PETSCII character to ASCII character extern char petscii2ascii(uint8 c); // Convert PETSCII string to ASCII string extern void petscii2ascii(char *dest, const uint8 *src, int max); // Check whether file is a mountable disk image or archive file, return type extern bool IsMountableFile(const char *path, int &type); // Read directory of mountable disk image or archive file into c64_dir_entry vector extern bool ReadDirectory(const char *path, int type, vector &vec); #endif