src/mess/machine/oric.c
| r5655 | r5656 | |
| 25 | 25 | #include "machine/applefdc.h" |
| 26 | 26 | #include "machine/6551.h" |
| 27 | 27 | #include "machine/ctronics.h" |
| 28 | | #include "devices/mfmdisk.h" |
| 29 | 28 | #include "devices/cassette.h" |
| 30 | 29 | #include "sound/ay8910.h" |
| 31 | 30 | |
| r5655 | r5656 | |
| 380 | 379 | { |
| 381 | 380 | if (enable_logging) |
| 382 | 381 | { |
| 383 | | logerror("oric via1 interrupt\r\n"); |
| 382 | //logerror("oric via1 interrupt\r\n"); |
| 384 | 383 | } |
| 385 | 384 | |
| 386 | 385 | oric_irqs |=(1<<0); |
| r5655 | r5656 | |
| 711 | 710 | break; |
| 712 | 711 | default: |
| 713 | 712 | data = via_r(via_0, offset & 0x0f); |
| 714 | | logerror("unhandled io read: %04x %02x\n", offset, data); |
| 713 | //logerror("unhandled io read: %04x %02x\n", offset, data); |
| 715 | 714 | break; |
| 716 | 715 | |
| 717 | 716 | } |
| r5655 | r5656 | |
| 747 | 746 | wd17xx_reset(fdc); |
| 748 | 747 | break; |
| 749 | 748 | case 0x0a: |
| 750 | | logerror("jasmin overlay ram w: %02x PC: %04x\n", data, cpu_get_pc(cputag_get_cpu(space->machine, "maincpu"))); |
| 749 | //logerror("jasmin overlay ram w: %02x PC: %04x\n", data, cpu_get_pc(cputag_get_cpu(space->machine, "maincpu"))); |
| 751 | 750 | port_3fa_w = data; |
| 752 | 751 | oric_jasmin_set_mem_0x0c000(space->machine); |
| 753 | 752 | break; |
| 754 | 753 | case 0x0b: |
| 755 | | logerror("jasmin romdis w: %02x PC: %04x\n", data, cpu_get_pc(cputag_get_cpu(space->machine, "maincpu"))); |
| 754 | //logerror("jasmin romdis w: %02x PC: %04x\n", data, cpu_get_pc(cputag_get_cpu(space->machine, "maincpu"))); |
| 756 | 755 | port_3fb_w = data; |
| 757 | 756 | oric_jasmin_set_mem_0x0c000(space->machine); |
| 758 | 757 | break; |
| r5655 | r5656 | |
| 990 | 989 | |
| 991 | 990 | port_314_w = data; |
| 992 | 991 | |
| 993 | | logerror("port_314_w: %02x\n",data); |
| 992 | //logerror("port_314_w: %02x\n",data); |
| 994 | 993 | |
| 995 | 994 | /* bit 6,5: drive */ |
| 996 | 995 | /* bit 4: side */ |
| r5655 | r5656 | |
| 1066 | 1065 | |
| 1067 | 1066 | const wd17xx_interface oric_wd17xx_interface = { oric_wd179x_callback, NULL }; |
| 1068 | 1067 | |
| 1069 | | DEVICE_START( oric_floppy ) |
| 1070 | | { |
| 1071 | | /* TODO - THIS DOES NOT MULTITASK BETWEEN ORIC BASICDSKs AND MFM DISKS */ |
| 1072 | | floppy_drive_init(device, NULL); |
| 1073 | | } |
| 1074 | | |
| 1075 | | |
| 1076 | | |
| 1077 | | DEVICE_IMAGE_LOAD( oric_floppy ) |
| 1078 | | { |
| 1079 | | /* attempt to open mfm disk */ |
| 1080 | | if (device_load_mfm_disk(image) == INIT_PASS) |
| 1081 | | { |
| 1082 | | floppy_drive_set_disk_image_interface(image, &mfm_disk_floppy_interface); |
| 1083 | | return INIT_PASS; |
| 1084 | | } |
| 1085 | | |
| 1086 | | /* if (device_load_basicdsk_floppy(image) == INIT_PASS) |
| 1087 | | { |
| 1088 | | // I don't know what the geometry of the disc image should be, so the |
| 1089 | | //default is 80 tracks, 2 sides, 9 sectors per track |
| 1090 | | basicdsk_set_geometry(image, 80, 2, 9, 512, 1, 0, FALSE); |
| 1091 | | floppy_drive_set_disk_image_interface(image, &basicdsk_floppy_interface); |
| 1092 | | return INIT_PASS; |
| 1093 | | }*/ |
| 1094 | | return INIT_FAIL; |
| 1095 | | } |
| 1096 | | |
| 1097 | 1068 | static void oric_common_init_machine(running_machine *machine) |
| 1098 | 1069 | { |
| 1099 | 1070 | /* clear all irqs */ |
| r5655 | r5656 | |
| 1205 | 1176 | { |
| 1206 | 1177 | if ((offset & 0x0f)!=0x0d) |
| 1207 | 1178 | { |
| 1208 | | logerror("via 0 r: %04x %04x\n",offset, (unsigned) cpu_get_reg(cputag_get_cpu(space->machine, "maincpu"), REG_GENPC)); |
| 1179 | //logerror("via 0 r: %04x %04x\n",offset, (unsigned) cpu_get_reg(cputag_get_cpu(space->machine, "maincpu"), REG_GENPC)); |
| 1209 | 1180 | } |
| 1210 | 1181 | } |
| 1211 | 1182 | /* it is repeated */ |
| r5655 | r5656 | |
| 1244 | 1215 | } |
| 1245 | 1216 | if (enable_logging) |
| 1246 | 1217 | { |
| 1247 | | logerror("via 0 w: %04x %02x %04x\n", offset, data,(unsigned) cpu_get_reg(cputag_get_cpu(space->machine, "maincpu"), REG_GENPC)); |
| 1218 | //logerror("via 0 w: %04x %02x %04x\n", offset, data,(unsigned) cpu_get_reg(cputag_get_cpu(space->machine, "maincpu"), REG_GENPC)); |
| 1248 | 1219 | } |
| 1249 | 1220 | |
| 1250 | 1221 | via_w(via_0, offset & 0x0f, data); |
| r5655 | r5656 | |
| 1363 | 1334 | |
| 1364 | 1335 | static READ8_DEVICE_HANDLER(telestrat_via2_in_a_func) |
| 1365 | 1336 | { |
| 1366 | | logerror("via 2 - port a %02x\n",telestrat_via2_port_a_data); |
| 1337 | //logerror("via 2 - port a %02x\n",telestrat_via2_port_a_data); |
| 1367 | 1338 | return telestrat_via2_port_a_data; |
| 1368 | 1339 | } |
| 1369 | 1340 | |
| 1370 | 1341 | |
| 1371 | 1342 | static WRITE8_DEVICE_HANDLER(telestrat_via2_out_a_func) |
| 1372 | 1343 | { |
| 1373 | | logerror("via 2 - port a w: %02x\n",data); |
| 1344 | //logerror("via 2 - port a w: %02x\n",data); |
| 1374 | 1345 | |
| 1375 | 1346 | telestrat_via2_port_a_data = data; |
| 1376 | 1347 | |
| r5655 | r5656 | |
| 1415 | 1386 | |
| 1416 | 1387 | if (state) |
| 1417 | 1388 | { |
| 1418 | | logerror("telestrat via2 interrupt\n"); |
| 1389 | //logerror("telestrat via2 interrupt\n"); |
| 1419 | 1390 | |
| 1420 | 1391 | oric_irqs |=(1<<2); |
| 1421 | 1392 | } |
src/mess/devices/mfmdisk.c
| r5655 | r5656 | |
| 1 | | /* mfm disk image type used by euphoric */ |
| 2 | | /* this disc image contains raw mfm data */ |
| 3 | | /* TODO: |
| 4 | | |
| 5 | | |
| 6 | | - Check code is correct for single density discs |
| 7 | | - Check code is correct for detecting number of sides and track count |
| 8 | | - clever write and read which correctly setup the raw mfm |
| 9 | | */ |
| 10 | | |
| 11 | | #include "driver.h" |
| 12 | | #include "mfmdisk.h" |
| 13 | | #include "flopdrv.h" |
| 14 | | |
| 15 | | |
| 16 | | static void mfm_disk_seek_callback(const device_config *image, int); |
| 17 | | static int mfm_disk_get_sectors_per_track(const device_config *image, int); |
| 18 | | static void mfm_disk_get_id_callback(const device_config *image, chrn_id *, int, int); |
| 19 | | static void mfm_disk_read_sector_data_into_buffer(const device_config *image, int side, int index1, char *ptr, int length); |
| 20 | | static void mfm_disk_write_sector_data_from_buffer(const device_config *image, int side, int index1, const char *ptr, int length,int ddam); |
| 21 | | |
| 22 | | const floppy_interface mfm_disk_floppy_interface = |
| 23 | | { |
| 24 | | mfm_disk_seek_callback, |
| 25 | | mfm_disk_get_sectors_per_track, /* done */ |
| 26 | | mfm_disk_get_id_callback, /* done */ |
| 27 | | mfm_disk_read_sector_data_into_buffer, /* done */ |
| 28 | | mfm_disk_write_sector_data_from_buffer, /* done */ |
| 29 | | NULL, |
| 30 | | NULL |
| 31 | | }; |
| 32 | | |
| 33 | | |
| 34 | | #define MFM_ID "MFM_DISK" |
| 35 | | |
| 36 | | #define MFM_DISK_DENSITY_FM_HIGH 1 |
| 37 | | #define MFM_DISK_DENSITY_MFM_LO 2 |
| 38 | | |
| 39 | | /* size of header */ |
| 40 | | #define mfm_disk_header_size 0x0100 |
| 41 | | |
| 42 | | /* size of a double density track in this image */ |
| 43 | | static const int TrackSizeMFMLo = 0x01900; |
| 44 | | |
| 45 | | /* number of disk images that this code can handle at one time */ |
| 46 | | #define MAX_MFM_DISK 4 |
| 47 | | |
| 48 | | /* max number of sectors that info can be stored about */ |
| 49 | | #define MAX_SECTORS 32 |
| 50 | | |
| 51 | | struct mfm_disk_sector_info |
| 52 | | { |
| 53 | | unsigned char *id_ptr; |
| 54 | | unsigned char *data_ptr; |
| 55 | | }; |
| 56 | | |
| 57 | | struct mfm_disk_info |
| 58 | | { |
| 59 | | /* pointer to image data */ |
| 60 | | unsigned char *pData; |
| 61 | | |
| 62 | | /* current track */ |
| 63 | | int CurrentTrack; |
| 64 | | |
| 65 | | /* from header */ |
| 66 | | unsigned long NumTracks; |
| 67 | | |
| 68 | | /* from header */ |
| 69 | | unsigned long NumSides; |
| 70 | | |
| 71 | | /* from header */ |
| 72 | | unsigned long Density; |
| 73 | | |
| 74 | | |
| 75 | | |
| 76 | | /* these apply to the current track */ |
| 77 | | int CachedTrack, CachedSide; |
| 78 | | unsigned long NumSectors; |
| 79 | | struct mfm_disk_sector_info sectors[32]; |
| 80 | | |
| 81 | | |
| 82 | | }; |
| 83 | | |
| 84 | | /* the disk images */ |
| 85 | | static struct mfm_disk_info mfm_disks[MAX_MFM_DISK]; |
| 86 | | |
| 87 | | /* this code is not very clever. It assumes that the data is stored as: |
| 88 | | |
| 89 | | id mark, data block, id mark, data block... |
| 90 | | |
| 91 | | This is ok for standard format discs and some copyprotections, however, |
| 92 | | I have seen discs on the Amstrad CPC which have: |
| 93 | | |
| 94 | | id mark, id mark, id mark, data block.... |
| 95 | | |
| 96 | | This code cannot detect these, because it does not know the difference between |
| 97 | | a data mark/deleted data mark and data in a data field or id field. |
| 98 | | |
| 99 | | This code also assumes that the N value in the ID field defines the size of the |
| 100 | | data block following. If the data block is a different size, it could miss sectors, |
| 101 | | or jump into the middle of a sector and then get confused about a id mark/data mark/ |
| 102 | | deleted data mark and data in the sector field! |
| 103 | | */ |
| 104 | | |
| 105 | | static struct mfm_disk_info *get_disk(const device_config *image) |
| 106 | | { |
| 107 | | int disk = image_index_in_device(image); |
| 108 | | return &mfm_disks[disk]; |
| 109 | | } |
| 110 | | |
| 111 | | /* TODO: Error checking if a id is found at very end of track, or a sector which |
| 112 | | goes over end of track */ |
| 113 | | static void mfm_info_cache_sector_info(const device_config *image,unsigned char *pTrackPtr, unsigned long Length) |
| 114 | | { |
| 115 | | /* initialise these with single density values if single density */ |
| 116 | | unsigned char IdMark = 0x0fe; |
| 117 | | unsigned char DataMark = 0x0fb; |
| 118 | | unsigned char DeletedDataMark = 0x0f8; |
| 119 | | |
| 120 | | unsigned long SectorCount; |
| 121 | | unsigned long N = 0; |
| 122 | | unsigned long SearchCode = 0; |
| 123 | | unsigned char *pStart = pTrackPtr; |
| 124 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 125 | | |
| 126 | | SectorCount = 0; |
| 127 | | |
| 128 | | do |
| 129 | | { |
| 130 | | switch (SearchCode) |
| 131 | | { |
| 132 | | /* searching for id's */ |
| 133 | | case 0: |
| 134 | | { |
| 135 | | /* found id mark? */ |
| 136 | | if (pTrackPtr[0] == IdMark) |
| 137 | | { |
| 138 | | /* store pointer to id mark */ |
| 139 | | mfm_disk->sectors[SectorCount].id_ptr = pTrackPtr; |
| 140 | | SectorCount++; |
| 141 | | |
| 142 | | /* grab N value - used to skip data in data field */ |
| 143 | | N = pTrackPtr[4]; |
| 144 | | |
| 145 | | /* skip past id field and crc */ |
| 146 | | pTrackPtr+=7; |
| 147 | | |
| 148 | | /* now looking for data field */ |
| 149 | | SearchCode = 1; |
| 150 | | } |
| 151 | | else |
| 152 | | { |
| 153 | | /* update position */ |
| 154 | | pTrackPtr++; |
| 155 | | } |
| 156 | | } |
| 157 | | break; |
| 158 | | |
| 159 | | /* searching for data id's */ |
| 160 | | case 1: |
| 161 | | { |
| 162 | | /* found data or deleted data? */ |
| 163 | | if ((pTrackPtr[0] == DataMark) || (pTrackPtr[0] == DeletedDataMark)) |
| 164 | | { |
| 165 | | /* yes */ |
| 166 | | mfm_disk->sectors[SectorCount-1].data_ptr = pTrackPtr; |
| 167 | | |
| 168 | | /* skip data field and id */ |
| 169 | | pTrackPtr+=(1<<(N+7)) + 3; |
| 170 | | |
| 171 | | /* now looking for id field */ |
| 172 | | SearchCode = 0; |
| 173 | | |
| 174 | | } |
| 175 | | else |
| 176 | | { |
| 177 | | pTrackPtr++; |
| 178 | | } |
| 179 | | } |
| 180 | | break; |
| 181 | | |
| 182 | | default: |
| 183 | | break; |
| 184 | | } |
| 185 | | } |
| 186 | | while ((pTrackPtr-pStart)<Length); |
| 187 | | |
| 188 | | mfm_disk->NumSectors = SectorCount; |
| 189 | | logerror("mfm disk: Num Sectors %02x\n,", (int) SectorCount); |
| 190 | | |
| 191 | | } |
| 192 | | |
| 193 | | static unsigned long mfm_disk_get_track_size(const device_config *image) |
| 194 | | { |
| 195 | | struct mfm_disk_info *pDisk = get_disk(image); |
| 196 | | switch (pDisk->Density) |
| 197 | | { |
| 198 | | case MFM_DISK_DENSITY_MFM_LO: |
| 199 | | return TrackSizeMFMLo; |
| 200 | | |
| 201 | | default: |
| 202 | | break; |
| 203 | | } |
| 204 | | |
| 205 | | return 0; |
| 206 | | } |
| 207 | | |
| 208 | | |
| 209 | | static unsigned char *mfm_disk_get_track_ptr(const device_config *image, int track, int side) |
| 210 | | { |
| 211 | | struct mfm_disk_info *pDisk = get_disk(image); |
| 212 | | |
| 213 | | unsigned long TrackSize; |
| 214 | | |
| 215 | | TrackSize = mfm_disk_get_track_size(image); |
| 216 | | |
| 217 | | return pDisk->pData + mfm_disk_header_size + (TrackSize*((track*pDisk->NumSides)+side)); |
| 218 | | } |
| 219 | | |
| 220 | | /* this is endian safe */ |
| 221 | | static unsigned long mfm_get_long(unsigned char *addr) |
| 222 | | { |
| 223 | | int i; |
| 224 | | unsigned long Data = 0; |
| 225 | | int Shift; |
| 226 | | |
| 227 | | Shift = 0; |
| 228 | | |
| 229 | | /* get 4 bytes */ |
| 230 | | for (i=0; i<4; i++) |
| 231 | | { |
| 232 | | /* get byte, shift it up and combine with existing value so far */ |
| 233 | | Data = Data | ((addr[i] & 0x0ff)<<Shift); |
| 234 | | /* update shift */ |
| 235 | | Shift = Shift+8; |
| 236 | | } |
| 237 | | |
| 238 | | return Data; |
| 239 | | } |
| 240 | | |
| 241 | | #if 0 |
| 242 | | /* check a mfm_disk image is valid */ |
| 243 | | int mfm_disk_id(int id) |
| 244 | | { |
| 245 | | mame_file *file; |
| 246 | | int result = 0; |
| 247 | | |
| 248 | | /* open file and determine image geometry */ |
| 249 | | file = image_fopen(IO_FLOPPY, id, FILETYPE_IMAGE, OSD_FOPEN_READ); |
| 250 | | |
| 251 | | if (file) |
| 252 | | { |
| 253 | | unsigned char header[mfm_disk_header_size]; |
| 254 | | unsigned long FileLength; |
| 255 | | |
| 256 | | /* get length of file */ |
| 257 | | FileLength = mame_fsize(file); |
| 258 | | |
| 259 | | if (FileLength!=0) |
| 260 | | { |
| 261 | | /* load header */ |
| 262 | | if (mame_fread(file, header, mfm_disk_header_size)) |
| 263 | | { |
| 264 | | /* check for text ident */ |
| 265 | | if (memcmp(header, MFM_ID, 8)==0) |
| 266 | | { |
| 267 | | unsigned long NumTracks; |
| 268 | | unsigned long TrackSize; |
| 269 | | unsigned long NumSides; |
| 270 | | unsigned long Density; |
| 271 | | |
| 272 | | NumTracks = mfm_get_long(&header[12]); |
| 273 | | |
| 274 | | NumSides = mfm_get_long(&header[16]); |
| 275 | | |
| 276 | | Density = mfm_get_long(&header[8]); |
| 277 | | |
| 278 | | switch (Density) |
| 279 | | { |
| 280 | | default: |
| 281 | | case MFM_DISK_DENSITY_MFM_LO: |
| 282 | | { |
| 283 | | TrackSize = TrackSizeMFMLo; |
| 284 | | } |
| 285 | | break; |
| 286 | | |
| 287 | | } |
| 288 | | |
| 289 | | /* size must be long enough to contain the data */ |
| 290 | | if (FileLength>=((NumTracks*NumSides*TrackSize)+mfm_disk_header_size)) |
| 291 | | { |
| 292 | | logerror("mfm disk id succeeded!\n"); |
| 293 | | result = 1; |
| 294 | | } |
| 295 | | } |
| 296 | | } |
| 297 | | } |
| 298 | | |
| 299 | | mame_fclose(file); |
| 300 | | } |
| 301 | | |
| 302 | | return result; |
| 303 | | } |
| 304 | | #endif |
| 305 | | |
| 306 | | |
| 307 | | /* load image */ |
| 308 | | DEVICE_IMAGE_LOAD( mfm_disk ) |
| 309 | | { |
| 310 | | struct mfm_disk_info *pDisk = get_disk(image); |
| 311 | | |
| 312 | | pDisk->pData = image_ptr(image); |
| 313 | | if (!pDisk->pData) |
| 314 | | return INIT_FAIL; |
| 315 | | |
| 316 | | pDisk->NumTracks = mfm_get_long(&pDisk->pData[12]); |
| 317 | | pDisk->NumSides = mfm_get_long(&pDisk->pData[16]); |
| 318 | | pDisk->Density = mfm_get_long(&pDisk->pData[8]); |
| 319 | | pDisk->CachedTrack = -1; |
| 320 | | pDisk->CachedSide = -1; |
| 321 | | pDisk->NumSectors = 0; |
| 322 | | |
| 323 | | floppy_drive_set_disk_image_interface(image, &mfm_disk_floppy_interface); |
| 324 | | |
| 325 | | logerror("mfm disk inserted!\n"); |
| 326 | | return INIT_PASS; |
| 327 | | } |
| 328 | | |
| 329 | | /* cache info about track */ |
| 330 | | static void mfm_disk_cache_data(const device_config *image, int track, int side) |
| 331 | | { |
| 332 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 333 | | |
| 334 | | if ((track!=mfm_disk->CachedTrack) || (side!=mfm_disk->CachedSide)) |
| 335 | | { |
| 336 | | unsigned char *pTrackPtr = mfm_disk_get_track_ptr(image, track, side); |
| 337 | | unsigned long TrackSize = mfm_disk_get_track_size(image); |
| 338 | | |
| 339 | | mfm_info_cache_sector_info(image, pTrackPtr, TrackSize); |
| 340 | | |
| 341 | | mfm_disk->CachedTrack = track; |
| 342 | | mfm_disk->CachedSide = side; |
| 343 | | } |
| 344 | | } |
| 345 | | |
| 346 | | |
| 347 | | |
| 348 | | static void mfm_disk_get_id_callback(const device_config *image, chrn_id *id, int id_index, int side) |
| 349 | | { |
| 350 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 351 | | |
| 352 | | mfm_disk_cache_data(image, mfm_disk->CurrentTrack, side); |
| 353 | | |
| 354 | | if (id_index<mfm_disk->NumSectors) |
| 355 | | { |
| 356 | | /* construct a id value */ |
| 357 | | id->C = mfm_disk->sectors[id_index].id_ptr[1]; |
| 358 | | id->H = mfm_disk->sectors[id_index].id_ptr[2]; |
| 359 | | id->R = mfm_disk->sectors[id_index].id_ptr[3]; |
| 360 | | id->N = mfm_disk->sectors[id_index].id_ptr[4]; |
| 361 | | id->data_id = id_index; |
| 362 | | id->flags = 0; |
| 363 | | |
| 364 | | /* get dam - assumes double density - to be fixed */ |
| 365 | | if (mfm_disk->sectors[id_index].data_ptr[0]==0x0f8) |
| 366 | | { |
| 367 | | id->flags |= ID_FLAG_DELETED_DATA; |
| 368 | | } |
| 369 | | } |
| 370 | | } |
| 371 | | |
| 372 | | static int mfm_disk_get_sectors_per_track(const device_config *image, int side) |
| 373 | | { |
| 374 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 375 | | |
| 376 | | /* attempting to access an invalid side or track? */ |
| 377 | | if ((side>=mfm_disk->NumSides) || (mfm_disk->CurrentTrack>=mfm_disk->NumTracks)) |
| 378 | | { |
| 379 | | /* no sectors */ |
| 380 | | return 0; |
| 381 | | } |
| 382 | | mfm_disk_cache_data(image, mfm_disk->CurrentTrack, side); |
| 383 | | |
| 384 | | /* return number of sectors per track */ |
| 385 | | return mfm_disk->NumSectors; |
| 386 | | } |
| 387 | | |
| 388 | | static void mfm_disk_seek_callback(const device_config *image, int physical_track) |
| 389 | | { |
| 390 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 391 | | mfm_disk->CurrentTrack = physical_track; |
| 392 | | } |
| 393 | | |
| 394 | | /* reading and writing are not clever, they need to be so that the data is correctly written back |
| 395 | | to the image */ |
| 396 | | static void mfm_disk_write_sector_data_from_buffer(const device_config *image, int side, int index1, const char *ptr, int length, int ddam) |
| 397 | | { |
| 398 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 399 | | unsigned char *pSectorPtr; |
| 400 | | |
| 401 | | mfm_disk_cache_data(image, mfm_disk->CurrentTrack, side); |
| 402 | | |
| 403 | | pSectorPtr = mfm_disk->sectors[index1].data_ptr+1; |
| 404 | | |
| 405 | | memcpy(pSectorPtr, ptr, length); |
| 406 | | } |
| 407 | | |
| 408 | | static void mfm_disk_read_sector_data_into_buffer(const device_config *image, int side, int index1, char *ptr, int length) |
| 409 | | { |
| 410 | | struct mfm_disk_info *mfm_disk = get_disk(image); |
| 411 | | unsigned char *pSectorPtr; |
| 412 | | |
| 413 | | mfm_disk_cache_data(image, mfm_disk->CurrentTrack, side); |
| 414 | | |
| 415 | | pSectorPtr = mfm_disk->sectors[index1].data_ptr+1; |
| 416 | | |
| 417 | | memcpy(ptr, pSectorPtr, length); |
| 418 | | } |
| 419 | | |
src/mess/formats/oric_dsk.c
| r0 | r5656 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | formats/oric_dsk.c |
| 4 | |
| 5 | Oric disk images |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #include <string.h> |
| 10 | #include "formats/oric_dsk.h" |
| 11 | #include "formats/basicdsk.h" |
| 12 | #include "driver.h" |
| 13 | #include "devices/flopdrv.h" |
| 14 | |
| 15 | |
| 16 | #define mfm_disk_header_size 0x0100 |
| 17 | #define MFM_ID "MFM_DISK" |
| 18 | |
| 19 | static const int TRACK_SIZE_MFM = 0x01900; |
| 20 | struct mfm_disk_sector_info |
| 21 | { |
| 22 | int id_ptr; |
| 23 | int data_ptr; |
| 24 | int sector_size; |
| 25 | UINT8 ddam; |
| 26 | }; |
| 27 | |
| 28 | #define ORICDSK_TAG "oricdsktag" |
| 29 | struct oricdsk_tag |
| 30 | { |
| 31 | int tracks; |
| 32 | int heads; |
| 33 | int geometry; |
| 34 | int tracksize; |
| 35 | int num_sectors; |
| 36 | struct mfm_disk_sector_info sector_data[32]; |
| 37 | }; |
| 38 | |
| 39 | |
| 40 | static struct oricdsk_tag *get_tag(floppy_image *floppy) |
| 41 | { |
| 42 | struct oricdsk_tag *tag; |
| 43 | tag = floppy_tag(floppy, ORICDSK_TAG); |
| 44 | return tag; |
| 45 | } |
| 46 | |
| 47 | |
| 48 | static FLOPPY_IDENTIFY(oric_dsk_identify) |
| 49 | { |
| 50 | UINT8 header[mfm_disk_header_size]; |
| 51 | |
| 52 | floppy_image_read(floppy, header, 0, mfm_disk_header_size); |
| 53 | if ( memcmp( header, MFM_ID, 8 ) ==0) { |
| 54 | int heads = header[8] + (header[9] << 8 ) + (header[10] << 16) + (header[11] << 24); |
| 55 | int tracks = header[12] + (header[13] << 8) + (header[14] << 16) + (header[15] << 24); |
| 56 | |
| 57 | if (floppy_image_size(floppy)==((tracks*heads*TRACK_SIZE_MFM)+mfm_disk_header_size)) { |
| 58 | *vote = 100; |
| 59 | } else { |
| 60 | *vote = 0; |
| 61 | } |
| 62 | } else { |
| 63 | *vote = 0; |
| 64 | } |
| 65 | return FLOPPY_ERROR_SUCCESS; |
| 66 | } |
| 67 | static int oric_get_track_offset(floppy_image *floppy,int track, int head) |
| 68 | { |
| 69 | if (get_tag(floppy)->geometry==1) { |
| 70 | return mfm_disk_header_size + (get_tag(floppy)->tracksize * track) + (head * get_tag(floppy)->tracksize * get_tag(floppy)->tracks); |
| 71 | } else { |
| 72 | return mfm_disk_header_size + (get_tag(floppy)->tracksize*((track * get_tag(floppy)->heads)+head)); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | static int oric_get_heads_per_disk(floppy_image *floppy) |
| 77 | { |
| 78 | return get_tag(floppy)->heads; |
| 79 | } |
| 80 | |
| 81 | static int oric_get_tracks_per_disk(floppy_image *floppy) |
| 82 | { |
| 83 | return get_tag(floppy)->tracks; |
| 84 | } |
| 85 | |
| 86 | static void mfm_info_cache_sector_info(floppy_image *floppy,int track,int head) |
| 87 | { |
| 88 | UINT8 track_data[TRACK_SIZE_MFM]; |
| 89 | |
| 90 | /* initialise these with single density values if single density */ |
| 91 | UINT8 IdMark = 0x0fe; |
| 92 | UINT8 DataMark = 0x0fb; |
| 93 | UINT8 DeletedDataMark = 0x0f8; |
| 94 | |
| 95 | UINT8 SectorCount; |
| 96 | UINT8 SearchCode = 0; |
| 97 | UINT8 sector_number = 0; |
| 98 | int ptr = 0; |
| 99 | int track_offset = oric_get_track_offset(floppy,track,head); |
| 100 | floppy_image_read(floppy, track_data, track_offset, TRACK_SIZE_MFM); |
| 101 | SectorCount = 0; |
| 102 | |
| 103 | do |
| 104 | { |
| 105 | switch (SearchCode) |
| 106 | { |
| 107 | /* searching for id's */ |
| 108 | case 0: |
| 109 | { |
| 110 | /* found id mark? */ |
| 111 | if (track_data[ptr] == IdMark) |
| 112 | { |
| 113 | sector_number = track_data[ptr+3]-1; |
| 114 | /* store pointer to id mark */ |
| 115 | get_tag(floppy)->sector_data[sector_number].id_ptr = ptr + track_offset; |
| 116 | SectorCount++; |
| 117 | |
| 118 | /* grab N value - used to skip data in data field */ |
| 119 | get_tag(floppy)->sector_data[sector_number].sector_size = (1<< (track_data[ptr+4]+7)); |
| 120 | |
| 121 | /* skip past id field and crc */ |
| 122 | ptr+=7; |
| 123 | |
| 124 | /* now looking for data field */ |
| 125 | SearchCode = 1; |
| 126 | } |
| 127 | else |
| 128 | { |
| 129 | /* update position */ |
| 130 | ptr++; |
| 131 | } |
| 132 | } |
| 133 | break; |
| 134 | |
| 135 | /* searching for data id's */ |
| 136 | case 1: |
| 137 | { |
| 138 | /* found data or deleted data? */ |
| 139 | if ((track_data[ptr] == DataMark) || (track_data[ptr] == DeletedDataMark)) |
| 140 | { |
| 141 | /* yes */ |
| 142 | get_tag(floppy)->sector_data[sector_number].data_ptr = ptr + track_offset + 1; |
| 143 | get_tag(floppy)->sector_data[sector_number].ddam = (track_data[ptr] == DeletedDataMark) ? ID_FLAG_DELETED_DATA : 0; |
| 144 | |
| 145 | /* skip data field and id */ |
| 146 | ptr += get_tag(floppy)->sector_data[sector_number].sector_size + 3; |
| 147 | |
| 148 | /* now looking for id field */ |
| 149 | SearchCode = 0; |
| 150 | } |
| 151 | else |
| 152 | { |
| 153 | ptr++; |
| 154 | } |
| 155 | } |
| 156 | break; |
| 157 | |
| 158 | default: |
| 159 | break; |
| 160 | } |
| 161 | } |
| 162 | while (ptr < TRACK_SIZE_MFM); |
| 163 | get_tag(floppy)->num_sectors = SectorCount; |
| 164 | |
| 165 | } |
| 166 | |
| 167 | static floperr_t get_offset(floppy_image *floppy, int head, int track, int sector, int sector_is_index, UINT64 *offset) |
| 168 | { |
| 169 | UINT64 offs; |
| 170 | |
| 171 | /* translate the sector to a raw sector */ |
| 172 | if (!sector_is_index) |
| 173 | { |
| 174 | sector -= 1; |
| 175 | } |
| 176 | mfm_info_cache_sector_info(floppy,track,head); |
| 177 | |
| 178 | /* check to see if we are out of range */ |
| 179 | if ((head < 0) || (head >= get_tag(floppy)->heads) || (track < 0) || (track >= get_tag(floppy)->tracks) |
| 180 | || (sector < 0) || (sector >=get_tag(floppy)->num_sectors)) |
| 181 | return FLOPPY_ERROR_SEEKERROR; |
| 182 | |
| 183 | offs = get_tag(floppy)->sector_data[sector].data_ptr; |
| 184 | if (offset) |
| 185 | *offset = offs; |
| 186 | return FLOPPY_ERROR_SUCCESS; |
| 187 | } |
| 188 | |
| 189 | |
| 190 | |
| 191 | static floperr_t internal_oric_read_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, void *buffer, size_t buflen) |
| 192 | { |
| 193 | UINT64 offset; |
| 194 | floperr_t err; |
| 195 | err = get_offset(floppy, head, track, sector, sector_is_index, &offset); |
| 196 | if (err) |
| 197 | return err; |
| 198 | floppy_image_read(floppy, buffer, offset, buflen); |
| 199 | return FLOPPY_ERROR_SUCCESS; |
| 200 | } |
| 201 | |
| 202 | |
| 203 | |
| 204 | static floperr_t internal_oric_write_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, const void *buffer, size_t buflen, int ddam) |
| 205 | { |
| 206 | UINT64 offset; |
| 207 | floperr_t err; |
| 208 | |
| 209 | err = get_offset(floppy, head, track, sector, sector_is_index, &offset); |
| 210 | if (err) |
| 211 | return err; |
| 212 | |
| 213 | floppy_image_write(floppy, buffer, offset, buflen); |
| 214 | return FLOPPY_ERROR_SUCCESS; |
| 215 | } |
| 216 | |
| 217 | |
| 218 | |
| 219 | static floperr_t oric_read_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen) |
| 220 | { |
| 221 | return internal_oric_read_sector(floppy, head, track, sector, FALSE, buffer, buflen); |
| 222 | } |
| 223 | |
| 224 | static floperr_t oric_write_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) |
| 225 | { |
| 226 | return internal_oric_write_sector(floppy, head, track, sector, FALSE, buffer, buflen, ddam); |
| 227 | } |
| 228 | |
| 229 | static floperr_t oric_read_indexed_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen) |
| 230 | { |
| 231 | return internal_oric_read_sector(floppy, head, track, sector, TRUE, buffer, buflen); |
| 232 | } |
| 233 | |
| 234 | static floperr_t oric_write_indexed_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam) |
| 235 | { |
| 236 | return internal_oric_write_sector(floppy, head, track, sector, TRUE, buffer, buflen, ddam); |
| 237 | } |
| 238 | |
| 239 | static floperr_t oric_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length) |
| 240 | { |
| 241 | floperr_t err; |
| 242 | err = get_offset(floppy, head, track, sector, FALSE, NULL); |
| 243 | if (err) |
| 244 | return err; |
| 245 | |
| 246 | if (sector_length) { |
| 247 | *sector_length = get_tag(floppy)->sector_data[sector].sector_size; |
| 248 | } |
| 249 | return FLOPPY_ERROR_SUCCESS; |
| 250 | } |
| 251 | |
| 252 | |
| 253 | |
| 254 | static floperr_t oric_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags) |
| 255 | { |
| 256 | floperr_t retVal; |
| 257 | |
| 258 | sector_index += 1; |
| 259 | |
| 260 | retVal = oric_get_sector_length(floppy, head, track, sector_index, sector_length); |
| 261 | if (sector_length!=NULL) { |
| 262 | *sector_length = get_tag(floppy)->sector_data[sector_index-1].sector_size; |
| 263 | } |
| 264 | if (cylinder) |
| 265 | *cylinder = track; |
| 266 | if (side) |
| 267 | *side = head; |
| 268 | if (sector) |
| 269 | *sector = sector_index; |
| 270 | if (flags) |
| 271 | *flags = get_tag(floppy)->sector_data[sector_index].ddam; |
| 272 | return retVal; |
| 273 | } |
| 274 | |
| 275 | |
| 276 | static FLOPPY_CONSTRUCT(oric_dsk_construct) |
| 277 | { |
| 278 | struct FloppyCallbacks *callbacks; |
| 279 | struct oricdsk_tag *tag; |
| 280 | UINT8 header[mfm_disk_header_size]; |
| 281 | |
| 282 | floppy_image_read(floppy, header, 0, mfm_disk_header_size); |
| 283 | |
| 284 | tag = (struct oricdsk_tag *) floppy_create_tag(floppy, ORICDSK_TAG, sizeof(struct oricdsk_tag)); |
| 285 | if (!tag) |
| 286 | return FLOPPY_ERROR_OUTOFMEMORY; |
| 287 | tag->heads = header[8] + (header[9] << 8 ) + (header[10] << 16) + (header[11] << 24); |
| 288 | tag->tracks = header[12] + (header[13] << 8) + (header[14] << 16) + (header[15] << 24); |
| 289 | tag->geometry = header[16] + (header[17] << 8) + (header[18] << 16) + (header[19] << 24); |
| 290 | tag->tracksize = 0x1900; |
| 291 | memset(tag->sector_data,0,sizeof(tag->sector_data)); |
| 292 | |
| 293 | callbacks = floppy_callbacks(floppy); |
| 294 | callbacks->read_sector = oric_read_sector; |
| 295 | callbacks->write_sector = oric_write_sector; |
| 296 | callbacks->read_indexed_sector = oric_read_indexed_sector; |
| 297 | callbacks->write_indexed_sector = oric_write_indexed_sector; |
| 298 | callbacks->get_sector_length = oric_get_sector_length; |
| 299 | callbacks->get_heads_per_disk = oric_get_heads_per_disk; |
| 300 | callbacks->get_tracks_per_disk = oric_get_tracks_per_disk; |
| 301 | callbacks->get_indexed_sector_info = oric_get_indexed_sector_info; |
| 302 | return FLOPPY_ERROR_SUCCESS; |
| 303 | } |
| 304 | /* ----------------------------------------------------------------------- */ |
| 305 | |
| 306 | FLOPPY_OPTIONS_START( oric ) |
| 307 | FLOPPY_OPTION( oricmfm, "dsk", "Oric MFM floppy disk image", oric_dsk_identify, oric_dsk_construct, NULL) |
| 308 | FLOPPY_OPTION( oric, "dsk", "Oric disk image", basicdsk_identify_default, basicdsk_construct_default, |
| 309 | HEADS([2]) |
| 310 | TRACKS([80]) |
| 311 | SECTORS([9]) |
| 312 | SECTOR_LENGTH([512]) |
| 313 | FIRST_SECTOR_ID([1])) |
| 314 | FLOPPY_OPTIONS_END |