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 }