Add OPL4 playback and analyzer support

This commit is contained in:
2026-09-15 14:59:29 +03:00
commit 1686838e03
553 changed files with 50524 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
/**
* @file txtlib.h
* @brief 䇃䇐䈜䈛 для вывода текста в окна WC — динамические буферы и печать строк
* @version 1.0
*
* Зависимости: wc_api.h (wc_prsrw, wc_window_t).
* Реализация: lib/txtlib.c.
*
* Формат буфера:
* buf[0] = capacity — максимальная емкость в символах (задаётся ОДИН РАЗ при buf_init)
* buf[1] = len — текущая длина (количество символов)
* buf[2..] = символы — не завершается \0!
*
* Объявление буфера:
* char work_buf[66]; // capacity = 64 символа
*
* Типичное использование:
* buf_init(work_buf, 64);
* buf_clear(work_buf);
* buf_append_str(work_buf, "Time: ");
* buf_append_u16_dec(work_buf, seconds);
* print_line(&win, 5, work_buf, WC_COLOR(WC_BLACK, WC_BRIGHT_WHITE));
*/
#ifndef TXTLIB_H
#define TXTLIB_H
#include "wc_api.h"
#define FS_SCREEN_COLS 96U /* макс. ширина экрана (90x36, запас) */
/**
* Вернуть (ширина окна - 4) = полезная ширина содержимого.
* Если win->width == 0, используется FS_SCREEN_COLS.
*/
static inline uint8_t get_content_width(const wc_window_t *win) {
uint8_t w = win->width;
return (w ? w : FS_SCREEN_COLS) - 4U;
}
/* ================================================================== */
/* ИНИЦИАЛИЗАЦИЯ И БАЗОВЫЕ ОПЕРАЦИИ */
/* ================================================================== */
/** Инициализировать буфер: записать capacity, len=0. Вызывать ОДИН РАЗ! */
static inline void buf_init(char *buf, uint8_t capacity) {
buf[0] = capacity;
buf[1] = 0;
}
/** Очистить буфер: len=0 (емкость не меняется). */
static inline void buf_clear(char *buf) {
buf[1] = 0;
}
/** Вернуть текущую длину буфера (количество символов). */
static inline uint8_t buf_len(const char *buf) {
return buf[1];
}
/* ================================================================== */
/* APPEND */
/* ================================================================== */
/**
* Добавить строку (\0-terminated) в конец буфера.
* Тихо усекается при переполнении (len не превышает capacity).
* @return len после добавления
*/
uint8_t buf_append_str(char *buf, const char *src);
/**
* Добавить один символ c в буфер.
* @return len после добавления
*/
uint8_t buf_append_char(char *buf, char c);
/**
* Добавить двухсимвольное hex-представление байта ("00".."FF").
* @param val значение 0..255
* @return len после добавления (+2)
*/
uint8_t buf_append_u8_hex(char *buf, uint8_t val);
/**
* Добавить uint16 в десятичном формате (без ведущих нулей).
* @return len после добавления
*/
uint8_t buf_append_u16_dec(char *buf, uint16_t val);
/**
* Добавить uint32 в десятичном формате.
* @return len после добавления
*/
uint8_t buf_append_u32_dec(char *buf, uint32_t val);
/**
* Добавить "MM:SS" (5 символов) в буфер. Без деления — вычитание.
* @param sec секунды (0..5999)
*/
void buf_append_mmss(char *buf, uint16_t sec);
/* ================================================================== */
/* ВЫВОД */
/* ================================================================== */
/**
* Вывести одну строку из буфера в окно win заполняя до ширины окна.
*  Передаётся атрибут цвета attr (EGA: bg[7:4] | fg[3:0]).
*
* @param win окно WC
* @param y строка внутри окна (1-базированное)
* @param buf буфер с длиной в buf[1] (формат buf[])
* @param attr EGA-атрибут: WC_COLOR(bg, fg)
*/
void print_line(wc_window_t *win, uint8_t y, const char *buf, uint8_t attr);
/* ================================================================== */
/* ИНИЦИАЛИЗАЦИЯ И ПРИМЕР ИСПОЛЬЗОВАНИЯ */
/* ================================================================== */
/*
// В начале плагина (например в init)
char meta_buf[122];
char work_buf[66]; // 64 символа
buf_init(meta_buf, 120);
buf_init(work_buf, 64); // или больше, если используешь для marquee
// Заполнение метаданных
buf_clear(meta_buf);
buf_append_str(meta_buf, "Artist - Super Long Track Name 2025 (Remix)");
// В цикле отрисовки:
uint8_t cw = get_content_width(my_win);
// Бегущая строка (используем work_buf как временный)
build_marquee(work_buf, meta_buf + 2, meta_buf[1], scroll_pos, cw);
print_marquee(my_win, 3, work_buf, 0x0F); // белый
scroll_pos++;
// Обычная строка (время)
buf_clear(work_buf);
buf_append_str(work_buf, "Time: ");
buf_append_u16_dec(work_buf, minutes);
buf_append_char(work_buf, ':');
buf_append_u16_dec(work_buf, seconds);
print_line(my_win, 5, work_buf, 0x0A);
*/
#endif // TXTLIB_H