diff -Naur spediv_v0.1/divide.c spediv_v0.2/divide.c
--- spediv_v0.1/divide.c	2005-06-25 21:57:21.000000000 +0200
+++ spediv_v0.2/divide.c	2005-07-04 13:30:58.000000000 +0200
@@ -107,6 +107,10 @@
 // active drive (0='A:', 1='B:')
 int divide_active_drive=0;
 
+struct divide_part_struct {	// partition info
+  int fd, len, ptr;
+};
+
 struct divide_drive_struct {
   char *path;		// image path
   int c,h,s;		// C/H/S geometry of disk
@@ -116,13 +120,8 @@
   byte identify[512];	// identify virtual sector
 
 // See README.divIDE for more information
-  int mbr_fd;		// Master Boot Record info
-  int mbr_len;
-  int mbr_ptr;
-
-  int partition_fd;	// partition info
-  int partition_len;
-  int partition_ptr;
+  struct divide_part_struct mbr;		// Master Boot Record info
+  struct divide_part_struct partition[4];	// partition info
 //
 
   byte buffer[512*DIVIDE_MAX_SEC_NR];
@@ -195,7 +194,7 @@
 }
 // initialize variables
 void divide_init() {
-  int i,j,drive;
+  int i, j, drive, part;
   
   // make copy of original spectrum memory (to recover it after unmaping divide memory)
   memcpy(orig_rom, PRNM(proc).mem, 16384);
@@ -230,8 +229,9 @@
     DISK.in_port_A7=0;
     DISK.in_port_BF=0;
     DISK.path=NULL;
-    DISK.mbr_fd=-1;
-    DISK.partition_fd=-1;
+    DISK.mbr.fd=-1;
+    for (part=0; part<4; part++)
+      DISK.partition[part].fd=-1;
   }
 }
 
@@ -250,13 +250,13 @@
 // it must contain files:
 //   .identify (virtual sector containing drive firmware information)
 //   .mbr (master boot record [and rest of track)
-//   part1 (partition image)
-//   part2..partN, .ebr (other partitions, not implemented in this stage)
+//   part1, part2, part3, part4 (partition image)
+//   part5..partN, .ebr (other partitions, not implemented in this stage)
 // this model was choosed to easy mount divide images under linux
 
 void divide_attach_drive(int drive, char *path) {
   char *fname;
-  int fd, r, len;
+  int fd, r, len, part;
   byte identify[512];
   
   if (!path) return;
@@ -280,26 +280,36 @@
     
     memcpy(DISK.identify, identify, 512);
     
-    // read Master Boot Record information
+    // open Master Boot Record file
     snprintf(fname, len, "%s/.mbr", path);
-    if ((DISK.mbr_fd=open(fname, O_RDWR))!=-1) {
+    if ((DISK.mbr.fd=open(fname, O_RDWR))!=-1) {
       // length is in sectors (512bytes blocks), extra chunk is ignored (if size is not divisible by 512)
-      DISK.mbr_len=(lseek(DISK.mbr_fd, 0, SEEK_END))>>9;
-      DISK.mbr_ptr=0;
+      DISK.mbr.len=(lseek(DISK.mbr.fd, 0, SEEK_END))>>9;
+      DISK.mbr.ptr=0;
       // this is for realistic emulation of moving disk head (not used now)
-      lseek(DISK.mbr_fd, DISK.mbr_ptr, SEEK_SET);
+      lseek(DISK.mbr.fd, DISK.mbr.ptr, SEEK_SET);
+    } else {
+      DISK.mbr.fd = -1;
+      DISK.mbr.len = 0;
+      DISK.mbr.ptr = 0;
     }
     
-    // read first partition
-    snprintf(fname, len, "%s/part1", path);
-    if ((DISK.partition_fd=open(fname, O_RDWR))!=-1) {
-      // length is in sectors (512bytes blocks), extra chunk is ignored (if size is not divisible by 512)
-      DISK.partition_len=(lseek(DISK.partition_fd, 0, SEEK_END))>>9;
-      DISK.partition_ptr=0;
-      // this is for realistic emulation of moving disk head (not used now)
-      lseek(DISK.partition_fd, DISK.partition_ptr, SEEK_SET);
+    // open partition files
+    for (part=0; part<4; part++) {
+      snprintf(fname, len, "%s/part%d", path, (part+1));
+      if ((DISK.partition[part].fd=open(fname, O_RDWR))!=-1) {
+        // length is in sectors (512bytes blocks), extra chunk is ignored (if size is not divisible by 512)
+        DISK.partition[part].len=(lseek(DISK.partition[part].fd, 0, SEEK_END))>>9;
+        DISK.partition[part].ptr=0;
+        // this is for realistic emulation of moving disk head (not used now)
+        lseek(DISK.partition[part].fd, DISK.partition[part].ptr, SEEK_SET);
+      } else {
+        DISK.partition[part].fd = -1;
+        DISK.partition[part].len = 0;
+        DISK.partition[part].ptr = 0;
+      }
     }
-
+    
     DISK.buffer_ptr=0;
     DISK.buffer_len=0;
     DISK.cmd=0;
@@ -319,18 +329,27 @@
 
 void divide_detach_drive(int drive) {
 
-  if (DISK.path) {
-    free(DISK.path);
-    DISK.path=NULL;
-  }
-  if (DISK.mbr_fd!=-1) {
-    close(DISK.mbr_fd);
-    DISK.mbr_fd=-1;
-  }
-  if (DISK.partition_fd!=-1) {
-    close(DISK.partition_fd);
-    DISK.partition_fd=-1;
-  }
+  int part;
+  
+  if (!DISK.path)
+    return;
+    
+  free(DISK.path);
+  DISK.path=NULL;
+
+  if (DISK.mbr.fd!=-1) {
+    close(DISK.mbr.fd);
+    DISK.mbr.fd=-1;
+    DISK.mbr.len=0;
+    DISK.mbr.ptr=0;
+  }
+  for (part=0; part<4; part++)
+    if (DISK.partition[part].fd!=-1) {
+      close(DISK.partition[part].fd);
+      DISK.partition[part].fd=-1;
+      DISK.partition[part].len=0;
+      DISK.partition[part].ptr=0;
+    }
   if (!drive)
     put_msg("Image successfully detached from drive 'A:'.");
   else
@@ -409,8 +428,8 @@
 
 // OUT wrapper
 void divide_port_out(int portl, byte data) {
-  int i,drive;
-  int lba;
+  int i, drive, part;
+  int lba, tlba;
   long size;
 
   drive = divide_active_drive;
@@ -430,6 +449,9 @@
     drive = divide_active_drive;
     DISK.port_BB = data;
     DISK2.port_BB = data;
+
+    DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DF & STATUS_CLR_DRQ & STATUS_CLR_ERR);
+    DISK.in_port_BF |= (STATUS_SET_DRDY);
     break;
   case 0xB7: // cylinder register high
     DISK.port_B7 = data;
@@ -469,7 +491,7 @@
         break;
 
       case 0x91: // initialise drive parameters
-        if ((DISK.mbr_fd == -1) || (DISK.partition_fd == -1)) {
+        if (!DISK.path || (DISK.port_AB == 0)) {
           // error
           DISK.in_port_A7 |= ERROR_SET_ABRT;
           DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DRQ);
@@ -477,16 +499,15 @@
           break;
         }
         // recalculate new geometry to fit CHS configuration
-        size = DISK.identify[112] + (DISK.identify[113] << 16);
-        if (size>16514064) size=16,514,064;
+        size = DISK.identify[120] | (DISK.identify[121] << 8) | (DISK.identify[122] << 16) | (DISK.identify[123] << 24);
+        if (size>16514064) size=16514064;
         
-        DISK.h = (DISK.port_BB&15)+1;
+        DISK.h = (DISK.port_BB&15) + 1;
         DISK.s = DISK.port_AB;
-        if ( (DISK.h * DISK.s) == 0 )
-          DISK.c = size / (DISK.h * DISK.s);
-        else
-          DISK.c = 0;
+        DISK.c = size / (DISK.h * DISK.s);
         if (DISK.c>65535) DISK.c=65535;
+
+        size = DISK.c * DISK.h * DISK.s;
         
         DISK.identify[108] = DISK.c & 0xFF;
         DISK.identify[109] = DISK.c >> 8;
@@ -497,12 +518,17 @@
         DISK.identify[112] = DISK.s & 0xFF;
         DISK.identify[113] = DISK.s >> 8;
         
+        DISK.identify[114] = size & 0xFF;
+        DISK.identify[115] = (size >> 8) & 0xFF;
+        DISK.identify[116] = (size >> 16) & 0xFF;
+        DISK.identify[117] = (size >> 24);
+        
         DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DF & STATUS_CLR_DRQ & STATUS_CLR_ERR);
         break;
 
       case 0xA1: // identify drive (ATAPI)
       case 0xEC: // identify drive (ATA)
-        if ((DISK.mbr_fd == -1) || (DISK.partition_fd == -1)) {
+        if (!DISK.path) {
           DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DRDY & STATUS_CLR_DRQ);
           DISK.in_port_BF |= (STATUS_SET_DF | STATUS_SET_ERR);
           break;
@@ -524,7 +550,7 @@
       case 0xC8: // read DMA with retry
       case 0xC9: // read DMA without retry
 
-        if ((DISK.mbr_fd == -1) || (DISK.partition_fd == -1) || (DISK.port_AB>DIVIDE_MAX_SEC_NR)) {
+        if (!DISK.path || (DISK.port_AB>DIVIDE_MAX_SEC_NR)) {
           DISK.in_port_A7 &= (ERROR_CLR_MC & ERROR_CLR_MCR);
           DISK.in_port_A7 |= (ERROR_SET_UNC | ERROR_SET_IDNF | ERROR_SET_ABRT | ERROR_SET_NM);
           DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DF & STATUS_CLR_DRQ);
@@ -545,12 +571,20 @@
         for (i=0; i<((DISK.port_AB == 0) ? 256 : DISK.port_AB); i++) // 0 means 256 sectors
         {
           // read 1 sector only. we cannot read all sectors at once because we have disk splitted into blocks
-          if (lba < DISK.mbr_len) {
-            DISK.mbr_ptr = lseek(DISK.mbr_fd, (lba << 9), SEEK_SET);
-            read(DISK.mbr_fd, DISK.buffer + DISK.buffer_len, 512);
+          tlba=lba;
+          if (tlba < DISK.mbr.len) {
+            DISK.mbr.ptr = lseek(DISK.mbr.fd, (tlba << 9), SEEK_SET);
+            read(DISK.mbr.fd, DISK.buffer + DISK.buffer_len, 512);
           } else {
-            DISK.partition_ptr = lseek(DISK.partition_fd, ((lba - DISK.mbr_len) << 9), SEEK_SET);
-            read(DISK.partition_fd, DISK.buffer + DISK.buffer_len, 512);
+            tlba-=DISK.mbr.len;
+            for (part=0; part<4; part++) {
+              if (tlba < DISK.partition[part].len) {
+                DISK.partition[part].ptr = lseek(DISK.partition[part].fd, (tlba << 9), SEEK_SET);
+                read(DISK.partition[part].fd, DISK.buffer + DISK.buffer_len, 512);
+                break;
+              }
+              tlba-=DISK.partition[part].len;
+            }
           }
           DISK.buffer_len += 512;
           lba++;
@@ -563,7 +597,7 @@
       case 0x31: // write sectors without retry
       case 0x32: // write long with retry
       case 0x33: // write long without retry
-        if ((DISK.mbr_fd == -1) || (DISK.partition_fd == -1) || (DISK.port_AB>DIVIDE_MAX_SEC_NR)) {
+        if (!DISK.path || (DISK.port_AB>DIVIDE_MAX_SEC_NR)) {
           DISK.in_port_A7 &= (ERROR_CLR_WP & ERROR_CLR_MC & ERROR_CLR_MCR);
           DISK.in_port_A7 |= (ERROR_SET_IDNF | ERROR_SET_ABRT | ERROR_SET_NM);
           DISK.in_port_BF &= (STATUS_CLR_BSY & STATUS_CLR_DF & STATUS_CLR_DRQ);
@@ -582,7 +616,7 @@
     }
     break;
   case 0xA3: // data register
-    if (DISK.mbr_fd==-1 || DISK.partition_fd==-1 || DISK.port_AB>DIVIDE_MAX_SEC_NR) {
+    if (!DISK.path || DISK.port_AB>DIVIDE_MAX_SEC_NR) {
       break;
     }
     if (DISK.cmd!=DIVIDE_WRITE_BUFF)
@@ -601,12 +635,20 @@
         lba = chs2lba(drive, (DISK.port_B7 << 8) | DISK.port_B3, DISK.port_BB & 0x0F, DISK.port_AF);
       
       // write sector to disk
-      if (lba < DISK.mbr_len) {
-        DISK.mbr_ptr = lseek(DISK.mbr_fd, (lba << 9), SEEK_SET);
-        write(DISK.mbr_fd, DISK.buffer + DISK.buffer_ptr, 512);
+      tlba=lba;
+      if (tlba < DISK.mbr.len) {
+        DISK.mbr.ptr = lseek(DISK.mbr.fd, (tlba << 9), SEEK_SET);
+        write(DISK.mbr.fd, DISK.buffer + DISK.buffer_len, 512);
       } else {
-        DISK.partition_ptr = lseek(DISK.partition_fd, ((lba - DISK.mbr_len) << 9), SEEK_SET);
-        write(DISK.partition_fd, DISK.buffer + DISK.buffer_ptr, 512);
+        tlba-=DISK.mbr.len;
+        for (part=0; part<4; part++) {
+          if (tlba < DISK.partition[part].len) {
+            DISK.partition[part].ptr = lseek(DISK.partition[part].fd, (tlba << 9), SEEK_SET);
+            write(DISK.partition[part].fd, DISK.buffer + DISK.buffer_len, 512);
+            break;
+          }
+          tlba-=DISK.partition[part].len;
+        }
       }
       DISK.buffer_ptr += 512;
       DISK.port_AB--;
