/* * pop_timer.c — единый владелец глобального таймера (FG4, банк 9). * * SDLPoP хранит rem_min/rem_tick и уменьшает rem_tick на каждом логическом * игровом кадре. Здесь та же схема: после нуля tick возвращается к 719, * поэтому 720 тиков образуют минуту. Настройки, экранные сообщения и * переход TIME_EXPIRED остаются снаружи: это делает ядро таймера чистым и * не привязывает его к ещё не реализованным title/cutscene режимам. */ #include #include "pop_timer.h" uint8_t pop_timer_minutes; uint16_t pop_timer_ticks; uint8_t pop_show_time; void pop_timer_new_game(void) __banked { pop_timer_minutes = POP_TIMER_START_MINUTES; pop_timer_ticks = POP_TIMER_START_TICKS; pop_show_time = 0; } uint8_t pop_timer_tick(uint8_t enabled, uint8_t may_run) __banked { if (!enabled || !may_run || pop_timer_minutes == 0) return 0; --pop_timer_ticks; if (pop_timer_ticks != 0) { /* Последняя минута: оригинал напоминает о времени КАЖДУЮ секунду * (rem_tick % 12 == 0) и специально гасит текущую строку, чтобы * новая встала немедленно, не дожидаясь её 24 тиков. */ if (pop_timer_minutes == 1 && pop_timer_ticks % 12 == 0) pop_show_time = 2; /* 2 = «показать, перебив текущую» */ return 0; } pop_timer_ticks = POP_TIMER_START_TICKS; --pop_timer_minutes; /* Круглые пятёрки и весь финальный отсчёт: seg008:1795. */ if (pop_timer_minutes != 0 && (pop_timer_minutes <= 5 || pop_timer_minutes % 5 == 0)) pop_show_time = 1; return (uint8_t)(pop_timer_minutes == 0); } void pop_timer_cheat_subtract(void) __banked { /* Это буквально правило SDLK_KP_MINUS: последнюю минуту читом не * отнимаем, иначе не получится отличить чит от настоящего expiry. */ if (pop_timer_minutes > 1) --pop_timer_minutes; pop_show_time = 2; /* оригинал показывает результат сразу */ } void pop_timer_cheat_add(void) __banked { /* SDLPoP хранит signed short, у нас достаточно byte: 255 минут — * практический максимум и насыщение не даёт тихо свернуться в нуль. */ if (pop_timer_minutes != 0xFF) ++pop_timer_minutes; pop_show_time = 2; } void pop_timer_qsave(pop_qs_io_t *io) __banked { uint8_t minutes = pop_timer_minutes; uint16_t ticks = pop_timer_ticks; pop_qs_u8(io, &minutes); pop_qs_u16(io, &ticks); if (io->reading && io->apply) { if (ticks == 0 || ticks > POP_TIMER_START_TICKS) { io->failed = 1; return; } pop_timer_minutes = minutes; pop_timer_ticks = ticks; } }