From 69c4b11f7b46786eff6ec7654d22276ed67c7409 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Fri, 21 Mar 2025 00:50:29 +0000 Subject: [PATCH] Rename name to param to represent that it is the parameter. Add pixel writing code, add rectangle rendering code. Implement ROP, Rectangle and Clip class methods. However, the drivers BSOD. --- doc/nvidia_notes/NV128.xlsx | Bin 9615 -> 9708 bytes .../86box/nv/classes/vid_nv3_classes.h | 112 ++++++++---- src/include/86box/nv/render/vid_nv3_render.h | 5 + src/include/86box/nv/vid_nv3.h | 57 +++--- src/include/86box/utils/video_stdlib.h | 2 +- src/utils/video/video_rop.c | 2 +- src/video/CMakeLists.txt | 1 + .../nv3/classes/nv3_class_001_beta_factor.c | 2 +- src/video/nv/nv3/classes/nv3_class_002_rop.c | 5 +- .../nv/nv3/classes/nv3_class_003_chroma_key.c | 2 +- .../nv/nv3/classes/nv3_class_004_plane_mask.c | 2 +- .../nv3_class_005_clipping_rectangle.c | 12 +- .../nv/nv3/classes/nv3_class_006_pattern.c | 2 +- .../nv/nv3/classes/nv3_class_007_rectangle.c | 33 +++- .../nv/nv3/classes/nv3_class_008_point.c | 2 +- src/video/nv/nv3/classes/nv3_class_009_line.c | 2 +- src/video/nv/nv3/classes/nv3_class_00a_lin.c | 2 +- .../nv/nv3/classes/nv3_class_00b_triangle.c | 2 +- .../classes/nv3_class_00c_win95_gdi_text.c | 2 +- src/video/nv/nv3/classes/nv3_class_00d_m2mf.c | 2 +- .../nv3_class_00e_scaled_image_from_mem.c | 2 +- src/video/nv/nv3/classes/nv3_class_010_blit.c | 2 +- .../nv/nv3/classes/nv3_class_011_image.c | 2 +- .../nv/nv3/classes/nv3_class_012_bitmap.c | 2 +- .../classes/nv3_class_014_transfer2memory.c | 2 +- .../nv3_class_015_stretched_image_from_cpu.c | 2 +- .../nv3_class_017_d3d5_tri_zeta_buffer.c | 2 +- .../classes/nv3_class_018_point_zeta_buffer.c | 2 +- .../classes/nv3_class_01c_image_in_memory.c | 1 + .../nv/nv3/classes/nv3_class_shared_methods.c | 1 + src/video/nv/nv3/render/nv3_render_core.c | 171 ++++++++++++++++++ .../nv/nv3/render/nv3_render_primitives.c | 46 +++++ 32 files changed, 395 insertions(+), 89 deletions(-) create mode 100644 src/video/nv/nv3/render/nv3_render_primitives.c diff --git a/doc/nvidia_notes/NV128.xlsx b/doc/nvidia_notes/NV128.xlsx index 919297d56816e5278deb74887f1c321198297f08..fbf57c5eb136926abfc26b411f6aec0ae899a3fc 100644 GIT binary patch delta 2944 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 delta 2864 zcmZWrX*AT07ygZ1n5eA7*q21a*b*|LjD0WrzBFU^T3XDEtt>@G_977`VJtDWD9e;R zvKx&3o$#U<5&wEWbk2MJ_uLQn-sd^@%RSF|?pLE!qv}sg=q0S)8VfxD%rgPNX#fBs zQ3?@(AxQVYK;*?pe^iByQ(&Irx%&lmCzvBs0xM?>q7*2%^~=M*adHu}0jqb&PV}jo z;PEH-$BVytM6EaJcXm4-(q`@s)~D)hOm!2z5TWNSuRT@_$(Hfz>XOpW;w=qG5%e!B z^A%?_8b%9^tc`r^Io;z>9$;%pRtH4Fl5Tr6b?%1Us?GdceDV?~v))=>MbR2!7LhcJ z7*EN0yL~T3ysE^pPzzo}ju9P4I@iE6@At+{#>$MD(|`M`UsJ27e%WE(9v|>yK;CN_ z)S09C8JavFDMmZX{s^tJ$?z)njlHvM`SO$?sIEc!{=7~H zRJ00St(np>oknLya0m#cbt3e)Jh`>p^aouTPLu^eejN6OB9U9y*a{jC)|MjsA$y?; zP7lIo)uyJ5RY-nis>w+Z+Y;YXdPJ`(?XtGsJ7mn4R6QLy`6DiW@TnC+Wdjllf*tt=lGj}rh}e6*nxyN7ZELsl^~)K0s$Kdj z{LYtR8MDkRff<*WB%))tg;Yc@BGV|i_kw9vJj__Zg_Hpu>vUmxnmKm&^vs;q%)1l* zQ?B@QiSJbIsvE%f~aLQX| zYPHs4bjaH;g8~FSpNKAf$%gZE@8?HnsSDwX&fA|xMQZrLuAh#leY(|D6r~nM(Ur0G z)qR#>W~Z*?_(ZQH9Q$oDMeEKSNTkdbk|>4-aK~$<^x|8LB?~ad+j?6MU(iKQoXu<} z_#cXrNEV5+de3Y;Z%`U5icMIP8fFzQNlg??@}qp(e3ie6s0OSvMrwD}ws$2Pt}$)* zMJ&2fnxo8V$w5srJhyyzJpyBwq|y0_u`9UkT!I`D-xpuB%;9J{H+lJ`07HEQ3oQnE zeT>}r_mUcbdqRJ%_LxA8ubP-?r&- zxLKZ&If{N?NP zLzn6xt#^_(A&2@xI>CfD@+{KPFuK}Ghn<}kN`h`)Op`EiH0L%zXC@J^88GDa4OV;s z;lQhoI0}Oyy4M+Gx}Q5ybw?8*%{-4&xuzknmr_NwTg;iEqZO+ihmp4mXgEa@1s!~% zd$lAXqdWN2bV!G1bT)&>>etM(jiRlfXE+xyH#!Q0>1p8>t9KW-Nb2N$!&0=diR=jw zbdh#jp^tn2J%3_bP{ZqPt0Q#vhlSnp&)w$6f(%>zLz_AKL+TBDqqb>MUyLfAHcV~O zh(3C*;2%nyq`r=yEW@K_s@2p63~by^d^f)M)XQcK;vH4@JdpbUL>B|C3V3nyWwsE9 zR*L<*dHZi_-4BwMmCLACGwXgs#bMEGG5P-c=zUhbMMurpg$i%t#k`RH_V29Vhzs*g zs83qJxU~ArGYqw+dLTHE7Qe>@j#L1ezsrC_U>5>Sv+yPDQL>0F5wu=KhR=GslUjM`ey%oZ$5k&&jKn!~^f9w(X#<<7C+}@bapt00epfce?Uv-2F z`&j?o@p&b=#k^HvptgkbDjTb2PQe5P1OTD9O^6^m<6kFD*plAR5j>E^HPN~G)v}cF zoh#=x#LLWXc+PWHVEa*4^@rb;4VCq;kvZI>ETr~tffGoeI?uyIr~QNI=9MO>)9kQF{eBZRj#Us zjta7tev*kd81-N5bJ`#9JHNx^4CKH??ETZTj}N*T#G=sw*2qpz|#xBo5Y-RLu` zvGalrBg4^o0e01T@zy-wvrd?u8{@W`)aILe7wq^T3y~gEbLxD&Khy;ymc5&!1d)Do zD`|#P?qs{C<==1R{-mjIzE8VTZVan+YB610vfByKRquwqME`3L3{hvNZEMd%l|g8y z+)NWze`eE!(_n@RNr9ro=_C`&bl-7w;8Z~UW#N0q14NerqJ$IFllxu_p~RM7td@nb zu#u-^%4>~y^MRU7_2cs$vTsE6{>zo99#XgV2lnzE)n5du>+QAVa~Ck&eXLtR-YuM)__PjfS8 zl*U*EU^M)94sF|Qsy`$AaFoO$d4l_x|500m74$> ziC_>V*tM&OfS=*@)LlegE_nCX;7RsY448L^kD}8_6%&J*`og6;&x)9BPp*>Q)uxG< z)3g40Npb7qrVQJx0DuFZ62RF=a6 #include <86box/nv/vid_nv3.h> -void nv3_class_001_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_001_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_002_rop.c b/src/video/nv/nv3/classes/nv3_class_002_rop.c index b771551d3..9286c180c 100644 --- a/src/video/nv/nv3/classes/nv3_class_002_rop.c +++ b/src/video/nv/nv3/classes/nv3_class_002_rop.c @@ -28,10 +28,13 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_002_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_002_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { + case NV3_ROP_SET_ROP: + nv3->pgraph.rop = param & 0xFF; + break; default: nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id); nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_INVALID_METHOD); diff --git a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c index 73901d08d..06750521e 100644 --- a/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c +++ b/src/video/nv/nv3/classes/nv3_class_003_chroma_key.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_003_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_003_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c b/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c index 48a96ab96..10788b5ce 100644 --- a/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c +++ b/src/video/nv/nv3/classes/nv3_class_004_plane_mask.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_004_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_004_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c b/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c index 1119147e7..8ba698aa5 100644 --- a/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c +++ b/src/video/nv/nv3/classes/nv3_class_005_clipping_rectangle.c @@ -27,10 +27,20 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_005_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_005_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { + case NV3_CLIP_POSITION: + nv3->pgraph.clip_start.x = (param >> 16) & 0xFFFF; + nv3->pgraph.clip_start.y = (param) & 0xFFFF; + nv_log("Clip Position: %d,%d", nv3->pgraph.clip_start.x, nv3->pgraph.clip_start.y); + break; + case NV3_CLIP_SIZE: + nv3->pgraph.clip_size.x = (param >> 16) & 0xFFFF; + nv3->pgraph.clip_size.y = (param) & 0xFFFF; + nv_log("Clip Size: %d,%d", nv3->pgraph.clip_start.x, nv3->pgraph.clip_start.y); + break; default: nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id); nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_INVALID_METHOD); diff --git a/src/video/nv/nv3/classes/nv3_class_006_pattern.c b/src/video/nv/nv3/classes/nv3_class_006_pattern.c index c8c81066f..ee3348669 100644 --- a/src/video/nv/nv3/classes/nv3_class_006_pattern.c +++ b/src/video/nv/nv3/classes/nv3_class_006_pattern.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_006_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_006_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c index 69e66ca31..dd82030ca 100644 --- a/src/video/nv/nv3/classes/nv3_class_007_rectangle.c +++ b/src/video/nv/nv3/classes/nv3_class_007_rectangle.c @@ -28,12 +28,41 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_007_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_007_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { + case NV3_RECTANGLE_COLOR: + nv3->pgraph.rectangle.color = param; + break; default: - nv_log("%s: Invalid or Unimplemented method 0x%04x", nv3_class_names[context.class_id & 0x1F], method_id); + /* Check for any rectangle point or size method. */ + if (method_id >= NV3_RECTANGLE_START && method_id <= NV3_RECTNAGLE_END) + { + uint32_t index = (method_id - NV3_RECTANGLE_START) / 8; + + // If the size is submitted, render it. + if (method_id & 0x04) + { + nv3->pgraph.rectangle.size[index].w = (param >> 16) & 0xFFFF; + nv3->pgraph.rectangle.size[index].h = param & 0xFFFF; + + nv_log("Rect%d Size=%d,%d\n", index, nv3->pgraph.rectangle.size[index].w, nv3->pgraph.rectangle.size[index].h); + + nv3_render_rect(nv3->pgraph.rectangle.position[index], nv3->pgraph.rectangle.size[index], nv3->pgraph.rectangle.color, grobj); + } + else // position + { + nv3->pgraph.rectangle.position[index].x = (param >> 16) & 0xFFFF; + nv3->pgraph.rectangle.position[index].y = param & 0xFFFF; + + nv_log("Rect%d Position=%d,%d\n", index, nv3->pgraph.rectangle.position[index].x, nv3->pgraph.rectangle.position[index].y); + } + + return; + } + + nv_log("%s: Invalid or Unimplemented method 0x%04x\n", nv3_class_names[context.class_id & 0x1F], method_id); nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_INVALID_METHOD); return; } diff --git a/src/video/nv/nv3/classes/nv3_class_008_point.c b/src/video/nv/nv3/classes/nv3_class_008_point.c index 0cd44b8cd..8647b27cb 100644 --- a/src/video/nv/nv3/classes/nv3_class_008_point.c +++ b/src/video/nv/nv3/classes/nv3_class_008_point.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_008_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_008_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_009_line.c b/src/video/nv/nv3/classes/nv3_class_009_line.c index 8d71f4d5e..dddbf5719 100644 --- a/src/video/nv/nv3/classes/nv3_class_009_line.c +++ b/src/video/nv/nv3/classes/nv3_class_009_line.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_009_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_009_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_00a_lin.c b/src/video/nv/nv3/classes/nv3_class_00a_lin.c index 141a2422c..45f1c97b9 100644 --- a/src/video/nv/nv3/classes/nv3_class_00a_lin.c +++ b/src/video/nv/nv3/classes/nv3_class_00a_lin.c @@ -29,7 +29,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_00a_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_00a_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_00b_triangle.c b/src/video/nv/nv3/classes/nv3_class_00b_triangle.c index 91cbaa837..e3bbf9f07 100644 --- a/src/video/nv/nv3/classes/nv3_class_00b_triangle.c +++ b/src/video/nv/nv3/classes/nv3_class_00b_triangle.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_00b_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_00b_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c index 3ba352b3c..66eddee71 100644 --- a/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c +++ b/src/video/nv/nv3/classes/nv3_class_00c_win95_gdi_text.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_00c_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c b/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c index 888ac89cf..687e1e763 100644 --- a/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c +++ b/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_00d_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_00d_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c b/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c index bf0286c20..f4bc8d6ee 100644 --- a/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c +++ b/src/video/nv/nv3/classes/nv3_class_00e_scaled_image_from_mem.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_00e_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_00e_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_010_blit.c b/src/video/nv/nv3/classes/nv3_class_010_blit.c index da2f16bda..c502bdd28 100644 --- a/src/video/nv/nv3/classes/nv3_class_010_blit.c +++ b/src/video/nv/nv3/classes/nv3_class_010_blit.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_010_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_010_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_011_image.c b/src/video/nv/nv3/classes/nv3_class_011_image.c index 4499693df..36679cb7f 100644 --- a/src/video/nv/nv3/classes/nv3_class_011_image.c +++ b/src/video/nv/nv3/classes/nv3_class_011_image.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_011_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_011_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_012_bitmap.c b/src/video/nv/nv3/classes/nv3_class_012_bitmap.c index ca8540b75..2ce3fb685 100644 --- a/src/video/nv/nv3/classes/nv3_class_012_bitmap.c +++ b/src/video/nv/nv3/classes/nv3_class_012_bitmap.c @@ -29,7 +29,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_012_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_012_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c b/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c index 6a18ff1d7..86be6a74a 100644 --- a/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c +++ b/src/video/nv/nv3/classes/nv3_class_014_transfer2memory.c @@ -29,7 +29,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_014_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_014_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c b/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c index c8560ad0f..5b499b73d 100644 --- a/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c +++ b/src/video/nv/nv3/classes/nv3_class_015_stretched_image_from_cpu.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_015_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_015_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c b/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c index 951ba862d..4f1e73774 100644 --- a/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c +++ b/src/video/nv/nv3/classes/nv3_class_017_d3d5_tri_zeta_buffer.c @@ -28,7 +28,7 @@ #include <86box/nv/vid_nv.h> #include <86box/nv/vid_nv3.h> -void nv3_class_017_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_017_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c b/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c index 80f10797f..4829fafb9 100644 --- a/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c +++ b/src/video/nv/nv3/classes/nv3_class_018_point_zeta_buffer.c @@ -30,7 +30,7 @@ struct nv3_object_class_018 nv3_d3d5_point_zeta_buffer; -void nv3_class_018_method(uint32_t name, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) +void nv3_class_018_method(uint32_t param, uint32_t method_id, nv3_ramin_context_t context, nv3_grobj_t grobj) { switch (method_id) { diff --git a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c index 30d6aee17..d55ee9511 100644 --- a/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c +++ b/src/video/nv/nv3/classes/nv3_class_01c_image_in_memory.c @@ -60,6 +60,7 @@ void nv3_class_01c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ /* Set the format */ nv3->pgraph.bpixel[src_buffer_id] = ((real_format & 0x03) | NV3_BPIXEL_FORMAT_IS_VALID); + nv_log("Image in Memory BUF%d COLOR_FORMAT=0x%04x", src_buffer_id, param); break; diff --git a/src/video/nv/nv3/classes/nv3_class_shared_methods.c b/src/video/nv/nv3/classes/nv3_class_shared_methods.c index 2f24daa41..38d45f70e 100644 --- a/src/video/nv/nv3/classes/nv3_class_shared_methods.c +++ b/src/video/nv/nv3/classes/nv3_class_shared_methods.c @@ -157,6 +157,7 @@ void nv3_notify_if_needed(uint32_t name, uint32_t method_id, nv3_ramin_context_t /* send the notification off */ nv_log("About to send hardware notification to 0x%08x (Check target)\n", final_address); + switch (info_notification_target) { case NV3_NOTIFICATION_TARGET_NVM: diff --git a/src/video/nv/nv3/render/nv3_render_core.c b/src/video/nv/nv3/render/nv3_render_core.c index 57df42b39..4dff864e0 100644 --- a/src/video/nv/nv3/render/nv3_render_core.c +++ b/src/video/nv/nv3/render/nv3_render_core.c @@ -35,3 +35,174 @@ uint32_t nv3_perform_rop(uint32_t src, uint32_t dst, uint32_t pattern, nv3_rende return video_rop_gdi_ternary(rop, dst, pattern, src); } +/* Expand a colour. + NOTE: THE GPU INTERNALLY OPERATES ON RGB10!!!!!!!!!!! +*/ +nv3_color_expanded_t nv3_render_expand_color(nv3_grobj_t grobj, uint32_t color) +{ + // grobj0 = seems to share the format of PGRAPH_CONTEXT_SWITCH register. + + uint8_t format = (grobj.grobj_0 & 0x07); + bool alpha_enabled = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_ALPHA) & 0x01; + + nv3_color_expanded_t color_final; + // set the pixel format + color_final.pixel_format = format; + + #ifdef ENABLE_NV_LOG + nv_log("Expanding Colour 0x%08x using pgraph_pixel_format 0x%x alpha enabled=%d", color, format, alpha_enabled); + #endif + + // default to fully opaque in case alpha is disabled + color_final.a = 0xFF; + + switch (format) + { + // ALL OF THESE TYPES ARE 32 BITS IN SIZE + + // 555 + case nv3_pgraph_pixel_format_r5g5b5: + nv3_color_16_a1r5g5b5_t new_color = *(nv3_color_16_a1r5g5b5_t*)&color; + // "stretch out" the colour + color_final.r = new_color.r * 0x20; + color_final.g = new_color.g * 0x20; + color_final.b = new_color.b * 0x20; + + if (alpha_enabled) + color_final.a = new_color.a; + + break; + // 888 (standard colour + 8-bit alpha) + case nv3_pgraph_pixel_format_r8g8b8: + if (alpha_enabled) + color_final.a = ((color >> 24) & 0xFF) * 4; + + color_final.r = ((color >> 16) & 0xFF) * 4; + color_final.g = ((color >> 8) & 0xFF) * 4; + color_final.b = (color & 0xFF) * 4; + + if (alpha_enabled) + color_final.a = new_color.a; + break; + case nv3_pgraph_pixel_format_r10g10b10: + nv3_color_x2a10g10b10_t new_color_rgb10 = *(nv3_color_x2a10g10b10_t*)&color; + + color_final.r = new_color_rgb10.r; + color_final.g = new_color_rgb10.g; + color_final.b = new_color_rgb10.b; + + if (alpha_enabled) + color_final.a = new_color.a; + + break; + case nv3_pgraph_pixel_format_y8: + color_final.a = (color >> 8) & 0xFF; + + // yuv + color_final.r = color_final.g = color_final.b = (color & 0xFF) * 4; // convert to rgb10 + break; + case nv3_pgraph_pixel_format_y16: + color_final.a = (color >> 16) & 0xFFFF; + + // yuv + color_final.r = color_final.g = color_final.b = (color & 0xFFFF) * 4; // convert to rgb10 + break; + default: + + } + + // i8 is a union under i16 + color_final.i16 = (color & 0xFFFF); + + return color_final; +} + +/* Convert expanded colour format to chroma key format */ +uint32_t nv3_render_to_chroma(nv3_color_expanded_t expanded) +{ + // convert the alpha to 1 bit. then return packed rgb10 + return !!expanded.a | (expanded.r << 30) | (expanded.b << 20) | (expanded.a << 10); +} + +/* Plots a pixel. */ +void nv3_render_pixel(nv3_position_16_t position, uint32_t color, nv3_grobj_t grobj) +{ + uint8_t alpha = 0xFF; + + // PFB_0 is always set to hardcoded "NO_TILING" value of 0x1114. + // It seems, you are meant to + + /* put this here for debugging + it may be needed later. */ + #ifdef DEBUG + uint8_t color_format_object = (grobj.grobj_0 >> NV3_PGRAPH_CONTEXT_SWITCH_COLOR_FORMAT) & 0x07; + #endif + uint32_t framebuffer_bpp = nv3->nvbase.svga.bpp; // maybe y16 too? + uint32_t current_buffer = (nv3->pgraph.context_switch >> NV3_PGRAPH_CONTEXT_SWITCH_SRC_BUFFER) & 0x03; + + /* doesn't seem*/ + nv3_color_argb_t color_data = *(nv3_color_argb_t*)&color; + + if (framebuffer_bpp == 32) + alpha = color_data.a; + + int32_t clip_end_x = nv3->pgraph.clip_start.x + nv3->pgraph.clip_size.x; + int32_t clip_end_y = nv3->pgraph.clip_start.y + nv3->pgraph.clip_size.y; + + /* First, check our current buffer. */ + /* Then do the clip. */ + if (position.x < nv3->pgraph.clip_start.x + || position.y < nv3->pgraph.clip_start.y + || position.x > clip_end_x + || position.y > clip_end_y) + { + // DO NOT DRAW THE PIXEL + return; + } + + /* TODO: Chroma Key, Pattern, Plane Mask...*/ + + /* Combine the current buffer with the pitch to get the address in the framebuffer to draw from. */ + uint32_t pixel_addr_vram = position.x + (nv3->pgraph.bpitch[current_buffer]) * position.y + nv3->pgraph.boffset[current_buffer]; + + pixel_addr_vram &= nv3->nvbase.svga.vram_mask; + + /* Go to vram and do the final ROP for a basic bitblit. + It seems we can skip the downconversion step *for now*, since (framebuffer bits per pixel) == (object bits per pixel) + I'm not sure how games will react. But it depends on how the D3D drivers operate, we may need ro convert texture formats to the current bpp internally. + + TODO: MOVE TO BPIXEL DEPTH or GROBJ0 to determine this, once we figure out how to get the bpixel depth. + */ + + uint32_t src = 0, dst = 0; + + switch (framebuffer_bpp) + { + case 8: + src = color & 0xFF; + dst = nv3->nvbase.svga.vram[pixel_addr_vram]; + nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00); + + break; + case 16: + uint16_t* vram_16 = (uint16_t*)(nv3->nvbase.svga.vram); + pixel_addr_vram >>= 1; + + src = color & 0xFFFF; + dst = vram_16[pixel_addr_vram]; + nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00); + + break; + case 32: + uint32_t* vram_32 = (uint32_t*)(nv3->nvbase.svga.vram); + pixel_addr_vram >>= 2; + + src = color; + dst = vram_32[pixel_addr_vram]; + nv3->nvbase.svga.vram[pixel_addr_vram] = video_rop_gdi_ternary(nv3->pgraph.rop, src, dst, 0x00); + + break; + } + + nv3->nvbase.svga.changedvram[pixel_addr_vram >> 12] = changeframecount; + +} \ No newline at end of file diff --git a/src/video/nv/nv3/render/nv3_render_primitives.c b/src/video/nv/nv3/render/nv3_render_primitives.c new file mode 100644 index 000000000..e44636acb --- /dev/null +++ b/src/video/nv/nv3/render/nv3_render_primitives.c @@ -0,0 +1,46 @@ +/* +* 86Box A hypervisor and IBM PC system emulator that specializes in +* running old operating systems and software designed for IBM +* PC systems and compatibles from 1981 through fairly recent +* system designs based on the PCI bus. +* +* This file is part of the 86Box distribution. +* +* NV3 code to render basic objects. +* +* +* +* Authors: Connor Hyde, I need a better email address ;^) +* +* Copyright 2024-2025 Connor Hyde +*/ + +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/mem.h> +#include <86box/pci.h> +#include <86box/rom.h> +#include <86box/video.h> +#include <86box/nv/vid_nv.h> +#include <86box/nv/vid_nv3.h> +#include <86box/utils/video_stdlib.h> + +void nv3_render_rect(nv3_position_16_t position, nv3_size_16_t size, uint32_t color, nv3_grobj_t grobj) +{ + nv3_position_16_t current_pos = {0}; + + for (int32_t y = position.y; y < (position.y + size.h); y++) + { + current_pos.y = y; + for (int32_t x = position.x; x < (position.x + size.w); x++) + { + current_pos.x = x; + + nv3_render_pixel(current_pos, color, grobj); + } + } +} \ No newline at end of file