diff options
Diffstat (limited to 'trunk/src/lib/formats/ami_dsk.c')
-rw-r--r-- | trunk/src/lib/formats/ami_dsk.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/trunk/src/lib/formats/ami_dsk.c b/trunk/src/lib/formats/ami_dsk.c new file mode 100644 index 00000000000..7b6b6e44751 --- /dev/null +++ b/trunk/src/lib/formats/ami_dsk.c @@ -0,0 +1,180 @@ +/*************************************************************************** + + 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/ami_dsk.c + + Amiga disk images + +*********************************************************************/ + +#include "formats/ami_dsk.h" + +adf_format::adf_format() : floppy_image_format_t() +{ +} + +const char *adf_format::name() const +{ + return "adf"; +} + +const char *adf_format::description() const +{ + return "Amiga ADF floppy disk image"; +} + +const char *adf_format::extensions() const +{ + return "adf"; +} + +bool adf_format::supports_save() const +{ + return true; +} + +int adf_format::identify(io_generic *io, UINT32 form_factor) +{ + UINT64 size = io_generic_size(io); + if ((size == 901120) || (size == 1802240)) + { + return 50; + } + return 0; +} + +bool adf_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) +{ + desc_s sectors[22]; + UINT8 sectdata[512*22]; + for(int i=0; i<22; i++) { + sectors[i].data = sectdata + 512*i; + sectors[i].size = 512; + sectors[i].sector_id = i; + } + + UINT64 size = io_generic_size(io); + if(size == 901120) { + image->set_variant(floppy_image::DSDD); + for(int track=0; track < 80; track++) { + for(int side=0; side < 2; side++) { + io_generic_read(io, sectdata, (track*2 + side)*512*11, 512*11); + generate_track(amiga_11, track, side, sectors, 11, 100000, image); + } + } + } else { + image->set_variant(floppy_image::DSHD); + for(int track=0; track < 80; track++) { + for(int side=0; side < 2; side++) { + io_generic_read(io, sectdata, (track*2 + side)*512*22, 512*22); + generate_track(amiga_22, track, side, sectors, 22, 200000, image); + } + } + } + + return true; +} + +UINT32 adf_format::g32(const UINT8 *trackbuf, int track_size, int pos) +{ + if(pos >= 0 && track_size-pos >= 40) { + int pp = pos >> 3; + int dp = pos & 7; + return + (trackbuf[pp] << (24+dp)) | + (trackbuf[pp+1] << (16+dp)) | + (trackbuf[pp+2] << (8+dp)) | + (trackbuf[pp+3] << dp) | + (trackbuf[pp+4] >> (8-dp)); + } else { + UINT32 res = 0; + for(int i=0; i<32; i++) { + int pp = (pos+i) % track_size; + if(trackbuf[pp>>3] & (0x80 >> (pp & 7))) + res |= 0x80000000 >> i; + } + return res; + } +} + +UINT32 adf_format::checksum(const UINT8 *trackbuf, int track_size, int pos, int long_count) +{ + UINT32 check = 0; + for(int i=0; i<long_count; i++) + check ^= g32(trackbuf, track_size, pos+32*i); + return check & 0x55555555; +} + +bool adf_format::save(io_generic *io, floppy_image *image) +{ + UINT8 sectdata[512*22]; + UINT8 trackbuf[300000/8]; + + bool hd = image->get_variant() == floppy_image::DSHD; + + int data_track_size = hd ? 512*22 : 512*11; + + for(int track=0; track < 80; track++) { + for(int side=0; side < 2; side++) { + int track_size; + generate_bitstream_from_track(track, side, hd ? 1000 : 2000, trackbuf, track_size, image); + + for(int i=0; i<track_size; i++) + if(g32(trackbuf, track_size, i) == 0x44894489 && + (g32(trackbuf, track_size, i+384) & 0x55555555) == checksum(trackbuf, track_size, i+32, 10) && + (g32(trackbuf, track_size, i+448) & 0x55555555) == checksum(trackbuf, track_size, i+480, 256)) { + + UINT32 head = ((g32(trackbuf, track_size, i+32) & 0x55555555) << 1) | (g32(trackbuf, track_size, i+64) & 0x55555555); + int sect = (head >> 8) & 0xff; + if(sect > (hd ? 22 : 11)) + continue; + + UINT8 *dest = sectdata + 512*sect; + for(int j=0; j<128; j++) { + UINT32 val = ((g32(trackbuf, track_size, i+480+32*j) & 0x55555555) << 1) | (g32(trackbuf, track_size, i+4576+32*j) & 0x55555555); + *dest++ = val >> 24; + *dest++ = val >> 16; + *dest++ = val >> 8; + *dest++ = val; + } + + io_generic_write(io, sectdata, (track*2 + side)*data_track_size, data_track_size); + } + } + } + return true; +} + +const floppy_format_type FLOPPY_ADF_FORMAT = &floppy_image_format_creator<adf_format>; |