/* One-time TDKPIN asset loading and subsequent board redraw. */ #include "tdkpin_game_assets.h" #include "tdkpin_arithmetic.h" #include "tdkpin_message_pump.h" #include "tdkpin_palette.h" #include "tdkpin_render.h" #include "tdkpin_sound.h" enum { DGROUP_INSTANCE = 0x06fe, DGROUP_SCENE_READY = 0x07cb, DGROUP_ASSETS_PENDING = 0x07cc, DGROUP_CURRENT_PLAYER = 0x07d1, DGROUP_BACKGROUND_BITMAP = 0x085b, DGROUP_BACKGROUND_OVERLAY_B = 0x085d, DGROUP_BACKGROUND_OVERLAY_A = 0x085f, DGROUP_DIGIT_BITMAP = 0x0861, DGROUP_CLAW_BITMAP = 0x0863, DGROUP_BOARD_DECORATION_BITMAP = 0x0865, DGROUP_DISPLAYED_STATUS_LEVEL = 0x086b, DGROUP_SPRITE_BITMAPS = 0x430b, DGROUP_STATUS_BITMAPS_BASE = 0x4319, DGROUP_ITEM_BITMAPS_BASE = 0x4321, DGROUP_PALETTE = 0x444e, DGROUP_PLAYER_SCORE_INDEX_BASE = 0x097e, DGROUP_SCORE_FACTOR_VALUES_BASE = 0x098e, DGROUP_SCORE_FACTORS_BASE = 0x09a1, WINDOW_HANDLE_OFFSET = 4, WINDOW_MASK_BITMAP_OFFSET = 0x52, WINDOW_IMAGE_BITMAP_OFFSET = 0x54, WINDOW_TRANSIENT_1_OFFSET = 0x4d, WINDOW_TRANSIENT_2_OFFSET = 0x4f, WINDOW_X_VALUE_OFFSET = 0x0ba2, WINDOW_Y_VALUE_OFFSET = 0x0ba6, WINDOW_ALREADY_REDRAWN_OFFSET = 0x0bd8, WINDOW_REDRAW_BUSY_OFFSET = 0x0bd9, WINDOW_HIDE_OBJECT_OFFSET = 0x0bde, WIN16_SRCCOPY = 0x00cc0020, WIN16_MASK_ROP = 0x00c60088, WIN16_IMAGE_ROP = 0x00ee0086, WIN16_IDC_ARROW = 0x7f00, }; static HBITMAP16 load_dat(uint16_t resource_id) { return tdkpin_load_bitmap_resource( win16_make_far_pointer(0, resource_id), g_win16_instance); } static void write_dgroup_handle(uint16_t offset, HBITMAP16 bitmap) { win16_write_u16(win16_dgroup_pointer(offset), 0, bitmap); } static void draw_loading_stage( Win16FarPtr progress_frame, uint8_t stage) { tdkpin_draw_loading_stage(progress_frame, stage); } /* 1000:53c5..5618 — one-time exact resource/handle publication sequence. */ static void load_all_assets( HDC16 destination, Win16FarPtr progress_frame) { HBITMAP16 splash = load_dat(995); HDC16 splash_dc = CreateCompatibleDC16(destination); HGDIOBJ16 previous_splash = SelectObject16(splash_dc, splash); (void)BitBlt16( destination, 0, 0, 640, 480, splash_dc, 0, 0, WIN16_SRCCOPY); (void)SelectObject16(splash_dc, previous_splash); (void)DeleteObject16(splash_dc); (void)DeleteObject16(splash); HBITMAP16 loading_bitmap = load_dat(994); win16_write_u16(progress_frame, 0xfffe, loading_bitmap); draw_loading_stage(progress_frame, 2); tdkpin_initialize_sounds(); draw_loading_stage(progress_frame, 3); draw_loading_stage(progress_frame, 4); write_dgroup_handle(DGROUP_BACKGROUND_OVERLAY_B, load_dat(998)); draw_loading_stage(progress_frame, 5); write_dgroup_handle(DGROUP_BACKGROUND_BITMAP, load_dat(998)); draw_loading_stage(progress_frame, 6); write_dgroup_handle( DGROUP_DIGIT_BITMAP, LoadBitmap16(g_win16_instance, win16_make_far_pointer(0, 500))); for (uint16_t index = 0; index < 8; index++) { draw_loading_stage(progress_frame, (uint8_t)(index + 7)); write_dgroup_handle( (uint16_t)(DGROUP_SPRITE_BITMAPS + index * 2), load_dat((uint16_t)(400 + index))); } for (uint16_t index = 1; index <= 4; index++) { draw_loading_stage(progress_frame, (uint8_t)(index + 14)); write_dgroup_handle( (uint16_t)(DGROUP_STATUS_BITMAPS_BASE + index * 2), load_dat((uint16_t)(700 + index))); } for (uint16_t index = 1; index <= 9; index++) { draw_loading_stage(progress_frame, (uint8_t)(index + 18)); write_dgroup_handle( (uint16_t)(DGROUP_ITEM_BITMAPS_BASE + index * 2), load_dat((uint16_t)(800 + index))); } (void)loading_bitmap; } static bool positive_i32_at(Win16FarPtr object, uint16_t offset) { return (int32_t)win16_read_u32(win16_far_add_offset(object, offset)) > 0; } /* 1000:5619..58e2 — transient board redraw and score/status publication. */ static void redraw_scene( Win16FarPtr window, HDC16 destination, HPALETTE16 previous_palette) { if (win16_read_u8( win16_far_add_offset(window, WINDOW_ALREADY_REDRAWN_OFFSET)) != 0) { return; } win16_write_u8( win16_far_add_offset(window, WINDOW_REDRAW_BUSY_OFFSET), 1); HDC16 background_dc = CreateCompatibleDC16(destination); HDC16 surface_dc = CreateCompatibleDC16(destination); RECT16 rectangle; (void)GetClientRect16( win16_read_u16(win16_far_add_offset(window, WINDOW_HANDLE_OFFSET)), win16_stack_pointer(&rectangle)); HBITMAP16 surface = CreateCompatibleBitmap16( destination, (INT16)(rectangle.right + 1), (INT16)(rectangle.bottom + 1)); HGDIOBJ16 old_background = SelectObject16( background_dc, win16_read_u16(win16_dgroup_pointer(DGROUP_BACKGROUND_BITMAP))); HGDIOBJ16 old_surface = SelectObject16(surface_dc, surface); (void)BitBlt16( surface_dc, 0, 0, rectangle.right, rectangle.bottom, background_dc, 0, 0, WIN16_SRCCOPY); (void)BitBlt16( background_dc, 0, 0, rectangle.right, rectangle.bottom, surface_dc, 0, 0, WIN16_SRCCOPY); (void)BitBlt16( destination, 0, 0, rectangle.right, rectangle.bottom, surface_dc, 0, 0, WIN16_SRCCOPY); (void)SelectObject16(surface_dc, old_surface); (void)DeleteObject16(surface); (void)DeleteDC16(surface_dc); (void)SelectObject16(background_dc, old_background); if (positive_i32_at(window, WINDOW_X_VALUE_OFFSET) && positive_i32_at(window, WINDOW_Y_VALUE_OFFSET) && win16_read_u8( win16_far_add_offset(window, WINDOW_HIDE_OBJECT_OFFSET)) == 0) { uint16_t x = win16_read_u16( win16_far_add_offset(window, WINDOW_X_VALUE_OFFSET)); uint16_t y = win16_read_u16( win16_far_add_offset(window, WINDOW_Y_VALUE_OFFSET)); uint16_t width = (uint16_t)( win16_read_u32(win16_far_add_offset(window, WINDOW_X_VALUE_OFFSET)) + 19); uint16_t height = (uint16_t)( win16_read_u32(win16_far_add_offset(window, WINDOW_Y_VALUE_OFFSET)) + 19); HGDIOBJ16 previous = SelectObject16( background_dc, win16_read_u16(win16_far_add_offset( window, WINDOW_IMAGE_BITMAP_OFFSET))); (void)BitBlt16( destination, (INT16)x, (INT16)y, (INT16)width, (INT16)height, background_dc, 0, 0, WIN16_MASK_ROP); (void)SelectObject16( background_dc, win16_read_u16(win16_far_add_offset( window, WINDOW_MASK_BITMAP_OFFSET))); (void)BitBlt16( destination, (INT16)x, (INT16)y, (INT16)width, (INT16)height, background_dc, 0, 0, WIN16_IMAGE_ROP); (void)SelectObject16(background_dc, previous); } (void)DeleteDC16(background_dc); win16_write_u16(window, WINDOW_TRANSIENT_1_OFFSET, 0); win16_write_u16(window, WINDOW_TRANSIENT_2_OFFSET, 0); win16_write_u8( win16_far_add_offset(window, WINDOW_REDRAW_BUSY_OFFSET), 0); (void)SelectPalette16(destination, previous_palette, 0); HCURSOR16 arrow = LoadCursor16( 0, win16_make_far_pointer(0, WIN16_IDC_ARROW)); (void)SetCursor16(arrow); (void)GetClientRect16( win16_read_u16(win16_far_add_offset(window, WINDOW_HANDLE_OFFSET)), win16_stack_pointer(&rectangle)); HWND16 handle = win16_read_u16(win16_far_add_offset(window, WINDOW_HANDLE_OFFSET)); HDC16 window_dc = GetDC16(handle); uint8_t current_player = win16_read_u8( win16_dgroup_pointer(DGROUP_CURRENT_PLAYER)); uint8_t factor = win16_read_u8(win16_dgroup_pointer( (uint16_t)(DGROUP_SCORE_FACTORS_BASE + current_player))); int32_t factor_value = (int32_t)win16_read_u32(win16_dgroup_pointer( (uint16_t)(DGROUP_SCORE_FACTOR_VALUES_BASE + current_player * 4))); tdkpin_draw_score( window_dc, borland_multiply_i32(factor, factor_value)); for (uint16_t player = 1; player <= 4; player++) { int32_t score = (int32_t)win16_read_u32(win16_dgroup_pointer( (uint16_t)(DGROUP_PLAYER_SCORE_INDEX_BASE + player * 4))); if (score > 0) { tdkpin_draw_score(window_dc, player); } } win16_write_u16( win16_dgroup_pointer(DGROUP_DISPLAYED_STATUS_LEVEL), 0, 99); tdkpin_update_status_display(current_player, window_dc); (void)ReleaseDC16(handle, window_dc); win16_write_u8(win16_dgroup_pointer(DGROUP_SCENE_READY), 1); } /* * 1000:5390 — exact public entry. Two middle words are ABI-preserved but unused. */ void tdkpin_initialize_assets_and_redraw( Win16FarPtr window, uint16_t ignored_1, uint16_t ignored_2, HDC16 destination) { (void)ignored_1; (void)ignored_2; HPALETTE16 palette = win16_read_u16(win16_dgroup_pointer(DGROUP_PALETTE)); HPALETTE16 previous_palette = SelectPalette16(destination, palette, 0); (void)UnrealizeObject16(palette); (void)RealizePalette16(destination); tdkpin_drain_messages_except_input(); uint8_t progress_storage[64] = {0}; Win16FarPtr progress_frame = win16_stack_pointer(progress_storage + 24); win16_write_u16(progress_frame, 0x0e, destination); if (win16_read_u8( win16_dgroup_pointer(DGROUP_ASSETS_PENDING)) != 0) { load_all_assets(destination, progress_frame); HBITMAP16 loading_bitmap = win16_read_u16(win16_far_add_offset(progress_frame, 0xfffe)); draw_loading_stage(progress_frame, 28); win16_write_u16( window, WINDOW_IMAGE_BITMAP_OFFSET, LoadBitmap16(g_win16_instance, win16_make_far_pointer(0, 102))); draw_loading_stage(progress_frame, 29); write_dgroup_handle(DGROUP_CLAW_BITMAP, load_dat(900)); draw_loading_stage(progress_frame, 30); win16_write_u16( window, WINDOW_MASK_BITMAP_OFFSET, LoadBitmap16(g_win16_instance, win16_make_far_pointer(0, 101))); draw_loading_stage(progress_frame, 31); write_dgroup_handle(DGROUP_BACKGROUND_OVERLAY_A, load_dat(997)); draw_loading_stage(progress_frame, 32); write_dgroup_handle(DGROUP_BOARD_DECORATION_BITMAP, load_dat(901)); draw_loading_stage(progress_frame, 33); write_dgroup_handle(0x0859, load_dat(600)); draw_loading_stage(progress_frame, 34); win16_write_u8(win16_dgroup_pointer(DGROUP_ASSETS_PENDING), 0); draw_loading_stage(progress_frame, 35); (void)DeleteObject16(loading_bitmap); (void)SelectPalette16(destination, previous_palette, 0); HCURSOR16 arrow = LoadCursor16( 0, win16_make_far_pointer(0, WIN16_IDC_ARROW)); (void)SetCursor16(arrow); } redraw_scene(window, destination, previous_palette); }