2010-08-09 13:31:09 +00:00
|
|
|
#ifdef PPU_CPP
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//bsnes mode7 renderer
|
|
|
|
//
|
|
|
|
//base algorithm written by anomie
|
|
|
|
//bsnes implementation written by byuu
|
|
|
|
//
|
|
|
|
//supports mode 7 + extbg + rotate + zoom + direct color + scrolling + m7sel + windowing + mosaic
|
|
|
|
//interlace and pseudo-hires support are automatic via main rendering routine
|
|
|
|
|
|
|
|
//13-bit sign extend
|
|
|
|
//--s---vvvvvvvvvv -> ssssssvvvvvvvvvv
|
|
|
|
#define CLIP(x) ( ((x) & 0x2000) ? ( (x) | ~0x03ff) : ((x) & 0x03ff) )
|
|
|
|
|
|
|
|
template<unsigned bg>
|
2010-08-09 13:31:09 +00:00
|
|
|
void PPU::render_line_mode7(uint8 pri0_pos, uint8 pri1_pos) {
|
2010-09-06 11:13:51 +00:00
|
|
|
if(layer_enabled[bg][0] == false) pri0_pos = 0;
|
|
|
|
if(layer_enabled[bg][1] == false) pri1_pos = 0;
|
|
|
|
if(pri0_pos + pri1_pos == 0) return;
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return;
|
|
|
|
|
|
|
|
int32 px, py;
|
|
|
|
int32 tx, ty, tile, palette;
|
|
|
|
|
|
|
|
int32 a = sclip<16>(cache.m7a);
|
|
|
|
int32 b = sclip<16>(cache.m7b);
|
|
|
|
int32 c = sclip<16>(cache.m7c);
|
|
|
|
int32 d = sclip<16>(cache.m7d);
|
|
|
|
|
|
|
|
int32 cx = sclip<13>(cache.m7x);
|
|
|
|
int32 cy = sclip<13>(cache.m7y);
|
|
|
|
int32 hofs = sclip<13>(cache.m7_hofs);
|
|
|
|
int32 vofs = sclip<13>(cache.m7_vofs);
|
|
|
|
|
|
|
|
int _pri, _x;
|
|
|
|
bool _bg_enabled = regs.bg_enabled[bg];
|
|
|
|
bool _bgsub_enabled = regs.bgsub_enabled[bg];
|
|
|
|
|
|
|
|
build_window_tables(bg);
|
2013-05-05 09:21:30 +00:00
|
|
|
uint8* wt_main = window[bg].main;
|
|
|
|
uint8* wt_sub = window[bg].sub;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
int32 y = (regs.mode7_vflip == false ? line : 255 - line);
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
uint16* mtable_x;
|
|
|
|
uint16* mtable_y;
|
2010-08-09 13:28:56 +00:00
|
|
|
if(bg == BG1) {
|
|
|
|
mtable_x = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0];
|
|
|
|
mtable_y = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0];
|
|
|
|
} else { //bg == BG2
|
|
|
|
//Mode7 EXTBG BG2 uses BG1 mosaic enable to control vertical mosaic,
|
|
|
|
//and BG2 mosaic enable to control horizontal mosaic...
|
|
|
|
mtable_x = (uint16*)mosaic_table[(regs.mosaic_enabled[BG2] == true) ? regs.mosaic_size : 0];
|
|
|
|
mtable_y = (uint16*)mosaic_table[(regs.mosaic_enabled[BG1] == true) ? regs.mosaic_size : 0];
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 psx = ((a * CLIP(hofs - cx)) & ~63) + ((b * CLIP(vofs - cy)) & ~63) + ((b * mtable_y[y]) & ~63) + (cx << 8);
|
|
|
|
int32 psy = ((c * CLIP(hofs - cx)) & ~63) + ((d * CLIP(vofs - cy)) & ~63) + ((d * mtable_y[y]) & ~63) + (cy << 8);
|
|
|
|
for(int32 x = 0; x < 256; x++) {
|
|
|
|
px = psx + (a * mtable_x[x]);
|
|
|
|
py = psy + (c * mtable_x[x]);
|
|
|
|
|
|
|
|
//mask floating-point bits (low 8 bits)
|
|
|
|
px >>= 8;
|
|
|
|
py >>= 8;
|
|
|
|
|
|
|
|
switch(regs.mode7_repeat) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0: //screen repetition outside of screen area
|
|
|
|
case 1: { //same as case 0
|
|
|
|
px &= 1023;
|
|
|
|
py &= 1023;
|
|
|
|
tx = ((px >> 3) & 127);
|
|
|
|
ty = ((py >> 3) & 127);
|
|
|
|
tile = vram[(ty * 128 + tx) << 1];
|
|
|
|
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
|
|
|
} break;
|
|
|
|
case 2: { //palette color 0 outside of screen area
|
|
|
|
if((px | py) & ~1023) {
|
|
|
|
palette = 0;
|
|
|
|
} else {
|
2010-08-09 13:28:56 +00:00
|
|
|
px &= 1023;
|
|
|
|
py &= 1023;
|
|
|
|
tx = ((px >> 3) & 127);
|
|
|
|
ty = ((py >> 3) & 127);
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
tile = vram[(ty * 128 + tx) << 1];
|
|
|
|
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
2013-05-05 09:21:30 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case 3: { //character 0 repetition outside of screen area
|
|
|
|
if((px | py) & ~1023) {
|
|
|
|
tile = 0;
|
|
|
|
} else {
|
|
|
|
px &= 1023;
|
|
|
|
py &= 1023;
|
|
|
|
tx = ((px >> 3) & 127);
|
|
|
|
ty = ((py >> 3) & 127);
|
|
|
|
tile = vram[(ty * 128 + tx) << 1];
|
|
|
|
}
|
|
|
|
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
|
|
|
|
} break;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(bg == BG1) {
|
|
|
|
_pri = pri0_pos;
|
|
|
|
} else {
|
|
|
|
_pri = (palette >> 7) ? pri1_pos : pri0_pos;
|
|
|
|
palette &= 0x7f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!palette) continue;
|
|
|
|
|
|
|
|
_x = (regs.mode7_hflip == false) ? (x) : (255 - x);
|
|
|
|
|
|
|
|
uint32 col;
|
|
|
|
if(regs.direct_color == true && bg == BG1) {
|
|
|
|
//direct color mode does not apply to bg2, as it is only 128 colors...
|
|
|
|
col = get_direct_color(0, palette);
|
|
|
|
} else {
|
|
|
|
col = get_palette(palette);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(regs.bg_enabled[bg] == true && !wt_main[_x]) {
|
|
|
|
if(pixel_cache[_x].pri_main < _pri) {
|
|
|
|
pixel_cache[_x].pri_main = _pri;
|
|
|
|
pixel_cache[_x].bg_main = bg;
|
|
|
|
pixel_cache[_x].src_main = col;
|
|
|
|
pixel_cache[_x].ce_main = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(regs.bgsub_enabled[bg] == true && !wt_sub[_x]) {
|
|
|
|
if(pixel_cache[_x].pri_sub < _pri) {
|
|
|
|
pixel_cache[_x].pri_sub = _pri;
|
|
|
|
pixel_cache[_x].bg_sub = bg;
|
|
|
|
pixel_cache[_x].src_sub = col;
|
|
|
|
pixel_cache[_x].ce_sub = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef CLIP
|
|
|
|
|
|
|
|
#endif
|