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

@ -135,7 +135,7 @@ void blockcpy_or(void *dst, void *src, size_t n, int pat)
for (; n; n--)
*pd++ = (unsigned char) (*ps++ | pat);
}
#define blockcpy memcpy
#define blockcpy memmove
#endif
#define TileNormMaker_(pix_func,ret) \
@ -1642,21 +1642,28 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
PicoDrawUpdateHighPal();
if (Pico.video.reg[12]&1) {
len = 320;
} else {
len = 256;
}
if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)
len = 160;
else if (Pico.video.reg[12]&1) len = 320;
else len = 256;
if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len == 256) {
switch (PicoIn.filter) {
case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, 256, f_pal); break;
case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, 256, f_pal); break;
case 1: h_upscale_snn_4_5(pd, 320, ps, 256, 256, f_pal); break;
default: h_upscale_nn_4_5(pd, 320, ps, 256, 256, f_pal); break;
}
if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len < 320) {
if (len == 256)
switch (PicoIn.filter) {
case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, len, f_pal); break;
case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, len, f_pal); break;
case 1: h_upscale_snn_4_5(pd, 320, ps, 256, len, f_pal); break;
default: h_upscale_nn_4_5(pd, 320, ps, 256, len, f_pal); break;
}
else if (len == 160)
switch (PicoIn.filter) {
case 3:
case 2: h_upscale_bl2_1_2(pd, 320, ps, 160, len, f_pal); break;
default: h_upscale_nn_1_2(pd, 320, ps, 160, len, f_pal); break;
}
} else {
if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len == 256) pd += 32;
if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)
pd += (320-len) / 2;
#if 1
h_copy(pd, 320, ps, 320, len, f_pal);
#else
@ -1670,9 +1677,10 @@ void FinalizeLine555(int sh, int line, struct PicoEState *est)
}
#endif
static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
{
unsigned char *pd = est->DrawLineDest;
unsigned char *ps = est->HighCol+8;
int len;
static int dirty_line;
@ -1680,8 +1688,8 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
{
// a hack for mid-frame palette changes
if (!(est->rendstatus & PDRAW_SONIC_MODE) | (line - dirty_line > 4)) {
// store a maximum of 2 additional palettes in SonicPal
if (est->SonicPalCount < 2)
// store a maximum of 3 additional palettes in SonicPal
if (est->SonicPalCount < 3)
est->SonicPalCount ++;
dirty_line = line;
est->rendstatus |= PDRAW_SONIC_MODE;
@ -1690,35 +1698,33 @@ static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)
Pico.m.dirtyPal = 2;
}
if (Pico.video.reg[12]&1) {
len = 320;
} else {
len = 256;
}
if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)
len = 160;
else if (Pico.video.reg[12]&1) len = 320;
else len = 256;
if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len == 256) {
unsigned char *ps = est->HighCol+8;
if (DrawLineDestIncrement == 0)
pd = est->HighCol+8;
if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len < 320) {
unsigned char pal = 0;
if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))
pal = est->SonicPalCount*0x40;
if (DrawLineDestIncrement == 0)
pd = est->HighCol+8;
// Smoothing can't be used with CLUT, hence it's always Nearest Neighbour.
// use reverse version since src and dest ptr may be the same.
rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);
} else if (DrawLineDestIncrement == 0) {
if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))
blockcpy_or(est->HighCol+8, est->HighCol+8, len, est->SonicPalCount*0x40);
if (len == 256)
// use reverse version since src and dest ptr may be the same.
rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);
else
rh_upscale_nn_1_2(pd, 320, ps, 256, len, f_or);
} else {
if (!(PicoIn.opt & POPT_DIS_32C_BORDER))
pd += 32;
if (!sh && (est->rendstatus & PDRAW_SONIC_MODE)) {
if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)
pd += (320-len) / 2;
if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))
// select active backup palette
blockcpy_or(pd, est->HighCol+8, len, est->SonicPalCount*0x40);
} else {
blockcpy(pd, est->HighCol+8, len);
}
blockcpy_or(pd, ps, len, est->SonicPalCount*0x40);
else if (pd != ps)
blockcpy(pd, ps, len);
}
}
@ -1893,8 +1899,15 @@ PICO_INTERNAL void PicoFrameStart(void)
static void DrawBlankedLine(int line, int offs, int sh, int bgc)
{
if (PicoScanBegin != NULL)
PicoScanBegin(line + offs);
int skip = skip_next_line;
if (PicoScanBegin != NULL && skip == 0)
skip = PicoScanBegin(line + offs);
if (skip) {
skip_next_line = skip - 1;
return;
}
BackFill(bgc, sh, &Pico.est);
@ -1902,7 +1915,7 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
FinalizeLine(sh, line, &Pico.est);
if (PicoScanEnd != NULL)
PicoScanEnd(line + offs);
skip_next_line = PicoScanEnd(line + offs);
Pico.est.HighCol += HighColIncrement;
Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement;
@ -1910,15 +1923,10 @@ static void DrawBlankedLine(int line, int offs, int sh, int bgc)
static void PicoLine(int line, int offs, int sh, int bgc)
{
int skip = 0;
if (skip_next_line > 0) {
skip_next_line--;
return;
}
int skip = skip_next_line;
Pico.est.DrawScanline = line;
if (PicoScanBegin != NULL)
if (PicoScanBegin != NULL && skip == 0)
skip = PicoScanBegin(line + offs);
if (skip) {

View file

@ -1642,27 +1642,42 @@ FinalizeLine555:
add r3, r10, #OFS_EST_HighPal
mov lr, #0xff
ldr r1, [r10, #OFS_EST_HighCol]
ldr r0, [r10, #OFS_EST_DrawLineDest]
add r1, r1, #8
ldrb r12, [r8, #OFS_Pico_video_reg+12]
mov lr, lr, lsl #1
tst r12, #1
movne r2, #320/8 @ len
bne .fl_no32colRGB555
ldr r5, [r10, #OFS_EST_PicoOpt]
mov r2, #256/8
ldr r1, [r10, #OFS_EST_HighCol]
ldr r0, [r10, #OFS_EST_DrawLineDest]
ldr r4, [r5]
tst r4, #0x4000
bne .fl_32scale_RGB555
tst r4, #0x0100
addeq r0, r0, #32*2
ldr r7, [r5, #OFS_PicoIn_AHW-OFS_PicoIn_opt]
ldrb r12,[r8, #OFS_Pico_video_reg+12]
ldr r2, [r8, #OFS_Pico_m_hardware]
add r1, r1, #8
tst r7, #0x10
beq .fl_no20colRGB555
and r7, r2, #0x3
cmp r7, #0x3 @ Game Gear, LCD?
bne .fl_no20colRGB555
mov r2, #160/8 @ len = 160
tst r4, #0x4000 @ EN_SOFTSCALE?
bne .fl_20scale_RGB555 @ scale 160->320
beq .fl_checkborder
.fl_no20colRGB555:
tst r12, #1 @ h32?
movne r2, #320/8 @ len = 320
bne .fl_no32colRGB555
moveq r2, #256/8 @ len = 256
tst r4, #0x4000 @ EN_SOFTSCALE?
bne .fl_32scale_RGB555 @ scale 256->320
.fl_checkborder:
tst r4, #0x0100 @ DIS_32C_BORDER?
rsbeq r4, r2, #320/8 @ pd += (320-len)/2
addeq r0, r0, r4, lsl #3
.fl_no32colRGB555:
#ifdef UNALIGNED_DRAWLINEDEST
@ this is basically for Gizmondo, which has unaligned odd lines in the framebuffer
tst r0, #2
@ -1715,9 +1730,9 @@ FinalizeLine555:
bne .fl_32scale_RGB555u
#endif
ands r5, r5, #0x3
addne pc, pc, r5, lsl #2
b .fl_32scale_nn
and r5, r5, #0x3
add pc, pc, r5, lsl #2
nop
b .fl_32scale_nn
b .fl_32scale_snn
b .fl_32scale_bl2
@ -1866,6 +1881,9 @@ FinalizeLine555:
ldmfd sp!, {r4-r10,pc}
.fl_32scale_bl4:
// TODO this should reflect the bl4 C algorithm, but it doesn't, it's bln.
and r9, r9, r9, lsl #1 @ nuke 2 LSBs to avoid spilling for n/4
.fl_32loop_bl4:
ldr r12, [r1], #4
ldr r7, [r1], #4
@ -1926,10 +1944,147 @@ FinalizeLine555:
subs r2, r2, #1
stmia r0!, {r4,r5,r6,r8,r10}
bne .fl_32scale_bl4
bne .fl_32loop_bl4
ldmfd sp!, {r4-r10,pc}
.fl_20scale_RGB555:
ldr r5, [r5, #OFS_PicoIn_filter-OFS_PicoIn_opt]
mov r9, #0xf700 @ f800 07e0 001f | e000 0780 001c | 3800 01e0 0007
orr r9, r9, #0x00de
#ifdef UNALIGNED_DRAWLINEDEST
tst r0, #2
bne .fl_20scale_RGB555u
#endif
and r5, r5, #0x2
add pc, pc, r5, lsl #1
nop
b .fl_20scale_nn
b .fl_20scale_bl2
.fl_20scale_nn:
ldr r12, [r1], #4
ldr r7, [r1], #4
and r4, lr, r12, lsl #1
ldrh r4, [r3, r4]
and r5, lr, r12, lsr #7
ldrh r5, [r3, r5]
and r6, lr, r12, lsr #15
ldrh r6, [r3, r6]
and r8 ,lr, r12, lsr #23
ldrh r8 ,[r3, r8 ]
orr r4, r4, r4, lsl #16
orr r5, r5, r5, lsl #16
orr r6, r6, r6, lsl #16
orr r8, r8, r8, lsl #16
stmia r0!, {r4,r5,r6,r8}
and r4, lr, r7, lsl #1
ldrh r4, [r3, r4]
and r5, lr, r7, lsr #7
ldrh r5, [r3, r5]
and r6 ,lr, r7, lsr #15
ldrh r6 ,[r3, r6]
and r8, lr, r7, lsr #23
ldrh r8, [r3, r8]
orr r4, r4, r4, lsl #16
orr r5, r5, r5, lsl #16
orr r6, r6, r6, lsl #16
orr r8, r8, r8, lsl #16
stmia r0!, {r4,r5,r6,r8}
subs r2, r2, #1
bne .fl_20scale_nn
ldmfd sp!, {r4-r10,pc}
.fl_20scale_bl2:
ldr r8, [r1]
and r8, lr, r8, lsl #1
ldrh r8, [r3, r8]
and r8, r8, r9
lsl r8, r8, #16
.fl_20loop_bl2:
ldr r12, [r1], #4
ldr r7, [r1], #4
and r4, lr, r12, lsl #1
ldrh r4, [r3, r4]
and r5, lr, r12, lsr #7
ldrh r5, [r3, r5]
and r6, lr, r12, lsr #15
ldrh r6, [r3, r6]
and r4, r4, r9
add r10,r4, r8, lsr #16
mov r10,r10,lsr #1
orr r4, r10,r4, lsl #16 @ (px-1+px0)/2 | px0
and r8 ,lr, r12, lsr #23
ldrh r8 ,[r3, r8]
and r5, r5, r9
add r10,r5, r4, lsr #16
mov r10,r10,lsr #1
orr r5, r10,r5, lsl #16 @ (px0 +px1)/2 | px1
and r6, r6, r9
add r10,r6, r5, lsr #16
mov r10,r10,lsr #1
orr r6, r10,r6, lsl #16 @ (px1 +px2)/2 | px2
and r8, r8, r9
add r10,r8, r6, lsr #16
mov r10,r10,lsr #1
orr r8, r10,r8, lsl #16 @ (px2 +px3)/2 | px3
stmia r0!, {r4,r5,r6,r8}
and r4, lr, r7, lsl #1
ldrh r4, [r3, r4]
and r5, lr, r7, lsr #7
ldrh r5, [r3, r5]
and r6, lr, r7, lsr #15
ldrh r6, [r3, r6]
and r4, r4, r9
add r10,r4, r8, lsr #16
mov r10,r10,lsr #1
orr r4, r10,r4, lsl #16 @ (px-1+px0)/2 | px0
and r8 ,lr, r7, lsr #23
ldrh r8 ,[r3, r8]
and r5, r5, r9
add r10,r5, r4, lsr #16
mov r10,r10,lsr #1
orr r5, r10,r5, lsl #16 @ (px0 +px1)/2 | px1
and r6, r6, r9
add r10,r6, r5, lsr #16
mov r10,r10,lsr #1
orr r6, r10,r6, lsl #16 @ (px1 +px2)/2 | px2
and r8, r8, r9
add r10,r8, r6, lsr #16
mov r10,r10,lsr #1
orr r8, r10,r8, lsl #16 @ (px2 +px3)/2 | px3
subs r2, r2, #1
stmia r0!, {r4,r5,r6,r8}
bne .fl_20loop_bl2
ldmfd sp!, {r4-r10,pc}
#ifdef UNALIGNED_DRAWLINEDEST
@ unaligned versions of loops
@ warning: starts drawing 2bytes before dst

View file

@ -248,7 +248,6 @@ enum media_type_e PicoLoadMedia(const char *filename,
}
}
else if (media_type == PM_MARK3) {
lprintf("detected SMS ROM\n");
PicoIn.AHW = PAHW_SMS;
}
@ -297,9 +296,18 @@ enum media_type_e PicoLoadMedia(const char *filename,
goto out;
}
rom_data = NULL; // now belongs to PicoCart
Pico.m.ncart_in = 0;
// simple test for GG. Do this here since m.hardware is nulled in Insert
if (PicoIn.AHW & PAHW_SMS) {
if (strstr(filename,".gg")) {
Pico.m.hardware |= 0x1;
lprintf("detected GG ROM\n");
} else
lprintf("detected SMS ROM\n");
}
// insert CD if it was detected
Pico.m.ncart_in = 0;
if (cd_img_type != CT_UNKNOWN) {
ret = cdd_load(filename, cd_img_type);
if (ret != 0) {

View file

@ -141,6 +141,8 @@ static void DrawSpritesM4(int scanline)
if (pv->reg[0] & 8)
xoff = 0;
xoff += line_offset;
if ((Pico.m.hardware & 0x3) == 0x3)
xoff -= 48; // GG LCD, adjust to center 160 px
sat = (u8 *)PicoMem.vram + ((pv->reg[5] & 0x7e) << 7);
if (pv->reg[1] & 2) {
@ -164,10 +166,12 @@ static void DrawSpritesM4(int scanline)
break;
}
sprites_x[s] = xoff + sat[MEM_LE2(0x80 + i*2)];
sprites_addr[s] = sprite_base + ((sat[MEM_LE2(0x80 + i*2 + 1)] & addr_mask) << (5-1)) +
((scanline - y) >> zoomed << (2-1));
s++;
if (xoff + sat[MEM_LE2(0x80 + i*2)] >= 0) {
sprites_x[s] = xoff + sat[MEM_LE2(0x80 + i*2)];
sprites_addr[s] = sprite_base + ((sat[MEM_LE2(0x80 + i*2 + 1)] & addr_mask) << (5-1)) +
((scanline - y) >> zoomed << (2-1));
s++;
}
}
// really half-assed but better than nothing
@ -296,9 +300,12 @@ static void DrawDisplayM4(int scanline)
// low priority tiles
if (!(pv->debug_p & PVD_KILL_B)) {
if (pv->reg[0] & 0x80) {
if ((Pico.m.hardware & 0x3) == 0x3) {
// on GG render only the center 160 px
DrawStripLowM4(nametab , dx | ((cells-12)<< 16),(tilex+6) | (ty << 16));
} else if (pv->reg[0] & 0x80) {
// vscroll disabled for rightmost 8 columns (e.g. Gauntlet)
int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline & 7;
int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline&7;
DrawStripLowM4(nametab, dx | ((cells-8) << 16), tilex | (ty << 16));
DrawStripLowM4(nametab2, dx2 | (8 << 16), tilex2 | (ty2 << 17));
} else
@ -311,8 +318,10 @@ static void DrawDisplayM4(int scanline)
// high priority tiles (use virtual layer switch just for fun)
if (!(pv->debug_p & PVD_KILL_A)) {
if (pv->reg[0] & 0x80) {
int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline & 7;
if ((Pico.m.hardware & 0x3) == 0x3) {
DrawStripHighM4(nametab , dx | ((cells-12)<< 16),(tilex+6) | (ty << 16));
} else if (pv->reg[0] & 0x80) {
int dx2 = dx + (cells-8)*8, tilex2 = tilex + (cells-8), ty2 = scanline&7;
DrawStripHighM4(nametab, dx | ((cells-8) << 16), tilex | (ty << 16));
DrawStripHighM4(nametab2, dx2 | (8 << 16), tilex2 | (ty2 << 17));
} else
@ -451,20 +460,21 @@ static void DrawSpritesM2(int scanline)
// now draw all sprites backwards
for (--s; s >= 0; s--) {
int x, w = (zoomed ? 16: 8);
int x, c, w = (zoomed ? 16: 8);
i = sprites_x[s];
x = sat[MEM_LE2(i+1)] + xoff;
if (sat[MEM_LE2(i+3)] & 0x80)
x -= 32;
c = sat[MEM_LE2(i+3)] & 0x0f;
if (x > 0) {
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s])];
if (zoomed) TileDoubleSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
else TileNormSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
if (zoomed) TileDoubleSprM2(x, pack, c);
else TileNormSprM2(x, pack, c);
}
if((pv->reg[1] & 0x2) && (x+=w) > 0) {
pack = PicoMem.vramb[MEM_LE2(sprites_addr[s]+0x10)];
if (zoomed) TileDoubleSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
else TileNormSprM2(x, pack, sat[MEM_LE2(i+3)] & 0xf);
if (zoomed) TileDoubleSprM2(x, pack, c);
else TileNormSprM2(x, pack, c);
}
}
}
@ -524,34 +534,45 @@ static void FinalizeLineRGB555SMS(int line);
void PicoFrameStartSMS(void)
{
int lines = 192, columns = 256, coffs;
int lines = 192, columns = 256, loffs, coffs;
skip_next_line = 0;
screen_offset = 24;
loffs = screen_offset = 24; // 192 lines is really 224 with top/bottom bars
Pico.est.rendstatus = PDRAW_32_COLS;
switch ((Pico.video.reg[0]&0x06) | (Pico.video.reg[1]&0x18)) {
// Copy LCD enable flag for easier handling
Pico.m.hardware &= ~0x2;
if (PicoIn.opt & POPT_EN_GG_LCD)
Pico.m.hardware |= 0x2;
if ((Pico.m.hardware & 0x3) == 0x3) {
// GG LCD always has 160x144 regardless of settings
screen_offset = 24; // nonetheless the vdp timing has 224 lines
loffs = 48;
lines = 144;
columns = 160;
} else switch ((Pico.video.reg[0]&0x06) | (Pico.video.reg[1]&0x18)) {
// SMS2 only 224/240 line modes, e.g. Micro Machines
case 0x06|0x08:
screen_offset = 0;
loffs = screen_offset = 0;
lines = 240;
break;
case 0x06|0x10:
screen_offset = 8;
loffs = screen_offset = 8;
lines = 224;
break;
}
if (PicoIn.opt & POPT_EN_SOFTSCALE) {
line_offset = 0;
coffs = 0;
columns = 320;
} else
line_offset = PicoIn.opt & POPT_DIS_32C_BORDER ? 0 : 32;
coffs = PicoIn.opt & POPT_DIS_32C_BORDER ? 0:(320-columns)/2;
line_offset = (PicoIn.opt & POPT_ALT_RENDERER ? coffs : 0);
coffs = line_offset;
if (FinalizeLineSMS == FinalizeLineRGB555SMS)
line_offset = 0 /* done in FinalizeLine */;
if (Pico.est.rendstatus != rendstatus_old || lines != rendlines) {
emu_video_mode_change(screen_offset, lines, coffs, columns);
emu_video_mode_change(loffs, lines, coffs, columns);
rendstatus_old = Pico.est.rendstatus;
rendlines = lines;
}
@ -562,14 +583,20 @@ void PicoFrameStartSMS(void)
void PicoLineSMS(int line)
{
if (skip_next_line > 0) {
skip_next_line--;
int skip = skip_next_line;
// GG LCD, render only visible part of screen
if ((Pico.m.hardware & 0x3) == 0x3 && (line < 24 || line >= 24+144))
goto norender;
if (PicoScanBegin != NULL && skip == 0)
skip = PicoScanBegin(line + screen_offset);
if (skip) {
skip_next_line = skip - 1;
return;
}
if (PicoScanBegin != NULL)
skip_next_line = PicoScanBegin(line + screen_offset);
// Draw screen:
BackFill(Pico.video.reg[7] & 0x0f, 0, &Pico.est);
if (Pico.video.reg[1] & 0x40) {
@ -583,19 +610,21 @@ void PicoLineSMS(int line)
if (PicoScanEnd != NULL)
skip_next_line = PicoScanEnd(line + screen_offset);
norender:
Pico.est.HighCol += HighColIncrement;
Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement;
}
/* Fixed palette for TMS9918 modes */
static u16 tmspal[32] = {
0x00,0x00,0x08,0x0c,0x10,0x30,0x01,0x3c,0x02,0x03,0x05,0x0f,0x04,0x33,0x15,0x3f
0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
};
void PicoDoHighPal555SMS(void)
{
unsigned int *spal=(void *)PicoMem.cram;
unsigned int *dpal=(void *)Pico.est.HighPal;
u32 *spal=(void *)PicoMem.cram;
u32 *dpal=(void *)Pico.est.HighPal;
unsigned int t;
int i;
@ -603,21 +632,9 @@ void PicoDoHighPal555SMS(void)
if (!(Pico.video.reg[0] & 0x4))
spal = (u32 *)tmspal;
/* cram is always stored as shorts, even though real hardware probably uses bytes */
if (PicoIn.AHW & PAHW_SMS) for (i = 0x20/2; i > 0; i--, spal++, dpal++) {
t = *spal;
#if defined(USE_BGR555)
t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<6) | ((t & 0x00300030)<<9);
t |= (t >> 2) | ((t >> 4) & 0x04210421);
#elif defined(USE_BGR565)
t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10);
t |= (t >> 2) | ((t >> 4) & 0x08610861);
#else
t = ((t & 0x00030003)<<14) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)>>1);
t |= (t >> 2) | ((t >> 4) & 0x08610861);
#endif
*dpal = t;
} else for (i = 0x20/2; i > 0; i--, spal++, dpal++) { // GG palette 4 bit/col
/* SMS 6 bit cram data was already converted to MD/GG format by vdp write,
* hence GG/SMS/TMS can all be handled the same here */
for (i = 0x20/2; i > 0; i--, spal++, dpal++) {
t = *spal;
#if defined(USE_BGR555)
t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
@ -646,15 +663,7 @@ static void FinalizeLineRGB555SMS(int line)
static void FinalizeLine8bitSMS(int line)
{
u8 *pd = Pico.est.DrawLineDest + line_offset;
u8 *ps = Pico.est.HighCol + line_offset + 8;
if (DrawLineDestIncrement) {
if (PicoIn.opt & POPT_EN_SOFTSCALE)
rh_upscale_nn_4_5(pd, 320, ps, 256, 256, f_nop);
else if (pd != ps)
memcpy(pd, ps, 256);
}
FinalizeLine8bit(0, line, &Pico.est);
}
void PicoDrawSetOutputSMS(pdso_t which)

View file

@ -64,7 +64,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
#define POPT_EN_MCD_PCM (1<<10)
#define POPT_EN_MCD_CDDA (1<<11)
#define POPT_EN_MCD_GFX (1<<12) // 00 x000
// unused (1<<13)
#define POPT_EN_GG_LCD (1<<13)
#define POPT_EN_SOFTSCALE (1<<14)
#define POPT_EN_MCD_RAMCART (1<<15)
#define POPT_DIS_VDP_FIFO (1<<16) // 0x 0000

View file

@ -670,6 +670,7 @@ PICO_INTERNAL void PicoFrameStart(void);
void PicoDrawSync(int to, int blank_last_line);
void BackFill(int reg7, int sh, struct PicoEState *est);
void FinalizeLine555(int sh, int line, struct PicoEState *est);
void FinalizeLine8bit(int sh, int line, struct PicoEState *est);
void PicoDrawSetOutBufMD(void *dest, int increment);
extern int (*PicoScanBegin)(unsigned int num);
extern int (*PicoScanEnd)(unsigned int num);

View file

@ -52,8 +52,17 @@ static void vdp_data_write(unsigned char d)
struct PicoVideo *pv = &Pico.video;
if (pv->type == 3) {
if (PicoMem.cram[pv->addr & 0x1f] != d) Pico.m.dirtyPal = 1;
PicoMem.cram[pv->addr & 0x1f] = d;
if (Pico.m.hardware & 0x1) { // GG, same layout as MD
unsigned a = pv->addr & 0x3f;
if (a & 0x1) d &= 0x0f;
if (((u8 *)PicoMem.cram)[MEM_LE2(a)] != d) Pico.m.dirtyPal = 1;
((u8 *)PicoMem.cram)[MEM_LE2(a)] = d;
} else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr)
unsigned a = pv->addr & 0x1f;
u16 c = (d&0x30)*0x40 + (d&0x0c)*0x10 + (d&0x03)*0x04;
if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1;
PicoMem.cram[a] = c | (c>>2);
}
} else {
PicoMem.vramb[MEM_LE2(pv->addr)] = d;
}
@ -130,7 +139,7 @@ static unsigned char z80_sms_in(unsigned short a)
{
case 0x00:
case 0x01:
d = 0xff;
d = 0xff & ~(PicoIn.pad[0] & 0x80);
break;
case 0x40: /* V counter */