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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. if (conf_get()->sfx_vol == 0) {
  51. return;
  52. }
  53. CRITICAL {
  54. play_bank = sfxs[sfx].bank;
  55. play_sample = sfxs[sfx].smp;
  56. play_length = sfxs[sfx].len;
  57. }
  58. }
  59. uint8_t sample_running(void) BANKED {
  60. return (play_length > 0) ? 1 : 0;
  61. }
  62. #if 1
  63. // TODO C version has a slight 'beep' always? and much worse at lower volumes?
  64. void sample_isr(void) NONBANKED {
  65. if (play_length == 0) {
  66. return;
  67. }
  68. NR51_REG = 0xBB; // turn CH3 off in left and right pan
  69. NR30_REG = 0x00; // turn DAC off
  70. START_ROM_BANK(play_bank);
  71. // load waveforms
  72. for (uint8_t i = 0; i < 16; i++) {
  73. _AUD3WAVERAM[i] = *(play_sample++);
  74. }
  75. END_ROM_BANK();
  76. NR30_REG = 0x80; // turn DAC on
  77. NR31_REG = 0xFE; // length of wave, 2nd shortest
  78. NR32_REG = (4 - conf_get()->sfx_vol) << 5;
  79. NR33_REG = 0x00; // low freq bits are zero
  80. NR34_REG = 0xC7; // start, no loop, high freq bits are 111
  81. NR51_REG = 0xFF; // turn all channels on
  82. play_length--;
  83. }
  84. #else
  85. // TODO ASM version has less beep at full volume, but also beeping at lower volumes?
  86. void sample_isr(void) NONBANKED NAKED {
  87. __asm
  88. ld hl, #_play_length ; something left to play?
  89. ld a, (hl+)
  90. or (hl)
  91. ret z
  92. ld hl, #_play_sample
  93. ld a, (hl+)
  94. ld h, (hl)
  95. ld l, a ; HL = current position inside the sample
  96. ; load new waveform
  97. ld a, (#__current_bank) ; save bank and switch
  98. ld e, a
  99. ld a, (#_play_bank)
  100. ld (_rROMB0), a
  101. ldh a, (_NR51_REG)
  102. ld c, a
  103. and #0b10111011
  104. ldh (_NR51_REG), a
  105. xor a
  106. ldh (_NR30_REG), a
  107. .irp ofs,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  108. ld a, (hl+)
  109. ldh (__AUD3WAVERAM+ofs), a
  110. .endm
  111. ld a, #0x80
  112. ldh (_NR30_REG), a
  113. ld a, #0xFE ; length of wave
  114. ldh (_NR31_REG), a
  115. ld a, #0x20 ; volume
  116. ldh (_NR32_REG), a
  117. xor a ; low freq bits are zero
  118. ldh (_NR33_REG), a
  119. ld a, #0xC7 ; start; no loop; high freq bits are 111
  120. ldh (_NR34_REG), a
  121. ld a, c
  122. ldh (_NR51_REG), a
  123. ld a, e ; restore bank
  124. ld (_rROMB0), a
  125. ld a, l ; save current position
  126. ld (#_play_sample), a
  127. ld a, h
  128. ld (#_play_sample+1), a
  129. ld hl, #_play_length ; decrement length variable
  130. ld a, (hl)
  131. sub #1
  132. ld (hl+), a
  133. ld a, (hl)
  134. sbc #0
  135. ld (hl), a
  136. ret
  137. __endasm;
  138. }
  139. #endif