File:  [UNIX Amiga Emulator] / uae / cia.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
  * 
  * CIA chip support v0.1
  * v0.0: 950301 
  *       stubs
  * v0.1: 950304
  *       hopefully all the timer functionality is implemented correctly
  *
  * (c) 1995 Bernd Schmidt
  */

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

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

static UBYTE ciaaicr,ciaaimask,ciabicr,ciabimask;
static UBYTE ciaacra,ciaacrb,ciabcra,ciabcrb;
static UWORD ciaata,ciaatb,ciabta,ciabtb;
static UWORD ciaala,ciaalb,ciabla,ciablb;
static ULONG ciaatod,ciabtod,ciaatol,ciabtol,ciaaalarm,ciabalarm;
static bool ciaatlatch,ciabtlatch;
static UBYTE ciaapra,ciaaprb,ciaadra,ciaadrb,ciaasdr;
static UBYTE ciabpra,ciabprb,ciabdra,ciabdrb,ciabsdr; 
static int div10,hsync,vsync;

static void setclr(UBYTE &p, UBYTE val)
{
  cout << "setclr\n";
  if (val & 0x80) {
    p |= val & 0x7F;
  } else {
    p &= ~val;
  }
}

static void RethinkICRA()
{
  if (ciaaimask & ciaaicr) {
    ciaaicr |= 0x80;
    mem.put_word(0xDFF09C,0x8008);
    cout << "CIA A int\n";
  } else {
    ciaaicr &= 0x7F;
    mem.put_word(0xDFF09C,0x0008);
  }
}

static void RethinkICRB()
{
  if (ciabimask & ciabicr) {
    ciabicr |= 0x80;
    mem.put_word(0xDFF09C,0xA000);
    cout << "CIA B int\n";
  } else {
    ciabicr &= 0x7F;
    mem.put_word(0xDFF09C,0x2000);
  }
}

UBYTE ReadCIAA(UWORD addr)
{
  UBYTE tmp;

  switch(addr & 0xf){
  case 0: 
    return (DISK_status() & 0x3C) | 0xc0; // no mouse
  case 1:
    return ciaaprb;
  case 2:
    return ciaadra;
  case 3:
    return ciaadrb;
  case 4:
    return ciaata & 0xff;
  case 5:
    return ciaata >> 8;
  case 6:
    return ciaatb & 0xff;
  case 7:
    return ciaatb >> 8;
  case 8:
    if (ciaatlatch) {
      ciaatlatch = 0;
      return ciaatol & 0xff;
    } else return ciaatod & 0xff;
  case 9:
    if (ciaatlatch) return (ciaatol >> 8) & 0xff;
    else return (ciaatod >> 8) & 0xff;
  case 10:
    ciaatlatch = 1; ciaatol = ciaatod; // ??? only if not already latched?
    return (ciaatol >> 16) & 0xff;
  case 12:
    return ciaasdr;
  case 13:
    tmp = ciaaicr; ciaaicr = 0; RethinkICRA(); return tmp;
  case 14:
    return ciaacra;
  case 15:
    return ciaacrb;
  }
  return 0;
}

UBYTE ReadCIAB(UWORD addr)
{
  UBYTE tmp;

  switch(addr & 0xf){
  case 0: 
    return ciabpra;
  case 1:
    return ciabprb;
  case 2:
    return ciabdra;
  case 3:
    return ciabdrb;
  case 4:
    return ciabta & 0xff;
  case 5:
    return ciabta >> 8;
  case 6:
    return ciabtb & 0xff;
  case 7:
    return ciabtb >> 8;
  case 8:
    if (ciabtlatch) {
      ciabtlatch = 0;
      return ciabtol & 0xff;
    } else return ciabtod & 0xff;
  case 9:
    if (ciabtlatch) return (ciabtol >> 8) & 0xff;
    else return (ciabtod >> 8) & 0xff;
  case 10:
    ciabtlatch = 1; ciabtol = ciabtod;
    return (ciabtol >> 16) & 0xff;
  case 12:
    return ciabsdr;
  case 13:
    tmp = ciabicr; ciabicr = 0; RethinkICRB(); return tmp;
  case 14:
    return ciabcra;
  case 15:
    return ciabcrb;
  }
  return 0;
}

void WriteCIAA(UWORD addr,UBYTE val)
{
  switch(addr & 0xf){
  case 0: 
    ciaapra = (ciaapra & ~0x3) | (val & 0x3); break;
  case 1:
    ciaaprb = val; break;
  case 2:
    ciaadra = val; break;
  case 3:
    ciaadrb = val; break;
  case 4:
    ciaala = (ciaala & 0xff00) | val;
    break;
  case 5:
    ciaala = (ciaala & 0xff) | (val << 8);
    if ((ciaacra & 1) == 0) ciaata = ciaala;
    if (ciaacra & 8) { ciaata = ciaala; ciaacra |= 1; }//??? load latch always?
    break;
  case 6:
    ciaalb = (ciaalb & 0xff00) | val;
    break;
  case 7:
    ciaalb = (ciaalb & 0xff) | (val << 8);
    if ((ciaacrb & 1) == 0) ciaatb = ciaalb;
    if (ciaacrb & 8) { ciaatb = ciaalb; ciaacrb |= 1; }
    break;
  case 8:
    if (ciaacrb & 0x80){
      ciaaalarm = (ciaaalarm & ~0xff) | val;
    } else {
      ciaatod = (ciaatod & ~0xff) | val;
    }
    break;
  case 9:
    if (ciaacrb & 0x80){
      ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
    } else {
      ciaatod = (ciaatod & ~0xff00) | (val << 8);
    }
    break;
  case 10:
    if (ciaacrb & 0x80){
      ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
    } else {
      ciaatod = (ciaatod & ~0xff0000) | (val << 16);
    }
    break;
  case 12:
    ciaasdr = val; break;
  case 13:
    setclr(ciaaimask,val); break; // ??? call RethinkICR() ?
  case 14:
    ciaacra = val;
    if (ciaacra & 0x10){
      ciaacra &= ~0x10;
      ciaata = ciaala;
    }
    cout << "CIAACRA write" << val << "\n";
    break;
  case 15:
    ciaacrb = val; 
    if (ciaacrb & 0x10){
      ciaacrb &= ~0x10;
      ciaatb = ciaalb;
    }
    cout << "CIAACRB write" << val << "\n";
    break;
  }
}

void WriteCIAB(UWORD addr,UBYTE val)
{
  switch(addr & 0xf){
  case 0:
    ciabpra = (ciabpra & ~0x3) | (val & 0x3); break;
  case 1:
    ciabprb = val; DISK_select(val); break;
  case 2:
    ciabdra = val; break;
  case 3:
    ciabdrb = val; break;
  case 4:
    ciabla = (ciabla & 0xff00) | val;
    break;
  case 5:
    ciabla = (ciabla & 0xff) | (val << 8);
    if ((ciabcra & 1) == 0) ciabta = ciabla;
    if (ciabcra & 8) { ciabta = ciabla; ciabcra |= 1; } 
    break;
  case 6:
    ciablb = (ciablb & 0xff00) | val;
    break;
  case 7:
    ciablb = (ciablb & 0xff) | (val << 8);
    if ((ciabcrb & 1) == 0) ciabtb = ciablb;
    if (ciabcrb & 8) { ciabtb = ciablb; ciabcrb |= 1; }
    break;
  case 8:
    if (ciabcrb & 0x80){
      ciabalarm = (ciabalarm & ~0xff) | val;
    } else {
      ciabtod = (ciabtod & ~0xff) | val;
    }
    break;
  case 9:
    if (ciabcrb & 0x80){
      ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
    } else {
      ciabtod = (ciabtod & ~0xff00) | (val << 8);
    }
    break;
  case 10:
    if (ciabcrb & 0x80){
      ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
    } else {
      ciabtod = (ciabtod & ~0xff0000) | (val << 16);
    }
    break;
  case 12:
    ciabsdr = val; break;
  case 13:
    setclr(ciabimask,val); break;
  case 14:
    ciabcra = val;
    if (ciabcra & 0x10){
      ciabcra &= ~0x10;
      ciabta = ciabla;
    }
    break;
    cout << "CIABCRA write" << val << "\n";
  case 15:
    ciabcrb = val; 
    if (ciabcrb & 0x10){
      ciabcrb &= ~0x10;
      ciabtb = ciablb;
    }
    break;
    cout << "CIBACRB write" << val << "\n";
  }
}

void CIA_reset()
{
  ciaatlatch = ciabtlatch = 0;
  ciaatod = ciabtod = 0;
  ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
  ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; // outmode = toggle;
  div10 = 0; hsync = vsync = 0;
}

void CIA_hsync() { hsync = 1; }
void CIA_vsync() { vsync = 1; }

void CIA_cycle()
{
  int aovfla = 0, aovflb = 0, bovfla = 0, bovflb = 0;
  //int foo = ciaacra | ciaacrb | ciabcra | ciabcrb;

  if (++div10 > 9) {
 //   if (foo & 1) cout << "CIA is ON: ICRs "<< hex << (int)ciaaimask << " " << (int)ciabimask << "!\n";
    div10 = 0;
    // CIA A timers
    if ((ciaacra & 0x21) == 0x01) {
      if (ciaata-- == 0) {
	aovfla = 1;
	if ((ciaacrb & 0x61) == 0x41) {
	  if (ciaatb-- == 0) aovflb = 1;
	}
      } 
    }
    if ((ciaacrb & 0x61) == 0x01) {
      if (ciaatb-- == 0) {
	aovflb = 1;
      }
    }
    // CIA B timers
    if ((ciabcra & 0x21) == 0x01) {
      if (ciabta-- == 0) {
	bovfla = 1;
	if ((ciabcrb & 0x61) == 0x41) {
	  if (ciabtb-- == 0) bovflb = 1;
	}
      } 
    }
    if ((ciabcrb & 0x61) == 0x01) {
      if (ciabtb-- == 0) {
	bovflb = 1;
      }
    }
    if (aovfla) {
      ciaaicr |= 1; RethinkICRA();
      ciaata = ciaala;
      if (ciaacra & 0x8) ciaacra &= ~1;
    }
    if (aovflb) {
      ciaaicr |= 2; RethinkICRA();
      ciaatb = ciaalb;
      if (ciaacrb & 0x8) ciaacrb &= ~1;
    }
    if (bovfla) {
      ciabicr |= 1; RethinkICRB();
      ciabta = ciabla;
      if (ciabcra & 0x8) ciabcra &= ~1;
    }
    if (bovflb) {
      ciabicr |= 2; RethinkICRA();
      ciabtb = ciablb;
      if (ciabcrb & 0x8) ciabcrb &= ~1;
    }
  }
  if (hsync){
    hsync = 0;
    ciabtod++;
    ciabtod &= 0xFFFFFF;
    if (ciabtod == ciabalarm) {
      ciabicr |= 4; RethinkICRB();
    }
  }
  if (vsync){
    vsync = 0;
    ciaatod++;
    ciaatod &= 0xFFFFFF;
    if (ciaatod == ciaaalarm) {
      ciaaicr |= 4; RethinkICRA();
    }
  }
  
}

void dumpcia()
{
  cout << hex << setw(2);
  cout << "A: CRA: " << (int)ciaacra << " CRB: " <<(int)ciaacrb << "IMASK: " <<
    (int)ciaaimask << " TOD: " << ciaatod << (ciaatlatch ? " latched" : "") << 
      " TA: " << ciaata << " TB:" << ciaatb << "\n"; 
  cout << "B: CRA: " << (int)ciabcra << " CRB: " <<(int)ciabcrb << "IMASK: " <<
    (int)ciabimask << " TOD: " << ciabtod << (ciabtlatch ? " latched" : "") << 
      " TA:" << ciabta << " TB:" << ciabtb << "\n"; 
}

UWORD cia64k::wget(UWORD addr)
{
  return bget(addr+1);
}

UBYTE cia64k::bget(UWORD addr)
{
 // cout << "CIA read at " << addr << "\n";
  if ((addr & 0xF0FF) == 0xE001)
    return ReadCIAA((addr & 0xF00) >> 8);
  if ((addr & 0xF0FF) == 0xD000)
    return ReadCIAB((addr & 0xF00) >> 8);
  return 0;
}

void cia64k::wput(UWORD addr,UWORD value)
{
  bput(addr+1,value);
}

void cia64k::bput(UWORD addr,UBYTE value)
{
//  cout << "CIA write " << (int)value << " at " << addr << "\n";
  if ((addr & 0xF0FF) == 0xE001)
    WriteCIAA((addr & 0xF00) >> 8,value);
  if ((addr & 0xF0FF) == 0xD000)
    WriteCIAB((addr & 0xF00) >> 8,value);
}

unix.superglobalmegacorp.com

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