// excerpt from nostalgia java client for reading amiga disks // this basically takes a raw MFM bytes in trbuffer (only least significant byte is important) // and populates a "myfloppy" object. // fields should be self-explanatory // inspired by Marco Veneri's Amiga Floppy Reader // by Keith Monahan (keith@techtravels.org) // www.techtravels.org/amiga/amigablog // Aug 2010 // this is ugly and need refactored, especially all my "magic" numbers // Freely redistributable, please give credit. offset = 0; // because we now send perfectly aligned data //if there havent been any errors yet then decode the MFM and check data/header checksums if (retry == false) { for (startdata = (offset + 8); startdata < 11972; startdata = startdata + 1088) { //DECODE THE HEADER ffodd = trbuffer[startdata]; ffeven = trbuffer[startdata + 4]; trackodd = trbuffer[startdata + 1]; trackeven = trbuffer[startdata + 1 + 4]; sectodd = trbuffer[startdata + 2]; secteven = trbuffer[startdata + 2 + 4]; secttoendodd = trbuffer[startdata + 3]; secttoendeven = trbuffer[startdata + 3 + 4]; // do MFM decoding here. first we mask both the odd and even bits // to remove the clock bits. MFM goes ... // then we shift the odd bits to the left one position // then we OR the odd bits with the even bits together to recombine // them into the original complete byte ffodd &= 0x00000055; ffeven &= 0x00000055; trackodd &= 0x00000055; trackeven &= 0x00000055; sectodd &= 0x00000055; secteven &= 0x00000055; secttoendodd &= 0x00000055; secttoendeven &= 0x00000055; ffodd = ffodd << 1; ffvalue = ffodd | ffeven; trackodd = trackodd << 1; trackvalue = trackodd | trackeven; sectodd = sectodd << 1; sectorvalue = sectodd | secteven; secttoendodd = secttoendodd << 1; sectortoendvalue = secttoendodd | secttoendeven; // combine +40, +41, +42, +43 bytes into the same 32-bit integer headercheckodd = ((trbuffer[startdata + 40] << 24) | (trbuffer[startdata + 41] << 16) | (trbuffer[startdata + 42] << 8) | (trbuffer[startdata + 43])); // combine +44, +45, +46, +47 bytes into the same 32-bit integer headercheckeven = ((trbuffer[startdata + 44] << 24) | (trbuffer[startdata + 45] << 16) | (trbuffer[startdata + 46] << 8) | (trbuffer[startdata + 47])); // mfm decoding for headerchecksum headercheckodd &= 0x55555555; headercheckeven &= 0x55555555; headercheckodd = headercheckodd << 1; headercheckvalue = headercheckodd | headercheckeven; // combine +48, +49, +50, +51 bytes into the same 32-bit integer datacheckodd = ((trbuffer[startdata + 48] << 24) | (trbuffer[startdata + 49] << 16) | (trbuffer[startdata + 50] << 8) | (trbuffer[startdata + 51])); // combine +52, +53, +54, +55 bytes into the same 32-bit integer datacheckeven = ((trbuffer[startdata + 52] << 24) | (trbuffer[startdata + 53] << 16) | (trbuffer[startdata + 54] << 8) | (trbuffer[startdata + 55])); // mfm decoding for datachecksum datacheckodd &= 0x55555555; datacheckeven &= 0x55555555; datacheckodd = datacheckodd << 1; datacheckvalue = datacheckodd | datacheckeven; // calculated data checksum here calculateddatachecksum = 0; for (loopzz = 0; loopzz < 128; loopzz++) { oddword = ((trbuffer[(loopzz * 4) + startdata + 56] << 24) | (trbuffer[(loopzz * 4) + 1 + startdata + 56] << 16) | (trbuffer[(loopzz * 4) + 2 + startdata + 56] << 8) | (trbuffer[(loopzz * 4) + 3 + startdata + 56])); evenword = ((trbuffer[(loopzz * 4) + 512 + startdata + 56] << 24) | (trbuffer[(loopzz * 4) + 1 + 512 + startdata + 56] << 16) | (trbuffer[(loopzz * 4) + 2 + 512 + startdata + 56] << 8) | (trbuffer[(loopzz * 4) + 3 + 512 + startdata + 56])); oddword &= 0x55555555; evenword &= 0x55555555; calculateddatachecksum ^= oddword ^ evenword; } // calculate headerchecksum calculatedheaderchecksum = 0; for (loopzz = 0; loopzz < 4; loopzz++) { oddword = ((trbuffer[(loopzz * 4) + startdata] << 24) | (trbuffer[(loopzz * 4) + 1 + startdata] << 16) | (trbuffer[(loopzz * 4) + 2 + startdata] << 8) | (trbuffer[(loopzz * 4) + 3 + startdata])); evenword = ((trbuffer[(loopzz * 4) + 16 + startdata] << 24) | (trbuffer[(loopzz * 4) + 1 + 16 + startdata] << 16) | (trbuffer[(loopzz * 4) + 2 + 16 + startdata] << 8) | (trbuffer[(loopzz * 4) + 3 + 16 + startdata])); oddword &= 0x55555555; evenword &= 0x55555555; calculatedheaderchecksum ^= oddword ^ evenword; } if (headercheckvalue == calculatedheaderchecksum) { statusmsg.append("H"); } else { statusmsg.append("Header Checksum mismatch: stored=" + Integer.toHexString(headercheckvalue) + " != " + Integer.toHexString(calculatedheaderchecksum) + " calculated RETRYING.....\n"); retry = true; } if (datacheckvalue == calculateddatachecksum) { statusmsg.append("D"); } else { statusmsg.append("Data Checksum mismatch: stored=" + Integer.toHexString(datacheckvalue) + " != " + Integer.toHexString(calculateddatachecksum) + " calculated RETRYING.....\n"); retry = true; } //if there still arent errors, after checking header and data checksum if (retry == false) { if (!((trackvalue < 0) || (trackvalue > 159) || (sectorvalue < 0) || (sectorvalue > 10) || (ffvalue != 0xFF) || (trackno != trackvalue) || (headercheckvalue != calculatedheaderchecksum) || (datacheckvalue != calculateddatachecksum))) { myfloppy.trackgroup[trackno].secgroup[sectorvalue].format_type = ffvalue; myfloppy.trackgroup[trackno].secgroup[sectorvalue].track = trackvalue; myfloppy.trackgroup[trackno].secgroup[sectorvalue].sector = sectorvalue; myfloppy.trackgroup[trackno].secgroup[sectorvalue].offset = sectortoendvalue; myfloppy.trackgroup[trackno].secgroup[sectorvalue].data_chk = datacheckvalue; // sector data is now at startdata + 56 for (loopzz = 0; loopzz < 512; loopzz++) { sectordataodd = trbuffer[startdata + loopzz + 56]; sectordataeven = trbuffer[startdata + loopzz + 56 + 512]; sectordataodd &= 0x00000055; sectordataeven &= 0x00000055; sectordataodd = sectordataodd << 1; sectordata[loopzz] = sectordataodd | sectordataeven; myfloppy.trackgroup[trackno].secgroup[sectorvalue].data[loopzz] = sectordata[loopzz]; } if (useamiganame.isSelected()) { if ((trackno == 80) && (sectorvalue == 0)) { int dnloop; String mydiskname; char[] tempchararray; tempchararray = new char[31]; for (dnloop = 0; dnloop < sectordata[432]; dnloop++) { tempchararray[dnloop] = (char) sectordata[433 + dnloop]; } mydiskname = new String(tempchararray).substring(0, sectordata[432]); myfloppy.floppyname = jLabel8.getText() + "\\" + mydiskname + ".ADF"; statusmsg.append("\nDisk filename set to " + myfloppy.floppyname + "\n"); jTextField2.setText(mydiskname + ".ADF"); } } statusmsg.append("" + sectorvalue); } // if sector numbers are valid else { if ((trackno < 0) || (trackno > 159) || (sectorvalue < 0) || (sectorvalue > 10) || (ffvalue != 0xFF)) { statusmsg.append("SOME VALUE OUT OF RANGE:\n"); statusmsg.append("ff value=0x" + java.lang.Integer.toHexString(ffvalue) + ". Should be 0xFF only.\n"); statusmsg.append("track value=0x" + java.lang.Integer.toHexString(trackvalue) + ". Should be 0-159.\n"); statusmsg.append("sector value=0x" + java.lang.Integer.toHexString(sectorvalue) + ". Should be 0-10.\n"); statusmsg.append("sectortoend value=0x" + java.lang.Integer.toHexString(sectortoendvalue) + ". should be 0-10.\n"); retry = true; } if (trackno != trackvalue) { statusmsg.append("SYNC PROBLEM: reading track #" + trackno + " but data contains track #" + trackvalue + " calculated RETRYING.....\n"); retry = true; } } // end else if sectors arent valid } // if there werent previous errors if (retry == true) { break; //dont bother doing the rest of the sectors if one is bad, just retry } }//for all sectors, all data received if (retry == false) { // if there are still no errors for (loopzz = 0; loopzz < 11; loopzz++) { if (myfloppy.trackgroup[trackno].secgroup[loopzz].format_type != 0xFF) { statusmsg.append("WARNING: NO DATA on track#" + trackno + "sector #" + loopzz + "\n"); retry = true; } } } // if retry==false if (stopnow == true) { stopbutton.setEnabled(false); return false; } } // if there haven't been errors retries++; } while ((retry == true) /*&& (retries < 10)*/);