mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v013r02 release.
[No changelog available]
This commit is contained in:
parent
c6c5f4669c
commit
f288280ceb
|
@ -28,29 +28,18 @@ void bCPU::run() {
|
|||
return;
|
||||
}
|
||||
|
||||
if(run_state.irq) {
|
||||
irq_run();
|
||||
return;
|
||||
}
|
||||
|
||||
if(run_state.stp) {
|
||||
exec_cycle();
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.cycle_pos == 0) {
|
||||
//interrupts only trigger on opcode edges
|
||||
if(time.nmi_pending == true) {
|
||||
time.nmi_pending = false;
|
||||
aa.w = 0xffea;
|
||||
run_state.irq = true;
|
||||
return;
|
||||
}
|
||||
if(time.irq_pending == true) {
|
||||
time.irq_pending = false;
|
||||
aa.w = 0xffee;
|
||||
run_state.irq = true;
|
||||
return;
|
||||
if(!run_state.irq && !run_state.stp) {
|
||||
if(time.nmi_pending == true) {
|
||||
time.nmi_pending = false;
|
||||
aa.w = 0xffea;
|
||||
run_state.irq = true;
|
||||
} else if(time.irq_pending == true) {
|
||||
time.irq_pending = false;
|
||||
aa.w = 0xffee;
|
||||
run_state.irq = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,12 @@ static int z;
|
|||
}
|
||||
|
||||
void bCPU::exec_cycle() {
|
||||
//irq active? run one bus cycle of the irq event and return
|
||||
if(run_state.irq) {
|
||||
irq_run();
|
||||
return;
|
||||
}
|
||||
|
||||
//on first cycle?
|
||||
if(status.cycle_pos == 0) {
|
||||
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define BSNES_VERSION "0.013"
|
||||
#define BSNES_VERSION "0.013 wip2"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#include "reader/reader.h"
|
||||
|
|
|
@ -5,18 +5,19 @@
|
|||
void bPPU::run() {}
|
||||
|
||||
void bPPU::scanline() {
|
||||
_y = cpu->vcounter();
|
||||
_screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6) ? 512 : 256;
|
||||
_interlace = cpu->interlace();
|
||||
_interlace_field = cpu->interlace_field();
|
||||
line.y = cpu->vcounter();
|
||||
line.width = (regs.bg_mode == 5 || regs.bg_mode == 6) ? 512 : 256;
|
||||
line.hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
|
||||
line.interlace = cpu->interlace();
|
||||
line.interlace_field = cpu->interlace_field();
|
||||
|
||||
if(_y == 0) {
|
||||
if(line.y == 0) {
|
||||
//RTO flag reset
|
||||
regs.time_over = false;
|
||||
regs.range_over = false;
|
||||
}
|
||||
|
||||
if(_y == 1) {
|
||||
if(line.y == 1) {
|
||||
//OAM FirstSprite priority set
|
||||
if(regs.oam_priority == true) {
|
||||
regs.oam_firstsprite = (regs.oam_addr & 0xfe) >> 1;
|
||||
|
@ -25,7 +26,7 @@ void bPPU::scanline() {
|
|||
}
|
||||
}
|
||||
|
||||
if(_y == (cpu->overscan() ? 239 : 224) && regs.display_disabled == false) {
|
||||
if(line.y == (cpu->overscan() ? 239 : 224) && regs.display_disabled == false) {
|
||||
//OAM address reset
|
||||
regs.oam_addr = ((regs.oam_addrh << 8) | regs.oam_addrl) << 1;
|
||||
}
|
||||
|
@ -34,7 +35,7 @@ void bPPU::scanline() {
|
|||
void bPPU::render_scanline() {
|
||||
if(status.render_output == false)return;
|
||||
|
||||
if(_y > 0 && _y < (cpu->overscan() ? 239 : 224)) {
|
||||
if(line.y > 0 && line.y < (cpu->overscan() ? 239 : 224)) {
|
||||
render_line();
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +253,7 @@ void bPPU::reset() {
|
|||
regs.time_over = false;
|
||||
regs.range_over = false;
|
||||
|
||||
_screen_width = 256; //needed for clear_window_cache()
|
||||
line.width = 256; //needed for clear_window_cache()
|
||||
update_sprite_list_sizes();
|
||||
clear_tiledata_cache();
|
||||
clear_window_cache();
|
||||
|
|
|
@ -15,7 +15,15 @@ uint8 region;
|
|||
|
||||
enum { NTSC = 0, PAL = 1 };
|
||||
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
|
||||
enum { SC_32x32 = 0, SC_32x64 = 1, SC_64x32 = 2, SC_64x64 = 3 };
|
||||
enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
|
||||
|
||||
struct {
|
||||
uint32 y;
|
||||
uint32 width;
|
||||
bool hires;
|
||||
bool interlace;
|
||||
bool interlace_field;
|
||||
} line;
|
||||
|
||||
struct sprite_item {
|
||||
uint8 width, height;
|
||||
|
|
|
@ -127,6 +127,7 @@ void bPPU::render_line() {
|
|||
|
||||
clear_pixel_cache();
|
||||
build_window_tables(COL);
|
||||
update_bg_info();
|
||||
|
||||
switch(regs.bg_mode) {
|
||||
case 0:render_line_mode0();break;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
//bppu_render.cpp
|
||||
int _screen_width;
|
||||
bool _interlace;
|
||||
int _interlace_field;
|
||||
|
||||
inline void render_line_mode0();
|
||||
inline void render_line_mode1();
|
||||
inline void render_line_mode2();
|
||||
|
@ -49,6 +45,13 @@ void build_window_tables(uint8 bg);
|
|||
inline void clear_window_cache();
|
||||
|
||||
//bppu_render_bg.cpp
|
||||
struct {
|
||||
uint16 tw, th; //tile width, height
|
||||
uint16 mx, my; //screen mask x, y
|
||||
} bg_info[4];
|
||||
|
||||
inline void update_bg_info();
|
||||
inline uint16 bg_get_tile(uint8 bg, uint16 x, uint16 y);
|
||||
void render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos);
|
||||
|
||||
//bppu_render_oam.cpp
|
||||
|
|
|
@ -1,263 +1,189 @@
|
|||
//called once at the start of every rendered scanline
|
||||
void bPPU::update_bg_info() {
|
||||
for(int bg=0;bg<4;bg++) {
|
||||
bg_info[bg].th = (regs.bg_tilesize[bg]) ? 4 : 3;
|
||||
bg_info[bg].tw = (line.hires) ? 4 : bg_info[bg].th;
|
||||
bg_info[bg].mx = (bg_info[bg].th == 4) ? (line.width << 1) : line.width;
|
||||
bg_info[bg].my = bg_info[bg].mx;
|
||||
if(regs.bg_scsize[bg] & 0x01)bg_info[bg].mx <<= 1;
|
||||
if(regs.bg_scsize[bg] & 0x02)bg_info[bg].my <<= 1;
|
||||
bg_info[bg].mx--;
|
||||
bg_info[bg].my--;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) {
|
||||
uint16 map_index, pos;
|
||||
x &= bg_info[bg].mx;
|
||||
y &= bg_info[bg].my;
|
||||
|
||||
//32 = SC width, height; tilemap data is stored as uint16
|
||||
//width(32) * height(32) * sizeof(uint16) = 2048
|
||||
switch(regs.bg_scsize[bg]) {
|
||||
case SC_32x32:map_index = 0; break;
|
||||
case SC_64x32:map_index = ((x >> bg_info[bg].th) / 32) * 2048; break;
|
||||
case SC_32x64:map_index = ((y >> bg_info[bg].th) / 32) * 2048; break;
|
||||
case SC_64x64:map_index = ((x >> bg_info[bg].th) / 32) * 2048 +
|
||||
((y >> bg_info[bg].th) / 32) * 4096; break;
|
||||
}
|
||||
|
||||
pos = ((((y >> bg_info[bg].th) & 31) * 32) + ((x >> bg_info[bg].tw) & 31)) << 1;
|
||||
return read16(vram, regs.bg_scaddr[bg] + map_index + pos);
|
||||
}
|
||||
|
||||
void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos) {
|
||||
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x;
|
||||
int _scaddr = regs.bg_scaddr[bg];
|
||||
int _tdaddr = regs.bg_tdaddr[bg];
|
||||
bool _bg_enabled = regs.bg_enabled[bg];
|
||||
bool _bgsub_enabled = regs.bgsub_enabled[bg];
|
||||
bool bg_enabled = regs.bg_enabled[bg];
|
||||
bool bgsub_enabled = regs.bgsub_enabled[bg];
|
||||
|
||||
uint16 opt_valid_bit; //offset-per-tile valid flag bit
|
||||
if(bg == BG1) {
|
||||
opt_valid_bit = 0x2000;
|
||||
} else if(bg == BG2) {
|
||||
opt_valid_bit = 0x4000;
|
||||
} else {
|
||||
opt_valid_bit = 0x0000;
|
||||
uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : ((bg == BG2) ? 0x4000 : 0x0000);
|
||||
uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0;
|
||||
|
||||
uint8 pal_size = (color_depth == 2) ? 256 : ((color_depth == 1) ? 16 : 4);
|
||||
//4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile
|
||||
//index is a tile number count to add to base tile number
|
||||
uint tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth);
|
||||
|
||||
uint8 *bg_td = (uint8*)bg_tiledata[color_depth];
|
||||
uint8 *bg_td_state = (uint8*)bg_tiledata_state[color_depth];
|
||||
|
||||
uint8 tile_width = bg_info[bg].tw;
|
||||
uint8 tile_height = bg_info[bg].th;
|
||||
uint16 mask_x = bg_info[bg].mx; //screen width mask
|
||||
uint16 mask_y = bg_info[bg].my; //screen height mask
|
||||
|
||||
uint x = 0;
|
||||
uint y = line.y;
|
||||
if(line.interlace && line.hires) {
|
||||
y = (y << 1) + line.interlace_field;
|
||||
}
|
||||
|
||||
//Mode 0 uses a special palette-indexing mode.
|
||||
//Since there are 8 selectable palettes per tile,
|
||||
//and there are 4 colors per palette on all four
|
||||
//BGs for Mode 0, each BG has a unique palette
|
||||
//entry point. This allows all 256 palette colors
|
||||
//to be used, instead of just the first 32.
|
||||
//entry = bg * 32, where 32 is from 8 * 4
|
||||
uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0;
|
||||
uint16 hscroll = (line.hires) ? (regs.bg_hofs[bg] << 1) : regs.bg_hofs[bg];
|
||||
uint16 vscroll = (line.interlace && line.hires) ? (regs.bg_vofs[bg] << 1) : regs.bg_vofs[bg];
|
||||
hscroll &= mask_x;
|
||||
vscroll &= mask_y;
|
||||
|
||||
uint8 pal_size, tiledata_size;
|
||||
switch(color_depth) {
|
||||
case COLORDEPTH_4:
|
||||
pal_size = 4;
|
||||
tiledata_size = 4; //<<4=*16
|
||||
break;
|
||||
case COLORDEPTH_16:
|
||||
pal_size = 16;
|
||||
tiledata_size = 5; //<<5=*32
|
||||
break;
|
||||
case COLORDEPTH_256:
|
||||
pal_size = 256;
|
||||
tiledata_size = 6; //<<6=*64
|
||||
break;
|
||||
}
|
||||
uint16 *mtable = (uint16*)mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0];
|
||||
uint16 mosaic_x;
|
||||
uint16 mosaic_y;
|
||||
|
||||
uint8 *bg_td, *bg_td_state;
|
||||
bg_td = (uint8*)bg_tiledata[color_depth];
|
||||
bg_td_state = (uint8*)bg_tiledata_state[color_depth];
|
||||
|
||||
uint16 screen_width, screen_height;
|
||||
screen_width = _screen_width;
|
||||
screen_height = _screen_width; //this is correct -- ppu tilemap is a perfect square
|
||||
|
||||
uint8 tile_size, tile_width, tile_height;
|
||||
tile_size = (regs.bg_tilesize[bg])?4:3; //<<4=*16, <<3=*8
|
||||
tile_width = tile_size;
|
||||
tile_height = tile_size;
|
||||
|
||||
int screen_x, screen_y;
|
||||
if(_interlace == true && _screen_width == 512) {
|
||||
screen_y = (_y << 1) + _interlace_field;
|
||||
} else {
|
||||
screen_y = _y;
|
||||
}
|
||||
|
||||
//Modes 5 and 6 seem to force 16-width tiles due to having twice the resolution.
|
||||
//The tile size attribute in $2105 has no effect on tile width.
|
||||
if(_screen_width == 512) {
|
||||
tile_width = 4; //<<4=*16
|
||||
}
|
||||
|
||||
if(tile_size == 4) { //16x16 tile size
|
||||
screen_width <<= 1;
|
||||
screen_height <<= 1;
|
||||
}
|
||||
|
||||
if(regs.bg_scsize[bg] & 0x01)screen_width <<= 1;
|
||||
if(regs.bg_scsize[bg] & 0x02)screen_height <<= 1;
|
||||
|
||||
uint16 screen_width_mask, screen_height_mask;
|
||||
screen_width_mask = screen_width - 1;
|
||||
screen_height_mask = screen_height - 1;
|
||||
|
||||
int bg_x, bg_y;
|
||||
uint16 vscroll, hscroll;
|
||||
if(_screen_width == 512) {
|
||||
hscroll = (regs.bg_hofs[bg] << 1) & screen_width_mask;
|
||||
} else {
|
||||
hscroll = regs.bg_hofs[bg] & screen_width_mask;
|
||||
}
|
||||
bg_x = hscroll;
|
||||
|
||||
if(_screen_width == 512 && _interlace == true) {
|
||||
vscroll = (regs.bg_vofs[bg] << 1) & screen_height_mask;
|
||||
} else {
|
||||
vscroll = regs.bg_vofs[bg] & screen_height_mask;
|
||||
}
|
||||
bg_y = (screen_y + vscroll) & screen_height_mask;
|
||||
|
||||
uint16 *mtable;
|
||||
int mosaic_x, mosaic_y;
|
||||
if(regs.mosaic_enabled[bg] == true) {
|
||||
mtable = (uint16*)mosaic_table[regs.mosaic_size];
|
||||
} else {
|
||||
mtable = (uint16*)mosaic_table[0];
|
||||
}
|
||||
|
||||
mosaic_x = mtable[bg_x];
|
||||
mosaic_y = mtable[bg_y];
|
||||
|
||||
uint8 tile_x;
|
||||
uint16 t, base_xpos, base_pos, pos;
|
||||
uint16 tile_num;
|
||||
int mirror_x, mirror_y;
|
||||
uint16 hval, vval;
|
||||
uint16 t, tile_pri, tile_num;
|
||||
uint8 pal_index, pal_num;
|
||||
uint8 *tile_ptr;
|
||||
int xpos, ypos;
|
||||
uint16 map_index, hoffset, voffset, col;
|
||||
uint xpos, ypos;
|
||||
uint16 hoffset, voffset, opt_x, col;
|
||||
bool mirror_x, mirror_y;
|
||||
bool is_opt_mode = (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6);
|
||||
|
||||
build_window_tables(bg);
|
||||
uint8 *wt_main = window_cache[bg].main;
|
||||
uint8 *wt_sub = window_cache[bg].sub;
|
||||
|
||||
screen_x = 0;
|
||||
do { //for(screen_x=0;screen_x<_screen_width;screen_x++) {
|
||||
if(regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6) {
|
||||
if(regs.bg_mode == 6) {
|
||||
//hires adjust
|
||||
tile_x = (mtable[screen_x + (hscroll & 15)] >> 4);
|
||||
} else {
|
||||
tile_x = (mtable[screen_x + (hscroll & 7)] >> 3);
|
||||
}
|
||||
int32 prev_x = -1, prev_y = -1;
|
||||
for(x=0;x<line.width;x++) {
|
||||
hoffset = x + hscroll;
|
||||
voffset = y + vscroll;
|
||||
|
||||
hoffset = hscroll;
|
||||
voffset = vscroll;
|
||||
if(is_opt_mode) {
|
||||
opt_x = (x + (hscroll & 7));
|
||||
|
||||
//tile 0 is unaffected by OPT mode...
|
||||
if(tile_x != 0) {
|
||||
//multiply by two to index into 16-bit table entries
|
||||
tile_x = ((tile_x - 1) & 31) << 1;
|
||||
if(opt_x >= 8) {
|
||||
hval = bg_get_tile(BG3,
|
||||
(opt_x - 8) + (regs.bg_hofs[BG3] & ~7),
|
||||
regs.bg_vofs[BG3]);
|
||||
|
||||
vval = bg_get_tile(BG3,
|
||||
(opt_x - 8) + (regs.bg_hofs[BG3] & ~7),
|
||||
regs.bg_vofs[BG3] + 8);
|
||||
|
||||
if(regs.bg_mode == 4) {
|
||||
pos = regs.bg_scaddr[BG3] + tile_x;
|
||||
t = read16(vram, pos);
|
||||
if(t & opt_valid_bit) {
|
||||
if(!(t & 0x8000)) {
|
||||
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
|
||||
if(hval & opt_valid_bit) {
|
||||
if(!(hval & 0x8000)) {
|
||||
hoffset = opt_x + (hval & ~7);
|
||||
} else {
|
||||
voffset = (t & 0x1fff) & screen_height_mask;
|
||||
voffset = y + hval;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pos = regs.bg_scaddr[BG3] + tile_x;
|
||||
t = read16(vram, pos);
|
||||
if(t & opt_valid_bit) {
|
||||
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
|
||||
if(hval & opt_valid_bit) {
|
||||
hoffset = opt_x + (hval & ~7);
|
||||
}
|
||||
pos = regs.bg_scaddr[BG3] + 64 + tile_x;
|
||||
t = read16(vram, pos);
|
||||
if(t & opt_valid_bit) {
|
||||
voffset = (t & 0x1fff) & screen_height_mask;
|
||||
if(vval & opt_valid_bit) {
|
||||
voffset = y + vval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mosaic_x = mtable[(screen_x + hoffset) & screen_width_mask ];
|
||||
mosaic_y = mtable[(screen_y + voffset) & screen_height_mask];
|
||||
}
|
||||
|
||||
switch(regs.bg_scsize[bg]) {
|
||||
case 0:
|
||||
map_index = 0;
|
||||
break;
|
||||
case 1:
|
||||
map_index = ((mosaic_x >> tile_size) >> 5) << 11;
|
||||
break;
|
||||
case 2:
|
||||
map_index = ((mosaic_y >> tile_size) >> 5) << 11;
|
||||
break;
|
||||
case 3:
|
||||
map_index = ((mosaic_x >> tile_size) >> 5) << 11 |
|
||||
((mosaic_y >> tile_size) >> 5) << 12;
|
||||
break;
|
||||
}
|
||||
mosaic_x = mtable[hoffset & mask_x];
|
||||
mosaic_y = mtable[voffset & mask_y];
|
||||
|
||||
base_xpos = ((mosaic_x >> 3) & 31);
|
||||
base_pos = (((mosaic_y >> tile_height) & 31) << 5) + ((mosaic_x >> tile_width) & 31);
|
||||
pos = _scaddr + map_index + (base_pos << 1);
|
||||
t = read16(vram, pos);
|
||||
mirror_y = !!(t & 0x8000);
|
||||
mirror_x = !!(t & 0x4000);
|
||||
if((mosaic_x >> 3) != prev_x || (mosaic_y >> 3) != prev_y) {
|
||||
prev_x = (mosaic_x >> 3);
|
||||
prev_y = (mosaic_y >> 3);
|
||||
|
||||
int _pri;
|
||||
_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
|
||||
t = bg_get_tile(bg, mosaic_x, mosaic_y);
|
||||
|
||||
tile_num = t & 0x03ff;
|
||||
mirror_y = !!(t & 0x8000);
|
||||
mirror_x = !!(t & 0x4000);
|
||||
|
||||
//16x16 horizontal tile mirroring
|
||||
if(tile_width == 4) {
|
||||
if(((mosaic_x & 15) >= 8 && !mirror_x) ||
|
||||
((mosaic_x & 15) < 8 && mirror_x))tile_num++;
|
||||
tile_num &= 0x03ff;
|
||||
}
|
||||
tile_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
|
||||
tile_num = t;
|
||||
|
||||
//16x16 vertical tile mirroring
|
||||
if(tile_height == 4) {
|
||||
if(((mosaic_y & 15) >= 8 && !mirror_y) ||
|
||||
((mosaic_y & 15) < 8 && mirror_y))tile_num += 16;
|
||||
tile_num &= 0x03ff;
|
||||
}
|
||||
|
||||
tile_num += (_tdaddr >> tiledata_size);
|
||||
|
||||
if(bg_td_state[tile_num] == 1) {
|
||||
render_bg_tile(color_depth, tile_num);
|
||||
}
|
||||
|
||||
pal_num = ((t >> 10) & 7);
|
||||
pal_index = pal_num * pal_size + bgpal_index;
|
||||
|
||||
if(mirror_y) { ypos = (7 - (mosaic_y & 7)); }
|
||||
else { ypos = ( (mosaic_y & 7)); }
|
||||
|
||||
//loop while we are rendering from the same tile, as there's no need to do all of the above work
|
||||
//unless we have rendered all of the visible tile, taking mosaic into account.
|
||||
tile_ptr = (uint8*)bg_td + (tile_num << 6) + (ypos << 3);
|
||||
do {
|
||||
if(mirror_x) { xpos = (7 - (mosaic_x & 7)); }
|
||||
else { xpos = ( (mosaic_x & 7)); }
|
||||
col = *(tile_ptr + xpos);
|
||||
if(col && window_cache[COL].main[screen_x]) {
|
||||
if(regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)) {
|
||||
col = get_direct_color(pal_num, col);
|
||||
} else {
|
||||
col = get_palette(col + pal_index);
|
||||
}
|
||||
|
||||
if(_bg_enabled == true && !wt_main[screen_x]) {
|
||||
if(pixel_cache[screen_x].pri_main < _pri) {
|
||||
pixel_cache[screen_x].pri_main = _pri;
|
||||
pixel_cache[screen_x].bg_main = 0x80 | bg;
|
||||
pixel_cache[screen_x].src_main = col;
|
||||
pixel_cache[screen_x].color_exempt = false;
|
||||
}
|
||||
}
|
||||
if(_bgsub_enabled == true && !wt_sub[screen_x]) {
|
||||
if(pixel_cache[screen_x].pri_sub < _pri) {
|
||||
pixel_cache[screen_x].pri_sub = _pri;
|
||||
pixel_cache[screen_x].bg_sub = 0x80 | bg;
|
||||
pixel_cache[screen_x].src_sub = col;
|
||||
}
|
||||
}
|
||||
if(tile_width == 4) { //16x16 horizontal tile mirroring
|
||||
if(!!(mosaic_x & 8) != mirror_x)tile_num++;
|
||||
}
|
||||
|
||||
bg_x++;
|
||||
bg_x &= screen_width_mask;
|
||||
mosaic_x = mtable[bg_x];
|
||||
if(tile_height == 4) { //16x16 vertical tile mirroring
|
||||
if(!!(mosaic_y & 8) != mirror_y)tile_num += 16;
|
||||
}
|
||||
|
||||
if(base_xpos != ((mosaic_x >> 3) & 31))break;
|
||||
if(++screen_x >= _screen_width)break;
|
||||
} while(1);
|
||||
} while(++screen_x < _screen_width);
|
||||
tile_num &= 0x03ff;
|
||||
tile_num += tiledata_index;
|
||||
|
||||
if(bg_td_state[tile_num] == 1) {
|
||||
render_bg_tile(color_depth, tile_num);
|
||||
}
|
||||
|
||||
pal_num = ((t >> 10) & 7);
|
||||
pal_index = (pal_num * pal_size) + bgpal_index;
|
||||
|
||||
ypos = mosaic_y & 7;
|
||||
if(mirror_y)ypos ^= 7; //invert y tile pos
|
||||
|
||||
tile_ptr = (uint8*)bg_td + (tile_num * 64) + (ypos * 8);
|
||||
}
|
||||
|
||||
xpos = mosaic_x & 7;
|
||||
if(mirror_x)xpos ^= 7; //invert x tile pos
|
||||
col = *(tile_ptr + xpos);
|
||||
if(col && window_cache[COL].main[x]) {
|
||||
if(regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)) {
|
||||
col = get_direct_color(pal_num, col);
|
||||
} else {
|
||||
col = get_palette(col + pal_index);
|
||||
}
|
||||
|
||||
if(bg_enabled == true && !wt_main[x]) {
|
||||
if(pixel_cache[x].pri_main < tile_pri) {
|
||||
pixel_cache[x].pri_main = tile_pri;
|
||||
pixel_cache[x].bg_main = 0x80 | bg;
|
||||
pixel_cache[x].src_main = col;
|
||||
pixel_cache[x].color_exempt = false;
|
||||
}
|
||||
}
|
||||
if(bgsub_enabled == true && !wt_sub[x]) {
|
||||
if(pixel_cache[x].pri_sub < tile_pri) {
|
||||
pixel_cache[x].pri_sub = tile_pri;
|
||||
pixel_cache[x].bg_sub = 0x80 | bg;
|
||||
pixel_cache[x].src_sub = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
if(d0 & __m)col += 1; \
|
||||
if(d1 & __m)col += 2; \
|
||||
*dest++ = col
|
||||
|
||||
#define render_bg_tile_line_16(__m) \
|
||||
col = 0; \
|
||||
if(d0 & __m)col += 1; \
|
||||
|
@ -10,6 +11,7 @@
|
|||
if(d2 & __m)col += 4; \
|
||||
if(d3 & __m)col += 8; \
|
||||
*dest++ = col
|
||||
|
||||
#define render_bg_tile_line_256(__m) \
|
||||
col = 0; \
|
||||
if(d0 & __m)col += 1; \
|
||||
|
@ -96,6 +98,10 @@ uint8 *dest;
|
|||
}
|
||||
}
|
||||
|
||||
#undef render_bg_tile_line_4
|
||||
#undef render_bg_tile_line_16
|
||||
#undef render_bg_tile_line_256
|
||||
|
||||
inline void bPPU::clear_pixel_cache() {
|
||||
memset(pixel_cache, 0, sizeof(pixel_cache));
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ uint16 *ptr;
|
|||
uint16 *ltable;
|
||||
ltable = (uint16*)light_table + (regs.display_brightness << 15);
|
||||
|
||||
if(_screen_width == 256) {
|
||||
if(line.width == 256) {
|
||||
for(x=0;x<256;x++) {
|
||||
_r = get_pixel(x);
|
||||
*ptr++ = *(ltable + _r);
|
||||
|
|
|
@ -43,9 +43,9 @@ uint8 *wt_main = window_cache[bg].main;
|
|||
uint8 *wt_sub = window_cache[bg].sub;
|
||||
|
||||
if(regs.mode7_vflip == true) {
|
||||
y = 255 - _y;
|
||||
y = 255 - line.y;
|
||||
} else {
|
||||
y = _y;
|
||||
y = line.y;
|
||||
}
|
||||
|
||||
uint16 *mtable_x, *mtable_y;
|
||||
|
|
|
@ -90,18 +90,18 @@ uint16 addr = 0x0200;
|
|||
bool bPPU::is_sprite_on_scanline() {
|
||||
//if sprite is entirely offscreen and doesn't wrap around to the left side of the screen,
|
||||
//then it is not counted. 256 is correct, and not 255 -- as one might first expect
|
||||
if(spr->x > 256 && (spr->x + spr->width) < 512 && _screen_width != 512)return false;
|
||||
if(spr->x > 256 && (spr->x + spr->width) < 512 && line.width != 512)return false;
|
||||
|
||||
if(regs.oam_halve == false) {
|
||||
if(_y >= spr->y && _y < (spr->y + spr->height)) {
|
||||
if(line.y >= spr->y && line.y < (spr->y + spr->height)) {
|
||||
return true;
|
||||
} else if((spr->y + spr->height) >= 256 && _y < ((spr->y + spr->height) & 255)) {
|
||||
} else if((spr->y + spr->height) >= 256 && line.y < ((spr->y + spr->height) & 255)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if(_y >= spr->y && _y < (spr->y + (spr->height >> 1))) {
|
||||
if(line.y >= spr->y && line.y < (spr->y + (spr->height >> 1))) {
|
||||
return true;
|
||||
} else if((spr->y + (spr->height >> 1)) >= 256 && _y < ((spr->y + (spr->height >> 1)) & 255)) {
|
||||
} else if((spr->y + (spr->height >> 1)) >= 256 && line.y < ((spr->y + (spr->height >> 1)) & 255)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -115,21 +115,21 @@ uint16 tile_width;
|
|||
|
||||
int x, y, chr, nameselect_index;
|
||||
x = spr->x;
|
||||
if(_screen_width == 512)x <<= 1;
|
||||
if(line.width == 512)x <<= 1;
|
||||
x &= 511;
|
||||
|
||||
if(spr->vflip) {
|
||||
y = ((spr->height - 1) - (_y - spr->y));
|
||||
y = ((spr->height - 1) - (line.y - spr->y));
|
||||
} else {
|
||||
y = (_y - spr->y);
|
||||
y = (line.y - spr->y);
|
||||
}
|
||||
//todo: double-check code below. seems that interlace_field
|
||||
//should be added to hires 512x448 sprites as well, and not
|
||||
//just when oam_halve is enabled...
|
||||
if(regs.oam_halve == true) {
|
||||
y <<= 1;
|
||||
if(_interlace == true && _screen_width == 512) {
|
||||
y += _interlace_field;
|
||||
if(line.interlace && line.width == 512) {
|
||||
y += line.interlace_field;
|
||||
}
|
||||
}
|
||||
y &= 255;
|
||||
|
@ -146,11 +146,11 @@ int x, y, chr, nameselect_index;
|
|||
int i, n, mx, pos, z;
|
||||
for(i=0;i<tile_width;i++) {
|
||||
z = x;
|
||||
z += (i << ((_screen_width == 512)?4:3));
|
||||
z += (i << ((line.width == 512) ? 4 : 3));
|
||||
z &= 511;
|
||||
//ignore sprites that are offscreen
|
||||
//sprites at 256 are still counted, even though they aren't visible onscreen
|
||||
if(z >= 257 && (z + 7) < 512 && _screen_width != 512)continue;
|
||||
if(z >= 257 && (z + 7) < 512 && line.width != 512)continue;
|
||||
|
||||
if(regs.oam_tilecount++ > 34)break;
|
||||
n = regs.oam_tilecount - 1;
|
||||
|
@ -186,19 +186,19 @@ int x, sx, col;
|
|||
tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3);
|
||||
for(x=0;x<8;x++) {
|
||||
sx &= 511;
|
||||
if(sx < _screen_width) {
|
||||
if(sx < line.width) {
|
||||
col = *(tile_ptr + ((t->hflip)?7-x:x));
|
||||
if(col) {
|
||||
col += t->pal;
|
||||
oam_line_pal[sx] = col;
|
||||
oam_line_pri[sx] = t->pri;
|
||||
if(_screen_width == 512) {
|
||||
if(line.width == 512) {
|
||||
oam_line_pal[sx + 1] = col;
|
||||
oam_line_pri[sx + 1] = t->pri;
|
||||
}
|
||||
}
|
||||
}
|
||||
sx += (_screen_width == 512)?2:1;
|
||||
sx += (line.width == 512) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,7 @@ uint8 *wt_sub = window_cache[OAM].sub;
|
|||
if(_bg_enabled == false && _bgsub_enabled == false)return;
|
||||
|
||||
int _pri;
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
if(oam_line_pri[x] == OAM_PRI_NONE)continue;
|
||||
|
||||
switch(oam_line_pri[x]) {
|
||||
|
|
|
@ -9,11 +9,11 @@ uint8 *wtbl;
|
|||
|
||||
if(bg != COL) {
|
||||
if(mainscreen == true && regs.window_enabled[bg] == false) {
|
||||
memset(wtbl, 0, _screen_width);
|
||||
memset(wtbl, 0, line.width);
|
||||
return;
|
||||
}
|
||||
if(mainscreen == false && regs.sub_window_enabled[bg] == false) {
|
||||
memset(wtbl, 0, _screen_width);
|
||||
memset(wtbl, 0, line.width);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -26,13 +26,13 @@ uint8 *wtbl;
|
|||
|
||||
if(mask == 0) {
|
||||
//always
|
||||
memset(wtbl, 1, _screen_width);
|
||||
memset(wtbl, 1, line.width);
|
||||
return;
|
||||
}
|
||||
|
||||
if(mask == 3) {
|
||||
//never
|
||||
memset(wtbl, 0, _screen_width);
|
||||
memset(wtbl, 0, line.width);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ bool r;
|
|||
window2_left = regs.window2_left;
|
||||
window2_right = regs.window2_right;
|
||||
|
||||
if(_screen_width == 512) {
|
||||
if(line.width == 512) {
|
||||
window1_left <<= 1;
|
||||
window1_right <<= 1;
|
||||
window2_left <<= 1;
|
||||
|
@ -64,29 +64,29 @@ bool r;
|
|||
}
|
||||
|
||||
if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == false) {
|
||||
memset(wtbl, clr, _screen_width);
|
||||
memset(wtbl, clr, line.width);
|
||||
} else if(regs.window1_enabled[bg] == true && regs.window2_enabled[bg] == false) {
|
||||
if(regs.window1_invert[bg] == false) {
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
wtbl[x] = (x >= window1_left && x <= window1_right) ? set : clr;
|
||||
}
|
||||
} else {
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
wtbl[x] = (x < window1_left || x > window1_right) ? set : clr;
|
||||
}
|
||||
}
|
||||
} else if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == true) {
|
||||
if(regs.window2_invert[bg] == false) {
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
wtbl[x] = (x >= window2_left && x <= window2_right) ? set : clr;
|
||||
}
|
||||
} else {
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
wtbl[x] = (x < window2_left || x > window2_right) ? set : clr;
|
||||
}
|
||||
}
|
||||
} else { //if(regs.window1_enabled[bg] == true && regs.window2_enabled[bg] == true) {
|
||||
for(x=0;x<_screen_width;x++) {
|
||||
for(x=0;x<line.width;x++) {
|
||||
if(regs.window1_invert[bg] == false) {
|
||||
w1_mask = (x >= window1_left && x <= window1_right);
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,6 @@ uint8 ppu1_version;
|
|||
//* reported by $213f
|
||||
uint8 ppu2_version;
|
||||
|
||||
int _y;
|
||||
MMIO *mmio;
|
||||
|
||||
struct scanline_info {
|
||||
|
|
Loading…
Reference in New Issue