1 |
cebix |
1.1 |
/* |
2 |
|
|
* IEC.h - IEC bus routines, 1541 emulation (DOS level) |
3 |
|
|
* |
4 |
cebix |
1.8 |
* Frodo (C) 1994-1997,2002-2005 Christian Bauer |
5 |
cebix |
1.1 |
* |
6 |
|
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
|
* it under the terms of the GNU General Public License as published by |
8 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#ifndef _IEC_H |
22 |
|
|
#define _IEC_H |
23 |
|
|
|
24 |
|
|
|
25 |
cebix |
1.7 |
/* |
26 |
|
|
* Definitions |
27 |
|
|
*/ |
28 |
|
|
|
29 |
cebix |
1.1 |
// Maximum length of file names |
30 |
|
|
const int NAMEBUF_LENGTH = 256; |
31 |
|
|
|
32 |
|
|
// C64 status codes |
33 |
|
|
enum { |
34 |
|
|
ST_OK = 0, // No error |
35 |
|
|
ST_READ_TIMEOUT = 0x02, // Timeout on reading |
36 |
|
|
ST_TIMEOUT = 0x03, // Timeout |
37 |
|
|
ST_EOF = 0x40, // End of file |
38 |
|
|
ST_NOTPRESENT = 0x80 // Device not present |
39 |
|
|
}; |
40 |
|
|
|
41 |
|
|
// 1541 error codes |
42 |
|
|
enum { |
43 |
|
|
ERR_OK, // 00 OK |
44 |
cebix |
1.3 |
ERR_SCRATCHED, // 01 FILES SCRATCHED |
45 |
|
|
ERR_UNIMPLEMENTED, // 03 UNIMPLEMENTED |
46 |
|
|
ERR_READ20, // 20 READ ERROR (block header not found) |
47 |
|
|
ERR_READ21, // 21 READ ERROR (no sync character) |
48 |
|
|
ERR_READ22, // 22 READ ERROR (data block not present) |
49 |
|
|
ERR_READ23, // 23 READ ERROR (checksum error in data block) |
50 |
|
|
ERR_READ24, // 24 READ ERROR (byte decoding error) |
51 |
|
|
ERR_WRITE25, // 25 WRITE ERROR (write-verify error) |
52 |
cebix |
1.1 |
ERR_WRITEPROTECT, // 26 WRITE PROTECT ON |
53 |
cebix |
1.3 |
ERR_READ27, // 27 READ ERROR (checksum error in header) |
54 |
|
|
ERR_WRITE28, // 28 WRITE ERROR (long data block) |
55 |
|
|
ERR_DISKID, // 29 DISK ID MISMATCH |
56 |
|
|
ERR_SYNTAX30, // 30 SYNTAX ERROR (general syntax) |
57 |
|
|
ERR_SYNTAX31, // 31 SYNTAX ERROR (invalid command) |
58 |
|
|
ERR_SYNTAX32, // 32 SYNTAX ERROR (command too long) |
59 |
cebix |
1.1 |
ERR_SYNTAX33, // 33 SYNTAX ERROR (wildcards on writing) |
60 |
cebix |
1.3 |
ERR_SYNTAX34, // 34 SYNTAX ERROR (missing file name) |
61 |
cebix |
1.1 |
ERR_WRITEFILEOPEN, // 60 WRITE FILE OPEN |
62 |
|
|
ERR_FILENOTOPEN, // 61 FILE NOT OPEN |
63 |
|
|
ERR_FILENOTFOUND, // 62 FILE NOT FOUND |
64 |
cebix |
1.3 |
ERR_FILEEXISTS, // 63 FILE EXISTS |
65 |
|
|
ERR_FILETYPE, // 64 FILE TYPE MISMATCH |
66 |
|
|
ERR_NOBLOCK, // 65 NO BLOCK |
67 |
|
|
ERR_ILLEGALTS, // 66 ILLEGAL TRACK OR SECTOR |
68 |
cebix |
1.1 |
ERR_NOCHANNEL, // 70 NO CHANNEL |
69 |
cebix |
1.3 |
ERR_DIRERROR, // 71 DIR ERROR |
70 |
|
|
ERR_DISKFULL, // 72 DISK FULL |
71 |
cebix |
1.1 |
ERR_STARTUP, // 73 Power-up message |
72 |
|
|
ERR_NOTREADY // 74 DRIVE NOT READY |
73 |
|
|
}; |
74 |
|
|
|
75 |
cebix |
1.7 |
// Mountable file types |
76 |
|
|
enum { |
77 |
|
|
FILE_IMAGE, // Disk image, handled by ImageDrive |
78 |
|
|
FILE_ARCH // Archive file, handled by ArchDrive |
79 |
|
|
}; |
80 |
cebix |
1.1 |
|
81 |
cebix |
1.3 |
// 1541 file types |
82 |
|
|
enum { |
83 |
|
|
FTYPE_DEL, // Deleted |
84 |
|
|
FTYPE_SEQ, // Sequential |
85 |
|
|
FTYPE_PRG, // Program |
86 |
|
|
FTYPE_USR, // User |
87 |
|
|
FTYPE_REL, // Relative |
88 |
|
|
FTYPE_UNKNOWN |
89 |
|
|
}; |
90 |
|
|
|
91 |
|
|
static const char ftype_char[9] = "DSPUL "; |
92 |
|
|
|
93 |
|
|
// 1541 file access modes |
94 |
|
|
enum { |
95 |
|
|
FMODE_READ, // Read |
96 |
|
|
FMODE_WRITE, // Write |
97 |
|
|
FMODE_APPEND, // Append |
98 |
|
|
FMODE_M // Read open file |
99 |
|
|
}; |
100 |
|
|
|
101 |
cebix |
1.1 |
// Drive LED states |
102 |
|
|
enum { |
103 |
|
|
DRVLED_OFF, // Inactive, LED off |
104 |
|
|
DRVLED_ON, // Active, LED on |
105 |
|
|
DRVLED_ERROR // Error, blink LED |
106 |
|
|
}; |
107 |
|
|
|
108 |
cebix |
1.6 |
// Information about file in disk image/archive file |
109 |
|
|
struct c64_dir_entry { |
110 |
|
|
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) |
111 |
|
|
: type(t), is_open(o), is_protected(p), size(s), offset(ofs), sa_lo(sal), sa_hi(sah) |
112 |
|
|
{ |
113 |
|
|
strncpy((char *)name, (const char *)n, 17); |
114 |
|
|
name[16] = 0; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
// Basic information |
118 |
|
|
uint8 name[17]; // File name (C64 charset, null-terminated) |
119 |
|
|
int type; // File type (see defines above) |
120 |
|
|
bool is_open; // Flag: file open |
121 |
|
|
bool is_protected; // Flag: file protected |
122 |
|
|
size_t size; // File size (may be approximated) |
123 |
|
|
|
124 |
|
|
// Special information |
125 |
|
|
off_t offset; // Offset of file in archive file |
126 |
|
|
uint8 sa_lo, sa_hi; // C64 start address |
127 |
|
|
}; |
128 |
|
|
|
129 |
cebix |
1.1 |
class Drive; |
130 |
|
|
class C64Display; |
131 |
|
|
class Prefs; |
132 |
|
|
|
133 |
|
|
// Class for complete IEC bus system with drives 8..11 |
134 |
|
|
class IEC { |
135 |
|
|
public: |
136 |
|
|
IEC(C64Display *display); |
137 |
|
|
~IEC(); |
138 |
|
|
|
139 |
|
|
void Reset(void); |
140 |
|
|
void NewPrefs(Prefs *prefs); |
141 |
|
|
void UpdateLEDs(void); |
142 |
|
|
|
143 |
|
|
uint8 Out(uint8 byte, bool eoi); |
144 |
|
|
uint8 OutATN(uint8 byte); |
145 |
|
|
uint8 OutSec(uint8 byte); |
146 |
cebix |
1.4 |
uint8 In(uint8 &byte); |
147 |
cebix |
1.1 |
void SetATN(void); |
148 |
|
|
void RelATN(void); |
149 |
|
|
void Turnaround(void); |
150 |
|
|
void Release(void); |
151 |
|
|
|
152 |
|
|
private: |
153 |
cebix |
1.7 |
Drive *create_drive(const char *path); |
154 |
|
|
|
155 |
cebix |
1.1 |
uint8 listen(int device); |
156 |
|
|
uint8 talk(int device); |
157 |
|
|
uint8 unlisten(void); |
158 |
|
|
uint8 untalk(void); |
159 |
|
|
uint8 sec_listen(void); |
160 |
|
|
uint8 sec_talk(void); |
161 |
|
|
uint8 open_out(uint8 byte, bool eoi); |
162 |
|
|
uint8 data_out(uint8 byte, bool eoi); |
163 |
cebix |
1.4 |
uint8 data_in(uint8 &byte); |
164 |
cebix |
1.1 |
|
165 |
|
|
C64Display *the_display; // Pointer to display object (for drive LEDs) |
166 |
|
|
|
167 |
cebix |
1.3 |
uint8 name_buf[NAMEBUF_LENGTH]; // Buffer for file names and command strings |
168 |
|
|
uint8 *name_ptr; // Pointer for reception of file name |
169 |
cebix |
1.1 |
int name_len; // Received length of file name |
170 |
|
|
|
171 |
|
|
Drive *drive[4]; // 4 drives (8..11) |
172 |
|
|
|
173 |
|
|
Drive *listener; // Pointer to active listener |
174 |
|
|
Drive *talker; // Pointer to active talker |
175 |
|
|
|
176 |
|
|
bool listener_active; // Listener selected, listener_data is valid |
177 |
|
|
bool talker_active; // Talker selected, talker_data is valid |
178 |
|
|
bool listening; // Last ATN was listen (to decide between sec_listen/sec_talk) |
179 |
|
|
|
180 |
|
|
uint8 received_cmd; // Received command code ($x0) |
181 |
|
|
uint8 sec_addr; // Received secondary address ($0x) |
182 |
|
|
}; |
183 |
|
|
|
184 |
|
|
// Abstract superclass for individual drives |
185 |
|
|
class Drive { |
186 |
|
|
public: |
187 |
|
|
Drive(IEC *iec); |
188 |
|
|
virtual ~Drive() {} |
189 |
|
|
|
190 |
cebix |
1.3 |
virtual uint8 Open(int channel, const uint8 *name, int name_len)=0; |
191 |
cebix |
1.1 |
virtual uint8 Close(int channel)=0; |
192 |
cebix |
1.4 |
virtual uint8 Read(int channel, uint8 &byte)=0; |
193 |
cebix |
1.1 |
virtual uint8 Write(int channel, uint8 byte, bool eoi)=0; |
194 |
|
|
virtual void Reset(void)=0; |
195 |
|
|
|
196 |
|
|
int LED; // Drive LED state |
197 |
|
|
bool Ready; // Drive is ready for operation |
198 |
|
|
|
199 |
|
|
protected: |
200 |
cebix |
1.3 |
void set_error(int error, int track = 0, int sector = 0); |
201 |
|
|
|
202 |
|
|
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); |
203 |
cebix |
1.1 |
|
204 |
cebix |
1.3 |
void execute_cmd(const uint8 *cmd, int cmd_len); |
205 |
|
|
virtual void block_read_cmd(int channel, int track, int sector, bool user_cmd = false); |
206 |
|
|
virtual void block_write_cmd(int channel, int track, int sector, bool user_cmd = false); |
207 |
|
|
virtual void block_execute_cmd(int channel, int track, int sector); |
208 |
|
|
virtual void block_allocate_cmd(int track, int sector); |
209 |
|
|
virtual void block_free_cmd(int track, int sector); |
210 |
|
|
virtual void buffer_pointer_cmd(int channel, int pos); |
211 |
|
|
virtual void mem_read_cmd(uint16 adr, uint8 len); |
212 |
|
|
virtual void mem_write_cmd(uint16 adr, uint8 len, uint8 *p); |
213 |
|
|
virtual void mem_execute_cmd(uint16 adr); |
214 |
|
|
virtual void copy_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_files, int old_files_len); |
215 |
|
|
virtual void rename_cmd(const uint8 *new_file, int new_file_len, const uint8 *old_file, int old_file_len); |
216 |
|
|
virtual void scratch_cmd(const uint8 *files, int files_len); |
217 |
|
|
virtual void position_cmd(const uint8 *cmd, int cmd_len); |
218 |
|
|
virtual void initialize_cmd(void); |
219 |
|
|
virtual void new_cmd(const uint8 *name, int name_len, const uint8 *comma); |
220 |
|
|
virtual void validate_cmd(void); |
221 |
|
|
void unsupp_cmd(void); |
222 |
|
|
|
223 |
|
|
char error_buf[256]; // Buffer with current error message |
224 |
|
|
char *error_ptr; // Pointer within error message |
225 |
|
|
int error_len; // Remaining length of error message |
226 |
cebix |
1.4 |
int current_error; // Number of current error |
227 |
cebix |
1.3 |
|
228 |
|
|
uint8 cmd_buf[64]; // Buffer for incoming command strings |
229 |
|
|
int cmd_len; // Length of received command |
230 |
cebix |
1.1 |
|
231 |
|
|
private: |
232 |
cebix |
1.3 |
IEC *the_iec; // Pointer to IEC object |
233 |
cebix |
1.1 |
}; |
234 |
cebix |
1.3 |
|
235 |
|
|
|
236 |
cebix |
1.7 |
/* |
237 |
|
|
* Functions |
238 |
|
|
*/ |
239 |
|
|
|
240 |
cebix |
1.3 |
// Convert ASCII character to PETSCII character |
241 |
cebix |
1.6 |
extern uint8 ascii2petscii(char c); |
242 |
cebix |
1.3 |
|
243 |
|
|
// Convert ASCII string to PETSCII string |
244 |
cebix |
1.6 |
extern void ascii2petscii(uint8 *dest, const char *src, int max); |
245 |
cebix |
1.3 |
|
246 |
|
|
// Convert PETSCII character to ASCII character |
247 |
|
|
extern char petscii2ascii(uint8 c); |
248 |
|
|
|
249 |
|
|
// Convert PETSCII string to ASCII string |
250 |
cebix |
1.6 |
extern void petscii2ascii(char *dest, const uint8 *src, int max); |
251 |
cebix |
1.7 |
|
252 |
|
|
// Check whether file is a mountable disk image or archive file, return type |
253 |
|
|
extern bool IsMountableFile(const char *path, int &type); |
254 |
|
|
|
255 |
|
|
// Read directory of mountable disk image or archive file into c64_dir_entry vector |
256 |
|
|
extern bool ReadDirectory(const char *path, int type, vector<c64_dir_entry> &vec); |
257 |
cebix |
1.1 |
|
258 |
|
|
#endif |