diff --git a/assets/disk0/home/dumpfont.js b/assets/disk0/home/dumpfont.js index 67c69d7..04f99db 100644 --- a/assets/disk0/home/dumpfont.js +++ b/assets/disk0/home/dumpfont.js @@ -8,31 +8,32 @@ if (!exec_args[1]) { return 1 } -let lowfilename = exec_args[1] + "_low.chr" -let highfilename = exec_args[1] + "_high.chr" +const fullFilePath = _G.shell.resolvePathInput(exec_args[1]).full +let lowfilename = fullFilePath + "_low.chr" +let highfilename = fullFilePath + "_high.chr" let workarea = sys.malloc(1920) // dump low rom sys.poke(-1299460, 16) for (let i = 0; i < 1920; i++) { - let byte = sys.peek(-1300607 - i) + let byte = sys.peek(-133121 - i) sys.poke(workarea + i, byte) } -filesystem.open("A", lowfilename, "W") -dma.ramToCom(workarea, filesystem._toPorts("A")[0], 1920) +const lowfile = files.open(lowfilename) +lowfile.pwrite(workarea, 1920, 0) println("Wrote CHR rom " + lowfilename) // dump high rom sys.poke(-1299460, 17) for (let i = 0; i < 1920; i++) { - let byte = sys.peek(-1300607 - i) + let byte = sys.peek(-133121 - i) sys.poke(workarea + i, byte) } -filesystem.open("A", highfilename, "W") -dma.ramToCom(workarea, filesystem._toPorts("A")[0], 1920) +const highfile = files.open(highfilename) +highfile.pwrite(workarea, 1920, 0) println("Wrote CHR rom " + highfilename) sys.free(workarea) \ No newline at end of file diff --git a/terranmon.txt b/terranmon.txt index d613362..32c1aaf 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -1005,7 +1005,7 @@ transmission capability, and region-of-interest coding. 0x31: Subtitle in "Simple" format with timecodes 0x32: Subtitle in "Karaoke" format 0x33: Subtitle in "Karaoke" format with timecodes - 0x3F: Videotex (full-frame text buffer image) + 0x3F: Videotex (full-frame text buffer memory image) 0x40: MP2 audio track (32 KHz) 0x41: Zstd-compressed 8-bit PCM (32 KHz, audio hardware's native format) @@ -1083,9 +1083,9 @@ transmission capability, and region-of-interest coding. ### List of Keys - Uint64 BGNT: Video begin time in nanoseconds (must be equal to the value of the first Timecode packet) - - Uint64 ENDT: Video end time in nanoseconds (must be equal to the value of the last Timecode packet) + - Uint64 ENDT: Video end time in nanoseconds (must be equal to BGNT + playback time) - Uint64 CDAT: Creation time in microseconds since UNIX Epoch (must be in UTC timezone) - - Bytes VNDR: Name and version of the encoder (for Reference encoder: "Encoder-TAV 20251014 (list,of,features)") + - Bytes VNDR: Name and version of the encoder (for Reference encoder: "Encoder-TAV 20251014 (list,of,features)") - Bytes FMPG: FFmpeg version (typically "ffmpeg version 8.0 Copyright (c) 2000-2025 the FFmpeg developers"; the first line of text FFmpeg emits) ## Extensible Packet Structure diff --git a/tsvm_core/src/net/torvald/tsvm/shader_crt_post.frag b/tsvm_core/src/net/torvald/tsvm/shader_crt_post.frag index 5cba0bb..8c5656c 100644 --- a/tsvm_core/src/net/torvald/tsvm/shader_crt_post.frag +++ b/tsvm_core/src/net/torvald/tsvm/shader_crt_post.frag @@ -15,6 +15,7 @@ // === UNIFORMS === uniform float time = 0.0; // Frame count uniform vec2 resolution = vec2(640.0, 480.0); // Virtual resolution (e.g., 640x480) +uniform float displayScale = 2.0; uniform sampler2D u_texture; // Input texture uniform vec2 flip = vec2(0.0, 0.0); // UV flip control (0,1 = flip Y) @@ -256,7 +257,7 @@ vec3 decodeCGAComposite(vec2 uv, vec2 texelSize, float pixelX, float pixelY) { // === TRINITRON PHOSPHOR MASK === vec3 trinitronMask(vec2 screenPos) { float strength = getPhosphorStrength(); - float outputX = screenPos.x * 2.0; // 2x display scale + float outputX = screenPos.x * displayScale; float stripe = mod(outputX, 3.0); float bleed = 0.15; @@ -279,7 +280,7 @@ vec3 trinitronMask(vec2 screenPos) { // === SCANLINE MASK === float scanlineMask(vec2 screenPos) { float strength = getScanlineStrength(); - float outputY = screenPos.y * 2.0; // 2x display scale + float outputY = screenPos.y * displayScale; float scanline = sin(outputY * PI); scanline = scanline * 0.5 + 0.5; diff --git a/video_encoder/decoder_tav.c b/video_encoder/decoder_tav.c index 00bb616..f8256f0 100644 --- a/video_encoder/decoder_tav.c +++ b/video_encoder/decoder_tav.c @@ -17,7 +17,7 @@ #include "decoder_tad.h" // Shared TAD decoder library #include "tav_avx512.h" // AVX-512 SIMD optimisations -#define DECODER_VENDOR_STRING "Decoder-TAV 20251124 (avx512,presets)" +#define DECODER_VENDOR_STRING "Decoder-TAV 20251126 (presets)" // TAV format constants #define TAV_MAGIC "\x1F\x54\x53\x56\x4D\x54\x41\x56" @@ -315,7 +315,7 @@ static void dequantise_dwt_subbands_perceptual(int q_index, int q_y_global, cons // Previous denormalization in EZBC caused int16_t overflow (clipping at 32767) // for bright pixels, creating dark DWT-pattern blemishes -#ifdef __AVX512F__ +/*#ifdef __AVX512F__ // Use AVX-512 optimised dequantization if available (1.1x speedup against -Ofast) // Check: subband has >=16 elements AND won't exceed buffer bounds const int subband_end = subband->coeff_start + subband->coeff_count; @@ -327,7 +327,7 @@ static void dequantise_dwt_subbands_perceptual(int q_index, int q_y_global, cons effective_quantiser ); } else { -#endif +#endif*/ // Scalar fallback or small subbands for (int i = 0; i < subband->coeff_count; i++) { const int idx = subband->coeff_start + i; @@ -336,9 +336,9 @@ static void dequantise_dwt_subbands_perceptual(int q_index, int q_y_global, cons dequantised[idx] = untruncated; } } -#ifdef __AVX512F__ +/*#ifdef __AVX512F__ } -#endif +#endif*/ } // Debug: Verify LL band was dequantised correctly diff --git a/video_encoder/encoder_tav.c b/video_encoder/encoder_tav.c index ec66460..136802e 100644 --- a/video_encoder/encoder_tav.c +++ b/video_encoder/encoder_tav.c @@ -19,7 +19,7 @@ #include #include "tav_avx512.h" // AVX-512 SIMD optimisations -#define ENCODER_VENDOR_STRING "Encoder-TAV 20251124 (3d-dwt,tad,ssf-tc,cdf53-motion,avx512,presets)" +#define ENCODER_VENDOR_STRING "Encoder-TAV 20251128 (3d-dwt,tad,ssf-tc,cdf53-motion,avx512,presets)" // TSVM Advanced Video (TAV) format constants #define TAV_MAGIC "\x1F\x54\x53\x56\x4D\x54\x41\x56" // "\x1FTSVM TAV" @@ -12158,13 +12158,13 @@ int main(int argc, char *argv[]) { printf("Updated header with actual frame count: %d\n", frame_count); } - // Update ENDT in extended header (calculate end time for last frame) + // Update ENDT in extended header (calculate end time of video) uint64_t endt_ns; if (enc->is_ntsc_framerate) { // NTSC framerates use denominator 1001 (e.g., 24000/1001, 30000/1001, 60000/1001) - endt_ns = ((uint64_t)(frame_count - 1) * 1001ULL * 1000000000ULL) / ((uint64_t)enc->output_fps * 1000ULL); + endt_ns = ((uint64_t)frame_count * 1001ULL * 1000000000ULL) / ((uint64_t)enc->output_fps * 1000ULL); } else { - endt_ns = ((uint64_t)(frame_count - 1) * 1000000000ULL) / (uint64_t)enc->output_fps; + endt_ns = ((uint64_t)frame_count * 1000000000ULL) / (uint64_t)enc->output_fps; } fseek(enc->output_fp, enc->extended_header_offset, SEEK_SET); fwrite(&endt_ns, sizeof(uint64_t), 1, enc->output_fp); diff --git a/video_encoder/encoder_tav_text.c b/video_encoder/encoder_tav_text.c index c4e163d..fbddb1f 100644 --- a/video_encoder/encoder_tav_text.c +++ b/video_encoder/encoder_tav_text.c @@ -24,8 +24,8 @@ Audio: MP2 encoding at 96 kbps, 32 KHz stereo (packet 0x20) Each text frame is treated as an I-frame with sync packet Usage: - gcc -O3 -std=c11 -Wall encoder_tav_text.c -o encoder_tav_text -lm -lzstd - ./encoder_tav_text -i video.mp4 -f font.chr -o output.vtx + gcc -Ofast -std=c11 -Wall encoder_tav_text.c -o encoder_tav_text -lm -lzstd + ./encoder_tav_text -i video.mp4 -f font.chr -o output.mv3 */ #define _POSIX_C_SOURCE 200809L @@ -93,6 +93,9 @@ static void generate_random_filename(char *filename) { char TEMP_AUDIO_FILE[42]; +// Global flag to disable inverted character matching +int g_no_invert_char = 0; + typedef struct { uint8_t *data; // Binary glyph data (PATCH_SZ bytes per glyph) int count; // Number of glyphs @@ -193,7 +196,7 @@ FontROM *load_font_rom(const char *path) { // Find best matching glyph for a grayscale patch int find_best_glyph(const uint8_t *patch, const FontROM *rom, uint8_t *out_bg, uint8_t *out_fg) { - // Try both normal and inverted matching + // Try both normal and inverted matching (unless --no-invert-char is set) int best_glyph = 0; float best_error = INFINITY; uint8_t best_bg = COLOR_BLACK, best_fg = COLOR_WHITE; @@ -209,25 +212,28 @@ int find_best_glyph(const uint8_t *patch, const FontROM *rom, uint8_t *out_bg, u err_normal += diff * diff; } - // Try inverted: glyph 0 = fg, glyph 1 = bg - float err_inverted = 0; - for (int i = 0; i < PATCH_SZ; i++) { - int expected = glyph[i] ? 0 : 255; - int diff = patch[i] - expected; - err_inverted += diff * diff; - } - if (err_normal < best_error) { best_error = err_normal; best_glyph = g; best_bg = COLOR_BLACK; best_fg = COLOR_WHITE; } - if (err_inverted < best_error) { - best_error = err_inverted; - best_glyph = g; - best_bg = COLOR_WHITE; - best_fg = COLOR_BLACK; + + // Try inverted: glyph 0 = fg, glyph 1 = bg (skip if --no-invert-char) + if (!g_no_invert_char) { + float err_inverted = 0; + for (int i = 0; i < PATCH_SZ; i++) { + int expected = glyph[i] ? 0 : 255; + int diff = patch[i] - expected; + err_inverted += diff * diff; + } + + if (err_inverted < best_error) { + best_error = err_inverted; + best_glyph = g; + best_bg = COLOR_WHITE; + best_fg = COLOR_BLACK; + } } } @@ -479,7 +485,7 @@ void write_text_packet(FILE *f, const uint8_t *bg_col, const uint8_t *fg_col, int main(int argc, char **argv) { if (argc < 7) { - fprintf(stderr, "Usage: %s -i