disk.cpp
  1  #include <stdint.h>
  2  #include <stdio.h>
  3  #include "emu.h"
  4  #include "emuapi.h"
  5  
  6  extern uint8_t bootdrive, hdcount;
  7  extern uint16_t segregs[6];
  8  extern uint8_t cf; 
  9  extern _bytewordregs_ regs;
 10  
 11  int file;
 12  
 13  struct struct_drive {
 14    uint32_t filesize;
 15    uint16_t cyls;
 16    uint16_t sects;
 17    uint16_t heads;
 18    uint8_t inserted;
 19  } disk[4];
 20  uint8_t sectorbuffer[512];
 21  
 22  uint8_t insertdisk(uint8_t drivenum) {
 23    if (drivenum & 0x80) {
 24      drivenum -= 126;
 25      disk[drivenum].sects = 63;
 26      disk[drivenum].heads = 16;
 27      disk[drivenum].cyls = 1023; //up to 512 MB
 28      hdcount = 1;
 29    } else {
 30  #ifdef FDD_144M
 31      disk[drivenum].cyls = 80;
 32      disk[drivenum].sects = 18;
 33      disk[drivenum].heads = 2;
 34  #endif
 35  #ifdef FDD_122M
 36      disk[drivenum].cyls = 80;
 37      disk[drivenum].sects = 15;
 38      disk[drivenum].heads = 2;
 39  #endif
 40  #ifdef FDD_720K
 41      disk[drivenum].cyls = 80;
 42      disk[drivenum].sects = 9;
 43      disk[drivenum].heads = 2;
 44  #endif
 45  #ifdef FDD_360K
 46      disk[drivenum].cyls = 40;
 47      disk[drivenum].sects = 9;
 48      disk[drivenum].heads = 2;
 49  #endif
 50  #ifdef FDD_320K
 51      disk[drivenum].cyls = 40;
 52      disk[drivenum].sects = 8;
 53      disk[drivenum].heads = 2;
 54  #endif
 55  #ifdef FDD_180K
 56      disk[drivenum].cyls = 40;
 57      disk[drivenum].sects = 9;
 58      disk[drivenum].heads = 1;
 59  #endif
 60    }
 61    disk[drivenum].inserted = 1;
 62    return 0;
 63  }
 64  
 65  void ejectdisk(uint8_t drivenum) {
 66    if (drivenum & 0x80) drivenum -= 126;
 67    disk[drivenum].inserted = 0;
 68  }
 69  
 70  extern uint16_t ramseg;
 71  extern "C" {
 72  extern void emu_SdReadBlock(int block, void * buf);
 73  }
 74  uint8_t sectdone;
 75  void getsect(uint32_t lba, uint8_t *dst) {
 76  #ifdef USB_DISK
 77    uint8_t chksum;
 78    uint32_t curmicros;
 79  retrysectget:
 80    Serial.write(0xFF);
 81    Serial.write(0x05);
 82    outByte(lba & 0xFF); chksum = lba & 0xFF;
 83    outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF;
 84    outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF;
 85    outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF;
 86    outByte(chksum);
 87    Serial.write(0xFE);
 88    Serial.write(0x02);
 89    sectdone = 0;
 90    curmicros = micros();
 91    while (!sectdone) {
 92      if (micros() < curmicros) curmicros = micros();
 93      if ((micros() - curmicros) >= 200000) goto retrysectget;
 94      net_loop();
 95    }
 96  #else
 97    if (file) 
 98    {  
 99      //printf("read block %d\n",lba);  
100      emu_FileSeek(file,lba*512,SEEK_SET);
101      emu_FileRead(dst,1*512,file); 
102    }   
103  #endif
104  }
105  
106  void putsect(uint32_t lba, uint8_t *src) {
107  #ifdef USB_DISK
108    uint8_t chksum;
109    uint16_t i;
110    uint32_t curmicros;
111  retrysectput:
112    Serial.write(0xFF);
113    Serial.write(0x06);
114    outByte(lba & 0xFF); chksum = lba & 0xFF;
115    outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF;
116    outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF;
117    outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF;
118    for (i=0; i<512; i++) {
119      outByte(src[i]);
120      chksum += src[i];
121    }
122    outByte(chksum);
123    Serial.write(0xFE);
124    Serial.write(0x02);
125    sectdone = 0;
126    curmicros = micros();
127    while (!sectdone) {
128      if (micros() < curmicros) curmicros = micros();
129      if ((micros() - curmicros) >= 200000) goto retrysectput;
130      net_loop();
131    }
132  #else
133    //card.writeBlock(lba, src);
134  #endif
135  }
136  void readdisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) {
137    uint32_t memdest, goodsects, dummy, lba;
138    if ((sect == 0) || !disk[drivenum].inserted) return;
139  #ifdef MEGA
140    SPI.setClockDivider(SPI_CLOCK_SDCARD);
141  #endif
142    lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1;
143    memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
144    for (goodsects = 0; goodsects < sectcount; goodsects++) {
145      getsect(lba, sectorbuffer);
146      memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
147      for (dummy = 0; dummy < 512; dummy++) {
148        write86(memdest++, sectorbuffer[dummy]);
149        //Serial.write(sectorbuffer[dummy]);
150      }
151      dstoff += 512;
152      lba++;
153    }
154    cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount;
155  #ifdef MEGA
156    SPI.setClockDivider(SPI_CLOCK_SPIRAM);
157  #endif
158  }
159  
160  void writedisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) {
161    uint32_t memdest, goodsects, dummy, lba;
162    if ((sect == 0) || !disk[drivenum].inserted) return;
163  #ifdef MEGA
164    SPI.setClockDivider(SPI_CLOCK_SDCARD);
165  #endif
166    lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1;
167    for (goodsects = 0; goodsects < sectcount; goodsects++) {
168      memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
169      for (dummy = 0; dummy < 512; dummy++) {
170        sectorbuffer[dummy] = read86(memdest++);
171      }
172      //card.erase(lba, lba);
173      putsect(lba, sectorbuffer);
174      dstoff += 512;
175      lba++;
176    }
177    cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount;
178  #ifdef MEGA
179    SPI.setClockDivider(SPI_CLOCK_SPIRAM);
180  #endif
181  }
182  
183  void diskhandler() {
184    static uint8_t lastdiskah[4], lastdiskcf[4];
185    uint8_t drivenum;
186    drivenum = regs.byteregs[regdl];
187    if (drivenum & 0x80) drivenum -= 126;
188    switch (regs.byteregs[regah]) {
189      case 0: //reset disk system
190        regs.byteregs[regah] = 0; cf = 0; //useless function in an emulator. say success and return.
191        break;
192      case 1: //return last status
193        regs.byteregs[regah] = lastdiskah[drivenum];
194        cf = lastdiskcf[drivenum];
195        return;
196      case 2: //read sector(s) into memory
197        if (disk[drivenum].inserted) {
198          readdisk(drivenum, segregs[reges], getreg16(regbx), (uint16_t)regs.byteregs[regch] + ((uint16_t)regs.byteregs[regcl] / 64) * 256, regs.byteregs[regcl] & 63, regs.byteregs[regdh], regs.byteregs[regal]);
199          cf = 0; regs.byteregs[regah] = 0;
200        } else {
201          cf = 1;
202          regs.byteregs[regah] = 1;
203        }
204        break;
205      case 3: //write sector(s) from memory
206        if (disk[drivenum].inserted) {
207          writedisk(drivenum, segregs[reges], getreg16(regbx), regs.byteregs[regch] + (regs.byteregs[regcl] / 64) * 256, regs.byteregs[regcl] & 63, regs.byteregs[regdh], regs.byteregs[regal]);
208          cf = 0; regs.byteregs[regah] = 0;
209        } else {
210          cf = 1;
211          regs.byteregs[regah] = 1;
212        }
213        break;
214      case 4:
215      case 5: //format track
216        cf = 0; regs.byteregs[regah] = 0;
217        break;
218      case 8: //get drive parameters
219        if (disk[drivenum].inserted) {
220          cf = 0; regs.byteregs[regah] = 0;
221          regs.byteregs[regch] = disk[drivenum].cyls - 1;
222          regs.byteregs[regcl] = disk[drivenum].sects & 63;
223          regs.byteregs[regcl] = regs.byteregs[regcl] + (disk[drivenum].cyls / 256) * 64;
224          regs.byteregs[regdh] = disk[drivenum].heads - 1;
225          //segregs[reges] = 0; regs.wordregs[regdi] = 0x7C0B; //floppy parameter table
226          if (drivenum < 2) {
227            regs.byteregs[regbl] = 4; //else regs.byteregs[regbl] = 0;
228            regs.byteregs[regdl] = 2;
229          } else regs.byteregs[regdl] = hdcount;
230        } else {
231          cf = 1; regs.byteregs[regah] = 0xAA;
232        }
233        break;
234      default:
235        cf = 1;
236    }
237    lastdiskah[drivenum] = regs.byteregs[regah];
238    lastdiskcf[drivenum] = cf;
239    if (regs.byteregs[regdl] & 0x80) write86(0x474, regs.byteregs[regah]);
240  }
241  
242  void initDisk(char * filename) {
243    int len=emu_FileSize(filename);
244    file = emu_FileOpen(filename,"a+r");
245    if (len) {
246      bootdrive = 0x80;
247      insertdisk(0x80);
248      hdcount = 1;
249    }
250    else {
251      bootdrive = 0xFF;
252      emu_FileClose(file);
253      file = NULL;
254    }
255  }