Sunday, April 19, 2009

Understanding WPC DMD Emulation in PinMAME

Bitmap Generation (updateDisplay and wpcdmd_update)

The updateDisplay() function in core.c calls wpcdmd_update() in wpc.c to create a color bitmap based on the DMD frame data stored in dmdlocals.DMDFrames[].
static void updateDisplay(struct mame_bitmap *bitmap, const struct rectangle
*cliprect, const struct core_dispLayout *layout, int *pos)
*bitmap is a pointer to the display bitmap structure and contains the following elements:
width = 320, height = 256, depth = 16, **line,, *base, rowpixels = 352, rowbytes = 704, plot = pp_16, read = rp_16, plot_box = pb_16

*cliprect is a pointer to the rectangle structure and contains the following elements:
min_x = 0, max_x = 255, min_y = 0, max_y = 255

*layout is a pointer to the global structure wpc_dispDMD with the parameters:
top =0, left = 0, start = 32, length = 128, type = 14, *ptr = wpcdmd_update

*pos is a pointer

When emulating a WPC rom, this function seems to mainly just call the layout->ptr function


wpcdmd_update(bitmap, cliprect, layout)
defined in "wpc.c" by


PINMAME_VIDEO_UPDATE(wpcdmd_update)

where PINMAME_VIDEO_UPDATE is defined in "core.h" as

#define PINMAME_VIDEO_UPDATE(name) int (name)(struct mame_bitmap *bitmap, const struct rectangle *cliprect, const struct core_dispLayout *layout)
The wpcdmd_update() function creates a temporary (64+2)x(256+2) byte array called dotCol. It fills the array with pixel intensity data based on the last three frames of DMD data and then calls the function video_update_core_dmd().

To generate the pixel data, an iterative loop is called to fill the dotCol array and a pointer *line is set to point to the start of a row of data. Row 0 is not written and line initially points to the first byte in Row 1.

The data is read in parallel from three different DMD frame buffers 16 bytes at a time. Each byte is used to generate 8 different pixel values in dotCol. Data is generated by reading three bytes (one from each DMD frame buffer). The first pixel value is generated by summing the least significant bits all three bytes to create a 2-bit value. The next pixel is generated by summing the second least significant bits, and so on, until eight pixel values are created.

After the frame buffers are read 16 times, 128 pixels of data will be created to complete a row in dotCol. This process is repeated for 32 iterations to complete the image. The image is then passed with a function call to


video_update_core_dmd(bitmap, cliprect, dotCol, layout);
This function now copies the image data from temporary buffer dotCol to bitmap. Before copying, row 0 and row 33 of dotCol are filled with 0's using the C++ memset() function. Also as each line is drawn dotCol[row][128] is set to zero. For each of the 128 pixel values in the line, a pixel in the corresponding row of the bitmap is assigned a color table value stored in dmdColor[].
By default, antialiasing is applied during the bitmap generation. The actual bitmap is twice as large as the DMD display. The DMD pixel values are placed at even row and column locations and the color is indexed using the dotCol value for that pixel. Odd row and column locations in the bitmap are colored using an antialias colormap. The colormap index for the antialias pixels are indexed by summing the dotCol values of the neigboring pixels.

Organization of the Color Palette

The color palette is initialized in "core.c".

1: DMD Off (20% DMD On)
2: DMD 33% (33% DMD On)
3: DMD 66% (67% DMD On)
4: DMD On
5-12: 8 Lamp On Colors (Black, White, Green, Red, Orange, Yellow, LBlue, LPurple)
13-20: 8 Lamp Off Colors (25% of Lamp On)
21-26: 6 AntiAlias Shades (Black - (dmd_antialias)% DMD On)
28: AntiAlias On 1 (72% DMD On)
29: AntiAlias On 2 (33% DMD On)
30: AntiAlias Off 1 (72% DMD Off)
31: AntiAlias Off 2 (33% DMD Off)
32-47: 16 AntiAlias Shades (AA Off 2 - AA On 2)
48-63: 16 AntiAlias Shades (AA Off1 - AA On 1)
64-79: 16 AntiAlias Shades (DMD Off - DMD On)




No comments:

Post a Comment