gfx/time: vsync через polling бита кадра, sleep/delayms без halt-подсчёта
gfx_wait_vsync() и sleep() раньше предполагали, что КАЖДОЕ прерывание на векторе 0xFF — кадровый тик; с CBL/клавиатурой на том же векторе это уже не так. gfx_wait_vsync(): вместо halt — polling бита 5 порта 0xFE (реальная позиция луча, см. MAME kbd_fe_r), доступного пока включён CBL bit7 порта 0x004E. Разделяемое владение портом с CBL через _cbl_port_ref/unref (тот же ref-counting паттерн, что у IM2-таблицы) — cbl_close() возвращает "немой" режим вместо полного выключения, если gfx ещё держит ссылку. Fallback на halt при таймауте. sleep()/delayms(): калиброванный busy-wait по духу delayms.asm вместо подсчёта halt-пробуждений. Калибровка одна на кадр (не на секунду — не переполняет uint16_t и не требует умножения/32-бит арифметики), общий движок libc/time/_sleep_calib.c для обеих функций. Fallback на старое поведение при EBUSY (фрейм-хук занят другим irq_install()). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,15 @@
|
||||
* был бы избыточен. _cbl_fill — callback приложения; _cbl_silence —
|
||||
* буфер тишины, malloc'ится в cbl_open() ТОЛЬКО при
|
||||
* CBL_UNDERRUN_SILENCE (иначе NULL).
|
||||
*
|
||||
* _cbl_port_ref/_cbl_port_unref (_cbl_port.c) — общий счётчик желающих
|
||||
* держать bit7 порта 0x004E включённым НЕЗАВИСИМО от полноценной CBL-
|
||||
* сессии. Нужно gfx_wait_vsync() (см. libc/gfx/gfx_wait_vsync.c): бит
|
||||
* 5 порта 0xFE отражает позицию луча (см. MAME sprinter.cpp kbd_fe_r),
|
||||
* но доступен ТОЛЬКО пока включён cbl_mode(). Если реальный CBL уже
|
||||
* открыт — портом владеет он, ref/unref его не трогают; иначе включают
|
||||
* bit7 "немым" кодом частоты _CBL_VSYNC_FREQ (таймер CBL не заводится
|
||||
* — divs[2]=0 в MAME — ни звука, ни прерываний, только синхро-бит).
|
||||
*/
|
||||
#ifndef _CBL_INTERNAL_H
|
||||
#define _CBL_INTERNAL_H
|
||||
@@ -33,6 +42,7 @@
|
||||
#define _CBL_CTRL_PORT 0x004E
|
||||
#define _CBL_DATA_PORT 0x4F
|
||||
#define _CBL_ACCEL_PAGE 0xFD /* спец-страница EMM: запись на W3@0xC000 идёт в CBL */
|
||||
#define _CBL_VSYNC_FREQ 0x02 /* "немой" код частоты — divs[2]=0 в MAME, таймер не идёт */
|
||||
|
||||
extern uint16_t _cbl_block; /* размер блока: 128 или 256 (по формату) */
|
||||
extern uint16_t _cbl_reqs; /* блоков-запросов обслужено */
|
||||
@@ -40,6 +50,7 @@ extern uint16_t _cbl_undr; /* из них недолив (fill в
|
||||
extern cbl_fill_fn _cbl_fill; /* callback приложения, может быть NULL */
|
||||
extern uint8_t _cbl_underrun_mode; /* CBL_UNDERRUN_* */
|
||||
extern uint8_t *_cbl_silence; /* буфер тишины или NULL */
|
||||
extern uint8_t _cbl_port_refs; /* держатели bit7 помимо реальной CBL-сессии */
|
||||
|
||||
/* Запись в 16-битный порт управления 0x004E. */
|
||||
void _cbl_ctrl(uint8_t v);
|
||||
@@ -49,4 +60,12 @@ void _cbl_ctrl(uint8_t v);
|
||||
void _cbl_pump_otir(void);
|
||||
void _cbl_pump_accel(void);
|
||||
|
||||
/* Разделяемое владение портом 0x004E (см. описание выше).
|
||||
* _cbl_port_sync пересчитывает нужное значение порта из текущего
|
||||
* состояния (реальная сессия? держатели?) и пишет его — вызывается
|
||||
* из ref/unref, а также из cbl_close() после снятия _irq_cbl_hook. */
|
||||
void _cbl_port_ref(void);
|
||||
void _cbl_port_unref(void);
|
||||
void _cbl_port_sync(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user