summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/lib/formats/st_dsk.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/lib/formats/st_dsk.c')
-rw-r--r--trunk/src/lib/formats/st_dsk.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/trunk/src/lib/formats/st_dsk.c b/trunk/src/lib/formats/st_dsk.c
new file mode 100644
index 00000000000..1965993feb2
--- /dev/null
+++ b/trunk/src/lib/formats/st_dsk.c
@@ -0,0 +1,356 @@
+/***************************************************************************
+
+ 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/st_dsk.c
+
+ All usual Atari ST formats
+
+*********************************************************************/
+
+#include "emu.h"
+#include "formats/st_dsk.h"
+
+st_format::st_format()
+{
+}
+
+const char *st_format::name() const
+{
+ return "st";
+}
+
+const char *st_format::description() const
+{
+ return "Atari ST floppy disk image";
+}
+
+const char *st_format::extensions() const
+{
+ return "st";
+}
+
+bool st_format::supports_save() const
+{
+ return true;
+}
+
+void st_format::find_size(io_generic *io, int &track_count, int &head_count, int &sector_count)
+{
+ int size = io_generic_size(io);
+ for(track_count=80; track_count <= 82; track_count++)
+ for(head_count=1; head_count <= 2; head_count++)
+ for(sector_count=9; sector_count <= 11; sector_count++)
+ if(size == 512*track_count*head_count*sector_count)
+ return;
+ track_count = head_count = sector_count = 0;
+}
+
+int st_format::identify(io_generic *io, UINT32 form_factor)
+{
+ int track_count, head_count, sector_count;
+ find_size(io, track_count, head_count, sector_count);
+
+ if(track_count)
+ return 50;
+ return 0;
+}
+
+bool st_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
+{
+ int track_count, head_count, sector_count;
+ find_size(io, track_count, head_count, sector_count);
+
+ UINT8 sectdata[11*512];
+ desc_s sectors[11];
+ for(int i=0; i<sector_count; i++) {
+ sectors[i].data = sectdata + 512*i;
+ sectors[i].size = 512;
+ sectors[i].sector_id = i + 1;
+ }
+
+ int track_size = sector_count*512;
+ for(int track=0; track < track_count; track++) {
+ for(int head=0; head < head_count; head++) {
+ io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size);
+ generate_track(atari_st_fcp_get_desc(track, head, head_count, sector_count),
+ track, head, sectors, sector_count, 100000, image);
+ }
+ }
+
+ image->set_variant(floppy_image::DSDD);
+
+ return true;
+}
+
+bool st_format::save(io_generic *io, floppy_image *image)
+{
+ int track_count, head_count, sector_count;
+ get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
+
+ if(track_count < 80)
+ track_count = 80;
+ else if(track_count > 82)
+ track_count = 82;
+
+ // Happens for a fully unformatted floppy
+ if(!head_count)
+ head_count = 1;
+
+ if(sector_count > 11)
+ sector_count = 11;
+ else if(sector_count < 9)
+ sector_count = 9;
+
+ UINT8 sectdata[11*512];
+ int track_size = sector_count*512;
+
+ for(int track=0; track < track_count; track++) {
+ for(int head=0; head < head_count; head++) {
+ get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
+ io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size);
+ }
+ }
+
+ return true;
+}
+
+
+msa_format::msa_format()
+{
+}
+
+const char *msa_format::name() const
+{
+ return "msa";
+}
+
+const char *msa_format::description() const
+{
+ return "Atari MSA floppy disk image";
+}
+
+const char *msa_format::extensions() const
+{
+ return "msa";
+}
+
+bool msa_format::supports_save() const
+{
+ return true;
+}
+
+void msa_format::read_header(io_generic *io, UINT16 &sign, UINT16 &sect, UINT16 &head, UINT16 &strack, UINT16 &etrack)
+{
+ UINT8 h[10];
+ io_generic_read(io, h, 0, 10);
+ sign = (h[0] << 8) | h[1];
+ sect = (h[2] << 8) | h[3];
+ head = (h[4] << 8) | h[5];
+ strack = (h[6] << 8) | h[7];
+ etrack = (h[8] << 8) | h[9];
+}
+
+bool msa_format::uncompress(UINT8 *buffer, int csize, int usize)
+{
+ UINT8 sectdata[11*512];
+ int src=0, dst=0;
+ while(src<csize && dst<usize) {
+ unsigned char c = buffer[src++];
+ if(c == 0xe5) {
+ if(csize-src < 3)
+ return false;
+ c = buffer[src++];
+ int count = (buffer[src] << 8) | buffer[src+1];
+ src += 2;
+ if(usize-dst < count)
+ return false;
+ for(int i=0; i<count; i++)
+ sectdata[dst++] = c;
+ } else
+ sectdata[dst++] = c;
+ }
+
+ if(src != csize || dst != usize)
+ return false;
+ memcpy(buffer, sectdata, usize);
+ return true;
+}
+
+bool msa_format::compress(const UINT8 *buffer, int usize, UINT8 *dest, int &csize)
+{
+ int src=0, dst=0;
+ while(src<usize && dst<usize) {
+ unsigned char c = buffer[src++];
+ int ncopy = 1;
+ while(src < usize && buffer[src] == c) {
+ src++;
+ ncopy++;
+ }
+ if(ncopy > 4 || c == 0xe5) {
+ if(dst+3 > usize)
+ return false;
+ dest[dst++] = 0xe5;
+ dest[dst++] = c;
+ dest[dst++] = ncopy >> 8;
+ dest[dst++] = ncopy;
+ } else {
+ src -= ncopy-1;
+ dest[dst++] = c;
+ }
+ }
+
+ csize = dst;
+
+ return dst < usize;
+}
+
+int msa_format::identify(io_generic *io, UINT32 form_factor)
+{
+ UINT16 sign, sect, head, strack, etrack;
+ read_header(io, sign, sect, head, strack, etrack);
+
+ if(sign == 0x0e0f &&
+ (sect >= 9 && sect <= 11) &&
+ (head == 0 || head == 1) &&
+ strack <= etrack &&
+ etrack < 82)
+ return 100;
+ return 0;
+}
+
+bool msa_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
+{
+ UINT16 sign, sect, heads, strack, etrack;
+ read_header(io, sign, sect, heads, strack, etrack);
+
+ UINT8 sectdata[11*512];
+ desc_s sectors[11];
+ for(int i=0; i<sect; i++) {
+ sectors[i].data = sectdata + 512*1;
+ sectors[i].size = 512;
+ sectors[i].sector_id = i + 1;
+ }
+
+ int pos = 10;
+ int track_size = sect*512;
+
+ for(int track=strack; track <= etrack; track++) {
+ for(int head=0; head <= heads; head++) {
+ UINT8 th[2];
+ io_generic_read(io, th, pos, 2);
+ pos += 2;
+ int tsize = (th[0] << 8) | th[1];
+ io_generic_read(io, sectdata, pos, tsize);
+ pos += tsize;
+ if(tsize < track_size) {
+ if(!uncompress(sectdata, tsize, track_size))
+ return false;
+ }
+ generate_track(atari_st_fcp_get_desc(track, head, head+1, sect),
+ track, head, sectors, sect, 100000, image);
+ }
+ }
+
+ image->set_variant(floppy_image::DSDD);
+ return true;
+}
+
+
+bool msa_format::save(io_generic *io, floppy_image *image)
+{
+ int track_count, head_count, sector_count;
+ get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count);
+
+ if(track_count < 80)
+ track_count = 80;
+ else if(track_count > 82)
+ track_count = 82;
+
+ // Happens for a fully unformatted floppy
+ if(!head_count)
+ head_count = 1;
+
+ if(sector_count > 11)
+ sector_count = 11;
+ else if(sector_count < 9)
+ sector_count = 9;
+
+ UINT8 header[10];
+ header[0] = 0x0e;
+ header[1] = 0x0f;
+ header[2] = 0;
+ header[3] = sector_count;
+ header[4] = 0;
+ header[5] = head_count-1;
+ header[6] = 0;
+ header[7] = 0;
+ header[8] = 0;
+ header[9] = track_count-1;
+
+ io_generic_write(io, header, 0, 10);
+
+ int pos = 10;
+
+ UINT8 sectdata[11*512];
+ UINT8 compdata[11*512];
+ int track_size = sector_count*512;
+
+ for(int track=0; track < track_count; track++) {
+ for(int head=0; head < head_count; head++) {
+ get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
+ int csize;
+ if(compress(sectdata, track_size, compdata, csize)) {
+ UINT8 th[2];
+ th[0] = csize >> 8;
+ th[1] = csize;
+ io_generic_write(io, th, pos, 2);
+ io_generic_write(io, compdata, pos+2, csize);
+ pos += 2+csize;
+ } else {
+ UINT8 th[2];
+ th[0] = track_size >> 8;
+ th[1] = track_size;
+ io_generic_write(io, th, pos, 2);
+ io_generic_write(io, sectdata, pos+2, track_size);
+ pos += 2+track_size;
+ }
+ }
+ }
+
+ return true;
+}
+
+const floppy_format_type FLOPPY_ST_FORMAT = &floppy_image_format_creator<st_format>;
+const floppy_format_type FLOPPY_MSA_FORMAT = &floppy_image_format_creator<msa_format>;