From 0e16ef5498562655c150825be4e543f69bf93ce6 Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Sat, 29 Mar 2025 23:25:15 +0000 Subject: [PATCH] Implemented a dummy M2MF class implementation until I fully understand it. This is enough to get Windows 9x to display something. --- .../86box/nv/classes/vid_nv3_classes.h | 24 ++++++++- .../nv/nv3/classes/nv3_class_003_chroma_key.c | 7 +++ .../classes/nv3_class_00c_win95_gdi_text.c | 2 +- src/video/nv/nv3/classes/nv3_class_00d_m2mf.c | 51 ++++++++++++++++++- 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/include/86box/nv/classes/vid_nv3_classes.h b/src/include/86box/nv/classes/vid_nv3_classes.h index 0503c0c66..4f52bf789 100644 --- a/src/include/86box/nv/classes/vid_nv3_classes.h +++ b/src/include/86box/nv/classes/vid_nv3_classes.h @@ -84,6 +84,8 @@ typedef enum nv3_pgraph_class_e #define NV3_BETA_FACTOR 0x0300 // Chroma Key +// Can't figure out what this is, used in 9x but certainly software, can't find anywhere... +#define NV3_CHROMA_UNKNOWN_0200 0x0200 #define NV3_CHROMA_KEY 0x0304 // Clip @@ -114,6 +116,25 @@ typedef enum nv3_pgraph_class_e #define NV3_RECTANGLE_MAX 16 #define NV3_RECTANGLE_END 0x0480 +// M2MF +#define NV3_M2MF_IN_CTXDMA_OFFSET 0x030C +#define NV3_M2MF_OUT_CTXDMA_OFFSET 0x0310 +#define NV3_M2MF_IN_PITCH 0x0314 +#define NV3_M2MF_OUT_PITCH 0x0318 +#define NV3_M2MF_SCANLINE_LENGTH_IN_BYTES 0x031C +#define NV3_M2MF_NUM_SCANLINES 0x0320 +#define NV3_M2MF_FORMAT 0x0324 + +// M2MF formats (IN and OUT ORed together) +#define NV3_M2MF_FORMAT_INPUT_INC_1 0x1 +#define NV3_M2MF_FORMAT_INPUT_INC_2 0x2 +#define NV3_M2MF_FORMAT_INPUT_INC_4 0x4 +#define NV3_M2MF_FORMAT_OUTPUT_INC_1 0x100 +#define NV3_M2MF_FORMAT_OUTPUT_INC_2 0x200 +#define NV3_M2MF_FORMAT_OUTPUT_INC_4 0x400 + +#define NV3_M2MF_NOTIFY 0x0328 + // blit #define NV3_BLIT_POSITION_IN 0x0300 #define NV3_BLIT_POSITION_OUT 0x0304 @@ -634,8 +655,7 @@ typedef struct nv3_object_class_00D uint32_t pitch_out; uint32_t line_length_in; // Stride? uint32_t line_count; - uint8_t format_input_bits; // 1 2 or 4 to increment by bits - uint8_t format_output_bits; // 1 2 to 4 to increment by bits + uint8_t format; // input increment 1 2 or 4, output increment 1 2 or 4 (represented by << 8) uint8_t reserved3[2]; uint32_t buffer_notify; // Notify the Buffedr uint8_t reserved4[0x1CD3]; 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 f2e575933..139099e78 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 @@ -32,10 +32,17 @@ void nv3_class_003_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ { switch (method_id) { + case NV3_CHROMA_UNKNOWN_0200: + nv_log("Method Execution: Chroma Unknown 0x0200 0x%08x", param); + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_SOFTWARE_METHOD_PENDING); + + break; case NV3_CHROMA_KEY: nv3_color_expanded_t expanded_color = nv3_render_expand_color(param, grobj); nv3->pgraph.chroma_key = nv3_render_to_chroma(expanded_color); + + nv_log("Method Execution: Chroma = 0x%08x", nv3->pgraph.chroma_key); break; default: warning("%s: Invalid or unimplemented method 0x%04x\n", nv3_class_names[context.class_id & 0x1F], 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 30926020a..e006c41f3 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 @@ -192,7 +192,7 @@ void nv3_class_00c_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ return; } - warning("%s: Invalid or unimplemented method 0x%04x\n", nv3_class_names[context.class_id & 0x1F], method_id); + 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_SOFTWARE_METHOD_PENDING); break; } 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 fd8f0d5f2..b75a8e546 100644 --- a/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c +++ b/src/video/nv/nv3/classes/nv3_class_00d_m2mf.c @@ -32,9 +32,58 @@ void nv3_class_00d_method(uint32_t param, uint32_t method_id, nv3_ramin_context_ { switch (method_id) { + case NV3_M2MF_IN_CTXDMA_OFFSET: + nv3->pgraph.m2mf.offset_in = param; + nv_log("Method Execution: M2MF Offset In = 0x%08x", param); + break; + case NV3_M2MF_OUT_CTXDMA_OFFSET: + nv3->pgraph.m2mf.offset_out = param; + nv_log("Method Execution: M2MF Offset Out = 0x%08x", param); + break; + case NV3_M2MF_IN_PITCH: + nv3->pgraph.m2mf.pitch_in = param; + nv_log("Method Execution: M2MF Pitch In = 0x%08x", param); + break; + case NV3_M2MF_OUT_PITCH: + nv3->pgraph.m2mf.pitch_out = param; + nv_log("Method Execution: M2MF Pitch Out = 0x%08x", param); + break; + case NV3_M2MF_SCANLINE_LENGTH_IN_BYTES: + nv3->pgraph.m2mf.line_length_in = param; + nv_log("Method Execution: M2MF Scanline Length in Bytes = 0x%08x", param); + break; + case NV3_M2MF_NUM_SCANLINES: + nv3->pgraph.m2mf.line_count = param; + nv_log("Method Execution: M2MF Num Scanlines = 0x%08x", param); + break; + case NV3_M2MF_FORMAT: + nv3->pgraph.m2mf.format = param; + nv_log("Method Execution: M2MF Format = 0x%08x", param); + break; + case NV3_M2MF_NOTIFY: + /* This is technically its own thing, but I don't know if it's ever a problem with how we've designed it */ + if (nv3->pgraph.notify_pending) + { + nv_log("M2MF notification with notify_pending already set. param=0x%08x, method=0x%04x, grobj=0x%08x 0x%08x 0x%08x 0x%08x\n"); + nv_log("IF THIS IS A DEBUG BUILD, YOU SHOULD SEE A CONTEXT BELOW"); + nv3_debug_ramin_print_context_info(param, context); + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_DOUBLE_NOTIFY); + + // disable + nv3->pgraph.notify_pending = false; + nv3_pgraph_interrupt_invalid(NV3_PGRAPH_INTR_1_DOUBLE_NOTIFY); + /* may need to disable fifo in this state */ + return; + } + + nv_log("Method Execution: TODO: ACTUALLY IMPLEMENT M2MF!!!!"); + // set a notify as pending. + nv3->pgraph.notifier = param; + nv3->pgraph.notify_pending = true; + break; default: warning("%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_SOFTWARE_METHOD_PENDING); - return; + break;; } } \ No newline at end of file