GameBoy (Color) port of the GTA San Andreas arcade game Duality
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.

sample.c 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * sample.c
  3. * Duality
  4. *
  5. * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
  6. *
  7. * Based on examples from gbdk-2020:
  8. * https://github.com/gbdk-2020/gbdk-2020/tree/develop/gbdk-lib/examples/gb/wav_sample
  9. *
  10. * And the docs for the DMG APU:
  11. * https://gbdev.io/pandocs/Audio_Registers.html
  12. *
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation, either version 3 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * See <http://www.gnu.org/licenses/>.
  24. */
  25. #include "banks.h"
  26. #include "config.h"
  27. #include "gb/hardware.h"
  28. #include "sfx_shoot.h"
  29. #include "sfx_expl_orb.h"
  30. #include "sfx_expl_ship.h"
  31. #include "sample.h"
  32. BANKREF(sample)
  33. static uint8_t play_bank = 1;
  34. static const uint8_t *play_sample = 0;
  35. static uint16_t play_length = 0;
  36. struct sfxs {
  37. uint8_t bank;
  38. uint8_t * const smp;
  39. uint16_t len;
  40. };
  41. static const struct sfxs sfxs[SFX_COUNT] = {
  42. { .bank = BANK(sfx_shoot), .smp = sfx_shoot, .len = sfx_shoot_SIZE >> 4 }, // SFX_SHOT
  43. { .bank = BANK(sfx_expl_orb), .smp = sfx_expl_orb, .len = sfx_expl_orb_SIZE >> 4 }, // SFX_EXPL_ORB
  44. { .bank = BANK(sfx_expl_ship), .smp = sfx_expl_ship, .len = sfx_expl_ship_SIZE >> 4 }, // SFX_EXPL_SHIP
  45. };
  46. void sample_play(enum SFXS sfx) BANKED {
  47. if (sfx >= SFX_COUNT) {
  48. return;
  49. }
  50. /*
  51. if (conf_get()->sfx_vol == 0) {
  52. return;
  53. }
  54. */
  55. CRITICAL {
  56. play_bank = sfxs[sfx].bank;
  57. play_sample = sfxs[sfx].smp;
  58. play_length = sfxs[sfx].len;
  59. }
  60. }
  61. uint8_t sample_running(void) BANKED {
  62. return (play_length > 0) ? 1 : 0;
  63. }
  64. #if 1
  65. // TODO C version has a slight 'beep' always? and much worse at lower volumes?
  66. void sample_isr(void) NONBANKED {
  67. if (play_length == 0) {
  68. return;
  69. }
  70. NR51_REG = 0xBB; // turn CH3 off in left and right pan
  71. NR30_REG = 0x00; // turn DAC off
  72. START_ROM_BANK(play_bank) {
  73. // load waveforms
  74. for (uint8_t i = 0; i < 16; i++) {
  75. _AUD3WAVERAM[i] = *(play_sample++);
  76. }
  77. } END_ROM_BANK
  78. NR30_REG = 0x80; // turn DAC on
  79. NR31_REG = 0xFE; // length of wave, 2nd shortest
  80. NR32_REG = (4 - /*conf_get()->sfx_vol*/0x03) << 5;
  81. NR33_REG = 0x00; // low freq bits are zero
  82. NR34_REG = 0xC7; // start, no loop, high freq bits are 111
  83. NR51_REG = 0xFF; // turn all channels on
  84. play_length--;
  85. }
  86. #else
  87. // TODO ASM version has less beep at full volume, but also beeping at lower volumes?
  88. void sample_isr(void) NONBANKED NAKED {
  89. __asm
  90. ld hl, #_play_length ; something left to play?
  91. ld a, (hl+)
  92. or (hl)
  93. ret z
  94. ld hl, #_play_sample
  95. ld a, (hl+)
  96. ld h, (hl)
  97. ld l, a ; HL = current position inside the sample
  98. ; load new waveform
  99. ld a, (#__current_bank) ; save bank and switch
  100. ld e, a
  101. ld a, (#_play_bank)
  102. ld (_rROMB0), a
  103. ldh a, (_NR51_REG)
  104. ld c, a
  105. and #0b10111011
  106. ldh (_NR51_REG), a
  107. xor a
  108. ldh (_NR30_REG), a
  109. .irp ofs,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  110. ld a, (hl+)
  111. ldh (__AUD3WAVERAM+ofs), a
  112. .endm
  113. ld a, #0x80
  114. ldh (_NR30_REG), a
  115. ld a, #0xFE ; length of wave
  116. ldh (_NR31_REG), a
  117. ld a, #0x20 ; volume
  118. ldh (_NR32_REG), a
  119. xor a ; low freq bits are zero
  120. ldh (_NR33_REG), a
  121. ld a, #0xC7 ; start; no loop; high freq bits are 111
  122. ldh (_NR34_REG), a
  123. ld a, c
  124. ldh (_NR51_REG), a
  125. ld a, e ; restore bank
  126. ld (_rROMB0), a
  127. ld a, l ; save current position
  128. ld (#_play_sample), a
  129. ld a, h
  130. ld (#_play_sample+1), a
  131. ld hl, #_play_length ; decrement length variable
  132. ld a, (hl)
  133. sub #1
  134. ld (hl+), a
  135. ld a, (hl)
  136. sbc #0
  137. ld (hl), a
  138. ret
  139. __endasm;
  140. }
  141. #endif