Previous 15994 Revisions Next

r14974 Friday 20th April, 2012 at 05:12:44 UTC by Jonathan Gevaryahu
Modern apple 2 disk decoder for 16-sector disk images implemented using Olivier's new system for floptool. Only supports importing from .dfi 50mhz multi-read x3 images at the moment. [Lord Nightmare, Balrog, Jason Scott, Karsten Scheibler]
[src/lib/formats]ap2_dsk.c ap2_dsk.h
[src/mess/tools/floptool]main.c

src/lib/formats/ap2_dsk.c
r14973r14974
11/*********************************************************************
22
3    ap2_dsk.c
3   ap2_dsk.c
44
5    Apple II disk images
5   Apple II disk images
66
77*********************************************************************/
88
r14973r14974
511511      SECTOR_LENGTH([256])
512512      FIRST_SECTOR_ID([0]))
513513LEGACY_FLOPPY_OPTIONS_END
514
515/***************************************************************************
516
517   New implementation
518
519****************************************************************************
520
521   Copyright Olivier Galibert, Lord Nightmare and Balrog
522   All rights reserved.
523
524   Redistribution and use in source and binary forms, with or without
525   modification, are permitted provided that the following conditions are
526   met:
527
528      * Redistributions of source code must retain the above copyright
529        notice, this list of conditions and the following disclaimer.
530      * Redistributions in binary form must reproduce the above copyright
531        notice, this list of conditions and the following disclaimer in
532        the documentation and/or other materials provided with the
533        distribution.
534      * Neither the name 'MAME' nor the names of its contributors may be
535        used to endorse or promote products derived from this software
536        without specific prior written permission.
537
538   THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
539   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
540   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
541   DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
542   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
543   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
544   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
545   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
546   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
547   IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
548   POSSIBILITY OF SUCH DAMAGE.
549
550****************************************************************************/
551
552
553a2_16sect_format::a2_16sect_format() : floppy_image_format_t()
554{
555}
556
557const char *a2_16sect_format::name() const
558{
559      return "a2_16sect";
560}
561
562const char *a2_16sect_format::description() const
563{
564      return "Apple II 16-sector dsk image";
565}
566
567const char *a2_16sect_format::extensions() const
568{
569      return "dsk";
570}
571
572bool a2_16sect_format::supports_save() const
573{
574      return true;
575}
576
577int a2_16sect_format::identify(io_generic *io, UINT32 form_factor)
578{
579      int size = io_generic_size(io);
580      int expected_size = 35 * 16 * 256;
581      return size == expected_size;
582}
583
584const floppy_image_format_t::desc_e a2_16sect_format::mac_gcr[] = {
585      { SECTOR_LOOP_START, 0, -1 },
586      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
587      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
588      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
589      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
590      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
591      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
592      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
593      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
594      {   RAWBITS, 0xd5aa96, 24 },
595      {   CRC_MACHEAD_START, 0 },
596      {     TRACK_ID_GCR6 },
597      {     SECTOR_ID_GCR6 },
598      {     TRACK_HEAD_ID_GCR6 },
599      {     SECTOR_INFO_GCR6 },
600      {   CRC_END, 0 },
601      {   CRC, 0 },
602      {   RAWBITS, 0xdeaaff, 24 },
603      {   RAWBITS, 0xff3fcf, 24 }, { RAWBITS, 0xf3fcff, 24 },
604      {   RAWBITS, 0xd5aaad, 24 },
605      {   SECTOR_ID_GCR6 },
606      {   SECTOR_DATA_MAC, -1 },
607      {   RAWBITS, 0xdeaaff, 24 },
608      {   RAWBITS, 0xff, 8 },
609      { SECTOR_LOOP_END },
610      { END },
611};
612
613
614bool a2_16sect_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
615{
616
617      UINT8 sector_data[(256)*16];
618      memset(sector_data, 0, sizeof(sector_data));
619
620      desc_s sectors[16];
621      int format = 0;
622      int pos_data = 0;
623
624      int head_count = 1;
625
626      for(int track=0; track < 35; track++) {
627            for(int head=0; head < head_count; head++) {
628                  for(int si=0; si<16; si++) {
629                        UINT8 *data = sector_data + (256)*si;
630                        sectors[si].data = data;
631                        sectors[si].size = 256;
632                        sectors[si].sector_id = si;
633                        sectors[si].sector_info = format;
634                        io_generic_read(io, data, pos_data, 256);
635                        pos_data += 256;
636                  }
637                  generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image);
638            }
639      }
640      return true;
641}
642
643UINT8 a2_16sect_format::gb(const UINT8 *buf, int ts, int &pos, int &wrap)
644{
645      UINT8 v = 0;
646      int w1 = wrap;
647      while(wrap != w1+2 && !(v & 0x80)) {
648            v = v << 1 | ((buf[pos >> 3] >> (7-(pos & 7))) & 1);
649            pos++;
650            if(pos == ts) {
651                  pos = 0;
652                  wrap++;
653            }
654      }
655      return v;
656}
657
658void a2_16sect_format::update_chk(const UINT8 *data, int size, UINT32 &chk)
659{
660}
661
662bool a2_16sect_format::save(io_generic *io, floppy_image *image)
663{
664      int g_tracks, g_heads;
665      int visualgrid[16][35]; // visualizer grid, cleared/initialized below
666#define NOTFOUND 0
667#define ADDRFOUND 1
668#define ADDRGOOD 2
669#define DATAFOUND 4
670#define DATAGOOD 8
671#define DATAPOST 16
672      for (int i = 0; i < 16; i++) {
673         for (int j = 0; j < 35; j++) {
674            visualgrid[i][j] = 0;
675         }
676      }
677      image->get_actual_geometry(g_tracks, g_heads);
678
679      int head = 0;
680
681      int pos_data = 0;
682
683      for(int track=0; track < 70; track+=2) {
684            UINT8 sectdata[(256)*16];
685            memset(sectdata, 0, sizeof(sectdata));
686            int nsect = 16;
687            UINT8 buf[130000]; // originally 13000, multiread dfi disks need larger
688            int ts;
689fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from physical track %d (logical %d)...", track, track/2);
690            generate_bitstream_from_track(track, head, 200000000/(1552*nsect*6), buf, ts, image); // 3104 needs tweaking, *3 is 3x multiread from a dfi disk
691fprintf(stderr,"done.\n");
692            int pos = 0;
693            int wrap = 0;
694            int hb = 0;
695            for(;;) {
696                  UINT8 v = gb(buf, ts, pos, wrap);
697                  if(v == 0xff)
698                        hb = 1;
699                  else if(hb == 1 && v == 0xd5)
700                        hb = 2;
701                  else if(hb == 2 && v == 0xaa)
702                        hb = 3;
703                  else if(hb == 3 && v == 0x96)
704                        hb = 4;
705                  else
706                        hb = 0;
707
708                  if(hb == 4) {
709                        UINT8 h[11];
710                        for(int i=0; i<11; i++)
711                              h[i] = gb(buf, ts, pos, wrap);
712                        //UINT8 v2 = gcr6bw_tb[h[2]];
713                        UINT8 vl = gcr4_decode(h[0],h[1]);
714                        UINT8 tr = gcr4_decode(h[2],h[3]);
715                        UINT8 se = gcr4_decode(h[4],h[5]);
716                        UINT8 chk = gcr4_decode(h[6],h[7]);
717                        UINT32 post = (h[8]<<16)|(h[9]<<8)|h[10];
718                        printf("Address Mark:\tVolume %d, Track %d, Sector %2d, Checksum %02X: %s, Postamble %03X: %s\n", vl, tr, se, chk, (chk ^ vl ^ tr ^ se)==0?"OK":"BAD", post, (post&0xFFFF00)==0xDEAA00?"OK":"BAD");
719                        if (tr == track/2 && se < nsect) {
720                              visualgrid[se][track/2] |= ADDRFOUND;
721                              visualgrid[se][track/2] |= (chk ^ vl ^ tr ^ se)==0?ADDRGOOD:0;
722                              int opos = pos;
723                              int owrap = wrap;
724                              hb = 0;
725                              for(int i=0; i<20 && hb != 4; i++) {
726                                    v = gb(buf, ts, pos, wrap);
727                                    if(v == 0xff)
728                                          hb = 1;
729                                    else if(hb == 1 && v == 0xd5)
730                                          hb = 2;
731                                    else if(hb == 2 && v == 0xaa)
732                                          hb = 3;
733                                    else if(hb == 3 && v == 0xad)
734                                          hb = 4;
735                                    else
736                                          hb = 0;
737                              }
738                              if(hb == 4) {
739                                    visualgrid[se][track/2] |= DATAFOUND;
740                                    UINT8 *dest = sectdata+(256)*se;
741                                    UINT8 data[0x157];
742                                    UINT32 dpost = 0;
743                                    UINT8 c = 0;
744                                    // first read in sector and decode to 6bit form
745                                    for(int i=0; i<0x156; i++) {
746                                          data[i] = gcr6bw_tb[gb(buf, ts, pos, wrap)] ^ c;
747                                          c = data[i];
748                                    //   printf("%02x ", c);
749                                    //   if (((i&0xf)+1)==0x10) printf("\n");
750                                    }
751                                    // read the checksum byte
752                                    data[0x156] = gcr6bw_tb[gb(buf,ts,pos,wrap)];
753                                    // now read the postamble bytes
754                                    for(int i=0; i<3; i++) {
755                                          dpost <<= 8;
756                                          dpost |= gb(buf, ts, pos, wrap);
757                                    }
758                                    // next combine in the upper 2 bits of each byte
759                                    UINT8 bit_swap[4] = { 0, 2, 1, 3 };
760                                    for(int i=0; i<0x56; i++)
761                                          data[i+0x056] = data[i+0x056]<<2 |  bit_swap[data[i]&3];
762                                    for(int i=0; i<0x56; i++)
763                                          data[i+0x0ac] = data[i+0x0ac]<<2 |  bit_swap[(data[i]>>2)&3];
764                                    for(int i=0; i<0x54; i++)
765                                          data[i+0x102] = data[i+0x102]<<2 |  bit_swap[(data[i]>>4)&3];
766                                    // now decode it into 256 bytes
767                                    // but only write it if the bitfield of the track shows datagood is NOT set.
768                                    // if it is set we don't want to overwrite a guaranteed good read with a bad one
769                                    if ((visualgrid[se][track/2]&DATAGOOD)==0) {
770                                       // TODO:
771                                       // if the current read is good but the postamble isn't, write it in.
772                                       // if the current read isn't good but the postamble is, its better than nothing.
773                                       // if the current read isn't good and neither is the postamble but nothing better
774                                       // has been written before, write it anyway.
775                                       for(int i=0x56; i<0x156; i++) {
776                                          UINT8 dv = data[i];
777                                          *dest++ = dv;
778                                       }
779                                    }
780                                    // do some checking
781                                    if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00) {
782                                    printf("Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD");
783                                    }
784                                    else visualgrid[se][track/2] |= DATAGOOD;
785                              } else {
786                                    pos = opos;
787                                    wrap = owrap;
788                              }
789                        }
790                        hb = 0;
791                  }
792                  if(wrap)
793                        break;
794            }
795            for(int i=0; i<nsect; i++) {
796                  //if(nsect>0) printf("t%d,", track);
797                  UINT8 *data = sectdata + (256)*i;
798                  io_generic_write(io, data, pos_data, 256);
799                  pos_data += 256;
800            }
801            //printf("\n");
802      }
803      // display a little table of which sectors decoded ok
804      for (int j = 0; j < 35; j++) {
805         printf("T%2d: ",j);
806         for (int i = 0; i < 16; i++) {
807            if (visualgrid[i][j] == NOTFOUND) printf("-NF-");
808            else {
809            if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" ");
810            if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" ");
811            if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" ");
812            if (visualgrid[i][j] & DATAGOOD) printf("D"); else printf(" ");
813            }
814            printf(" ");
815         }
816         printf("\n");
817      }
818
819      return true;
820}
821
822const floppy_format_type FLOPPY_A216S_FORMAT = &floppy_image_format_creator<a2_16sect_format>;
No newline at end of file
src/lib/formats/ap2_dsk.h
r14973r14974
11/*********************************************************************
22
3    ap2_dsk.h
3   ap2_dsk.h
44
5    Apple II disk images
5   Apple II disk images
66
77*********************************************************************/
88
r14973r14974
1414
1515/***************************************************************************
1616
17    Constants
17   Constants
1818
1919***************************************************************************/
2020
21#define APPLE2_NIBBLE_SIZE         416
22#define APPLE2_SMALL_NIBBLE_SIZE   374
23#define APPLE2_TRACK_COUNT         35
24#define APPLE2_SECTOR_COUNT         16
25#define APPLE2_SECTOR_SIZE         256
21#define APPLE2_NIBBLE_SIZE                      416
22#define APPLE2_SMALL_NIBBLE_SIZE        374
23#define APPLE2_TRACK_COUNT                      35
24#define APPLE2_SECTOR_COUNT                     16
25#define APPLE2_SECTOR_SIZE                      256
2626
2727
2828
r14973r14974
3030
3131LEGACY_FLOPPY_OPTIONS_EXTERN(apple2);
3232
33#endif /* AP2_DISK_H */
33// new style code
34
35class a2_16sect_format : public floppy_image_format_t
36{
37public:
38      a2_16sect_format();
39
40      virtual int identify(io_generic *io, UINT32 form_factor);
41      virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
42      virtual bool save(io_generic *io, floppy_image *image);
43
44      virtual const char *name() const;
45      virtual const char *description() const;
46      virtual const char *extensions() const;
47      virtual bool supports_save() const;
48
49private:
50      static const desc_e mac_gcr[];
51
52      UINT8 gb(const UINT8 *buf, int ts, int &pos, int &wrap);
53      void update_chk(const UINT8 *data, int size, UINT32 &chk);
54};
55
56extern const floppy_format_type FLOPPY_A216S_FORMAT;
57
58#endif /* AP2_DISK_H */
No newline at end of file
src/mess/tools/floptool/main.c
r14973r14974
3333#include "formats/pc_dsk.h"
3434
3535#include "formats/ap_dsk35.h"
36#include "formats/ap2_dsk.h"
3637
3738static floppy_format_type floppy_formats[] = {
3839   FLOPPY_MFI_FORMAT,
r14973r14974
5152   FLOPPY_PC_FORMAT,
5253
5354   FLOPPY_DC42_FORMAT,
55   FLOPPY_A216S_FORMAT,
5456};
5557
5658void CLIB_DECL logerror(const char *format, ...)

Previous 15994 Revisions Next


© 1998-2018 The MESS Team