Compare commits

...
3 Commits
Author SHA1 Message Date
byuu 402c146a53 Update to bsnes v009 release.
- Fixed non-interlaced display modes from not drawing every other frame
    - Changed OAM halve to skip every other scanline in 224-height modes
    - Updated renderer to properly support games that switch resolutions mid-frame
    - Fixed VRAM address remapping modes, fixes DQ3R, FF: MQ
    - Fixed a bug in main color window clipping affecting BGs
    - Added video color curve option, thanks to Overload for the idea + color table
    - Added vblank, FPS counter, and DDraw surface memory options to settings menu
    - Added fullscreen modes 640x480 and 1024x768 to video modes
    - Added option to toggle the menubar on and off by pressing the escape key
    - Mode3 was not rendering sprites
    - Priorities were wrong for modes 2-4, thanks to anomie for info
    - Fixed a serious bug in IRQ interrupts. May not be perfect, but helps many games
2005-06-26 11:07:38 +00:00
byuu a471c150c9 Update to bsnes v008 release.
moving the window + main color window clipping into the bg/oam/mode7 rendering routines themselves, I was able to greatly simplify the most complicated part of rendering: the final pass where color add/sub effects are applied. As a result, the new PPU core is not only ~35% faster (on graphics intensive screens, even faster on simpler screens), but more accurate as well. Awesome.
In celebration, I´m releasing bsnes v0.008. I can actually run all games I have at >60fps on my Athlon 1.67ghz PC. Probably not something to brag about, though ...
Oh, and I also updated the keyboard polling code to only capture keypresses if the main window has focus. I´ve been meaning to do this for the better part of a year now, but never got around to it.
If, for some reason, you still want to use the old renderer, you can uncomment the first line in src/ppu/bppu/bppu.h and recompile the emulator yourself. Or you can use v0.007a, I´ll leave it up for a bit.
2005-06-21 09:13:40 +00:00
byuu ea38ea2537 Update to bsnes v007a release.
[No changelog available]
2005-06-13 04:34:10 +00:00
50 changed files with 2690 additions and 922 deletions

No files matched your search

+19 -4
View File
@@ -1,9 +1,11 @@
#[bsnes v0.007 configuration file]
#[bsnes v0.009 configuration file]
#[video mode]
# 0: 256x224w
# 1: 512x448w
# 2: 960x720w
# 0: 256x224w
# 1: 512x448w
# 2: 960x720w
# 3: 640x480f
# 4: 1024x768f
video.mode = 1
#[video memory type]
@@ -19,3 +21,16 @@ video.mode = 1
# way to guarantee that the output image will not be
# filtered.
video.use_vram = true
#[color curve]
# gives a more NTSC TV-style feel to the color palette
# by darkening the image contrast.
video.color_curve = enabled
#[show fps]
# true: show fps in titlebar
# false: do not show fps in titlebar
gui.show_fps = true
#[wait for vertical retrace]
video.vblank = false
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+10 -10
View File
@@ -5,9 +5,9 @@ bool changed, notify_ppu;
uint8 count, new_count, pos;
}frameskip;
bool signal_scanline, signal_frame;
void frameskip_update_status();
void inc_vcounter();
void dram_refresh_test();
inline void frameskip_update_status();
inline void inc_vcounter();
inline void dram_refresh_test();
public:
struct {
@@ -23,14 +23,14 @@ public:
uint32 pos, last_pos;
}cc2;
void set_frameskip(uint8 fs);
inline void set_frameskip(uint8 fs);
void add_cc1_cycles(uint32 cycles);
void add_cc2_cycles(uint32 cycles);
void sync();
void run();
void power();
void reset();
inline void add_cc1_cycles(uint32 cycles);
inline void add_cc2_cycles(uint32 cycles);
inline void sync();
inline void run();
inline void power();
inline void reset();
bClock();
~bClock();
+2 -1
View File
@@ -89,7 +89,7 @@ uint16 v, h, hc, vs;
//IRQ test
if(!regs.p.i) {
if(status.virq_enabled == true && status.virq_enabled == true) {
if(status.virq_enabled == true && status.hirq_enabled == true) {
if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) {
status.irq_triggered = true;
status.irq_pin = 0;
@@ -148,6 +148,7 @@ void bCPU::frame() {
status.nmi_triggered = false;
status.r4210_read = false;
status.irq_triggered = false;
status.irq_pin = 1;
dma->hdma_initialize();
+10 -10
View File
@@ -165,19 +165,19 @@ struct {
void mmio_w43x6(uint8 value, uint8 i);
void mmio_w43x7(uint8 value, uint8 i);
void exec_opcode();
inline void exec_opcode();
uint8 op_read ();
uint8 op_read (uint8 mode, uint32 addr);
void op_write(uint8 mode, uint32 addr, uint8 value);
uint8 stack_read ();
void stack_write(uint8 value);
inline uint8 op_read ();
inline uint8 op_read (uint8 mode, uint32 addr);
inline void op_write(uint8 mode, uint32 addr, uint8 value);
inline uint8 stack_read ();
inline void stack_write(uint8 value);
//cpu extra-cycle conditions
void cpu_c2();
void cpu_c4(uint16 a, uint16 b);
void cpu_c6(uint16 a);
void cpu_io();
inline void cpu_c2();
inline void cpu_c4(uint16 a, uint16 b);
inline void cpu_c6(uint16 a);
inline void cpu_io();
//opcode functions
void init_op_tables();
+4
View File
@@ -303,21 +303,25 @@ void bCPU::mmio_w4206(uint8 value) {
//HTIMEL
void bCPU::mmio_w4207(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
if(status.irq_triggered == false)status.irq_pin = 1;
}
//HTIMEH
void bCPU::mmio_w4208(uint8 value) {
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
if(status.irq_triggered == false)status.irq_pin = 1;
}
//VTIMEL
void bCPU::mmio_w4209(uint8 value) {
status.virq_pos = (status.virq_pos & 0xff00) | value;
if(status.irq_triggered == false)status.irq_pin = 1;
}
//VTIMEH
void bCPU::mmio_w420a(uint8 value) {
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
if(status.irq_triggered == false)status.irq_pin = 1;
}
//DMAEN
+6 -23
View File
@@ -113,28 +113,17 @@ uint32 b, w;
}
}
void bROM::load_sram(uint8 *buffer, uint32 size) {
void bROM::load_sram(Reader *rf) {
if(rom_loaded == false)return;
if(size > sram_size) {
memcpy(sram_data, buffer, sram_size);
} else {
memset(sram_data, 0, sram_size);
memcpy(sram_data, buffer, size);
}
rf->read(&sram_data, sram_size);
}
uint32 bROM::save_sram(uint8 **buffer) {
uint8 *t;
if(rom_loaded == false)return 0;
if(!sram_size)return 0;
void bROM::save_sram(Writer *wf) {
if(rom_loaded == false)return;
if(!sram_size)return;
if(*buffer) {
t = (uint8*)memalloc(sram_size, "bROM::save_sram");
memcpy(t, sram_data, sram_size);
*buffer = t;
}
return sram_size;
wf->write(sram_data, sram_size);
}
void bROM::load_rom(Reader *rf) {
@@ -176,12 +165,6 @@ end:
case 6:sram_size = 64 * 1024;break;
case 7:sram_size = 128 * 1024;break;
}
if(sram_size) {
sram_data = (uint8*)memalloc(sram_size, "bROM::sram_data");
memset(sram_data, 0, sram_size);
} else {
sram_data = 0;
}
dprintf("Image Name : \"%s\"", cart_title);
dprintf("Image Type : %s", (mapper == LOROM)?"LoROM":"HiROM");
+7 -7
View File
@@ -8,13 +8,13 @@ enum { LOROM = 0, HIROM = 1 };
uint8 *data, *sram_data;
uint8 mapper;
uint32 size, sram_size;
void load_rom(Reader *rf);
void load_sram(uint8 *buffer, uint32 size);
uint32 save_sram(uint8 **buffer);
void unload();
uint8 read (uint32 addr);
void write(uint32 addr, byte value);
void write_protect(bool yn);
void load_rom(Reader *rf);
void load_sram(Reader *rf);
void save_sram(Writer *wf);
void unload();
uint8 read (uint32 addr);
void write(uint32 addr, byte value);
void write_protect(bool yn);
bROM();
~bROM();
+5 -5
View File
@@ -11,11 +11,11 @@ enum { WRAP_NONE = 0, WRAP_BANK = 1, WRAP_PAGE = 2 };
class ROM : public Memory {
public:
virtual void load_rom(Reader *rf) = 0;
virtual void load_sram(uint8 *buffer, uint32 size) = 0;
virtual uint32 save_sram(uint8 **buffer) = 0;
virtual void unload() = 0;
virtual void write_protect(bool yn) = 0;
virtual void load_rom(Reader *rf) = 0;
virtual void load_sram(Reader *rf) = 0;
virtual void save_sram(Writer *wf) = 0;
virtual void unload() = 0;
virtual void write_protect(bool yn) = 0;
};
class MMIO : public Memory {
+22 -11
View File
@@ -1,29 +1,40 @@
#include "../../base.h"
#include "bppu_mmio.cpp"
#ifdef _BPPU_OLDRENDER
#include "bppu_old_render.cpp"
#else
#include "bppu_render.cpp"
#endif
void bPPU::run() {}
void bPPU::scanline() {
uint16 v = clock->vcounter();
if(v > 0 && v < clock->visible_scanlines()) {
if(clock->interlace() || regs.oam_halve == true) {
output->frame_mode |= PPUOutput::INTERLACE;
output->scanline_mode[v] |= PPUOutput::INTERLACE;
}
_y = clock->vcounter();
_screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256;
_interlace = clock->interlace();
_interlace_field = clock->interlace_field();
if(_y > 0 && _y < clock->visible_scanlines()) {
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
output->frame_mode |= PPUOutput::DOUBLEWIDTH;
output->scanline_mode[v] |= PPUOutput::DOUBLEWIDTH;
output->hires = true;
output->line[_y].hires = true;
}
render_line(v);
if(_interlace == true) {
output->interlace = true;
output->line[_y].interlace = true;
}
render_line();
}
}
void bPPU::frame() {
snes->notify(SNES::RENDER_FRAME);
output->frame_mode = PPUOutput::NORMAL;
output->hires = false;
output->interlace = false;
for(int i=0;i<239;i++) {
output->scanline_mode[i] = PPUOutput::NORMAL;
output->line[i].hires = false;
output->line[i].interlace = false;
}
}
+9 -1
View File
@@ -1,3 +1,5 @@
//#define _BPPU_OLDRENDER
class bPPU;
class bPPUMMIO : public MMIO {
@@ -194,10 +196,16 @@ struct {
void latch_counters();
/* PPU render functions */
#ifdef _BPPU_OLDRENDER
#include "bppu_old_render.h"
#else
#include "bppu_render.h"
#endif
uint16 *light_table;
uint16 *mosaic_table[16];
void render_line(uint16 line);
void render_line();
/* Required functions */
void run();
+2 -2
View File
@@ -6,14 +6,14 @@ void bPPU::latch_counters() {
uint16 bPPU::get_vram_address() {
uint16 addr;
addr = regs.vram_addr << 1;
addr = regs.vram_addr;
switch(regs.vram_mapping) {
case 0:break;
case 1:addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7);break;
case 2:addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7);break;
case 3:addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7);break;
}
return addr;
return (addr << 1);
}
//INIDISP
+133
View File
@@ -0,0 +1,133 @@
#include "bppu_old_render_cache.cpp"
#include "bppu_old_render_windows.cpp"
#include "bppu_old_render_main.cpp"
#include "bppu_old_render_mode7.cpp"
namespace bPPURenderTables {
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5 };
uint8 lookup_mode0[12] = {
BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode1_pri0[10] = {
BG3, OAM, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode1_pri1[10] = {
BG3, OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM, BG3
};
uint8 lookup_mode2[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode3[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode4[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode5[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode6[6] = {
OAM, OAM, BG1, OAM, BG1, OAM
};
uint8 lookup_mode7[5] = {
OAM, BG1, OAM, OAM, OAM
};
uint8 lookup_mode7_extbg[6] = {
BG2, OAM, OAM, BG2, OAM, OAM
};
};
void bPPU::render_line_mode0() {
render_line_bg (7, 10, COLORDEPTH_4, BG1);
render_line_bg (6, 9, COLORDEPTH_4, BG2);
render_line_bg (1, 4, COLORDEPTH_4, BG3);
render_line_bg (0, 3, COLORDEPTH_4, BG4);
render_line_oam(2, 5, 8, 11);
set_layer_pixels(12, bPPURenderTables::lookup_mode0);
}
void bPPU::render_line_mode1() {
switch(regs.bg3_priority) {
case 0:
render_line_bg (5, 8, COLORDEPTH_16, BG1);
render_line_bg (4, 7, COLORDEPTH_16, BG2);
render_line_bg (0, 2, COLORDEPTH_4, BG3);
render_line_oam(1, 3, 6, 9);
set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri0);
break;
case 1:
render_line_bg (4, 7, COLORDEPTH_16, BG1);
render_line_bg (3, 6, COLORDEPTH_16, BG2);
render_line_bg (0, 9, COLORDEPTH_4, BG3);
render_line_oam(1, 2, 5, 8);
set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri1);
break;
}
}
void bPPU::render_line_mode2() {
render_line_bg (3, 6, COLORDEPTH_16, BG1);
render_line_bg (2, 5, COLORDEPTH_16, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode2);
}
void bPPU::render_line_mode3() {
render_line_bg (3, 6, COLORDEPTH_256, BG1);
render_line_bg (2, 5, COLORDEPTH_16, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode3);
}
void bPPU::render_line_mode4() {
render_line_bg (3, 6, COLORDEPTH_256, BG1);
render_line_bg (2, 5, COLORDEPTH_4, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode4);
}
void bPPU::render_line_mode5() {
render_line_bg (3, 6, COLORDEPTH_16, BG1);
render_line_bg (2, 5, COLORDEPTH_4, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode5);
}
void bPPU::render_line_mode6() {
render_line_bg (2, 4, COLORDEPTH_16, BG1);
render_line_oam(0, 1, 3, 5);
set_layer_pixels(8, bPPURenderTables::lookup_mode6);
}
void bPPU::render_line_mode7() {
if(regs.mode7_extbg == false) {
render_line_m7 (1, 0, 0); //bg2 priorities are ignored
render_line_oam(0, 2, 3, 4);
set_layer_pixels(5, bPPURenderTables::lookup_mode7);
} else {
render_line_m7 (0, 0, 3); //bg1 priority is ignored
render_line_oam(1, 2, 4, 5);
set_layer_pixels(6, bPPURenderTables::lookup_mode7_extbg);
}
}
void bPPU::render_line() {
if(regs.display_disabled == true) {
memset(output->buffer + (_y << 1) * 512, 0, 2048);
return;
}
clear_layer_cache();
clear_pixel_cache();
switch(regs.bg_mode) {
case 0:render_line_mode0();break;
case 1:render_line_mode1();break;
case 2:render_line_mode2();break;
case 3:render_line_mode3();break;
case 4:render_line_mode4();break;
case 5:render_line_mode5();break;
case 6:render_line_mode6();break;
case 7:render_line_mode7();break;
}
render_line_to_output();
}
+70
View File
@@ -0,0 +1,70 @@
//bppu_render.cpp
void render_line_mode0();
void render_line_mode1();
void render_line_mode2();
void render_line_mode3();
void render_line_mode4();
void render_line_mode5();
void render_line_mode6();
void render_line_mode7();
//bppu_render_cache.cpp
enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 };
enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 };
enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 };
struct {
uint8 color_main, color_sub;
uint8 src_main, src_sub;
uint8 blend_type;
}pixel_cache[512];
uint8 layer_cache[512 * 12];
uint8 *bg_tiledata[3];
uint8 *bg_tiledata_state[3];
void clear_pixel_cache(void);
void clear_layer_cache(void);
void init_tiledata_cache(void);
void clear_tiledata_cache(void);
//bppu_render_windows.cpp
enum { WINDOWMASK_OR = 0, WINDOWMASK_AND = 1, WINDOWMASK_XOR = 2, WINDOWMASK_XNOR = 3 };
bool windows_not_obstructing(uint8 layer, uint8 bg, uint16 x);
bool color_windows_not_obstructing(uint16 x, uint8 color_mask_type);
//bppu_render_main.cpp
enum {
SH_2 = 1, SH_4 = 2, SH_8 = 3, SH_16 = 4,
SH_32 = 5, SH_64 = 6, SH_128 = 7, SH_256 = 8,
SH_512 = 9, SH_1024 = 10, SH_2048 = 11, SH_4096 = 12
};
enum { COLORMODE_ADD = 0, COLORMODE_SUB = 1 };
enum { PPU_MAIN = 0, PPU_SUB = 1 };
enum { OAM_PRI_NONE = 4 };
uint8 oam_line_pal[512], oam_line_pri[512];
struct {
byte num;
byte width, height;
word x, y;
word character;
byte v_flip, h_flip;
byte palette;
byte priority;
}current_sprite;
void render_line_to_output();
inline uint16 addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg);
inline uint16 addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg);
void render_bg_tile(uint8 color_depth, uint8 bg, uint16 tile_num);
void set_pixel(uint8 bg, uint16 x, uint8 pal_index);
void set_layer_pixels(uint8 layer_count, uint8 *layer_bg_lookup);
void set_sprite_attributes(uint8 sprite_num);
void render_oam_sprite(void);
void render_line_oam(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 layer_pos_pri2, uint8 layer_pos_pri3);
void render_line_bg(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 color_depth, uint8 bg);
//bppu_render_mode7.cpp
void render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1);
+33
View File
@@ -0,0 +1,33 @@
//this should be reset once every scanline
void bPPU::clear_pixel_cache(void) {
for(int i=0;i<512;i++) {
pixel_cache[i].color_main = 0;
pixel_cache[i].color_sub = 0;
pixel_cache[i].src_main = BACK;
pixel_cache[i].src_sub = BACK;
pixel_cache[i].blend_type = BLENDTYPE_BACK;
}
}
//this should be reset once every scanline
void bPPU::clear_layer_cache(void) {
memset(&layer_cache, 0, 512 * 12);
}
void bPPU::init_tiledata_cache(void) {
bg_tiledata[TILE_2BIT] = (uint8*)malloc(262144);
bg_tiledata[TILE_4BIT] = (uint8*)malloc(131072);
bg_tiledata[TILE_8BIT] = (uint8*)malloc( 65536);
bg_tiledata_state[TILE_2BIT] = (uint8*)malloc( 4096);
bg_tiledata_state[TILE_4BIT] = (uint8*)malloc( 2048);
bg_tiledata_state[TILE_8BIT] = (uint8*)malloc( 1024);
}
void bPPU::clear_tiledata_cache(void) {
memset(bg_tiledata[TILE_2BIT], 0, 262144);
memset(bg_tiledata[TILE_4BIT], 0, 131072);
memset(bg_tiledata[TILE_4BIT], 0, 65536);
memset(bg_tiledata_state[TILE_2BIT], 0, 4096);
memset(bg_tiledata_state[TILE_4BIT], 0, 2048);
memset(bg_tiledata_state[TILE_8BIT], 0, 1024);
}
@@ -195,9 +195,9 @@ uint16 c, cx, cy;
uint16 screen_width;
uint16 v, vline_pos = clock->vcounter();
v = vline_pos;
screen_width = (output->scanline_mode[v] & PPUOutput::DOUBLEWIDTH)?512:256;
screen_width = (output->line[v].hires)?512:256;
if(!(output->scanline_mode[v] & PPUOutput::INTERLACE)) {
if(output->line[v].interlace == false) {
ptr = (uint16*)output->buffer + ((vline_pos << 1)) * 512;
} else {
ptr = (uint16*)output->buffer + ((vline_pos << 1) + clock->interlace_field()) * 512;
+110
View File
@@ -0,0 +1,110 @@
#define CLIP_10BIT_SIGNED(x) \
((x) & ((1 << 10) - 1)) + (((((x) & (1 << 13)) ^ (1 << 13)) - (1 << 13)) >> 3)
#define CAST_WORDTOINT(x) \
(int)(((x & 0x8000)?(x | 0xffff0000):(x & 0x00007fff)))
void bPPU::render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1) {
int x;
int step_m7a, step_m7c, m7a, m7b, m7c, m7d;
int hoffset, voffset;
int centerx, centery;
int xx, yy;
int px, py;
int tx, ty, tile, palette, priority;
uint8 layer_pos;
hoffset = (CAST_WORDTOINT(regs.bg_hofs[BG1]) << 7) >> 7;
voffset = (CAST_WORDTOINT(regs.bg_vofs[BG1]) << 7) >> 7;
centerx = (CAST_WORDTOINT(regs.m7x) << 7) >> 7;
centery = (CAST_WORDTOINT(regs.m7y) << 7) >> 7;
if(regs.mode7_vflip == true) {
yy = 223 - clock->vcounter();
} else {
yy = clock->vcounter();
}
yy += CLIP_10BIT_SIGNED(voffset - centery);
m7b = CAST_WORDTOINT(regs.m7b) * yy + (centerx << 8);
m7d = CAST_WORDTOINT(regs.m7d) * yy + (centery << 8);
step_m7a = CAST_WORDTOINT(regs.m7a);
step_m7c = CAST_WORDTOINT(regs.m7c);
xx = CLIP_10BIT_SIGNED(hoffset - centerx);
m7a = CAST_WORDTOINT(regs.m7a) * xx;
m7c = CAST_WORDTOINT(regs.m7c) * xx;
for(x=0;x<256;x++) {
px = ((m7a + m7b) >> 8);
py = ((m7c + m7d) >> 8);
switch(regs.mode7_repeat) {
case 0: //screen repitition outside of screen area
case 1: //same as case 0
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
break;
case 2: //character 0 repetition outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
tx = 0;
ty = 0;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
}
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
break;
case 3: //palette color 0 outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
palette = 0;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
}
break;
}
if(regs.mode7_extbg == false) {
if(palette) {
layer_pos = layer_pos_bg1;
if(regs.mode7_hflip == true) {
set_layer_pixel(255 - x, palette);
} else {
set_layer_pixel(x, palette);
}
}
} else {
priority = (palette >> 7);
palette &= 0x7f;
if(palette) {
if(priority == 0) {
layer_pos = layer_pos_bg2_pri0;
} else {
layer_pos = layer_pos_bg2_pri1;
}
if(regs.mode7_hflip == true) {
set_layer_pixel(255 - x, palette);
} else {
set_layer_pixel(x, palette);
}
}
}
m7a += step_m7a;
m7c += step_m7c;
}
}
+159
View File
@@ -0,0 +1,159 @@
bool bPPU::windows_not_obstructing(uint8 layer, uint8 bg, uint16 x) {
uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked
uint16 window1_left, window1_right, window2_left, window2_right;
if(layer == PPU_MAIN) {
if(regs.bg_window_enabled[bg] == false)return true;
} else if(layer == PPU_SUB) {
if(regs.bgsub_window_enabled[bg] == false)return true;
}
window1_left = regs.window1_left;
window1_right = regs.window1_right;
window2_left = regs.window2_left;
window2_right = regs.window2_right;
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == false) {
if(regs.bg_window1_invert[bg] == false) {
if(x >= window1_left && x <= window1_right)return false;
return true;
} else {
if(x < window1_left || x > window1_right)return false;
return true;
}
} else if(regs.bg_window2_enabled[bg] == true && regs.bg_window1_enabled[bg] == false) {
if(regs.bg_window2_invert[bg] == false) {
if(x >= window2_left && x <= window2_right)return false;
return true;
} else {
if(x < window2_left || x > window2_right)return false;
return true;
}
} else if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == true) {
if(regs.bg_window1_invert[bg] == false) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
}
if(regs.bg_window2_invert[bg] == false) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
switch(regs.bg_window_mask[bg]) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)return false;
return true;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)return false;
return true;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)return false;
return true;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)return false;
return true;
}
}
return true;
}
bool bPPU::color_windows_not_obstructing(uint16 x, uint8 color_mask_type) {
uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked
uint8 color_mask;
bool r;
uint16 window1_left, window1_right, window2_left, window2_right;
if(color_mask_type == PPU_MAIN) {
color_mask = regs.color_mask;
} else {
color_mask = regs.colorsub_mask;
}
if(color_mask == 0)return false;
if(color_mask == 3)return true;
window1_left = regs.window1_left;
window1_right = regs.window1_right;
window2_left = regs.window2_left;
window2_right = regs.window2_right;
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(regs.color_window1_enabled == false && regs.color_window2_enabled == false) {
r = true;
} else if(regs.color_window1_enabled == true && regs.color_window2_enabled == false) {
if(regs.color_window1_invert == false) {
if(x >= window1_left && x <= window1_right)r = false;
else r = true;
} else {
if(x < window1_left || x > window1_right)r = false;
else r = true;
}
} else if(regs.color_window1_enabled == false && regs.color_window2_enabled == true) {
if(regs.color_window2_invert == false) {
if(x >= window2_left && x <= window2_right)r = false;
else r = true;
} else {
if(x < window2_left || x > window2_right)r = false;
else r = true;
}
} else if(regs.color_window1_enabled == true && regs.color_window2_enabled == true) {
if(regs.color_window1_invert == false) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
}
if(regs.color_window2_invert == false) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
switch(regs.color_window_mask) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)r = false;
else r = true;
break;
}
}
if(color_mask == 2) {
r = (r == true)?false:true;
}
return r;
}
+99 -88
View File
@@ -1,124 +1,135 @@
#include "bppu_render_cache.cpp"
#include "bppu_render_windows.cpp"
#include "bppu_render_main.cpp"
#include "bppu_render_bg.cpp"
#include "bppu_render_oam.cpp"
#include "bppu_render_mode7.cpp"
#include "bppu_render_addsub.cpp"
#include "bppu_render_line.cpp"
namespace bPPURenderTables {
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5 };
uint8 lookup_mode0[12] = {
BG4, BG3, OAM, BG4, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode1_pri0[10] = {
BG3, OAM, BG3, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode1_pri1[10] = {
BG3, OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM, BG3
};
uint8 lookup_mode2[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode3[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode4[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode5[8] = {
OAM, OAM, BG2, BG1, OAM, BG2, BG1, OAM
};
uint8 lookup_mode6[6] = {
OAM, OAM, BG1, OAM, BG1, OAM
};
uint8 lookup_mode7[5] = {
OAM, BG1, OAM, OAM, OAM
};
uint8 lookup_mode7_extbg[6] = {
BG2, OAM, OAM, BG2, OAM, OAM
};
};
void bPPU::render_line_mode0() {
render_line_bg (7, 10, COLORDEPTH_4, BG1);
render_line_bg (6, 9, COLORDEPTH_4, BG2);
render_line_bg (1, 4, COLORDEPTH_4, BG3);
render_line_bg (0, 3, COLORDEPTH_4, BG4);
render_line_oam(2, 5, 8, 11);
set_layer_pixels(12, bPPURenderTables::lookup_mode0);
/*
Mode 0: ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
BG4B, BG3B, OAM0, BG4A, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
*/
inline void bPPU::render_line_mode0() {
render_line_bg(BG1, COLORDEPTH_4, 8, 11);
render_line_bg(BG2, COLORDEPTH_4, 7, 10);
render_line_bg(BG3, COLORDEPTH_4, 2, 5);
render_line_bg(BG4, COLORDEPTH_4, 1, 4);
render_line_oam(3, 6, 9, 12);
}
void bPPU::render_line_mode1() {
/*
Mode 1 (pri=0): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
Mode 1 (pri=1): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3, BG3A
*/
inline void bPPU::render_line_mode1() {
switch(regs.bg3_priority) {
case 0:
render_line_bg (5, 8, COLORDEPTH_16, BG1);
render_line_bg (4, 7, COLORDEPTH_16, BG2);
render_line_bg (0, 2, COLORDEPTH_4, BG3);
render_line_oam(1, 3, 6, 9);
set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri0);
render_line_bg(BG1, COLORDEPTH_16, 6, 9);
render_line_bg(BG2, COLORDEPTH_16, 5, 8);
render_line_bg(BG3, COLORDEPTH_4, 1, 3);
render_line_oam(2, 4, 7, 10);
break;
case 1:
render_line_bg (4, 7, COLORDEPTH_16, BG1);
render_line_bg (3, 6, COLORDEPTH_16, BG2);
render_line_bg (0, 9, COLORDEPTH_4, BG3);
render_line_oam(1, 2, 5, 8);
set_layer_pixels(10, bPPURenderTables::lookup_mode1_pri1);
render_line_bg(BG1, COLORDEPTH_16, 5, 8);
render_line_bg(BG2, COLORDEPTH_16, 4, 7);
render_line_bg(BG3, COLORDEPTH_4, 1, 10);
render_line_oam(2, 3, 6, 9);
break;
}
}
void bPPU::render_line_mode2() {
render_line_bg (3, 6, COLORDEPTH_16, BG1);
render_line_bg (2, 5, COLORDEPTH_16, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode2);
/*
Mode 2: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode2() {
render_line_bg(BG1, COLORDEPTH_16, 3, 7);
render_line_bg(BG2, COLORDEPTH_16, 1, 5);
render_line_oam(2, 4, 6, 8);
}
void bPPU::render_line_mode3() {
render_line_bg (3, 6, COLORDEPTH_256, BG1);
render_line_bg (2, 5, COLORDEPTH_16, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode3);
/*
Mode 3: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode3() {
render_line_bg(BG1, COLORDEPTH_256, 3, 7);
render_line_bg(BG2, COLORDEPTH_16, 1, 5);
render_line_oam(2, 4, 6, 8);
}
void bPPU::render_line_mode4() {
render_line_bg (3, 6, COLORDEPTH_256, BG1);
render_line_bg (2, 5, COLORDEPTH_4, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode4);
/*
Mode 4: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode4() {
render_line_bg(BG1, COLORDEPTH_256, 3, 7);
render_line_bg(BG2, COLORDEPTH_4, 1, 5);
render_line_oam(2, 4, 6, 8);
}
void bPPU::render_line_mode5() {
render_line_bg (3, 6, COLORDEPTH_16, BG1);
render_line_bg (2, 5, COLORDEPTH_4, BG2);
render_line_oam(0, 1, 4, 7);
set_layer_pixels(8, bPPURenderTables::lookup_mode5);
/*
Mode 5: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode5() {
render_line_bg(BG1, COLORDEPTH_16, 3, 7);
render_line_bg(BG2, COLORDEPTH_4, 1, 5);
render_line_oam(2, 4, 6, 8);
}
void bPPU::render_line_mode6() {
render_line_bg (2, 4, COLORDEPTH_16, BG1);
render_line_oam(0, 1, 3, 5);
set_layer_pixels(8, bPPURenderTables::lookup_mode6);
/*
Mode 6: ->
1, 2, 3, 4, 5, 6
OAM0, BG1B, OAM1, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode6() {
render_line_bg(BG1, COLORDEPTH_16, 2, 5);
render_line_oam(1, 3, 4, 6);
}
void bPPU::render_line_mode7() {
/*
Mode7: ->
1, 2, 3, 4, 5
OAM0, BG1n, OAM1, OAM2, OAM3
***
This appears to be incorrect, possibly should be...
BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3
***
Mode 7 (extbg): ->
1, 2, 3, 4, 5, 6
BG2B, OAM0, OAM1, BG2A, OAM2, OAM3
*/
inline void bPPU::render_line_mode7() {
if(regs.mode7_extbg == false) {
render_line_m7 (1, 0, 0); //bg2 priorities are ignored
render_line_oam(0, 2, 3, 4);
set_layer_pixels(5, bPPURenderTables::lookup_mode7);
render_line_mode7(2, 0, 0); //bg2 priorities are ignored
render_line_oam(1, 3, 4, 5);
} else {
render_line_m7 (0, 0, 3); //bg1 priority is ignored
render_line_oam(1, 2, 4, 5);
set_layer_pixels(6, bPPURenderTables::lookup_mode7_extbg);
render_line_mode7(0, 1, 4); //bg1 priority is ignored
render_line_oam(2, 3, 5, 6);
}
}
void bPPU::render_line(uint16 line) {
void bPPU::render_line() {
if(regs.display_disabled == true) {
memset(output->buffer + (line << 1) * 512, 0, 2048);
memset(output->buffer + (_y << 10), 0, 2048);
return;
}
clear_layer_cache();
clear_pixel_cache();
build_color_window_tables();
switch(regs.bg_mode) {
case 0:render_line_mode0();break;
case 1:render_line_mode1();break;
@@ -129,5 +140,5 @@ void bPPU::render_line(uint16 line) {
case 6:render_line_mode6();break;
case 7:render_line_mode7();break;
}
render_line_to_output();
render_line_output();
}
+53 -42
View File
@@ -1,50 +1,54 @@
//bppu_render.cpp
void render_line_mode0();
void render_line_mode1();
void render_line_mode2();
void render_line_mode3();
void render_line_mode4();
void render_line_mode5();
void render_line_mode6();
void render_line_mode7();
int _screen_width;
bool _interlace;
int _interlace_field;
inline void render_line_mode0();
inline void render_line_mode1();
inline void render_line_mode2();
inline void render_line_mode3();
inline void render_line_mode4();
inline void render_line_mode5();
inline void render_line_mode6();
inline void render_line_mode7();
//bppu_render_cache.cpp
enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 };
enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 };
enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 };
struct {
uint8 color_main, color_sub;
uint8 src_main, src_sub;
uint8 blend_type;
enum { PC_BG1 = 0x80, PC_BG2 = 0x81, PC_BG3 = 0x82, PC_BG4 = 0x83, PC_OAM = 0x84, PC_BACK = 0x00 };
struct _pixel {
//palette # index for main/subscreen pixels
//0 = transparent / use palette color # 0
uint8 src_main, src_sub;
//indicates source of palette # for main/subscreen (BG1-4, OAM, or back)
uint8 bg_main, bg_sub;
//priority level of src_n. to set src_n,
//the priority of the pixel must be >pri_n
uint8 pri_main, pri_sub;
}pixel_cache[512];
uint8 layer_cache[512 * 12];
uint8 *bg_tiledata[3];
uint8 *bg_tiledata_state[3];
void clear_pixel_cache(void);
void clear_layer_cache(void);
void init_tiledata_cache(void);
void clear_tiledata_cache(void);
void render_bg_tile(uint8 color_depth, uint16 tile_num);
inline void clear_pixel_cache();
void init_tiledata_cache();
void clear_tiledata_cache();
//bppu_render_windows.cpp
enum { WINDOWMASK_OR = 0, WINDOWMASK_AND = 1, WINDOWMASK_XOR = 2, WINDOWMASK_XNOR = 3 };
uint8 main_windowtable[5][512], sub_windowtable[5][512],
main_colorwindowtable[512], sub_colorwindowtable[512];
bool windows_not_obstructing(uint8 layer, uint8 bg, uint16 x);
bool color_windows_not_obstructing(uint16 x, uint8 color_mask_type);
void build_window_table(uint8 bg, uint8 *wtbl, bool mainscreen);
void build_window_tables(uint8 bg);
void build_color_window_table(uint8 *wtbl, uint8 mask);
void build_color_window_tables();
//bppu_render_main.cpp
enum {
SH_2 = 1, SH_4 = 2, SH_8 = 3, SH_16 = 4,
SH_32 = 5, SH_64 = 6, SH_128 = 7, SH_256 = 8,
SH_512 = 9, SH_1024 = 10, SH_2048 = 11, SH_4096 = 12
};
enum { COLORMODE_ADD = 0, COLORMODE_SUB = 1 };
enum { PPU_MAIN = 0, PPU_SUB = 1 };
enum { OAM_PRI_NONE = 4 };
uint8 oam_line_pal[512], oam_line_pri[512];
//bppu_render_bg.cpp
void render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos);
//bppu_render_oam.cpp
struct {
byte num;
byte width, height;
@@ -55,16 +59,23 @@ struct {
byte priority;
}current_sprite;
void render_line_to_output();
inline uint16 addsub_pixels(uint8 x, uint8 cdest_index, uint8 cdest_bg, uint8 csrc_index, uint8 csrc_bg);
inline uint16 addsub_pixel(uint8 x, uint8 cdest_index, uint8 cdest_bg);
void render_bg_tile(uint8 color_depth, uint8 bg, uint16 tile_num);
void set_pixel(uint8 bg, uint16 x, uint8 pal_index);
void set_layer_pixels(uint8 layer_count, uint8 *layer_bg_lookup);
void set_sprite_attributes(uint8 sprite_num);
void render_oam_sprite(void);
void render_line_oam(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 layer_pos_pri2, uint8 layer_pos_pri3);
void render_line_bg(uint8 layer_pos_pri0, uint8 layer_pos_pri1, uint8 color_depth, uint8 bg);
enum { OAM_PRI_NONE = 4 };
uint8 oam_line_pal[512], oam_line_pri[512];
void set_sprite_attributes(uint8 sprite_num);
void render_oam_sprite();
void render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos);
//bppu_render_mode7.cpp
void render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1);
void render_line_mode7(uint8 bg1_pri, uint8 bg2b_pri, uint8 bg2a_pri);
//bppu_render_addsub.cpp
inline uint16 addsub_pixels(int cdest_index, int cdest_bg, int csrc_index, int csrc_bg);
inline uint16 addsub_pixel(int cdest_index, int cdest_bg);
//bppu_render_line.cpp
enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 };
inline uint16 get_palette(int index);
inline uint16 get_pixel(int x);
inline void render_line_output();
+109
View File
@@ -0,0 +1,109 @@
inline uint16 bPPU::addsub_pixels(int cdest_index, int cdest_bg, int csrc_index, int csrc_bg) {
int r, g, b;
uint32 cdest = get_palette(cdest_index);
uint32 csrc = get_palette(csrc_index);
uint16 res;
//oam palettes 0-3 are not affected by color add/sub
if(cdest_bg == OAM) {
if(cdest_index < 192) {
return cdest;
}
}
switch(regs.color_mode) {
case 0: //COLORMODE_ADD:
if(regs.color_halve == true) {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
cdest >>= 1;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
} else {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
if(cdest & 0x04000000)cdest |= 0x03e00000;
if(cdest & 0x00008000)cdest |= 0x00007c00;
if(cdest & 0x00000020)cdest |= 0x0000001f;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
}
break;
case 1: //COLORMODE_SUB:
if(regs.color_halve == true) {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return (cdest & 0x7bde) >> 1;
} else {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return cdest;
}
break;
}
return 0x0000; //prevent annoying warning message
}
inline uint16 bPPU::addsub_pixel(int cdest_index, int cdest_bg) {
int r, g, b;
uint32 cdest = get_palette(cdest_index);
uint32 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10);
uint16 res;
//only oam palettes 4-7 are affected by color add/sub
if(cdest_bg == OAM) {
if(cdest_index < 192) {
return cdest;
}
}
switch(regs.color_mode) {
case 0: //COLORMODE_ADD:
if(regs.color_halve == true && regs.addsub_mode == 0) {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
cdest >>= 1;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
} else {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
if(cdest & 0x04000000)cdest |= 0x03e00000;
if(cdest & 0x00008000)cdest |= 0x00007c00;
if(cdest & 0x00000020)cdest |= 0x0000001f;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
}
break;
case 1: //COLORMODE_SUB:
if(regs.color_halve == true && regs.addsub_mode == 0) {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return (cdest & 0x7bde) >> 1;
} else {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return cdest;
}
break;
}
return 0x0000; //prevent annoying warning message
}
+232
View File
@@ -0,0 +1,232 @@
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];
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;
}
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;
}
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;
uint8 pal_index;
uint8 *tile_ptr;
int xpos, ypos;
uint16 map_index, hoffset, voffset, col;
uint8 *wt_main = main_windowtable[bg];
uint8 *wt_sub = sub_windowtable[bg];
build_window_tables(bg);
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) {
tile_x = (mtable[screen_x + (hscroll & 15)] >> 4);
} else {
tile_x = (mtable[screen_x + (hscroll & 7)] >> 3);
}
hoffset = hscroll;
voffset = vscroll;
if(tile_x != 0) {
tile_x = (tile_x - 1) & 31;
if(regs.bg_mode == 4) {
pos = regs.bg_scaddr[BG3] + (tile_x << 1);
t = *((uint16*)vram + (pos >> 1));
if(t & opt_valid_bit) {
if(!(t & 0x8000)) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
} else {
voffset = (t & 0x1fff) & screen_height_mask;
}
}
} else {
pos = regs.bg_scaddr[BG3] + (tile_x << 1);
t = *((uint16*)vram + (pos >> 1));
if(t & opt_valid_bit) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
}
pos = regs.bg_scaddr[BG3] + 64 + (tile_x << 1);
t = *((uint16*)vram + (pos >> 1));
if(t & opt_valid_bit) {
voffset = (t & 0x1fff) & screen_height_mask;
}
}
}
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;
}
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 = *((uint16*)vram + (pos >> 1));
mirror_y = (t & 0x8000)?1:0;
mirror_x = (t & 0x4000)?1:0;
int _pri;
_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
tile_num = t & 0x03ff;
if(tile_width == 4) {
if(((mosaic_x & 15) >= 8 && !mirror_x) ||
((mosaic_x & 15) < 8 && mirror_x))tile_num++;
tile_num &= 0x03ff;
}
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_index = ((t >> 10) & 7) * pal_size;
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);
while(1) {
if(mirror_x) { xpos = (7 - (mosaic_x & 7)); }
else { xpos = ( (mosaic_x & 7)); }
col = *(tile_ptr + xpos);
if(col && main_colorwindowtable[screen_x]) {
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 + pal_index;
}
}
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 + pal_index;
}
}
}
bg_x++;
bg_x &= screen_width_mask;
mosaic_x = mtable[bg_x];
if(base_xpos != ((mosaic_x >> 3) & 31))break;
screen_x++;
if(screen_x >= _screen_width)break;
}
}
}
+105 -20
View File
@@ -1,30 +1,115 @@
//this should be reset once every scanline
void bPPU::clear_pixel_cache(void) {
int i;
for(i=0;i<512;i++) {
pixel_cache[i].color_main = 0;
pixel_cache[i].color_sub = 0;
pixel_cache[i].src_main = BACK;
pixel_cache[i].src_sub = BACK;
pixel_cache[i].blend_type = BLENDTYPE_BACK;
#define render_bg_tile_line_4(__m) \
col = 0; \
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; \
if(d1 & __m)col += 2; \
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; \
if(d1 & __m)col += 2; \
if(d2 & __m)col += 4; \
if(d3 & __m)col += 8; \
if(d4 & __m)col += 16; \
if(d5 & __m)col += 32; \
if(d6 & __m)col += 64; \
if(d7 & __m)col += 128; \
*dest++ = col
void bPPU::render_bg_tile(uint8 color_depth, uint16 tile_num) {
uint8 mask, d0, d1, d2, d3, d4, d5, d6, d7, col;
int x, y;
uint32 pos;
uint8 *dest;
switch(color_depth) {
case COLORDEPTH_4:
dest = (uint8*)bg_tiledata[TILE_2BIT] + tile_num * 64;
pos = tile_num * 16;
y = 8;
while(y--) {
d0 = vram[pos ];
d1 = vram[pos + 1];
render_bg_tile_line_4(0x80);
render_bg_tile_line_4(0x40);
render_bg_tile_line_4(0x20);
render_bg_tile_line_4(0x10);
render_bg_tile_line_4(0x08);
render_bg_tile_line_4(0x04);
render_bg_tile_line_4(0x02);
render_bg_tile_line_4(0x01);
pos += 2;
}
bg_tiledata_state[TILE_2BIT][tile_num] = 0;
break;
case COLORDEPTH_16:
dest = (uint8*)bg_tiledata[TILE_4BIT] + tile_num * 64;
pos = tile_num * 32;
y = 8;
while(y--) {
d0 = vram[pos ];
d1 = vram[pos + 1];
d2 = vram[pos + 16];
d3 = vram[pos + 17];
render_bg_tile_line_16(0x80);
render_bg_tile_line_16(0x40);
render_bg_tile_line_16(0x20);
render_bg_tile_line_16(0x10);
render_bg_tile_line_16(0x08);
render_bg_tile_line_16(0x04);
render_bg_tile_line_16(0x02);
render_bg_tile_line_16(0x01);
pos += 2;
}
bg_tiledata_state[TILE_4BIT][tile_num] = 0;
break;
case COLORDEPTH_256:
dest = (uint8*)bg_tiledata[TILE_8BIT] + tile_num * 64;
pos = tile_num * 64;
y = 8;
while(y--) {
d0 = vram[pos ];
d1 = vram[pos + 1];
d2 = vram[pos + 16];
d3 = vram[pos + 17];
d4 = vram[pos + 32];
d5 = vram[pos + 33];
d6 = vram[pos + 48];
d7 = vram[pos + 49];
render_bg_tile_line_256(0x80);
render_bg_tile_line_256(0x40);
render_bg_tile_line_256(0x20);
render_bg_tile_line_256(0x10);
render_bg_tile_line_256(0x08);
render_bg_tile_line_256(0x04);
render_bg_tile_line_256(0x02);
render_bg_tile_line_256(0x01);
pos += 2;
}
bg_tiledata_state[TILE_8BIT][tile_num] = 0;
break;
}
}
//this should be reset once every scanline
void bPPU::clear_layer_cache(void) {
memset(&layer_cache, 0, 512 * 12);
inline void bPPU::clear_pixel_cache() {
memset(pixel_cache, 0, sizeof(pixel_cache));
}
void bPPU::init_tiledata_cache(void) {
bg_tiledata[TILE_2BIT] = (byte*)malloc(262144);
bg_tiledata[TILE_4BIT] = (byte*)malloc(131072);
bg_tiledata[TILE_8BIT] = (byte*)malloc( 65536);
bg_tiledata_state[TILE_2BIT] = (byte*)malloc( 4096);
bg_tiledata_state[TILE_4BIT] = (byte*)malloc( 2048);
bg_tiledata_state[TILE_8BIT] = (byte*)malloc( 1024);
void bPPU::init_tiledata_cache() {
bg_tiledata[TILE_2BIT] = (uint8*)malloc(262144);
bg_tiledata[TILE_4BIT] = (uint8*)malloc(131072);
bg_tiledata[TILE_8BIT] = (uint8*)malloc( 65536);
bg_tiledata_state[TILE_2BIT] = (uint8*)malloc( 4096);
bg_tiledata_state[TILE_4BIT] = (uint8*)malloc( 2048);
bg_tiledata_state[TILE_8BIT] = (uint8*)malloc( 1024);
}
void bPPU::clear_tiledata_cache(void) {
void bPPU::clear_tiledata_cache() {
memset(bg_tiledata[TILE_2BIT], 0, 262144);
memset(bg_tiledata[TILE_4BIT], 0, 131072);
memset(bg_tiledata[TILE_4BIT], 0, 65536);
+76
View File
@@ -0,0 +1,76 @@
inline uint16 bPPU::get_palette(int index) {
return *((uint16*)cgram + index);
}
inline uint16 bPPU::get_pixel(int x) {
_pixel *p = &pixel_cache[x];
uint16 _r;
if(p->bg_main && p->bg_sub) {
if(regs.bg_color_enabled[p->bg_main & 0x7f] && sub_colorwindowtable[x]) {
if(regs.addsub_mode) {
_r = addsub_pixels(p->src_main, p->bg_main & 0x7f, p->src_sub, p->bg_sub & 0x7f);
} else {
_r = addsub_pixel(p->src_main, p->bg_main & 0x7f);
}
} else {
_r = get_palette(p->src_main);
}
} else if(p->bg_main) {
if(regs.bg_color_enabled[p->bg_main & 0x7f] && sub_colorwindowtable[x]) {
_r = addsub_pixel(p->src_main, p->bg_main & 0x7f);
} else {
_r = get_palette(p->src_main);
}
} else if(p->bg_sub) {
if(regs.bg_color_enabled[BACK]) {
if(sub_colorwindowtable[x]) {
if(regs.addsub_mode) {
_r = addsub_pixels(0, BACK, p->src_sub, p->bg_sub & 0x7f);
} else {
_r = addsub_pixel(0, BACK);
}
} else {
_r = get_palette(0);
}
} else {
_r = 0x0000;
}
} else {
if(main_colorwindowtable[x]) {
if(regs.bg_color_enabled[BACK] && sub_colorwindowtable[x]) {
_r = addsub_pixel(0, BACK);
} else {
_r = get_palette(0);
}
} else {
_r = 0x0000;
}
}
return _r;
}
inline void bPPU::render_line_output() {
int x;
uint16 _r;
uint16 *ptr;
ptr = (uint16*)output->buffer + (_y << 10);
if(_interlace == true) {
ptr += _interlace_field << 9;
}
uint16 *ltable;
ltable = (uint16*)light_table + (regs.display_brightness << 16);
if(_screen_width == 256) {
for(x=0;x<256;x++) {
_r = get_pixel(x);
*ptr = *(ltable + _r);
ptr += 2;
}
} else {
for(x=0;x<512;x++) {
_r = get_pixel(x);
*ptr++ = *(ltable + _r);
}
}
}
+58 -30
View File
@@ -4,14 +4,14 @@
#define CAST_WORDTOINT(x) \
(int)(((x & 0x8000)?(x | 0xffff0000):(x & 0x00007fff)))
void bPPU::render_line_m7(uint8 layer_pos_bg1, uint8 layer_pos_bg2_pri0, uint8 layer_pos_bg2_pri1) {
void bPPU::render_line_mode7(uint8 bg1_pri, uint8 bg2b_pri, uint8 bg2a_pri) {
int x;
int step_m7a, step_m7c, m7a, m7b, m7c, m7d;
int hoffset, voffset;
int centerx, centery;
int xx, yy;
int px, py;
int tx, ty, tile, palette, priority;
int tx, ty, tile, palette;
uint8 layer_pos;
hoffset = (CAST_WORDTOINT(regs.bg_hofs[BG1]) << 7) >> 7;
voffset = (CAST_WORDTOINT(regs.bg_vofs[BG1]) << 7) >> 7;
@@ -20,9 +20,9 @@ uint8 layer_pos;
centery = (CAST_WORDTOINT(regs.m7y) << 7) >> 7;
if(regs.mode7_vflip == true) {
yy = 223 - clock->vcounter();
yy = 223 - _y;
} else {
yy = clock->vcounter();
yy = _y;
}
yy += CLIP_10BIT_SIGNED(voffset - centery);
@@ -37,6 +37,23 @@ uint8 layer_pos;
m7a = CAST_WORDTOINT(regs.m7a) * xx;
m7c = CAST_WORDTOINT(regs.m7c) * xx;
int _pri, _x, _bg;
bool _bg_enabled, _bgsub_enabled;
if(regs.mode7_extbg == false) {
_pri = bg1_pri;
_bg = BG1;
_bg_enabled = regs.bg_enabled[BG1];
_bgsub_enabled = regs.bgsub_enabled[BG1];
} else {
_bg = BG2;
_bg_enabled = regs.bg_enabled[BG2];
_bgsub_enabled = regs.bgsub_enabled[BG2];
}
uint8 *wt_main = main_windowtable[_bg];
uint8 *wt_sub = sub_windowtable[_bg];
build_window_tables(_bg);
for(x=0;x<256;x++) {
px = ((m7a + m7b) >> 8);
py = ((m7c + m7d) >> 8);
@@ -46,10 +63,10 @@ uint8 layer_pos;
case 1: //same as case 0
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tx = ((px >> 3) & 127);
ty = ((py >> 3) & 127);
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
break;
case 2: //character 0 repetition outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
@@ -58,11 +75,11 @@ uint8 layer_pos;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tx = ((px >> 3) & 127);
ty = ((py >> 3) & 127);
}
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
break;
case 3: //palette color 0 outside of screen area
if(px < 0 || px > 1023 || py < 0 || py > 1023) {
@@ -70,40 +87,51 @@ uint8 layer_pos;
} else {
px &= 1023;
py &= 1023;
tx = ((px >> SH_8) & 127);
ty = ((py >> SH_8) & 127);
tx = ((px >> 3) & 127);
ty = ((py >> 3) & 127);
tile = vram[(ty * 128 + tx) << 1];
palette = vram[(((tile << SH_64) + ((py & 7) << SH_8) + (px & 7)) << 1) + 1];
palette = vram[(((tile << 6) + ((py & 7) << 3) + (px & 7)) << 1) + 1];
}
break;
}
if(!palette)goto _end_setpixel;
if(regs.mode7_extbg == false) {
if(palette) {
layer_pos = layer_pos_bg1;
if(regs.mode7_hflip == true) {
set_layer_pixel(255 - x, palette);
} else {
set_layer_pixel(x, palette);
}
//_pri set at top of function, as it is static
if(regs.mode7_hflip == true) {
_x = 255 - x;
} else {
_x = x;
}
} else {
priority = (palette >> 7);
_pri = (palette >> 7) ? bg2a_pri : bg2b_pri;
palette &= 0x7f;
if(palette) {
if(priority == 0) {
layer_pos = layer_pos_bg2_pri0;
} else {
layer_pos = layer_pos_bg2_pri1;
if(regs.mode7_hflip == true) {
_x = 255 - x;
} else {
_x = x;
}
}
if(main_colorwindowtable[_x]) {
if(_bg_enabled == true && !wt_main[_x]) {
if(pixel_cache[_x].pri_main < _pri) {
pixel_cache[_x].pri_main = _pri;
pixel_cache[_x].bg_main = 0x80 | _bg;
pixel_cache[_x].src_main = palette;
}
if(regs.mode7_hflip == true) {
set_layer_pixel(255 - x, palette);
} else {
set_layer_pixel(x, palette);
}
if(_bgsub_enabled == true && !wt_sub[_x]) {
if(pixel_cache[_x].pri_sub < _pri) {
pixel_cache[_x].pri_sub = _pri;
pixel_cache[_x].bg_sub = 0x80 | _bg;
pixel_cache[_x].src_sub = palette;
}
}
}
_end_setpixel:
m7a += step_m7a;
m7c += step_m7c;
}
+193
View File
@@ -0,0 +1,193 @@
void bPPU::set_sprite_attributes(uint8 sprite_num) {
uint32 t;
uint8 size, b;
uint16 x;
t = *((uint32*)oam + sprite_num);
b = oam[512 + (sprite_num >> 2)];
switch(sprite_num & 3) {
case 0: size = !!(b & 0x02); x = (b & 0x01)?0x100:0; break;
case 1: size = !!(b & 0x08); x = (b & 0x04)?0x100:0; break;
case 2: size = !!(b & 0x20); x = (b & 0x10)?0x100:0; break;
case 3: size = !!(b & 0x80); x = (b & 0x40)?0x100:0; break;
}
current_sprite.num = sprite_num;
current_sprite.priority = (t >> 28) & 3;
current_sprite.x = x | (t & 0xff);
current_sprite.y = ((t >> 8) + 1) & 0xff;
current_sprite.v_flip = !!(t & 0x80000000);
current_sprite.h_flip = !!(t & 0x40000000);
current_sprite.palette = (t >> 25) & 7;
current_sprite.character = (t >> 16) & 0x01ff;
//size: 0 = small, 1 = large
switch(regs.oam_basesize) {
case 0:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 16; current_sprite.height = 16; }
break;
case 1:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
case 2:
if(!size) { current_sprite.width = 8; current_sprite.height = 8; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 3:
if(!size) { current_sprite.width = 16; current_sprite.height = 16; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
case 4:
if(!size) { current_sprite.width = 16; current_sprite.height = 16; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 5:
if(!size) { current_sprite.width = 32; current_sprite.height = 32; }
else { current_sprite.width = 64; current_sprite.height = 64; }
break;
case 6:
if(!size) { current_sprite.width = 16; current_sprite.height = 32; }
else { current_sprite.width = 32; current_sprite.height = 64; }
break;
case 7:
if(!size) { current_sprite.width = 16; current_sprite.height = 32; }
else { current_sprite.width = 32; current_sprite.height = 32; }
break;
}
}
void bPPU::render_oam_sprite() {
uint16 pos, col, chr, tiledata_inc;
uint8 d0, d1, d2, d3, pal_index;
int x, y, z, x1, mx, mask, p;
int tile_width;
tile_width = current_sprite.width >> 3; //e.x. 16x16 sprite = 2x2 tiles
if(_interlace == true && _screen_width == 512) {
y = (_y << 1) + _interlace_field;
} else {
y = _y;
}
x = current_sprite.x;
if(_screen_width == 512) {
x <<= 1;
}
if(current_sprite.v_flip) {
y = ((current_sprite.height - 1) - (_y - current_sprite.y));
} else {
y = (_y - current_sprite.y);
}
if(regs.oam_halve == true) {
y <<= 1;
if(_interlace == true && _screen_width == 512) {
y += _interlace_field;
}
}
y &= 255;
chr = current_sprite.character;
tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0;
chr += (y >> 3) << 4;
pal_index = (current_sprite.palette << 4);
for(x1=0;x1<tile_width;x1++) {
if(current_sprite.h_flip)mx = (tile_width - 1) - x1;
else mx = x1;
pos = regs.oam_tdaddr + ((chr + mx) << 5) + ((y & 7) << 1) + tiledata_inc;
d0 = vram[pos ];
d1 = vram[pos + 1];
d2 = vram[pos + 16];
d3 = vram[pos + 17];
for(z=0;z<8;z++) {
if(current_sprite.h_flip) {
mask = 0x01 << z;
} else {
mask = 0x80 >> z;
}
x &= 511;
if(x < _screen_width) {
col = 0;
if(d0 & mask)col += 1;
if(d1 & mask)col += 2;
if(d2 & mask)col += 4;
if(d3 & mask)col += 8;
if(col) {
col += pal_index;
col += 128;
if(oam_line_pri[x] == OAM_PRI_NONE) {
oam_line_pal[x] = col;
oam_line_pri[x] = current_sprite.priority;
}
if(_screen_width == 512) {
if(oam_line_pri[x + 1] == OAM_PRI_NONE) {
oam_line_pal[x + 1] = col;
oam_line_pri[x + 1] = current_sprite.priority;
}
}
}
}
x += (_screen_width == 512)?2:1;
}
}
}
void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) {
int s;
bool _bg_enabled = regs.bg_enabled[OAM];
bool _bgsub_enabled = regs.bgsub_enabled[OAM];
if(_bg_enabled == false && _bgsub_enabled == false)return;
uint8 *wt_main = main_windowtable[OAM];
uint8 *wt_sub = sub_windowtable[OAM];
build_window_tables(OAM);
memset(oam_line_pri, OAM_PRI_NONE, 512);
for(s=0;s<128;s++) {
set_sprite_attributes(s);
if(regs.oam_halve == false) {
if(_y >= current_sprite.y && _y < (current_sprite.y + current_sprite.height)) {
render_oam_sprite();
} else if((current_sprite.y + current_sprite.height) >= 256 && _y < ((current_sprite.y + current_sprite.height) & 255)) {
render_oam_sprite();
}
} else {
if(_y >= current_sprite.y && _y < (current_sprite.y + (current_sprite.height >> 1))) {
render_oam_sprite();
} else if((current_sprite.y + current_sprite.height) >= 256 && _y < ((current_sprite.y + (current_sprite.height >> 1)) & 255)) {
render_oam_sprite();
}
}
}
int _pri;
for(int x=0;x<_screen_width;x++) {
if(oam_line_pri[x] == OAM_PRI_NONE)continue;
switch(oam_line_pri[x]) {
case 0:_pri = pri0_pos;break;
case 1:_pri = pri1_pos;break;
case 2:_pri = pri2_pos;break;
case 3:_pri = pri3_pos;break;
}
if(main_colorwindowtable[x]) {
if(_bg_enabled == true && !wt_main[x]) {
if(pixel_cache[x].pri_main < _pri) {
pixel_cache[x].pri_main = _pri;
pixel_cache[x].bg_main = PC_OAM;
pixel_cache[x].src_main = oam_line_pal[x];
}
}
if(_bgsub_enabled == true && !wt_sub[x]) {
if(pixel_cache[x].pri_sub < _pri) {
pixel_cache[x].pri_sub = _pri;
pixel_cache[x].bg_sub = PC_OAM;
pixel_cache[x].src_sub = oam_line_pal[x];
}
}
}
}
}
+129 -105
View File
@@ -1,95 +1,122 @@
bool bPPU::windows_not_obstructing(uint8 layer, uint8 bg, uint16 x) {
uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked
uint16 window1_left, window1_right, window2_left, window2_right;
if(layer == PPU_MAIN) {
if(regs.bg_window_enabled[bg] == false)return true;
} else if(layer == PPU_SUB) {
if(regs.bgsub_window_enabled[bg] == false)return true;
void bPPU::build_window_table(uint8 bg, uint8 *wtbl, bool mainscreen) {
if(mainscreen == true && regs.bg_window_enabled[bg] == false) {
memset(wtbl, 0, _screen_width);
return;
}
if(mainscreen == false && regs.bgsub_window_enabled[bg] == false) {
memset(wtbl, 0, _screen_width);
return;
}
uint16 window1_left, window1_right, window2_left, window2_right;
int w1_mask, w2_mask; //1 = masked, 0 = not masked
int x;
bool r;
window1_left = regs.window1_left;
window1_right = regs.window1_right;
window2_left = regs.window2_left;
window2_right = regs.window2_right;
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
if(_screen_width == 512) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == false) {
if(regs.bg_window1_enabled[bg] == false && regs.bg_window2_enabled[bg] == false) {
memset(wtbl, 0, _screen_width);
} else if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == false) {
if(regs.bg_window1_invert[bg] == false) {
if(x >= window1_left && x <= window1_right)return false;
return true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x >= window1_left && x <= window1_right)?true:false;
}
} else {
if(x < window1_left || x > window1_right)return false;
return true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x < window1_left || x > window1_right)?true:false;
}
}
} else if(regs.bg_window2_enabled[bg] == true && regs.bg_window1_enabled[bg] == false) {
} else if(regs.bg_window1_enabled[bg] == false && regs.bg_window2_enabled[bg] == true) {
if(regs.bg_window2_invert[bg] == false) {
if(x >= window2_left && x <= window2_right)return false;
return true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x >= window2_left && x <= window2_right)?true:false;
}
} else {
if(x < window2_left || x > window2_right)return false;
return true;
}
} else if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == true) {
if(regs.bg_window1_invert[bg] == false) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x < window2_left || x > window2_right)?true:false;
}
}
} else { //if(regs.bg_window1_enabled[bg] == true && regs.bg_window2_enabled[bg] == true) {
for(x=0;x<_screen_width;x++) {
if(regs.bg_window1_invert[bg] == false) {
w1_mask = (x >= window1_left && x <= window1_right);
} else {
w1_mask = (x < window1_left || x > window1_right);
}
if(regs.bg_window2_invert[bg] == false) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
if(regs.bg_window2_invert[bg] == false) {
w2_mask = (x >= window2_left && x <= window2_right);
} else {
w2_mask = (x < window2_left || x > window2_right);
}
switch(regs.bg_window_mask[bg]) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)return false;
return true;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)return false;
return true;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)return false;
return true;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)return false;
return true;
switch(regs.bg_window_mask[bg]) {
case 0: //WINDOWMASK_OR:
wtbl[x] = ((w1_mask | w2_mask) == 1)?true:false;
break;
case 1: //WINDOWMASK_AND:
wtbl[x] = ((w1_mask & w2_mask) == 1)?true:false;
break;
case 2: //WINDOWMASK_XOR:
wtbl[x] = ((w1_mask ^ w2_mask) == 1)?true:false;
break;
case 3: //WINDOWMASK_XNOR:
wtbl[x] = ((w1_mask ^ w2_mask) == 0)?true:false;
break;
}
}
}
return true;
}
bool bPPU::color_windows_not_obstructing(uint16 x, uint8 color_mask_type) {
uint8 w1_mask, w2_mask; //1 = masked, 0 = not masked
uint8 color_mask;
bool r;
uint16 window1_left, window1_right, window2_left, window2_right;
if(color_mask_type == PPU_MAIN) {
color_mask = regs.color_mask;
} else {
color_mask = regs.colorsub_mask;
void bPPU::build_window_tables(uint8 bg) {
build_window_table(bg, main_windowtable[bg], true);
build_window_table(bg, sub_windowtable[bg], false);
}
void bPPU::build_color_window_table(uint8 *wtbl, uint8 mask) {
if(mask == 0) {
//always
memset(wtbl, 1, _screen_width);
return;
}
if(color_mask == 0)return false;
if(color_mask == 3)return true;
if(mask == 3) {
//never
memset(wtbl, 0, _screen_width);
return;
}
int _true, _false;
if(mask == 1) {
//inside window only
_true = 1;
_false = 0;
} else { //mask == 2
//outside window only
_true = 0;
_false = 1;
}
uint16 window1_left, window1_right, window2_left, window2_right;
int w1_mask, w2_mask; //1 = masked, 0 = not masked
int x;
bool r;
window1_left = regs.window1_left;
window1_right = regs.window1_right;
window2_left = regs.window2_left;
window2_right = regs.window2_right;
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
if(_screen_width == 512) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
@@ -97,63 +124,60 @@ uint16 window1_left, window1_right, window2_left, window2_right;
}
if(regs.color_window1_enabled == false && regs.color_window2_enabled == false) {
r = true;
memset(wtbl, _false, _screen_width);
} else if(regs.color_window1_enabled == true && regs.color_window2_enabled == false) {
if(regs.color_window1_invert == false) {
if(x >= window1_left && x <= window1_right)r = false;
else r = true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x >= window1_left && x <= window1_right)?_true:_false;
}
} else {
if(x < window1_left || x > window1_right)r = false;
else r = true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x < window1_left || x > window1_right)?_true:_false;
}
}
} else if(regs.color_window1_enabled == false && regs.color_window2_enabled == true) {
if(regs.color_window2_invert == false) {
if(x >= window2_left && x <= window2_right)r = false;
else r = true;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x >= window2_left && x <= window2_right)?_true:_false;
}
} else {
if(x < window2_left || x > window2_right)r = false;
else r = true;
}
} else if(regs.color_window1_enabled == true && regs.color_window2_enabled == true) {
if(regs.color_window1_invert == false) {
if(x >= window1_left && x <= window1_right)w1_mask = 1;
else w1_mask = 0;
} else {
if(x < window1_left || x > window1_right)w1_mask = 1;
else w1_mask = 0;
for(x=0;x<_screen_width;x++) {
wtbl[x] = (x < window2_left || x > window2_right)?_true:_false;
}
}
} else { //if(regs.color_window1_enabled == true && regs.color_window2_enabled == true) {
for(x=0;x<_screen_width;x++) {
if(regs.color_window1_invert == false) {
w1_mask = (x >= window1_left && x <= window1_right);
} else {
w1_mask = (x < window1_left || x > window1_right);
}
if(regs.color_window2_invert == false) {
if(x >= window2_left && x <= window2_right)w2_mask = 1;
else w2_mask = 0;
} else {
if(x < window2_left || x > window2_right)w2_mask = 1;
else w2_mask = 0;
}
if(regs.color_window2_invert == false) {
w2_mask = (x >= window2_left && x <= window2_right);
} else {
w2_mask = (x < window2_left || x > window2_right);
}
switch(regs.color_window_mask) {
case WINDOWMASK_OR:
if((w1_mask | w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_AND:
if((w1_mask & w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XOR:
if((w1_mask ^ w2_mask) == 1)r = false;
else r = true;
break;
case WINDOWMASK_XNOR:
if((w1_mask ^ w2_mask) == 0)r = false;
else r = true;
break;
switch(regs.color_window_mask) {
case 0: //WINDOWMASK_OR:
wtbl[x] = ((w1_mask | w2_mask) == 1)?_true:_false;
break;
case 1: //WINDOWMASK_AND:
wtbl[x] = ((w1_mask & w2_mask) == 1)?_true:_false;
break;
case 2: //WINDOWMASK_XOR:
wtbl[x] = ((w1_mask ^ w2_mask) == 1)?_true:_false;
break;
case 3: //WINDOWMASK_XNOR:
wtbl[x] = ((w1_mask ^ w2_mask) == 0)?_true:_false;
break;
}
}
}
}
if(color_mask == 2) {
r = (r == true)?false:true;
}
return r;
void bPPU::build_color_window_tables() {
build_color_window_table(main_colorwindowtable, regs.color_mask);
build_color_window_table(sub_colorwindowtable, regs.colorsub_mask);
}
+4 -2
View File
@@ -3,9 +3,11 @@
PPUOutput::PPUOutput() {
buffer = (uint16*)memalloc(512 * 478 * 2, "PPUOutput::buffer");
memset(buffer, 0, 512 * 478 * 2);
frame_mode = NORMAL;
hires = false;
interlace = false;
for(int i=0;i<239;i++) {
scanline_mode[i] = NORMAL;
line[i].hires = false;
line[i].interlace = false;
}
}
+5 -7
View File
@@ -1,12 +1,9 @@
class PPUOutput {
public:
enum {
NORMAL = 0,
INTERLACE = 1,
DOUBLEWIDTH = 2
};
uint8 frame_mode;
uint8 scanline_mode[239];
bool hires, interlace;
struct {
bool hires, interlace;
}line[239];
uint16 *buffer;
PPUOutput();
~PPUOutput();
@@ -14,6 +11,7 @@ uint16 *buffer;
class PPU {
public:
int _y;
PPUOutput *output;
MMIO *mmio;
virtual uint8 vram_read (uint16 addr) = 0;
+48 -45
View File
@@ -1,24 +1,38 @@
#include "../base.h"
bool FileReader::open(char *fn) {
/* is the filename too short to be a file? */
if(strlen(fn) < 4)return false;
uint32 FileReader::size() {
return fsize;
}
int i;
for(i=strlen(fn) - 1;i>=0;i--) {
if(fn[i] == '.')break;
/*
This function will allocate memory even if open() fails.
This is needed so that when SRAM files do not exist, the
memory for the SRAM data will be allocated still.
The memory is flushed to 0x00 when no file is opened.
*/
void FileReader::read(uint8 **buffer, uint32 length) {
uint8 *data;
if(length == 0) {
/* read the entire file into RAM */
data = (uint8*)memalloc(fsize);
memset(data, 0, fsize);
if(fp)fread(data, 1, fsize, fp);
} else if(length > fsize) {
/* read the entire file into RAM, pad the rest with 0x00s */
data = (uint8*)memalloc(length);
memset(data, 0, length);
if(fp)fread(data, 1, fsize, fp);
} else { //fsize >= length
/* read as much of the file as possible, truncate the rest */
data = (uint8*)memalloc(length);
memset(data, 0, length);
if(fp)fread(data, 1, length, fp);
}
if(fn[i] != '.')return false;
char *filetype = fn + i;
/* make sure we support this file format before loading it */
if(stricmp(filetype, ".smc") &&
stricmp(filetype, ".swc") &&
stricmp(filetype, ".fig") &&
stricmp(filetype, ".ufo") &&
stricmp(filetype, ".gd3") &&
stricmp(filetype, ".078"))return false;
*buffer = data;
}
bool FileReader::open(uint8 type, char *fn) {
fp = fopen(fn, "rb");
if(!fp)return false;
@@ -26,12 +40,7 @@ char *filetype = fn + i;
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if(!stricmp(filetype, ".smc") ||
!stricmp(filetype, ".swc") ||
!stricmp(filetype, ".fig") ||
!stricmp(filetype, ".ufo") ||
!stricmp(filetype, ".gd3") ||
!stricmp(filetype, ".078")) {
if(type == TYPE_ROM) {
/* remove header if it exists */
if((fsize & 0xfff) == 0x200) {
fsize -= 0x200;
@@ -48,29 +57,23 @@ char *filetype = fn + i;
return true;
}
void FileReader::read(uint8 **buffer, uint32 length) {
uint8 *data;
if(length == 0) {
/* read the entire file into RAM */
data = (uint8*)memalloc(fsize);
fread(data, 1, fsize, fp);
} else if(length > fsize) {
/* read the entire file into RAM, pad the rest with 0x00s */
data = (uint8*)memalloc(length);
memset(data, 0, length);
fread(data, 1, fsize, fp);
} else { //fsize >= length
/* read as much of the file as possible, truncate the rest */
data = (uint8*)memalloc(length);
fread(data, 1, length, fp);
}
*buffer = data;
}
uint32 FileReader::size() {
return fsize;
}
void FileReader::close() {
if(fp)fclose(fp);
}
void FileWriter::write(uint8 *buffer, uint32 length) {
if(!fp)return;
fwrite(buffer, 1, length, fp);
}
bool FileWriter::open(char *fn) {
fp = fopen(fn, "wb");
if(!fp)return false;
return true;
}
void FileWriter::close() {
if(fp)fclose(fp);
}
+23 -1
View File
@@ -10,11 +10,33 @@ FILE *fp;
uint32 fsize;
public:
enum {
TYPE_ROM = 0,
TYPE_SRAM = 1
};
uint32 size();
void read(uint8 **buffer, uint32 length = 0);
bool open(char *fn);
bool open(uint8 type, char *fn);
void close();
FileReader() { fp = 0; fsize = 0; }
~FileReader() { if(fp)fclose(fp); }
};
class Writer {
public:
virtual void write(uint8 *buffer, uint32 length) = 0;
};
class FileWriter : public Writer {
private:
FILE *fp;
public:
void write(uint8 *buffer, uint32 length);
bool open(char *fn);
void close();
FileWriter() { fp = 0; }
~FileWriter() { if(fp)fclose(fp); }
};
+2 -2
View File
@@ -1,5 +1,5 @@
CC = cl
CFLAGS = /nologo /O2 /Ob2
CFLAGS = /nologo /O2 /Ogityb2 /Gr /Gs
OBJS = winmain.obj \
libstring.obj libconfig.obj \
clock.obj bclock.obj \
@@ -8,7 +8,7 @@ OBJS = winmain.obj \
cpu.obj bcpu.obj \
ppu.obj bppu.obj \
snes.obj
LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib
LIBS = kernel32.lib user32.lib gdi32.lib comdlg32.lib ddraw.lib dxguid.lib
all: $(OBJS)
$(CC) /Febsnes_g2.exe $(CFLAGS) $(OBJS) $(LIBS)
+16 -13
View File
@@ -86,7 +86,7 @@ void bSNES::run() {
}
void bSNES::render_frame() {
renderer->update();
dd_renderer->update();
}
/***********************
@@ -94,18 +94,21 @@ void bSNES::render_frame() {
***********************/
#define KeyState(key) ((GetAsyncKeyState(key) & 0x8000)?1:0)
void bSNES::poll_input() {
joypad1.up = KeyState(VK_UP);
joypad1.down = KeyState(VK_DOWN);
joypad1.left = KeyState(VK_LEFT);
joypad1.right = KeyState(VK_RIGHT);
joypad1.select = KeyState(VK_LSHIFT) | KeyState(VK_RSHIFT);
joypad1.start = KeyState(VK_RETURN);
joypad1.y = KeyState('A');
joypad1.b = KeyState('Z');
joypad1.x = KeyState('S');
joypad1.a = KeyState('X');
joypad1.l = KeyState('D');
joypad1.r = KeyState('C');
/* Only capture input when main window has focus */
if(GetForegroundWindow() == w_main->hwnd) {
joypad1.up = KeyState(VK_UP);
joypad1.down = KeyState(VK_DOWN);
joypad1.left = KeyState(VK_LEFT);
joypad1.right = KeyState(VK_RIGHT);
joypad1.select = KeyState(VK_LSHIFT) | KeyState(VK_RSHIFT);
joypad1.start = KeyState(VK_RETURN);
joypad1.y = KeyState('A');
joypad1.b = KeyState('Z');
joypad1.x = KeyState('S');
joypad1.a = KeyState('X');
joypad1.l = KeyState('D');
joypad1.r = KeyState('C');
}
//Check for debugger-based key locks
if(is_debugger_enabled == true) {
+11 -2
View File
@@ -6,10 +6,19 @@ public:
struct {
uint32 mode;
uint32 use_vram;
uint32 color_curve;
uint32 vblank;
}video;
struct {
uint32 show_fps;
}gui;
Config() {
__config_add(video.mode, 1, DEC);
__config_add(video.use_vram, true, TRUEFALSE);
__config_add(video.mode, 1, DEC);
__config_add(video.use_vram, true, TRUEFALSE);
__config_add(video.color_curve, true, ENABLED);
__config_add(video.vblank, false, TRUEFALSE);
__config_add(gui.show_fps, true, TRUEFALSE);
}
}cfg;
+340
View File
@@ -0,0 +1,340 @@
DDRenderer::DDRenderer() {
lpdd = 0;
lpdd7 = 0;
lpdds = 0;
lpddsb = 0;
lpddc = 0;
int i, c;
for(i=0,c=0;i<16;i++) {
color_curve_table[i] = c;
c = c + i + 1;
}
for(;i<31;i++) {
color_curve_table[i] = c;
c += 8;
}
color_curve_table[i] = 0xff;
}
void DDRenderer::update_color_lookup_table() {
int i, r, g, b;
lpddsb->GetSurfaceDesc(&ddsd);
color_depth = ddsd.ddpfPixelFormat.dwRGBBitCount;
if(color_depth == 15) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
if(cfg.video.color_curve) {
r = color_curve_table[r] >> 3;
g = color_curve_table[g] >> 3;
b = color_curve_table[b] >> 3;
}
color_lookup_table[i] = (r << 10) | (g << 5) | (b);
}
} else if(color_depth == 16) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
if(cfg.video.color_curve) {
r = color_curve_table[r] >> 3;
g = color_curve_table[g] >> 2;
b = color_curve_table[b] >> 3;
} else {
g = (g << 1) | (g >> 4);
}
color_lookup_table[i] = (r << 11) | (g << 5) | (b);
}
} else if(color_depth == 32) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
if(cfg.video.color_curve) {
r = color_curve_table[r];
g = color_curve_table[g];
b = color_curve_table[b];
} else {
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
}
color_lookup_table[i] = (r << 16) | (g << 8) | (b);
}
} else {
alert("Error: Unsupported color depth [%d]", color_depth);
}
}
void DDRenderer::set_window(HWND hwnd_handle) { hwnd = hwnd_handle; }
/*
This function tries to create a 16-bit backbuffer whenever possible,
even in 24/32-bit mode. This is possible because DDraw automatically
handles conversion from 16bpp->32bpp in hardware. This only works
when both the source and dest buffers are in VRAM, though.
The SNES resolution is 256x224. The top scanline is never drawn, so
256x223 is used. Hires mode doubles the screen width, and hires+interlace
double the screen height, making the resolution 512x446.
There is one more problem, however. On some video cards, when blitting
from video memory from 256x223->512x446, a bilinear filter is applied by
the video card, and sometimes this filter tries to read past the source
video memory to get interpolation data. This results in a line of garble
on the right and bottom edges of the screen. Therefore, an additional
4 pixels in each direction is added to the backbuffer.
The backbuffer is thusly 512+4 * 476+4
*/
void DDRenderer::create_backbuffer() {
int color_depth;
lpdds->GetSurfaceDesc(&ddsd);
color_depth = ddsd.ddpfPixelFormat.dwRGBBitCount;
if(color_depth == 15 || color_depth == 16) {
goto try_native_backbuffer;
} else {
if(cfg.video.use_vram == false) {
goto try_native_backbuffer;
}
}
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if(cfg.video.use_vram) {
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = 512 + 4;
ddsd.dwHeight = 476 + 4;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
ddsd.ddpfPixelFormat.dwRBitMask = 0xf800;
ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
if(lpdd->CreateSurface(&ddsd, &lpddsb, 0) == DD_OK)goto clear_backbuffer;
try_native_backbuffer:
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if(cfg.video.use_vram) {
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = 512 + 4;
ddsd.dwHeight = 476 + 4;
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
clear_backbuffer:
if(!lpddsb) {
alert("Error: Failed to create DirectDraw backbuffer, cannot continue");
exit(0);
}
DDBLTFX fx;
fx.dwSize = sizeof(DDBLTFX);
fx.dwFillColor = 0x00000000;
lpddsb->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
}
void DDRenderer::to_windowed() {
destroy();
fullscreen = false;
DirectDrawCreate(0, &lpdd, 0);
lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwnd);
lpdds->SetClipper(lpddc);
create_backbuffer();
update_color_lookup_table();
redraw();
}
void DDRenderer::to_fullscreen(int _width, int _height) {
destroy();
fullscreen = true;
width = _width;
height = _height;
DirectDrawCreate(0, &lpdd, 0);
/*
lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7);
lpdd7->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd7->SetDisplayMode(width, height, 16, 60, 0);
*/
lpdd->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd->SetDisplayMode(width, height, 16);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwnd);
lpdds->SetClipper(lpddc);
create_backbuffer();
update_color_lookup_table();
redraw();
}
void DDRenderer::set_source_window() {
SetRect(&lpddrc, 0, 0,
(ppu->output->hires == false)?256:512,
(ppu->output->interlace == false)?223:446);
}
void DDRenderer::redraw() {
RECT rd;
POINT p;
HRESULT hr;
int rx, ry;
if(fullscreen == false) {
p.x = p.y = 0;
ClientToScreen(hwnd, &p);
GetClientRect(hwnd, &rd);
OffsetRect(&rd, p.x, p.y);
} else {
switch(width) {
case 640: //x480
SetRect(&rd, 0, 2, 512, 448);
OffsetRect(&rd, (640 - 512) / 2, (480 - 446) / 2);
break;
case 1024: //x768
SetRect(&rd, 0, 0, 1024, 768);
break;
}
}
if(cfg.video.vblank) {
lpdd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
}
hr = lpdds->Blt(&rd, lpddsb, &lpddrc, DDBLT_WAIT, 0);
if(hr == DDERR_SURFACELOST) {
lpdds->Restore();
lpddsb->Restore();
}
if(cfg.gui.show_fps == false)return;
uint32 fps;
char s[256], t[256];
fps_timer->tick();
if(fps_timer->second_passed() == true) {
sprintf(s, BSNES_TITLE);
if(rom_image->loaded() == true) {
fps = fps_timer->get_ticks();
if(w_main->frameskip == 0) {
sprintf(t, " : %d fps", fps);
} else {
sprintf(t, " : %d fps [fs: %d]", fps * (1 + w_main->frameskip), w_main->frameskip);
}
strcat(s, t);
}
SetWindowText(w_main->hwnd, s);
fps_timer->reset();
}
}
#include "dd_renderer16.cpp"
void DDRenderer::update16() {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
set_source_window();
if(ppu->output->hires == false) {
if(ppu->output->interlace == false) {
update16_256x224();
} else {
update16_256x448();
}
} else {
if(ppu->output->interlace == false) {
update16_512x224();
} else {
update16_512x448();
}
}
lpddsb->Unlock(0);
}
#include "dd_renderer32.cpp"
void DDRenderer::update32() {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
set_source_window();
if(ppu->output->hires == false) {
if(ppu->output->interlace == false) {
update32_256x224();
} else {
update32_256x448();
}
} else {
if(ppu->output->interlace == false) {
update32_512x224();
} else {
update32_512x448();
}
}
lpddsb->Unlock(0);
}
void DDRenderer::update() {
switch(color_depth) {
case 15:
case 16:
update16();
break;
case 32:
update32();
break;
}
redraw();
}
void DDRenderer::destroy() {
if(lpddc) {
lpddc->Release();
lpddc = 0;
}
if(lpddsb) {
lpddsb->Release();
lpddsb = 0;
}
if(lpdds) {
lpdds->Release();
lpdds = 0;
}
if(lpdd7) {
lpdd7->Release();
lpdd7 = 0;
}
if(lpdd) {
lpdd->Release();
lpdd = 0;
}
}
+40
View File
@@ -0,0 +1,40 @@
#include <ddraw.h>
class DDRenderer {
public:
LPDIRECTDRAW lpdd;
LPDIRECTDRAW7 lpdd7;
LPDIRECTDRAWSURFACE lpdds, lpddsb;
LPDIRECTDRAWCLIPPER lpddc;
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
RECT lpddrc;
HWND hwnd;
bool fullscreen;
int width, height; //used for fullscreen mode clipping only
uint8 color_depth;
uint8 color_curve_table[32];
uint32 color_lookup_table[65536];
void set_window(HWND hwnd_handle);
void create_backbuffer();
void to_windowed();
void to_fullscreen(int _width, int _height);
void set_source_window();
void redraw();
inline void update16_256x224();
inline void update16_256x448();
inline void update16_512x224();
inline void update16_512x448();
void update16();
inline void update32_256x224();
inline void update32_256x448();
inline void update32_512x224();
inline void update32_512x448();
void update32();
void update();
void destroy();
void update_color_lookup_table();
DDRenderer();
};
DDRenderer *dd_renderer;
+123
View File
@@ -0,0 +1,123 @@
inline void DDRenderer::update16_256x224() {
uint16 *src;
uint16 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint16*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 1) - 256;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 8;
}
for(y=1+overscan_adjust;y<224+overscan_adjust;y++) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
src += 512;
}
}
inline void DDRenderer::update16_256x448() {
uint16 *src;
uint16 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint16*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 1) - 256;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 16;
}
for(y=2+overscan_adjust;y<448+overscan_adjust;y++) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
if(ppu->output->line[y >> 1].interlace == false) {
src += (y & 1)?512:-512;
}
}
}
inline void DDRenderer::update16_512x224() {
uint16 *src;
uint16 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint16*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 1) - 512;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 8;
}
for(y=1+overscan_adjust;y<224+overscan_adjust;y++) {
if(ppu->output->line[y].hires == true) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
} else {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
*dest++ = color_lookup_table[*src];
src += 2;
}
}
dest += pitch;
src += 512;
}
}
inline void DDRenderer::update16_512x448() {
uint16 *src;
uint16 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint16*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 1) - 512;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 16;
}
for(y=2+overscan_adjust;y<448+overscan_adjust;y++) {
if(ppu->output->line[y >> 1].hires == true) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
} else {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
*dest++ = color_lookup_table[*src];
src += 2;
}
}
dest += pitch;
if(ppu->output->line[y >> 1].interlace == false) {
src += (y & 1)?512:-512;
}
}
}
+123
View File
@@ -0,0 +1,123 @@
inline void DDRenderer::update32_256x224() {
uint16 *src;
uint32 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint32*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 2) - 256;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 8;
}
for(y=1+overscan_adjust;y<224+overscan_adjust;y++) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
src += 512;
}
}
inline void DDRenderer::update32_256x448() {
uint16 *src;
uint32 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint32*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 2) - 256;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 16;
}
for(y=2+overscan_adjust;y<448+overscan_adjust;y++) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
if(ppu->output->line[y >> 1].interlace == false) {
src += (y & 1)?512:-512;
}
}
}
inline void DDRenderer::update32_512x224() {
uint16 *src;
uint32 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint32*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 2) - 512;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 8;
}
for(y=1+overscan_adjust;y<224+overscan_adjust;y++) {
if(ppu->output->line[y].hires == true) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
} else {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
*dest++ = color_lookup_table[*src];
src += 2;
}
}
dest += pitch;
src += 512;
}
}
inline void DDRenderer::update32_512x448() {
uint16 *src;
uint32 *dest;
uint32 pitch;
int x, y;
src = (uint16*)ppu->output->buffer + (1 << 10);
dest = (uint32*)ddsd.lpSurface;
pitch = (ddsd.lPitch >> 2) - 512;
int overscan_adjust = 0;
if(clock->overscan() == true) {
src += 8 << 10;
overscan_adjust = 16;
}
for(y=2+overscan_adjust;y<448+overscan_adjust;y++) {
if(ppu->output->line[y >> 1].hires == true) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
} else {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
*dest++ = color_lookup_table[*src];
src += 2;
}
}
dest += pitch;
if(ppu->output->line[y >> 1].interlace == false) {
src += (y & 1)?512:-512;
}
}
}
-29
View File
@@ -67,32 +67,3 @@ va_list args;
w_console->write(str, Console::DEBUG_MESSAGE);
}
}
uint32 load_file(char *fn, uint8 **buffer) {
FILE *fp;
uint8 *data;
int fsize;
fp = fopen(fn, "rb");
if(!fp)return 0;
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
if(!fsize) {
fclose(fp);
return 0;
}
fseek(fp, 0, SEEK_SET);
data = (uint8*)memalloc(fsize);
fread(data, 1, fsize, fp);
fclose(fp);
*buffer = data;
return fsize;
}
bool save_file(char *fn, uint8 *data, uint32 size) {
FILE *fp;
fp = fopen(fn, "wb");
if(!fp)return false;
fwrite(data, 1, size, fp);
fclose(fp);
return true;
}
+15 -20
View File
@@ -22,23 +22,19 @@ bool ROMImage::load() {
dprintf("* Loading [%s]...", rom_fn);
Reader *rf = new FileReader();
FileReader *f_rf = static_cast<FileReader*>(rf);
if(!f_rf->open(rom_fn)) {
FileReader *rf = new FileReader();
if(!rf->open(FileReader::TYPE_ROM, rom_fn)) {
alert("Error loading image file [%s]!", rom_fn);
return false;
}
mem_bus->rom->load_rom(rf);
f_rf->close();
delete rf;
mem_bus->rom->load_rom(static_cast<Reader*>(rf));
rf->close();
uint8 *sram_data;
uint32 sram_size;
sram_size = load_file(sram_fn, &sram_data);
if(sram_size) {
mem_bus->rom->load_sram(sram_data, sram_size);
memfree(sram_data);
}
rf->open(FileReader::TYPE_SRAM, sram_fn);
mem_bus->rom->load_sram(static_cast<Reader*>(rf));
rf->close();
delete(rf);
file_loaded = true;
bsnes->debugger_activate();
@@ -48,13 +44,12 @@ uint32 sram_size;
void ROMImage::unload() {
if(file_loaded == false)return;
uint8 *sram_data;
uint32 sram_size;
sram_size = mem_bus->rom->save_sram(&sram_data);
if(sram_size) {
save_file(sram_fn, sram_data, sram_size);
memfree(sram_data);
}
FileWriter *wf = new FileWriter();
wf->open(sram_fn);
mem_bus->rom->save_sram(static_cast<Writer*>(wf));
wf->close();
delete(wf);
file_loaded = false;
bsnes->debugger_deactivate();
+13 -8
View File
@@ -1,7 +1,7 @@
HFONT hFont, hMonofont;
#include "dd_renderer.cpp"
#include "ui_window.cpp"
#include "ui_render.cpp"
#include "ui_main.cpp"
#include "ui_console.cpp"
#include "ui_bp.cpp"
@@ -29,18 +29,23 @@ void CreateWindows() {
}
void init_ui0() {
renderer = new Render();
w_main = new MainWindow();
w_console = new Console();
w_bp = new BreakpointEditor();
w_memory = new MemoryEditor();
dd_renderer = new DDRenderer();
w_main = new MainWindow();
w_console = new Console();
w_bp = new BreakpointEditor();
w_memory = new MemoryEditor();
}
void init_ui1() {
CreateFonts();
CreateWindows();
SetFocus(w_main->hwnd);
renderer->set_window(w_main->hwnd);
renderer->to_windowed();
dd_renderer->set_window(w_main->hwnd);
dd_renderer->to_windowed();
w_main->show_menu();
w_main->set_video_mode(cfg.video.mode);
w_main->set_frameskip(0);
bsnes->debugger_deactivate();
}
+24 -32
View File
@@ -1,7 +1,9 @@
enum {
VIDEOMODE_256x224w = 0,
VIDEOMODE_512x448w,
VIDEOMODE_960x720w
VIDEOMODE_960x720w,
VIDEOMODE_640x480f,
VIDEOMODE_1024x768f
};
enum {
@@ -23,6 +25,12 @@ enum {
MENU_SETTINGS_VIDEOMODE_256x224w,
MENU_SETTINGS_VIDEOMODE_512x448w,
MENU_SETTINGS_VIDEOMODE_960x720w,
MENU_SETTINGS_VIDEOMODE_640x480f,
MENU_SETTINGS_VIDEOMODE_1024x768f,
MENU_SETTINGS_USEVRAM,
MENU_SETTINGS_VBLANK,
MENU_SETTINGS_COLORCURVE,
MENU_SETTINGS_SHOWFPS,
MENU_SETTINGS_DEBUGGER
};
@@ -122,27 +130,36 @@ enum {
class Window {
public:
HWND hwnd;
HWND hwnd;
HMENU hmenu;
bool visible, menu_visible;
bool fullscreen, visible, cursor_visible;
RECT workarea, wa_offset;
struct { int width, height; }window;
void resize(int width, int height);
void center();
void show_menu();
void hide_menu();
void show();
void hide();
void to_left(HWND _hwnd = 0);
void to_center();
void to_right();
void to_top();
void to_middle();
void to_bottom(HWND _hwnd = 0);
void hide();
void show();
void show_menu();
void hide_menu();
Window();
};
class MainWindow : public Window {
public:
uint8 frameskip;
int width, height;
void to_fullscreen();
void to_windowed();
void set_frameskip(uint8 fs);
void adjust_video_mode(bool fullscreen_mode);
void set_video_mode(uint8 mode);
void menu_load();
void menu_unload();
@@ -225,28 +242,3 @@ uint32 edit_mode, edit_addr, edit_mask;
};
MemoryEditor *w_memory;
#include <ddraw.h>
class Render {
public:
LPDIRECTDRAW lpdd;
LPDIRECTDRAWSURFACE lpdds, lpddsb;
LPDIRECTDRAWCLIPPER lpddc;
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
HWND hwnd;
uint8 color_depth;
void set_window(HWND hwnd_handle);
void to_windowed();
void to_fullscreen();
void set_source_window(RECT *rs);
void redraw();
void update16();
void update32();
void update();
void destroy();
void update_color_lookup_table();
Render();
};
Render *renderer;
+126 -29
View File
@@ -15,32 +15,86 @@ void MainWindow::set_frameskip(uint8 fs) {
w_main->frameskip = fs;
}
void MainWindow::set_video_mode(uint8 mode) {
hide();
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_UNCHECKED);
switch(mode) {
case VIDEOMODE_256x224w:
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_CHECKED);
resize(256, 223);
break;
case VIDEOMODE_512x448w:
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED);
resize(512, 446);
break;
case VIDEOMODE_960x720w:
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_CHECKED);
resize(960, 720);
break;
void MainWindow::to_fullscreen() {
if(bsnes->debugger_enabled() == true) {
bsnes->debugger_disable();
}
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP);
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TOPMOST);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, width, height, 0);
dd_renderer->to_fullscreen(width, height);
hide_menu();
}
void MainWindow::to_windowed() {
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
SetWindowLong(hwnd, GWL_EXSTYLE, 0);
//always call in case the video mode change is simply changing
//the backbuffer from a VRAM surface to a DRAM surface.
dd_renderer->to_windowed();
if(dd_renderer->fullscreen == true) {
show_menu();
}
}
void MainWindow::adjust_video_mode(bool fullscreen_mode) {
fullscreen = fullscreen_mode;
if(fullscreen == true) {
to_fullscreen();
} else {
to_windowed();
}
resize(width, height);
if(fullscreen == false)center();
if(bsnes->debugger_enabled() == true) {
to_bottom();
to_right();
} else {
to_middle();
to_center();
}
}
void MainWindow::set_video_mode(uint8 mode) {
hide();
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED);
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_UNCHECKED);
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_UNCHECKED);
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_640x480f, MF_UNCHECKED);
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_1024x768f, MF_UNCHECKED);
switch(mode) {
case VIDEOMODE_256x224w:
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_CHECKED);
width = 256;
height = 223;
adjust_video_mode(false);
break;
case VIDEOMODE_512x448w:
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_512x448w, MF_CHECKED);
width = 512;
height = 446;
adjust_video_mode(false);
break;
case VIDEOMODE_960x720w:
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_960x720w, MF_CHECKED);
width = 960;
height = 720;
adjust_video_mode(false);
break;
case VIDEOMODE_640x480f:
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_640x480f, MF_CHECKED);
width = 640;
height = 480;
adjust_video_mode(true);
break;
case VIDEOMODE_1024x768f:
CheckMenuItem(hmenu, MENU_SETTINGS_VIDEOMODE_1024x768f, MF_CHECKED);
width = 1024;
height = 768;
adjust_video_mode(true);
break;
}
cfg.video.mode = mode;
show();
}
@@ -79,6 +133,16 @@ void MainWindow::menu_unload() {
long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch(msg) {
case WM_KEYDOWN:
if(wparam == VK_ESCAPE) {
if(GetMenu(w_main->hwnd) == NULL) {
w_main->show_menu();
} else {
w_main->hide_menu();
}
w_main->center();
}
break;
case WM_COMMAND:
switch(LOWORD(wparam)) {
case MENU_FILE_LOAD:
@@ -123,6 +187,31 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
case MENU_SETTINGS_VIDEOMODE_960x720w:
w_main->set_video_mode(VIDEOMODE_960x720w);
break;
case MENU_SETTINGS_VIDEOMODE_640x480f:
w_main->set_video_mode(VIDEOMODE_640x480f);
break;
case MENU_SETTINGS_VIDEOMODE_1024x768f:
w_main->set_video_mode(VIDEOMODE_1024x768f);
break;
case MENU_SETTINGS_USEVRAM:
cfg.video.use_vram ^= 1;
w_main->set_video_mode(cfg.video.mode);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_USEVRAM, (cfg.video.use_vram)?MF_CHECKED:MF_UNCHECKED);
break;
case MENU_SETTINGS_VBLANK:
cfg.video.vblank ^= 1;
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VBLANK, (cfg.video.vblank)?MF_CHECKED:MF_UNCHECKED);
break;
case MENU_SETTINGS_COLORCURVE:
cfg.video.color_curve ^= 1;
dd_renderer->update_color_lookup_table();
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_COLORCURVE, (cfg.video.color_curve)?MF_CHECKED:MF_UNCHECKED);
break;
case MENU_SETTINGS_SHOWFPS:
cfg.gui.show_fps ^= 1;
SetWindowText(w_main->hwnd, BSNES_TITLE);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_SHOWFPS, (cfg.gui.show_fps)?MF_CHECKED:MF_UNCHECKED);
break;
case MENU_SETTINGS_DEBUGGER:
if(bsnes->debugger_enabled() == true) {
bsnes->debugger_disable();
@@ -137,7 +226,7 @@ long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
PostQuitMessage(0);
break;
case WM_PAINT:
renderer->redraw();
dd_renderer->redraw();
break;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
@@ -157,7 +246,7 @@ WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
w_main->hwnd = CreateWindow("bsnes", "bsnes v" BSNES_VERSION " ~byuu",
w_main->hwnd = CreateWindowEx(0, "bsnes", "bsnes v" BSNES_VERSION " ~byuu",
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
0, 0, 512, 446,
0, 0, GetModuleHandle(0), 0);
@@ -192,18 +281,26 @@ HMENU hsubmenu, hbranchmenu;
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Frameskip");
hbranchmenu = CreatePopupMenu();
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_256x224w, "256x224 Windowed [16:15]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_512x448w, "512x448 Windowed [16:15]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_960x720w, "960x720 Windowed [4:3]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_256x224w, "256x224 Windowed [16:15]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_512x448w, "512x448 Windowed [16:15]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_960x720w, "960x720 Windowed [4:3]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_640x480f, "640x480 Fullscreen [16:15]");
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_1024x768f, "1024x768 Fullscreen [4:3]");
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Video Mode");
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_USEVRAM, "Use &Video Memory Surface");
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_VBLANK, "&Wait for Vertical Retrace");
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_COLORCURVE, "Use &Color Curve");
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_SHOWFPS, "&Show FPS");
AppendMenu(hsubmenu, MF_SEPARATOR, 0, "");
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_DEBUGGER, "&Debugger");
AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings");
w_main->show_menu();
w_main->set_video_mode(cfg.video.mode);
w_main->set_frameskip(0);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_USEVRAM, (cfg.video.use_vram)?MF_CHECKED:MF_UNCHECKED);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VBLANK, (cfg.video.vblank)?MF_CHECKED:MF_UNCHECKED);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_COLORCURVE, (cfg.video.color_curve)?MF_CHECKED:MF_UNCHECKED);
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_SHOWFPS, (cfg.gui.show_fps)?MF_CHECKED:MF_UNCHECKED);
}
MainWindow::MainWindow() {
-332
View File
@@ -1,332 +0,0 @@
//This is in the global namespace for inline assembly optimizations.
//If it were in a class, I would have to cast a pointer to it, and
//to read from a pointer array requires an extra opcode:
//mov eax,[array+eax*4] -> lea ebx,[parray] ; mov ebx,[ebx+eax*4]
uint32 color_lookup_table[65536];
Render::Render() {
lpdd = 0;
lpdds = 0;
lpddsb = 0;
lpddc = 0;
}
void Render::update_color_lookup_table() {
int i, r, g, b;
lpdds->GetSurfaceDesc(&ddsd);
color_depth = ddsd.ddpfPixelFormat.dwRGBBitCount;
if(color_depth == 15) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
color_lookup_table[i] = (r << 10) | (g << 5) | (b);
}
} else if(color_depth == 16) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
g = (g << 1) | (g >> 4);
color_lookup_table[i] = (r << 11) | (g << 5) | (b);
}
} else if(color_depth == 32) {
for(i=0;i<65536;i++) {
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
color_lookup_table[i] = (r << 16) | (g << 8) | (b);
}
} else {
alert("Error: Unsupported color depth [%d]", color_depth);
}
}
void Render::set_window(HWND hwnd_handle) { hwnd = hwnd_handle; }
void Render::to_windowed() {
destroy();
DirectDrawCreate(0, &lpdd, 0);
lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwnd);
lpdds->SetClipper(lpddc);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if(cfg.video.use_vram) {
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = 512;
ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
update_color_lookup_table();
update();
}
void Render::to_fullscreen() {
destroy();
DirectDrawCreate(0, &lpdd, 0);
lpdd->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd->SetDisplayMode(640, 480, 16);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpdd->CreateSurface(&ddsd, &lpdds, 0);
lpdd->CreateClipper(0, &lpddc, 0);
lpddc->SetHWnd(0, hwnd);
lpdds->SetClipper(lpddc);
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
if(cfg.video.use_vram) {
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
} else {
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
ddsd.dwWidth = 512;
ddsd.dwHeight = 478;
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
update_color_lookup_table();
update();
}
void Render::set_source_window(RECT *rs) {
switch(ppu->output->frame_mode) {
case 0:SetRect(rs, 0, 0, 256, 223);break;
case 1:SetRect(rs, 0, 0, 256, 446);break;
case 2:SetRect(rs, 0, 0, 512, 223);break;
case 3:SetRect(rs, 0, 0, 512, 446);break;
}
}
void Render::redraw() {
RECT rd, rs;
POINT p;
HRESULT hr;
p.x = p.y = 0;
ClientToScreen(hwnd, &p);
GetClientRect(hwnd, &rd);
OffsetRect(&rd, p.x, p.y);
set_source_window(&rs);
hr = lpdds->Blt(&rd, lpddsb, &rs, DDBLT_WAIT, 0);
if(hr == DDERR_SURFACELOST) {
lpdds->Restore();
lpddsb->Restore();
}
uint32 fps;
char s[256], t[256];
fps_timer->tick();
if(fps_timer->second_passed() == true) {
sprintf(s, "bsnes v" BSNES_VERSION " ~byuu");
if(rom_image->loaded() == true) {
fps = fps_timer->get_ticks();
if(w_main->frameskip == 0) {
sprintf(t, " : %d fps", fps);
} else {
sprintf(t, " : %d fps [fs: %d]", fps * (1 + w_main->frameskip), w_main->frameskip);
}
strcat(s, t);
}
SetWindowText(w_main->hwnd, s);
fps_timer->reset();
}
}
void Render::update16() {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
uint16 *src = (uint16*)ppu->output->buffer;
uint16 *dest = (uint16*)ddsd.lpSurface;
uint32 pitch;
int x, y;
/* skip first scanline */
src += 1024;
if(clock->overscan() == true) {
if(ppu->output->frame_mode & PPUOutput::INTERLACE) {
src += 1024 * 16;
} else {
src += 1024 * 8;
}
}
if(ppu->output->frame_mode == PPUOutput::NORMAL) {
/* 256x223 */
pitch = (ddsd.lPitch >> 1) - 256;
y = 223;
while(y--) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
src += 512;
}
} else if(ppu->output->frame_mode == PPUOutput::INTERLACE) {
/* 256x446 */
pitch = (ddsd.lPitch >> 1) - 256;
y = 446;
while(y--) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
}
} else if(ppu->output->frame_mode == PPUOutput::DOUBLEWIDTH) {
/* 512x223 */
pitch = (ddsd.lPitch >> 1) - 512;
y = 223;
while(y--) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
dest += pitch;
src += 512;
}
} else {
/* 512x446 */
pitch = (ddsd.lPitch >> 1) - 512;
y = 446;
while(y--) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
dest += pitch;
}
}
lpddsb->Unlock(0);
}
void Render::update32() {
HRESULT hr;
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
if(hr != DD_OK)return;
uint16 *src = (uint16*)ppu->output->buffer;
uint32 *dest = (uint32*)ddsd.lpSurface;
uint32 pitch;
int x, y;
/* skip first scanline */
src += 1024;
if(clock->overscan() == true) {
if(ppu->output->frame_mode & PPUOutput::INTERLACE) {
src += 1024 * 16;
} else {
src += 1024 * 8;
}
}
if(ppu->output->frame_mode == PPUOutput::NORMAL) {
/* 256x223 */
pitch = (ddsd.lPitch >> 2) - 256;
y = 223;
while(y--) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
src += 512;
}
} else if(ppu->output->frame_mode == PPUOutput::INTERLACE) {
/* 256x446 */
pitch = (ddsd.lPitch >> 2) - 256;
y = 446;
while(y--) {
x = 256;
while(x--) {
*dest++ = color_lookup_table[*src];
src += 2;
}
dest += pitch;
}
} else if(ppu->output->frame_mode == PPUOutput::DOUBLEWIDTH) {
/* 512x223 */
pitch = (ddsd.lPitch >> 2) - 512;
y = 223;
while(y--) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
dest += pitch;
src += 512;
}
} else {
/* 512x446 */
pitch = (ddsd.lPitch >> 2) - 512;
y = 446;
while(y--) {
x = 512;
while(x--) {
*dest++ = color_lookup_table[*src++];
}
dest += pitch;
}
}
lpddsb->Unlock(0);
}
void Render::update() {
switch(color_depth) {
case 15:
case 16:
update16();
break;
case 32:
update32();
break;
}
redraw();
}
void Render::destroy() {
if(lpddc) {
lpddc->Release();
lpddc = 0;
}
if(lpddsb) {
lpddsb->Release();
lpddsb = 0;
}
if(lpdds) {
lpdds->Release();
lpdds = 0;
}
if(lpdd) {
lpdd->Release();
lpdd = 0;
}
}
+108 -36
View File
@@ -1,14 +1,95 @@
void Window::resize(int width, int height) {
int style;
window.width = width;
window.height = height;
style = GetWindowLong(hwnd, GWL_STYLE);
if(style & WS_CAPTION) {
width += GetSystemMetrics(SM_CXFIXEDFRAME) << 1;
height += GetSystemMetrics(SM_CYFIXEDFRAME) << 1;
height += GetSystemMetrics(SM_CYCAPTION);
}
if(width == GetSystemMetrics(SM_CXSCREEN) && height == GetSystemMetrics(SM_CYSCREEN)) {
fullscreen = true;
} else {
fullscreen = false;
}
if(fullscreen == false) {
if(GetMenu(hwnd) != 0) {
height += GetSystemMetrics(SM_CYMENU);
}
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
} else {
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, width, height, 0);
}
}
void Window::center() {
RECT rc;
int x, y, wx, wy;
hide();
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER);
GetClientRect(hwnd, &rc);
x = width + width - (rc.right - rc.left);
y = height + height - (rc.bottom - rc.top);
wx = (GetSystemMetrics(SM_CXSCREEN) - x) / 2;
wy = (GetSystemMetrics(SM_CYSCREEN) - y) / 2;
SetWindowPos(hwnd, 0, wx, wy, x, y, SWP_NOZORDER);
POINT p;
if(fullscreen == true) {
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, window.width, window.height, 0);
return;
}
GetWindowRect(hwnd, &rc);
p.x = p.y = 0;
ClientToScreen(hwnd, &p);
OffsetRect(&rc, p.x, p.y);
int sw = GetSystemMetrics(SM_CXSCREEN),
sh = GetSystemMetrics(SM_CYSCREEN);
int x = (sw - (rc.right - rc.left)) >> 1,
y = (sh - (rc.bottom - rc.top)) >> 1;
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
void Window::show_menu() {
RECT rc;
int width, height;
if(GetMenu(hwnd) != NULL)return;
SetMenu(hwnd, hmenu);
if(cursor_visible == false) {
ShowCursor(TRUE);
cursor_visible = true;
}
if(fullscreen == true) {
return;
}
resize(window.width, window.height);
}
void Window::hide_menu() {
RECT rc;
int width, height;
if(GetMenu(hwnd) == NULL)return;
SetMenu(hwnd, NULL);
if(fullscreen == true) {
if(cursor_visible == true) {
ShowCursor(FALSE);
cursor_visible = false;
}
return;
}
resize(window.width, window.height);
}
void Window::show() {
int style;
style = GetWindowLong(hwnd, GWL_STYLE);
if(style & WS_VISIBLE)return;
ShowWindow(hwnd, SW_NORMAL);
}
void Window::hide() {
int style;
style = GetWindowLong(hwnd, GWL_STYLE);
if(!(style & WS_VISIBLE))return;
ShowWindow(hwnd, SW_HIDE);
}
void Window::to_left(HWND _hwnd) {
@@ -17,6 +98,8 @@ int offset = 0;
if(_hwnd) {
GetWindowRect(_hwnd, &rc);
offset = rc.right;
} else {
offset = wa_offset.left;
}
GetWindowRect(hwnd, &rc);
rc.left = offset;
@@ -34,13 +117,14 @@ void Window::to_right() {
RECT rc;
GetWindowRect(hwnd, &rc);
rc.left = GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left);
rc.left -= wa_offset.right;
SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
void Window::to_top() {
RECT rc;
GetWindowRect(hwnd, &rc);
rc.top = 0;
rc.top = wa_offset.top;
SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
@@ -60,34 +144,22 @@ int offset = 0;
}
GetWindowRect(hwnd, &rc);
rc.top = GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top) - offset;
rc.top -= wa_offset.bottom;
SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
void Window::hide() {
if(visible == true) {
ShowWindow(hwnd, SW_HIDE);
visible = false;
}
}
void Window::show() {
if(visible == false) {
ShowWindow(hwnd, SW_NORMAL);
visible = true;
}
}
void Window::show_menu() {
SetMenu(hwnd, hmenu);
menu_visible = true;
}
void Window::hide_menu() {
SetMenu(hwnd, 0);
menu_visible = false;
}
Window::Window() {
visible = false;
menu_visible = false;
fullscreen = false;
visible = false;
cursor_visible = true;
hmenu = NULL;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea, 0);
int sw = GetSystemMetrics(SM_CXSCREEN),
sh = GetSystemMetrics(SM_CYSCREEN);
wa_offset.left = workarea.left;
wa_offset.top = workarea.top;
wa_offset.right = sw - workarea.right;
wa_offset.bottom = sh - workarea.bottom;
}
+12 -3
View File
@@ -1,5 +1,6 @@
#define INTERFACE_MAIN
#define BSNES_VERSION "0.007"
#define BSNES_VERSION "0.009"
#define BSNES_TITLE "bsnes v" BSNES_VERSION " ~byuu"
#include "winmain.h"
#include "../base.h"
@@ -7,6 +8,7 @@
#include "bsnes.h"
#include "ui.h"
#include "dd_renderer.h"
#include "timer.cpp"
fpstimer *fps_timer;
@@ -34,11 +36,18 @@ void term_snes() {
if(snes) { delete(snes); snes = 0; }
}
void get_config_fn(string &str) {
char *t = (char*)malloc(4096);
_getcwd(t, 4095);
str = t;
free(t);
str += "\\bsnes.cfg";
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MSG msg;
string cfg_fn;
_getcwd(cfg_fn, 4096);
cfg_fn += "\\bsnes.cfg";
get_config_fn(cfg_fn);
cfg.load(cfg_fn);
meminit();
fps_timer = new fpstimer();