1 |
|
/* |
2 |
|
* 1541d64.cpp - 1541 emulation in disk image files (.d64/.x64/zipcode) |
3 |
|
* |
4 |
< |
* Frodo (C) 1994-1997,2002-2003 Christian Bauer |
4 |
> |
* Frodo Copyright (C) Christian Bauer |
5 |
|
* zipcode decoding routines (C) 1993-1997 Marko Mäkelä, Paul David Doherty |
6 |
|
* |
7 |
|
* This program is free software; you can redistribute it and/or modify |
109 |
|
|
110 |
|
// Prototypes |
111 |
|
static bool match(const uint8 *p, int p_len, const uint8 *n); |
112 |
+ |
static FILE *open_image_file(const char *path, bool write_mode); |
113 |
+ |
static bool parse_image_file(FILE *f, image_file_desc &desc); |
114 |
|
|
115 |
|
|
116 |
|
/* |
119 |
|
|
120 |
|
ImageDrive::ImageDrive(IEC *iec, const char *filepath) : Drive(iec), the_file(NULL), bam(ram + 0x700), bam_dirty(false) |
121 |
|
{ |
122 |
+ |
desc.type = TYPE_D64; |
123 |
+ |
desc.header_size = 0; |
124 |
+ |
desc.num_tracks = 35; |
125 |
+ |
desc.id1 = desc.id2 = 0; |
126 |
+ |
desc.has_error_info = false; |
127 |
+ |
|
128 |
|
for (int i=0; i<18; i++) { |
129 |
|
ch[i].mode = CHMOD_FREE; |
130 |
|
ch[i].buf = NULL; |
1300 |
|
}; |
1301 |
|
|
1302 |
|
// Read sector, return error code |
1303 |
< |
int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) |
1303 |
> |
static int read_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) |
1304 |
|
{ |
1305 |
|
// Convert track/sector to byte offset in file |
1306 |
|
long offset = offset_from_ts(desc, track, sector); |
1320 |
|
} |
1321 |
|
|
1322 |
|
// Write sector, return error code |
1323 |
< |
int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) |
1323 |
> |
static int write_sector(FILE *f, const image_file_desc &desc, int track, int sector, uint8 *buffer) |
1324 |
|
{ |
1325 |
|
// Convert track/sector to byte offset in file |
1326 |
|
long offset = offset_from_ts(desc, track, sector); |
1356 |
|
} |
1357 |
|
|
1358 |
|
// Write error info back to image file |
1359 |
< |
void write_back_error_info(FILE *f, const image_file_desc &desc) |
1359 |
> |
static void write_back_error_info(FILE *f, const image_file_desc &desc) |
1360 |
|
{ |
1361 |
|
if (desc.type == TYPE_D64 && desc.has_error_info) { |
1362 |
|
int num_sectors = desc.num_tracks == 40 ? NUM_SECTORS_40 : NUM_SECTORS_35; |
1366 |
|
} |
1367 |
|
|
1368 |
|
// Format disk image |
1369 |
< |
bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len) |
1369 |
> |
static bool format_image(FILE *f, image_file_desc &desc, bool lowlevel, uint8 id1, uint8 id2, const uint8 *disk_name, int disk_name_len) |
1370 |
|
{ |
1371 |
|
uint8 p[256]; |
1372 |
|
|
1963 |
|
* Open disk image file, return file handle |
1964 |
|
*/ |
1965 |
|
|
1966 |
< |
FILE *open_image_file(const char *path, bool write_mode) |
1966 |
> |
static FILE *open_image_file(const char *path, bool write_mode) |
1967 |
|
{ |
1968 |
|
#if 0 |
1969 |
|
if (is_zipcode_file(path)) { |
2047 |
|
return true; |
2048 |
|
} |
2049 |
|
|
2050 |
< |
bool parse_image_file(FILE *f, image_file_desc &desc) |
2050 |
> |
static bool parse_image_file(FILE *f, image_file_desc &desc) |
2051 |
|
{ |
2052 |
|
// Read header |
2053 |
|
uint8 header[64]; |
2069 |
|
} |
2070 |
|
|
2071 |
|
|
2072 |
+ |
/* |
2073 |
+ |
* Read directory of disk image file into (empty) c64_dir_entry vector, |
2074 |
+ |
* returns false on error |
2075 |
+ |
*/ |
2076 |
+ |
|
2077 |
+ |
bool ReadImageDirectory(const char *path, vector<c64_dir_entry> &vec) |
2078 |
+ |
{ |
2079 |
+ |
bool result = false; |
2080 |
+ |
|
2081 |
+ |
// Open file |
2082 |
+ |
FILE *f = open_image_file(path, false); |
2083 |
+ |
if (f) { |
2084 |
+ |
int num_dir_blocks = 0; |
2085 |
+ |
|
2086 |
+ |
// Determine file type and fill in image_file_desc structure |
2087 |
+ |
image_file_desc desc; |
2088 |
+ |
if (!parse_image_file(f, desc)) |
2089 |
+ |
goto done; |
2090 |
+ |
|
2091 |
+ |
// Scan all directory blocks |
2092 |
+ |
uint8 dir[256]; |
2093 |
+ |
dir[DIR_NEXT_TRACK] = DIR_TRACK; |
2094 |
+ |
dir[DIR_NEXT_SECTOR] = 1; |
2095 |
+ |
|
2096 |
+ |
while (dir[DIR_NEXT_TRACK] && num_dir_blocks < num_sectors[DIR_TRACK]) { |
2097 |
+ |
if (read_sector(f, desc, dir[DIR_NEXT_TRACK], dir[DIR_NEXT_SECTOR], dir) != ERR_OK) |
2098 |
+ |
break; |
2099 |
+ |
num_dir_blocks++; |
2100 |
+ |
|
2101 |
+ |
// Scan all 8 entries of a block |
2102 |
+ |
uint8 *de = dir + DIR_ENTRIES; |
2103 |
+ |
for (int j=0; j<8; j++, de+=SIZEOF_DE) { |
2104 |
+ |
|
2105 |
+ |
// Skip empty entries |
2106 |
+ |
if (de[DE_TYPE] == 0) |
2107 |
+ |
continue; |
2108 |
+ |
|
2109 |
+ |
// Convert file name (strip everything after and including the first trailing space) |
2110 |
+ |
uint8 name_buf[17]; |
2111 |
+ |
memcpy(name_buf, de + DE_NAME, 16); |
2112 |
+ |
name_buf[16] = 0; |
2113 |
+ |
uint8 *p = (uint8 *)memchr(name_buf, 0xa0, 16); |
2114 |
+ |
if (p) |
2115 |
+ |
*p = 0; |
2116 |
+ |
|
2117 |
+ |
// Convert file type |
2118 |
+ |
int type = de[DE_TYPE] & 7; |
2119 |
+ |
if (type > 4) |
2120 |
+ |
type = FTYPE_UNKNOWN; |
2121 |
+ |
|
2122 |
+ |
// Read start address |
2123 |
+ |
uint8 sa_lo = 0, sa_hi = 0; |
2124 |
+ |
uint8 buf[256]; |
2125 |
+ |
if (read_sector(f, desc, de[DE_TRACK], de[DE_SECTOR], buf) == ERR_OK) { |
2126 |
+ |
sa_lo = buf[2]; |
2127 |
+ |
sa_hi = buf[3]; |
2128 |
+ |
} |
2129 |
+ |
|
2130 |
+ |
// Add entry |
2131 |
+ |
vec.push_back(c64_dir_entry(name_buf, type, !(de[DE_TYPE] & 0x80), de[DE_TYPE] & 0x40, ((de[DE_NUM_BLOCKS_H] << 8) + de[DE_NUM_BLOCKS_L]) * 254, 0, sa_lo, sa_hi)); |
2132 |
+ |
} |
2133 |
+ |
} |
2134 |
+ |
|
2135 |
+ |
result = true; |
2136 |
+ |
done: fclose(f); |
2137 |
+ |
} |
2138 |
+ |
return result; |
2139 |
+ |
} |
2140 |
+ |
|
2141 |
+ |
|
2142 |
|
/* |
2143 |
|
* Create new blank disk image file, returns false on error |
2144 |
|
*/ |