#include #include #include "emu.h" extern "C" { #include "emuapi.h" } extern uint8_t bootdrive, hdcount; extern uint16_t segregs[6]; extern uint8_t cf; extern _bytewordregs_ regs; int file; struct struct_drive { uint32_t filesize; uint16_t cyls; uint16_t sects; uint16_t heads; uint8_t inserted; } disk[4]; uint8_t sectorbuffer[512]; uint8_t insertdisk(uint8_t drivenum) { if (drivenum & 0x80) { drivenum -= 126; disk[drivenum].sects = 63; disk[drivenum].heads = 16; disk[drivenum].cyls = 1023; //up to 512 MB hdcount = 1; } else { #ifdef FDD_144M disk[drivenum].cyls = 80; disk[drivenum].sects = 18; disk[drivenum].heads = 2; #endif #ifdef FDD_122M disk[drivenum].cyls = 80; disk[drivenum].sects = 15; disk[drivenum].heads = 2; #endif #ifdef FDD_720K disk[drivenum].cyls = 80; disk[drivenum].sects = 9; disk[drivenum].heads = 2; #endif #ifdef FDD_360K disk[drivenum].cyls = 40; disk[drivenum].sects = 9; disk[drivenum].heads = 2; #endif #ifdef FDD_320K disk[drivenum].cyls = 40; disk[drivenum].sects = 8; disk[drivenum].heads = 2; #endif #ifdef FDD_180K disk[drivenum].cyls = 40; disk[drivenum].sects = 9; disk[drivenum].heads = 1; #endif } disk[drivenum].inserted = 1; return 0; } void ejectdisk(uint8_t drivenum) { if (drivenum & 0x80) drivenum -= 126; disk[drivenum].inserted = 0; } extern uint16_t ramseg; extern "C" { extern void emu_SdReadBlock(int block, void * buf); } uint8_t sectdone; void getsect(uint32_t lba, uint8_t *dst) { #ifdef USB_DISK uint8_t chksum; uint32_t curmicros; retrysectget: Serial.write(0xFF); Serial.write(0x05); outByte(lba & 0xFF); chksum = lba & 0xFF; outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF; outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF; outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF; outByte(chksum); Serial.write(0xFE); Serial.write(0x02); sectdone = 0; curmicros = micros(); while (!sectdone) { if (micros() < curmicros) curmicros = micros(); if ((micros() - curmicros) >= 200000) goto retrysectget; net_loop(); } #else if (file) { //printf("read block %d\n",lba); emu_FileSeek(lba*512); emu_FileRead((char *)dst,1*512); } #endif } void putsect(uint32_t lba, uint8_t *src) { #ifdef USB_DISK uint8_t chksum; uint16_t i; uint32_t curmicros; retrysectput: Serial.write(0xFF); Serial.write(0x06); outByte(lba & 0xFF); chksum = lba & 0xFF; outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF; outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF; outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF; for (i=0; i<512; i++) { outByte(src[i]); chksum += src[i]; } outByte(chksum); Serial.write(0xFE); Serial.write(0x02); sectdone = 0; curmicros = micros(); while (!sectdone) { if (micros() < curmicros) curmicros = micros(); if ((micros() - curmicros) >= 200000) goto retrysectput; net_loop(); } #else //card.writeBlock(lba, src); #endif } void readdisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) { uint32_t memdest, goodsects, dummy, lba; if ((sect == 0) || !disk[drivenum].inserted) return; #ifdef MEGA SPI.setClockDivider(SPI_CLOCK_SDCARD); #endif lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1; memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff; for (goodsects = 0; goodsects < sectcount; goodsects++) { getsect(lba, sectorbuffer); memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff; for (dummy = 0; dummy < 512; dummy++) { write86(memdest++, sectorbuffer[dummy]); //Serial.write(sectorbuffer[dummy]); } dstoff += 512; lba++; } cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount; #ifdef MEGA SPI.setClockDivider(SPI_CLOCK_SPIRAM); #endif } void writedisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) { uint32_t memdest, goodsects, dummy, lba; if ((sect == 0) || !disk[drivenum].inserted) return; #ifdef MEGA SPI.setClockDivider(SPI_CLOCK_SDCARD); #endif lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1; for (goodsects = 0; goodsects < sectcount; goodsects++) { memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff; for (dummy = 0; dummy < 512; dummy++) { sectorbuffer[dummy] = read86(memdest++); } //card.erase(lba, lba); putsect(lba, sectorbuffer); dstoff += 512; lba++; } cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount; #ifdef MEGA SPI.setClockDivider(SPI_CLOCK_SPIRAM); #endif } void diskhandler() { static uint8_t lastdiskah[4], lastdiskcf[4]; uint8_t drivenum; drivenum = regs.byteregs[regdl]; if (drivenum & 0x80) drivenum -= 126; switch (regs.byteregs[regah]) { case 0: //reset disk system regs.byteregs[regah] = 0; cf = 0; //useless function in an emulator. say success and return. break; case 1: //return last status regs.byteregs[regah] = lastdiskah[drivenum]; cf = lastdiskcf[drivenum]; return; case 2: //read sector(s) into memory if (disk[drivenum].inserted) { 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]); cf = 0; regs.byteregs[regah] = 0; } else { cf = 1; regs.byteregs[regah] = 1; } break; case 3: //write sector(s) from memory if (disk[drivenum].inserted) { writedisk(drivenum, segregs[reges], getreg16(regbx), regs.byteregs[regch] + (regs.byteregs[regcl] / 64) * 256, regs.byteregs[regcl] & 63, regs.byteregs[regdh], regs.byteregs[regal]); cf = 0; regs.byteregs[regah] = 0; } else { cf = 1; regs.byteregs[regah] = 1; } break; case 4: case 5: //format track cf = 0; regs.byteregs[regah] = 0; break; case 8: //get drive parameters if (disk[drivenum].inserted) { cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regch] = disk[drivenum].cyls - 1; regs.byteregs[regcl] = disk[drivenum].sects & 63; regs.byteregs[regcl] = regs.byteregs[regcl] + (disk[drivenum].cyls / 256) * 64; regs.byteregs[regdh] = disk[drivenum].heads - 1; //segregs[reges] = 0; regs.wordregs[regdi] = 0x7C0B; //floppy parameter table if (drivenum < 2) { regs.byteregs[regbl] = 4; //else regs.byteregs[regbl] = 0; regs.byteregs[regdl] = 2; } else regs.byteregs[regdl] = hdcount; } else { cf = 1; regs.byteregs[regah] = 0xAA; } break; default: cf = 1; } lastdiskah[drivenum] = regs.byteregs[regah]; lastdiskcf[drivenum] = cf; if (regs.byteregs[regdl] & 0x80) write86(0x474, regs.byteregs[regah]); } void initDisk(char * filename) { int len=emu_FileSize(filename); file = emu_FileOpen(filename); if (len) { bootdrive = 0x80; insertdisk(0x80); hdcount = 1; } else { bootdrive = 0xFF; emu_FileClose(); file = NULL; } }