777 lines
18 KiB
C
777 lines
18 KiB
C
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#ifdef CATWEASEL
|
|
|
|
#include "options.h"
|
|
#include "memory.h"
|
|
#include "ioport.h"
|
|
#include "catweasel.h"
|
|
#include "uae.h"
|
|
|
|
struct catweasel_contr cwc;
|
|
|
|
static int cwhsync;
|
|
static int handshake;
|
|
|
|
void catweasel_hsync (void)
|
|
{
|
|
if (cwhsync <= 0)
|
|
return;
|
|
cwhsync--;
|
|
if (cwhsync == 0) {
|
|
if (handshake)
|
|
ioport_write (currprefs.catweasel_io + 0xd0, 0);
|
|
handshake = 0;
|
|
}
|
|
}
|
|
|
|
int catweasel_read_joystick (uae_u8 *dir, uae_u8 *buttons)
|
|
{
|
|
if (cwc.type != CATWEASEL_TYPE_MK3)
|
|
return 0;
|
|
*dir = ioport_read (currprefs.catweasel_io + 0xc0);
|
|
*buttons = ioport_read (currprefs.catweasel_io + 0xc8);
|
|
return 1;
|
|
}
|
|
|
|
int catweasel_read_keyboard (uae_u8 *keycode)
|
|
{
|
|
uae_u8 v;
|
|
if (cwc.type != CATWEASEL_TYPE_MK3)
|
|
return 0;
|
|
v = ioport_read (currprefs.catweasel_io + 0xd4);
|
|
if (!(v & 0x80))
|
|
return 0;
|
|
if (handshake)
|
|
return 0;
|
|
*keycode = ioport_read (currprefs.catweasel_io + 0xd0);
|
|
ioport_write (currprefs.catweasel_io + 0xd0, 0);
|
|
handshake = 1;
|
|
cwhsync = 10;
|
|
return 1;
|
|
}
|
|
|
|
uae_u32 catweasel_do_bget (uaecptr addr)
|
|
{
|
|
if (cwc.type == CATWEASEL_TYPE_MK3) {
|
|
if ((currprefs.catweasel_io & 3) == 0 && addr >= 0xc0 && addr <= 0xfc)
|
|
return ioport_read (currprefs.catweasel_io + addr);
|
|
} else {
|
|
if (addr >= currprefs.catweasel_io && addr <= currprefs.catweasel_io + 8) {
|
|
return ioport_read (addr & 0x3ff);
|
|
} else if(addr >= 0x10000 + currprefs.catweasel_io && addr <= 0x10000 + currprefs.catweasel_io) {
|
|
return ioport_read (addr & 0x3ff);
|
|
} else if ((addr & 0x3ff) < 0x200 || (addr & 0x3ff) >= 0x400) {
|
|
write_log("catweasel_bget @%08.8X!\n",addr);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void catweasel_do_bput (uaecptr addr, uae_u32 b)
|
|
{
|
|
if (cwc.type == CATWEASEL_TYPE_MK3) {
|
|
if ((currprefs.catweasel_io & 3) == 0 && addr >= 0xc0 && addr <= 0xfc)
|
|
ioport_write (currprefs.catweasel_io + addr, b);
|
|
} else {
|
|
if (addr >= currprefs.catweasel_io && addr <= currprefs.catweasel_io + 8) {
|
|
ioport_write (addr & 0x3ff, b);
|
|
} else if(addr >= 0x10000 + currprefs.catweasel_io && addr <= 0x10000 + currprefs.catweasel_io) {
|
|
ioport_write (addr & 0x3ff, b);
|
|
} else if ((addr & 0x3ff) < 0x200 || (addr & 0x3ff) >= 0x400) {
|
|
write_log("catweasel_bput @%08.8X=%02.2X!\n",addr,b);
|
|
}
|
|
}
|
|
}
|
|
|
|
int catweasel_init (void)
|
|
{
|
|
if (!currprefs.catweasel_io)
|
|
return 0;
|
|
if (!ioport_init ())
|
|
return 0;
|
|
cwc.type = currprefs.catweasel_io >= 0x400 ? CATWEASEL_TYPE_MK3 : CATWEASEL_TYPE_MK1;
|
|
cwc.iobase = currprefs.catweasel_io;
|
|
catweasel_init_controller (&cwc);
|
|
return 1;
|
|
}
|
|
|
|
void catweasel_free (void)
|
|
{
|
|
if (!currprefs.catweasel_io)
|
|
return;
|
|
ioport_free ();
|
|
}
|
|
|
|
#define outb(v,port) ioport_write(port,v)
|
|
#define inb(port) ioport_read(port)
|
|
|
|
#define LONGEST_TRACK 16000
|
|
|
|
static uae_u8 mfmbuf[LONGEST_TRACK * 4];
|
|
static uae_u8 tmpmfmbuffer[LONGEST_TRACK * 2];
|
|
|
|
static int bitshiftcompare(uae_u8 *src,int bit,int len,uae_u8 *comp)
|
|
{
|
|
uae_u8 b;
|
|
int ones,zeros,len2;
|
|
|
|
ones=zeros=0;
|
|
len2=len;
|
|
while(len--) {
|
|
b = (comp[0] << bit) | (comp[1] >> (8 - bit));
|
|
if(b != *src) return 1;
|
|
if(b==0x00) zeros++;
|
|
if(b==0xff) ones++;
|
|
src++;
|
|
comp++;
|
|
}
|
|
if(ones==len2||zeros==len2) return 1;
|
|
return 0;
|
|
}
|
|
|
|
static uae_u8 *mergepieces(uae_u8 *start,int len,int bits,uae_u8 *sync)
|
|
{
|
|
uae_u8 *dst=tmpmfmbuffer;
|
|
uae_u8 b;
|
|
int size;
|
|
int shift;
|
|
|
|
size=len-(sync-start);
|
|
memcpy(dst,sync,size);
|
|
dst+=size;
|
|
b=start[len];
|
|
b&=~(255>>bits);
|
|
b|=start[0]>>bits;
|
|
*dst++=b;
|
|
shift=8-bits;
|
|
while(start<=sync+2000) {
|
|
*dst++=(start[0]<<shift)|(start[1]>>(8-shift));
|
|
start++;
|
|
}
|
|
return tmpmfmbuffer;
|
|
}
|
|
|
|
#define SCANOFFSET 1 /* scanning range in bytes, -SCANOFFSET to SCANOFFSET */
|
|
#define SCANOFFSET2 20
|
|
#define SCANLENGHT 200 /* scanning length in bytes */
|
|
|
|
static uae_u8* scantrack(uae_u8 *sync1,uae_u8 *sync2,int *trackbytes,int *trackbits)
|
|
{
|
|
int i,bits,bytes,matched;
|
|
uae_u8 *sync2bak=sync2;
|
|
|
|
sync1+=SCANOFFSET2;
|
|
sync2+=SCANOFFSET2;
|
|
while(sync1 < sync2bak - 2*SCANOFFSET - SCANOFFSET2 - SCANLENGHT) {
|
|
matched=0x7fff;
|
|
for(i=0;i<2*SCANOFFSET*8;i++) {
|
|
bits=i&7;
|
|
bytes=-SCANOFFSET+(i>>3);
|
|
if(!bitshiftcompare(sync1,bits,SCANLENGHT,sync2+bytes)) {
|
|
if(matched==0x7fff) {
|
|
matched=i;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(matched!=0x7fff && i>=2*SCANOFFSET*8) {
|
|
bits=matched&7;
|
|
bytes=-SCANOFFSET+(matched>>3);
|
|
*trackbytes=sync2+bytes-sync1;
|
|
*trackbits=bits;
|
|
return mergepieces(sync1,*trackbytes,*trackbits,sync2bak);
|
|
}
|
|
sync1++;
|
|
sync2++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static unsigned char threshtab[128];
|
|
|
|
static void codec_makethresh(int trycnt, const unsigned char *origt, unsigned char *t, int numthresh)
|
|
{
|
|
static unsigned char tab[10] = { 0, 0, 0, 0, -1, -2, 1, 2, -1, 1 };
|
|
|
|
if (trycnt >= sizeof (tab))
|
|
trycnt = sizeof (tab) - 1;
|
|
while(numthresh--)
|
|
t[numthresh] = origt[numthresh] + tab[trycnt];
|
|
}
|
|
|
|
static void codec_init_threshtab(int trycnt, const unsigned char *origt)
|
|
{
|
|
static unsigned char old_thresholds[2] = { 0, 0 };
|
|
unsigned char t[2];
|
|
int a, i;
|
|
|
|
codec_makethresh(trycnt, origt, t, 2);
|
|
|
|
if(*(unsigned short*)t == *(unsigned short*)old_thresholds)
|
|
return;
|
|
|
|
for(i=0,a=2; i<128; i++) {
|
|
if(i == t[0] || i == t[1])
|
|
a++;
|
|
threshtab[i] = a;
|
|
}
|
|
|
|
*(unsigned short*)&old_thresholds = *(unsigned short*)t;
|
|
}
|
|
|
|
static __inline__ void CWSetCReg(catweasel_contr *c, unsigned char clear, unsigned char set)
|
|
{
|
|
c->control_register = (c->control_register & ~clear) | set;
|
|
outb(c->control_register, c->io_sr);
|
|
}
|
|
|
|
static void CWTriggerStep(catweasel_contr *c)
|
|
{
|
|
CWSetCReg(c, c->crm_step, 0);
|
|
CWSetCReg(c, 0, c->crm_step);
|
|
}
|
|
|
|
void catweasel_init_controller(catweasel_contr *c)
|
|
{
|
|
int i, j;
|
|
|
|
if(!c->iobase)
|
|
return;
|
|
|
|
switch(c->type) {
|
|
case CATWEASEL_TYPE_MK1:
|
|
c->crm_sel0 = 1 << 5;
|
|
c->crm_sel1 = 1 << 4;
|
|
c->crm_mot0 = 1 << 3;
|
|
c->crm_mot1 = 1 << 7;
|
|
c->crm_dir = 1 << 1;
|
|
c->crm_step = 1 << 0;
|
|
c->srm_trk0 = 1 << 4;
|
|
c->srm_dchg = 1 << 5;
|
|
c->srm_writ = 1 << 1;
|
|
c->io_sr = c->iobase + 2;
|
|
c->io_mem = c->iobase;
|
|
break;
|
|
case CATWEASEL_TYPE_MK3:
|
|
c->crm_sel0 = 1 << 2;
|
|
c->crm_sel1 = 1 << 3;
|
|
c->crm_mot0 = 1 << 1;
|
|
c->crm_mot1 = 1 << 5;
|
|
c->crm_dir = 1 << 4;
|
|
c->crm_step = 1 << 7;
|
|
c->srm_trk0 = 1 << 2;
|
|
c->srm_dchg = 1 << 5;
|
|
c->srm_writ = 1 << 6;
|
|
c->srm_dskready = 1 << 4;
|
|
c->io_sr = c->iobase + 0xe8;
|
|
c->io_mem = c->iobase + 0xe0;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
c->control_register = 255;
|
|
|
|
/* select all drives, step inside */
|
|
CWSetCReg(c, c->crm_dir | c->crm_sel0 | c->crm_sel1, 0);
|
|
for(i=0;i<2;i++) {
|
|
c->drives[i].number = i;
|
|
c->drives[i].contr = c;
|
|
c->drives[i].diskindrive = 0;
|
|
|
|
/* select only the respective drive, step to track 0 */
|
|
if(i == 0) {
|
|
CWSetCReg(c, c->crm_sel0, c->crm_dir | c->crm_sel1);
|
|
} else {
|
|
CWSetCReg(c, c->crm_sel1, c->crm_dir | c->crm_sel0);
|
|
}
|
|
|
|
for(j = 0; j < 86 && (inb(c->io_sr) & c->srm_trk0); j++) {
|
|
CWTriggerStep(c);
|
|
sleep_millis(6);
|
|
}
|
|
|
|
if(j < 86) {
|
|
c->drives[i].type = 1;
|
|
c->drives[i].track = 0;
|
|
} else {
|
|
c->drives[i].type = 0;
|
|
}
|
|
}
|
|
c->drives[0].sel = c->crm_sel0;
|
|
c->drives[0].mot = c->crm_mot0;
|
|
c->drives[1].sel = c->crm_sel1;
|
|
c->drives[1].mot = c->crm_mot1;
|
|
CWSetCReg(c, 0, c->crm_sel0 | c->crm_sel1); /* deselect all drives */
|
|
}
|
|
|
|
void catweasel_free_controller(catweasel_contr *c)
|
|
{
|
|
if(!c->iobase)
|
|
return;
|
|
|
|
/* all motors off, deselect all drives */
|
|
CWSetCReg(c, 0, c->crm_mot0 | c->crm_mot1 | c->crm_sel0 | c->crm_sel1);
|
|
}
|
|
|
|
void catweasel_set_motor(catweasel_drive *d, int on)
|
|
{
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
if (on)
|
|
CWSetCReg(d->contr, d->mot, 0);
|
|
else
|
|
CWSetCReg(d->contr, 0, d->mot);
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
}
|
|
|
|
int catweasel_step(catweasel_drive *d, int dir)
|
|
{
|
|
catweasel_contr *c = d->contr;
|
|
CWSetCReg(c, d->sel, 0);
|
|
if (dir > 0)
|
|
CWSetCReg(c, c->crm_dir, 0);
|
|
else
|
|
CWSetCReg(c, 0, c->crm_dir);
|
|
CWTriggerStep (c);
|
|
CWSetCReg(c, 0, d->sel);
|
|
d->track += dir > 0 ? 1 : -1;
|
|
return 1;
|
|
}
|
|
|
|
int catweasel_disk_changed(catweasel_drive *d)
|
|
{
|
|
int ret;
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
ret = (inb(d->contr->io_sr) & d->contr->srm_dchg) ? 0 : 1;
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
return ret;
|
|
}
|
|
|
|
int catweasel_diskready(catweasel_drive *d)
|
|
{
|
|
int ret;
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
ret = (inb(d->contr->io_sr) & d->contr->srm_dskready) ? 0 : 1;
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
return ret;
|
|
}
|
|
|
|
int catweasel_track0(catweasel_drive *d)
|
|
{
|
|
int ret;
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
ret = (inb(d->contr->io_sr) & d->contr->srm_trk0) ? 0 : 1;
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
if (ret)
|
|
d->track = 0;
|
|
return ret;
|
|
}
|
|
|
|
int catweasel_write_protected(catweasel_drive *d)
|
|
{
|
|
int ret;
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
ret = !(inb(d->contr->io_sr) & 8);
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
return ret;
|
|
}
|
|
|
|
uae_u8 catweasel_read_byte(catweasel_drive *d)
|
|
{
|
|
return inb(d->contr->io_mem);
|
|
}
|
|
|
|
static const unsigned char amiga_thresholds[] = { 0x22, 0x30 }; // 27, 38 for 5.25"
|
|
|
|
#define FLOPPY_WRITE_LEN 6250
|
|
|
|
#define MFMMASK 0x55555555
|
|
static uae_u32 getmfmlong (uae_u16 * mbuf)
|
|
{
|
|
return (uae_u32)(((*mbuf << 16) | *(mbuf + 1)) & MFMMASK);
|
|
}
|
|
|
|
static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, int track)
|
|
{
|
|
int i, secwritten = 0;
|
|
uae_u32 odd, even, chksum, id, dlong;
|
|
uae_u8 *secdata;
|
|
uae_u8 secbuf[544];
|
|
char sectable[22];
|
|
int num_sectors = 11;
|
|
int ec = 0;
|
|
|
|
memset (sectable, 0, sizeof (sectable));
|
|
mend -= (4 + 16 + 8 + 512);
|
|
while (secwritten < num_sectors) {
|
|
int trackoffs;
|
|
|
|
do {
|
|
while (*mbuf++ != 0x4489) {
|
|
if (mbuf >= mend) {
|
|
ec = 1;
|
|
goto err;
|
|
}
|
|
}
|
|
} while (*mbuf++ != 0x4489);
|
|
|
|
odd = getmfmlong (mbuf);
|
|
even = getmfmlong (mbuf + 2);
|
|
mbuf += 4;
|
|
id = (odd << 1) | even;
|
|
|
|
trackoffs = (id & 0xff00) >> 8;
|
|
if (trackoffs > 10) {
|
|
ec = 2;
|
|
goto err;
|
|
}
|
|
chksum = odd ^ even;
|
|
for (i = 0; i < 4; i++) {
|
|
odd = getmfmlong (mbuf);
|
|
even = getmfmlong (mbuf + 8);
|
|
mbuf += 2;
|
|
|
|
dlong = (odd << 1) | even;
|
|
if (dlong) {
|
|
ec = 6;
|
|
goto err;
|
|
}
|
|
chksum ^= odd ^ even;
|
|
} /* could check here if the label is nonstandard */
|
|
mbuf += 8;
|
|
odd = getmfmlong (mbuf);
|
|
even = getmfmlong (mbuf + 2);
|
|
mbuf += 4;
|
|
if (((odd << 1) | even) != chksum) {
|
|
ec = 3;
|
|
goto err;
|
|
}
|
|
odd = (id & 0x00ff0000) >> 16;
|
|
if (odd != track) {
|
|
ec = 7;
|
|
goto err;
|
|
}
|
|
odd = getmfmlong (mbuf);
|
|
even = getmfmlong (mbuf + 2);
|
|
mbuf += 4;
|
|
chksum = (odd << 1) | even;
|
|
secdata = secbuf + 32;
|
|
for (i = 0; i < 128; i++) {
|
|
odd = getmfmlong (mbuf);
|
|
even = getmfmlong (mbuf + 256);
|
|
mbuf += 2;
|
|
dlong = (odd << 1) | even;
|
|
*secdata++ = dlong >> 24;
|
|
*secdata++ = dlong >> 16;
|
|
*secdata++ = dlong >> 8;
|
|
*secdata++ = dlong;
|
|
chksum ^= odd ^ even;
|
|
}
|
|
mbuf += 256;
|
|
if (chksum) {
|
|
ec = 4;
|
|
goto err;
|
|
}
|
|
sectable[trackoffs] = 1;
|
|
secwritten++;
|
|
memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
|
|
}
|
|
if (secwritten == 0 || secwritten < 0) {
|
|
ec = 5;
|
|
goto err;
|
|
}
|
|
return 0;
|
|
err:
|
|
write_log ("mfm decode error %d. secwritten=%d\n", ec, secwritten);
|
|
for (i = 0; i < num_sectors; i++)
|
|
write_log ("%d:%d ", i, sectable[i]);
|
|
write_log ("\n");
|
|
return ec;
|
|
}
|
|
|
|
static void mfmcode (uae_u16 * mfm, int words)
|
|
{
|
|
uae_u32 lastword = 0;
|
|
|
|
while (words--) {
|
|
uae_u32 v = *mfm;
|
|
uae_u32 lv = (lastword << 16) | v;
|
|
uae_u32 nlv = 0x55555555 & ~lv;
|
|
uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
|
|
|
|
*mfm++ = v | mfmbits;
|
|
lastword = v;
|
|
}
|
|
}
|
|
|
|
#define FLOPPY_GAP_LEN 360
|
|
|
|
static int amigados_mfmcode (uae_u8 *src, uae_u16 *dst, int num_secs, int track)
|
|
{
|
|
int sec;
|
|
memset (dst, 0xaa, FLOPPY_GAP_LEN * 2);
|
|
|
|
for (sec = 0; sec < num_secs; sec++) {
|
|
uae_u8 secbuf[544];
|
|
int i;
|
|
uae_u16 *mfmbuf = dst + 544 * sec + FLOPPY_GAP_LEN;
|
|
uae_u32 deven, dodd;
|
|
uae_u32 hck = 0, dck = 0;
|
|
|
|
secbuf[0] = secbuf[1] = 0x00;
|
|
secbuf[2] = secbuf[3] = 0xa1;
|
|
secbuf[4] = 0xff;
|
|
secbuf[5] = track;
|
|
secbuf[6] = sec;
|
|
secbuf[7] = num_secs - sec;
|
|
|
|
for (i = 8; i < 24; i++)
|
|
secbuf[i] = 0;
|
|
|
|
mfmbuf[0] = mfmbuf[1] = 0xaaaa;
|
|
mfmbuf[2] = mfmbuf[3] = 0x4489;
|
|
|
|
memcpy (secbuf + 32, src + sec * 512, 512);
|
|
deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
|
|
| (secbuf[6] << 8) | (secbuf[7]));
|
|
dodd = deven >> 1;
|
|
deven &= 0x55555555;
|
|
dodd &= 0x55555555;
|
|
|
|
mfmbuf[4] = dodd >> 16;
|
|
mfmbuf[5] = dodd;
|
|
mfmbuf[6] = deven >> 16;
|
|
mfmbuf[7] = deven;
|
|
|
|
for (i = 8; i < 48; i++)
|
|
mfmbuf[i] = 0xaaaa;
|
|
for (i = 0; i < 512; i += 4) {
|
|
deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
|
|
| (secbuf[i + 34] << 8) | (secbuf[i + 35]));
|
|
dodd = deven >> 1;
|
|
deven &= 0x55555555;
|
|
dodd &= 0x55555555;
|
|
mfmbuf[(i >> 1) + 32] = dodd >> 16;
|
|
mfmbuf[(i >> 1) + 33] = dodd;
|
|
mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
|
|
mfmbuf[(i >> 1) + 256 + 33] = deven;
|
|
}
|
|
|
|
for (i = 4; i < 24; i += 2)
|
|
hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
|
|
|
|
deven = dodd = hck;
|
|
dodd >>= 1;
|
|
mfmbuf[24] = dodd >> 16;
|
|
mfmbuf[25] = dodd;
|
|
mfmbuf[26] = deven >> 16;
|
|
mfmbuf[27] = deven;
|
|
|
|
for (i = 32; i < 544; i += 2)
|
|
dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
|
|
|
|
deven = dodd = dck;
|
|
dodd >>= 1;
|
|
mfmbuf[28] = dodd >> 16;
|
|
mfmbuf[29] = dodd;
|
|
mfmbuf[30] = deven >> 16;
|
|
mfmbuf[31] = deven;
|
|
mfmcode (mfmbuf + 4, 544 - 4);
|
|
|
|
}
|
|
return (num_secs * 544 + FLOPPY_GAP_LEN) * 2 * 8;
|
|
}
|
|
|
|
static uae_u16 amigamfmbuffer[LONGEST_TRACK];
|
|
static uae_u8 amigabuffer[512*22];
|
|
|
|
/* search and align to 0x4489 WORDSYNC markers */
|
|
static int isamigatrack(uae_u8 *mfmdata, uae_u8 *mfmdatae, uae_u16 *mfmdst, int track)
|
|
{
|
|
uae_u16 *dst = amigamfmbuffer;
|
|
int len;
|
|
int shift, syncshift, sync,ret;
|
|
uae_u32 l;
|
|
uae_u16 w;
|
|
|
|
sync = syncshift = shift = 0;
|
|
len = (mfmdatae - mfmdata) * 8;
|
|
if (len > LONGEST_TRACK * 8)
|
|
len = LONGEST_TRACK * 8;
|
|
while (len--) {
|
|
l = (mfmdata[0] << 16) | (mfmdata[1] << 8) | (mfmdata[2] << 0);
|
|
w = l >> (8 - shift);
|
|
if (w == 0x4489) {
|
|
sync = 1;
|
|
syncshift = 0;
|
|
}
|
|
if (sync) {
|
|
if (syncshift == 0) *dst++ = w;
|
|
syncshift ++;
|
|
if (syncshift == 16) syncshift = 0;
|
|
}
|
|
shift++;
|
|
if (shift == 8) {
|
|
mfmdata++;
|
|
shift = 0;
|
|
}
|
|
}
|
|
if (sync) {
|
|
ret=drive_write_adf_amigados (amigamfmbuffer, dst, amigabuffer, track);
|
|
if(!ret)
|
|
return amigados_mfmcode (amigabuffer, mfmdst, 11, track);
|
|
write_log ("decode error %d\n", ret);
|
|
} else {
|
|
write_log ("decode error: no sync found\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int catweasel_fillmfm (catweasel_drive *d, uae_u16 *mfm, int side, int clock, int rawmode)
|
|
{
|
|
int i, j, oldsync, syncs[10], synccnt, endcnt;
|
|
uae_u32 tt1 = 0, tt2 = 0;
|
|
uae_u8 *p1;
|
|
int bytes = 0, bits = 0;
|
|
static int lasttrack, trycnt;
|
|
|
|
if (cwc.type == 0)
|
|
return 0;
|
|
if (d->contr->control_register & d->mot)
|
|
return 0;
|
|
if (!catweasel_read (d, side, 1, rawmode))
|
|
return 0;
|
|
if(d->contr->type == CATWEASEL_TYPE_MK1) {
|
|
inb(d->contr->iobase + 1);
|
|
inb(d->contr->io_mem); /* ignore first byte */
|
|
} else {
|
|
outb(0, d->contr->iobase + 0xe4);
|
|
}
|
|
catweasel_read_byte (d);
|
|
if (lasttrack == d->track)
|
|
trycnt++;
|
|
else
|
|
trycnt = 0;
|
|
lasttrack = d->track;
|
|
codec_init_threshtab(trycnt, amiga_thresholds);
|
|
i = 0; j = 0;
|
|
synccnt = 0;
|
|
oldsync = -1;
|
|
endcnt = 0;
|
|
while (j < LONGEST_TRACK * 4) {
|
|
uae_u8 b = catweasel_read_byte (d);
|
|
if (b >= 250) {
|
|
if (b == 255 - endcnt) {
|
|
endcnt++;
|
|
if (endcnt == 5)
|
|
break;
|
|
} else
|
|
endcnt = 0;
|
|
}
|
|
if (rawmode) {
|
|
if (b & 0x80) {
|
|
if (oldsync < j) {
|
|
syncs[synccnt++] = j;
|
|
oldsync = j + 300;
|
|
}
|
|
}
|
|
if (synccnt >= 3 && j > oldsync)
|
|
break;
|
|
}
|
|
b = threshtab[b & 0x7f];
|
|
tt1 = (tt1 << b) + 1;
|
|
tt2 += b;
|
|
|
|
if (tt2 >= 16) {
|
|
tt2 -= 16;
|
|
mfmbuf[j++] = tt1 >> (tt2 + 8);
|
|
mfmbuf[j++] = tt1 >> tt2;
|
|
}
|
|
i++;
|
|
}
|
|
write_log ("cyl=%d, side=%d, length %d, syncs %d\n", d->track, side, j, synccnt);
|
|
if (rawmode) {
|
|
if (synccnt >= 3) {
|
|
p1 = scantrack (mfmbuf + syncs[1], mfmbuf + syncs[2], &bytes, &bits);
|
|
if (p1) {
|
|
j = 0;
|
|
for (i = 0; i < bytes + 2; i+=2) {
|
|
mfm[j++] = (p1[i] << 8) | p1[i + 1];
|
|
}
|
|
return bytes * 8 + bits;
|
|
}
|
|
}
|
|
} else {
|
|
return isamigatrack (mfmbuf, mfmbuf + j, mfm, d->track * 2 + side);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int catweasel_read(catweasel_drive *d, int side, int clock, int rawmode)
|
|
{
|
|
int iobase = d->contr->iobase;
|
|
|
|
CWSetCReg(d->contr, d->sel, 0);
|
|
if(d->contr->type == CATWEASEL_TYPE_MK1) {
|
|
CWSetCReg(d->contr, 1<<2, (!side)<<2); /* set disk side */
|
|
|
|
inb(iobase+1); /* ra reset */
|
|
outb(clock*128, iobase+3);
|
|
|
|
inb(iobase+1);
|
|
inb(iobase+0);
|
|
// inb(iobase+0);
|
|
// outb(0, iobase+3); /* don't store index pulse */
|
|
|
|
inb(iobase+1);
|
|
|
|
inb(iobase+7); /* start reading */
|
|
sleep_millis(rawmode ? 550 : 225);
|
|
outb(0, iobase+1); /* stop reading, don't reset RAM pointer */
|
|
|
|
outb(128, iobase+0); /* add data end mark */
|
|
outb(128, iobase+0);
|
|
|
|
inb(iobase+1); /* Reset RAM pointer */
|
|
} else {
|
|
CWSetCReg(d->contr, 1<<6, (!side)<<6); /* set disk side */
|
|
|
|
outb(0, iobase + 0xe4); /* Reset memory pointer */
|
|
switch(clock) {
|
|
case 0: /* 28MHz */
|
|
outb(128, iobase + 0xec);
|
|
break;
|
|
case 1: /* 14MHz */
|
|
outb(0, iobase + 0xec);
|
|
break;
|
|
}
|
|
inb(iobase + 0xe0);
|
|
inb(iobase + 0xe0);
|
|
outb(0, iobase + 0xec); /* no IRQs, no MFM predecode */
|
|
inb(iobase + 0xe0);
|
|
outb(0, iobase + 0xec); /* don't store index pulse */
|
|
|
|
outb(0, iobase + 0xe4); /* Reset memory pointer */
|
|
inb(iobase + 0xf0); /* start reading */
|
|
sleep_millis(rawmode ? 550 : 225);
|
|
inb(iobase + 0xe4); /* stop reading, don't reset RAM pointer */
|
|
|
|
outb(255, iobase + 0xe0); /* add data end mark */
|
|
outb(254, iobase + 0xe0); /* add data end mark */
|
|
outb(253, iobase + 0xe0); /* add data end mark */
|
|
outb(252, iobase + 0xe0); /* add data end mark */
|
|
outb(251, iobase + 0xe0); /* add data end mark */
|
|
outb(0, iobase + 0xe4); /* Reset memory pointer */
|
|
}
|
|
CWSetCReg(d->contr, 0, d->sel);
|
|
return 1;
|
|
}
|
|
|
|
#endif
|