Mercurial > repos > blastem
comparison vgm.c @ 2041:638eb2d25696 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 05 Aug 2021 09:29:33 -0700 |
parents | 327332138c5c |
children |
comparison
equal
deleted
inserted
replaced
1984:0d5f88e53dca | 2041:638eb2d25696 |
---|---|
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 { |
65 uint64_t delta = cycle - writer->last_cycle; | 66 if (cycle < writer->last_cycle) { |
66 delta *= (uint64_t)44100; | 67 //This can happen when a YM-2612 write happens immediately after a PSG write |
67 delta /= (uint64_t)writer->master_clock; | 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 } | |
72 uint64_t last_sample = (uint64_t)writer->last_cycle * (uint64_t)44100; | |
73 last_sample /= (uint64_t)writer->master_clock; | |
74 uint64_t sample = ((uint64_t)cycle + (uint64_t)writer->extra_delta) * (uint64_t)44100; | |
75 sample /= (uint64_t)writer->master_clock; | |
76 uint32_t delta = sample - last_sample; | |
68 | 77 |
69 uint32_t mclks_per_sample = writer->master_clock / 44100; | 78 writer->last_cycle = cycle; |
70 writer->last_cycle += delta * mclks_per_sample; | 79 writer->extra_delta = 0; |
71 writer->header.num_samples += delta; | 80 writer->header.num_samples += delta; |
72 wait_commands(writer, delta); | 81 wait_commands(writer, delta); |
73 } | 82 } |
74 | 83 |
84 static uint8_t last_cmd; | |
75 void vgm_sn76489_write(vgm_writer *writer, uint32_t cycle, uint8_t value) | 85 void vgm_sn76489_write(vgm_writer *writer, uint32_t cycle, uint8_t value) |
76 { | 86 { |
77 add_wait(writer, cycle); | 87 add_wait(writer, cycle); |
78 uint8_t cmd[2] = {CMD_PSG, value}; | 88 uint8_t cmd[2] = {CMD_PSG, value}; |
89 last_cmd = CMD_PSG; | |
79 fwrite(cmd, 1, sizeof(cmd), writer->f); | 90 fwrite(cmd, 1, sizeof(cmd), writer->f); |
80 } | 91 } |
81 | 92 |
82 void vgm_ym2612_init(vgm_writer *writer, uint32_t clock) | 93 void vgm_ym2612_init(vgm_writer *writer, uint32_t clock) |
83 { | 94 { |
86 | 97 |
87 void vgm_ym2612_part1_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) | 98 void vgm_ym2612_part1_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) |
88 { | 99 { |
89 add_wait(writer, cycle); | 100 add_wait(writer, cycle); |
90 uint8_t cmd[3] = {CMD_YM2612_0, reg, value}; | 101 uint8_t cmd[3] = {CMD_YM2612_0, reg, value}; |
102 last_cmd = CMD_YM2612_0; | |
91 fwrite(cmd, 1, sizeof(cmd), writer->f); | 103 fwrite(cmd, 1, sizeof(cmd), writer->f); |
92 } | 104 } |
93 | 105 |
94 void vgm_ym2612_part2_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) | 106 void vgm_ym2612_part2_write(vgm_writer *writer, uint32_t cycle, uint8_t reg, uint8_t value) |
95 { | 107 { |
96 add_wait(writer, cycle); | 108 add_wait(writer, cycle); |
97 uint8_t cmd[3] = {CMD_YM2612_1, reg, value}; | 109 uint8_t cmd[3] = {CMD_YM2612_1, reg, value}; |
110 last_cmd = CMD_YM2612_1; | |
98 fwrite(cmd, 1, sizeof(cmd), writer->f); | 111 fwrite(cmd, 1, sizeof(cmd), writer->f); |
99 } | 112 } |
100 | 113 |
101 void vgm_adjust_cycles(vgm_writer *writer, uint32_t deduction) | 114 void vgm_adjust_cycles(vgm_writer *writer, uint32_t deduction) |
102 { | 115 { |
103 if (deduction > writer->last_cycle) { | 116 if (deduction > writer->last_cycle) { |
117 writer->extra_delta += deduction - writer->last_cycle; | |
104 writer->last_cycle = 0; | 118 writer->last_cycle = 0; |
105 } else { | 119 } else { |
106 writer->last_cycle -= deduction; | 120 writer->last_cycle -= deduction; |
107 } | 121 } |
108 } | 122 } |
109 | 123 |
110 void vgm_close(vgm_writer *writer) | 124 void vgm_close(vgm_writer *writer) |
111 { | 125 { |
126 uint8_t cmd = 0x66; | |
127 fwrite(&cmd, 1, sizeof(cmd), writer->f); | |
112 writer->header.eof_offset = ftell(writer->f) - offsetof(vgm_header, eof_offset); | 128 writer->header.eof_offset = ftell(writer->f) - offsetof(vgm_header, eof_offset); |
113 fseek(writer->f, SEEK_SET, 0); | 129 fseek(writer->f, SEEK_SET, 0); |
114 fwrite(&writer->header, sizeof(writer->header), 1, writer->f); | 130 fwrite(&writer->header, sizeof(writer->header), 1, writer->f); |
115 fclose(writer->f); | 131 fclose(writer->f); |
116 free(writer); | 132 free(writer); |