#pragma once
const int Z80FQ = 3500000; // todo: #define as (conf.frame*conf.intfq)
const int FDD_RPS = 5; // rotation speed
const int MAX_TRACK_LEN = 6250;
const int MAX_CYLS = 86; // don't load images with so many tracks
const int MAX_PHYS_CYL = 86; // don't seek over it
const int MAX_SEC = 256;
struct SECHDR
{
unsigned char c,s,n,l;
unsigned short crc; // CRC чруюыютър ёхъЄюЁр
// Їыруш crc чюэ√ рфЁхёр ш фрээ√ї:
// ╧Ёш ЇюЁьрЄшЁютрэшш:
// 0 - ухэхЁшЁєхЄё яЁртшы№эюх чэрўхэшх crc
// 1 - чряшё№ crc шч crc(фы рфЁхёр)/crcd(фы фрээ√ї)
// 2 - ю°шсюўэ√щ crc (ухэхЁшЁєхЄё шэтхЁёшхщ яЁртшы№эюую crc))
// ╧Ёш ўЄхэшш (ЇєэъЎш seek єёЄрэртыштрхЄ яюы c1 ш c2):
// 0 - ЁрёёўшЄрээюх crc эх ёютярфрхЄ ё єърчрээ√ь т чруюыютъх (тючтЁр∙рхЄё crc error)
// 1 - ЁрёёўшЄрээюх crc ёютярфрхЄ ё єърчрээ√ь т чруюыютъх
unsigned char c1, c2;
u8 *data; // ╙ърчрЄхы№ эр фрээ√х ёхъЄюЁр тэєЄЁш ЄЁ¤ър
u8 *id; // ╙ърчрЄхы№ эр чруюыютюъ ёхъЄюЁр тэєЄЁш ЄЁ¤ър
u8 *wp; // ╙ърчрЄхы№ эр сшЄютє■ ърЁЄє ёсющэ√ї срщЄют ёхъЄюЁр тэєЄЁш ЄЁ¤ър (шёяюы№чєхЄё Єюы№ъю яЁш чруЁєчъх)
unsigned wp_start; // ═юьхЁ яхЁтюую сшЄр т ърЁЄх ёсющэ√ї срщЄют (юЄэюёшЄхы№эю эрўрыр ЄЁ¤ър) фы фрээюую ёхъЄюЁр
unsigned datlen; // ╨рчьхЁ ёхъЄюЁр т срщЄрї
unsigned crcd; // used to load specific CRC from FDI-file
};
enum SEEK_MODE { JUST_SEEK = 0, LOAD_SECTORS = 1 };
static inline bool test_bit(const u8 *data, unsigned bit)
{
return (data[bit >> 3] & (1U << (bit & 7))) != 0;
}
static inline void set_bit(u8 *data, unsigned bit)
{
data[bit >> 3] |= (1U << (bit & 7));
}
static inline void clr_bit(u8 *data, unsigned bit)
{
data[bit >> 3] &= ~(1U << (bit & 7));
}
struct TRKCACHE
{
// cached track position
struct FDD *drive;
unsigned cyl, side;
// generic track data
unsigned trklen;
// pointer to data inside UDI
u8 *trkd; // фрээ√х (ьюцхЄ с√Є№ NULL, хёыш ЄЁ¤ъ схч фрээ√ї)
u8 *trki; // сшЄютр ърЁЄр ёшэїЁюшьяєы№ёют
u8 *trkwp; // сшЄютр ърЁЄр ёсющэ√ї срщЄют
unsigned ts_byte; // cpu.t per byte
SEEK_MODE sf; // flag: is sectors filled
unsigned s; // no. of sectors
// sectors on track
SECHDR hdr[MAX_SEC];
void set_i(unsigned pos) { set_bit(trki, pos); }
void clr_i(unsigned pos) { clr_bit(trki, pos); }
bool test_i(unsigned pos) { return test_bit(trki, pos); }
void set_wp(unsigned pos) { set_bit(trkwp, pos); }
bool test_wp(unsigned pos) { return test_bit(trkwp, pos); }
void write(unsigned pos, unsigned char byte, u8 index)
{
if(!trkd)
return;
trkd[pos] = byte;
if (index)
set_i(pos);
else
clr_i(pos);
}
void seek(FDD *d, unsigned cyl, unsigned side, SEEK_MODE fs);
void format(); // before use, call seek(d,c,s,JUST_SEEK), set s and hdr[]
unsigned write_sector(unsigned sec, unsigned char *data); // call seek(d,c,s,LOAD_SECTORS)
const SECHDR *get_sector(unsigned sec) const; // before use, call fill(d,c,s,LOAD_SECTORS)
void dump();
void clear()
{
drive = nullptr;
trkd = nullptr;
ts_byte = Z80FQ/(MAX_TRACK_LEN * FDD_RPS);
}
TRKCACHE() { clear(); }
};
struct FDD
{
u8 Id;
// drive data
__int64 motor; // 0 - not spinning, >0 - time when it'll stop
unsigned char track; // head position
// disk data
unsigned char *rawdata; // used in VirtualAlloc/VirtualFree
unsigned rawsize;
// ═рўры№эюх ўшёыю фюЁюцхъ (яЁш чруЁєчъх юсЁрчр шыш яЁш ёючфрэшш яєёЄюую фшёър), ьюцхЄ с√Є№ єтхышўхэю фю MAX_CYLS
// яєЄхь ЇюЁрЄшЁютрэш фюяюыэшЄхы№э√ї фюЁюцхъ єЄшышЄрьш Єшяр ADS ш яюфюсэ√ї
unsigned cyls;
unsigned sides;
unsigned trklen[MAX_CYLS][2];
u8 *trkd[MAX_CYLS][2]; // фрээ√х
u8 *trki[MAX_CYLS][2]; // сшЄют√х ърЁЄ√ ёшэїЁюшьяєы№ёют
u8 *trkwp[MAX_CYLS][2]; // сшЄют√х ърЁЄ√ ёсющэ√ї срщЄют
unsigned char optype; // bits: 0-not modified, 1-write sector, 2-format track
unsigned char snaptype;
TRKCACHE t; // used in read/write image
char name[0x200];
char dsc[0x200];
char test();
void free();
int index();
void format_trd(unsigned CylCnt); // ╚ёяюы№чєхЄё Єюы№ъю фы wldr_trd
void emptydisk(unsigned FreeSecCnt); // ╚ёяюы№чєхЄё Єюы№ъю фы wldr_trd
int addfile(unsigned char *hdr, unsigned char *data); // ╚ёяюы№чєхЄё Єюы№ъю фы wldr_trd
void addboot(); // ╚ёяюы№чєхЄё Єюы№ъю фы wldr_trd
void newdisk(unsigned cyls, unsigned sides);
int read(unsigned char snType);
int read_scl();
int read_hob();
int read_trd();
int write_trd(FILE *ff);
int read_fdi();
int write_fdi(FILE *ff);
int read_td0();
int write_td0(FILE *ff);
int read_udi();
int write_udi(FILE *ff);
void format_isd();
int read_isd();
int write_isd(FILE *ff);
void format_pro();
int read_pro();
int write_pro(FILE *ff);
~FDD() { free(); }
};
struct WD1793
{
enum WDSTATE
{
S_IDLE = 0,
S_WAIT,
S_DELAY_BEFORE_CMD,
S_CMD_RW,
S_FOUND_NEXT_ID,
S_RDSEC,
S_READ,
S_WRSEC,
S_WRITE,
S_WRTRACK,
S_WR_TRACK_DATA,
S_TYPE1_CMD,
S_STEP,
S_SEEKSTART,
S_RESTORE,
S_SEEK,
S_VERIFY,
S_VERIFY2,
S_WAIT_HLT,
S_WAIT_HLT_RW,
S_EJECT1,
S_EJECT2
};
__int64 next, time;
__int64 idx_tmo;
FDD *seldrive;
unsigned tshift;
WDSTATE state, state2;
unsigned char cmd;
unsigned char data, track, sector;
unsigned char rqs, status;
u8 sign_status; // ┬эх°эшх ёшуэры√ (яюър Єюы№ъю HLD)
unsigned drive, side; // update this with changing 'system'
signed char stepdirection;
unsigned char system; // beta128 system register
unsigned idx_cnt; // idx counter
// read/write sector(s) data
__int64 end_waiting_am;
unsigned foundid; // index in trkcache.hdr for next encountered ID and bytes before this ID
unsigned rwptr, rwlen;
// format track data
unsigned start_crc;
enum CMDBITS
{
CMD_SEEK_RATE = 0x03,
CMD_SEEK_VERIFY = 0x04,
CMD_SEEK_HEADLOAD = 0x08,
CMD_SEEK_TRKUPD = 0x10,
CMD_SEEK_DIR = 0x20,
CMD_WRITE_DEL = 0x01,
CMD_SIDE_CMP_FLAG = 0x02,
CMD_DELAY = 0x04,
CMD_SIDE = 0x08,
CMD_SIDE_SHIFT = 3,
CMD_MULTIPLE = 0x10
};
enum BETA_STATUS
{
DRQ = 0x40,
INTRQ = 0x80
};
enum WD_STATUS
{
WDS_BUSY = 0x01,
WDS_INDEX = 0x02,
WDS_DRQ = 0x02,
WDS_TRK00 = 0x04,
WDS_LOST = 0x04,
WDS_CRCERR = 0x08,
WDS_NOTFOUND = 0x10,
WDS_SEEKERR = 0x10,
WDS_RECORDT = 0x20,
WDS_HEADL = 0x20,
WDS_WRFAULT = 0x20,
WDS_WRITEP = 0x40,
WDS_NOTRDY = 0x80
};
enum WD_SYS
{
SYS_HLT = 0x08
};
enum WD_SIG
{
SIG_HLD = 0x01
};
unsigned char in(unsigned char port);
void out(unsigned char port, unsigned char val);
u8 RdStatus();
void process();
void find_marker();
char notready();
void load();
void getindex();
void trdos_traps();
// TRKCACHE trkcache;
FDD fdd[4];
bool EjectPending;
void Eject(unsigned Drive);
WD1793()
{
for(unsigned i = 0; i < 4; i++) // [vv] ─ы єфюсёЄтр юЄырфъш
fdd[i].Id = u8(i);
seldrive = &fdd[0];
idx_cnt = 0;
idx_tmo = LLONG_MAX;
sign_status = 0;
tshift = 0;
EjectPending = false;
}
};