diff --git a/.gitattributes b/.gitattributes index 680964b4fb7..4f5ee594ad5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -810,8 +810,6 @@ src/emu/machine/adc1213x.c svneol=native#text/plain src/emu/machine/adc1213x.h svneol=native#text/plain src/emu/machine/am53cf96.c svneol=native#text/plain src/emu/machine/am53cf96.h svneol=native#text/plain -src/emu/machine/am8530h.c svneol=native#text/plain -src/emu/machine/am8530h.h svneol=native#text/plain src/emu/machine/amigafdc.c svneol=native#text/plain src/emu/machine/amigafdc.h svneol=native#text/plain src/emu/machine/at28c16.c svneol=native#text/plain diff --git a/src/emu/cpu/m68000/m68kfpu.c b/src/emu/cpu/m68000/m68kfpu.c index adeb77591db..a8ceb390b53 100644 --- a/src/emu/cpu/m68000/m68kfpu.c +++ b/src/emu/cpu/m68000/m68kfpu.c @@ -1823,12 +1823,60 @@ static void do_frestore_null(m68ki_cpu_core *m68k) m68k->fpu_just_reset = 1; } +static void m68040_do_fsave(m68ki_cpu_core *m68k, UINT32 addr, int reg, int inc) +{ + if (m68k->fpu_just_reset) + { + m68ki_write_32(m68k, addr, 0); + } + else + { + // we normally generate an IDLE frame + if(reg != -1) + REG_A(m68k)[reg] += inc ? 6*4 : -6*4; + perform_fsave(m68k, addr, inc); + } +} + +static void m68040_do_frestore(m68ki_cpu_core *m68k, UINT32 addr, int reg) +{ + UINT32 temp = m68ki_read_32(m68k, addr); + + // check for NULL frame + if (temp & 0xff000000) + { + // we don't handle non-NULL frames + m68k->fpu_just_reset = 0; + + if (reg != -1) + { + // how about an IDLE frame? + if ((temp & 0x00ff0000) == 0x00180000) + { + REG_A(m68k)[reg] += 6*4; + } // check UNIMP + else if ((temp & 0x00ff0000) == 0x00380000) + { + REG_A(m68k)[reg] += 14*4; + } // check BUSY + else if ((temp & 0x00ff0000) == 0x00b40000) + { + REG_A(m68k)[reg] += 45*4; + } + } + } + else + { + do_frestore_null(m68k); + } +} + void m68040_fpu_op1(m68ki_cpu_core *m68k) { int ea = m68k->ir & 0x3f; int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); - UINT32 addr, temp; + UINT32 addr; switch ((m68k->ir >> 6) & 0x3) { @@ -1838,50 +1886,47 @@ void m68040_fpu_op1(m68ki_cpu_core *m68k) { case 2: // (An) addr = REG_A(m68k)[reg]; - - if (m68k->fpu_just_reset) - { - m68ki_write_32(m68k, addr, 0); - } - else - { - // we normally generate an IDLE frame - perform_fsave(m68k, addr, 1); - } + m68040_do_fsave(m68k, addr, -1, 1); break; case 3: // (An)+ - addr = EA_AY_PI_32(m68k); + addr = EA_AY_PI_32(m68k); + m68040_do_fsave(m68k, addr, reg, 1); + break; - if (m68k->fpu_just_reset) - { - m68ki_write_32(m68k, addr, 0); - } - else - { - // we normally generate an IDLE frame - REG_A(m68k)[reg] += 6*4; - perform_fsave(m68k, addr, 1); - } - break; + case 4: // -(An) + addr = EA_AY_PD_32(m68k); + m68040_do_fsave(m68k, addr, reg, 0); + break; - case 4: // -(An) - addr = EA_AY_PD_32(m68k); + case 5: // (D16, An) + addr = EA_AY_DI_16(m68k); + m68040_do_fsave(m68k, addr, -1, 0); + break; - if (m68k->fpu_just_reset) + case 7: // + switch (reg) + { + case 1: // (abs32) { - m68ki_write_32(m68k, addr, 0); + addr = EA_AL_32(m68k); + m68040_do_fsave(m68k, addr, -1, 1); + break; } - else + case 2: // (d16, PC) { - // we normally generate an IDLE frame - REG_A(m68k)[reg] -= 6*4; - perform_fsave(m68k, addr, 0); + addr = EA_PCDI_16(m68k); + m68040_do_fsave(m68k, addr, -1, 1); + break; } - break; + default: + fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); + } - default: - fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); + break; + + default: + fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); } break; } @@ -1891,95 +1936,44 @@ void m68040_fpu_op1(m68ki_cpu_core *m68k) { switch (mode) { - case 2: // (An) - addr = REG_A(m68k)[reg]; - temp = m68ki_read_32(m68k, addr); + case 2: // (An) + addr = REG_A(m68k)[reg]; + m68040_do_frestore(m68k, addr, -1); + break; - // check for NULL frame - if (temp & 0xff000000) + case 3: // (An)+ + addr = EA_AY_PI_32(m68k); + m68040_do_frestore(m68k, addr, reg); + break; + + case 5: // (D16, An) + addr = EA_AY_DI_16(m68k); + m68040_do_frestore(m68k, addr, -1); + break; + + case 7: // + switch (reg) + { + case 1: // (abs32) { - // we don't handle non-NULL frames and there's no pre/post inc/dec to do here - m68k->fpu_just_reset = 0; + addr = EA_AL_32(m68k); + m68040_do_frestore(m68k, addr, -1); + break; } - else + case 2: // (d16, PC) { - do_frestore_null(m68k); + addr = EA_PCDI_16(m68k); + m68040_do_frestore(m68k, addr, -1); + break; } - break; + default: + fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); + } - case 3: // (An)+ - addr = EA_AY_PI_32(m68k); - temp = m68ki_read_32(m68k, addr); + break; - // check for NULL frame - if (temp & 0xff000000) - { - m68k->fpu_just_reset = 0; - - // how about an IDLE frame? - if ((temp & 0x00ff0000) == 0x00180000) - { - REG_A(m68k)[reg] += 6*4; - } // check UNIMP - else if ((temp & 0x00ff0000) == 0x00380000) - { - REG_A(m68k)[reg] += 14*4; - } // check BUSY - else if ((temp & 0x00ff0000) == 0x00b40000) - { - REG_A(m68k)[reg] += 45*4; - } - } - else - { - do_frestore_null(m68k); - } - break; - - case 5: // (D16, An) - addr = EA_AY_DI_16(m68k); - temp = m68ki_read_32(m68k, addr); - - // check for NULL frame - if (temp & 0xff000000) - { - // we don't handle non-NULL frames and there's no pre/post inc/dec to do here - m68k->fpu_just_reset = 0; - } - else - { - do_frestore_null(m68k); - } - break; - - case 7: // - switch (reg) - { - case 2: // (d16, PC) - { - addr = EA_PCDI_16(m68k);; - temp = m68ki_read_32(m68k, addr); - - // check for NULL frame - if (temp & 0xff000000) - { - // we don't handle non-NULL frames and there's no pre/post inc/dec to do here - m68k->fpu_just_reset = 0; - } - else - { - do_frestore_null(m68k); - } - break; - } - default: - fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); - } - - break; - - default: - fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); + default: + fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); } break; } diff --git a/src/emu/delegate.h b/src/emu/delegate.h index 2c2a9ebd711..9bf0c674d42 100644 --- a/src/emu/delegate.h +++ b/src/emu/delegate.h @@ -761,5 +761,8 @@ public: delegate &operator=(const basetype &src) { *static_cast(this) = src; return *this; } }; +// Some useful delegates + +typedef delegate line_cb_t; #endif /* __DELEGATE_H__ */ diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 290a2710410..8cd85435986 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -165,7 +165,6 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/adc1038.o \ $(EMUMACHINE)/adc1213x.o \ $(EMUMACHINE)/am53cf96.o \ - $(EMUMACHINE)/am8530h.o \ $(EMUMACHINE)/amigafdc.o \ $(EMUMACHINE)/at28c16.o \ $(EMUMACHINE)/cdp1852.o \ diff --git a/src/emu/machine/am8530h.c b/src/emu/machine/am8530h.c deleted file mode 100644 index 7c5e311f908..00000000000 --- a/src/emu/machine/am8530h.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "am8530h.h" - -const device_type AM8530H = &device_creator; - -am8530h_device::am8530h_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, AM8530H, "AM8530H", tag, owner, clock) -{ -} - -void am8530h_device::set_int_change_cb(int_cb_t _int_change_cb) -{ - int_change_cb = _int_change_cb; -} - - -void am8530h_device::device_start() -{ -} - -READ8_MEMBER( am8530h_device::ca_r ) -{ - return 0xff; -} - -READ8_MEMBER( am8530h_device::cb_r ) -{ - return 0xff; -} - -READ8_MEMBER( am8530h_device::da_r ) -{ - return 0x40; -} - -READ8_MEMBER( am8530h_device::db_r ) -{ - return 0x40; -} - -WRITE8_MEMBER( am8530h_device::ca_w ) -{ - fprintf(stderr, "ca_w %x, %02x\n", offset, data); -} - -WRITE8_MEMBER( am8530h_device::cb_w ) -{ - fprintf(stderr, "cb_w %x, %02x\n", offset, data); -} - -WRITE8_MEMBER( am8530h_device::da_w ) -{ - fprintf(stderr, "da_w %x, %02x\n", offset, data); -} - -WRITE8_MEMBER( am8530h_device::db_w ) -{ - fprintf(stderr, "db_w %x, %02x\n", offset, data); -} diff --git a/src/emu/machine/am8530h.h b/src/emu/machine/am8530h.h deleted file mode 100644 index 6797e16e20c..00000000000 --- a/src/emu/machine/am8530h.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __AM8530H_H__ -#define __AM8530H_H__ - -#include "emu.h" - -#define MCFG_AM8530H_ADD(_tag, _int_change_cb) \ - MCFG_DEVICE_ADD(_tag, AM8530H, 0) \ - downcast(device)->set_int_change_cb(_int_change_cb); - -class am8530h_device : public device_t { -public: - typedef delegate int_cb_t; - - am8530h_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - void set_int_change_cb(int_cb_t int_change_cb); - - DECLARE_READ8_MEMBER(ca_r); - DECLARE_READ8_MEMBER(cb_r); - DECLARE_READ8_MEMBER(da_r); - DECLARE_READ8_MEMBER(db_r); - - DECLARE_WRITE8_MEMBER(ca_w); - DECLARE_WRITE8_MEMBER(cb_w); - DECLARE_WRITE8_MEMBER(da_w); - DECLARE_WRITE8_MEMBER(db_w); - - void data_a_w(UINT8 val); - void data_b_w(UINT8 val); - - void int_ack(); - bool int_level_get(); - -protected: - virtual void device_start(); - -private: - int_cb_t int_change_cb; -}; - -extern const device_type AM8530H; - -#endif diff --git a/src/emu/machine/mccs1850.c b/src/emu/machine/mccs1850.c index 38d446d577c..4477985f318 100644 --- a/src/emu/machine/mccs1850.c +++ b/src/emu/machine/mccs1850.c @@ -131,7 +131,8 @@ inline void mccs1850_device::check_interrupt() m_ram[REGISTER_STATUS] &= ~STATUS_IT; } - m_out_int_func(interrupt ? ASSERT_LINE : CLEAR_LINE); + if(!int_cb.isnull()) + int_cb(interrupt); } @@ -139,11 +140,12 @@ inline void mccs1850_device::check_interrupt() // set_pse_line - //------------------------------------------------- -inline void mccs1850_device::set_pse_line(int state) +inline void mccs1850_device::set_pse_line(bool state) { m_pse = state; - m_out_pse_func(m_pse); + if(!pse_cb.isnull()) + pse_cb(m_pse); } @@ -156,6 +158,7 @@ inline UINT8 mccs1850_device::read_register(offs_t offset) switch (offset) { case REGISTER_COUNTER_LATCH: + case REGISTER_COUNTER_LATCH+3: // Required by the NeXT power on test // load counter value into latch m_ram[REGISTER_COUNTER_LATCH] = m_counter >> 24; m_ram[REGISTER_COUNTER_LATCH + 1] = m_counter >> 16; @@ -195,7 +198,7 @@ inline void mccs1850_device::write_register(offs_t offset, UINT8 data) if (data & CONTROL_PD) { if (LOG) logerror("MCCS1850 '%s' Power Down\n", tag()); - set_pse_line(0); + set_pse_line(false); } if (data & CONTROL_AR) @@ -262,7 +265,7 @@ inline void mccs1850_device::advance_seconds() else { // wake up - set_pse_line(1); + set_pse_line(true); } } } @@ -291,27 +294,11 @@ mccs1850_device::mccs1850_device(const machine_config &mconfig, const char *tag, { } - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void mccs1850_device::device_config_complete() +void mccs1850_device::set_cb(cb_t _int_cb, cb_t _pse_cb, cb_t _nuc_cb) { - // inherit a copy of the static data - const mccs1850_interface *intf = reinterpret_cast(static_config()); - if (intf != NULL) - *static_cast(this) = *intf; - - // or initialize to defaults if none provided - else - { - memset(&m_out_int_cb, 0, sizeof(m_out_int_cb)); - memset(&m_out_pse_cb, 0, sizeof(m_out_pse_cb)); - memset(&m_out_nuc_cb, 0, sizeof(m_out_nuc_cb)); - } + int_cb = _int_cb; + pse_cb = _pse_cb; + nuc_cb = _nuc_cb; } @@ -321,11 +308,6 @@ void mccs1850_device::device_config_complete() void mccs1850_device::device_start() { - // resolve callbacks - m_out_int_func.resolve(m_out_int_cb, *this); - m_out_pse_func.resolve(m_out_pse_cb, *this); - m_out_nuc_func.resolve(m_out_nuc_cb, *this); - // allocate timers m_clock_timer = timer_alloc(TIMER_CLOCK); m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768)); @@ -456,7 +438,7 @@ WRITE_LINE_MEMBER( mccs1850_device::sck_w ) if (m_bits == 8) { - if (LOG) logerror("MCCS1850 '%s' %s Address %u\n", tag(), BIT(m_address, 7) ? "Write" : "Read", m_address & 0x7f); + if (LOG) logerror("MCCS1850 '%s' %s Address %02x\n", tag(), BIT(m_address, 7) ? "Write" : "Read", m_address & 0x7f); m_bits = 0; m_state = STATE_DATA; @@ -559,7 +541,7 @@ WRITE_LINE_MEMBER( mccs1850_device::pwrsw_w ) check_interrupt(); } - set_pse_line(1); + set_pse_line(true); } } diff --git a/src/emu/machine/mccs1850.h b/src/emu/machine/mccs1850.h index da3e43a72d0..7a1427847e7 100644 --- a/src/emu/machine/mccs1850.h +++ b/src/emu/machine/mccs1850.h @@ -31,41 +31,27 @@ // INTERFACE CONFIGURATION MACROS //************************************************************************** -#define MCFG_MCCS1850_ADD(_tag, _clock, _config) \ +#define MCFG_MCCS1850_ADD(_tag, _clock, _int_cb, _pse_cb, _nuc_cb) \ MCFG_DEVICE_ADD(_tag, MCCS1850, _clock) \ - MCFG_DEVICE_CONFIG(_config) - - -#define MCCS1850_INTERFACE(name) \ - const mccs1850_interface (name) = - + downcast(device)->set_cb(_int_cb, _pse_cb, _nuc_cb); //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -// ======================> mccs1850_interface - -struct mccs1850_interface -{ - devcb_write_line m_out_int_cb; - devcb_write_line m_out_pse_cb; - devcb_write_line m_out_nuc_cb; -}; - - - // ======================> mccs1850_device class mccs1850_device : public device_t, public device_rtc_interface, - public device_nvram_interface, - public mccs1850_interface + public device_nvram_interface { public: + typedef delegate cb_t; + // construction/destruction mccs1850_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + void set_cb(cb_t int_cb, cb_t pse_cb, cb_t nuc_cb); DECLARE_WRITE_LINE_MEMBER( ce_w ); DECLARE_WRITE_LINE_MEMBER( sck_w ); @@ -77,7 +63,6 @@ public: protected: // device-level overrides - virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); @@ -93,16 +78,14 @@ protected: private: inline void check_interrupt(); - inline void set_pse_line(int state); + inline void set_pse_line(bool state); inline UINT8 read_register(offs_t offset); inline void write_register(offs_t offset, UINT8 data); inline void advance_seconds(); static const device_timer_id TIMER_CLOCK = 0; - devcb_resolved_write_line m_out_int_func; - devcb_resolved_write_line m_out_pse_func; - devcb_resolved_write_line m_out_nuc_func; + cb_t int_cb, pse_cb, nuc_cb; UINT8 m_ram[0x80]; // RAM diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 5b1bffb3a0e..7b1759affbb 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -213,34 +213,71 @@ UINT64 floppy_image_size(floppy_image_legacy *floppy); /* misc */ const char *floppy_error(floperr_t err); + ////////////////////////////////////////////////////////// -/// New implementation +// New implementation ////////////////////////////////////////////////////////// class floppy_image; +//! Class representing a floppy image format. class floppy_image_format_t { public: floppy_image_format_t(); virtual ~floppy_image_format_t(); - + + /*! @brief Identify an image. + The identify function tests if the image is valid + for this particular format. + @param io buffer containing the image data. + @param form_factor Physical form factor of disk, from the enum + in floppy_image + @return 1 if image valid, 0 otherwise. + */ virtual int identify(io_generic *io, UINT32 form_factor) = 0; - virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image) = 0; + + /*! @brief Load an image. + The load function opens an image file and converts it to the + internal MESS floppy representation. + @param io source buffer containing the image data. + @param form_factor Physical form factor of disk, from the enum + in floppy_image + @param image output buffer for data in MESS internal format. + @return true on success, false otherwise. + */ + virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image) = 0; + + /*! @brief Save an image. + The save function writes back an image from the MESS internal + floppy representation to the appropriate format on disk. + @param io output buffer for the data in the on-disk format. + @param image source buffer containing data in MESS internal format. + @return true on success, false otherwise. + */ virtual bool save(io_generic *io, floppy_image *image); + //! @returns string containing name of format. virtual const char *name() const = 0; + //! @returns string containing description of format. virtual const char *description() const = 0; + //! @returns string containing comma-separated list of file + //! extensions the format may use. virtual const char *extensions() const = 0; + //! @returns true if format supports saving. virtual bool supports_save() const = 0; + //! Used if a linked list of formats is needed floppy_image_format_t *next; + //! This appends a format to the linked list of formats, needed for floppy_image_device(). void append(floppy_image_format_t *_next); - + //! This checks if the file has the proper extension for this format. + //! @param file_name + //! @returns true if file matches the extension. bool extension_matches(const char *file_name) const; - + protected: - // Input for convert_to_edge + //! Input for convert_to_edge enum { MG_SHIFT = 28, @@ -251,85 +288,105 @@ protected: // **** Reader helpers **** - // Struct designed for easy track data description - // Optional, you can always do things by hand, but useful nevertheless - // A vector of these structures describes one track. - + //! Struct designed for easy track data description. Contains an opcode and two params. + + //! Optional, you can always do things by hand, but useful nevertheless. + //! A vector of these structures describes one track. + struct desc_e { - int type, p1, p2; + int type, //!< An opcode + p1, //!< first param + p2; //!< second param }; - + + //! Opcodes of the format description language used by generate_track() enum { - END, // End of description - MFM, // One byte in p1 to be mfm-encoded, msb first, repeated p2 times - MFMBITS, // A value of p2 bits in p1 to be mfm-encoded, msb first - RAW, // One 16 bits word in p1 to be written raw, msb first, repeated p2 times - RAWBITS, // A value of p2 bits in p1 to be copied as-is, msb first - TRACK_ID, // Track id byte, mfm-encoded - TRACK_ID_GCR6, // Track id low 6 bits, gcr6-encoded - HEAD_ID, // Head id byte, mfm-encoded - TRACK_HEAD_ID_GCR6, // Track id 7th bit + head, gc6-encoded - SECTOR_ID, // Sector id byte, mfm-encoded - SECTOR_ID_GCR6, // Sector id byte, gcr6-encoded - SIZE_ID, // Sector size code on one byte [log2(size/128)], mfm-encoded - SECTOR_INFO_GCR6, // Sector info byte, gcr6-encoded - OFFSET_ID_O, // Offset (track*2+head) byte, odd bits, mfm-encoded - OFFSET_ID_E, // Offset (track*2+head) byte, even bits, mfm-encoded - SECTOR_ID_O, // Sector id byte, odd bits, mfm-encoded - SECTOR_ID_E, // Sector id byte, even bits, mfm-encoded - REMAIN_O, // Remaining sector count, odd bits, mfm-encoded, total sector count in p1 - REMAIN_E, // Remaining sector count, even bits, mfm-encoded, total sector count in p1 + END, //!< End of description + MFM, //!< One byte in p1 to be mfm-encoded, msb first, repeated p2 times + MFMBITS, //!< A value of p2 bits in p1 to be mfm-encoded, msb first + RAW, //!< One 16 bits word in p1 to be written raw, msb first, repeated p2 times + RAWBITS, //!< A value of p2 bits in p1 to be copied as-is, msb first + TRACK_ID, //!< Track id byte, mfm-encoded + TRACK_ID_GCR6, //!< Track id low 6 bits, gcr6-encoded + HEAD_ID, //!< Head id byte, mfm-encoded + TRACK_HEAD_ID_GCR6, //!< Track id 7th bit + head, gc6-encoded + SECTOR_ID, //!< Sector id byte, mfm-encoded + SECTOR_ID_GCR6, //!< Sector id byte, gcr6-encoded + SIZE_ID, //!< Sector size code on one byte [log2(size/128)], mfm-encoded + SECTOR_INFO_GCR6, //!< Sector info byte, gcr6-encoded + OFFSET_ID_O, //!< Offset (track*2+head) byte, odd bits, mfm-encoded + OFFSET_ID_E, //!< Offset (track*2+head) byte, even bits, mfm-encoded + SECTOR_ID_O, //!< Sector id byte, odd bits, mfm-encoded + SECTOR_ID_E, //!< Sector id byte, even bits, mfm-encoded + REMAIN_O, //!< Remaining sector count, odd bits, mfm-encoded, total sector count in p1 + REMAIN_E, //!< Remaining sector count, even bits, mfm-encoded, total sector count in p1 - SECTOR_DATA, // Sector data to mfm-encode, which in p1, -1 for the current one per the sector id - SECTOR_DATA_O, // Sector data to mfm-encode, odd bits only, which in p1, -1 for the current one per the sector id - SECTOR_DATA_E, // Sector data to mfm-encode, even bits only, which in p1, -1 for the current one per the sector id - SECTOR_DATA_MAC, // Transformed sector data + checksum, mac style, id in p1, -1 for the current one per the sector id + SECTOR_DATA, //!< Sector data to mfm-encode, which in p1, -1 for the current one per the sector id + SECTOR_DATA_O, //!< Sector data to mfm-encode, odd bits only, which in p1, -1 for the current one per the sector id + SECTOR_DATA_E, //!< Sector data to mfm-encode, even bits only, which in p1, -1 for the current one per the sector id + SECTOR_DATA_MAC, //!< Transformed sector data + checksum, mac style, id in p1, -1 for the current one per the sector id - CRC_CCITT_START, // Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id - CRC_AMIGA_START, // Start an amiga checksum calculation, p1 = crc id - CRC_MACHEAD_START, // Start of the mac gcr6 sector header checksum calculation (xor of pre-encode 6-bits values, gcr6-encoded) - CRC_END, // End the checksum, p1 = crc id - CRC, // Write a checksum in the apporpriate format, p1 = crc id + CRC_CCITT_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id + CRC_AMIGA_START, //!< Start an amiga checksum calculation, p1 = crc id + CRC_MACHEAD_START, //!< Start of the mac gcr6 sector header checksum calculation (xor of pre-encode 6-bits values, gcr6-encoded) + CRC_END, //!< End the checksum, p1 = crc id + CRC, //!< Write a checksum in the apporpriate format, p1 = crc id - SECTOR_LOOP_START, // Start of the per-sector loop, sector number goes from p1 to p2 inclusive - SECTOR_LOOP_END, // End of the per-sector loop - SECTOR_INTERLEAVE_SKEW, // Defines interleave and skew for sector counting + SECTOR_LOOP_START, //!< Start of the per-sector loop, sector number goes from p1 to p2 inclusive + SECTOR_LOOP_END, //!< End of the per-sector loop + SECTOR_INTERLEAVE_SKEW, //!< Defines interleave and skew for sector counting }; - // Sector data description + //! Sector data description struct desc_s { - int size; // Sector size, int bytes - const UINT8 *data; // Sector data - UINT8 sector_id; // Sector ID - UINT8 sector_info; // Sector free byte + int size; //!< Sector size, int bytes + const UINT8 *data; //!< Sector data + UINT8 sector_id; //!< Sector ID + UINT8 sector_info; //!< Sector free byte }; - // Generate one track according to the description vector - // "sect" is a vector indexed by sector id - // "track_size" is in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm - + /*! @brief Generate one track according to the description vector. + @param desc track data description + @param track + @param head + @param sect a vector indexed by sector id. + @param sect_count number of sectors. + @param track_size in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm. + @param image + */ void generate_track(const desc_e *desc, int track, int head, const desc_s *sect, int sect_count, int track_size, floppy_image *image); - // Generate a track from cell binary values, MSB-first, size in cells and not bytes + /*! @brief Generate a track from cell binary values, MSB-first. + @param track + @param head + @param trackbuf track input buffer. + @param track_size in cells, not bytes. + @param image + */ void generate_track_from_bitstream(int track, int head, const UINT8 *trackbuf, int track_size, floppy_image *image); - // Generate a track from cell level values (0/1/W/D/N) - // - // Splice pos is the position of the track splice. For normal - // formats, use -1. For protected formats, you're supposed to - // know. trackbuf may be modified at that position or after. - // - // Note that this function needs to be able to split cells in two, - // so no time value should be less than 2, and even values are a - // good idea. - + //! @brief Generate a track from cell level values (0/1/W/D/N). + + /*! Note that this function needs to be able to split cells in two, + so no time value should be less than 2, and even values are a + good idea. + */ + /*! @param track + @param head + @param trackbuf track input buffer. + @param track_size in cells, not bytes. + @param splice_pos is the position of the track splice. For normal + formats, use -1. For protected formats, you're supposed to + know. trackbuf may be modified at that position or after. + @param image + */ void generate_track_from_levels(int track, int head, UINT32 *trackbuf, int track_size, int splice_pos, floppy_image *image); - // Normalize the times in a cell buffer to sum up to 200000000 + //! Normalize the times in a cell buffer to sum up to 200000000 void normalize_times(UINT32 *buffer, int bitlen); - // Some conversion tables + // Some conversion tables for gcr6 static const UINT8 gcr6fw_tb[0x40], gcr6bw_tb[0x100]; // Some useful descriptions shared by multiple formats @@ -343,7 +400,7 @@ protected: // Fastcopy Pro optimized formats, with fake sector header for // faster verify and skew/interleave where appropriate - static const desc_e atari_st_fcp_9[]; + static const desc_e atari_st_fcp_9[]; static const desc_e *const atari_st_fcp_10[10]; static const desc_e atari_st_fcp_11[]; @@ -363,83 +420,108 @@ protected: // **** Writer helpers **** - // Rebuild a cell bitstream for a track. Takes the cell standard - // angular size as a parameter, gives out a msb-first bitstream. - // Beware that fuzzy bits will always give out the same value. - // - // Output buffer size should be 34% more than the nominal number - // of cells (the dpll tolerates a cell size down to 75% of the - // nominal one, with gives a cell count of 1/0.75=1.333... times - // the nominal one). - // - // Output size is given in bits (cells). - // - // Computing the standard angular size of a cell is - // simple. Noting: - // d = standard cell duration in microseconds - // r = motor rotational speed in rpm - // then: - // a = r * d * 10 / 3 - // - // Some values: - // Type Cell RPM Size + /*! @brief Rebuild a cell bitstream for a track. + Takes the cell standard + angular size as a parameter, gives out a msb-first bitstream. - // C1541 tr 1-17 3.25 300 3250 - // C1541 tr 18-24 3.50 300 3500 - // C1541 tr 25-30 3.75 300 3750 - // C1541 tr 31+ 4.00 300 4000 - // 5.25" SD 4 300 4000 - // 5.25" DD 2 300 2000 - // 5.25" HD 1 360 1200 - // 3.5" SD 4 300 4000 - // 3.5" DD 2 300 2000 - // 3.5" HD 1 300 1000 - // 3.5" ED 0.5 300 500 + Beware that fuzzy bits will always give out the same value. + @param track + @param head + @param cell_size + @param trackbuf Output buffer size should be 34% more than the nominal number + of cells (the dpll tolerates a cell size down to 75% of the + nominal one, with gives a cell count of 1/0.75=1.333... times + the nominal one). + @param track_size Output size is given in bits (cells). + @param image + */ + /*! @verbatim + Computing the standard angular size of a cell is + simple. Noting: + d = standard cell duration in microseconds + r = motor rotational speed in rpm + then: + a = r * d * 10 / 3. + Some values: + Type Cell RPM Size + + C1541 tr 1-17 3.25 300 3250 + C1541 tr 18-24 3.50 300 3500 + C1541 tr 25-30 3.75 300 3750 + C1541 tr 31+ 4.00 300 4000 + 5.25" SD 4 300 4000 + 5.25" DD 2 300 2000 + 5.25" HD 1 360 1200 + 3.5" SD 4 300 4000 + 3.5" DD 2 300 2000 + 3.5" HD 1 300 1000 + 3.5" ED 0.5 300 500 + @endverbatim + */ void generate_bitstream_from_track(int track, int head, int cell_size, UINT8 *trackbuf, int &track_size, floppy_image *image); - + + //! Defines a standard sector for extracting. struct desc_xs { - int track, head, size; - const UINT8 *data; + int track, //!< Track for this sector + head, //!< Head for this sector + size; //!< Size of this sector + const UINT8 *data; //!< Data within this sector }; - // Extract standard sectors from a regenerated bitstream - // sectors must point to an array of 256 desc_xs - // An existing sector is reconizable by having ->data non-null - // Sector data is written in sectdata up to sectdata_size bytes + //! @brief Extract standard sectors from a regenerated bitstream. + //! Sectors must point to an array of 256 desc_xs. - // The ones implemented here are the ones used by multiple - // systems. + //! An existing sector is recognizable by having ->data non-null. + //! Sector data is written in sectdata up to sectdata_size bytes. - // PC-type sectors with MFM encoding, sector size can go from 128 bytes to 16K + //! The ones implemented here are the ones used by multiple + //! systems. + + //! PC-type sectors with MFM encoding, sector size can go from 128 bytes to 16K. void extract_sectors_from_bitstream_mfm_pc(const UINT8 *bitstream, int track_size, desc_xs *sectors, UINT8 *sectdata, int sectdata_size); - // Get a geometry (including sectors) from an image - // PC-type sectors with MFM encoding + //! @brief Get a geometry (including sectors) from an image. + + //! PC-type sectors with MFM encoding void get_geometry_mfm_pc(floppy_image *image, int cell_size, int &track_count, int &head_count, int §or_count); - // Regenerate the data for a full track - // PC-type sectors with MFM encoding and fixed-size + //! Regenerate the data for a full track. + //! PC-type sectors with MFM encoding and fixed-size. void get_track_data_mfm_pc(int track, int head, floppy_image *image, int cell_size, int sector_size, int sector_count, UINT8 *sectdata); + //! Look up a bit in a level-type stream. bool bit_r(const UINT32 *buffer, int offset); + //! Look up multiple bits UINT32 bitn_r(const UINT32 *buffer, int offset, int count); + //! Write a bit with a given size. void bit_w(UINT32 *buffer, int offset, bool val, UINT32 size = 1000); + //! Calculate a CCITT-type CRC. UINT16 calc_crc_ccitt(const UINT32 *buffer, int start, int end); + //! Write a series of (raw) bits and increment the offset. void raw_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000); + //! MFM-encode and write a series of bits void mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000); + //! MFM-encode every two bits and write void mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size = 1000); + //! GCR6 encode (Apple II 16-sector and Mac-style GCR) UINT32 gcr6_encode(UINT8 va, UINT8 vb, UINT8 vc); + //! GCR6 decode void gcr6_decode(UINT8 e0, UINT8 e1, UINT8 e2, UINT8 e3, UINT8 &va, UINT8 &vb, UINT8 &vc); private: enum { CRC_NONE, CRC_AMIGA, CRC_CCITT, CRC_MACHEAD }; enum { MAX_CRC_COUNT = 64 }; + + //! Holds data used internally for generating CRCs. struct gen_crc_info { - int type, start, end, write; - bool fixup_mfm_clock; + int type, //!< Type of CRC + start, //!< Start position + end, //!< End position + write; //!< where to write the CRC + bool fixup_mfm_clock; //!< would the MFM clock bit after the CRC need to be fixed? }; bool type_no_data(int type) const; @@ -459,7 +541,7 @@ private: int calc_sector_index(int num, int interleave, int skew, int total_sectors, int track_head); }; -// a device_type is simply a pointer to its alloc function +// a dce_type is simply a pointer to its alloc function typedef floppy_image_format_t *(*floppy_format_type)(); // this template function creates a stub which constructs a image format @@ -471,85 +553,132 @@ floppy_image_format_t *floppy_image_format_creator() // ======================> floppy_image -// class representing floppy image +//! Class representing floppy image + +//! Internal format is close but not identical to the mfi format. +//! +//! +//! Track data consists of a series of 32-bits lsb-first values +//! representing magnetic cells. Bits 0-27 indicate the absolute +//! position of the start of the cell (not the size), and bits +//! 28-31 the type. Type can be: +//! - 0, MG_A -> Magnetic orientation A +//! - 1, MG_B -> Magnetic orientation B +//! - 2, MG_N -> Non-magnetized zone (neutral) +//! - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing +//! +//! The position is in angular units of 1/200,000,000th of a turn. +//! The last cell implicit end position is of course 200,000,000. +//! +//! Unformatted tracks are encoded as zero-size. +//! +//! The "track splice" information indicates where to start writing +//! if you try to rewrite a physical disk with the data. Some +//! preservation formats encode that information, it is guessed for +//! others. The write track function of fdcs should set it. The +//! representation is the angular position relative to the index. +//! +//! The media type is divided in two parts. The first half +//! indicates the physical form factor, i.e. all medias with that +//! form factor can be physically inserted in a reader that handles +//! it. The second half indicates the variants which are usually +//! detectable by the reader, such as density and number of sides. + + class floppy_image { public: - // Internal format is close but not identical to the mfi format. - // - // - // Track data consists of a series of 32-bits lsb-first values - // representing magnetic cells. Bits 0-27 indicate the absolute - // position of the start of the cell (not the size), and bits - // 28-31 the type. Type can be: - // - 0, MG_A -> Magnetic orientation A - // - 1, MG_B -> Magnetic orientation B - // - 2, MG_N -> Non-magnetized zone (neutral) - // - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing - // - // The position is in angular units of 1/200,000,000th of a turn. - // The last cell implicit end position is of course 200,000,000. - // - // Unformatted tracks are encoded as zero-size. - // - // The "track splice" information indicates where to start writing - // if you try to rewrite a physical disk with the data. Some - // preservation formats encode that information, it is guessed for - // others. The write track function of fdcs should set it. The - // representation is the angular position relative to the index. - // - // The media type is divided in two parts. The first half - // indicate the physical form factor, i.e. all medias with that - // form factor can be physically inserted in a reader that handles - // it. The second half indicates the variants which are usually - // detectable by the reader, such as density and number of sides. - + //! Floppy format data enum { TIME_MASK = 0x0fffffff, MG_MASK = 0xf0000000, - MG_SHIFT = 28, - - MG_A = (0 << MG_SHIFT), - MG_B = (1 << MG_SHIFT), - MG_N = (2 << MG_SHIFT), - MG_D = (3 << MG_SHIFT) + MG_SHIFT = 28, //!< Bitshift constant for magnetic orientation data + MG_A = (0 << MG_SHIFT), //!< - 0, MG_A -> Magnetic orientation A + MG_B = (1 << MG_SHIFT), //!< - 1, MG_B -> Magnetic orientation B + MG_N = (2 << MG_SHIFT), //!< - 2, MG_N -> Non-magnetized zone (neutral) + MG_D = (3 << MG_SHIFT) //!< - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing }; - // Form factors + + //! Form factors enum { - FF_UNKNOWN = 0x00000000, // Unknown, useful when converting - FF_35 = 0x20203533, // "35 " - FF_525 = 0x20353235, // "525 " + FF_UNKNOWN = 0x00000000, //!< Unknown, useful when converting + FF_35 = 0x20203533, //!< "35 " 3.5 inch disk + FF_525 = 0x20353235, //!< "525 " 5.25 inch disk }; - // Variants + //! Variants enum { - SSSD = 0x44535353, // "SSSD", - SSDD = 0x44445353, // "DSSD", - DSDD = 0x44445344, // "DSDD", - DSHD = 0x44485344, // "DSHD", - DSED = 0x44455344, // "DSED", + SSSD = 0x44535353, //!< "SSSD", Single-sided single-density + SSDD = 0x44445353, //!< "DSSD", Double-sided single-density + DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K) + DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K) + DSED = 0x44455344, //!< "DSED", Double-sided extra-density (2880K) }; - // construction/destruction +// construction/destruction + + + //! floppy_image constructor + /*! + @param _tracks number of tracks. + @param _heads number of heads. + @param _form_factor form factor of drive (from enum) + */ floppy_image(int tracks, int heads, UINT32 form_factor); virtual ~floppy_image(); - + + //! @return the form factor. UINT32 get_form_factor() { return form_factor; } + //! @return the variant. UINT32 get_variant() { return variant; } - void set_variant(UINT32 v) { variant = v; } + //! @param v the variant. + void set_variant(UINT32 v) { variant = v; } + /*! + @param track + @param head + @param size size of this track + */ void set_track_size(int track, int head, UINT32 size) { track_size[track][head] = size; ensure_alloc(track, head); } + + /*! + @param track track number + @param head head number + @return a pointer to the data buffer for this track and head + */ UINT32 *get_buffer(int track, int head) { return cell_data[track][head]; } + //! @return the track size + //! @param track + //! @param head UINT32 get_track_size(int track, int head) { return track_size[track][head]; } - void set_write_splice_position(int track, int head, UINT32 pos) { write_splice[track][head] = pos; } - UINT32 get_write_splice_position(int track, int head) const { return write_splice[track][head]; } - void get_maximal_geometry(int &tracks, int &heads); - void get_actual_geometry(int &tracks, int &heads); + + //! Sets the write splice position. + //! The "track splice" information indicates where to start writing + //! if you try to rewrite a physical disk with the data. Some + //! preservation formats encode that information, it is guessed for + //! others. The write track function of fdcs should set it. The + //! representation is the angular position relative to the index. + /*! @param track + @param head + @param pos the position + */ + void set_write_splice_position(int track, int head, UINT32 pos) { write_splice[track][head] = pos; } + //! @return the current write splice position. + UINT32 get_write_splice_position(int track, int head) const { return write_splice[track][head]; } + //! @return the maximal geometry supported by thie format. + void get_maximal_geometry(int &tracks, int &heads); + //! @return the current geometry of the loaded image. + void get_actual_geometry(int &tracks, int &heads); + //! Returns the variant name for the particular disk form factor/variant + //! @param form_factor + //! @param variant + //! @param returns a string containing the variant name. static const char *get_variant_name(UINT32 form_factor, UINT32 variant); private: + enum { MAX_FLOPPY_HEADS = 2, MAX_FLOPPY_TRACKS = 84