home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 6
/
AACD06.ISO
/
AACD
/
Emulation
/
Atari800
/
antic_old.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-26
|
33KB
|
1,554 lines
/*
*****************************************************************
* *
* Section : Antic Display Modes *
* Original Author : David Firth *
* : Thomas Richter (thor) *
* Date Written : 28th May 1995 *
* : 17th February 1988 *
* Version : 1.3 *
* *
* *
* Description *
* ----------- *
* *
* Section that handles Antic display modes. Not required *
* for BASIC version. *
* *
*****************************************************************
*/
#include <stdio.h>
#include <string.h>
#ifndef AMIGA
#include "config.h"
#endif
#include "atari.h"
#include "rt-config.h"
#include "mem.h"
#include "cpu.h"
#include "gtia.h"
#include "antic.h"
#define FALSE 0
#define TRUE 1
int xmin;
int xmax;
int dmactl_xmin_noscroll;
int dmactl_xmax_noscroll;
static int dmactl_xmin_scroll;
static int dmactl_xmax_scroll;
static int memory_basis; /* refresh cycles needed for memory */
static int pm_dma; /* DMA cycles needed by P/M graphics */
static int char_delta;
static int char_offset;
static int invert_mask;
static int blank_mask;
static int screenaddr;
/* colour lookup tables */
static int lookup_f[256];
static int lookup_4[256];
static int lookup24[256];
static int lookup_6[256];
static int lookup_9[256];
static char *rcsid = "$Id: antic.c,v 1.30 1998/02/17 thor,david Exp $";
UBYTE CHACTL;
UBYTE CHBASE;
UWORD DLIST,DLISTINIT;
UBYTE DMACTL;
UBYTE HSCROL;
UBYTE NMIEN;
UBYTE NMIST;
UBYTE PMBASE;
UBYTE VSCROL;
int DMAwidth;
extern UWORD regPC;
/*
* These are defined for Word (2 Byte) memory accesses. I have not
* defined Longword (4 Byte) values since the Sparc architecture
* requires that Longword are on a longword boundry.
*
* Words accesses don't appear to be a problem because the first
* pixel plotted on a line will always be at an even offset, and
* hence on a word boundry.
*
* Note: HSCROL is in colour clocks whereas the pixels are emulated
* down to a half colour clock - the first pixel plotted is
* moved across by 2*HSCROL
*/
#define PF2_COLPF0 0x0404
#define PF2_COLPF1 0x0505
#define PF2_COLPF2 0x0606
#define PF2_COLPF3 0x0707
#define PF2_COLBK 0x0808
#define PF2_COLPF1_FID 0x1515
#define PF4_COLPF0 0x04040404
#define PF4_COLPF1 0x05050505
#define PF4_COLPF2 0x06060606
#define PF4_COLPF3 0x07070707
#define PF4_COLBK 0x08080808
#define PF4_COLPF1_FID 0x15151515
/* The middle of the display. All color/display/whatever changes BEFORE that
cycle are seen on the same row.
All changes after this color clock are visible ON THE NEXT row */
#define CC_MIDDLE 50
/* The propagation delay needed by the 6502 to react on the NMI interrupt */
#define DLI_DELAY 8
/* The number of cycles available on the same row to proceed after WSYNC and
before the horizontal blank */
#define AFTER_WSYNC 20
/* The number of cycles available after the horizontal blank but before the
DMA of antic actually starts */
#define BEFORE_DMA 0
/* The line where the VSYNC is generated. */
#define VSYNC_POS 250
int cc_middle=CC_MIDDLE;
int dli_delay=DLI_DELAY;
int after_wsync=AFTER_WSYNC;
int before_dma=BEFORE_DMA;
int vsync_pos=VSYNC_POS;
int ypos;
/*
* Pre-computed values for improved performance
*/
static int chbase_40; /* CHBASE for 40 character mode */
static int chbase_20; /* CHBASE for 20 character mode */
static int maddr_s; /* Address of Missiles - Single Line Resolution */
static int p0addr_s; /* Address of Player0 - Single Line Resolution */
static int p1addr_s; /* Address of Player1 - Single Line Resolution */
static int p2addr_s; /* Address of Player2 - Single Line Resolution */
static int p3addr_s; /* Address of Player3 - Single Line Resolution */
static int maddr_d; /* Address of Missiles - Double Line Resolution */
static int p0addr_d; /* Address of Player0 - Double Line Resolution */
static int p1addr_d; /* Address of Player1 - Double Line Resolution */
static int p2addr_d; /* Address of Player2 - Double Line Resolution */
static int p3addr_d; /* Address of Player3 - Double Line Resolution */
int wsync_halt = 0;
static int carry=0; /* carry over of CPU cycles */
/*
=============================================================
Define screen as ULONG to ensure that it is Longword aligned.
This allows special optimisations under certain conditions.
-------------------------------------------------------------
The extra 16 scanlines is used as an overflow buffer and has
enough room for any extra mode line. It is needed on the
occasions that a valid JVB instruction is not found in the
display list - An automatic break out will occur when ypos
is greater than the ATARI_HEIGHT, if its one less than this
there must be enough space for another mode line.
=============================================================
*/
ULONG *atari_screen = NULL;
UBYTE *scrn_ptr;
/* I/O register read */
mtype ANTIC_CHBASE_GET(void)
{
return CHBASE;
}
mtype ANTIC_CHACTL_GET(void)
{
return CHACTL;
}
mtype ANTIC_DLISTL_GET(void)
{
return DLIST & 0xff;
}
mtype ANTIC_DLISTH_GET(void)
{
return DLIST >> 8;
}
mtype ANTIC_DMACTL_GET(void)
{
return DMACTL;
}
mtype ANTIC_VCOUNT_GET(void)
{
return ypos >> 1;
}
mtype ANTIC_NMIEN_GET(void)
{
return NMIEN | 0x1f;
}
mtype ANTIC_NMIST_GET(void)
{
return NMIST;
}
mtype ANTIC_WSYNC_GET(void)
{
if (wsync_halt)
printf("Double wsync!\n");
wsync_halt++;
return 0xff;
}
/* I/O put routines */
int ANTIC_CHBASE_PUT(mtype byte)
{
CHBASE = byte;
chbase_40 = (byte << 8) & 0xfc00;
chbase_20 = (byte << 8) & 0xfe00;
return FALSE;
}
int ANTIC_CHACTL_PUT(mtype byte)
{
CHACTL = byte;
/*
=================================================================
Check for vertical reflect, video invert and character blank bits
=================================================================
*/
switch (CHACTL & 0x07)
{
case 0x00 :
char_offset = 0;
char_delta = 1;
invert_mask = 0x00;
blank_mask = 0x00;
break;
case 0x01 :
char_offset = 0;
char_delta = 1;
invert_mask = 0x00;
blank_mask = 0x80;
break;
case 0x02 :
char_offset = 0;
char_delta = 1;
invert_mask = 0x80;
blank_mask = 0x00;
break;
case 0x03 :
char_offset = 0;
char_delta = 1;
invert_mask = 0x80;
blank_mask = 0x80;
break;
case 0x04 :
char_offset = 7;
char_delta = -1;
invert_mask = 0x00;
blank_mask = 0x00;
break;
case 0x05 :
char_offset = 7;
char_delta = -1;
invert_mask = 0x00;
blank_mask = 0x80;
break;
case 0x06 :
char_offset = 7;
char_delta = -1;
invert_mask = 0x80;
blank_mask = 0x00;
break;
case 0x07 :
char_offset = 7;
char_delta = -1;
invert_mask = 0x80;
blank_mask = 0x80;
break;
}
return FALSE;
}
int ANTIC_DLISTL_PUT(mtype byte)
{
DLIST = (DLIST & 0xff00) | byte;
DLISTINIT = DLIST;
return FALSE;
}
int ANTIC_DLISTH_PUT(mtype byte)
{
DLIST = (DLIST & 0x00ff) | (byte<<8);
DLISTINIT = DLIST;
return FALSE;
}
int ANTIC_DMACTL_PUT(mtype byte)
{
/* printf("DMACTL set to %2x at %4x\n",byte,regPC); */
DMACTL = byte;
switch (DMACTL & 0x03)
{
case 0x00 :
dmactl_xmin_noscroll = dmactl_xmax_noscroll = 0;
dmactl_xmin_scroll = dmactl_xmax_scroll = 0;
DMAwidth = 0;
memory_basis = 9; /* nine cycles for refresh */
break;
case 0x01 :
dmactl_xmin_noscroll = 64;
dmactl_xmax_noscroll = ATARI_WIDTH - 64;
dmactl_xmin_scroll = 32;
dmactl_xmax_scroll = ATARI_WIDTH - 32;
DMAwidth = 4;
memory_basis = 2; /* nine cycles for refresh */
break;
case 0x02 :
dmactl_xmin_noscroll = 32;
dmactl_xmax_noscroll = ATARI_WIDTH - 32;
dmactl_xmin_scroll = 0;
dmactl_xmax_scroll = ATARI_WIDTH;
memory_basis = 1;
DMAwidth = 5;
break;
case 0x03 :
dmactl_xmin_noscroll = dmactl_xmin_scroll = 0;
dmactl_xmax_noscroll = dmactl_xmax_scroll = ATARI_WIDTH;
memory_basis = 0;
DMAwidth = 6;
break;
}
pm_dma = 0; /* cycles needed for PM graphics */
if (DMACTL & 0x0C) /* Player DMA enables missile DMA */
pm_dma += 1;
if (DMACTL & 0x08) /* Player DMA ? */
pm_dma += 4;
/* SingleLine DMACTL & 0x10 not covered here */
return FALSE;
}
int ANTIC_HSCROL_PUT(mtype byte)
{
HSCROL = byte & 0x0f;
return FALSE;
}
int ANTIC_NMIEN_PUT(mtype byte)
{
NMIEN = byte | 0x1f;
/* printf("Wrote %d into NMIEN.\n",byte); */
return FALSE;
}
int ANTIC_NMIRES_PUT(mtype byte)
{
NMIST = 0x1f;
return FALSE;
}
int ANTIC_PMBASE_PUT(mtype byte)
{
UWORD pmbase_s;
UWORD pmbase_d;
PMBASE = byte;
pmbase_s = (PMBASE & 0xf8) << 8;
pmbase_d = (PMBASE & 0xfc) << 8;
maddr_s = pmbase_s + 768;
p0addr_s = pmbase_s + 1024;
p1addr_s = pmbase_s + 1280;
p2addr_s = pmbase_s + 1536;
p3addr_s = pmbase_s + 1792;
maddr_d = pmbase_d + 384;
p0addr_d = pmbase_d + 512;
p1addr_d = pmbase_d + 640;
p2addr_d = pmbase_d + 768;
p3addr_d = pmbase_d + 896;
return FALSE;
}
int ANTIC_VSCROL_PUT(mtype byte)
{
VSCROL = byte & 0x0f;
return FALSE;
}
int ANTIC_WSYNC_PUT(mtype byte)
{
wsync_halt ++;
return TRUE;
}
void Init_Antic (int *argc, char *argv[],int base)
{
int i;
int j;
if (argc) {
for (i=j=1;i<*argc;i++)
{
if (strcmp(argv[i],"-xcolpf1") == 0)
enable_xcolpf1 = TRUE;
else
argv[j++] = argv[i];
}
*argc = j;
}
NMIEN = 0x1f;
NMIST = 0x00;
DMACTL = 0x00;
VSCROL = 0x00;
HSCROL = 0x00;
/* setup lookup tables */
memset(lookup_f,0,256*sizeof(int));
memset(lookup_4,0,256*sizeof(int));
memset(lookup24,0,256*sizeof(int));
memset(lookup_9,0,256*sizeof(int));
lookup_f[0x00]=PF_COLPF2;
lookup_f[0x80]=lookup_f[0x40]=lookup_f[0x20]=
lookup_f[0x10]=lookup_f[0x08]=lookup_f[0x04]=
lookup_f[0x02]=lookup_f[0x01]=PF_COLPF1_FID;
lookup_4[0x00]=PF2_COLBK;
lookup_4[0x40]=lookup_4[0x10]=lookup_4[0x04]=lookup_4[0x01]=PF2_COLPF0;
lookup_4[0x80]=lookup_4[0x20]=lookup_4[0x08]=lookup_4[0x02]=PF2_COLPF1;
lookup_4[0xc0]=lookup_4[0x30]=lookup_4[0x0c]=lookup_4[0x03]=PF2_COLPF2;
lookup24[0x00]=PF2_COLBK;
lookup24[0x40]=lookup24[0x10]=lookup24[0x04]=lookup24[0x01]=PF2_COLPF0;
lookup24[0x80]=lookup24[0x20]=lookup24[0x08]=lookup24[0x02]=PF2_COLPF1;
lookup24[0xc0]=lookup24[0x30]=lookup24[0x0c]=lookup24[0x03]=PF2_COLPF3;
lookup_9[0x00]=PF2_COLBK;
lookup_9[0x80]=lookup_9[0x40]=lookup_9[0x20]=lookup_9[0x10]=
lookup_9[0x08]=lookup_9[0x04]=lookup_9[0x02]=lookup_9[0x01]=PF2_COLPF0;
memset(lookup_6+0x00,PF2_COLPF0,0x40*sizeof(int));
memset(lookup_6+0x40,PF2_COLPF1,0x40*sizeof(int));
memset(lookup_6+0x80,PF2_COLPF2,0x40*sizeof(int));
memset(lookup_6+0xc0,PF2_COLPF3,0x40*sizeof(int));
SetHW(base+_DMACTL,0xff0f,&ANTIC_DMACTL_GET,&ANTIC_DMACTL_PUT);
SetHW(base+_CHACTL,0xff0f,&ANTIC_CHACTL_GET,&ANTIC_CHACTL_PUT);
SetHW(base+_DLISTL,0xff0f,&ANTIC_DLISTL_GET,&ANTIC_DLISTL_PUT);
SetHW(base+_DLISTH,0xff0f,&ANTIC_DLISTH_GET,&ANTIC_DLISTH_PUT);
SetHW(base+_HSCROL,0xff0f,NULL,&ANTIC_HSCROL_PUT);
SetHW(base+_VSCROL,0xff0f,NULL,&ANTIC_VSCROL_PUT);
SetHW(base+_PMBASE,0xff0f,NULL,&ANTIC_PMBASE_PUT);
SetHW(base+_CHBASE,0xff0f,&ANTIC_CHBASE_GET,&ANTIC_CHBASE_PUT);
SetHW(base+_VCOUNT,0xff0f,&ANTIC_VCOUNT_GET,NULL);
SetHW(base+_NMIEN,0xff0f,&ANTIC_NMIEN_GET,&ANTIC_NMIEN_PUT);
SetHW(base+_NMIRES,0xff0f,&ANTIC_NMIST_GET,&ANTIC_NMIRES_PUT);
SetHW(base+_WSYNC,0xff0f,&ANTIC_WSYNC_GET,&ANTIC_WSYNC_PUT);
}
void antic_blank (int nlines)
{
if (nlines > 0)
{
int nbytes;
nbytes = nlines * ATARI_MODULO;
memset (scrn_ptr, PF_COLBK, nbytes);
}
}
static int vskipbefore = 0;
static int vskipafter = 0;
void antic_2 ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = (xmax - xmin) >> 3;
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
int invert;
int blank;
UBYTE *ptr = t_scrn_ptr;
int j;
screenaddr++;
chaddr = chbase_40 + char_offset + ((screendata & 0x7f) << 3);
if (screendata & invert_mask)
invert = 0xff;
else
invert = 0x00;
if (screendata & blank_mask)
blank = 0x00;
else
blank = 0xff;
for (j=0;j<8;j++)
{
int chdata;
chdata = (APeek(chaddr) ^ invert) & blank;
chaddr += char_delta;
if (j<vskipbefore || j>vskipafter)
continue;
if (chdata) {
*ptr++ = lookup_f[chdata & 0x80];
*ptr++ = lookup_f[chdata & 0x40];
*ptr++ = lookup_f[chdata & 0x20];
*ptr++ = lookup_f[chdata & 0x10];
*ptr++ = lookup_f[chdata & 0x08];
*ptr++ = lookup_f[chdata & 0x04];
*ptr++ = lookup_f[chdata & 0x02];
*ptr++ = lookup_f[chdata & 0x01];
} else {
#ifdef UNALIGNED_LONG_OK
ULONG *l_ptr = (ULONG*)ptr;
*l_ptr++ = PF4_COLPF2;
*l_ptr++ = PF4_COLPF2;
ptr = (UBYTE*)l_ptr;
#else
UWORD *w_ptr = (UWORD*)ptr;
*w_ptr++ = PF2_COLPF2;
*w_ptr++ = PF2_COLPF2;
*w_ptr++ = PF2_COLPF2;
*w_ptr++ = PF2_COLPF2;
ptr = (UBYTE*)w_ptr;
#endif
}
ptr += (ATARI_MODULO - 8);
}
t_scrn_ptr += 8;
}
}
/*
* Function to display Antic Mode 3
*/
void antic_3 ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = (xmax - xmin) >> 3;
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
int invert;
int blank;
int lowercase;
int first=0;
int second=0;
UBYTE *ptr = t_scrn_ptr;
int j;
screenaddr++;
chaddr = chbase_40 + ((screendata & 0x7f) << 3) + char_offset;
if (screendata & invert_mask)
invert = 0xff;
else
invert = 0x00;
if (screendata & blank_mask)
blank = 0x00;
else
blank = 0xff;
if ((screendata & 0x60) == 0x60)
lowercase = TRUE;
else
lowercase = FALSE;
for (j=0;j<10;j++)
{
int chdata;
if (lowercase) {
switch (j) {
case 0 :
first = APeek(chaddr);
chaddr += char_delta;
chdata = 0;
break;
case 1 :
second = APeek(chaddr);
chaddr += char_delta;
chdata = 0;
break;
case 8 :
chdata = first;
break;
case 9 :
chdata = second;
break;
default :
chdata = APeek(chaddr);
chaddr += char_delta;
break;
}
} else if (j < 8) {
chdata = APeek(chaddr);
chaddr += char_delta;
} else {
chdata = 0;
}
chdata = (chdata ^ invert) & blank;
if (j<vskipbefore || j>vskipafter)
continue;
if (chdata) {
*ptr++ = lookup_f[chdata & 0x80];
*ptr++ = lookup_f[chdata & 0x40];
*ptr++ = lookup_f[chdata & 0x20];
*ptr++ = lookup_f[chdata & 0x10];
*ptr++ = lookup_f[chdata & 0x08];
*ptr++ = lookup_f[chdata & 0x04];
*ptr++ = lookup_f[chdata & 0x02];
*ptr++ = lookup_f[chdata & 0x01];
} else {
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
*ptr++ = PF_COLPF2;
}
ptr += (ATARI_MODULO - 8);
}
t_scrn_ptr += 8;
}
}
/*
* Funtion to display Antic Mode 4
*/
void antic_4 ()
{
UWORD *t_scrn_ptr = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = (xmax - xmin) >> 3;
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
int *lookup;
UWORD *ptr = t_scrn_ptr;
int j;
screenaddr++;
chaddr = chbase_40 + ((screendata & 0x7f) << 3) + char_offset;
if (screendata & 0x80)
lookup = lookup24;
else
lookup = lookup_4;
for (j=0;j<8;j++)
{
int chdata;
chdata = APeek(chaddr);
chaddr += char_delta;
if (j<vskipbefore || j>vskipafter)
continue;
if (chdata) {
*ptr++ = lookup[chdata & 0xc0];
*ptr++ = lookup[chdata & 0x30];
*ptr++ = lookup[chdata & 0x0c];
*ptr++ = lookup[chdata & 0x03];
} else {
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
}
ptr += ((ATARI_MODULO - 8) >> 1);
}
t_scrn_ptr += 4;
}
}
/*
* Function to Display Antic Mode 5
*/
void antic_5 ()
{
UWORD *t_scrn_ptr1 = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = nchars = (xmax - xmin) >> 3;
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
int *lookup;
UWORD *ptr1 = t_scrn_ptr1;
int j;
screenaddr++;
chaddr = chbase_40 + ((UWORD)(screendata & 0x7f) << 3) + char_offset;
if (screendata & 0x80)
lookup = lookup24;
else
lookup = lookup_4;
for (j=0;j<16;j++)
{
int chdata;
chdata = APeek(chaddr);
if (j & 0x01) chaddr += char_delta;
if (j<vskipbefore || j>vskipafter)
continue;
if (chdata) {
*ptr1++ = lookup[chdata & 0xc0];
*ptr1++ = lookup[chdata & 0x30];
*ptr1++ = lookup[chdata & 0x0c];
*ptr1++ = lookup[chdata & 0x03];
} else {
*ptr1++ = PF2_COLBK;
*ptr1++ = PF2_COLBK;
*ptr1++ = PF2_COLBK;
*ptr1++ = PF2_COLBK;
}
ptr1 += ((ATARI_MODULO - 8) >> 1);
}
t_scrn_ptr1 += (8 >> 1);
}
}
/*
* Function to Display Antic Mode 6
*/
void antic_6 ()
{
UWORD *t_scrn_ptr = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = (xmax - xmin) >> 4; /* Divide by 16 */
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
UWORD *ptr = t_scrn_ptr;
int colour=0;
int j;
screenaddr++;
chaddr = chbase_20 + ((UWORD)(screendata & 0x3f) << 3) + char_offset;
colour = lookup_6[screendata];
for (j=0;j<8;j++) {
int chdata;
int k;
chdata = memory[chaddr];
chaddr += char_delta;
if (j<vskipbefore || j>vskipafter)
continue;
for (k=0;k<8;k++)
{
if (chdata & 0x80)
*ptr++ = colour;
else *ptr++ = PF2_COLBK;
chdata = chdata << 1;
}
ptr += ((ATARI_MODULO - 16) >> 1);
}
t_scrn_ptr += (16 >> 1);
}
}
/*
* Function to Display Antic Mode 7
*/
void antic_7 ()
{
UWORD *t_scrn_ptr1 = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nchars = (xmax - xmin) >> 4; /* Divide by 16 */
int i;
for (i=0;i<nchars;i++)
{
int screendata = APeek(screenaddr);
int chaddr;
UWORD *ptr1 = t_scrn_ptr1;
int colour=0;
int j;
screenaddr++;
chaddr = chbase_20 + ((UWORD)(screendata & 0x3f) << 3) + char_offset;
colour = lookup_6[screendata];
for (j=0;j<16;j++)
{
int chdata;
int k;
chdata = APeek(chaddr);
if (j & 0x01) chaddr += char_delta;
if (j<vskipbefore || j>vskipafter)
continue;
for (k=0;k<8;k++)
{
if (chdata & 0x80) *ptr1++ = colour;
else *ptr1++ = PF2_COLBK;
chdata = chdata << 1;
}
ptr1 += ((ATARI_MODULO - 16) >> 1);
}
t_scrn_ptr1 += (16 >> 1);
}
}
/*
* Function to Display Antic Mode 8
*/
void antic_8 ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 5; /* Divide by 32 */
int i;
for (i=0;i<nbytes;i++)
{
int screendata = APeek(screenaddr);
int j;
screenaddr++;
for (j=0;j<4;j++) {
int colour;
UBYTE *ptr = t_scrn_ptr;
int k;
colour = lookup_4[screendata & 0xc0];
for (k=0;k<8;k++) {
if (k<vskipbefore || k>vskipafter)
continue;
memset (ptr, colour, 8);
ptr += ATARI_MODULO;
}
screendata = screendata << 2;
t_scrn_ptr += 8;
}
}
}
/*
* Function to Display Antic Mode 9
*/
void antic_9 ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 5; /* Divide by 32 */
int i;
for (i=0;i<nbytes;i++)
{
int screendata = APeek(screenaddr);
int j;
screenaddr++;
for (j=0;j<8;j++) {
int colour;
UBYTE *ptr = t_scrn_ptr;
int k;
colour = lookup_9[screendata & 0x80];
for (k=0;k<4;k++) {
if (k<vskipbefore || k>vskipafter)
continue;
memset (ptr, colour, 4);
ptr += ATARI_MODULO;
}
screendata = screendata << 1;
t_scrn_ptr += 4;
}
}
}
/*
* Function to Display Antic Mode a
*/
void antic_a ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 4; /* Divide by 16 */
int i;
for (i=0;i<nbytes;i++)
{
int screendata = APeek(screenaddr);
int j;
screenaddr++;
for (j=0;j<4;j++)
{
int colour;
UBYTE *ptr = t_scrn_ptr;
int k;
colour = lookup_4[screendata & 0xc0];
for (k=0;k<4;k++) {
if (k<vskipbefore || k>vskipafter)
continue;
memset (ptr, colour, 4);
ptr += ATARI_MODULO;
}
screendata = screendata << 2;
t_scrn_ptr += 4;
}
}
}
/*
* Function to Display Antic Mode b
*/
void antic_b ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 4; /* Divide by 16 */
int i;
for (i=0;i<nbytes;i++)
{
int screendata = APeek(screenaddr);
int j;
screenaddr++;
for (j=0;j<8;j++) {
int colour;
UBYTE *ptr = t_scrn_ptr;
int k;
colour = lookup_9[screendata & 0x80];
for (k=0;k<2;k++) {
if (k<vskipbefore || k>vskipafter)
continue;
*ptr++ = colour;
*ptr++ = colour;
ptr += (ATARI_MODULO-2);
}
screendata = screendata << 1;
t_scrn_ptr += 2;
}
}
}
/*
* Function to Display Antic Mode c
*/
void antic_c ()
{
UWORD *t_scrn_ptr1 = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 4;
int i;
for (i=0;i<nbytes;i++)
{
UWORD *ptr=t_scrn_ptr1;
int j;
int screendata=APeek(screenaddr);
screenaddr++;
for (j=0;j<2;j++) {
if (j<vskipbefore || j>vskipafter)
continue;
if (screendata) {
*ptr++ = lookup_9[screendata & 0x80];
*ptr++ = lookup_9[screendata & 0x40];
*ptr++ = lookup_9[screendata & 0x20];
*ptr++ = lookup_9[screendata & 0x10];
*ptr++ = lookup_9[screendata & 0x08];
*ptr++ = lookup_9[screendata & 0x04];
*ptr++ = lookup_9[screendata & 0x02];
*ptr++ = lookup_9[screendata & 0x01];
} else {
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
}
ptr += ((ATARI_MODULO-8)>>1);
}
t_scrn_ptr1 += 8;
}
}
/*
* Function to Display Antic Mode d
*/
void antic_d ()
{
UWORD *t_scrn_ptr1 = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 3;
int i;
for (i=0;i<nbytes;i++)
{
UWORD *ptr=t_scrn_ptr1;
int j;
int screendata=APeek(screenaddr);
screenaddr++;
for (j=0;j<2;j++) {
if (j<vskipbefore || j>vskipafter)
continue;
if (screendata) {
*ptr++ = lookup_4[screendata & 0xc0];
*ptr++ = lookup_4[screendata & 0x30];
*ptr++ = lookup_4[screendata & 0x0c];
*ptr++ = lookup_4[screendata & 0x03];
} else {
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
*ptr++ = PF2_COLBK;
}
ptr += ((ATARI_MODULO-8)>>1);
}
t_scrn_ptr1 += 4;
}
}
/*
* Function to display Antic Mode e
*/
void antic_e ()
{
UWORD *t_scrn_ptr = (UWORD*)&scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 3;
int i;
for (i=0;i<nbytes;i++)
{
int screendata = APeek(screenaddr);
screenaddr++;
if (screendata)
{
*t_scrn_ptr++ = lookup_4[screendata & 0xc0];
*t_scrn_ptr++ = lookup_4[screendata & 0x30];
*t_scrn_ptr++ = lookup_4[screendata & 0x0c];
*t_scrn_ptr++ = lookup_4[screendata & 0x03];
}
else
{
#ifdef UNALIGNED_LONG_OK
ULONG *l_ptr = (ULONG*)t_scrn_ptr;
*l_ptr++ = PF4_COLBK;
*l_ptr++ = PF4_COLBK;
t_scrn_ptr = (UWORD*)l_ptr;
#else
*t_scrn_ptr++ = PF2_COLBK;
*t_scrn_ptr++ = PF2_COLBK;
*t_scrn_ptr++ = PF2_COLBK;
*t_scrn_ptr++ = PF2_COLBK;
#endif
}
}
}
/*
* Function to display Antic Mode f
*/
void antic_f ()
{
UBYTE *t_scrn_ptr = &scrn_ptr[FILLIN_OFFSET+xmin];
int nbytes = (xmax - xmin) >> 3;
int i;
for (i=0;i<nbytes;i++)
{
UBYTE screendata = APeek(screenaddr);
screenaddr++;
if (screendata)
{
*t_scrn_ptr++ = lookup_f[screendata & 0x80];
*t_scrn_ptr++ = lookup_f[screendata & 0x40];
*t_scrn_ptr++ = lookup_f[screendata & 0x20];
*t_scrn_ptr++ = lookup_f[screendata & 0x10];
*t_scrn_ptr++ = lookup_f[screendata & 0x08];
*t_scrn_ptr++ = lookup_f[screendata & 0x04];
*t_scrn_ptr++ = lookup_f[screendata & 0x02];
*t_scrn_ptr++ = lookup_f[screendata & 0x01];
}
else
{
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
*t_scrn_ptr++ = PF_COLPF2;
}
}
}
/*
*****************************************************************
* *
* Section : Display List *
* Original Author : David Firth *
* Date Written : 28th May 1995 *
* Version : 1.0 *
* *
* Description *
* ----------- *
* *
* Section that handles Antic Display List. Not required for *
* BASIC version. *
* *
*****************************************************************
*/
void pmg_dma (void)
{
int yhalf = ypos >> 1;
/* single line shift not yet implemented.... */
if (DMACTL & 0x08)
{
if (DMACTL & 0x10)
{
GRAFP0 = memory[p0addr_s + ypos];
GRAFP1 = memory[p1addr_s + ypos];
GRAFP2 = memory[p2addr_s + ypos];
GRAFP3 = memory[p3addr_s + ypos];
}
else
{
GRAFP0 = memory[p0addr_d + yhalf - delayp0];
GRAFP1 = memory[p1addr_d + yhalf - delayp1];
GRAFP2 = memory[p2addr_d + yhalf - delayp2];
GRAFP3 = memory[p3addr_d + yhalf - delayp3];
}
}
if (DMACTL & 0x0C) /* Player DMA enables missile DMA as well */
{
if (DMACTL & 0x10)
GRAFM = memory[maddr_s + ypos];
else {
int mis0,mis1,mis2,mis3;
mis0 = memory[maddr_d + yhalf - delaym0];
mis1 = memory[maddr_d + yhalf - delaym1];
mis2 = memory[maddr_d + yhalf - delaym2];
mis3 = memory[maddr_d + yhalf - delaym3];
GRAFM = (mis0 & 0x03) | (mis1 & 0x0c) | (mis2 & 0x30) | (mis3 & 0xc0);
}
}
}
static void Clear_Border(int hscrol)
{
int scrol=HSCROL+HSCROL;
int shift=FILLIN_OFFSET;
int left=FILLIN_OFFSET+dmactl_xmin_noscroll;
if (hscrol) {
shift -= scrol;
if ((DMACTL & 0x03)!=0x03)
left -= scrol;
}
memset(scrn_ptr,PF_COLBK,left);
memset(scrn_ptr+dmactl_xmax_noscroll+shift,PF_COLBK,
ATARI_MODULO-dmactl_xmax_noscroll-shift);
}
static void ANTIC_Scanline(int dmacycles,int nmi,int hscrol)
{
int before;
int after;
int add;
before=cc_middle-before_dma-dmacycles;
after=114-cc_middle-after_wsync;
if (before<0) {
after += before;
before = 0;
}
add = carry;
Clear_Border(hscrol);
if (!wsync_halt) {
if (before_dma>0)
add = GO(before_dma+add);
if (nmi) {
before += add;
before -= dli_delay;
if (before>0) {
NMI();
nmi = FALSE;
add = GO(before);
}
} else {
before += add;
if (before>0)
add = GO(before);
}
}
pmg_dma ();
Atari_ScanLine (hscrol);
if (!wsync_halt) {
if (nmi) {
after += add;
after -= dli_delay;
if (after>0) {
NMI();
nmi = FALSE;
add = GO(after);
}
} else {
after += add;
if (after>0)
add = GO(after);
}
}
wsync_halt=0;
if (nmi) {
NMI();
add = GO(after_wsync-dli_delay+add);
} else add = GO(after_wsync+add);
carry = add;
scrn_ptr += ATARI_MODULO;
ypos++;
}
void ANTIC_RunDisplayList (void)
{
int JVB=FALSE;
int vscrol_flag=0;
int nlines=0;
int i;
int IR;
int acnt;
int acntn;
int dmawidth;
int hscrol;
wsync_halt = 0;
/*
* VCOUNT must equal zero for some games but the first line starts
* when VCOUNT=4. This portion processes when VCOUNT=0, 1, 2 and 3
*/
scrn_ptr = (UBYTE*)atari_screen;
DLIST=DLISTINIT;
for (ypos = 0; ypos <8 ;ypos++) {
carry=GO (carry+105); /* 114 minus 9 memory cycles */
}
NMIST = 0x00;
for (ypos = 8, JVB=FALSE ; ypos < (ATARI_HEIGHT + 8);) {
if ((DMACTL & 0x10) || (ypos & 0x01)==0)
acntn=pm_dma;
else
acntn=0;
acnt = 0;
/* Counter for DMA type needed by ANTIC. One cycle per byte
acnt is the counter for the extra cycles of the first scanline
of the modeline acntn for all following lines */
if (JVB || (DMACTL & 0x20)==0) {
antic_blank(1);
ANTIC_Scanline(9,FALSE,FALSE);
} else {
IR = APeek(DLIST);
DLIST++;
acnt++;
vskipbefore = 0;
vskipafter = 127;
hscrol = FALSE;
xmin = dmactl_xmin_noscroll;
xmax = dmactl_xmax_noscroll;
dmawidth = DMAwidth;
switch (IR & 0x0f)
{
case 0x00 :
nlines = ((IR >> 4) & 0x07) + 1;
antic_blank (nlines);
break;
case 0x01 :
if (IR & 0x40)
JVB = TRUE;
DLIST = DAPeek(DLIST);
acnt += 2;
nlines = 1;
antic_blank (1); /* Jump aparently uses 1 scan line */
break;
default :
if (IR & 0x40) {
screenaddr = DAPeek(DLIST);
DLIST += 2;
acnt += 2;
}
if (IR & 0x20) {
if (!vscrol_flag) {
vskipbefore = (int)VSCROL;
vscrol_flag = TRUE;
}
}
else if (vscrol_flag) {
vskipafter = VSCROL;
vscrol_flag = FALSE;
}
if (IR & 0x10) {
xmin = dmactl_xmin_scroll;
xmax = dmactl_xmax_scroll;
hscrol = TRUE;
if (dmawidth<6) {
dmawidth++;
acntn--; /* one memory refresh cycle is dropped */
}
}
switch (IR & 0x0f) {
case 0x02 :
nlines = 8;
acnt += dmawidth*8+memory_basis-9;
acntn += dmawidth*8+9;
antic_2 ();
break;
case 0x03 :
nlines = 10;
acnt += dmawidth*8+memory_basis-9;
acntn += dmawidth*8+9;
antic_3 ();
break;
case 0x04 :
nlines = 8;
acnt += dmawidth*8+memory_basis-9;
acntn += dmawidth*8+9;
antic_4 ();
break;
case 0x05 :
nlines = 16;
acnt += dmawidth*8+memory_basis-9;
acntn += dmawidth*8+9;
antic_5 ();
break;
case 0x06 :
nlines = 8;
acnt += dmawidth*4;
acntn += dmawidth*4+9;
antic_6 ();
break;
case 0x07 :
nlines = 16;
acnt += dmawidth*4;
acntn += dmawidth*4+9;
antic_7 ();
break;
case 0x08 :
nlines = 8;
acnt += dmawidth*2+9;
antic_8 ();
break;
case 0x09 :
nlines = 4;
acnt += dmawidth*2+9;
antic_9 ();
break;
case 0x0a :
nlines = 4;
acnt += dmawidth*4+9;
antic_a ();
break;
case 0x0b :
nlines = 2;
acnt += dmawidth*4+9;
antic_b ();
break;
case 0x0c :
nlines = 1;
acnt += dmawidth*4+9;
antic_c ();
break;
case 0x0d :
nlines = 2;
acnt += dmawidth*8+9;
antic_d ();
break;
case 0x0e :
nlines = 1;
acnt += dmawidth*8+9;
antic_e ();
break;
case 0x0f :
nlines = 1;
acnt += dmawidth*8+9;
antic_f ();
break;
default :
printf("IR %x caused problems.\n",IR);
nlines = 0;
break;
}
break;
}
if (nlines > 0) {
int dma;
int nmi=FALSE;
nlines--;
dma=acnt+acntn;
if (vskipafter<nlines)
nlines=vskipafter;
for (i=vskipbefore;i<nlines;i++) {
ANTIC_Scanline(dma,FALSE,hscrol);
dma=acntn;
}
if (IR & 0x80) {
if (NMIEN & 0x80) {
NMIST = 0x80;
nmi = TRUE;
}
}
ANTIC_Scanline(dma,nmi,hscrol);
}
}
}
for(ypos=248; ypos<vsync_pos;ypos++)
carry = GO(carry+105);
NMIST = 0x40; /* Set VBLANK */
if (NMIEN & 0x40) {
carry=GO (carry+7);
/* Needed for programs that monitor NMIST (Spy's Demise, GORF) */
NMI ();
carry -= dli_delay+7; /* Needed by 6502 to react */
}
if (tv_mode == PAL)
for (ypos=vsync_pos;ypos<312;ypos++)
carry=GO (carry+105);
else
for (ypos=vsync_pos;ypos<262;ypos++)
carry=GO (carry+105);
}