1 /*
2 * mon_drive.c - The VICE built-in monitor drive functions.
3 *
4 * Written by
5 * Andreas Boose <viceteam@t-online.de>
6 * Daniel Sladic <sladic@eecg.toronto.edu>
7 * Ettore Perazzoli <ettore@comm2000.it>
8 *
9 * This file is part of VICE, the Versatile Commodore Emulator.
10 * See README for copyright notice.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 * 02111-1307 USA.
26 *
27 */
28
29 #include "vice.h"
30
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "attach.h"
35 #include "diskcontents.h"
36 #include "diskimage.h"
37 #include "imagecontents.h"
38 #include "lib.h"
39 #include "machine-bus.h"
40 #include "montypes.h"
41 #include "mon_drive.h"
42 #include "mon_util.h"
43 #include "resources.h"
44 #include "serial.h"
45 #include "types.h"
46 #include "uimon.h"
47 #include "vdrive.h"
48 #include "vdrive-command.h"
49
50
51 #define ADDR_LIMIT(x) ((uint16_t)(addr_mask(x)))
52
53
mon_drive_block_cmd(int op,int track,int sector,MON_ADDR addr)54 void mon_drive_block_cmd(int op, int track, int sector, MON_ADDR addr)
55 {
56 vdrive_t *vdrive;
57
58 mon_evaluate_default_addr(&addr);
59
60 /* TODO: other units, drive 1? */
61 vdrive = file_system_get_vdrive(8, 0);
62
63 if (!vdrive || vdrive->image == NULL) {
64 mon_out("No disk attached\n");
65 return;
66 }
67
68 if (!op) {
69 uint8_t readdata[256];
70 int i, j, dst;
71 MEMSPACE dest_mem;
72
73 /* We ignore disk error codes here. */
74 if (vdrive_read_sector(vdrive, readdata, track, sector)
75 < 0) {
76 mon_out("Error reading track %d sector %d\n", track, sector);
77 return;
78 }
79
80 if (mon_is_valid_addr(addr)) {
81 dst = addr_location(addr);
82 dest_mem = addr_memspace(addr);
83
84 for (i = 0; i < 256; i++) {
85 mon_set_mem_val(dest_mem, ADDR_LIMIT(dst + i), readdata[i]);
86 }
87
88 mon_out("Read track %d sector %d into address $%04x\n",
89 track, sector, (unsigned int)dst);
90 } else {
91 for (i = 0; i < 16; i++) {
92 mon_out(">%04x", (unsigned int)(i * 16));
93 for (j = 0; j < 16; j++) {
94 if ((j & 3) == 0) {
95 mon_out(" ");
96 }
97 mon_out(" %02x", readdata[i * 16 + j]);
98 }
99 mon_out("\n");
100 }
101 }
102 } else {
103 uint8_t writedata[256];
104 int i, src;
105 MEMSPACE src_mem;
106
107 src = addr_location(addr);
108 src_mem = addr_memspace(addr);
109
110 for (i = 0; i < 256; i++) {
111 writedata[i] = mon_get_mem_val(src_mem, ADDR_LIMIT(src + i));
112 }
113
114 if (vdrive_write_sector(vdrive, writedata, track, sector)) {
115 mon_out("Error writing track %d sector %d\n", track, sector);
116 return;
117 }
118
119 mon_out("Write data from address $%04x to track %d sector %d\n",
120 (unsigned int)src, track, sector);
121 }
122 }
123
124
mon_drive_execute_disk_cmd(char * cmd)125 void mon_drive_execute_disk_cmd(char *cmd)
126 {
127 unsigned int len;
128 vdrive_t *vdrive;
129
130 /* FIXME */
131 vdrive = file_system_get_vdrive(8, 0);
132
133 len = (unsigned int)strlen(cmd);
134
135 vdrive_command_execute(vdrive, (uint8_t *)cmd, len);
136 }
137
138 /* FIXME: this function should perhaps live elsewhere */
139 /* check if a drive is associated with a filesystem/directory */
mon_drive_is_fsdevice(int drive_unit)140 int mon_drive_is_fsdevice(int drive_unit)
141 {
142 int virtualdev = 0, truedrive = 0, iecdevice = 0 /* , fsdevice = 0 */;
143 /* FIXME: unsure if this check really works as advertised */
144 resources_get_int("VirtualDevices", &virtualdev);
145 resources_get_int("DriveTrueEmulation", &truedrive);
146 resources_get_int_sprintf("IECDevice%i", &iecdevice, drive_unit);
147 /* resources_get_int_sprintf("FileSystemDevice%i", &fsdevice, drive_unit); */
148 if ((virtualdev && !truedrive) || (!virtualdev && iecdevice)) {
149 if (machine_bus_device_type_get(drive_unit) == SERIAL_DEVICE_FS) {
150 return 1;
151 }
152 }
153 return 0;
154 }
155
156 /* FIXME: this function should perhaps live elsewhere */
157 /* for a given drive unit, return the associated fsdevice directory, or NULL
158 if there is none */
mon_drive_get_fsdevice_path(int drive_unit)159 const char *mon_drive_get_fsdevice_path(int drive_unit)
160 {
161 const char *fspath = NULL;
162 if (mon_drive_is_fsdevice(drive_unit)) {
163 resources_get_string_sprintf("FSDevice%iDir", &fspath, drive_unit);
164 }
165 return fspath;
166 }
167
mon_drive_list(int drive_unit)168 void mon_drive_list(int drive_unit)
169 {
170 const char *name;
171 image_contents_t *listing;
172 vdrive_t *vdrive;
173 /* TODO: drive 1? */
174 unsigned int drive = 0;
175 const char *fspath = NULL;
176
177 if ((drive_unit < 8) || (drive_unit > 11)) {
178 drive_unit = 8;
179 }
180
181 vdrive = file_system_get_vdrive(drive_unit, drive);
182
183 if (vdrive == NULL || vdrive->image == NULL) {
184 if ((fspath = mon_drive_get_fsdevice_path(drive_unit))) {
185 mon_show_dir(fspath);
186 return;
187 }
188 mon_out("Drive %i not ready.\n", drive_unit);
189 return;
190 }
191
192 name = disk_image_name_get(vdrive->image);
193
194 listing = diskcontents_read(name, drive_unit, drive);
195
196 if (listing != NULL) {
197 char *string = image_contents_to_string(listing, 1);
198 image_contents_file_list_t *element = listing->file_list;
199
200 mon_out("%s\n", string);
201 lib_free(string);
202
203 if (element == NULL) {
204 mon_out("Empty image\n");
205 } else {
206 do {
207 string = image_contents_file_to_string(element, 1);
208 mon_out("%s\n", string);
209 lib_free(string);
210 }
211 while ((element = element->next) != NULL);
212 }
213
214 if (listing->blocks_free >= 0) {
215 string = lib_msprintf("%d blocks free.\n", listing->blocks_free);
216 mon_out("%s", string);
217 lib_free(string);
218 }
219 }
220 }
221
222