File:  [UNIX Amiga Emulator] / uae / custom.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, 3 months ago) by root
Branches: MAIN, BSchmidt
CVS tags: uae001, HEAD
uae-0.1

 /* 
  * UAE - The Unusable Amiga Emulator
  * 
  * custom chip support v0.6
  *
  * v0.0: 950228
  *       provide DMACON/INTENA/INTREQ dummys so that KS gets the memory check
  *       right
  * v0.1: 950304
  *       more registers (partially) implemented
  *       copper and beam position should work, so should interrupts
  * v0.2: 950305
  *       Blitter implemented. Doesn't work.
  *       some b/w playfield support
  * v0.3: 950306
  *       many bug fixes
  * v0.4: 950309
  *       lots more bug fixes. A hand holding a disk appears in the X window!
  *       But it sure looks messed up.
  * v0.5: 950311
  *       hopefully fixed all remaining blitter bugs. The hand and the disk 
  *       look PERFECT!
  * v0.6: 950312
  *       interface to disk code
  *
  * (c) 1995 Bernd Schmidt
  */

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

#include "amiga.h"
#include "memory.h"
#include "custom.h"
#include "cia.h"
#include "disk.h"
#include "xwin.h"

static const int maxhpos = 227,maxvpos = 312;
static const int dskdelay = 80; // FIXME: ???

UWORD custom64k::wget(UWORD addr)
{
  UWORD (*f)() = cchiptable[(addr >> 1) & 0xFF].get;
  if (f != 0) return (*f)();
  else {
    cout << "Custom read at " << hex << addr << "\n";
    return 0;
  }
}

UBYTE custom64k::bget(UWORD addr)
{
  return wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
}

void custom64k::wput(UWORD addr,UWORD value)
{
  void (*f)(UWORD) = cchiptable[(addr >> 1) & 0xFF].put;
  if (f != 0) (*f)(value);
  else {
    cout << "Custom write " << hex << value << " at " << addr << "\n";
  }
}

void custom64k::bput(UWORD addr,UBYTE value)
{
  wput(addr & 0xfffe,value << (addr & 1 ? 0 : 8)); // ??
}

static void setclr(UWORD &p, UWORD val)
{
//  cout << "setclr, new val ";
  if (val & 0x8000) {
    p |= val & 0x7FFF;
  } else {
    p &= ~val;
  }
 // cout << hex << p << "\n";
}

 /* 
  * hardware register values that are visible/can be written to by someone
  */

static UWORD dmacon,intena,intreq,adkcon;
static UWORD vpos, hpos, lof;

static ULONG cop1lc,cop2lc,copcon;

static ULONG bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
static UWORD bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
static WORD  bpl1mod,bpl2mod;

static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
static WORD  bltamod,bltbmod,bltcmod,bltdmod;
static UWORD bltcon0,bltcon1;
static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;

static ULONG dskpt;
static UWORD dsklen,dsksync;

 /*
  * "hidden" hardware registers
  */

static ULONG coplc;
static UWORD copi1,copi2;

static enum {
  COP_stop, COP_read, COP_wait, COP_move, COP_skip  
} copstate;

static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
static bool blitonedot,blitsign;
static long int bltwait;

static enum {
  BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next,BLT_wait
} bltstate;

static UWORD plffirstline,plflastline,plffirstword,plflastword;

static enum {
  PF_above, PF_left, PF_within, PF_right, PF_below
} pfieldstate;

static UWORD dskmfm,dskbyte,dskdmaen,dsktime;
static bool dsksynced;

 /*
  * helper functions
  */

static void calcdiw()
{
  plffirstline = diwstrt >> 8;
  plflastline = diwstop >> 8;
  if ((plflastline & 0x80) == 0) plflastline |= 0x100;
  plffirstword = (ddfstrt & 0x1FC) * 4;
  plflastword = ((ddfstop & 0x1FC)+8) *4;
}

 /* 
  * register functions
  */

static UWORD DMACONR() 
{
  return dmacon | (bltstate==BLT_done ? 0 : 0x4000)
    | (blitzero ? 0x2000 : 0); 
}
static UWORD INTENAR() { return intena; }
static UWORD INTREQR() { return intreq; }
static UWORD ADKCONR() { return adkcon; }
static UWORD VPOSR() { return (vpos >> 8) | lof; }
static UWORD VHPOSR() { return (vpos << 8) | hpos; } 

static void  DMACON(UWORD v) { setclr(dmacon,v); dmacon &= 0x1FFF; }
static void  INTENA(UWORD v) { setclr(intena,v); }
static void  INTREQ(UWORD v) { setclr(intreq,v); }
static void  ADKCON(UWORD v) { setclr(adkcon,v); }

static void  BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
static void  BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
static void  BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
static void  BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
static void  BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
static void  BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
static void  BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }

static void  BPLCON0(UWORD v) { bplcon0 = v; }
static void  BPLCON1(UWORD v) { bplcon1 = v; }
static void  BPLCON2(UWORD v) { bplcon2 = v; }
static void  BPLCON3(UWORD v) { bplcon3 = v; }

static void  BPL1MOD(UWORD v) { bpl1mod = v; }
static void  BPL2MOD(UWORD v) { bpl2mod = v; }

static void  BPL1DAT(UWORD v) { bpl1dat = v; }
static void  BPL2DAT(UWORD v) { bpl2dat = v; }
static void  BPL3DAT(UWORD v) { bpl3dat = v; }
static void  BPL4DAT(UWORD v) { bpl4dat = v; }
static void  BPL5DAT(UWORD v) { bpl5dat = v; }
static void  BPL6DAT(UWORD v) { bpl6dat = v; }

static void  DIWSTRT(UWORD v) { diwstrt = v; calcdiw(); }
static void  DIWSTOP(UWORD v) { diwstop = v; calcdiw(); }
static void  DDFSTRT(UWORD v) { ddfstrt = v; calcdiw(); }
static void  DDFSTOP(UWORD v) { ddfstop = v; calcdiw(); }

static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }

static UWORD COPJMPR1() { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; return 0; }
static UWORD COPJMPR2() { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; return 0; }
static void  COPJMP1(UWORD) { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; }
static void  COPJMP2(UWORD) { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; }

static void  BLTADAT(UWORD v) { bltadat = v; }
static void  BLTBDAT(UWORD v) { bltbdat = v; }
static void  BLTCDAT(UWORD v) { bltcdat = v; }

static void  BLTAMOD(UWORD v) { bltamod = v; }
static void  BLTBMOD(UWORD v) { bltbmod = v; }
static void  BLTCMOD(UWORD v) { bltcmod = v; }
static void  BLTDMOD(UWORD v) { bltdmod = v; }

static void  BLTCON0(UWORD v) { bltcon0 = v; }
static void  BLTCON1(UWORD v) { bltcon1 = v; }

static void  BLTAFWM(UWORD v) { bltafwm = v; }
static void  BLTALWM(UWORD v) { bltalwm = v; }

static void  BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
static void  BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
static void  BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
static void  BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
static void  BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
static void  BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
static void  BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
static void  BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
static void  BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; }

static void  DSKSYNC(UWORD v) { dsksync = v; }
static void  DSKDAT(UWORD v) { dskmfm = v; }
static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }

static void  DSKLEN(UWORD v) 
{
  if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
  dsktime = dskdelay; dsksynced = false;
  dsklen = v;
}

static UWORD DSKBYTR() 
{
  UWORD v = dsklen >> 1 & 0x6000;
  v |= dskbyte;
  dskbyte &= ~0x8000;
  if (dsksync == dskmfm) v |= 0x1000;
  return v;
}

static UWORD DSKDATR() { return dskmfm; }

custom64k::custom_func custom64k::functable[] = {
  { 0x002,  { &DMACONR, 0 }},
  { 0x096,  { 0, DMACON  }},
  { 0x01C,  { &INTENAR, 0 }},
  { 0x09A,  { 0, INTENA  }},
  { 0x01E,  { &INTREQR, 0 }},
  { 0x09C,  { 0, INTREQ  }},
  { 0x010,  { &ADKCONR, 0 }},
  { 0x09E,  { 0, ADKCON  }},

  { 0x006,  { &VHPOSR, 0 }},
  { 0x004,  { &VPOSR, 0 }},

  { 0x080,  { 0, &COP1LCH }},
  { 0x082,  { 0, &COP1LCL }},
  { 0x084,  { 0, &COP2LCH }},
  { 0x086,  { 0, &COP2LCL }},

  { 0x088,  { &COPJMPR1, &COPJMP1 }},
  { 0x08A,  { &COPJMPR2, &COPJMP2 }},

  { 0x08E,  { 0, &DIWSTRT }},
  { 0x090,  { 0, &DIWSTOP }},
  { 0x092,  { 0, &DDFSTRT }},
  { 0x094,  { 0, &DDFSTOP }},

  { 0x0E0,  { 0, &BPL1PTH }},
  { 0x0E2,  { 0, &BPL1PTL }},
  { 0x0E4,  { 0, &BPL2PTH }},
  { 0x0E6,  { 0, &BPL2PTL }},
  { 0x0E8,  { 0, &BPL3PTH }},
  { 0x0EA,  { 0, &BPL3PTL }},
  { 0x0EC,  { 0, &BPL4PTH }},
  { 0x0EE,  { 0, &BPL4PTL }},
  { 0x0F0,  { 0, &BPL5PTH }},
  { 0x0F2,  { 0, &BPL5PTL }},
  { 0x0F4,  { 0, &BPL6PTH }},
  { 0x0F6,  { 0, &BPL6PTL }},

  { 0x100,  { 0, &BPLCON0 }},
  { 0x102,  { 0, &BPLCON1 }},
  { 0x104,  { 0, &BPLCON2 }},
  { 0x106,  { 0, &BPLCON3 }},

  { 0x108,  { 0, &BPL1MOD }},
  { 0x10A,  { 0, &BPL2MOD }},

  { 0x110,  { 0, &BPL1DAT }},
  { 0x112,  { 0, &BPL2DAT }},
  { 0x114,  { 0, &BPL3DAT }},
  { 0x116,  { 0, &BPL4DAT }},
  { 0x118,  { 0, &BPL5DAT }},
  { 0x11A,  { 0, &BPL6DAT }},

  { 0x040,  { 0, &BLTCON0 }},
  { 0x042,  { 0, &BLTCON1 }},

  { 0x044,  { 0, &BLTAFWM }},
  { 0x046,  { 0, &BLTALWM }},

  { 0x064,  { 0, &BLTAMOD }},
  { 0x062,  { 0, &BLTBMOD }},
  { 0x060,  { 0, &BLTCMOD }},
  { 0x066,  { 0, &BLTDMOD }},

  { 0x050,  { 0, &BLTAPTH }},
  { 0x052,  { 0, &BLTAPTL }},
  { 0x04C,  { 0, &BLTBPTH }},
  { 0x04E,  { 0, &BLTBPTL }},
  { 0x048,  { 0, &BLTCPTH }},
  { 0x04A,  { 0, &BLTCPTL }},
  { 0x054,  { 0, &BLTDPTH }},
  { 0x056,  { 0, &BLTDPTL }},

  { 0x070,  { 0, &BLTCDAT }},
  { 0x072,  { 0, &BLTBDAT }},
  { 0x074,  { 0, &BLTADAT }},

  { 0x058,  { 0, &BLTSIZE }},

  { 0x008,  { &DSKDATR, 0 }},
  { 0x01A,  { &DSKBYTR, 0 }},
  { 0x026,  { 0, &DSKDAT }},
  { 0x024,  { 0, &DSKLEN }},
  { 0x020,  { 0, &DSKPTH }},
  { 0x022,  { 0, &DSKPTL }},
  { 0x07E,  { 0, &DSKSYNC }},

  { 0xFFFF, { 0, 0 }}
};

custom64k::cchipaddr *custom64k::cchiptable = 0;

custom64k::custom64k()
{
  if (!cchiptable){
    // CUSTOM CHIP INITIALIZATION
    // build function pointer table
    cchiptable = new cchipaddr[256];
    for (int i=0;i<256;i++) {
      cchiptable[i].get = 0;
      cchiptable[i].put = 0;
    }
    for(custom_func *f = functable; f->addr != 0xffff; f++){
      cchiptable[f->addr >> 1] = f->fptrs;
    }
    customreset();
  }
}

void customreset()
{
  // reset some values
  vpos = hpos = lof = 0;
  dmacon = intena = 0;
  bltstate = BLT_done;
  copstate = COP_stop;
  copcon = 0;
  dskdmaen = 0;
}

static bool dmaen(UWORD dmamask)
{
  return (dmamask & dmacon) && (dmacon & 0x200);
}

static bool copcomp()
{
  UWORD vp = vpos & ((copi2 >> 8) & 0x7F);
  UWORD hp = hpos & (copi2 & 0xFE);
  UWORD vcmp = copi1 >> 8;
  UWORD hcmp = copi1 & 0xFE;
  return (vp >= vcmp) && (hp >= hcmp) && ((copi2 & 0x8000) /*|| bfd FIXME*/);  
}

static void do_copper()
{
  switch(copstate){
  case COP_read:
    if (dmaen(0x80)){
 //     cout << "copper read at " << hex << coplc << "\n";
      copi1 = mem.get_word(coplc); 
      copi2 = mem.get_word(coplc+2);
      coplc += 4;
      copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
    } 
    break;
  case COP_move:
 //   cout << "copper move " << hex << copi1 << " " << copi2 << "\n";
    if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
      mem.put_word(0xDFF000+copi1,copi2);
    copstate = COP_read; // FIXME: copdang
    break;
  case COP_skip:
    if (copcomp()) coplc += 4;
    copstate = COP_read;
    break;
  case COP_wait:
    if (copcomp()) copstate = COP_read;
    break;
  case COP_stop:
    break;
  }
}

static void blitter_read()
{
  if (bltcon0 & 0xe00){
    if (!dmaen(0x40)) return; // blitter stopped
    if (!blitline){
      if (bltcon0 & 0x800) bltadat = mem.get_word(bltapt);
      if (bltcon0 & 0x400) bltbdat = mem.get_word(bltbpt);
    }
    if (bltcon0 & 0x200) bltcdat = mem.get_word(bltcpt);
  }
  bltstate = BLT_work;
}

static void blitter_write()
{
  if (bltddat) blitzero = false;
  if (bltcon0 & 0x100){
    if (!dmaen(0x40)) return;
    mem.put_word(bltdpt,bltddat);
  }
  bltstate = BLT_next;
}

static void blitter_blit()
{
  UWORD blitahold,blitbhold,blitchold;

  if (blitdesc) { // aaarggh!
    UWORD bltamask = 0xffff;

    if (!blitlpos) { bltamask &= bltafwm; }
    if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }

    // FIXME? The following two lines are probably not 100% exact
    blitahold = ((ULONG)((bltadat & bltamask) << 16) | blitpreva) 
      >> (16-blitashift);
    blitbhold = ((ULONG)(bltbdat << 16) | blitprevb) >> (16-blitbshift);
    blitchold = bltcdat;
  } else {
    UWORD bltamask = 0xffff;

    if (!blitlpos) { bltamask &= bltafwm; }
    if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
    // FIXME? The following two lines are probably not 100% exact
    blitahold = ((ULONG)(blitpreva << 16) | (bltadat&bltamask)) >> blitashift;
    blitbhold = ((ULONG)(blitprevb << 16) | bltbdat) >> blitbshift;
    blitchold = bltcdat;
  }
  bltddat = 0;
  for(int i=0; i<16; i++) {
    // oh dear, this is SLOW!
    int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
      | ((blitchold >> 15) & 1);
    blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
    if (bltcon0 & (1 << minterm)) 
      bltddat |= (1 << (15-i));
  }
  if (blitfill){
    UWORD fillmask = 1;
    for (;fillmask;fillmask <<= 1){
      UWORD tmp = bltddat;
      if (blitfc) {
	if (blitife) bltddat |= fillmask; else bltddat ^= fillmask;
      }
      if (tmp & fillmask) blitfc = !blitfc;
    } 
  }
  bltstate = BLT_write;
  blitpreva = bltadat; blitprevb = bltbdat;
}

static void blitter_nxblit()
{
  bltstate = BLT_read;
  if (blitdesc){
    if (++blitlpos == hblitsize) {
      if (--vblitsize == 0) {
	bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
      }
      blitlpos = 0;
      if (bltcon0 & 0x800) bltapt -= 2+bltamod; 
      if (bltcon0 & 0x400) bltbpt -= 2+bltbmod; 
      if (bltcon0 & 0x200) bltcpt -= 2+bltcmod; 
      if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
    } else {
      if (bltcon0 & 0x800) bltapt -= 2; 
      if (bltcon0 & 0x400) bltbpt -= 2; 
      if (bltcon0 & 0x200) bltcpt -= 2; 
      if (bltcon0 & 0x100) bltdpt -= 2;

    }
  } else {
    if (++blitlpos == hblitsize) {
      if (--vblitsize == 0) { 
	bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
      }
      blitlpos = 0;
      if (bltcon0 & 0x800) bltapt += 2+bltamod; 
      if (bltcon0 & 0x400) bltbpt += 2+bltbmod; 
      if (bltcon0 & 0x200) bltcpt += 2+bltcmod; 
      if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
    } else {
      if (bltcon0 & 0x800) bltapt += 2; 
      if (bltcon0 & 0x400) bltbpt += 2; 
      if (bltcon0 & 0x200) bltcpt += 2; 
      if (bltcon0 & 0x100) bltdpt += 2;
    }
  }
}

static void blitter_line_incx(int =1)
{
  blinea >>= 1;
  if (!blinea) {
    blinea = 0x8000;
    bltcnxlpt += 2;
    bltdnxlpt += 2;
  }
}

static void blitter_line_decx(int shm=1)
{
  if (shm) blineb = (blineb << 2) | (blineb >> 14);
  blinea <<= 1;
  if (!blinea) {
    blinea = 1;
    bltcnxlpt -= 2;
    bltdnxlpt -= 2;
  }
}

static void blitter_line_decy(int shm=1)
{
  if (shm) blineb = (blineb >> 1) | (blineb << 15);
  bltcnxlpt -= bltcmod;
  bltdnxlpt -= bltcmod; // ??? ??? ??? am I wrong or doesn't KS1.3 set bltdmod?
  blitonedot = 0;
}

static void blitter_line_incy(int shm=1)
{
  if (shm) blineb = (blineb >> 1) | (blineb << 15);
  bltcnxlpt += bltcmod;
  bltdnxlpt += bltcmod; // ??? ??? ???
  blitonedot = 0;
}

static void blitter_line()
{
  bltddat = 0;
  UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
  if (blitsing && blitonedot) blitahold = 0;
  blitonedot = 1;
  for(int i=0; i<16; i++) {
    int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
      | ((blitchold >> 15) & 1);
    blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
    if (bltcon0 & (1 << minterm)) bltddat |= (1 << (15-i));
  }
  if (!blitsign){
    bltapt += (WORD)bltamod;
    if (bltcon1 & 0x10){
      if (bltcon1 & 0x8) blitter_line_decy(0); else blitter_line_incy(0);
    } else {
      if (bltcon1 & 0x8) blitter_line_decx(0); else blitter_line_incx(0);
    }
  } else {
    bltapt += (WORD)bltbmod;
  }
  if (bltcon1 & 0x10){
    if (bltcon1 & 0x4) blitter_line_decx(); else blitter_line_incx();
  } else {
    if (bltcon1 & 0x4) blitter_line_decy(); else blitter_line_incy();
  }
  blitsign = 0 > (WORD)bltapt;
  bltstate = BLT_write;
}

static void blitter_nxline()
{
  if (--vblitsize == 0) {
    bltstate = BLT_wait; bltwait = /*0xE2*31*/2; mem.put_word(0xDFF09C,0x8040);
  } else {
    bltstate = BLT_read;
    bltcpt = bltcnxlpt;
    bltdpt = bltdnxlpt;
  }
}

static void do_blitter()
{
  switch(bltstate) {
  case BLT_init:
    cout << "Blit started!";
    vblitsize = bltsize >> 6;
    hblitsize = bltsize & 0x3F;
    if (!vblitsize) vblitsize = 1024;
    if (!hblitsize) hblitsize = 64;
    blitlpos = 0;
    blitzero = true; blitpreva = blitprevb = 0;
    blitline = bltcon1 & 1;
    blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
    
    if (blitline) {
      cout << " line\n";
      bltcnxlpt = bltcpt;
      bltdnxlpt = bltdpt;
      blitsing = bltcon1 & 0x2;
      blinea = bltadat >> blitashift;
      blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
      blitsign = bltcon1 & 0x40; 
      blitonedot = false;
      bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
    } else {
      blitfc = bltcon1 & 0x4;
      blitife = bltcon1 & 0x8;
      blitfill = bltcon1 & 0x18;
      if (blitfill) cout << " fill";
      if ((bltcon1 & 0x18) == 0x18) cout << "STRANGE FILL MODE ALERT!!\n";
      blitdesc = bltcon1 & 0x2;
      if(blitdesc) cout << " desc";
      cout << "\n";
    }
    bltstate = BLT_read;
    break;
  case BLT_read:
    blitter_read();
    break;
  case BLT_write:
    blitter_write();
    break;
  case BLT_work:
    if (blitline) blitter_line(); else blitter_blit();
    break;
  case BLT_next:
    if (blitline) blitter_nxline(); else blitter_nxblit();
    break;
  case BLT_wait:
    if (!--bltwait) bltstate = BLT_done;
    break;
  case BLT_done:
    break;
  }
}

  // note: fall-throughs in all playfield functions

static void pfield_fetchdata()
{
  if (/*dmaen(0x100)*/ 1) {
    switch(bplcon0 & 0x7000){
    case 0x6000:
      bpl6dat = mem.get_word(bpl6pt); bpl6pt += 2;
    case 0x5000:
      bpl5dat = mem.get_word(bpl5pt); bpl5pt += 2;
    case 0x4000:
      bpl4dat = mem.get_word(bpl4pt); bpl4pt += 2;
    case 0x3000:
      bpl3dat = mem.get_word(bpl3pt); bpl3pt += 2;
    case 0x2000:
      bpl2dat = mem.get_word(bpl2pt); bpl2pt += 2;
    case 0x1000:
      bpl1dat = mem.get_word(bpl1pt); bpl1pt += 2;
    }
  }
}

static void pfield_hsync()
{
  if (/*dmaen(0x100)*/ 1) {
    switch(bplcon0 & 0x7000){
    case 0x6000:
      bpl6pt += bpl2mod;
    case 0x5000:
      bpl5pt += bpl1mod;
    case 0x4000:
      bpl4pt += bpl2mod;
    case 0x3000:
      bpl3pt += bpl1mod;
    case 0x2000:
      bpl2pt += bpl2mod;
    case 0x1000:
      bpl1pt += bpl1mod;
    }
  }
}

static UWORD pfield_nextpixel()
{
  UWORD tmp = 0;
  switch(bplcon0 & 0x7000){
  case 0x6000: 
    tmp = (bpl6dat >> 15); bpl6dat <<= 1;
  case 0x5000: 
    tmp = (tmp << 1) | (bpl5dat >> 15); bpl5dat <<= 1;
  case 0x4000: 
    tmp = (tmp << 1) | (bpl4dat >> 15); bpl4dat <<= 1;
  case 0x3000: 
    tmp = (tmp << 1) | (bpl3dat >> 15); bpl3dat <<= 1;
  case 0x2000: 
    tmp = (tmp << 1) | (bpl2dat >> 15); bpl2dat <<= 1;
  case 0x1000: 
    tmp = (tmp << 1) | (bpl1dat >> 15); bpl1dat <<= 1;
  } 
  return tmp;
}

static void do_playfield()
{
  int xpos = hpos * 4;
  if (vpos >= plffirstline && vpos < plflastline){
    if (xpos >= plffirstword && xpos < plflastword){
      if (bplcon0 & 0x8000){
	if ((xpos & 0xF) == 0){
	  pfield_fetchdata();
	  for(int i=0;i<16;i++){
	    UWORD pixel = pfield_nextpixel() & 3;
	    int col;
	    if (pixel == 3) col = 1;
	    else if (pixel == 0) col = 0;
	    else col = (pixel & 1) == ((xpos ^ vpos) & 1);
	    DrawPixel(xpos+i,vpos,col);
	  }
	}
      } else {
	if ((xpos & 0x1F) == 0){
	  pfield_fetchdata();
	  for(int i=0;i<16;i++){
	    UWORD pixel = pfield_nextpixel() & 3;
	    int col;
	    if (pixel == 3) col = 1;
	    else if (pixel == 0) col = 0;
	    else col = (pixel & 1) == ((xpos ^ vpos) & 1);
	    DrawPixel(xpos+i*2,vpos,col);
	    DrawPixel(xpos+i*2+1,vpos,col);
	  }
	}
      }
    }
  }
}

static void do_disk()
{
  if (dskdmaen > 1 && dmaen(0x10)){
    if (--dsktime == 0) {
      dsktime = dskdelay;
      if (dsklen & 0x4000){
	// write
      } else {
	DISK_GetData(dskmfm,dskbyte);
	dskbyte |= 0x8000;
	if (dskmfm == dsksync) {
	  mem.put_word(0xDFF09C,0x9000);
	  dsksynced = true;
	}
	if (dsksynced || !(adkcon & 0x400)){
	  mem.put_word(dskpt,dskmfm); dskpt+=2;
	}
      }
    }
  }
}

static void do_vsync()
{
//  intreq |= 1 << i_vertb;
  mem.put_word(0xDFF09C,0x8020);
  lof ^= 1;
//  if (copstate != COP_stop)
    mem.put_word(0xDFF088,0); // restart copper
  CIA_vsync();
}

void clockcycle()
{
  if (++hpos == maxhpos){
    hpos = 0; CIA_hsync();
    pfield_hsync();
    if (++vpos == maxvpos) {
      vpos = 0;
      do_vsync();
    }
  }
  do_copper();
  do_playfield();
  do_blitter();
  do_disk();
  CIA_cycle();
}

void dumpcustom()
{
  cout << "DMACON: " << DMACONR() << " INTENA: " << intena << " INTREQ: "
    << intreq << " VPOS: " << vpos << " HPOS: " << hpos << "\n";
}

int intlev()
{
  UWORD imask = intreq & intena;
  if (imask && (intena & 0x4000)){
 //   cout << hex << "intreq " << intreq << " intena " << intena <<"\n";
    if (imask & 0x2000) return 6;
    if (imask & 0x1800) return 5;
    if (imask & 0x0780) return 4;
    if (imask & 0x0070) return 3;
    if (imask & 0x0008) return 2;
    if (imask & 0x0007) return 1;
  }
  return -1;
}

unix.superglobalmegacorp.com

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