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); uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 data); void spcram_write(uint16 addr, uint8 data);
inline uint8 port_read (uint8 port); uint8 port_read (uint8 port);
inline void port_write(uint8 port, uint8 data); void port_write(uint8 port, uint8 data);
/***** /*****
* core APU bus functions * core APU bus functions

View File

@ -8,4 +8,4 @@ bool enabled;
inline void add_clocks(int clocks); inline void add_clocks(int clocks);
inline void tick_timers(); 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 BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus #define MEMCORE bMemBus
@ -28,7 +28,7 @@
#if defined(PROCESSOR_X86) #if defined(PROCESSOR_X86)
#define ARCH_LSB #define ARCH_LSB
#elif defined(PROCESSOR_X86) #elif defined(PROCESSOR_X86_64)
#define ARCH_LSB #define ARCH_LSB
#elif defined(PROCESSOR_G5) #elif defined(PROCESSOR_G5)
#define ARCH_MSB #define ARCH_MSB

View File

@ -197,57 +197,21 @@ FileWriter ff(sram_fn);
ff.write(sram, info.ram_size); 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) { void Cartridge::load_rom(Reader &rf) {
uint8 *data = rf.read(); uint size = rf.size();
uint size = rf.size(); bool header = ((size & 0x7fff) == 512);
bool header = ((size & 0x7fff) == 0x0200);
info.rom_size = size - (header ? 512 : 0); info.rom_size = size - (header ? 512 : 0);
if(info.rom_size & 0x7fff) {
base_rom = (uint8*)malloc(info.rom_size); info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
memcpy(base_rom, data + (header ? 512 : 0), info.rom_size); }
SafeFree(data); base_rom = rf.read(info.rom_size + (header ? 512 : 0));
rom = base_rom + (header ? 512 : 0);
info.crc32 = 0xffffffff; info.crc32 = 0xffffffff;
for(int32 i = 0; i < info.rom_size; i++) { 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.crc32 = ~info.crc32;
info.rom_size = mirror(base_rom, info.rom_size);
rom = base_rom;
} }
bool Cartridge::load(const char *fn) { bool Cartridge::load(const char *fn) {

View File

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

Binary file not shown.

View File

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

View File

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

View File

@ -70,7 +70,6 @@ typedef signed short int16;
typedef signed long int32; typedef signed long int32;
typedef signed long long int64; typedef signed long long int64;
/***** /*****
* templates * 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 ;cross-platform x86 implementation of libco
; ;
;context save/restore adheres to c/c++ ABI ;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 saves esp+ebp+esi+edi+ebx
;context ignores eax+ecx+edx ;context ignores eax+ecx+edx
@ -22,6 +22,7 @@ section .code
;***** ;*****
;linker-specific name decorations ;linker-specific name decorations
;***** ;*****
%ifdef WIN32
%define malloc _malloc %define malloc _malloc
%define free _free %define free _free
@ -33,6 +34,7 @@ section .code
%define co_jump @co_jump@4 %define co_jump @co_jump@4
%define co_call @co_call@4 %define co_call @co_call@4
%define co_return @co_return@0 %define co_return @co_return@0
%endif
extern malloc extern malloc
extern free extern free
@ -47,7 +49,7 @@ global co_call
global co_return global co_return
;***** ;*****
;extern "C" void __fastcall co_init(); ;extern "C" void fastcall co_init();
;***** ;*****
align 16 align 16
@ -65,7 +67,7 @@ co_init:
ret ret
;***** ;*****
;extern "C" void __fastcall co_term(); ;extern "C" void fastcall co_term();
;***** ;*****
align 16 align 16
@ -73,7 +75,7 @@ co_term:
ret ret
;***** ;*****
;extern "C" thread_t __fastcall co_active(); ;extern "C" thread_t fastcall co_active();
;return = eax ;return = eax
;***** ;*****
@ -87,7 +89,7 @@ co_active:
ret 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 ;ecx = coentry
;edx = heapsize ;edx = heapsize
;return = eax ;return = eax
@ -107,8 +109,12 @@ co_create:
;create heap space (stack + register storage) ;create heap space (stack + register storage)
add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align) add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align)
push ecx push ecx
push edx
push edx push edx
call malloc call malloc
add esp,4
pop edx pop edx
pop ecx pop ecx
@ -130,7 +136,7 @@ co_create:
ret ;return allocated memory block as thread handle 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 ;ecx = cothread
;***** ;*****
@ -142,7 +148,7 @@ co_delete:
ret ret
;***** ;*****
;extern "C" void __fastcall co_jump(thread_t cothread); ;extern "C" void fastcall co_jump(thread_t cothread);
;ecx = cothread ;ecx = cothread
;***** ;*****
@ -166,7 +172,7 @@ co_jump:
ret ret
;***** ;*****
;extern "C" void __fastcall co_call(thread_t cothread); ;extern "C" void fastcall co_call(thread_t cothread);
;ecx = cothread ;ecx = cothread
;***** ;*****
@ -191,7 +197,7 @@ co_call:
ret ret
;***** ;*****
;extern "C" void __fastcall co_return(); ;extern "C" void fastcall co_return();
;***** ;*****
align 16 align 16

View File

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

View File

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

View File

@ -55,6 +55,15 @@ enum { TYPE_WRAM, TYPE_MMIO, TYPE_CART };
void power(); void power();
void reset(); 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();
~bMemBus(); ~bMemBus();
}; };

View File

@ -15,22 +15,8 @@
* $[80-bf]:[2000-5fff] MMIO * $[80-bf]:[2000-5fff] MMIO
*****/ *****/
void bMemBus::cart_map_generic(uint type) { void bMemBus::cart_map_generic(uint type) {
uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size; uint rom_size = cartridge.info.rom_size;
ROM_size = cartridge.info.rom_size; uint ram_size = cartridge.info.ram_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);
}
for(uint page = 0x0000; page <= 0xffff; page++) { for(uint page = 0x0000; page <= 0xffff; page++) {
if(memory_type(page << 8) != TYPE_CART)continue; 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 //HiROM SRAM region
//$[20-3f|a0-bf]:[6000-7fff] //$[20-3f|a0-bf]:[6000-7fff]
if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr & 0xe000) == 0x6000) { 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 = ((bank & 0x7f) - 0x20) * 0x2000 + ((addr & 0xffff) - 0x6000);
addr %= SRAM_size; addr %= ram_size;
page_handle[page] = cartridge.sram + addr; page_handle[page] = cartridge.sram + addr;
page_read [page] = &bMemBus::read_ram; page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_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] //$[70-7f|f0-ff]:[0000-7fff]
//Note: WRAM is remapped over $[7e-7f]:[0000-ffff] //Note: WRAM is remapped over $[7e-7f]:[0000-ffff]
if(bank >= 0x70 && bank <= 0x7f && (addr & 0x8000) == 0x0000) { if(bank >= 0x70 && bank <= 0x7f && (addr & 0x8000) == 0x0000) {
if(SRAM_size == 0)continue; if(ram_size == 0)continue;
if(type == Cartridge::LOROM || !(bank & 0x80)) { if(type == Cartridge::LOROM || !(bank & 0x80)) {
//HiROM maps $[f0-ff]:[0000-7fff] to ROM //HiROM maps $[f0-ff]:[0000-7fff] to ROM
addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff); addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff);
addr %= SRAM_size; addr %= ram_size;
page_handle[page] = cartridge.sram + addr; page_handle[page] = cartridge.sram + addr;
page_read [page] = &bMemBus::read_ram; page_read [page] = &bMemBus::read_ram;
page_write [page] = &bMemBus::write_ram; page_write [page] = &bMemBus::write_ram;
@ -82,18 +68,12 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
switch(type) { switch(type) {
case Cartridge::LOROM: { case Cartridge::LOROM: {
addr = (bank & 0x7f) * 0x8000 + (addr & 0x7fff); addr = (bank & 0x7f) * 0x8000 + (addr & 0x7fff);
addr &= ROM_mask; addr = mirror(rom_size, addr);
if(addr >= P0_size) {
addr = P0_size + (addr & (P1_size - 1));
}
} break; } break;
case Cartridge::HIROM: { case Cartridge::HIROM: {
addr &= ROM_mask; addr = mirror(rom_size, addr);
if(addr >= P0_size) {
addr = P0_size + (addr & (P1_size - 1));
}
} break; } break;
case Cartridge::EXLOROM: { case Cartridge::EXLOROM: {
@ -103,13 +83,13 @@ uint32 P0_size, P1_size, ROM_mask, ROM_size, SRAM_size;
} else { } else {
addr &= 0x3fffff; addr &= 0x3fffff;
} }
addr %= ROM_size; addr = mirror(rom_size, addr);
} break; } break;
case Cartridge::EXHIROM: { case Cartridge::EXHIROM: {
addr &= 0x3fffff; addr &= 0x3fffff;
addr += (bank < 0x80) ? 0x400000 : 0x000000; addr += (bank < 0x80) ? 0x400000 : 0x000000;
addr %= ROM_size; addr = mirror(rom_size, addr);
} break; } 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( void bMemBus::cart_map_range(
uint mode, uint mode,
uint8 bank_lo, uint8 bank_hi, 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++) { for(uint page = page_lo; page <= page_hi; page++) {
uint16 n = (bank << 8) + page; uint16 n = (bank << 8) + page;
page_handle[n] = data + index; page_handle[n] = data + mirror(size, index);
if(size) { index = (index + 256) % size; } if(size) { index = (index + 256) % size; }
switch(type) { switch(type) {

View File

@ -14,6 +14,7 @@ enum {
MAP_OBC1, 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); 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() #define mapper(name) void cart_map_##name()

View File

@ -6,7 +6,6 @@ void bPPU::run() {}
void bPPU::scanline() { void bPPU::scanline() {
line.y = r_cpu->vcounter(); line.y = r_cpu->vcounter();
line.width = (regs.hires) ? 512 : 256;
line.interlace = r_cpu->interlace(); line.interlace = r_cpu->interlace();
line.interlace_field = r_cpu->interlace_field(); line.interlace_field = r_cpu->interlace_field();
@ -89,8 +88,8 @@ void bPPU::power() {
region = snes->region(); region = snes->region();
//$2100 //$2100
regs.display_disabled = 0; regs.display_disabled = 1;
regs.display_brightness = 0; regs.display_brightness = 15;
//$2101 //$2101
regs.oam_basesize = 0; regs.oam_basesize = 0;
@ -99,12 +98,12 @@ void bPPU::power() {
//$2102-$2103 //$2102-$2103
regs.oam_baseaddr = 0x0000; regs.oam_baseaddr = 0x0000;
regs.oam_addr = 0x0000; regs.oam_addr = regs.oam_baseaddr << 1;
regs.oam_priority = false; regs.oam_priority = false;
regs.oam_firstsprite = 0x00; regs.oam_firstsprite = 0;
//$2104 //$2104
regs.oam_latchdata = 0x00; regs.oam_latchdata = 0x00;
//$2105 //$2105
regs.bg_tilesize[BG1] = 0; regs.bg_tilesize[BG1] = 0;
@ -113,7 +112,6 @@ void bPPU::power() {
regs.bg_tilesize[BG4] = 0; regs.bg_tilesize[BG4] = 0;
regs.bg3_priority = 0; regs.bg3_priority = 0;
regs.bg_mode = 0; regs.bg_mode = 0;
regs.hires = false;
//$2106 //$2106
regs.mosaic_size = 0; regs.mosaic_size = 0;
@ -205,10 +203,10 @@ void bPPU::power() {
regs.window2_invert [COL] = false; regs.window2_invert [COL] = false;
//$2126-$2129 //$2126-$2129
regs.window1_left = 0; regs.window1_left = 0x00;
regs.window1_right = 0; regs.window1_right = 0x00;
regs.window2_left = 0; regs.window2_left = 0x00;
regs.window2_right = 0; regs.window2_right = 0x00;
//$212a-$212b //$212a-$212b
regs.window_mask[BG1] = 0; regs.window_mask[BG1] = 0;
@ -245,7 +243,8 @@ void bPPU::power() {
//$2130 //$2130
regs.color_mask = 0; regs.color_mask = 0;
regs.colorsub_mask = 0; regs.colorsub_mask = 0;
regs.addsub_mode = 0; regs.addsub_mode = false;
regs.direct_color = false;
//$2131 //$2131
regs.color_mode = 0; regs.color_mode = 0;
@ -304,7 +303,6 @@ void bPPU::reset() {
regs.bg_y[2] = 0; regs.bg_y[2] = 0;
regs.bg_y[3] = 0; regs.bg_y[3] = 0;
line.width = 256;
clear_tiledata_cache(); clear_tiledata_cache();
} }
@ -377,62 +375,25 @@ bPPU::bPPU() {
init_tiledata_cache(); init_tiledata_cache();
for(int l = 0; l < 16; l++) { for(int l = 0; l < 16; l++) {
mosaic_table[l] = (uint16*)malloc(4096 * 2);
for(int i = 0; i < 4096; i++) { for(int i = 0; i < 4096; i++) {
mosaic_table[l][i] = (i / (l + 1)) * (l + 1); 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++) { for(int l = 0; l < 16; l++) {
int r, g, b; 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; double m = (double)l / 15.0;
for(int i = 0; i < 32768; i++) { for(int i = 0; i < 32768; i++) {
if(l == 0) { *ptr++ = 0; continue; }
if(l == 15) { *ptr++ = i; continue; }
r = (i ) & 31; r = (i ) & 31;
g = (i >> 5) & 31; g = (i >> 5) & 31;
b = (i >> 10) & 31; b = (i >> 10) & 31;
r = minmax<0, 31>((int)((double)r * m)); r = minmax<0, 31>( (int)((double)r * m + 0.5) );
g = minmax<0, 31>((int)((double)g * m)); g = minmax<0, 31>( (int)((double)g * m + 0.5) );
b = minmax<0, 31>((int)((double)b * m)); 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(vram);
SafeFree(oam); SafeFree(oam);
SafeFree(cgram); 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 }; enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
struct { struct {
uint32 y; uint y;
uint32 width; bool interlace;
bool interlace; bool interlace_field;
bool interlace_field;
} line; } line;
struct { struct {
@ -43,7 +42,6 @@ struct {
bool bg_tilesize[4]; bool bg_tilesize[4];
bool bg3_priority; bool bg3_priority;
uint8 bg_mode; uint8 bg_mode;
bool hires;
//$2106 //$2106
uint8 mosaic_size; uint8 mosaic_size;
@ -227,8 +225,8 @@ struct {
#include "bppu_render.h" #include "bppu_render.h"
uint16 *light_table; uint16 light_table[16][32768];
uint16 *mosaic_table[16]; uint16 mosaic_table[16][4096];
void render_line(); void render_line();
void update_oam_status(); void update_oam_status();
@ -240,7 +238,7 @@ uint16 *mosaic_table[16];
void power(); void power();
void reset(); 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();
~bPPU(); ~bPPU();

View File

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

View File

@ -45,7 +45,7 @@ Mode 0: ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
BG4B, BG3B, OAM0, BG4A, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 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(BG1, COLORDEPTH_4, 8, 11);
render_line_bg(BG2, COLORDEPTH_4, 7, 10); render_line_bg(BG2, COLORDEPTH_4, 7, 10);
render_line_bg(BG3, COLORDEPTH_4, 2, 5); 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 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3 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) { if(regs.bg3_priority) {
render_line_bg(BG1, COLORDEPTH_16, 5, 8); render_line_bg(BG1, COLORDEPTH_16, 5, 8);
render_line_bg(BG2, COLORDEPTH_16, 4, 7); render_line_bg(BG2, COLORDEPTH_16, 4, 7);
@ -81,7 +81,7 @@ Mode 2: ->
1, 2, 3, 4, 5, 6, 7, 8 1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 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(BG1, COLORDEPTH_16, 3, 7);
render_line_bg(BG2, COLORDEPTH_16, 1, 5); render_line_bg(BG2, COLORDEPTH_16, 1, 5);
render_line_oam(2, 4, 6, 8); render_line_oam(2, 4, 6, 8);
@ -92,7 +92,7 @@ Mode 3: ->
1, 2, 3, 4, 5, 6, 7, 8 1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 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(BG1, COLORDEPTH_256, 3, 7);
render_line_bg(BG2, COLORDEPTH_16, 1, 5); render_line_bg(BG2, COLORDEPTH_16, 1, 5);
render_line_oam(2, 4, 6, 8); render_line_oam(2, 4, 6, 8);
@ -103,7 +103,7 @@ Mode 4: ->
1, 2, 3, 4, 5, 6, 7, 8 1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 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(BG1, COLORDEPTH_256, 3, 7);
render_line_bg(BG2, COLORDEPTH_4, 1, 5); render_line_bg(BG2, COLORDEPTH_4, 1, 5);
render_line_oam(2, 4, 6, 8); render_line_oam(2, 4, 6, 8);
@ -114,7 +114,7 @@ Mode 5: ->
1, 2, 3, 4, 5, 6, 7, 8 1, 2, 3, 4, 5, 6, 7, 8
BG2B, OAM0, BG1B, OAM1, BG2A, OAM2, BG1A, OAM3 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(BG1, COLORDEPTH_16, 3, 7);
render_line_bg(BG2, COLORDEPTH_4, 1, 5); render_line_bg(BG2, COLORDEPTH_4, 1, 5);
render_line_oam(2, 4, 6, 8); render_line_oam(2, 4, 6, 8);
@ -125,7 +125,7 @@ Mode 6: ->
1, 2, 3, 4, 5, 6 1, 2, 3, 4, 5, 6
OAM0, BG1B, OAM1, OAM2, BG1A, OAM3 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_bg(BG1, COLORDEPTH_16, 2, 5);
render_line_oam(1, 3, 4, 6); render_line_oam(1, 3, 4, 6);
} }
@ -139,7 +139,7 @@ Mode 7 EXTBG: ->
1, 2, 3, 4, 5, 6, 7 1, 2, 3, 4, 5, 6, 7
BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3 BG2B, OAM0, BG1n, OAM1, BG2A, OAM2, OAM3
*/ */
inline void bPPU::render_line_mode7() { void bPPU::render_line_mode7() {
if(regs.mode7_extbg == false) { if(regs.mode7_extbg == false) {
render_line_mode7(BG1, 2, 2); render_line_mode7(BG1, 2, 2);
render_line_oam(1, 3, 4, 5); render_line_oam(1, 3, 4, 5);
@ -151,7 +151,7 @@ inline void bPPU::render_line_mode7() {
} }
void bPPU::render_line() { 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); memset(output + (line.y * 1024), 0, 1024);
return; 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); inline uint16 addsub(uint32 x, uint32 y, bool halve);
//bppu_render_line.cpp //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_palette(uint8 index);
inline uint16 get_direct_color(uint8 p, uint8 t); inline uint16 get_direct_color(uint8 p, uint8 t);
inline uint16 get_pixel_normal(uint32 x); inline uint16 get_pixel_normal(uint32 x);
inline uint16 get_pixel_swap(uint32 x); inline uint16 get_pixel_swap(uint32 x);
inline uint16 get_pixel_lores(uint32 x); inline void render_line_output();
inline uint16 get_pixel_hires(uint32 x);
inline void render_line_output();

View File

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

View File

@ -99,9 +99,9 @@ uint8 *dest;
#undef render_bg_tile_line_4bpp #undef render_bg_tile_line_4bpp
#undef render_bg_tile_line_8bpp #undef render_bg_tile_line_8bpp
inline void bPPU::clear_pixel_cache() { void bPPU::clear_pixel_cache() {
uint16 main = get_palette(0); 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; uint32 i = 255;
do { do {
pixel_cache[i].src_main = main; pixel_cache[i].src_main = main;

View File

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

View File

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

View File

@ -1,90 +1,127 @@
ifeq ($(PLATFORM),win-visualc) # bsnes makefile
CC = cl
CXX = cl ##################################
### 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 AS = nasm
RM = del ASFLAGS = -f elf
OBJ = obj LIBS = `pkg-config --libs gtk+-2.0` `sdl-config --libs`
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 endif
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32 ifeq ($(PLATFORM),win-visualc)
LINK = OS = win
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \ CC = cl
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib 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 endif
ifeq ($(PLATFORM),win-visualc-wip) ifeq ($(PLATFORM),win-visualc-wip)
OS = win
CC = cl CC = cl
CXX = cl CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm AS = nasm
RM = del ASFLAGS = -f win32 -DWIN32
OBJ = obj LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /LTCG 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 endif
ifeq ($(PLATFORM),win-visualc-pgi) ifeq ($(PLATFORM),win-visualc-pgi)
OS = win
CC = cl CC = cl
CXX = cl CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm AS = nasm
RM = del ASFLAGS = -f win32 -DWIN32
OBJ = obj LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT 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 endif
ifeq ($(PLATFORM),win-visualc-pgo) ifeq ($(PLATFORM),win-visualc-pgo)
OS = win
CC = cl CC = cl
CXX = cl CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN
AS = nasm AS = nasm
RM = del ASFLAGS = -f win32 -DWIN32
OBJ = obj LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE 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 endif
ifeq ($(PLATFORM),win-visualc-sdl) ifeq ($(PLATFORM),win-visualc-sdl)
OS = win
CC = cl CC = cl
CXX = cl CFLAGS = /nologo /O2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_SDL
AS = nasm AS = nasm
RM = del ASFLAGS = -f win32 -DWIN32
OBJ = obj LIBS = sdlmain.lib sdl.lib dsound.lib
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
endif endif
OBJS = main.$(OBJ) \ #####################################
libco.$(OBJ) libstring.$(OBJ) libconfig.$(OBJ) \ ### compiler / assembler switches ###
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) \ #####################################
memory.$(OBJ) bmemory.$(OBJ) \
cpu.$(OBJ) scpu.$(OBJ) bcpu.$(OBJ) \ ifeq ($(CC),gcc)
apu.$(OBJ) sapu.$(OBJ) bapu.$(OBJ) \ OUT = -obsnes
bdsp.$(OBJ) \ CXX = g++
ppu.$(OBJ) bppu.$(OBJ) \ OBJ = o
snes.$(OBJ) \ COBJFLAG = -c
srtc.$(OBJ) sdd1.$(OBJ) c4.$(OBJ) dsp1.$(OBJ) dsp2.$(OBJ) obc1.$(OBJ) endif
# 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) \ ifeq ($(CC),cl)
# jma.$(OBJ) jcrc32.$(OBJ) lzmadec.$(OBJ) 7zlzma.$(OBJ) iiostrm.$(OBJ) inbyte.$(OBJ) lzma.$(OBJ) winout.$(OBJ) 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) all: $(OBJS)
rc /r /fobsnes.res bsnes.rc $(CXX) $(OUT) $(CFLAGS) $(OBJS) $(LIBS) $(LINK)
$(CC) /Febsnes.exe $(CFLAGS) $(OBJS) bsnes.res $(LIBS) $(LINK)
# mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1 # mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
clean: clean:
@ -99,117 +136,120 @@ clean:
######################### #########################
### platform-specific ### ### platform-specific ###
######################### #########################
main.$(OBJ): *.cpp *.h video/* audio/* input/* ../config/* win/* win/settings/* win/debugger/* main.$(OBJ): *.cpp *.h video/* audio/* input/* ../config/* win/* win/settings/* win/debugger/* sdl/*
$(COMPILE) main.cpp $(CXX) $(CFLAGS) $(COBJFLAG) main.cpp
bsnes.res: bsnes.rc
rc /r /fobsnes.res bsnes.rc
################# #################
### libraries ### ### libraries ###
################# #################
libco.$(OBJ): ../lib/* libco.$(OBJ): ../lib/*
$(ASSEMBLE) -o libco.$(OBJ) ../lib/libco_x86.asm $(AS) $(ASFLAGS) $(ASOBJFLAG) libco.$(OBJ) ../lib/libco_x86.asm
# $(COMPILE) /Folibco.obj ../lib/libco_win32.cpp # $(CXX) $(CFLAGS) $(COBJFLAG) /Folibco.$(OBJ) ../lib/libco_win32.cpp
libstring.$(OBJ): ../lib/*.cpp ../lib/*.h libstring.$(OBJ): ../lib/*.cpp ../lib/*.h
$(COMPILE) ../lib/libstring.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../lib/libstring.cpp
libconfig.$(OBJ): ../lib/*.cpp ../lib/*.h libconfig.$(OBJ): ../lib/*.cpp ../lib/*.h
$(COMPILE) ../lib/libconfig.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../lib/libconfig.cpp
############## ##############
### memory ### ### memory ###
############## ##############
memory.$(OBJ): ../memory/memory.cpp ../memory/memory.h 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/* bmemory.$(OBJ): ../memory/bmemory/* ../memory/bmemory/mapper/*
$(COMPILE) ../memory/bmemory/bmemory.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../memory/bmemory/bmemory.cpp
########### ###########
### cpu ### ### cpu ###
########### ###########
cpu.$(OBJ): ../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/* 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/* bcpu.$(OBJ): ../cpu/bcpu/*
$(COMPILE) ../cpu/bcpu/bcpu.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../cpu/bcpu/bcpu.cpp
########### ###########
### apu ### ### apu ###
########### ###########
apu.$(OBJ): ../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/* 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/* bapu.$(OBJ): ../apu/bapu/*
$(COMPILE) ../apu/bapu/bapu.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../apu/bapu/bapu.cpp
########### ###########
### dsp ### ### dsp ###
########### ###########
bdsp.$(OBJ): ../dsp/bdsp/* bdsp.$(OBJ): ../dsp/bdsp/*
$(COMPILE) ../dsp/bdsp/bdsp.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../dsp/bdsp/bdsp.cpp
########### ###########
### ppu ### ### ppu ###
########### ###########
ppu.$(OBJ): ../ppu/*.cpp ../ppu/*.h ppu.$(OBJ): ../ppu/*.cpp ../ppu/*.h
$(COMPILE) ../ppu/ppu.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../ppu/ppu.cpp
bppu.$(OBJ): ../ppu/bppu/* bppu.$(OBJ): ../ppu/bppu/*
$(COMPILE) ../ppu/bppu/bppu.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../ppu/bppu/bppu.cpp
################# #################
### utilities ### ### utilities ###
################# #################
reader.$(OBJ): ../reader/*.cpp ../reader/*.h reader.$(OBJ): ../reader/*.cpp ../reader/*.h
$(COMPILE) ../reader/reader.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../reader/reader.cpp
cart.$(OBJ): ../cart/*.cpp ../cart/*.h cart.$(OBJ): ../cart/*.cpp ../cart/*.h
$(COMPILE) ../cart/cart.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../cart/cart.cpp
cheat.$(OBJ): ../cheat/*.cpp ../cheat/*.h cheat.$(OBJ): ../cheat/*.cpp ../cheat/*.h
$(COMPILE) ../cheat/cheat.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../cheat/cheat.cpp
############ ############
### snes ### ### snes ###
############ ############
snes.$(OBJ): ../snes/* ../snes/video/* ../snes/audio/* ../snes/input/* snes.$(OBJ): ../snes/* ../snes/video/* ../snes/audio/* ../snes/input/*
$(COMPILE) ../snes/snes.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../snes/snes.cpp
##################### #####################
### special chips ### ### special chips ###
##################### #####################
srtc.$(OBJ): ../chip/srtc/* srtc.$(OBJ): ../chip/srtc/*
$(COMPILE) ../chip/srtc/srtc.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/srtc/srtc.cpp
sdd1.$(OBJ): ../chip/sdd1/* sdd1.$(OBJ): ../chip/sdd1/*
$(COMPILE) ../chip/sdd1/sdd1.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/sdd1/sdd1.cpp
c4.$(OBJ): ../chip/c4/* c4.$(OBJ): ../chip/c4/*
$(COMPILE) ../chip/c4/c4.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/c4/c4.cpp
dsp1.$(OBJ): ../chip/dsp1/* dsp1.$(OBJ): ../chip/dsp1/*
$(COMPILE) ../chip/dsp1/dsp1.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/dsp1/dsp1.cpp
dsp2.$(OBJ): ../chip/dsp2/* dsp2.$(OBJ): ../chip/dsp2/*
$(COMPILE) ../chip/dsp2/dsp2.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/dsp2/dsp2.cpp
obc1.$(OBJ): ../chip/obc1/* obc1.$(OBJ): ../chip/obc1/*
$(COMPILE) ../chip/obc1/obc1.cpp $(CXX) $(CFLAGS) $(COBJFLAG) ../chip/obc1/obc1.cpp
############ ############
### zlib ### ### zlib ###
############ ############
adler32.$(OBJ): ../reader/zlib/*.c ../reader/zlib/*.h adler32.$(OBJ): ../reader/zlib/*.c ../reader/zlib/*.h
$(COMPILE) ../reader/zlib/*.c $(CC) $(CFLAGS) $(COBJFLAG) ../reader/zlib/*.c
########### ###########
### jma ### ### jma ###
########### ###########
jma.$(OBJ): ../reader/jma/*.cpp ../reader/jma/*.h 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 { class Audio {
public: public:
uint frequency; uint frequency;
virtual void run(uint32 sample) = 0; virtual void run(uint32 sample) {}
virtual void set_frequency(uint new_freq) = 0; virtual void set_frequency(uint new_freq) {}
virtual void clear_audio() = 0; virtual void clear_audio() {}
virtual void init() = 0; virtual void init() {}
virtual void term() = 0; virtual void term() {}
Audio() : frequency(32000) {} Audio() : frequency(32000) {}
} *uiAudio; } *uiAudio;

View File

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

View File

@ -2,6 +2,7 @@
class AudioDS : public Audio { class AudioDS : public Audio {
public: public:
HWND hwnd;
LPDIRECTSOUND ds; LPDIRECTSOUND ds;
LPDIRECTSOUNDBUFFER dsb_p, dsb_b; LPDIRECTSOUNDBUFFER dsb_p, dsb_b;
DSBUFFERDESC dsbd; DSBUFFERDESC dsbd;
@ -21,7 +22,8 @@ struct {
void init(); void init();
void term(); void term();
AudioDS() { AudioDS(HWND handle = 0) {
hwnd = (handle) ? handle : GetDesktopWindow();
ds = 0; ds = 0;
dsb_p = 0; dsb_p = 0;
dsb_b = 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 { namespace config {
struct System { struct System {
static Setting video, audio, input;
static Setting regulate_speed; static Setting regulate_speed;
static Setting speed_slowest, speed_slow, speed_normal, speed_fast, speed_fastest; static Setting speed_slowest, speed_slow, speed_normal, speed_fast, speed_fastest;
} system; } 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::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_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); 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); Setting System::speed_fastest (&config_file, "system.speed_fastest", "Fastest speed setting", 64000, Setting::DEC);
struct Video { struct Video {
static Setting renderer; static Setting profile;
static Setting profile, fullscreen;
static Setting profile_0, profile_1, profile_2, profile_3; static Setting profile_0, profile_1, profile_2, profile_3;
static Setting profile_4, profile_5, profile_6, profile_7; 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; static Setting pscanline_intensity, iscanline_intensity;
} video; } 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::profile(&config_file, "video.profile", "", 2, Setting::DEC);
Setting Video::fullscreen(0, "video.fullscreen", "", false, Setting::TRUE_FALSE);
/* software_filter /* software_filter
* hardware_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" "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" "Format: software_filter;hardware_filter;video_standard;multiplier-1;correct_aspect_ratio;\n"
" enable_scanlines;manual_render_size;render_width;render_height;\n" " enable_scanlines;manual_render_size;render_width;render_height;\n"
" resolution_width;resolution_height;refresh_rate;triple_buffering" " fullscreen;triple_buffering;resolution_width;resolution_height;refresh_rate"
"", "0;0;0;0;false;false;false;256;224;0;0;0;false"); "", "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;0;0;0;false"); 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;0;0;0;false"); 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;0;0;0;false"); 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;0;0;0;false"); 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;0;0;0;false;false;false;256;224;0;0;0;false"); 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;0;0;0;false;false;false;256;224;0;0;0;false"); 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;0;0;0;false;false;false;256;224;0;0;0;false"); 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::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", Setting Video::pscanline_intensity(&config_file, "video.pscanline_intensity",
"Progressive scanline intensity\n" "Progressive scanline intensity\n"
"Value is percentage of intensity from 0 to 100", 30, Setting::DEC); "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() keymap key; //this must be initialized by init()
bool8 keystate[4096]; bool8 keystate[4096];
virtual void poll() = 0; virtual void poll() {}
virtual void poll(uint8 device); virtual void poll(uint8 device);
virtual void init(); virtual void init();
virtual void term(); 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 * platform abstraction layer
*****/ *****/
#if defined(PLATFORM_WIN) #if defined(UI_WIN)
#include "win/main.cpp" #include "win/main.cpp"
#elif defined(PLATFORM_SDL) #elif defined(UI_GTK)
#include "gtk/main.cpp"
#elif defined(UI_SDL)
#include "sdl/main.cpp" #include "sdl/main.cpp"
#else #else
#error "unsupported platform" #error "unsupported platform"

View File

@ -22,7 +22,9 @@ void bSNES::video_run() {
render(); render();
} }
void bSNES::sound_run(uint32 data) {} void bSNES::sound_run(uint32 data) {
uiAudio->run(data);
}
uint16 *bSNES::video_lock(uint &pitch) { uint16 *bSNES::video_lock(uint &pitch) {
if(SDL_MUSTLOCK(screen)) { if(SDL_MUSTLOCK(screen)) {
@ -49,57 +51,12 @@ void bSNES::video_unlock() {
*** Input functions *** *** 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) { void bSNES::poll_input(uint8 type) {
uint8 *keystate = SDL_GetKeyState(0); uiInput->poll(type);
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;
} }
bool bSNES::get_input_status(uint8 device, uint8 button) { bool bSNES::get_input_status(uint8 device, uint8 button) {
switch(device) { return uiInput->get_status(device, button);
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;
} }
void bSNES::notify(uint32 message, uint32 param1, uint32 param2) {} 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 { class bSNES : public SNES {
private: private:
uint32 run_status; uint32 run_status;
bJoypad joypad1, joypad2;
public: public:
enum { STOP = 0, RUN }; enum { STOP = 0, RUN };

View File

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

View File

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

View File

@ -16,7 +16,7 @@ HRESULT hr;
presentation.Flags = D3DPRESENTFLAG_VIDEO; presentation.Flags = D3DPRESENTFLAG_VIDEO;
presentation.SwapEffect = (settings.triple_buffering == true) ? presentation.SwapEffect = (settings.triple_buffering == true) ?
D3DSWAPEFFECT_FLIP : D3DSWAPEFFECT_DISCARD; D3DSWAPEFFECT_FLIP : D3DSWAPEFFECT_DISCARD;
presentation.hDeviceWindow = wMain.hwnd; presentation.hDeviceWindow = hwnd;
presentation.BackBufferCount = (settings.triple_buffering == true) ? 2 : 1; presentation.BackBufferCount = (settings.triple_buffering == true) ? 2 : 1;
presentation.MultiSampleType = D3DMULTISAMPLE_NONE; presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
presentation.MultiSampleQuality = 0; presentation.MultiSampleQuality = 0;
@ -26,7 +26,7 @@ HRESULT hr;
D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
presentation.FullScreen_RefreshRateInHz = settings.refresh_rate; presentation.FullScreen_RefreshRateInHz = settings.refresh_rate;
if(bool(config::video.fullscreen) == false) { if(settings.fullscreen == false) {
presentation.Windowed = true; presentation.Windowed = true;
presentation.BackBufferFormat = D3DFMT_UNKNOWN; presentation.BackBufferFormat = D3DFMT_UNKNOWN;
presentation.BackBufferWidth = 0; presentation.BackBufferWidth = 0;
@ -38,7 +38,7 @@ HRESULT hr;
presentation.BackBufferHeight = settings.resolution_height; 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); D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentation, &device);
if(hr != D3D_OK) { if(hr != D3D_OK) {
alert("Failed to create Direct3D9 device"); alert("Failed to create Direct3D9 device");
@ -328,6 +328,8 @@ void VideoD3D::update() {
} }
bool VideoD3D::capture_screenshot() { bool VideoD3D::capture_screenshot() {
if(!d3dx || !pD3DXSaveSurfaceToFileA) { return false; }
//fill both backbuffers with currently rendered image //fill both backbuffers with currently rendered image
redraw(); redraw();
redraw(); redraw();
@ -358,8 +360,7 @@ uint32 format;
format = D3DXIFF_PNG; format = D3DXIFF_PNG;
} }
D3DXSaveSurfaceToFile(fn, static_cast<D3DXIMAGE_FILEFORMAT>(format), pD3DXSaveSurfaceToFileA(fn, format, temp_surface, NULL, NULL);
temp_surface, NULL, NULL);
temp_surface->Release(); temp_surface->Release();
return true; return true;
} }
@ -379,7 +380,9 @@ void VideoD3D::term() {
SafeRelease(lpd3d); SafeRelease(lpd3d);
} }
VideoD3D::VideoD3D() { VideoD3D::VideoD3D(HWND handle) {
hwnd = handle;
vertex_buffer = 0; vertex_buffer = 0;
surface = 0; surface = 0;
texture = 0; texture = 0;
@ -388,6 +391,56 @@ VideoD3D::VideoD3D() {
scanline[2] = 0; scanline[2] = 0;
device = 0; device = 0;
lpd3d = 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 #undef D3DVERTEX

View File

@ -1,8 +1,8 @@
#include <d3d9.h> #include <d3d9.h>
#include <d3dx9.h>
class VideoD3D : public Video { class VideoD3D : public Video {
public: public:
HWND hwnd;
LPDIRECT3D9 lpd3d; LPDIRECT3D9 lpd3d;
LPDIRECT3DDEVICE9 device; LPDIRECT3DDEVICE9 device;
LPDIRECT3DVERTEXBUFFER9 vertex_buffer, *vertex_ptr; LPDIRECT3DVERTEXBUFFER9 vertex_buffer, *vertex_ptr;
@ -14,6 +14,10 @@ D3DCAPS9 d3dcaps;
LPDIRECT3DTEXTURE9 texture, scanline[3]; LPDIRECT3DTEXTURE9 texture, scanline[3];
LPDIRECT3DSURFACE9 surface, temp_surface; 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 { struct d3dvertex {
float x, y, z, rhw; //screen coords float x, y, z, rhw; //screen coords
uint32 color; //diffuse color uint32 color; //diffuse color
@ -58,5 +62,6 @@ struct {
void redraw(); void redraw();
void update(); 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); lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7);
SafeRelease(lpdd); SafeRelease(lpdd);
if(bool(config::video.fullscreen) == true) { if(settings.fullscreen == true) {
lpdd7->SetCooperativeLevel(wMain.hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); lpdd7->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
lpdd7->SetDisplayMode(settings.resolution_width, settings.resolution_height, 16, settings.refresh_rate, 0); lpdd7->SetDisplayMode(settings.resolution_width, settings.resolution_height, 16, settings.refresh_rate, 0);
} else { } else {
lpdd7->SetCooperativeLevel(wMain.hwnd, DDSCL_NORMAL); lpdd7->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
} }
create_presentation(); create_presentation();
lpdd7->CreateClipper(0, &clipper, 0); lpdd7->CreateClipper(0, &clipper, 0);
clipper->SetHWnd(0, wMain.hwnd); clipper->SetHWnd(0, hwnd);
screen->SetClipper(clipper); screen->SetClipper(clipper);
create_render_target(); create_render_target();
@ -101,7 +101,7 @@ DDBLTFX fx;
backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
surface->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); screen->Flip(0, DDFLIP_WAIT);
backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); backbuffer->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
screen->Flip(0, DDFLIP_WAIT); screen->Flip(0, DDFLIP_WAIT);
@ -113,7 +113,7 @@ void VideoDD::create_presentation() {
memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
ddsd.dwSize = sizeof(DDSURFACEDESC2); ddsd.dwSize = sizeof(DDSURFACEDESC2);
if(bool(config::video.fullscreen) == true) { if(settings.fullscreen == true) {
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = (settings.triple_buffering == true) ? 2 : 1; ddsd.dwBackBufferCount = (settings.triple_buffering == true) ? 2 : 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
@ -149,14 +149,14 @@ RECT rd, rs;
snes->get_video_info(&vi); snes->get_video_info(&vi);
SetRect(&rs, 0, 0, vi.width, vi.height); 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); SetRect(&rd, settings.rx, settings.ry, settings.rx + settings.rw, settings.ry + settings.rh);
backbuffer->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); backbuffer->Blt(&rd, surface, &rs, DDBLT_WAIT, 0);
hr = screen->Flip(0, DDFLIP_WAIT); hr = screen->Flip(0, DDFLIP_WAIT);
} else { } else {
POINT p = { 0, 0 }; POINT p = { 0, 0 };
ClientToScreen(wMain.hwnd, &p); ClientToScreen(hwnd, &p);
GetClientRect(wMain.hwnd, &rd); GetClientRect(hwnd, &rd);
OffsetRect(&rd, p.x, p.y); OffsetRect(&rd, p.x, p.y);
hr = screen->Blt(&rd, surface, &rs, DDBLT_WAIT, 0); hr = screen->Blt(&rd, surface, &rs, DDBLT_WAIT, 0);
@ -184,7 +184,9 @@ void VideoDD::term() {
SafeRelease(lpdd); SafeRelease(lpdd);
} }
VideoDD::VideoDD() { VideoDD::VideoDD(HWND handle) {
hwnd = handle;
lpdd = 0; lpdd = 0;
lpdd7 = 0; lpdd7 = 0;
screen = 0; screen = 0;

View File

@ -2,6 +2,7 @@
class VideoDD : public Video { class VideoDD : public Video {
private: private:
HWND hwnd;
LPDIRECTDRAW lpdd; LPDIRECTDRAW lpdd;
LPDIRECTDRAW7 lpdd7; LPDIRECTDRAW7 lpdd7;
LPDIRECTDRAWSURFACE7 screen, backbuffer; LPDIRECTDRAWSURFACE7 screen, backbuffer;
@ -29,5 +30,5 @@ public:
void redraw(); void redraw();
void update(); 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->manual_render_size = strmatch(part[i++], "true");
v->render_width = strdec(part[i++]); v->render_width = strdec(part[i++]);
v->render_height = 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_width = strdec(part[i++]);
v->resolution_height = strdec(part[i++]); v->resolution_height = strdec(part[i++]);
v->refresh_rate = 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_width < 256)v->render_width = 256;
if(v->render_height < 224)v->render_height = 224; 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, "%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_width); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->render_height); 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_width); strcat(line, part); strcat(line, ";");
sprintf(part, "%d", v->resolution_height); 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, "%d", v->refresh_rate); strcat(line, part);
sprintf(part, "%s", v->triple_buffering ? "true" : "false"); strcat(line, part);
switch(profile) { switch(profile) {
case 0: config::video.profile_0.sset(strptr(line)); break; 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.triple_buffering = v->triple_buffering;
settings.hardware_filter = v->hardware_filter;
settings.enable_scanlines = v->enable_scanlines; 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_width = (v->resolution_width) ? v->resolution_width : screen_width();
settings.resolution_height = (v->resolution_height) ? v->resolution_height : screen_height(); settings.resolution_height = (v->resolution_height) ? v->resolution_height : screen_height();
settings.refresh_rate = v->refresh_rate; settings.refresh_rate = v->refresh_rate;

View File

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

View File

@ -55,7 +55,7 @@ uint8 r = 0x00;
r = r_mem->read(addr); r = r_mem->read(addr);
} break; } break;
case SPCRAM: case SPCRAM:
r = r_apu->spcram_read(addr & 0xffff); r = r_apu->spcram[addr & 0xffff];
break; break;
case VRAM: case VRAM:
r = r_ppu->vram_read(addr & 0xffff); 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); r_mem->cart_write_protect(true);
break; break;
case SPCRAM: case SPCRAM:
r_apu->spcram_write(addr & 0xffff, data); r_apu->spcram[addr & 0xffff] = data;
break; break;
case VRAM: case VRAM:
r_ppu->vram_write(addr & 0xffff, data); r_ppu->vram_write(addr & 0xffff, data);

View File

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

View File

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

View File

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

View File

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

View File

@ -85,7 +85,7 @@ int x = 15, y = 30;
GammaSlider.SetPos(int32(config::snes.gamma)); GammaSlider.SetPos(int32(config::snes.gamma));
y += 75; 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); GammaRamp.Check(config::snes.gamma_ramp);
y += 15; y += 15;
Sepia.Create(this, "visible", x, y, 475, 15, "Sepia"); 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.Create(this, "visible", x, y, 475, 15, "Grayscale");
Grayscale.Check(config::snes.grayscale); Grayscale.Check(config::snes.grayscale);
y += 15; 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); Invert.Check(config::snes.invert);
y += 20; y += 20;

View File

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

View File

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

View File

@ -31,13 +31,28 @@ long height;
init_settings(); init_settings();
init_debugger(); init_debugger();
if(strmatch(config::video.renderer.sget(), "dd")) { if(!stricmp(config::system.video.sget(), "dd")) {
uiVideo = new VideoDD(); uiVideo = new VideoDD(wMain.hwnd);
//} else if(!stricmp(config::system.video.sget(), "sdl")) {
// uiVideo = new VideoSDL((void*)wMain.hwnd);
} else { } 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(); uiVideo->init();
uiAudio->init(); uiAudio->init();
uiInput->init(); uiInput->init();
@ -56,6 +71,7 @@ void term_ui() {
uiVideo->term(); uiVideo->term();
uiAudio->term(); uiAudio->term();
uiInput->term(); uiInput->term();
SafeDelete(uiVideo); SafeDelete(uiVideo);
SafeDelete(uiAudio); SafeDelete(uiAudio);
SafeDelete(uiInput); SafeDelete(uiInput);

View File

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