sms, basic gamegear support

This commit is contained in:
kub 2021-10-13 21:30:54 +02:00
parent 0df7401c02
commit 466fa07953
16 changed files with 451 additions and 214 deletions

View file

@ -58,9 +58,6 @@
.endif
orr r2, r2, r2, lsr #3
.if \sh == 1
str r2, [r0, #0x40*2*4]
.endif
str r2, [r0], #4
.endm
@ -101,10 +98,10 @@ bgr444_to_rgb32_sh:
subs r12, r12, #1
ldmia r1!, {r4-r7}
convRGB32_2 r4, 1
convRGB32_2 r5, 1
convRGB32_2 r6, 1
convRGB32_2 r7, 1
convRGB32_2 r4, 2
convRGB32_2 r5, 2
convRGB32_2 r6, 2
convRGB32_2 r7, 2
bgt .loopRGB32sh
mov r12, #0x40>>3 @ repeats
@ -112,10 +109,10 @@ bgr444_to_rgb32_sh:
.loopRGB32hi:
ldmia r1!, {r4-r7}
convRGB32_2 r4, 2
convRGB32_2 r5, 2
convRGB32_2 r6, 2
convRGB32_2 r7, 2
convRGB32_2 r4, 1
convRGB32_2 r5, 1
convRGB32_2 r6, 1
convRGB32_2 r7, 1
subs r12, r12, #1
bgt .loopRGB32hi

View file

@ -326,6 +326,8 @@ static void system_announce(void)
if (PicoIn.AHW & PAHW_SMS) {
sys_name = "Master System";
if (Pico.m.hardware & 0x1)
sys_name = "Game Gear";
#ifdef NO_SMS
extra = " [no support]";
#endif
@ -587,7 +589,7 @@ void emu_prep_defconfig(void)
memset(&defaultConfig, 0, sizeof(defaultConfig));
defaultConfig.EmuOpt = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP |
EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/;
defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|
defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|POPT_EN_GG_LCD |
POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 |
POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX |
POPT_EN_DRC|POPT_ACC_SPRITES |

View file

@ -42,7 +42,7 @@ static const char *rom_exts[] = {
"bin", "smd", "gen", "md",
"iso", "cso", "cue", "chd",
"32x",
"sms",
"sms", "gg",
NULL
};
@ -536,6 +536,7 @@ static menu_entry e_menu_adv_options[] =
mee_onoff ("Disable YM2612 SSG-EG", MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG),
mee_onoff ("Emulate SN76496 (PSG)", MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG),
mee_onoff ("Emulate YM2413 (FM)", MA_OPT2_ENABLE_YM2413 ,PicoIn.opt, POPT_EN_YM2413),
mee_onoff ("Emulate Game Gear LCD", MA_OPT2_ENABLE_GGLCD ,PicoIn.opt, POPT_EN_GG_LCD),
mee_onoff ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoIn.opt, POPT_DIS_IDLE_DET),
mee_onoff ("Disable frame limiter", MA_OPT2_NO_FRAME_LIMIT,currentConfig.EmuOpt, EOPT_NO_FRMLIMIT),
mee_onoff ("Enable dynarecs", MA_OPT2_DYNARECS, PicoIn.opt, POPT_EN_DRC),

View file

@ -52,6 +52,7 @@ typedef enum
MA_OPT2_DISABLE_YM_SSG,
MA_OPT2_ENABLE_SN76496,
MA_OPT2_ENABLE_YM2413,
MA_OPT2_ENABLE_GGLCD,
MA_OPT2_NO_LAST_ROM,
MA_OPT2_RAMTIMINGS, /* gp2x */
MA_OPT2_NO_FRAME_LIMIT, /* psp */

View file

@ -35,12 +35,20 @@
*/
#include <pico/pico_types.h>
/* LSB of all colors in a pixel */
#if defined(USE_BGR555)
#define PXLSB 0x0421
#else
#define PXLSB 0x0821
#endif
/* RGB565 pixel mixing, see https://www.compuphase.com/graphic/scale3.htm and
http://blargg.8bitalley.com/info/rgb_mixing.html */
/* 2-level mixing */
//#define p_05(d,p1,p2) d=(((p1)+(p2) + ( ((p1)^(p2))&0x0821))>>1) // round up
//#define p_05(d,p1,p2) d=(((p1)+(p2) - ( ((p1)^(p2))&0x0821))>>1) // round down
#define p_05(d,p1,p2) d=(((p1)&(p2)) + ((((p1)^(p2))&~0x0821)>>1))
//#define p_05(d,p1,p2) d=(((p1)+(p2) + ( ((p1)^(p2))&PXLSB))>>1) // round up
//#define p_05(d,p1,p2) d=(((p1)+(p2) - ( ((p1)^(p2))&PXLSB))>>1) // round down
#define p_05(d,p1,p2) d=(((p1)&(p2)) + ((((p1)^(p2))&~PXLSB)>>1))
/* 4-level mixing, 2 times slower */
// 1/4*p1 + 3/4*p2 = 1/2*(1/2*(p1+p2) + p2)
#define p_025(d,p1,p2) p_05(t, p1, p2); p_05( d, t, p2)
@ -322,6 +330,21 @@ scalers h:
si += ss - w; \
} while (0)
// reverse version for overlapping buffers
#define rh_upscale_nn_1_2(di,ds,si,ss,w,f) do { \
int i; \
di += w*2; \
si += w; \
for (i = w/2; i > 0; i--, si -= 2, di -= 4) { \
di[-1] = f(si[-1]); \
di[-2] = f(si[-1]); \
di[-3] = f(si[-2]); \
di[-4] = f(si[-2]); \
} \
di += ds; \
si += ss; \
} while (0)
#define h_upscale_bl2_1_2(di,ds,si,ss,w,f) do { \
int i; uint p = f(si[0]); \
for (i = w/2; i > 0; i--, si += 2, di += 4) { \
@ -514,11 +537,12 @@ scalers v:
} else { \
int j; \
l = 0; \
di -= 4*ds; \
di -= 3*ds; \
for (j = 0; j < 2; j++) { \
v_copy(&di[0], &di[-ds], w, f_nop); \
di += 2*ds; \
} \
di -= ds; \
} \
} while (0)
@ -528,11 +552,12 @@ scalers v:
} else { \
int j; \
l = 0; \
di -= 4*ds; \
di -= 3*ds; \
for (j = 0; j < 2; j++) { \
v_mix(&di[0], &di[-ds], &di[ds], w, p_05, f_nop); \
di += 2*ds; \
} \
di -= ds; \
} \
} while (0)

View file

@ -105,7 +105,7 @@ static void change_renderer(int diff)
}
#define is_16bit_mode() \
(currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X))
(currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X) || doing_bg_frame)
static void (*osd_text)(int x, int y, const char *text);
@ -248,7 +248,7 @@ static int EmuScanEnd8_rot(unsigned int num)
/* line doublers */
static unsigned int ld_counter;
static int ld_left, ld_lines;
static int ld_left, ld_lines; // numbers in Q1 format
static int EmuScanBegin16_ld(unsigned int num)
{
@ -271,9 +271,9 @@ static int EmuScanEnd16_ld(unsigned int num)
emu_scan_end(ld_counter);
ld_counter++;
ld_left--;
ld_left -= 2;
if (ld_left <= 0) {
ld_left = ld_lines;
ld_left += ld_lines;
EmuScanBegin16_ld(num);
memcpy(Pico.est.DrawLineDest, oldline, 320 * gp2x_current_bpp / 8);
@ -313,6 +313,7 @@ static int make_local_pal_md(int fast_mode)
else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode
bgr444_to_rgb32(localPal, Pico.est.SonicPal);
bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);
memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess
}
else {
bgr444_to_rgb32(localPal, Pico.est.SonicPal);
@ -331,18 +332,7 @@ static int make_local_pal_md(int fast_mode)
static int make_local_pal_sms(int fast_mode)
{
unsigned short *spal = PicoMem.cram;
unsigned int *dpal = (void *)localPal;
unsigned int i, t;
for (i = 0x40; i > 0; i--) {
t = *spal++;
t = ((t & 0x0003) << 22) | ((t & 0x000c) << 12) | ((t & 0x0030) << 2);
t |= t >> 2;
t |= t >> 4;
*dpal++ = t;
}
bgr444_to_rgb32(localPal, PicoMem.cram);
Pico.m.dirtyPal = 0;
return 0x40;
}
@ -486,6 +476,9 @@ static void vid_reset_mode(void)
int gp2x_mode = 16;
int renderer = get_renderer();
if (doing_bg_frame)
renderer = RT_16BIT;
PicoIn.opt &= ~POPT_ALT_RENDERER;
emu_scan_begin = NULL;
emu_scan_end = NULL;
@ -557,11 +550,13 @@ static void vid_reset_mode(void)
Pico.m.dirtyPal = 1;
PicoIn.opt &= ~POPT_EN_SOFTSCALE;
PicoIn.opt &= ~(POPT_DIS_32C_BORDER|POPT_EN_SOFTSCALE);
if (currentConfig.scaling == EOPT_SCALE_SW) {
PicoIn.opt |= POPT_EN_SOFTSCALE;
PicoIn.filter = EOPT_FILTER_BILINEAR2;
}
} else if (currentConfig.scaling == EOPT_SCALE_HW && is_16bit_mode())
// hw scaling, render without any padding
PicoIn.opt |= POPT_DIS_32C_BORDER;
// palette converters for 8bit modes
make_local_pal = (PicoIn.AHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;
@ -572,6 +567,12 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
int scalex = 320, scaley = 240;
int ln_offs = 0;
/* line doubling for swscaling, also needed for bg frames */
if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {
ld_lines = ld_left = 2*line_count / (240 - line_count);
PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);
}
if (doing_bg_frame)
return;
@ -579,10 +580,8 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
osd_y = 232;
/* set up hwscaling here */
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
if (col_count < 320 && currentConfig.scaling == EOPT_SCALE_HW) {
scalex = col_count;
PicoIn.opt |= POPT_DIS_32C_BORDER;
osd_fps_x = col_count - (320-OSD_FPS_X);
}
@ -594,11 +593,6 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
gp2x_video_RGB_setscaling(ln_offs, scalex, scaley);
/* line doubling */
if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {
ld_lines = ld_left = line_count / (240 - line_count);
PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);
}
// clear whole screen in all buffers
if (!is_16bit_mode())
@ -731,6 +725,8 @@ void pemu_forced_frame(int no_scale, int do_emu)
doing_bg_frame = 1;
PicoDrawSetCallbacks(NULL, NULL);
Pico.m.dirtyPal = 1;
PicoIn.opt &= ~POPT_DIS_32C_BORDER;
gp2x_current_bpp = 16;
if (!no_scale)
no_scale = currentConfig.scaling == EOPT_SCALE_NONE;
@ -749,6 +745,7 @@ void plat_video_loop_prepare(void)
// make sure we are in correct mode
change_renderer(0);
vid_reset_mode();
rendstatus_old = -1;
}
void pemu_loop_prep(void)

View file

@ -89,8 +89,8 @@ static retro_audio_sample_batch_t audio_batch_cb;
#define INITIAL_SND_RATE 44100
static const float VOUT_PAR = 0.0;
static const float VOUT_4_3 = (224.0f * (4.0f / 3.0f));
static const float VOUT_CRT = (224.0f * 1.29911f);
static const float VOUT_4_3 = (4.0f / 3.0f);
static const float VOUT_CRT = (1.29911f);
static bool show_overscan = false;
static bool old_show_overscan = false;
@ -746,7 +746,7 @@ void retro_get_system_info(struct retro_system_info *info)
#define _GIT_VERSION "-" GIT_VERSION
#endif
info->library_version = VERSION _GIT_VERSION;
info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|chd|sms";
info->valid_extensions = "bin|gen|smd|md|32x|cue|iso|chd|sms|gg";
info->need_fullpath = true;
}
@ -899,7 +899,7 @@ typedef struct patch
} patch;
extern void decode(char *buff, patch *dest);
extern uint16_t m68k_read16(uint32_t a);
extern uint32_t m68k_read16(uint32_t a);
extern void m68k_write16(uint32_t a, uint16_t d);
void retro_cheat_reset(void)
@ -1494,12 +1494,13 @@ static void update_variables(bool first_run)
var.value = NULL;
var.key = "picodrive_aspect";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
int height = vout_height >= 192 && vout_height <= 224 ? 224 : vout_height;
if (strcmp(var.value, "4/3") == 0)
user_vout_width = VOUT_4_3;
user_vout_width = VOUT_4_3 * height;
else if (strcmp(var.value, "CRT") == 0)
user_vout_width = VOUT_CRT;
user_vout_width = VOUT_CRT * height;
else
user_vout_width = VOUT_PAR;
user_vout_width = VOUT_PAR * height;
}
if (user_vout_width != old_user_vout_width)
@ -1801,7 +1802,8 @@ void retro_init(void)
sceBlock = getVMBlock();
#endif
PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80|POPT_EN_YM2413
PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM
| POPT_EN_PSG|POPT_EN_Z80|POPT_EN_YM2413|POPT_EN_GG_LCD
| POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX
| POPT_EN_32X|POPT_EN_PWM
| POPT_ACC_SPRITES|POPT_DIS_32C_BORDER;

View file

@ -95,7 +95,7 @@ static void draw_cd_leds(void)
* for display isn't always possible.
*/
static u16 *screen_buffer(u16 *buf)
static inline u16 *screen_buffer(u16 *buf)
{
return buf + screen_y * g_screen_ppitch + screen_x -
(out_y * g_screen_ppitch + out_x);
@ -105,34 +105,46 @@ void screen_blit(u16 *pd, int pp, u8* ps, int ss, u16 *pal)
{
typedef void (*upscale_t)
(u16 *di,int ds, u8 *si,int ss, int w,int h, u16 *pal);
upscale_t upscale_hv[] = {
static const upscale_t upscale_256_224_hv[] = {
upscale_rgb_nn_x_4_5_y_16_17, upscale_rgb_snn_x_4_5_y_16_17,
upscale_rgb_bl2_x_4_5_y_16_17, upscale_rgb_bl4_x_4_5_y_16_17,
};
upscale_t upscale_h[] = {
static const upscale_t upscale_256_224_h[] = {
upscale_rgb_nn_x_4_5, upscale_rgb_snn_x_4_5,
upscale_rgb_bl2_x_4_5, upscale_rgb_bl4_x_4_5,
};
upscale_t upscale_v[] = {
static const upscale_t upscale_256_224_v[] = {
upscale_rgb_nn_y_16_17, upscale_rgb_snn_y_16_17,
upscale_rgb_bl2_y_16_17, upscale_rgb_bl4_y_16_17,
};
upscale_t *upscale;
static const upscale_t upscale_160_144_hv[] = {
upscale_rgb_nn_x_1_2_y_3_5, upscale_rgb_nn_x_1_2_y_3_5,
upscale_rgb_bl2_x_1_2_y_3_5, upscale_rgb_bl4_x_1_2_y_3_5,
};
static const upscale_t upscale_160_144_h[] = {
upscale_rgb_nn_x_1_2, upscale_rgb_nn_x_1_2,
upscale_rgb_bl2_x_1_2, upscale_rgb_bl2_x_1_2,
};
static const upscale_t upscale_160_144_v[] = {
upscale_rgb_nn_y_3_5, upscale_rgb_nn_y_3_5,
upscale_rgb_bl2_y_3_5, upscale_rgb_bl4_y_3_5,
};
const upscale_t *upscale;
int y;
// handle software upscaling
upscale = NULL;
if (currentConfig.scaling == EOPT_SCALE_SW && out_w == 256) {
if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)
// h+v scaling
upscale = upscale_hv;
else
// h scaling
upscale = upscale_h;
} else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224) {
// v scaling
upscale = upscale_v;
} else {
if (currentConfig.scaling == EOPT_SCALE_SW) {
if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)
// h+v scaling
upscale = out_w == 256 ? upscale_256_224_hv: upscale_160_144_hv;
else
// h scaling
upscale = out_w == 256 ? upscale_256_224_h : upscale_160_144_h;
} else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)
// v scaling
upscale = out_w == 256 ? upscale_256_224_v : upscale_160_144_v;
if (!upscale) {
// no scaling
for (y = 0; y < out_h; y++)
h_copy(pd, pp, ps, 328, out_w, f_pal);
@ -280,16 +292,16 @@ static int vscale_state;
static int cb_vscaling_begin(unsigned int line)
{
static int prevline = 999;
// at start of new frame?
if (line < prevline) {
// set y frame offset (see emu_change_video_mode)
if (line <= out_y) {
// set y frame offset (see emu_video_mode_change)
Pico.est.DrawLineDest = screen_buffer(g_screen_ptr) +
(out_y * g_screen_ppitch + out_x);
(out_y * g_screen_ppitch /*+ out_x*/);
vscale_state = 0;
}
prevline = line;
return out_y - line;
} else if (line > out_y + out_h)
return 1;
return 0;
}
@ -301,16 +313,25 @@ static int cb_vscaling_nop(unsigned int line)
static int cb_vscaling_end(unsigned int line)
{
u16 *dest = Pico.est.DrawLineDest;
switch (currentConfig.filter) {
case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
}
if (out_h == 144)
switch (currentConfig.filter) {
case 0: v_upscale_nn_3_5(dest, g_screen_ppitch, 320, vscale_state);
break;
default: v_upscale_snn_3_5(dest, g_screen_ppitch, 320, vscale_state);
break;
}
else
switch (currentConfig.filter) {
case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);
break;
}
Pico.est.DrawLineDest = dest;
return 0;
}
@ -337,10 +358,10 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
}
switch (currentConfig.vscaling) {
case EOPT_SCALE_HW:
screen_h = (out_h < 224 ? 224 : out_h);
screen_h = (out_h < 224 && out_h > 144 ? 224 : out_h);
screen_y = 0;
// NTSC always has 224 visible lines, anything smaller has bars
if (out_h < 224)
if (out_h < 224 && out_h > 144)
screen_y += (224 - out_h)/2;
// handle vertical centering for 16 bit mode
if (is_16bit_mode())
@ -349,7 +370,7 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
case EOPT_SCALE_SW:
screen_y = (screen_h - 240)/2;
// NTSC always has 224 visible lines, anything smaller has bars
if (out_h < 224)
if (out_h < 224 && out_h > 144)
screen_y += (224 - out_h)/2;
// in 16 bit mode sw scaling is divided between core and platform
if (is_16bit_mode() && out_h < 240)