2020-06-13 14:14:37 +00:00
|
|
|
/*
|
2020-05-24 14:16:40 +00:00
|
|
|
* UAE - The Un*x Amiga Emulator
|
2020-06-13 14:14:37 +00:00
|
|
|
*
|
2020-05-24 14:16:40 +00:00
|
|
|
* Floppy disk emulation
|
|
|
|
*
|
2020-08-16 19:26:22 +00:00
|
|
|
* Copyright 1995 Bernd Schmidt, Hannu Rummukainen
|
2020-05-24 14:16:40 +00:00
|
|
|
*/
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2020-05-24 14:16:40 +00:00
|
|
|
#include "shared.h"
|
|
|
|
|
|
|
|
#include "memory.h"
|
2020-06-13 14:14:37 +00:00
|
|
|
#include "events.h"
|
|
|
|
#include "custom.h"
|
2020-05-24 14:16:40 +00:00
|
|
|
#include "ersatz.h"
|
|
|
|
#include "disk.h"
|
|
|
|
#include "gui.h"
|
2020-08-16 19:26:22 +00:00
|
|
|
#include "zfile.h"
|
2020-06-13 14:14:37 +00:00
|
|
|
#include "autoconf.h"
|
|
|
|
#include "readcpu.h"
|
|
|
|
#include "newcpu.h"
|
|
|
|
#include "xwin.h"
|
2020-05-24 14:16:40 +00:00
|
|
|
|
|
|
|
#define NB_DRIVE 1
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
|
|
|
|
#define STATIC_INLINE static
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
#define FLOPPY_GAP_LEN 360
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
#define FLOPPY_SPEED 50
|
2020-06-13 14:14:37 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
#ifdef HAS_FLOPPYWRITE
|
|
|
|
uae_u16* mfmwrite;
|
|
|
|
static uae_u16 mfmwrbuffer[16384]; /* space for maximum disk DMA transfer */
|
|
|
|
#endif
|
2020-06-13 14:14:37 +00:00
|
|
|
|
|
|
|
static int side, direction, step;
|
|
|
|
static uae_u8 selected = 15;
|
|
|
|
static int dskready;
|
2020-05-24 14:16:40 +00:00
|
|
|
|
|
|
|
typedef struct {
|
2020-06-13 14:14:37 +00:00
|
|
|
uae_u16 sync;
|
|
|
|
uae_u16 len;
|
|
|
|
uae_u32 offs;
|
2020-05-24 14:16:40 +00:00
|
|
|
} trackid;
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
#define MAX_TRACKS 328
|
|
|
|
|
2020-05-24 14:16:40 +00:00
|
|
|
typedef enum { ADF_NORMAL, ADF_EXT1 } drive_filetype;
|
|
|
|
typedef struct {
|
|
|
|
FILE *diskfile;
|
|
|
|
drive_filetype filetype;
|
2020-06-13 14:14:37 +00:00
|
|
|
trackid trackdata[MAX_TRACKS];
|
|
|
|
unsigned int buffered_cyl, buffered_side;
|
|
|
|
unsigned int cyl;
|
|
|
|
int side;
|
2020-05-24 14:16:40 +00:00
|
|
|
int motoroff;
|
|
|
|
int wrprot;
|
2020-06-13 14:14:37 +00:00
|
|
|
uae_u16 bigmfmbuf[0x4000];
|
2020-08-16 19:26:22 +00:00
|
|
|
int mfmbufpos;
|
2020-06-13 14:14:37 +00:00
|
|
|
int tracklen;
|
|
|
|
unsigned long last_cycles;
|
|
|
|
int mfmpos;
|
|
|
|
unsigned int num_tracks, num_secs;
|
|
|
|
/* dskchange is set to a small number when a disk is removed. At a step
|
|
|
|
* impulse, it is reset if there is a new disk in the drive or counted
|
|
|
|
* down to 1 if the drive contains a disk. DISK_check_change will only
|
|
|
|
* insert a new disk when dskchange is 1, or if the dskchange_time timer
|
|
|
|
* expires. The last condition can happen if AmigaOS isn't running and a
|
|
|
|
* game/demo doesn't use the step motor to check for a new disk.
|
|
|
|
*/
|
|
|
|
int dskchange;
|
|
|
|
int dskchange_time;
|
2020-05-24 14:16:40 +00:00
|
|
|
} drive;
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
drive floppy[NB_DRIVE];
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static void drive_fill_bigbuf (drive *drv);
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
#ifdef unused
|
|
|
|
FILE *DISK_validate_filename (const char *fname, int leave_open, int *wrprot)
|
|
|
|
{
|
|
|
|
FILE *f = fopen (fname, "r+b");
|
|
|
|
if (f) {
|
|
|
|
if (wrprot)
|
|
|
|
*wrprot = 0;
|
|
|
|
} else {
|
|
|
|
if (wrprot)
|
|
|
|
*wrprot = 1;
|
|
|
|
f = fopen (fname, "rb");
|
|
|
|
}
|
|
|
|
if (!leave_open)
|
|
|
|
fclose (f);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
#endif
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static int drive_insert (drive *drv, int dnum, const char *fname)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
unsigned char buffer[10];
|
2020-08-16 19:26:22 +00:00
|
|
|
emu_printf("insert");
|
|
|
|
emu_printf(fname);
|
|
|
|
|
|
|
|
#ifdef unused
|
|
|
|
drv->diskfile = DISK_validate_filename (fname, 1, &drv->wrprot);
|
|
|
|
#endif
|
|
|
|
drv->diskfile = emu_FileOpen(fname);
|
|
|
|
if (drv->diskfile == 0) {
|
|
|
|
drv->tracklen = 2000;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy (currprefs.df[dnum], fname, 255);
|
|
|
|
currprefs.df[dnum][255] = 0;
|
|
|
|
strncpy (changed_prefs.df[dnum], fname, 255);
|
|
|
|
changed_prefs.df[dnum][255] = 0;
|
|
|
|
//gui_filename(dnum, fname);
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
emu_FileRead(buffer, 8);
|
2020-08-16 19:26:22 +00:00
|
|
|
if (strncmp((char *)buffer,"UAE--ADF",8) == 0) {
|
|
|
|
emu_printf("UAE--ADF");
|
|
|
|
int offs = 160*4+8;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
drv->filetype = ADF_EXT1;
|
|
|
|
drv->num_tracks = 160;
|
|
|
|
drv->num_secs = 11;
|
|
|
|
|
|
|
|
drv->wrprot = 1; /* write to adf_ext1 not implemented */
|
|
|
|
for(i=0; i<160; i++) {
|
|
|
|
emu_FileRead(buffer, 4);
|
|
|
|
drv->trackdata[i].sync = buffer[0]*256 + buffer[1];
|
|
|
|
drv->trackdata[i].len = buffer[2]*256 + buffer[3];
|
|
|
|
drv->trackdata[i].offs = offs;
|
|
|
|
offs += drv->trackdata[i].len;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsigned int i;
|
|
|
|
emu_printf("NORMAL");
|
|
|
|
|
|
|
|
drv->filetype = ADF_NORMAL;
|
|
|
|
|
|
|
|
i = emu_FileSize(fname);
|
|
|
|
emu_FileOpen(fname);
|
|
|
|
/* High-density disk? */
|
|
|
|
if (i >= 160*22*512)
|
|
|
|
drv->num_tracks = i / (512*(drv->num_secs = 22));
|
|
|
|
else
|
|
|
|
drv->num_tracks = i / (512*(drv->num_secs = 11));
|
|
|
|
|
|
|
|
if (drv->num_tracks > MAX_TRACKS)
|
|
|
|
write_log ("Your diskfile is too big!\n");
|
|
|
|
for(i = 0; i < drv->num_tracks; i++) {
|
|
|
|
drv->trackdata[i].len = 512 * drv->num_secs;
|
|
|
|
drv->trackdata[i].sync = 0;
|
|
|
|
drv->trackdata[i].offs = i * 512 * drv->num_secs;
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
drv->buffered_side = 2; /* will force read */
|
2020-08-16 19:26:22 +00:00
|
|
|
drive_fill_bigbuf (drv);
|
2020-06-13 14:14:37 +00:00
|
|
|
return 1;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static int drive_empty (drive *drv)
|
2020-06-13 14:14:37 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
return drv->diskfile == 0;
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static void drive_step (drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
if (!drive_empty(drv))
|
2020-08-16 19:26:22 +00:00
|
|
|
drv->dskchange = 0;
|
2020-06-13 14:14:37 +00:00
|
|
|
else if (drv->dskchange > 1) {
|
2020-08-16 19:26:22 +00:00
|
|
|
/* printf("Stepping...\n");
|
2020-06-13 14:14:37 +00:00
|
|
|
drv->dskchange--;*/
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
if (direction) {
|
2020-08-16 19:26:22 +00:00
|
|
|
if (drv->cyl) drv->cyl--;
|
2020-05-24 14:16:40 +00:00
|
|
|
} else {
|
2020-08-16 19:26:22 +00:00
|
|
|
if (drv->cyl < drv->num_tracks/2) drv->cyl++;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static int drive_track0 (drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
return drv->cyl == 0;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static int drive_writeprotected (drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
return drv->wrprot || drv->diskfile == NULL;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static int drive_running (drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
return !drv->motoroff;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static void drive_motor (drive *drv, int off)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
if (drv->motoroff && !off) {
|
2020-08-16 19:26:22 +00:00
|
|
|
drv->last_cycles = cycles;
|
|
|
|
drv->mfmpos = 0;
|
|
|
|
eventtab[ev_diskindex].active = 1;
|
|
|
|
if (drv->tracklen)
|
|
|
|
eventtab[ev_diskindex].evtime = FLOPPY_SPEED * drv->tracklen + cycles;
|
|
|
|
else
|
|
|
|
eventtab[ev_diskindex].evtime = cycles + 1000;
|
|
|
|
eventtab[ev_diskindex].oldcycles = cycles;
|
2020-06-13 14:14:37 +00:00
|
|
|
} else if (off)
|
2020-08-16 19:26:22 +00:00
|
|
|
eventtab[ev_diskindex].active = 0;
|
2020-05-24 14:16:40 +00:00
|
|
|
drv->motoroff = off;
|
2020-08-16 19:26:22 +00:00
|
|
|
events_schedule ();
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
static void drive_fill_bigbuf(drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
int tr = drv->cyl*2 + side;
|
2020-05-24 14:16:40 +00:00
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
if (!drv->diskfile) {
|
2020-08-16 19:26:22 +00:00
|
|
|
drv->tracklen = 2000;
|
|
|
|
memset (drv->bigmfmbuf,0xaa,drv->tracklen*2);
|
|
|
|
return;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
if (drv->buffered_cyl == drv->cyl && drv->buffered_side == side)
|
2020-08-16 19:26:22 +00:00
|
|
|
return;
|
2020-06-13 14:14:37 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
/* if (drv->num_tracks <= tr) {
|
|
|
|
write_log ("Access beyond end of floppy image!\n");
|
|
|
|
}*/
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
if (drv->trackdata[tr].sync == 0) {
|
2020-08-16 19:26:22 +00:00
|
|
|
/* Normal AmigaDOS format track */
|
|
|
|
unsigned int sec;
|
|
|
|
drv->tracklen = drv->num_secs*544 + FLOPPY_GAP_LEN;
|
|
|
|
memset (drv->bigmfmbuf,0xaa,FLOPPY_GAP_LEN*2);
|
|
|
|
|
|
|
|
for (sec = 0; sec < drv->num_secs; sec++) {
|
|
|
|
uae_u8 secbuf[544];
|
|
|
|
int i;
|
|
|
|
uae_u16 *mfmbuf = drv->bigmfmbuf + 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] = tr;
|
|
|
|
secbuf[6] = sec;
|
|
|
|
secbuf[7] = drv->num_secs-sec;
|
|
|
|
|
|
|
|
for(i = 8; i < 24; i++)
|
|
|
|
secbuf[i] = 0;
|
|
|
|
|
|
|
|
emu_FileSeek (drv->trackdata[tr].offs + sec*512,
|
|
|
|
SEEK_SET);
|
|
|
|
emu_FileRead (&secbuf[32],512);
|
|
|
|
|
|
|
|
mfmbuf[0] = mfmbuf[1] = 0xaaaa;
|
|
|
|
mfmbuf[2] = mfmbuf[3] = 0x4489;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
} else {
|
|
|
|
int i;
|
2020-08-16 19:26:22 +00:00
|
|
|
drv->tracklen = drv->trackdata[tr].len/2 + 1;
|
|
|
|
drv->bigmfmbuf[0] = drv->trackdata[tr].sync;
|
|
|
|
emu_FileSeek(drv->trackdata[tr].offs, SEEK_SET);
|
|
|
|
emu_FileRead((char *)(drv->bigmfmbuf + 1), drv->trackdata[tr].len);
|
|
|
|
for (i = 0; i < drv->trackdata[tr].len/2; i++) {
|
|
|
|
uae_u16 *mfm = drv->bigmfmbuf + i + 1;
|
|
|
|
uae_u8 *data = (uae_u8 *)mfm;
|
|
|
|
|
|
|
|
*mfm = 256 * *data + *(data+1);
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
|
|
|
drv->buffered_side = side;
|
|
|
|
drv->buffered_cyl = drv->cyl;
|
|
|
|
drv->last_cycles = cycles;
|
|
|
|
drv->mfmpos = 0;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
/* Perform DMA for the time interval since the last call. */
|
|
|
|
static int drive_update_reads (drive *drv, uaecptr *ptr, int *length, int *syncfound, int sync)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
unsigned long maxbytes = (cycles - drv->last_cycles) * 2 / FLOPPY_SPEED;
|
|
|
|
unsigned long maxcount = maxbytes >> 1;
|
|
|
|
drv->last_cycles += maxcount * FLOPPY_SPEED;
|
2020-06-13 14:14:37 +00:00
|
|
|
|
|
|
|
drive_fill_bigbuf(drv);
|
2020-08-16 19:26:22 +00:00
|
|
|
|
|
|
|
if (! ptr) {
|
|
|
|
if (! drv->motoroff)
|
|
|
|
drv->mfmpos += maxcount;
|
|
|
|
drv->mfmpos %= drv->tracklen;
|
|
|
|
} else {
|
|
|
|
while (maxcount-- > 0 && *length > 0) {
|
|
|
|
unsigned int word;
|
|
|
|
if (drv->mfmpos > drv->tracklen) {
|
|
|
|
write_log ("Bug in disk code - mfmpos too large\n");
|
|
|
|
drv->mfmpos = 0;
|
|
|
|
}
|
|
|
|
word = drv->bigmfmbuf[drv->mfmpos];
|
|
|
|
if (*syncfound) {
|
|
|
|
put_word (*ptr, word);
|
|
|
|
(*ptr) += 2;
|
|
|
|
(*length)--;
|
|
|
|
}
|
|
|
|
if (word == sync)
|
|
|
|
*syncfound = 1;
|
|
|
|
if (! drv->motoroff)
|
|
|
|
drv->mfmpos++;
|
|
|
|
if (drv->mfmpos > drv->tracklen)
|
|
|
|
drv->mfmpos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ! drv->motoroff && maxbytes >= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We assume that drive_update_reads has already been called. */
|
|
|
|
static void drive_get_data (drive *drv, uae_u16 *mfm, uae_u16 *byt)
|
|
|
|
{
|
|
|
|
*mfm = drv->bigmfmbuf[drv->mfmpos];
|
|
|
|
if (cycles - drv->last_cycles > (FLOPPY_SPEED / 2))
|
|
|
|
*byt = *mfm & 0xff;
|
|
|
|
else
|
|
|
|
*byt = (*mfm >> 8) & 0xff;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MFMMASK 0x55555555
|
2020-08-16 19:26:22 +00:00
|
|
|
STATIC_INLINE uae_u32 getmfmlong (uae_u16* mbuf)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
return ((*mbuf << 16) | *(mbuf + 1)) & MFMMASK;
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static void drive_write_data (drive *drv, uae_u16 *mbuf, int length)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
#ifdef HAS_FLOPPYWRITE
|
2020-05-24 14:16:40 +00:00
|
|
|
int i, secwritten = 0;
|
2020-06-13 14:14:37 +00:00
|
|
|
uae_u32 odd, even, chksum, id, dlong;
|
|
|
|
uae_u8* secdata;
|
|
|
|
uae_u8 secbuf[544];
|
|
|
|
uae_u16 *mend = mbuf + length;
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
if (drive_writeprotected (drv))
|
|
|
|
return;
|
2020-06-13 14:14:37 +00:00
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
drive_fill_bigbuf (drv);
|
2020-05-24 14:16:40 +00:00
|
|
|
mend -= (4 + 16 + 8 + 512);
|
2020-06-13 14:14:37 +00:00
|
|
|
while (length > 0) {
|
2020-08-16 19:26:22 +00:00
|
|
|
int trackoffs;
|
|
|
|
|
|
|
|
do {
|
|
|
|
while (*mbuf++ != 0x4489) {
|
|
|
|
if (mbuf >= mend)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} while (*mbuf++ != 0x4489);
|
|
|
|
|
|
|
|
odd = getmfmlong (mbuf);
|
|
|
|
even = getmfmlong (mbuf + 2);
|
|
|
|
mbuf += 4;
|
|
|
|
id = (odd << 1) | even;
|
|
|
|
|
|
|
|
trackoffs = (id & 0xff00) >> 8;
|
|
|
|
if (trackoffs > 10) {
|
|
|
|
//write_log ("Disk write: weird sector number %d\n", trackoffs);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
chksum = odd ^ even;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
odd = getmfmlong(mbuf);
|
|
|
|
even = getmfmlong(mbuf+8);
|
|
|
|
mbuf += 2;
|
|
|
|
|
|
|
|
dlong = (odd << 1) | even;
|
|
|
|
if (dlong)
|
|
|
|
secwritten = -200;
|
|
|
|
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
|
|
|
|
|| ((id & 0x00ff0000) >> 16) != drv->cyl*2 + side)
|
|
|
|
{
|
|
|
|
write_log ("Disk write: checksum error on sector header\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
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) & 0xff;
|
|
|
|
*secdata++ = dlong >> 8; *secdata++ = dlong;
|
|
|
|
chksum ^= odd ^ even;
|
|
|
|
}
|
|
|
|
mbuf += 256;
|
|
|
|
if (chksum) {
|
|
|
|
write_log ("Disk write: data checksum error\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
secwritten++;
|
|
|
|
emu_FileSeek (drv->trackdata[drv->cyl*2 + side].offs + trackoffs*512,
|
|
|
|
SEEK_SET);
|
|
|
|
emu_FileRead (secbuf+32, 512);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
drv->buffered_side = 2; /* will force read */
|
2020-08-16 19:26:22 +00:00
|
|
|
|
|
|
|
if (secwritten == 0)
|
|
|
|
write_log ("Disk write in unsupported format\n");
|
2020-05-24 14:16:40 +00:00
|
|
|
if (secwritten < 0)
|
2020-08-16 19:26:22 +00:00
|
|
|
write_log ("Disk write: sector labels ignored\n");
|
|
|
|
#endif
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
static void drive_eject (drive *drv)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
if (! drive_empty (drv))
|
|
|
|
emu_FileClose();
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
drv->dskchange = 4;
|
|
|
|
drv->dskchange_time = 20;
|
2020-08-16 19:26:22 +00:00
|
|
|
/* printf("setting changed bit %d\n", drv-floppy);*/
|
2020-05-24 14:16:40 +00:00
|
|
|
drv->diskfile = 0;
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
/* We use this function if we have no Kickstart ROM.
|
2020-06-13 14:14:37 +00:00
|
|
|
* No error checking - we trust our luck. */
|
|
|
|
void DISK_ersatz_read (int tr, int sec, uaecptr dest)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
uae_u8 *dptr = get_real_address(dest);
|
2020-08-16 19:26:22 +00:00
|
|
|
emu_FileSeek (floppy[0].trackdata[tr].offs + sec*512, SEEK_SET);
|
|
|
|
emu_FileRead (dptr, 512);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void disk_eject (int num)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
//gui_filename(num, "");
|
2020-05-24 14:16:40 +00:00
|
|
|
drive_eject(floppy + num);
|
2020-08-16 19:26:22 +00:00
|
|
|
*currprefs.df[num] = *changed_prefs.df[num] = 0;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void disk_insert (int num, const char *name)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
/* just to be sure */
|
2020-08-16 19:26:22 +00:00
|
|
|
drive_eject (floppy + num);
|
|
|
|
drive_insert (floppy + num, num, name);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-06-13 14:14:37 +00:00
|
|
|
void DISK_check_change (void)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
int i;
|
|
|
|
static int count = 0;
|
|
|
|
count++;
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
for (i = 0; i < NB_DRIVE; i++) {
|
|
|
|
if (strcmp (currprefs.df[i], changed_prefs.df[i]) != 0) {
|
|
|
|
if (currprefs.df[i][0] != '\0') {
|
|
|
|
drive_eject(floppy + i);
|
|
|
|
currprefs.df[i][0] = '\0';
|
|
|
|
//gui_filename(i, "");
|
|
|
|
} else if (floppy[i].dskchange == 1) {
|
|
|
|
/* In theory, it should work without the dskchange test.
|
|
|
|
* In practice, it doesn't. */
|
|
|
|
drive_insert (floppy + i, i, changed_prefs.df[i]);
|
|
|
|
} else if (floppy[i].dskchange > 1 && floppy[i].dskchange_time > 0) {
|
|
|
|
/* Force the dskchange bit to go to 1 after a given timeout */
|
|
|
|
if (--floppy[i].dskchange_time == 0) {
|
|
|
|
floppy[i].dskchange = 1;
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
2020-08-16 19:26:22 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
int disk_empty (int num)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
return drive_empty (floppy + num);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_init (void)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
int i;
|
2020-06-13 14:14:37 +00:00
|
|
|
for (i = 0; i < NB_DRIVE; i++)
|
2020-08-16 19:26:22 +00:00
|
|
|
if (!drive_insert (floppy+i, i, currprefs.df[i]))
|
|
|
|
disk_eject (i);
|
2020-06-13 14:14:37 +00:00
|
|
|
|
|
|
|
if (disk_empty (0))
|
2020-08-16 19:26:22 +00:00
|
|
|
write_log ("No disk in drive 0.\n");
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ledstate[] = { 0,0,0,0 };
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_select (uae_u8 data)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
int step_pulse;
|
|
|
|
int dr;
|
2020-08-16 19:26:22 +00:00
|
|
|
|
|
|
|
if (selected != ((data >> 3) & 15))
|
|
|
|
dskready = 0;
|
2020-05-24 14:16:40 +00:00
|
|
|
selected = (data >> 3) & 15;
|
2020-06-13 14:14:37 +00:00
|
|
|
side = 1 - ((data >> 2) & 1);
|
|
|
|
|
2020-05-24 14:16:40 +00:00
|
|
|
direction = (data >> 1) & 1;
|
|
|
|
step_pulse = data & 1;
|
|
|
|
if (step != step_pulse) {
|
2020-08-16 19:26:22 +00:00
|
|
|
step = step_pulse;
|
|
|
|
if (step == 0){
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++){
|
|
|
|
if (!(selected & (1 << dr))) {
|
|
|
|
drive_step (floppy + dr);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
2020-08-16 19:26:22 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++){
|
2020-08-16 19:26:22 +00:00
|
|
|
if (!(selected & (1<<dr))) {
|
|
|
|
drive_motor(floppy + dr, data >> 7);
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++) {
|
2020-08-16 19:26:22 +00:00
|
|
|
int state = (!(selected & (1<<dr))) | !floppy[dr].motoroff;
|
|
|
|
if (state == ledstate[dr])
|
|
|
|
continue;
|
|
|
|
//gui_led (dr + 1, state);
|
|
|
|
//ledstate[dr] = state;
|
|
|
|
//gui_ledstate &= ~(1 << (dr + 1));
|
|
|
|
//gui_ledstate |= state << (dr + 1);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
uae_u8 DISK_status (void)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-06-13 14:14:37 +00:00
|
|
|
uae_u8 st = 0x3c;
|
2020-05-24 14:16:40 +00:00
|
|
|
int dr;
|
2020-08-16 19:26:22 +00:00
|
|
|
|
2020-05-24 14:16:40 +00:00
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++){
|
2020-08-16 19:26:22 +00:00
|
|
|
drive *drv = floppy + dr;
|
|
|
|
if (!(selected & (1 << dr))) {
|
|
|
|
if (drive_running(drv)){
|
|
|
|
if (dskready) st &= ~0x20;
|
|
|
|
dskready = 1;
|
|
|
|
} else {
|
|
|
|
st &= ~0x20; /* report drive ID */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drive_track0 (drv)) { st &= ~0x10; }
|
|
|
|
if (drive_writeprotected (drv)) { st &= ~8; }
|
|
|
|
if (drv->dskchange) {
|
|
|
|
/*printf("changed bit set: %d\n",dr); */
|
|
|
|
st &= ~0x4;
|
|
|
|
if (drv->dskchange > 1)
|
|
|
|
drv->dskchange--;
|
|
|
|
}
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_GetData (uae_u16 *mfm, uae_u16 *byt)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
int dr;
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++){
|
|
|
|
if (!(selected & (1<<dr))) {
|
2020-08-16 19:26:22 +00:00
|
|
|
drive_get_data (floppy + dr, mfm, byt);
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_InitWrite (void)
|
|
|
|
{
|
|
|
|
#ifdef HAS_FLOPPYWRITE
|
|
|
|
mfmwrite = mfmwrbuffer;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int DISK_update_reads (uaecptr *ptr, int *length, int *syncfound, int sync)
|
2020-06-13 14:14:37 +00:00
|
|
|
{
|
|
|
|
int dr;
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++) {
|
2020-08-16 19:26:22 +00:00
|
|
|
if (!(selected & (1<<dr))) {
|
|
|
|
return drive_update_reads (floppy + dr, ptr, length, syncfound, sync);
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
2020-08-16 19:26:22 +00:00
|
|
|
return 0;
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_WriteData (int length)
|
2020-06-13 14:14:37 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
#ifdef HAS_FLOPPYWRITE
|
|
|
|
int dr;
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++) {
|
|
|
|
if (!(selected & (1<<dr))) {
|
|
|
|
drive_write_data(floppy + dr, mfmwrbuffer, length);
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|
2020-08-16 19:26:22 +00:00
|
|
|
#endif
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_search_sync (int cycle_limit, unsigned int sync)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
int dr;
|
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++) {
|
|
|
|
if (!(selected & (1 << dr))) {
|
|
|
|
drive *drv = floppy + dr;
|
|
|
|
unsigned long offs = drv->mfmpos;
|
|
|
|
unsigned long missing = FLOPPY_SPEED - (cycles - drv->last_cycles);
|
|
|
|
unsigned long count = 0;
|
|
|
|
if (missing == 0) {
|
|
|
|
write_log ("bug in disk code: missing == 0\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (missing < cycle_limit) {
|
|
|
|
count += missing;
|
|
|
|
cycle_limit -= missing;
|
|
|
|
missing = FLOPPY_SPEED;
|
|
|
|
if (drv->bigmfmbuf[offs] == sync) {
|
|
|
|
eventtab[ev_disksync].active = 1;
|
|
|
|
eventtab[ev_disksync].oldcycles = cycles;
|
|
|
|
eventtab[ev_disksync].evtime = cycles + count;
|
|
|
|
events_schedule ();
|
|
|
|
}
|
|
|
|
offs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
/* Called when DMA gets restarted, so that we don't do DMA for the
|
|
|
|
parts of the track that went past us while DMA was off. */
|
|
|
|
void DISK_reset_cycles (void)
|
2020-05-24 14:16:40 +00:00
|
|
|
{
|
|
|
|
int dr;
|
2020-08-16 19:26:22 +00:00
|
|
|
for (dr = 0; dr < NB_DRIVE; dr++) {
|
|
|
|
drive *drv = floppy + dr;
|
|
|
|
unsigned long count = (cycles - drv->last_cycles) / FLOPPY_SPEED;
|
|
|
|
drv->mfmpos += count;
|
|
|
|
drv->mfmpos %= drv->tracklen;
|
|
|
|
drv->last_cycles += count * FLOPPY_SPEED;
|
2020-05-24 14:16:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-16 19:26:22 +00:00
|
|
|
void DISK_StartRead ()
|
|
|
|
{
|
|
|
|
DISK_reset_cycles ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int first = 0;
|
|
|
|
|
|
|
|
void disk_swap(const char * disk0, const char * disk1)
|
2020-06-13 14:14:37 +00:00
|
|
|
{
|
2020-08-16 19:26:22 +00:00
|
|
|
emu_printf("disk swap");
|
|
|
|
drive_eject(floppy + 0);
|
|
|
|
if (first == 0)
|
|
|
|
{
|
|
|
|
first = 1;
|
|
|
|
emu_printf(disk0);
|
|
|
|
drive_insert(floppy + 0, 0, disk0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
first = 0;
|
|
|
|
emu_printf(disk1);
|
|
|
|
drive_insert(floppy + 0, 0, disk1);
|
|
|
|
}
|
2020-06-13 14:14:37 +00:00
|
|
|
}
|