#include "ibm.h" #include "disc.h" #include "disc_sector.h" #include "fdc.h" #include "fdd.h" /*Handling for 'sector based' image formats (like .IMG) as opposed to 'stream based' formats (eg .FDI)*/ #define MAX_SECTORS 256 typedef struct { uint8_t c, h, r, n; int rate; uint8_t *data; } sector_t; static sector_t disc_sector_data[2][2][MAX_SECTORS]; static int disc_sector_count[2][2]; void (*disc_sector_writeback[2])(int drive, int track); enum { STATE_IDLE, STATE_READ_FIND_SECTOR, STATE_READ_SECTOR, STATE_READ_FIND_FIRST_SECTOR, STATE_READ_FIRST_SECTOR, STATE_READ_FIND_NEXT_SECTOR, STATE_READ_NEXT_SECTOR, STATE_WRITE_FIND_SECTOR, STATE_WRITE_SECTOR, STATE_READ_FIND_ADDRESS, STATE_READ_ADDRESS, STATE_FORMAT_FIND, STATE_FORMAT }; static int disc_sector_state; static int disc_sector_track; static int disc_sector_side; static int disc_sector_drive; static int disc_sector_sector; static int disc_sector_n; static int disc_intersector_delay = 0; static uint8_t disc_sector_fill; static int cur_sector, cur_byte; static int index_count; void disc_sector_reset(int drive, int side) { disc_sector_count[drive][side] = 0; } void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data) { sector_t *s = &disc_sector_data[drive][side][disc_sector_count[drive][side]]; //pclog("disc_sector_add: drive=%i side=%i %i r=%i\n", drive, side, disc_sector_count[drive][side],r ); if (disc_sector_count[drive][side] >= MAX_SECTORS) return; s->c = c; s->h = h; s->r = r; s->n = n; s->rate = rate; s->data = data; disc_sector_count[drive][side]++; } static int get_bitcell_period() { return (disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].rate * 300) / fdd_getrpm(disc_sector_drive); } void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size) { // pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate, sector, track, side); if (sector == SECTOR_FIRST) disc_sector_state = STATE_READ_FIND_FIRST_SECTOR; else if (sector == SECTOR_NEXT) disc_sector_state = STATE_READ_FIND_NEXT_SECTOR; else disc_sector_state = STATE_READ_FIND_SECTOR; disc_sector_track = track; disc_sector_side = side; disc_sector_drive = drive; disc_sector_sector = sector; disc_sector_n = sector_size; index_count = 0; } void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size) { // pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate); disc_sector_state = STATE_WRITE_FIND_SECTOR; disc_sector_track = track; disc_sector_side = side; disc_sector_drive = drive; disc_sector_sector = sector; disc_sector_n = sector_size; index_count = 0; } void disc_sector_readaddress(int drive, int track, int side, int rate) { // pclog("disc_sector_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate, track, side); disc_sector_state = STATE_READ_FIND_ADDRESS; disc_sector_track = track; disc_sector_side = side; disc_sector_drive = drive; index_count = 0; } void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill) { disc_sector_state = STATE_FORMAT_FIND; disc_sector_track = track; disc_sector_side = side; disc_sector_drive = drive; disc_sector_fill = fill; index_count = 0; } void disc_sector_stop() { disc_sector_state = STATE_IDLE; } static void advance_byte() { if (disc_intersector_delay) { disc_intersector_delay--; return; } cur_byte++; if (cur_byte >= (128 << disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].n)) { cur_byte = 0; cur_sector++; if (cur_sector >= disc_sector_count[disc_sector_drive][disc_sector_side]) { cur_sector = 0; fdc_indexpulse(); index_count++; } disc_intersector_delay = 40; } } void disc_sector_poll() { sector_t *s; int data; if (cur_sector >= disc_sector_count[disc_sector_drive][disc_sector_side]) cur_sector = 0; if (cur_byte >= (128 << disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].n)) cur_byte = 0; s = &disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector]; switch (disc_sector_state) { case STATE_IDLE: break; case STATE_READ_FIND_SECTOR: /* pclog("STATE_READ_FIND_SECTOR: cur_sector=%i cur_byte=%i sector=%i,%i side=%i,%i track=%i,%i period=%i,%i\n", cur_sector, cur_byte, disc_sector_sector, s->r, disc_sector_side, s->h, disc_sector_track, s->c, fdc_get_bitcell_period(), get_bitcell_period());*/ if (index_count > 1) { // pclog("Find sector not found\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } /* pclog("%i %i %i %i %i\n", cur_byte, disc_sector_track != s->c, disc_sector_side != s->h, disc_sector_sector != s->r, fdc_get_bitcell_period() != get_bitcell_period());*/ if (cur_byte || disc_sector_track != s->c || disc_sector_side != s->h || disc_sector_sector != s->r || disc_sector_n != s->n || fdc_get_bitcell_period() != get_bitcell_period() || !fdd_can_read_medium(disc_sector_drive ^ fdd_swap) || disc_intersector_delay) { advance_byte(); break; } disc_sector_state = STATE_READ_SECTOR; case STATE_READ_SECTOR: // pclog("STATE_READ_SECTOR: cur_byte=%i %i\n", cur_byte, disc_intersector_delay); if (fdc_data(s->data[cur_byte])) { // pclog("fdc_data failed\n"); return; } advance_byte(); if (!cur_byte) { disc_sector_state = STATE_IDLE; fdc_finishread(); } break; case STATE_READ_FIND_FIRST_SECTOR: if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (cur_byte || !index_count || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } disc_sector_state = STATE_READ_FIRST_SECTOR; case STATE_READ_FIRST_SECTOR: if (fdc_data(s->data[cur_byte])) return; advance_byte(); if (!cur_byte) { disc_sector_state = STATE_IDLE; fdc_finishread(); } break; case STATE_READ_FIND_NEXT_SECTOR: if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (index_count) { // pclog("Find next sector hit end of track\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } disc_sector_state = STATE_READ_NEXT_SECTOR; case STATE_READ_NEXT_SECTOR: if (fdc_data(s->data[cur_byte])) break; advance_byte(); if (!cur_byte) { disc_sector_state = STATE_IDLE; fdc_finishread(); } break; case STATE_WRITE_FIND_SECTOR: if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (writeprot[disc_sector_drive]) { fdc_writeprotect(); disc_sector_state = STATE_IDLE; return; } if (index_count > 1) { // pclog("Write find sector not found\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (cur_byte || disc_sector_track != s->c || disc_sector_side != s->h || disc_sector_sector != s->r || disc_sector_n != s->n || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } disc_sector_state = STATE_WRITE_SECTOR; case STATE_WRITE_SECTOR: data = fdc_getdata(cur_byte == ((128 << s->n) - 1)); if (data == -1) break; s->data[cur_byte] = data; advance_byte(); if (!cur_byte) { disc_sector_state = STATE_IDLE; disc_sector_writeback[disc_sector_drive](disc_sector_drive, disc_sector_track); fdc_finishread(); } break; case STATE_READ_FIND_ADDRESS: if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (index_count) { // pclog("Find next sector hit end of track\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } disc_sector_state = STATE_READ_ADDRESS; case STATE_READ_ADDRESS: fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0); disc_sector_state = STATE_IDLE; break; case STATE_FORMAT_FIND: if (writeprot[disc_sector_drive]) { fdc_writeprotect(); disc_sector_state = STATE_IDLE; return; } if (!index_count || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); fdc_notfound(); disc_sector_state = STATE_IDLE; break; } if (fdc_get_bitcell_period() != get_bitcell_period()) { fdc_notfound(); disc_sector_state = STATE_IDLE; break; } disc_sector_state = STATE_FORMAT; case STATE_FORMAT: if (!disc_intersector_delay && fdc_get_bitcell_period() == get_bitcell_period()) s->data[cur_byte] = disc_sector_fill; advance_byte(); if (index_count == 2) { disc_sector_writeback[disc_sector_drive](disc_sector_drive, disc_sector_track); fdc_finishread(); disc_sector_state = STATE_IDLE; } break; } }