diff --git a/Makefile b/Makefile index fc3607d..c531058 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,12 @@ include $(LIB)/common.mk %.data.o: %.data $(BUILD_BINARY_O) +%.pattern.o: %.pattern + $(BUILD_BINARY_O) + +%.tile.o: %.tile + $(BUILD_BINARY_O) + %.bin.o: %.bin $(BUILD_BINARY_O) @@ -45,6 +51,8 @@ vdp2/nbg0.elf: vdp2/nbg0.o res/butterfly.data.o res/butterfly.data.pal.o vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o +vdp2/color_calculation_ratio.elf: vdp2/color_calculation_ratio.o res/mai00.data.o res/mai.data.pal.o res/haohmaru.data.o res/haohmaru.data.pal.o res/forest.data.pal.o res/forest.pattern.o res/forest.tile.o + vdp1/polygon.elf: vdp1/polygon.o vdp1/cube.elf: vdp1/cube.o $(LIBGCC) vdp1/cube2.elf: vdp1/cube2.o diff --git a/res/forest.data b/res/forest.data new file mode 100644 index 0000000..6e8f15f Binary files /dev/null and b/res/forest.data differ diff --git a/res/forest.data.pal b/res/forest.data.pal new file mode 100644 index 0000000..15855a2 Binary files /dev/null and b/res/forest.data.pal differ diff --git a/res/forest.pattern b/res/forest.pattern new file mode 100644 index 0000000..aebad97 Binary files /dev/null and b/res/forest.pattern differ diff --git a/res/forest.tile b/res/forest.tile new file mode 100644 index 0000000..8afe162 --- /dev/null +++ b/res/forest.tile @@ -0,0 +1,3 @@ +ߩ""")""")""")""")""")"""9""!"""ߙybVfbVfbVfbVfbVfbVfbVfbVfeVUUeeUUUeUUUeUUUeUUVUUUVUUUVUUUUUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUVfeUffeUffeUffeUffeUffeUffeUfffififfffff"2"#""#"2"2"""r":!#9:2##*3#3#)r"9ݻy"""2"""))""":"32)iiffffkffififfifYffififf"3f")fb")f"9f"2b3""&"#&)))))999yffffffffffffffffUfUUUfUUUfUUUfUUUfUUefUUefUUefUUUUUfUUUfUUUfUUUfUUUfUUUfUUUfUUUffUUUfUUUfUUUfUUUfUUUfUUUeUUUeUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUVeeeeeeeefffffffffiffjffffiffffߙݙۙٙٙٙٙ"""""""" """""""""""!"#)bVfbVfbVfc&ffc&ffb&ffb&ffb&fVUUUVUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVeUffeVffUVffUVffUfffUeffUeffUeff[ymkkkjwyٙ")22)3"3)""r#)""2""")2""""2""9*9r)9""293):y29r2""9r"*3#"3";"#"#""""")))))ʙfkVkRfkb["vj"b"fr"2"""fj""ff")ff#9ff2f"f)f9)*+j)fffgffyy}ݙffffffffffffffffefUUefUUefUUefUUefUUefUUefUUefUUUUUfUUUfUUUfUUUfUUUfUUUfUUUVUUUVeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUVUUUVUUUVUUUVUUUUUUUUUUUUUUUUeeee˦eY~eYfeYfeYffkffkfffgfjfifffۙfwyiiٙٙٙ"")"")""+""*"#*"")"")"")fb&ffbbffbrefbbefbbefbV5fbV5fbV5UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUVUeffUeffUeffVUffVUfnVUfoVUfoVUfoݙߙٙٙڙٙy2*""9"29#2)32")"""")#2#2)"""""")")""3"""""""9rҩ""""*")")y")r")"92")))욒f#23"2&#"&"""#""#"#)iiiiffffbfffaivfbfffiffmݙ{vfffffffffffffffefUUefUUefUUeVUUeVUUeVUUeVUUeVeUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUVeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeYfeYVfeYffeVffeVfneVf~eVfieVfiiꙙyijm[ڙ۩ﻙ"")"")"")"")"")#3)32")"#fcfRfceRfbeRfceRfceUfceUfceUfceUUUUUUUUUUUUUUUUU%UUU%UUU%UUURUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUVVUfiVUfieVfieUfieUfeUfeUfeUfݩ陙ߙݙy陙ڪںwy)2)"2)"3")")"""")#")22"""2"z)"yyy۫۫"#"""""""2""""""222***)""""""2""")""""""'"*"*6:":2:jjjjffffffiffffffffffٙnٙeޙVmyߙwٙٙ陚zffffffffffffffffeVeUeVeUeVeUeVfUeVVUeVVUeVVUeVVUUUUVUUUVUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUfieUVUiVUVUiVUVUiVUޙٙߙޙimi険yy3""9""#"9""2"!92"3"":)2+ffffffgfceUfceUfSeUfReUfReUfVUUeVUUeVUURUUURUUURUUUR%UUU%UURRUUU"UURU%UUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUVeUfeUfeUfeUfeUfeUfeUfeUfy陙٩ݙ뛣ޙz͒힙ݓݝݭݙݙ"""""=""2"##"2#"߲"")"")""#'ۻۺ۹ݙ"9"##>""#2"""""292*2)2ҙ2Қ22-2="2#2"#"""#""""""""":"""*"*ꪝ/#??#>*jjj˪ʪʪfgoffgΦffofffvgff陯ޙkfjfffffffff뙩yzzffffffffffffffffeVVUeVVUeVVUeVVUeVVUeUVUeUVUeeVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUiVUVUiVUVUiUeUeYiUeYݛٙޙyy""*9"*""*9"*2"*'"*"3922VffffeeUeVUUeVUUUeUUUeUUUeUUVeUUVUUUVUUUU%%URURUU6RURUV%U%U%RUURU%URRUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUf%UUfeUfeUfeUfeUfeUfeUieUieUiݙٙٙٙٙٙݙݙݙݙݙݙݙݟݟݟݟݟݟݟݟݙݙݙݙݙݙݙٙٙٙٙٙy۹ݙݙݙݙݙݙݙ"""22"""י"יٙٙٙ"""#2""""""3""""#-"""""""""2"""22 "2 "#""32""""""""""""#ͪ"#"#""#2""##":""*:#":""22""""""*"!:"*"""*"""*ݪ*ݺ着߯ݫfffffffiffifffffffffffgV홙iffffffffffffffffffffffffffffffffffffffffeeUeeeUeeeUeeeUeeeUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeYiUeYUeYiUeYUeYiUeYUVYiUVYݙݙݙݻ۾ݻ۩ιݷyy"""'""""")""""-"""*"fUeUeUeU+eU9UU:fUU-fUUVUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUU%UURUUUU5UUUeUUUUUUeUUU%UUUUUU%UUfRUUfRUUfU%UfUQVfURffUUfUURVeUiUUiUUiUUiUViUViUViUViٙݹݙݙݙݙݙݙݙݙߝݟߝݝݝݾݺߙ}ۻ}ۻ}ۻ߻驙ݙݙݙݙݙݙݙٙٙٙٙٙٙٙٙ""""""2"""2*"*"""-?:߫,Ӻ̽Ң9:š¹šɩڪڪ"""ꪪۯݭݪݙݙݙݙݙݙݙݙiiiiiiiiffifffifffifffffUUefUUefUUefUUefUUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUfUUUfUUVYUVYUVYUVYUVYUVUUVUUVUݙݙݙݙݙݙݙͻݻٙٙٙיٙ"2*!3+22;2*"fUU"fUU"fUU"&UU"&UU"&UU"&UU""UUeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUU%UUUeUUU%UUUeUUUUUUeUUU%UUUUUUUUV6UUV&UUVRUUfVUUffUUffUUffUUffUViUViUVi%ViaViUURUV)yٙٹיݹ뻚ݺݙݙݙݙݙٙٙٙٙٙyٙ"2!*"""#"""""+"""""""""":˯ڪ着着着着ݪʪݬݪݪͪܬݙݙݙݙݙݙݙݙiiiiiiiifffffffffUUefUUefUUefUUefUUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUfUUUfUUUfUUUfUUUfeUUVeUUVeUUVeUVUUVUUVUUVUUeUUeUUeUUeUYݙݙݙݙݙݙݙۻۻݻݻݻ"f*f!f+f2f;f2f*f""UU""UU""%Ub"%Ub"Ve""VU"#&Ub"%eUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUUefUUefUUefUUefUUefUUefZUefUVUV)UVUVUVUVUVUYܙ))͝ݝݙڙݙݙy""#22#""""9#2""22"#".#"2<""*""ͪꪪ̪̪ݪ쪻ݬʪߺݙݙݙݙݙʻ˻ifffffffffUUefUUefUUefUUefUUeeeUeeeUeeeUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUVeUUVfUUVfUeUYUeUYUeUYUeUYUeUYUefiUefiUefiݙۻۻ߻߫ۻ2ff&fff"ffeffeffeffefUUUb""Uf""Uf""Ueb"UeR"Uef"Uee"UeURUUUUUUUU%UUU%UUU"UUU"eUU"%UU"%UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUVefUVUfUVUfUVUfUfUfUeUfUeUfUYUYUYUYUYUYUYU:s+*"!"+#"""2*2"222""2""""""#)""""#9"#9"*"!"+""+****"̪̪̬Ϭ̬̬̬ʪʪʪʪʪʪ̪̪̬ϫʪʪ̪̪̪̪ʻffffffffeeUVeeUVeeUVeeUVeeUVeeUUefUUUfUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVfUUVfUUVfUUVfUUVfUUVfUUUfUUUfUefiUefiUefiUefiUefeUeVeUeVeUeVeۻffiffffffUfUfUffUbzfUfffUbffUfffUUeURUeUUVUUUVUUUVUUUVUUUeUUUeUUU""UU""UU""%UR"%UR""UR""%U""%R"""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUfUeUfUeUfUeUfUeUfUeUfUeUfUeVfUUUUUUUU"""2""""""""""2""")"##")22")"9************̬̬̬̬̬̬̬ʪʪʪʪʪʪʪ̪̼̪̪̪̪̪̪̪̪ffffffffefUUefUUefUUVfUUVfUUVfUUVfUUVfUUeUUUVUUUVUUUVUUUVUUUVUUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUfUUUfUUUVUUUVUUUVUUUVUUUUeeVeeeVeeeVeeVVeeVVeeVVeeVUeeVUe߿ݙݙݙڙۙffffffffffffffifififfiffbeUffeUfeUfeUveVfeUfeUffeUeUUUeUUUeUUUeUUUUUUUUUUUUUUURUUUU%""R5""U%&"Q5%SU%%RR%%UU%UUR%%U%UUU"UUU"UU"%UU""UU#"&UR2"UU"#%UeVfUeVfUeffUeffUUffUUffUUffUUffUUUUUiUfUfiUfiy"""3"2"32"*3""!:##"*)***ʪ***,ə̬̬̪̪̪̪̪̼̬ͪ̚̚ܪ̺̪̪̪̪̪ʻffffffffVfUUVfUUVfUVfUUVfUeVeUUVeUUVeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeVUefUeefUeffUeffUefVUefVUefVUefYYYYYYUUګffffffffffiffffffffffffffffffffffeUffeUffeRffeUfffUf"%ec""5f"%""UUR"%UR#%U%#"U%""%#""UU""R%"%RU%UUR5%UU%UUQfUUUUUR""%"""%""""UR""UU""UUR"UUV"UUURUUZUUUUUUUUUUUff"Uff#"ff""f"#!&R"""UR""UU""UfiUfiUfUfiUf%i")2""fii""#22""22#""""""""")""#"2"9"̙̙̙̙̪̪̪̪̪̚̚̚ʪʪʪݪݪߪڪ̬̬̪̪̪̪̪̪̪ʪʬʪ˹˚ʩʫʫeeeeeeeefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUVeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUUVfUUVfUUVfUUVfUUVfUUVfUUUVUfeYeYeYeYfYfUfffffffffffffffaff"fR""f"""""%f"""ffb"ffb""ffS2Re"1%R2%RUSRfU%U"5e""Ue"RSe%c5eU"!#"eUS"""""""U""""R"%RR"%U""%e""%e2"%U""UUUUeU%UUU%UUUUUUUUUUUUUUUUUUUUUUUUUUUUUf2UUfeUUVeUUVeUUVUUUVUUUVUUUVU#"""""""U"""Ug"2Ua2)Uf")Vb!)Vfb9"6ff"""""""""""&""2""f#&"fiif""""""""#2"""""2"3""""""""""")2"""""""""""""""2)3)9{̻̻ʪʪʪ߭ݭݭݪߪڪ̪̚əʙ˙eeeefefefefefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUVVeUVVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUUfUfUfUfUefefeYfeY&c%S&baefgffr!#2""#"""""""b""%6b2Rfe2"e"2"""""#2U""%%"UR%""S%"""5"%S%UU"R"%S2"%%R""b##"&f"""eR"&UV5eUV%%%Vb"262"R""&f"""""""&UUUUUUUUUUUUwvuUUUgUwwUUUUUUUUUUUUVUUUVUWUVUuUVUUUVUUUVUUVfUUVWeVfb&Vfc&ViiVifVffVfbfVfbfVfbfbbVffbVfbbVfiiYfbiffbiffbif""fifffff)ffifiəə̙ə̙˙ݪݭݭܪʙʙəʫffefefffefffefffefffefffefffefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVfUUVfUUVkUUVfUUVfUUVfUUVfUUffUUeUUUeUUUfUUUfUUUfUUUfeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfeYfeYfVeVfVeVfVeUfVeVfVeUVeUfiffifffffffffifffiffffffifififfffb##fffb"fff"&g2"'fS""f#ffw"b"fc5"%"e"%U%"RR%"RR"U"RR2"RR""R%""5""""""""2"""%!2#%"""Sb""Rf""R""""""""""""""""""""""""#""""U""%UeUUUeveU&#aU&f"U23"U"""Re"%2eU""UUvWUUWfUUVeUUVef5VebeVeb&""b&2"UfbfUfffUfbfUfgfUV`fUVffUVbf"%fffafiffffafffVff`vffffffiffffffffifffifffifffifififfiffffiffffbfffffifififfifffiffefffffffffffiiiܬݬݪ̪̪̪̪ڽڧyڹyͪߪͪǪ٪ީ̙̪̪ffffeffeffeffefefffffffffffeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURffUUffeUffeUffeeffe"ff""&b"""b2"VeUUVfUUUfUURfUU"eU"R#U"R%"%"5#UUUUUUUUUUUUUUUUUUUUUUUUU"UU%"UUUfUUfUUfUUVUUVUUUeYUUeYUUeYffffffiViifiififffiffiffffiff&fff3""R2""R"""%fb""b&""'f""fcR"%""%%"""%"""%"""U"""""!S"&"""%U"R""U""""2""""""""""R""&R"#"""#2"""R"""""%"2"%"""!2"""""""""""""eUR"&R""&""&""""""""""""&""""2Ub2b"b"b"&Uvf&Vef"f2f"""&"""6UU"""%bf%UffeUffeUffeUfffffffffffffffffffffffffffifffffffffffffffffffiffffffffffifffffffffffffffiffffffffffffffffiffffffffffffffffffffiffiffifffifffiffffifffiffffffffffffifffifffffffffifffffifffffffffffffffiiffifififf۪ʪʪ̪wʪwʪywwwzwwwywwwwwwwywzfiffiffffffffffffffffffffffffffffffffffffffffffffffffffffffeUUfeUUfeUUfeUUfeUUfUUUfUUUfUUUUUURUUUUUUURUUb"UR#"U""6U""&U""'""b%"&b"ff""ff"#wfg"fvR"fr5"ffU"UR%##"fU%"VU%%"U#R"U"""U""%U""USURUUUUUUUU"%UU""UU""UU"""UR"R%U"UUUUUUUUUUUUUUUUUUUU%UUU"UUU"UUUYYYfViUVifUViUUVffffffffffffifffffffifffffffff6Vf""#V2""&R""!r"&b""b&""b6""c"b"""""""""""""""U""U"%"%UR"""""""&""""%R"2b&"5UU""U"RUR&R"#2R"%"2""%U"""U"""%""""""""""R"""%"""""b"""#2""b""""2"""2""b"""eUURV""%"%UV"%UV"%UV"&UV"!V!1UR"%"2"%"R"ffffffffffffffff"&ff#&ff"fff&fffffffffffffffiffiffffffffffffbffffffffffffffffifffffffff2fffifffiiffffffffffffffffiffifffiffffffffffffffffffiffffffffffffiffffffffffffffffffffffffffffffffffffffffffiffiffffffifffffffffffffffffffififffiiffifffffffifffiffffffffffffffffffffffifffijfgwywwywwwwwygwfyywwwwwwwwwwywwzwwzwywwywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwzwwwwwzywwwwyyywwyzywwgzywywwywwwwwwwwwwwwwwwwffwfwfffwfffvfffffffiffffifffffifffffffffffiffffffffifffifffffffifffffffffffffffffffaff"ff""fff"ffffeUUUeUUUeUQU"U"2%U%#%UU"UURUUUUUU"WUUUVUUU"UURUUU"%""22"""U""fcb&""b6""e&""V6RU"f%RUUU#"""&"""&"b#R""UV""U"UU""""R"fvV""v""fb2"R"U""""Q"""U"""%""""R"V"UUR""%R""UUU"UUU"UUUUUUUUUUU"eUU""%U"#"UUUViUUUUUUYUUUUUUUUUUUUUUUUUUUUffffffffffffffiffVifVffffffffiffiffiffffffffff"b2c"&"c"&"c1bb&b&ff"""f"""f""""""""""""""""#"""""%#&f%#b&""fb"""R2""%R"""%"""RU""6!R"bU%"6"Sf"""""%R""R36"Q"QUR""""""&ff"gS"&e5U&ar"!&e""&e"%VfU%R"cUR"&"R"2"R%2"RU2%"%R%""RR2"e"2"%b"""f""ffffffff&fff""Qf22%"""%""""2"""%fffcffe"ffc"ff#f%"6b"RR""RR""5""""R"""R"""#'"%fff%ffffb"%b"")fY""ff"2ff"ffffffffffffffbfffbffff"ffb2&fr""f3!f"""f""&f"&bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffifffffefffffffafffbfffbfffbffffffffb&ff"&ff"&fi"&ff"&f"'b"fffffiffi6fffffffffffffifffsUiffififffffffffffbfwzgwwffwwffgyffffffgffffffffwyywzwwwywgwwwwwwwwyzwwvwwwwwwywwwwwzwwywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwywwywwwwwwwwwwwwwywzwwywwwwwwwwwwwwwwwwwwwwwzwwwwwwwwwwwwwwwwwwwwwwwwwwwzywwzwwwwwviwwffyvffffffffffffffffffffffffffffffffffffffffiffffffffffffffffffffffffffiffiffffffffvfffifjVffffffffffffffffffffffffffffffffffb"fa""f#""f"""b"""c"""UUUR%UU"2eQ""UR""UR"%UR"UU""UR"""#e6"#6e%#R&%"2"%RR"""%"""%%"""U"2""c""Ub""U2""UUR2fR6"6Rb"RR3"%""""R"#"S""&fffb%"&bfff""R&""R&"""U""2UUb""U&"""6""2&"""&2""b""""""UR""UR"%V"#&e"""f""&"""&"""&%UUUUUUUUuUUUWUUUVUUU'UR"VUR"uW""VfffVfiUfiUffUfeUR&fU"""""""fiffffifffffffffffff6f3"b""f&""&f2#&"2%"""2"""c""&R"""2"2""U""""R""26ff&a"""fff%"""%"""""&f2&b"&bbRf&%"fb""""#"""#""""f"#ff%R%"&35S 3"MFV586Uc#fc#3""feR"S""""""""#"#UVg"5f5RSSR%"UUS"vUS%f2%&%R"%R2""""""""RU""U%"""&""""2"#U2"%SU6%U&"%6U""""""""""%S""R%""URUR"rR%#U%RR""%3"%R"6b""&fa5"ffb"&ff"&ff""""UU"""R"Sfff"R"""R"b""2"2!b"2fb5""&"UU6c#bf2agf&&gf6"'f6"bf&"bf6&U6&c2&"&ff""ff""ff2fa"&ff&fffeRf2R%fffffffffffffff6ffe"ffR"!b""""2"fffbfffbfffbfff"ff""r"""""""2""&b""&b""fb"1vfffff"""V""&c"""b&ff&9f""fr"#""""""R"""%""""ffb%ff5Rffb"fffffff&fffff5SfU5R2f6#&b&"fffb"vbb2eb""eR"%b#2%bffffffffffiUff""R!#UR""R"""2"""iwwwwgwfg"ff"vff%gfg&ffwywwywwwwwywwwwwgwfwwwwwwwffgfwwwwwwwwwwwwwwwwzwwwwwwwwgwwwwwwwwwzwwzwwwwwwwwwwwwywwwwwwwwwwwwwwwwwwwwwwwwwwwwfwvffwwwwwzfwwvfwvffwffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffiffffffffffffffffffffffbfcc#fffifffffffffffr"fb""f"""&""%fffffffffff&fff1fff1!fbS&f"&fb"b"2"fb""ff""r"2"#32"""'%"%R""R##U"""R"""R"""""""%"""R"""SUU"""%R"""UR""2U"&e4%RE"U%"%"U"""""3R"#"R%U%"R##"UfR""b"%U&"%"R""SV"R&"R2&&%R&cb""%&"#Rf""5&b"ReU"Rb"""U""""R""cR"f%R"b6fb&&2c"ef""""&%""&&""'bc2#"&""ff"&"""&f"3""e"c"#2"&#"""f b"&6"evb"&Vr"uf""fff"c"2c&fgf""""a""""fb""b&2"""vf"""f"#"f32"&fg&"&f&"""#""#%"""R"""UU""""R""U2""""""""""""""R""""""""""""""""%U""R&"%%R"%R"""#&&""b&""b5"&"V"&"&"&"b"&b""f"%R""RR""#"""R"""""""""""""U""%""#"%"")6"#"R&V"c%!Rc"c2b""#&"""6"2""e"""&"""6#2"2b%R"bRR"e"R"e"R"""""UR%"Q%""Vf"v#3"b""""""""""R"UU"""""""""#""""U""%"R"%"R"%"5Ube"#"%U2"""""""""""""#2"""f""&6#fv"Uc62"6fR%Qb2%U"R!Re"ffc2"R6c""%U"""""""f!"3'ef2rf#"%UR"2"fS%U"""b""fb""35USR#"R#"cUU"#"#"2""b""%""R"""U""""R"""%""&b"U3""#RR"U"2"c#%13&&"R#f"S%""&%""""&"""""""23"2#""""bfgf&b##26ff3""""%R"e2R"b""UQ2""5""b"R"f""S""UU"""""""""""""%U""%"R5S5RR""2UU3""#%#"%"R"%"2"%"5"%"#""R#""R#%"""%""6%"&bc"b&%"gvU"&f""&f"#%"&fffvfffffffb'ff""fg""&g2""fSf"&wwwvfffgfffvffffwff#fvg"wvcRfffUfgwwwfff'fffbff26gv2&gg2!gf2"gfwwwvfwvffffffff&ff"fb""vf""vf""ffffffffffffffeffffb&ff"!fb"#fb"ffffffffb""f"#!a""b"!f""&b""fr"ffffffff""&f"!vf"&ff#&ff"fff&ffffffffffffffbffb"ff##fb""fb2"f"2"f%S"UR"f"""&"""&"""&%U""R%""5R"%&'"ffffffff2ff5RffrR""UR"""55"""fbr"fSb3ff%&ff5fff2b"ff""ff5Rf2R%U"%"e"%"c"R"f"R"f%"1fR"&b"#"UUR""""""""""""""%U"#Q&""UR"b"""""""""U"""RU""%""""U""""""""%R"""%262fff"&##R"ffR"2"""""""""""""bS"Rc#"UVb%Rf2&S32#b"""""'b"""b"f""&Sffg"&R"USff"%U""R&"%%Pf%R##""""c"""&b"%f"&1"22c""""""""""""f12"U&b"#bb"&"b"&"b"b"b"b"b"b&""&f"23"#&2#"b""2c""&#""&"""&#""&f#""#b2"#&""#VR""V%""65""b"""b2""U""""U""UR"R"""%"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2%"2R%"%"%"%#%"%"R"%"R""U""2""""""""""""""""""""&f""&"b""f6""2fbb"R&b"R"R%&"R%b"%Rf"#2"""(""2""""""f"""&"""c2""""""""""""""""2#"#"#" #"(3" BS""""""""UR"%""b""#eR"e"U"a5U"&!%"%UU"%"RUURfffR""#"""#"""1%""2R""S%""U5""%RV"""Sb""R"""U"""U"""2"UR""R%""%S"%"5"%"R"%"R"#""%R"""""""""""""f"""#2#""""&"""6""#R"""f""&bURc#fU"f6"""b""f"""#"""R2"#%R&b""bc2""""UR"%"RU%fe""c&5"&f""""#"UUU""#%U"R%%"a%R%"%"#"#"%"R"%"RR%U"%UUU""#""""&"""&UR"&R%"&%U"&""#""5SRf2#""eRR2b%R"&""#6""b&""b&""""%U"""""""""""&"""V""56%"#6R"""&&""b&""b6"""&""S6R""e""Sb""f"&"&ff%"ff"#&f"&Uc"%"V""e#S""U"""""2"f2"c2"VsR"6rR"r&""""""""""%Uff#"&""6&"b&&"vfb#%g""&f""ffUUf&f#f&"c&""b"""&""&""v&""v&""f&""fb""f""6"""&"#2f"b&f"fff"&f""2&&b2&fb"&f"2&f"""f"""f"""f"""f"""f#&cf"c&f"b&fUfSf"aVUV2""&"##2b"""#"""#""R#c%"%c""%b%U5b"RUb"%URR""UR""#R"""R2""%""3#"U23"%S3"RbR%&#%U""R%2fb"&"f#Sf6"&"cR6fU""2""b"ff"&e""!6f""U"""2#"""3%"fb"2""f""b2b#Uff2""%UU""""""""""""#%2f%"R&URRVU%!U"%#"R6"Q"%X"%UUc"S3b"%U"2""3"""%R""%%R""R%"U"2""Sf"UV"b"&"e2a2b"c2b"b&#"b&2"""""""""""""""""""&"""&"""&"""&#"""&b""b&2"b&"""&"""6"""b""bc""c&3"&b""#""f"""b""#6""""""""""""""&f"2Vcb"%#&""Uf"""""""""&"""""""""UR"""%R"SS"%"fb"&"b"cf""f#"""""""""""""""#"""" """""" 0 ""1!"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""#&"!6b"b2f&"""""##""""""""""""fff"""b"ff""""2"32""""""""""""""R%""%RR""#U2""Q%""%U"""%"""R""""R%%S%UU2""""""UU"U"""#5U"""R"""U"""""R"""%""UR""UR""RR""U""""2""""""""""""""UUUR%""%"eUU"""""""""""%"""R"""5""""R""""%""""R""""""R""U""""2"""""""""""""""""""""""&"b"&b"aab"b"b"b&""c+2"&b""""#U""%%UUR"""""""""""""""""""""""""RR"%"R"%"R"R"2"R2R"R&""2%""%R"""""""""""""""#"#""fb"#b""&b""#&6&""#f"""#""""#&""#""b"""b"""""""""""fb""2b#f# M"""8""#"""2""""""""""""2"""2""""""""""""""b"""""""#""#"""""""""""""""""""""%R"2"UU"""""""""""""""""""""""""Rb"U#"""2""""fb""b6""&b"""6"""""f""""#""#"&"2"&""""b"""c""""2""""2&fb"""b"2f""""""""""#"""3fffbf"""#2""""""""""""""""""""""""""#""&"2%S&"R#'VUR&ab""f&""#f"""2"b""%""&f"#b&""fb"%R#"#%""%"R"%&f%R"%UR"""""""""""""""#""""""ff""""""""#""""&""3b""&2""6"""b"""b"22b&""&fb"""b"""b"""b"""b"""b""""""""""%"""%""""""""""""""""""""UR#"R!35#2"""U"""R"""R""!b"""R"%S""""""&f""&"bR"fb%"""%""""R"""bb"#f2"##"""# 2""'&"#"v""gg""&b"""&"""&fb#2b&""ff""f"""r2""""""&"""b2""#"""""3#""fb#& R#`d"eC"fff"&""""ff"#""""#3""""""""""""b"2b&b"ff"&f"""b22"2""""""""""""""""""""""""""""""""""""""""""""""'"1 "0!  #30 0!"""""#""2#"""# 1"""""""" """2"23"""1!""""""""""""""2"""2"3"!"21""""#"""""""#""""!""" """"""""""""""" """3"""!""" """"""""""""""""""""""""""""""""""""UUUR##2%"UUS""""""""""""""""""""""""2""""%""""R""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2""#""""""""""""""""2#2"# 0""200#!23#(2V&2h "!"""""""""""fffb""&"ffb"""""322"#"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2"""0"""!""#""""""""""""""""""""""""# 2" "2 """"""""""""""""""""2"""""""""""""f"&"&"b#"""""""""""""""""""""32&"ffb"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""#""""&""""""#""1""2"""2""6b%b#ff"#R%""SC""4"#"""""#22b""f"""""2"""""2""" 2""# 2" """""b&""b&""6c"""""""#""""""""""""""""""""""""""""""""""#""""""# """"""""""""""""""""""""""""""""""""V"""%""#%""""""""""""""""""""fff3bb"f&ffbS""""#2#""""""""""""""ff"#&#"b"f"&2"""##""""""""""""fc"""&c"ff2&""2"32#""""""""""""""""""#"!32b"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2""""""""""""3 b!12b&#1!'&"&""2#"!0a"b0032""2#"  ! 312""#!""#1"" "#01"#!"" 33 "#"2b2""0"#b2"#b"""#3!#b09`"3b###"2 `p1"b2#c#"bb3b3ib'"3""b"""#'""b"2#b&'""&"2r2`6&""""""""""""""!"""'"""!"""&"b"&"""b""#"""b"""b""""&#b""#b"&!a"#""""b"""""7r"r"f&#&2a&f6af6""""""""""&""r#%"#2bg&2b"&""f""""""""" """""""&"""2"""&"""%"b"2# """020b"1"b##"b"13b"1b"0""#3"""" "0"""" 2"1`" 3# #!" ""!"!1!""!"#"#""#32"""""""" ""10""22"# 2"""!2""""""""""""""""!3""!"#2"""""#&!"#""""'"#2'a#!2"&bb&1b"&1"""b&0 r2& a"&# "!b&!a#2"""'# 2!!0"&"""&"""""#'""! 22"7""#2"r"!6"!b"2"p&#" 2"""""""" """2"r"""""0b#"f!"""" 2""02"" "20#f " """"""""""""##"""""" ""2"""!" 3"# " 30 0! " #"0# 0 0# " 2  2 """2"" """#30 1""""""""""""""#!""" "023"r""!"# c"""b""""#""""""""2""""2""2"""b""""""""""""""""""""""""""""""""""""2""#""""b""2"""b"&"b"!2""&!b#""""2""&"""12#2&c"6 23c&#b""""""""""""""""#"""2"# 0&#""'#""""""""""""""""""""""!"2&#""!"&""""""##""#"""#"""""#"&"""2""b&2""""#""2""""""""""#""""""""b""2# 2"33""""""""""""b""""2""#b&"6"02 p&"&b0%p!&610""r"&2# "f!""f" 1b&b2!c00fb210"fcfi` 26i!6i!6c"""b""2"2"p"r#2#"2"b""!b2"219&  03"&2""&3""&36!"&02223""&""#&"3`92"2)""""""2)"" )"21 ""1"2a 3 i)" )" "3:#9  ") "#""a&"#&#"!"!"R!'"b!&"# b3R`0""6""""6"""&#""62""2#3"!""22!6b3b6b&&&b!&&"262 3'""23"bf"c&&"`f&" f"g!000101!"6"b"%"b"&""c3Q1p9b""b""#b"""p# 2##""""b"b1""#"""r"""`"""r#2"2"##""1# 9s# ""#"") q"&1#2"" "!2"#!"2""2"" #13 "0"""""""""""0022"&""3!"aaaqcbbr"bc2"c!!b`a6 111 #1#3112"""#2"""!##b&""b""b""""""#333" ""f 2f#""a""&2"1f""0f 2"b"""f&'"f02f&6"`2&"!&" """3'"#0a"&"&#!0 1q00'##b'""b"b"&"3&"""""3f""#&"&#"""2""2""""2"b"00b """"##2&b b"#&r""&b22""6bb"""`b20p"bcb"ccb2"#b"acb"b`b"""a" '"b!32b&""#&&c"2"b&&6"&"c2b2c#&"#"f1!3v1"b'bbf"%"""&"b"2"b"!1c!!!a "#a%"""&&""2&""33""%&#"&&"&2 &&2"&&2#&#)&12"""#ab`c1b#b#"cc"b"b"""1 `a31g"""b2""f2"b&"b"""pr"c3s3b"b"b#"#""c"0a&0&"3"&2&##2""0!#2#! "12#  )01a1!01"3 " 1!0""2b3"2 "2s3#p" &222b""32&""""b"&#1&3b'22` 6661a602"""b# ##3b""3b""0"2""b"!"``"!""#""#"!2"&'#2"2"2&0""!"""2""" #"" "#3#2310"""0"0#2"#3!  0"3!2!0"!""2&#&" "&!62&b `2&c'&bf"&##"#"2!2'#301!6& "6#""!"&&!"""!"""3 #" "2"3"!"2!""#!")"#"")192*#3"" )09#93 "#1""#"""0"#0c#2"" !`21b1!&2b"&2""&2b"& `b&s#&bb `ab&cc"""#2"&#""&"&'2""60&&1f&2!"2f%&2"&"""2'r"6&2"&`"ff32"bf""""!!"3 "b#3 2 2b2!c2 ""3" !"2#""0 "2"3"""p1100 3#"2#3#!"02!&""32 p"b!#b!2!&31"""!"90! """"#""""000a&&`&0"&6110 ""!0#&b6" `&"&2&q"1b"""b""""2"!b&"cb&ab "#3`#"!b"""b2"#"!"#2b"fv!a"'#&##6##""`  q`b300"#1 "#!"""#!&"###""3#""``b"# `""#b""#"""c3#2`!2b2 1!1c6&&#&2"p6 #c&p"a0 #b""cbf#S#fab'a``afWbaa&!"!b2""#"""b#2"b32c"6""" 1""2""""""""""2"b""#2""b6&"R  +"2" 1")")#"2""""b3b""""""""" 0#3#2&2"!3"7""""2bb&"2r"#b302`0b#b"#7""b&2"c!2"6#3a&a& 0a2"03302" 22"""0# !#" 0""0" "22 ""#3#3'"3" ""#!"!"#!)"##2# !9""2"`"3#202!02""#2f#2 f ""3"&1b""&c#&"&36"&66!!a`2"b!""b"#3"" p2 #a!0`26&#&1""3"3""&#"#3"" )")"23#2`"1"" vb1ca"2a3g```p2g`f"f""b"""br ab"#r""#""c""``r""&6!32"!qb"3" ab2a``b"2&c2&2"""" #" ##""2a3322 "! 02# 3 !"`p"a"`!g3"1 61612`&3!b2`6a ""2"b&s2ab&&1 "&"&"&b#b &2b"&"2&"&#2 2"3#!"""#2""32"#0"22"2 """""3&#1"&2&2&2#!`"b2"2b6#""&"""&#2#2"#" 6b2 &22b2 b  6P``!")# 2#"2!!3! !""!"#!""1""0321"!"""2"2" "#" """13!""""""""""#)"")"!3#33"92#!"20"#3r 2 222"!2"""2""""6 3" # &0""#1"""`1"b7#"b023b6#1b6#3b2"0""""#"""##3""""2#'&"3#2 ""2""&""""""#7"2"'" 0"0"c6"#c&"##6""""""#""332"#b&&&""2""&&6#6&6"671 """&&"""b"&## 6 c" "b#6#"&3b"&#b#b&23"!b& `&2b"& 1"&"2"""# 3""b c"2b2b""c2b"2b"b"b"b2""3&2""2&"&`a#aa#ab3!"2""2"!""03332 2!62!63#!122  3 ##02!!!#!2" "R"""b"&"#2&#c" #b'!b# 1"'!2v" &"3!"c2&"b&"c" #" 2bi"" `cb bcb"""#2b"b"b02"&2b#3"&b2r'"bc"#&b#c"`6a#00"3#&"2""2&2f&2&#"2b"&2f#&"`&2`b!2ab&3b&3`aQbf2cc&&202""#310003p0b&""#&"""&""#"b 6"r``f92 9202#12&&"""&6""&"1ap0`gr!v`!s&#"b2c""6b"b&a`aaaaPb3bb"b&c"c2"""&bc!`cqbc"cbb"b"2bb"3b""a"b2&b&"&b2"0"#2 ""0""0""0""!" 1#)#""2!"221)!29 2#"!2!b#2"b""3"""b"#b`""#! #" "#"#&&2"6!"&2##2#212'"62""#"###22#"3" "&""&"""""""""##"32 3 )2"!3)6"""2"26"p"& 2s&2b36""3"c'b" "#s&a`Q`csbbc)r&bbc&122"6"&"!12"6#)#6"�!"222&"""p""&"b"""`&"""""#""""### "3"2&# """2&"""1"" 0""3"020##"""""&"b""2"""""""2#!#2""0)b&6"""")b&&"""""2""2"""""#3"!)""""" 2!"0q##30 1"# 26 "!"1b&!bb&3 #"! 0""2""""""##32""7&# '#2'&"20""#22""2"!0 2"3#3####"#000""# "#""2"#32"00"""""#02 +  9"))""22)!01!3321"#2 " 2"""!a"1!0#3333""""3"" 2"`0bb`1a 3""")3")## !!3!  !2"102"#1! "  #3"""""""2" ""00!"# " 3"0 " 00"#"1" #"""#c6#a#`"#213"0"0"1!b"r"b##2"2#"##203"#2b"R""b"2"##""#""#3"""""#""&"&#f"""a0 r"22"""""""""""""cb""cf&##&6#f"0b&""b&#""&#""""b""#6""b&"b!""c6"""&"""&""""""&2c"#cf"e"""""""""""%""&&""&2"" """""""#"#3""# ""32b"b2" a1&20#& """""# 3 "2"& "6"0"2""""" 33301"#!""2"2""3"#22""!""2" """ """ ""2232""2"!'!# #2"" 1"""2"""#""2!"""2" " "# 2303!""#!" 3!#""" "#2"""" 2" 2#2#2" "# 239""962"26"&")"#)#"2"""""3"""""""6"""&"" &"##"""""""""""""!)"#" # )11) 0)22"""""3"""""b3""b)""")"""#"""9""")""")"""3"ib&#i""##2"")")3#")"""""""""")#)"""9")"#92)"#" 92)" 2#92"%#b"&#b"2#b"""""""""""""""""""""""&&###1"""&6#"&""""&""3&" 1#6"Rb"02#"0`"&3c2'!b"2#" )b&&"!26)b&)b6&)`66"""&"""6""""#))"")#2)3"")91" #)3" 3 9" ") " 1"""190"")"2"22"" "# ""2""! 0!2 2"#"""#""32""2"" """""02""2"1#2"32!"2#3!"#2!!#"#02 0 !1"""2""2"32""""2#0""2"23##""3"2"2"""" #)3)"9#"#""" 2""2""""""""""""#"#""" !11" !##2 !#2" 2" 2322 2  2#22 # "*!3"2"22" "" ""#"" "2""2"""""3!!"""""""" \ No newline at end of file diff --git a/res/forest.xcf b/res/forest.xcf new file mode 100644 index 0000000..56bc660 Binary files /dev/null and b/res/forest.xcf differ diff --git a/res/haohmaru.data b/res/haohmaru.data new file mode 100644 index 0000000..98478ae Binary files /dev/null and b/res/haohmaru.data differ diff --git a/res/haohmaru.data.pal b/res/haohmaru.data.pal new file mode 100644 index 0000000..297630e Binary files /dev/null and b/res/haohmaru.data.pal differ diff --git a/res/haohmaru.xcf b/res/haohmaru.xcf new file mode 100644 index 0000000..19a2b55 Binary files /dev/null and b/res/haohmaru.xcf differ diff --git a/scsp/fm.cpp b/scsp/fm.cpp index eb45e55..cb4dbec 100644 --- a/scsp/fm.cpp +++ b/scsp/fm.cpp @@ -740,7 +740,7 @@ void main() */ vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 - vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0 // zeroize character/cell data from 0 up to plane_a_offset fill(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a)); diff --git a/scsp/sound_cpu__midi.cpp b/scsp/sound_cpu__midi.cpp index f88de86..4e486c4 100644 --- a/scsp/sound_cpu__midi.cpp +++ b/scsp/sound_cpu__midi.cpp @@ -240,7 +240,7 @@ void v_blank_in_int() scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN); // flip planes; - vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a + plane_ix); + vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a + plane_ix); //plane_ix = !plane_ix; // wait at least 300us, as specified in the SMPC manual. @@ -355,8 +355,8 @@ void main() 2-word: value of bit 5-0 * 0x4000 */ vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 - vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 - vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0 // zeroize character/cell data from 0 up to plane_a_offset fill(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a)); diff --git a/tools/tile.py b/tools/tile.py new file mode 100644 index 0000000..60cfe3c --- /dev/null +++ b/tools/tile.py @@ -0,0 +1,68 @@ +import sys +import struct + +with open(sys.argv[1], 'rb') as f: + buf = f.read() + +stride = 320 + +def get_tile(buf, tx, ty): + tile = [] + for y in range(8): + row = [] + for x in range(8): + yy = ty * 8 + y + xx = tx * 8 + x + ix = yy * stride + xx + px = buf[ix] + row.append(px) + tile.append(tuple(row)) + return tuple(tile) + +def tile_input(buf): + tiles = [] + pattern = [] + + for ty in range(240 // 8): + for tx in range(320 // 8): + tile = get_tile(buf, tx, ty) + #if tile in tiles: + # pass + #else: + # tiles.append(tile) + #tile_ix = tiles.index(tile) + tiles.append(tile) + tile_ix = len(tiles) - 1 + pattern.append(tile_ix) + + return tiles, pattern + + +def emit_tile(tile): + for row in tile: + for ix in range(len(row) // 2): + a = row[ix * 2 + 0] + b = row[ix * 2 + 1] + c = ((a & 0xf) << 4) | ((b & 0xf) << 0) + yield c + +def emit_tiles(tiles): + for tile in tiles: + yield from emit_tile(tile) + +def emit_tile_data(tiles): + b = bytes(emit_tiles(tiles)) + with open(sys.argv[2], 'wb') as f: + f.write(b) + +def emit_pattern_data(pattern): + with open(sys.argv[3], 'wb') as f: + for ix in pattern: + assert ix < 1200, ix + b = struct.pack('>H', ix) + f.write(b) + +assert len(sys.argv) == 4, len(sys.argv) +tiles, pattern = tile_input(buf) +emit_tile_data(tiles) +emit_pattern_data(pattern) diff --git a/vdp1/normal_sprite_color_bank.cpp b/vdp1/normal_sprite_color_bank.cpp index 0daf77e..d4b9fc1 100644 --- a/vdp1/normal_sprite_color_bank.cpp +++ b/vdp1/normal_sprite_color_bank.cpp @@ -57,7 +57,7 @@ uint32_t character_pattern_table(const uint32_t top) // `table_size` is in bytes; divide by two to get uint16_t indicies. uint32_t buf_ix = 0; for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) { - uint32_t tmp = buf[buf_ix]; + uint16_t tmp = buf[buf_ix]; table[table_ix] = (((tmp >> 8) & 0xff) << 8) | (((tmp >> 0) & 0xff) << 0); @@ -72,7 +72,7 @@ void main() { uint32_t color_address, character_address; uint32_t top = (sizeof (union vdp1_vram)); - uint32_t color_bank = 5; // completely random and arbitrary value + uint32_t color_bank = 0; // completely random and arbitrary value color_palette(color_bank); // For color bank color, COLR is concatenated bitwise with pixel data. See // Figure 6.17 in the VDP1 manual. diff --git a/vdp2/color_calculation_ratio.cpp b/vdp2/color_calculation_ratio.cpp new file mode 100644 index 0000000..1c8ed14 --- /dev/null +++ b/vdp2/color_calculation_ratio.cpp @@ -0,0 +1,328 @@ +#include +#include "vdp2.h" +#include "vdp1.h" + +#include "../common/vdp2_func.hpp" +#include "../common/copy.hpp" + +extern void * _mai_data_pal_start __asm("_binary_res_mai_data_pal_start"); +extern void * _mai_data_pal_size __asm("_binary_res_mai_data_pal_size"); + +extern void * _mai00_data_start __asm("_binary_res_mai00_data_start"); +extern void * _mai00_data_size __asm("_binary_res_mai00_data_size"); + +extern void * _haohmaru_data_pal_start __asm("_binary_res_haohmaru_data_pal_start"); +extern void * _haohmaru_data_pal_size __asm("_binary_res_haohmaru_data_pal_size"); + +extern void * _haohmaru_data_start __asm("_binary_res_haohmaru_data_start"); +extern void * _haohmaru_data_size __asm("_binary_res_haohmaru_data_size"); + +extern void * _forest_pattern_start __asm("_binary_res_forest_pattern_start"); +extern void * _forest_pattern_size __asm("_binary_res_forest_pattern_size"); + +extern void * _forest_tile_start __asm("_binary_res_forest_tile_start"); +extern void * _forest_tile_size __asm("_binary_res_forest_tile_size"); + +extern void * _forest_data_pal_start __asm("_binary_res_forest_data_pal_start"); +extern void * _forest_data_pal_size __asm("_binary_res_forest_data_pal_size"); + +inline constexpr uint16_t rgb15(const uint8_t * rgb24) +{ + return ((rgb24[2] >> 3) << 10) // blue + | ((rgb24[1] >> 3) << 5) // green + | ((rgb24[0] >> 3) << 0); // red +} + +void vdp2_color_palette(const uint32_t color_index_offset, + const uint8_t * buf, + const uint32_t buf_size) +{ + uint16_t * table = &vdp2.cram.u16[color_index_offset]; + + uint32_t buf_ix = 0; + for (uint32_t i = 0; i < (buf_size / 3); i++) { + table[i] = rgb15(&buf[buf_ix]); + buf_ix += 3; + } +} + +void vdp2_color_palette() +{ + { /* mai palette */ + const uint32_t buf_size = reinterpret_cast(&_mai_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_mai_data_pal_start); + + vdp2_color_palette(0, buf, buf_size); + } + + { /* forest palette */ + const uint32_t buf_size = reinterpret_cast(&_forest_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_forest_data_pal_start); + + vdp2_color_palette(16, buf, buf_size); + } + + { /* haohmaru palette */ + const uint32_t buf_size = reinterpret_cast(&_haohmaru_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_haohmaru_data_pal_start); + + vdp2_color_palette(32, buf, buf_size); + } +} + +uint32_t character_pattern_table(const uint32_t top, const uint32_t * buf, const uint32_t buf_size) +{ + // Unlike vdp2 cell format, vdp1 sprites appear to be much more dimensionally + // flexible. The data is interpreted as a row-major packed array, where the + // row/horizontal stride is equal to the sprite width (as configured in the + // draw command). This is identical to how the input palette index data is + // structured, so there is no transformation to do here, only a plain memory + // copy. + + // Divide `buf_size` by two because this converts (indexed color) 8 bit pixels + // to 4 bit pixels. Round up to the nearest 0x20 (for an 8000 pixel/8000 byte + // image, this rounding is a no-op). + const uint32_t table_size = ((buf_size / 2) + 0x20 - 1) & (-0x20); + const uint32_t table_address = top - table_size; + uint16_t * table = &vdp1.vram.u16[(table_address / 2)]; + + // `table_size` is in bytes; divide by two to get uint16_t indicies. + uint32_t buf_ix = 0; + for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) { + uint32_t tmp = buf[buf_ix]; + + table[table_ix] = (((tmp >> 24) & 0xf) << 12) + | (((tmp >> 16) & 0xf) << 8 ) + | (((tmp >> 8 ) & 0xf) << 4 ) + | (((tmp >> 0 ) & 0xf) << 0 ); + + buf_ix += 1; + } + + return table_address; +} + +uint32_t forest_cell_data(uint32_t top) +{ + const uint32_t buf_size = reinterpret_cast(&_forest_tile_size); + const uint32_t * buf = reinterpret_cast(&_forest_tile_start); + + // round to nearest multiple of 32 + const uint32_t table_size = ((buf_size) + 0x20 - 1) & (-0x20); + const uint32_t base_address = top - table_size; // in bytes + + copy(&vdp2.vram.u32[base_address / 4], buf, buf_size); + + return base_address; +} + +void forest_init() +{ + /* enable display of NBG0 */ + vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON; + + /* set character format for NBG0 to palettized 16 color + set enable "cell format" for NBG0 + set character size for NBG0 to 1x1 cell */ + vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR + | CHCTLA__N0BMEN__CELL_FORMAT + | CHCTLA__N0CHSZ__1x1_CELL; + + /* plane size */ + vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1; + + /* map plane offset + 1-word: value of bit 6-0 * 0x2000 + 2-word: value of bit 5-0 * 0x4000 + */ + constexpr int plane_a = 0; + constexpr int plane_a_offset = plane_a * 0x4000; + + vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 + vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0 + + uint32_t top = (sizeof (union vdp2_vram)); + + uint32_t cell_top = top = forest_cell_data(0x080000); + uint32_t pattern_name = cell_top / 32; + + /* use 2-word (32-bit) pattern names */ + vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD; + + const uint32_t buf_size = reinterpret_cast(&_forest_pattern_size); + const uint16_t * buf = reinterpret_cast(&_forest_pattern_start); + + uint32_t * pattern = &vdp2.vram.u32[(plane_a_offset / 4)]; + uint32_t x = 0; + uint32_t y = 0; + for (uint32_t i = 0; i < (buf_size / 2); i++) { + pattern[y * 64 + x] = 1 << 16 | (buf[i] + (cell_top / 32)); + x++; + if (x >= 40) { + x = 0; + y++; + } + } +} + +void main() +{ + // Sega Saturn has 4 Mbit VRAM + vdp2.reg.VRSIZE = 0; + // Disable VRAM bank partitioning during CPU access + vdp2.reg.RAMCTL = 0; + + // Enable CPU access to VDP2 VRAM at all cycles + vdp2.reg.CYCA0 = 0xeeee'eeee; + vdp2.reg.CYCA1 = 0xeeee'eeee; // A1 is irrelevant because bank partitioning is not enabled yet + vdp2.reg.CYCB0 = 0xeeee'eeee; + vdp2.reg.CYCB1 = 0xeeee'eeee; // B1 is irrelevant because bank partitioning is not enabled yet + + // initialize VDP2 VRAM + vdp2_color_palette(); + forest_init(); + + // NBG0 Pattern Name Data read at T0 from bank A0 (0x000000 - 0x01ffff) + // NBG0 Character Pattern Data read at T0 from bank B1 (0x060000 - 0x07ffff) + // all other VDP2 VRAM accesses disabled + // + // This is because: + // - N0MPA / N0MPB / N0MPC / N0MPD are at addresses 0x000000 through 0x002000 (bank A0) + // - forest_cell_data ("Character Pattern Data" for NBG0) is at addresses 0x076a00 through 0x07ffff (bank B1) + vdp2.reg.CYCA0 = 0x0fff'ffff; + vdp2.reg.CYCA1 = 0xffff'ffff; + vdp2.reg.CYCB0 = 0xffff'ffff; + vdp2.reg.CYCB1 = 0x4fff'ffff; + + // Enable VRAM bank partitioning + vdp2.reg.RAMCTL = RAMCTL__VRAMD | RAMCTL__VRBMD; + + uint32_t mai_character_address; + uint32_t haohmaru_character_address; + uint32_t top = (sizeof (union vdp1_vram)); + + { /* mai */ + const uint32_t buf_size = reinterpret_cast(&_mai00_data_size); + const uint32_t * buf = reinterpret_cast(&_mai00_data_start); + top = mai_character_address = character_pattern_table(top, buf, buf_size); + } + + { /* haohmaru */ + const uint32_t buf_size = reinterpret_cast(&_haohmaru_data_size); + const uint32_t * buf = reinterpret_cast(&_haohmaru_data_start); + top = haohmaru_character_address = character_pattern_table(top, buf, buf_size); + } + + // DISP: Please make sure to change this bit from 0 to 1 during V blank. + vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE + | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); + + // SPCTL__SPCCCS__EQUAL: only perform color calculation on Sprite (pixels) + // that have a priority number exactly equal ot SPCCN + // + // Sprite Data is Type 0 + vdp2.reg.SPCTL = SPCTL__SPCCCS__EQUAL + | SPCTL__SPCCN(1) + | SPCTL__SPTYPE(0); + + // Enable Sprite Color Calculation + vdp2.reg.CCCTL = CCCTL__SPCCEN; + + // VDP2 User's Manual: + // "When sprite data is in an RGB format, sprite register 0 is selected" + // "When the value of a priority number is 0h, it is read as transparent" + // + // From a VDP2 perspective: in VDP1 16-color lookup table mode, VDP1 is still + // sending RGB data to VDP2. This sprite color data as configured in + // `color_lookup_table` from a VDP2 priority perspective uses sprite register 0. + // + // The power-on value of PRISA is zero. Set the priority for sprite register 0 + // to some number greater than zero, so that the color data is not interpreted + // as "transparent". + vdp2.reg.PRISA = PRISA__S0PRIN(2) // Sprite register 0 PRIority Number + | PRISA__S1PRIN(1); + vdp2.reg.PRINA = PRINA__N0PRIN(1); + + /* TVM settings must be performed from the second H-blank IN interrupt after the + V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank + OUT interrupt. */ + // "normal" display resolution, 16 bits per pixel, 512x256 framebuffer + vdp1.reg.TVMR = TVMR__TVM__NORMAL; + + // swap framebuffers every 1 cycle; non-interlace + vdp1.reg.FBCR = 0; + + // during a framebuffer erase cycle, write the color "transparent" to each pixel + constexpr uint16_t black = 0x0000; + vdp1.reg.EWDR = black; + + // the EWLR/EWRR macros use somewhat nontrivial math for the X coordinates + // erase upper-left coordinate + vdp1.reg.EWLR = EWLR__16BPP_X1(0) | EWLR__Y1(0); + + // erase lower-right coordinate + vdp1.reg.EWRR = EWRR__16BPP_X3(319) | EWRR__Y3(239); + + vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES; + vdp1.vram.cmd[0].LINK = 0; + vdp1.vram.cmd[0].XC = 319; + vdp1.vram.cmd[0].YC = 239; + + vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE; + vdp1.vram.cmd[1].LINK = 0; + vdp1.vram.cmd[1].XA = 0; + vdp1.vram.cmd[1].YA = 0; + + vdp1.vram.cmd[2].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; + vdp1.vram.cmd[2].LINK = 0; + // The "end code" is 0xf, which is being used in the mai sprite palette. If + // both transparency and end codes are enabled, it seems there are only 14 + // usable colors in the 4-bit color mode. + vdp1.vram.cmd[2].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; + // It appears Kronos does not correctly calculate the color address in the + // VDP1 debugger. Kronos will report FFFC when the actual color table address + // in this example is 7FFE0. + vdp1.vram.cmd[2].COLR = COLR__COLOR_BANK__TYPE0__PR(0) + | 0; + vdp1.vram.cmd[2].SRCA = mai_character_address >> 3; + vdp1.vram.cmd[2].SIZE = SIZE__X(72) | SIZE__Y(100); + vdp1.vram.cmd[2].XA = 100; + vdp1.vram.cmd[2].YA = 100; + + vdp1.vram.cmd[3].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; + vdp1.vram.cmd[3].LINK = 0; + // The "end code" is 0xf, which is being used in the mai sprite palette. If + // both transparency and end codes are enabled, it seems there are only 14 + // usable colors in the 4-bit color mode. + vdp1.vram.cmd[3].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; + // It appears Kronos does not correctly calculate the color address in the + // VDP1 debugger. Kronos will report FFFC when the actual color table address + // in this example is 7FFE0. + vdp1.vram.cmd[3].COLR = COLR__COLOR_BANK__TYPE0__PR(1) + | 32; + vdp1.vram.cmd[3].SRCA = haohmaru_character_address >> 3; + vdp1.vram.cmd[3].SIZE = SIZE__X(104) | SIZE__Y(132); + vdp1.vram.cmd[3].XA = 120; + vdp1.vram.cmd[3].YA = 110; + + vdp1.vram.cmd[4].CTRL = CTRL__END; + + // start drawing (execute the command list) on every frame + vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE; + + int dir = 1; + int ratio = 0; + while (1) { + v_blank_in(); + + // increment/decrement the color calculation ratio once every 4 frames + vdp2.reg.CCRSA = CCRSA__S0CCRT(ratio >> 2); + + ratio += dir; + if (ratio >= (32 << 2) || ratio < 0) { + dir = -dir; + ratio += dir; + } + } +} diff --git a/vdp2/nbg0_16color.cpp b/vdp2/nbg0_16color.cpp index 100d4f8..91a17d4 100644 --- a/vdp2/nbg0_16color.cpp +++ b/vdp2/nbg0_16color.cpp @@ -105,7 +105,7 @@ void main() vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 - vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0 uint32_t top = (sizeof (union vdp2_vram)); palette_data(); @@ -118,7 +118,7 @@ void main() /* use 2-word (32-bit) pattern names */ vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD; - fill(&vdp2.vram.u32[(plane_a_offset / 2)], pattern_name, plane_size); + fill(&vdp2.vram.u32[(plane_a_offset / 4)], pattern_name, plane_size); // both 1-word and 2-word have identical behavior; 2-word is enabled to reduce/focus suspicion. }