/* Low-level TDKPIN background/overlay bitmap blits. */ #include "tdkpin_render.h" #include "tdkpin_arithmetic.h" enum { DGROUP_BACKGROUND_BITMAP = 0x085b, DGROUP_OVERLAY_BITMAP_B = 0x085d, DGROUP_OVERLAY_BITMAP_A = 0x085f, WIN16_SRCCOPY = 0x00cc0020, WIN16_SRCAND = 0x008800c6, DGROUP_DIGIT_BITMAP = 0x0861, DGROUP_PLAYER_SCORE_INDEX_BASE = 0x097e, }; static HBITMAP16 dgroup_bitmap(uint16_t offset) { return win16_read_u16(win16_dgroup_pointer(offset)); } /* 1008:07b6 — copy a supplied bitmap's origin into the background bitmap. */ void tdkpin_blit_bitmap_to_background( HBITMAP16 bitmap, INT16 height, INT16 width, INT16 y, INT16 x, HDC16 reference_dc) { HDC16 background_dc = CreateCompatibleDC16(reference_dc); HDC16 bitmap_dc = CreateCompatibleDC16(reference_dc); HGDIOBJ16 old_background = SelectObject16( background_dc, dgroup_bitmap(DGROUP_BACKGROUND_BITMAP)); HGDIOBJ16 old_bitmap = SelectObject16(bitmap_dc, bitmap); (void)BitBlt16( background_dc, x, y, width, height, bitmap_dc, 0, 0, WIN16_SRCCOPY); (void)SelectObject16(bitmap_dc, old_bitmap); (void)SelectObject16(background_dc, old_background); (void)DeleteDC16(bitmap_dc); (void)DeleteDC16(background_dc); } /* 1008:0837 — restore a rectangle from overlay bitmap 085f. */ void tdkpin_restore_background_region_a( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 reference_dc) { HDC16 background_dc = CreateCompatibleDC16(reference_dc); HDC16 overlay_dc = CreateCompatibleDC16(reference_dc); HGDIOBJ16 old_background = SelectObject16( background_dc, dgroup_bitmap(DGROUP_BACKGROUND_BITMAP)); HGDIOBJ16 old_overlay = SelectObject16( overlay_dc, dgroup_bitmap(DGROUP_OVERLAY_BITMAP_A)); (void)BitBlt16( background_dc, x, y, width, height, overlay_dc, x, y, WIN16_SRCCOPY); (void)SelectObject16(overlay_dc, old_overlay); (void)SelectObject16(background_dc, old_background); (void)DeleteDC16(overlay_dc); (void)DeleteDC16(background_dc); } /* 1008:08bb — byte-identical restore using overlay bitmap 085d. */ void tdkpin_restore_background_region_b( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 reference_dc) { HDC16 background_dc = CreateCompatibleDC16(reference_dc); HDC16 overlay_dc = CreateCompatibleDC16(reference_dc); HGDIOBJ16 old_background = SelectObject16( background_dc, dgroup_bitmap(DGROUP_BACKGROUND_BITMAP)); HGDIOBJ16 old_overlay = SelectObject16( overlay_dc, dgroup_bitmap(DGROUP_OVERLAY_BITMAP_B)); (void)BitBlt16( background_dc, x, y, width, height, overlay_dc, x, y, WIN16_SRCCOPY); (void)SelectObject16(overlay_dc, old_overlay); (void)SelectObject16(background_dc, old_background); (void)DeleteDC16(overlay_dc); (void)DeleteDC16(background_dc); } /* 1008:093f — copy one background rectangle to the destination DC. */ void tdkpin_present_background_region( INT16 height, INT16 width, INT16 y, INT16 x, HDC16 destination) { HDC16 background_dc = CreateCompatibleDC16(destination); HGDIOBJ16 old_background = SelectObject16( background_dc, dgroup_bitmap(DGROUP_BACKGROUND_BITMAP)); (void)BitBlt16( destination, x, y, width, height, background_dc, x, y, WIN16_SRCCOPY); (void)SelectObject16(background_dc, old_background); (void)DeleteDC16(background_dc); } static int16_t score_destination_x(uint16_t player_or_value) { switch (player_or_value) { case 1: return 0x129 - 20; case 2: return 0x155 - 20; case 3: return 0x181 - 20; case 4: return 0x1ad - 20; default: return 0x0fd - 20; } } static int32_t resolve_score_value(int32_t value_or_player) { if (value_or_player < 1 || value_or_player > 4) { return value_or_player; } uint16_t offset = (uint16_t)( DGROUP_PLAYER_SCORE_INDEX_BASE + (uint16_t)value_or_player * 4); return (int32_t)win16_read_u32(win16_dgroup_pointer(offset)); } /* * 1008:0996 — compose an eight-place decimal score into a 40x150 temporary * bitmap. Values 1..4 select the corresponding one-based player score; all * other int32 values render directly. Leading zeroes are suppressed except the * least-significant position, and digit sprites are combined with SRCAND. */ void tdkpin_draw_score(HDC16 destination, int32_t value_or_player) { HDC16 background_dc = CreateCompatibleDC16(destination); HDC16 score_dc = CreateCompatibleDC16(destination); HBITMAP16 score_bitmap = CreateCompatibleBitmap16(destination, 40, 150); int16_t destination_x = score_destination_x((uint16_t)value_or_player); int32_t value = resolve_score_value(value_or_player); HGDIOBJ16 old_background = SelectObject16( background_dc, dgroup_bitmap(DGROUP_BACKGROUND_BITMAP)); HGDIOBJ16 old_score = SelectObject16(score_dc, score_bitmap); (void)BitBlt16( score_dc, 0, 0, 40, 130, background_dc, destination_x, 478, WIN16_SRCCOPY); for (uint8_t position = 0; position < 8; position++) { BorlandDivI32Result digit_division = borland_divide_i32(value, 10); uint8_t digit = (uint8_t)digit_division.remainder; BorlandDivI32Result quotient_division = borland_divide_i32(value, 10); value = quotient_division.quotient; if (digit != 0 || value > 0 || position == 0) { (void)SelectObject16( background_dc, dgroup_bitmap(DGROUP_DIGIT_BITMAP)); (void)BitBlt16( score_dc, 0, (INT16)((7 - position) * 16), 28, 16, background_dc, (INT16)((uint16_t)digit << 4), 0, WIN16_SRCAND); } } (void)BitBlt16( destination, destination_x, 478, 40, 130, score_dc, 0, 0, WIN16_SRCCOPY); (void)SelectObject16(background_dc, old_background); (void)SelectObject16(score_dc, old_score); (void)DeleteObject16(score_bitmap); (void)DeleteDC16(background_dc); (void)DeleteDC16(score_dc); }