diff --git a/trunk/output/luaScripts/scrolling-pitch-display.lua b/trunk/output/luaScripts/scrolling-pitch-display.lua new file mode 100644 index 00000000..2c6e4c02 --- /dev/null +++ b/trunk/output/luaScripts/scrolling-pitch-display.lua @@ -0,0 +1,206 @@ +-- Scrolling Pitch Display for FCEUX +-- 2014-07-19 +-- Robert Hart (rnhart.net) + +SCREEN_LEFT = 0 +SCREEN_RIGHT = 255 +MIDI_LEFT = 18 +MIDI_RIGHT = 102 + +MIDI_RANGE = (MIDI_RIGHT + 1) - MIDI_LEFT +SCREEN_RANGE = (SCREEN_RIGHT + 1) - SCREEN_LEFT + +BACKGROUND_COLOR = {0,0,0,70} + +SCROLL_BOTTOM = 225 +SCROLL_SIZE = 216 +KEYBOARD_SIZE = 5 + +KEYBOARD_TOP = SCROLL_BOTTOM +KEYBOARD_BOTTOM = SCROLL_BOTTOM + KEYBOARD_SIZE + +KEYBOARD_FILLS = ({[0]="white","black","white","black","white","white","black","white","black","white","black","white"}) + + +-- FCEUX 2.2.2 pitch fixes + +SHORT_FIX_DOWN = 12 * ( math.log(93/2) / math.log(2) ) +DPCM_FIX_DOWN = 12 * ( math.log(11) / math.log(2) ) + + +function round(x) + return math.floor( x + .5 ) +end + +function Scale(x) + temp = math.floor ( (x - MIDI_LEFT) * SCREEN_RANGE / MIDI_RANGE + .5 ) + if (temp < SCREEN_LEFT) then temp = SCREEN_LEFT + elseif (temp > SCREEN_RIGHT) then temp = SCREEN_RIGHT + end + return temp +end + +WIDTH = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2} + +COLOR = {[0]="P39", [1]="P15", [2]="P2C", [3]="P15", ["triangle"]="P12", ["noise-short"]="P30", ["noise-long"]="P10", ["dpcm"]="P1A", ["dpcm-melodic"]="P2A" } + + +function Reset() + + history = {} + previous_frame = emu.framecount() - 1 + + + -- Set up DPCM visualization function + + hash = rom.gethash("md5") + + if (hash == "d4782e6bbf337f075174345fe4848983") then -- My demo + + DELTAS_PERIOD = 64 + DPCM_KEY_DOWN = 12 * (math.log(DELTAS_PERIOD)/math.log(2)) + DPCM_KEY_DOWN = DPCM_KEY_DOWN + DPCM_FIX_DOWN + + DPCM_Function = function() + if(snd.dpcm.volume > 0) then + if (snd.dpcm.dmcaddress == 0xC000) then + dpcm_key = Scale(snd.dpcm.midikey - DPCM_KEY_DOWN) + dpcm_color = COLOR["dpcm-melodic"] + dpcm_width = WIDTH[8] + else + dpcm_key = Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency) + dpcm_color = COLOR["dpcm"] + dpcm_width = WIDTH[8] + end + return {dpcm_key, dpcm_color, dpcm_width} + else + return nil + end + end + + elseif (hash == "e02c7c510e0e37b1f2711103fff9e58a") then -- Ikinari Musician + + DELTAS_PERIOD = 64 + DPCM_KEY_DOWN = 12 * (math.log(DELTAS_PERIOD)/math.log(2)) + DPCM_KEY_DOWN = DPCM_KEY_DOWN + DPCM_FIX_DOWN + + DPCM_Function = function() + if(snd.dpcm.volume > 0) then + if (snd.dpcm.dmcaddress == 0xFF00) then + dpcm_key = Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency) + dpcm_color = COLOR["dpcm"] + dpcm_width = WIDTH[round((snd.dpcm.dmcseed/127)*14)+1] + elseif (snd.dpcm.dmcaddress == 0xFF80) then + dpcm_key = Scale(snd.dpcm.midikey - DPCM_KEY_DOWN) + dpcm_color = COLOR["dpcm-melodic"] + dpcm_width = WIDTH[8] + end + return {dpcm_key, dpcm_color, dpcm_width} + else + return nil + end + end + + else -- Default DPCM + + previous_seed = sound.get().rp2a03.dpcm.dmcseed + + DPCM_Function = function() + if(snd.dpcm.volume > 0) then + previous_seed = snd.dpcm.dmcseed + return {Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency), COLOR["dpcm"], WIDTH[8]} + elseif ( snd.dpcm.dmcseed ~= previous_seed) then + seed_change = math.abs(previous_seed - snd.dpcm.dmcseed) + previous_seed = snd.dpcm.dmcseed + return {Scale(MIDI_LEFT + 17), COLOR["dpcm"], (math.floor(((seed_change-1)/127)*3))} + else + return nil + end + end + + end + +end + + +function Draw() + if(emu.framecount() - previous_frame ~= 1) then Reset() end + previous_frame = emu.framecount() + + gui.box(0,0,255,239,BACKGROUND_COLOR) + + snd = sound.get().rp2a03 + + if(snd.square1.volume > 0) then + c1 = {Scale(snd.square1.midikey),COLOR[snd.square1.duty], WIDTH[math.floor(15*snd.square1.volume)]} + else + c1 = nil + end + + if(snd.square2.volume > 0) then + c2 = {Scale(snd.square2.midikey),COLOR[snd.square2.duty], WIDTH[math.floor(15*snd.square2.volume)]} + else + c2 = nil + end + + if((snd.triangle.volume > 0) and (snd.triangle.regs.frequency > 1)) then + c3 = {Scale(snd.triangle.midikey),COLOR["triangle"], WIDTH[8]} + else + c3 = nil + end + + if(snd.noise.volume > 0) then + if(snd.noise.short) then + noise_key = Scale(snd.noise.midikey - SHORT_FIX_DOWN) + noise_color = COLOR["noise-short"] + else + noise_key = Scale(MIDI_LEFT + 16 - snd.noise.regs.frequency) + noise_color = COLOR["noise-long"] + end + + c4 = {noise_key, noise_color, WIDTH[math.floor(15*snd.noise.volume)]} + else + c4 = nil + end + + c5 = DPCM_Function() + + table.insert(history, 1, {c1,c2,c3,c4,c5}) + table.remove(history, SCROLL_SIZE) + + -- draw keyboard + + for i = MIDI_LEFT,MIDI_RIGHT do + fill = KEYBOARD_FILLS[i%12] + left = Scale(i - .5) + right = Scale(i + .5) + gui.box(left,KEYBOARD_TOP,right,KEYBOARD_BOTTOM,fill,"gray") + end + + -- draw notes + + for i = 1, #history do + for j = 1, 5 do + if(type(history[i][j]) ~= "nil") then + x = history[i][j][1] + y = SCROLL_BOTTOM - i + c = history[i][j][2] + w = history[i][j][3] + gui.box(x-w-1,y-1,x+w+1,y,"black") + gui.line(x-w,y,x+w,y,c) + end + end + end + +end + +Reset() +emu.registerafter(Draw) + +emu.print( " blue = triangle gray = noise, long*") +emu.print( " cyan = pulse, 1/2 white = noise, short") +emu.print( " red = pulse, 1/4 dk gn = dpcm, non-periodic*") +emu.print( " yellow = pulse, 1/8 green = dpcm, periodic") +emu.print( "") +emu.print( "* percussive frequencies shown as 16 lowest pitches") +