diff options
author | 2013-02-22 10:53:15 +0000 | |
---|---|---|
committer | 2013-02-22 10:53:15 +0000 | |
commit | 2b25f4a87f24cbac5480d658085517283ad67b3b (patch) | |
tree | 05259271a2a59ca6e6ee706ab96a8de0b909813b /src/mess/machine/appldriv.c | |
parent | b25a1c367a3409865f2b049851a0235526b96978 (diff) |
Moved some mess devices to proper place (nw)
Diffstat (limited to 'src/mess/machine/appldriv.c')
-rw-r--r-- | src/mess/machine/appldriv.c | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/src/mess/machine/appldriv.c b/src/mess/machine/appldriv.c new file mode 100644 index 00000000000..6c91161d067 --- /dev/null +++ b/src/mess/machine/appldriv.c @@ -0,0 +1,334 @@ +/********************************************************************* + + appldriv.c + + Apple 5.25" floppy drive emulation (to be interfaced with applefdc.c) + +*********************************************************************/ +#include "emu.h" +#include "appldriv.h" +#include "imagedev/flopdrv.h" +#include "formats/ap2_dsk.h" + +// our parent's device is the Disk II card (Apple II) or main driver (Mac, IIgs) +// either way, get the drive from there. +#define PARENT_FLOPPY_0 "^floppy0" +#define PARENT_FLOPPY_1 "^floppy1" +#define PARENT_FLOPPY_2 "^floppy2" +#define PARENT_FLOPPY_3 "^floppy3" + +INLINE apple525_floppy_image_device *get_device(device_t *device) +{ + assert(device != NULL); + assert(device->type() == FLOPPY_APPLE); + + return (apple525_floppy_image_device *) downcast<apple525_floppy_image_device *>(device); +} + +static int apple525_enable_mask = 1; + +device_t *apple525_get_subdevice(device_t *device, int drive) +{ + switch(drive) { + case 0 : return device->subdevice(PARENT_FLOPPY_0); + case 1 : return device->subdevice(PARENT_FLOPPY_1); + case 2 : return device->subdevice(PARENT_FLOPPY_2); + case 3 : return device->subdevice(PARENT_FLOPPY_3); + } + return NULL; +} + +device_t *apple525_get_device_by_type(device_t *device, int ftype, int drive) +{ + int i; + int cnt = 0; + for (i=0;i<4;i++) { + device_t *disk = apple525_get_subdevice(device, i); + if (floppy_get_drive_type(disk)==ftype) { + if (cnt==drive) { + return disk; + } + cnt++; + } + } + return NULL; +} + +void apple525_set_enable_lines(device_t *device,int enable_mask) +{ + apple525_enable_mask = enable_mask; +} + +/* ----------------------------------------------------------------------- */ + +static void apple525_load_current_track(device_t *image) +{ + int len; + apple525_floppy_image_device *disk; + + disk = get_device(image); + len = sizeof(disk->track_data); + + floppy_drive_read_track_data_info_buffer(image, 0, disk->track_data, &len); + disk->track_loaded = 1; + disk->track_dirty = 0; +} + +static void apple525_save_current_track(device_t *image, int unload) +{ + int len; + apple525_floppy_image_device *disk; + + disk = get_device(image); + + if (disk->track_dirty) + { + len = sizeof(disk->track_data); + floppy_drive_write_track_data_info_buffer(image, 0, disk->track_data, &len); + disk->track_dirty = 0; + } + if (unload) + disk->track_loaded = 0; +} + +static void apple525_seek_disk(device_t *img, signed int step) +{ + int track; + int pseudo_track; + apple525_floppy_image_device *disk; + + disk = get_device(img); + + apple525_save_current_track(img, FALSE); + + track = floppy_drive_get_current_track(img); + pseudo_track = (track * 2) + disk->tween_tracks; + + pseudo_track += step; + if (pseudo_track < 0) + pseudo_track = 0; + else if (pseudo_track/2 >= APPLE2_TRACK_COUNT) + pseudo_track = APPLE2_TRACK_COUNT*2-1; + + if (pseudo_track/2 != track) + { + floppy_drive_seek(img, pseudo_track/2 - floppy_drive_get_current_track(img)); + disk->track_loaded = 0; + } + + if (pseudo_track & 1) + disk->tween_tracks = 1; + else + disk->tween_tracks = 0; +} + +static void apple525_disk_set_lines(device_t *device,device_t *image, UINT8 new_state) +{ + apple525_floppy_image_device *cur_disk; + UINT8 old_state; + unsigned int phase; + + cur_disk = get_device(image); + + old_state = cur_disk->state; + cur_disk->state = new_state; + + if ((new_state & 0x0F) > (old_state & 0x0F)) + { + phase = 0; + switch((old_state ^ new_state) & 0x0F) + { + case 1: phase = 0; break; + case 2: phase = 1; break; + case 4: phase = 2; break; + case 8: phase = 3; break; + } + + phase -= floppy_drive_get_current_track(image) * 2; + if (cur_disk->tween_tracks) + phase--; + phase %= 4; + + switch(phase) + { + case 1: + apple525_seek_disk(image, +1); + break; + case 3: + apple525_seek_disk(image, -1); + break; + } + } +} + +int apple525_get_count(device_t *device) +{ + int cnt = 0; + if ((device->subdevice("^"FLOPPY_0)!=NULL) && (floppy_get_drive_type(device->subdevice("^"FLOPPY_0)) == FLOPPY_TYPE_APPLE) && (get_device(device->subdevice(PARENT_FLOPPY_0))!=NULL)) cnt++; + if ((device->subdevice("^"FLOPPY_1)!=NULL) && (floppy_get_drive_type(device->subdevice("^"FLOPPY_1)) == FLOPPY_TYPE_APPLE) && (get_device(device->subdevice(PARENT_FLOPPY_1))!=NULL)) cnt++; + if ((device->subdevice("^"FLOPPY_2)!=NULL) && (floppy_get_drive_type(device->subdevice("^"FLOPPY_2)) == FLOPPY_TYPE_APPLE) && (get_device(device->subdevice(PARENT_FLOPPY_2))!=NULL)) cnt++; + if ((device->subdevice("^"FLOPPY_3)!=NULL) && (floppy_get_drive_type(device->subdevice("^"FLOPPY_3)) == FLOPPY_TYPE_APPLE) && (get_device(device->subdevice(PARENT_FLOPPY_3))!=NULL)) cnt++; + + return cnt; +} + +void apple525_set_lines(device_t *device, UINT8 lines) +{ + int i, count; + device_t *image; + + count = apple525_get_count(device); + for (i = 0; i < count; i++) + { + if (apple525_enable_mask & (1 << i)) + { + image = apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i); + if (image) + apple525_disk_set_lines(device,image, lines); + } + } +} + +/* reads/writes a byte; write_value is -1 for read only */ +static UINT8 apple525_process_byte(device_t *img, int write_value) +{ + UINT8 read_value; + apple525_floppy_image_device *disk; + int spinfract_divisor; + int spinfract_dividend; + apple525_floppy_image_device *config = get_device(img); + device_image_interface *image = dynamic_cast<device_image_interface *>(img); + + disk = get_device(img); + spinfract_dividend = config->get_dividend(); + spinfract_divisor = config->get_divisor(); + + /* no image initialized for that drive ? */ + if (!image->exists()) + return 0xFF; + + /* check the spin count if reading*/ + if (write_value < 0) + { + disk->spin_count++; + disk->spin_count %= spinfract_divisor; + if (disk->spin_count >= spinfract_dividend) + return 0x00; + } + + /* load track if need be */ + if (disk->track_loaded == 0) + apple525_load_current_track(img); + + /* perform the read */ + read_value = disk->track_data[disk->position]; + + /* perform the write, if applicable */ + if (write_value >= 0) + { + disk->track_data[disk->position] = write_value; + disk->track_dirty = 1; + } + + disk->position++; + disk->position %= ARRAY_LENGTH(disk->track_data); + + /* when writing; save the current track after every full sector write */ + if ((write_value >= 0) && ((disk->position % APPLE2_NIBBLE_SIZE) == 0)) + apple525_save_current_track(img, FALSE); + + return read_value; +} + +static device_t *apple525_selected_image(device_t *device) +{ + int i,count; + + count = apple525_get_count(device); + + for (i = 0; i < count; i++) + { + if (apple525_enable_mask & (1 << i)) + return apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i); + } + return NULL; +} + +UINT8 apple525_read_data(device_t *device) +{ + device_t *image; + image = apple525_selected_image(device); + return image ? apple525_process_byte(image, -1) : 0xFF; +} + +void apple525_write_data(device_t *device,UINT8 data) +{ + device_t *image; + image = apple525_selected_image(device); + if (image) + apple525_process_byte(image, data); +} + +int apple525_read_status(device_t *device) +{ + int i, count, result = 0; + device_image_interface *image; + + count = apple525_get_count(device); + + for (i = 0; i < count; i++) + { + if (apple525_enable_mask & (1 << i)) + { + image = dynamic_cast<device_image_interface *>(apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i)); + if (image && image->is_readonly()) + result = 1; + } + } + return result; +} + +// device type definition +const device_type FLOPPY_APPLE = &device_creator<apple525_floppy_image_device>; + +//------------------------------------------------- +// apple525_floppy_image_device - constructor +//------------------------------------------------- + +apple525_floppy_image_device::apple525_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : legacy_floppy_image_device(mconfig, FLOPPY_APPLE, "Apple Disk II", tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apple525_floppy_image_device::device_start() +{ + legacy_floppy_image_device::device_start(); + floppy_set_type(this,FLOPPY_TYPE_APPLE); + + state = 0; + tween_tracks = 0; + track_loaded = 0; + track_dirty = 0; + position = 0; + spin_count = 0; + memset(track_data, 0, sizeof(track_data)); +} + +bool apple525_floppy_image_device::call_load() +{ + int result = legacy_floppy_image_device::call_load(); + floppy_drive_seek(*this, -999); + floppy_drive_seek(*this, +35/2); + return result; +} + +void apple525_floppy_image_device::call_unload() +{ + apple525_save_current_track(this, TRUE); + + legacy_floppy_image_device::call_unload(); +} |