/* TDKPIN's small ObjectWindows/MMTIMER system-timer class. */ #include "tdkpin_system_timer.h" enum { SYSTEM_TIMER_VMT_OFFSET = 0, SYSTEM_TIMER_ID_OFFSET = 2, SYSTEM_TIMER_RECIPIENT_OFFSET = 4, }; /* * 1008:295c — create the underlying MMTIMER timer. * MOV AL,[BP+0a] deliberately preserves AH returned by the stack checker, so * the imported word-valued one_shot argument is not merely zero or one. */ uint16_t tdkpin_system_timer_start( Win16FarPtr object, uint8_t one_shot, uint16_t resolution_ms, uint16_t delay_ms) { uint16_t stack_result = borland_check_stack(2); uint16_t one_shot_word = (uint16_t)((stack_result & 0xff00u) | one_shot); HWND16 recipient = win16_read_u16(win16_far_add_offset( object, SYSTEM_TIMER_RECIPIENT_OFFSET)); return SystemTimerMake16( recipient, delay_ms, resolution_ms, one_shot_word); } /* 1008:2932 — cancel a live multimedia timer, then clear its id. */ void tdkpin_system_timer_stop(Win16FarPtr object) { (void)borland_check_stack(0); uint16_t timer_id = win16_read_u16(win16_far_add_offset(object, SYSTEM_TIMER_ID_OFFSET)); if (timer_id != 0) { (void)TimeKillEvent16(timer_id); } win16_write_u16(object, SYSTEM_TIMER_ID_OFFSET, 0); } /* * 1008:28a3 — construct the six-byte timer object and start its timer. * A zero timer id invokes the Borland constructor-failure cleanup. That frees * newly allocated instances but leaves caller-owned instances in place because * 1020:03ef cleared their hidden VMT ownership argument. */ Win16FarPtr tdkpin_system_timer_construct( Win16FarPtr object, uint16_t vmt, uint8_t one_shot, uint16_t resolution_ms, uint16_t delay_ms, HWND16 recipient) { (void)borland_check_stack(0); BorlandObjectCallFrame frame = {object, vmt}; if (!borland_enter_object_constructor( &frame, SYSTEM_TIMER_VMT_OFFSET)) { return frame.object; } frame.object = borland_default_object_constructor(frame.object, 0); win16_write_u16(frame.object, SYSTEM_TIMER_ID_OFFSET, 0); win16_write_u16(frame.object, SYSTEM_TIMER_RECIPIENT_OFFSET, recipient); uint16_t timer_id = tdkpin_system_timer_start( frame.object, one_shot, resolution_ms, delay_ms); win16_write_u16(frame.object, SYSTEM_TIMER_ID_OFFSET, timer_id); if (timer_id == 0) { borland_finish_object_destructor( &frame, SYSTEM_TIMER_VMT_OFFSET); } return frame.object; } /* 1008:2906 — stop the timer, run the root destructor, and release if owned. */ void tdkpin_system_timer_destruct(Win16FarPtr object, uint16_t vmt) { (void)borland_check_stack(0); BorlandObjectCallFrame frame = {object, vmt}; tdkpin_system_timer_stop(frame.object); borland_default_object_destructor(frame.object, 0); borland_finish_object_destructor(&frame, SYSTEM_TIMER_VMT_OFFSET); }