libbgi: FPS-делитель gfx_set_fps_div(n) поверх цепочки кадровых IRQ
Логический кадр = ровно n кадровых интервалов (1=50/2=25/3=~16.7 fps); при переполнении слота — выравнивание на ближайший фронт (без дрейфа фазы, в отличие от наивного «жди n фронтов»). Механика: фоновый счётчик _gfx_frame_tick инкрементит _gfx_frame_isr, поставленный в СВОЙ слот цепи (irq_chain_add); gfx_set_fps_div(1) снимает только этот слот (irq_chain_remove), не трогая хендлер приложения. gfx_wait_vsync: ветка n>=2 (счётчик + halt) перед лучевым поллингом; поллинг вынесен в static gfx_wait_vsync_beam (функция с хвостовым __asm не должна иметь переходов через asm — SDCC не эмитит эпилог-метку; ранний return делителя в чистом-C gfx_wait_vsync). Файлы: common/_gfx_fps_state.c (данные), _gfx_frame_isr.c (ISR), gfx_set_fps_div.c (сеттер, единственная ссылка на irq-механику → DCE). Работает tiny/big/huge (цепочка all-modes); small для мелких программ = EINVAL. Проверено MAME (tests/fpsdiv): n=1/2/3 → 20/40/60 кадров на 20 wait'ов (drift=0); n=2 с рендер-заглушкой ~1 кадр → период держится 2 (поглощение перерасхода, наивный путь дал бы ~60); huge идентично; small = EINVAL graceful. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -313,4 +313,17 @@ void _bgi_poly_edge(int x0, int y0, int x1, int y1);
|
||||
extern void _cbl_port_ref(void);
|
||||
extern void _cbl_port_unref(void);
|
||||
|
||||
/* ---- FPS-делитель (frame pacing) --------------------------------- *
|
||||
* Фоновый счётчик кадров через цепочку кадровых IRQ (libc/irq). Данные
|
||||
* в common/_gfx_fps_state.c; при _gfx_fps_div<=1 путь не активен и
|
||||
* gfx_wait_vsync остаётся лучевым поллингом. Механику irq_chain_add
|
||||
* дёргает ТОЛЬКО gfx_set_fps_div.c (DCE). */
|
||||
extern uint8_t _gfx_fps_div; /* 0/1 = старый путь; >=2 — делитель */
|
||||
extern volatile uint8_t _gfx_frame_tick; /* инкрементит _gfx_frame_isr */
|
||||
extern uint8_t _gfx_fps_last; /* тик прошлого выхода из wait */
|
||||
|
||||
/* Кадровый ISR: чистый инкремент _gfx_frame_tick (правила irq.h —
|
||||
* никаких ESTEX/gfx/банков). */
|
||||
void _gfx_frame_isr(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user