From eafd4e6f2350fe72ae5f237e22b76a226cf78f3b Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 8 Mar 2024 16:17:59 +0800 Subject: [PATCH] holly: add video output data --- client.py | 2 - headers.mk | 3 + holly/core_bits.hpp | 2 +- holly/video_output.hpp | 19 ++++ holly/video_output_mode.cpp | 177 ++++++++++++++++++++++++++++++++++++ regs/core_bits.csv | 2 +- regs/core_bits.ods | Bin 22275 -> 22291 bytes regs/gen/video_output.py | 147 ++++++++++++++++++++++++++++++ regs/video_output.csv | 24 +++++ regs/video_output.ods | Bin 0 -> 23338 bytes 10 files changed, 372 insertions(+), 4 deletions(-) create mode 100644 holly/video_output.hpp create mode 100644 holly/video_output_mode.cpp create mode 100644 regs/gen/video_output.py create mode 100644 regs/video_output.csv create mode 100644 regs/video_output.ods diff --git a/client.py b/client.py index 516745d..a26f832 100644 --- a/client.py +++ b/client.py @@ -41,8 +41,6 @@ def symmetric(ser, b): l.extend(res) if len(l) + 8 >= i: break - else: - time.sleep(0.0001) ser.write(bytes([c])) diff --git a/headers.mk b/headers.mk index ec34f63..27a82f7 100644 --- a/headers.mk +++ b/headers.mk @@ -31,6 +31,9 @@ holly/ta_vertex_parameter.hpp: regs/vertex_parameter_format.csv regs/gen/ta_para holly/object_list_data.hpp: regs/object_list.csv regs/gen/core_bits.py python regs/gen/core_bits.py $< object_list_data > $@ +holly/video_output_mode.cpp: regs/video_output.csv regs/gen/video_output.py + python regs/gen/video_output.py $< > $@ + # MAPLE maple/maple_bus_commands.hpp: regs/maple_bus_commands.csv regs/gen/maple_bus_commands.py diff --git a/holly/core_bits.hpp b/holly/core_bits.hpp index fd22958..a85c607 100644 --- a/holly/core_bits.hpp +++ b/holly/core_bits.hpp @@ -392,7 +392,7 @@ namespace text_control { namespace vo_control { constexpr uint32_t pclk_delay_reset = 1 << 21; - constexpr uint32_t pclk_delay(uint32_t num) { return (num & 0xf) << 16; } + constexpr uint32_t pclk_delay(uint32_t num) { return (num & 0x1f) << 16; } constexpr uint32_t pixel_double = 1 << 8; namespace field_mode { diff --git a/holly/video_output.hpp b/holly/video_output.hpp new file mode 100644 index 0000000..49d7394 --- /dev/null +++ b/holly/video_output.hpp @@ -0,0 +1,19 @@ +#include + +namespace video_output { + +struct mode { + const uint32_t fb_r_ctrl; + const uint32_t spg_load; + const uint32_t spg_hblank; + const uint32_t spg_vblank; + const uint32_t spg_width; + const uint32_t spg_control; + const uint32_t vo_startx; + const uint32_t vo_starty; + const uint32_t vo_control; + const uint32_t spg_hblank_int; + const uint32_t spg_vblank_int; +}; + +} diff --git a/holly/video_output_mode.cpp b/holly/video_output_mode.cpp new file mode 100644 index 0000000..2a7e570 --- /dev/null +++ b/holly/video_output_mode.cpp @@ -0,0 +1,177 @@ +#include + +#include "core_bits.hpp" +#include "video_output.hpp" + +namespace video_output { + const struct mode vga = { + .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_1 + , + .spg_load = spg_load::vcount(0x20c) + | spg_load::hcount(0x359) + , + .spg_hblank = spg_hblank::hbend(0x07e) + | spg_hblank::hbstart(0x345) + , + .spg_vblank = spg_vblank::vbend(0x028) + | spg_vblank::vbstart(0x208) + , + .spg_width = spg_width::eqwidth(0x00f) + | spg_width::bpwidth(0x319) + | spg_width::vswidth(0x3) + | spg_width::hswidth(0x3f) + , + .spg_control = spg_control::sync_direction::output + , + .vo_startx = vo_startx::horizontal_start_position(0x0a8) + , + .vo_starty = vo_starty::vertical_start_position_on_field_2(0x028) + | vo_starty::vertical_start_position_on_field_1(0x028) + , + .vo_control = vo_control::pclk_delay(0x16) + , + .spg_hblank_int = spg_hblank_int::line_comp_val(0x345) + , + .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) + | spg_vblank_int::vblank_in_interrupt_line_number(0x208) + , + }; + const struct mode ntsc_ni = { + .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 + , + .spg_load = spg_load::vcount(0x106) + | spg_load::hcount(0x359) + , + .spg_hblank = spg_hblank::hbend(0x07e) + | spg_hblank::hbstart(0x345) + , + .spg_vblank = spg_vblank::vbend(0x012) + | spg_vblank::vbstart(0x102) + , + .spg_width = spg_width::eqwidth(0x00f) + | spg_width::bpwidth(0x319) + | spg_width::vswidth(0x3) + | spg_width::hswidth(0x3f) + , + .spg_control = spg_control::sync_direction::output + | spg_control::ntsc + , + .vo_startx = vo_startx::horizontal_start_position(0x0a4) + , + .vo_starty = vo_starty::vertical_start_position_on_field_2(0x012) + | vo_starty::vertical_start_position_on_field_1(0x011) + , + .vo_control = vo_control::pclk_delay(0x16) + | vo_control::pixel_double + , + .spg_hblank_int = spg_hblank_int::line_comp_val(0x345) + , + .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) + | spg_vblank_int::vblank_in_interrupt_line_number(0x102) + , + }; + const struct mode ntsc_i = { + .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 + , + .spg_load = spg_load::vcount(0x20c) + | spg_load::hcount(0x359) + , + .spg_hblank = spg_hblank::hbend(0x07e) + | spg_hblank::hbstart(0x345) + , + .spg_vblank = spg_vblank::vbend(0x024) + | spg_vblank::vbstart(0x204) + , + .spg_width = spg_width::eqwidth(0x01f) + | spg_width::bpwidth(0x16c) + | spg_width::vswidth(0x6) + | spg_width::hswidth(0x3f) + , + .spg_control = spg_control::sync_direction::output + | spg_control::ntsc + | spg_control::interlace + , + .vo_startx = vo_startx::horizontal_start_position(0x0a4) + , + .vo_starty = vo_starty::vertical_start_position_on_field_2(0x012) + | vo_starty::vertical_start_position_on_field_1(0x012) + , + .vo_control = vo_control::pclk_delay(0x16) + | vo_control::pixel_double + , + .spg_hblank_int = spg_hblank_int::line_comp_val(0x345) + , + .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) + | spg_vblank_int::vblank_in_interrupt_line_number(0x102) + , + }; + const struct mode pal_ni = { + .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 + , + .spg_load = spg_load::vcount(0x138) + | spg_load::hcount(0x35f) + , + .spg_hblank = spg_hblank::hbend(0x08d) + | spg_hblank::hbstart(0x34b) + , + .spg_vblank = spg_vblank::vbend(0x016) + | spg_vblank::vbstart(0x134) + , + .spg_width = spg_width::eqwidth(0x0f) + | spg_width::bpwidth(0x31f) + | spg_width::vswidth(0x3) + | spg_width::hswidth(0x3f) + , + .spg_control = spg_control::sync_direction::output + | spg_control::pal + , + .vo_startx = vo_startx::horizontal_start_position(0x0ae) + , + .vo_starty = vo_starty::vertical_start_position_on_field_2(0x02e) + | vo_starty::vertical_start_position_on_field_1(0x02e) + , + .vo_control = vo_control::pclk_delay(0x16) + | vo_control::pixel_double + , + .spg_hblank_int = spg_hblank_int::line_comp_val(0x34b) + , + .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) + | spg_vblank_int::vblank_in_interrupt_line_number(0x134) + , + }; + const struct mode pal_i = { + .fb_r_ctrl = fb_r_ctrl::vclk_div::pclk_vclk_2 + , + .spg_load = spg_load::vcount(0x270) + | spg_load::hcount(0x35f) + , + .spg_hblank = spg_hblank::hbend(0x08d) + | spg_hblank::hbstart(0x34b) + , + .spg_vblank = spg_vblank::vbend(0x02c) + | spg_vblank::vbstart(0x26c) + , + .spg_width = spg_width::eqwidth(0x01f) + | spg_width::bpwidth(0x16a) + | spg_width::vswidth(0x5) + | spg_width::hswidth(0x3f) + , + .spg_control = spg_control::sync_direction::output + | spg_control::pal + | spg_control::interlace + , + .vo_startx = vo_startx::horizontal_start_position(0x0ae) + , + .vo_starty = vo_starty::vertical_start_position_on_field_2(0x02e) + | vo_starty::vertical_start_position_on_field_1(0x02d) + , + .vo_control = vo_control::pclk_delay(0x16) + | vo_control::pixel_double + , + .spg_hblank_int = spg_hblank_int::line_comp_val(0x34b) + , + .spg_vblank_int = spg_vblank_int::vblank_out_interrupt_line_number(0x015) + | spg_vblank_int::vblank_in_interrupt_line_number(0x134) + , + }; +} diff --git a/regs/core_bits.csv b/regs/core_bits.csv index dec7246..3c8d0f0 100644 --- a/regs/core_bits.csv +++ b/regs/core_bits.csv @@ -207,7 +207,7 @@ "TEXT_CONTROL",,"4-0","stride",,"0x1f",,,,,, ,,,,,,,,,,, "VO_CONTROL",,21,"pclk_delay_reset",1,,,,,,, -"VO_CONTROL",,"20-16","pclk_delay",,"0b1111",,,,,, +"VO_CONTROL",,"20-16","pclk_delay",,"0b11111",,,,,, "VO_CONTROL",,8,"pixel_double",1,,,,,,, "VO_CONTROL","field_mode","7-4","use_field_flag_from_spg","0x0",,,,,,, "VO_CONTROL","field_mode","7-4","use_inverse_of_field_flag_from_spg","0x1",,,,,,, diff --git a/regs/core_bits.ods b/regs/core_bits.ods index 986407c356fceceac40c63c1e09c0e075d6c9b85..e0267475b2495b4549ee6a6dd0027900e5302107 100644 GIT binary patch delta 5625 zcma(#WmuG3w=;AMA>G|QbazTfcOxJuA>A{yAR!Dmh#(!(4FW?d-AG7>gdi!+PrbP00yn7S!PooH1p?X`Dh&mk2q%G0|-=}Rmn=XdgwZs09V zFqYsb>6suxsB2=8$kso^P!!qQ`8=b(qVOaCHcJ9Xw4vx}EPHr_Y*b?khAD=Ir#u@k z`6{GN-iYXgz1&A!a6I~I>3jH{_?PVY)*&M?#0QZInZ1zXDOZEXqZloAhwb%o#UDjz z1MG-3XdZ1DJdCX~1%kuV+|<~yc#PlZjga@2eI-ky|b)+J5a zXoYd#me$IE_&m@)u~WfPdcTb=4dXqpd%3PkZXwA3_Hg!ldDO%?Pr_n2dCJ^eL^;?> zyIscjl{-k=B8PMt)8d+S2coTxj^W0w=l3260O%kC0KfmGzn>KrfXadawLxZ4Z#b!f z6{FHXzW94(QZqd`@a0{i_RkLv2!R)ja5E9D-V9OWBF%*QzhF#Zb=)sXbZdIGx1a&@iphl`!CwLGHt7WLF}L=8>BLt?S#Qj_k6GKde#p?!;s6fo~ts2UOWchD`T zz+SK`NunJ<(%i-{V{+>-rLe-Pvo0Q3ceE(Eds~a{ zlW;x#N~Tq$XQhiH*k$r^J7@F(P3s1(c6cGZ9O~|FoBVu2Z`$MF52(|d!vM3o3&A5^ zQJuSHKet1U^x*n$vu0O(Jq6;O+4v4VxWT8bXJwUz66pcpGx-c+NwDig^MpasG_f2A zlFUEGKG0r=ZmK;fOIWqzx>fGAR0BgZ}Cs=KpF!?Ck> z((Dnb+Cad|BmPAF^5V;IUsNX5SF#*m9EdT`TKjePGT}(iJZtNv%-)!23M54rSjo=-}Q^Uf74C}=*kZaKzf3;5W?~=!uTzoe6e6FyioF+|E4tjII zgajLbc}#Iy(-J+Z&?5QcY~I?AxmNZi#t)}Ec4}2hn}grcl9#I2=R1|7dNB%FuIz6p zxI1SDi=#c-23Bkxo^w7=pPbX^-Cy{g0p4tJ0LgDF@o9X!(f^`@E3sozEahos4iTeW zk~jd^Zg=@#Pk8(BkUfc-xE459(YC&Nic^GUQN&=nfV5k?$avn?gvc%Fc)xh_&9Eq zx0W%^jN^piiwTu6XOSl|kuq@0C20t;VTx8Y7&lBZe@r zabYvJaB_W)2j;1KT46;fDHIw3wOu6+Vh)XQ5NZb$w8xdKy zZr%%JSWd77S*)QGMkS93@k=SbNZ)vJGd&A=%2fDg)RIzOHHi7Ziio0jNXZ!mVnbiP z9474klukv)o((>)+;z#2LZ|#8Mpq|XgK$d|wK7%8H8AXQZ>U{?4%eG{Nb60;2Igof zhpW2W8wvK!>q9v@tJ4fh2=z{eo?Qv!@FhE1{_ZNVVt?2EuJTnwSYKO(6#E z=45BUaLwRhqbl#Wy<_zkpQ}c4xap^KE+w&~;g>_4?W&y!BRSD-1cPJl(gU$Tr?k(D zjo8geO*~?9OT7m=jmvpkhk>6rd>Nnboj)OMm+_FG(GR009)UYFLEz7v^u_d;Rb1L! zWiOcNbB)e5s(WvUqjoPsQMTw#U3C*5=x~WGWP`PMoa8xJlAf%DcVbpbMXwPljdU{M zADl^zn!5KKPst#;@i|cmE_jySNg=~B{~rXBfk6?xQV2|iFPx`mn{Kkl!Dda(Dv6F$ zZV}eUHwM;m3paA zf?S;}>qoCoEAS5equZPyS-qLkiCObos%=*i9;i;|^jE8?v$OkBHfBtz1NYY%g#`+G z)LRY6wT~-B@>?odL-rUnWw0CtI<&XRyQZJQb>{2UQ4~HV?$SJ(z}F3F_T9sN}-ZGcQLENw6s`rtTj z?THari6dXmzMq+q8fo?cxRp|9oww!a-|te)RYXTIKYAl0lWK*__QR?fs-3g-6N*BD zwG)Zz)rys@P-^C456kiMiCk06<1iM{3?_{!uH>4^X(OVYhqLhFou+4_>Xr4GrKQTI z`dptvZsWI~Vb7-CVacnsDpMZmK0;x^C{6w%6ye;Fb)SD{_o6^pU+TUU>`NSC@OliCl!@-$-W>`-mZIJcl$6VZAmI-T{}9%Pz<7xa3U$i_Y_yLgThq z{e1i+CB(_&@K|9-NBueaV3WB=d96z~Ute&U|?US3YFj-EVzF3i9%%ByFTrj z;G!xOaoHQnxmw}}DEO<-1H|&x9wnQmSwSEZNHpkX-dNtl;jLqZ{f)jpX9&ba^^c=* z!pBrP9wsG0dJk1zHGNii>|;_hG;(x4k=SEJ>LsqkQx^CcCs_3(I9k4s{YI6CwRK;Y zU&%wRPc;)M!7md)d)(~4D+qnuQg-LzBSqgpV`8gF0x$T0FNZKs$lW&cI*zX~`H%}K zaTfD$&V0xo{Ep17QcRu2hM|g%;(Nov?*+$i3$hvJU{B#*i zFqUZVSx24_WAU14@RSuL&+&cg#Pn@*k1~}QnKK9phE}krP>uCfK~eF2j(Lhz_zlS+ zcSfx3tKL4s6TxlR$=vze(xKD~hZB9sG$(Pr>HDCRj%vIxJ4MN+h$S8{SpltHjdBUd zEI7iR>=Z#Q{lQun{b9T@V@Tp8nOF29Le-?!-t9{DII)P_V<7Rf$T&UWd@4*QAm01l zHwSDGr4S9NzLUwI*>uh^LP4as2;4r<{zHh?n~2Iy%lKwJ0{Ku)_og@R3Ayb zT4Z*}&g#_XpfSRS!Fp@?w5D1icG{FH?xfz`&X(*@^0>Wg%^$THD?J&?7EwMH(F*KQ z&=iWWNWLO}d?PHv02cGuK=OscH04Hjv;_l_a`p~M)@q?D`bFxf#upv9%nZ5DbO7&3 zm{FR;_+Ki7LuKJ2Vtx6bHm?haNh0Csjm~n)#rL@EDxZ-{#j!llZ3+R}tULLqSs<4H zuF(jm*zGPn=FTk_99lS}LZX1S?rsUS?0wAgYCHlG;s?QB$17&TY9?bP$!lOM@@Dj?Vn6uYTZFPg3j?RB6joG(&m zj2_;c`lj5dWJ@e_ktZl%ppCWlfjCWoyd>-vIkZS1%gB5BaE{=)9kVB=GUnBr@&c=v z`K;6?m)QFsm{hTeB7Tr*WP0T4;2W(XmF{DvX#QKmna@tZHF?H;PDe&FcXHs~K?fbr#^SvTZwN*YpiqJK{UAqWn7%}^^^|8>LXR3; z!$ia&qNi9^8g*x67>^PX?6Ff%QaKeZ#- z8u4 z{C?iD4%oMDYRD-+Qs77~_$L`#8?gUe*#-+N~AZ zw99yxIr+|c{0Lf}5hql?Ou)TY+#CttX zqEwAII??Xd>cA#j6g-kjuxROYQ$eh>E41T0QO{T@p?7dczSx8SW=U#PF>a|Xkq}z- zzDvA+14%QZ=)d70!#f=N>{_N(D^*egt}L=Nga4QpF>F*|IirKNc{}*HFfT<!A_t&nh&b8dir}^i8bSU;4W@2Vt)h z;ehVFtVL2;rR=njA1C>oS2oralj5d>8< z1u?*pGLvoqL}`r{h)(lxVOgWfz0sHQRs2z$0a6_D`tHZt@i@mHq&Pou$_>A+S_O0A zB=xoqjuWYvm90;m?kOZ;?-BZ3TOq<7+r3u+K;A1vXm1|bh(`>cRgC4X}to%WlpNT+V{WkL2r$lyswhA zrv22$WS^K&oXs_VxrR86F|?ex=V%VacJEhj%HGGzXS`ev8n4vXpfM zcX_-FF}oXJ^}625+;zpv#EUh)PI&QXp>>41NFwRUu2k{`CjzrD6Iyqq>elY8|IObK ztm;;q)veJB6~vFYo{c^Y_o&sja5uT0Xd2Pgu$&8346kFl?g11n|vBw+(~)NA_Z2_IP#GT0Mi z+nw!sE24yA>lGH^_SI>xyvm=;kc|aKPT)(iCe##?m6+z5G!%Q9=5AbylAro0b_q{=>*~%7{j@ny zMf9v2{JOi2s!nZ%pnmLSm(xl@5}Bv)u-`sa8ZY(<+}CP6`(&fp%ff zlV{T|4Ws~ounyACd;vrv0{mRj{hc9TX}bImer*Q-=tBWyuz6j27!DE^`)}>PmH(yl zCjp3sf%OPs)%yQkA&%%$06YF-WdT9|ZzmUjSupBsd)Tre4O*J+FXn#$NX!Hf delta 5559 zcmZu#bzD?i*Pfwc0Eeytq`N^{5b16tC8R@`0Y+*l6_6g04(SF3X(*K?iwUN zjVv8IX&5cu0OA&VO`&R>da^{#Osu!;6plqejAj3`h+F zLeQ^}I5;@JLspxkNdkXcBh%5T5gM^+{G`n&BL<(!?m#T!DjY5YgRxJB<)ivrJdCwT zjb1ySlUc4&EdI9DbF^pOGK-1t(O^yvyxkkSv_8SD{Uaq zM+^!gX?)W5sE^|n&^VJN4pE&jtF2xr+{bB&y<4tcLo)T%RVdIDj@l6x~0RSCz0N~G$^w+5( z{V-W^g00Y5x0ec{k;RyFh^}X_3a^=4rkf*2+EDwTw0dKyQ{mga=3PdgSE@p zE%?JT{I)mJGLVbHbaq5W%RM;Rmv_^!9i9Nn6_bp|+BiazS^=lchc0CW&Z&MJXVzx= zQUbikwIiq5<05h(M1sVyIA`k#wu$z(EJ+m|j05B!{Ej;UnUP408J@Af9+BXf5Si^PZ$G7-cqRc` z$G0GI0_Eq%13s}_vT@uTh{@WC1NwuBz6Jox?uY&ksYs1|uoha1+#m<9N2NK>EY1vG zx~#7E)SDdV+ga2#2#TQD*Lt#kVvf{oC@0A9?`B*m4|!PmK*N`i#P8LOupHoo-S@K;MFk=(70Gp z$7*FNdByZ$VuPm;?37UxJcA~FQ7oH3D=IjclnoN-(|8>zVVf%E&IK>u@wg-z*tfrd zpm`M0JoesNEz^Qq=y_P;_09GQEWFIZI2s#l*gzByii;FTj3i`P%eGKi$iL=!hIkrr zoOiGMHFFyK?x;S~NDfyq)-X>KAtLr9b)K*Fg)%`J?KD^yk~pMu&@gCk@xy@7tr@EW z7ZsTvaUr|9lfP88+hRVP(W%jkdn6O6^eIp&cF9M0)rZYv#Ro>ydf!uWPd@~mY%s~L zJ_+ICs4uN2qU7AdD|f}hlw*Wae^+=#){}M~3`$}^@j_$4I@~O?IRcs$jt@9lBODe( zd!ZJ7gk9pQ>1;29;i&y*;~_$cm4{$>r~uc#eZfWa$XT6{RA(%heb2JRchjrZvGZJ_ zX=%K;DFz#6#QmcxQwMj|k&#S(r76mV2w@vd>=BG<2tqNKq$*w_+5x6tUzXI@QL_2< zj@#|(K|Q#g-P9d1+NuOvfHIQ_WJm~GDP*}zUug<~;H8h*f*ljwk z5lY>_MxR~$6sxWBN@q@wuFg_mCBpbq^S2V5Il|#Hvdr_V1o!>SdZ>&ybopJs1`FSh z;M#KC*!-)9pKgVZwa=?YIqs1_qek{jt#$(>{V@T(M(;=uUV%)gz z?EAjp#;B|Uxqa_{Q@5b>;96d^NZFNfQKuOQH$QyP`FO|4yX?m&H~@8_3E)u#Vs@^#R5G;#*4V z1_Fbj`|e-NHddr=Dl+#`%Rw_a1yfxySS_Z z9y_5lx#)mPyu&6ViPp_}^R#_{RYK#Ly=&n4_CLlo#&m zvTI`MlOsVIc)vBLf1+B#!Z&5vDdYLLDW74()CD<%Q+M3c1O|!L8w|v7Ma=Ws&=C=$ zQw8Fmr|)tG;YE~5`PYO+F{xIlj=3j}fSC!sz$xa5>bX#Vor|yM>j|2LpM$-UB!aOc z#MZQN8p7y%cf%$iss+k!IF!YDZQx3hML7!!&5VmUm%1^_ii)1jgcLGGTMvU&{H2Nh z@BE^!>v%cF!=8|G|^-Zcjy2)Kz;<;}Jl#wYvY#F4Y>mYxT+QL^ddde zat9gAC!(GITA<4>udnJ<$@qoU!rT%PpVcdSG+cOjNGw{`=Uh05wAU}{rbQu3p1p)# zyWOx&?1_9|d>r`!Tvp=;7agT*OU{ zdDO~Lozi94Q#qoD;ya^i0dNBr`jar-p*XQkA|AF@a1rLys#mFEQPs`503pgLRNBV6 zc>Ae1K@(`VkuXgc1mqCGz<;cH%n(D$3L~f|CK9aI5FprJ1c_~Po9G2S)3nB|;+=!M z@Ck1tWMRy6(E${bvtUSs2qNV(0G7y5T3cOKONpzpnRf{LnR9_=ygqqKubND^EU!;_)yBw}{UCq?0D! zw{@c6I7|f9=tQQ5z=Tyn))z#GOe|RoTSL!R+&p&|6H(W?P1K?=8v$hBkM+m-K|r0+vqOyuT73s-F>IWDfdUjHxV+ku6`C z6c|PkpKzI~wI0>Ba=Fip-fZHFk<#z)Gm`+(;{y;^D!EEsM=FF*&e+_F=FmEW>jArm z0nKlS?IvV{&=%3& z7_)ONSsg|QGU_7nCGjIFjc(u1t3ZTQ(J7ZTVoRxc&uH0cih7zWXBxQOvMxdxssYVz z4-u}MGRj91gA6%Y!A@J^X=Onw`0zvl)}rqy)V(E8JiG0xq5}!)%k`!21!{xB*vwz` zh%cg30|R{$GaDsc-1~ku;{hu&e%tCcD4~YyK(O>#c`P3H@H$O>x387u8Xd)c&%rs1B5yMqbRs=ajBE)=M!X>K3cwBETYDa&zgYD#S~ z*Gqvz_C^Ox{bnC&If=okoo^drLn9$eW=0)N&WQ_k9sEV}w+jy!=NI$uDO`1rM7u8(lR<+!vgrxoW}T*j@Xb=AFm=osv~eY0QgEK{jRFtXR_b zoJjUfTw?|>1FNRr+!%{HQx}Nq&p2LuGAM^aZFn*#PDcl`3sdZwNMb8mOc4B*JjqFm z62=c~=-{HjqM$zUkh%nSSvqBWJ&UkC(g{w!`c_NZ(&hsrdS}Kq)!5J)tinz49+dy2 z3MWaIBYL0it*m)`S*&aVbu*cktAsXY0GJV4eUCV!&cb33Wi3)IZ4`JaXDGg{_o4gt zS4PpDf}w%10Dv9VpBaVVUwwYH0?7r-@20z2Ui|5w_Pe@H;*bP!8OSY6%CMwoLbb6n>v#)zW=Qc1UCMlsD6agNOgSxYz*3yD83YC1rpnY zthE5c?=i-Ya1o;rIARCd%hz@x&zn9@1i3`nmk~dvrL<(rjJA`?ZF2aD7ub79G9kXD^;@4*=!R8H>U6{++$tD^HtTVSkh#M)AA+8Sa`sq*{cJV{Um>G0xgb?U?Y zN+QoYUjeZEAS|%CMh1u0o{V0s}KAicM1uU;rjsEB7*;ssBCJiUo( zbz!=kKQcndyq&qfZ|38-;ji5}?eoxodChA_Y%b!V>3)2t<)#MzE=FFolJBKKuIiBF zD>>h^Yg)St%)DTR*&g2X^$Kb?#S3B64|1Omjv$P|k&pu}p1?<*)^+%4;l1~9sI86o zEnqytcAxI5w|D}sTcFXt88j-sT9p;4a78LXnf4jPc1eoF>$RJ(AD`dN>_+t@KJLJz zquRh>4NoO_;&^c{;`1Yz7d&Nw&4y`-rP$EieRZE6)-7~5H5Y=B8RXUS$5jwbt zYLUrRY8C9gS?BWzH=iP_4!6(GKy ze%9&`;(Lghk$W@uZaeztU9d9iQ^1qIDGHRW^7-&Lq@mv zAWM@(J;sFJJcn6>)kYui;S~l;Dq0Ur39mFjAGdH1Sk4D1gbpTcyM5g)4dB{~i`J&4 zK^#@JDNxX#Ew0sB6-ZLT#tKq$X6p0(xYWV}7{gS8n2vvP4?!Rl=UMlXO2246*OhNV zsTMi7G*9Z)zylGELhkU7H-C^NLFA0w`Ed!5}B{P0D)OO5wj`oLce^WQu z1kO{{6aavT4%$!Z28c!q_{{=h{^sP6MY?|oJfxEzHS%1S6gdb4as1clx6MC_QULuw zCx9qqFpwm{faVXWC#z2l?ENXZi}csW`y=}46b&7SR0Yxz{@W*VUYGhO8;Bg#WBuFG z0~kO1{~8tpk+Odo{#v*IjDJe|zaD>vM~WM8|8eJNAd35o-u%s5A&U%njDF4jS$X6A zYbP$4KdWunGnXg7Ywf>2(_b9dKkwIHb@|_870GS*pY5v|QUf`Wc7|+!-XPwP8jW2X esUuFo^}p`^c_R3K`}&E}k^6>pSmC" + yield "" + yield '#include "core_bits.hpp"' + yield '#include "video_output.hpp"' + yield "" + +def max_length(regs): + max_length = 0 + for register, *_ in regs: + if len(register) > max_length: + max_length = len(register) + return max_length + 1 + +if __name__ == "__main__": + rows = read_input_headerless(sys.argv[1]) + formats0, *regs0 = rows + b0, b1, *format_names = formats0 + assert (b0, b1) == ("", ""), (b0, b1) + regs = list(parse_regs(regs0)) + modes = transpose_by_name(format_names, regs) + max_length = max_length(regs) + render, out = renderer() + render(render_header()) + render(render_namespace(modes, max_length)) + sys.stdout.write(out.getvalue()) diff --git a/regs/video_output.csv b/regs/video_output.csv new file mode 100644 index 0000000..4108b8c --- /dev/null +++ b/regs/video_output.csv @@ -0,0 +1,24 @@ +,,"VGA","NTSC_NI","NTSC_I","PAL_NI","PAL_I" +"FB_R_CTRL","vclk_div","1",0,0,0,0 +"SPG_LOAD","vcount","20c",106,"20c",138,270 +,"hcount","359","359","359","35f","35f" +"SPG_HBLANK","hbend","07e","07e","07e","08d","08d" +,"hbstart","345","345",345,"34b","34b" +"SPG_VBLANK","vbend","028","012","024","016","02c" +,"vbstart","208","102","204","134","26c" +"SPG_WIDTH","eqwidth","00f","00f","01f","0f","01f" +,"bpwidth","319","319","16c","31f","16a" +,"vswidth","3","3","6","3","5" +,"hswidth","3f","3f","3f","3f","3f" +"SPG_CONTROL","sync_direction","1","1","1","1","1" +,"pal","0","0","0","1","1" +,"ntsc","0","1","1","0","0" +,"interlace","0","0","1","0","1" +"VO_STARTX","horizontal_start_position","0a8","0a4","0a4","0ae","0ae" +"VO_STARTY","vertical_start_position_on_field_2","028","012","012","02e","02e" +,"vertical_start_position_on_field_1","028","011","012","02e","02d" +"VO_CONTROL","pclk_delay","16","16","16","16","16" +,"pixel_double","0","1","1","1","1" +"SPG_HBLANK_INT","line_comp_val","345","345","345","34b","34b" +"SPG_VBLANK_INT","vblank_out_interrupt_line_number","015","015","015","015","015" +,"vblank_in_interrupt_line_number","208","102","102","134","134" diff --git a/regs/video_output.ods b/regs/video_output.ods new file mode 100644 index 0000000000000000000000000000000000000000..988b53fcb8906df356c89c4fbc46b41c0af1976b GIT binary patch literal 23338 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