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 | |
parent | b25a1c367a3409865f2b049851a0235526b96978 (diff) |
Moved some mess devices to proper place (nw)
Diffstat (limited to 'src/mess/machine')
-rw-r--r-- | src/mess/machine/a2diskii.c | 2 | ||||
-rw-r--r-- | src/mess/machine/appldriv.c | 334 | ||||
-rw-r--r-- | src/mess/machine/appldriv.h | 86 | ||||
-rw-r--r-- | src/mess/machine/apple2.c | 4 | ||||
-rw-r--r-- | src/mess/machine/apple3.c | 2 | ||||
-rw-r--r-- | src/mess/machine/microdrv.c | 203 | ||||
-rw-r--r-- | src/mess/machine/microdrv.h | 103 | ||||
-rw-r--r-- | src/mess/machine/sonydriv.c | 571 | ||||
-rw-r--r-- | src/mess/machine/sonydriv.h | 70 | ||||
-rw-r--r-- | src/mess/machine/zx8302.c | 2 |
10 files changed, 1372 insertions, 5 deletions
diff --git a/src/mess/machine/a2diskii.c b/src/mess/machine/a2diskii.c index ab2d93cc52a..f9dce090dc7 100644 --- a/src/mess/machine/a2diskii.c +++ b/src/mess/machine/a2diskii.c @@ -10,7 +10,7 @@ #include "includes/apple2.h" #include "imagedev/flopdrv.h" #include "formats/ap2_dsk.h" -#include "devices/appldriv.h" +#include "machine/appldriv.h" #include "machine/applefdc.h" #include "machine/a2diskii.h" 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(); +} diff --git a/src/mess/machine/appldriv.h b/src/mess/machine/appldriv.h new file mode 100644 index 00000000000..29cf2759aa0 --- /dev/null +++ b/src/mess/machine/appldriv.h @@ -0,0 +1,86 @@ +/********************************************************************* + + appldriv.h + + Apple 5.25" floppy drive emulation (to be interfaced with applefdc.c) + +*********************************************************************/ + +#ifndef APPLDRIV_H +#define APPLDRIV_H + +#include "emu.h" +#include "imagedev/flopdrv.h" +#include "formats/ap2_dsk.h" + +void apple525_set_lines(device_t *device,UINT8 lines); +void apple525_set_enable_lines(device_t *device,int enable_mask); + +UINT8 apple525_read_data(device_t *device); +void apple525_write_data(device_t *device,UINT8 data); +int apple525_read_status(device_t *device); +int apple525_get_count(running_machine &machine); + +class apple525_floppy_image_device : public legacy_floppy_image_device +{ +public: + // construction/destruction + apple525_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual bool call_load(); + virtual void call_unload(); + void set_params(int dividend, int divisor) { m_dividend = dividend; m_divisor = divisor;} + + int get_dividend() { return m_dividend; } + int get_divisor() { return m_divisor; } + + // these elements should be private, but are not yet + unsigned int state : 4; /* bits 0-3 are the phase */ + unsigned int tween_tracks : 1; + unsigned int track_loaded : 1; + unsigned int track_dirty : 1; + int position; + int spin_count; /* simulate drive spin to fool RWTS test at $BD34 */ + UINT8 track_data[APPLE2_NIBBLE_SIZE * APPLE2_SECTOR_COUNT]; + +protected: + virtual void device_start(); + +private: + int m_dividend; + int m_divisor; +}; + +// device type definition +extern const device_type FLOPPY_APPLE; + +#define MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + downcast<apple525_floppy_image_device *>(device)->set_params(_dividend,_divisor); + +#define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_ADD(_config,_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) + +#define MCFG_LEGACY_FLOPPY_APPLE_4_DRIVES_ADD(_config,_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ + MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY_APPLE, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) + +#define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_REMOVE() \ + MCFG_DEVICE_REMOVE(FLOPPY_0) \ + MCFG_DEVICE_REMOVE(FLOPPY_1) + +#endif /* APPLDRIV_H */ diff --git a/src/mess/machine/apple2.c b/src/mess/machine/apple2.c index 4e02a320424..8e428d77bee 100644 --- a/src/mess/machine/apple2.c +++ b/src/mess/machine/apple2.c @@ -15,8 +15,8 @@ #include "machine/a2bus.h" #include "machine/ay3600.h" #include "machine/applefdc.h" -#include "devices/sonydriv.h" -#include "devices/appldriv.h" +#include "machine/sonydriv.h" +#include "machine/appldriv.h" #include "imagedev/flopdrv.h" #include "imagedev/cassette.h" #include "sound/speaker.h" diff --git a/src/mess/machine/apple3.c b/src/mess/machine/apple3.c index 55ec3a6f90b..7843c322c14 100644 --- a/src/mess/machine/apple3.c +++ b/src/mess/machine/apple3.c @@ -20,7 +20,7 @@ #include "machine/6522via.h" #include "machine/ay3600.h" #include "machine/applefdc.h" -#include "devices/appldriv.h" +#include "machine/appldriv.h" #include "machine/mos6551.h" #include "machine/ram.h" diff --git a/src/mess/machine/microdrv.c b/src/mess/machine/microdrv.c new file mode 100644 index 00000000000..fb3e43fed72 --- /dev/null +++ b/src/mess/machine/microdrv.c @@ -0,0 +1,203 @@ +/********************************************************************* + + microdrv.c + + MESS interface to the Sinclair Microdrive image abstraction code + +*********************************************************************/ + +#include "emu.h" +#include "microdrv.h" + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define LOG 1 + +#define MDV_SECTOR_COUNT 255 +#define MDV_SECTOR_LENGTH 686 +#define MDV_IMAGE_LENGTH (MDV_SECTOR_COUNT * MDV_SECTOR_LENGTH) + +#define MDV_PREAMBLE_LENGTH 12 +#define MDV_GAP_LENGTH 120 + +#define MDV_OFFSET_HEADER_PREAMBLE 0 +#define MDV_OFFSET_HEADER MDV_OFFSET_HEADER_PREAMBLE + MDV_PREAMBLE_LENGTH +#define MDV_OFFSET_DATA_PREAMBLE 28 +#define MDV_OFFSET_DATA MDV_OFFSET_DATA_PREAMBLE + MDV_PREAMBLE_LENGTH +#define MDV_OFFSET_GAP 566 + +#define MDV_BITRATE 120000 // invalid, from ZX microdrive + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +// device type definition +const device_type MICRODRIVE = &device_creator<microdrive_image_device>; + +//------------------------------------------------- +// microdrive_image_device - constructor +//------------------------------------------------- + +microdrive_image_device::microdrive_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, MICRODRIVE, "Microdrive", tag, owner, clock), + device_image_interface(mconfig, *this) +{ +} + +//------------------------------------------------- +// microdrive_image_device - destructor +//------------------------------------------------- + +microdrive_image_device::~microdrive_image_device() +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void microdrive_image_device::device_config_complete() +{ + // inherit a copy of the static data + const microdrive_interface *intf = reinterpret_cast<const microdrive_interface *>(static_config()); + if (intf != NULL) + *static_cast<microdrive_interface *>(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_comms_out_cb, 0, sizeof(m_out_comms_out_cb)); + memset(&m_interface, 0, sizeof(m_interface)); + memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo)); + } + + // set brief and instance name + update_names(); +} + + +void microdrive_image_device::device_start() +{ + // resolve callbacks + m_out_comms_out_func.resolve(m_out_comms_out_cb, *this); + + // allocate track buffers + m_left = auto_alloc_array(machine(), UINT8, MDV_IMAGE_LENGTH / 2); + m_right = auto_alloc_array(machine(), UINT8, MDV_IMAGE_LENGTH / 2); + + // allocate timers + m_bit_timer = timer_alloc(); + m_bit_timer->adjust(attotime::zero, 0, attotime::from_hz(MDV_BITRATE)); + m_bit_timer->enable(0); +} + +bool microdrive_image_device::call_load() +{ + if (length() != MDV_IMAGE_LENGTH) + return IMAGE_INIT_FAIL; + + for (int i = 0; i < MDV_IMAGE_LENGTH / 2; i++) + { + fread(m_left, 1); + fread(m_right, 1); + } + + m_bit_offset = 0; + m_byte_offset = 0; + + return IMAGE_INIT_PASS; +} + +void microdrive_image_device::call_unload() +{ + memset(m_left, 0, MDV_IMAGE_LENGTH / 2); + memset(m_right, 0, MDV_IMAGE_LENGTH / 2); +} + +void microdrive_image_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + m_bit_offset++; + + if (m_bit_offset == 8) + { + m_bit_offset = 0; + m_byte_offset++; + + if (m_byte_offset == MDV_IMAGE_LENGTH) + { + m_byte_offset = 0; + } + } +} + +WRITE_LINE_MEMBER( microdrive_image_device::clk_w ) +{ + if (LOG) logerror("Microdrive '%s' CLK: %u\n", tag(), state); + if (!m_clk && state) + { + m_comms_out = m_comms_in; + if (LOG) logerror("Microdrive '%s' COMMS OUT: %u\n", tag(), m_comms_out); + m_out_comms_out_func(m_comms_out); + m_bit_timer->enable(m_comms_out); + } + m_clk = state; +} + +WRITE_LINE_MEMBER( microdrive_image_device::comms_in_w ) +{ + if (LOG) logerror("Microdrive '%s' COMMS IN: %u\n", tag(), state); + m_comms_in = state; +} + +WRITE_LINE_MEMBER( microdrive_image_device::erase_w ) +{ + if (LOG) logerror("Microdrive '%s' ERASE: %u\n", tag(), state); + m_erase = state; +} + +WRITE_LINE_MEMBER( microdrive_image_device::read_write_w ) +{ + if (LOG) logerror("Microdrive '%s' READ/WRITE: %u\n", tag(), state); + m_read_write = state; +} + +WRITE_LINE_MEMBER( microdrive_image_device::data1_w ) +{ + if (m_comms_out && !m_read_write) + { + // TODO + } +} + +WRITE_LINE_MEMBER( microdrive_image_device::data2_w ) +{ + if (m_comms_out && !m_read_write) + { + // TODO + } +} + +READ_LINE_MEMBER( microdrive_image_device::data1_r ) +{ + int data = 0; + if (m_comms_out && m_read_write) + { + data = BIT(m_left[m_byte_offset], 7 - m_bit_offset); + } + return data; +} + +READ_LINE_MEMBER( microdrive_image_device::data2_r ) +{ + int data = 0; + if (m_comms_out && m_read_write) + { + data = BIT(m_right[m_byte_offset], 7 - m_bit_offset); + } + return data; +} diff --git a/src/mess/machine/microdrv.h b/src/mess/machine/microdrv.h new file mode 100644 index 00000000000..65cd535f458 --- /dev/null +++ b/src/mess/machine/microdrv.h @@ -0,0 +1,103 @@ +/********************************************************************* + + microdrv.h + + MESS interface to the Sinclair Microdrive image abstraction code + +*********************************************************************/ + +#pragma once + +#ifndef __MICRODRV__ +#define __MICRODRV__ + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ +// ======================> microdrive_interface + +struct microdrive_interface +{ + devcb_write_line m_out_comms_out_cb; + const char * m_interface; + device_image_display_info_func m_device_displayinfo; +}; + +// ======================> microdrive_image_device + +class microdrive_image_device : public device_t, + public microdrive_interface, + public device_image_interface +{ +public: + // construction/destruction + microdrive_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~microdrive_image_device(); + + // image-level overrides + virtual bool call_load(); + virtual void call_unload(); + virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); } + virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { return load_software(swlist, swname, start_entry); } + + virtual iodevice_t image_type() const { return IO_CASSETTE; } + + virtual bool is_readable() const { return 1; } + virtual bool is_writeable() const { return 1; } + virtual bool is_creatable() const { return 0; } + virtual bool must_be_loaded() const { return 0; } + virtual bool is_reset_on_load() const { return 0; } + virtual const char *image_interface() const { return "ql_cass"; } + virtual const char *file_extensions() const { return "mdv"; } + virtual const option_guide *create_option_guide() const { return NULL; } + + // specific implementation + DECLARE_WRITE_LINE_MEMBER( clk_w ); + DECLARE_WRITE_LINE_MEMBER( comms_in_w ); + DECLARE_WRITE_LINE_MEMBER( erase_w ); + DECLARE_WRITE_LINE_MEMBER( read_write_w ); + DECLARE_WRITE_LINE_MEMBER( data1_w ); + DECLARE_WRITE_LINE_MEMBER( data2_w ); + DECLARE_READ_LINE_MEMBER ( data1_r ); + DECLARE_READ_LINE_MEMBER ( data2_r ); +protected: + // device-level overrides + virtual void device_config_complete(); + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); +private: + devcb_resolved_write_line m_out_comms_out_func; + + int m_clk; + int m_comms_in; + int m_comms_out; + int m_erase; + int m_read_write; + + UINT8 *m_left; + UINT8 *m_right; + + int m_bit_offset; + int m_byte_offset; + + emu_timer *m_bit_timer; +}; + +// device type definition +extern const device_type MICRODRIVE; + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MDV_1 "mdv1" +#define MDV_2 "mdv2" + +#define MCFG_MICRODRIVE_ADD(_tag, _config) \ + MCFG_DEVICE_ADD(_tag, MICRODRIVE, 0) \ + MCFG_DEVICE_CONFIG(_config) + +#define MICRODRIVE_CONFIG(_name) \ + const microdrive_interface (_name) = + +#endif diff --git a/src/mess/machine/sonydriv.c b/src/mess/machine/sonydriv.c new file mode 100644 index 00000000000..8424473ada1 --- /dev/null +++ b/src/mess/machine/sonydriv.c @@ -0,0 +1,571 @@ +/********************************************************************* + + sonydriv.c + + Apple/Sony 3.5" floppy drive emulation (to be interfaced with iwm.c) + + Nate Woods, Raphael Nabet, R. Belmont + + This floppy drive was present in all variants of Lisa 2 (including Mac XL), + all Apple IIgs and IIc Plus machines, and in all Macintoshes in production + before 1988, when SWIM and SuperDrive were introduced. + + There were three major variants : + - A single-sided 400k unit which was used on Lisa 2/Mac XL, and Macintosh + 128k/512k. This unit needs the computer to send the proper pulses to + control the drive motor rotation. It can be connected to all early + Macintosh (but not Mac Classic?) as an external unit. + - A double-sided 800k unit which was used on Macintosh Plus, 512ke, and + early SE and II*. This unit generates its own drive motor rotation + control signals. It can be connected to earlier (and later) Macintosh as + an external or internal unit. Some Lisa2/10 and Mac XL were upgraded to + use it, too, but a fdc ROM upgrade was required. + - A double-sided 1440k unit. This is fully back compatible with the 800k + drive, and adds 1440k MFM capability. This drive, called FDHD or + SuperDrive by Apple, came in automatic and manual-inject versions. + + TODO : + * support for other image formats? + * should we support more than 2 floppy disk units? (Mac SE supported 3 drives) + +*********************************************************************/ + +#include "emu.h" +#include "machine/applefdc.h" +#include "sonydriv.h" +#include "formats/ap_dsk35.h" +#include "imagedev/flopdrv.h" + + +#ifdef MAME_DEBUG +#define LOG_SONY 1 +#define LOG_SONY_EXTRA 0 +#else +#define LOG_SONY 0 +#define LOG_SONY_EXTRA 0 +#endif + +/* + These lines are normally connected to the PHI0-PHI3 lines of the IWM +*/ +enum +{ + SONY_CA0 = 0x01, + SONY_CA1 = 0x02, + SONY_CA2 = 0x04, + SONY_LSTRB = 0x08 +}; + +/* + Structure that describes the state of a floppy drive, and the associated + disk image +*/ +struct floppy_t +{ + device_t *img; + emu_file *fd; + + unsigned int disk_switched : 1; /* disk-in-place status bit */ + unsigned int head : 1; /* active head (-> floppy side) */ + unsigned int step : 1; + int motor_on; + + unsigned int loadedtrack_valid : 1; /* is data in track buffer valid ? */ + unsigned int loadedtrack_dirty : 1; /* has data in track buffer been modified? */ + size_t loadedtrack_size; /* size of loaded track */ + size_t loadedtrack_pos; /* position within loaded track */ + UINT8 *loadedtrack_data; /* pointer to track buffer */ + + int is_fdhd; /* is drive an FDHD? */ + int is_400k; /* drive is single-sided, which means 400K */ +}; + +struct sonydriv_t +{ + int lines; /* four lines SONY_CA0 - SONY_LSTRB */ + + int floppy_enable; /* whether a drive is enabled or not (-> enable line) */ + int floppy_select; /* which drive is enabled */ + + int sel_line; /* one single line Is 0 or 1 */ + + unsigned int rotation_speed; /* drive rotation speed - ignored if ext_speed_control == 0 */ + floppy_t floppy[2]; /* data for two floppy disk units */ +}; +static sonydriv_t sony; + +/* bit of code used in several places - I am unsure why it is here */ +static int sony_enable2(void) +{ + return (sony.lines & SONY_CA1) && (sony.lines & SONY_LSTRB); +} + +static void load_track_data(device_t *device,int floppy_select) +{ + int track_size; + device_image_interface *cur_image; + UINT8 *new_data; + floppy_t *f; + + f = &sony.floppy[floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, floppy_select)); + + floppy_image_legacy *fimg = flopimg_get_image(&cur_image->device()); + + if (!fimg) + { + return; + } + + track_size = floppy_get_track_size(fimg, f->head, floppy_drive_get_current_track(&cur_image->device())); + if (f->loadedtrack_data) auto_free(device->machine(),f->loadedtrack_data); + new_data = auto_alloc_array(device->machine(),UINT8,track_size); + if (!new_data) + { + return; + } + + floppy_drive_read_track_data_info_buffer(&cur_image->device(), f->head, new_data, &track_size); + f->loadedtrack_valid = 1; + f->loadedtrack_dirty = 0; + f->loadedtrack_size = track_size; + f->loadedtrack_data = new_data; + f->loadedtrack_pos = 0; +} + + + +static void save_track_data(device_t *device, int floppy_select) +{ + device_image_interface *cur_image; + floppy_t *f; + int len; + + f = &sony.floppy[floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, floppy_select)); + + if (f->loadedtrack_dirty) + { + len = f->loadedtrack_size; + floppy_drive_write_track_data_info_buffer(&cur_image->device(), f->head, f->loadedtrack_data, &len); + f->loadedtrack_dirty = 0; + } +} + + + +UINT8 sony_read_data(device_t *device) +{ + UINT8 result = 0; + device_image_interface *cur_image; + floppy_t *f; + + if (sony_enable2() || (! sony.floppy_enable)) + return 0xFF; /* right ??? */ + + f = &sony.floppy[sony.floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); + if (!cur_image->exists()) + return 0xFF; + + if (!f->loadedtrack_valid) + load_track_data(device, sony.floppy_select); + + if (!f->loadedtrack_data) + { + return 0xFF; + } + + result = sony_fetchtrack(f->loadedtrack_data, f->loadedtrack_size, &f->loadedtrack_pos); + return result; +} + + + +void sony_write_data(device_t *device,UINT8 data) +{ + device_image_interface *cur_image; + floppy_t *f; + + f = &sony.floppy[sony.floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); + if (!cur_image->exists()) + return; + + if (!f->loadedtrack_valid) + load_track_data(device,sony.floppy_select); + + if (!f->loadedtrack_data) + { + return; + } + + sony_filltrack(f->loadedtrack_data, f->loadedtrack_size, &f->loadedtrack_pos, data); + f->loadedtrack_dirty = 1; +} + + + +static int sony_rpm(floppy_t *f, device_t *cur_image) +{ + int result = 0; + device_image_interface *image =dynamic_cast<device_image_interface *>(cur_image); + /* + * The Mac floppy controller was interesting in that its speed was adjusted + * while the thing was running. On the tracks closer to the rim, it was + * sped up so that more data could be placed on it. Hence, this function + * has different results depending on the track number + * + * The Mac Plus (and probably the other Macs that use the IWM) verify that + * the speed of the floppy drive is within a certain range depending on + * what track the floppy is at. These RPM values are just guesses and are + * probably not fully accurate, but they are within the range that the Mac + * Plus expects and thus are probably in the right ballpark. + * + * Note - the timing values are the values returned by the Mac Plus routine + * that calculates the speed; I'm not sure what units they are in + */ + + if ((f->is_400k) && (sony.rotation_speed)) + { + /* 400k unit : rotation speed should be controlled by computer */ + result = sony.rotation_speed; + } + else + { /* 800k unit : rotation speed controlled by drive */ +#if 1 /* Mac Plus */ + static const int speeds[] = + { + 500, /* 00-15: timing value 117B (acceptable range {1135-11E9} */ + 550, /* 16-31: timing value ???? (acceptable range {12C6-138A} */ + 600, /* 32-47: timing value ???? (acceptable range {14A7-157F} */ + 675, /* 48-63: timing value ???? (acceptable range {16F2-17E2} */ + 750 /* 64-79: timing value ???? (acceptable range {19D0-1ADE} */ + }; +#else /* Lisa 2 */ + /* 237 + 1.3*(256-reg) */ + static const int speeds[] = + { + 293, /* 00-15: timing value ???? (acceptable range {0330-0336} */ + 322, /* 16-31: timing value ???? (acceptable range {02ED-02F3} */ + 351, /* 32-47: timing value ???? (acceptable range {02A7-02AD} */ + 394, /* 48-63: timing value ???? (acceptable range {0262-0266} */ + 439 /* 64-79: timing value ???? (acceptable range {021E-0222} */ + }; +#endif + if (cur_image && image->exists()) + result = speeds[floppy_drive_get_current_track(cur_image) / 16]; + } + return result; +} + +int sony_read_status(device_t *device) +{ + int result = 1; + int action; + floppy_t *f; + device_image_interface *cur_image; + + action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); + + if (LOG_SONY_EXTRA) + { + printf("sony.status(): action=%x pc=0x%08x%s\n", + action, (int) device->machine().firstcpu->pc(), sony.floppy_enable ? "" : " (no drive enabled)"); + } + + if ((! sony_enable2()) && sony.floppy_enable) + { + f = &sony.floppy[sony.floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); + if (!cur_image->exists()) + cur_image = NULL; + + switch(action) { + case 0x00: /* Step direction */ + result = f->step; + break; + case 0x01: /* Lower head activate */ + if (f->head != 0) + { + save_track_data(device,sony.floppy_select); + f->head = 0; + f->loadedtrack_valid = 0; + } + result = 0; + break; + case 0x02: /* Disk in place */ + result = cur_image ? 0 : 1; /* 0=disk 1=nodisk */ + break; + case 0x03: /* Upper head activate (not on 400k) */ + if ((f->head != 1) && !(f->is_400k)) + { + save_track_data(device,sony.floppy_select); + f->head = 1; + f->loadedtrack_valid = 0; + } + result = 0; + break; + case 0x04: /* Disk is stepping 0=stepping 1=not stepping*/ + result = 1; + break; + case 0x05: /* Drive is SuperDrive: 0 = 400/800k, 1 = SuperDrive */ + result = f->is_fdhd ? 1: 0; + break; + case 0x06: /* Disk is locked 0=locked 1=unlocked */ + if (cur_image) + result = floppy_wpt_r(&cur_image->device()); + else + result = 0; + break; + case 0x08: /* Motor on 0=on 1=off */ + result = f->motor_on; + break; + case 0x09: /* Number of sides: 0=single sided, 1=double sided */ + if (cur_image) + { + floppy_image_legacy *fimg = flopimg_get_image(&cur_image->device()); + if (fimg) + { + result = floppy_get_heads_per_disk(fimg) - 1; + f->is_400k = result ? 0 : 1; + } + } + break; + case 0x0a: /* At track 0: 0=track zero 1=not track zero */ + logerror("sony.status(): reading Track 0 pc=0x%08x\n", (int) device->machine().firstcpu->pc()); + if (cur_image) + result = floppy_tk00_r(&cur_image->device()); + else + result = 0; + break; + case 0x0b: /* Disk ready: 0=ready, 1=not ready */ + result = 0; + break; + case 0x0c: /* Disk switched */ + { + if (cur_image) + { + if (!floppy_dskchg_r(&cur_image->device())) + { + f->disk_switched = 1; + } + } + result = f->disk_switched; + } + break; + case 0x0d: /* Unknown */ + /* I'm not sure what this one does, but the Mac Plus executes the + * following code that uses this status: + * + * 417E52: moveq #$d, D0 ; Status 0x0d + * 417E54: bsr 4185fe ; Query IWM status + * 417E58: bmi 417e82 ; If result=1, then skip + * + * This code is called in the Sony driver's open method, and + * _AddDrive does not get called if this status 0x0d returns 1. + * Hence, we are returning 0 + */ + result = 0; + break; + case 0x0e: /* Tachometer */ + /* (time in seconds) / (60 sec/minute) * (rounds/minute) * (60 pulses) * (2 pulse phases) */ + if (cur_image) + { + result = ((int) (device->machine().time().as_double() / 60.0 * sony_rpm(f, &cur_image->device()) * 60.0 * 2.0)) & 1; + } + break; + case 0x0f: /* 400k/800k: Drive installed: 0=drive connected, 1=drive not connected */ + /* FDHD: Inserted disk density: 0=HD, 1=DD */ + if (f->is_fdhd) + { + result = 1; + } + else + { + result = 0; + } + break; + default: + if (LOG_SONY) + logerror("sony_status(): unknown action\n"); + break; + } + } + + return result; +} + +static void sony_doaction(device_t *device) +{ + int action; + floppy_t *f; + device_image_interface *cur_image; + + action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | ((sony.lines & SONY_CA2) >> 2) | (sony.sel_line << 1); + + if (LOG_SONY) + { + logerror("sony_doaction(): action=%d pc=0x%08x%s\n", + action, (int) device->machine().firstcpu->pc(), (sony.floppy_enable) ? "" : " (MOTOR OFF)"); + } + + if (sony.floppy_enable) + { + f = &sony.floppy[sony.floppy_select]; + cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); + if (!cur_image->exists()) + cur_image = NULL; + + switch(action) + { + case 0x00: /* Set step inward (higher tracks) */ + f->step = 0; + break; + case 0x01: /* Set step outward (lower tracks) */ + f->step = 1; + break; + case 0x03: /* Reset diskswitched */ + f->disk_switched = 0; + break; + case 0x04: /* Step disk */ + if (cur_image) + { + save_track_data(device,sony.floppy_select); + if (f->step) + floppy_drive_seek(&cur_image->device(), -1); + else + floppy_drive_seek(&cur_image->device(), +1); + f->loadedtrack_valid = 0; + } + break; + case 0x08: /* Turn motor on */ + f->motor_on = CLEAR_LINE; + if (cur_image) + floppy_mon_w(&cur_image->device(), f->motor_on); + break; + case 0x09: /* Turn motor off */ + f->motor_on = ASSERT_LINE; + if (cur_image) + floppy_mon_w(&cur_image->device(), f->motor_on); + break; + case 0x0d: /* Eject disk */ + if (cur_image) + cur_image->unload(); + break; + default: + if (LOG_SONY) + logerror("sony_doaction(): unknown action %d\n", action); + break; + } + } +} + +void sony_set_lines(device_t *device,UINT8 lines) +{ + int old_sony_lines = sony.lines; + + sony.lines = lines & 0x0F; + + { + //int action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); + //printf("sony.set_lines: %02x, action now %d\n", lines&0xf, action); + } + + /* have we just set LSTRB ? */ + if ((sony.lines & ~old_sony_lines) & SONY_LSTRB) + { + /* if so, write drive reg */ + sony_doaction(device); + } + + if (LOG_SONY_EXTRA) + logerror("sony.set_lines(): %d\n", lines); +} + +void sony_set_enable_lines(device_t *device,int enable_mask) +{ + switch (enable_mask) + { + case 0: + default: /* well, we have to do something, right ? */ + sony.floppy_enable = 0; + break; + case 1: + sony.floppy_enable = 1; + sony.floppy_select = 0; + break; + case 2: + sony.floppy_enable = 1; + sony.floppy_select = 1; + break; + } + + if (LOG_SONY_EXTRA) + logerror("sony.set_enable_lines(): %d\n", enable_mask); +} + +void sony_set_sel_line(device_t *device,int sel) +{ + sony.sel_line = sel ? 1 : 0; + + { + //int action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); + //printf("sony.set_sel_line: %d, action now %d\n", sony.sel_line, action); + } + + if (LOG_SONY_EXTRA) + logerror("sony.set_sel_line(): %s line IWM_SEL\n", sony.sel_line ? "setting" : "clearing"); +} + +void sony_set_speed(int speed) +{ + sony.rotation_speed = speed; +} + +// device type definition +const device_type FLOPPY_SONY = &device_creator<sonydriv_floppy_image_device>; + +//------------------------------------------------- +// sonydriv_floppy_image_device - constructor +//------------------------------------------------- + +sonydriv_floppy_image_device::sonydriv_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : legacy_floppy_image_device(mconfig, FLOPPY_SONY, "Floppy Disk [Sony]", tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sonydriv_floppy_image_device::device_start() +{ + legacy_floppy_image_device::device_start(); + floppy_set_type(this, FLOPPY_TYPE_SONY); + + sony.floppy[0].is_fdhd = 0; + sony.floppy[1].is_fdhd = 0; + sony.floppy[0].is_400k = 0; + sony.floppy[1].is_400k = 0; + sony.floppy[0].loadedtrack_data = NULL; + sony.floppy[1].loadedtrack_data = NULL; + sony.floppy[0].head = 0; + sony.floppy[1].head = 0; + sony.rotation_speed = 0; +} + +void sonydriv_floppy_image_device::call_unload() +{ + int id; + device_t *fdc; + + /* locate the FDC */ + fdc = machine().device("fdc"); + + id = floppy_get_drive_by_type(this,FLOPPY_TYPE_SONY); + save_track_data(fdc, id); + memset(&sony.floppy[id], 0, sizeof(sony.floppy[id])); + + legacy_floppy_image_device::call_unload(); +} diff --git a/src/mess/machine/sonydriv.h b/src/mess/machine/sonydriv.h new file mode 100644 index 00000000000..059a33238cd --- /dev/null +++ b/src/mess/machine/sonydriv.h @@ -0,0 +1,70 @@ +/********************************************************************* + + sonydriv.h + + Apple/Sony 3.5" floppy drive emulation (to be interfaced with applefdc.c) + +*********************************************************************/ + +#ifndef SONYDRIV_H +#define SONYDRIV_H + +#include "image.h" +#include "imagedev/flopdrv.h" + +#if 0 +enum +{ + SONY_FLOPPY_ALLOW400K = 0x0001, + SONY_FLOPPY_ALLOW800K = 0x0002, + + SONY_FLOPPY_SUPPORT2IMG = 0x4000, + SONY_FLOPPY_EXT_SPEED_CONTROL = 0x8000 // means the speed is controlled by computer +}; +#endif + +void sony_set_lines(device_t *device,UINT8 lines); +void sony_set_enable_lines(device_t *device,int enable_mask); +void sony_set_sel_line(device_t *device,int sel); + +void sony_set_speed(int speed); + +UINT8 sony_read_data(device_t *device); +void sony_write_data(device_t *device,UINT8 data); +int sony_read_status(device_t *device); + +class sonydriv_floppy_image_device : public legacy_floppy_image_device +{ +public: + // construction/destruction + sonydriv_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual void call_unload(); +protected: + virtual void device_start(); +}; + +// device type definition +extern const device_type FLOPPY_SONY; + +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_ADD(_config) \ + MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_SONY, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_SONY, 0) \ + MCFG_DEVICE_CONFIG(_config) + +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_ADDITIONAL_ADD(_config) \ + MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY_SONY, 0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY_SONY, 0) \ + MCFG_DEVICE_CONFIG(_config) + +#define MCFG_LEGACY_FLOPPY_SONY_2_DRIVES_MODIFY(_config) \ + MCFG_DEVICE_MODIFY(FLOPPY_0) \ + MCFG_DEVICE_CONFIG(_config) \ + MCFG_DEVICE_MODIFY(FLOPPY_1) \ + MCFG_DEVICE_CONFIG(_config) + + + +#endif /* SONYDRIV_H */ diff --git a/src/mess/machine/zx8302.c b/src/mess/machine/zx8302.c index b77609d7cf2..1fab0e55310 100644 --- a/src/mess/machine/zx8302.c +++ b/src/mess/machine/zx8302.c @@ -21,7 +21,7 @@ #include "emu.h" #include <time.h> -#include "devices/microdrv.h" +#include "machine/microdrv.h" #include "zx8302.h" |