comparison vgm.c @ 2002:fc8fd89aeba9

Fix VGM delay calculation overflow when a YM-2612 write follows a PSG write in close succession
author Mike Pavone <pavone@retrodev.com>
date Tue, 14 Jul 2020 20:19:47 -0700
parents e35b00626b3e
children 327332138c5c
comparison
equal deleted inserted replaced
2001:f77d36a975ff 2002:fc8fd89aeba9
58 uint8_t cmd[3] = {CMD_WAIT, delta, delta >> 8}; 58 uint8_t cmd[3] = {CMD_WAIT, delta, delta >> 8};
59 fwrite(cmd, 1, sizeof(cmd), writer->f); 59 fwrite(cmd, 1, sizeof(cmd), writer->f);
60 } 60 }
61 } 61 }
62 62
63 #include "util.h"
63 static void add_wait(vgm_writer *writer, uint32_t cycle) 64 static void add_wait(vgm_writer *writer, uint32_t cycle)
64 { 65 {
66 if (cycle < writer->last_cycle) {
67 //This can happen when a YM-2612 write happens immediately after a PSG write
68 //due to the relatively low granularity of the PSG's internal clock
69 //given that VGM only has a granularity of 44.1 kHz ignoring this is harmless
70 return;
71 }
65 uint64_t last_sample = (uint64_t)writer->last_cycle * (uint64_t)44100; 72 uint64_t last_sample = (uint64_t)writer->last_cycle * (uint64_t)44100;
66 last_sample /= (uint64_t)writer->master_clock; 73 last_sample /= (uint64_t)writer->master_clock;
67 uint64_t sample = (uint64_t)cycle * (uint64_t)44100; 74 uint64_t sample = (uint64_t)cycle * (uint64_t)44100;
68 sample /= (uint64_t)writer->master_clock; 75 sample /= (uint64_t)writer->master_clock;
69 uint32_t delta = sample - last_sample; 76 uint32_t delta = sample - last_sample;
71 writer->last_cycle = cycle; 78 writer->last_cycle = cycle;
72 writer->header.num_samples += delta; 79 writer->header.num_samples += delta;
73 wait_commands(writer, delta); 80 wait_commands(writer, delta);
74 } 81 }
75 82
83 static uint8_t last_cmd;
76 void vgm_sn76489_write(vgm_writer *writer, uint32_t cycle, uint8_t value) 84 void vgm_sn76489_write(vgm_writer *writer, uint32_t cycle, uint8_t value)
77 { 85 {
78 add_wait(writer, cycle); 86 add_wait(writer, cycle);
79 uint8_t cmd[2] = {CMD_PSG, value}; 87 uint8_t cmd[2] = {CMD_PSG, value};
88 last_cmd = CMD_PSG;
80 fwrite(cmd, 1, sizeof(cmd), writer->f); 89 fwrite(cmd, 1, sizeof(cmd), writer->f);
81 } 90 }
82 91
83 void vgm_ym2612_init(vgm_writer *writer, uint32_t clock) 92 void vgm_ym2612_init(vgm_writer *writer, uint32_t clock)
84 { 93 {
87 96
88 void vgm_ym2612_part1_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) 97 void vgm_ym2612_part1_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value)
89 { 98 {
90 add_wait(writer, cycle); 99 add_wait(writer, cycle);
91 uint8_t cmd[3] = {CMD_YM2612_0, reg, value}; 100 uint8_t cmd[3] = {CMD_YM2612_0, reg, value};
101 last_cmd = CMD_YM2612_0;
92 fwrite(cmd, 1, sizeof(cmd), writer->f); 102 fwrite(cmd, 1, sizeof(cmd), writer->f);
93 } 103 }
94 104
95 void vgm_ym2612_part2_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) 105 void vgm_ym2612_part2_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value)
96 { 106 {
97 add_wait(writer, cycle); 107 add_wait(writer, cycle);
98 uint8_t cmd[3] = {CMD_YM2612_1, reg, value}; 108 uint8_t cmd[3] = {CMD_YM2612_1, reg, value};
109 last_cmd = CMD_YM2612_1;
99 fwrite(cmd, 1, sizeof(cmd), writer->f); 110 fwrite(cmd, 1, sizeof(cmd), writer->f);
100 } 111 }
101 112
102 void vgm_adjust_cycles(vgm_writer *writer, uint32_t deduction) 113 void vgm_adjust_cycles(vgm_writer *writer, uint32_t deduction)
103 { 114 {