diff options
author | Olivier Galibert <galibert@pobox.com> | 2012-11-15 20:19:53 +0000 |
---|---|---|
committer | Olivier Galibert <galibert@pobox.com> | 2012-11-15 20:19:53 +0000 |
commit | 6a43e78d976ee3473916a4ae9257dfb925385536 (patch) | |
tree | 21706d6801460e6aca6263a081398534fff74735 | |
parent | 63388ba30fd25abaecd00ed5fd316c55051b7550 (diff) |
(mess) floppy: Add IMD support [O. Galibert]
-rw-r--r-- | src/lib/formats/flopimg.c | 11 | ||||
-rw-r--r-- | src/lib/formats/flopimg.h | 2 | ||||
-rw-r--r-- | src/lib/formats/imd_dsk.c | 301 | ||||
-rw-r--r-- | src/mess/drivers/apc.c | 8 |
4 files changed, 319 insertions, 3 deletions
diff --git a/src/lib/formats/flopimg.c b/src/lib/formats/flopimg.c index 388c4ca7533..a4a3189168f 100644 --- a/src/lib/formats/flopimg.c +++ b/src/lib/formats/flopimg.c @@ -1190,6 +1190,17 @@ void floppy_image_format_t::mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val } } +void floppy_image_format_t::fm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size) +{ + int prec = offset ? bit_r(buffer, offset-1) : 0; + for(int i=n-1; i>=0; i--) { + int bit = (val >> i) & 1; + bit_w(buffer, offset++, true); + bit_w(buffer, offset++, bit, size); + prec = bit; + } +} + void floppy_image_format_t::mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size) { int prec = offset ? bit_r(buffer, offset-1) : 0; diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 6858aa6f6af..a51cb8570aa 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -510,6 +510,8 @@ protected: 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); + //! FM-encode and write a series of bits + void fm_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 diff --git a/src/lib/formats/imd_dsk.c b/src/lib/formats/imd_dsk.c index 5ae14faad92..79b9f2663c6 100644 --- a/src/lib/formats/imd_dsk.c +++ b/src/lib/formats/imd_dsk.c @@ -273,3 +273,304 @@ FLOPPY_CONSTRUCT( imd_dsk_construct ) return FLOPPY_ERROR_SUCCESS; } + +/*************************************************************************** + + Copyright Olivier Galibert + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +****************************************************************************/ + +/********************************************************************* + + formats/imd_dsk.h + + IMD disk images + +*********************************************************************/ + +#include "emu.h" +#include "imd_dsk.h" + +imd_format::imd_format() +{ +} + +const char *imd_format::name() const +{ + return "imd"; +} + +const char *imd_format::description() const +{ + return "IMD disk image"; +} + +const char *imd_format::extensions() const +{ + return "imd"; +} + +void imd_format::fixnum(char *start, char *end) const +{ + end--; + if(*end != '0') + return; + while(end > start) { + end--; + if(*end == ' ') + *end = '0'; + else if(*end != '0') + return; + }; +} + +int imd_format::identify(io_generic *io, UINT32 form_factor) +{ + char h[32]; + + io_generic_read(io, h, 0, 31); + h[31] = 0; + for(int i=0; i != 31; i++) + if(h[i] >= '0' && h[i] <= '9')\ + h[i] = '0'; + + fixnum(h+10, h+12); + fixnum(h+13, h+15); + fixnum(h+16, h+20); + fixnum(h+21, h+23); + fixnum(h+24, h+26); + fixnum(h+27, h+29); + + if(!strcmp(h, "IMD 0.00: 00/00/0000 00:00:00\015\012")) + return 100; + + return 0; +} + +// 1.1.1.1.1.1.0.0 - fc +// 1.1.0.1.0.1.1.1 +// f77a + +// 1.1.1.1.1.1.1.0 - fe +// 1.1.0.0.0.1.1.1 +// f57e + +// 1.1.1.1.1.0.1.1 - fb +// 1.1.0.0.0.1.1.1 +// f56f + +// 1.1.1.1.1.0.0.0 - f8 +// 1.1.0.0.0.1.1.1 +// f56a + +bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) +{ + int size = io_generic_size(io); + UINT8 *img = global_alloc_array(UINT8, size); + io_generic_read(io, img, 0, size); + + int pos; + for(pos=0; pos < size && img[pos] != 0x1a; pos++); + pos++; + + if(pos >= size) + return false; + + while(pos < size) { + UINT8 mode = img[pos++]; + UINT8 track = img[pos++]; + UINT8 head = img[pos++]; + UINT8 sector_count = img[pos++]; + UINT8 ssize = img[pos++]; + + if(ssize == 0xff) + throw emu_fatalerror("imd_format: Unsupported variable sector size on track %d head %d", track, head); + + UINT32 size = ssize < 7 ? 128 << ssize : 8192; + + static const int rates[3] = { 500000, 300000, 250000 }; + bool fm = mode < 3; + int rate = rates[mode % 3]; + int rpm = form_factor == floppy_image::FF_8 || (floppy_image::FF_525 && rate >= 300) ? 360 : 300; + int cell_count = (fm ? 1 : 2)*rate*60/rpm; + + const UINT8 *snum = img+pos; + pos += sector_count; + const UINT8 *tnum = head & 0x80 ? img+pos : NULL; + if(tnum) + pos += sector_count; + const UINT8 *hnum = head & 0x40 ? img+pos : NULL; + if(hnum) + pos += sector_count; + + head &= 0x3f; + + UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000); + int tpos = 0; + + // gap 4a , IAM and gap 1 + if(fm) { + for(int i=0; i<40; i++) fm_w(track_data, tpos, 8, 0xff); + for(int i=0; i< 6; i++) fm_w(track_data, tpos, 8, 0x00); + raw_w(track_data, tpos, 16, 0xf77a); + for(int i=0; i<26; i++) fm_w(track_data, tpos, 8, 0xff); + } else { + for(int i=0; i<80; i++) mfm_w(track_data, tpos, 8, 0x4e); + for(int i=0; i<12; i++) mfm_w(track_data, tpos, 8, 0x00); + for(int i=0; i< 3; i++) raw_w(track_data, tpos, 16, 0x5224); + mfm_w(track_data, tpos, 8, 0xfc); + for(int i=0; i<50; i++) mfm_w(track_data, tpos, 8, 0x4e); + } + + // Compute the available and expected size for gap3 + int gap3 = form_factor == floppy_image::FF_8 ? 25 : + ssize < 512 ? + (form_factor == floppy_image::FF_35 ? 54 : 50) : + (form_factor == floppy_image::FF_35 ? 84 : 80); + + int etpos = tpos; + if(fm) + etpos += sector_count*(6+5+2+11+6+1+ssize+2)*16; + else + etpos += sector_count*(12+3+5+2+22+12+3+1+ssize+2)*16; + + if(etpos > cell_count) + throw emu_fatalerror("imd_format: Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos); + + if(etpos + gap3*16*(sector_count-1) > cell_count) + gap3 = (cell_count - etpos) / 16 / (sector_count-1); + + // Build the track + if(fm) { + for(int i=0; i<sector_count; i++) { + UINT8 stype = img[pos++]; + + int cpos; + UINT16 crc; + // sync and IDAM and gap 2 + for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0xff); + cpos = tpos; + raw_w(track_data, tpos, 8, 0xf57e); + fm_w (track_data, tpos, 8, tnum ? tnum[i] : track); + fm_w (track_data, tpos, 8, hnum ? hnum[i] : head); + fm_w (track_data, tpos, 8, snum[i]); + fm_w (track_data, tpos, 8, ssize); + crc = calc_crc_ccitt(track_data, cpos, tpos); + fm_w (track_data, tpos, 16, crc); + for(int j=0; j<11; j++) fm_w(track_data, tpos, 8, 0xff); + + if(stype == 0 || stype > 8) + for(int j=0; j<6+1+size+2+gap3; j++) fm_w(track_data, tpos, 8, 0xff); + + else { + // sync, DAM, data and gap 3 + for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0xff); + cpos = tpos; + raw_w(track_data, tpos, 8, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf56a : 0xf56f); + if(stype == 2 || stype == 4 || stype == 6 || stype == 8) { + for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos]); + pos++; + } else + for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos++]); + crc = calc_crc_ccitt(track_data, cpos, tpos); + if(stype == 5 || stype == 6 || stype == 7 || stype == 8) + crc = 0xffff^crc; + fm_w(track_data, tpos, 16, crc); + for(int j=0; j<gap3; j++) fm_w(track_data, tpos, 8, 0xff); + } + } + + // Gap 4b + + while(tpos < cell_count-15) fm_w(track_data, tpos, 8, 0xff); + raw_w(track_data, tpos, cell_count-tpos, 0xffff >> (16+tpos-cell_count)); + + } else { + for(int i=0; i<sector_count; i++) { + UINT8 stype = img[pos++]; + + int cpos; + UINT16 crc; + // sync and IDAM and gap 2 + for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); + cpos = tpos; + for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); + mfm_w(track_data, tpos, 8, 0xfe); + mfm_w(track_data, tpos, 8, tnum ? tnum[i] : track); + mfm_w(track_data, tpos, 8, hnum ? hnum[i] : head); + mfm_w(track_data, tpos, 8, snum[i]); + mfm_w(track_data, tpos, 8, ssize); + crc = calc_crc_ccitt(track_data, cpos, tpos); + mfm_w(track_data, tpos, 16, crc); + for(int j=0; j<22; j++) mfm_w(track_data, tpos, 8, 0x4e); + + if(stype == 0 || stype > 8) + for(int j=0; j<12+4+size+2+gap3; j++) mfm_w(track_data, tpos, 8, 0x4e); + + else { + // sync, DAM, data and gap 3 + for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); + cpos = tpos; + for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); + mfm_w(track_data, tpos, 8, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf8 : 0xfb); + if(stype == 2 || stype == 4 || stype == 6 || stype == 8) { + for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos]); + pos++; + } else + for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos++]); + if(stype == 5 || stype == 6 || stype == 7 || stype == 8) + crc = 0xffff^crc; + crc = calc_crc_ccitt(track_data, cpos, tpos); + mfm_w(track_data, tpos, 16, crc); + for(int j=0; j<gap3; j++) mfm_w(track_data, tpos, 8, 0x4e); + } + } + + // Gap 4b + + while(tpos < cell_count-15) mfm_w(track_data, tpos, 8, 0x4e); + raw_w(track_data, tpos, cell_count-tpos, 0x9254 >> (16+tpos-cell_count)); + } + + generate_track_from_levels(track, head, track_data, cell_count, 0, image); + global_free(track_data); + } + + global_free(img); + return true; +} + + +bool imd_format::supports_save() const +{ + return false; +} + +const floppy_format_type FLOPPY_IMD_FORMAT = &floppy_image_format_creator<imd_format>; diff --git a/src/mess/drivers/apc.c b/src/mess/drivers/apc.c index f8b9f5d149e..a811011393e 100644 --- a/src/mess/drivers/apc.c +++ b/src/mess/drivers/apc.c @@ -60,6 +60,7 @@ #include "imagedev/flopdrv.h" #include "formats/mfi_dsk.h" #include "formats/d88_dsk.h" +#include "formats/imd_dsk.h" //#include "sound/ay8910.h" class apc_state : public driver_device @@ -606,8 +607,9 @@ static I8237_INTERFACE( dma8237_config ) static const floppy_format_type apc_floppy_formats[] = { FLOPPY_D88_FORMAT, + FLOPPY_IMD_FORMAT, FLOPPY_MFI_FORMAT, - NULL // TODO: IMD + NULL }; static SLOT_INTERFACE_START( apc_floppies ) @@ -647,8 +649,8 @@ static MACHINE_CONFIG_START( apc, apc_state ) MCFG_SCREEN_REFRESH_RATE(60) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) MCFG_SCREEN_UPDATE_DRIVER(apc_state, screen_update) - MCFG_SCREEN_SIZE(32*8, 32*8) - MCFG_SCREEN_VISIBLE_AREA(0*8, 32*8-1, 0*8, 32*8-1) + MCFG_SCREEN_SIZE(640, 494) + MCFG_SCREEN_VISIBLE_AREA(0*8, 640-1, 0*8, 494-1) MCFG_GFXDECODE(apc) |