207 lines
5.6 KiB
Lua
207 lines
5.6 KiB
Lua
-- 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")
|
|
|