trunk/src/mess/machine/microdrv.c
| r0 | r21306 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | microdrv.c |
| 4 | |
| 5 | MESS interface to the Sinclair Microdrive image abstraction code |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #include "emu.h" |
| 10 | #include "microdrv.h" |
| 11 | |
| 12 | /*************************************************************************** |
| 13 | CONSTANTS |
| 14 | ***************************************************************************/ |
| 15 | |
| 16 | #define LOG 1 |
| 17 | |
| 18 | #define MDV_SECTOR_COUNT 255 |
| 19 | #define MDV_SECTOR_LENGTH 686 |
| 20 | #define MDV_IMAGE_LENGTH (MDV_SECTOR_COUNT * MDV_SECTOR_LENGTH) |
| 21 | |
| 22 | #define MDV_PREAMBLE_LENGTH 12 |
| 23 | #define MDV_GAP_LENGTH 120 |
| 24 | |
| 25 | #define MDV_OFFSET_HEADER_PREAMBLE 0 |
| 26 | #define MDV_OFFSET_HEADER MDV_OFFSET_HEADER_PREAMBLE + MDV_PREAMBLE_LENGTH |
| 27 | #define MDV_OFFSET_DATA_PREAMBLE 28 |
| 28 | #define MDV_OFFSET_DATA MDV_OFFSET_DATA_PREAMBLE + MDV_PREAMBLE_LENGTH |
| 29 | #define MDV_OFFSET_GAP 566 |
| 30 | |
| 31 | #define MDV_BITRATE 120000 // invalid, from ZX microdrive |
| 32 | |
| 33 | /*************************************************************************** |
| 34 | TYPE DEFINITIONS |
| 35 | ***************************************************************************/ |
| 36 | |
| 37 | // device type definition |
| 38 | const device_type MICRODRIVE = &device_creator<microdrive_image_device>; |
| 39 | |
| 40 | //------------------------------------------------- |
| 41 | // microdrive_image_device - constructor |
| 42 | //------------------------------------------------- |
| 43 | |
| 44 | microdrive_image_device::microdrive_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 45 | : device_t(mconfig, MICRODRIVE, "Microdrive", tag, owner, clock), |
| 46 | device_image_interface(mconfig, *this) |
| 47 | { |
| 48 | } |
| 49 | |
| 50 | //------------------------------------------------- |
| 51 | // microdrive_image_device - destructor |
| 52 | //------------------------------------------------- |
| 53 | |
| 54 | microdrive_image_device::~microdrive_image_device() |
| 55 | { |
| 56 | } |
| 57 | |
| 58 | //------------------------------------------------- |
| 59 | // device_config_complete - perform any |
| 60 | // operations now that the configuration is |
| 61 | // complete |
| 62 | //------------------------------------------------- |
| 63 | |
| 64 | void microdrive_image_device::device_config_complete() |
| 65 | { |
| 66 | // inherit a copy of the static data |
| 67 | const microdrive_interface *intf = reinterpret_cast<const microdrive_interface *>(static_config()); |
| 68 | if (intf != NULL) |
| 69 | *static_cast<microdrive_interface *>(this) = *intf; |
| 70 | |
| 71 | // or initialize to defaults if none provided |
| 72 | else |
| 73 | { |
| 74 | memset(&m_out_comms_out_cb, 0, sizeof(m_out_comms_out_cb)); |
| 75 | memset(&m_interface, 0, sizeof(m_interface)); |
| 76 | memset(&m_device_displayinfo, 0, sizeof(m_device_displayinfo)); |
| 77 | } |
| 78 | |
| 79 | // set brief and instance name |
| 80 | update_names(); |
| 81 | } |
| 82 | |
| 83 | |
| 84 | void microdrive_image_device::device_start() |
| 85 | { |
| 86 | // resolve callbacks |
| 87 | m_out_comms_out_func.resolve(m_out_comms_out_cb, *this); |
| 88 | |
| 89 | // allocate track buffers |
| 90 | m_left = auto_alloc_array(machine(), UINT8, MDV_IMAGE_LENGTH / 2); |
| 91 | m_right = auto_alloc_array(machine(), UINT8, MDV_IMAGE_LENGTH / 2); |
| 92 | |
| 93 | // allocate timers |
| 94 | m_bit_timer = timer_alloc(); |
| 95 | m_bit_timer->adjust(attotime::zero, 0, attotime::from_hz(MDV_BITRATE)); |
| 96 | m_bit_timer->enable(0); |
| 97 | } |
| 98 | |
| 99 | bool microdrive_image_device::call_load() |
| 100 | { |
| 101 | if (length() != MDV_IMAGE_LENGTH) |
| 102 | return IMAGE_INIT_FAIL; |
| 103 | |
| 104 | for (int i = 0; i < MDV_IMAGE_LENGTH / 2; i++) |
| 105 | { |
| 106 | fread(m_left, 1); |
| 107 | fread(m_right, 1); |
| 108 | } |
| 109 | |
| 110 | m_bit_offset = 0; |
| 111 | m_byte_offset = 0; |
| 112 | |
| 113 | return IMAGE_INIT_PASS; |
| 114 | } |
| 115 | |
| 116 | void microdrive_image_device::call_unload() |
| 117 | { |
| 118 | memset(m_left, 0, MDV_IMAGE_LENGTH / 2); |
| 119 | memset(m_right, 0, MDV_IMAGE_LENGTH / 2); |
| 120 | } |
| 121 | |
| 122 | void microdrive_image_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 123 | { |
| 124 | m_bit_offset++; |
| 125 | |
| 126 | if (m_bit_offset == 8) |
| 127 | { |
| 128 | m_bit_offset = 0; |
| 129 | m_byte_offset++; |
| 130 | |
| 131 | if (m_byte_offset == MDV_IMAGE_LENGTH) |
| 132 | { |
| 133 | m_byte_offset = 0; |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | WRITE_LINE_MEMBER( microdrive_image_device::clk_w ) |
| 139 | { |
| 140 | if (LOG) logerror("Microdrive '%s' CLK: %u\n", tag(), state); |
| 141 | if (!m_clk && state) |
| 142 | { |
| 143 | m_comms_out = m_comms_in; |
| 144 | if (LOG) logerror("Microdrive '%s' COMMS OUT: %u\n", tag(), m_comms_out); |
| 145 | m_out_comms_out_func(m_comms_out); |
| 146 | m_bit_timer->enable(m_comms_out); |
| 147 | } |
| 148 | m_clk = state; |
| 149 | } |
| 150 | |
| 151 | WRITE_LINE_MEMBER( microdrive_image_device::comms_in_w ) |
| 152 | { |
| 153 | if (LOG) logerror("Microdrive '%s' COMMS IN: %u\n", tag(), state); |
| 154 | m_comms_in = state; |
| 155 | } |
| 156 | |
| 157 | WRITE_LINE_MEMBER( microdrive_image_device::erase_w ) |
| 158 | { |
| 159 | if (LOG) logerror("Microdrive '%s' ERASE: %u\n", tag(), state); |
| 160 | m_erase = state; |
| 161 | } |
| 162 | |
| 163 | WRITE_LINE_MEMBER( microdrive_image_device::read_write_w ) |
| 164 | { |
| 165 | if (LOG) logerror("Microdrive '%s' READ/WRITE: %u\n", tag(), state); |
| 166 | m_read_write = state; |
| 167 | } |
| 168 | |
| 169 | WRITE_LINE_MEMBER( microdrive_image_device::data1_w ) |
| 170 | { |
| 171 | if (m_comms_out && !m_read_write) |
| 172 | { |
| 173 | // TODO |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | WRITE_LINE_MEMBER( microdrive_image_device::data2_w ) |
| 178 | { |
| 179 | if (m_comms_out && !m_read_write) |
| 180 | { |
| 181 | // TODO |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | READ_LINE_MEMBER( microdrive_image_device::data1_r ) |
| 186 | { |
| 187 | int data = 0; |
| 188 | if (m_comms_out && m_read_write) |
| 189 | { |
| 190 | data = BIT(m_left[m_byte_offset], 7 - m_bit_offset); |
| 191 | } |
| 192 | return data; |
| 193 | } |
| 194 | |
| 195 | READ_LINE_MEMBER( microdrive_image_device::data2_r ) |
| 196 | { |
| 197 | int data = 0; |
| 198 | if (m_comms_out && m_read_write) |
| 199 | { |
| 200 | data = BIT(m_right[m_byte_offset], 7 - m_bit_offset); |
| 201 | } |
| 202 | return data; |
| 203 | } |
trunk/src/mess/machine/microdrv.h
| r0 | r21306 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | microdrv.h |
| 4 | |
| 5 | MESS interface to the Sinclair Microdrive image abstraction code |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #pragma once |
| 10 | |
| 11 | #ifndef __MICRODRV__ |
| 12 | #define __MICRODRV__ |
| 13 | |
| 14 | /*************************************************************************** |
| 15 | TYPE DEFINITIONS |
| 16 | ***************************************************************************/ |
| 17 | // ======================> microdrive_interface |
| 18 | |
| 19 | struct microdrive_interface |
| 20 | { |
| 21 | devcb_write_line m_out_comms_out_cb; |
| 22 | const char * m_interface; |
| 23 | device_image_display_info_func m_device_displayinfo; |
| 24 | }; |
| 25 | |
| 26 | // ======================> microdrive_image_device |
| 27 | |
| 28 | class microdrive_image_device : public device_t, |
| 29 | public microdrive_interface, |
| 30 | public device_image_interface |
| 31 | { |
| 32 | public: |
| 33 | // construction/destruction |
| 34 | microdrive_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 35 | virtual ~microdrive_image_device(); |
| 36 | |
| 37 | // image-level overrides |
| 38 | virtual bool call_load(); |
| 39 | virtual void call_unload(); |
| 40 | virtual void call_display_info() { if (m_device_displayinfo) m_device_displayinfo(*this); } |
| 41 | virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry) { return load_software(swlist, swname, start_entry); } |
| 42 | |
| 43 | virtual iodevice_t image_type() const { return IO_CASSETTE; } |
| 44 | |
| 45 | virtual bool is_readable() const { return 1; } |
| 46 | virtual bool is_writeable() const { return 1; } |
| 47 | virtual bool is_creatable() const { return 0; } |
| 48 | virtual bool must_be_loaded() const { return 0; } |
| 49 | virtual bool is_reset_on_load() const { return 0; } |
| 50 | virtual const char *image_interface() const { return "ql_cass"; } |
| 51 | virtual const char *file_extensions() const { return "mdv"; } |
| 52 | virtual const option_guide *create_option_guide() const { return NULL; } |
| 53 | |
| 54 | // specific implementation |
| 55 | DECLARE_WRITE_LINE_MEMBER( clk_w ); |
| 56 | DECLARE_WRITE_LINE_MEMBER( comms_in_w ); |
| 57 | DECLARE_WRITE_LINE_MEMBER( erase_w ); |
| 58 | DECLARE_WRITE_LINE_MEMBER( read_write_w ); |
| 59 | DECLARE_WRITE_LINE_MEMBER( data1_w ); |
| 60 | DECLARE_WRITE_LINE_MEMBER( data2_w ); |
| 61 | DECLARE_READ_LINE_MEMBER ( data1_r ); |
| 62 | DECLARE_READ_LINE_MEMBER ( data2_r ); |
| 63 | protected: |
| 64 | // device-level overrides |
| 65 | virtual void device_config_complete(); |
| 66 | virtual void device_start(); |
| 67 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 68 | private: |
| 69 | devcb_resolved_write_line m_out_comms_out_func; |
| 70 | |
| 71 | int m_clk; |
| 72 | int m_comms_in; |
| 73 | int m_comms_out; |
| 74 | int m_erase; |
| 75 | int m_read_write; |
| 76 | |
| 77 | UINT8 *m_left; |
| 78 | UINT8 *m_right; |
| 79 | |
| 80 | int m_bit_offset; |
| 81 | int m_byte_offset; |
| 82 | |
| 83 | emu_timer *m_bit_timer; |
| 84 | }; |
| 85 | |
| 86 | // device type definition |
| 87 | extern const device_type MICRODRIVE; |
| 88 | |
| 89 | /*************************************************************************** |
| 90 | DEVICE CONFIGURATION MACROS |
| 91 | ***************************************************************************/ |
| 92 | |
| 93 | #define MDV_1 "mdv1" |
| 94 | #define MDV_2 "mdv2" |
| 95 | |
| 96 | #define MCFG_MICRODRIVE_ADD(_tag, _config) \ |
| 97 | MCFG_DEVICE_ADD(_tag, MICRODRIVE, 0) \ |
| 98 | MCFG_DEVICE_CONFIG(_config) |
| 99 | |
| 100 | #define MICRODRIVE_CONFIG(_name) \ |
| 101 | const microdrive_interface (_name) = |
| 102 | |
| 103 | #endif |
trunk/src/mess/machine/sonydriv.c
| r0 | r21306 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | sonydriv.c |
| 4 | |
| 5 | Apple/Sony 3.5" floppy drive emulation (to be interfaced with iwm.c) |
| 6 | |
| 7 | Nate Woods, Raphael Nabet, R. Belmont |
| 8 | |
| 9 | This floppy drive was present in all variants of Lisa 2 (including Mac XL), |
| 10 | all Apple IIgs and IIc Plus machines, and in all Macintoshes in production |
| 11 | before 1988, when SWIM and SuperDrive were introduced. |
| 12 | |
| 13 | There were three major variants : |
| 14 | - A single-sided 400k unit which was used on Lisa 2/Mac XL, and Macintosh |
| 15 | 128k/512k. This unit needs the computer to send the proper pulses to |
| 16 | control the drive motor rotation. It can be connected to all early |
| 17 | Macintosh (but not Mac Classic?) as an external unit. |
| 18 | - A double-sided 800k unit which was used on Macintosh Plus, 512ke, and |
| 19 | early SE and II*. This unit generates its own drive motor rotation |
| 20 | control signals. It can be connected to earlier (and later) Macintosh as |
| 21 | an external or internal unit. Some Lisa2/10 and Mac XL were upgraded to |
| 22 | use it, too, but a fdc ROM upgrade was required. |
| 23 | - A double-sided 1440k unit. This is fully back compatible with the 800k |
| 24 | drive, and adds 1440k MFM capability. This drive, called FDHD or |
| 25 | SuperDrive by Apple, came in automatic and manual-inject versions. |
| 26 | |
| 27 | TODO : |
| 28 | * support for other image formats? |
| 29 | * should we support more than 2 floppy disk units? (Mac SE supported 3 drives) |
| 30 | |
| 31 | *********************************************************************/ |
| 32 | |
| 33 | #include "emu.h" |
| 34 | #include "machine/applefdc.h" |
| 35 | #include "sonydriv.h" |
| 36 | #include "formats/ap_dsk35.h" |
| 37 | #include "imagedev/flopdrv.h" |
| 38 | |
| 39 | |
| 40 | #ifdef MAME_DEBUG |
| 41 | #define LOG_SONY 1 |
| 42 | #define LOG_SONY_EXTRA 0 |
| 43 | #else |
| 44 | #define LOG_SONY 0 |
| 45 | #define LOG_SONY_EXTRA 0 |
| 46 | #endif |
| 47 | |
| 48 | /* |
| 49 | These lines are normally connected to the PHI0-PHI3 lines of the IWM |
| 50 | */ |
| 51 | enum |
| 52 | { |
| 53 | SONY_CA0 = 0x01, |
| 54 | SONY_CA1 = 0x02, |
| 55 | SONY_CA2 = 0x04, |
| 56 | SONY_LSTRB = 0x08 |
| 57 | }; |
| 58 | |
| 59 | /* |
| 60 | Structure that describes the state of a floppy drive, and the associated |
| 61 | disk image |
| 62 | */ |
| 63 | struct floppy_t |
| 64 | { |
| 65 | device_t *img; |
| 66 | emu_file *fd; |
| 67 | |
| 68 | unsigned int disk_switched : 1; /* disk-in-place status bit */ |
| 69 | unsigned int head : 1; /* active head (-> floppy side) */ |
| 70 | unsigned int step : 1; |
| 71 | int motor_on; |
| 72 | |
| 73 | unsigned int loadedtrack_valid : 1; /* is data in track buffer valid ? */ |
| 74 | unsigned int loadedtrack_dirty : 1; /* has data in track buffer been modified? */ |
| 75 | size_t loadedtrack_size; /* size of loaded track */ |
| 76 | size_t loadedtrack_pos; /* position within loaded track */ |
| 77 | UINT8 *loadedtrack_data; /* pointer to track buffer */ |
| 78 | |
| 79 | int is_fdhd; /* is drive an FDHD? */ |
| 80 | int is_400k; /* drive is single-sided, which means 400K */ |
| 81 | }; |
| 82 | |
| 83 | struct sonydriv_t |
| 84 | { |
| 85 | int lines; /* four lines SONY_CA0 - SONY_LSTRB */ |
| 86 | |
| 87 | int floppy_enable; /* whether a drive is enabled or not (-> enable line) */ |
| 88 | int floppy_select; /* which drive is enabled */ |
| 89 | |
| 90 | int sel_line; /* one single line Is 0 or 1 */ |
| 91 | |
| 92 | unsigned int rotation_speed; /* drive rotation speed - ignored if ext_speed_control == 0 */ |
| 93 | floppy_t floppy[2]; /* data for two floppy disk units */ |
| 94 | }; |
| 95 | static sonydriv_t sony; |
| 96 | |
| 97 | /* bit of code used in several places - I am unsure why it is here */ |
| 98 | static int sony_enable2(void) |
| 99 | { |
| 100 | return (sony.lines & SONY_CA1) && (sony.lines & SONY_LSTRB); |
| 101 | } |
| 102 | |
| 103 | static void load_track_data(device_t *device,int floppy_select) |
| 104 | { |
| 105 | int track_size; |
| 106 | device_image_interface *cur_image; |
| 107 | UINT8 *new_data; |
| 108 | floppy_t *f; |
| 109 | |
| 110 | f = &sony.floppy[floppy_select]; |
| 111 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, floppy_select)); |
| 112 | |
| 113 | floppy_image_legacy *fimg = flopimg_get_image(&cur_image->device()); |
| 114 | |
| 115 | if (!fimg) |
| 116 | { |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | track_size = floppy_get_track_size(fimg, f->head, floppy_drive_get_current_track(&cur_image->device())); |
| 121 | if (f->loadedtrack_data) auto_free(device->machine(),f->loadedtrack_data); |
| 122 | new_data = auto_alloc_array(device->machine(),UINT8,track_size); |
| 123 | if (!new_data) |
| 124 | { |
| 125 | return; |
| 126 | } |
| 127 | |
| 128 | floppy_drive_read_track_data_info_buffer(&cur_image->device(), f->head, new_data, &track_size); |
| 129 | f->loadedtrack_valid = 1; |
| 130 | f->loadedtrack_dirty = 0; |
| 131 | f->loadedtrack_size = track_size; |
| 132 | f->loadedtrack_data = new_data; |
| 133 | f->loadedtrack_pos = 0; |
| 134 | } |
| 135 | |
| 136 | |
| 137 | |
| 138 | static void save_track_data(device_t *device, int floppy_select) |
| 139 | { |
| 140 | device_image_interface *cur_image; |
| 141 | floppy_t *f; |
| 142 | int len; |
| 143 | |
| 144 | f = &sony.floppy[floppy_select]; |
| 145 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, floppy_select)); |
| 146 | |
| 147 | if (f->loadedtrack_dirty) |
| 148 | { |
| 149 | len = f->loadedtrack_size; |
| 150 | floppy_drive_write_track_data_info_buffer(&cur_image->device(), f->head, f->loadedtrack_data, &len); |
| 151 | f->loadedtrack_dirty = 0; |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | |
| 156 | |
| 157 | UINT8 sony_read_data(device_t *device) |
| 158 | { |
| 159 | UINT8 result = 0; |
| 160 | device_image_interface *cur_image; |
| 161 | floppy_t *f; |
| 162 | |
| 163 | if (sony_enable2() || (! sony.floppy_enable)) |
| 164 | return 0xFF; /* right ??? */ |
| 165 | |
| 166 | f = &sony.floppy[sony.floppy_select]; |
| 167 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); |
| 168 | if (!cur_image->exists()) |
| 169 | return 0xFF; |
| 170 | |
| 171 | if (!f->loadedtrack_valid) |
| 172 | load_track_data(device, sony.floppy_select); |
| 173 | |
| 174 | if (!f->loadedtrack_data) |
| 175 | { |
| 176 | return 0xFF; |
| 177 | } |
| 178 | |
| 179 | result = sony_fetchtrack(f->loadedtrack_data, f->loadedtrack_size, &f->loadedtrack_pos); |
| 180 | return result; |
| 181 | } |
| 182 | |
| 183 | |
| 184 | |
| 185 | void sony_write_data(device_t *device,UINT8 data) |
| 186 | { |
| 187 | device_image_interface *cur_image; |
| 188 | floppy_t *f; |
| 189 | |
| 190 | f = &sony.floppy[sony.floppy_select]; |
| 191 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); |
| 192 | if (!cur_image->exists()) |
| 193 | return; |
| 194 | |
| 195 | if (!f->loadedtrack_valid) |
| 196 | load_track_data(device,sony.floppy_select); |
| 197 | |
| 198 | if (!f->loadedtrack_data) |
| 199 | { |
| 200 | return; |
| 201 | } |
| 202 | |
| 203 | sony_filltrack(f->loadedtrack_data, f->loadedtrack_size, &f->loadedtrack_pos, data); |
| 204 | f->loadedtrack_dirty = 1; |
| 205 | } |
| 206 | |
| 207 | |
| 208 | |
| 209 | static int sony_rpm(floppy_t *f, device_t *cur_image) |
| 210 | { |
| 211 | int result = 0; |
| 212 | device_image_interface *image =dynamic_cast<device_image_interface *>(cur_image); |
| 213 | /* |
| 214 | * The Mac floppy controller was interesting in that its speed was adjusted |
| 215 | * while the thing was running. On the tracks closer to the rim, it was |
| 216 | * sped up so that more data could be placed on it. Hence, this function |
| 217 | * has different results depending on the track number |
| 218 | * |
| 219 | * The Mac Plus (and probably the other Macs that use the IWM) verify that |
| 220 | * the speed of the floppy drive is within a certain range depending on |
| 221 | * what track the floppy is at. These RPM values are just guesses and are |
| 222 | * probably not fully accurate, but they are within the range that the Mac |
| 223 | * Plus expects and thus are probably in the right ballpark. |
| 224 | * |
| 225 | * Note - the timing values are the values returned by the Mac Plus routine |
| 226 | * that calculates the speed; I'm not sure what units they are in |
| 227 | */ |
| 228 | |
| 229 | if ((f->is_400k) && (sony.rotation_speed)) |
| 230 | { |
| 231 | /* 400k unit : rotation speed should be controlled by computer */ |
| 232 | result = sony.rotation_speed; |
| 233 | } |
| 234 | else |
| 235 | { /* 800k unit : rotation speed controlled by drive */ |
| 236 | #if 1 /* Mac Plus */ |
| 237 | static const int speeds[] = |
| 238 | { |
| 239 | 500, /* 00-15: timing value 117B (acceptable range {1135-11E9} */ |
| 240 | 550, /* 16-31: timing value ???? (acceptable range {12C6-138A} */ |
| 241 | 600, /* 32-47: timing value ???? (acceptable range {14A7-157F} */ |
| 242 | 675, /* 48-63: timing value ???? (acceptable range {16F2-17E2} */ |
| 243 | 750 /* 64-79: timing value ???? (acceptable range {19D0-1ADE} */ |
| 244 | }; |
| 245 | #else /* Lisa 2 */ |
| 246 | /* 237 + 1.3*(256-reg) */ |
| 247 | static const int speeds[] = |
| 248 | { |
| 249 | 293, /* 00-15: timing value ???? (acceptable range {0330-0336} */ |
| 250 | 322, /* 16-31: timing value ???? (acceptable range {02ED-02F3} */ |
| 251 | 351, /* 32-47: timing value ???? (acceptable range {02A7-02AD} */ |
| 252 | 394, /* 48-63: timing value ???? (acceptable range {0262-0266} */ |
| 253 | 439 /* 64-79: timing value ???? (acceptable range {021E-0222} */ |
| 254 | }; |
| 255 | #endif |
| 256 | if (cur_image && image->exists()) |
| 257 | result = speeds[floppy_drive_get_current_track(cur_image) / 16]; |
| 258 | } |
| 259 | return result; |
| 260 | } |
| 261 | |
| 262 | int sony_read_status(device_t *device) |
| 263 | { |
| 264 | int result = 1; |
| 265 | int action; |
| 266 | floppy_t *f; |
| 267 | device_image_interface *cur_image; |
| 268 | |
| 269 | action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); |
| 270 | |
| 271 | if (LOG_SONY_EXTRA) |
| 272 | { |
| 273 | printf("sony.status(): action=%x pc=0x%08x%s\n", |
| 274 | action, (int) device->machine().firstcpu->pc(), sony.floppy_enable ? "" : " (no drive enabled)"); |
| 275 | } |
| 276 | |
| 277 | if ((! sony_enable2()) && sony.floppy_enable) |
| 278 | { |
| 279 | f = &sony.floppy[sony.floppy_select]; |
| 280 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); |
| 281 | if (!cur_image->exists()) |
| 282 | cur_image = NULL; |
| 283 | |
| 284 | switch(action) { |
| 285 | case 0x00: /* Step direction */ |
| 286 | result = f->step; |
| 287 | break; |
| 288 | case 0x01: /* Lower head activate */ |
| 289 | if (f->head != 0) |
| 290 | { |
| 291 | save_track_data(device,sony.floppy_select); |
| 292 | f->head = 0; |
| 293 | f->loadedtrack_valid = 0; |
| 294 | } |
| 295 | result = 0; |
| 296 | break; |
| 297 | case 0x02: /* Disk in place */ |
| 298 | result = cur_image ? 0 : 1; /* 0=disk 1=nodisk */ |
| 299 | break; |
| 300 | case 0x03: /* Upper head activate (not on 400k) */ |
| 301 | if ((f->head != 1) && !(f->is_400k)) |
| 302 | { |
| 303 | save_track_data(device,sony.floppy_select); |
| 304 | f->head = 1; |
| 305 | f->loadedtrack_valid = 0; |
| 306 | } |
| 307 | result = 0; |
| 308 | break; |
| 309 | case 0x04: /* Disk is stepping 0=stepping 1=not stepping*/ |
| 310 | result = 1; |
| 311 | break; |
| 312 | case 0x05: /* Drive is SuperDrive: 0 = 400/800k, 1 = SuperDrive */ |
| 313 | result = f->is_fdhd ? 1: 0; |
| 314 | break; |
| 315 | case 0x06: /* Disk is locked 0=locked 1=unlocked */ |
| 316 | if (cur_image) |
| 317 | result = floppy_wpt_r(&cur_image->device()); |
| 318 | else |
| 319 | result = 0; |
| 320 | break; |
| 321 | case 0x08: /* Motor on 0=on 1=off */ |
| 322 | result = f->motor_on; |
| 323 | break; |
| 324 | case 0x09: /* Number of sides: 0=single sided, 1=double sided */ |
| 325 | if (cur_image) |
| 326 | { |
| 327 | floppy_image_legacy *fimg = flopimg_get_image(&cur_image->device()); |
| 328 | if (fimg) |
| 329 | { |
| 330 | result = floppy_get_heads_per_disk(fimg) - 1; |
| 331 | f->is_400k = result ? 0 : 1; |
| 332 | } |
| 333 | } |
| 334 | break; |
| 335 | case 0x0a: /* At track 0: 0=track zero 1=not track zero */ |
| 336 | logerror("sony.status(): reading Track 0 pc=0x%08x\n", (int) device->machine().firstcpu->pc()); |
| 337 | if (cur_image) |
| 338 | result = floppy_tk00_r(&cur_image->device()); |
| 339 | else |
| 340 | result = 0; |
| 341 | break; |
| 342 | case 0x0b: /* Disk ready: 0=ready, 1=not ready */ |
| 343 | result = 0; |
| 344 | break; |
| 345 | case 0x0c: /* Disk switched */ |
| 346 | { |
| 347 | if (cur_image) |
| 348 | { |
| 349 | if (!floppy_dskchg_r(&cur_image->device())) |
| 350 | { |
| 351 | f->disk_switched = 1; |
| 352 | } |
| 353 | } |
| 354 | result = f->disk_switched; |
| 355 | } |
| 356 | break; |
| 357 | case 0x0d: /* Unknown */ |
| 358 | /* I'm not sure what this one does, but the Mac Plus executes the |
| 359 | * following code that uses this status: |
| 360 | * |
| 361 | * 417E52: moveq #$d, D0 ; Status 0x0d |
| 362 | * 417E54: bsr 4185fe ; Query IWM status |
| 363 | * 417E58: bmi 417e82 ; If result=1, then skip |
| 364 | * |
| 365 | * This code is called in the Sony driver's open method, and |
| 366 | * _AddDrive does not get called if this status 0x0d returns 1. |
| 367 | * Hence, we are returning 0 |
| 368 | */ |
| 369 | result = 0; |
| 370 | break; |
| 371 | case 0x0e: /* Tachometer */ |
| 372 | /* (time in seconds) / (60 sec/minute) * (rounds/minute) * (60 pulses) * (2 pulse phases) */ |
| 373 | if (cur_image) |
| 374 | { |
| 375 | result = ((int) (device->machine().time().as_double() / 60.0 * sony_rpm(f, &cur_image->device()) * 60.0 * 2.0)) & 1; |
| 376 | } |
| 377 | break; |
| 378 | case 0x0f: /* 400k/800k: Drive installed: 0=drive connected, 1=drive not connected */ |
| 379 | /* FDHD: Inserted disk density: 0=HD, 1=DD */ |
| 380 | if (f->is_fdhd) |
| 381 | { |
| 382 | result = 1; |
| 383 | } |
| 384 | else |
| 385 | { |
| 386 | result = 0; |
| 387 | } |
| 388 | break; |
| 389 | default: |
| 390 | if (LOG_SONY) |
| 391 | logerror("sony_status(): unknown action\n"); |
| 392 | break; |
| 393 | } |
| 394 | } |
| 395 | |
| 396 | return result; |
| 397 | } |
| 398 | |
| 399 | static void sony_doaction(device_t *device) |
| 400 | { |
| 401 | int action; |
| 402 | floppy_t *f; |
| 403 | device_image_interface *cur_image; |
| 404 | |
| 405 | action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | ((sony.lines & SONY_CA2) >> 2) | (sony.sel_line << 1); |
| 406 | |
| 407 | if (LOG_SONY) |
| 408 | { |
| 409 | logerror("sony_doaction(): action=%d pc=0x%08x%s\n", |
| 410 | action, (int) device->machine().firstcpu->pc(), (sony.floppy_enable) ? "" : " (MOTOR OFF)"); |
| 411 | } |
| 412 | |
| 413 | if (sony.floppy_enable) |
| 414 | { |
| 415 | f = &sony.floppy[sony.floppy_select]; |
| 416 | cur_image = dynamic_cast<device_image_interface *>(floppy_get_device_by_type(device->machine(), FLOPPY_TYPE_SONY, sony.floppy_select)); |
| 417 | if (!cur_image->exists()) |
| 418 | cur_image = NULL; |
| 419 | |
| 420 | switch(action) |
| 421 | { |
| 422 | case 0x00: /* Set step inward (higher tracks) */ |
| 423 | f->step = 0; |
| 424 | break; |
| 425 | case 0x01: /* Set step outward (lower tracks) */ |
| 426 | f->step = 1; |
| 427 | break; |
| 428 | case 0x03: /* Reset diskswitched */ |
| 429 | f->disk_switched = 0; |
| 430 | break; |
| 431 | case 0x04: /* Step disk */ |
| 432 | if (cur_image) |
| 433 | { |
| 434 | save_track_data(device,sony.floppy_select); |
| 435 | if (f->step) |
| 436 | floppy_drive_seek(&cur_image->device(), -1); |
| 437 | else |
| 438 | floppy_drive_seek(&cur_image->device(), +1); |
| 439 | f->loadedtrack_valid = 0; |
| 440 | } |
| 441 | break; |
| 442 | case 0x08: /* Turn motor on */ |
| 443 | f->motor_on = CLEAR_LINE; |
| 444 | if (cur_image) |
| 445 | floppy_mon_w(&cur_image->device(), f->motor_on); |
| 446 | break; |
| 447 | case 0x09: /* Turn motor off */ |
| 448 | f->motor_on = ASSERT_LINE; |
| 449 | if (cur_image) |
| 450 | floppy_mon_w(&cur_image->device(), f->motor_on); |
| 451 | break; |
| 452 | case 0x0d: /* Eject disk */ |
| 453 | if (cur_image) |
| 454 | cur_image->unload(); |
| 455 | break; |
| 456 | default: |
| 457 | if (LOG_SONY) |
| 458 | logerror("sony_doaction(): unknown action %d\n", action); |
| 459 | break; |
| 460 | } |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | void sony_set_lines(device_t *device,UINT8 lines) |
| 465 | { |
| 466 | int old_sony_lines = sony.lines; |
| 467 | |
| 468 | sony.lines = lines & 0x0F; |
| 469 | |
| 470 | { |
| 471 | //int action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); |
| 472 | //printf("sony.set_lines: %02x, action now %d\n", lines&0xf, action); |
| 473 | } |
| 474 | |
| 475 | /* have we just set LSTRB ? */ |
| 476 | if ((sony.lines & ~old_sony_lines) & SONY_LSTRB) |
| 477 | { |
| 478 | /* if so, write drive reg */ |
| 479 | sony_doaction(device); |
| 480 | } |
| 481 | |
| 482 | if (LOG_SONY_EXTRA) |
| 483 | logerror("sony.set_lines(): %d\n", lines); |
| 484 | } |
| 485 | |
| 486 | void sony_set_enable_lines(device_t *device,int enable_mask) |
| 487 | { |
| 488 | switch (enable_mask) |
| 489 | { |
| 490 | case 0: |
| 491 | default: /* well, we have to do something, right ? */ |
| 492 | sony.floppy_enable = 0; |
| 493 | break; |
| 494 | case 1: |
| 495 | sony.floppy_enable = 1; |
| 496 | sony.floppy_select = 0; |
| 497 | break; |
| 498 | case 2: |
| 499 | sony.floppy_enable = 1; |
| 500 | sony.floppy_select = 1; |
| 501 | break; |
| 502 | } |
| 503 | |
| 504 | if (LOG_SONY_EXTRA) |
| 505 | logerror("sony.set_enable_lines(): %d\n", enable_mask); |
| 506 | } |
| 507 | |
| 508 | void sony_set_sel_line(device_t *device,int sel) |
| 509 | { |
| 510 | sony.sel_line = sel ? 1 : 0; |
| 511 | |
| 512 | { |
| 513 | //int action = ((sony.lines & (SONY_CA1 | SONY_CA0)) << 2) | (sony.sel_line << 1) | ((sony.lines & SONY_CA2) >> 2); |
| 514 | //printf("sony.set_sel_line: %d, action now %d\n", sony.sel_line, action); |
| 515 | } |
| 516 | |
| 517 | if (LOG_SONY_EXTRA) |
| 518 | logerror("sony.set_sel_line(): %s line IWM_SEL\n", sony.sel_line ? "setting" : "clearing"); |
| 519 | } |
| 520 | |
| 521 | void sony_set_speed(int speed) |
| 522 | { |
| 523 | sony.rotation_speed = speed; |
| 524 | } |
| 525 | |
| 526 | // device type definition |
| 527 | const device_type FLOPPY_SONY = &device_creator<sonydriv_floppy_image_device>; |
| 528 | |
| 529 | //------------------------------------------------- |
| 530 | // sonydriv_floppy_image_device - constructor |
| 531 | //------------------------------------------------- |
| 532 | |
| 533 | sonydriv_floppy_image_device::sonydriv_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 534 | : legacy_floppy_image_device(mconfig, FLOPPY_SONY, "Floppy Disk [Sony]", tag, owner, clock) |
| 535 | { |
| 536 | } |
| 537 | |
| 538 | //------------------------------------------------- |
| 539 | // device_start - device-specific startup |
| 540 | //------------------------------------------------- |
| 541 | |
| 542 | void sonydriv_floppy_image_device::device_start() |
| 543 | { |
| 544 | legacy_floppy_image_device::device_start(); |
| 545 | floppy_set_type(this, FLOPPY_TYPE_SONY); |
| 546 | |
| 547 | sony.floppy[0].is_fdhd = 0; |
| 548 | sony.floppy[1].is_fdhd = 0; |
| 549 | sony.floppy[0].is_400k = 0; |
| 550 | sony.floppy[1].is_400k = 0; |
| 551 | sony.floppy[0].loadedtrack_data = NULL; |
| 552 | sony.floppy[1].loadedtrack_data = NULL; |
| 553 | sony.floppy[0].head = 0; |
| 554 | sony.floppy[1].head = 0; |
| 555 | sony.rotation_speed = 0; |
| 556 | } |
| 557 | |
| 558 | void sonydriv_floppy_image_device::call_unload() |
| 559 | { |
| 560 | int id; |
| 561 | device_t *fdc; |
| 562 | |
| 563 | /* locate the FDC */ |
| 564 | fdc = machine().device("fdc"); |
| 565 | |
| 566 | id = floppy_get_drive_by_type(this,FLOPPY_TYPE_SONY); |
| 567 | save_track_data(fdc, id); |
| 568 | memset(&sony.floppy[id], 0, sizeof(sony.floppy[id])); |
| 569 | |
| 570 | legacy_floppy_image_device::call_unload(); |
| 571 | } |
trunk/src/mess/machine/appldriv.c
| r0 | r21306 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | appldriv.c |
| 4 | |
| 5 | Apple 5.25" floppy drive emulation (to be interfaced with applefdc.c) |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | #include "emu.h" |
| 9 | #include "appldriv.h" |
| 10 | #include "imagedev/flopdrv.h" |
| 11 | #include "formats/ap2_dsk.h" |
| 12 | |
| 13 | // our parent's device is the Disk II card (Apple II) or main driver (Mac, IIgs) |
| 14 | // either way, get the drive from there. |
| 15 | #define PARENT_FLOPPY_0 "^floppy0" |
| 16 | #define PARENT_FLOPPY_1 "^floppy1" |
| 17 | #define PARENT_FLOPPY_2 "^floppy2" |
| 18 | #define PARENT_FLOPPY_3 "^floppy3" |
| 19 | |
| 20 | INLINE apple525_floppy_image_device *get_device(device_t *device) |
| 21 | { |
| 22 | assert(device != NULL); |
| 23 | assert(device->type() == FLOPPY_APPLE); |
| 24 | |
| 25 | return (apple525_floppy_image_device *) downcast<apple525_floppy_image_device *>(device); |
| 26 | } |
| 27 | |
| 28 | static int apple525_enable_mask = 1; |
| 29 | |
| 30 | device_t *apple525_get_subdevice(device_t *device, int drive) |
| 31 | { |
| 32 | switch(drive) { |
| 33 | case 0 : return device->subdevice(PARENT_FLOPPY_0); |
| 34 | case 1 : return device->subdevice(PARENT_FLOPPY_1); |
| 35 | case 2 : return device->subdevice(PARENT_FLOPPY_2); |
| 36 | case 3 : return device->subdevice(PARENT_FLOPPY_3); |
| 37 | } |
| 38 | return NULL; |
| 39 | } |
| 40 | |
| 41 | device_t *apple525_get_device_by_type(device_t *device, int ftype, int drive) |
| 42 | { |
| 43 | int i; |
| 44 | int cnt = 0; |
| 45 | for (i=0;i<4;i++) { |
| 46 | device_t *disk = apple525_get_subdevice(device, i); |
| 47 | if (floppy_get_drive_type(disk)==ftype) { |
| 48 | if (cnt==drive) { |
| 49 | return disk; |
| 50 | } |
| 51 | cnt++; |
| 52 | } |
| 53 | } |
| 54 | return NULL; |
| 55 | } |
| 56 | |
| 57 | void apple525_set_enable_lines(device_t *device,int enable_mask) |
| 58 | { |
| 59 | apple525_enable_mask = enable_mask; |
| 60 | } |
| 61 | |
| 62 | /* ----------------------------------------------------------------------- */ |
| 63 | |
| 64 | static void apple525_load_current_track(device_t *image) |
| 65 | { |
| 66 | int len; |
| 67 | apple525_floppy_image_device *disk; |
| 68 | |
| 69 | disk = get_device(image); |
| 70 | len = sizeof(disk->track_data); |
| 71 | |
| 72 | floppy_drive_read_track_data_info_buffer(image, 0, disk->track_data, &len); |
| 73 | disk->track_loaded = 1; |
| 74 | disk->track_dirty = 0; |
| 75 | } |
| 76 | |
| 77 | static void apple525_save_current_track(device_t *image, int unload) |
| 78 | { |
| 79 | int len; |
| 80 | apple525_floppy_image_device *disk; |
| 81 | |
| 82 | disk = get_device(image); |
| 83 | |
| 84 | if (disk->track_dirty) |
| 85 | { |
| 86 | len = sizeof(disk->track_data); |
| 87 | floppy_drive_write_track_data_info_buffer(image, 0, disk->track_data, &len); |
| 88 | disk->track_dirty = 0; |
| 89 | } |
| 90 | if (unload) |
| 91 | disk->track_loaded = 0; |
| 92 | } |
| 93 | |
| 94 | static void apple525_seek_disk(device_t *img, signed int step) |
| 95 | { |
| 96 | int track; |
| 97 | int pseudo_track; |
| 98 | apple525_floppy_image_device *disk; |
| 99 | |
| 100 | disk = get_device(img); |
| 101 | |
| 102 | apple525_save_current_track(img, FALSE); |
| 103 | |
| 104 | track = floppy_drive_get_current_track(img); |
| 105 | pseudo_track = (track * 2) + disk->tween_tracks; |
| 106 | |
| 107 | pseudo_track += step; |
| 108 | if (pseudo_track < 0) |
| 109 | pseudo_track = 0; |
| 110 | else if (pseudo_track/2 >= APPLE2_TRACK_COUNT) |
| 111 | pseudo_track = APPLE2_TRACK_COUNT*2-1; |
| 112 | |
| 113 | if (pseudo_track/2 != track) |
| 114 | { |
| 115 | floppy_drive_seek(img, pseudo_track/2 - floppy_drive_get_current_track(img)); |
| 116 | disk->track_loaded = 0; |
| 117 | } |
| 118 | |
| 119 | if (pseudo_track & 1) |
| 120 | disk->tween_tracks = 1; |
| 121 | else |
| 122 | disk->tween_tracks = 0; |
| 123 | } |
| 124 | |
| 125 | static void apple525_disk_set_lines(device_t *device,device_t *image, UINT8 new_state) |
| 126 | { |
| 127 | apple525_floppy_image_device *cur_disk; |
| 128 | UINT8 old_state; |
| 129 | unsigned int phase; |
| 130 | |
| 131 | cur_disk = get_device(image); |
| 132 | |
| 133 | old_state = cur_disk->state; |
| 134 | cur_disk->state = new_state; |
| 135 | |
| 136 | if ((new_state & 0x0F) > (old_state & 0x0F)) |
| 137 | { |
| 138 | phase = 0; |
| 139 | switch((old_state ^ new_state) & 0x0F) |
| 140 | { |
| 141 | case 1: phase = 0; break; |
| 142 | case 2: phase = 1; break; |
| 143 | case 4: phase = 2; break; |
| 144 | case 8: phase = 3; break; |
| 145 | } |
| 146 | |
| 147 | phase -= floppy_drive_get_current_track(image) * 2; |
| 148 | if (cur_disk->tween_tracks) |
| 149 | phase--; |
| 150 | phase %= 4; |
| 151 | |
| 152 | switch(phase) |
| 153 | { |
| 154 | case 1: |
| 155 | apple525_seek_disk(image, +1); |
| 156 | break; |
| 157 | case 3: |
| 158 | apple525_seek_disk(image, -1); |
| 159 | break; |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | int apple525_get_count(device_t *device) |
| 165 | { |
| 166 | int cnt = 0; |
| 167 | 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++; |
| 168 | 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++; |
| 169 | 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++; |
| 170 | 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++; |
| 171 | |
| 172 | return cnt; |
| 173 | } |
| 174 | |
| 175 | void apple525_set_lines(device_t *device, UINT8 lines) |
| 176 | { |
| 177 | int i, count; |
| 178 | device_t *image; |
| 179 | |
| 180 | count = apple525_get_count(device); |
| 181 | for (i = 0; i < count; i++) |
| 182 | { |
| 183 | if (apple525_enable_mask & (1 << i)) |
| 184 | { |
| 185 | image = apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i); |
| 186 | if (image) |
| 187 | apple525_disk_set_lines(device,image, lines); |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | /* reads/writes a byte; write_value is -1 for read only */ |
| 193 | static UINT8 apple525_process_byte(device_t *img, int write_value) |
| 194 | { |
| 195 | UINT8 read_value; |
| 196 | apple525_floppy_image_device *disk; |
| 197 | int spinfract_divisor; |
| 198 | int spinfract_dividend; |
| 199 | apple525_floppy_image_device *config = get_device(img); |
| 200 | device_image_interface *image = dynamic_cast<device_image_interface *>(img); |
| 201 | |
| 202 | disk = get_device(img); |
| 203 | spinfract_dividend = config->get_dividend(); |
| 204 | spinfract_divisor = config->get_divisor(); |
| 205 | |
| 206 | /* no image initialized for that drive ? */ |
| 207 | if (!image->exists()) |
| 208 | return 0xFF; |
| 209 | |
| 210 | /* check the spin count if reading*/ |
| 211 | if (write_value < 0) |
| 212 | { |
| 213 | disk->spin_count++; |
| 214 | disk->spin_count %= spinfract_divisor; |
| 215 | if (disk->spin_count >= spinfract_dividend) |
| 216 | return 0x00; |
| 217 | } |
| 218 | |
| 219 | /* load track if need be */ |
| 220 | if (disk->track_loaded == 0) |
| 221 | apple525_load_current_track(img); |
| 222 | |
| 223 | /* perform the read */ |
| 224 | read_value = disk->track_data[disk->position]; |
| 225 | |
| 226 | /* perform the write, if applicable */ |
| 227 | if (write_value >= 0) |
| 228 | { |
| 229 | disk->track_data[disk->position] = write_value; |
| 230 | disk->track_dirty = 1; |
| 231 | } |
| 232 | |
| 233 | disk->position++; |
| 234 | disk->position %= ARRAY_LENGTH(disk->track_data); |
| 235 | |
| 236 | /* when writing; save the current track after every full sector write */ |
| 237 | if ((write_value >= 0) && ((disk->position % APPLE2_NIBBLE_SIZE) == 0)) |
| 238 | apple525_save_current_track(img, FALSE); |
| 239 | |
| 240 | return read_value; |
| 241 | } |
| 242 | |
| 243 | static device_t *apple525_selected_image(device_t *device) |
| 244 | { |
| 245 | int i,count; |
| 246 | |
| 247 | count = apple525_get_count(device); |
| 248 | |
| 249 | for (i = 0; i < count; i++) |
| 250 | { |
| 251 | if (apple525_enable_mask & (1 << i)) |
| 252 | return apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i); |
| 253 | } |
| 254 | return NULL; |
| 255 | } |
| 256 | |
| 257 | UINT8 apple525_read_data(device_t *device) |
| 258 | { |
| 259 | device_t *image; |
| 260 | image = apple525_selected_image(device); |
| 261 | return image ? apple525_process_byte(image, -1) : 0xFF; |
| 262 | } |
| 263 | |
| 264 | void apple525_write_data(device_t *device,UINT8 data) |
| 265 | { |
| 266 | device_t *image; |
| 267 | image = apple525_selected_image(device); |
| 268 | if (image) |
| 269 | apple525_process_byte(image, data); |
| 270 | } |
| 271 | |
| 272 | int apple525_read_status(device_t *device) |
| 273 | { |
| 274 | int i, count, result = 0; |
| 275 | device_image_interface *image; |
| 276 | |
| 277 | count = apple525_get_count(device); |
| 278 | |
| 279 | for (i = 0; i < count; i++) |
| 280 | { |
| 281 | if (apple525_enable_mask & (1 << i)) |
| 282 | { |
| 283 | image = dynamic_cast<device_image_interface *>(apple525_get_device_by_type(device, FLOPPY_TYPE_APPLE, i)); |
| 284 | if (image && image->is_readonly()) |
| 285 | result = 1; |
| 286 | } |
| 287 | } |
| 288 | return result; |
| 289 | } |
| 290 | |
| 291 | // device type definition |
| 292 | const device_type FLOPPY_APPLE = &device_creator<apple525_floppy_image_device>; |
| 293 | |
| 294 | //------------------------------------------------- |
| 295 | // apple525_floppy_image_device - constructor |
| 296 | //------------------------------------------------- |
| 297 | |
| 298 | apple525_floppy_image_device::apple525_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 299 | : legacy_floppy_image_device(mconfig, FLOPPY_APPLE, "Apple Disk II", tag, owner, clock) |
| 300 | { |
| 301 | } |
| 302 | |
| 303 | //------------------------------------------------- |
| 304 | // device_start - device-specific startup |
| 305 | //------------------------------------------------- |
| 306 | |
| 307 | void apple525_floppy_image_device::device_start() |
| 308 | { |
| 309 | legacy_floppy_image_device::device_start(); |
| 310 | floppy_set_type(this,FLOPPY_TYPE_APPLE); |
| 311 | |
| 312 | state = 0; |
| 313 | tween_tracks = 0; |
| 314 | track_loaded = 0; |
| 315 | track_dirty = 0; |
| 316 | position = 0; |
| 317 | spin_count = 0; |
| 318 | memset(track_data, 0, sizeof(track_data)); |
| 319 | } |
| 320 | |
| 321 | bool apple525_floppy_image_device::call_load() |
| 322 | { |
| 323 | int result = legacy_floppy_image_device::call_load(); |
| 324 | floppy_drive_seek(*this, -999); |
| 325 | floppy_drive_seek(*this, +35/2); |
| 326 | return result; |
| 327 | } |
| 328 | |
| 329 | void apple525_floppy_image_device::call_unload() |
| 330 | { |
| 331 | apple525_save_current_track(this, TRUE); |
| 332 | |
| 333 | legacy_floppy_image_device::call_unload(); |
| 334 | } |
trunk/src/mess/machine/appldriv.h
| r0 | r21306 | |
| 1 | /********************************************************************* |
| 2 | |
| 3 | appldriv.h |
| 4 | |
| 5 | Apple 5.25" floppy drive emulation (to be interfaced with applefdc.c) |
| 6 | |
| 7 | *********************************************************************/ |
| 8 | |
| 9 | #ifndef APPLDRIV_H |
| 10 | #define APPLDRIV_H |
| 11 | |
| 12 | #include "emu.h" |
| 13 | #include "imagedev/flopdrv.h" |
| 14 | #include "formats/ap2_dsk.h" |
| 15 | |
| 16 | void apple525_set_lines(device_t *device,UINT8 lines); |
| 17 | void apple525_set_enable_lines(device_t *device,int enable_mask); |
| 18 | |
| 19 | UINT8 apple525_read_data(device_t *device); |
| 20 | void apple525_write_data(device_t *device,UINT8 data); |
| 21 | int apple525_read_status(device_t *device); |
| 22 | int apple525_get_count(running_machine &machine); |
| 23 | |
| 24 | class apple525_floppy_image_device : public legacy_floppy_image_device |
| 25 | { |
| 26 | public: |
| 27 | // construction/destruction |
| 28 | apple525_floppy_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 29 | |
| 30 | virtual bool call_load(); |
| 31 | virtual void call_unload(); |
| 32 | void set_params(int dividend, int divisor) { m_dividend = dividend; m_divisor = divisor;} |
| 33 | |
| 34 | int get_dividend() { return m_dividend; } |
| 35 | int get_divisor() { return m_divisor; } |
| 36 | |
| 37 | // these elements should be private, but are not yet |
| 38 | unsigned int state : 4; /* bits 0-3 are the phase */ |
| 39 | unsigned int tween_tracks : 1; |
| 40 | unsigned int track_loaded : 1; |
| 41 | unsigned int track_dirty : 1; |
| 42 | int position; |
| 43 | int spin_count; /* simulate drive spin to fool RWTS test at $BD34 */ |
| 44 | UINT8 track_data[APPLE2_NIBBLE_SIZE * APPLE2_SECTOR_COUNT]; |
| 45 | |
| 46 | protected: |
| 47 | virtual void device_start(); |
| 48 | |
| 49 | private: |
| 50 | int m_dividend; |
| 51 | int m_divisor; |
| 52 | }; |
| 53 | |
| 54 | // device type definition |
| 55 | extern const device_type FLOPPY_APPLE; |
| 56 | |
| 57 | #define MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ |
| 58 | downcast<apple525_floppy_image_device *>(device)->set_params(_dividend,_divisor); |
| 59 | |
| 60 | #define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_ADD(_config,_dividend,_divisor) \ |
| 61 | MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ |
| 62 | MCFG_DEVICE_CONFIG(_config) \ |
| 63 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ |
| 64 | MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ |
| 65 | MCFG_DEVICE_CONFIG(_config) \ |
| 66 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) |
| 67 | |
| 68 | #define MCFG_LEGACY_FLOPPY_APPLE_4_DRIVES_ADD(_config,_dividend,_divisor) \ |
| 69 | MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY_APPLE, 0) \ |
| 70 | MCFG_DEVICE_CONFIG(_config) \ |
| 71 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ |
| 72 | MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY_APPLE, 0) \ |
| 73 | MCFG_DEVICE_CONFIG(_config) \ |
| 74 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ |
| 75 | MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY_APPLE, 0) \ |
| 76 | MCFG_DEVICE_CONFIG(_config) \ |
| 77 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) \ |
| 78 | MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY_APPLE, 0) \ |
| 79 | MCFG_DEVICE_CONFIG(_config) \ |
| 80 | MCFG_LEGACY_FLOPPY_APPLE_PARAMS(_dividend,_divisor) |
| 81 | |
| 82 | #define MCFG_LEGACY_FLOPPY_APPLE_2_DRIVES_REMOVE() \ |
| 83 | MCFG_DEVICE_REMOVE(FLOPPY_0) \ |
| 84 | MCFG_DEVICE_REMOVE(FLOPPY_1) |
| 85 | |
| 86 | #endif /* APPLDRIV_H */ |