mirror of https://github.com/bsnes-emu/bsnes.git
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
This commit is contained in:
parent
a471c150c9
commit
402c146a53
21
bsnes.cfg
21
bsnes.cfg
|
@ -1,9 +1,11 @@
|
||||||
#[bsnes v0.007a configuration file]
|
#[bsnes v0.009 configuration file]
|
||||||
|
|
||||||
#[video mode]
|
#[video mode]
|
||||||
# 0: 256x224w
|
# 0: 256x224w
|
||||||
# 1: 512x448w
|
# 1: 512x448w
|
||||||
# 2: 960x720w
|
# 2: 960x720w
|
||||||
|
# 3: 640x480f
|
||||||
|
# 4: 1024x768f
|
||||||
video.mode = 1
|
video.mode = 1
|
||||||
|
|
||||||
#[video memory type]
|
#[video memory type]
|
||||||
|
@ -19,9 +21,16 @@ video.mode = 1
|
||||||
# way to guarantee that the output image will not be
|
# way to guarantee that the output image will not be
|
||||||
# filtered.
|
# filtered.
|
||||||
video.use_vram = true
|
video.use_vram = true
|
||||||
#video.use_vram = false
|
|
||||||
|
#[color curve]
|
||||||
|
# gives a more NTSC TV-style feel to the color palette
|
||||||
|
# by darkening the image contrast.
|
||||||
|
video.color_curve = enabled
|
||||||
|
|
||||||
#[show fps]
|
#[show fps]
|
||||||
# true: show fps in titlebar
|
# true: show fps in titlebar
|
||||||
# false: do not show fps in titlebar
|
# false: do not show fps in titlebar
|
||||||
#gui.show_fps = false
|
gui.show_fps = true
|
||||||
|
|
||||||
|
#[wait for vertical retrace]
|
||||||
|
video.vblank = false
|
||||||
|
|
BIN
bsnes_g2.exe
BIN
bsnes_g2.exe
Binary file not shown.
|
@ -5,9 +5,9 @@ bool changed, notify_ppu;
|
||||||
uint8 count, new_count, pos;
|
uint8 count, new_count, pos;
|
||||||
}frameskip;
|
}frameskip;
|
||||||
bool signal_scanline, signal_frame;
|
bool signal_scanline, signal_frame;
|
||||||
void frameskip_update_status();
|
inline void frameskip_update_status();
|
||||||
void inc_vcounter();
|
inline void inc_vcounter();
|
||||||
void dram_refresh_test();
|
inline void dram_refresh_test();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct {
|
struct {
|
||||||
|
@ -23,14 +23,14 @@ public:
|
||||||
uint32 pos, last_pos;
|
uint32 pos, last_pos;
|
||||||
}cc2;
|
}cc2;
|
||||||
|
|
||||||
void set_frameskip(uint8 fs);
|
inline void set_frameskip(uint8 fs);
|
||||||
|
|
||||||
void add_cc1_cycles(uint32 cycles);
|
inline void add_cc1_cycles(uint32 cycles);
|
||||||
void add_cc2_cycles(uint32 cycles);
|
inline void add_cc2_cycles(uint32 cycles);
|
||||||
void sync();
|
inline void sync();
|
||||||
void run();
|
inline void run();
|
||||||
void power();
|
inline void power();
|
||||||
void reset();
|
inline void reset();
|
||||||
|
|
||||||
bClock();
|
bClock();
|
||||||
~bClock();
|
~bClock();
|
||||||
|
|
|
@ -89,7 +89,7 @@ uint16 v, h, hc, vs;
|
||||||
|
|
||||||
//IRQ test
|
//IRQ test
|
||||||
if(!regs.p.i) {
|
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) {
|
if(v == status.virq_pos && h >= status.hirq_pos && status.irq_pin == 1) {
|
||||||
status.irq_triggered = true;
|
status.irq_triggered = true;
|
||||||
status.irq_pin = 0;
|
status.irq_pin = 0;
|
||||||
|
@ -148,6 +148,7 @@ void bCPU::frame() {
|
||||||
status.nmi_triggered = false;
|
status.nmi_triggered = false;
|
||||||
status.r4210_read = false;
|
status.r4210_read = false;
|
||||||
|
|
||||||
|
status.irq_triggered = false;
|
||||||
status.irq_pin = 1;
|
status.irq_pin = 1;
|
||||||
|
|
||||||
dma->hdma_initialize();
|
dma->hdma_initialize();
|
||||||
|
|
|
@ -165,19 +165,19 @@ struct {
|
||||||
void mmio_w43x6(uint8 value, uint8 i);
|
void mmio_w43x6(uint8 value, uint8 i);
|
||||||
void mmio_w43x7(uint8 value, uint8 i);
|
void mmio_w43x7(uint8 value, uint8 i);
|
||||||
|
|
||||||
void exec_opcode();
|
inline void exec_opcode();
|
||||||
|
|
||||||
uint8 op_read ();
|
inline uint8 op_read ();
|
||||||
uint8 op_read (uint8 mode, uint32 addr);
|
inline uint8 op_read (uint8 mode, uint32 addr);
|
||||||
void op_write(uint8 mode, uint32 addr, uint8 value);
|
inline void op_write(uint8 mode, uint32 addr, uint8 value);
|
||||||
uint8 stack_read ();
|
inline uint8 stack_read ();
|
||||||
void stack_write(uint8 value);
|
inline void stack_write(uint8 value);
|
||||||
|
|
||||||
//cpu extra-cycle conditions
|
//cpu extra-cycle conditions
|
||||||
void cpu_c2();
|
inline void cpu_c2();
|
||||||
void cpu_c4(uint16 a, uint16 b);
|
inline void cpu_c4(uint16 a, uint16 b);
|
||||||
void cpu_c6(uint16 a);
|
inline void cpu_c6(uint16 a);
|
||||||
void cpu_io();
|
inline void cpu_io();
|
||||||
|
|
||||||
//opcode functions
|
//opcode functions
|
||||||
void init_op_tables();
|
void init_op_tables();
|
||||||
|
|
|
@ -303,21 +303,25 @@ void bCPU::mmio_w4206(uint8 value) {
|
||||||
//HTIMEL
|
//HTIMEL
|
||||||
void bCPU::mmio_w4207(uint8 value) {
|
void bCPU::mmio_w4207(uint8 value) {
|
||||||
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
|
status.hirq_pos = (status.hirq_pos & 0xff00) | value;
|
||||||
|
if(status.irq_triggered == false)status.irq_pin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//HTIMEH
|
//HTIMEH
|
||||||
void bCPU::mmio_w4208(uint8 value) {
|
void bCPU::mmio_w4208(uint8 value) {
|
||||||
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
|
status.hirq_pos = (status.hirq_pos & 0x00ff) | (value << 8);
|
||||||
|
if(status.irq_triggered == false)status.irq_pin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//VTIMEL
|
//VTIMEL
|
||||||
void bCPU::mmio_w4209(uint8 value) {
|
void bCPU::mmio_w4209(uint8 value) {
|
||||||
status.virq_pos = (status.virq_pos & 0xff00) | value;
|
status.virq_pos = (status.virq_pos & 0xff00) | value;
|
||||||
|
if(status.irq_triggered == false)status.irq_pin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//VTIMEH
|
//VTIMEH
|
||||||
void bCPU::mmio_w420a(uint8 value) {
|
void bCPU::mmio_w420a(uint8 value) {
|
||||||
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
|
status.virq_pos = (status.virq_pos & 0x00ff) | (value << 8);
|
||||||
|
if(status.irq_triggered == false)status.irq_pin = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//DMAEN
|
//DMAEN
|
||||||
|
|
|
@ -11,14 +11,18 @@ void bPPU::run() {}
|
||||||
|
|
||||||
void bPPU::scanline() {
|
void bPPU::scanline() {
|
||||||
_y = clock->vcounter();
|
_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(_y > 0 && _y < clock->visible_scanlines()) {
|
||||||
if(clock->interlace() || regs.oam_halve == true) {
|
|
||||||
output->frame_mode |= PPUOutput::INTERLACE;
|
|
||||||
output->scanline_mode[_y] |= PPUOutput::INTERLACE;
|
|
||||||
}
|
|
||||||
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
|
if(regs.bg_mode == 5 || regs.bg_mode == 6) {
|
||||||
output->frame_mode |= PPUOutput::DOUBLEWIDTH;
|
output->hires = true;
|
||||||
output->scanline_mode[_y] |= PPUOutput::DOUBLEWIDTH;
|
output->line[_y].hires = true;
|
||||||
|
}
|
||||||
|
if(_interlace == true) {
|
||||||
|
output->interlace = true;
|
||||||
|
output->line[_y].interlace = true;
|
||||||
}
|
}
|
||||||
render_line();
|
render_line();
|
||||||
}
|
}
|
||||||
|
@ -26,9 +30,11 @@ void bPPU::scanline() {
|
||||||
|
|
||||||
void bPPU::frame() {
|
void bPPU::frame() {
|
||||||
snes->notify(SNES::RENDER_FRAME);
|
snes->notify(SNES::RENDER_FRAME);
|
||||||
output->frame_mode = PPUOutput::NORMAL;
|
output->hires = false;
|
||||||
|
output->interlace = false;
|
||||||
for(int i=0;i<239;i++) {
|
for(int i=0;i<239;i++) {
|
||||||
output->scanline_mode[i] = PPUOutput::NORMAL;
|
output->line[i].hires = false;
|
||||||
|
output->line[i].interlace = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@ void bPPU::latch_counters() {
|
||||||
|
|
||||||
uint16 bPPU::get_vram_address() {
|
uint16 bPPU::get_vram_address() {
|
||||||
uint16 addr;
|
uint16 addr;
|
||||||
addr = regs.vram_addr << 1;
|
addr = regs.vram_addr;
|
||||||
switch(regs.vram_mapping) {
|
switch(regs.vram_mapping) {
|
||||||
case 0:break;
|
case 0:break;
|
||||||
case 1:addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7);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 2:addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7);break;
|
||||||
case 3:addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7);break;
|
case 3:addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7);break;
|
||||||
}
|
}
|
||||||
return addr;
|
return (addr << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//INIDISP
|
//INIDISP
|
||||||
|
|
|
@ -195,9 +195,9 @@ uint16 c, cx, cy;
|
||||||
uint16 screen_width;
|
uint16 screen_width;
|
||||||
uint16 v, vline_pos = clock->vcounter();
|
uint16 v, vline_pos = clock->vcounter();
|
||||||
v = vline_pos;
|
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;
|
ptr = (uint16*)output->buffer + ((vline_pos << 1)) * 512;
|
||||||
} else {
|
} else {
|
||||||
ptr = (uint16*)output->buffer + ((vline_pos << 1) + clock->interlace_field()) * 512;
|
ptr = (uint16*)output->buffer + ((vline_pos << 1) + clock->interlace_field()) * 512;
|
||||||
|
|
|
@ -48,54 +48,55 @@ inline void bPPU::render_line_mode1() {
|
||||||
/*
|
/*
|
||||||
Mode 2: ->
|
Mode 2: ->
|
||||||
1, 2, 3, 4, 5, 6, 7, 8
|
1, 2, 3, 4, 5, 6, 7, 8
|
||||||
OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
|
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode2() {
|
inline void bPPU::render_line_mode2() {
|
||||||
render_line_bg(BG1, COLORDEPTH_16, 4, 7);
|
render_line_bg(BG1, COLORDEPTH_16, 3, 7);
|
||||||
render_line_bg(BG2, COLORDEPTH_16, 3, 6);
|
render_line_bg(BG2, COLORDEPTH_16, 1, 5);
|
||||||
render_line_oam(1, 2, 5, 8);
|
render_line_oam(2, 4, 6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mode 3: ->
|
Mode 3: ->
|
||||||
1, 2, 3, 4, 5, 6, 7, 8
|
1, 2, 3, 4, 5, 6, 7, 8
|
||||||
OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
|
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode3() {
|
inline void bPPU::render_line_mode3() {
|
||||||
render_line_bg(BG1, COLORDEPTH_256, 4, 7);
|
render_line_bg(BG1, COLORDEPTH_256, 3, 7);
|
||||||
render_line_bg(BG2, COLORDEPTH_16, 3, 6);
|
render_line_bg(BG2, COLORDEPTH_16, 1, 5);
|
||||||
|
render_line_oam(2, 4, 6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mode 4: ->
|
Mode 4: ->
|
||||||
1, 2, 3, 4, 5, 6, 7, 8
|
1, 2, 3, 4, 5, 6, 7, 8
|
||||||
OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
|
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode4() {
|
inline void bPPU::render_line_mode4() {
|
||||||
render_line_bg(BG1, COLORDEPTH_256, 4, 7);
|
render_line_bg(BG1, COLORDEPTH_256, 3, 7);
|
||||||
render_line_bg(BG2, COLORDEPTH_4, 3, 6);
|
render_line_bg(BG2, COLORDEPTH_4, 1, 5);
|
||||||
render_line_oam(1, 2, 5, 8);
|
render_line_oam(2, 4, 6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mode 5: ->
|
Mode 5: ->
|
||||||
1, 2, 3, 4, 5, 6, 7, 8
|
1, 2, 3, 4, 5, 6, 7, 8
|
||||||
OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
|
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode5() {
|
inline void bPPU::render_line_mode5() {
|
||||||
render_line_bg(BG1, COLORDEPTH_16, 4, 7);
|
render_line_bg(BG1, COLORDEPTH_16, 3, 7);
|
||||||
render_line_bg(BG2, COLORDEPTH_4, 3, 6);
|
render_line_bg(BG2, COLORDEPTH_4, 1, 5);
|
||||||
render_line_oam(1, 2, 5, 8);
|
render_line_oam(2, 4, 6, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mode 6: ->
|
Mode 6: ->
|
||||||
1, 2, 3, 4, 5, 6
|
1, 2, 3, 4, 5, 6
|
||||||
OAM0, OAM1, BG1B, OAM2, BG1A, OAM3
|
OAM0, BG1B, OAM1, OAM2, BG1A, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode6() {
|
inline void bPPU::render_line_mode6() {
|
||||||
render_line_bg(BG1, COLORDEPTH_16, 3, 5);
|
render_line_bg(BG1, COLORDEPTH_16, 2, 5);
|
||||||
render_line_oam(1, 2, 4, 6);
|
render_line_oam(1, 3, 4, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,27 +104,27 @@ Mode7: ->
|
||||||
1, 2, 3, 4, 5
|
1, 2, 3, 4, 5
|
||||||
OAM0, BG1n, OAM1, OAM2, OAM3
|
OAM0, BG1n, OAM1, OAM2, OAM3
|
||||||
|
|
||||||
|
***
|
||||||
|
This appears to be incorrect, possibly should be...
|
||||||
|
BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3
|
||||||
|
***
|
||||||
Mode 7 (extbg): ->
|
Mode 7 (extbg): ->
|
||||||
1, 2, 3, 4, 5, 6
|
1, 2, 3, 4, 5, 6
|
||||||
BG2B, OAM0, OAM1, BG2A, OAM2, OAM3
|
BG2B, OAM0, OAM1, BG2A, OAM2, OAM3
|
||||||
*/
|
*/
|
||||||
inline void bPPU::render_line_mode7() {
|
inline void bPPU::render_line_mode7() {
|
||||||
if(regs.mode7_extbg == false) {
|
if(regs.mode7_extbg == false) {
|
||||||
render_line_mode7(1, 0, 0); //bg2 priorities are ignored
|
render_line_mode7(2, 0, 0); //bg2 priorities are ignored
|
||||||
render_line_oam(0, 2, 3, 4);
|
render_line_oam(1, 3, 4, 5);
|
||||||
} else {
|
} else {
|
||||||
render_line_mode7(0, 0, 3); //bg1 priority is ignored
|
render_line_mode7(0, 1, 4); //bg1 priority is ignored
|
||||||
render_line_oam(1, 2, 4, 5);
|
render_line_oam(2, 3, 5, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bPPU::render_line() {
|
void bPPU::render_line() {
|
||||||
_screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6)?512:256;
|
|
||||||
_interlace = clock->interlace();
|
|
||||||
_interlace_field = clock->interlace_field();
|
|
||||||
|
|
||||||
if(regs.display_disabled == true) {
|
if(regs.display_disabled == true) {
|
||||||
memset(output->buffer + (((_y << 1) + _interlace_field) << 9), 0, 1024);
|
memset(output->buffer + (_y << 10), 0, 2048);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,7 @@
|
||||||
namespace bPPUAddSubTables {
|
|
||||||
uint8 adjust_buffer_full[96] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
||||||
31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
|
|
||||||
};
|
|
||||||
uint8 adjust_buffer_half[96] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint16 bPPU::addsub_pixels(int cdest_index, int cdest_bg, int csrc_index, int csrc_bg) {
|
inline uint16 bPPU::addsub_pixels(int cdest_index, int cdest_bg, int csrc_index, int csrc_bg) {
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
uint16 cdest = get_palette(cdest_index);
|
uint32 cdest = get_palette(cdest_index);
|
||||||
uint16 csrc = get_palette(csrc_index);
|
uint32 csrc = get_palette(csrc_index);
|
||||||
uint16 res;
|
uint16 res;
|
||||||
//oam palettes 0-3 are not affected by color add/sub
|
//oam palettes 0-3 are not affected by color add/sub
|
||||||
if(cdest_bg == OAM) {
|
if(cdest_bg == OAM) {
|
||||||
|
@ -22,43 +9,54 @@ uint16 res;
|
||||||
return cdest;
|
return cdest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(csrc_bg == OAM) {
|
|
||||||
if(csrc_index < 192) {
|
|
||||||
return csrc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(regs.color_mode) {
|
switch(regs.color_mode) {
|
||||||
case 0: //COLORMODE_ADD:
|
case 0: //COLORMODE_ADD:
|
||||||
if(regs.color_halve == true) {
|
if(regs.color_halve == true) {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
|
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
|
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
|
cdest += csrc;
|
||||||
|
cdest >>= 1;
|
||||||
|
cdest &= 0x03e07c1f;
|
||||||
|
return (cdest >> 16) | cdest;
|
||||||
} else {
|
} else {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) ));
|
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) ));
|
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) ));
|
cdest += csrc;
|
||||||
|
if(cdest & 0x04000000)cdest |= 0x03e00000;
|
||||||
|
if(cdest & 0x00008000)cdest |= 0x00007c00;
|
||||||
|
if(cdest & 0x00000020)cdest |= 0x0000001f;
|
||||||
|
cdest &= 0x03e07c1f;
|
||||||
|
return (cdest >> 16) | cdest;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: //COLORMODE_SUB:
|
case 1: //COLORMODE_SUB:
|
||||||
if(regs.color_halve == true) {
|
if(regs.color_halve == true) {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )) >> 1;
|
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )) >> 1;
|
else cdest -= (csrc & 0x7c00);
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )) >> 1;
|
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 {
|
} else {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) ));
|
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) ));
|
else cdest -= (csrc & 0x7c00);
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) ));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return ((r) | (g << 5) | (b << 10));
|
return 0x0000; //prevent annoying warning message
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint16 bPPU::addsub_pixel(int cdest_index, int cdest_bg) {
|
inline uint16 bPPU::addsub_pixel(int cdest_index, int cdest_bg) {
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
uint16 cdest = get_palette(cdest_index);
|
uint32 cdest = get_palette(cdest_index);
|
||||||
uint16 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10);
|
uint32 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10);
|
||||||
uint16 res;
|
uint16 res;
|
||||||
//only oam palettes 4-7 are affected by color add/sub
|
//only oam palettes 4-7 are affected by color add/sub
|
||||||
if(cdest_bg == OAM) {
|
if(cdest_bg == OAM) {
|
||||||
|
@ -70,26 +68,42 @@ uint16 res;
|
||||||
switch(regs.color_mode) {
|
switch(regs.color_mode) {
|
||||||
case 0: //COLORMODE_ADD:
|
case 0: //COLORMODE_ADD:
|
||||||
if(regs.color_halve == true && regs.addsub_mode == 0) {
|
if(regs.color_halve == true && regs.addsub_mode == 0) {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) )) >> 1;
|
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) )) >> 1;
|
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) )) >> 1;
|
cdest += csrc;
|
||||||
|
cdest >>= 1;
|
||||||
|
cdest &= 0x03e07c1f;
|
||||||
|
return (cdest >> 16) | cdest;
|
||||||
} else {
|
} else {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) + ((csrc ) & 31) ));
|
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) + ((csrc >> 5) & 31) ));
|
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) + ((csrc >> 10) & 31) ));
|
cdest += csrc;
|
||||||
|
if(cdest & 0x04000000)cdest |= 0x03e00000;
|
||||||
|
if(cdest & 0x00008000)cdest |= 0x00007c00;
|
||||||
|
if(cdest & 0x00000020)cdest |= 0x0000001f;
|
||||||
|
cdest &= 0x03e07c1f;
|
||||||
|
return (cdest >> 16) | cdest;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: //COLORMODE_SUB:
|
case 1: //COLORMODE_SUB:
|
||||||
if(regs.color_halve == true && regs.addsub_mode == 0) {
|
if(regs.color_halve == true && regs.addsub_mode == 0) {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) )) >> 1;
|
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) )) >> 1;
|
else cdest -= (csrc & 0x7c00);
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_half + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) )) >> 1;
|
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 {
|
} else {
|
||||||
r = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest ) & 31) - ((csrc ) & 31) ));
|
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
|
||||||
g = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 5) & 31) - ((csrc >> 5) & 31) ));
|
else cdest -= (csrc & 0x7c00);
|
||||||
b = *(bPPUAddSubTables::adjust_buffer_full + 32 + ( ((cdest >> 10) & 31) - ((csrc >> 10) & 31) ));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return ((r) | (g << 5) | (b << 10));
|
return 0x0000; //prevent annoying warning message
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,6 @@ uint8 *wt_main = main_windowtable[bg];
|
||||||
uint8 *wt_sub = sub_windowtable[bg];
|
uint8 *wt_sub = sub_windowtable[bg];
|
||||||
build_window_tables(bg);
|
build_window_tables(bg);
|
||||||
for(screen_x=0;screen_x<_screen_width;screen_x++) {
|
for(screen_x=0;screen_x<_screen_width;screen_x++) {
|
||||||
if(wt_main[screen_x] && wt_sub[screen_x])continue;
|
|
||||||
|
|
||||||
if(regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6) {
|
if(regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6) {
|
||||||
if(regs.bg_mode == 6) {
|
if(regs.bg_mode == 6) {
|
||||||
tile_x = (mtable[screen_x + (hscroll & 15)] >> 4);
|
tile_x = (mtable[screen_x + (hscroll & 15)] >> 4);
|
||||||
|
|
|
@ -53,7 +53,10 @@ inline void bPPU::render_line_output() {
|
||||||
int x;
|
int x;
|
||||||
uint16 _r;
|
uint16 _r;
|
||||||
uint16 *ptr;
|
uint16 *ptr;
|
||||||
ptr = (uint16*)output->buffer + (((_y << 1) + _interlace_field) << 9); //((y * 2) + interlace) * scanline_width
|
ptr = (uint16*)output->buffer + (_y << 10);
|
||||||
|
if(_interlace == true) {
|
||||||
|
ptr += _interlace_field << 9;
|
||||||
|
}
|
||||||
|
|
||||||
uint16 *ltable;
|
uint16 *ltable;
|
||||||
ltable = (uint16*)light_table + (regs.display_brightness << 16);
|
ltable = (uint16*)light_table + (regs.display_brightness << 16);
|
||||||
|
|
|
@ -81,11 +81,13 @@ int tile_width;
|
||||||
} else {
|
} else {
|
||||||
y = (_y - current_sprite.y);
|
y = (_y - current_sprite.y);
|
||||||
}
|
}
|
||||||
y &= 255;
|
|
||||||
if(regs.oam_halve == true) {
|
if(regs.oam_halve == true) {
|
||||||
y <<= 1;
|
y <<= 1;
|
||||||
y += _interlace_field;
|
if(_interlace == true && _screen_width == 512) {
|
||||||
|
y += _interlace_field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
y &= 255;
|
||||||
|
|
||||||
chr = current_sprite.character;
|
chr = current_sprite.character;
|
||||||
tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0;
|
tiledata_inc = (chr & 0x100)?(regs.oam_nameselect << 13):0;
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
PPUOutput::PPUOutput() {
|
PPUOutput::PPUOutput() {
|
||||||
buffer = (uint16*)memalloc(512 * 478 * 2, "PPUOutput::buffer");
|
buffer = (uint16*)memalloc(512 * 478 * 2, "PPUOutput::buffer");
|
||||||
memset(buffer, 0, 512 * 478 * 2);
|
memset(buffer, 0, 512 * 478 * 2);
|
||||||
frame_mode = NORMAL;
|
hires = false;
|
||||||
|
interlace = false;
|
||||||
for(int i=0;i<239;i++) {
|
for(int i=0;i<239;i++) {
|
||||||
scanline_mode[i] = NORMAL;
|
line[i].hires = false;
|
||||||
|
line[i].interlace = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
class PPUOutput {
|
class PPUOutput {
|
||||||
public:
|
public:
|
||||||
enum {
|
bool hires, interlace;
|
||||||
NORMAL = 0,
|
struct {
|
||||||
INTERLACE = 1,
|
bool hires, interlace;
|
||||||
DOUBLEWIDTH = 2
|
}line[239];
|
||||||
};
|
|
||||||
uint8 frame_mode;
|
|
||||||
uint8 scanline_mode[239];
|
|
||||||
uint16 *buffer;
|
uint16 *buffer;
|
||||||
PPUOutput();
|
PPUOutput();
|
||||||
~PPUOutput();
|
~PPUOutput();
|
||||||
|
|
|
@ -25,7 +25,7 @@ enum {
|
||||||
|
|
||||||
class Writer {
|
class Writer {
|
||||||
public:
|
public:
|
||||||
virtual void write(uint8 *buffer, uint32 length);
|
virtual void write(uint8 *buffer, uint32 length) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileWriter : public Writer {
|
class FileWriter : public Writer {
|
||||||
|
|
|
@ -8,7 +8,7 @@ OBJS = winmain.obj \
|
||||||
cpu.obj bcpu.obj \
|
cpu.obj bcpu.obj \
|
||||||
ppu.obj bppu.obj \
|
ppu.obj bppu.obj \
|
||||||
snes.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)
|
all: $(OBJS)
|
||||||
$(CC) /Febsnes_g2.exe $(CFLAGS) $(OBJS) $(LIBS)
|
$(CC) /Febsnes_g2.exe $(CFLAGS) $(OBJS) $(LIBS)
|
||||||
|
|
|
@ -6,6 +6,8 @@ public:
|
||||||
struct {
|
struct {
|
||||||
uint32 mode;
|
uint32 mode;
|
||||||
uint32 use_vram;
|
uint32 use_vram;
|
||||||
|
uint32 color_curve;
|
||||||
|
uint32 vblank;
|
||||||
}video;
|
}video;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -13,8 +15,10 @@ struct {
|
||||||
}gui;
|
}gui;
|
||||||
|
|
||||||
Config() {
|
Config() {
|
||||||
__config_add(video.mode, 1, DEC);
|
__config_add(video.mode, 1, DEC);
|
||||||
__config_add(video.use_vram, true, TRUEFALSE);
|
__config_add(video.use_vram, true, TRUEFALSE);
|
||||||
__config_add(gui.show_fps, true, TRUEFALSE);
|
__config_add(video.color_curve, true, ENABLED);
|
||||||
|
__config_add(video.vblank, false, TRUEFALSE);
|
||||||
|
__config_add(gui.show_fps, true, TRUEFALSE);
|
||||||
}
|
}
|
||||||
}cfg;
|
}cfg;
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
DDRenderer::DDRenderer() {
|
DDRenderer::DDRenderer() {
|
||||||
lpdd = 0;
|
lpdd = 0;
|
||||||
|
lpdd7 = 0;
|
||||||
lpdds = 0;
|
lpdds = 0;
|
||||||
lpddsb = 0;
|
lpddsb = 0;
|
||||||
lpddc = 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() {
|
void DDRenderer::update_color_lookup_table() {
|
||||||
|
@ -14,6 +26,11 @@ int i, r, g, b;
|
||||||
r = (i ) & 31;
|
r = (i ) & 31;
|
||||||
g = (i >> 5) & 31;
|
g = (i >> 5) & 31;
|
||||||
b = (i >> 10) & 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);
|
color_lookup_table[i] = (r << 10) | (g << 5) | (b);
|
||||||
}
|
}
|
||||||
} else if(color_depth == 16) {
|
} else if(color_depth == 16) {
|
||||||
|
@ -21,7 +38,13 @@ int i, r, g, b;
|
||||||
r = (i ) & 31;
|
r = (i ) & 31;
|
||||||
g = (i >> 5) & 31;
|
g = (i >> 5) & 31;
|
||||||
b = (i >> 10) & 31;
|
b = (i >> 10) & 31;
|
||||||
g = (g << 1) | (g >> 4);
|
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);
|
color_lookup_table[i] = (r << 11) | (g << 5) | (b);
|
||||||
}
|
}
|
||||||
} else if(color_depth == 32) {
|
} else if(color_depth == 32) {
|
||||||
|
@ -29,9 +52,15 @@ int i, r, g, b;
|
||||||
r = (i ) & 31;
|
r = (i ) & 31;
|
||||||
g = (i >> 5) & 31;
|
g = (i >> 5) & 31;
|
||||||
b = (i >> 10) & 31;
|
b = (i >> 10) & 31;
|
||||||
r = (r << 3) | (r >> 2);
|
if(cfg.video.color_curve) {
|
||||||
g = (g << 3) | (g >> 2);
|
r = color_curve_table[r];
|
||||||
b = (b << 3) | (b >> 2);
|
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);
|
color_lookup_table[i] = (r << 16) | (g << 8) | (b);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,6 +75,17 @@ void DDRenderer::set_window(HWND hwnd_handle) { hwnd = hwnd_handle; }
|
||||||
even in 24/32-bit mode. This is possible because DDraw automatically
|
even in 24/32-bit mode. This is possible because DDraw automatically
|
||||||
handles conversion from 16bpp->32bpp in hardware. This only works
|
handles conversion from 16bpp->32bpp in hardware. This only works
|
||||||
when both the source and dest buffers are in VRAM, though.
|
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() {
|
void DDRenderer::create_backbuffer() {
|
||||||
int color_depth;
|
int color_depth;
|
||||||
|
@ -69,8 +109,8 @@ int color_depth;
|
||||||
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ddsd.dwWidth = 512;
|
ddsd.dwWidth = 512 + 4;
|
||||||
ddsd.dwHeight = 478;
|
ddsd.dwHeight = 476 + 4;
|
||||||
|
|
||||||
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
||||||
|
@ -79,7 +119,7 @@ int color_depth;
|
||||||
ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
|
ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
|
||||||
ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
|
ddsd.ddpfPixelFormat.dwBBitMask = 0x001f;
|
||||||
|
|
||||||
if(lpdd->CreateSurface(&ddsd, &lpddsb, 0) == DD_OK)return;
|
if(lpdd->CreateSurface(&ddsd, &lpddsb, 0) == DD_OK)goto clear_backbuffer;
|
||||||
|
|
||||||
try_native_backbuffer:
|
try_native_backbuffer:
|
||||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
||||||
|
@ -92,14 +132,26 @@ try_native_backbuffer:
|
||||||
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
ddsd.dwWidth = 512;
|
ddsd.dwWidth = 512 + 4;
|
||||||
ddsd.dwHeight = 478;
|
ddsd.dwHeight = 476 + 4;
|
||||||
|
|
||||||
lpdd->CreateSurface(&ddsd, &lpddsb, 0);
|
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() {
|
void DDRenderer::to_windowed() {
|
||||||
destroy();
|
destroy();
|
||||||
|
fullscreen = false;
|
||||||
DirectDrawCreate(0, &lpdd, 0);
|
DirectDrawCreate(0, &lpdd, 0);
|
||||||
lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
|
lpdd->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
|
||||||
|
|
||||||
|
@ -115,14 +167,22 @@ void DDRenderer::to_windowed() {
|
||||||
|
|
||||||
create_backbuffer();
|
create_backbuffer();
|
||||||
update_color_lookup_table();
|
update_color_lookup_table();
|
||||||
update();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DDRenderer::to_fullscreen() {
|
void DDRenderer::to_fullscreen(int _width, int _height) {
|
||||||
destroy();
|
destroy();
|
||||||
|
fullscreen = true;
|
||||||
|
width = _width;
|
||||||
|
height = _height;
|
||||||
DirectDrawCreate(0, &lpdd, 0);
|
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->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
|
||||||
lpdd->SetDisplayMode(640, 480, 16);
|
lpdd->SetDisplayMode(width, height, 16);
|
||||||
|
|
||||||
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
|
||||||
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
||||||
|
@ -136,28 +196,40 @@ void DDRenderer::to_fullscreen() {
|
||||||
|
|
||||||
create_backbuffer();
|
create_backbuffer();
|
||||||
update_color_lookup_table();
|
update_color_lookup_table();
|
||||||
update();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DDRenderer::set_source_window(RECT *rs) {
|
void DDRenderer::set_source_window() {
|
||||||
switch(ppu->output->frame_mode) {
|
SetRect(&lpddrc, 0, 0,
|
||||||
case 0:SetRect(rs, 0, 0, 256, 223);break;
|
(ppu->output->hires == false)?256:512,
|
||||||
case 1:SetRect(rs, 0, 0, 256, 446);break;
|
(ppu->output->interlace == false)?223:446);
|
||||||
case 2:SetRect(rs, 0, 0, 512, 223);break;
|
|
||||||
case 3:SetRect(rs, 0, 0, 512, 446);break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DDRenderer::redraw() {
|
void DDRenderer::redraw() {
|
||||||
RECT rd, rs;
|
RECT rd;
|
||||||
POINT p;
|
POINT p;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
p.x = p.y = 0;
|
int rx, ry;
|
||||||
ClientToScreen(hwnd, &p);
|
if(fullscreen == false) {
|
||||||
GetClientRect(hwnd, &rd);
|
p.x = p.y = 0;
|
||||||
OffsetRect(&rd, p.x, p.y);
|
ClientToScreen(hwnd, &p);
|
||||||
set_source_window(&rs);
|
GetClientRect(hwnd, &rd);
|
||||||
hr = lpdds->Blt(&rd, lpddsb, &rs, DDBLT_WAIT, 0);
|
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) {
|
if(hr == DDERR_SURFACELOST) {
|
||||||
lpdds->Restore();
|
lpdds->Restore();
|
||||||
lpddsb->Restore();
|
lpddsb->Restore();
|
||||||
|
@ -168,7 +240,7 @@ uint32 fps;
|
||||||
char s[256], t[256];
|
char s[256], t[256];
|
||||||
fps_timer->tick();
|
fps_timer->tick();
|
||||||
if(fps_timer->second_passed() == true) {
|
if(fps_timer->second_passed() == true) {
|
||||||
sprintf(s, "bsnes v" BSNES_VERSION " ~byuu");
|
sprintf(s, BSNES_TITLE);
|
||||||
if(rom_image->loaded() == true) {
|
if(rom_image->loaded() == true) {
|
||||||
fps = fps_timer->get_ticks();
|
fps = fps_timer->get_ticks();
|
||||||
if(w_main->frameskip == 0) {
|
if(w_main->frameskip == 0) {
|
||||||
|
@ -183,147 +255,51 @@ char s[256], t[256];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "dd_renderer16.cpp"
|
||||||
void DDRenderer::update16() {
|
void DDRenderer::update16() {
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
|
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
|
||||||
if(hr != DD_OK)return;
|
if(hr != DD_OK)return;
|
||||||
|
|
||||||
uint16 *src = (uint16*)ppu->output->buffer;
|
set_source_window();
|
||||||
uint16 *dest = (uint16*)ddsd.lpSurface;
|
if(ppu->output->hires == false) {
|
||||||
uint32 pitch;
|
if(ppu->output->interlace == false) {
|
||||||
int x, y;
|
update16_256x224();
|
||||||
/* skip first scanline */
|
|
||||||
src += 1024;
|
|
||||||
|
|
||||||
if(clock->overscan() == true) {
|
|
||||||
if(ppu->output->frame_mode & PPUOutput::INTERLACE) {
|
|
||||||
src += 1024 * 16;
|
|
||||||
} else {
|
} else {
|
||||||
src += 1024 * 8;
|
update16_256x448();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
/* 512x446 */
|
if(ppu->output->interlace == false) {
|
||||||
pitch = (ddsd.lPitch >> 1) - 512;
|
update16_512x224();
|
||||||
y = 446;
|
} else {
|
||||||
while(y--) {
|
update16_512x448();
|
||||||
x = 512;
|
|
||||||
while(x--) {
|
|
||||||
*dest++ = color_lookup_table[*src++];
|
|
||||||
}
|
|
||||||
dest += pitch;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lpddsb->Unlock(0);
|
lpddsb->Unlock(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "dd_renderer32.cpp"
|
||||||
void DDRenderer::update32() {
|
void DDRenderer::update32() {
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
|
hr = lpddsb->Lock(0, &ddsd, DDLOCK_WAIT, 0);
|
||||||
if(hr != DD_OK)return;
|
if(hr != DD_OK)return;
|
||||||
|
|
||||||
uint16 *src = (uint16*)ppu->output->buffer;
|
set_source_window();
|
||||||
uint32 *dest = (uint32*)ddsd.lpSurface;
|
if(ppu->output->hires == false) {
|
||||||
uint32 pitch;
|
if(ppu->output->interlace == false) {
|
||||||
int x, y;
|
update32_256x224();
|
||||||
/* skip first scanline */
|
|
||||||
src += 1024;
|
|
||||||
|
|
||||||
if(clock->overscan() == true) {
|
|
||||||
if(ppu->output->frame_mode & PPUOutput::INTERLACE) {
|
|
||||||
src += 1024 * 16;
|
|
||||||
} else {
|
} else {
|
||||||
src += 1024 * 8;
|
update32_256x448();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
} else {
|
||||||
/* 512x446 */
|
if(ppu->output->interlace == false) {
|
||||||
pitch = (ddsd.lPitch >> 2) - 512;
|
update32_512x224();
|
||||||
y = 446;
|
} else {
|
||||||
while(y--) {
|
update32_512x448();
|
||||||
x = 512;
|
|
||||||
while(x--) {
|
|
||||||
*dest++ = color_lookup_table[*src++];
|
|
||||||
}
|
|
||||||
dest += pitch;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lpddsb->Unlock(0);
|
lpddsb->Unlock(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,6 +329,10 @@ void DDRenderer::destroy() {
|
||||||
lpdds->Release();
|
lpdds->Release();
|
||||||
lpdds = 0;
|
lpdds = 0;
|
||||||
}
|
}
|
||||||
|
if(lpdd7) {
|
||||||
|
lpdd7->Release();
|
||||||
|
lpdd7 = 0;
|
||||||
|
}
|
||||||
if(lpdd) {
|
if(lpdd) {
|
||||||
lpdd->Release();
|
lpdd->Release();
|
||||||
lpdd = 0;
|
lpdd = 0;
|
||||||
|
|
|
@ -2,20 +2,33 @@
|
||||||
class DDRenderer {
|
class DDRenderer {
|
||||||
public:
|
public:
|
||||||
LPDIRECTDRAW lpdd;
|
LPDIRECTDRAW lpdd;
|
||||||
|
LPDIRECTDRAW7 lpdd7;
|
||||||
LPDIRECTDRAWSURFACE lpdds, lpddsb;
|
LPDIRECTDRAWSURFACE lpdds, lpddsb;
|
||||||
LPDIRECTDRAWCLIPPER lpddc;
|
LPDIRECTDRAWCLIPPER lpddc;
|
||||||
DDSURFACEDESC ddsd;
|
DDSURFACEDESC ddsd;
|
||||||
DDSCAPS ddscaps;
|
DDSCAPS ddscaps;
|
||||||
|
RECT lpddrc;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
uint8 color_depth;
|
bool fullscreen;
|
||||||
|
int width, height; //used for fullscreen mode clipping only
|
||||||
|
uint8 color_depth;
|
||||||
|
uint8 color_curve_table[32];
|
||||||
uint32 color_lookup_table[65536];
|
uint32 color_lookup_table[65536];
|
||||||
void set_window(HWND hwnd_handle);
|
void set_window(HWND hwnd_handle);
|
||||||
void create_backbuffer();
|
void create_backbuffer();
|
||||||
void to_windowed();
|
void to_windowed();
|
||||||
void to_fullscreen();
|
void to_fullscreen(int _width, int _height);
|
||||||
void set_source_window(RECT *rs);
|
void set_source_window();
|
||||||
void redraw();
|
void redraw();
|
||||||
|
inline void update16_256x224();
|
||||||
|
inline void update16_256x448();
|
||||||
|
inline void update16_512x224();
|
||||||
|
inline void update16_512x448();
|
||||||
void update16();
|
void update16();
|
||||||
|
inline void update32_256x224();
|
||||||
|
inline void update32_256x448();
|
||||||
|
inline void update32_512x224();
|
||||||
|
inline void update32_512x448();
|
||||||
void update32();
|
void update32();
|
||||||
void update();
|
void update();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,5 +42,10 @@ void init_ui1() {
|
||||||
SetFocus(w_main->hwnd);
|
SetFocus(w_main->hwnd);
|
||||||
dd_renderer->set_window(w_main->hwnd);
|
dd_renderer->set_window(w_main->hwnd);
|
||||||
dd_renderer->to_windowed();
|
dd_renderer->to_windowed();
|
||||||
|
|
||||||
|
w_main->show_menu();
|
||||||
|
w_main->set_video_mode(cfg.video.mode);
|
||||||
|
w_main->set_frameskip(0);
|
||||||
|
|
||||||
bsnes->debugger_deactivate();
|
bsnes->debugger_deactivate();
|
||||||
}
|
}
|
||||||
|
|
31
src/win/ui.h
31
src/win/ui.h
|
@ -1,7 +1,9 @@
|
||||||
enum {
|
enum {
|
||||||
VIDEOMODE_256x224w = 0,
|
VIDEOMODE_256x224w = 0,
|
||||||
VIDEOMODE_512x448w,
|
VIDEOMODE_512x448w,
|
||||||
VIDEOMODE_960x720w
|
VIDEOMODE_960x720w,
|
||||||
|
VIDEOMODE_640x480f,
|
||||||
|
VIDEOMODE_1024x768f
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -23,6 +25,12 @@ enum {
|
||||||
MENU_SETTINGS_VIDEOMODE_256x224w,
|
MENU_SETTINGS_VIDEOMODE_256x224w,
|
||||||
MENU_SETTINGS_VIDEOMODE_512x448w,
|
MENU_SETTINGS_VIDEOMODE_512x448w,
|
||||||
MENU_SETTINGS_VIDEOMODE_960x720w,
|
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
|
MENU_SETTINGS_DEBUGGER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -122,27 +130,36 @@ enum {
|
||||||
|
|
||||||
class Window {
|
class Window {
|
||||||
public:
|
public:
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
HMENU hmenu;
|
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 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_left(HWND _hwnd = 0);
|
||||||
void to_center();
|
void to_center();
|
||||||
void to_right();
|
void to_right();
|
||||||
void to_top();
|
void to_top();
|
||||||
void to_middle();
|
void to_middle();
|
||||||
void to_bottom(HWND _hwnd = 0);
|
void to_bottom(HWND _hwnd = 0);
|
||||||
void hide();
|
|
||||||
void show();
|
|
||||||
void show_menu();
|
|
||||||
void hide_menu();
|
|
||||||
Window();
|
Window();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MainWindow : public Window {
|
class MainWindow : public Window {
|
||||||
public:
|
public:
|
||||||
uint8 frameskip;
|
uint8 frameskip;
|
||||||
|
int width, height;
|
||||||
|
void to_fullscreen();
|
||||||
|
void to_windowed();
|
||||||
void set_frameskip(uint8 fs);
|
void set_frameskip(uint8 fs);
|
||||||
|
void adjust_video_mode(bool fullscreen_mode);
|
||||||
void set_video_mode(uint8 mode);
|
void set_video_mode(uint8 mode);
|
||||||
void menu_load();
|
void menu_load();
|
||||||
void menu_unload();
|
void menu_unload();
|
||||||
|
|
|
@ -15,32 +15,86 @@ void MainWindow::set_frameskip(uint8 fs) {
|
||||||
w_main->frameskip = fs;
|
w_main->frameskip = fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::set_video_mode(uint8 mode) {
|
void MainWindow::to_fullscreen() {
|
||||||
hide();
|
if(bsnes->debugger_enabled() == true) {
|
||||||
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VIDEOMODE_256x224w, MF_UNCHECKED);
|
bsnes->debugger_disable();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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) {
|
if(bsnes->debugger_enabled() == true) {
|
||||||
to_bottom();
|
to_bottom();
|
||||||
to_right();
|
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;
|
cfg.video.mode = mode;
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
@ -79,6 +133,16 @@ void MainWindow::menu_unload() {
|
||||||
|
|
||||||
long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
long __stdcall wndproc_main(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
switch(msg) {
|
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:
|
case WM_COMMAND:
|
||||||
switch(LOWORD(wparam)) {
|
switch(LOWORD(wparam)) {
|
||||||
case MENU_FILE_LOAD:
|
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:
|
case MENU_SETTINGS_VIDEOMODE_960x720w:
|
||||||
w_main->set_video_mode(VIDEOMODE_960x720w);
|
w_main->set_video_mode(VIDEOMODE_960x720w);
|
||||||
break;
|
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:
|
case MENU_SETTINGS_DEBUGGER:
|
||||||
if(bsnes->debugger_enabled() == true) {
|
if(bsnes->debugger_enabled() == true) {
|
||||||
bsnes->debugger_disable();
|
bsnes->debugger_disable();
|
||||||
|
@ -157,7 +246,7 @@ WNDCLASS wc;
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
RegisterClass(&wc);
|
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,
|
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||||
0, 0, 512, 446,
|
0, 0, 512, 446,
|
||||||
0, 0, GetModuleHandle(0), 0);
|
0, 0, GetModuleHandle(0), 0);
|
||||||
|
@ -192,18 +281,26 @@ HMENU hsubmenu, hbranchmenu;
|
||||||
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Frameskip");
|
AppendMenu(hsubmenu, MF_STRING | MF_POPUP, (unsigned int)hbranchmenu, "&Frameskip");
|
||||||
|
|
||||||
hbranchmenu = CreatePopupMenu();
|
hbranchmenu = CreatePopupMenu();
|
||||||
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_256x224w, "256x224 Windowed [16:15]");
|
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_512x448w, "512x448 Windowed [16:15]");
|
||||||
AppendMenu(hbranchmenu, MF_STRING, MENU_SETTINGS_VIDEOMODE_960x720w, "960x720 Windowed [4:3]");
|
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 | 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_SEPARATOR, 0, "");
|
||||||
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_DEBUGGER, "&Debugger");
|
AppendMenu(hsubmenu, MF_STRING, MENU_SETTINGS_DEBUGGER, "&Debugger");
|
||||||
AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings");
|
AppendMenu(w_main->hmenu, MF_STRING | MF_POPUP, (unsigned int)hsubmenu, "&Settings");
|
||||||
|
|
||||||
w_main->show_menu();
|
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_USEVRAM, (cfg.video.use_vram)?MF_CHECKED:MF_UNCHECKED);
|
||||||
w_main->set_video_mode(cfg.video.mode);
|
CheckMenuItem(w_main->hmenu, MENU_SETTINGS_VBLANK, (cfg.video.vblank)?MF_CHECKED:MF_UNCHECKED);
|
||||||
w_main->set_frameskip(0);
|
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() {
|
MainWindow::MainWindow() {
|
||||||
|
|
|
@ -1,14 +1,95 @@
|
||||||
void Window::resize(int width, int height) {
|
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;
|
RECT rc;
|
||||||
int x, y, wx, wy;
|
POINT p;
|
||||||
hide();
|
if(fullscreen == true) {
|
||||||
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER);
|
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, window.width, window.height, 0);
|
||||||
GetClientRect(hwnd, &rc);
|
return;
|
||||||
x = width + width - (rc.right - rc.left);
|
}
|
||||||
y = height + height - (rc.bottom - rc.top);
|
GetWindowRect(hwnd, &rc);
|
||||||
wx = (GetSystemMetrics(SM_CXSCREEN) - x) / 2;
|
p.x = p.y = 0;
|
||||||
wy = (GetSystemMetrics(SM_CYSCREEN) - y) / 2;
|
ClientToScreen(hwnd, &p);
|
||||||
SetWindowPos(hwnd, 0, wx, wy, x, y, SWP_NOZORDER);
|
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) {
|
void Window::to_left(HWND _hwnd) {
|
||||||
|
@ -17,6 +98,8 @@ int offset = 0;
|
||||||
if(_hwnd) {
|
if(_hwnd) {
|
||||||
GetWindowRect(_hwnd, &rc);
|
GetWindowRect(_hwnd, &rc);
|
||||||
offset = rc.right;
|
offset = rc.right;
|
||||||
|
} else {
|
||||||
|
offset = wa_offset.left;
|
||||||
}
|
}
|
||||||
GetWindowRect(hwnd, &rc);
|
GetWindowRect(hwnd, &rc);
|
||||||
rc.left = offset;
|
rc.left = offset;
|
||||||
|
@ -34,13 +117,14 @@ void Window::to_right() {
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetWindowRect(hwnd, &rc);
|
GetWindowRect(hwnd, &rc);
|
||||||
rc.left = GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left);
|
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);
|
SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::to_top() {
|
void Window::to_top() {
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetWindowRect(hwnd, &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);
|
SetWindowPos(hwnd, 0, rc.left, rc.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,34 +144,22 @@ int offset = 0;
|
||||||
}
|
}
|
||||||
GetWindowRect(hwnd, &rc);
|
GetWindowRect(hwnd, &rc);
|
||||||
rc.top = GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top) - offset;
|
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);
|
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() {
|
Window::Window() {
|
||||||
visible = false;
|
fullscreen = false;
|
||||||
menu_visible = 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#define INTERFACE_MAIN
|
#define INTERFACE_MAIN
|
||||||
#define BSNES_VERSION "0.008"
|
#define BSNES_VERSION "0.009"
|
||||||
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION " ~byuu"
|
||||||
#include "winmain.h"
|
#include "winmain.h"
|
||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue