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
+69
View File
@@ -0,0 +1,69 @@
/* Auto-generated by gen_freq_tables.js — DO NOT EDIT */
#ifndef FREQ_LUT_MAP_H
#define FREQ_LUT_MAP_H
#include "types.h"
/* AY/YM2149: bypass |psg_khz - 1750| <= 35 */
#define FREQ_LUT_HW_KHZ 1750u
#define FREQ_LUT_BYPASS_TOL 35u /* 2% */
/* YM2203: bypass |ym_khz - 3500| <= 70 */
#define FREQ_LUT_HW_YM_KHZ 3500u
#define FREQ_LUT_BYPASS_TOL_YM 70u /* 2% */
#define FREQ_LUT_AY_COUNT 6u
#define FREQ_LUT_YM_COUNT 5u
#define FREQ_LUT_PSG_ENTRIES 4096u /* 12-bit PSG */
#define FREQ_LUT_PSG_BYTES 8192u /* per PSG table */
typedef struct {
uint16_t clk_khz; /* canonical clock in kHz (PSG or YM master) */
uint16_t tol_khz; /* ±tolerance in kHz (5%) */
uint8_t page; /* plugin page (PAGE_BASE-based) */
uint16_t offset; /* PSG table byte offset within page */
} freq_lut_entry_t;
/* AY/YM2149 PSG table map (tolerance = 5% of canonical PSG clock)
* Layout: 2 ratios per page, PSG_A@0x0000, PSG_B@0x2000 */
static const freq_lut_entry_t freq_lut_map_ay[FREQ_LUT_AY_COUNT] = {
{ 1790u, 90u, 1, 0x0000 }, /* NTSC_1790 */
{ 1500u, 75u, 1, 0x2000 }, /* 3MHz_1500 */
{ 2000u, 100u, 2, 0x0000 }, /* 4MHz_2000 */
{ 1000u, 50u, 2, 0x2000 }, /* CPC_1000 */
{ 1250u, 63u, 3, 0x0000 }, /* 1250 */
{ 750u, 38u, 3, 0x2000 } /* 1500_750 */
};
/* YM2203 table map (full master clock, PSG table = same as AY entry) */
static const freq_lut_entry_t freq_lut_map_ym[FREQ_LUT_YM_COUNT] = {
{ 3580u, 179u, 1, 0x0000 }, /* NTSC_1790 (YM2203@3580kHz) */
{ 3000u, 150u, 1, 0x2000 }, /* 3MHz_1500 (YM2203@3000kHz) */
{ 4000u, 200u, 2, 0x0000 }, /* 4MHz_2000 (YM2203@4000kHz) */
{ 2500u, 125u, 3, 0x0000 }, /* 1250 (YM2203@2500kHz) */
{ 1500u, 75u, 3, 0x2000 } /* 1500_750 (YM2203@1500kHz) */
};
/* FM F-Number множитель (YM2203): scaled = fnum × fm_mul / 7.
* 0 = bypass (масштабирование не нужно).
* ASM на Z80: умножение через shifts+adds, деление на 7 binary division */
static const uint8_t freq_lut_fm_mul[FREQ_LUT_YM_COUNT] = {
0, /* NTSC_1790: 1.022727 = bypass (2.3%) */
6, /* 3MHz_1500: 0.857143 = ×6/7 */
8, /* 4MHz_2000: 1.142857 = ×8/7 */
5, /* 1250: 0.714286 = ×5/7 */
3 /* 1500_750: 0.428571 = ×3/7 */
};
/*
* Usage in vgm.c (parse_header):
*
* 1. Bypass check: |clock_khz - HW| <= BYPASS_TOL → native
* 2. Find matching table → set page, PSG base = offset
* 3. For YM2203: fm_mul = freq_lut_fm_mul[j]
*
* PSG: scaled_period = freq_lut_base[period_12bit]
* FM: asm_scale_fm() : fb_scaled = fnum × fm_mul / 7
* if (fb_scaled > 2047) block++, fb_scaled >>= 1
*/
#endif /* FREQ_LUT_MAP_H */