diff --git a/doc/nvidia_notes/status.xlsx b/doc/nvidia_notes/status.xlsx index 0b76f7036..e23fe6c72 100644 Binary files a/doc/nvidia_notes/status.xlsx and b/doc/nvidia_notes/status.xlsx differ diff --git a/src/include/86box/nv/render/vid_nv3_render.h b/src/include/86box/nv/render/vid_nv3_render.h index fd76042d6..65541fa0d 100644 --- a/src/include/86box/nv/render/vid_nv3_render.h +++ b/src/include/86box/nv/render/vid_nv3_render.h @@ -40,4 +40,5 @@ bool nv3_render_chroma_test(nv3_grobj_t grobj, uint32_t color); void nv3_render_blit_screen2screen(nv3_grobj_t grobj); /* GDI */ -void nv3_render_gdi_type_d(nv3_grobj_t grobj, uint32_t param); \ No newline at end of file +void nv3_render_gdi_type_d(nv3_grobj_t grobj, uint32_t param); /* GDI Type-D: Clipped 1bpp text */ +void nv3_render_gdi_type_e(nv3_grobj_t grobj, uint32_t param); /* GDI Type-E: Clipped 1bpp two-colour text */ \ No newline at end of file diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index 78cc3953a..e70a0bec6 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -1233,7 +1233,7 @@ typedef struct nv3_pgraph_s struct nv3_object_class_00E scaled_image_from_memory; struct nv3_object_class_010 blit; struct nv3_object_class_011 image; - nv3_position_16_t image_current_position; /* This is here so we can hold the current state of the image */ + nv3_position_16_t image_current_position; /* This is here so we can hold the current state of the image */ struct nv3_object_class_012 bitmap; struct nv3_object_class_014 transfer2memory; struct nv3_object_class_015 stretched_image_from_cpu; 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 dcad8b088..8d126e6cc 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 @@ -66,17 +66,52 @@ void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ /* small case*/ if (nv3->pgraph.win95_gdi_text.size_in_d.w < 0x0010) { - nv3->pgraph.win95_gdi_text_current_position.x = (nv3->pgraph.win95_gdi_text.point_d.x + nv3->pgraph.win95_gdi_text.size_in_d.w); + nv3->pgraph.win95_gdi_text_current_position.x = (nv3->pgraph.win95_gdi_text.point_d.x + (nv3->pgraph.win95_gdi_text.size_in_d.w - 1)); nv3->pgraph.win95_gdi_text_current_position.y = (nv3->pgraph.win95_gdi_text.point_d.y); } /* large case: draw (7-0) (15-8)*/ else { - uint16_t large_start = (nv3->pgraph.win95_gdi_text.size_in_d.w >> 1) ; + uint16_t large_start = (nv3->pgraph.win95_gdi_text.size_in_d.w >> 1) - 1; nv3->pgraph.win95_gdi_text_current_position.x = (nv3->pgraph.win95_gdi_text.point_d.x + large_start); nv3->pgraph.win95_gdi_text_current_position.y = (nv3->pgraph.win95_gdi_text.point_d.y); } + break; + /* Type E: Two-colour 1bpp */ + case NV3_W95TXT_E_CLIP_TOPLEFT: + nv3->pgraph.win95_gdi_text.clip_e.left = (param & 0xFFFF); + nv3->pgraph.win95_gdi_text.clip_e.top = ((param >> 16) & 0xFFFF); + break; + case NV3_W95TXT_E_CLIP_BOTTOMRIGHT: + nv3->pgraph.win95_gdi_text.clip_e.right = (param & 0xFFFF); + nv3->pgraph.win95_gdi_text.clip_e.bottom = ((param >> 16) & 0xFFFF); + /* is it "only if we are out of the top left or the bottom right or is it "all of them"*/ + break; + case NV3_W95TXT_E_CLIP_COLOR_0: + nv3->pgraph.win95_gdi_text.color0_e = param; + break; + case NV3_W95TXT_E_CLIP_COLOR_1: + nv3->pgraph.win95_gdi_text.color1_e = param; + break; + case NV3_W95TXT_E_CLIP_SIZE_IN: + nv3->pgraph.win95_gdi_text.size_in_e.w = (param & 0xFFFF); + nv3->pgraph.win95_gdi_text.size_in_e.h = ((param >> 16) & 0xFFFF); + break; + case NV3_W95TXT_E_CLIP_SIZE_OUT: + nv3->pgraph.win95_gdi_text.size_out_e.w = (param & 0xFFFF); + nv3->pgraph.win95_gdi_text.size_out_e.h = ((param >> 16) & 0xFFFF); + break; + case NV3_W95TXT_E_CLIP_POSITION: + nv3->pgraph.win95_gdi_text.point_e.x = (param & 0xFFFF); + nv3->pgraph.win95_gdi_text.point_e.y = ((param >> 16) & 0xFFFF); + + uint16_t large_start = (nv3->pgraph.win95_gdi_text.size_in_e.w >> 1) - 1; + + //nv3->pgraph.win95_gdi_text_current_position.x = (nv3->pgraph.win95_gdi_text.point_e.x + large_start); + nv3->pgraph.win95_gdi_text_current_position.x = nv3->pgraph.win95_gdi_text.point_e.x; + nv3->pgraph.win95_gdi_text_current_position.y = (nv3->pgraph.win95_gdi_text.point_e.y); + break; default: /* Type A submission: these are the same things as rectangles */ @@ -124,6 +159,24 @@ void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ nv3_render_gdi_type_d(grobj, nv3->pgraph.win95_gdi_text.mono_color1_d[index]); return; } + else if (method_id >= NV3_W95TXT_E_CLIP_CLIPRECT_START && method_id <= NV3_W95TXT_E_CLIP_CLIPRECT_END) + { + /* lol */ + uint32_t index = (method_id - NV3_W95TXT_E_CLIP_CLIPRECT_START) >> 3; + + nv3->pgraph.win95_gdi_text.mono_color1_d[index] = param; + + /* Mammoth logger! */ + nv_log("Rect GDI-E%d Data=%08x SizeIn%04x,%04x SizeOut%04x,%04x Point%04x,%04x Color=%08x Clip Left=0x%04x Right=0x%04x Top=0x%04x Bottom=0x%04x", + index, param, nv3->pgraph.win95_gdi_text.size_in_e.w, nv3->pgraph.win95_gdi_text.size_in_e.h, + nv3->pgraph.win95_gdi_text.size_out_e.w, nv3->pgraph.win95_gdi_text.size_out_e.h, + nv3->pgraph.win95_gdi_text.point_e.x, nv3->pgraph.win95_gdi_text.point_e.y, + nv3->pgraph.win95_gdi_text.color1_e, + nv3->pgraph.win95_gdi_text.clip_e.left, nv3->pgraph.win95_gdi_text.clip_e.right, nv3->pgraph.win95_gdi_text.clip_e.top, nv3->pgraph.win95_gdi_text.clip_e.bottom); + + nv3_render_gdi_type_e(grobj, nv3->pgraph.win95_gdi_text.mono_color1_d[index]); + return; + } 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_SOFTWARE_METHOD_PENDING); diff --git a/src/video/nv/nv3/render/nv3_render_primitives.c b/src/video/nv/nv3/render/nv3_render_primitives.c index 49684edc3..6190040a5 100644 --- a/src/video/nv/nv3/render/nv3_render_primitives.c +++ b/src/video/nv/nv3/render/nv3_render_primitives.c @@ -55,32 +55,37 @@ void nv3_render_text_1bpp(bool bit, nv3_grobj_t grobj) if (nv3->pgraph.win95_gdi_text_current_position.y >= clip_y) bit = false; + uint32_t final_color; + // if it's a 0 bit we don't need to do anything if (bit) { switch (nv3->nvbase.svga.bpp) { case 8: - uint32_t final_color8 = (nv3->pgraph.win95_gdi_text.color1_d & 0xFF); /* do we need to add anything? mul blend perhaps? */ - nv3_render_write_pixel(nv3->pgraph.win95_gdi_text_current_position, final_color8, grobj); + final_color = (nv3->pgraph.win95_gdi_text.color1_d & 0xFF); /* do we need to add anything? mul blend perhaps? */ break; case 16: - uint32_t final_color16 = (nv3->pgraph.win95_gdi_text.color1_d & 0xFFFF); /* do we need to add anything? mul blend perhaps? */ - nv3_render_write_pixel(nv3->pgraph.win95_gdi_text_current_position, final_color16, grobj); + final_color = (nv3->pgraph.win95_gdi_text.color1_d & 0xFFFF); /* do we need to add anything? mul blend perhaps? */ break; case 32: - uint32_t final_color32 = (nv3->pgraph.win95_gdi_text.color1_d); /* do we need to add anything? mul blend perhaps? */ - nv3_render_write_pixel(nv3->pgraph.win95_gdi_text_current_position, final_color32, grobj); + final_color = (nv3->pgraph.win95_gdi_text.color1_d); /* do we need to add anything? mul blend perhaps? */ break; } } + /* in type d colour0 is always transparent */ + if (bit) + nv3_render_write_pixel(nv3->pgraph.win95_gdi_text_current_position, final_color, grobj); + /* increment the position - the bitmap is stored horizontally backward */ nv3->pgraph.win95_gdi_text_current_position.x--; - if (nv3->pgraph.win95_gdi_text_current_position.x <= nv3->pgraph.win95_gdi_text.point_d.x) + /* check if we need to go down a line */ + if (nv3->pgraph.win95_gdi_text_current_position.x < nv3->pgraph.win95_gdi_text.point_d.x) { - nv3->pgraph.win95_gdi_text_current_position.x = nv3->pgraph.win95_gdi_text.point_d.x + nv3->pgraph.win95_gdi_text.size_in_d.w; + nv3->pgraph.win95_gdi_text_current_position.x = (nv3->pgraph.win95_gdi_text.point_d.x + nv3->pgraph.win95_gdi_text.size_in_d.w - 1); + nv3->pgraph.win95_gdi_text_current_position.y++; } @@ -92,7 +97,6 @@ void nv3_render_text_1bpp(bool bit, nv3_grobj_t grobj) { return; } - } void nv3_render_gdi_type_d(nv3_grobj_t grobj, uint32_t param) @@ -100,8 +104,6 @@ void nv3_render_gdi_type_d(nv3_grobj_t grobj, uint32_t param) // reset when a position is submitted nv3_position_16_t start_position = nv3->pgraph.win95_gdi_text_current_position; - // is this clip or point? - /* Go through the bitmap that was sent, bit by bit. */ for (int32_t bit_num = 0; bit_num <= 31; bit_num++) { @@ -109,4 +111,77 @@ void nv3_render_gdi_type_d(nv3_grobj_t grobj, uint32_t param) nv3_render_text_1bpp(bit, grobj); } +} + +/* 2-colour 1bpp color-expanded text from [7-0] */ +void nv3_render_text_1bpp_2color(uint8_t byte, nv3_grobj_t grobj) +{ + for (int32_t bit_num = 0; bit_num <= 7; bit_num++) + { + bool bit = (byte >> bit_num) & 0x01; + + uint16_t clip_x = nv3->pgraph.win95_gdi_text.point_e.x + nv3->pgraph.win95_gdi_text.size_out_e.w; + uint16_t clip_y = nv3->pgraph.win95_gdi_text.point_e.y + nv3->pgraph.win95_gdi_text.size_out_e.h; + + /* they send more data than they need */ + if (nv3->pgraph.win95_gdi_text_current_position.y >= clip_y) + bit = false; + + // if it's a 0 bit we don't need to do anything + + uint32_t final_color; + + switch (nv3->nvbase.svga.bpp) + { + case 8: + final_color = (bit) ? (nv3->pgraph.win95_gdi_text.color1_e & 0xFF) : (nv3->pgraph.win95_gdi_text.color0_e & 0xFF); /* do we need to add anything? mul blend perhaps? */ + break; + case 16: + final_color = (bit) ? (nv3->pgraph.win95_gdi_text.color1_e & 0xFFFF) : (nv3->pgraph.win95_gdi_text.color0_e & 0xFFFF); /* do we need to add anything? mul blend perhaps? */ + break; + case 32: + final_color = (bit) ? nv3->pgraph.win95_gdi_text.color1_e : nv3->pgraph.win95_gdi_text.color0_e; /* do we need to add anything? mul blend perhaps? */ + break; + } + + nv3_render_write_pixel(nv3->pgraph.win95_gdi_text_current_position, final_color, grobj); + + /* increment the position - the bitmap is stored horizontally backward */ + nv3->pgraph.win95_gdi_text_current_position.x--; + + /* see if we need to go to the next line */ + if (nv3->pgraph.win95_gdi_text_current_position.x < nv3->pgraph.win95_gdi_text.point_e.x) + { + nv3->pgraph.win95_gdi_text_current_position.x = nv3->pgraph.win95_gdi_text.point_e.x + (nv3->pgraph.win95_gdi_text.size_in_e.w - 1); + nv3->pgraph.win95_gdi_text_current_position.y++; + } + + /* check if we are in the clipping rectangle */ + if (nv3->pgraph.win95_gdi_text_current_position.x < nv3->pgraph.win95_gdi_text.clip_e.left + || nv3->pgraph.win95_gdi_text_current_position.x > nv3->pgraph.win95_gdi_text.clip_e.right + || nv3->pgraph.win95_gdi_text_current_position.y < nv3->pgraph.win95_gdi_text.clip_e.top + || nv3->pgraph.win95_gdi_text_current_position.y > nv3->pgraph.win95_gdi_text.clip_e.bottom) + { + return; + } + } + + +} + +void nv3_render_gdi_type_e(nv3_grobj_t grobj, uint32_t param) +{ + // reset when a position is submitted + nv3_position_16_t start_position = nv3->pgraph.win95_gdi_text_current_position; + + /* we have to interpret every bit in reverse order but in the right bit order */ + uint8_t byte0 = ((param & 0xFF000000) >> 24); + uint8_t byte1 = ((param & 0xFF0000) >> 16); + uint8_t byte2 = ((param & 0xFF00) >> 8); + uint8_t byte3 = (param & 0xFF); + + nv3_render_text_1bpp_2color(byte0, grobj); + nv3_render_text_1bpp_2color(byte1, grobj); + nv3_render_text_1bpp_2color(byte2, grobj); + nv3_render_text_1bpp_2color(byte3, grobj); } \ No newline at end of file