for (; n; n--)\r
*pd++ = (unsigned char) (*ps++ | pat);\r
}\r
-#define blockcpy memcpy\r
+#define blockcpy memmove\r
#endif\r
\r
#define TileNormMaker_(pix_func,ret) \\r
\r
PicoDrawUpdateHighPal();\r
\r
- if (Pico.video.reg[12]&1) {\r
- len = 320;\r
- } else {\r
- len = 256;\r
- }\r
-\r
- if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len == 256) {\r
- switch (PicoIn.filter) {\r
- case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
- case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
- case 1: h_upscale_snn_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
- default: h_upscale_nn_4_5(pd, 320, ps, 256, 256, f_pal); break;\r
- }\r
+ if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)\r
+ len = 160;\r
+ else if (Pico.video.reg[12]&1) len = 320;\r
+ else len = 256;\r
+\r
+ if ((*est->PicoOpt & POPT_EN_SOFTSCALE) && len < 320) {\r
+ if (len == 256)\r
+ switch (PicoIn.filter) {\r
+ case 3: h_upscale_bl4_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+ case 2: h_upscale_bl2_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+ case 1: h_upscale_snn_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+ default: h_upscale_nn_4_5(pd, 320, ps, 256, len, f_pal); break;\r
+ }\r
+ else if (len == 160)\r
+ switch (PicoIn.filter) {\r
+ case 3:\r
+ case 2: h_upscale_bl2_1_2(pd, 320, ps, 160, len, f_pal); break;\r
+ default: h_upscale_nn_1_2(pd, 320, ps, 160, len, f_pal); break;\r
+ }\r
} else {\r
- if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len == 256) pd += 32;\r
+ if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)\r
+ pd += (320-len) / 2;\r
#if 1\r
h_copy(pd, 320, ps, 320, len, f_pal);\r
#else\r
}\r
#endif\r
\r
-static void FinalizeLine8bit(int sh, int line, struct PicoEState *est)\r
+void FinalizeLine8bit(int sh, int line, struct PicoEState *est)\r
{\r
unsigned char *pd = est->DrawLineDest;\r
+ unsigned char *ps = est->HighCol+8;\r
int len;\r
static int dirty_line;\r
\r
{\r
// a hack for mid-frame palette changes\r
if (!(est->rendstatus & PDRAW_SONIC_MODE) | (line - dirty_line > 4)) {\r
- // store a maximum of 2 additional palettes in SonicPal\r
- if (est->SonicPalCount < 2)\r
+ // store a maximum of 3 additional palettes in SonicPal\r
+ if (est->SonicPalCount < 3)\r
est->SonicPalCount ++;\r
dirty_line = line;\r
est->rendstatus |= PDRAW_SONIC_MODE;\r
Pico.m.dirtyPal = 2;\r
}\r
\r
- if (Pico.video.reg[12]&1) {\r
- len = 320;\r
- } else {\r
- len = 256;\r
- }\r
+ if ((PicoIn.AHW & PAHW_SMS) && (Pico.m.hardware & 0x3) == 0x3)\r
+ len = 160;\r
+ else if (Pico.video.reg[12]&1) len = 320;\r
+ else len = 256;\r
+\r
+ if (DrawLineDestIncrement == 0)\r
+ pd = est->HighCol+8;\r
\r
- if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len == 256) {\r
- unsigned char *ps = est->HighCol+8;\r
+ if ((PicoIn.opt & POPT_EN_SOFTSCALE) && len < 320) {\r
unsigned char pal = 0;\r
\r
if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))\r
pal = est->SonicPalCount*0x40;\r
- if (DrawLineDestIncrement == 0)\r
- pd = est->HighCol+8;\r
// Smoothing can't be used with CLUT, hence it's always Nearest Neighbour.\r
- // use reverse version since src and dest ptr may be the same.\r
- rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);\r
- } else if (DrawLineDestIncrement == 0) {\r
- if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))\r
- blockcpy_or(est->HighCol+8, est->HighCol+8, len, est->SonicPalCount*0x40);\r
+ if (len == 256)\r
+ // use reverse version since src and dest ptr may be the same.\r
+ rh_upscale_nn_4_5(pd, 320, ps, 256, len, f_or);\r
+ else\r
+ rh_upscale_nn_1_2(pd, 320, ps, 256, len, f_or);\r
} else {\r
- if (!(PicoIn.opt & POPT_DIS_32C_BORDER))\r
- pd += 32;\r
- if (!sh && (est->rendstatus & PDRAW_SONIC_MODE)) {\r
+ if (!(*est->PicoOpt & POPT_DIS_32C_BORDER) && len < 320)\r
+ pd += (320-len) / 2;\r
+ if (!sh && (est->rendstatus & PDRAW_SONIC_MODE))\r
// select active backup palette\r
- blockcpy_or(pd, est->HighCol+8, len, est->SonicPalCount*0x40);\r
- } else {\r
- blockcpy(pd, est->HighCol+8, len);\r
- }\r
+ blockcpy_or(pd, ps, len, est->SonicPalCount*0x40);\r
+ else if (pd != ps)\r
+ blockcpy(pd, ps, len);\r
}\r
}\r
\r
\r
static void DrawBlankedLine(int line, int offs, int sh, int bgc)\r
{\r
- if (PicoScanBegin != NULL)\r
- PicoScanBegin(line + offs);\r
+ int skip = skip_next_line;\r
+\r
+ if (PicoScanBegin != NULL && skip == 0)\r
+ skip = PicoScanBegin(line + offs);\r
+\r
+ if (skip) {\r
+ skip_next_line = skip - 1;\r
+ return;\r
+ }\r
\r
BackFill(bgc, sh, &Pico.est);\r
\r
FinalizeLine(sh, line, &Pico.est);\r
\r
if (PicoScanEnd != NULL)\r
- PicoScanEnd(line + offs);\r
+ skip_next_line = PicoScanEnd(line + offs);\r
\r
Pico.est.HighCol += HighColIncrement;\r
Pico.est.DrawLineDest = (char *)Pico.est.DrawLineDest + DrawLineDestIncrement;\r
\r
static void PicoLine(int line, int offs, int sh, int bgc)\r
{\r
- int skip = 0;\r
-\r
- if (skip_next_line > 0) {\r
- skip_next_line--;\r
- return;\r
- }\r
+ int skip = skip_next_line;\r
\r
Pico.est.DrawScanline = line;\r
- if (PicoScanBegin != NULL)\r
+ if (PicoScanBegin != NULL && skip == 0)\r
skip = PicoScanBegin(line + offs);\r
\r
if (skip) {\r
add r3, r10, #OFS_EST_HighPal\r
\r
mov lr, #0xff\r
+ mov lr, lr, lsl #1\r
\r
+ ldr r5, [r10, #OFS_EST_PicoOpt]\r
ldr r1, [r10, #OFS_EST_HighCol]\r
ldr r0, [r10, #OFS_EST_DrawLineDest]\r
+ ldr r4, [r5]\r
+ ldr r7, [r5, #OFS_PicoIn_AHW-OFS_PicoIn_opt]\r
+ ldrb r12,[r8, #OFS_Pico_video_reg+12]\r
+ ldr r2, [r8, #OFS_Pico_m_hardware]\r
add r1, r1, #8\r
\r
- ldrb r12, [r8, #OFS_Pico_video_reg+12]\r
- mov lr, lr, lsl #1\r
+ tst r7, #0x10\r
+ beq .fl_no20colRGB555\r
+ and r7, r2, #0x3\r
+ cmp r7, #0x3 @ Game Gear, LCD?\r
+ bne .fl_no20colRGB555\r
\r
- tst r12, #1\r
- movne r2, #320/8 @ len\r
+ mov r2, #160/8 @ len = 160\r
+ tst r4, #0x4000 @ EN_SOFTSCALE?\r
+ bne .fl_20scale_RGB555 @ scale 160->320\r
+ beq .fl_checkborder\r
+\r
+.fl_no20colRGB555:\r
+ tst r12, #1 @ h32?\r
+ movne r2, #320/8 @ len = 320\r
bne .fl_no32colRGB555\r
- ldr r5, [r10, #OFS_EST_PicoOpt]\r
- mov r2, #256/8\r
- ldr r4, [r5]\r
- tst r4, #0x4000\r
- bne .fl_32scale_RGB555\r
- tst r4, #0x0100\r
- addeq r0, r0, #32*2\r
+ moveq r2, #256/8 @ len = 256\r
+ tst r4, #0x4000 @ EN_SOFTSCALE?\r
+ bne .fl_32scale_RGB555 @ scale 256->320\r
\r
-.fl_no32colRGB555:\r
+.fl_checkborder:\r
+ tst r4, #0x0100 @ DIS_32C_BORDER?\r
+ rsbeq r4, r2, #320/8 @ pd += (320-len)/2\r
+ addeq r0, r0, r4, lsl #3\r
\r
+.fl_no32colRGB555:\r
#ifdef UNALIGNED_DRAWLINEDEST\r
@ this is basically for Gizmondo, which has unaligned odd lines in the framebuffer\r
tst r0, #2\r
bne .fl_32scale_RGB555u\r
#endif\r
\r
- ands r5, r5, #0x3\r
- addne pc, pc, r5, lsl #2\r
- b .fl_32scale_nn\r
+ and r5, r5, #0x3\r
+ add pc, pc, r5, lsl #2\r
+ nop\r
b .fl_32scale_nn\r
b .fl_32scale_snn\r
b .fl_32scale_bl2\r
ldmfd sp!, {r4-r10,pc}\r
\r
.fl_32scale_bl4:\r
+ // TODO this should reflect the bl4 C algorithm, but it doesn't, it's bln.\r
+ and r9, r9, r9, lsl #1 @ nuke 2 LSBs to avoid spilling for n/4\r
+.fl_32loop_bl4:\r
ldr r12, [r1], #4\r
ldr r7, [r1], #4\r
\r
subs r2, r2, #1\r
\r
stmia r0!, {r4,r5,r6,r8,r10}\r
- bne .fl_32scale_bl4\r
+ bne .fl_32loop_bl4\r
+\r
+ ldmfd sp!, {r4-r10,pc}\r
+\r
+.fl_20scale_RGB555:\r
+ ldr r5, [r5, #OFS_PicoIn_filter-OFS_PicoIn_opt]\r
+\r
+ mov r9, #0xf700 @ f800 07e0 001f | e000 0780 001c | 3800 01e0 0007\r
+ orr r9, r9, #0x00de\r
+\r
+#ifdef UNALIGNED_DRAWLINEDEST\r
+ tst r0, #2\r
+ bne .fl_20scale_RGB555u\r
+#endif\r
+\r
+ and r5, r5, #0x2\r
+ add pc, pc, r5, lsl #1\r
+ nop\r
+ b .fl_20scale_nn\r
+ b .fl_20scale_bl2\r
+\r
+.fl_20scale_nn:\r
+ ldr r12, [r1], #4\r
+ ldr r7, [r1], #4\r
+\r
+ and r4, lr, r12, lsl #1\r
+ ldrh r4, [r3, r4]\r
+ and r5, lr, r12, lsr #7\r
+ ldrh r5, [r3, r5]\r
+ and r6, lr, r12, lsr #15\r
+ ldrh r6, [r3, r6]\r
+ and r8 ,lr, r12, lsr #23\r
+ ldrh r8 ,[r3, r8 ]\r
+\r
+ orr r4, r4, r4, lsl #16\r
+ orr r5, r5, r5, lsl #16\r
+ orr r6, r6, r6, lsl #16\r
+ orr r8, r8, r8, lsl #16\r
+ stmia r0!, {r4,r5,r6,r8}\r
+\r
+ and r4, lr, r7, lsl #1\r
+ ldrh r4, [r3, r4]\r
+ and r5, lr, r7, lsr #7\r
+ ldrh r5, [r3, r5]\r
+ and r6 ,lr, r7, lsr #15\r
+ ldrh r6 ,[r3, r6]\r
+ and r8, lr, r7, lsr #23\r
+ ldrh r8, [r3, r8]\r
+\r
+ orr r4, r4, r4, lsl #16\r
+ orr r5, r5, r5, lsl #16\r
+ orr r6, r6, r6, lsl #16\r
+ orr r8, r8, r8, lsl #16\r
+ stmia r0!, {r4,r5,r6,r8}\r
+\r
+ subs r2, r2, #1\r
+ bne .fl_20scale_nn\r
+\r
+ ldmfd sp!, {r4-r10,pc}\r
+\r
+\r
+.fl_20scale_bl2:\r
+ ldr r8, [r1]\r
+ and r8, lr, r8, lsl #1\r
+ ldrh r8, [r3, r8]\r
+ and r8, r8, r9\r
+ lsl r8, r8, #16\r
+\r
+.fl_20loop_bl2:\r
+ ldr r12, [r1], #4\r
+ ldr r7, [r1], #4\r
+\r
+ and r4, lr, r12, lsl #1\r
+ ldrh r4, [r3, r4]\r
+ and r5, lr, r12, lsr #7\r
+ ldrh r5, [r3, r5]\r
+ and r6, lr, r12, lsr #15\r
+ ldrh r6, [r3, r6]\r
+\r
+ and r4, r4, r9\r
+ add r10,r4, r8, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r4, r10,r4, lsl #16 @ (px-1+px0)/2 | px0\r
+\r
+ and r8 ,lr, r12, lsr #23\r
+ ldrh r8 ,[r3, r8]\r
+\r
+ and r5, r5, r9\r
+ add r10,r5, r4, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r5, r10,r5, lsl #16 @ (px0 +px1)/2 | px1\r
+\r
+ and r6, r6, r9\r
+ add r10,r6, r5, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r6, r10,r6, lsl #16 @ (px1 +px2)/2 | px2\r
+\r
+ and r8, r8, r9\r
+ add r10,r8, r6, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r8, r10,r8, lsl #16 @ (px2 +px3)/2 | px3\r
+\r
+ stmia r0!, {r4,r5,r6,r8}\r
+\r
+ and r4, lr, r7, lsl #1\r
+ ldrh r4, [r3, r4]\r
+ and r5, lr, r7, lsr #7\r
+ ldrh r5, [r3, r5]\r
+ and r6, lr, r7, lsr #15\r
+ ldrh r6, [r3, r6]\r
+\r
+ and r4, r4, r9\r
+ add r10,r4, r8, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r4, r10,r4, lsl #16 @ (px-1+px0)/2 | px0\r
+\r
+ and r8 ,lr, r7, lsr #23\r
+ ldrh r8 ,[r3, r8]\r
+\r
+ and r5, r5, r9\r
+ add r10,r5, r4, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r5, r10,r5, lsl #16 @ (px0 +px1)/2 | px1\r
+\r
+ and r6, r6, r9\r
+ add r10,r6, r5, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r6, r10,r6, lsl #16 @ (px1 +px2)/2 | px2\r
+\r
+ and r8, r8, r9\r
+ add r10,r8, r6, lsr #16\r
+ mov r10,r10,lsr #1\r
+ orr r8, r10,r8, lsl #16 @ (px2 +px3)/2 | px3\r
+\r
+ subs r2, r2, #1\r
+ stmia r0!, {r4,r5,r6,r8}\r
+ bne .fl_20loop_bl2\r
\r
ldmfd sp!, {r4-r10,pc}\r
\r
+\r
#ifdef UNALIGNED_DRAWLINEDEST\r
@ unaligned versions of loops\r
@ warning: starts drawing 2bytes before dst\r
}
}
else if (media_type == PM_MARK3) {
- lprintf("detected SMS ROM\n");
PicoIn.AHW = PAHW_SMS;
}
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) {
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) {
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
// 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
// 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
// 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);
}
}
}
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;
}
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) {
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;
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);
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)
#define POPT_EN_MCD_PCM (1<<10)\r
#define POPT_EN_MCD_CDDA (1<<11)\r
#define POPT_EN_MCD_GFX (1<<12) // 00 x000\r
-// unused (1<<13)\r
+#define POPT_EN_GG_LCD (1<<13)\r
#define POPT_EN_SOFTSCALE (1<<14)\r
#define POPT_EN_MCD_RAMCART (1<<15)\r
#define POPT_DIS_VDP_FIFO (1<<16) // 0x 0000\r
void PicoDrawSync(int to, int blank_last_line);\r
void BackFill(int reg7, int sh, struct PicoEState *est);\r
void FinalizeLine555(int sh, int line, struct PicoEState *est);\r
+void FinalizeLine8bit(int sh, int line, struct PicoEState *est);\r
void PicoDrawSetOutBufMD(void *dest, int increment);\r
extern int (*PicoScanBegin)(unsigned int num);\r
extern int (*PicoScanEnd)(unsigned int num);\r
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;
}
{
case 0x00:
case 0x01:
- d = 0xff;
+ d = 0xff & ~(PicoIn.pad[0] & 0x80);
break;
case 0x40: /* V counter */
.endif\r
\r
orr r2, r2, r2, lsr #3\r
-.if \sh == 1\r
- str r2, [r0, #0x40*2*4]\r
-.endif\r
str r2, [r0], #4\r
.endm\r
\r
subs r12, r12, #1\r
\r
ldmia r1!, {r4-r7}\r
- convRGB32_2 r4, 1\r
- convRGB32_2 r5, 1\r
- convRGB32_2 r6, 1\r
- convRGB32_2 r7, 1\r
+ convRGB32_2 r4, 2\r
+ convRGB32_2 r5, 2\r
+ convRGB32_2 r6, 2\r
+ convRGB32_2 r7, 2\r
bgt .loopRGB32sh\r
\r
mov r12, #0x40>>3 @ repeats\r
\r
.loopRGB32hi:\r
ldmia r1!, {r4-r7}\r
- convRGB32_2 r4, 2\r
- convRGB32_2 r5, 2\r
- convRGB32_2 r6, 2\r
- convRGB32_2 r7, 2\r
+ convRGB32_2 r4, 1\r
+ convRGB32_2 r5, 1\r
+ convRGB32_2 r6, 1\r
+ convRGB32_2 r7, 1\r
\r
subs r12, r12, #1\r
bgt .loopRGB32hi\r
\r
if (PicoIn.AHW & PAHW_SMS) {\r
sys_name = "Master System";\r
+ if (Pico.m.hardware & 0x1)\r
+ sys_name = "Game Gear";\r
#ifdef NO_SMS\r
extra = " [no support]";\r
#endif\r
memset(&defaultConfig, 0, sizeof(defaultConfig));\r
defaultConfig.EmuOpt = EOPT_EN_SRAM | EOPT_EN_SOUND | EOPT_16BPP |\r
EOPT_EN_CD_LEDS | EOPT_GZIP_SAVES | 0x10/*?*/;\r
- defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|\r
+ defaultConfig.s_PicoOpt = POPT_EN_SNDFILTER|POPT_EN_YM2413|POPT_EN_GG_LCD |\r
POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 |\r
POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX |\r
POPT_EN_DRC|POPT_ACC_SPRITES |\r
"bin", "smd", "gen", "md",
"iso", "cso", "cue", "chd",
"32x",
- "sms",
+ "sms", "gg",
NULL
};
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),
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 */
*/
#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)
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) { \
} 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)
} 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)
}\r
\r
#define is_16bit_mode() \\r
- (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X))\r
+ (currentConfig.renderer == RT_16BIT || (PicoIn.AHW & PAHW_32X) || doing_bg_frame)\r
\r
static void (*osd_text)(int x, int y, const char *text);\r
\r
\r
/* line doublers */\r
static unsigned int ld_counter;\r
-static int ld_left, ld_lines;\r
+static int ld_left, ld_lines; // numbers in Q1 format\r
\r
static int EmuScanBegin16_ld(unsigned int num)\r
{\r
emu_scan_end(ld_counter);\r
\r
ld_counter++;\r
- ld_left--;\r
+ ld_left -= 2;\r
if (ld_left <= 0) {\r
- ld_left = ld_lines;\r
+ ld_left += ld_lines;\r
\r
EmuScanBegin16_ld(num);\r
memcpy(Pico.est.DrawLineDest, oldline, 320 * gp2x_current_bpp / 8);\r
else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode\r
bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);\r
+ memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess\r
}\r
else {\r
bgr444_to_rgb32(localPal, Pico.est.SonicPal);\r
\r
static int make_local_pal_sms(int fast_mode)\r
{\r
- unsigned short *spal = PicoMem.cram;\r
- unsigned int *dpal = (void *)localPal;\r
- unsigned int i, t;\r
-\r
- for (i = 0x40; i > 0; i--) {\r
- t = *spal++;\r
- t = ((t & 0x0003) << 22) | ((t & 0x000c) << 12) | ((t & 0x0030) << 2);\r
- t |= t >> 2;\r
- t |= t >> 4;\r
- *dpal++ = t;\r
- }\r
-\r
+ bgr444_to_rgb32(localPal, PicoMem.cram);\r
Pico.m.dirtyPal = 0;\r
return 0x40;\r
}\r
int gp2x_mode = 16;\r
int renderer = get_renderer();\r
\r
+ if (doing_bg_frame)\r
+ renderer = RT_16BIT;\r
+\r
PicoIn.opt &= ~POPT_ALT_RENDERER;\r
emu_scan_begin = NULL;\r
emu_scan_end = NULL;\r
\r
Pico.m.dirtyPal = 1;\r
\r
- PicoIn.opt &= ~POPT_EN_SOFTSCALE;\r
+ PicoIn.opt &= ~(POPT_DIS_32C_BORDER|POPT_EN_SOFTSCALE);\r
if (currentConfig.scaling == EOPT_SCALE_SW) {\r
PicoIn.opt |= POPT_EN_SOFTSCALE;\r
PicoIn.filter = EOPT_FILTER_BILINEAR2;\r
- }\r
+ } else if (currentConfig.scaling == EOPT_SCALE_HW && is_16bit_mode())\r
+ // hw scaling, render without any padding\r
+ PicoIn.opt |= POPT_DIS_32C_BORDER;\r
\r
// palette converters for 8bit modes\r
make_local_pal = (PicoIn.AHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;\r
int scalex = 320, scaley = 240;\r
int ln_offs = 0;\r
\r
+ /* line doubling for swscaling, also needed for bg frames */\r
+ if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {\r
+ ld_lines = ld_left = 2*line_count / (240 - line_count);\r
+ PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);\r
+ }\r
+\r
if (doing_bg_frame)\r
return;\r
\r
osd_y = 232;\r
\r
/* set up hwscaling here */\r
- PicoIn.opt &= ~POPT_DIS_32C_BORDER;\r
if (col_count < 320 && currentConfig.scaling == EOPT_SCALE_HW) {\r
scalex = col_count;\r
- PicoIn.opt |= POPT_DIS_32C_BORDER;\r
osd_fps_x = col_count - (320-OSD_FPS_X);\r
}\r
\r
\r
gp2x_video_RGB_setscaling(ln_offs, scalex, scaley);\r
\r
- /* line doubling */\r
- if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {\r
- ld_lines = ld_left = line_count / (240 - line_count);\r
- PicoDrawSetCallbacks(EmuScanBegin16_ld, EmuScanEnd16_ld);\r
- }\r
\r
// clear whole screen in all buffers\r
if (!is_16bit_mode())\r
doing_bg_frame = 1;\r
PicoDrawSetCallbacks(NULL, NULL);\r
Pico.m.dirtyPal = 1;\r
+ PicoIn.opt &= ~POPT_DIS_32C_BORDER;\r
+ gp2x_current_bpp = 16;\r
\r
if (!no_scale)\r
no_scale = currentConfig.scaling == EOPT_SCALE_NONE;\r
// make sure we are in correct mode\r
change_renderer(0);\r
vid_reset_mode();\r
+ rendstatus_old = -1;\r
}\r
\r
void pemu_loop_prep(void)\r
#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;
#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;
}
} 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)
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)
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;
* for display isn't always possible.\r
*/\r
\r
-static u16 *screen_buffer(u16 *buf)\r
+static inline u16 *screen_buffer(u16 *buf)\r
{\r
return buf + screen_y * g_screen_ppitch + screen_x -\r
(out_y * g_screen_ppitch + out_x);\r
{\r
typedef void (*upscale_t)\r
(u16 *di,int ds, u8 *si,int ss, int w,int h, u16 *pal);\r
- upscale_t upscale_hv[] = {\r
+ static const upscale_t upscale_256_224_hv[] = {\r
upscale_rgb_nn_x_4_5_y_16_17, upscale_rgb_snn_x_4_5_y_16_17,\r
upscale_rgb_bl2_x_4_5_y_16_17, upscale_rgb_bl4_x_4_5_y_16_17,\r
};\r
- upscale_t upscale_h[] = {\r
+ static const upscale_t upscale_256_224_h[] = {\r
upscale_rgb_nn_x_4_5, upscale_rgb_snn_x_4_5,\r
upscale_rgb_bl2_x_4_5, upscale_rgb_bl4_x_4_5,\r
};\r
- upscale_t upscale_v[] = {\r
+ static const upscale_t upscale_256_224_v[] = {\r
upscale_rgb_nn_y_16_17, upscale_rgb_snn_y_16_17,\r
upscale_rgb_bl2_y_16_17, upscale_rgb_bl4_y_16_17,\r
};\r
- upscale_t *upscale;\r
+ static const upscale_t upscale_160_144_hv[] = {\r
+ upscale_rgb_nn_x_1_2_y_3_5, upscale_rgb_nn_x_1_2_y_3_5,\r
+ upscale_rgb_bl2_x_1_2_y_3_5, upscale_rgb_bl4_x_1_2_y_3_5,\r
+ };\r
+ static const upscale_t upscale_160_144_h[] = {\r
+ upscale_rgb_nn_x_1_2, upscale_rgb_nn_x_1_2,\r
+ upscale_rgb_bl2_x_1_2, upscale_rgb_bl2_x_1_2,\r
+ };\r
+ static const upscale_t upscale_160_144_v[] = {\r
+ upscale_rgb_nn_y_3_5, upscale_rgb_nn_y_3_5,\r
+ upscale_rgb_bl2_y_3_5, upscale_rgb_bl4_y_3_5,\r
+ };\r
+ const upscale_t *upscale;\r
int y;\r
\r
// handle software upscaling\r
upscale = NULL;\r
- if (currentConfig.scaling == EOPT_SCALE_SW && out_w == 256) {\r
- if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
- // h+v scaling\r
- upscale = upscale_hv;\r
- else\r
- // h scaling\r
- upscale = upscale_h;\r
- } else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224) {\r
- // v scaling\r
- upscale = upscale_v;\r
- } else {\r
+ if (currentConfig.scaling == EOPT_SCALE_SW) {\r
+ if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
+ // h+v scaling\r
+ upscale = out_w == 256 ? upscale_256_224_hv: upscale_160_144_hv;\r
+ else\r
+ // h scaling\r
+ upscale = out_w == 256 ? upscale_256_224_h : upscale_160_144_h;\r
+ } else if (currentConfig.vscaling == EOPT_SCALE_SW && out_h <= 224)\r
+ // v scaling\r
+ upscale = out_w == 256 ? upscale_256_224_v : upscale_160_144_v;\r
+ if (!upscale) {\r
// no scaling\r
for (y = 0; y < out_h; y++)\r
h_copy(pd, pp, ps, 328, out_w, f_pal);\r
\r
static int cb_vscaling_begin(unsigned int line)\r
{\r
- static int prevline = 999;\r
-\r
// at start of new frame?\r
- if (line < prevline) {\r
- // set y frame offset (see emu_change_video_mode)\r
+ if (line <= out_y) {\r
+ // set y frame offset (see emu_video_mode_change)\r
Pico.est.DrawLineDest = screen_buffer(g_screen_ptr) +\r
- (out_y * g_screen_ppitch + out_x);\r
+ (out_y * g_screen_ppitch /*+ out_x*/);\r
vscale_state = 0;\r
- }\r
- prevline = line;\r
+ return out_y - line;\r
+ } else if (line > out_y + out_h)\r
+ return 1;\r
+\r
return 0;\r
}\r
\r
static int cb_vscaling_end(unsigned int line)\r
{\r
u16 *dest = Pico.est.DrawLineDest;\r
- switch (currentConfig.filter) {\r
- case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
- break;\r
- case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
- break;\r
- case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
- break;\r
- default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
- break;\r
- }\r
+\r
+ if (out_h == 144)\r
+ switch (currentConfig.filter) {\r
+ case 0: v_upscale_nn_3_5(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ default: v_upscale_snn_3_5(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ }\r
+ else\r
+ switch (currentConfig.filter) {\r
+ case 3: v_upscale_bl4_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ case 2: v_upscale_bl2_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ case 1: v_upscale_snn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ default: v_upscale_nn_16_17(dest, g_screen_ppitch, 320, vscale_state);\r
+ break;\r
+ }\r
Pico.est.DrawLineDest = dest;\r
return 0;\r
}\r
}\r
switch (currentConfig.vscaling) {\r
case EOPT_SCALE_HW:\r
- screen_h = (out_h < 224 ? 224 : out_h);\r
+ screen_h = (out_h < 224 && out_h > 144 ? 224 : out_h);\r
screen_y = 0;\r
// NTSC always has 224 visible lines, anything smaller has bars\r
- if (out_h < 224)\r
+ if (out_h < 224 && out_h > 144)\r
screen_y += (224 - out_h)/2;\r
// handle vertical centering for 16 bit mode\r
if (is_16bit_mode())\r
case EOPT_SCALE_SW:\r
screen_y = (screen_h - 240)/2;\r
// NTSC always has 224 visible lines, anything smaller has bars\r
- if (out_h < 224)\r
+ if (out_h < 224 && out_h > 144)\r
screen_y += (224 - out_h)/2;\r
// in 16 bit mode sw scaling is divided between core and platform\r
if (is_16bit_mode() && out_h < 240)\r
get_define OFS_PicoIn_ PicoInterface opt ; echo "$line" >>$fn
get_define OFS_PicoIn_ PicoInterface filter ; echo "$line" >>$fn
+get_define OFS_PicoIn_ PicoInterface AHW ; echo "$line" >>$fn
get_define OFS_EST_ PicoEState DrawScanline ; echo "$line" >>$fn
get_define OFS_EST_ PicoEState rendstatus ; echo "$line" >>$fn