Skip to content

Instantly share code, notes, and snippets.

@Bananattack
Created July 9, 2019 00:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bananattack/4fceb66f24824f41167b0c2e385a9440 to your computer and use it in GitHub Desktop.
Save Bananattack/4fceb66f24824f41167b0c2e385a9440 to your computer and use it in GitHub Desktop.
wavedumper script for VBA-rr, along with some samples captured with it (incomplete dumps). public domain, use for whatever you want, no warranty/liability/etc.
local colors = {
transparent = {r = 0x00; g = 0x00; b = 0x00; a = 0x00};
background = {r = 0x33; g = 0x66; b = 0xCC; a = 0xE0};
text = {r = 0xFF; g = 0xFF; b = 0xFF; a = 0xFF};
outline = {r = 0x00; g = 0x00; b = 0x00; a = 0x80};
button = {r = 0xCC; g = 0x33; b = 0x99; a = 0xFF};
glow = {r = 0xFF; g = 0xFF; b = 0xFF; a = 0x20};
}
local gb = {
header = {
logo = 0x0104;
title = 0x0134;
};
audio = {
wave = {
toggle = 0xFF1A;
TOGGLE_ENABLE = 0x80;
TOGGLE_DISABLE = 0x80;
ram = 0xFF30;
toggle = 0xFF1A;
TOGGLE_ENABLE = 0x80;
TOGGLE_DISABLE = 0x00;
length = 0xFF1B;
volume = 0xFF1C;
VOLUME_0 = 0x00;
VOLUME_100 = 0x20;
VOLUME_50 = 0x40;
VOLUME_25 = 0x60;
frequency = {
low = 0xFF1D;
high = 0xFF1E;
HIGH_RESTART = 0x80;
HIGH_COUNT = 0x40;
HIGH_MASK = 0x07;
};
};
volume = 0xFF24;
VOLUME_RIGHT_VIN = 0x80;
VOLUME_RIGHT_MASK = 0x70;
VOLUME_LEFT_VIN = 0x08;
VOLUME_LEFT_MASK = 0x07;
pan = 0xFF25;
PAN_NOISE_R = 0x80;
PAN_NOISE_L = 0x08;
PAN_WAVE_R = 0x40;
PAN_WAVE_L = 0x04;
PAN_TONE2_R = 0x20;
PAN_TONE2_L = 0x02;
PAN_TONE_R = 0x10;
PAN_TONE_L = 0x01;
ctrl = 0xFF26;
CTRL_ENABLE = 0x80;
CTRL_DISABLE = 0x00;
CTRL_NOISE = 0x08;
CTRL_WAVE = 0x04;
CTRL_TONE2 = 0x02;
CTRL_TONE = 0x01;
};
};
local gba = {
header = {
title = 0x80000A0;
};
audio = {
wave = {
toggle = 0x4000070;
TOGGLE_ENABLE = 0x80;
TOGGLE_DISABLE = 0x80;
TOGGLE_BANK_SWITCH = 0x40;
TOGGLE_WIDE_SAMPLE = 0x20;
ram = 0x4000090;
length_volume = 0x4000072;
VOLUME_LEGACY_MASK = 0x6000;
VOLUME_0 = 0x00000;
VOLUME_100 = 0x2000;
VOLUME_50 = 0x4000;
VOLUME_25 = 0x6000;
VOLUME_FORCE_75_BIT = 0x8000;
frequency = 0x4000072;
FREQ_RESTART = 0x8000;
FREQ_COUNT = 0x4000;
FREQ_MASK = 0x07FF;
};
volume_pan = 0x4000080;
VOLUME_RIGHT_MASK = 0x0007;
VOLUME_LEFT_MASK = 0x0070;
PAN_NOISE_R = 0x8000;
PAN_NOISE_L = 0x0800;
PAN_WAVE_R = 0x4000;
PAN_WAVE_L = 0x0400;
PAN_TONE2_R = 0x2000;
PAN_TONE2_L = 0x0200;
PAN_TONE_R = 0x1000;
PAN_TONE_L = 0x0100;
ctrl = 0x4000084;
CTRL_ENABLE = 0x80;
CTRL_DISABLE = 0x00;
CTRL_NOISE = 0x08;
CTRL_WAVE = 0x04;
CTRL_TONE2 = 0x02;
CTRL_TONE = 0x01;
};
}
local samples = {
count = 0;
title = '';
gb = false;
index = 0;
};
local ui = {}
ui.visible = true
ui.unpress = {}
function ui.window(x, y, x2, y2)
gui.box(x - 1, y, x2, y2, colors.background, colors.background)
end
function ui.text(x, y, text)
gui.text(x, y, text, colors.text, colors.outline)
end
function ui.textbutton(x, y, text, inputs, onclick)
local x2 = x + #text * 4 + 4
local y2 = y + 12
gui.box(x, y, x2, y2, colors.button, colors.outline)
gui.text(x + 3, y + 3, text, colors.text, colors.outline)
if x <= inputs.xmouse and inputs.xmouse <= x2
and y <= inputs.ymouse and inputs.ymouse <= y2 then
gui.box(x, y, x2, y2, colors.glow, colors.outline)
if inputs.leftclick and onclick then
if not ui.unpress.leftclick then
onclick()
ui.unpress.leftclick = true
end
end
end
end
local unpack = unpack or table.unpack
local gb_logo = string.char(
0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99,
0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E
)
function check_logo()
for i = 1, #gb_logo do
if memory.readbyte(gb.header.logo + i - 1, 48) ~= gb_logo:byte(i, i) then
return false
end
end
return true
end
function check_sample(samples)
if samples.busy then
return
end
samples.busy = true
local sample = {}
if samples.gb then
for i = 0, 15 do
table.insert(sample, string.format('%02X', memory.readbyte(gb.audio.wave.ram + i)))
end
else
for i = 0, 7 do
table.insert(sample, string.format('%04X', memory.readword(gba.audio.wave.ram + i)))
end
end
sample = table.concat(sample, '')
local sample_index = samples[sample]
if not sample_index then
samples.count = samples.count + 1
samples[sample] = samples.count
samples[samples.count] = sample
sample_index = samples[sample]
end
samples.index = sample_index
samples.busy = false
end
while true do
local inputs = input.get()
local is_gameboy = check_logo()
local title = {}
if is_gameboy then
samples.gb = true
for i = 0, 15 do
local c = memory.readbyte(gb.header.title + i)
if c == 0 then
break
end
table.insert(title, c)
end
else
samples.gb = false
for i = 0, 15 do
memory.registerwrite(gba.audio.wave.ram + 0x0F, function() check_sample(samples) end)
end
for i = 0, 15 do
local c = memory.readbyte(gba.header.title + i)
if c == 0 then
break
end
table.insert(title, c)
end
end
title = string.char(unpack(title))
if samples.title ~= title or samples.gb ~= is_gameboy then
samples = {count = 0; title = title; gb = is_gameboy; index = 0}
end
if samples.gb then
check_sample(samples)
end
if inputs.rightclick then
if not ui.unpress.rightclick then
ui.visible = not ui.visible
ui.unpress.rightclick = true
end
else
ui.unpress.rightclick = false
end
for k, v in pairs(ui.unpress) do
if not inputs[k] then
ui.unpress[k] = false
end
end
if ui.visible then
if samples.gb then
ui.window(0, 0, 160, 35)
ui.window(0, 120, 160, 144, colors.background, colors.background)
ui.text(4, 4, 'WAVE:'
.. (bit.band(memory.readbyte(gb.audio.wave.toggle), gb.audio.wave.TOGGLE_ENABLE) ~= 0 and ' ON' or 'OFF')
.. ' PAN:'
.. (bit.band(memory.readbyte(gb.audio.pan), gb.audio.PAN_WAVE_L) ~= 0 and 'L' or '-')
.. '/'
.. (bit.band(memory.readbyte(gb.audio.pan), gb.audio.PAN_WAVE_R) ~= 0 and 'R' or '-')
.. ' VOL:'
.. (bit.band(memory.readbyte(gb.audio.wave.volume), 0x60) == gb.audio.wave.VOLUME_0 and ' 0'
or bit.band(memory.readbyte(gb.audio.wave.volume), 0x60) == gb.audio.wave.VOLUME_100 and '100'
or bit.band(memory.readbyte(gb.audio.wave.volume), 0x60) == gb.audio.wave.VOLUME_50 and ' 50'
or bit.band(memory.readbyte(gb.audio.wave.volume), 0x60) == gb.audio.wave.VOLUME_25 and ' 25'
or '???')
.. '% '
.. 'PLAYING:' .. (bit.band(memory.readbyte(gb.audio.ctrl), gb.audio.CTRL_WAVE) ~= 0 and 'YES' or ' NO'))
ui.text(4, 16, 'SAMPLE ')
ui.text(4, 24, samples.index .. ' / ' .. samples.count)
if samples.count > 0 then
for i = 0, 15 do
ui.text(40 + (i % 8) * 12, 16 + math.floor(i / 8) * 8, samples[samples.index]:sub(i * 2 + 1, i * 2 + 2))
end
end
ui.text(40, 128, '' .. title)
ui.textbutton(4, 124, 'Save', inputs, function()
local fn = title:gsub('[^%-A-Za-z0-9 _]', '')
local f = io.open(fn .. '.txt', 'w')
f:write(title .. '\n')
f:write(('-'):rep(#title) .. '\n')
f:write('\n')
f:write(samples.count .. ' sample(s) captured.\n')
f:write('\n')
for i, sample in ipairs(samples) do
local name = 'Sample #' .. i
f:write(name .. '\n')
f:write(('-'):rep(#name) .. '\n\n')
f:write('HEX:\n\n')
local hex = {}
for i = 1, 15 do
table.insert(hex, sample:sub(i * 2 + 1, i * 2 + 2))
end
f:write(table.concat(hex, ' '))
f:write('\n\n')
f:write('MML:\n\n')
local mml = {}
for i = 1, 15 do
table.insert(mml, math.floor(tonumber(hex[i], 16) / 16) .. ' ' .. (tonumber(hex[i], 16) % 16))
end
f:write(table.concat(mml, ' '))
f:write('\n\n')
f:write('ASM:\n\n')
f:write('DB $' .. table.concat(hex, ', $') .. '\n')
f:write('\n\n')
end
f:close()
gui.popup('Saved samples to "' .. fn .. '.txt" successfully!')
end)
else
ui.window(0, 0, 240, 35)
ui.window(0, 136, 240, 160, colors.background, colors.background)
ui.text(4, 4, 'WAVE:'
.. (bit.band(memory.readword(gba.audio.wave.toggle), gba.audio.wave.TOGGLE_ENABLE) ~= 0 and ' ON' or 'OFF')
.. ' BANK: '
.. (bit.band(memory.readword(gba.audio.wave.toggle), gba.audio.wave.TOGGLE_BANK_SWITCH) ~= 0 and '0' or '1')
.. ' SIZE: '
.. (bit.band(memory.readword(gba.audio.wave.toggle), gba.audio.wave.TOGGLE_WIDE_SAMPLE) ~= 0 and '64' or '32')
.. ' PAN:'
.. (bit.band(memory.readword(gba.audio.volume_pan), gba.audio.PAN_WAVE_L) ~= 0 and 'L' or '-')
.. '/'
.. (bit.band(memory.readword(gba.audio.volume_pan), gba.audio.PAN_WAVE_R) ~= 0 and 'R' or '-')
.. ' VOL:'
.. (
bit.band(memory.readword(gba.audio.wave.length_volume), gba.audio.wave.VOLUME_FORCE_75_BIT) ~= 0 and ' 75'
or bit.band(memory.readword(gba.audio.wave.length_volume), gba.audio.wave.VOLUME_LEGACY_MASK) == gba.audio.wave.VOLUME_0 and ' 0'
or bit.band(memory.readword(gba.audio.wave.length_volume), gba.audio.wave.VOLUME_LEGACY_MASK) == gba.audio.wave.VOLUME_100 and '100'
or bit.band(memory.readword(gba.audio.wave.length_volume), gba.audio.wave.VOLUME_LEGACY_MASK) == gba.audio.wave.VOLUME_50 and ' 50'
or bit.band(memory.readword(gba.audio.wave.length_volume), gba.audio.wave.VOLUME_LEGACY_MASK) == gba.audio.wave.VOLUME_25 and ' 25'
or '???')
.. '% '
.. 'PLAYING:' .. (bit.band(memory.readword(gba.audio.ctrl), gba.audio.CTRL_WAVE) ~= 0 and 'YES' or ' NO'))
ui.text(4, 16, 'SAMPLE ')
ui.text(4, 24, samples.index .. ' / ' .. samples.count)
if samples.count > 0 then
for i = 0, 15 do
ui.text(40 + (i % 8) * 12, 16 + math.floor(i / 8) * 8, samples[samples.index]:sub(i * 2 + 1, i * 2 + 2))
end
end
ui.text(40, 144, '' .. title)
ui.textbutton(4, 142, 'Save', inputs, function()
local fn = title:gsub('[^%-A-Za-z0-9 _]', '')
local f = io.open(fn .. '.txt', 'w')
print(title .. '.txt')
f:write(title .. '\n')
f:write(('-'):rep(#title) .. '\n')
f:write('\n')
f:write(samples.count .. ' sample(s) captured.\n')
f:write('\n')
for i, sample in ipairs(samples) do
local name = 'Sample #' .. i
f:write(name .. '\n')
f:write(('-'):rep(#name) .. '\n\n')
f:write('HEX:\n\n')
local hex = {}
for i = 1, 15 do
table.insert(hex, sample:sub(i * 2 + 1, i * 2 + 2))
end
f:write(table.concat(hex, ' '))
f:write('\n\n')
f:write('MML:\n\n')
local mml = {}
for i = 1, 15 do
table.insert(mml, math.floor(tonumber(hex[i], 16) / 16) .. ' ' .. (tonumber(hex[i], 16) % 16))
end
f:write(table.concat(mml, ' '))
f:write('\n\n')
f:write('ASM:\n\n')
f:write('DB $' .. table.concat(hex, ', $') .. '\n')
f:write('\n\n')
end
f:close()
gui.popup('Saved samples to "' .. fn .. '.txt" successfully!')
end)
end
end
emu.frameadvance()
end
CASTLEVANIA2 BEL
----------------
5 sample(s) captured.
Sample #1
---------
HEX:
80 8F FF 88 80 88 80 00 08 08 88 80 00 80 00
MML:
8 0 8 15 15 15 8 8 8 0 8 8 8 0 0 0 0 8 0 8 8 8 8 0 0 0 8 0 0 0
ASM:
DB $80, $8F, $FF, $88, $80, $88, $80, $00, $08, $08, $88, $80, $00, $80, $00
Sample #2
---------
HEX:
23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF
MML:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
ASM:
DB $23, $45, $67, $89, $AB, $CD, $EF, $01, $23, $45, $67, $89, $AB, $CD, $EF
Sample #3
---------
HEX:
45 56 67 89 9A AB BC 34 45 56 67 89 9A AB BC
MML:
4 5 5 6 6 7 8 9 9 10 10 11 11 12 3 4 4 5 5 6 6 7 8 9 9 10 10 11 11 12
ASM:
DB $45, $56, $67, $89, $9A, $AB, $BC, $34, $45, $56, $67, $89, $9A, $AB, $BC
Sample #4
---------
HEX:
46 8A CE FD B9 75 31 02 46 8A CE FD B9 75 31
MML:
4 6 8 10 12 14 15 13 11 9 7 5 3 1 0 2 4 6 8 10 12 14 15 13 11 9 7 5 3 1
ASM:
DB $46, $8A, $CE, $FD, $B9, $75, $31, $02, $46, $8A, $CE, $FD, $B9, $75, $31
Sample #5
---------
HEX:
34 56 67 89 9A BC DE 23 34 56 67 89 9A BC DE
MML:
3 4 5 6 6 7 8 9 9 10 11 12 13 14 2 3 3 4 5 6 6 7 8 9 9 10 11 12 13 14
ASM:
DB $34, $56, $67, $89, $9A, $BC, $DE, $23, $34, $56, $67, $89, $9A, $BC, $DE
KIRBY DREAM LAND
----------------
2 sample(s) captured.
Sample #1
---------
HEX:
66 AA EE FF FF FE EA A6 66 8A CF FE EC A6 33
MML:
6 6 10 10 14 14 15 15 15 15 15 14 14 10 10 6 6 6 8 10 12 15 15 14 14 12 10 6 3 3
ASM:
DB $66, $AA, $EE, $FF, $FF, $FE, $EA, $A6, $66, $8A, $CF, $FE, $EC, $A6, $33
Sample #2
---------
HEX:
57 9B DF DB 97 53 10 13 57 9B DF DB 97 53 10
MML:
5 7 9 11 13 15 13 11 9 7 5 3 1 0 1 3 5 7 9 11 13 15 13 11 9 7 5 3 1 0
ASM:
DB $57, $9B, $DF, $DB, $97, $53, $10, $13, $57, $9B, $DF, $DB, $97, $53, $10
MEGA_EXE3_WHA6BE
----------------
3 sample(s) captured.
Sample #1
---------
HEX:
FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF 00 FF
MML:
15 15 0 0 15 15 0 0 15 15 0 0 15 15 0 0 15 15 0 0 15 15 0 0 15 15 0 0 15 15
ASM:
DB $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF, $00, $FF
Sample #2
---------
HEX:
FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00
MML:
15 15 15 15 15 15 15 15 15 15 15 15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00, $00, $00, $00, $00, $00, $00, $00
Sample #3
---------
HEX:
FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
MML:
15 15 15 15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $FF, $FF, $FF, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
MEGAMAN6_FXXBR6E
----------------
3 sample(s) captured.
Sample #1
---------
HEX:
00 00 FF FF 00 00 FF FF 00 00 FF FF 00 00 FF
MML:
0 0 0 0 15 15 15 15 0 0 0 0 15 15 15 15 0 0 0 0 15 15 15 15 0 0 0 0 15 15
ASM:
DB $00, $00, $FF, $FF, $00, $00, $FF, $FF, $00, $00, $FF, $FF, $00, $00, $FF
Sample #2
---------
HEX:
FF FF FF FF FF FF FF FF FF FF FF FF FF 00 FF
MML:
15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 0 0 15 15
ASM:
DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00, $FF
Sample #3
---------
HEX:
FF FF FF FF FF 00 FF 00 00 00 00 00 00 00 00
MML:
15 15 15 15 15 15 15 15 15 15 0 0 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $FF, $FF, $FF, $FF, $FF, $00, $FF, $00, $00, $00, $00, $00, $00, $00, $00
POKEPIN R/S
-----------
1 sample(s) captured.
Sample #1
---------
HEX:
02 8A 46 CE 8A FD CE B9 FD 75 B9 31 75 02 31
MML:
0 2 8 10 4 6 12 14 8 10 15 13 12 14 11 9 15 13 7 5 11 9 3 1 7 5 0 2 3 1
ASM:
DB $02, $8A, $46, $CE, $8A, $FD, $CE, $B9, $FD, $75, $B9, $31, $75, $02, $31
SAGA2
-----
4 sample(s) captured.
Sample #1
---------
HEX:
FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00
MML:
15 15 15 15 15 15 15 15 15 15 15 15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $00, $00, $00, $00, $00, $00, $00, $00
Sample #2
---------
HEX:
BB BB BB 00 00 00 00 00 00 00 00 00 00 00 00
MML:
11 11 11 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $BB, $BB, $BB, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
Sample #3
---------
HEX:
FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
MML:
15 15 15 15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $FF, $FF, $FF, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
Sample #4
---------
HEX:
CC 99 66 99 CC FF 00 00 00 00 00 00 00 00 00
MML:
12 12 9 9 6 6 9 9 12 12 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ASM:
DB $CC, $99, $66, $99, $CC, $FF, $00, $00, $00, $00, $00, $00, $00, $00, $00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment