ras.cpp
来自「DGen源码最后版本」· C++ 代码 · 共 784 行 · 第 1/2 页
CPP
784 行
*(where+4 ) = pal[((tile & 0xf0000000)>>26)+2];
*(where+5 ) = pal[((tile & 0xf0000000)>>26) ]; }
if(tile & 0x000f0000) { *(where+6 ) = pal[((tile & 0x000f0000)>>14)+1];
*(where+7 ) = pal[((tile & 0x000f0000)>>14)+2];
*(where+8 ) = pal[((tile & 0x000f0000)>>14) ]; }
if(tile & 0x00f00000) { *(where+9 ) = pal[((tile & 0x00f00000)>>18)+1];
*(where+10) = pal[((tile & 0x00f00000)>>18)+2];
*(where+11) = pal[((tile & 0x00f00000)>>18) ]; }
if(tile & 0x00000f00) { *(where+12) = pal[((tile & 0x00000f00)>> 6)+1];
*(where+13) = pal[((tile & 0x00000f00)>> 6)+2];
*(where+14) = pal[((tile & 0x00000f00)>> 6) ]; }
if(tile & 0x0000f000) { *(where+15) = pal[((tile & 0x0000f000)>>10)+1];
*(where+16) = pal[((tile & 0x0000f000)>>10)+2];
*(where+17) = pal[((tile & 0x0000f000)>>10) ]; }
if(tile & 0x0000000f) { *(where+18) = pal[((tile & 0x0000000f)<< 2)+1];
*(where+19) = pal[((tile & 0x0000000f)<< 2)+2];
*(where+20) = pal[((tile & 0x0000000f)<< 2) ]; }
if(tile & 0x000000f0) { *(where+21) = pal[((tile & 0x000000f0)>> 2)+1];
*(where+22) = pal[((tile & 0x000000f0)>> 2)+2];
*(where+23) = pal[((tile & 0x000000f0)>> 2) ]; }
} else {
if(tile & 0x000000f0) { *(where ) = pal[((tile & 0x000000f0)>> 2)+1];
*(where+ 1) = pal[((tile & 0x000000f0)>> 2)+2];
*(where+ 2) = pal[((tile & 0x000000f0)>> 2) ]; }
if(tile & 0x0000000f) { *(where+ 3) = pal[((tile & 0x0000000f)<< 2)+1];
*(where+ 4) = pal[((tile & 0x0000000f)<< 2)+2];
*(where+ 5) = pal[((tile & 0x0000000f)<< 2) ]; }
if(tile & 0x0000f000) { *(where+ 6) = pal[((tile & 0x0000f000)>>10)+1];
*(where+ 7) = pal[((tile & 0x0000f000)>>10)+2];
*(where+ 8) = pal[((tile & 0x0000f000)>>10) ]; }
if(tile & 0x00000f00) { *(where+ 9) = pal[((tile & 0x00000f00)>> 6)+1];
*(where+10) = pal[((tile & 0x00000f00)>> 6)+2];
*(where+11) = pal[((tile & 0x00000f00)>> 6) ]; }
if(tile & 0x00f00000) { *(where+12) = pal[((tile & 0x00f00000)>>18)+1];
*(where+13) = pal[((tile & 0x00f00000)>>18)+2];
*(where+14) = pal[((tile & 0x00f00000)>>18) ]; }
if(tile & 0x000f0000) { *(where+15) = pal[((tile & 0x000f0000)>>14)+1];
*(where+16) = pal[((tile & 0x000f0000)>>14)+2];
*(where+17) = pal[((tile & 0x000f0000)>>14) ]; }
if(tile & 0xf0000000) { *(where+18) = pal[((tile & 0xf0000000)>>26)+1];
*(where+19) = pal[((tile & 0xf0000000)>>26)+2];
*(where+20) = pal[((tile & 0xf0000000)>>26) ]; }
if(tile & 0x0f000000) { *(where+21) = pal[((tile & 0x0f000000)>>22)+1];
*(where+22) = pal[((tile & 0x0f000000)>>22)+2];
*(where+23) = pal[((tile & 0x0f000000)>>22) ]; }
}
}
// Blit tile solidly, for 4 byte-per-pixel
inline void md_vdp::draw_tile4_solid(int which, int line, unsigned char *where)
{
unsigned tile, temp, *pal;
unsigned *wwhere = (unsigned*)where;
pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette
temp = *pal; *pal = highpal[reg[7]&0x3f]; // Get background color
if(which & 0x1000) // y flipped
line ^= 7; // take from the bottom, instead of the top
if(reg[12] & 2) // interlace
tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3));
else
tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2));
// Blit the tile!
if(which & 0x800) // x flipped
{
*(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)];
*(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)];
*(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)];
*(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)];
*(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)];
*(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)];
*(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)];
*(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)];
} else {
*(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)];
*(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)];
*(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)];
*(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)];
*(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)];
*(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)];
*(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)];
*(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)];
}
// Restore the original color
*pal = temp;
}
// Blit tile, leaving color zero transparent, for 4 byte per pixel
inline void md_vdp::draw_tile4(int which, int line, unsigned char *where)
{
unsigned tile, *pal;
unsigned *wwhere = (unsigned*)where;
pal = highpal + (which >> 9 & 0x30); // Determine which 16-color palette
if(which & 0x1000) // y flipped
line ^= 7; // take from the bottom, instead of the top
if(reg[12] & 2) // interlace
tile = *(unsigned*)(vram + ((which&0x7ff) << 6) + (line << 3));
else
tile = *(unsigned*)(vram + ((which&0x7ff) << 5) + (line << 2));
// If the tile is all 0's, why waste the time?
if(!tile) return;
// Blit the tile!
if(which & 0x800) // x flipped
{
if(tile & PIXEL7) *(wwhere ) = pal[((tile & PIXEL7)>>SHIFT7)];
if(tile & PIXEL6) *(wwhere+1) = pal[((tile & PIXEL6)>>SHIFT6)];
if(tile & PIXEL5) *(wwhere+2) = pal[((tile & PIXEL5)>>SHIFT5)];
if(tile & PIXEL4) *(wwhere+3) = pal[((tile & PIXEL4)>>SHIFT4)];
if(tile & PIXEL3) *(wwhere+4) = pal[((tile & PIXEL3)>>SHIFT3)];
if(tile & PIXEL2) *(wwhere+5) = pal[((tile & PIXEL2)>>SHIFT2)];
if(tile & PIXEL1) *(wwhere+6) = pal[((tile & PIXEL1)>>SHIFT1)];
if(tile & PIXEL0) *(wwhere+7) = pal[((tile & PIXEL0)>>SHIFT0)];
} else {
if(tile & PIXEL0) *(wwhere ) = pal[((tile & PIXEL0)>>SHIFT0)];
if(tile & PIXEL1) *(wwhere+1) = pal[((tile & PIXEL1)>>SHIFT1)];
if(tile & PIXEL2) *(wwhere+2) = pal[((tile & PIXEL2)>>SHIFT2)];
if(tile & PIXEL3) *(wwhere+3) = pal[((tile & PIXEL3)>>SHIFT3)];
if(tile & PIXEL4) *(wwhere+4) = pal[((tile & PIXEL4)>>SHIFT4)];
if(tile & PIXEL5) *(wwhere+5) = pal[((tile & PIXEL5)>>SHIFT5)];
if(tile & PIXEL6) *(wwhere+6) = pal[((tile & PIXEL6)>>SHIFT6)];
if(tile & PIXEL7) *(wwhere+7) = pal[((tile & PIXEL7)>>SHIFT7)];
}
}
#endif // ASM_TILES
// Draw the window (front or back)
void md_vdp::draw_window(int line, int front)
{
int size;
int x, y, w, start;
int pl, add;
int total_window;
unsigned char *where;
int which;
// Set everything up
y = line >> 3;
total_window = (y < (reg[18]&0x1f)) ^ (reg[18] >> 7);
// Wide or narrow
size = (reg[12] & 1)? 64 : 32;
pl = (reg[3] << 10) + ((y&0x3f)*size*2);
// Wide(320) or narrow(256)?
if(reg[12] & 1)
{
w = 40;
start = -8;
} else {
w = 32;
start = 24;
}
add = -2;
where = dest + (start * Bpp);
for(x=-1; x<w; ++x)
{
if(!total_window)
if(reg[17] & 0x80)
{
if(x < ((reg[17]&0x1f) << 1)) goto skip;
} else {
if(x >= ((reg[17]&0x1f) << 1)) goto skip;
}
which = get_word(((unsigned char*)vram) + (pl+(add&((size-1)<<1))));
if((which>>15) == front)
draw_tile(which, line&7, where);
skip:
add += 2; where += Bpp_times8;
}
}
void md_vdp::draw_sprites(int line, int front)
{
unsigned which;
int tx, ty, x, y, xend, ysize, yoff, i;
unsigned char *where, *sprite;
// Sprites have to be in reverse order :P
for(i = sprite_count - 1; i >= 0; --i)
{
sprite = sprite_base + (sprite_order[i] << 3);
// Get the first tile
which = get_word(sprite + 4);
// Only do it if it's on the right priority
if((which >> 15) == front)
{
// Get the sprite's location
y = get_word(sprite);
x = get_word(sprite + 6) & 0x1ff;
// Interlace?
if(reg[12] & 2)
y = (y & 0x3fe) >> 1;
else
y &= 0x1ff;
x -= 0x80;
y -= 0x80;
yoff = (line - y);
// Narrow mode?
if(!(reg[12] & 1)) x += 32;
xend = ((sprite[2] << 1) & 0x18) + x;
ysize = sprite[2] & 0x3;
// Render if this sprite's on this line
if(xend > -8 && x < 320 && yoff >= 0 && yoff <= (ysize<<3)+7)
{
ty = yoff & 7;
// y flipped?
if(which & 0x1000)
which += ysize - (yoff >> 3);
else
which += (yoff >> 3);
++ysize;
// x flipped?
if(which & 0x800)
{
where = dest + (xend * Bpp);
for(tx = xend; tx >= x; tx -= 8)
{
if(tx > -8 && tx < 320)
draw_tile(which, ty, where);
which += ysize;
where -= Bpp_times8;
}
} else {
where = dest + (x * Bpp);
for(tx = x; tx <= xend; tx += 8)
{
if(tx > -8 && tx < 320)
draw_tile(which, ty, where);
which += ysize;
where += Bpp_times8;
}
}
}
}
}
}
// The body for the next few functions is in an extraneous header file.
// Phil, I hope I left enough in this file for GLOBAL to hack it right. ;)
// Thanks to John Stiles for this trick :)
void md_vdp::draw_plane_back0(int line)
{
#define FRONT 0
#define PLANE 0
#include "ras-drawplane.h"
#undef PLANE
#undef FRONT
}
void md_vdp::draw_plane_back1(int line)
{
#define FRONT 0
#define PLANE 1
#include "ras-drawplane.h"
#undef PLANE
#undef FRONT
}
void md_vdp::draw_plane_front0(int line)
{
#define FRONT 1
#define PLANE 0
#include "ras-drawplane.h"
#undef PLANE
#undef FRONT
}
void md_vdp::draw_plane_front1(int line)
{
#define FRONT 1
#define PLANE 1
#include "ras-drawplane.h"
#undef PLANE
#undef FRONT
}
// The main interface function, to generate a scanline
void md_vdp::draw_scanline(struct bmap *bits, int line)
{
unsigned *ptr, i;
// Set the destination in the bmap
dest = bits->data + (bits->pitch * (line + 8) + 16);
// If bytes per pixel hasn't yet been set, do it
if(!Bpp)
{
if(bits->bpp <= 8) Bpp = 1;
else if(bits->bpp <= 16) Bpp = 2;
else if(bits->bpp <= 24) Bpp = 3;
else Bpp = 4;
Bpp_times8 = Bpp << 3; // used for tile blitting
#ifdef ASM_TILES
_asm_tiles_init(vram, reg, highpal); // pass these values to the asm tiles
#endif
}
// If the palette's been changed, update it
if(dirt[0x34] & 2)
{
ptr = highpal;
// What color depth are we?
switch(bits->bpp)
{
case 32:
case 24:
for(i = 0; i < 128; i += 2)
*ptr++ = ((cram[i+1]&0x0e) << 20) |
((cram[i+1]&0xe0) << 8 ) |
((cram[i] &0x0e) << 4 );
break;
case 16:
for(i = 0; i < 128; i += 2)
*ptr++ = ((cram[i+1]&0x0e) << 12) |
((cram[i+1]&0xe0) << 3 ) |
((cram[i] &0x0e) << 1 );
break;
case 15:
for(i = 0; i < 128; i += 2)
*ptr++ = ((cram[i+1]&0x0e) << 11) |
((cram[i+1]&0xe0) << 2 ) |
((cram[i] &0x0e) << 1 );
break;
case 8:
default:
// Let the hardware palette sort it out :P
for(i = 0; i < 64; ++i) *ptr++ = i;
}
// Clean up the dirt
dirt[0x34] &= ~2;
pal_dirty = 1;
}
// Render the screen if it's turned on
if(reg[1] & 0x40)
{
// Recalculate the sprite order, if it's dirty
if((dirt[0x30] & 0x20) || (dirt[0x34] & 1))
{
unsigned next = 0;
// Find the sprite base in VRAM
sprite_base = vram + (reg[5]<<9);
// Order the sprites
sprite_count = sprite_order[0] = 0;
do {
next = sprite_base[(next << 3) + 3];
sprite_order[++sprite_count] = next;
// No more than 256 sprites/line, a reasonable limit ;)
} while (next && sprite_count < 0x100);
// Clean up the dirt
dirt[0x30] &= ~32; dirt[0x34] &= ~1;
}
// Draw, from the bottom up
// Low priority
draw_plane_back1(line);
draw_plane_back0(line);
draw_window(line, 0);
draw_sprites(line, 0);
// High priority
draw_plane_front1(line);
draw_plane_front0(line);
draw_window(line, 1);
draw_sprites(line, 1);
} else {
// The display is off, paint it black
// Do it a dword at a time
unsigned *destl = (unsigned*)dest;
for(i = 0; i < (80 * Bpp); ++i) destl[i] = 0;
}
// If we're in narrow (256) mode, cut off the messy edges
if(!(reg[12] & 1))
{
unsigned *destl = (unsigned*)dest;
for(i = 0; i < Bpp_times8; ++i)
destl[i] = destl[i + (72 * Bpp)] = 0;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?