Add v0.7 source
This commit is contained in:
commit
3c253c2cf8
188 changed files with 52566 additions and 0 deletions
490
src/dma.c
Normal file
490
src/dma.c
Normal file
|
|
@ -0,0 +1,490 @@
|
|||
#include "ibm.h"
|
||||
#include "video.h"
|
||||
#include "io.h"
|
||||
#include "dma.h"
|
||||
|
||||
extern int ins;
|
||||
int output;
|
||||
uint8_t dmaregs[16];
|
||||
int dmaon[4];
|
||||
uint8_t dma16regs[16];
|
||||
int dma16on[4];
|
||||
|
||||
void dma_reset()
|
||||
{
|
||||
int c;
|
||||
dma.wp=0;
|
||||
for (c=0;c<16;c++) dmaregs[c]=0;
|
||||
for (c=0;c<4;c++)
|
||||
{
|
||||
dma.mode[c]=0;
|
||||
dma.ac[c]=0;
|
||||
dma.cc[c]=0;
|
||||
dma.ab[c]=0;
|
||||
dma.cb[c]=0;
|
||||
}
|
||||
dma.m=0;
|
||||
|
||||
dma16.wp=0;
|
||||
for (c=0;c<16;c++) dma16regs[c]=0;
|
||||
for (c=0;c<4;c++)
|
||||
{
|
||||
dma16.mode[c]=0;
|
||||
dma16.ac[c]=0;
|
||||
dma16.cc[c]=0;
|
||||
dma16.ab[c]=0;
|
||||
dma16.cb[c]=0;
|
||||
}
|
||||
dma16.m=0;
|
||||
}
|
||||
|
||||
uint8_t dma_read(uint16_t addr)
|
||||
{
|
||||
uint8_t temp;
|
||||
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
|
||||
switch (addr&0xF)
|
||||
{
|
||||
case 0:
|
||||
/* if (((dma.mode[0]>>2)&3)==2)
|
||||
{
|
||||
dma.ac[0]++;
|
||||
dma.cc[0]--;
|
||||
if (dma.cc[0]<0)
|
||||
{
|
||||
dma.ac[0]=dma.ab[0];
|
||||
dma.cc[0]=dma.cb[0];
|
||||
}
|
||||
}*/
|
||||
case 2: case 4: case 6: /*Address registers*/
|
||||
dma.wp^=1;
|
||||
if (dma.wp) return dma.ac[(addr>>1)&3]&0xFF;
|
||||
return dma.ac[(addr>>1)&3]>>8;
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
// printf("DMA count %i = %04X\n", (addr>>1)&3, dma.cc[(addr>>1)&3]);
|
||||
dma.wp^=1;
|
||||
if (dma.wp) temp=dma.cc[(addr>>1)&3]&0xFF;
|
||||
else temp=dma.cc[(addr>>1)&3]>>8;
|
||||
// printf("%02X\n",temp);
|
||||
return temp;
|
||||
case 8: /*Status register*/
|
||||
temp=dma.stat;
|
||||
dma.stat=0;
|
||||
return temp|1;
|
||||
case 0xD:
|
||||
return 0;
|
||||
}
|
||||
// printf("Bad DMA read %04X %04X:%04X\n",addr,CS,pc);
|
||||
return dmaregs[addr&0xF];
|
||||
}
|
||||
|
||||
void dma_write(uint16_t addr, uint8_t val)
|
||||
{
|
||||
// printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc);
|
||||
dmaregs[addr&0xF]=val;
|
||||
switch (addr&0xF)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma.wp^=1;
|
||||
if (dma.wp) dma.ab[(addr>>1)&3]=(dma.ab[(addr>>1)&3]&0xFF00)|val;
|
||||
else dma.ab[(addr>>1)&3]=(dma.ab[(addr>>1)&3]&0xFF)|(val<<8);
|
||||
dma.ac[(addr>>1)&3]=dma.ab[(addr>>1)&3];
|
||||
dmaon[(addr>>1)&3]=1;
|
||||
// printf("DMA addr %i now %04X\n",(addr>>1)&3,dma.ac[(addr>>1)&3]);
|
||||
return;
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma.wp^=1;
|
||||
if (dma.wp) dma.cb[(addr>>1)&3]=(dma.cb[(addr>>1)&3]&0xFF00)|val;
|
||||
else dma.cb[(addr>>1)&3]=(dma.cb[(addr>>1)&3]&0xFF)|(val<<8);
|
||||
dma.cc[(addr>>1)&3]=dma.cb[(addr>>1)&3];
|
||||
dmaon[(addr>>1)&3]=1;
|
||||
// printf("DMA count %i now %04X\n",(addr>>1)&3,dma.cc[(addr>>1)&3]);
|
||||
return;
|
||||
case 8: /*Control register*/
|
||||
dma.command = val;
|
||||
return;
|
||||
case 0xA: /*Mask*/
|
||||
if (val&4) dma.m|=(1<<(val&3));
|
||||
else dma.m&=~(1<<(val&3));
|
||||
return;
|
||||
case 0xB: /*Mode*/
|
||||
dma.mode[val&3]=val;
|
||||
return;
|
||||
case 0xC: /*Clear FF*/
|
||||
dma.wp=0;
|
||||
return;
|
||||
case 0xD: /*Master clear*/
|
||||
dma.wp=0;
|
||||
dma.m=0xF;
|
||||
return;
|
||||
case 0xF: /*Mask write*/
|
||||
dma.m=val&0xF;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dma16_read(uint16_t addr)
|
||||
{
|
||||
uint8_t temp;
|
||||
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
|
||||
addr>>=1;
|
||||
switch (addr&0xF)
|
||||
{
|
||||
case 0:
|
||||
if (((dma16.mode[0]>>2)&3)==2)
|
||||
{
|
||||
dma16.ac[0]++;
|
||||
dma16.cc[0]--;
|
||||
if (dma16.cc[0]<0)
|
||||
{
|
||||
dma16.ac[0]=dma16.ab[0];
|
||||
dma16.cc[0]=dma16.cb[0];
|
||||
}
|
||||
}
|
||||
case 2: case 4: case 6: /*Address registers*/
|
||||
dma16.wp^=1;
|
||||
if (dma16.wp) return dma16.ac[(addr>>1)&3]&0xFF;
|
||||
return dma16.ac[(addr>>1)&3]>>8;
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma16.wp^=1;
|
||||
// printf("Read %04X\n",dma16.cc[1]);
|
||||
if (dma16.wp) temp=dma16.cc[(addr>>1)&3]&0xFF;
|
||||
else temp=dma16.cc[(addr>>1)&3]>>8;
|
||||
// printf("%02X\n",temp);
|
||||
return temp;
|
||||
case 8: /*Status register*/
|
||||
temp=dma16.stat;
|
||||
dma16.stat=0;
|
||||
return temp|1;
|
||||
}
|
||||
return dma16regs[addr&0xF];
|
||||
}
|
||||
|
||||
void dma16_write(uint16_t addr, uint8_t val)
|
||||
{
|
||||
// printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc);
|
||||
addr>>=1;
|
||||
dma16regs[addr&0xF]=val;
|
||||
switch (addr&0xF)
|
||||
{
|
||||
case 0: case 2: case 4: case 6: /*Address registers*/
|
||||
dma16.wp^=1;
|
||||
if (dma16.wp) dma16.ab[(addr>>1)&3]=(dma16.ab[(addr>>1)&3]&0xFF00)|val;
|
||||
else dma16.ab[(addr>>1)&3]=(dma16.ab[(addr>>1)&3]&0xFF)|(val<<8);
|
||||
dma16.ac[(addr>>1)&3]=dma16.ab[(addr>>1)&3];
|
||||
dma16on[(addr>>1)&3]=1;
|
||||
// printf("dma16 addr %i now %04X\n",(addr>>1)&3,dma16.ac[(addr>>1)&3]);
|
||||
return;
|
||||
case 1: case 3: case 5: case 7: /*Count registers*/
|
||||
dma16.wp^=1;
|
||||
if (dma16.wp) dma16.cb[(addr>>1)&3]=(dma16.cb[(addr>>1)&3]&0xFF00)|val;
|
||||
else dma16.cb[(addr>>1)&3]=(dma16.cb[(addr>>1)&3]&0xFF)|(val<<8);
|
||||
dma16.cc[(addr>>1)&3]=dma16.cb[(addr>>1)&3];
|
||||
dma16on[(addr>>1)&3]=1;
|
||||
// printf("dma16 count %i now %04X\n",(addr>>1)&3,dma16.cc[(addr>>1)&3]);
|
||||
return;
|
||||
case 8: /*Control register*/
|
||||
return;
|
||||
case 0xA: /*Mask*/
|
||||
if (val&4) dma16.m|=(1<<(val&3));
|
||||
else dma16.m&=~(1<<(val&3));
|
||||
return;
|
||||
case 0xB: /*Mode*/
|
||||
dma16.mode[val&3]=val;
|
||||
return;
|
||||
case 0xC: /*Clear FF*/
|
||||
dma16.wp=0;
|
||||
return;
|
||||
case 0xD: /*Master clear*/
|
||||
dma16.wp=0;
|
||||
dma16.m=0xF;
|
||||
return;
|
||||
case 0xF: /*Mask write*/
|
||||
dma16.m=val&0xF;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dmapages[16];
|
||||
static int primed = 0;
|
||||
void dma_page_write(uint16_t addr, uint8_t val)
|
||||
{
|
||||
if (!(addr&0xF))
|
||||
{
|
||||
// printf("Write page %03X %02X %04X:%04X\n",addr,val,CS,pc);
|
||||
// if (val==0x29 && pc==0xD25) output=1;
|
||||
}
|
||||
dmapages[addr&0xF]=val;
|
||||
switch (addr&0xF)
|
||||
{
|
||||
case 1:
|
||||
dma.page[2]=(AT)?val:val&0xF;
|
||||
break;
|
||||
case 2:
|
||||
dma.page[3]=(AT)?val:val&0xF;
|
||||
break;
|
||||
case 3:
|
||||
dma.page[1]=(AT)?val:val&0xF;
|
||||
// pclog("DMA1 page %02X\n",val);
|
||||
break;
|
||||
case 0xB:
|
||||
dma16.page[1]=val;
|
||||
break;
|
||||
}
|
||||
// printf("Page write %04X %02X\n",addr,val);
|
||||
}
|
||||
|
||||
uint8_t dma_page_read(uint16_t addr)
|
||||
{
|
||||
return dmapages[addr&0xF];
|
||||
}
|
||||
|
||||
void dma_init()
|
||||
{
|
||||
io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL);
|
||||
io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL);
|
||||
}
|
||||
|
||||
void dma16_init()
|
||||
{
|
||||
io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL);
|
||||
io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
uint8_t _dma_read(uint32_t addr)
|
||||
{
|
||||
switch (addr&0xFFFF8000)
|
||||
{
|
||||
case 0xA0000: case 0xA8000:
|
||||
return video_read_a000(addr);
|
||||
case 0xB0000:
|
||||
return video_read_b000(addr);
|
||||
case 0xB8000:
|
||||
return video_read_b800(addr);
|
||||
}
|
||||
if (isram[addr>>16]) return ram[addr];
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void _dma_write(uint32_t addr, uint8_t val)
|
||||
{
|
||||
switch (addr&0xFFFF8000)
|
||||
{
|
||||
case 0xA0000: case 0xA8000:
|
||||
video_write_a000(addr,val);
|
||||
return;
|
||||
case 0xB0000:
|
||||
video_write_b000(addr,val);
|
||||
return;
|
||||
case 0xB8000:
|
||||
video_write_b800(addr,val);
|
||||
return;
|
||||
case 0xC0000: case 0xC8000: case 0xD0000: case 0xD8000:
|
||||
case 0xE0000: case 0xE8000: case 0xF0000: case 0xF8000:
|
||||
return;
|
||||
}
|
||||
if (isram[addr>>16]) ram[addr]=val;
|
||||
}
|
||||
/*void writedma2(uint8_t val)
|
||||
{
|
||||
// printf("Write to %05X %02X %i\n",(dma.page[2]<<16)+dma.ac[2],val,dma.m&4);
|
||||
if (!(dma.m&4))
|
||||
{
|
||||
ram[((dma.page[2]<<16)+dma.ac[2])&rammask]=val;
|
||||
dma.ac[2]++;
|
||||
dma.cc[2]--;
|
||||
if (dma.cc[2]==-1)
|
||||
{
|
||||
dma.m|=4;
|
||||
dma.stat|=4;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
uint8_t readdma2()
|
||||
{
|
||||
uint8_t temp;
|
||||
// pclog("Read DMA2 %02X %02X\n",dma.m,dma.mode[2]);
|
||||
if (dma.m&4)
|
||||
{
|
||||
fdc_abort();
|
||||
return 0xFF;
|
||||
}
|
||||
if ((dma.mode[2]&0xC)!=8)
|
||||
{
|
||||
fdc_abort();
|
||||
return 0xFF;
|
||||
}
|
||||
temp=_dma_read((dma.ac[2]+(dma.page[2]<<16))&rammask); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
|
||||
// pclog("DMA2 %02X %05X\n",temp,(dma.ac[2]+(dma.page[2]<<16))&rammask);
|
||||
if (dma.mode[2]&0x20) dma.ac[2]--;
|
||||
else dma.ac[2]++;
|
||||
dma.cc[2]--;
|
||||
if (!dma.cc[2] && (dma.mode[2]&0x10))
|
||||
{
|
||||
dma.cc[2]=dma.cb[2]+1;
|
||||
dma.ac[2]=dma.ab[2];
|
||||
}
|
||||
else if (dma.cc[2]<=-1)
|
||||
dma.m|=4;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void writedma2(uint8_t temp)
|
||||
{
|
||||
// pclog("Write DMA2 %02X %02X %04X\n",dma.m,dma.mode[2],dma.cc[2]);
|
||||
if (dma.m&4)
|
||||
{
|
||||
fdc_abort();
|
||||
return;
|
||||
}
|
||||
if ((dma.mode[2]&0xC)!=4)
|
||||
{
|
||||
fdc_abort();
|
||||
return;
|
||||
}
|
||||
// pclog("Write %05X %05X %02X\n",(dma.ac[2]+(dma.page[2]<<16)),rammask,temp);
|
||||
// ram[(dma.ac[2]+(dma.page[2]<<16))&rammask]=temp;
|
||||
_dma_write((dma.ac[2]+(dma.page[2]<<16))&rammask,temp);
|
||||
if (dma.mode[2]&0x20) dma.ac[2]--;
|
||||
else dma.ac[2]++;
|
||||
dma.cc[2]--;
|
||||
if (!dma.cc[2] && (dma.mode[2]&0x10))
|
||||
{
|
||||
dma.cc[2]=dma.cb[2]+1;
|
||||
dma.ac[2]=dma.ab[2];
|
||||
}
|
||||
else if (dma.cc[2]<=-1)
|
||||
{
|
||||
// pclog("Reached TC\n");
|
||||
fdc_abort();
|
||||
dma.m|=4;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t readdma1()
|
||||
{
|
||||
uint8_t temp=0;
|
||||
/*if ((dma.ac[1]+(dma.page[1]<<16))<0x800000) */temp=ram[(dma.ac[1]+(dma.page[1]<<16))&rammask];
|
||||
// printf("Read DMA1 from %05X %02X %04X %02X %i\n",dma.ac[1]+(dma.page[1]<<16),dma.mode[1],dma.cc[1],temp,dmaon[1]);
|
||||
if (!dmaon[1])
|
||||
{
|
||||
// printf("DMA off!\n");
|
||||
return temp;
|
||||
}
|
||||
dma.ac[1]++;
|
||||
dma.cc[1]--;
|
||||
if (dma.cc[1]<=-1 && (dma.mode[1]&0x10))
|
||||
{
|
||||
dma.cc[1]=dma.cb[1];
|
||||
dma.ac[1]=dma.ab[1];
|
||||
}
|
||||
else if (dma.cc[1]<=-1)
|
||||
dmaon[1]=0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
uint16_t readdma5()
|
||||
{
|
||||
uint16_t temp=0;
|
||||
// pclog("Read DMA5 %i %04X\n",dma16on[1],dma16.cc[1]);
|
||||
/*if ((dma16.ac[1]+(dma16.page[1]<<16))<0x800000) */temp=ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16))&rammask]|(ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16)+1)&rammask]<<8);
|
||||
//readmemwl(dma16.ac[1]+(dma16.page[1]<<16));
|
||||
// printf("Read DMA1 from %05X %05X %02X %04X\n",dma.ac[1]+(dma.page[1]<<16),(dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16),dma16.mode[1],temp);
|
||||
if (!dma16on[1])
|
||||
{
|
||||
// printf("DMA off!\n");
|
||||
return temp;
|
||||
}
|
||||
dma16.ac[1]++;
|
||||
dma16.cc[1]--;
|
||||
if (dma16.cc[1]<=-1 && (dma16.mode[1]&0x10))
|
||||
{
|
||||
dma16.cc[1]=dma16.cb[1];
|
||||
dma16.ac[1]=dma16.ab[1];
|
||||
}
|
||||
else if (dma16.cc[1]<=-1)
|
||||
dma16on[1]=0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
void writedma1(uint8_t temp)
|
||||
{
|
||||
if (!dmaon[1]) return;
|
||||
ram[(dma.ac[1]+(dma.page[1]<<16))&rammask]=temp;
|
||||
dma.ac[1]++;
|
||||
dma.cc[1]--;
|
||||
if (!dma.cc[1] && (dma.mode[1]&0x10))
|
||||
{
|
||||
dma.cc[1]=dma.cb[1]+1;
|
||||
dma.ac[1]=dma.ab[1];
|
||||
}
|
||||
else if (dma.cc[1]<=-1)
|
||||
dmaon[1]=0;
|
||||
}
|
||||
void writedma5(uint16_t temp)
|
||||
{
|
||||
if (!dma16on[1]) return;
|
||||
ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16))&rammask]=temp;
|
||||
ram[((dma16.ac[1]<<1)+((dma16.page[1]&~1)<<16)+1)&rammask]=temp>>8;
|
||||
|
||||
dma16.ac[1]++;
|
||||
dma16.cc[1]--;
|
||||
if (dma16.cc[1]<=-1 && (dma16.mode[1]&0x10))
|
||||
{
|
||||
dma16.cc[1]=dma16.cb[1];
|
||||
dma16.ac[1]=dma16.ab[1];
|
||||
}
|
||||
else if (dma16.cc[1]<=-1)
|
||||
dma16on[1]=0;
|
||||
}
|
||||
|
||||
int readdma3()
|
||||
{
|
||||
uint8_t temp=ram[((dma.page[3]<<16)+dma.ac[3])&rammask];
|
||||
if (dma.m&8)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// printf("Read DMA 3 - %02X %05X %i\n",temp,(dma.page[3]<<16)+dma.ac[3],dma.cc[3]);
|
||||
if (!(dma.m&8))
|
||||
{
|
||||
dma.ac[3]++;
|
||||
dma.cc[3]--;
|
||||
if (dma.cc[3]==-1)
|
||||
{
|
||||
dma.m|=8;
|
||||
dma.stat|=8;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
void readdma0()
|
||||
{
|
||||
if (AT) ppi.pb^=0x10;
|
||||
if (dma.command & 4) return;
|
||||
// if (AMSTRAD) return;
|
||||
refreshread();
|
||||
// pclog("Read refresh %02X %02X %04X %04X\n",dma.m,dma.mode[0],dma.ac[0],dma.cc[0]);
|
||||
if (dma.m&1) return;
|
||||
// readmembl((dma.page[0]<<16)+dma.ac[0]);
|
||||
// if (!(dma.m&1))
|
||||
// {
|
||||
dma.ac[0]+=2;
|
||||
dma.cc[0]--;
|
||||
if (dma.cc[0]==-1)
|
||||
{
|
||||
dma.stat|=1;
|
||||
dma.ac[0]=dma.ab[0];
|
||||
dma.cc[0]=dma.cb[0];
|
||||
}
|
||||
// }
|
||||
// ppi.pb^=0x10;
|
||||
}
|
||||
|
||||
void dumpdma()
|
||||
{
|
||||
printf("Address : %04X %04X %04X %04X\n",dma.ac[0],dma.ac[1],dma.ac[2],dma.ac[3]);
|
||||
printf("Count : %04X %04X %04X %04X\n",dma.cc[0],dma.cc[1],dma.cc[2],dma.cc[3]);
|
||||
printf("Mask %02X Stat %02X\n",dma.m,dma.stat);
|
||||
}
|
||||
Loading…
Reference in a new issue