Skip to content

Instantly share code, notes, and snippets.

@shirriff
Last active December 23, 2021 21:13
Show Gist options
  • Save shirriff/b06676f3a909dec01a373cf7d1903611 to your computer and use it in GitHub Desktop.
Save shirriff/b06676f3a909dec01a373cf7d1903611 to your computer and use it in GitHub Desktop.
UM66T sound chip analysis program
# This code prints out the melody in the UM66T sound chip's ROM.
# The ROM holds Jingle Bells, Santa Claus is Coming to Town, and We Wish You a Merry Christmas.
# See this Twitter thread for details: https://twitter.com/kenshirriff/status/1472297415201869831
from collections import defaultdict
notes = ['X', 'X', 'G4', 'A5', 'B5', 'C5', 'D5', 'E5', 'F5', 'G5', 'A6', 'B6', 'C6', 'X', 'X', 'X']
# Hard-coded ROM contents.
bits = {"24,1":0,"15,0":1,"15,1":0,"15,3":1,"15,4":0,"14,4":1,"13,4":0,"12,4":1,"11,4":0,"10,4":1,"9,4":1,"8,4":0,"7,4":0,"6,4":1,"5,4":1,"4,4":0,"0,4":0,"1,4":1,"2,4":1,"3,4":0,"0,1":1,"0,0":1,"3,0":1,"4,0":1,"7,0":1,"8,0":1,"11,0":1,"12,0":1,"17,0":1,"19,0":1,"20,0":1,"23,0":1,"25,0":1,"26,0":1,"29,0":1,"31,0":1,"30,1":1,"28,1":1,"26,1":1,"25,1":1,"22,1":1,"21,1":1,"18,1":1,"17,1":1,"30,5":1,"31,6":1,"30,8":1,"30,9":1,"30,10":1,"31,11":1,"31,13":1,"31,14":1,"30,15":1,"31,16":1,"30,18":1,"30,19":1,"31,20":1,"31,21":1,"30,23":1,"31,24":1,"31,25":1,"31,26":1,"31,28":1,"30,29":1,"30,28":0,"29,26":1,"29,25":1,"29,24":1,"29,23":1,"29,21":1,"29,20":1,"29,19":1,"29,18":1,"29,16":1,"28,15":1,"29,14":1,"28,13":1,"29,11":1,"28,10":1,"28,8":0,"29,8":1,"28,9":1,"29,6":1,"28,5":1,"28,4":1,"28,3":1,"27,3":1,"27,4":1,"27,5":1,"26,6":1,"26,8":1,"26,9":1,"27,10":1,"27,11":1,"26,13":1,"27,14":1,"27,15":1,"27,16":1,"27,18":1,"26,19":1,"27,20":1,"26,21":1,"27,23":1,"27,24":0,"26,24":1,"26,25":1,"27,26":1,"26,28":1,"27,29":1,"25,29":1,"25,28":1,"25,26":1,"24,24":1,"25,25":1,"24,23":1,"24,21":1,"24,20":1,"24,19":1,"25,18":1,"24,16":1,"24,15":1,"24,14":1,"25,13":1,"24,11":1,"24,10":1,"25,9":1,"24,8":1,"25,6":1,"24,5":1,"24,4":1,"24,3":1,"23,3":1,"22,4":1,"22,5":1,"23,6":1,"23,8":1,"23,9":1,"22,10":1,"22,11":1,"22,13":1,"23,14":1,"22,15":1,"22,16":1,"23,18":1,"23,19":1,"22,20":1,"23,21":1,"23,23":1,"22,24":1,"23,25":1,"23,26":1,"22,28":1,"23,29":1,"21,29":1,"21,28":1,"20,26":1,"20,25":1,"20,24":1,"20,23":1,"20,21":1,"20,20":1,"20,19":1,"20,18":1,"20,16":1,"20,15":1,"21,14":1,"20,13":1,"21,11":1,"21,10":1,"21,9":1,"21,8":1,"20,6":1,"21,5":1,"20,4":1,"20,3":1,"19,3":1,"19,4":1,"18,5":1,"19,6":1,"18,7":0,"18,8":1,"18,9":1,"19,10":1,"19,11":1,"19,13":1,"18,14":1,"18,15":1,"18,16":1,"18,18":1,"18,19":1,"19,20":1,"18,21":1,"19,23":1,"19,24":1,"19,25":1,"19,26":1,"19,28":1,"18,29":1,"17,29":1,"16,28":1,"17,26":1,"16,25":1,"16,24":1,"16,23":1,"16,21":1,"16,20":1,"17,19":1,"16,18":1,"17,16":1,"17,15":1,"16,14":1,"17,13":1,"16,11":1,"16,10":1,"17,9":1,"17,8":1,"16,6":1,"16,5":1,"16,4":1,"16,2":0,"16,3":1,"14,1":1,"14,5":1,"15,6":1,"14,8":1,"15,9":1,"14,10":1,"15,11":1,"14,13":1,"15,14":1,"14,15":1,"15,16":1,"14,18":1,"14,19":1,"15,20":1,"15,21":1,"15,23":1,"15,24":1,"15,25":1,"15,26":1,"15,28":1,"14,29":1,"13,29":1,"12,28":1,"12,26":1,"14,25":0,"13,25":1,"12,24":1,"12,23":1,"12,21":1,"12,20":1,"13,19":1,"12,19":0,"12,18":1,"13,16":1,"13,15":1,"13,14":1,"13,13":1,"13,11":1,"13,10":1,"13,9":1,"13,8":1,"13,6":1,"13,5":1,"12,3":1,"12,1":1,"11,1":1,"11,3":1,"10,5":1,"10,6":1,"10,8":1,"11,9":1,"10,10":1,"11,11":1,"10,13":1,"11,14":1,"10,15":1,"10,16":1,"11,18":1,"11,19":1,"11,20":1,"10,21":1,"11,23":1,"10,24":1,"11,25":1,"11,26":1,"10,28":1,"11,29":1,"9,29":1,"8,28":1,"8,26":1,"8,25":1,"8,24":1,"9,23":1,"8,21":1,"8,20":1,"8,19":1,"9,18":1,"9,19":0,"8,16":1,"9,15":1,"8,14":1,"9,13":1,"9,11":1,"9,10":1,"8,9":1,"8,8":1,"9,6":1,"9,5":1,"8,3":1,"8,1":1,"6,1":1,"7,3":1,"6,5":1,"7,6":1,"6,8":1,"7,9":1,"6,10":1,"7,11":1,"7,13":1,"7,14":1,"6,15":1,"7,16":1,"7,18":1,"6,19":1,"7,20":1,"7,21":1,"7,23":1,"7,24":1,"6,25":1,"7,26":1,"7,28":1,"7,29":1,"4,29":1,"4,28":1,"4,26":1,"5,25":0,"4,24":1,"4,23":1,"4,21":1,"4,20":1,"4,19":1,"5,18":1,"5,16":1,"5,15":1,"5,14":1,"4,13":1,"4,11":1,"5,10":1,"4,9":1,"5,8":1,"5,6":0,"5,5":1,"4,3":1,"5,1":1,"2,1":1,"3,3":1,"2,5":1,"3,6":1,"3,8":0,"3,9":1,"2,10":1,"3,11":1,"3,12":0,"2,13":1,"3,14":1,"2,15":1,"2,16":1,"3,18":1,"2,19":1,"3,20":1,"3,21":1,"3,23":1,"2,24":1,"3,25":1,"3,26":1,"3,28":1,"3,29":1,"1,29":1,"0,28":1,"1,26":1,"0,25":1,"0,24":1,"0,23":1,"0,21":1,"0,20":1,"1,19":1,"1,18":1,"1,16":1,"1,15":1,"0,14":1,"1,13":0,"1,11":1,"0,10":1,"0,9":1,"1,8":1,"1,6":1,"0,5":1,"0,3":1,"29,29":1,"29,28":1,"1,0":0,"31,3":1,"31,4":1,"0,13":1,"2,8":1,"4,6":1,"4,25":1}
def get(x, y):
return int(bits.get('%d,%d' % (x, y), 0))
def dump1():
row = 0
for y in range(0, 30):
# The ROM row numbering includes the spacer rows, so skip over those.
if y in [2, 7, 12, 17, 22, 27]: continue
print(y, end=" ")
for x in range(0, 32, 2):
x0 = get(x, y)
x1 = get(x + 1, y)
if x0 != x1:
print(x0, end="")
else:
print('***')
print()
row += 1
def dump2():
yidx = [[0 + 5 * k, 1 + 5 * k, 4 + 5 * k, 3 + 5 * k] for k in range(0, 6)]
for n in range(0, 64):
xc = n % 16
yc = n >> 4
def get2(x, y):
if x % 2:
return get(2 * x, y)
else:
return get(2 * x + 1, y)
bitsn = [get2(xc, yidx[i][yc]) for i in range(0, 4)]
bitsdur = [get2(xc, yidx[i][yc]) for i in range(4, 6)]
bitsn_s = ''.join(map(str, bitsn))
bitsdur_s = ''.join(map(str, bitsdur))
n = bitsn[0] * 8 + bitsn[1] * 4 + bitsn[2] * 2 + bitsn[3]
print(n, notes[n], bitsn_s, bitsdur_s)
dump2()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment