home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ST-Computer Leser 2002 January
/
STC_CD_01_2002.iso
/
JAGUAR
/
JAG_SRC
/
SOURCE
/
OBJECT.C
< prev
next >
Wrap
C/C++ Source or Header
|
2001-08-18
|
20KB
|
482 lines
////////////////////////////////////////////////////////////////////////////////
// Jagulator: Atari Jaguar Console Emulation Project (object.c)
// -----------------------------------------------------------------------------
// Jagulator is the Copyright (c) RealityMan 1998-2001 and is provided "as is"
// without any expressed or implied warranty. I have no Trademarks, Legal or
// otherwise. Atari, Jaguar and the Atari Logo are copyright Hasbro Inc. All
// other Copyrights and Trademarks are acknowledged. This project is in no way
// linked to Atari/Hasbro or other associated Atari companies.
#include "core.h"
////////////////////////////////////////////////////////////////////////////////
// Macros
//#define DBGOP // Include Object Processor Debug Code
////////////////////////////////////////////////////////////////////////////////
// Globals
static GLuint fi[0x2EC00]; // Frame Image (512 x 374)
static dword tolp; // Traversing Object List Pointer
static char *iolp; // Internal Object Pointer
static dword hi, lo; // Object Phrase Hi and Lo Words
static dword olir; // Object List in Cartridge Rom Flag
extern GLuint clut[]; // RGBA Translation of CrY CLUT Table
////////////////////////////////////////////////////////////////////////////////
// Process a Standard Bitmap or Scaled Bitmap Object
void object_bitmap( dword scale )
{
word xpos; // X Position of First Pixel
word ypos; // Y Position (in Half Lines)
word height; // Number of Data Lines in Object
word depth; // Bits Per Pixel
word pitch; // Skipping
word dwidth; // Data Width in Phrases
word iwidth; // Image Width in Phrases
word index; // Pallette Address Element
word flags; // Reflect, RMW, Trans, Release
word fpix; // First Pixel to be Displayed
dword link; // Address of Next Object
dword data; // Address of Pixel Data
dword temp; // Temporary Bit Data
word hscale; // Horizontal Scaling
word vscale; // Vertical Scaling
word remainder; // Scaling Remainder
dword trans; // Transparency Flag
static int bpp[6] = { 1, 2, 4, 8, 16, 24 };
word wpil; // 16 Bit Words Per Image Line
word wpdl; // 16 Bit Words Per Data Line
word ddil; // 16 Bit Words Difference Above
dword index_d; // Index * 2 (To Reduce Calc Time)
// Process First Bitmap Object Phrase. First Phrase Obtained from
// Object Processor List Execution Routine object_exec()
ypos = (lo & O_YPOS ) >> 3;
height = (lo & O_HEIGHT) >> 14;
temp = (lo & O_LINK1 ) >> 24;
temp |= (hi & O_LINK2 ) << 8;
link = (temp << 3) | (tolp & 0xFFE00007);
data = (hi & O_DATA ) >> 8;
// Obtain Second Bitmap Phrase
hi = *(word *)(iolp + 8) << 16;
hi |= *(word *)(iolp + 10);
lo = *(word *)(iolp + 12) << 16;
lo |= *(word *)(iolp + 14);
// Process Second Bitmap Object Phrase
xpos = (lo & O_XPOS );
depth = (lo & O_DEPTH ) >> 12;
pitch = (lo & O_PITCH ) >> 15;
dwidth = (lo & O_DWIDTH ) >> 18;
iwidth = (lo & O_IWIDTH1) >> 28;
iwidth |= (hi & O_IWIDTH2) << 4;
index = (hi & O_INDEX ) >> 6;
flags = (hi & O_FLAGS );
fpix = (hi & O_1STPIX ) >> 17;
index_d = (2 * index);
// Obtain and Process Third Bitmap Object Phrase if Scaled Object
if( scale )
{
hi = *(word *)(iolp + 16) << 16;
hi |= *(word *)(iolp + 18);
lo = *(word *)(iolp + 20) << 16;
lo |= *(word *)(iolp + 22);
hscale = (lo & O_HSCALE);
vscale = (lo & O_VSCALE) >> 8;
remainder = (lo & O_REMAIN) >> 16;
}
#ifdef DBGOP
if( scale )
print( BLUE"Object List: Scaled Bitmap Object (OLP = 0x%08X)\n",tolp );
else
print( BLUE"Object List: Bitmap Object (OLP = 0x%08X)\n", tolp );
print( "YPOS : 0x%04X (%04i/2 = %04i) HEIGHT : 0x%04X (%04i)\n",
ypos, ypos, ypos/2, height, height );
print( "LINK : 0x%08X DATA : 0x%08X\n",link, data );
print( "XPOS : 0x%04X (%04i) DEPTH : 0x%04X\n",
xpos, xpos, depth );
print( "PITCH : 0x%04X DWIDTH : 0x%04X IWIDTH : 0x%04X INDEX "
": 0x%04X\n", pitch, dwidth, iwidth, index );
print( "REFLECT : 0x%01X RMW : 0x%01X TRANS : 0x%01X "
"RELEASE : 0x%01X\n", flags & 0x01, (flags & 0x02) >> 1,
(flags & 0x04) >> 2, (flags & 0x08) >> 3 );
print( "FIRSTPIX : 0x%04X ", fpix );
if( scale )
print( "HSCALE : 0x%04X VSCALE : 0x%04X REMAIN : 0x%04X\n",
hscale, vscale, remainder );
print( "Image = %i x %i\n", (dwidth * 64) / bpp[depth], height );
#endif
// Activate Transparency if Required
if( (flags & O_TRANS) )
{
clut[0] &= 0x00FFFFFF;
clut[index_d] &= 0x00FFFFFF;
trans = 1;
}
else
{
clut[0] |= 0xFF000000;
clut[index_d] |= 0xFF000000;
trans = 0;
}
// Write Image Data to Frame Image
{
int x; // Frame Image Index
int i, j; // Loop Iterators
dword dw, addr; // Data Word and Address
wpil = (iwidth * 8) / 2; // Number of Words Per Visible Data Line
wpdl = (dwidth * 8) / 2; // Number of Words Per Actual Data Line
ddil = (wpdl - wpil) * 2; // Difference Between Image & Data Lines
addr = data; // Get Jaguar Data Address
switch( depth )
{
// --- 1BPP [CLUT] -------------------------------------------------
case 0:
x = 0; // Initialise Frame Image Index
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image using the CLUT
fi[x++] = clut[(index_d + ((dw & 0x8000) >> 15))];
fi[x++] = clut[(index_d + ((dw & 0x4000) >> 14))];
fi[x++] = clut[(index_d + ((dw & 0x2000) >> 13))];
fi[x++] = clut[(index_d + ((dw & 0x1000) >> 12))];
fi[x++] = clut[(index_d + ((dw & 0x0800) >> 11))];
fi[x++] = clut[(index_d + ((dw & 0x0400) >> 10))];
fi[x++] = clut[(index_d + ((dw & 0x0200) >> 9 ))];
fi[x++] = clut[(index_d + ((dw & 0x0100) >> 8 ))];
fi[x++] = clut[(index_d + ((dw & 0x0080) >> 7 ))];
fi[x++] = clut[(index_d + ((dw & 0x0040) >> 6 ))];
fi[x++] = clut[(index_d + ((dw & 0x0020) >> 5 ))];
fi[x++] = clut[(index_d + ((dw & 0x0010) >> 4 ))];
fi[x++] = clut[(index_d + ((dw & 0x0008) >> 3 ))];
fi[x++] = clut[(index_d + ((dw & 0x0004) >> 2 ))];
fi[x++] = clut[(index_d + ((dw & 0x0002) >> 1 ))];
fi[x++] = clut[(index_d + ((dw & 0x0001) ))];
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on Differences
// Between The Data Width and Image Width
addr += ddil;
}
break;
// --- 2BPP [CLUT] -------------------------------------------------
case 1:
x = 0; // Initialise Frame Image Index
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image using the CLUT
fi[x++] = clut[(index_d + ((dw & 0xC000) >> 14))];
fi[x++] = clut[(index_d + ((dw & 0x3000) >> 12))];
fi[x++] = clut[(index_d + ((dw & 0x0C00) >> 10))];
fi[x++] = clut[(index_d + ((dw & 0x0300) >> 8 ))];
fi[x++] = clut[(index_d + ((dw & 0x00C0) >> 6 ))];
fi[x++] = clut[(index_d + ((dw & 0x0030) >> 4 ))];
fi[x++] = clut[(index_d + ((dw & 0x000C) >> 2 ))];
fi[x++] = clut[(index_d + ((dw & 0x0003) ))];
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on Differences
// Between The Data Width and Image Width
addr += ddil;
}
break;
// --- 4BPP [CLUT] -------------------------------------------------
case 2:
x = 0; // Initialise Frame Image Index
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image using the CLUT
fi[x++] = clut[(index_d + ((dw & 0xF000) >> 12))];
fi[x++] = clut[(index_d + ((dw & 0x0F00) >> 8 ))];
fi[x++] = clut[(index_d + ((dw & 0x00F0) >> 4 ))];
fi[x++] = clut[(index_d + ((dw & 0x000F) ))];
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on Differences
// Between The Data Width and Image Width
addr += ddil;
}
break;
// --- 8BPP [CLUT] -------------------------------------------------
case 3:
x = 0; // Initialise Frame Image Index
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image using the CLUT
fi[x++] = clut[((dw & 0xFF00) >> 8)];
fi[x++] = clut[((dw & 0x00FF) )];
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on Differences
// Between The Data Width and Image Width
addr += ddil;
}
break;
// --- 16BPP -------------------------------------------------------
case 4: // 16 Bpp - 65536 Colors
x = 0; // Initialise Frame Image Index
switch( gst.cmode )
{
case 0: // CRY16
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image
fi[x++] = cry16_rgb32( dw, trans );
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on
// Differences Between The Data Width and Image Width
addr += ddil;
}
break;
case 3: // RGB16
// Lines
for( i = height; i > 0; i-- )
{
// Pixels
for( j = 0; j < wpil; j ++ )
{
// Read 16 Bit Word from Jaguar Memory
dw = mem_readword( addr );
// Update Frame Image
fi[x++] = rgb16_rgb32( dw, trans );
// Increment Jaguar Memory Address
addr += 2;
}
// Increment Jaguar Memory Address Dependant on
// Differences Between The Data Width and Image Width
addr += ddil;
}
break;
default:
#ifdef DBGOP
error( "OP-BMP: Unsupported 16-Bit Color Mode [%i]",
gst.cmode );
#endif
break;
}
break;
// --- 24BPP -------------------------------------------------------
case 5:
#ifdef DBGOP
error( "OP-BMP: Unsupported Color Depth [%i]", depth );
#endif
break;
}
}
// Set Pixel X, Y Position
glRasterPos2i( xpos, (ypos / 2) );
// Draw with Correct Orientation and Scaling if Required
if( scale )
{
glPixelZoom( (GLfloat)((1.0 / 32.0) * hscale),
-((GLfloat)((1.0 / 32.0) * vscale)) );
}
else
{
glPixelZoom( 1.0, -1.0 );
}
// Send Image to Back Buffer
glDrawPixels( ((iwidth * 64) / bpp[depth]), height,
GL_RGBA, GL_UNSIGNED_BYTE, &fi );
#ifdef DBGOP
glBegin( GL_QUADS );
glVertex2i( xpos, (ypos / 2) );
glVertex2i( xpos + ((iwidth * 64) / bpp[depth]), (ypos / 2) );
glVertex2i( xpos + ((iwidth * 64) / bpp[depth]), (ypos / 2) + height );
glVertex2i( xpos, (ypos / 2) + height );
glEnd();
#endif
// Obtain Link Address to Next Object
tolp = link;
}
////////////////////////////////////////////////////////////////////////////////
// Process a Branch Object
void object_branch( void )
{
static dword link;
link = ((lo & 0xFF000000) >> 21) | ((hi & 0x000007FF) << 11);
#ifdef DBGOP
print( BLUE"Object List - Branch Object (OLP = 0x%08X)\n", tolp );
print( "YPOS = 0x%04X LINK = 0x%06X\n",(lo & 0x3FF8) >> 3, link );
#endif
switch( ((lo & 0x0001C000) >> 14) )
{
case O_BREQ:
#ifdef DBGOP
print( "Branch to Link if YPOS==VC or YPOS==7FF\n" );
#endif
tolp = link;
break;
case O_BRGT:
#ifdef DBGOP
print( "Branch to Link if YPOS > VC\n" );
#endif
tolp += 8;
break;
case O_BRLT:
#ifdef DBGOP
print( "Branch to Link if YPOS < VC\n" );
#endif
tolp += 8;
break;
case O_BROP:
#ifdef DBGOP
print( YEL"Branch to Link if Object Processor Flag Set\n" );
#endif
gst.olista = FALSE;
break;
case O_BRHALF:
#ifdef DBGOP
print( YEL"Branch to Link if on Second Half of Display Line\n" );
#endif
gst.olista = FALSE;
break;
}
}
////////////////////////////////////////////////////////////////////////////////
// Process a Stop Object
void object_stop( void )
{
#ifdef DBGOP
print( BLUE"Object List - Stop Object (OLP = 0x%08X)\n", tolp );
if( (hi & 0xFFFFFFFF) && (lo & 0xFFFFFFF8) )
error( "Unhandled STOP Object Data" );
#endif
gst.olista = FALSE;
}
////////////////////////////////////////////////////////////////////////////////
// Object Processor Execution
void object_exec( void )
{
if( !gst.vmode ) return; // Don't Continue if Video Mode Not Set
#ifdef DBGOP
print( CYAN"Object Processor Starting...\n" );
#endif
gst.objActive = TRUE; // Object Processing is Starting
obj_framestart();
#ifdef DBGOP
// Wireframe Mode
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
#endif
// Setup Transparency Dependant on Alpha Channel (0=Transparent, 1=Opaque)
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
tolp = gst.olp; // Set Traversing Object List Pointer
if( tolp >= 0x800000 ) olir = 1;
else olir = 0;
gst.olista = TRUE; // Set Object List Active Flag
while( gst.olista ) // Process Object List
{
// Set Memory Pointer Dependant on Object List Location
if( olir ) iolp = (st.game + (tolp - 0x800000));
else iolp = (st.ram + tolp);
// Get Object List Phrase
hi = *(word *)(iolp ) << 16;
hi |= *(word *)(iolp + 2);
lo = *(word *)(iolp + 4) << 16;
lo |= *(word *)(iolp + 6);
switch( lo & O_MASK_TYPE )
{
case BITOBJ: object_bitmap( 0 ); break;
case SCBITOBJ: object_bitmap( 1 ); break;
case STOPOBJ: object_stop(); break;
case BRANCHOBJ: object_branch(); break;
case GPUOBJ:
default:
#ifdef DBG
print( YEL"OP - Unknown Object Type\n" );
#endif
gst.olista = FALSE;
break;
}
}
obj_frameend();
gst.objActive = FALSE; // Object Processing is Terminating
#ifdef DBGOP
print( BROWN"Displayed Frame %i\n", gst.frame++ );
print( RED"Object Processor Stopping...\n" );
#endif
}