Compare commits
No commits in common. "main" and "sky-scroll" have entirely different histories.
main
...
sky-scroll
15
.gitignore
vendored
|
|
@ -2,13 +2,8 @@
|
||||||
loader/build
|
loader/build
|
||||||
loader/tools/cc1541/cc1541
|
loader/tools/cc1541/cc1541
|
||||||
|
|
||||||
loader/samples/minexample/**/*.bak
|
loader/samples/minexample/*.bak
|
||||||
loader/samples/minexample/**/*.o
|
loader/samples/minexample/*.o
|
||||||
loader/samples/minexample/**/*.zx0.prg
|
loader/samples/minexample/*.zx0.prg
|
||||||
loader/samples/minexample/**/*.lz.prg
|
loader/samples/minexample/*.lz.prg
|
||||||
loader/samples/minexample/**/*.tmp
|
loader/samples/minexample/*.tmp
|
||||||
loader/samples/minexample/main.zx0
|
|
||||||
loader/samples/minexample/song0.bin
|
|
||||||
loader/samples/minexample/song1.bin
|
|
||||||
loader/samples/minexample/font.prg
|
|
||||||
loader/samples/minexample/test/*.prg
|
|
||||||
|
|
|
||||||
|
|
@ -1,423 +1,66 @@
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
50,ys2/11_lilia_final/koala/png/01.png
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
20,ys2/11_lilia_final/koala/png/04.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/05.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/06.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/07.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/06.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/05.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
3,ys2/11_lilia_final/koala/png/04.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
|
|
||||||
6,../../../assets/ys2/11_lilia_final/koala/png/04.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/05.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/06.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/07.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/06.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/05.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/04.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
3,ys2/11_lilia_final/koala/png/08.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
3,ys2/11_lilia_final/koala/png/09.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
3,ys2/11_lilia_final/koala/png/10.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
3,ys2/11_lilia_final/koala/png/11.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
3,ys2/11_lilia_final/koala/png/10.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
3,ys2/11_lilia_final/koala/png/09.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
3,ys2/11_lilia_final/koala/png/08.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
7,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
7,ys2/11_lilia_final/koala/png/03.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
7,ys2/11_lilia_final/koala/png/02.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
50,ys2/11_lilia_final/koala/png/01.png
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/08.png
|
3,ys2/11_lilia_final/koala/png/12.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/09.png
|
3,ys2/11_lilia_final/koala/png/13.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/10.png
|
3,ys2/11_lilia_final/koala/png/14.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/11.png
|
3,ys2/11_lilia_final/koala/png/15.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/10.png
|
200,ys2/11_lilia_final/koala/png/16.png
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/09.png
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/08.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
6,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/01.png
|
|
||||||
1,../../../assets/ys2/11_lilia_final/koala/png/02.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/03b.png
|
|
||||||
3,../../../assets/ys2/11_lilia_final/koala/png/02b.png
|
|
||||||
20,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/13.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/14.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/15.png
|
|
||||||
2,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
10,../../../assets/ys2/11_lilia_final/koala/png/16.png
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -bpc 0,6,14,-1 -o ../loader/samples/minexample/badguy.bin 01_badguyz_cut.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/badguy.bin 01_badguyz_cut.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/tower_beam.bin 04_tower_beam.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/tower_beam.bin 04_tower_beam.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/tower.bin 03_tower.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/tower.bin 03_tower.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/lilia_hero.bin ys2/08_lilia_hero/koala/png/01.png
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/lilia_hero.bin ys2/08_lilia_hero/koala/png/01.png
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/lilia.bin lilia.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/lilia.bin lilia.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/field.bin 05_field_will_loop.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/field.bin 05_field_will_loop.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/falling_star.bin 06_falling_star.csv
|
../png2prg/png2prg_darwin_arm64 -m koala -o ../loader/samples/minexample/falling_star.bin 06_falling_star.csv
|
||||||
../png2prg/png2prg_darwin_arm64 -m koala -bpc 0,-1,-1,-1 -o ../loader/samples/minexample/lilia_talk.bin 11_lilia_final.csv
|
|
||||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 689 B After Width: | Height: | Size: 721 B |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 856 B After Width: | Height: | Size: 892 B |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 6.8 KiB |
|
|
@ -97,7 +97,6 @@ C1541 = c1541
|
||||||
CC1541 = ../../tools/cc1541/cc1541
|
CC1541 = ../../tools/cc1541/cc1541
|
||||||
ZX02 = zx02/build/zx02
|
ZX02 = zx02/build/zx02
|
||||||
ZX02_SRC = zx02
|
ZX02_SRC = zx02
|
||||||
FURC64 = furC64
|
|
||||||
PYTHON = python3
|
PYTHON = python3
|
||||||
|
|
||||||
MKDIR = mkdir -p
|
MKDIR = mkdir -p
|
||||||
|
|
@ -116,7 +115,7 @@ CAT = cat
|
||||||
|
|
||||||
BUILDDIR = ../../build
|
BUILDDIR = ../../build
|
||||||
INTERMDIR = ../../build/intermediate
|
INTERMDIR = ../../build/intermediate
|
||||||
LOADER_SRC = ../..
|
LOADER_SRC = ../../src
|
||||||
LOADER = $(BUILDDIR)/loader-$(_PLATFORM_).prg
|
LOADER = $(BUILDDIR)/loader-$(_PLATFORM_).prg
|
||||||
|
|
||||||
RESOURCESDIR = ../resources
|
RESOURCESDIR = ../resources
|
||||||
|
|
@ -131,8 +130,6 @@ DISKIMAGE = $(BUILDDIR)/$(NAME)-$(_PLATFORM_).d64
|
||||||
AS_FLAGS = -Wa -I../../../shared -I ../../include -u __EXEHDR__
|
AS_FLAGS = -Wa -I../../../shared -I ../../include -u __EXEHDR__
|
||||||
|
|
||||||
ZX0PRGS = \
|
ZX0PRGS = \
|
||||||
song0.zx0.prg \
|
|
||||||
song1.zx0.prg \
|
|
||||||
badguy.zx0.prg \
|
badguy.zx0.prg \
|
||||||
title_320-prepared.zx0.prg \
|
title_320-prepared.zx0.prg \
|
||||||
tower.zx0.prg \
|
tower.zx0.prg \
|
||||||
|
|
@ -141,12 +138,10 @@ ZX0PRGS = \
|
||||||
falling_star.zx0.prg \
|
falling_star.zx0.prg \
|
||||||
lilia.zx0.prg \
|
lilia.zx0.prg \
|
||||||
lilia_hero.zx0.prg \
|
lilia_hero.zx0.prg \
|
||||||
island.zx0.prg \
|
sky_scroll.zx0.prg
|
||||||
clouds.zx0.prg \
|
|
||||||
lilia_talk.zx0.prg
|
|
||||||
|
|
||||||
LZPRGS = \
|
LZPRGS = \
|
||||||
island_map.lz.prg
|
sky_scroll_map.lz.prg
|
||||||
|
|
||||||
|
|
||||||
default: diskimage
|
default: diskimage
|
||||||
|
|
@ -164,7 +159,7 @@ $(LOADER): $(LOADERCFG)
|
||||||
|
|
||||||
assemble: $(ASSEMBLE)
|
assemble: $(ASSEMBLE)
|
||||||
|
|
||||||
$(ASSEMBLE): $(SOURCE) $(LOADER) main.zx0
|
$(ASSEMBLE): $(SOURCE) $(LOADER) $(LOADERCFG)
|
||||||
$(MKDIR) $(BUILDDIR)
|
$(MKDIR) $(BUILDDIR)
|
||||||
$(MKDIR) $(INTERMDIR)
|
$(MKDIR) $(INTERMDIR)
|
||||||
ifeq ($(_PLATFORM_),c64)
|
ifeq ($(_PLATFORM_),c64)
|
||||||
|
|
@ -178,14 +173,13 @@ endif
|
||||||
|
|
||||||
diskimage: $(DISKIMAGE)
|
diskimage: $(DISKIMAGE)
|
||||||
|
|
||||||
$(DISKIMAGE): $(ASSEMBLE) $(CC1541) $(ZX0PRGS) $(LZPRGS) font.prg
|
$(DISKIMAGE): $(ASSEMBLE) $(CC1541) $(ZX0PRGS) $(LZPRGS)
|
||||||
$(RM) $@
|
$(RM) $@
|
||||||
$(CC1541) -n "otomata labs" -i " 2025" \
|
$(CC1541) -n "otomata labs" -i " 2025" \
|
||||||
-f "ys2intro" -w $< \
|
-f "ys2intro" -w $< \
|
||||||
-f "song0" -w song0.zx0.prg \
|
-f "sid" -w use_this_sid.bin \
|
||||||
-f "song1" -w song1.zx0.prg \
|
|
||||||
-f "badguy" -w badguy.zx0.prg \
|
-f "badguy" -w badguy.zx0.prg \
|
||||||
-f "font" -w font.prg \
|
-f "font" -w font.bin \
|
||||||
-f "intrbmp" -w title_320-prepared.zx0.prg \
|
-f "intrbmp" -w title_320-prepared.zx0.prg \
|
||||||
-f "tower" -w tower.zx0.prg \
|
-f "tower" -w tower.zx0.prg \
|
||||||
-f "towerbm" -w tower_beam.zx0.prg \
|
-f "towerbm" -w tower_beam.zx0.prg \
|
||||||
|
|
@ -193,10 +187,8 @@ $(DISKIMAGE): $(ASSEMBLE) $(CC1541) $(ZX0PRGS) $(LZPRGS) font.prg
|
||||||
-f "fallstar" -w falling_star.zx0.prg \
|
-f "fallstar" -w falling_star.zx0.prg \
|
||||||
-f "lilia" -w lilia.zx0.prg \
|
-f "lilia" -w lilia.zx0.prg \
|
||||||
-f "lilhero" -w lilia_hero.zx0.prg \
|
-f "lilhero" -w lilia_hero.zx0.prg \
|
||||||
-f "island" -w island.zx0.prg \
|
-f "skyscr" -w sky_scroll.zx0.prg \
|
||||||
-f "islandmap" -w island_map.lz.prg \
|
-f "skyscrmap" -w sky_scroll_map.lz.prg \
|
||||||
-f "clouds" -w clouds.zx0.prg \
|
|
||||||
-f "liltalk" -w lilia_talk.zx0.prg \
|
|
||||||
$@
|
$@
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -211,6 +203,9 @@ run71: $(DISKIMAGE)
|
||||||
$(EMU71) $(realpath $^)
|
$(EMU71) $(realpath $^)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(INTERMDIR)/%.prg: $(RESOURCESDIR)/%.bin
|
||||||
|
$(PRINTF) '\000\140' | $(CAT) - $? > $@ # octal 140 = hex 60
|
||||||
|
|
||||||
$(CC1541):
|
$(CC1541):
|
||||||
make -C $(LOADER_SRC) cc1541
|
make -C $(LOADER_SRC) cc1541
|
||||||
|
|
||||||
|
|
@ -219,31 +214,14 @@ $(ZX02):
|
||||||
|
|
||||||
%.zx0.prg: %.bin $(ZX02)
|
%.zx0.prg: %.bin $(ZX02)
|
||||||
$(ZX02) $< $@.tmp
|
$(ZX02) $< $@.tmp
|
||||||
$(PRINTF) "\000\200" | $(CAT) - $@.tmp > $@
|
$(PRINTF) "\x00\x80" | cat - $@.tmp > $@
|
||||||
$(RM) $@.tmp
|
$(RM) $@.tmp
|
||||||
|
|
||||||
%.lz.prg: %.bin
|
%.lz.prg: %.bin
|
||||||
$(PYTHON) aart_lz.py $< $@.tmp
|
$(PYTHON) aart_lz.py $< $@.tmp
|
||||||
$(PRINTF) "\000\220" | $(CAT) - $@.tmp > $@
|
$(PRINTF) "\x00\x90" | cat - $@.tmp > $@
|
||||||
$(RM) $@.tmp
|
$(RM) $@.tmp
|
||||||
|
|
||||||
main.zx0: main.asm
|
|
||||||
$(RM) $@
|
|
||||||
$(AS) -t c64 -C bin.cfg -o $@.tmp $<
|
|
||||||
$(ZX02) $@.tmp $@
|
|
||||||
$(RM) $@.tmp
|
|
||||||
|
|
||||||
song0.bin: ys2_fixed_drums.fur
|
|
||||||
cd $(FURC64) && ./convert.sh $(abspath $<)
|
|
||||||
cp $(FURC64)/asm/song.bin $@
|
|
||||||
|
|
||||||
song1.bin: ys2_lilia_sid.fur
|
|
||||||
cd $(FURC64) && ./convert.sh $(abspath $<)
|
|
||||||
cp $(FURC64)/asm/song.bin $@
|
|
||||||
|
|
||||||
font.prg: test/main.asm font.bin #test/logo.bin test/txtbg.bin
|
|
||||||
$(AS) -t c64 -C test/bin.cfg -o $@ $<
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-$(RM) $(ZX0PRGS) $(LZPRGS)
|
-$(RM) $(ZX0PRGS) $(LZPRGS)
|
||||||
-$(RM) *.o $(ASSEMBLE) $(DISKIMAGE)
|
-$(RM) *.o $(ASSEMBLE) $(DISKIMAGE)
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
MEMORY {
|
|
||||||
ZP: file = "", start = $0002, size = $00FE, define = yes;
|
|
||||||
MAIN: file = %O, start = $E000, size = $1FFA;
|
|
||||||
}
|
|
||||||
SEGMENTS {
|
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
|
||||||
CODE: load = MAIN, type = rw;
|
|
||||||
RODATA: load = MAIN, type = ro, optional = yes;
|
|
||||||
DATA: load = MAIN, type = rw, optional = yes;
|
|
||||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
rm lilia_talk*.*
|
|
||||||
../../../assets/png2prg_linux_amd64 -m koala -o lilia_talk.bin ../../../assets/11_lilia_final.csv
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
f = open("liltalk_speak.txt","r").readlines()
|
|
||||||
f = [x[:-1] for x in f]
|
|
||||||
|
|
||||||
line_addrs = []
|
|
||||||
char_cnt = 0
|
|
||||||
for line in f:
|
|
||||||
if line == '':
|
|
||||||
line_addrs.append(char_cnt)
|
|
||||||
char_cnt = 0
|
|
||||||
else:
|
|
||||||
num = 0
|
|
||||||
i = 0
|
|
||||||
while i < len(line) and line[i] in "0123456789":
|
|
||||||
num = num*10+int(line[i])
|
|
||||||
i += 1
|
|
||||||
str = line[i+1:]
|
|
||||||
str = str.upper()
|
|
||||||
if "\\N" in str: str = str.split("\\N")[0]
|
|
||||||
print(str)
|
|
||||||
#str = str.replace("\\N","")
|
|
||||||
char_cnt += len(str)
|
|
||||||
line_addrs.append(char_cnt)
|
|
||||||
|
|
||||||
out = [0xFE, (40-line_addrs[0])//2]
|
|
||||||
cnt = 1
|
|
||||||
for line in f:
|
|
||||||
if line == '':
|
|
||||||
out.append(0xFE) # set line addr to beginning
|
|
||||||
out.append((40-line_addrs[cnt])//2)
|
|
||||||
cnt += 1
|
|
||||||
else:
|
|
||||||
num = 0
|
|
||||||
i = 0
|
|
||||||
while i < len(line) and line[i] in "0123456789":
|
|
||||||
num = num*10+int(line[i])
|
|
||||||
i += 1
|
|
||||||
str = line[i+1:]
|
|
||||||
str = str.upper()
|
|
||||||
str = str.replace("\\N","\n")
|
|
||||||
out.append(num)
|
|
||||||
out.append(len(str))
|
|
||||||
for x in str: out.append(ord(x))
|
|
||||||
out.append(0xFF)
|
|
||||||
|
|
||||||
f = open("liltalk.bin","wb")
|
|
||||||
f.write(bytearray(out))
|
|
||||||
f.close()
|
|
||||||
8
loader/samples/minexample/furC64/.gitignore
vendored
|
|
@ -1,8 +0,0 @@
|
||||||
__pycache__
|
|
||||||
asm/song.asm
|
|
||||||
asm/song.bin
|
|
||||||
*.o
|
|
||||||
*.lbl
|
|
||||||
*.lst
|
|
||||||
*.map
|
|
||||||
*.prg
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
# furC64
|
|
||||||
a C64/SID sound driver for Furnace
|
|
||||||
|
|
||||||
### **THIS SOUND DRIVER IS CURRENTLY A WIP**
|
|
||||||
|
|
||||||
A SID driver that's easy to make music with? It's more likely than you think.
|
|
||||||
|
|
||||||
* You have to have [Python](https://www.python.org/) and the [CC65 toolchain](https://cc65.github.io/) installed
|
|
||||||
* You **have** to set the pitch linearity option to "None". You can do this by going to `window -> song -> compatability flags -> Pitch/Playback -> Pitch linearity` and then setting the option to "None".
|
|
||||||
|
|
||||||
* The driver only supports **arpeggio, waveform, duty and cutoff** macros in each instrument and it DOESN'T support LFO and ADSR macros nor delay and step length, **although you can use LFO macros in the duty and cutoff macros (as in range-sweeping)**
|
|
||||||
|
|
||||||
* The furC64 driver only supports these effects:
|
|
||||||
* 00xx: arpeggio
|
|
||||||
* 01xx: pitch slide up
|
|
||||||
* 02xx: pitch slide down
|
|
||||||
* 03xx: portamento
|
|
||||||
* 04xx: vibrato
|
|
||||||
* 09xx: set speed 1
|
|
||||||
* 0Bxx: jump to pattern
|
|
||||||
* 0Dxx: jump to next pattern
|
|
||||||
* 0Fxx: set speed 2
|
|
||||||
* 1Axx: disable/enable envelope reset
|
|
||||||
* 1Bxx: reset cutoff
|
|
||||||
* 1Cxx: reset pulse-width
|
|
||||||
* 4xxx: set filter cutoff
|
|
||||||
* E1xx: note slide up
|
|
||||||
* E2xx: note slide down
|
|
||||||
* E5xx: note fine-pitch
|
|
||||||
* EAxx: legato
|
|
||||||
* ECxx: note cut
|
|
||||||
|
|
||||||
when you've finished / want to test out this driver:
|
|
||||||
* open the terminal/command prompt **to the furC64 directory**
|
|
||||||
* run `convert.sh your_fur_file.fur` or `convert.bat file.fur` (depending on your OS)
|
|
||||||
* in the `furC64/asm` directory you'll hopefully see a file called **`furC64-test.prg`**
|
|
||||||
* that's your .prg file that you can run on hardware or on an emulator like VICE!
|
|
||||||
|
|
||||||
Hopefully you'll have fun with this driver alongside [furNES](https://github.com/AnnoyedArt1256/furNES) :D
|
|
||||||
|
|
||||||
Libraries used: chipchune
|
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
FEATURES {
|
|
||||||
STARTADDRESS: default = $0801;
|
|
||||||
}
|
|
||||||
MEMORY {
|
|
||||||
ZP: file = "", start = $0002, size = $00FE, define = yes;
|
|
||||||
MAIN: file = "", start = %S, size = $A000 - %S;
|
|
||||||
PLAYER: file = %O, start = $A000, size = $5FFA;
|
|
||||||
}
|
|
||||||
SEGMENTS {
|
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
|
||||||
CODE: load = MAIN, type = rw;
|
|
||||||
RODATA: load = MAIN, type = ro, optional = yes;
|
|
||||||
DATA: load = MAIN, type = rw, optional = yes;
|
|
||||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
|
||||||
PLAYER: load = PLAYER, type = rw, define = yes;
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
FEATURES {
|
|
||||||
STARTADDRESS: default = $0801;
|
|
||||||
}
|
|
||||||
SYMBOLS {
|
|
||||||
__LOADADDR__: type = import;
|
|
||||||
}
|
|
||||||
MEMORY {
|
|
||||||
ZP: file = "", start = $0002, size = $00FE, define = yes;
|
|
||||||
LOADADDR: file = %O, start = %S - 2, size = $0002;
|
|
||||||
MAIN: file = %O, start = %S, size = $A000 - %S;
|
|
||||||
PLAYER: file = %O, start = $A000, size = $5FFA;
|
|
||||||
}
|
|
||||||
SEGMENTS {
|
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
|
||||||
LOADADDR: load = LOADADDR, type = ro;
|
|
||||||
EXEHDR: load = MAIN, type = ro, optional = yes;
|
|
||||||
CODE: load = MAIN, type = rw;
|
|
||||||
RODATA: load = MAIN, type = ro, optional = yes;
|
|
||||||
DATA: load = MAIN, type = rw, optional = yes;
|
|
||||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
|
||||||
PLAYER: load = MAIN, run = PLAYER, type = rw, define = yes;
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
"$')+.147:>AEINRW\bhnu|<7C><><EFBFBD><EFBFBD>ク皇俑褻<E4BF91>
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
&8K^s‰¡¹Ôð
,Mq–½çBs¨àY›â,{Î'„çQÀ6³7ÄYö<59>N Ï¢<C38F>mgoˆ²í:œŸDÚÎßdÚu8&?‰´œ¿"È´ëqLh8E<7F>hÖã˜ÿ$ÿ
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
"""
|
|
||||||
:mod:`chipchune` is a Python library for manipulating several
|
|
||||||
different kinds of chiptune music files.
|
|
||||||
|
|
||||||
Currently supports:
|
|
||||||
- Furnace (:mod:`chipchune.furnace`) (almost!)
|
|
||||||
|
|
||||||
Plans to support:
|
|
||||||
- DefleMask (:mod:`chipchune.deflemask`)
|
|
||||||
- FamiTracker (:mod:`chipchune.famitracker`)
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
`pip install git+https://github.com/ZoomTen/chipchune@master`
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
__version__ = "0.0.1"
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
import struct
|
|
||||||
from enum import Enum
|
|
||||||
from typing import BinaryIO, Any, cast
|
|
||||||
import io
|
|
||||||
|
|
||||||
known_sizes = {
|
|
||||||
'c': 1,
|
|
||||||
'b': 1, 'B': 1,
|
|
||||||
'?': 1,
|
|
||||||
'h': 2, 'H': 2,
|
|
||||||
'i': 4, 'I': 4,
|
|
||||||
'l': 4, 'L': 4,
|
|
||||||
'q': 8, 'Q': 8,
|
|
||||||
'e': 2, 'f': 4,
|
|
||||||
'd': 8
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class EnumShowNameOnly(Enum):
|
|
||||||
"""
|
|
||||||
Just an Enum, except its string repr is
|
|
||||||
just the enum's name
|
|
||||||
"""
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.__repr__()
|
|
||||||
|
|
||||||
|
|
||||||
class EnumValueEquals(Enum):
|
|
||||||
"""
|
|
||||||
Enum that can be compared to its raw value.
|
|
||||||
"""
|
|
||||||
def __eq__(self, other: Any) -> bool:
|
|
||||||
return cast(bool, self.value == other)
|
|
||||||
|
|
||||||
|
|
||||||
def truthy_to_boolbyte(value: Any) -> bytes:
|
|
||||||
"""
|
|
||||||
If value is truthy, output b'\x01'. Else output b'\x00'.
|
|
||||||
|
|
||||||
:param value: anything
|
|
||||||
"""
|
|
||||||
if value:
|
|
||||||
return b'\x01'
|
|
||||||
else:
|
|
||||||
return b'\x00'
|
|
||||||
|
|
||||||
|
|
||||||
# these are just to make the typehinter happy
|
|
||||||
# cast(dolphin, foobar) should've been named trust_me_bro_im_a(dolphin, foobar)
|
|
||||||
|
|
||||||
|
|
||||||
def read_int(file: BinaryIO, signed: bool = False) -> int:
|
|
||||||
"""
|
|
||||||
4 bytes
|
|
||||||
"""
|
|
||||||
if signed:
|
|
||||||
return cast(int, struct.unpack('<i', file.read(known_sizes['i']))[0])
|
|
||||||
return cast(int, struct.unpack('<I', file.read(known_sizes['I']))[0])
|
|
||||||
|
|
||||||
|
|
||||||
def read_short(file: BinaryIO, signed: bool = False) -> int:
|
|
||||||
"""
|
|
||||||
2 bytes
|
|
||||||
"""
|
|
||||||
if signed:
|
|
||||||
return cast(int, struct.unpack('<h', file.read(known_sizes['h']))[0])
|
|
||||||
return cast(int, struct.unpack('<H', file.read(known_sizes['H']))[0])
|
|
||||||
|
|
||||||
|
|
||||||
def read_byte(file: BinaryIO, signed: bool = False) -> int:
|
|
||||||
"""
|
|
||||||
1 bytes
|
|
||||||
"""
|
|
||||||
if signed:
|
|
||||||
return cast(int, struct.unpack('<b', file.read(known_sizes['b']))[0])
|
|
||||||
return cast(int, struct.unpack('<B', file.read(known_sizes['B']))[0])
|
|
||||||
|
|
||||||
|
|
||||||
def read_float(file: BinaryIO) -> float:
|
|
||||||
"""
|
|
||||||
4 bytes
|
|
||||||
"""
|
|
||||||
return cast(float, struct.unpack('<f', file.read(known_sizes['f']))[0])
|
|
||||||
|
|
||||||
|
|
||||||
def read_str(file: BinaryIO) -> str:
|
|
||||||
"""
|
|
||||||
variable string (ends in \\x00)
|
|
||||||
"""
|
|
||||||
buffer = bytearray()
|
|
||||||
char = file.read(1)
|
|
||||||
while char != b'\x00':
|
|
||||||
buffer += char
|
|
||||||
char = file.read(1)
|
|
||||||
return buffer.decode('utf-8')
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
"""
|
|
||||||
soon!
|
|
||||||
"""
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
"""
|
|
||||||
soon!
|
|
||||||
"""
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
"""
|
|
||||||
Tools to manipulate Furnace .fur files.
|
|
||||||
|
|
||||||
- :mod:`chipchune.furnace.module`: Tools to inspect and manipulate module files.
|
|
||||||
- :mod:`chipchune.furnace.instrument`: Tools to inspect and manipulate instrument data from within or without the module.
|
|
||||||
- :mod:`chipchune.furnace.sample`: Tools to inspect and manipulate sample data (might be merged with inst?)
|
|
||||||
- :mod:`chipchune.furnace.wavetable`: Tools to inspect and manipulate wavetable data
|
|
||||||
- :mod:`chipchune.furnace.enums`: Various constants that apply to Furnace.
|
|
||||||
- :mod:`chipchune.furnace.data_types`: Various data types that apply to Furnace.
|
|
||||||
|
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
from chipchune.furnace.module import FurnaceModule
|
|
||||||
|
|
||||||
module = FurnaceModule("tests/samples/furnace/skate_or_die.143.fur")
|
|
||||||
|
|
||||||
pattern = module.get_pattern(0, 0, 0)
|
|
||||||
|
|
||||||
print(pattern.as_clipboard())
|
|
||||||
|
|
||||||
for row in pattern.data:
|
|
||||||
print(row)
|
|
||||||
"""
|
|
||||||
|
|
@ -1,706 +0,0 @@
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import Tuple, List, TypedDict, Any, Union, Dict
|
|
||||||
|
|
||||||
from .enums import (
|
|
||||||
ChipType, LinearPitch, LoopModality, DelayBehavior, JumpTreatment, InputPortSet, OutputPortSet,
|
|
||||||
InstrumentType, MacroCode, OpMacroCode, MacroType, MacroItem, GBHwCommand, WaveFX, ESFilterMode,
|
|
||||||
SNESSusMode, GainMode, Note
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# modules
|
|
||||||
@dataclass
|
|
||||||
class ChipInfo:
|
|
||||||
"""
|
|
||||||
Information on a single chip.
|
|
||||||
"""
|
|
||||||
type: ChipType
|
|
||||||
#: shall be a simple dict, no enums needed
|
|
||||||
flags: Dict[str, Any] = field(default_factory=dict)
|
|
||||||
panning: float = 0.0
|
|
||||||
surround: float = 0.0
|
|
||||||
"""
|
|
||||||
Chip front/rear balance.
|
|
||||||
"""
|
|
||||||
volume: float = 1.0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ModuleMeta:
|
|
||||||
"""
|
|
||||||
Module metadata.
|
|
||||||
"""
|
|
||||||
name: str = ''
|
|
||||||
name_jp: str = ''
|
|
||||||
author: str = ''
|
|
||||||
author_jp: str = ''
|
|
||||||
album: str = ''
|
|
||||||
"""
|
|
||||||
Can also be the game name or container name.
|
|
||||||
"""
|
|
||||||
album_jp: str = ''
|
|
||||||
sys_name: str = 'Sega Genesis/Mega Drive'
|
|
||||||
sys_name_jp: str = ''
|
|
||||||
comment: str = ''
|
|
||||||
version: int = 0
|
|
||||||
tuning: float = 440.0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class TimingInfo:
|
|
||||||
"""
|
|
||||||
Timing information for a single subsong.
|
|
||||||
"""
|
|
||||||
arp_speed = 1
|
|
||||||
clock_speed = 60.0
|
|
||||||
highlight: Tuple[int, int] = (4, 16)
|
|
||||||
speed: Tuple[int, int] = (0, 0)
|
|
||||||
timebase = 1
|
|
||||||
virtual_tempo: Tuple[int, int] = (150, 150)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ChipList:
|
|
||||||
"""
|
|
||||||
Information about chips used in the module.
|
|
||||||
"""
|
|
||||||
list: List[ChipInfo] = field(default_factory=list)
|
|
||||||
master_volume: float = 2.0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(repr=False)
|
|
||||||
class ChannelDisplayInfo:
|
|
||||||
"""
|
|
||||||
Relating to channel display in Pattern and Order windows.
|
|
||||||
"""
|
|
||||||
name: str = ''
|
|
||||||
abbreviation: str = ''
|
|
||||||
collapsed: bool = False
|
|
||||||
shown: bool = True
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return "ChannelDisplayInfo(name='%s', abbreviation='%s', collapsed=%s, shown=%s)" % (
|
|
||||||
self.name,
|
|
||||||
self.abbreviation,
|
|
||||||
self.collapsed,
|
|
||||||
self.shown
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class ModuleCompatFlags:
|
|
||||||
"""
|
|
||||||
Module compatibility flags, a.k.a. "The Motherload"
|
|
||||||
|
|
||||||
Default values correspond with fileOps.cpp in the furnace src.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# compat 1
|
|
||||||
|
|
||||||
limit_slides: bool = False
|
|
||||||
linear_pitch: LinearPitch = field(default_factory=lambda: LinearPitch.FULL_LINEAR)
|
|
||||||
loop_modality: LoopModality = field(default_factory=lambda: LoopModality.DO_NOTHING)
|
|
||||||
proper_noise_layout: bool = True
|
|
||||||
wave_duty_is_volume: bool = False
|
|
||||||
reset_macro_on_porta: bool = False
|
|
||||||
legacy_volume_slides: bool = False
|
|
||||||
compatible_arpeggio: bool = False
|
|
||||||
note_off_resets_slides: bool = True
|
|
||||||
target_resets_slides: bool = True
|
|
||||||
arpeggio_inhibits_portamento: bool = False
|
|
||||||
wack_algorithm_macro: bool = False
|
|
||||||
broken_shortcut_slides: bool = False
|
|
||||||
ignore_duplicates_slides: bool = False
|
|
||||||
stop_portamento_on_note_off: bool = False
|
|
||||||
continuous_vibrato: bool = False
|
|
||||||
broken_dac_mode: bool = False
|
|
||||||
one_tick_cut: bool = False
|
|
||||||
instrument_change_allowed_in_porta: bool = True
|
|
||||||
reset_note_base_on_arpeggio_stop: bool = True
|
|
||||||
|
|
||||||
# compat 2 (>= dev70)
|
|
||||||
|
|
||||||
broken_speed_selection: bool = False
|
|
||||||
no_slides_on_first_tick: bool = False
|
|
||||||
next_row_reset_arp_pos: bool = False
|
|
||||||
ignore_jump_at_end: bool = False
|
|
||||||
buggy_portamento_after_slide: bool = False
|
|
||||||
gb_ins_affects_env: bool = True
|
|
||||||
shared_extch_state: bool = True
|
|
||||||
ignore_outside_dac_mode_change: bool = False
|
|
||||||
e1e2_takes_priority: bool = False
|
|
||||||
new_sega_pcm: bool = True
|
|
||||||
weird_fnum_pitch_slides: bool = False
|
|
||||||
sn_duty_resets_phase: bool = False
|
|
||||||
linear_pitch_macro: bool = True
|
|
||||||
pitch_slide_speed_in_linear: int = 4
|
|
||||||
old_octave_boundary: bool = False
|
|
||||||
disable_opn2_dac_volume_control: bool = False
|
|
||||||
new_volume_scaling: bool = True
|
|
||||||
volume_macro_lingers: bool = True
|
|
||||||
broken_out_vol: bool = False
|
|
||||||
e1e2_stop_on_same_note: bool = False
|
|
||||||
broken_porta_after_arp: bool = False
|
|
||||||
sn_no_low_periods: bool = False
|
|
||||||
cut_delay_effect_policy: DelayBehavior = field(default_factory=lambda: DelayBehavior.LAX)
|
|
||||||
jump_treatment: JumpTreatment = field(default_factory=lambda: JumpTreatment.ALL_JUMPS)
|
|
||||||
auto_sys_name: bool = True
|
|
||||||
disable_sample_macro: bool = False
|
|
||||||
broken_out_vol_2: bool = False
|
|
||||||
old_arp_strategy: bool = False
|
|
||||||
|
|
||||||
# not-a-compat (>= dev135)
|
|
||||||
|
|
||||||
auto_patchbay: bool = True
|
|
||||||
|
|
||||||
# compat 3 (>= dev138)
|
|
||||||
|
|
||||||
broken_porta_during_legato: bool = False
|
|
||||||
|
|
||||||
broken_fm_off: bool = False
|
|
||||||
pre_note_no_effect: bool = False
|
|
||||||
old_dpcm: bool = False
|
|
||||||
reset_arp_phase_on_new_note: bool = False
|
|
||||||
ceil_volume_scaling: bool = False
|
|
||||||
old_always_set_volume: bool = False
|
|
||||||
old_sample_offset: bool = False
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SubSong:
|
|
||||||
"""
|
|
||||||
Information on a single subsong.
|
|
||||||
"""
|
|
||||||
name: str = ''
|
|
||||||
comment: str = ''
|
|
||||||
speed_pattern: List[int] = field(default_factory=lambda: [6])
|
|
||||||
"""
|
|
||||||
Maximum 16 entries.
|
|
||||||
"""
|
|
||||||
grooves: List[List[int]] = field(default_factory=list)
|
|
||||||
timing: TimingInfo = field(default_factory=TimingInfo)
|
|
||||||
pattern_length = 64
|
|
||||||
order: Dict[int, List[int]] = field(default_factory=lambda: {
|
|
||||||
0: [0], 1: [0], 2: [0], 3: [0], 4: [0],
|
|
||||||
5: [0], 6: [0], 7: [0], 8: [0], 9: [0]
|
|
||||||
})
|
|
||||||
effect_columns: List[int] = field(default_factory=lambda: [
|
|
||||||
1 for _ in range(
|
|
||||||
ChipType.YM2612.channels + ChipType.SMS.channels
|
|
||||||
)
|
|
||||||
])
|
|
||||||
channel_display: List[ChannelDisplayInfo] = field(default_factory=lambda: [
|
|
||||||
ChannelDisplayInfo() for _ in range(
|
|
||||||
ChipType.YM2612.channels + ChipType.SMS.channels
|
|
||||||
)
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class FurnaceRow:
|
|
||||||
"""
|
|
||||||
Represents a single row in a pattern.
|
|
||||||
"""
|
|
||||||
note: Note
|
|
||||||
octave: int
|
|
||||||
instrument: int
|
|
||||||
volume: int
|
|
||||||
effects: List[Tuple[int, int]] = field(default_factory=list)
|
|
||||||
|
|
||||||
def as_clipboard(self) -> str:
|
|
||||||
"""
|
|
||||||
Renders the selected row in Furnace clipboard format (without header!)
|
|
||||||
|
|
||||||
:return: Furnace clipboard data (str)
|
|
||||||
"""
|
|
||||||
note_maps = {
|
|
||||||
Note.Cs: "C#",
|
|
||||||
Note.D_: "D-",
|
|
||||||
Note.Ds: "D#",
|
|
||||||
Note.E_: "E-",
|
|
||||||
Note.F_: "F-",
|
|
||||||
Note.Fs: "F#",
|
|
||||||
Note.G_: "G-",
|
|
||||||
Note.Gs: "G#",
|
|
||||||
Note.A_: "A-",
|
|
||||||
Note.As: "A#",
|
|
||||||
Note.B_: "B-",
|
|
||||||
Note.C_: "C-",
|
|
||||||
}
|
|
||||||
if self.note == Note.OFF:
|
|
||||||
note_str = "OFF"
|
|
||||||
elif self.note == Note.OFF_REL:
|
|
||||||
note_str = "==="
|
|
||||||
elif self.note == Note.REL:
|
|
||||||
note_str = "REL"
|
|
||||||
elif self.note == Note.__:
|
|
||||||
note_str = "..."
|
|
||||||
else:
|
|
||||||
note_str = "%s%d" % (note_maps[self.note], self.octave)
|
|
||||||
|
|
||||||
vol = ".." if self.volume==0xffff else "%02X" % self.volume
|
|
||||||
ins = ".." if self.instrument==0xffff else "%02X" % self.instrument
|
|
||||||
|
|
||||||
rep_str = "%s%s%s"
|
|
||||||
|
|
||||||
for fx in self.effects:
|
|
||||||
cmd, val = fx
|
|
||||||
cmd_str = ".." if cmd == 0xffff else "%02X" % cmd
|
|
||||||
val_str = ".." if val == 0xffff else "%02X" % val
|
|
||||||
rep_str += "%s%s" % (cmd_str, val_str)
|
|
||||||
|
|
||||||
return rep_str % (
|
|
||||||
note_str,
|
|
||||||
ins, vol
|
|
||||||
) + "|"
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
if self.note == Note.OFF:
|
|
||||||
note_str = "OFF"
|
|
||||||
elif self.note == Note.OFF_REL:
|
|
||||||
note_str = "==="
|
|
||||||
elif self.note == Note.REL:
|
|
||||||
note_str = "///"
|
|
||||||
elif self.note == Note.__:
|
|
||||||
note_str = "---"
|
|
||||||
else:
|
|
||||||
note_str = "%s%d" % (self.note, self.octave)
|
|
||||||
|
|
||||||
vol = "--" if self.volume==0xffff else "%02x" % self.volume
|
|
||||||
ins = "--" if self.instrument==0xffff else "%02x" % self.instrument
|
|
||||||
|
|
||||||
rep_str = "row data: %s %s %s"
|
|
||||||
|
|
||||||
for fx in self.effects:
|
|
||||||
cmd, val = fx
|
|
||||||
cmd_str = "--" if cmd == 0xffff else "%02x" % cmd
|
|
||||||
val_str = "--" if val == 0xffff else "%02x" % val
|
|
||||||
rep_str += " %s%s" % (cmd_str, val_str)
|
|
||||||
|
|
||||||
return "<" + rep_str % (
|
|
||||||
note_str,
|
|
||||||
ins, vol
|
|
||||||
) + ">"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class FurnacePattern:
|
|
||||||
"""
|
|
||||||
Represents one pattern in a module.
|
|
||||||
"""
|
|
||||||
channel: int = 0
|
|
||||||
index: int = 0
|
|
||||||
subsong: int = 0
|
|
||||||
data: List[FurnaceRow] = field(default_factory=list) # yeah...
|
|
||||||
name: str = ""
|
|
||||||
|
|
||||||
def as_clipboard(self) -> str:
|
|
||||||
"""
|
|
||||||
Renders the selected pattern in Furnace clipboard format.
|
|
||||||
|
|
||||||
:return: Furnace clipboard data
|
|
||||||
"""
|
|
||||||
return "org.tildearrow.furnace - Pattern Data\n0\n" + "\n".join([x.as_clipboard() for x in self.data])
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return "<Furnace pattern %s for ch.%02d of subsong %02d>" % (
|
|
||||||
self.name if len(self.name) > 0 else "%02x" % self.index,
|
|
||||||
self.channel,
|
|
||||||
self.subsong
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InputPatchBayEntry(TypedDict):
|
|
||||||
"""
|
|
||||||
A patch that has an "input" connector.
|
|
||||||
"""
|
|
||||||
set: InputPortSet
|
|
||||||
"""
|
|
||||||
The set that the patch belongs to.
|
|
||||||
"""
|
|
||||||
port: int
|
|
||||||
"""
|
|
||||||
Which port to connect to.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class OutputPatchBayEntry(TypedDict):
|
|
||||||
"""
|
|
||||||
A patch that has an "output" connector.
|
|
||||||
"""
|
|
||||||
set: OutputPortSet
|
|
||||||
"""
|
|
||||||
The set that the patch belongs to.
|
|
||||||
"""
|
|
||||||
port: int
|
|
||||||
"""
|
|
||||||
Which port to connect from.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class PatchBay:
|
|
||||||
"""
|
|
||||||
A single patchbay connection.
|
|
||||||
"""
|
|
||||||
source: OutputPatchBayEntry
|
|
||||||
dest: InputPatchBayEntry
|
|
||||||
|
|
||||||
|
|
||||||
# instruments
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureAbstract:
|
|
||||||
"""
|
|
||||||
Base class for all InsFeature* classes. Not really to be used.
|
|
||||||
"""
|
|
||||||
_code: str = field(init=False)
|
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
|
||||||
if len(self._code) != 2:
|
|
||||||
raise ValueError('No code defined for this instrument feature')
|
|
||||||
|
|
||||||
# def serialize(self) -> bytes:
|
|
||||||
# raise Exception('Method serialize() has not been overridden...')
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureName(InsFeatureAbstract, str):
|
|
||||||
"""
|
|
||||||
Instrument's name block. Can be used as a string.
|
|
||||||
"""
|
|
||||||
_code = 'NA'
|
|
||||||
name: str = ''
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsMeta:
|
|
||||||
version: int = 143
|
|
||||||
type: InstrumentType = InstrumentType.FM_4OP
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFMOperator:
|
|
||||||
am: bool = False
|
|
||||||
ar: int = 0
|
|
||||||
dr: int = 0
|
|
||||||
mult: int = 0
|
|
||||||
rr: int = 0
|
|
||||||
sl: int = 0
|
|
||||||
tl: int = 0
|
|
||||||
dt2: int = 0
|
|
||||||
rs: int = 0
|
|
||||||
dt: int = 0
|
|
||||||
d2r: int = 0
|
|
||||||
ssg_env: int = 0
|
|
||||||
dam: int = 0
|
|
||||||
dvb: int = 0
|
|
||||||
egt: bool = False
|
|
||||||
ksl: int = 0
|
|
||||||
sus: bool = False
|
|
||||||
vib: bool = False
|
|
||||||
ws: int = 0
|
|
||||||
ksr: bool = False
|
|
||||||
enable: bool = True
|
|
||||||
kvs: int = 2
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureFM(InsFeatureAbstract):
|
|
||||||
_code = 'FM'
|
|
||||||
alg: int = 0
|
|
||||||
fb: int = 4
|
|
||||||
fms: int = 0
|
|
||||||
ams: int = 0
|
|
||||||
fms2: int = 0
|
|
||||||
ams2: int = 0
|
|
||||||
ops: int = 2
|
|
||||||
opll_preset: int = 0
|
|
||||||
op_list: List[InsFMOperator] = field(default_factory=lambda: [
|
|
||||||
InsFMOperator(
|
|
||||||
tl=42, ar=31, dr=8,
|
|
||||||
sl=15, rr=3, mult=5,
|
|
||||||
dt=5
|
|
||||||
),
|
|
||||||
InsFMOperator(
|
|
||||||
tl=48, ar=31, dr=4,
|
|
||||||
sl=11, rr=1, mult=1,
|
|
||||||
dt=5
|
|
||||||
),
|
|
||||||
InsFMOperator(
|
|
||||||
tl=18, ar=31, dr=10,
|
|
||||||
sl=15, rr=4, mult=1,
|
|
||||||
dt=0
|
|
||||||
),
|
|
||||||
InsFMOperator(
|
|
||||||
tl=2, ar=31, dr=9,
|
|
||||||
sl=15, rr=9, mult=1,
|
|
||||||
dt=0
|
|
||||||
),
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SingleMacro:
|
|
||||||
kind: Union[MacroCode, OpMacroCode] = field(default_factory=lambda: MacroCode.VOL)
|
|
||||||
mode: int = 0
|
|
||||||
type: MacroType = field(default_factory=lambda: MacroType.SEQUENCE)
|
|
||||||
delay: int = 0
|
|
||||||
speed: int = 1
|
|
||||||
open: bool = False
|
|
||||||
data: List[Union[int, MacroItem]] = field(default_factory=list)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureMacro(InsFeatureAbstract):
|
|
||||||
_code = 'MA'
|
|
||||||
macros: List[SingleMacro] = field(default_factory=lambda: [SingleMacro()])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureOpr1Macro(InsFeatureMacro):
|
|
||||||
_code = 'O1'
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureOpr2Macro(InsFeatureMacro):
|
|
||||||
_code = 'O2'
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureOpr3Macro(InsFeatureMacro):
|
|
||||||
_code = 'O3'
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureOpr4Macro(InsFeatureMacro):
|
|
||||||
_code = 'O4'
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class GBHwSeq:
|
|
||||||
command: GBHwCommand
|
|
||||||
data: List[int] = field(default_factory=lambda: [0, 0])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureGB(InsFeatureAbstract):
|
|
||||||
_code = 'GB'
|
|
||||||
env_vol: int = 15
|
|
||||||
env_dir: int = 0
|
|
||||||
env_len: int = 2
|
|
||||||
sound_len: int = 0
|
|
||||||
soft_env: bool = False
|
|
||||||
always_init: bool = False
|
|
||||||
hw_seq: List[GBHwSeq] = field(default_factory=list)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class GenericADSR:
|
|
||||||
a: int = 0
|
|
||||||
d: int = 0
|
|
||||||
s: int = 0
|
|
||||||
r: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureC64(InsFeatureAbstract):
|
|
||||||
_code = '64'
|
|
||||||
tri_on: bool = False
|
|
||||||
saw_on: bool = True
|
|
||||||
pulse_on: bool = False
|
|
||||||
noise_on: bool = False
|
|
||||||
envelope: GenericADSR = field(default_factory=lambda: GenericADSR(a=0, d=8, s=0, r=0))
|
|
||||||
duty: int = 2048
|
|
||||||
ring_mod: int = 0
|
|
||||||
osc_sync: int = 0
|
|
||||||
to_filter: bool = False
|
|
||||||
vol_is_cutoff: bool = False
|
|
||||||
init_filter: bool = False
|
|
||||||
duty_is_abs: bool = False
|
|
||||||
filter_is_abs: bool = False
|
|
||||||
no_test: bool = False
|
|
||||||
res: int = 0
|
|
||||||
cut: int = 0
|
|
||||||
hp: bool = False
|
|
||||||
lp: bool = False
|
|
||||||
bp: bool = False
|
|
||||||
ch3_off: bool = False
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SampleMap:
|
|
||||||
freq: int = 0
|
|
||||||
sample_index: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DPCMMap:
|
|
||||||
pitch: int = 0
|
|
||||||
delta: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureAmiga(InsFeatureAbstract): # Sample data
|
|
||||||
_code = 'SM'
|
|
||||||
init_sample: int = 0
|
|
||||||
use_note_map: bool = False
|
|
||||||
use_sample: bool = False
|
|
||||||
use_wave: bool = False
|
|
||||||
wave_len: int = 31
|
|
||||||
sample_map: List[SampleMap] = field(default_factory=lambda: [SampleMap() for _ in range(120)])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureDPCMMap(InsFeatureAbstract): # DPCM sample data
|
|
||||||
_code = 'NE'
|
|
||||||
use_map: bool = False
|
|
||||||
sample_map: List[DPCMMap] = field(default_factory=lambda: [SampleMap() for _ in range(120)])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureX1010(InsFeatureAbstract):
|
|
||||||
_code = 'X1'
|
|
||||||
bank_slot: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeaturePowerNoise(InsFeatureAbstract):
|
|
||||||
_code = 'PN'
|
|
||||||
octave: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureSID2(InsFeatureAbstract):
|
|
||||||
_code = 'S2'
|
|
||||||
noise_mode: int = 0
|
|
||||||
wave_mix: int = 0
|
|
||||||
volume: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureN163(InsFeatureAbstract):
|
|
||||||
_code = 'N1'
|
|
||||||
wave: int = -1
|
|
||||||
wave_pos: int = 0
|
|
||||||
wave_len: int = 32
|
|
||||||
wave_mode: int = 3
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureFDS(InsFeatureAbstract): # Virtual Boy
|
|
||||||
_code = 'FD'
|
|
||||||
mod_speed: int = 0
|
|
||||||
mod_depth: int = 0
|
|
||||||
init_table_with_first_wave: bool = False # compat
|
|
||||||
mod_table: List[int] = field(default_factory=lambda: [0 for i in range(32)])
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureMultiPCM(InsFeatureAbstract):
|
|
||||||
_code = 'MP'
|
|
||||||
ar: int = 15
|
|
||||||
d1r: int = 15
|
|
||||||
dl: int = 0
|
|
||||||
d2r: int = 0
|
|
||||||
rr: int = 15
|
|
||||||
rc: int = 15
|
|
||||||
lfo: int = 0
|
|
||||||
vib: int = 0
|
|
||||||
am: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureWaveSynth(InsFeatureAbstract):
|
|
||||||
_code = 'WS'
|
|
||||||
wave_indices: List[int] = field(default_factory=lambda: [0, 0])
|
|
||||||
rate_divider: int = 1
|
|
||||||
effect: WaveFX = WaveFX.NONE
|
|
||||||
enabled: bool = False
|
|
||||||
global_effect: bool = False
|
|
||||||
speed: int = 0
|
|
||||||
params: List[int] = field(default_factory=lambda: [0, 0, 0, 0])
|
|
||||||
one_shot: bool = False # not read?
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureSoundUnit(InsFeatureAbstract):
|
|
||||||
_code = 'SU'
|
|
||||||
switch_roles: bool = False
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureES5506(InsFeatureAbstract):
|
|
||||||
_code = 'ES'
|
|
||||||
filter_mode: ESFilterMode = ESFilterMode.LPK2_LPK1
|
|
||||||
k1: int = 0xffff
|
|
||||||
k2: int = 0xffff
|
|
||||||
env_count: int = 0
|
|
||||||
left_volume_ramp: int = 0
|
|
||||||
right_volume_ramp: int = 0
|
|
||||||
k1_ramp: int = 0
|
|
||||||
k2_ramp: int = 0
|
|
||||||
k1_slow: int = 0
|
|
||||||
k2_slow: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureSNES(InsFeatureAbstract):
|
|
||||||
_code = 'SN'
|
|
||||||
use_env: bool = True
|
|
||||||
sus: SNESSusMode = SNESSusMode.DIRECT
|
|
||||||
gain_mode: GainMode = GainMode.DIRECT
|
|
||||||
gain: int = 127
|
|
||||||
d2: int = 0
|
|
||||||
envelope: GenericADSR = field(default_factory=lambda: GenericADSR(a=15, d=7, s=7, r=0))
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureOPLDrums(InsFeatureAbstract):
|
|
||||||
_code = 'LD'
|
|
||||||
fixed_drums: bool = False
|
|
||||||
kick_freq: int = 1312
|
|
||||||
snare_hat_freq: int = 1360
|
|
||||||
tom_top_freq: int = 448
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class _InsFeaturePointerAbstract(InsFeatureAbstract):
|
|
||||||
"""
|
|
||||||
Also not really to be used. Container for all "list" features.
|
|
||||||
"""
|
|
||||||
_code = 'LL'
|
|
||||||
pointers: Dict[int, int] = field(default_factory=dict)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureSampleList(_InsFeaturePointerAbstract):
|
|
||||||
"""
|
|
||||||
List of pointers to all samples used by this instrument.
|
|
||||||
"""
|
|
||||||
_code = 'SL'
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class InsFeatureWaveList(_InsFeaturePointerAbstract):
|
|
||||||
"""
|
|
||||||
List of pointers to all wave tables used by this instrument.
|
|
||||||
"""
|
|
||||||
_code = 'WL'
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class WavetableMeta:
|
|
||||||
name: str = ''
|
|
||||||
width: int = 32
|
|
||||||
height: int = 32
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SampleMeta:
|
|
||||||
name: str = ''
|
|
||||||
length: int = 0
|
|
||||||
sample_rate: int = 0
|
|
||||||
bitdepth: int = 0
|
|
||||||
loop_start: int = 0
|
|
||||||
loop_end: int = 0
|
|
||||||
|
|
@ -1,648 +0,0 @@
|
||||||
from chipchune._util import EnumShowNameOnly, EnumValueEquals
|
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
class LinearPitch(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Options for :attr:`chipchune.furnace.data_types.ModuleCompatFlags.linear_pitch`.
|
|
||||||
"""
|
|
||||||
NON_LINEAR = 0
|
|
||||||
ONLY_PITCH_CHANGE = 1
|
|
||||||
FULL_LINEAR = 2
|
|
||||||
|
|
||||||
|
|
||||||
class LoopModality(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Options for :attr:`chipchune.furnace.data_types.ModuleCompatFlags.loop_modality`.
|
|
||||||
"""
|
|
||||||
HARD_RESET_CHANNELS = 0
|
|
||||||
SOFT_RESET_CHANNELS = 1
|
|
||||||
DO_NOTHING = 2
|
|
||||||
|
|
||||||
|
|
||||||
class DelayBehavior(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Options for :attr:`chipchune.furnace.data_types.ModuleCompatFlags.cut_delay_effect_policy`.
|
|
||||||
"""
|
|
||||||
STRICT = 0
|
|
||||||
BROKEN = 1
|
|
||||||
LAX = 2
|
|
||||||
|
|
||||||
|
|
||||||
class JumpTreatment(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Options for :attr:`chipchune.furnace.data_types.ModuleCompatFlags.jump_treatment`.
|
|
||||||
"""
|
|
||||||
ALL_JUMPS = 0
|
|
||||||
FIRST_JUMP_ONLY = 1
|
|
||||||
ROW_JUMP_PRIORITY = 2
|
|
||||||
|
|
||||||
|
|
||||||
class Note(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
All notes recognized by Furnace
|
|
||||||
"""
|
|
||||||
__ = 0
|
|
||||||
Cs = 1
|
|
||||||
D_ = 2
|
|
||||||
Ds = 3
|
|
||||||
E_ = 4
|
|
||||||
F_ = 5
|
|
||||||
Fs = 6
|
|
||||||
G_ = 7
|
|
||||||
Gs = 8
|
|
||||||
A_ = 9
|
|
||||||
As = 10
|
|
||||||
B_ = 11
|
|
||||||
C_ = 12
|
|
||||||
OFF = 100
|
|
||||||
OFF_REL = 101
|
|
||||||
REL = 102
|
|
||||||
|
|
||||||
|
|
||||||
class MacroItem(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Special values used only in this parser, to allow data editing similar to that
|
|
||||||
of Furnace itself.
|
|
||||||
"""
|
|
||||||
LOOP = 0
|
|
||||||
RELEASE = 1
|
|
||||||
|
|
||||||
|
|
||||||
class MacroCode(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Marks what aspect of an instrument does a macro change.
|
|
||||||
"""
|
|
||||||
|
|
||||||
VOL = 0
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- C64 cutoff
|
|
||||||
"""
|
|
||||||
|
|
||||||
ARP = 1
|
|
||||||
"""
|
|
||||||
Not applicable to MSM6258 and MSM6295.
|
|
||||||
"""
|
|
||||||
|
|
||||||
DUTY = 2
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- AY noise freq
|
|
||||||
- POKEY audctl
|
|
||||||
- Mikey duty/int
|
|
||||||
- MSM5232 group ctrl
|
|
||||||
- Beeper/Pokemon Mini pulse width
|
|
||||||
- T6W28 noise type
|
|
||||||
- Virtual Boy noise length
|
|
||||||
- PC Engine/Namco/WonderSwan noise type
|
|
||||||
- SNES noise freq
|
|
||||||
- Namco 163 waveform pos.
|
|
||||||
- ES5506 filter mode
|
|
||||||
- MSM6258/MSM6295 freq. divider
|
|
||||||
- ADPCMA global volume
|
|
||||||
- QSound echo level
|
|
||||||
"""
|
|
||||||
|
|
||||||
WAVE = 3
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- OPLL patch
|
|
||||||
- OPZ/OPM lfo1 shape
|
|
||||||
"""
|
|
||||||
|
|
||||||
PITCH = 4
|
|
||||||
|
|
||||||
EX1 = 5
|
|
||||||
"""
|
|
||||||
- OPZ/OPM am depth
|
|
||||||
- C64 filter mode
|
|
||||||
- SAA1099 envelope
|
|
||||||
- X1-010 env. mode
|
|
||||||
- Namco 163 wave length
|
|
||||||
- FDS mod depth
|
|
||||||
- TSU cutoff
|
|
||||||
- ES5506 filter k1
|
|
||||||
- MSM6258 clk divider
|
|
||||||
- QSound echo feedback
|
|
||||||
- SNES special
|
|
||||||
- MSM5232 group attack
|
|
||||||
- AY8930 duty?
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX2 = 6
|
|
||||||
"""
|
|
||||||
- C64 resonance
|
|
||||||
- Namco 163 wave update
|
|
||||||
- FDS mod speed
|
|
||||||
- TSU resonance
|
|
||||||
- ES5506 filter k2
|
|
||||||
- QSound echo length
|
|
||||||
- SNES gain
|
|
||||||
- MSM5232 group decay
|
|
||||||
- AY3/AY8930 envelope
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX3 = 7
|
|
||||||
"""
|
|
||||||
- C64 special
|
|
||||||
- AY/AY8930 autoenv num
|
|
||||||
- X1-010 autoenv num
|
|
||||||
- Namco 163 waveload wave
|
|
||||||
- FDS mod position
|
|
||||||
- TSU control
|
|
||||||
- MSM5232 noise
|
|
||||||
"""
|
|
||||||
|
|
||||||
ALG = 8
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- AY/AY8930 autoenv den
|
|
||||||
- X1-010 autoenv den
|
|
||||||
- Namco 163 waveload pos
|
|
||||||
- ES5506 control
|
|
||||||
"""
|
|
||||||
|
|
||||||
FB = 9
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- AY8930 noise & mask
|
|
||||||
- Namco 163 waveload len
|
|
||||||
- ES5506 outputs
|
|
||||||
"""
|
|
||||||
|
|
||||||
FMS = 10
|
|
||||||
"""
|
|
||||||
Also:
|
|
||||||
- AY8930 noise | mask
|
|
||||||
- Namco 163 waveload trigger
|
|
||||||
"""
|
|
||||||
|
|
||||||
AMS = 11
|
|
||||||
|
|
||||||
PAN_L = 12
|
|
||||||
|
|
||||||
PAN_R = 13
|
|
||||||
|
|
||||||
PHASE_RESET = 14
|
|
||||||
|
|
||||||
EX4 = 15
|
|
||||||
"""
|
|
||||||
- C64 test/gate
|
|
||||||
- TSU phase reset timer
|
|
||||||
- FM/OPM opmask
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX5 = 16
|
|
||||||
"""
|
|
||||||
- OPZ am depth 2
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX6 = 17
|
|
||||||
"""
|
|
||||||
- OPZ pm depth 2
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX7 = 18
|
|
||||||
"""
|
|
||||||
- OPZ lfo2 speed
|
|
||||||
"""
|
|
||||||
|
|
||||||
EX8 = 19
|
|
||||||
"""
|
|
||||||
- OPZ lfo2 shape
|
|
||||||
"""
|
|
||||||
|
|
||||||
STOP = 255
|
|
||||||
"""
|
|
||||||
Marks end of macro reading.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class OpMacroCode(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Controls which FM parameter a macro should change.
|
|
||||||
"""
|
|
||||||
AM = 0
|
|
||||||
AR = 1
|
|
||||||
DR = 2
|
|
||||||
MULT = 3
|
|
||||||
RR = 4
|
|
||||||
SL = 5
|
|
||||||
TL = 6
|
|
||||||
DT2 = 7
|
|
||||||
RS = 8
|
|
||||||
DT = 9
|
|
||||||
D2R = 10
|
|
||||||
SSG_EG = 11
|
|
||||||
DAM = 12
|
|
||||||
DVB = 13
|
|
||||||
EGT = 14
|
|
||||||
KSL = 15
|
|
||||||
SUS = 16
|
|
||||||
VIB = 17
|
|
||||||
WS = 18
|
|
||||||
KSR = 19
|
|
||||||
|
|
||||||
|
|
||||||
class MacroType(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Instrument macro type (version 120+).
|
|
||||||
"""
|
|
||||||
SEQUENCE = 0
|
|
||||||
ADSR = 1
|
|
||||||
LFO = 2
|
|
||||||
|
|
||||||
|
|
||||||
class MacroSize(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Type of value stored in the instrument file.
|
|
||||||
"""
|
|
||||||
_value_: int
|
|
||||||
num_bytes: int
|
|
||||||
signed: bool
|
|
||||||
|
|
||||||
UINT8: Tuple[int, int, bool] = (0, 1, False)
|
|
||||||
INT8: Tuple[int, int, bool] = (1, 1, True)
|
|
||||||
INT16: Tuple[int, int, bool] = (2, 2, True)
|
|
||||||
INT32: Tuple[int, int, bool] = (3, 4, True)
|
|
||||||
|
|
||||||
def __new__(cls, id: int, num_bytes: int, signed: bool): # type: ignore[no-untyped-def]
|
|
||||||
member = object.__new__(cls)
|
|
||||||
member._value_ = id
|
|
||||||
setattr(member, 'num_bytes', num_bytes)
|
|
||||||
setattr(member, 'signed', signed)
|
|
||||||
return member
|
|
||||||
|
|
||||||
|
|
||||||
class GBHwCommand(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Game Boy hardware envelope commands.
|
|
||||||
"""
|
|
||||||
ENVELOPE = 0
|
|
||||||
SWEEP = 1
|
|
||||||
WAIT = 2
|
|
||||||
WAIT_REL = 3
|
|
||||||
LOOP = 4
|
|
||||||
LOOP_REL = 5
|
|
||||||
|
|
||||||
|
|
||||||
class SampleType(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Sample types used in Furnace
|
|
||||||
"""
|
|
||||||
ZX_DRUM = 0
|
|
||||||
NES_DPCM = 1
|
|
||||||
QSOUND_ADPCM = 4
|
|
||||||
ADPCM_A = 5
|
|
||||||
ADPCM_B = 6
|
|
||||||
X68K_ADPCM = 7
|
|
||||||
PCM_8 = 8
|
|
||||||
SNES_BRR = 9
|
|
||||||
VOX = 10
|
|
||||||
PCM_16 = 16
|
|
||||||
|
|
||||||
|
|
||||||
class InstrumentType(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Instrument types currently available as of version 144.
|
|
||||||
"""
|
|
||||||
STANDARD = 0
|
|
||||||
FM_4OP = 1
|
|
||||||
GB = 2
|
|
||||||
C64 = 3
|
|
||||||
AMIGA = 4
|
|
||||||
PCE = 5
|
|
||||||
SSG = 6
|
|
||||||
AY8930 = 7
|
|
||||||
TIA = 8
|
|
||||||
SAA1099 = 9
|
|
||||||
VIC = 10
|
|
||||||
PET = 11
|
|
||||||
VRC6 = 12
|
|
||||||
FM_OPLL = 13
|
|
||||||
FM_OPL = 14
|
|
||||||
FDS = 15
|
|
||||||
VB = 16
|
|
||||||
N163 = 17
|
|
||||||
KONAMI_SCC = 18
|
|
||||||
FM_OPZ = 19
|
|
||||||
POKEY = 20
|
|
||||||
PC_BEEPER = 21
|
|
||||||
WONDERSWAN = 22
|
|
||||||
LYNX = 23
|
|
||||||
VERA = 24
|
|
||||||
X1010 = 25
|
|
||||||
VRC6_SAW = 26
|
|
||||||
ES5506 = 27
|
|
||||||
MULTIPCM = 28
|
|
||||||
SNES = 29
|
|
||||||
TSU = 30
|
|
||||||
NAMCO_WSG = 31
|
|
||||||
OPL_DRUMS = 32
|
|
||||||
FM_OPM = 33
|
|
||||||
NES = 34
|
|
||||||
MSM6258 = 35
|
|
||||||
MSM6295 = 36
|
|
||||||
ADPCM_A = 37
|
|
||||||
ADPCM_B = 38
|
|
||||||
SEGAPCM = 39
|
|
||||||
QSOUND = 40
|
|
||||||
YMZ280B = 41
|
|
||||||
RF5C68 = 42
|
|
||||||
MSM5232 = 43
|
|
||||||
T6W28 = 44
|
|
||||||
K007232 = 45
|
|
||||||
GA20 = 46
|
|
||||||
POKEMON_MINI = 47
|
|
||||||
SM8521 = 48
|
|
||||||
PV1000 = 49
|
|
||||||
|
|
||||||
|
|
||||||
class ChipType(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Furnace chip database, either planned or implemented.
|
|
||||||
Contains console name, chip ID and number of channels.
|
|
||||||
"""
|
|
||||||
_value_: int
|
|
||||||
channels: int
|
|
||||||
|
|
||||||
YMU759 = (0x01, 17)
|
|
||||||
GENESIS = (0x02, 10) # YM2612 + SN76489
|
|
||||||
SMS = (0x03, 4) # SN76489
|
|
||||||
GB = (0x04, 4) # LR53902
|
|
||||||
PCE = (0x05, 6) # HuC6280
|
|
||||||
NES = (0x06, 5) # RP2A03
|
|
||||||
C64_8580 = (0x07, 3) # SID r8580
|
|
||||||
SEGA_ARCADE = (0x08, 13) # YM2151 + SegaPCM
|
|
||||||
NEO_GEO_CD = (0x09, 13)
|
|
||||||
|
|
||||||
GENESIS_EX = (0x42, 13) # YM2612 + SN76489
|
|
||||||
SMS_JP = (0x43, 13) # SN76489 + YM2413
|
|
||||||
NES_VRC7 = (0x46, 11) # RP2A03 + YM2413
|
|
||||||
C64_6581 = (0x47, 3) # SID r6581
|
|
||||||
NEO_GEO_CD_EX = (0x49, 16)
|
|
||||||
|
|
||||||
AY38910 = (0x80, 3)
|
|
||||||
AMIGA = (0x81, 4) # Paula
|
|
||||||
YM2151 = (0x82, 8) # YM2151
|
|
||||||
YM2612 = (0x83, 6) # YM2612
|
|
||||||
TIA = (0x84, 2)
|
|
||||||
VIC20 = (0x85, 4)
|
|
||||||
PET = (0x86, 1)
|
|
||||||
SNES = (0x87, 8) # SPC700
|
|
||||||
VRC6 = (0x88, 3)
|
|
||||||
OPLL = (0x89, 9) # YM2413
|
|
||||||
FDS = (0x8a, 1)
|
|
||||||
MMC5 = (0x8b, 3)
|
|
||||||
N163 = (0x8c, 8)
|
|
||||||
OPN = (0x8d, 6) # YM2203
|
|
||||||
PC98 = (0x8e, 16) # YM2608
|
|
||||||
OPL = (0x8f, 9) # YM3526
|
|
||||||
|
|
||||||
OPL2 = (0x90, 9) # YM3812
|
|
||||||
OPL3 = (0x91, 18) # YMF262
|
|
||||||
MULTIPCM = (0x92, 24)
|
|
||||||
PC_SPEAKER = (0x93, 1) # Intel 8253
|
|
||||||
POKEY = (0x94, 4)
|
|
||||||
RF5C68 = (0x95, 8)
|
|
||||||
WONDERSWAN = (0x96, 4)
|
|
||||||
SAA1099 = (0x97, 6)
|
|
||||||
OPZ = (0x98, 8)
|
|
||||||
POKEMON_MINI = (0x99, 1)
|
|
||||||
AY8930 = (0x9a, 3)
|
|
||||||
SEGAPCM = (0x9b, 16)
|
|
||||||
VIRTUAL_BOY = (0x9c, 6)
|
|
||||||
VRC7 = (0x9d, 6)
|
|
||||||
YM2610B = (0x9e, 16)
|
|
||||||
ZX_BEEPER = (0x9f, 6) # tildearrow's engine
|
|
||||||
|
|
||||||
YM2612_EX = (0xa0, 9)
|
|
||||||
SCC = (0xa1, 5)
|
|
||||||
OPL_DRUMS = (0xa2, 11)
|
|
||||||
OPL2_DRUMS = (0xa3, 11)
|
|
||||||
OPL3_DRUMS = (0xa4, 20)
|
|
||||||
NEO_GEO = (0xa5, 14)
|
|
||||||
NEO_GEO_EX = (0xa6, 17)
|
|
||||||
OPLL_DRUMS = (0xa7, 11)
|
|
||||||
LYNX = (0xa8, 4)
|
|
||||||
SEGAPCM_DMF = (0xa9, 5)
|
|
||||||
MSM6295 = (0xaa, 4)
|
|
||||||
MSM6258 = (0xab, 1)
|
|
||||||
COMMANDER_X16 = (0xac, 17) # VERA
|
|
||||||
BUBBLE_SYSTEM_WSG = (0xad, 2)
|
|
||||||
OPL4 = (0xae, 42)
|
|
||||||
OPL4_DRUMS = (0xaf, 44)
|
|
||||||
|
|
||||||
SETA = (0xb0, 16) # Allumer X1-010
|
|
||||||
ES5506 = (0xb1, 32)
|
|
||||||
Y8950 = (0xb2, 10)
|
|
||||||
Y8950_DRUMS = (0xb3, 12)
|
|
||||||
SCC_PLUS = (0xb4, 5)
|
|
||||||
TSU = (0xb5, 8)
|
|
||||||
YM2203_EX = (0xb6, 9)
|
|
||||||
YM2608_EX = (0xb7, 19)
|
|
||||||
YMZ280B = (0xb8, 8)
|
|
||||||
NAMCO = (0xb9, 3) # Namco WSG
|
|
||||||
N15XX = (0xba, 8) # Namco 15xx
|
|
||||||
CUS30 = (0xbb, 8) # Namco CUS30
|
|
||||||
MSM5232 = (0xbc, 8)
|
|
||||||
YM2612_PLUS_EX = (0xbd, 11)
|
|
||||||
YM2612_PLUS = (0xbe, 7)
|
|
||||||
T6W28 = (0xbf, 4)
|
|
||||||
|
|
||||||
PCM_DAC = (0xc0, 1)
|
|
||||||
YM2612_CSM = (0xc1, 10)
|
|
||||||
NEO_GEO_CSM = (0xc2, 18) # YM2610 CSM
|
|
||||||
YM2203_CSM = (0xc3, 10)
|
|
||||||
YM2608_CSM = (0xc4, 20)
|
|
||||||
YM2610B_CSM = (0xc5, 20)
|
|
||||||
K007232 = (0xc6, 2)
|
|
||||||
GA20 = (0xc7, 4)
|
|
||||||
SM8521 = (0xc8, 3)
|
|
||||||
M114S = (0xc9, 16)
|
|
||||||
ZX_BEEPER_QUADTONE: Tuple[int, int] = (0xca, 5) # Natt Akuma's engine
|
|
||||||
PV_1000: Tuple[int, int] = (0xcb, 3) # NEC D65010G031
|
|
||||||
K053260 = (0xcc, 4)
|
|
||||||
TED = (0xcd, 2)
|
|
||||||
NAMCO_C140 = (0xce, 24)
|
|
||||||
NAMCO_C219 = (0xcf, 16)
|
|
||||||
|
|
||||||
NAMCO_C352 = (0xd0, 32)
|
|
||||||
ESFM = (0xd1, 18)
|
|
||||||
ES5503 = (0xd2, 32)
|
|
||||||
POWERNOISE = (0xd4, 4)
|
|
||||||
DAVE = (0xd5, 6)
|
|
||||||
NDS = (0xd6, 16)
|
|
||||||
GBA = (0xd7, 2)
|
|
||||||
GBA_MINMOD = (0xd8, 16)
|
|
||||||
BIFURCATOR = (0xd9, 4)
|
|
||||||
YM2610B_EX = (0xde, 19)
|
|
||||||
|
|
||||||
QSOUND = (0xe0, 19)
|
|
||||||
|
|
||||||
SID2 = (0xf0, 3) # SID2
|
|
||||||
FIVEE01 = (0xf1, 5) # 5E01
|
|
||||||
PONG = (0xfc, 1)
|
|
||||||
DUMMY = (0xfd, 1)
|
|
||||||
|
|
||||||
RESERVED_1 = (0xfe, 1)
|
|
||||||
RESERVED_2 = (0xff, 1)
|
|
||||||
|
|
||||||
def __new__(cls, id: int, channels: int): # type: ignore[no-untyped-def]
|
|
||||||
member = object.__new__(cls)
|
|
||||||
member._value_ = id
|
|
||||||
setattr(member, 'channels', channels)
|
|
||||||
return member
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
# repr abuse
|
|
||||||
# about as stupid as "mapping for the renderer"...
|
|
||||||
return "%s (0x%02x), %d channel%s" % (
|
|
||||||
self.name, self._value_, self.channels,
|
|
||||||
"s" if self.channels != 1 else ""
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InputPortSet(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Devices which contain an "input" port.
|
|
||||||
"""
|
|
||||||
SYSTEM = 0
|
|
||||||
NULL = 0xFFF
|
|
||||||
|
|
||||||
|
|
||||||
class OutputPortSet(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Devices which contain an "output" port.
|
|
||||||
"""
|
|
||||||
CHIP_1 = 0
|
|
||||||
CHIP_2 = 1
|
|
||||||
CHIP_3 = 2
|
|
||||||
CHIP_4 = 3
|
|
||||||
CHIP_5 = 4
|
|
||||||
CHIP_6 = 5
|
|
||||||
CHIP_7 = 6
|
|
||||||
CHIP_8 = 7
|
|
||||||
CHIP_9 = 8
|
|
||||||
CHIP_10 = 9
|
|
||||||
CHIP_11 = 10
|
|
||||||
CHIP_12 = 11
|
|
||||||
CHIP_13 = 12
|
|
||||||
CHIP_14 = 13
|
|
||||||
CHIP_15 = 14
|
|
||||||
CHIP_16 = 15
|
|
||||||
CHIP_17 = 16
|
|
||||||
CHIP_18 = 17
|
|
||||||
CHIP_19 = 18
|
|
||||||
CHIP_20 = 19
|
|
||||||
CHIP_21 = 20
|
|
||||||
CHIP_22 = 21
|
|
||||||
CHIP_23 = 22
|
|
||||||
CHIP_24 = 23
|
|
||||||
CHIP_25 = 24
|
|
||||||
CHIP_26 = 25
|
|
||||||
CHIP_27 = 26
|
|
||||||
CHIP_28 = 27
|
|
||||||
CHIP_29 = 28
|
|
||||||
CHIP_30 = 29
|
|
||||||
CHIP_31 = 30
|
|
||||||
CHIP_32 = 31
|
|
||||||
PREVIEW = 0xFFD
|
|
||||||
METRONOME = 0xFFE
|
|
||||||
NULL = 0xFFF
|
|
||||||
|
|
||||||
|
|
||||||
class WaveFX(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Used in :attr:`chipchune.furnace.data_types.InsFeatureWaveSynth.effect`.
|
|
||||||
"""
|
|
||||||
NONE = 0
|
|
||||||
|
|
||||||
# single waveform
|
|
||||||
INVERT = 1
|
|
||||||
ADD = 2
|
|
||||||
SUBTRACT = 3
|
|
||||||
AVERAGE = 4
|
|
||||||
PHASE = 5
|
|
||||||
CHORUS = 6
|
|
||||||
|
|
||||||
# double waveform
|
|
||||||
NONE_DUAL = 128
|
|
||||||
WIPE = 129
|
|
||||||
FADE = 130
|
|
||||||
PING_PONG = 131
|
|
||||||
OVERLAY = 132
|
|
||||||
NEGATIVE_OVERLAY = 133
|
|
||||||
SLIDE = 134
|
|
||||||
MIX = 135
|
|
||||||
PHASE_MOD = 136
|
|
||||||
|
|
||||||
|
|
||||||
class ESFilterMode(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Used in :attr:`chipchune.furnace.data_types.InsFeatureES5506.filter_mode`.
|
|
||||||
"""
|
|
||||||
HPK2_HPK2 = 0
|
|
||||||
HPK2_LPK1 = 1
|
|
||||||
LPK2_LPK2 = 2
|
|
||||||
LPK2_LPK1 = 3
|
|
||||||
|
|
||||||
|
|
||||||
class GainMode(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Used in :attr:`chipchune.furnace.data_types.InsFeatureSNES.gain_mode`.
|
|
||||||
"""
|
|
||||||
DIRECT = 0
|
|
||||||
DEC_LINEAR = 4
|
|
||||||
DEC_LOG = 5
|
|
||||||
INC_LINEAR = 6
|
|
||||||
INC_INVLOG = 7
|
|
||||||
|
|
||||||
|
|
||||||
class SNESSusMode(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Used in :attr:`chipchune.furnace.data_types.InsFeatureSNES.sus`.
|
|
||||||
"""
|
|
||||||
DIRECT = 0
|
|
||||||
SUS_WITH_DEC = 1
|
|
||||||
SUS_WITH_EXP = 2
|
|
||||||
SUS_WITH_REL = 3
|
|
||||||
|
|
||||||
|
|
||||||
class _FurInsImportType(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Also only used in this parser to differentiate between different types of instrument formats.
|
|
||||||
"""
|
|
||||||
# Old format
|
|
||||||
FORMAT_0_FILE = 0
|
|
||||||
FORMAT_0_EMBED = 1
|
|
||||||
|
|
||||||
# Dev127 format
|
|
||||||
FORMAT_1_FILE = 2
|
|
||||||
FORMAT_1_EMBED = 3
|
|
||||||
|
|
||||||
class _FurWavetableImportType(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Also only used in this parser to differentiate between different types of wavetable formats.
|
|
||||||
"""
|
|
||||||
FILE = 0
|
|
||||||
EMBED = 1
|
|
||||||
|
|
||||||
class _FurSampleType(EnumShowNameOnly, EnumValueEquals):
|
|
||||||
"""
|
|
||||||
Also only used in this parser to differentiate between different types of sample formats.
|
|
||||||
"""
|
|
||||||
PCM_1_BIT = 0
|
|
||||||
DPCM = 1
|
|
||||||
YMZ = 3
|
|
||||||
QSOUND = 4
|
|
||||||
ADPCM_A = 5
|
|
||||||
ADPCM_B = 6
|
|
||||||
K05_ADPCM = 7
|
|
||||||
PCM_8_BIT = 8
|
|
||||||
BRR = 9
|
|
||||||
VOX = 10
|
|
||||||
ULAW = 11
|
|
||||||
C219 = 12
|
|
||||||
IMA = 13
|
|
||||||
PCM_16_BIT = 16
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
from io import BytesIO
|
|
||||||
from typing import Optional, Union, BinaryIO, List
|
|
||||||
|
|
||||||
from chipchune._util import read_short, read_int, read_str
|
|
||||||
from .data_types import SampleMeta
|
|
||||||
from .enums import _FurSampleType
|
|
||||||
|
|
||||||
FILE_MAGIC_STR = b'SMP2'
|
|
||||||
|
|
||||||
|
|
||||||
class FurnaceSample:
|
|
||||||
def __init__(self) -> None:
|
|
||||||
self.meta: SampleMeta = SampleMeta()
|
|
||||||
"""
|
|
||||||
Sample metadata.
|
|
||||||
"""
|
|
||||||
self.data: bytearray = b''
|
|
||||||
"""
|
|
||||||
Sample data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def load_from_stream(self, stream: BinaryIO) -> None:
|
|
||||||
"""
|
|
||||||
Load a sample from an **uncompressed** stream.
|
|
||||||
|
|
||||||
:param stream: File-like object containing the uncompressed wavetable.
|
|
||||||
"""
|
|
||||||
if stream.read(len(FILE_MAGIC_STR)) != FILE_MAGIC_STR:
|
|
||||||
raise ValueError('Bad magic value for a wavetable file')
|
|
||||||
blk_size = read_int(stream)
|
|
||||||
if blk_size > 0:
|
|
||||||
smp_data = BytesIO(stream.read(blk_size))
|
|
||||||
else:
|
|
||||||
smp_data = stream
|
|
||||||
|
|
||||||
self.meta.name = read_str(smp_data)
|
|
||||||
self.meta.length = read_int(smp_data)
|
|
||||||
read_int(smp_data) # compatablity rate
|
|
||||||
self.meta.sample_rate = read_int(smp_data)
|
|
||||||
self.meta.depth = int(smp_data.read(1)[0])
|
|
||||||
smp_data.read(1) # loop direction
|
|
||||||
smp_data.read(1) # flags
|
|
||||||
smp_data.read(1) # flags 2
|
|
||||||
self.meta.loop_start = read_int(smp_data)
|
|
||||||
self.meta.loop_end = read_int(smp_data)
|
|
||||||
smp_data.read(16) # sample presence bitfields
|
|
||||||
self.data = smp_data.read(self.meta.length)
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
from io import BytesIO
|
|
||||||
from typing import Optional, Union, BinaryIO, List
|
|
||||||
|
|
||||||
from chipchune._util import read_short, read_int, read_str
|
|
||||||
from .data_types import WavetableMeta
|
|
||||||
from .enums import _FurWavetableImportType
|
|
||||||
|
|
||||||
FILE_MAGIC_STR = b'-Furnace waveta-'
|
|
||||||
EMBED_MAGIC_STR = b'WAVE'
|
|
||||||
|
|
||||||
|
|
||||||
class FurnaceWavetable:
|
|
||||||
def __init__(self, file_name: Optional[str] = None) -> None:
|
|
||||||
"""
|
|
||||||
Creates or opens a new Furnace wavetable as a Python object.
|
|
||||||
|
|
||||||
:param file_name: (Optional)
|
|
||||||
If specified, then it will parse a file as a FurnaceWavetable. If file name (str) is
|
|
||||||
given, it will load that file.
|
|
||||||
|
|
||||||
Defaults to None.
|
|
||||||
"""
|
|
||||||
self.file_name: Optional[str] = None
|
|
||||||
"""
|
|
||||||
Original file name, if the object was initialized with one.
|
|
||||||
"""
|
|
||||||
self.meta: WavetableMeta = WavetableMeta()
|
|
||||||
"""
|
|
||||||
Wavetable metadata.
|
|
||||||
"""
|
|
||||||
self.data: List[int] = []
|
|
||||||
"""
|
|
||||||
Wavetable data.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(file_name, str):
|
|
||||||
self.load_from_file(file_name)
|
|
||||||
|
|
||||||
def load_from_file(self, file_name: Optional[str] = None) -> None:
|
|
||||||
if isinstance(file_name, str):
|
|
||||||
self.file_name = file_name
|
|
||||||
if self.file_name is None:
|
|
||||||
raise RuntimeError('No file name set, either set self.file_name or pass file_name to the function')
|
|
||||||
|
|
||||||
# since we're loading from an uncompressed file, we can just check the file magic number
|
|
||||||
with open(self.file_name, 'rb') as f:
|
|
||||||
detect_magic = f.peek(len(FILE_MAGIC_STR))[:len(FILE_MAGIC_STR)]
|
|
||||||
if detect_magic == FILE_MAGIC_STR:
|
|
||||||
return self.load_from_stream(f, _FurWavetableImportType.FILE)
|
|
||||||
else: # uncompressed for sure
|
|
||||||
raise ValueError('No recognized file type magic')
|
|
||||||
|
|
||||||
def load_from_bytes(self, data: bytes, import_as: Union[int, _FurWavetableImportType]) -> None:
|
|
||||||
"""
|
|
||||||
Load a wavetable from a series of bytes.
|
|
||||||
|
|
||||||
:param data: Bytes
|
|
||||||
"""
|
|
||||||
return self.load_from_stream(
|
|
||||||
BytesIO(data),
|
|
||||||
import_as
|
|
||||||
)
|
|
||||||
|
|
||||||
def load_from_stream(self, stream: BinaryIO, import_as: Union[int, _FurWavetableImportType]) -> None:
|
|
||||||
"""
|
|
||||||
Load a wavetable from an **uncompressed** stream.
|
|
||||||
|
|
||||||
:param stream: File-like object containing the uncompressed wavetable.
|
|
||||||
:param import_as: int
|
|
||||||
- 0 = wavetable file
|
|
||||||
- 1 = wavetable embedded in module
|
|
||||||
"""
|
|
||||||
if import_as == _FurWavetableImportType.FILE:
|
|
||||||
if stream.read(len(FILE_MAGIC_STR)) != FILE_MAGIC_STR:
|
|
||||||
raise ValueError('Bad magic value for a wavetable file')
|
|
||||||
version = read_short(stream)
|
|
||||||
read_short(stream) # reserved
|
|
||||||
self.__load_embed(stream)
|
|
||||||
|
|
||||||
elif import_as == _FurWavetableImportType.EMBED:
|
|
||||||
return self.__load_embed(stream)
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ValueError('Invalid import type')
|
|
||||||
|
|
||||||
def __load_embed(self, stream: BinaryIO) -> None:
|
|
||||||
if stream.read(len(EMBED_MAGIC_STR)) != EMBED_MAGIC_STR:
|
|
||||||
raise RuntimeError('Bad magic value for a wavetable embed')
|
|
||||||
|
|
||||||
blk_size = read_int(stream)
|
|
||||||
if blk_size > 0:
|
|
||||||
wt_data = BytesIO(stream.read(blk_size))
|
|
||||||
else:
|
|
||||||
wt_data = stream
|
|
||||||
|
|
||||||
self.meta.name = read_str(wt_data)
|
|
||||||
self.meta.width = read_int(wt_data)
|
|
||||||
read_int(wt_data) # reserved
|
|
||||||
self.meta.height = read_int(wt_data) + 1 # serialized height is 1 lower than actual value
|
|
||||||
|
|
||||||
self.data = [read_int(wt_data) for _ in range(self.meta.width)]
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
"""
|
|
||||||
Generic format for manipulating to, from, and between tracker formats.
|
|
||||||
|
|
||||||
- :mod:`chipchune.interchange.enums`: Various constants.
|
|
||||||
- :mod:`chipchune.interchange.furnace`: Adapters for Furnace.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import enum
|
|
||||||
from chipchune._util import EnumShowNameOnly
|
|
||||||
|
|
||||||
class InterNote(EnumShowNameOnly):
|
|
||||||
"""
|
|
||||||
Common note interchange format.
|
|
||||||
"""
|
|
||||||
__ = enum.auto() # Signifies a blank space in tracker
|
|
||||||
C_ = enum.auto()
|
|
||||||
Cs = enum.auto()
|
|
||||||
D_ = enum.auto()
|
|
||||||
Ds = enum.auto()
|
|
||||||
E_ = enum.auto()
|
|
||||||
F_ = enum.auto()
|
|
||||||
Fs = enum.auto()
|
|
||||||
G_ = enum.auto()
|
|
||||||
Gs = enum.auto()
|
|
||||||
A_ = enum.auto()
|
|
||||||
As = enum.auto()
|
|
||||||
B_ = enum.auto()
|
|
||||||
Off = enum.auto()
|
|
||||||
OffRel = enum.auto()
|
|
||||||
Rel = enum.auto()
|
|
||||||
Echo = enum.auto()
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
from chipchune.furnace.enums import Note as FurnaceNote
|
|
||||||
from chipchune.interchange.enums import InterNote
|
|
||||||
|
|
||||||
def furnace_note_to_internote(note: FurnaceNote) -> InterNote:
|
|
||||||
"""
|
|
||||||
Convert a Furnace note into an InterNote.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
- Exception: If the supplied note is out of range.
|
|
||||||
"""
|
|
||||||
if note == FurnaceNote.__: return InterNote.__
|
|
||||||
elif note == FurnaceNote.C_: return InterNote.C_
|
|
||||||
elif note == FurnaceNote.Cs: return InterNote.Cs
|
|
||||||
elif note == FurnaceNote.D_: return InterNote.D_
|
|
||||||
elif note == FurnaceNote.Ds: return InterNote.Ds
|
|
||||||
elif note == FurnaceNote.E_: return InterNote.E_
|
|
||||||
elif note == FurnaceNote.F_: return InterNote.F_
|
|
||||||
elif note == FurnaceNote.Fs: return InterNote.Fs
|
|
||||||
elif note == FurnaceNote.G_: return InterNote.G_
|
|
||||||
elif note == FurnaceNote.Gs: return InterNote.Gs
|
|
||||||
elif note == FurnaceNote.A_: return InterNote.A_
|
|
||||||
elif note == FurnaceNote.As: return InterNote.As
|
|
||||||
elif note == FurnaceNote.B_: return InterNote.B_
|
|
||||||
elif note == FurnaceNote.OFF: return InterNote.Off
|
|
||||||
elif note == FurnaceNote.OFF_REL: return InterNote.OffRel
|
|
||||||
elif note == FurnaceNote.REL: return InterNote.Rel
|
|
||||||
else:
|
|
||||||
raise Exception("Invalid note value %s" % note)
|
|
||||||
|
|
||||||
def internote_to_furnace_note(note: InterNote) -> FurnaceNote:
|
|
||||||
"""
|
|
||||||
Convert an InterNote into a Furnace note. If the equivalent
|
|
||||||
value is unable to be determined, a blank note `__` is returned.
|
|
||||||
"""
|
|
||||||
if note == InterNote.__: return FurnaceNote.__
|
|
||||||
elif note == InterNote.C_: return FurnaceNote.C_
|
|
||||||
elif note == InterNote.Cs: return FurnaceNote.Cs
|
|
||||||
elif note == InterNote.D_: return FurnaceNote.D_
|
|
||||||
elif note == InterNote.Ds: return FurnaceNote.Ds
|
|
||||||
elif note == InterNote.E_: return FurnaceNote.E_
|
|
||||||
elif note == InterNote.F_: return FurnaceNote.F_
|
|
||||||
elif note == InterNote.Fs: return FurnaceNote.Fs
|
|
||||||
elif note == InterNote.G_: return FurnaceNote.G_
|
|
||||||
elif note == InterNote.Gs: return FurnaceNote.Gs
|
|
||||||
elif note == InterNote.A_: return FurnaceNote.A_
|
|
||||||
elif note == InterNote.As: return FurnaceNote.As
|
|
||||||
elif note == InterNote.B_: return FurnaceNote.B_
|
|
||||||
elif note == InterNote.Off: return FurnaceNote.OFF
|
|
||||||
elif note == InterNote.OffRel: return FurnaceNote.OFF_REL
|
|
||||||
elif note == InterNote.Rel: return FurnaceNote.REL
|
|
||||||
else:
|
|
||||||
return FurnaceNote.__
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
"""
|
|
||||||
Utilities for manipulating, converting, etc. tracker data.
|
|
||||||
|
|
||||||
- :mod:`chipchune.utils.conversion`: Conversion tools.
|
|
||||||
"""
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
from chipchune.furnace.module import FurnacePattern
|
|
||||||
from chipchune.interchange.enums import InterNote
|
|
||||||
from chipchune.interchange.furnace import furnace_note_to_internote
|
|
||||||
from typing import Union, List, Tuple
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class SequenceEntry:
|
|
||||||
"""
|
|
||||||
A representation of a row in note-length format. Such a format is commonly
|
|
||||||
used across different sound engines and sequenced data.
|
|
||||||
|
|
||||||
A pattern can be turned into a list of SequenceEntries, which should be easier
|
|
||||||
to convert into a format of your choice.
|
|
||||||
"""
|
|
||||||
note: InterNote
|
|
||||||
length: int
|
|
||||||
volume: int
|
|
||||||
"""
|
|
||||||
Tracker-defined volume; although this should be -1 for undefined values.
|
|
||||||
"""
|
|
||||||
octave: int
|
|
||||||
"""
|
|
||||||
Tracker-defined octave; although this should be -1 for undefined values.
|
|
||||||
"""
|
|
||||||
instrument: int
|
|
||||||
"""
|
|
||||||
Tracker-defined instrument number; although this should be -1 for undefined values.
|
|
||||||
"""
|
|
||||||
effects: List[Tuple[int, int]] = field(default_factory=list)
|
|
||||||
"""
|
|
||||||
Tracker-defined effects list; if undefined, this should be empty.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def pattern_to_sequence(pattern: Union[FurnacePattern, None]) -> List[SequenceEntry]:
|
|
||||||
"""
|
|
||||||
Interface to convert a pattern from tracker rows to a "sequence", which is
|
|
||||||
really a list of SequenceEntries.
|
|
||||||
|
|
||||||
:param pattern:
|
|
||||||
A pattern object. Supported types at the moment: `FurnacePattern`.
|
|
||||||
Anything outside of the supported types will throw a `TypeError`.
|
|
||||||
"""
|
|
||||||
if isinstance(pattern, FurnacePattern):
|
|
||||||
return furnace_pattern_to_sequence(pattern)
|
|
||||||
else:
|
|
||||||
raise TypeError("Invalid pattern type; must be one of: FurnacePattern")
|
|
||||||
|
|
||||||
def furnace_pattern_to_sequence(pattern: FurnacePattern) -> List[SequenceEntry]:
|
|
||||||
converted: List[SequenceEntry] = []
|
|
||||||
last_volume = -1
|
|
||||||
for i in pattern.data:
|
|
||||||
note = furnace_note_to_internote(i.note)
|
|
||||||
effects = i.effects
|
|
||||||
volume = i.volume
|
|
||||||
instrument = i.instrument
|
|
||||||
|
|
||||||
if effects == [(65535, 65535)]:
|
|
||||||
effects = []
|
|
||||||
|
|
||||||
if volume == 65535:
|
|
||||||
volume = last_volume
|
|
||||||
else:
|
|
||||||
last_volume = volume
|
|
||||||
|
|
||||||
if instrument == 65535:
|
|
||||||
instrument = -1
|
|
||||||
|
|
||||||
if note == InterNote.__:
|
|
||||||
if len(converted) == 0:
|
|
||||||
converted.append(
|
|
||||||
SequenceEntry(
|
|
||||||
note=InterNote.__,
|
|
||||||
length=1,
|
|
||||||
volume=volume,
|
|
||||||
octave=i.octave,
|
|
||||||
instrument=instrument,
|
|
||||||
effects=effects,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
converted[-1].length += 1
|
|
||||||
else:
|
|
||||||
converted.append(
|
|
||||||
SequenceEntry(
|
|
||||||
note=note,
|
|
||||||
length=1,
|
|
||||||
volume=volume,
|
|
||||||
octave=i.octave,
|
|
||||||
instrument=instrument,
|
|
||||||
effects=effects,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return converted
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
@echo off
|
|
||||||
if [%1]==[] goto usage
|
|
||||||
python3 convert_to_asm.py %1
|
|
||||||
echo converted .fur file to .asm!
|
|
||||||
cd asm
|
|
||||||
cl65 -d -vm -l furC64.lst -g -u __EXEHDR__ -t c64 -C .\c64-asm.cfg -m furC64.map -Ln furC64.lbl -o furC64-test.prg furC64.asm
|
|
||||||
@echo compiled .prg file at asm/furC64-test.prg
|
|
||||||
cd ..
|
|
||||||
goto :eof
|
|
||||||
:usage
|
|
||||||
@echo No arguments supplied
|
|
||||||
@echo Make sure to run this command with an argument
|
|
||||||
@echo example: convert.bat test_file.fur
|
|
||||||
exit /B 1
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
if [ $# -eq 0 ]
|
|
||||||
then
|
|
||||||
echo "No arguments supplied"
|
|
||||||
echo "Make sure to run this command with an argument"
|
|
||||||
echo "example: convert.sh test_file.fur"
|
|
||||||
else
|
|
||||||
python3 convert_to_asm.py $1
|
|
||||||
echo "converted .fur file to .asm!"
|
|
||||||
cd asm
|
|
||||||
cl65 -d -vm -l furC64.lst -g -u __EXEHDR__ -t c64 -C ./exe.cfg -m furC64.map -Ln furC64.lbl -o furC64-test.prg furC64.asm
|
|
||||||
cl65 -d -C ./bin.cfg -o song.bin furC64.asm
|
|
||||||
echo "compiled .prg file at asm/furC64-test.prg"
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
@ -1,786 +0,0 @@
|
||||||
from chipchune.furnace.module import FurnaceModule
|
|
||||||
from chipchune.furnace.data_types import InsFeatureMacro, InsFeatureC64, InsFeatureAmiga
|
|
||||||
from chipchune.furnace.enums import MacroCode, MacroItem, MacroType
|
|
||||||
from chipchune.furnace.enums import InstrumentType
|
|
||||||
import sys
|
|
||||||
|
|
||||||
subsong = 0
|
|
||||||
note_transpose = 0
|
|
||||||
dups = {}
|
|
||||||
|
|
||||||
print(sys.argv)
|
|
||||||
module = FurnaceModule(sys.argv[1])
|
|
||||||
chnum = module.get_num_channels()
|
|
||||||
|
|
||||||
speed_type = len(module.subsongs[subsong].speed_pattern)
|
|
||||||
|
|
||||||
notes = ["C_","Cs","D_","Ds","E_","F_","Fs","G_","Gs","A_","As","B_"]
|
|
||||||
|
|
||||||
def comp(pat):
|
|
||||||
i = 0
|
|
||||||
o = []
|
|
||||||
n = 0
|
|
||||||
while i < len(pat):
|
|
||||||
j = i
|
|
||||||
k = 0
|
|
||||||
if pat[i] >= 0x40 and pat[i] < 128: i += 1
|
|
||||||
elif pat[i] == 0xFB: i += 2
|
|
||||||
elif pat[i] == 0xFC: i += 2
|
|
||||||
elif pat[i] == 0xE0: i += 2
|
|
||||||
elif pat[i] == 0xE1: i += 2
|
|
||||||
elif pat[i] == 0xE2: i += 2
|
|
||||||
elif pat[i] == 0xE3: i += 2
|
|
||||||
elif pat[i] == 0xE4: i += 2
|
|
||||||
elif pat[i] == 0xE5: i += 3
|
|
||||||
elif pat[i] == 0xE6: i += 2
|
|
||||||
elif pat[i] == 0xE7: i += 2
|
|
||||||
elif pat[i] == 0xE8: i += 2
|
|
||||||
elif pat[i] == 0xE9: i += 3
|
|
||||||
elif pat[i] == 0xEA: i += 3
|
|
||||||
elif pat[i] == 0xEB: i += 2
|
|
||||||
elif pat[i] == 0xEC: i += 2
|
|
||||||
elif pat[i] == 0xED: i += 2
|
|
||||||
elif pat[i] == 0xEE: i += 2
|
|
||||||
elif pat[i] == 0xEF: i += 1
|
|
||||||
elif pat[i] == 0xF0: i += 1
|
|
||||||
elif pat[i] == 0xF1: i += 2
|
|
||||||
elif pat[i] == 0xF2: i += 2
|
|
||||||
elif pat[i] == 0xFF: i += 2
|
|
||||||
elif pat[i] == 0xFD:
|
|
||||||
i += 1
|
|
||||||
n = 2
|
|
||||||
elif pat[i] == 0xFE:
|
|
||||||
i += 1
|
|
||||||
n = 2
|
|
||||||
elif pat[i] >= 128:
|
|
||||||
i += 1
|
|
||||||
n = 2
|
|
||||||
else:
|
|
||||||
k = 1
|
|
||||||
if n == 0:
|
|
||||||
o.append(pat[i])
|
|
||||||
elif pat[i] > 1:
|
|
||||||
o.append(pat[i]-1)
|
|
||||||
#print(i,pat[i])
|
|
||||||
i += 1
|
|
||||||
n = max(n-1,0)
|
|
||||||
if k == 0:
|
|
||||||
o.extend(pat[j:i])
|
|
||||||
#print(pat,"\n",o,"\n")
|
|
||||||
return o
|
|
||||||
|
|
||||||
def conv_pattern(pattern):
|
|
||||||
out = [0]
|
|
||||||
oldtemp = [0,0]
|
|
||||||
r = 0
|
|
||||||
bitind = 0
|
|
||||||
oldins = -1
|
|
||||||
for row in pattern.data:
|
|
||||||
has03xx = 0
|
|
||||||
for l in row.effects:
|
|
||||||
k = list(l)
|
|
||||||
if k[0] == 0x03 and k[1] > 0:
|
|
||||||
has03xx = 1
|
|
||||||
break
|
|
||||||
|
|
||||||
temp = []
|
|
||||||
notnote = 0
|
|
||||||
new_byte = 0
|
|
||||||
if row.instrument != 65535 and oldins != row.instrument:
|
|
||||||
new_byte = 1
|
|
||||||
if row.instrument < 0x40:
|
|
||||||
temp.append(row.instrument+0x40)
|
|
||||||
else:
|
|
||||||
temp.append(0xFB)
|
|
||||||
temp.append(row.instrument)
|
|
||||||
oldins = row.instrument
|
|
||||||
if row.volume != 65535:
|
|
||||||
new_byte = 1
|
|
||||||
temp.append(0xFC)
|
|
||||||
temp.append(row.volume)
|
|
||||||
|
|
||||||
hasEffect = [-1,-1]
|
|
||||||
has0Dxx = -1
|
|
||||||
for l in row.effects:
|
|
||||||
k = list(l)
|
|
||||||
if k[1] == 65535:
|
|
||||||
k[1] = 0
|
|
||||||
|
|
||||||
if k[0] == 0xD:
|
|
||||||
new_byte = 1
|
|
||||||
has0Dxx = k[1]
|
|
||||||
continue
|
|
||||||
if k[0] == 0x0B:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xED, k[1]])
|
|
||||||
has0Dxx = 0
|
|
||||||
continue
|
|
||||||
if k[0] == 0xEE:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xF2, k[1]])
|
|
||||||
has0Dxx = 0
|
|
||||||
continue
|
|
||||||
if (k[0] == 0x09 or k[0] == 0x0F) and (speed_type == 1):
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE1, k[1]])
|
|
||||||
temp.extend([0xE0, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x0F and (speed_type == 2):
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE1, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x09 and (speed_type == 2):
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE0, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x00:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE2, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x01:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE3, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x02:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE4, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x03 and k[1] == 0:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE4, 0])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x03 and k[1] > 0:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE5, k[1], max(min(notes.index(str(row.note))+(row.octave*12)+note_transpose,95),0)])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x04:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE6, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x1B:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE7, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x1C:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE8, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0xE1:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xE9, k[1]>>4, k[1]&15])
|
|
||||||
continue
|
|
||||||
if k[0] == 0xE2:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xEA, k[1]>>4, k[1]&15])
|
|
||||||
continue
|
|
||||||
if k[0] == 0xE5:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xEB, k[1]])
|
|
||||||
continue
|
|
||||||
if k[0] == 0xEC:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xEC, k[1]])
|
|
||||||
continue
|
|
||||||
if (k[0]>>4) == 4:
|
|
||||||
new_byte = 1
|
|
||||||
temp.extend([0xEE, (k[1]|(k[0]&0xf)<<8)>>3])
|
|
||||||
continue
|
|
||||||
if k[0] == 0xEA:
|
|
||||||
new_byte = 1
|
|
||||||
if k[1] == 0:
|
|
||||||
temp.extend([0xEF])
|
|
||||||
else:
|
|
||||||
temp.extend([0xF0])
|
|
||||||
continue
|
|
||||||
if k[0] == 0x1A:
|
|
||||||
new_byte = 1
|
|
||||||
if k[1] > 0:
|
|
||||||
temp.extend([0xF1, 0x00])
|
|
||||||
else:
|
|
||||||
temp.extend([0xF1, 0xFF])
|
|
||||||
continue
|
|
||||||
if str(row.note) == "OFF_REL":
|
|
||||||
notnote = 1
|
|
||||||
new_byte = 1
|
|
||||||
temp.append(0xFD)
|
|
||||||
elif str(row.note) == "REL":
|
|
||||||
notnote = 1
|
|
||||||
new_byte = 1
|
|
||||||
temp.append(0xFD)
|
|
||||||
elif str(row.note) == "OFF":
|
|
||||||
notnote = 1
|
|
||||||
new_byte = 1
|
|
||||||
temp.append(0xFE)
|
|
||||||
elif str(row.note) == "__" or (has03xx == 1):
|
|
||||||
if has03xx == 0:
|
|
||||||
notnote = 1
|
|
||||||
#temp.append(0x80)
|
|
||||||
else:
|
|
||||||
new_byte = 1
|
|
||||||
temp.append(max(min(notes.index(str(row.note))+(row.octave*12)+note_transpose,95),0)+0x80)
|
|
||||||
|
|
||||||
if new_byte == 1:
|
|
||||||
temp.append(0)
|
|
||||||
out.extend(temp)
|
|
||||||
durpass = False
|
|
||||||
if out[-1] >= 63:
|
|
||||||
out.append(0)
|
|
||||||
if has0Dxx > -1:
|
|
||||||
out[-1] += 1
|
|
||||||
if out[0] == 0: out = out[1:]
|
|
||||||
out.extend([0xFF, has0Dxx])
|
|
||||||
return out
|
|
||||||
out[-1] += 1
|
|
||||||
r += 1
|
|
||||||
out.extend([0xFF, 0])
|
|
||||||
if out[0] == 0: out = out[1:]
|
|
||||||
return out
|
|
||||||
|
|
||||||
f = open("asm/song.asm","w")
|
|
||||||
|
|
||||||
relW = []
|
|
||||||
relA = []
|
|
||||||
relD = []
|
|
||||||
relC = []
|
|
||||||
|
|
||||||
f.write("ticks_init:")
|
|
||||||
f.write(".byte ")
|
|
||||||
if speed_type == 1:
|
|
||||||
f.write(str(module.subsongs[subsong].speed_pattern[0])+", ")
|
|
||||||
f.write(str(module.subsongs[subsong].speed_pattern[0])+"\n")
|
|
||||||
elif speed_type == 2:
|
|
||||||
f.write(str(module.subsongs[subsong].speed_pattern[0])+", ")
|
|
||||||
f.write(str(module.subsongs[subsong].speed_pattern[1])+"\n")
|
|
||||||
|
|
||||||
f.write("insFL:\n")
|
|
||||||
f.write(".lobytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"F")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("insFH:\n")
|
|
||||||
f.write(".hibytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"F")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write("insAL:\n")
|
|
||||||
f.write(".lobytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"A")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("insAH:\n")
|
|
||||||
f.write(".hibytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"A")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write("insDL:\n")
|
|
||||||
f.write(".lobytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"D")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("insDH:\n")
|
|
||||||
f.write(".hibytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"D")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write("insWL:\n")
|
|
||||||
f.write(".lobytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"W")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("insWH:\n")
|
|
||||||
f.write(".hibytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"W")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write("insCL:\n")
|
|
||||||
f.write(".lobytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"C")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("insCH:\n")
|
|
||||||
f.write(".hibytes ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
f.write("ins"+str(i)+"C")
|
|
||||||
if i == len(module.instruments)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
features = module.instruments[i].features
|
|
||||||
a = filter(
|
|
||||||
lambda x: (
|
|
||||||
type(x) == InsFeatureMacro
|
|
||||||
), features
|
|
||||||
)
|
|
||||||
macros = []
|
|
||||||
for j in a:
|
|
||||||
macros = j.macros
|
|
||||||
hasWaveMacro = 0
|
|
||||||
hasCutMacro = 0
|
|
||||||
for j in macros:
|
|
||||||
kind = j.kind
|
|
||||||
if kind == MacroCode.WAVE:
|
|
||||||
hasWaveMacro = 1
|
|
||||||
continue
|
|
||||||
if kind == MacroCode.ALG:
|
|
||||||
hasCutMacro = 1
|
|
||||||
continue
|
|
||||||
|
|
||||||
hasAbsFilter = False
|
|
||||||
hasAbsDuty = False
|
|
||||||
written_ins = False
|
|
||||||
|
|
||||||
a = filter(
|
|
||||||
lambda x: (
|
|
||||||
type(x) == InsFeatureMacro
|
|
||||||
), features
|
|
||||||
)
|
|
||||||
macros = []
|
|
||||||
for j in a:
|
|
||||||
macros = j.macros
|
|
||||||
for j in macros:
|
|
||||||
kind = j.kind
|
|
||||||
if kind == MacroCode.DUTY and j.type == MacroType.LFO:
|
|
||||||
hasAbsDuty = True
|
|
||||||
|
|
||||||
a = filter(
|
|
||||||
lambda x: (
|
|
||||||
type(x) == InsFeatureC64
|
|
||||||
), features
|
|
||||||
)
|
|
||||||
for j in a:
|
|
||||||
wave = j.tri_on
|
|
||||||
wave |= j.saw_on<<1
|
|
||||||
wave |= j.pulse_on<<2
|
|
||||||
wave |= j.noise_on<<3
|
|
||||||
wave <<= 4
|
|
||||||
wave |= j.ring_mod<<2
|
|
||||||
wave |= j.osc_sync<<1
|
|
||||||
f.write("ins"+str(i)+"F:\n")
|
|
||||||
f.write(".byte ")
|
|
||||||
f.write(str(wave)+", ")
|
|
||||||
ad = (j.envelope.a<<4)|j.envelope.d
|
|
||||||
sr = (j.envelope.s<<4)|j.envelope.r
|
|
||||||
f.write(str(ad)+", ")
|
|
||||||
f.write(str(sr)+", ")
|
|
||||||
f.write(str(j.duty&0xff)+", ")
|
|
||||||
f.write(str(j.duty>>8)+", ")
|
|
||||||
flags = 0
|
|
||||||
if j.duty_is_abs:
|
|
||||||
flags |= 1
|
|
||||||
if hasWaveMacro:
|
|
||||||
flags |= 2
|
|
||||||
if j.to_filter:
|
|
||||||
flags |= 4
|
|
||||||
if j.init_filter:
|
|
||||||
flags |= 8
|
|
||||||
if j.filter_is_abs:
|
|
||||||
flags |= 16
|
|
||||||
if hasCutMacro:
|
|
||||||
flags |= 32
|
|
||||||
if not j.no_test:
|
|
||||||
flags |= 64
|
|
||||||
f.write(str(flags)+", ")
|
|
||||||
fil = 0
|
|
||||||
fil = j.lp<<4
|
|
||||||
fil |= j.bp<<5
|
|
||||||
fil |= j.hp<<6
|
|
||||||
fil |= j.ch3_off<<7
|
|
||||||
f.write(str(j.res<<4)+", ")
|
|
||||||
f.write(str(fil)+", ")
|
|
||||||
f.write(str(j.cut&0xff)+", ")
|
|
||||||
f.write(str((j.cut>>8)&15)+"\n")
|
|
||||||
f.write("\n")
|
|
||||||
written_ins = True
|
|
||||||
hasAbsDuty |= j.duty_is_abs
|
|
||||||
hasAbsFilter = j.filter_is_abs
|
|
||||||
if written_ins == False:
|
|
||||||
f.write("ins"+str(i)+"F:\n")
|
|
||||||
f.write(".byte 32, 8, 0, 255, 7, 0\n")
|
|
||||||
a = filter(
|
|
||||||
lambda x: (
|
|
||||||
type(x) == InsFeatureMacro
|
|
||||||
), features
|
|
||||||
)
|
|
||||||
arp = [128,0xFF,0xFF]
|
|
||||||
duty = [0xFF,0xFF]
|
|
||||||
wave = [0xFF,0xFF]
|
|
||||||
cutoff = [0xFF,0xFF]
|
|
||||||
macros = []
|
|
||||||
for j in a:
|
|
||||||
macros = j.macros
|
|
||||||
hasRelTotal = [0,0,0,0]
|
|
||||||
for j in macros:
|
|
||||||
kind = j.kind
|
|
||||||
if kind == MacroCode.ARP:
|
|
||||||
s = j.speed
|
|
||||||
arp = []
|
|
||||||
loop = 0xff
|
|
||||||
hasRel = 0
|
|
||||||
oldlen = 0
|
|
||||||
if j.data[-1] == MacroItem.LOOP:
|
|
||||||
arr = [MacroItem.LOOP, j.data[-2]]
|
|
||||||
j.data = j.data[:-2] + arr
|
|
||||||
for k in j.data:
|
|
||||||
if k == MacroItem.LOOP:
|
|
||||||
loop = oldlen
|
|
||||||
elif k == MacroItem.RELEASE:
|
|
||||||
arp.append(0xFF)
|
|
||||||
arp.append(loop)
|
|
||||||
relA.append(len(arp))
|
|
||||||
oldlen = max(len(arp),0)
|
|
||||||
hasRel = 1
|
|
||||||
elif (k>>30) > 0:
|
|
||||||
arp.append(0xFE)
|
|
||||||
k = abs(k^(1<<30))
|
|
||||||
k = max(min(k,95),0)
|
|
||||||
arp.append(k%120)
|
|
||||||
oldlen = max(len(arp),0)
|
|
||||||
else:
|
|
||||||
if k < 0:
|
|
||||||
arp.append((k%120)-120+128)
|
|
||||||
else:
|
|
||||||
arp.append((k%120)+128)
|
|
||||||
oldlen = max(len(arp),0)
|
|
||||||
if hasRel == 0:
|
|
||||||
relA.append(len(arp))
|
|
||||||
hasRelTotal[1] = 1
|
|
||||||
len_temp = len(arp)
|
|
||||||
arp.append(0xFF)
|
|
||||||
arp.append(loop if loop!=len_temp else 0xff)
|
|
||||||
if kind == MacroCode.DUTY and j.type == MacroType.LFO:
|
|
||||||
while type(j.data[0]) is not int:
|
|
||||||
j.data = j.data[1:]
|
|
||||||
|
|
||||||
s = j.speed
|
|
||||||
duty = []
|
|
||||||
hasRel = 0
|
|
||||||
lfo = j.data[13]
|
|
||||||
while lfo <= 1023:
|
|
||||||
lfo += j.data[11]
|
|
||||||
if lfo > 1023: break
|
|
||||||
k = lfo
|
|
||||||
if k & 512:
|
|
||||||
k = 1023-lfo
|
|
||||||
k >>= 1
|
|
||||||
k = j.data[0]+((k+(j.data[1]-j.data[0])*k)>>8)
|
|
||||||
if (k&0xff) == 255:
|
|
||||||
duty.append(254)
|
|
||||||
else:
|
|
||||||
duty.append(k&0xff)
|
|
||||||
duty.append(k>>8)
|
|
||||||
if hasRel == 0:
|
|
||||||
relD.append(0)
|
|
||||||
hasRelTotal[2] = 1
|
|
||||||
duty.append(0xFF)
|
|
||||||
duty.append(0)
|
|
||||||
elif kind == MacroCode.DUTY:
|
|
||||||
s = j.speed
|
|
||||||
duty = []
|
|
||||||
loop = 0xff
|
|
||||||
loop2 = 0
|
|
||||||
hasRel = 0
|
|
||||||
for k in j.data:
|
|
||||||
if k == MacroItem.LOOP:
|
|
||||||
loop = loop2
|
|
||||||
elif k == MacroItem.RELEASE:
|
|
||||||
duty.append(0xFF)
|
|
||||||
duty.append(loop)
|
|
||||||
relD.append(len(duty))
|
|
||||||
hasRel = 1
|
|
||||||
else:
|
|
||||||
loop2 = len(duty)+2
|
|
||||||
if hasAbsDuty:
|
|
||||||
if (k&0xff) == 255:
|
|
||||||
duty.append(254)
|
|
||||||
else:
|
|
||||||
duty.append(k&0xff)
|
|
||||||
duty.append(k>>8)
|
|
||||||
else:
|
|
||||||
k = 32768-(k*4) #4)
|
|
||||||
duty.append(k&0xff)
|
|
||||||
duty.append(k>>8)
|
|
||||||
if hasRel == 0:
|
|
||||||
relD.append(len(duty))
|
|
||||||
hasRelTotal[2] = 1
|
|
||||||
len_temp = len(duty)
|
|
||||||
duty.append(0xFF)
|
|
||||||
duty.append(loop if loop!=len_temp else 0xff)
|
|
||||||
if kind == MacroCode.ALG and j.type == MacroType.LFO:
|
|
||||||
while type(j.data[0]) is not int:
|
|
||||||
j.data = j.data[1:]
|
|
||||||
|
|
||||||
s = j.speed
|
|
||||||
cutoff = []
|
|
||||||
hasRel = 0
|
|
||||||
lfo = j.data[13]
|
|
||||||
while lfo <= 1023:
|
|
||||||
lfo += j.data[11]
|
|
||||||
k = lfo
|
|
||||||
if k & 512:
|
|
||||||
k = 1023-lfo
|
|
||||||
k >>= 1
|
|
||||||
k = j.data[0]+((k+(j.data[1]-j.data[0])*k)>>8)
|
|
||||||
if (k&0xff) == 255:
|
|
||||||
cutoff.append(254)
|
|
||||||
else:
|
|
||||||
cutoff.append(k&0xff)
|
|
||||||
cutoff.append(k>>8)
|
|
||||||
if hasRel == 0:
|
|
||||||
relC.append(len(cutoff))
|
|
||||||
hasRelTotal[3] = 1
|
|
||||||
cutoff.append(0xFF)
|
|
||||||
cutoff.append(0)
|
|
||||||
elif kind == MacroCode.ALG:
|
|
||||||
s = j.speed
|
|
||||||
cutoff = []
|
|
||||||
loop = 0xff
|
|
||||||
loop2 = 0
|
|
||||||
hasRel = 0
|
|
||||||
for k in j.data:
|
|
||||||
if k == MacroItem.LOOP:
|
|
||||||
loop = loop2
|
|
||||||
elif k == MacroItem.RELEASE:
|
|
||||||
cutoff.append(0xFF)
|
|
||||||
cutoff.append(loop)
|
|
||||||
relC.append(len(cutoff))
|
|
||||||
hasRel = 1
|
|
||||||
else:
|
|
||||||
loop2 = len(cutoff)+1
|
|
||||||
if hasAbsFilter:
|
|
||||||
if (k&0xff) == 255:
|
|
||||||
cutoff.append(254)
|
|
||||||
else:
|
|
||||||
cutoff.append(k&0xff)
|
|
||||||
cutoff.append(k>>8)
|
|
||||||
else:
|
|
||||||
k = 32768+k*7
|
|
||||||
cutoff.append(k&0xff)
|
|
||||||
cutoff.append(k>>8)
|
|
||||||
if hasRel == 0:
|
|
||||||
relC.append(len(cutoff))
|
|
||||||
hasRelTotal[3] = 1
|
|
||||||
len_temp = len(cutoff)
|
|
||||||
cutoff.append(0xFF)
|
|
||||||
cutoff.append(loop if loop!=len_temp else 0xff)
|
|
||||||
if kind == MacroCode.WAVE:
|
|
||||||
s = j.speed
|
|
||||||
wave = []
|
|
||||||
loop = 0xff
|
|
||||||
loop2 = 0
|
|
||||||
hasRel = 0
|
|
||||||
for k in j.data:
|
|
||||||
if k == MacroItem.LOOP:
|
|
||||||
loop = len(wave)
|
|
||||||
elif k == MacroItem.RELEASE:
|
|
||||||
wave.append(0xFF)
|
|
||||||
wave.append(loop)
|
|
||||||
relW.append(len(wave))
|
|
||||||
hasRel = 1
|
|
||||||
else:
|
|
||||||
wave.append(k<<4)
|
|
||||||
if hasRel == 0:
|
|
||||||
relW.append(len(wave))
|
|
||||||
hasRelTotal[0] = 1
|
|
||||||
len_temp = len(wave)
|
|
||||||
wave.append(0xFF)
|
|
||||||
wave.append(loop if loop!=len_temp else 0xff)
|
|
||||||
if hasRelTotal[0] == 0:
|
|
||||||
relW.append(0)
|
|
||||||
if hasRelTotal[1] == 0:
|
|
||||||
relA.append(0)
|
|
||||||
if hasRelTotal[2] == 0:
|
|
||||||
relD.append(0)
|
|
||||||
if hasRelTotal[3] == 0:
|
|
||||||
relC.append(0)
|
|
||||||
wave = str(wave)[1:-1]
|
|
||||||
duty = str(duty)[1:-1]
|
|
||||||
arp = str(arp)[1:-1]
|
|
||||||
cutoff = str(cutoff)[1:-1]
|
|
||||||
if arp in dups:
|
|
||||||
f.write("ins"+str(i)+"A = "+dups[arp]+"\n")
|
|
||||||
else:
|
|
||||||
f.write("ins"+str(i)+"A:\n")
|
|
||||||
f.write(".byte "+arp+"\n")
|
|
||||||
dups[arp] = "ins"+str(i)+"A"
|
|
||||||
|
|
||||||
if duty in dups:
|
|
||||||
f.write("ins"+str(i)+"D = "+dups[duty]+"\n")
|
|
||||||
else:
|
|
||||||
f.write("ins"+str(i)+"D:\n")
|
|
||||||
f.write(".byte "+duty+"\n")
|
|
||||||
dups[duty] = "ins"+str(i)+"D"
|
|
||||||
|
|
||||||
if wave in dups:
|
|
||||||
f.write("ins"+str(i)+"W = "+dups[wave]+"\n")
|
|
||||||
else:
|
|
||||||
f.write("ins"+str(i)+"W:\n")
|
|
||||||
f.write(".byte "+wave+"\n")
|
|
||||||
dups[wave] = "ins"+str(i)+"W"
|
|
||||||
|
|
||||||
if cutoff in dups:
|
|
||||||
f.write("ins"+str(i)+"C = "+dups[cutoff]+"\n")
|
|
||||||
else:
|
|
||||||
f.write("ins"+str(i)+"C:\n")
|
|
||||||
f.write(".byte "+cutoff+"\n")
|
|
||||||
dups[cutoff] = "ins"+str(i)+"C"
|
|
||||||
|
|
||||||
relW = str(relW)[1:-1]
|
|
||||||
relD = str(relD)[1:-1]
|
|
||||||
relA = str(relA)[1:-1]
|
|
||||||
f.write("insArel:\n")
|
|
||||||
f.write(".byte "+relA+"\n")
|
|
||||||
f.write("insDrel:\n")
|
|
||||||
f.write(".byte "+relD+"\n")
|
|
||||||
f.write("insWrel:\n")
|
|
||||||
f.write(".byte "+relW+"\n")
|
|
||||||
|
|
||||||
for i in range(chnum):
|
|
||||||
order = module.subsongs[subsong].order[i]
|
|
||||||
f.write("order"+str(i)+"len = "+str(len(order))+"\n")
|
|
||||||
f.write("order"+str(i)+"L:\n")
|
|
||||||
f.write(".byte ")
|
|
||||||
for o in range(len(order)):
|
|
||||||
f.write("<(patCH"+str(i)+"N"+str(order[o])+"-1)")
|
|
||||||
if o == len(order)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
f.write("order"+str(i)+"H:\n")
|
|
||||||
f.write(".byte ")
|
|
||||||
for o in range(len(order)):
|
|
||||||
f.write(">(patCH"+str(i)+"N"+str(order[o])+"-1)")
|
|
||||||
if o == len(order)-1:
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
for i in range(chnum):
|
|
||||||
order = module.subsongs[subsong].order[i]
|
|
||||||
avail_patterns = filter(
|
|
||||||
lambda x: (
|
|
||||||
x.channel == i and
|
|
||||||
x.subsong == subsong
|
|
||||||
),
|
|
||||||
module.patterns
|
|
||||||
)
|
|
||||||
for p in avail_patterns:
|
|
||||||
patnum = p.index
|
|
||||||
#print(patnum,i)
|
|
||||||
g = str(comp(conv_pattern(p)))[1:-1]
|
|
||||||
f.write("patCH"+str(i)+"N"+str(patnum)+":\n")
|
|
||||||
f.write(".byte "+g+"\n")
|
|
||||||
|
|
||||||
if chnum == 4:
|
|
||||||
f.write("sampleHS:\n.hibytes ")
|
|
||||||
for i in range(len(module.samples)):
|
|
||||||
f.write("PCM"+str(i))
|
|
||||||
if i == (len(module.samples)-1):
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write("sampleHE:\n.hibytes ")
|
|
||||||
for i in range(len(module.samples)):
|
|
||||||
f.write("PCMe"+str(i))
|
|
||||||
if i == (len(module.samples)-1):
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
total_maps = []
|
|
||||||
f.write("insSI:\n.byte ")
|
|
||||||
for i in range(len(module.instruments)):
|
|
||||||
features = module.instruments[i].features
|
|
||||||
a = filter(
|
|
||||||
lambda x: (
|
|
||||||
type(x) == InsFeatureAmiga
|
|
||||||
), features
|
|
||||||
)
|
|
||||||
init_sample = 0
|
|
||||||
for j in a:
|
|
||||||
if j.init_sample > 0 and j.init_sample != 65535:
|
|
||||||
init_sample = j.init_sample
|
|
||||||
break
|
|
||||||
f.write(str(init_sample))
|
|
||||||
if i == (len(module.instruments)-1):
|
|
||||||
f.write("\n")
|
|
||||||
else:
|
|
||||||
f.write(", ")
|
|
||||||
|
|
||||||
f.write(".res 256-(*&$ff), 0\n")
|
|
||||||
for i in range(len(module.samples)):
|
|
||||||
sample = []
|
|
||||||
rate = max(min(module.samples[i].meta.sample_rate,384000),100)
|
|
||||||
smp = list(module.samples[i].data)
|
|
||||||
k = 0
|
|
||||||
while k < len(smp):
|
|
||||||
j = smp[int(k)]
|
|
||||||
s = float(((int(j)+128)&0xff))
|
|
||||||
s = ((s-128)/1.65)+128
|
|
||||||
#s = ((s-128)/1.6)+128
|
|
||||||
s = int(s/16)
|
|
||||||
#s = (s>>1)+8
|
|
||||||
sample.append(s)
|
|
||||||
k += rate/7812
|
|
||||||
s = sample[-1]
|
|
||||||
if (len(sample)%256) == 0:
|
|
||||||
sample.extend([s]*256)
|
|
||||||
else:
|
|
||||||
while (len(sample)%256) != 0:
|
|
||||||
sample.append(s)
|
|
||||||
f.write("PCM"+str(i)+":\n.byte "+str(sample)[1:-1]+"\n")
|
|
||||||
f.write("PCMe"+str(i)+":\n")
|
|
||||||
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# frequency calculation code taken from
|
|
||||||
# https://codebase64.org/doku.php?id=base:how_to_calculate_your_own_sid_frequency_table
|
|
||||||
|
|
||||||
tuning = module.meta.tuning
|
|
||||||
f = open("asm/note_lo.bin","wb")
|
|
||||||
for i in range(96):
|
|
||||||
hz = tuning * (2**(float(i-57)/12.0))
|
|
||||||
cnst = (256**3)/985248.0 # PAL frequency
|
|
||||||
freq = min(max(hz*cnst,0),0xffff)
|
|
||||||
f.write(bytearray([int(freq)&0xff]))
|
|
||||||
f.close()
|
|
||||||
f = open("asm/note_hi.bin","wb")
|
|
||||||
for i in range(96):
|
|
||||||
hz = tuning * (2**(float(i-57)/12.0))
|
|
||||||
cnst = (256**3)/985248.0 # PAL frequency
|
|
||||||
freq = min(max(hz*cnst,0),0xffff)
|
|
||||||
f.write(bytearray([(int(freq)>>8)&0xff]))
|
|
||||||
f.close()
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
python3 conv_liltalk.py
|
|
||||||
./build_liltalk.sh
|
|
||||||
rm main.o main.zx0*
|
|
||||||
make
|
|
||||||
|
|
@ -1,454 +0,0 @@
|
||||||
3 A
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 y
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3
|
|
||||||
3 O
|
|
||||||
3 K
|
|
||||||
3 ?
|
|
||||||
20
|
|
||||||
|
|
||||||
3 .
|
|
||||||
3 .
|
|
||||||
3 .
|
|
||||||
3
|
|
||||||
3 W
|
|
||||||
3 h
|
|
||||||
3 o
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 y
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
20 ?
|
|
||||||
|
|
||||||
6
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
|
|
||||||
3 T
|
|
||||||
3 h
|
|
||||||
3 a
|
|
||||||
3 n
|
|
||||||
3 k
|
|
||||||
3
|
|
||||||
3 g
|
|
||||||
3 o
|
|
||||||
3 o
|
|
||||||
3 d
|
|
||||||
3 n
|
|
||||||
3 e
|
|
||||||
3 s
|
|
||||||
3 s
|
|
||||||
2 .\n
|
|
||||||
1
|
|
||||||
|
|
||||||
3 I
|
|
||||||
3 '
|
|
||||||
3 m
|
|
||||||
3
|
|
||||||
3 L
|
|
||||||
3 i
|
|
||||||
3 l
|
|
||||||
3 i
|
|
||||||
3 a
|
|
||||||
3
|
|
||||||
3 f
|
|
||||||
3 r
|
|
||||||
3 o
|
|
||||||
3 m
|
|
||||||
3
|
|
||||||
3 L
|
|
||||||
3 a
|
|
||||||
3 n
|
|
||||||
3 c
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 v
|
|
||||||
3 i
|
|
||||||
3 l
|
|
||||||
3 l
|
|
||||||
3 a
|
|
||||||
3 g
|
|
||||||
3 e
|
|
||||||
3 .
|
|
||||||
20
|
|
||||||
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
1
|
|
||||||
|
|
||||||
3 H
|
|
||||||
3 a
|
|
||||||
3 v
|
|
||||||
3 i
|
|
||||||
3 n
|
|
||||||
3 g
|
|
||||||
3
|
|
||||||
3 s
|
|
||||||
3 o
|
|
||||||
3 m
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 k
|
|
||||||
3 i
|
|
||||||
3 n
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 o
|
|
||||||
3 f
|
|
||||||
3
|
|
||||||
3 p
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3 m
|
|
||||||
3 o
|
|
||||||
3 n
|
|
||||||
3 i
|
|
||||||
3 t
|
|
||||||
3 i
|
|
||||||
3 o
|
|
||||||
3 n
|
|
||||||
2 ,\n
|
|
||||||
1
|
|
||||||
|
|
||||||
3 I
|
|
||||||
3
|
|
||||||
3 c
|
|
||||||
3 a
|
|
||||||
3 m
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 t
|
|
||||||
3 o
|
|
||||||
3
|
|
||||||
3 h
|
|
||||||
3 a
|
|
||||||
3 v
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3
|
|
||||||
3 l
|
|
||||||
3 o
|
|
||||||
3 o
|
|
||||||
3 k
|
|
||||||
3 .
|
|
||||||
20
|
|
||||||
|
|
||||||
3 S
|
|
||||||
3 u
|
|
||||||
3 d
|
|
||||||
3 d
|
|
||||||
3 e
|
|
||||||
3 n
|
|
||||||
3 l
|
|
||||||
3 y
|
|
||||||
3 ,
|
|
||||||
3 t
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3 a
|
|
||||||
3
|
|
||||||
3 w
|
|
||||||
3 a
|
|
||||||
3 s
|
|
||||||
3
|
|
||||||
3 e
|
|
||||||
3 n
|
|
||||||
3 v
|
|
||||||
3 e
|
|
||||||
3 l
|
|
||||||
3 o
|
|
||||||
3 p
|
|
||||||
3 e
|
|
||||||
3 d
|
|
||||||
2 \n
|
|
||||||
1
|
|
||||||
|
|
||||||
3 b
|
|
||||||
3 y
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3
|
|
||||||
3 l
|
|
||||||
3 i
|
|
||||||
3 g
|
|
||||||
3 h
|
|
||||||
3 t
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 n
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 y
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3
|
|
||||||
3 c
|
|
||||||
3 o
|
|
||||||
3 l
|
|
||||||
3 l
|
|
||||||
3 a
|
|
||||||
3 p
|
|
||||||
3 s
|
|
||||||
3 e
|
|
||||||
3 d.
|
|
||||||
20
|
|
||||||
|
|
||||||
3 W
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 m
|
|
||||||
3
|
|
||||||
3 I
|
|
||||||
20 ?
|
|
||||||
|
|
||||||
3 T
|
|
||||||
3 h
|
|
||||||
3 i
|
|
||||||
3 s
|
|
||||||
3
|
|
||||||
3 i
|
|
||||||
3 s
|
|
||||||
3
|
|
||||||
3 t
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 k
|
|
||||||
3 i
|
|
||||||
3 n
|
|
||||||
3 g
|
|
||||||
3 d
|
|
||||||
3 o
|
|
||||||
3 m
|
|
||||||
3
|
|
||||||
3 c
|
|
||||||
3 a
|
|
||||||
3 l
|
|
||||||
3 l
|
|
||||||
3 e
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 Y
|
|
||||||
3 s
|
|
||||||
3 .
|
|
||||||
6
|
|
||||||
|
|
||||||
3 T
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3 '
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 m
|
|
||||||
3 o
|
|
||||||
3 n
|
|
||||||
3 s
|
|
||||||
3 t
|
|
||||||
3 e
|
|
||||||
3 r
|
|
||||||
3 s
|
|
||||||
3
|
|
||||||
3 n
|
|
||||||
3 e
|
|
||||||
3 a
|
|
||||||
3 r
|
|
||||||
3 .
|
|
||||||
2 \n
|
|
||||||
20
|
|
||||||
|
|
||||||
3 W
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 s
|
|
||||||
3 h
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3 l
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 g
|
|
||||||
3 o.
|
|
||||||
20
|
|
||||||
|
|
||||||
3 H
|
|
||||||
3 o
|
|
||||||
3 w
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 b
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3 t
|
|
||||||
3
|
|
||||||
3 i
|
|
||||||
3 t
|
|
||||||
2 ,\n
|
|
||||||
1
|
|
||||||
|
|
||||||
3 c
|
|
||||||
3 a
|
|
||||||
3 n
|
|
||||||
3
|
|
||||||
3 y
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3
|
|
||||||
3 s
|
|
||||||
3 t
|
|
||||||
3 a
|
|
||||||
3 n
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 u
|
|
||||||
3 p?
|
|
||||||
20
|
|
||||||
|
|
||||||
3 Y
|
|
||||||
3 e
|
|
||||||
3 a
|
|
||||||
3 h
|
|
||||||
3 ,
|
|
||||||
3 I
|
|
||||||
3 '
|
|
||||||
3 m
|
|
||||||
3
|
|
||||||
3 a
|
|
||||||
3 l
|
|
||||||
3 r
|
|
||||||
3 i
|
|
||||||
3 g
|
|
||||||
3 h
|
|
||||||
3 t
|
|
||||||
3 .
|
|
||||||
3
|
|
||||||
3 S
|
|
||||||
3 h
|
|
||||||
3 o
|
|
||||||
3 u
|
|
||||||
3 l
|
|
||||||
3 d
|
|
||||||
3
|
|
||||||
3 w
|
|
||||||
3 e\n
|
|
||||||
|
|
||||||
3
|
|
||||||
3 G
|
|
||||||
3 o
|
|
||||||
3
|
|
||||||
3 b
|
|
||||||
3 e
|
|
||||||
3 f
|
|
||||||
3 o
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 t
|
|
||||||
3 h
|
|
||||||
3 e
|
|
||||||
3
|
|
||||||
3 m
|
|
||||||
3 o
|
|
||||||
3 n
|
|
||||||
3 s
|
|
||||||
3 t
|
|
||||||
3 e
|
|
||||||
3 r
|
|
||||||
3 s
|
|
||||||
3
|
|
||||||
3 c
|
|
||||||
3 o
|
|
||||||
3 m
|
|
||||||
3 e
|
|
||||||
20 ?
|
|
||||||
|
|
||||||
3 S
|
|
||||||
3 u
|
|
||||||
3 r
|
|
||||||
3 e
|
|
||||||
20 .
|
|
||||||
210
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
MEMORY {
|
|
||||||
ZP: file = "", start = $0002, size = $00FE, define = yes;
|
|
||||||
MAIN: file = %O, start = $0BFE, size = $C402;
|
|
||||||
}
|
|
||||||
SEGMENTS {
|
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
|
||||||
CODE: load = MAIN, type = rw;
|
|
||||||
RODATA: load = MAIN, type = ro, optional = yes;
|
|
||||||
DATA: load = MAIN, type = rw, optional = yes;
|
|
||||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
.zeropage
|
|
||||||
|
|
||||||
.segment "CODE"
|
|
||||||
|
|
||||||
.word $0c00
|
|
||||||
.incbin "font.bin"
|
|
||||||
.res 12
|
|
||||||
|
|
||||||
entry:
|
|
||||||
jmp *
|
|
||||||