summaryrefslogtreecommitdiff
path: root/rbfloppy.c
diff options
context:
space:
mode:
authorJeff Armstrong <jeffrey.armstrong@approximatrix.com>2017-04-05 08:24:53 -0400
committerJeff Armstrong <jeffrey.armstrong@approximatrix.com>2017-04-05 08:24:53 -0400
commit9e41edbc48b85663236009cba2391df165dd1ee4 (patch)
tree9f0da6419e7b6bf342d8fe5abbbb1422790b21c6 /rbfloppy.c
downloadrbimg-9e41edbc48b85663236009cba2391df165dd1ee4.tar.gz
rbimg-9e41edbc48b85663236009cba2391df165dd1ee4.zip
Initial importHEADmaster
Diffstat (limited to 'rbfloppy.c')
-rwxr-xr-xrbfloppy.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/rbfloppy.c b/rbfloppy.c
new file mode 100755
index 0000000..3202e27
--- /dev/null
+++ b/rbfloppy.c
@@ -0,0 +1,175 @@
+/* Rainbow Image Utilities
+ * Copyright © 2008 Jeffrey Armstrong <jeff@rainbow-100.com>
+ * http://jeff.rainbow-100.com/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* rbfloppy.obj - A collection of direct disk access routines
+ * by Jeff Armstrong
+ */
+
+#include <dos.h>
+#include "rbfloppy.h"
+#include <stdio.h>
+
+/* Structure that represents the block of data needed to call interrupt
+ * 0x65, which allows direct disk access. The order here is very
+ * important.
+ */
+struct dsk_bios_block {
+ unsigned char command;
+ unsigned char drive_id;
+ unsigned char sector;
+ unsigned char phys_unit;
+ unsigned int track;
+ unsigned int sector_count;
+ unsigned int data;
+ unsigned int segment;
+};
+
+/* The map that is used to skew/deskew sector addresses */
+static int skew[11] = {0,1,6,2,7,3,8,4,9,5,10};
+
+/* The current program addressing mode */
+static int current_mode = MODE_PHYSICAL;
+
+/* An internal method to unskew a given sector number */
+int unskew(int sector);
+
+/* Writes a given sector using the data in buffer */
+int write_sector(int unit, int track, int sector, char *buffer)
+{
+ return access_sector(CMD_WRITE_VERIFY, unit, track, sector, buffer);
+}
+
+/* Reads a specified sector from disk into buffer */
+int read_sector(int unit, int track, int sector, char *buffer)
+{
+ return access_sector(CMD_READ, unit, track, sector, buffer);
+}
+
+/* Internal routine that performs all actual disk access through calls
+ * to interrupt 0x65. Some command ints are already #defined, but
+ * a few more exist that aren't listed here.
+ */
+int access_sector(int command, int unit, int track, int sector, char *buffer)
+{
+struct dsk_bios_block write;
+struct SREGS segregs;
+union REGS r;
+
+char *pt;
+
+ /* Sectors are numbered 1 to 10 */
+ if(sector > 10)
+ return ERROR_BAD_SECTOR;
+
+ /* The current data segment is needed for the interrupt call */
+ segread(&segregs);
+
+ write.command = (unsigned char)command;
+ write.drive_id = (unsigned char)0xFF;
+ write.track = (unsigned int)track;
+
+ /* Determine the sector if skewing is necessary */
+ if(track > 1 && get_mode() == MODE_PHYSICAL)
+ write.sector = (unsigned char)unskew(sector);
+ else
+ write.sector = (unsigned char)sector;
+
+ write.sector_count = (unsigned int)1;
+ write.phys_unit = (unsigned char)(0+unit*16);
+
+ write.data = (unsigned int)buffer;
+ write.segment = segregs.ds;
+
+ /* Only for debugging */
+ pt = &write;
+
+#ifdef DEBUG
+ printf("Sz: %d: 0:%d 1:%d 2:%d 3:%d 4:%d 5:%d 6:%d 7:%d of:%d ds%d\n",
+ sizeof(write),pt[0],pt[1],pt[2],pt[3],pt[4]+pt[5]*256,
+ pt[6]+pt[7]*256,pt[8]+pt[9]*256,pt[10]+pt[11]*256,
+ &buffer[0],segregs.ds);
+#endif
+
+ r.x.bx = &write;
+
+ int86(FLOPPY_INTR,&r,&r);
+
+ if(r.h.al == 0)
+ return OK;
+ else
+ return ERROR_FROM_BIOS;
+}
+
+/* Determines the unit number for access_sector() from a given character.
+ * Expects a drive letter or a number. Returns -1 on error.
+ */
+int drive_id(char id)
+{
+int drv;
+
+ switch(id) {
+ case 'A':
+ case 'a':
+ case 0:
+ case '0':
+ drv = 0;
+ break;
+ case 'B':
+ case 'b':
+ case 1:
+ case '1':
+ drv = 1;
+ break;
+ case 'C':
+ case 'c':
+ case 2:
+ case '2':
+ drv = 2;
+ break;
+ case 'D':
+ case 'd':
+ case 3:
+ case '3':
+ drv = 3;
+ break;
+ default:
+ drv = -1;
+ }
+
+ return drv;
+}
+
+/* Returns an unskewed sector number from a skewed address */
+int unskew(int sector) {
+ return sector <= 10 && sector > 0 ? skew[sector] : 1;
+}
+
+/* Sets the mode of the sector addressing to either physical or
+ * logical by assigning a static variable.
+ */
+void set_mode(int mode)
+{
+ if(mode == MODE_PHYSICAL || mode == MODE_LOGICAL)
+ current_mode = mode;
+}
+
+/* Returns the current addressing mode */
+int get_mode()
+{
+ return current_mode;
+} \ No newline at end of file