Update to bsnes v016r52 release.

bsnes now builds with no warnings on Linux:
               http://byuu.cinnamonpirate.com/images/desktop082106.png
               However, input is not working unless you build the non-
GTK+ port (see below for more info).

 I'm planning on releasing next weekend. This will likely be the last
public WIP, unless something major is found before the weekend:
               byuu.cinnamonpirate.com/files/bsnes_v016_wip52.zip <-
copy/paste link







> If you can actually get it going fast in an all-in-one window like
> that it'd be cool. I normally just punt and have the GUI separate
> from the emulator output (GTK or Qt for the UI, SDL for the output)
> but it'd be nice for my NEStopia port if I could make it "one piece"
> like the Win32 original




 I can. Please take a look at my above sourcecode, and check your
private messages for another note. Specifically, src/ui/video/sdl.cpp
and src/ui/gtk/gtk_mainwindow.cpp. I am able to merge the SDL output
into the GTK+ window by setting the environment variable
"SDL_WINDOWID=%ld", GDK_WINDOW_XWINDOW(mydrawingbox->window).
 One important thing to note is that you must not initialize SDL video
until the render window has been realized. Simply showing the window
is not enough. You need to also clear all pending events in GTK+ after
showing the window before calling SDL video init, or it will die.
               You can do that with this code:






    gtk_widget_show(mainwindow);
                       while(gtk_events_pending() == true) {
                       gtk_main_iteration_do(false);
                       }




 However, one problem I am having is that by calling
gtk_main_iteration_do(), it steals all SDL input, and I'm not able to
poll any keypresses. This happens whether I embed the SDL video output
into the GTK+ window or not. The only way to get SDL input is to
ignore all GTK+ events, effectively freezing the window completely.

               I don't suppose you'd mind sharing how you got SDL
input working with GTK+ with me?
This commit is contained in:
byuu 2006-08-21 00:43:46 +00:00
parent 0ed9edfcdb
commit 192e53bb87
67 changed files with 1152 additions and 535 deletions

BIN
bsnes.exe

Binary file not shown.

View File

@ -1,8 +1,8 @@
uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 data);
inline uint8 port_read (uint8 port);
inline void port_write(uint8 port, uint8 data);
uint8 port_read (uint8 port);
void port_write(uint8 port, uint8 data);
/*****
* core APU bus functions

View File

@ -8,4 +8,4 @@ bool enabled;
inline void add_clocks(int clocks);
inline void tick_timers();
inline uint32 clocks_executed();
uint32 clocks_executed();

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.016.44"
#define BSNES_VERSION "0.016.52"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
@ -28,7 +28,7 @@
#if defined(PROCESSOR_X86)
#define ARCH_LSB
#elif defined(PROCESSOR_X86)
#elif defined(PROCESSOR_X86_64)
#define ARCH_LSB
#elif defined(PROCESSOR_G5)
#define ARCH_MSB

View File

@ -197,57 +197,21 @@ FileWriter ff(sram_fn);
ff.write(sram, info.ram_size);
}
uint Cartridge::mirror_realloc(uint8 *&data, uint size) {
for(int i = 31; i >= 0; i--) {
if(size & (1 << i)) {
if(!(size & ~(1 << i))) { return 1 << i; }
data = (uint8*)realloc(data, 2 << i);
return 2 << i;
}
}
return 0;
}
uint Cartridge::mirror(uint8 *&data, uint size) {
uint r = mirror_realloc(data, size);
while(size < r) {
uint i = 0;
for(; i < 32; i++) { if(size & (1 << i))break; }
uint masklo = 1 << i++;
for(; i < 32; i++) { if(size & (1 << i))break; }
uint maskhi = 1 << i;
if(i > 31)break; //no mirroring necessary
while(masklo < maskhi) {
uint start = size - masklo;
memcpy(data + size, data + start, masklo);
size += masklo;
masklo <<= 1;
}
}
return r;
}
void Cartridge::load_rom(Reader &rf) {
uint8 *data = rf.read();
uint size = rf.size();
bool header = ((size & 0x7fff) == 0x0200);
uint size = rf.size();
bool header = ((size & 0x7fff) == 512);
info.rom_size = size - (header ? 512 : 0);
base_rom = (uint8*)malloc(info.rom_size);
memcpy(base_rom, data + (header ? 512 : 0), info.rom_size);
SafeFree(data);
if(info.rom_size & 0x7fff) {
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
}
base_rom = rf.read(info.rom_size + (header ? 512 : 0));
rom = base_rom + (header ? 512 : 0);
info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) {
info.crc32 = crc32_adjust(info.crc32, base_rom[i]);
info.crc32 = crc32_adjust(info.crc32, rom[i]);
}
info.crc32 = ~info.crc32;
info.rom_size = mirror(base_rom, info.rom_size);
rom = base_rom;
}
bool Cartridge::load(const char *fn) {

View File

@ -78,9 +78,6 @@ struct {
uint header_index;
} info;
uint mirror_realloc(uint8 *&data, uint size);
uint mirror(uint8 *&data, uint size);
void load_rom(Reader &rf);
void load_sram();
void save_sram();

Binary file not shown.

View File

@ -1,7 +1,7 @@
//Build OAM
void C4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i=0x1fd;i>oamptr && i>=0;i-=4) {
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
if(i >= 0)ram[i] = 0xe0;
}
@ -19,58 +19,55 @@ uint8 sprcount;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
for(int pri=0x30;pri>=0;pri-=0x10) {
uint32 srcptr = 0x220;
for(int i=ram[0x620];i>0 && sprcount>0;i--, srcptr+=16) {
if((ram[srcptr + 4] & 0x30) != pri)continue;
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 srcptr = 0x220;
for(int i = ram[0x620]; i > 0 && sprcount > 0; i--, srcptr += 16) {
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt=r_mem->read(spraddr++);sprcnt>0 && sprcount>0;sprcnt--, spraddr+=4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt = r_mem->read(spraddr++); sprcnt > 0 && sprcount > 0; sprcnt--, spraddr += 4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
}
@ -178,13 +175,11 @@ uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;
uint16 mask2 = 0x3f3f;
int32 i, j;
int16 height, temp;
for(j = 0; j < 0x10; j++) {
for(int j = 0; j < 0x10; j++) {
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa00 + height * 2);
@ -202,22 +197,22 @@ int16 height, temp;
destptr += 16;
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
int16 height = -((int8)read(waveptr + 0xb00)) - 16;
for(int i = 0; i < 40; i++) {
uint16 temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa10 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
}

View File

@ -20,11 +20,11 @@
#include "cpu/cpu.h"
#include "cpu/scpu/scpu.h"
#include "cpu/bcpu/bcpu.h"
//#include "cpu/bcpu/bcpu.h"
#include "apu/apu.h"
#include "apu/sapu/sapu.h"
#include "apu/bapu/bapu.h"
//#include "apu/bapu/bapu.h"
#include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h"

View File

@ -70,7 +70,6 @@ typedef signed short int16;
typedef signed long int32;
typedef signed long long int64;
/*****
* templates
*****/

View File

@ -1,9 +1,9 @@
;*****
;libco_x86 : version 0.06 ~byuu (05/21/06)
;libco_x86 : version 0.07 ~byuu (08/15/06)
;cross-platform x86 implementation of libco
;
;context save/restore adheres to c/c++ ABI
;for x86 win32, linux and freebsd
;for x86 windows, linux and freebsd
;
;context saves esp+ebp+esi+edi+ebx
;context ignores eax+ecx+edx
@ -22,6 +22,7 @@ section .code
;*****
;linker-specific name decorations
;*****
%ifdef WIN32
%define malloc _malloc
%define free _free
@ -33,6 +34,7 @@ section .code
%define co_jump @co_jump@4
%define co_call @co_call@4
%define co_return @co_return@0
%endif
extern malloc
extern free
@ -47,7 +49,7 @@ global co_call
global co_return
;*****
;extern "C" void __fastcall co_init();
;extern "C" void fastcall co_init();
;*****
align 16
@ -65,7 +67,7 @@ co_init:
ret
;*****
;extern "C" void __fastcall co_term();
;extern "C" void fastcall co_term();
;*****
align 16
@ -73,7 +75,7 @@ co_term:
ret
;*****
;extern "C" thread_t __fastcall co_active();
;extern "C" thread_t fastcall co_active();
;return = eax
;*****
@ -87,7 +89,7 @@ co_active:
ret
;*****
;extern "C" thread_t __fastcall co_create(thread_p coentry, unsigned int heapsize);
;extern "C" thread_t fastcall co_create(thread_p coentry, unsigned int heapsize);
;ecx = coentry
;edx = heapsize
;return = eax
@ -107,8 +109,12 @@ co_create:
;create heap space (stack + register storage)
add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align)
push ecx
push edx
push edx
call malloc
add esp,4
pop edx
pop ecx
@ -130,7 +136,7 @@ co_create:
ret ;return allocated memory block as thread handle
;*****
;extern "C" void __fastcall co_delete(thread_t cothread);
;extern "C" void fastcall co_delete(thread_t cothread);
;ecx = cothread
;*****
@ -142,7 +148,7 @@ co_delete:
ret
;*****
;extern "C" void __fastcall co_jump(thread_t cothread);
;extern "C" void fastcall co_jump(thread_t cothread);
;ecx = cothread
;*****
@ -166,7 +172,7 @@ co_jump:
ret
;*****
;extern "C" void __fastcall co_call(thread_t cothread);
;extern "C" void fastcall co_call(thread_t cothread);
;ecx = cothread
;*****
@ -191,7 +197,7 @@ co_call:
ret
;*****
;extern "C" void __fastcall co_return();
;extern "C" void fastcall co_return();
;*****
align 16

View File

@ -34,10 +34,10 @@ void Control::Focus() { SetFocus(hwnd); }
void Control::Enable(bool do_enable) {
if(do_enable == true) {
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_DISABLED);
EnableWindow(hwnd, TRUE);
state.ws &= ~WS_DISABLED;
} else {
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_DISABLED);
EnableWindow(hwnd, FALSE);
state.ws |= WS_DISABLED;
}
}

View File

@ -66,14 +66,16 @@ uint region = read(0xffd9) & 0x7f;
rom_loaded = true;
//print cartridge info to debug console
char t[256];
dprintf("* CRC32 : %0.8x", cartridge.info.crc32);
dprintf("* Name : \"%s\"", cartridge.info.name);
dprintf("* PCB : %s", cartridge.info.pcb);
dprintf("* ROM Size : %dmbit", cartridge.info.rom_size / 1024 / 1024 * 8);
dprintf("* RAM Size : %dkbit", cartridge.info.ram_size / 1024 * 8);
calc_size(t, cartridge.info.rom_size);
dprintf("* ROM Size : %s", t);
calc_size(t, cartridge.info.ram_size);
dprintf("* RAM Size : %s", t);
dprintf("* Region : %s", (cartridge.info.region == Cartridge::NTSC) ? "NTSC" : "PAL");
char t[256];
strcpy(t, "");
if(cartridge.info.srtc)strcat(t, "S-RTC, ");
if(cartridge.info.sdd1)strcat(t, "S-DD1, ");
@ -124,22 +126,23 @@ void bMemBus::unload_cart() {
*****************************************/
uint8 bMemBus::memory_type(uint32 addr) {
uint8 bank;
bank = addr >> 16;
uint8 bank = addr >> 16;
addr &= 0xffff;
if((bank >= 0x00 && bank <= 0x3f) || (bank >= 0x80 && bank <= 0xbf)) {
if((bank & 0x40) == 0x00) {
//$[00-3f|80-bf]:[0000-ffff]
if(addr >= 0x0000 && addr <= 0x1fff)return TYPE_WRAM;
if(addr >= 0x2000 && addr <= 0x5fff)return TYPE_MMIO;
return TYPE_CART;
}
if((bank >= 0x40 && bank <= 0x7d) || (bank >= 0xc0 && bank <= 0xff)) {
return TYPE_CART;
if((bank & 0xfe) == 0x7e) {
//$[7e-7f]:[0000-ffff]
return TYPE_WRAM;
}
//(bank >= 0x7e && bank <= 0x7f)
return TYPE_WRAM;
//$[40-7d|c0-ff]:[0000-ffff]
return TYPE_CART;
}
uint8 bMemBus::read(uint32 addr) {
@ -209,7 +212,7 @@ void bMemBus::cart_map_system() {
void bMemBus::power() {
cart_write_protect(true);
memset(wram, 0xff, 0x020000);
memset(wram, 0x55, 0x020000);
reset();
}

View File

@ -55,6 +55,15 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
void power();
void reset();
//load_cart() helper
void calc_size(char *t, uint size) {
if(size < 1024) { sprintf(t, "%dbit", size); return; }
size /= 1024;
if(size < 1024) { sprintf(t, "%dkbit", size); return; }
size /= 1024;
sprintf(t, "%dmbit", size);
}
bMemBus();
~bMemBus();
};

View File

@ -15,22 +15,8 @@
* $[80-bf]:[2000-5fff] MMIO
*****/
void bMemBus::cart_map_generic(uint type) {
uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
ROM_size = cartridge.info.rom_size;
SRAM_size = cartridge.info.ram_size;
//calculate highest power of 2, which is the size of the first ROM chip
P0_size = 0x800000;
while(!(ROM_size & P0_size))P0_size >>= 1;
P1_size = ROM_size - P0_size;
if(ROM_size == P0_size) {
//cart only contains one ROM chip
ROM_mask = (P0_size - 1);
} else {
//cart contains two ROM chips
ROM_mask = (P0_size + P0_size - 1);
}
uint rom_size = cartridge.info.rom_size;
uint ram_size = cartridge.info.ram_size;
for(uint page = 0x0000; page <= 0xffff; page++) {
if(memory_type(page << 8) != TYPE_CART)continue;
@ -51,10 +37,10 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
//HiROM SRAM region
//$[20-3f|a0-bf]:[6000-7fff]
if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr & 0xe000) == 0x6000) {
if(SRAM_size == 0)continue;
if(ram_size == 0)continue;
addr = ((bank & 0x7f) - 0x20) * 0x2000 + ((addr & 0xffff) - 0x6000);
addr %= SRAM_size;
addr %= ram_size;
page_handle[page] = cartridge.sram + addr;
page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_ram;
@ -65,12 +51,12 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
//$[70-7f|f0-ff]:[0000-7fff]
//Note: WRAM is remapped over $[7e-7f]:[0000-ffff]
if(bank >= 0x70 && bank <= 0x7f && (addr & 0x8000) == 0x0000) {
if(SRAM_size == 0)continue;
if(ram_size == 0)continue;
if(type == Cartridge::LOROM || !(bank & 0x80)) {
//HiROM maps $[f0-ff]:[0000-7fff] to ROM
addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff);
addr %= SRAM_size;
addr %= ram_size;
page_handle[page] = cartridge.sram + addr;
page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_ram;
@ -82,18 +68,12 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
switch(type) {
case Cartridge::LOROM: {
addr = (bank & 0x7f) * 0x8000 + (addr & 0x7fff);
addr &= ROM_mask;
if(addr >= P0_size) {
addr = P0_size + (addr & (P1_size - 1));
}
addr = (bank & 0x7f) * 0x8000 + (addr & 0x7fff);
addr = mirror(rom_size, addr);
} break;
case Cartridge::HIROM: {
addr &= ROM_mask;
if(addr >= P0_size) {
addr = P0_size + (addr & (P1_size - 1));
}
addr = mirror(rom_size, addr);
} break;
case Cartridge::EXLOROM: {
@ -103,13 +83,13 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
} else {
addr &= 0x3fffff;
}
addr %= ROM_size;
addr = mirror(rom_size, addr);
} break;
case Cartridge::EXHIROM: {
addr &= 0x3fffff;
addr += (bank < 0x80) ? 0x400000 : 0x000000;
addr %= ROM_size;
addr = mirror(rom_size, addr);
} break;
}

View File

@ -1,3 +1,16 @@
uint bMemBus::mirror(uint size, uint pos) {
if(size == 0)return 0;
if(pos < size)return pos;
uint mask = 1 << 31;
while(!(pos & mask))mask >>= 1;
if(size <= (pos & mask)) {
return mirror(size, pos - mask);
} else {
return mask + mirror(size - mask, pos - mask);
}
}
void bMemBus::cart_map_range(
uint mode,
uint8 bank_lo, uint8 bank_hi,
@ -33,7 +46,7 @@ uint8 page_hi = (addr_hi >> 8) & 255;
for(uint page = page_lo; page <= page_hi; page++) {
uint16 n = (bank << 8) + page;
page_handle[n] = data + index;
page_handle[n] = data + mirror(size, index);
if(size) { index = (index + 256) % size; }
switch(type) {

View File

@ -14,6 +14,7 @@ enum {
MAP_OBC1,
};
uint mirror(uint size, uint pos);
void cart_map_range(uint mode, uint8 bank_lo, uint8 bank_hi, uint16 addr_lo, uint16 addr_hi, uint type, uint offset = 0);
#define mapper(name) void cart_map_##name()

View File

@ -6,7 +6,6 @@ void bPPU::run() {}
void bPPU::scanline() {
line.y = r_cpu->vcounter();
line.width = (regs.hires) ? 512 : 256;
line.interlace = r_cpu->interlace();
line.interlace_field = r_cpu->interlace_field();
@ -89,8 +88,8 @@ void bPPU::power() {
region = snes->region();
//$2100
regs.display_disabled = 0;
regs.display_brightness = 0;
regs.display_disabled = 1;
regs.display_brightness = 15;
//$2101
regs.oam_basesize = 0;
@ -99,12 +98,12 @@ void bPPU::power() {
//$2102-$2103
regs.oam_baseaddr = 0x0000;
regs.oam_addr = 0x0000;
regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_priority = false;
regs.oam_firstsprite = 0x00;
regs.oam_firstsprite = 0;
//$2104
regs.oam_latchdata = 0x00;
regs.oam_latchdata = 0x00;
//$2105
regs.bg_tilesize[BG1] = 0;
@ -113,7 +112,6 @@ void bPPU::power() {
regs.bg_tilesize[BG4] = 0;
regs.bg3_priority = 0;
regs.bg_mode = 0;
regs.hires = false;
//$2106
regs.mosaic_size = 0;
@ -205,10 +203,10 @@ void bPPU::power() {
regs.window2_invert [COL] = false;
//$2126-$2129
regs.window1_left = 0;
regs.window1_right = 0;
regs.window2_left = 0;
regs.window2_right = 0;
regs.window1_left = 0x00;
regs.window1_right = 0x00;
regs.window2_left = 0x00;
regs.window2_right = 0x00;
//$212a-$212b
regs.window_mask[BG1] = 0;
@ -245,7 +243,8 @@ void bPPU::power() {
//$2130
regs.color_mask = 0;
regs.colorsub_mask = 0;
regs.addsub_mode = 0;
regs.addsub_mode = false;
regs.direct_color = false;
//$2131
regs.color_mode = 0;
@ -304,7 +303,6 @@ void bPPU::reset() {
regs.bg_y[2] = 0;
regs.bg_y[3] = 0;
line.width = 256;
clear_tiledata_cache();
}
@ -377,62 +375,25 @@ bPPU::bPPU() {
init_tiledata_cache();
for(int l = 0; l < 16; l++) {
mosaic_table[l] = (uint16*)malloc(4096 * 2);
for(int i = 0; i < 4096; i++) {
mosaic_table[l][i] = (i / (l + 1)) * (l + 1);
}
}
light_table = (uint16*)malloc(16 * 32768 * 2);
uint16 *ptr = (uint16*)light_table;
for(int l = 0; l < 16; l++) {
int r, g, b;
#if 0
double y, cb, cr;
double kr = 0.2126, kb = 0.0722, kg = (1.0 - kr - kb);
for(int i = 0; i < 32768; i++) {
if(l == 0) { *ptr++ = 0; continue; }
if(l == 15) { *ptr++ = i; continue; }
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
y = (double)r * kr + (double)g * kg + (double)b * kb;
cb = ((double)b - y) / (2.0 - 2.0 * kb);
cr = ((double)r - y) / (2.0 - 2.0 * kr);
y *= (double)l / 15.0;
cb *= (double)l / 15.0;
cr *= (double)l / 15.0;
r = y + cr * (2.0 - 2.0 * kr);
b = y + cb * (2.0 - 2.0 * kb);
g = (y - b * kb - r * kr) / kg;
r = minmax<0, 31>(r);
g = minmax<0, 31>(g);
b = minmax<0, 31>(b);
*ptr++ = (r) | (g << 5) | (b << 10);
}
#else
double m = (double)l / 15.0;
for(int i = 0; i < 32768; i++) {
if(l == 0) { *ptr++ = 0; continue; }
if(l == 15) { *ptr++ = i; continue; }
r = (i ) & 31;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
r = minmax<0, 31>((int)((double)r * m));
g = minmax<0, 31>((int)((double)g * m));
b = minmax<0, 31>((int)((double)b * m));
r = minmax<0, 31>( (int)((double)r * m + 0.5) );
g = minmax<0, 31>( (int)((double)g * m + 0.5) );
b = minmax<0, 31>( (int)((double)b * m + 0.5) );
*ptr++ = (r) | (g << 5) | (b << 10);
light_table[l][i] = (b << 10) | (g << 5) | (r);
}
#endif
}
}
@ -440,10 +401,4 @@ bPPU::~bPPU() {
SafeFree(vram);
SafeFree(oam);
SafeFree(cgram);
for(int i = 0; i < 16; i++) {
SafeFree(mosaic_table[i]);
}
SafeFree(light_table);
}

View File

@ -8,10 +8,9 @@ enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
struct {
uint32 y;
uint32 width;
bool interlace;
bool interlace_field;
uint y;
bool interlace;
bool interlace_field;
} line;
struct {
@ -43,7 +42,6 @@ struct {
bool bg_tilesize[4];
bool bg3_priority;
uint8 bg_mode;
bool hires;
//$2106
uint8 mosaic_size;
@ -227,8 +225,8 @@ struct {
#include "bppu_render.h"
uint16 *light_table;
uint16 *mosaic_table[16];
uint16 light_table[16][32768];
uint16 mosaic_table[16][4096];
void render_line();
void update_oam_status();
@ -240,7 +238,7 @@ uint16 *mosaic_table[16];
void power();
void reset();
bool scanline_is_hires() { return (regs.pseudo_hires || regs.hires); }
bool scanline_is_hires() { return (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6); }
bPPU();
~bPPU();

View File

@ -147,7 +147,6 @@ void bPPU::mmio_w2105(uint8 value) {
regs.bg_tilesize[BG1] = bool(value & 0x10);
regs.bg3_priority = bool(value & 0x08);
regs.bg_mode = (value & 7);
regs.hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
}
//MOSAIC

View File

@ -45,7 +45,7 @@ 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() {
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);
@ -62,7 +62,7 @@ Mode 1 (pri=0): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
*/
inline void bPPU::render_line_mode1() {
void bPPU::render_line_mode1() {
if(regs.bg3_priority) {
render_line_bg(BG1, COLORDEPTH_16, 5, 8);
render_line_bg(BG2, COLORDEPTH_16, 4, 7);
@ -81,7 +81,7 @@ Mode 2: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode2() {
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);
@ -92,7 +92,7 @@ Mode 3: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode3() {
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);
@ -103,7 +103,7 @@ Mode 4: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode4() {
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);
@ -114,7 +114,7 @@ Mode 5: ->
1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode5() {
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);
@ -125,7 +125,7 @@ Mode 6: ->
1, 2, 3, 4, 5, 6
OAM0, BG1B, OAM1, OAM2, BG1A, OAM3
*/
inline void bPPU::render_line_mode6() {
void bPPU::render_line_mode6() {
render_line_bg(BG1, COLORDEPTH_16, 2, 5);
render_line_oam(1, 3, 4, 6);
}
@ -139,7 +139,7 @@ Mode 7 EXTBG: ->
1, 2, 3, 4, 5, 6, 7
BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3
*/
inline void bPPU::render_line_mode7() {
void bPPU::render_line_mode7() {
if(regs.mode7_extbg == false) {
render_line_mode7(BG1, 2, 2);
render_line_oam(1, 3, 4, 5);
@ -151,7 +151,7 @@ inline void bPPU::render_line_mode7() {
}
void bPPU::render_line() {
if(regs.display_disabled == true || regs.display_brightness == 0) {
if(regs.display_disabled == true) {
memset(output + (line.y * 1024), 0, 1024);
return;
}

View File

@ -88,12 +88,8 @@ void render_line_mode7(uint8 bg, uint8 pri0_pos, uint8 pri1_pos);
inline uint16 addsub(uint32 x, uint32 y, bool halve);
//bppu_render_line.cpp
enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 };
inline uint16 get_palette(uint8 index);
inline uint16 get_direct_color(uint8 p, uint8 t);
inline uint16 get_pixel_normal(uint32 x);
inline uint16 get_pixel_swap(uint32 x);
inline uint16 get_pixel_lores(uint32 x);
inline uint16 get_pixel_hires(uint32 x);
inline void render_line_output();
inline void render_line_output();

View File

@ -1,10 +1,13 @@
//called once at the start of every rendered scanline
void bPPU::update_bg_info() {
uint hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
uint width = (!hires) ? 256 : 512;
for(int bg = 0; bg < 4; bg++) {
bg_info[bg].th = (regs.bg_tilesize[bg]) ? 4 : 3;
bg_info[bg].tw = (regs.hires) ? 4 : bg_info[bg].th;
bg_info[bg].tw = (hires) ? 4 : bg_info[bg].th;
bg_info[bg].mx = (bg_info[bg].th == 4) ? (line.width << 1) : line.width;
bg_info[bg].mx = (bg_info[bg].th == 4) ? (width << 1) : width;
bg_info[bg].my = bg_info[bg].mx;
if(regs.bg_scsize[bg] & 0x01)bg_info[bg].mx <<= 1;
if(regs.bg_scsize[bg] & 0x02)bg_info[bg].my <<= 1;
@ -66,20 +69,22 @@ uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff
//index is a tile number count to add to base tile number
uint tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth);
uint8 *bg_td = (uint8*)bg_tiledata[color_depth];
uint8 *bg_td_state = (uint8*)bg_tiledata_state[color_depth];
uint8 *bg_td = bg_tiledata[color_depth];
uint8 *bg_td_state = bg_tiledata_state[color_depth];
uint8 tile_width = bg_info[bg].tw;
uint8 tile_height = bg_info[bg].th;
uint16 mask_x = bg_info[bg].mx; //screen width mask
uint16 mask_y = bg_info[bg].my; //screen height mask
uint16 x = 0;
uint16 y = regs.bg_y[bg];
uint16 hscroll = regs.bg_hofs[bg];
uint16 vscroll = regs.bg_vofs[bg];
if(regs.hires) {
uint hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
uint width = (!hires) ? 256 : 512;
if(hires) {
hscroll <<= 1;
if(regs.interlace) {
vscroll <<= 1;
@ -87,7 +92,7 @@ uint16 vscroll = regs.bg_vofs[bg];
}
}
uint16 *mtable = (uint16*)mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0];
uint16 *mtable = mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0];
uint16 hval, vval;
uint16 t, tile_pri, tile_num;
@ -102,8 +107,8 @@ bool is_opt_mode = (config::ppu.opt_enable == true) && (regs.bg_mode == 2 || r
uint8 *wt_main = window[bg].main;
uint8 *wt_sub = window[bg].sub;
int32 prev_x = -1, prev_y = -1;
for(x = 0; x < line.width; x++) {
uint16 prev_x = 0xffff, prev_y = 0xffff;
for(uint16 x = 0; x < width; x++) {
hoffset = mtable[x] + hscroll;
voffset = y + vscroll;
@ -148,18 +153,18 @@ int32 prev_x = -1, prev_y = -1;
t = bg_get_tile(bg, hoffset, voffset);
mirror_y = bool(t & 0x8000);
mirror_x = bool(t & 0x4000);
mirror_y = !!(t & 0x8000);
mirror_x = !!(t & 0x4000);
tile_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
tile_num = t;
if(tile_width == 4) { //16x16 horizontal tile mirroring
if(bool(hoffset & 8) != mirror_x)tile_num++;
if(!!(hoffset & 8) != mirror_x)tile_num++;
}
if(tile_height == 4) { //16x16 vertical tile mirroring
if(bool(voffset & 8) != mirror_y)tile_num += 16;
if(!!(voffset & 8) != mirror_y)tile_num += 16;
}
tile_num &= 0x03ff;
@ -176,7 +181,7 @@ int32 prev_x = -1, prev_y = -1;
ypos = voffset & 7;
if(mirror_y)ypos ^= 7; //invert y tile pos
tile_ptr = (uint8*)bg_td + (tile_num * 64) + (ypos * 8);
tile_ptr = bg_td + (tile_num * 64) + (ypos * 8);
}
xpos = hoffset & 7;
@ -189,7 +194,7 @@ int32 prev_x = -1, prev_y = -1;
col = get_palette(col + pal_index);
}
if(!regs.hires) {
if(!hires) {
if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); }
if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); }
} else {

View File

@ -99,9 +99,9 @@ uint8 *dest;
#undef render_bg_tile_line_4bpp
#undef render_bg_tile_line_8bpp
inline void bPPU::clear_pixel_cache() {
void bPPU::clear_pixel_cache() {
uint16 main = get_palette(0);
uint16 sub = (regs.pseudo_hires || regs.hires) ? main : regs.color_rgb;
uint16 sub = (regs.pseudo_hires || regs.bg_mode == 5 || regs.bg_mode == 6) ? main : regs.color_rgb;
uint32 i = 255;
do {
pixel_cache[i].src_main = main;

View File

@ -81,33 +81,24 @@ uint8 bg_sub;
return src_main;
}
inline uint16 bPPU::get_pixel_lores(uint32 x) {
return get_pixel_normal(x);
}
inline uint16 bPPU::get_pixel_hires(uint32 x) {
if(x & 1) {
return get_pixel_normal(x >> 1);
} else {
return get_pixel_swap(x >> 1);
}
}
inline void bPPU::render_line_output() {
uint16 *ptr = (uint16*)output + (line.y * 1024) +
((line.interlace && line.interlace_field) ? 512 : 0);
uint16 *ltable = (uint16*)light_table + (regs.display_brightness << 15);
if(!regs.pseudo_hires && !regs.hires) {
uint16 *ptr = (uint16*)output + (line.y * 1024) +
((line.interlace && line.interlace_field) ? 512 : 0);
uint16 *luma = light_table[regs.display_brightness];
if(!regs.pseudo_hires && regs.bg_mode != 5 && regs.bg_mode != 6) {
for(int x = 0; x < 256; x++) {
*ptr++ = *(ltable + get_pixel_lores(x));
*ptr++ = luma[get_pixel_normal(x)];
}
} else {
uint32 curr, prev = 0;
for(int x = 0; x < 512; x++) {
curr = *(ltable + get_pixel_hires(x));
for(int x = 0; x < 256; x++) {
curr = luma[get_pixel_swap(x)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr;
curr = luma[get_pixel_normal(x)];
*ptr++ = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
prev = curr;
//*ptr++ = *(ltable + get_pixel_hires(x));
}
}
}

View File

@ -19,7 +19,7 @@ enum { NTSC = 0, PAL = 1 };
//system functions
virtual inline void run();
virtual inline void runtoframe();
virtual void runtoframe();
virtual void init();
virtual void term();

View File

@ -1,90 +1,127 @@
ifeq ($(PLATFORM),win-visualc)
CC = cl
CXX = cl
# bsnes makefile
##################################
### platform-specific settings ###
##################################
ifeq ($(PLATFORM),x-gcc-gtk)
OS = unix
CC = gcc
CFLAGS = -O3 -fomit-frame-pointer -ffast-math -DPLATFORM_X -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_GTK `pkg-config --cflags gtk+-2.0` `sdl-config --cflags`
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK =
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
ASFLAGS = -f elf
LIBS = `pkg-config --libs gtk+-2.0` `sdl-config --libs`
endif
ifeq ($(PLATFORM),win-visualc)
OS = win
CC = cl
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
endif
ifeq ($(PLATFORM),win-visualc-wip)
OS = win
CC = cl
CXX = cl
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LINK = /link /LTCG
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
endif
ifeq ($(PLATFORM),win-visualc-pgi)
OS = win
CC = cl
CXX = cl
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
endif
ifeq ($(PLATFORM),win-visualc-pgo)
OS = win
CC = cl
CXX = cl
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
ASFLAGS = -f win32 -DWIN32
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
endif
ifeq ($(PLATFORM),win-visualc-sdl)
OS = win
CC = cl
CXX = cl
CFLAGS = /nologo /O2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_SDL
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /DPLATFORM_SDL /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK =
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
sdlmain.lib sdl.lib
ASFLAGS = -f win32 -DWIN32
LIBS = sdlmain.lib sdl.lib dsound.lib
endif
OBJS = main.$(OBJ) \
libco.$(OBJ) libstring.$(OBJ) libconfig.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) \
memory.$(OBJ) bmemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) bcpu.$(OBJ) \
apu.$(OBJ) sapu.$(OBJ) bapu.$(OBJ) \
bdsp.$(OBJ) \
ppu.$(OBJ) bppu.$(OBJ) \
snes.$(OBJ) \
srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) obc1.$(OBJ)
# adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) gzio.$(OBJ) inffast.$(OBJ) \
# inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ) \
# jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
#####################################
### compiler / assembler switches ###
#####################################
ifeq ($(CC),gcc)
OUT = -obsnes
CXX = g++
OBJ = o
COBJFLAG = -c
endif
ifeq ($(CC),cl)
OUT = /Febsnes.exe
CXX = cl
OBJ = obj
COBJFLAG = /c
endif
ifeq ($(AS),nasm)
ASOBJFLAG = -o
endif
###################
### OS switches ###
###################
ifeq ($(OS),unix)
RM = rm -f
endif
ifeq ($(OS),win)
RM = del
LIBS += kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib
endif
#########################
### begin compilation ###
#########################
OBJS = main.$(OBJ) \
libco.$(OBJ) libstring.$(OBJ) libconfig.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) \
memory.$(OBJ) bmemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) \
apu.$(OBJ) sapu.$(OBJ) \
bdsp.$(OBJ) \
ppu.$(OBJ) bppu.$(OBJ) \
snes.$(OBJ) \
srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) obc1.$(OBJ)
#adler32.$(OBJ) compress.$(OBJ) crc32.$(OBJ) deflate.$(OBJ) gzio.$(OBJ) inffast.$(OBJ) \
#inflate.$(OBJ) inftrees.$(OBJ) ioapi.$(OBJ) trees.$(OBJ) unzip.$(OBJ) zip.$(OBJ) zutil.$(OBJ) \
#jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ)
ifeq ($(OS),win)
ifeq ($(CC),cl)
OBJS += bsnes.res
endif
endif
all: $(OBJS)
rc /r /fobsnes.res bsnes.rc
$(CC) /Febsnes.exe $(CFLAGS) $(OBJS) bsnes.res $(LIBS) $(LINK)
$(CXX) $(OUT) $(CFLAGS) $(OBJS) $(LIBS) $(LINK)
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
clean:
@ -99,117 +136,120 @@ clean:
#########################
### platform-specific ###
#########################
main.$(OBJ): *.cpp *.h video/* audio/* input/* ../config/* win/* win/settings/* win/debugger/*
$(COMPILE) main.cpp
main.$(OBJ): *.cpp *.h video/* audio/* input/* ../config/* win/* win/settings/* win/debugger/* sdl/*
$(CXX) $(CFLAGS) $(COBJFLAG) main.cpp
bsnes.res: bsnes.rc
rc /r /fobsnes.res bsnes.rc
#################
### libraries ###
#################
libco.$(OBJ): ../lib/*
$(ASSEMBLE) -o libco.$(OBJ) ../lib/libco_x86.asm
# $(COMPILE) /Folibco.obj ../lib/libco_win32.cpp
$(AS) $(ASFLAGS) $(ASOBJFLAG) libco.$(OBJ) ../lib/libco_x86.asm
# $(CXX) $(CFLAGS) $(COBJFLAG) /Folibco.$(OBJ) ../lib/libco_win32.cpp
libstring.$(OBJ): ../lib/*.cpp ../lib/*.h
$(COMPILE) ../lib/libstring.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../lib/libstring.cpp
libconfig.$(OBJ): ../lib/*.cpp ../lib/*.h
$(COMPILE) ../lib/libconfig.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../lib/libconfig.cpp
##############
### memory ###
##############
memory.$(OBJ): ../memory/memory.cpp ../memory/memory.h
$(COMPILE) ../memory/memory.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../memory/memory.cpp
bmemory.$(OBJ): ../memory/bmemory/* ../memory/bmemory/mapper/*
$(COMPILE) ../memory/bmemory/bmemory.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../memory/bmemory/bmemory.cpp
###########
### cpu ###
###########
cpu.$(OBJ): ../cpu/*
$(COMPILE) ../cpu/cpu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../cpu/cpu.cpp
scpu.$(OBJ): ../cpu/scpu/* ../cpu/scpu/core/* ../cpu/scpu/dma/* ../cpu/scpu/memory/* ../cpu/scpu/mmio/* ../cpu/scpu/timing/*
$(COMPILE) ../cpu/scpu/scpu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../cpu/scpu/scpu.cpp
bcpu.$(OBJ): ../cpu/bcpu/*
$(COMPILE) ../cpu/bcpu/bcpu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../cpu/bcpu/bcpu.cpp
###########
### apu ###
###########
apu.$(OBJ): ../apu/*
$(COMPILE) ../apu/apu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../apu/apu.cpp
sapu.$(OBJ): ../apu/sapu/* ../apu/sapu/core/* ../apu/sapu/memory/* ../apu/sapu/timing/*
$(COMPILE) ../apu/sapu/sapu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../apu/sapu/sapu.cpp
bapu.$(OBJ): ../apu/bapu/*
$(COMPILE) ../apu/bapu/bapu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../apu/bapu/bapu.cpp
###########
### dsp ###
###########
bdsp.$(OBJ): ../dsp/bdsp/*
$(COMPILE) ../dsp/bdsp/bdsp.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../dsp/bdsp/bdsp.cpp
###########
### ppu ###
###########
ppu.$(OBJ): ../ppu/*.cpp ../ppu/*.h
$(COMPILE) ../ppu/ppu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../ppu/ppu.cpp
bppu.$(OBJ): ../ppu/bppu/*
$(COMPILE) ../ppu/bppu/bppu.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../ppu/bppu/bppu.cpp
#################
### utilities ###
#################
reader.$(OBJ): ../reader/*.cpp ../reader/*.h
$(COMPILE) ../reader/reader.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../reader/reader.cpp
cart.$(OBJ): ../cart/*.cpp ../cart/*.h
$(COMPILE) ../cart/cart.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../cart/cart.cpp
cheat.$(OBJ): ../cheat/*.cpp ../cheat/*.h
$(COMPILE) ../cheat/cheat.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../cheat/cheat.cpp
############
### snes ###
############
snes.$(OBJ): ../snes/* ../snes/video/* ../snes/audio/* ../snes/input/*
$(COMPILE) ../snes/snes.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../snes/snes.cpp
#####################
### special chips ###
#####################
srtc.$(OBJ): ../chip/srtc/*
$(COMPILE) ../chip/srtc/srtc.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/srtc/srtc.cpp
sdd1.$(OBJ): ../chip/sdd1/*
$(COMPILE) ../chip/sdd1/sdd1.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/sdd1/sdd1.cpp
c4.$(OBJ): ../chip/c4/*
$(COMPILE) ../chip/c4/c4.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/c4/c4.cpp
dsp1.$(OBJ): ../chip/dsp1/*
$(COMPILE) ../chip/dsp1/dsp1.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/dsp1/dsp1.cpp
dsp2.$(OBJ): ../chip/dsp2/*
$(COMPILE) ../chip/dsp2/dsp2.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/dsp2/dsp2.cpp
obc1.$(OBJ): ../chip/obc1/*
$(COMPILE) ../chip/obc1/obc1.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../chip/obc1/obc1.cpp
############
### zlib ###
############
adler32.$(OBJ): ../reader/zlib/*.c ../reader/zlib/*.h
$(COMPILE) ../reader/zlib/*.c
$(CC) $(CFLAGS) $(COBJFLAG) ../reader/zlib/*.c
###########
### jma ###
###########
jma.$(OBJ): ../reader/jma/*.cpp ../reader/jma/*.h
$(COMPILE) ../reader/jma/*.cpp
$(CXX) $(CFLAGS) $(COBJFLAG) ../reader/jma/*.cpp

View File

@ -1,11 +1,11 @@
class Audio {
public:
uint frequency;
virtual void run(uint32 sample) = 0;
virtual void set_frequency(uint new_freq) = 0;
virtual void clear_audio() = 0;
virtual void init() = 0;
virtual void term() = 0;
virtual void run(uint32 sample) {}
virtual void set_frequency(uint new_freq) {}
virtual void clear_audio() {}
virtual void init() {}
virtual void term() {}
Audio() : frequency(32000) {}
} *uiAudio;

View File

@ -4,7 +4,7 @@ void AudioDS::run(uint32 sample) {
if(data.buffer_pos >= data.samples_per_frame) {
uint32 pos, size;
void *buffer;
if(bool(config::system.regulate_speed) == true) {
if(config::system.regulate_speed == true) {
for(;;) {
dsb_b->GetCurrentPosition(&pos, 0);
data.read_buffer = pos / data.buffer_size;
@ -62,7 +62,7 @@ void AudioDS::init() {
data.buffer_size = data.samples_per_frame * 4;
DirectSoundCreate(0, &ds, 0);
ds->SetCooperativeLevel(wMain.hwnd, DSSCL_PRIORITY);
ds->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);

View File

@ -2,6 +2,7 @@
class AudioDS : public Audio {
public:
HWND hwnd;
LPDIRECTSOUND ds;
LPDIRECTSOUNDBUFFER dsb_p, dsb_b;
DSBUFFERDESC dsbd;
@ -21,7 +22,8 @@ struct {
void init();
void term();
AudioDS() {
AudioDS(HWND handle = 0) {
hwnd = (handle) ? handle : GetDesktopWindow();
ds = 0;
dsb_p = 0;
dsb_b = 0;

2
src/ui/cc.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/sh
gmake PLATFORM=x-gcc-gtk

2
src/ui/clean.sh Normal file
View File

@ -0,0 +1,2 @@
#!/bin/sh
gmake PLATFORM=x-gcc-gtk clean

View File

@ -1,9 +1,15 @@
namespace config {
struct System {
static Setting video, audio, input;
static Setting regulate_speed;
static Setting speed_slowest, speed_slow, speed_normal, speed_fast, speed_fastest;
} system;
Setting System::video(&config_file, "system.video", "Video hardware interface", "");
Setting System::audio(&config_file, "system.audio", "Audio hardware interface", "");
Setting System::input(&config_file, "system.input", "Input hardware interface", "");
Setting System::regulate_speed(&config_file, "system.regulate_speed", "Regulate speed to 60hz (NTSC) / 50hz (PAL)", true, Setting::TRUE_FALSE);
Setting System::speed_slowest (&config_file, "system.speed_slowest", "Slowest speed setting (in hz)", 16000, Setting::DEC);
Setting System::speed_slow (&config_file, "system.speed_slow", "Slow speed setting", 24000, Setting::DEC);
@ -12,19 +18,14 @@ Setting System::speed_fast (&config_file, "system.speed_fast", "Fast spee
Setting System::speed_fastest (&config_file, "system.speed_fastest", "Fastest speed setting", 64000, Setting::DEC);
struct Video {
static Setting renderer;
static Setting profile, fullscreen;
static Setting profile;
static Setting profile_0, profile_1, profile_2, profile_3;
static Setting profile_4, profile_5, profile_6, profile_7;
static Setting use_vram, triple_buffering;
static Setting use_vram;
static Setting pscanline_intensity, iscanline_intensity;
} video;
Setting Video::renderer(&config_file, "video.renderer", "Video renderer\n"
"\"dd\" (DirectDraw7 -- faster, less features)\n"
"\"d3d\" (Direct3D9 -- slower, more features)", "d3d");
Setting Video::profile(&config_file, "video.profile", "", 2, Setting::DEC);
Setting Video::fullscreen(0, "video.fullscreen", "", false, Setting::TRUE_FALSE);
/* software_filter
* hardware_filter
@ -45,18 +46,17 @@ Setting Video::profile_0(&config_file, "video.profile_0", "Video profile 0-7 con
"Please use bsnes GUI configuration editor to modify video profile settings\n"
"Format: software_filter;hardware_filter;video_standard;multiplier-1;correct_aspect_ratio;\n"
" enable_scanlines;manual_render_size;render_width;render_height;\n"
" resolution_width;resolution_height;refresh_rate;triple_buffering"
"", "0;0;0;0;false;false;false;256;224;0;0;0;false");
Setting Video::profile_1(&config_file, "video.profile_1", "", "0;0;0;1;false;false;false;512;448;0;0;0;false");
Setting Video::profile_2(&config_file, "video.profile_2", "", "0;1;0;1;true;false;false;597;448;0;0;0;false");
Setting Video::profile_3(&config_file, "video.profile_3", "", "0;1;0;2;true;false;false;896;672;0;0;0;false");
Setting Video::profile_4(&config_file, "video.profile_4", "", "0;1;0;3;true;false;false;1195;896;0;0;0;false");
Setting Video::profile_5(&config_file, "video.profile_5", "", "0;0;0;0;false;false;false;256;224;0;0;0;false");
Setting Video::profile_6(&config_file, "video.profile_6", "", "0;0;0;0;false;false;false;256;224;0;0;0;false");
Setting Video::profile_7(&config_file, "video.profile_7", "", "0;0;0;0;false;false;false;256;224;0;0;0;false");
" fullscreen;triple_buffering;resolution_width;resolution_height;refresh_rate"
"", "0;0;0;0;false;false;false;256;224;false;false;0;0;0");
Setting Video::profile_1(&config_file, "video.profile_1", "", "0;0;0;1;false;false;false;512;448;false;false;0;0;0");
Setting Video::profile_2(&config_file, "video.profile_2", "", "0;1;0;1;true;false;false;597;448;false;false;0;0;0");
Setting Video::profile_3(&config_file, "video.profile_3", "", "0;1;0;2;true;false;false;896;672;false;false;0;0;0");
Setting Video::profile_4(&config_file, "video.profile_4", "", "0;1;0;3;true;false;false;1195;896;false;false;0;0;0");
Setting Video::profile_5(&config_file, "video.profile_5", "", "0;1;0;1;true;false;false;597;448;true;false;0;0;0");
Setting Video::profile_6(&config_file, "video.profile_6", "", "0;1;0;2;true;false;false;896;672;true;false;0;0;0");
Setting Video::profile_7(&config_file, "video.profile_7", "", "0;1;0;3;true;false;false;1195;896;true;false;0;0;0");
Setting Video::use_vram(&config_file, "video.use_vram", "Use Video RAM instead of System RAM", true, Setting::TRUE_FALSE);
Setting Video::triple_buffering(&config_file, "video.triple_buffering", "Use triple buffering", false, Setting::TRUE_FALSE);
Setting Video::pscanline_intensity(&config_file, "video.pscanline_intensity",
"Progressive scanline intensity\n"
"Value is percentage of intensity from 0 to 100", 30, Setting::DEC);

48
src/ui/gtk/bsnes.cpp Normal file
View File

@ -0,0 +1,48 @@
void bSNES::set_status(uint32 new_status) { run_status = new_status; }
uint32 bSNES::get_status() { return run_status; }
void bSNES::run() {
if(cartridge.loaded() == false)return;
switch(run_status) {
case RUN:
SNES::runtoframe();
return;
case STOP:
return;
}
}
void bSNES::video_run() {
if(r_ppu->status.frames_updated == true) {
char t[256];
r_ppu->status.frames_updated = false;
sprintf(t, "%s : %d fps", BSNES_TITLE, r_ppu->status.frames_executed);
gtk_window_set_title(GTK_WINDOW(main_window.window), t);
}
uiVideo->redraw();
}
void bSNES::sound_run(uint32 data) {
uiAudio->run(data);
}
uint16 *bSNES::video_lock(uint &pitch) {
return uiVideo->lock(pitch);
}
void bSNES::video_unlock() {
uiVideo->unlock();
}
void bSNES::poll_input(uint8 type) {
uiInput->poll(type);
}
bool bSNES::get_input_status(uint8 device, uint8 button) {
return uiInput->get_status(device, button);
}
void bSNES::notify(uint32 message, uint32 param1, uint32 param2) {}
bSNES::bSNES() { run_status = STOP; }

22
src/ui/gtk/bsnes.h Normal file
View File

@ -0,0 +1,22 @@
class bSNES : public SNES {
private:
uint32 run_status;
public:
enum { STOP = 0, RUN };
void run();
void video_run();
void sound_run(uint32 data);
uint16 *video_lock(uint &pitch);
void video_unlock();
void set_status(uint32 status);
uint32 get_status();
void poll_input(uint8 type);
bool get_input_status(uint8 device, uint8 button);
void notify(uint32 message, uint32 param1, uint32 param2);
bSNES();
} *bsnes;

View File

@ -0,0 +1,192 @@
const char about_text[4096] = ""
"bsnes -- version " BSNES_VERSION "\r\n"
"Author: byuu\r\n"
"Project began: October 14th, 2004\r\n"
"\r\n\r\n"
"Contributors:\r\n"
" anomie, blargg, DMV27, GIGO, kode54, Nach,\r\n"
" Overload, Richard Bannister, TRAC, zones";
struct MainWindow {
GtkWidget *window;
GtkWidget *box;
GtkWidget *menu;
GtkWidget *menu_file, *menu_file_item;
GtkWidget *menu_file_loadrom;
GtkWidget *menu_file_unloadrom;
GtkWidget *menu_file_separator1;
GtkWidget *menu_file_reset;
GtkWidget *menu_file_power;
GtkWidget *menu_file_separator2;
GtkWidget *menu_file_quit;
GtkWidget *menu_help, *menu_help_item;
GtkWidget *menu_help_about;
GdkColor render_bg;
GtkWidget *render;
GtkWidget *fileopen;
GtkWidget *aboutbox;
} main_window;
void init_main_window();
void menu_main_window(const char *item);
void term_main_window();
void load_rom();
void cancel_load_rom();
void unload_rom();
void snes_reset();
void snes_power();
void close_aboutbox();
void init_main_window() {
MainWindow *w = &main_window;
//
//create window
//
w->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(w->window), BSNES_TITLE);
gtk_window_set_resizable(GTK_WINDOW(w->window), false);
g_signal_connect(G_OBJECT(w->window), "destroy", G_CALLBACK(term_main_window), 0);
//
//create widget container
//
w->box = gtk_vbox_new(false, 0);
gtk_container_add(GTK_CONTAINER(w->window), w->box);
gtk_widget_show(w->box);
//
//create menu
//
w->menu = gtk_menu_bar_new();
gtk_widget_show(w->menu);
w->menu_file = gtk_menu_new();
w->menu_file_item = gtk_menu_item_new_with_label("File");
gtk_widget_show(w->menu_file_item);
#define add_item(menu, item, label, id) \
item = gtk_menu_item_new_with_label(label); \
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); \
g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(menu_main_window), (gpointer)id); \
gtk_widget_show(item)
#define add_separator(menu, item) \
item = gtk_separator_menu_item_new(); \
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); \
gtk_widget_show(item)
add_item (w->menu_file, w->menu_file_loadrom, "Load ROM", "file.loadrom");
add_item (w->menu_file, w->menu_file_unloadrom, "Unload ROM", "file.unloadrom");
add_separator(w->menu_file, w->menu_file_separator1);
add_item (w->menu_file, w->menu_file_reset, "Reset", "file.reset");
add_item (w->menu_file, w->menu_file_power, "Power (Hard Reset)", "file.power");
add_separator(w->menu_file, w->menu_file_separator2);
add_item (w->menu_file, w->menu_file_quit, "Quit", "file.quit");
w->menu_help = gtk_menu_new();
w->menu_help_item = gtk_menu_item_new_with_label("Help");
gtk_widget_show(w->menu_help_item);
add_item (w->menu_help, w->menu_help_about, "About", "help.about");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu_file_item), w->menu_file);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(w->menu_help_item), w->menu_help);
gtk_menu_bar_append(GTK_MENU_BAR(w->menu), w->menu_file_item);
gtk_menu_bar_append(GTK_MENU_BAR(w->menu), w->menu_help_item);
#undef add_item
#undef add_separator
//
//create render widget
//
w->render_bg.pixel = 0;
w->render_bg.red = 0;
w->render_bg.green = 0;
w->render_bg.blue = 0;
w->render = gtk_drawing_area_new();
gtk_widget_set_size_request(w->render, 256, 224);
gtk_widget_modify_bg(w->render, GTK_STATE_NORMAL, &w->render_bg);
gtk_widget_show(w->render);
//
//pack widgets
//
gtk_box_pack_start(GTK_BOX(w->box), w->menu, false, false, 0);
gtk_box_pack_end(GTK_BOX(w->box), w->render, true, true, 0);
//
//display window
//
gtk_widget_show(w->window);
while(gtk_events_pending() == true) {
gtk_main_iteration_do(false);
}
//
//initializations
//
w->fileopen = 0;
}
void menu_main_window(const char *item) {
MainWindow *w = &main_window;
if(!strcmp(item, "file.loadrom")) {
if(!w->fileopen) {
w->fileopen = gtk_file_selection_new("Load ROM");
g_signal_connect_swapped(G_OBJECT(w->fileopen), "destroy", G_CALLBACK(cancel_load_rom), 0);
g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(w->fileopen)->ok_button), "clicked", G_CALLBACK(load_rom), 0);
g_signal_connect_swapped(G_OBJECT(GTK_FILE_SELECTION(w->fileopen)->cancel_button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)w->fileopen);
}
gtk_widget_show(w->fileopen);
} else if(!strcmp(item, "file.unloadrom")) {
if(cartridge.loaded() == true) { cartridge.unload(); }
gtk_window_set_title(GTK_WINDOW(w->window), BSNES_TITLE);
gdk_window_invalidate_rect(GDK_WINDOW(w->render->window), 0, true);
} else if(!strcmp(item, "file.reset")) {
bsnes->reset();
} else if(!strcmp(item, "file.power")) {
bsnes->power();
} else if(!strcmp(item, "file.quit")) {
term_main_window();
} else if(!strcmp(item, "help.about")) {
if(!w->aboutbox) {
w->aboutbox = gtk_message_dialog_new(0, (GtkDialogFlags)0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, about_text);
gtk_window_set_title(GTK_WINDOW(w->aboutbox), "About bsnes...");
g_signal_connect_swapped(G_OBJECT(w->aboutbox), "destroy", G_CALLBACK(close_aboutbox), 0);
g_signal_connect_swapped(G_OBJECT(w->aboutbox), "response", G_CALLBACK(gtk_widget_destroy), (gpointer)w->aboutbox);
}
gtk_widget_show(w->aboutbox);
}
}
void term_main_window() {
running = false;
}
void load_rom() {
if(!main_window.fileopen)return;
const char *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(main_window.fileopen));
gtk_widget_hide(main_window.fileopen);
if(cartridge.loaded() == true) { cartridge.unload(); }
if(cartridge.load(fn) == false) { return; }
bsnes->power();
}
void cancel_load_rom() {
main_window.fileopen = 0;
}
void close_aboutbox() {
main_window.aboutbox = 0;
}

92
src/ui/gtk/main.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "main.h"
#include "bsnes.h"
#include "gtk_mainwindow.cpp"
#include "bsnes.cpp"
#include "../video/gtk.h"
#include "../video/gtk.cpp"
#include "../video/sdl.h"
#include "../video/sdl.cpp"
#ifdef PLATFORM_WIN
#include "../audio/dsound.h"
#include "../audio/dsound.cpp"
#endif
#include "../input/sdl.h"
#include "../input/sdl.cpp"
void alert(char *s, ...) {
char str[4096];
va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
#ifdef PLATFORM_WIN
MessageBox(0, str, "bsnes", MB_OK);
#else
fprintf(stdout, "%s\r\n", str);
#endif
}
void dprintf(char *s, ...) {
char str[4096];
va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
fprintf(stdout, "%s\r\n", str);
}
#ifdef PLATFORM_WIN
int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
int argc = __argc;
char **argv = __argv;
#else
int main(int argc, char *argv[]) {
#endif
gtk_init(&argc, &argv);
init_main_window();
config_file.load("bsnes.cfg");
init_snes();
uiVideo = new VideoSDL((void*)GDK_WINDOW_XWINDOW(main_window.render->window));
uiAudio = new Audio();
uiInput = new InputSDL((void*)GDK_WINDOW_XWINDOW(main_window.render->window));
uiVideo->init();
uiAudio->init();
uiInput->init();
//will not run if cartridge not loaded
bsnes->set_status(bSNES::RUN);
if(argc >= 2 && cartridge.load(argv[1]) == true) {
snes->power();
}
while(running == true) {
bsnes->run();
while(gtk_events_pending() == true) {
gtk_main_iteration_do(false);
}
SDL_Event event;
while(SDL_PollEvent(&event)) {
}
}
end:
config_file.save("bsnes.cfg");
cartridge.unload();
uiVideo->term();
uiAudio->term();
uiInput->term();
SafeDelete(uiVideo);
SafeDelete(uiAudio);
SafeDelete(uiInput);
term_snes();
return 0;
}

4
src/ui/gtk/main.h Normal file
View File

@ -0,0 +1,4 @@
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
bool running = true; //set to false to terminate main program loop

View File

@ -16,7 +16,7 @@ struct joypad {
keymap key; //this must be initialized by init()
bool8 keystate[4096];
virtual void poll() = 0;
virtual void poll() {}
virtual void poll(uint8 device);
virtual void init();
virtual void term();

37
src/ui/input/sdl.cpp Normal file
View File

@ -0,0 +1,37 @@
void InputSDL::poll(uint8 device) {
Input::poll(device);
}
void InputSDL::poll() {
memcpy(keystate, SDL_GetKeyState(0), SDLK_LAST);
}
void InputSDL::init() {
#include "sdl_keymap.cpp"
Input::init();
}
void InputSDL::term() {
Input::term();
}
InputSDL::InputSDL(void *handle) {
window = handle;
//
//SDL hack
//Put SDL output into main GTK+ window, rather than
//creating a new window for SDL output.
//
if(window) {
char t[64];
sprintf(t, "SDL_WINDOWID=%ld", window);
#if defined(COMPILER_GCC)
putenv(t);
#elif defined(COMPILER_VISUALC)
_putenv(t);
#endif
}
}
InputSDL::~InputSDL() {}

13
src/ui/input/sdl.h Normal file
View File

@ -0,0 +1,13 @@
class InputSDL : public Input {
private:
void *window;
public:
void poll();
void poll(uint8 device);
void init();
void term();
InputSDL(void *handle = 0);
~InputSDL();
};

View File

@ -0,0 +1,37 @@
key.esc = SDLK_ESCAPE;
key.up = SDLK_UP;
key.down = SDLK_DOWN;
key.left = SDLK_LEFT;
key.right = SDLK_RIGHT;
key.a = SDLK_a;
key.b = SDLK_b;
key.c = SDLK_c;
key.d = SDLK_d;
key.e = SDLK_e;
key.f = SDLK_f;
key.g = SDLK_g;
key.h = SDLK_h;
key.i = SDLK_i;
key.j = SDLK_j;
key.k = SDLK_k;
key.l = SDLK_l;
key.m = SDLK_m;
key.n = SDLK_n;
key.o = SDLK_o;
key.p = SDLK_p;
key.q = SDLK_q;
key.r = SDLK_r;
key.s = SDLK_s;
key.t = SDLK_t;
key.u = SDLK_u;
key.v = SDLK_v;
key.w = SDLK_w;
key.x = SDLK_x;
key.y = SDLK_y;
key.z = SDLK_z;
key.lshift = SDLK_LSHIFT;
key.rshift = SDLK_RSHIFT;
key.enter = SDLK_RETURN;

View File

@ -22,9 +22,11 @@ void term_snes();
* platform abstraction layer
*****/
#if defined(PLATFORM_WIN)
#if defined(UI_WIN)
#include "win/main.cpp"
#elif defined(PLATFORM_SDL)
#elif defined(UI_GTK)
#include "gtk/main.cpp"
#elif defined(UI_SDL)
#include "sdl/main.cpp"
#else
#error "unsupported platform"

View File

@ -22,7 +22,9 @@ void bSNES::video_run() {
render();
}
void bSNES::sound_run(uint32 data) {}
void bSNES::sound_run(uint32 data) {
uiAudio->run(data);
}
uint16 *bSNES::video_lock(uint &pitch) {
if(SDL_MUSTLOCK(screen)) {
@ -49,57 +51,12 @@ void bSNES::video_unlock() {
*** Input functions ***
***********************/
//It would appear that keystate does not need to be released
//after calling SDL_GetKeyState... doing so causes libSDL
//to throw error messages about a bad free call to stdout...
void bSNES::poll_input(uint8 type) {
uint8 *keystate = SDL_GetKeyState(0);
joypad1.up = keystate[(int)config::input.joypad1.up];
joypad1.down = keystate[(int)config::input.joypad1.down];
joypad1.left = keystate[(int)config::input.joypad1.left];
joypad1.right = keystate[(int)config::input.joypad1.right];
joypad1.select = keystate[(int)config::input.joypad1.select];
joypad1.start = keystate[(int)config::input.joypad1.start];
joypad1.y = keystate[(int)config::input.joypad1.y];
joypad1.b = keystate[(int)config::input.joypad1.b];
joypad1.x = keystate[(int)config::input.joypad1.x];
joypad1.a = keystate[(int)config::input.joypad1.a];
joypad1.l = keystate[(int)config::input.joypad1.l];
joypad1.r = keystate[(int)config::input.joypad1.r];
//It's impossible to hold both up+down, or left+right down
//at the same time on a directional pad; and besides, allowing
//this to happen causes glitches in many SNES games.
if(joypad1.up) joypad1.down = 0;
if(joypad1.left)joypad1.right = 0;
uiInput->poll(type);
}
bool bSNES::get_input_status(uint8 device, uint8 button) {
switch(device) {
case DEV_JOYPAD1:
switch(button) {
case JOYPAD_UP: return joypad1.up;
case JOYPAD_DOWN: return joypad1.down;
case JOYPAD_LEFT: return joypad1.left;
case JOYPAD_RIGHT: return joypad1.right;
case JOYPAD_A: return joypad1.a;
case JOYPAD_B: return joypad1.b;
case JOYPAD_X: return joypad1.x;
case JOYPAD_Y: return joypad1.y;
case JOYPAD_L: return joypad1.l;
case JOYPAD_R: return joypad1.r;
case JOYPAD_SELECT:return joypad1.select;
case JOYPAD_START: return joypad1.start;
}
break;
}
return 0;
}
bJoypad::bJoypad() {
up = down = left = right = false;
a = b = x = y = false;
l = r = select = start = false;
return uiInput->get_status(device, button);
}
void bSNES::notify(uint32 message, uint32 param1, uint32 param2) {}

View File

@ -1,15 +1,6 @@
class bJoypad {
public:
bool up, down, left, right;
bool a, b, x, y;
bool l, r, select, start;
bJoypad();
};
class bSNES : public SNES {
private:
uint32 run_status;
bJoypad joypad1, joypad2;
public:
enum { STOP = 0, RUN };

View File

@ -4,13 +4,21 @@
#include "render.cpp"
#include "bsnes.cpp"
#ifdef PLATFORM_WIN
#include "../audio/dsound.h"
#include "../audio/dsound.cpp"
#endif
#include "../input/sdl.h"
#include "../input/sdl.cpp"
void alert(char *s, ...) {
char str[4096];
va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
#ifdef _WIN32
#ifdef PLATFORM_WIN
MessageBox(0, str, "bsnes", MB_OK);
#else
fprintf(stdout, "%s\r\n", str);
@ -27,7 +35,7 @@ va_list args;
}
void center_window() {
#ifdef _WIN32
#ifdef PLATFORM_WIN
HWND hwnd;
RECT rc;
int x, y;
@ -39,13 +47,13 @@ int x, y;
#endif
}
#ifdef _WIN32
#ifdef PLATFORM_WIN
int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
int argc = __argc;
char **argv = __argv;
SDL_SetModuleHandle(GetModuleHandle(0));
#else
int SDL_main(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
#endif
SDL_Event event;
@ -59,6 +67,15 @@ SDL_Event event;
init_snes();
#ifdef PLATFORM_WIN
uiAudio = new AudioDS();
#else
uiAudio = new Audio();
#endif
uiInput = new InputSDL();
uiAudio->init();
uiInput->init();
if(cartridge.load(argv[1]) == false) {
alert("Failed to load image. Usage: bsnes_sdl <filename.smc>");
goto _end;
@ -73,7 +90,7 @@ SDL_Event event;
screen_rect.h = 224;
screen = SDL_SetVideoMode(screen_rect.w, screen_rect.h, 16,
SDL_HWSURFACE | ((config::video.fullscreen) ? SDL_FULLSCREEN : 0));
SDL_HWSURFACE | (0 ? SDL_FULLSCREEN : 0));
if(!screen) { alert("Failed to initialize SDL"); goto _end; }
backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000);
@ -115,6 +132,10 @@ int cursor_status;
_end:
config_file.save("bsnes_sdl.cfg");
cartridge.unload();
uiAudio->term();
uiInput->term();
SafeDelete(uiAudio);
SafeDelete(uiInput);
term_snes();
return 0;

View File

@ -1,4 +1,4 @@
#ifdef _WIN32
#ifdef PLATFORM_WIN
#include <windows.h>
#endif

View File

@ -16,7 +16,7 @@ HRESULT hr;
presentation.Flags = D3DPRESENTFLAG_VIDEO;
presentation.SwapEffect = (settings.triple_buffering == true) ?
D3DSWAPEFFECT_FLIP : D3DSWAPEFFECT_DISCARD;
presentation.hDeviceWindow = wMain.hwnd;
presentation.hDeviceWindow = hwnd;
presentation.BackBufferCount = (settings.triple_buffering == true) ? 2 : 1;
presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
presentation.MultiSampleQuality = 0;
@ -26,7 +26,7 @@ HRESULT hr;
D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
presentation.FullScreen_RefreshRateInHz = settings.refresh_rate;
if(bool(config::video.fullscreen) == false) {
if(settings.fullscreen == false) {
presentation.Windowed = true;
presentation.BackBufferFormat = D3DFMT_UNKNOWN;
presentation.BackBufferWidth = 0;
@ -38,7 +38,7 @@ HRESULT hr;
presentation.BackBufferHeight = settings.resolution_height;
}
hr = lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wMain.hwnd,
hr = lpd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device);
if(hr != D3D_OK) {
alert("Failed to create Direct3D9 device");
@ -328,6 +328,8 @@ void VideoD3D::update() {
}
bool VideoD3D::capture_screenshot() {
if(!d3dx || !pD3DXSaveSurfaceToFileA) { return false; }
//fill both backbuffers with currently rendered image
redraw();
redraw();
@ -358,8 +360,7 @@ uint32 format;
format = D3DXIFF_PNG;
}
D3DXSaveSurfaceToFile(fn, static_cast<D3DXIMAGE_FILEFORMAT>(format),
temp_surface, NULL, NULL);
pD3DXSaveSurfaceToFileA(fn, format, temp_surface, NULL, NULL);
temp_surface->Release();
return true;
}
@ -379,7 +380,9 @@ void VideoD3D::term() {
SafeRelease(lpd3d);
}
VideoD3D::VideoD3D() {
VideoD3D::VideoD3D(HWND handle) {
hwnd = handle;
vertex_buffer = 0;
surface = 0;
texture = 0;
@ -388,6 +391,56 @@ VideoD3D::VideoD3D() {
scanline[2] = 0;
device = 0;
lpd3d = 0;
//Below code dynamically loads d3dx9 DLL at runtime
//to map D3DXSaveSurfaceToFileA function, used to
//capture screenshots.
//
//We are forced to link against this DLL dynamically
//because Microsoft decided that releasing 10+ versions
//of this DLL, all with different filenames, rather than
//making one DLL that was backwards-compatible.
//
//As a result of this blatant stupidity, if the application
//statically links against d3dx9.lib, then the application
//will then *require* the version of the d3dx9 DLL included
//with the DX9 SDK used to build said application.
//
//And since most end users generally have not downloaded
//every single bimonthly DX9 update, the application will
//completely fail to load when it cannot find said dx9 DLL.
//
//Hillariously enough, most (if not all) of the d3dx9
//functionality appears to be backwards-compatible anyway,
//including this function.
//
//Therefore, as a workaround, we search through all possible
//DLL filenames. If a d3dx9 DLL is found, we dynamically map
//the D3DXSaveSurfaceToFileA function. Otherwise, screenshot
//support will fail silently.
//
//The benefit to this approach is that it allows all users
//to run this application, without explicitly requiring said
//d3dx9 DLL to run the application at all.
d3dx = 0;
pD3DXSaveSurfaceToFileA = 0;
for(int i = 0; i < 256; i++) {
char t[256];
sprintf(t, "d3dx9_%d.dll", i);
d3dx = LoadLibrary(t);
if(d3dx) { break; }
}
if(!d3dx) { d3dx = LoadLibrary("d3dx9.dll"); }
if(!d3dx) { return; }
pD3DXSaveSurfaceToFileA = (HRESULT(WINAPI*)(LPCSTR, DWORD, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*))
GetProcAddress(d3dx, "D3DXSaveSurfaceToFileA");
}
VideoD3D::~VideoD3D() {
if(d3dx)FreeLibrary(d3dx);
}
#undef D3DVERTEX

View File

@ -1,8 +1,8 @@
#include <d3d9.h>
#include <d3dx9.h>
class VideoD3D : public Video {
public:
HWND hwnd;
LPDIRECT3D9 lpd3d;
LPDIRECT3DDEVICE9 device;
LPDIRECT3DVERTEXBUFFER9 vertex_buffer, *vertex_ptr;
@ -14,6 +14,10 @@ D3DCAPS9 d3dcaps;
LPDIRECT3DTEXTURE9 texture, scanline[3];
LPDIRECT3DSURFACE9 surface, temp_surface;
HINSTANCE d3dx;
HRESULT (WINAPI *pD3DXSaveSurfaceToFileA)(LPCSTR, DWORD, LPDIRECT3DSURFACE9, CONST PALETTEENTRY*, CONST RECT*);
enum { D3DXIFF_BMP = 0, D3DXIFF_JPG = 1, D3DXIFF_PNG = 3 };
struct d3dvertex {
float x, y, z, rhw; //screen coords
uint32 color; //diffuse color
@ -58,5 +62,6 @@ struct {
void redraw();
void update();
VideoD3D();
VideoD3D(HWND handle = 0);
~VideoD3D();
};

View File

@ -7,17 +7,17 @@ bool VideoDD::update_video_profile() {
lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7);
SafeRelease(lpdd);
if(bool(config::video.fullscreen) == true) {
lpdd7->SetCooperativeLevel(wMain.hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
if(settings.fullscreen == true) {
lpdd7->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd7->SetDisplayMode(settings.resolution_width, settings.resolution_height, 16, settings.refresh_rate, 0);
} else {
lpdd7->SetCooperativeLevel(wMain.hwnd, DDSCL_NORMAL);
lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
}
create_presentation();
lpdd7->CreateClipper(0, &clipper, 0);
clipper->SetHWnd(0, wMain.hwnd);
clipper->SetHWnd(0, hwnd);
screen->SetClipper(clipper);
create_render_target();
@ -101,7 +101,7 @@ DDBLTFX fx;
backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
surface->Blt (0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
if(bool(config::video.fullscreen) == true) {
if(settings.fullscreen == true) {
screen->Flip(0, DDFLIP_WAIT);
backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
screen->Flip(0, DDFLIP_WAIT);
@ -113,7 +113,7 @@ void VideoDD::create_presentation() {
memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize = sizeof(DDSURFACEDESC2);
if(bool(config::video.fullscreen) == true) {
if(settings.fullscreen == true) {
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = (settings.triple_buffering == true) ? 2 : 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
@ -149,14 +149,14 @@ RECT rd, rs;
snes->get_video_info(&vi);
SetRect(&rs, 0, 0, vi.width, vi.height);
if(bool(config::video.fullscreen) == true) {
if(settings.fullscreen == true) {
SetRect(&rd, settings.rx, settings.ry, settings.rx + settings.rw, settings.ry + settings.rh);
backbuffer->Blt(&rd, surface, &rs, DDBLT_WAIT, 0);
hr = screen->Flip(0, DDFLIP_WAIT);
} else {
POINT p = { 0, 0 };
ClientToScreen(wMain.hwnd, &p);
GetClientRect(wMain.hwnd, &rd);
ClientToScreen(hwnd, &p);
GetClientRect(hwnd, &rd);
OffsetRect(&rd, p.x, p.y);
hr = screen->Blt(&rd, surface, &rs, DDBLT_WAIT, 0);
@ -184,7 +184,9 @@ void VideoDD::term() {
SafeRelease(lpdd);
}
VideoDD::VideoDD() {
VideoDD::VideoDD(HWND handle) {
hwnd = handle;
lpdd = 0;
lpdd7 = 0;
screen = 0;

View File

@ -2,6 +2,7 @@
class VideoDD : public Video {
private:
HWND hwnd;
LPDIRECTDRAW lpdd;
LPDIRECTDRAW7 lpdd7;
LPDIRECTDRAWSURFACE7 screen, backbuffer;
@ -29,5 +30,5 @@ public:
void redraw();
void update();
VideoDD();
VideoDD(HWND handle);
};

38
src/ui/video/gtk.cpp Normal file
View File

@ -0,0 +1,38 @@
//WARNING: GTK video renderer is currently broken
//Renderer is displaying incorrect colors
uint16 *VideoGTK::lock(uint &pitch) {
pitch = 512;
return (uint16*)buffer;
}
void VideoGTK::unlock() {}
void VideoGTK::redraw() {
uint8 *dest = gdkbuffer;
uint16 *src = buffer;
uint z = 256 * 224;
while(z--) {
uint32 p = *src++;
*(uint32*)dest = ((p & 0xf800) << 8) | ((p & 0x07e0) << 5) | ((p & 0x001f) << 3);
dest += 3;
}
gdk_draw_rgb_image(GDK_DRAWABLE(widget->window), gc, 0, 0, 256, 224, GDK_RGB_DITHER_NONE, gdkbuffer, 768);
}
void VideoGTK::update() { redraw(); }
void VideoGTK::init() {
buffer = (uint16*)malloc(256 * 224 * 2);
gdkbuffer = (uint8*) malloc(256 * 224 * 3);
}
void VideoGTK::term() {
SafeFree(buffer);
SafeFree(gdkbuffer);
}
VideoGTK::VideoGTK(GtkWidget *output_widget) {
widget = output_widget;
gc = gdk_gc_new(GDK_DRAWABLE(output_widget->window));
}

23
src/ui/video/gtk.h Normal file
View File

@ -0,0 +1,23 @@
#include <gtk/gtk.h>
class VideoGTK : public Video {
private:
GtkWidget *widget;
GdkGC *gc;
uint16 *buffer;
uint8 *gdkbuffer;
public:
uint16 *lock(uint &pitch);
void unlock();
uint screen_width() { return 1152; }
uint screen_height() { return 864; }
void redraw();
void update();
void init();
void term();
VideoGTK(GtkWidget *output_widget);
};

45
src/ui/video/sdl.cpp Normal file
View File

@ -0,0 +1,45 @@
uint16 *VideoSDL::lock(uint &pitch) {
if(SDL_MUSTLOCK(backbuffer)) { SDL_LockSurface(backbuffer); }
pitch = backbuffer->pitch;
return (uint16*)backbuffer->pixels;
}
void VideoSDL::unlock() {
if(SDL_MUSTLOCK(backbuffer)) { SDL_UnlockSurface(backbuffer); }
}
void VideoSDL::redraw() {
SDL_BlitSurface(backbuffer, 0, screen, 0);
SDL_UpdateRect(screen, 0, 0, 256, 224);
}
void VideoSDL::update() { redraw(); }
void VideoSDL::init() {
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
screen = SDL_SetVideoMode(256, 224, 16, SDL_HWSURFACE);
backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000);
}
void VideoSDL::term() {}
VideoSDL::VideoSDL(void *handle) {
window = handle;
//
//SDL hack
//Put SDL output into main GTK+ window, rather than
//creating a new window for SDL output.
//
if(window) {
char t[64];
sprintf(t, "SDL_WINDOWID=%ld", window);
#if defined(COMPILER_GCC)
putenv(t);
#elif defined(COMPILER_VISUALC)
_putenv(t);
#endif
}
}

21
src/ui/video/sdl.h Normal file
View File

@ -0,0 +1,21 @@
#include <SDL.h>
class VideoSDL : public Video {
private:
void *window;
SDL_Surface *screen, *backbuffer;
public:
uint16 *lock(uint &pitch);
void unlock();
uint screen_width() { return 1152; }
uint screen_height() { return 864; }
void redraw();
void update();
void init();
void term();
VideoSDL(void *handle = 0);
};

View File

@ -25,10 +25,11 @@ int i = 0;
v->manual_render_size = strmatch(part[i++], "true");
v->render_width = strdec(part[i++]);
v->render_height = strdec(part[i++]);
v->fullscreen = strmatch(part[i++], "true");
v->triple_buffering = strmatch(part[i++], "true");
v->resolution_width = strdec(part[i++]);
v->resolution_height = strdec(part[i++]);
v->refresh_rate = strdec(part[i++]);
v->triple_buffering = strmatch(part[i++], "true");
if(v->render_width < 256)v->render_width = 256;
if(v->render_height < 224)v->render_height = 224;
@ -50,10 +51,11 @@ VideoSettings *v = &video_settings[profile];
sprintf(part, "%s", v->manual_render_size ? "true" : "false"); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->render_width); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->render_height); strcat(line, part); strcat(line, ";");
sprintf(part, "%s", v->fullscreen ? "true" : "false"); strcat(line, part); strcat(line, ";");
sprintf(part, "%s", v->triple_buffering ? "true" : "false"); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->resolution_width); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->resolution_height); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->refresh_rate); strcat(line, part); strcat(line, ";");
sprintf(part, "%s", v->triple_buffering ? "true" : "false"); strcat(line, part);
sprintf(part, "%d", v->refresh_rate); strcat(line, part);
switch(profile) {
case 0: config::video.profile_0.sset(strptr(line)); break;
@ -90,11 +92,13 @@ VideoSettings *v = &video_settings[profile];
}
}
settings.hardware_filter = v->hardware_filter;
settings.fullscreen = v->fullscreen;
settings.triple_buffering = v->triple_buffering;
settings.hardware_filter = v->hardware_filter;
settings.enable_scanlines = v->enable_scanlines;
if((bool)config::video.fullscreen == true) {
if(v->fullscreen == true) {
settings.resolution_width = (v->resolution_width) ? v->resolution_width : screen_width();
settings.resolution_height = (v->resolution_height) ? v->resolution_height : screen_height();
settings.refresh_rate = v->refresh_rate;

View File

@ -13,10 +13,11 @@ struct VideoSettings {
bool manual_render_size;
uint render_width;
uint render_height;
bool fullscreen;
bool triple_buffering;
uint resolution_width;
uint resolution_height;
uint refresh_rate;
bool triple_buffering;
} video_settings[8];
void load_video_settings(uint profile);
@ -30,8 +31,10 @@ struct {
uint render_width;
uint render_height;
uint hardware_filter;
bool fullscreen;
bool triple_buffering;
uint hardware_filter;
bool enable_scanlines;
uint resolution_width;
@ -48,8 +51,8 @@ struct {
virtual uint screen_width() = 0;
virtual uint screen_height() = 0;
virtual bool update_video_profile() = 0;
virtual void clear_video() = 0;
virtual bool update_video_profile() { return true; }
virtual void clear_video() {}
virtual void pause_enable() {}
virtual void pause_disable() {}

View File

@ -55,7 +55,7 @@ uint8 r = 0x00;
r = r_mem->read(addr);
} break;
case SPCRAM:
r = r_apu->spcram_read(addr & 0xffff);
r = r_apu->spcram[addr & 0xffff];
break;
case VRAM:
r = r_ppu->vram_read(addr & 0xffff);
@ -80,7 +80,7 @@ void Debugger::write(uint8 mode, uint32 addr, uint8 data) {
r_mem->cart_write_protect(true);
break;
case SPCRAM:
r_apu->spcram_write(addr & 0xffff, data);
r_apu->spcram[addr & 0xffff] = data;
break;
case VRAM:
r_ppu->vram_write(addr & 0xffff, data);

View File

@ -107,7 +107,7 @@ bool MemoryEditor::Event(EventInfo &info) {
case EVENT_CHANGED:
case EVENT_CLICKED: {
if(info.control == &Mode) {
if(info.control == &Mode && info.event_id == EVENT_CHANGED) {
switch(Mode.GetSelection()) {
case 0:
status.mode = Debugger::DRAM;
@ -147,7 +147,7 @@ bool MemoryEditor::Event(EventInfo &info) {
}
Refresh();
} else if(info.control == &Goto) {
} else if(info.control == &GotoAddr) {
char t[16 + 1];
GotoAddr.GetText(t, 16);
status.addr = strhex(t) & status.mask;
@ -247,9 +247,9 @@ void MemoryEditor::Setup() {
SetWindowLong(View.hwnd, GWL_WNDPROC, (long)NSMemoryEditor::wndproc_new_memory_view);
Mode.Create(this, "visible", 405, 5, 90, 200, "DRAM|ROM|SRAM|SPCRAM|VRAM|OAM|CGRAM");
GotoAddr.Create(this, "visible|edge", 405, 26, 55, 20, "000000");
GotoLabel.Create(this, "visible", 405, 26 + 4, 35, 15, "Goto:");
GotoAddr.Create(this, "visible|edge", 440, 26, 55, 20, "000000");
GotoAddr.SetFont(global::fwf);
Goto.Create(this, "visible", 460, 26, 35, 20, "Go");
OffsetLabel.Create(this, "visible", 405, 50, 90, 15, "Offset: Data:");
Offset.Create(this, "visible|edge", 405, 65, 55, 20, "000000");

View File

@ -12,8 +12,8 @@ class MemoryEditor : public Window {
public:
Editbox View;
Combobox Mode;
Label GotoLabel;
Editbox GotoAddr;
Button Goto;
Label OffsetLabel;
Editbox Offset;
Editbox Data;

View File

@ -30,7 +30,7 @@ void set_video_profile(uint profile) {
uiVideo->update_video_settings();
string t;
if(bool(config::video.fullscreen) == true) {
if(uiVideo->settings.fullscreen == true) {
strcpy(t, "topmost|popup");
if(wMain.Visible())strcat(t, "|visible");
wMain.HideMenu();
@ -57,12 +57,21 @@ string t;
}
void toggle_fullscreen() {
config::video.fullscreen.toggle();
if(bool(config::video.fullscreen) == true) {
wSettings.Hide();
wAbout.Hide();
debugger.deactivate();
bool fullscreen = !uiVideo->settings.fullscreen;
uint i;
for(i = 0; i < 8; i++) {
if(video_settings[i].fullscreen == fullscreen)break;
}
if(i <= 7) {
if(fullscreen == true) {
wSettings.Hide();
wAbout.Hide();
debugger.deactivate();
}
config::video.profile = i;
}
event::set_video_profile(config::video.profile);
}

View File

@ -12,13 +12,17 @@
#include "../video/d3d.h"
#include "../video/ddraw.h"
//#include "../video/sdl.h"
#include "../audio/dsound.h"
#include "../input/dinput.h"
//#include "../input/sdl.h"
#include "../video/d3d.cpp"
#include "../video/ddraw.cpp"
//#include "../video/sdl.cpp"
#include "../audio/dsound.cpp"
#include "../input/dinput.cpp"
//#include "../input/sdl.cpp"
#include "event.cpp"
#include "ui.cpp"

View File

@ -85,7 +85,7 @@ int x = 15, y = 30;
GammaSlider.SetPos(int32(config::snes.gamma));
y += 75;
GammaRamp.Create(this, "visible", x, y, 475, 15, "Half Gamma Adjust (darkens image, helps prevent washed out colors)");
GammaRamp.Create(this, "visible", x, y, 475, 15, "Half gamma adjust (darkens image, helps prevent washed out colors)");
GammaRamp.Check(config::snes.gamma_ramp);
y += 15;
Sepia.Create(this, "visible", x, y, 475, 15, "Sepia");
@ -94,7 +94,7 @@ int x = 15, y = 30;
Grayscale.Create(this, "visible", x, y, 475, 15, "Grayscale");
Grayscale.Check(config::snes.grayscale);
y += 15;
Invert.Create(this, "visible", x, y, 475, 15, "Invert Colors");
Invert.Create(this, "visible", x, y, 475, 15, "Invert colors");
Invert.Check(config::snes.invert);
y += 20;

View File

@ -9,6 +9,8 @@ bool VideoSettingsWindow::Event(EventInfo &info) {
SaveSettings(VideoProfile.GetSelection());
} else if(info.control == &SelectProfile) {
event::set_video_profile(VideoProfile.GetSelection());
} else if(info.control == &ManualRenderSize || info.control == &Fullscreen) {
UpdateControls();
}
} break;
@ -17,6 +19,19 @@ bool VideoSettingsWindow::Event(EventInfo &info) {
return false;
}
void VideoSettingsWindow::UpdateControls() {
bool r = ManualRenderSize.Checked();
Multiplier.Enable(!r);
FixAspectRatio.Enable(!r);
RenderWidth.Enable(r);
RenderHeight.Enable(r);
r = Fullscreen.Checked();
FullResWidth.Enable(r);
FullResHeight.Enable(r);
FullResHz.Enable(r);
}
void VideoSettingsWindow::LoadSettings(uint profile) {
load_video_settings(profile);
@ -30,10 +45,13 @@ VideoSettings *v = &video_settings[profile];
ManualRenderSize.Check(v->manual_render_size);
RenderWidth.SetText("%d", v->render_width);
RenderHeight.SetText("%d", v->render_height);
Fullscreen.Check(v->fullscreen);
TripleBuffering.Check(v->triple_buffering);
FullResWidth.SetText("%d", v->resolution_width);
FullResHeight.SetText("%d", v->resolution_height);
FullResHz.SetText("%d", v->refresh_rate);
TripleBuffering.Check(v->triple_buffering);
UpdateControls();
}
void VideoSettingsWindow::SaveSettings(uint profile) {
@ -50,13 +68,14 @@ char t[64 + 1];
v->render_width = strdec(t);
RenderHeight.GetText(t, 64);
v->render_height = strdec(t);
v->fullscreen = Fullscreen.Checked();
v->triple_buffering = TripleBuffering.Checked();
FullResWidth.GetText(t, 64);
v->resolution_width = strdec(t);
FullResHeight.GetText(t, 64);
v->resolution_height = strdec(t);
FullResHz.GetText(t, 64);
v->refresh_rate = strdec(t);
v->triple_buffering = TripleBuffering.Checked();
//update config file line entry
save_video_settings(profile);
@ -107,9 +126,8 @@ int x = 15, y = 30;
FixAspectRatio.Create(this, "visible|auto", x, y, 460, 16, "Correct aspect ratio");
Scanlines.Create(this, "visible|auto", x, y + 15, 460, 15, "Enable hardware scanlines");
ManualRenderSize.Create(this, "visible|auto", x, y + 30, 460, 15,
"Manual render screen size (ignores correct aspect ratio and multiplier settings)");
y += 45;
ManualRenderSize.Create(this, "visible|auto", x, y + 30, 460, 15, "Manual render screen size");
y += 47;
RenderWidthLabel.Create(this, "visible", x, y + 3, 90, 15, "Render width:");
RenderWidth.Create(this, "visible|edge", x + 90, y, 50, 20);
@ -117,19 +135,20 @@ int x = 15, y = 30;
RenderHeight.Create(this, "visible|edge", x + 240, y, 50, 20);
y += 25;
Separator1.Create(this, "visible|sunken", x, y, 460, 3);
Separator2.Create(this, "visible|sunken", x, y, 460, 3);
y += 8;
Fullscreen.Create(this, "visible|auto", x, y, 460, 16, "Fullscreen");
TripleBuffering.Create(this, "visible|auto", x, y + 15, 460, 15, "Triple buffering (buggy, causes sound desync)");
y += 35;
FullResWidthLabel.Create(this, "visible", x, y + 3, 90, 15, "Resolution width:");
FullResWidth.Create(this, "visible|edge", x + 90, y, 50, 20);
FullResHeightLabel.Create(this, "visible", x + 150, y + 3, 90, 15, "Resolution height:");
FullResHeight.Create(this, "visible|edge", x + 240, y, 50, 20);
FullResHzLabel.Create(this, "visible", x + 300, y + 3, 70, 15, "Refresh rate:");
FullResHz.Create(this, "visible|edge", x + 370, y, 50, 20);
y += 22;
TripleBuffering.Create(this, "visible|auto", x, y, 460, 15, "Triple buffering (buggy, causes sound desync)");
y += 20;
y += 27;
ApplySettings.Create(this, "visible", x, y, 120, 25, "Apply settings");
SelectProfile.Create(this, "visible", x + 125, y, 120, 25, "Set as active profile");

View File

@ -20,17 +20,19 @@ Editbox RenderWidth;
Label RenderHeightLabel;
Editbox RenderHeight;
Label Separator2;
Checkbox Fullscreen;
Checkbox TripleBuffering;
Label FullResWidthLabel;
Editbox FullResWidth;
Label FullResHeightLabel;
Editbox FullResHeight;
Label FullResHzLabel;
Editbox FullResHz;
Checkbox TripleBuffering;
Button ApplySettings;
Button SelectProfile;
bool Event(EventInfo &info);
void UpdateControls();
void LoadSettings(uint profile);
void SaveSettings(uint profile);

View File

@ -31,13 +31,28 @@ long height;
init_settings();
init_debugger();
if(strmatch(config::video.renderer.sget(), "dd")) {
uiVideo = new VideoDD();
if(!stricmp(config::system.video.sget(), "dd")) {
uiVideo = new VideoDD(wMain.hwnd);
//} else if(!stricmp(config::system.video.sget(), "sdl")) {
// uiVideo = new VideoSDL((void*)wMain.hwnd);
} else {
uiVideo = new VideoD3D();
uiVideo = new VideoD3D(wMain.hwnd);
}
uiAudio = new AudioDS();
uiInput = new InputDI();
if(!stricmp(config::system.audio.sget(), "none")) {
uiAudio = new Audio();
} else {
uiAudio = new AudioDS(wMain.hwnd);
}
if(!stricmp(config::system.input.sget(), "none")) {
uiInput = new Input();
//} else if(!stricmp(config::system.input.sget(), "sdl")) {
// uiInput = new InputSDL((void*)wMain.hwnd);
} else {
uiInput = new InputDI();
}
uiVideo->init();
uiAudio->init();
uiInput->init();
@ -56,6 +71,7 @@ void term_ui() {
uiVideo->term();
uiAudio->term();
uiInput->term();
SafeDelete(uiVideo);
SafeDelete(uiAudio);
SafeDelete(uiInput);

View File

@ -45,12 +45,11 @@ bool MainWindow::Event(EventInfo &info) {
uint id = info.control_id;
bool ctrl = uiInput->keydown(key->lctrl) || uiInput->keydown(key->rctrl);
if(id == key->esc) {
if(bool(config::video.fullscreen) == false) {
if(uiVideo->settings.fullscreen == false) {
ShowMenu(!MenuVisible());
Center();
} else {
config::video.fullscreen = false;
event::set_video_profile(config::video.profile);
event::toggle_fullscreen();
}
} else if(id == key->f11) {
event::toggle_fullscreen();