Human68k CUI emulator with sound.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vgm.c 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "vgm.h"
  2. static const uint8_t header[] = {
  3. /* 0x-0 0x-1 0x-2 0x-3 0x-4 0x-5 0x-6 0x-7 0x-8 0x-9 0x-a 0x-b 0x-c 0x-d 0x-e 0x-f */
  4. /* 0x0- */ 0x56, 0x67, 0x6d, 0x20, 0x4a, 0x83, 0x01, 0x00, 0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  5. /* 0x1- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x9a, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00,
  6. /* 0x2- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  7. /* 0x3- */ 0x00, 0x09, 0x3d, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  8. /* 0x4- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  9. /* 0x5- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  10. /* 0x6- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  11. /* 0x7- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  12. /* 0x8- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  13. /* 0x9- */ 0x00, 0x12, 0x7a, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  14. /* 0xa- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  15. /* 0xb- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  16. /* 0xc- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  17. /* 0xd- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  18. /* 0xe- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19. /* 0xf- */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  20. };
  21. int vgm_logger_begin(struct vgm_logger *l, char *filename) {
  22. l->f = fopen(filename, "wb");
  23. if(!l->f) return -1;
  24. fwrite(header, 1, sizeof(header), l->f);
  25. l->last_wait = 0;
  26. l->size = 0;
  27. return 0;
  28. }
  29. void vgm_logger_wait(struct vgm_logger *l, int samples) {
  30. l->last_wait += samples;
  31. l->total_samples += samples;
  32. }
  33. void vgm_logger_write_wait(struct vgm_logger *l, int samples) {
  34. if(samples <= 0) return;
  35. uint8_t buf[3];
  36. int len = 0;
  37. if(samples == 735) {
  38. buf[0] = 0x62;
  39. len = 1;
  40. } else if(samples == 882) {
  41. buf[0] = 0x63;
  42. len = 1;
  43. } else if(samples <= 16) {
  44. buf[0] = 0x70 + samples - 1;
  45. len = 1;
  46. } else {
  47. while(samples > 65535) {
  48. buf[0] = 0x61;
  49. buf[1] = 0xff;
  50. buf[2] = 0xff;
  51. fwrite(buf, 1, 3, l->f);
  52. l->size += 3;
  53. samples -= 65535;
  54. }
  55. buf[0] = 0x61;
  56. buf[1] = samples & 0xff;
  57. buf[2] = samples >> 8;
  58. len = 3;
  59. }
  60. fwrite(buf, 1, len, l->f);
  61. l->size += len;
  62. }
  63. void vgm_logger_write(struct vgm_logger *l, uint8_t *buf, int len) {
  64. if(l->last_wait) {
  65. vgm_logger_write_wait(l, l->last_wait);
  66. l->last_wait = 0;
  67. }
  68. fwrite(buf, 1, len, l->f);
  69. l->size += len;
  70. }
  71. void vgm_logger_write_ay(struct vgm_logger *l, uint8_t reg, uint8_t data) {
  72. uint8_t buf[3];
  73. buf[0] = 0xa0;
  74. buf[1] = reg;
  75. buf[2] = data;
  76. vgm_logger_write(l, buf, 3);
  77. }
  78. void vgm_logger_write_ym2151(struct vgm_logger *l, uint8_t reg, uint8_t data) {
  79. uint8_t buf[3];
  80. buf[0] = 0x54;
  81. buf[1] = reg;
  82. buf[2] = data;
  83. vgm_logger_write(l, buf, 3);
  84. }
  85. void vgm_logger_write_okim6258(struct vgm_logger *l, uint8_t reg, uint8_t data) {
  86. uint8_t buf[3];
  87. buf[0] = 0xb7;
  88. buf[1] = reg;
  89. buf[2] = data;
  90. vgm_logger_write(l, buf, 3);
  91. }
  92. void vgm_logger_end(struct vgm_logger *l) {
  93. if(l->last_wait)
  94. vgm_logger_write_wait(l, l->last_wait);
  95. fseek(l->f, 0x04, SEEK_SET);
  96. l->size += sizeof(header) - 4;
  97. fwrite(&l->size, 1, 4, l->f);
  98. fseek(l->f, 0x18, SEEK_SET);
  99. fwrite(&l->total_samples, 1, 4, l->f);
  100. fclose(l->f);
  101. }