mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-09 01:09:46 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
402c146a53 | ||
|
|
a471c150c9 | ||
|
|
ea38ea2537 |
No files matched your search
@@ -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
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+10
-10
@@ -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();
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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();
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user