mirror of
https://github.com/Oibaf66/frodo-wii.git
synced 2024-11-25 04:47:00 +01:00
259 lines
8.0 KiB
C
259 lines
8.0 KiB
C
|
/*
|
||
|
* IEC.h - IEC bus routines, 1541 emulation (DOS level)
|
||
|
*
|
||
|
* Frodo (C) 1994-1997,2002-2005 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<c64_dir_entry> &vec);
|
||
|
|
||
|
#endif
|