From 3de7ec98b18ea87517ca62fc36ffac8c70775f94 Mon Sep 17 00:00:00 2001 From: Vincent Bousquet Date: Mon, 9 Sep 2024 18:43:30 +0200 Subject: [PATCH] DMD: fix LibPinMame, fix WhiteStar error --- src/wpc/alvgdmd.c | 2 +- src/wpc/capcom.c | 4 +- src/wpc/core.c | 692 +++++++++++++++-------------------------- src/wpc/core.h | 34 +- src/wpc/dedmd.c | 9 +- src/wpc/gts3dmd.c | 2 +- src/wpc/sam.c | 20 +- src/wpc/sam_original.c | 6 +- src/wpc/se.c | 10 +- src/wpc/sleic.c | 2 +- src/wpc/spinb.c | 4 +- src/wpc/wpc.c | 2 +- 12 files changed, 309 insertions(+), 478 deletions(-) diff --git a/src/wpc/alvgdmd.c b/src/wpc/alvgdmd.c index 88614c3de..ab73f413f 100644 --- a/src/wpc/alvgdmd.c +++ b/src/wpc/alvgdmd.c @@ -347,6 +347,6 @@ static INTERRUPT_GEN(dmd32_firq2) { PINMAME_VIDEO_UPDATE(alvgdmd_update) { core_dmd_update_pwm(&dmdlocals.pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, &dmdlocals.pwm_state); return 0; } diff --git a/src/wpc/capcom.c b/src/wpc/capcom.c index 396b5f6e5..be76251cc 100644 --- a/src/wpc/capcom.c +++ b/src/wpc/capcom.c @@ -964,7 +964,7 @@ PINMAME_VIDEO_UPDATE(cc_dmd128x32) { *line++ = 0; RAM+=16; } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } @@ -993,7 +993,7 @@ PINMAME_VIDEO_UPDATE(cc_dmd256x64) { } RAM+=16; } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } diff --git a/src/wpc/core.c b/src/wpc/core.c index 26d8345dc..0ad748cba 100644 --- a/src/wpc/core.c +++ b/src/wpc/core.c @@ -721,7 +721,7 @@ static struct { int lastGI[CORE_MAXGI]; UINT64 lastSol; /*-- VPinMame specifics --*/ - #ifdef VPINMAME + #if defined(VPINMAME) || defined(LIBPINMAME) UINT8 vpm_dmd_last_lum[DMD_MAXY * DMD_MAXX]; UINT8 vpm_dmd_luminance_lut[256]; UINT32 vpm_dmd_color_lut[256]; @@ -849,407 +849,8 @@ static PALETTE_INIT(core) { } /*----------------------------------- -/ Generic DMD display handler +/ Generic segment display handler /------------------------------------*/ -void video_update_core_dmd(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout) { - int ii, jj; - - #define DMD_OFS(row, col) ((row)*layout->length + col) - - // Dedicated processing for hardware generations using core PWM luminance computation since they prepare both raw frames and luminance data - if (core_gameData->gen & (/*GEN_SAM | GEN_SPA |*/ GEN_ALVG | GEN_ALVG_DMD2 | GEN_GTS3 | GEN_ALLWPC | GEN_DEDMD16 | GEN_DEDMD32 | GEN_DEDMD64 | GEN_ALLWS)) { - const int isMainDMD = layout->length >= 128; // Up to 2 main DMDs (1 for all games, except Strike'n Spares which has 2) - const int isStrikeNSpares = strncasecmp(Machine->gamedrv->name, "snspare", 7) == 0; - - // Render to internal display, using computed luminance, if there is a visible display (PinMame and VPinMame with its window shown) - // FIXME check for VPinMame window hidden/shown state, and do not render if hidden - // FIXME apply colors ? - #if defined(PINMAME) || defined(VPINMAME) - #define DMD_PAL(x) ((int)sizeof(core_palette) / 3 - 48 + ((3 * (int)x) >> 4)) // The trail of PinMame palette has 48 DMD dot shades - //#define DMD_PAL(x) = dmdColor[63 + (x >> 4)] - pen_t *dmdColor = &Machine->pens[COL_DMDOFF]; - BMTYPE **lines = ((BMTYPE **)bitmap->line) + (layout->top * locals.displaySize); - for (ii = 0; ii < layout->start; ii++) { - BMTYPE *line = (*lines) + (layout->left * locals.displaySize); - for (jj = 0; jj < layout->length; jj++) { - int p = coreGlobals.dmdDotLum[DMD_OFS(ii, jj)], q = DMD_PAL(coreGlobals.dmdDotLum[DMD_OFS(ii, jj)]); - *line = DMD_PAL(coreGlobals.dmdDotLum[DMD_OFS(ii, jj)]); - line += locals.displaySize; - } - lines += locals.displaySize; - } - // Apply antialiasing if enabled or clear pixels between dots - assert((locals.displaySize == 1) || (locals.displaySize == 2)); - if (locals.displaySize == 2) { - int noaa = !pmoptions.dmd_antialias || (layout->type & CORE_DMDNOAA); - lines = ((BMTYPE **)bitmap->line) + (layout->top * locals.displaySize); - for (ii = 0; ii < layout->start * 2 - 1; ii++) { - BMTYPE *line = (*lines) + layout->left; - for (jj = 0; jj < layout->length * 2 - 1; jj++) { - int pi = (ii - 1) >> 1, pj = (jj - 1) >> 1; - if (noaa) { - if ((ii & 1) || (jj & 1)) - *line = DMD_PAL(0); - } else if ((ii & 1) && (jj & 1)) { // Corner point - int lum = ((int)coreGlobals.dmdDotLum[DMD_OFS(pi, pj)] + (int)coreGlobals.dmdDotLum[DMD_OFS(pi+1, pj)] + (int)coreGlobals.dmdDotLum[DMD_OFS(pi, pj+1)] + (int)coreGlobals.dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 6; - *line = DMD_PAL(lum); - } else if (ii & 1) { // Vertical side point - int lum = ((int)coreGlobals.dmdDotLum[DMD_OFS(pi, pj+1)] + (int)coreGlobals.dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 3; - *line = DMD_PAL(lum); - } else if (jj & 1) { // Horizontal side point - int lum = ((int)coreGlobals.dmdDotLum[DMD_OFS(pi+1, pj)] + (int)coreGlobals.dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 3; - *line = DMD_PAL(lum); - } - line ++; - } - lines ++; - } - } - #undef DMD_PAL - #endif - - // Prepare data for VPinMame interface, using computed luminance and applying user LUT for luminance/color (Controller.RawDmdPixels / Controller.RawColoredDmdPixels) - #ifdef VPINMAME - if (isMainDMD) { - g_raw_dmdx = layout->length; - g_raw_dmdy = layout->start; - if (memcmp(locals.vpm_dmd_last_lum, coreGlobals.dmdDotLum, layout->length * layout->start) != 0) { - g_needs_DMD_update = 1; - UINT8* rawLum = g_raw_dmdbuffer; - UINT32* rawCol = g_raw_colordmdbuffer; - for (ii = 0; ii < layout->start; ii++) { - for (jj = 0; jj < layout->length; jj++) { - UINT8 lum = coreGlobals.dmdDotLum[DMD_OFS(ii, jj)]; - (*rawLum++) = locals.vpm_dmd_luminance_lut[lum]; - (*rawCol++) = locals.vpm_dmd_color_lut[lum]; - } - } - memcpy(locals.vpm_dmd_last_lum, coreGlobals.dmdDotLum, layout->length * layout->start); - } - } - #endif - - // Send main DMDs raw frame to dmddevice plugins - #ifdef VPINMAME - if (isMainDMD && g_fShowPinDMD) { - if (isStrikeNSpares) { - if (layout->top != 0) - renderDMDFrame(core_gameData->gen, layout->length, layout->start, (UINT8*)coreGlobals.dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - else - render2ndDMDFrame(core_gameData->gen, layout->length, layout->start, (UINT8*)coreGlobals.dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - } - else { - renderDMDFrame(core_gameData->gen, layout->length, layout->start, (UINT8*)coreGlobals.dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - render2ndDMDFrame(core_gameData->gen, layout->length, layout->start, (UINT8*)coreGlobals.dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - } - } - #endif - - // Capture main DMDs raw frame - // TODO this is disabled for Strikes'n Spares which has 2 DMDs - // TODO not sure to understand why frame capture is performed if dmddevice is enabled simultaneously with virtual DMD. Remove it ? - #ifdef VPINMAME - if (isMainDMD && !isStrikeNSpares && (g_fDumpFrames || (g_fShowPinDMD && g_fShowWinDMD))) { - FILE *f; - char *ptr; - char DumpFilename[MAX_PATH]; - const DWORD tick = GetTickCount(); - #ifndef _WIN64 - const HINSTANCE hInst = GetModuleHandle("VPinMAME.dll"); - #else - const HINSTANCE hInst = GetModuleHandle("VPinMAME64.dll"); - #endif - GetModuleFileName(hInst, DumpFilename, MAX_PATH); - ptr = strrchr(DumpFilename, '\\'); - strcpy_s(ptr + 1, 11, "DmdDump\\"); - strcat_s(DumpFilename, MAX_PATH, Machine->gamedrv->name); - - // Additional single bitplane raw frames for GTS3, WPC and Alvin G. - if (raw_dmd_frame_count != 0) { - FILE* fr; - char RawFilename[MAX_PATH]; - strcpy_s(RawFilename, MAX_PATH, DumpFilename); - strcat_s(RawFilename, MAX_PATH, ".raw"); - fr = fopen(RawFilename, "rb"); - if (fr) { - fclose(fr); - fr = fopen(RawFilename, "ab"); - } - else { - fr = fopen(RawFilename, "ab"); - if (fr) { - fputc(0x52, fr); - fputc(0x41, fr); - fputc(0x57, fr); - fputc(0x00, fr); - fputc(0x01, fr); - fputc(layout->length, fr); - fputc(layout->start, fr); - fputc(raw_dmd_frame_count, fr); - } - } - if (fr) { - fwrite(&tick, 1, 4, fr); - fwrite(raw_dmd_frames, 1, (layout->length * layout->start / 8 * raw_dmd_frame_count), fr); - fclose(fr); - } - } - - // Raw frames (multiple bitplanes, combined from PWM pattern) - strcat_s(DumpFilename, MAX_PATH, ".txt"); - f = fopen(DumpFilename, "a"); - if (f) { - fprintf(f, "0x%08x\n", tick); - for (jj = 0; jj < layout->start; jj++) { - for (ii = 0; ii < layout->length; ii++) - fprintf(f, "%01x", coreGlobals.dmdDotRaw[DMD_OFS(ii, jj)]); - fprintf(f, "\n"); - } - fprintf(f, "\n"); - fclose(f); - } - } - #endif - } - - // Processing for drivers that are not yet using the core PWM implementation - else { - pen_t *dmdColor = &Machine->pens[COL_DMDOFF]; - pen_t *aaColor = &Machine->pens[COL_DMDAA]; - BMTYPE **lines = ((BMTYPE **)bitmap->line) + (layout->top*locals.displaySize); - int noaa = !pmoptions.dmd_antialias || (layout->type & CORE_DMDNOAA); - - // prepare all brightness & color/palette tables for mappings from internal DMD representation: - const int shade_16_enabled = (core_gameData->gen & (GEN_SAM|GEN_SPA|GEN_ALVG|GEN_ALVG_DMD2|GEN_GTS3)) != 0; - -#if defined(VPINMAME) || defined(LIBPINMAME) - - const UINT8 perc0 = (pmoptions.dmd_perc0 > 0) ? pmoptions.dmd_perc0 : 20; - const UINT8 perc1 = (pmoptions.dmd_perc33 > 0) ? pmoptions.dmd_perc33 : 33; - const UINT8 perc2 = (pmoptions.dmd_perc66 > 0) ? pmoptions.dmd_perc66 : 67; - const UINT8 perc3 = 100; - - static const int levelgts3[16] = {0/*5*/, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100}; // GTS3 and AlvinG brightness seems okay - static const int levelsam[16] = {0/*5*/, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 90, 100}; // SAM brightness seems okay - - const int * const level = (core_gameData->gen & (GEN_SAM|GEN_SPA)) ? levelsam : levelgts3; - - const UINT8 raw_4[4] = {perc0,perc1,perc2,perc3}; - const UINT8 raw_16[16] = {level[0],level[1],level[2],level[3],level[4],level[5],level[6],level[7],level[8],level[9],level[10],level[11],level[12],level[13],level[14],level[15]}; - - UINT32 palette32_4[4]; - UINT32 palette32_16[16]; - unsigned char palette[4][3]; - - int rStart = 0xFF, gStart = 0xE0, bStart = 0x20; - if ((pmoptions.dmd_red > 0) || (pmoptions.dmd_green > 0) || (pmoptions.dmd_blue > 0)) { - rStart = pmoptions.dmd_red; gStart = pmoptions.dmd_green; bStart = pmoptions.dmd_blue; - } - - /*-- Autogenerate DMD Color Shades--*/ - palette[0][0] = rStart * perc0 / 100; - palette[0][1] = gStart * perc0 / 100; - palette[0][2] = bStart * perc0 / 100; - palette[1][0] = rStart * perc1 / 100; - palette[1][1] = gStart * perc1 / 100; - palette[1][2] = bStart * perc1 / 100; - palette[2][0] = rStart * perc2 / 100; - palette[2][1] = gStart * perc2 / 100; - palette[2][2] = bStart * perc2 / 100; - palette[3][0] = rStart * perc3 / 100; - palette[3][1] = gStart * perc3 / 100; - palette[3][2] = bStart * perc3 / 100; - - /*-- If the "colorize" option is set, use the individual option colors for the shades --*/ - if (pmoptions.dmd_colorize) { - if (pmoptions.dmd_red0 > 0 || pmoptions.dmd_green0 > 0 || pmoptions.dmd_blue0 > 0) { - palette[0][0] = pmoptions.dmd_red0; - palette[0][1] = pmoptions.dmd_green0; - palette[0][2] = pmoptions.dmd_blue0; - } - if (pmoptions.dmd_red33 > 0 || pmoptions.dmd_green33 > 0 || pmoptions.dmd_blue33 > 0) { - palette[1][0] = pmoptions.dmd_red33; - palette[1][1] = pmoptions.dmd_green33; - palette[1][2] = pmoptions.dmd_blue33; - } - if (pmoptions.dmd_red66 > 0 || pmoptions.dmd_green66 > 0 || pmoptions.dmd_blue66 > 0) { - palette[2][0] = pmoptions.dmd_red66; - palette[2][1] = pmoptions.dmd_green66; - palette[2][2] = pmoptions.dmd_blue66; - } - } - - for (ii = 0; ii < 4; ++ii) - palette32_4[ii] = (UINT32)palette[ii][0] | (((UINT32)palette[ii][1]) << 8) | (((UINT32)palette[ii][2]) << 16); - - for(ii = 0; ii < 16; ++ii) - palette32_16[ii] = (rStart*level[ii]/100) | ((gStart*level[ii]/100) << 8) | ((bStart*level[ii]/100) << 16); - - // - - if(layout->length >= 128) // Main DMD (don't send mini DMDs) - { - g_raw_dmdx = layout->length; - g_raw_dmdy = layout->start; - - // Strikes N' Spares has 2 standard DMDs - if (strncasecmp(Machine->gamedrv->name, "snspare", 7) == 0) - { - g_raw_dmdy = 64; - // shift offset into the raw DMDs, depending on which display is updated in here - if (layout->top != 0) - raw_dmdoffs = 128 * 32; - else - raw_dmdoffs = 0; - } - } -#endif - - for (ii = 0; ii < layout->start; ii++) { - BMTYPE *line = (*lines++) + (layout->left*locals.displaySize); - for (jj = 0; jj < layout->length; jj++) { - const int offs = DMD_OFS(ii, jj); - const UINT8 col = coreGlobals.dmdDotRaw[offs]; - #if defined(VPINMAME) || defined(LIBPINMAME) - currbuffer[offs] = col; - #ifdef LIBPINMAME - g_raw_dmdbuffer[offs] = (g_fDmdMode == 0) ? (shade_16_enabled ? raw_16[col] : raw_4[col]) : col; - #else - if (layout->length >= 128) { // Main DMD (don't send mini DMDs) - g_raw_dmdbuffer[offs + raw_dmdoffs] = shade_16_enabled ? raw_16[col] : raw_4[col]; - g_raw_colordmdbuffer[offs + raw_dmdoffs] = shade_16_enabled ? palette32_16[col] : palette32_4[col]; - } - #endif - #endif - *line++ = shade_16_enabled ? dmdColor[col+63] : dmdColor[col]; - if (locals.displaySize > 1 && jj < layout->length-1) - *line++ = noaa ? 0 : aaColor[col + (coreGlobals.dmdDotRaw[DMD_OFS(ii, jj+1)])]; - } - if (locals.displaySize > 1) { - int col1 = (coreGlobals.dmdDotRaw[DMD_OFS(ii,0)]) + (coreGlobals.dmdDotRaw[DMD_OFS(ii+1,0)]); - line = (*lines++) + (layout->left*locals.displaySize); - for (jj = 0; jj < layout->length; jj++) { - int col2 = (coreGlobals.dmdDotRaw[DMD_OFS(ii,jj+1)]) + (coreGlobals.dmdDotRaw[DMD_OFS(ii+1,jj+1)]); - *line++ = noaa ? 0 : aaColor[col1]; - if (jj < layout->length-1) - *line++ = noaa ? 0 : aaColor[2*(col1 + col2)/5]; - col1 = col2; - } - } - } - -#ifdef VPINMAME - if ((layout->length == 128) || (layout->length == 192) || (layout->length == 256)) { // Don't send mini DMD to dmddevice - //external dmd - if (g_fShowPinDMD) - { - if (strncasecmp(Machine->gamedrv->name, "snspare", 7) == 0) - { - if (layout->top != 0) - renderDMDFrame(core_gameData->gen, layout->length, layout->start, currbuffer, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - else - render2ndDMDFrame(core_gameData->gen, layout->length, layout->start, currbuffer, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - } else { - renderDMDFrame(core_gameData->gen, layout->length, layout->start, currbuffer, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - render2ndDMDFrame(core_gameData->gen, layout->length, layout->start, currbuffer, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); - } - } - - if (oldbuffer != NULL) { // detect if same frame again - if (memcmp(oldbuffer, currbuffer, (layout->length * layout->start)) != 0) - { - g_needs_DMD_update = 1; - - if ((g_fShowPinDMD && g_fShowWinDMD) || g_fDumpFrames) // output dump frame to .txt - { - FILE *f; - char *ptr; - char DumpFilename[MAX_PATH]; - - const DWORD tick = GetTickCount(); -#ifndef _WIN64 - const HINSTANCE hInst = GetModuleHandle("VPinMAME.dll"); -#else - const HINSTANCE hInst = GetModuleHandle("VPinMAME64.dll"); -#endif - GetModuleFileName(hInst, DumpFilename, MAX_PATH); - ptr = strrchr(DumpFilename, '\\'); - strcpy_s(ptr + 1, 11, "DmdDump\\"); - strcat_s(DumpFilename, MAX_PATH, Machine->gamedrv->name); - - if (raw_dmd_frame_count != 0) { - FILE* fr; - char RawFilename[MAX_PATH]; - strcpy_s(RawFilename, MAX_PATH, DumpFilename); - strcat_s(RawFilename, MAX_PATH, ".raw"); - fr = fopen(RawFilename, "rb"); - if (fr) { - fclose(fr); - fr = fopen(RawFilename, "ab"); - } - else { - fr = fopen(RawFilename, "ab"); - if(fr) - { - fputc(0x52, fr); - fputc(0x41, fr); - fputc(0x57, fr); - fputc(0x00, fr); - fputc(0x01, fr); - fputc(layout->length, fr); - fputc(layout->start, fr); - fputc(raw_dmd_frame_count, fr); - } - } - if(fr) - { - fwrite(&tick, 1, 4, fr); - fwrite(raw_dmd_frames, 1, (layout->length * layout->start / 8 * raw_dmd_frame_count), fr); - fclose(fr); - } - } - - strcat_s(DumpFilename, MAX_PATH, ".txt"); - f = fopen(DumpFilename, "a"); - if (f) { - fprintf(f, "0x%08x\n", tick); - for (jj = 0; jj < layout->start; jj++) { - for (ii = 0; ii < layout->length; ii++) - { - const UINT8 col = currbuffer[jj*layout->length + ii]; - fprintf(f, "%01x", col); - } - fprintf(f, "\n"); - } - fprintf(f, "\n"); - fclose(f); - } - } - } - } - - raw_dmd_frame_count = 0; - - // swap buffers - if (currbuffer == buffer1) { - currbuffer = buffer2; - oldbuffer = buffer1; - } - else { - currbuffer = buffer1; - oldbuffer = buffer2; - } - } -#endif - } - - #undef DMD_OFS - - #ifdef VPINMAME - has_DMD_Video = 1; - #endif -} - #ifdef VPINMAME # define inRect(r,l,t,w,h) FALSE #else /* VPINMAME */ @@ -1259,9 +860,6 @@ INLINE int inRect(const struct rectangle *r, int left, int top, int width, int h } #endif /* VPINMAME */ -/*----------------------------------- -/ Generic segment display handler -/------------------------------------*/ static void updateDisplay(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout_array) { if (layout_array == NULL) { DBGLOG(("gen_refresh without LCD layout\n")); return; } @@ -3069,9 +2667,7 @@ void core_write_pwm_output_lamp_matrix(int startIndex, UINT8 columns, UINT8 rows All hardware so far (Alvin G, Data East, Sega/Stern Whitestar, GTS3, WPC, SAM, Capcom, Sleic (Spain), Spinball) creates shades using PWM on a plasma or LED display (later Stern games). Therefore, PinMame offers access to the - raw high frequency frames (f.e. for coloring) or to a PWM integrated view (f.e. for rendering). Sadly some colorization - plugins used the legacy preshaded frames to identify and color frame, so access to these legacy shades is also provided - for backward compatibility. + raw high frequency frames (f.e. for coloring) or to a PWM integrated view (f.e. for rendering). Unlike lamps which have varying strobe periods, DMD are rasterized at a fixed frequency. Therefore, the implementation simply stores the frames at this frequency and apply a (simple) low pass filter to account for the eye flicker-fusion limit. @@ -3127,16 +2723,13 @@ fprintf(']\n'); fprintf('sum=%i\n', sum(int_factor * b)); */ -// TODO for the time being, DMD are always updated from core/updateDisplay, running at a fixed 60Hz. This may lead to stutters -// as it is not aligned with real display refresh rate. We should update DMD on request but this needs to make these functions -// thread safe. - void core_dmd_pwm_init(core_tDMDPWMState* dmd_state, const int width, const int height, const int filter, const int raw_combiner) { + assert((width & 0x0007) == 0); dmd_state->width = width; dmd_state->height = height; - dmd_state->rawFrameSize = width * height / 8; + dmd_state->frameSize = width * height; + dmd_state->rawFrameSize = dmd_state->frameSize / 8; dmd_state->raw_combiner = raw_combiner; - assert(dmd_state->rawFrameSize * 8 == width * height); static const UINT16 fir_colorization_3_frames[] = { 20000, 20000, 20000 }; switch (filter) { @@ -3193,10 +2786,14 @@ void core_dmd_pwm_init(core_tDMDPWMState* dmd_state, const int width, const int assert(0); // Unsupported filter } dmd_state->rawFrames = malloc(dmd_state->nFrames * dmd_state->rawFrameSize); - dmd_state->shadedFrame = malloc(dmd_state->width * dmd_state->height * sizeof(UINT16)); - assert(dmd_state->rawFrames != NULL && dmd_state->shadedFrame != NULL); + dmd_state->shadedFrame = malloc(dmd_state->frameSize * sizeof(UINT16)); + dmd_state->bitplaneFrame = malloc(dmd_state->frameSize * sizeof(UINT8)); + dmd_state->luminanceFrame = malloc(dmd_state->frameSize * sizeof(UINT8)); + assert(dmd_state->rawFrames != NULL && dmd_state->shadedFrame != NULL && dmd_state->bitplaneFrame != NULL && dmd_state->luminanceFrame != NULL); memset(dmd_state->rawFrames, 0, dmd_state->nFrames * dmd_state->rawFrameSize); - memset(dmd_state->shadedFrame, 0, dmd_state->width * dmd_state->height * sizeof(UINT16)); + memset(dmd_state->shadedFrame, 0, dmd_state->frameSize * sizeof(UINT16)); + memset(dmd_state->bitplaneFrame, 0, dmd_state->frameSize * sizeof(UINT8)); + memset(dmd_state->luminanceFrame, 0, dmd_state->frameSize * sizeof(UINT8)); dmd_state->nextFrame = 0; } @@ -3205,20 +2802,28 @@ void core_dmd_pwm_exit(core_tDMDPWMState* dmd_state) { dmd_state->rawFrames = NULL; free(dmd_state->shadedFrame); dmd_state->shadedFrame = NULL; + free(dmd_state->bitplaneFrame); + dmd_state->bitplaneFrame = NULL; + free(dmd_state->luminanceFrame); + dmd_state->luminanceFrame = NULL; } +// TODO for the time being, DMD are always updated from core/updateDisplay, running at a fixed 60Hz. This may lead to stutters +// as it is not aligned with real display refresh rate. We should update DMD on request but this needs to make these functions +// thread safe. To avoid synchronization, a simple loop model with consumer accesing data before barrier, and provider pushing +// data after the barrier should be enough. void core_dmd_submit_frame(core_tDMDPWMState* dmd_state, const UINT8* frame, const int ntimes) { - for (int i = 0; i < ntimes; i++) { - memcpy(dmd_state->rawFrames + dmd_state->nextFrame * dmd_state->rawFrameSize, frame, dmd_state->rawFrameSize); - dmd_state->nextFrame = (dmd_state->nextFrame + 1) % dmd_state->nFrames; - dmd_state->frame_index++; - } + for (int i = 0; i < ntimes; i++) { + memcpy(dmd_state->rawFrames + dmd_state->nextFrame * dmd_state->rawFrameSize, frame, dmd_state->rawFrameSize); + dmd_state->nextFrame = (dmd_state->nextFrame + 1) % dmd_state->nFrames; + dmd_state->frame_index++; + } } void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { int ii, jj, kk; - // Apply low pass filter over stored frames + // Apply low pass filter over stored frames then scale down to final shades memset(dmd_state->shadedFrame, 0, dmd_state->width * dmd_state->height * sizeof(UINT16)); for (ii = 0; ii < dmd_state->fir_size; ii++) { const UINT16 frame_weight = dmd_state->fir_weights[ii]; @@ -3235,29 +2840,26 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { } } } - - // Scale down to final shades UINT16* line = dmd_state->shadedFrame; for (ii = 0; ii < dmd_state->height * dmd_state->width; ii++) { unsigned int data = (unsigned int) (*line++); // unsigned int precision is needed here - coreGlobals.dmdDotLum[ii] = (UINT8)((255u * data) / dmd_state->fir_sum); + dmd_state->luminanceFrame[ii] = (UINT8)((255u * data) / dmd_state->fir_sum); } - // Store raw bitplane frames for colorization plugins in a backward compatible manner + // Compute combined bitplane frames as they used to be for backward compatibility with colorization plugins #if defined(VPINMAME) || defined(LIBPINMAME) - // Compute combined bitplane frame as they used to be for backward compatibility with colorization plugins switch (dmd_state->raw_combiner) { case CORE_DMD_PWM_COMBINER_LUM_4: for (ii = 0; ii < dmd_state->height * dmd_state->width; ii++) - coreGlobals.dmdDotRaw[ii] = coreGlobals.dmdDotLum[ii] >> 6; + dmd_state->bitplaneFrame[ii] = dmd_state->luminanceFrame[ii] >> 6; break; case CORE_DMD_PWM_COMBINER_LUM_16: // GTS3 never had a stable combiner since PWM patterns vary over 1/3/6/8/10 frames, hence it provided raw 1 bitplane frame and not really stable combined one for (ii = 0; ii < dmd_state->height * dmd_state->width; ii++) - coreGlobals.dmdDotRaw[ii] = coreGlobals.dmdDotLum[ii] >> 4; + dmd_state->bitplaneFrame[ii] = dmd_state->luminanceFrame[ii] >> 4; break; case CORE_DMD_PWM_COMBINER_SUM_3: // Sum of the last 3 raw frames seen (WPC) { - UINT8* rawData = &coreGlobals.dmdDotRaw[0]; + UINT8* rawData = &dmd_state->bitplaneFrame[0]; UINT8* frame0 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 1)) % dmd_state->nFrames) * dmd_state->rawFrameSize; UINT8* frame1 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 2)) % dmd_state->nFrames) * dmd_state->rawFrameSize; UINT8* frame2 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 3)) % dmd_state->nFrames) * dmd_state->rawFrameSize; @@ -3278,7 +2880,7 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { case CORE_DMD_PWM_COMBINER_SUM_2_1: // high bit for double length frame, low bit for single length frame case CORE_DMD_PWM_COMBINER_SUM_1_2: { - UINT8 *rawData = &coreGlobals.dmdDotRaw[0], *frame0, *frame1; + UINT8 *rawData = &dmd_state->bitplaneFrame[0], *frame0, *frame1; if (dmd_state->raw_combiner == CORE_DMD_PWM_COMBINER_SUM_2_1) { // double length frame are the 2 before last one, single length frame is the last one (Data East 128x32, Sega/Stern Whitestar) frame0 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 2)) % dmd_state->nFrames) * dmd_state->rawFrameSize; frame1 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 1)) % dmd_state->nFrames) * dmd_state->rawFrameSize; @@ -3303,7 +2905,7 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { break; case CORE_DMD_PWM_COMBINER_SUM_4: // Sum of the last 4 frames (Alvin G. for Pistol Poker & Mystery Castle) { - UINT8* rawData = &coreGlobals.dmdDotRaw[0]; + UINT8* rawData = &dmd_state->bitplaneFrame[0]; UINT8* frame0 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 1)) % dmd_state->nFrames) * dmd_state->rawFrameSize; UINT8* frame1 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 2)) % dmd_state->nFrames) * dmd_state->rawFrameSize; UINT8* frame2 = dmd_state->rawFrames + ((dmd_state->nextFrame + (dmd_state->nFrames - 3)) % dmd_state->nFrames) * dmd_state->rawFrameSize; @@ -3318,7 +2920,11 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { default: assert(0); // Unsupported combiner } - // For GTS3, WPC and Alvin G. 2 also store raw single bitplane frame + #endif + + // For GTS3, WPC and Alvin G. 2 also store raw single bitplane frame for backward compatibility with colorization plugins + // TODO move these data to dmd_state struct (for cleanup and to fix multiple DMD support for GTS3 Strikes N' Spares) + #if defined(VPINMAME) || defined(LIBPINMAME) if (core_gameData->gen & (GEN_ALLWPC | GEN_GTS3 | GEN_ALVG_DMD2)) { raw_dmd_frame_count = dmd_state->nFrames > CORE_MAX_RAW_DMD_FRAMES ? CORE_MAX_RAW_DMD_FRAMES : dmd_state->nFrames; UINT8* rawData = &raw_dmd_frames[0]; @@ -3336,6 +2942,226 @@ void core_dmd_update_pwm(core_tDMDPWMState* dmd_state) { #endif } +// Render to internal display, using provided luminance, if there is a visible display (PinMame always, and VPinMame when its window is shown) +// FIXME apply colors LUT ? +#if defined(PINMAME) || defined(VPINMAME) +void core_dmd_render_internal(struct mame_bitmap *bitmap, const int x, const int y, const int width, const int height, const UINT8* dmdDotLum, const int apply_aa) { + #define DMD_OFS(row, col) ((row)*width + col) + #define DMD_PAL(x) ((int)sizeof(core_palette) / 3 - 48 + ((3 * (int)x) >> 4)) // The trail of PinMame palette has 48 DMD dot shades + //#define DMD_PAL(x) = dmdColor[63 + (x >> 4)] + int ii, jj; + pen_t *dmdColor = &Machine->pens[COL_DMDOFF]; + BMTYPE **lines = ((BMTYPE **)bitmap->line) + (y * locals.displaySize); + for (ii = 0; ii < height; ii++) { + BMTYPE *line = (*lines) + (x * locals.displaySize); + for (jj = 0; jj < width; jj++) { + int p = dmdDotLum[DMD_OFS(ii, jj)], q = DMD_PAL(dmdDotLum[DMD_OFS(ii, jj)]); + *line = DMD_PAL(dmdDotLum[DMD_OFS(ii, jj)]); + line += locals.displaySize; + } + lines += locals.displaySize; + } + // Apply antialiasing if enabled or clear pixels between dots + assert((locals.displaySize == 1) || (locals.displaySize == 2)); + if (locals.displaySize == 2) { + lines = ((BMTYPE **)bitmap->line) + (y * locals.displaySize); + for (ii = 0; ii < height * 2 - 1; ii++) { + BMTYPE *line = (*lines) + x; + for (jj = 0; jj < width * 2 - 1; jj++) { + int pi = (ii - 1) >> 1, pj = (jj - 1) >> 1; + if (!apply_aa) { + if ((ii & 1) || (jj & 1)) + *line = DMD_PAL(0); + } else if ((ii & 1) && (jj & 1)) { // Corner point + int lum = ((int)dmdDotLum[DMD_OFS(pi, pj)] + (int)dmdDotLum[DMD_OFS(pi+1, pj)] + (int)dmdDotLum[DMD_OFS(pi, pj+1)] + (int)dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 6; + *line = DMD_PAL(lum); + } else if (ii & 1) { // Vertical side point + int lum = ((int)dmdDotLum[DMD_OFS(pi, pj+1)] + (int)dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 3; + *line = DMD_PAL(lum); + } else if (jj & 1) { // Horizontal side point + int lum = ((int)dmdDotLum[DMD_OFS(pi+1, pj)] + (int)dmdDotLum[DMD_OFS(pi+1, pj+1)]) / 3; + *line = DMD_PAL(lum); + } + line ++; + } + lines ++; + } + } + #undef DMD_OFS + #undef DMD_PAL +} +#endif + +// Prepare data for VPinMame interface, using computed luminance and applying user LUT for luminance/color (Controller.RawDmdPixels / Controller.RawColoredDmdPixels) +#ifdef VPINMAME +void core_dmd_render_vpm(const int width, const int height, const UINT8* dmdDotLum) { + const int size = width * height; + g_raw_dmdx = width; + g_raw_dmdy = height; + if (memcmp(locals.vpm_dmd_last_lum, dmdDotLum, size) != 0) { + memcpy(locals.vpm_dmd_last_lum, dmdDotLum, size); + UINT8* rawLum = g_raw_dmdbuffer; + UINT32* rawCol = g_raw_colordmdbuffer; + for (int ii = 0; ii < size; ii++) { + UINT8 lum = dmdDotLum[ii]; + (*rawLum++) = locals.vpm_dmd_luminance_lut[lum]; + (*rawCol++) = locals.vpm_dmd_color_lut[lum]; + } + g_needs_DMD_update = 1; + } +} +#endif + +// Prepare data for LibPinMame interface (similar to VPinMame but without color LUT, and with a global flag to select luminance/bitplanes) +#ifdef LIBPINMAME +void core_dmd_render_lpm(const int width, const int height, const UINT8* dmdDotLum, const UINT8* dmdDotRaw) { + const int size = width * height; + g_raw_dmdx = width; + g_raw_dmdy = height; + if (g_fDmdMode == 0) { // PINMAME_DMD_MODE_BRIGHTNESS + if (memcmp(locals.vpm_dmd_last_lum, dmdDotLum, size) != 0) { + memcpy(locals.vpm_dmd_last_lum, dmdDotLum, size); + UINT8* rawLum = g_raw_dmdbuffer; + for (int ii = 0; ii < size; ii++) + (*rawLum++) = locals.vpm_dmd_luminance_lut[dmdDotLum[ii]]; + g_needs_DMD_update = 1; + } + } + else if (g_fDmdMode == 1) {// PINMAME_DMD_MODE_RAW + if (memcmp(g_raw_dmdbuffer, dmdDotRaw, size) != 0) { + memcpy(g_raw_dmdbuffer, dmdDotRaw, size); + g_needs_DMD_update = 1; + } + } +} +#endif + +// Send main DMD bitplane frame to dmddevice plugins +#ifdef VPINMAME +void core_dmd_render_dmddevice(const int width, const int height, const UINT8* dmdDotRaw, const int isDMD2) { + if (g_fShowPinDMD) { + const int isStrikeNSpares = strncasecmp(Machine->gamedrv->name, "snspare", 7) == 0; + if (isStrikeNSpares) { + if (isDMD2) + renderDMDFrame(core_gameData->gen, width, height, dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); + else + render2ndDMDFrame(core_gameData->gen, width, height, dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); + } + else { + renderDMDFrame(core_gameData->gen, width, height, dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); + render2ndDMDFrame(core_gameData->gen, width, height, dmdDotRaw, g_fDumpFrames, Machine->gamedrv->name, raw_dmd_frame_count, raw_dmd_frames); + } + } +} +#endif + +// Save main DMD bitplane and raw frames to a capture file +// TODO this is disabled for Strikes'n Spares which has 2 DMDs +// TODO not sure to understand why frame capture is performed if dmddevice is enabled simultaneously with virtual DMD. Remove it ? +#ifdef VPINMAME +void core_dmd_capture_frame(const int width, const int height, const UINT8* dmdDotRaw, const int rawFrameCount, const UINT8* rawFrame) { + const int isStrikeNSpares = strncasecmp(Machine->gamedrv->name, "snspare", 7) == 0; + if (!isStrikeNSpares && (g_fDumpFrames || (g_fShowPinDMD && g_fShowWinDMD))) { + FILE *f; + char *ptr; + char DumpFilename[MAX_PATH]; + const DWORD tick = GetTickCount(); + #ifndef _WIN64 + const HINSTANCE hInst = GetModuleHandle("VPinMAME.dll"); + #else + const HINSTANCE hInst = GetModuleHandle("VPinMAME64.dll"); + #endif + GetModuleFileName(hInst, DumpFilename, MAX_PATH); + ptr = strrchr(DumpFilename, '\\'); + strcpy_s(ptr + 1, 11, "DmdDump\\"); + strcat_s(DumpFilename, MAX_PATH, Machine->gamedrv->name); + + // Additional single bitplane raw frames for GTS3, WPC and Alvin G. + if (rawFrameCount != 0) { + FILE* fr; + char RawFilename[MAX_PATH]; + strcpy_s(RawFilename, MAX_PATH, DumpFilename); + strcat_s(RawFilename, MAX_PATH, ".raw"); + fr = fopen(RawFilename, "rb"); + if (fr) { + fclose(fr); + fr = fopen(RawFilename, "ab"); + } + else { + fr = fopen(RawFilename, "ab"); + if (fr) { + fputc(0x52, fr); + fputc(0x41, fr); + fputc(0x57, fr); + fputc(0x00, fr); + fputc(0x01, fr); + fputc(width, fr); + fputc(height, fr); + fputc(rawFrameCount, fr); + } + } + if (fr) { + fwrite(&tick, 1, 4, fr); + fwrite(rawFrame, 1, (width * height / 8 * rawFrameCount), fr); + fclose(fr); + } + } + + // Bitplane frame combined from PWM pattern of raw frames + strcat_s(DumpFilename, MAX_PATH, ".txt"); + f = fopen(DumpFilename, "a"); + if (f) { + fprintf(f, "0x%08x\n", tick); + for (int jj = 0; jj < height; jj++) { + for (int ii = 0; ii < width; ii++) + fprintf(f, "%01x", dmdDotRaw[jj*width + ii]); + fprintf(f, "\n"); + } + fprintf(f, "\n"); + fclose(f); + } + } +} +#endif + +void core_dmd_video_update(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout, core_tDMDPWMState* dmd_state) { + UINT8 *dmdDotRaw, *dmdDotLum; + + if (dmd_state) { // Full DMD state with luminance and bitplane state + dmdDotRaw = dmd_state->bitplaneFrame; + dmdDotLum = dmd_state->luminanceFrame; + } + else { // Only bitplane state: consider luminance equal to (scaled) bitplane output + dmdDotRaw = &coreGlobals.dmdDotRaw[0]; + dmdDotLum = &coreGlobals.dmdDotLum[0]; + const int shift = (core_gameData->gen & (GEN_SAM|GEN_SPA)) != 0 ? 4 : 6; + for (int ii = 0; ii < layout->length; ii++) + dmdDotLum[ii] = dmdDotRaw[ii] << shift; + } + + #if defined(PINMAME) + core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA)); + + #elif defined(LIBPINMAME) + const int isMainDMD = layout->length >= 128; // Up to 2 main DMDs (1 for all games, except Strike'n Spares which has 2) + if (isMainDMD) { + core_dmd_render_lpm(layout->length, layout->start, dmdDotLum, dmdDotRaw); + has_DMD_Video = 1; + } + + #elif defined(VPINMAME) + const int isMainDMD = layout->length >= 128; // Up to 2 main DMDs (1 for all games, except Strike'n Spares which has 2) + // FIXME check for VPinMame window hidden/shown state, and do not render if hidden + core_dmd_render_internal(bitmap, layout->left, layout->top, layout->length, layout->start, dmdDotLum, pmoptions.dmd_antialias && !(layout->type & CORE_DMDNOAA)); + if (isMainDMD) { + core_dmd_render_vpm(layout->length, layout->start, dmdDotLum); + core_dmd_render_dmddevice(layout->length, layout->start, dmdDotRaw, layout->top != 0); + core_dmd_capture_frame(layout->length, layout->start, dmdDotRaw, raw_dmd_frame_count ,raw_dmd_frames); + has_DMD_Video = 1; + } + #endif +} + // // diff --git a/src/wpc/core.h b/src/wpc/core.h index 7630a4302..f295d9ced 100644 --- a/src/wpc/core.h +++ b/src/wpc/core.h @@ -230,7 +230,6 @@ typedef struct core_dispLayout core_tLCDLayout, *core_ptLCDLayout; #define PINMAME_VIDEO_UPDATE(name) int (name)(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout) typedef int (*ptPinMAMEvidUpdate)(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout); -extern void video_update_core_dmd(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout); /*---------------------- / WPC driver constants @@ -599,19 +598,25 @@ INLINE void core_zero_cross(void) { coreGlobals.lastACZeroCrossTimeStamp = timer /*-- DMD PWM integration --*/ typedef struct { - int width; // DMD width - int height; // DMD height - int revByte; // Is bitset reversed ? - int rawFrameSize; // Size of a raw DMD frame in bytes (width * height / 8) - UINT8* rawFrames; // Buffer for incoming raw frames - UINT16* shadedFrame; // Shaded frame computed from raw frames - int nextFrame; // Position in circular buffer to store next raw frame - int nFrames; // Number of frames to store and consider to create shades (depends on hardware refresh frequency and used PWM patterns) - int raw_combiner; // Enum (see CORE_DMD_PWM_COMBINER_...) that defines how to combine bitplane to create multi plane raw frame for colorization plugin - int fir_size; // Selected filter (depends on hardware refresh frequency and number of stored frames) - UINT16* fir_weights; // Selected filter (depends on hardware refresh frequency and number of stored frames) - unsigned int fir_sum; // Sum of filter weights - unsigned int frame_index; // Raw frame index + // Definition initialized at startup using 'core_dmd_pwm_init' then unmutable + int width; // DMD width + int height; // DMD height + int revByte; // Is bitset reversed ? + int frameSize; // Size of a DMD frame in bytes (width * height) + int rawFrameSize; // Size of a raw DMD frame in bytes (width * height / 8) + int nFrames; // Number of frames to store and consider to create shades (depends on hardware refresh frequency and used PWM patterns) + int raw_combiner; // CORE_DMD_PWM_COMBINER_... enum that defines how to combine bitplanes to create multi plane raw frame for colorization plugin + int fir_size; // Selected filter (depends on hardware refresh frequency and number of stored frames) + UINT16* fir_weights; // Selected filter (depends on hardware refresh frequency and number of stored frames) + unsigned int fir_sum; // Sum of filter weights + // Data acquisition, feeded by the driver through 'core_dmd_submit_frame' + UINT8* rawFrames; // Buffer for incoming raw frames + int nextFrame; // Position in circular buffer to store next raw frame + UINT16* shadedFrame; // Shaded frame computed from raw frames + unsigned int frame_index; // Raw frame index + // Integrated data, computed by 'core_dmd_update_pwm' + UINT8* bitplaneFrame; // DMD: bitplane frame built up from raw rasterized frames (depends on each driver, stable result that can be used for post processing like colorization, ...) + UINT8* luminanceFrame; // DMD: linear luminance computed from PWM frames, for rendering (result may change and can't be considered as stable accross PinMame builds) } core_tDMDPWMState; #define CORE_DMD_PWM_FILTER_DE_128x16 0 @@ -633,6 +638,7 @@ extern void core_dmd_pwm_init(core_tDMDPWMState* dmd_state, const int width, con extern void core_dmd_pwm_exit(core_tDMDPWMState* dmd_state); extern void core_dmd_submit_frame(core_tDMDPWMState* dmd_state, const UINT8* frame, const int ntimes); extern void core_dmd_update_pwm(core_tDMDPWMState* dmd_state); +extern void core_dmd_video_update(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout, core_tDMDPWMState* dmd_state); extern void core_sound_throttle_adj(int sIn, int *sOut, int buffersize, double samplerate); diff --git a/src/wpc/dedmd.c b/src/wpc/dedmd.c index bf948f503..d0caac996 100644 --- a/src/wpc/dedmd.c +++ b/src/wpc/dedmd.c @@ -101,7 +101,7 @@ MACHINE_DRIVER_END RA0 - A9 => used to toggle between frame while rasterizing each row MA8..12 - A10..14 - RA0 is also wired to ROWCLOCK, therefore row is advanced once every 2 rasterized rows - - The start address can be either 0x2000 or 0x2100 (i.e. MA13 is always set), with CURSOR always being defined on 0x2000 / row 0, which led + - The start address is usually either 0x2000 or 0x2100 (i.e. with MA13 set), with CURSOR always being defined on one of these / row 0, which led to guess that CURSOR signal is used to generate FIRQ (frame IRQ to CPU, trigerring some animation update). Results looks good but this would be nice to check this assumption on real hardware. */ @@ -110,7 +110,6 @@ static void dmd32_vblank(int which) { // Store 2 next rasterized frame, as the CRTC is setup to render 2 contiguous full frames for each VBLANK unsigned int base = crtc6845_start_address_r(0); // MA0..13 assert((base & 0x00FF) == 0x0000); // As the mapping of lowest 8 bits is not implemented (would need complex data copy and does not seem to be used by any game) - assert((base & 0x2000) == 0x2000); // As the implementation supposed this to be always true assert(crtc6845_rasterized_height_r(0) == 64); // As the implementation requires this to be always true unsigned int src = /*((base >> 3) & 0x000F) | ((base << 1) & 0x0100) |*/ ((base << 2) & 0x7C00); core_dmd_submit_frame(&dmdlocals.pwm_state, dmd32RAM + src, 2); // First frame has been displayed 2/3 of the time (500kHz row clock) @@ -210,7 +209,7 @@ PINMAME_VIDEO_UPDATE(dedmd32_update) { } #endif core_dmd_update_pwm(&dmdlocals.pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, &dmdlocals.pwm_state); return 0; } @@ -316,7 +315,7 @@ static void dmd64_vblank(int which) { PINMAME_VIDEO_UPDATE(dedmd64_update) { core_dmd_update_pwm(&dmdlocals.pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, &dmdlocals.pwm_state); return 0; } @@ -557,6 +556,6 @@ static void dmd16_setbank(int bit, int value) { /*-- update display --*/ PINMAME_VIDEO_UPDATE(dedmd16_update) { core_dmd_update_pwm(&dmdlocals.pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, &dmdlocals.pwm_state); return 0; } diff --git a/src/wpc/gts3dmd.c b/src/wpc/gts3dmd.c index 0aaf20b98..3c6c03891 100644 --- a/src/wpc/gts3dmd.c +++ b/src/wpc/gts3dmd.c @@ -19,7 +19,7 @@ extern GTS3_DMDlocals GTS3_dmdlocals[2]; int gts3_dmd128x32(int which, struct mame_bitmap* bitmap, const struct rectangle* cliprect, const struct core_dispLayout* layout) { core_dmd_update_pwm(>S3_dmdlocals[which].pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, >S3_dmdlocals[which].pwm_state); return 0; } diff --git a/src/wpc/sam.c b/src/wpc/sam.c index f68465c97..f6aafbd8e 100644 --- a/src/wpc/sam.c +++ b/src/wpc/sam.c @@ -628,7 +628,7 @@ static MEMORY_READ32_START(sam_readmem) { 0x01100000, 0x011FFFFF, samswitch_r }, //Various Input Signals { 0x02000000, 0x020FFFFF, MRA32_RAM }, //U9 Boot Flash Eprom { 0x02100000, 0x0211FFFF, MRA32_RAM }, //nvram_r }, //U11 NVRAM (128K) - { 0x02400000, 0x024000FF, samio_r }, //I/O Related + { 0x02400000, 0x024000FF, samio_r }, //I/O Related { 0x03000000, 0x030000FF, MRA32_RAM }, //USB Related { 0x04000000, 0x047FFFFF, MRA32_RAM }, //1st 8MB of Flash ROM U44 Mapped here { 0x04800000, 0x04FFFFFF, MRA32_BANK1 }, //Banked Access to Flash ROM U44 (including 1st 8MB ALSO!) @@ -1143,7 +1143,7 @@ static MEMORY_WRITE32_START(sam_writemem) { 0x01080000, 0x0109EFFF, MWA32_RAM }, //U13 RAM - DMD Data for output { 0x0109F000, 0x010FFFFF, samxilinx_w }, //U13 RAM - Sound Data for output { 0x01100000, 0x01FFFFFF, samdmdram_w }, //Various Output Signals - { 0x02100000, 0x0211FFFF, MWA32_RAM, &nvram }, //U11 NVRAM (128K) 0x02100000,0x0211ffff + { 0x02100000, 0x0211FFFF, MWA32_RAM, &nvram }, //U11 NVRAM (128K) 0x02100000,0x0211ffff { 0x02200000, 0x022fffff, sam_io2_w }, //LE versions: more I/O stuff (mostly LED lamps) { 0x02400000, 0x02FFFFFF, sambank_w }, //I/O Related { 0x03000000, 0x030000FF, MWA32_RAM }, //USB Related @@ -1743,10 +1743,10 @@ static void sam_transmit_serial(int usartno, data8_t *data, int size) } -/********************/ -/* VBLANK Section */ -/********************/ -static INTERRUPT_GEN(sam_vblank) { +/******************************/ +/* Interface update Section */ +/******************************/ +static INTERRUPT_GEN(sam_interface_update) { /*------------------------------- / copy local data to interface /--------------------------------*/ @@ -1814,7 +1814,7 @@ static MACHINE_DRIVER_START(sam1) MDRV_CPU_ADD(AT91, SAM_CPUFREQ) // AT91R40008 MDRV_CPU_MEMORY(sam_readmem, sam_writemem) MDRV_CPU_PORTS(sam_readport, sam_writeport) - MDRV_CPU_VBLANK_INT(sam_vblank, 1) + MDRV_CPU_VBLANK_INT(sam_interface_update, 1) MDRV_CPU_PERIODIC_INT(sam_irq, SAM_IRQFREQ) MDRV_CORE_INIT_RESET_STOP(sam, sam1, sam) MDRV_DIPS(8) @@ -1883,7 +1883,7 @@ static PINMAME_VIDEO_UPDATE(samdmd_update) { } } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } @@ -1905,7 +1905,7 @@ static PINMAME_VIDEO_UPDATE(samminidmd_update) { coreGlobals.drawSeg[5*dmd_x + 35*dmd_y + ii] = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } @@ -1925,7 +1925,7 @@ static PINMAME_VIDEO_UPDATE(samminidmd2_update) { coreGlobals.drawSeg[ii] = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } diff --git a/src/wpc/sam_original.c b/src/wpc/sam_original.c index b01cd6673..7dca14c13 100644 --- a/src/wpc/sam_original.c +++ b/src/wpc/sam_original.c @@ -182,7 +182,7 @@ static PINMAME_VIDEO_UPDATE(sam1_dmd32_update) { } } } - video_update_core_dmd(bitmap, cliprect, dotCol, layout); + core_dmd_video_update(bitmap, cliprect, dotCol, layout, NULL); return 0; } @@ -1031,7 +1031,7 @@ static PINMAME_VIDEO_UPDATE(sam1_minidmd_update) { *seg++ = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, dotCol, layout); + core_dmd_video_update(bitmap, cliprect, dotCol, layout, NULL); return 0; } @@ -1071,7 +1071,7 @@ static PINMAME_VIDEO_UPDATE(sam1_minidmd2_update) { | (dotCol[3][ii] ? 4 : 0) | (dotCol[4][ii] ? 2 : 0) | (dotCol[5][ii] ? 1 : 0); } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, dotCol, layout); + core_dmd_video_update(bitmap, cliprect, dotCol, layout, NULL); return 0; } diff --git a/src/wpc/se.c b/src/wpc/se.c index 2d8012e77..b69308ab8 100644 --- a/src/wpc/se.c +++ b/src/wpc/se.c @@ -895,7 +895,7 @@ PINMAME_VIDEO_UPDATE(seminidmd1_update) { *seg++ = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } // MINI DMD Type 1 (Ripley's) (3 x 5x7) @@ -919,7 +919,7 @@ PINMAME_VIDEO_UPDATE(seminidmd1s_update) { *seg++ = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } // MINI DMD Type 2 (Monopoly) (15x7) @@ -943,7 +943,7 @@ PINMAME_VIDEO_UPDATE(seminidmd2_update) { *seg++ = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } // MINI DMD Type 3 (RCT) (21x5) @@ -968,7 +968,7 @@ PINMAME_VIDEO_UPDATE(seminidmd3_update) { *seg++ = bits; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } // 3-Color MINI DMD Type 4 (Simpsons) (14x10) @@ -1000,7 +1000,7 @@ PINMAME_VIDEO_UPDATE(seminidmd4_update) { *seg++ = bits2; } if (!pmoptions.dmd_only) - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } diff --git a/src/wpc/sleic.c b/src/wpc/sleic.c index 3d47f6684..c2d55e3e5 100644 --- a/src/wpc/sleic.c +++ b/src/wpc/sleic.c @@ -318,6 +318,6 @@ PINMAME_VIDEO_UPDATE(sleic_dmd_update) { *line = 0; } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } diff --git a/src/wpc/spinb.c b/src/wpc/spinb.c index 69fae982a..1b8ea45ac 100644 --- a/src/wpc/spinb.c +++ b/src/wpc/spinb.c @@ -1485,7 +1485,7 @@ PINMAME_VIDEO_UPDATE(SPINBdmd_update) { } *line = 0; } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } @@ -1524,7 +1524,7 @@ PINMAME_VIDEO_UPDATE(SPINBdmd_update) { } *line = 0; } - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, NULL); return 0; } diff --git a/src/wpc/wpc.c b/src/wpc/wpc.c index b1a538183..b9a68669e 100644 --- a/src/wpc/wpc.c +++ b/src/wpc/wpc.c @@ -1625,7 +1625,7 @@ static void wpc_dmd_hsync(int param) { int wpcdmd_update(int height, struct mame_bitmap* bitmap, const struct rectangle* cliprect, const struct core_dispLayout* layout) { core_dmd_update_pwm(&dmdlocals.pwm_state); - video_update_core_dmd(bitmap, cliprect, layout); + core_dmd_video_update(bitmap, cliprect, layout, &dmdlocals.pwm_state); return 0; }