|
@@ -3,6 +3,7 @@
|
|
|
* (C) notaz, 2013
|
|
|
* (C) aliaspider, 2016
|
|
|
* (C) Daniel De Matteis, 2013
|
|
|
+ * (C) kub, 2020
|
|
|
*
|
|
|
* This work is licensed under the terms of MAME license.
|
|
|
* See COPYING file in the top-level directory.
|
|
@@ -80,12 +81,8 @@ static retro_input_state_t input_state_cb;
|
|
|
static retro_environment_t environ_cb;
|
|
|
static retro_audio_sample_batch_t audio_batch_cb;
|
|
|
|
|
|
-#if defined(RENDER_GSKIT_PS2)
|
|
|
-#define VOUT_MAX_WIDTH 328
|
|
|
-#else
|
|
|
#define VOUT_MAX_WIDTH 320
|
|
|
#define VOUT_32COL_WIDTH 256
|
|
|
-#endif
|
|
|
#define VOUT_MAX_HEIGHT 240
|
|
|
|
|
|
#define INITIAL_SND_RATE 44100
|
|
@@ -109,6 +106,8 @@ static int vout_width, vout_height, vout_offset;
|
|
|
static float user_vout_width = 0.0;
|
|
|
|
|
|
#if defined(RENDER_GSKIT_PS2)
|
|
|
+#define VOUT_8BIT_WIDTH 328
|
|
|
+#define VOUT_8BIT_HEIGHT 256
|
|
|
RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL;
|
|
|
static void *retro_palette;
|
|
|
static struct retro_hw_ps2_insets padding;
|
|
@@ -213,6 +212,28 @@ void cache_flush_d_inval_i(void *start, void *end)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+#ifdef RENDER_GSKIT_PS2
|
|
|
+/* ee-gcc is version 3.2, where these aren't yet defined */
|
|
|
+void __builtin___clear_cache(void *b, void *e)
|
|
|
+{
|
|
|
+#if 0 /* which of these is overall faster for lots of small cache updates? */
|
|
|
+ SyncDCache(b, e);
|
|
|
+#else
|
|
|
+ FlushCache(0); /* WRITEBACK_DCACHE */
|
|
|
+#endif
|
|
|
+ FlushCache(2); /* INVALIDATE_ICACHE */
|
|
|
+}
|
|
|
+
|
|
|
+int __builtin_parity(unsigned v)
|
|
|
+{
|
|
|
+ /* credits to bit twiddling hacks, https://graphics.stanford.edu/~seander/bithacks.html */
|
|
|
+ v ^= v >> 16;
|
|
|
+ v ^= v >> 8;
|
|
|
+ v ^= v >> 4;
|
|
|
+ return (0x6996 >> (v&0xf)) & 1;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef __MACH__
|
|
|
/* calls to this may be generated by the compiler, but it's missing in libc? */
|
|
|
void __clear_cache(void *start, void *end)
|
|
@@ -604,17 +625,29 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
|
|
|
vout_16bit = vout_format == PDF_RGB555 || (PicoIn.AHW & PAHW_32X);
|
|
|
|
|
|
#if defined(RENDER_GSKIT_PS2)
|
|
|
+ // calculate the borders of the real image inside the picodrive image
|
|
|
+ vout_width = (vout_16bit ? VOUT_MAX_WIDTH : VOUT_8BIT_WIDTH);
|
|
|
+ vout_height = (vout_16bit ? VOUT_MAX_HEIGHT : VOUT_8BIT_HEIGHT);
|
|
|
+ vout_offset = (vout_16bit ? 0 : 8); // 8bit has 8 px overlap area on the left
|
|
|
if (is_32cols) {
|
|
|
- padding = (struct retro_hw_ps2_insets){start_line, 16.0f, VOUT_MAX_HEIGHT - line_count - start_line, 64.0f};
|
|
|
+ // 256x240, with or w/o overlap on the left and 64 px on the right
|
|
|
+ padding = (struct retro_hw_ps2_insets){start_line, vout_offset, vout_height - line_count - start_line, vout_width - 256.0f - vout_offset};
|
|
|
} else {
|
|
|
- padding = (struct retro_hw_ps2_insets){start_line, 16.0f, VOUT_MAX_HEIGHT - line_count - start_line, 0.0f};
|
|
|
+ // 320x240, with or w/o overlap on the left and none on the right
|
|
|
+ padding = (struct retro_hw_ps2_insets){start_line, vout_offset, vout_height - line_count - start_line, vout_width - 320.0f - vout_offset};
|
|
|
}
|
|
|
|
|
|
- vout_width = VOUT_MAX_WIDTH;
|
|
|
- vout_height = VOUT_MAX_HEIGHT;
|
|
|
- memset(vout_buf, 0, vout_width * VOUT_MAX_HEIGHT);
|
|
|
+ int pxsz = (vout_16bit ? 2 : 1); // pixel size: RGB = 16 bits, CLUT = 8 bits
|
|
|
+ memset(vout_buf, 0, pxsz * vout_width * vout_height);
|
|
|
memset(retro_palette, 0, gsKit_texture_size_ee(16, 16, GS_PSM_CT16));
|
|
|
- PicoDrawSetOutBuf(vout_buf, vout_width);
|
|
|
+ PicoDrawSetOutBuf(vout_buf, pxsz * vout_width);
|
|
|
+ if (ps2) {
|
|
|
+ // prepare image as texture for rendering
|
|
|
+ ps2->coreTexture->Width = vout_width;
|
|
|
+ ps2->coreTexture->Height = vout_height;
|
|
|
+ ps2->coreTexture->PSM = (vout_16bit ? GS_PSM_CT16 : GS_PSM_T8);
|
|
|
+ ps2->padding = padding;
|
|
|
+ }
|
|
|
#else
|
|
|
vout_width = is_32cols ? VOUT_32COL_WIDTH : VOUT_MAX_WIDTH;
|
|
|
memset(vout_buf, 0, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);
|
|
@@ -1653,10 +1686,11 @@ void retro_run(void)
|
|
|
buff = (uint32_t *)RETRO_HW_FRAME_BUFFER_VALID;
|
|
|
|
|
|
if (!ps2) {
|
|
|
+ // get access to the graphics hardware
|
|
|
if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) {
|
|
|
printf("Failed to get HW rendering interface!\n");
|
|
|
return;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) {
|
|
|
printf("HW render interface mismatch, expected %u, got %u!\n",
|
|
@@ -1664,72 +1698,32 @@ void retro_run(void)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ps2->coreTexture->Width = vout_width;
|
|
|
- ps2->coreTexture->Height = vout_height;
|
|
|
- ps2->coreTexture->PSM = GS_PSM_T8;
|
|
|
ps2->coreTexture->ClutPSM = GS_PSM_CT16;
|
|
|
ps2->coreTexture->Filter = GS_FILTER_LINEAR;
|
|
|
ps2->coreTexture->Clut = retro_palette;
|
|
|
- }
|
|
|
|
|
|
- if (Pico.m.dirtyPal) {
|
|
|
- int i;
|
|
|
- unsigned short int *pal=(void *)ps2->coreTexture->Clut;
|
|
|
-
|
|
|
- if (PicoIn.AHW & PAHW_SMS) {
|
|
|
- // SMS
|
|
|
- unsigned int *spal=(void *)PicoMem.cram;
|
|
|
- unsigned int *dpal=(void *)pal;
|
|
|
- unsigned int t;
|
|
|
-
|
|
|
- /* cram is always stored as shorts, even though real hardware probably uses bytes */
|
|
|
- for (i = 0x20/2; i > 0; i--, spal++, dpal++) {
|
|
|
- t = *spal;
|
|
|
- t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<6) | ((t & 0x00300030)<<9);
|
|
|
- t |= t >> 2;
|
|
|
- t |= (t >> 4) & 0x08610861;
|
|
|
- *dpal = t;
|
|
|
- }
|
|
|
- pal[0xe0] = 0;
|
|
|
-
|
|
|
-
|
|
|
- } else if (PicoIn.AHW & PAHW_32X) {
|
|
|
- // MCD+32X
|
|
|
- } else if (PicoIn.AHW & PAHW_MCD) {
|
|
|
- // MCD
|
|
|
- } else {
|
|
|
- // MD
|
|
|
- if(Pico.video.reg[0xC]&8){
|
|
|
- do_pal_convert_with_shadows(pal, PicoMem.cram);
|
|
|
- } else {
|
|
|
- do_pal_convert(pal, PicoMem.cram);
|
|
|
- if (Pico.est.rendstatus & PDRAW_SONIC_MODE) {
|
|
|
- memcpy(&pal[0x80], pal, 0x40*2);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //Rotate CLUT.
|
|
|
- for (i = 0; i < 256; i++) {
|
|
|
- if ((i&0x18) == 8) {
|
|
|
- unsigned short int tmp = pal[i];
|
|
|
- pal[i] = pal[i+8];
|
|
|
- pal[i+8] = tmp;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Pico.m.dirtyPal = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (PicoIn.AHW & PAHW_SMS) {
|
|
|
ps2->coreTexture->Mem = vout_buf;
|
|
|
- } else {
|
|
|
- ps2->coreTexture->Mem = Pico.est.Draw2FB;
|
|
|
+ ps2->coreTexture->Width = vout_width;
|
|
|
+ ps2->coreTexture->Height = vout_height;
|
|
|
+ ps2->coreTexture->PSM = (vout_16bit ? GS_PSM_CT16 : GS_PSM_T8);
|
|
|
+ ps2->padding = padding;
|
|
|
}
|
|
|
|
|
|
- ps2->padding = padding;
|
|
|
-
|
|
|
+ // CLUT update needed?
|
|
|
+ if (!vout_16bit && Pico.m.dirtyPal) {
|
|
|
+ PicoDrawUpdateHighPal();
|
|
|
+
|
|
|
+ // Rotate CLUT. PS2 is special since entries in CLUT are not in sequence.
|
|
|
+ unsigned short int *pal=(void *)retro_palette;
|
|
|
+ for (i = 0; i < 256; i+=8) {
|
|
|
+ if ((i&0x18) == 0x08)
|
|
|
+ memcpy(pal+i,Pico.est.HighPal+i+8,16);
|
|
|
+ else if ((i&0x18) == 0x10)
|
|
|
+ memcpy(pal+i,Pico.est.HighPal+i-8,16);
|
|
|
+ else
|
|
|
+ memcpy(pal+i,Pico.est.HighPal+i,16);
|
|
|
+ }
|
|
|
+ }
|
|
|
#else
|
|
|
if (!vout_16bit) {
|
|
|
/* The 8 bit renderers write a CLUT image in Pico.est.Draw2FB, while libretro wants RGB in vout_buf.
|
|
@@ -1809,21 +1803,13 @@ void retro_init(void)
|
|
|
#ifdef _3DS
|
|
|
vout_buf = linearMemAlign(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2, 0x80);
|
|
|
#elif defined(RENDER_GSKIT_PS2)
|
|
|
- vout_buf = memalign(128, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT);
|
|
|
+ vout_buf = memalign(4096, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);
|
|
|
retro_palette = memalign(128, gsKit_texture_size_ee(16, 16, GS_PSM_CT16));
|
|
|
#else
|
|
|
vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2);
|
|
|
#endif
|
|
|
|
|
|
PicoInit();
|
|
|
-#if defined(RENDER_GSKIT_PS2)
|
|
|
- PicoDrawSetOutFormat(PDF_NONE, 0);
|
|
|
- PicoDrawSetOutBuf(vout_buf, vout_width);
|
|
|
- PicoDrawSetOutputMode4(PDF_8BIT);
|
|
|
-#else
|
|
|
- PicoDrawSetOutFormat(PDF_RGB555, 0);
|
|
|
- PicoDrawSetOutBuf(vout_buf, vout_width * 2);
|
|
|
-#endif
|
|
|
|
|
|
//PicoIn.osdMessage = plat_status_msg_busy_next;
|
|
|
PicoIn.mcdTrayOpen = disk_tray_open;
|