Skip to content

Commit

Permalink
beta 10.2 (bsnes 114.3)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerKoun committed Feb 2, 2020
1 parent e39c597 commit 3a74cbe
Show file tree
Hide file tree
Showing 42 changed files with 590 additions and 330 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
# bsnes-hd *beta 10.1*
# bsnes-hd *beta 10.2*

- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas
- [GitHub project](https://github.com/DerKoun/bsnes-hd) for source code, issues, feature requests, ...
- [Reddit](https://www.reddit.com/r/emulation/search/?q=bsnes-hd&restrict_sr=1&sort=new) for announcements and discussions on *r/emulation*
- [Discord](https://discord.gg/7ahAzCV) if you prefer chatting (Thanks to everyone who set it up and keeps it running)
- [Forum](https://www.retrowide.com/forums) for widescreen discussions, both ROM-hacking and technical

1. [What is it?](#what-is-it)
2. [Help wanted](#help-wanted)
3. [Settings](#settings)
4. [Differences in setting/options from bsnes](#differences-in-settingoptions-from-bsnes)
5. [Widescreen technical](#widescreen-technical)


## What is it?

Expand Down Expand Up @@ -152,21 +160,24 @@ The amount of neighboring lines used to smooth color gradients that are applied

The amount of neighboring lines used to smooth Window effects, like iris transitions, shadows or spell effects. "*0*" disables smoothing and is the default. (*This feature is considered a preview, as the lines at the top and bottom of effects are currently not entirely HD and it still has noticeable issues. Please let me know about any games/scenes/effects that work noticeable badly or well*)

## Differences in setting/options from bsnes
## Differences in Setting/Options from bsnes

### Settings / Output / Show Overscan Area (Show Overscan)

In *bsnes* the overscan setting allows switching between cropping 8 and 0 lines form top and bottom, which are unused due to the way TVs in the time of the SNES worked. In *bsnes-hd* it switches between 12 and 8 lines, defaulting to 12 (*off*). This cuts of 4 lines on both sides that technically contain content, but should not cut important information as these lines are still in an area that wasn't safe to use (12 lines is 5%). The reason to do is that the resulting height of 216 is exactly a 5th of 1080, so you can integer scale to HD and 4K resolutions, e.g. *5x* at *16:9* is exactly *1080 HD* with every Mode 7 pixel rendered specifically.

## Widescreen technical
## Widescreen Technical

### Dimensions

The amount of pixel columns added to both sides for the various aspect ratios are: (4:3, 16), (16:10, 40), (16:9, 64), (2:1, 88), (21:9, 120). Those currently are for overscan *off* (see above) and don't change when you change that setting.
The amount of pixel columns added to both sides for the various aspect ratios are, depending on some settings:
- overscan *off*, aspect correction *off*: (4:3, 16), (16:10, 44), (16:9, 64), (2:1, 88), (21:9, 124).
- overscan *on*, aspect correction *off*: (4:3, 20), (16:10, 52), (16:9, 72), (2:1, 96), (21:9, 132).
- overscan *on*, aspect correction *on*: (4:3, 0), (16:10, 24), (16:9, 44), (2:1, 64), (21:9, 96).

### Maximum width for objects/sprites

The maximum width for widescreen areas that still can have places objects in them is *96* (exactly 2:1 AR with overscan *on*).
The maximum width for widescreen areas that still can have places objects in them is *96* (exactly 2:1 AR with overscan *on* and aspect correction *off* or 21:9 with overscan *on* and aspect correction *on*).

### Object/sprite wrap-around

Expand Down
4 changes: 2 additions & 2 deletions bsnes/emulator/emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ using namespace nall;

namespace Emulator {
static const string Name = "bsnes-hd beta";
static const string Version = "10.1";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
static const string Version = "10.2";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
static const string Author = "DerKoun(byuu)";
static const string License = "GPLv3";
static const string Website = "https://github.com/DerKoun/bsnes-hd";

//incremented only when serialization format changes
static const string SerializerVersion = "112";
static const string SerializerVersion = "114.2";

namespace Constants {
namespace Colorburst {
Expand Down
28 changes: 28 additions & 0 deletions bsnes/emulator/hdtoolkit.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace HdToolkit {
static constexpr auto determineWsExt(int ws, bool overscan, bool aspectCorrection) -> int {
if (ws < 200) {
return ws;
}
int w = ws / 100;
int h = ws % 100;
double val = overscan ? 224.0 : 216.0;
val *= w;
val /= h;
if (aspectCorrection) {
val *= 7;
val /= 8;
}
val -= 256;
val /= 2;
val /= 4;
if (overscan || aspectCorrection) {
val += 0.5;
}
ws = (int)val;
if (ws <= 0) {
return 0;
}
ws *= 4;
return ws;
}
}
14 changes: 10 additions & 4 deletions bsnes/gb/Core/apu.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,16 @@ static void tick_noise_envelope(GB_gameboy_t *gb)
void GB_apu_div_event(GB_gameboy_t *gb)
{
if (!gb->apu.global_enable) return;
if (gb->apu.skip_div_event) {
gb->apu.skip_div_event = false;
if (gb->apu.skip_div_event == GB_SKIP_DIV_EVENT_SKIP) {
gb->apu.skip_div_event = GB_SKIP_DIV_EVENT_SKIPPED;
return;
}
gb->apu.div_divider++;
if (gb->apu.skip_div_event == GB_SKIP_DIV_EVENT_SKIPPED) {
gb->apu.skip_div_event = GB_SKIP_DIV_EVENT_INACTIVE;
}
else {
gb->apu.div_divider++;
}

if ((gb->apu.div_divider & 1) == 0) {
for (unsigned i = GB_SQUARE_2 + 1; i--;) {
Expand Down Expand Up @@ -534,7 +539,8 @@ void GB_apu_init(GB_gameboy_t *gb)
/* APU glitch: When turning the APU on while DIV's bit 4 (or 5 in double speed mode) is on,
the first DIV/APU event is skipped. */
if (gb->div_counter & (gb->cgb_double_speed? 0x2000 : 0x1000)) {
gb->apu.skip_div_event = true;
gb->apu.skip_div_event = GB_SKIP_DIV_EVENT_SKIP;
gb->apu.div_divider = 1;
}
}

Expand Down
5 changes: 4 additions & 1 deletion bsnes/gb/Core/apu.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ typedef struct

} noise_channel;

bool skip_div_event;
#define GB_SKIP_DIV_EVENT_INACTIVE 0
#define GB_SKIP_DIV_EVENT_SKIPPED 1
#define GB_SKIP_DIV_EVENT_SKIP 2
uint8_t skip_div_event;
bool current_lfsr_sample;
} GB_apu_t;

Expand Down
2 changes: 1 addition & 1 deletion bsnes/gb/Core/debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const
GB_log(gb, "AF = $%04x (%c%c%c%c)\n", gb->registers[GB_REGISTER_AF], /* AF can't really be an address */
(gb->f & GB_CARRY_FLAG)? 'C' : '-',
(gb->f & GB_HALF_CARRY_FLAG)? 'H' : '-',
(gb->f & GB_SUBSTRACT_FLAG)? 'N' : '-',
(gb->f & GB_SUBTRACT_FLAG)? 'N' : '-',
(gb->f & GB_ZERO_FLAG)? 'Z' : '-');
GB_log(gb, "BC = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_BC], false));
GB_log(gb, "DE = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_DE], false));
Expand Down
26 changes: 20 additions & 6 deletions bsnes/gb/Core/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,17 @@ static void display_vblank(GB_gameboy_t *gb)
}
}
else {
uint32_t color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped && GB_is_cgb(gb) ?
gb->rgb_encode_callback(gb, 0, 0, 0) :
gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF);
uint32_t color = 0;
if (GB_is_cgb(gb)) {
color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped ?
gb->rgb_encode_callback(gb, 0, 0, 0) :
gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF);
}
else {
color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped ?
gb->background_palettes_rgb[3] :
gb->background_palettes_rgb[4];
}
for (unsigned i = 0; i < WIDTH * LINES; i++) {
gb ->screen[i] = color;
}
Expand Down Expand Up @@ -966,10 +974,16 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
GB_STAT_update(gb);

if (gb->frame_skip_state == GB_FRAMESKIP_LCD_TURNED_ON) {
if (!GB_is_sgb(gb) || gb->current_lcd_line < LINES) {
display_vblank(gb);
if (GB_is_cgb(gb)) {
GB_timing_sync(gb);
gb->frame_skip_state = GB_FRAMESKIP_FIRST_FRAME_SKIPPED;
}
else {
if (!GB_is_sgb(gb) || gb->current_lcd_line < LINES) {
display_vblank(gb);
}
gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED;
}
gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED;
}
else {
gb->frame_skip_state = GB_FRAMESKIP_SECOND_FRAME_RENDERED;
Expand Down
80 changes: 64 additions & 16 deletions bsnes/gb/Core/gb.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,21 +573,41 @@ void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback)
#endif
}

const GB_palette_t GB_PALETTE_GREY = {{{0x00, 0x00, 0x00}, {0x55, 0x55, 0x55}, {0xaa, 0xaa, 0xaa}, {0xff ,0xff, 0xff}, {0xff ,0xff, 0xff}}};
const GB_palette_t GB_PALETTE_DMG = {{{0x08, 0x18, 0x10}, {0x39, 0x61, 0x39}, {0x84, 0xa5, 0x63}, {0xc6, 0xde, 0x8c}, {0xd2 ,0xe6 ,0xa6}}};
const GB_palette_t GB_PALETTE_MGB = {{{0x07, 0x10, 0x0e}, {0x3a, 0x4c, 0x3a}, {0x81, 0x8d, 0x66}, {0xc2, 0xce, 0x93}, {0xcf, 0xda, 0xac}}};
const GB_palette_t GB_PALETTE_GBL = {{{0x0a, 0x1c, 0x15}, {0x35, 0x78, 0x62}, {0x56, 0xb4, 0x95}, {0x7f, 0xe2, 0xc3}, {0x91, 0xea, 0xd0}}};

void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
static void update_dmg_palette(GB_gameboy_t *gb)
{
if (!gb->rgb_encode_callback && !GB_is_cgb(gb)) {
const GB_palette_t *palette = gb->dmg_palette ?: &GB_PALETTE_GREY;
if (gb->rgb_encode_callback && !GB_is_cgb(gb)) {
gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] =
callback(gb, 0xFF, 0xFF, 0xFF);
gb->rgb_encode_callback(gb, palette->colors[3].r, palette->colors[3].g, palette->colors[3].b);
gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] =
callback(gb, 0xAA, 0xAA, 0xAA);
gb->rgb_encode_callback(gb, palette->colors[2].r, palette->colors[2].g, palette->colors[2].b);
gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] =
callback(gb, 0x55, 0x55, 0x55);
gb->rgb_encode_callback(gb, palette->colors[1].r, palette->colors[1].g, palette->colors[1].b);
gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] =
callback(gb, 0, 0, 0);
gb->rgb_encode_callback(gb, palette->colors[0].r, palette->colors[0].g, palette->colors[0].b);

// LCD off color
gb->background_palettes_rgb[4] =
gb->rgb_encode_callback(gb, palette->colors[4].r, palette->colors[4].g, palette->colors[4].b);
}
}

void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette)
{
gb->dmg_palette = palette;
update_dmg_palette(gb);
}

void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback)
{

gb->rgb_encode_callback = callback;
update_dmg_palette(gb);

for (unsigned i = 0; i < 32; i++) {
GB_palette_changed(gb, true, i * 2);
Expand Down Expand Up @@ -858,6 +878,36 @@ static void reset_ram(GB_gameboy_t *gb)
}
}

static void request_boot_rom(GB_gameboy_t *gb)
{
if (gb->boot_rom_load_callback) {
GB_boot_rom_t type = 0;
switch (gb->model) {
case GB_MODEL_DMG_B:
type = GB_BOOT_ROM_DMG;
break;
case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC:
case GB_MODEL_SGB_PAL_NO_SFC:
type = GB_BOOT_ROM_SGB;
break;
case GB_MODEL_SGB2:
case GB_MODEL_SGB2_NO_SFC:
type = GB_BOOT_ROM_SGB2;
break;
case GB_MODEL_CGB_C:
case GB_MODEL_CGB_E:
type = GB_BOOT_ROM_CGB;
break;
case GB_MODEL_AGB:
type = GB_BOOT_ROM_AGB;
break;
}
gb->boot_rom_load_callback(gb, type);
}
}

void GB_reset(GB_gameboy_t *gb)
{
uint32_t mbc_ram_size = gb->mbc_ram_size;
Expand All @@ -882,16 +932,7 @@ void GB_reset(GB_gameboy_t *gb)
gb->vram_size = 0x2000;
memset(gb->vram, 0, gb->vram_size);

if (gb->rgb_encode_callback) {
gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] =
gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF);
gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] =
gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA);
gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] =
gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55);
gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] =
gb->rgb_encode_callback(gb, 0, 0, 0);
}
update_dmg_palette(gb);
}
reset_ram(gb);

Expand Down Expand Up @@ -937,6 +978,7 @@ void GB_reset(GB_gameboy_t *gb)
}

gb->magic = state_magic();
request_boot_rom(gb);
}

void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model)
Expand Down Expand Up @@ -1082,3 +1124,9 @@ void GB_set_icd_vreset_callback(GB_gameboy_t *gb, GB_icd_vreset_callback_t callb
{
gb->icd_vreset_callback = callback;
}

void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t callback)
{
gb->boot_rom_load_callback = callback;
request_boot_rom(gb);
}
32 changes: 30 additions & 2 deletions bsnes/gb/Core/gb.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@
#error Unable to detect endianess
#endif

typedef struct {
struct {
uint8_t r,g,b;
} colors[5];
} GB_palette_t;

extern const GB_palette_t GB_PALETTE_GREY;
extern const GB_palette_t GB_PALETTE_DMG;
extern const GB_palette_t GB_PALETTE_MGB;
extern const GB_palette_t GB_PALETTE_GBL;

typedef union {
struct {
uint8_t seconds;
Expand All @@ -61,7 +72,6 @@ typedef union {
uint8_t data[5];
} GB_rtc_time_t;


typedef enum {
// GB_MODEL_DMG_0 = 0x000,
// GB_MODEL_DMG_A = 0x001,
Expand Down Expand Up @@ -98,7 +108,7 @@ enum {
enum {
GB_CARRY_FLAG = 16,
GB_HALF_CARRY_FLAG = 32,
GB_SUBSTRACT_FLAG = 64,
GB_SUBTRACT_FLAG = 64,
GB_ZERO_FLAG = 128,
};

Expand Down Expand Up @@ -219,6 +229,17 @@ typedef enum {
GB_LOG_UNDERLINE_MASK = GB_LOG_DASHED_UNDERLINE | GB_LOG_UNDERLINE
} GB_log_attributes;

typedef enum {
GB_BOOT_ROM_DMG0,
GB_BOOT_ROM_DMG,
GB_BOOT_ROM_MGB,
GB_BOOT_ROM_SGB,
GB_BOOT_ROM_SGB2,
GB_BOOT_ROM_CGB0,
GB_BOOT_ROM_CGB,
GB_BOOT_ROM_AGB,
} GB_boot_rom_t;

#ifdef GB_INTERNAL
#define LCDC_PERIOD 70224
#define CPU_FREQUENCY 0x400000
Expand Down Expand Up @@ -249,6 +270,7 @@ typedef void (*GB_joyp_write_callback_t)(GB_gameboy_t *gb, uint8_t value);
typedef void (*GB_icd_pixel_callback_t)(GB_gameboy_t *gb, uint8_t row);
typedef void (*GB_icd_hreset_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_icd_vreset_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_boot_rom_load_callback_t)(GB_gameboy_t *gb, GB_boot_rom_t type);

typedef struct {
bool state;
Expand Down Expand Up @@ -513,6 +535,7 @@ struct GB_gameboy_internal_s {
uint32_t *screen;
uint32_t background_palettes_rgb[0x20];
uint32_t sprite_palettes_rgb[0x20];
const GB_palette_t *dmg_palette;
GB_color_correction_mode_t color_correction_mode;
bool keys[4][GB_KEY_MAX];

Expand Down Expand Up @@ -542,6 +565,7 @@ struct GB_gameboy_internal_s {
GB_icd_vreset_callback_t icd_hreset_callback;
GB_icd_vreset_callback_t icd_vreset_callback;
GB_read_memory_callback_t read_memory_callback;
GB_boot_rom_load_callback_t boot_rom_load_callback;

/* IR */
long cycles_since_ir_change; // In 8MHz units
Expand Down Expand Up @@ -695,6 +719,10 @@ void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callb
void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback);
void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback);
void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_callback_t callback);
/* Called when a new boot ROM is needed. The callback should call GB_load_boot_rom or GB_load_boot_rom_from_buffer */
void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t callback);

void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette);

/* These APIs are used when using internal clock */
void GB_set_serial_transfer_bit_start_callback(GB_gameboy_t *gb, GB_serial_transfer_bit_start_callback_t callback);
Expand Down
Loading

0 comments on commit 3a74cbe

Please sign in to comment.