* (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.
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
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;
#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)
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);
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",
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.
#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;