diff --git a/src/include/86box/nv/vid_nv3.h b/src/include/86box/nv/vid_nv3.h index 98e60ee72..7b037c41c 100644 --- a/src/include/86box/nv/vid_nv3.h +++ b/src/include/86box/nv/vid_nv3.h @@ -618,6 +618,17 @@ extern const device_config_t nv3_config[]; #define NV3_PGRAPH_CLASS1C_MEM2IMAGE_START 0x5C0000 // class 55, 56, 62, 63? #define NV3_PGRAPH_CLASS1C_MEM2IMAGE_END 0x5C1FFF +/* + OBJECT METHODS +*/ + +// Global stuff +#define NV3_ROOT_HI_IM_OBJECT_MCOBJECTYFACE 0x0 // I'm going insane at 00:48 14/02/2025 +#define NV3_SET_NOTIFY_CONTEXT_FOR_DMA 0x100 // Set object ctx for dma...see nv3_dma_context_t structure +#define NV3_SET_NOTIFY 0x104 + +#define NV3_W95TXT_COLORA 0x3FC // It's the colour of the text. This is used to submit a dummy object so the notifier can be used to sync in Win2000 DDraw6 drivers. + #define NV3_PGRAPH_REGISTER_END 0x401FFF // end of pgraph registers #define NV3_PGRAPH_REAL_END 0x5C1FFF @@ -724,9 +735,6 @@ extern const device_config_t nv3_config[]; // not done -// Master Control - - // CRTC/CIO (0x3b0-0x3df) #define NV3_CRTC_DATA_OUT 0x3C0 @@ -810,6 +818,8 @@ extern const device_config_t nv3_config[]; #define NV3_CRTC_REGISTER_RMA_MODE_MAX 0x0F + + /* STRUCTURES FOR THE GPU START HERE OBJECT CLASS & RENDERING RELATED STUFF IS IN VID_NV3_CLASSES.H @@ -1358,9 +1368,9 @@ bool nv3_ramin_arbitrate_write(uint32_t address, uint32_t value); / // RAMIN functions uint32_t nv3_ramht_hash(uint32_t name, uint32_t channel); -bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint32_t channel_id, uint32_t subchannel_id); +bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel_id, uint8_t subchannel_id); #ifndef RELEASE_BUILD -void nv3_debug_ramin_print_context_info(uint32_t name, nv3_ramin_context_t context); +void nv3_debug_ramin_print_context_info(uint32_t name, nv3_ramin_context_t context); #endif uint32_t nv3_ramfc_read(uint32_t address); 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 dd6c49fed..39f7e2b81 100644 --- a/src/video/nv/nv3/classes/nv3_class_shared_methods.c +++ b/src/video/nv/nv3/classes/nv3_class_shared_methods.c @@ -32,4 +32,9 @@ void nv3_generic_method(uint32_t method_id, nv3_grobj_t grobj) { +} + +void nv3_notify() +{ + } \ No newline at end of file diff --git a/src/video/nv/nv3/subsystems/nv3_pfifo.c b/src/video/nv/nv3/subsystems/nv3_pfifo.c index 6e7a4c453..a6252f3b7 100644 --- a/src/video/nv/nv3/subsystems/nv3_pfifo.c +++ b/src/video/nv/nv3/subsystems/nv3_pfifo.c @@ -500,13 +500,13 @@ Back to sanity uint32_t nv3_pfifo_cache1_gray2normal(uint32_t val) { uint32_t mask = val >> 1; - + // shift right until we have our normla number again while (mask) { - // NT4 drivers v1.29 do this the other way around?? - val ^= mask; + // Algorithm from NT4 drivers, version 1.29 mask >>= 1; + val ^= mask; } return val; @@ -530,11 +530,11 @@ void nv3_pfifo_cache0_pull() return; // There is only one entry for cache0 - uint16_t current_channel = nv3->pfifo.cache0_settings.channel; - uint32_t current_subchannel = nv3->pfifo.cache0_entry.subchannel; + uint8_t current_channel = nv3->pfifo.cache0_settings.channel; + uint8_t current_subchannel = nv3->pfifo.cache0_entry.subchannel; uint32_t current_name = nv3->pfifo.cache0_entry.data; - uint32_t current_method = nv3->pfifo.cache0_entry.method; - + uint16_t current_method = nv3->pfifo.cache0_entry.method; + // i.e. there is no method in cache0, so we have to find the object. if (!current_method) { @@ -543,6 +543,7 @@ void nv3_pfifo_cache0_pull() } uint32_t current_context = nv3->pfifo.cache0_settings.context[0]; // only 1 entry for CACHE0 so basically ignore the other context entries? + uint8_t class_id = ((nv3_ramin_context_t*)¤t_context)->class_id; // Tell the CPU if we found a software method if (current_context & 0x800000) @@ -594,6 +595,8 @@ void nv3_pfifo_cache1_push(uint32_t addr, uint32_t val) { oh_shit = true; oh_shit_reason = nv3_runout_reason_no_cache_available; + new_address |= (nv3_runout_reason_no_cache_available << NV3_PFIFO_RUNOUT_RAMIN_ERR); + } // Check if runout is full @@ -627,7 +630,7 @@ void nv3_pfifo_cache1_push(uint32_t addr, uint32_t val) { // Cache reassignment required if (!nv3->pfifo.cache_reassignment - || (nv3->pfifo.cache0_settings.get_address != nv3->pfifo.cache0_settings.get_address)) + || (nv3->pfifo.cache1_settings.get_address != nv3->pfifo.cache1_settings.get_address)) { oh_shit = true; oh_shit_reason = nv3_runout_reason_no_cache_available; @@ -654,13 +657,13 @@ void nv3_pfifo_cache1_push(uint32_t addr, uint32_t val) uint32_t next_put_address = nv3_pfifo_cache1_gray2normal(current_put_address) + 1; if (nv3->nvbase.gpu_revision >= NV3_BOOT_REG_REV_C00) // RIVA 128ZX# - next_put_address &= NV3_PFIFO_CACHE1_SIZE_REV_C; + next_put_address &= (NV3_PFIFO_CACHE1_SIZE_REV_C - 1); else - next_put_address &= NV3_PFIFO_CACHE1_SIZE_REV_AB; + next_put_address &= (NV3_PFIFO_CACHE1_SIZE_REV_AB - 1); - nv3->pfifo.cache1_settings.put_address = nv3_pfifo_cache1_normal2gray(next_put_address); + nv3->pfifo.cache1_settings.put_address = nv3_pfifo_cache1_normal2gray(next_put_address) << 2; - nv_log("Submitted object [PIO]: Channel %d, Subchannel %d, Method ID 0x%04x (Put Address is now %d)\n", + nv_log("Submitted object [PIO]: Channel %d.%d, Method ID 0x%04x (Put Address is now %d)\n", channel, subchannel, method_offset, nv3->pfifo.cache1_settings.put_address); // Now we're done. Phew! @@ -679,25 +682,27 @@ void nv3_pfifo_cache1_pull() uint32_t get_address = nv3->pfifo.cache1_settings.get_address >> 2; // 32 bit aligned probably - uint16_t current_channel = nv3->pfifo.cache1_settings.channel; - uint32_t current_subchannel = nv3->pfifo.cache1_entries[get_address].subchannel; + uint8_t current_channel = nv3->pfifo.cache1_settings.channel; + uint8_t current_subchannel = nv3->pfifo.cache1_entries[get_address].subchannel; uint32_t current_name = nv3->pfifo.cache1_entries[get_address].data; - uint32_t current_method = nv3->pfifo.cache1_entries[get_address].method; + uint16_t current_method = nv3->pfifo.cache1_entries[get_address].method; - // i.e. there is no method in cache0, so we have to find the object. + // i.e. there is no method in cache1, so we have to find the object. if (!current_method) { if (!nv3_ramin_find_object(current_name, 0, current_channel, current_subchannel)) return; // interrupt was fired, and we went to ramro } - uint32_t current_context = nv3->pfifo.cache0_settings.context[current_subchannel]; // only 1 entry for CACHE0 so basically ignore the other context entries? + uint32_t current_context = nv3->pfifo.cache1_settings.context[current_subchannel]; // get the current subchannel + + uint8_t class_id = ((nv3_ramin_context_t*)¤t_context)->class_id; // Tell the CPU if we found a software method if (current_context & 0x800000) { - nv3->pfifo.cache0_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; - nv3->pfifo.cache0_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; + nv3->pfifo.cache1_settings.puller_control |= NV3_PFIFO_CACHE0_PULLER_CONTROL_SOFTWARE_METHOD; + nv3->pfifo.cache1_settings.puller_control &= ~NV3_PFIFO_CACHE0_PULLER_CONTROL_ENABLED; nv3_pfifo_interrupt(NV3_PFIFO_INTR_CACHE_ERROR, true); } @@ -705,12 +710,12 @@ void nv3_pfifo_cache1_pull() uint32_t next_get_address = nv3_pfifo_cache1_gray2normal(get_address) + 1; if (nv3->nvbase.gpu_revision >= NV3_BOOT_REG_REV_C00) // RIVA 128ZX# - next_get_address &= NV3_PFIFO_CACHE1_SIZE_REV_C; + next_get_address &= (NV3_PFIFO_CACHE1_SIZE_REV_C - 1); else - next_get_address &= NV3_PFIFO_CACHE1_SIZE_REV_AB; + next_get_address &= (NV3_PFIFO_CACHE1_SIZE_REV_AB - 1); // Is this needed? - nv3->pfifo.cache0_settings.get_address = nv3_pfifo_cache1_normal2gray(next_get_address) << 2; + nv3->pfifo.cache1_settings.get_address = nv3_pfifo_cache1_normal2gray(next_get_address) << 2; #ifndef RELEASE_BUILD nv_log("***** OBJECT PULLED, SUBMITTING GRAPHICS COMMANDS CURRENTLY UNIMPLEMENTED - ****** Contextual information below\n"); diff --git a/src/video/nv/nv3/subsystems/nv3_pgraph.c b/src/video/nv/nv3/subsystems/nv3_pgraph.c index 85ad21cff..212980c8a 100644 --- a/src/video/nv/nv3/subsystems/nv3_pgraph.c +++ b/src/video/nv/nv3/subsystems/nv3_pgraph.c @@ -468,7 +468,16 @@ void nv3_pgraph_vblank_start(svga_t* svga) nv3_pgraph_interrupt_valid(NV3_PGRAPH_INTR_EN_0_VBLANK); } -void nv3_pgraph_submit() +/* Arbitrates graphics object submission to the right object types */ +void nv3_pgraph_submit(uint8_t name, uint16_t method, uint8_t channel, uint8_t subchannel, uint8_t class_id, uint32_t context) { + // class id can be derived from the context but we debug log it before we get here + switch (method) + { + // This method is how we figure out which methods exist. + case NV3_ROOT_HI_IM_OBJECT_MCOBJECTYFACE: + nv_log("Hi, I'm an NV []"); + break; + } } \ No newline at end of file diff --git a/src/video/nv/nv3/subsystems/nv3_pramin.c b/src/video/nv/nv3/subsystems/nv3_pramin.c index 8dcba1b54..18538cd91 100644 --- a/src/video/nv/nv3/subsystems/nv3_pramin.c +++ b/src/video/nv/nv3/subsystems/nv3_pramin.c @@ -347,7 +347,7 @@ bool nv3_ramin_arbitrate_write(uint32_t address, uint32_t value) } // THIS IS THE MOST IMPORTANT FUNCTION! -bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint32_t channel, uint32_t subchannel) +bool nv3_ramin_find_object(uint32_t name, uint32_t cache_num, uint8_t channel, uint8_t subchannel) { // TODO: WRITE IT!!! // Set the number of entries to search based on the ramht size (2*(size+1))