File:  [UNIX Amiga Emulator] / uae / disk.cc
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:37:52 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, BSchmidt
CVS tags: uae001, HEAD
uae-0.1

 /* 
  * UAE - The Unusable Amiga Emulator
  * 
  * disk support v0.0
  * v0.0: 950312
  *
  * (c) 1995 Bernd Schmidt
  */

#include <iostream.h>
#include <iomanip.h>
#include <unistd.h>
#include <stdio.h>

#include "amiga.h"
#include "disk.h"

static int side, direction, step;
static UBYTE selected = 15;
static bool dskready;

class drive {
  FILE *diskfile;
  unsigned int track;
  unsigned int motoroff;
  unsigned int trackoffs,insecpos;
  bool secok;
  UBYTE secbuf[544];
  UWORD mfmbuf[544];
  ULONG getseculong(unsigned int offset);
  ULONG getmfmulong(unsigned int offset);
  void readsec();
public:
  drive(char *fname=0);
  void eject();
  void insert(char *fname);
  void step();
  bool track0() { return track == 0; }
  bool empty() { return diskfile == 0; }
  void motor(int off);
  void GetData(UWORD &,UWORD &);
};

drive::drive(char *fname)
{
  diskfile = 0;
  if (fname != 0) insert(fname);
  track = 0;
  motoroff = 1;
}

void drive::eject()
{
  if (diskfile != 0) fclose(diskfile);
  diskfile = 0;
}

void drive::insert(char *fname)
{
  diskfile = fopen(fname,"r+");
}

void drive::step()
{
  if (direction) {
    if (track) track--;
  } else {
    if(track<85) track++;
  }
}

void drive::motor(int off) 
{
  if (motoroff && !off) { trackoffs = 0; insecpos = 0; secok = false; }
  motoroff = off;
}

ULONG drive::getmfmulong(unsigned int offs)
{
  return (mfmbuf[offs] << 16) | mfmbuf[offs+1];
}

ULONG drive::getseculong(unsigned int offs)
{
  return (secbuf[offs] << 24) | (secbuf[offs+1] << 16) | (secbuf[offs+2] << 8)
    | (secbuf[offs+3]);
}

void drive::readsec()
{
  int i;
  secbuf[0] = secbuf[1] = 0x00;
  secbuf[2] = secbuf[3] = 0xa1;
  secbuf[4] = 0xff;
  secbuf[5] = track*2+side;
  secbuf[6] = trackoffs;
  secbuf[7] = 10-trackoffs;
  for(i=8;i<24;i++) secbuf[i] = 0;
  fseek(diskfile,((track*2+side)*11+trackoffs)*512,SEEK_SET);
  fread(&secbuf[32],sizeof(UBYTE),512,diskfile);

  mfmbuf[0] = mfmbuf[1] = 0xaaaa;
  mfmbuf[2] = mfmbuf[3] = 0x4489;
  ULONG deven,dodd;
  deven = getseculong(4); 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] = 0;
  for (i=0;i<512;i+=4){
    deven = getseculong(i+32);
    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;
  }
  
  ULONG hck=0,dck=0;
  for(i=4;i<24;i+=2) hck += getmfmulong(i);
  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 += getmfmulong(i);
  deven = dodd = dck; dodd >>= 1;
  mfmbuf[28] = dodd >> 16; mfmbuf[29] = dodd;
  mfmbuf[30] = deven>> 16; mfmbuf[31] = deven;  
  secok = true;
}

void drive::GetData(UWORD &mfm,UWORD &byt)
{
  if (!secok) readsec();
  mfm = mfmbuf[insecpos]; byt = secbuf[insecpos++];
  if (insecpos == 544){
    secok = false; 
    if (++trackoffs == 11) trackoffs = 0;
  }
}

static drive floppy[4];

void DISK_init()
{
  floppy[0].insert("wb13.adf");
}

void DISK_select(UBYTE data)
{
  int step_pulse;
  if (selected != ((data >> 3) & 15)) dskready = false;
  selected = (data >> 3) & 15;
  side = (data >> 2) & 1;
  direction = (data >> 1) & 1;
  step_pulse = data & 1;
  if (step != step_pulse) {
    step = step_pulse;
    if (step == 0){
      for (int dr=0;dr<4;dr++){
	if (!(selected & (1<<dr))) {
	  floppy[dr].step();
	}
      }
    }
  }
  for (int dr=0;dr<4;dr++){
    if (!(selected & (1<<dr))) {
      floppy[dr].motor(data >> 7);
    }
  }
}

UBYTE DISK_status()
{
  UBYTE st = 0x3c;
  if (dskready) st &= ~0x20;
  dskready = true;
  for (int dr=0;dr<4;dr++){
    if (!(selected & (1 << dr))) {
      if (floppy[dr].track0()) { st &= ~0x10; }
      if (floppy[dr].empty()) { st &= ~0x4; }
    }
  }
  return st;
}

void DISK_GetData(UWORD &mfm,UWORD &byt)
{
  for (int dr=0;dr<4;dr++){
    if (!(selected & (1<<dr))) {
      floppy[dr].GetData(mfm,byt);
    }
  }
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.