Mercurial > repos > blastem
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 { |