/* Five-target rotation and 91x90 panel compositor from TDKPIN Code1. */ #include "tdkpin_mechanism_render.h" #include "tdkpin_sound.h" typedef struct { INT16 x; INT16 y; } TargetPoint; static const TargetPoint g_target_positions[6][5] = { {{9, 41}, {23, 11}, {56, 14}, {63, 47}, {35, 63}}, {{11, 45}, {18, 13}, {52, 11}, {63, 42}, {39, 64}}, {{13, 50}, {15, 17}, {46, 9}, {64, 37}, {44, 62}}, {{17, 55}, {11, 23}, {39, 7}, {64, 30}, {50, 59}}, {{21, 60}, {9, 28}, {35, 7}, {62, 25}, {54, 56}}, {{8, 35}, {26, 8}, {59, 18}, {59, 50}, {27, 61}}, }; static Win16FarPtr caller_receiver(uint16_t caller_bp) { uint16_t offset = win16_read_stack_u16((uint16_t)(caller_bp + 6)); uint16_t selector = win16_read_stack_u16((uint16_t)(caller_bp + 8)); return win16_make_far_pointer(selector, offset); } static void rotate_target_state(uint16_t caller_bp, Win16FarPtr receiver) { static const uint16_t record_words[5] = { 0x3371, 0x33c4, 0x3417, 0x346a, 0x34bd}; uint16_t first_word = win16_read_u16( win16_dgroup_pointer(record_words[0])); for (uint16_t index = 0; index < 4; index++) { win16_write_u16( win16_dgroup_pointer(record_words[index]), 0, win16_read_u16(win16_dgroup_pointer(record_words[index + 1]))); } win16_write_u16( win16_dgroup_pointer(record_words[4]), 0, first_word); uint16_t row = (uint16_t)( 0x0476 + (uint16_t)g_current_player * 0x14u); uint8_t first_byte = win16_read_u8( win16_far_add_offset(receiver, row)); for (uint16_t index = 0; index < 4; index++) { win16_write_u8( win16_far_add_offset(receiver, (uint16_t)(row + index)), win16_read_u8(win16_far_add_offset( receiver, (uint16_t)(row + index + 1)))); } win16_write_u8( win16_far_add_offset(receiver, (uint16_t)(row + 4)), first_byte); for (uint16_t item = 15; item <= 19; item++) { tdkpin_refresh_player_item(caller_bp, item); } } /* 1000:6f27 -- render and optionally rotate the five-target panel. */ void tdkpin_rotate_and_draw_targets(uint16_t caller_bp) { Win16FarPtr receiver = caller_receiver(caller_bp); HWND16 window = win16_read_u16(win16_far_add_offset(receiver, 4)); HDC16 dc = GetDC16(window); HDC16 source_dc = CreateCompatibleDC16(dc); HDC16 panel_dc = CreateCompatibleDC16(dc); HBITMAP16 panel_bitmap = CreateCompatibleBitmap16(dc, 91, 90); HGDIOBJ16 old_source = SelectObject16( source_dc, win16_read_u16(win16_dgroup_pointer(0x0859))); HGDIOBJ16 old_panel = SelectObject16(panel_dc, panel_bitmap); int32_t state = (int32_t)win16_read_u32(win16_dgroup_pointer(0x0855)); if (state < 6) { INT16 source_x = (INT16)(uint16_t)( ((uint32_t)state - 1u) * 91u); (void)BitBlt16( panel_dc, 0, 0, 91, 90, source_dc, source_x, 0, 0x00cc0020u); } else { (void)SelectObject16( source_dc, win16_read_u16(win16_dgroup_pointer(0x085d))); (void)BitBlt16( panel_dc, 0, 0, 91, 90, source_dc, 79, 33, 0x00cc0020u); (void)SelectObject16( source_dc, win16_read_u16(win16_dgroup_pointer(0x0859))); rotate_target_state(caller_bp, receiver); } if (state == 1) { tdkpin_play_sound_if_not_tilted(11); } if (state >= 1 && state <= 6) { static const uint16_t target_words[5] = { 0x3371, 0x33c4, 0x3417, 0x346a, 0x34bd}; const TargetPoint *positions = g_target_positions[state - 1]; for (uint16_t index = 0; index < 5; index++) { if (win16_read_u16( win16_dgroup_pointer(target_words[index])) != 0) { (void)BitBlt16( panel_dc, positions[index].x, positions[index].y, 17, 17, source_dc, 455, 17, 0x008800c6u); (void)BitBlt16( panel_dc, positions[index].x, positions[index].y, 17, 17, source_dc, 455, 0, 0x00ee0086u); } } } (void)BitBlt16( dc, 79, 33, 91, 90, panel_dc, 0, 0, 0x00cc0020u); (void)SelectObject16(source_dc, old_source); (void)SelectObject16(panel_dc, old_panel); (void)DeleteObject16(panel_bitmap); (void)DeleteDC16(panel_dc); (void)DeleteDC16(source_dc); (void)ReleaseDC16(window, dc); }