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