NV2A : Copied over all PGRAPH code from XQEMU / OpenXbox. All OpenGL-calls are still disabled.

This commit is contained in:
PatrickvL 2018-02-02 15:35:50 +01:00
parent 0ac96332a7
commit 4e07867c47
8 changed files with 3426 additions and 355 deletions

View File

@ -642,6 +642,10 @@ static void nv2a_vblank_thread(NV2AState *d)
} }
} }
// See NV2ABlockInfo regions[] PRAMIN
#define NV_PRAMIN_ADDR 0x00700000
#define NV_PRAMIN_SIZE 0x100000
void CxbxReserveNV2AMemory(NV2AState *d) void CxbxReserveNV2AMemory(NV2AState *d)
{ {
// Reserve NV2A memory : // Reserve NV2A memory :
@ -673,7 +677,7 @@ void CxbxReserveNV2AMemory(NV2AState *d)
} }
printf("[0x%.4X] INIT: Allocated %d MiB of Xbox NV2A PRAMIN memory at 0x%.8X to 0x%.8X\n", printf("[0x%.4X] INIT: Allocated %d MiB of Xbox NV2A PRAMIN memory at 0x%.8X to 0x%.8X\n",
GetCurrentThreadId(), NV_PRAMIN_SIZE / ONE_MB, NV2A_ADDR + NV_PRAMIN_ADDR, NV2A_ADDR + NV_PRAMIN_ADDR + NV_PRAMIN_SIZE - 1); GetCurrentThreadId(), d->pramin.ramin_size / ONE_MB, d->pramin.ramin_ptr, d->pramin.ramin_ptr + d->pramin.ramin_size - 1);
} }
void EmuNV2A_Init() void EmuNV2A_Init()
@ -682,6 +686,7 @@ void EmuNV2A_Init()
d->pcrtc.start = 0; d->pcrtc.start = 0;
d->vram_ptr = (uint8_t*)MM_SYSTEM_PHYSICAL_MAP;
d->vram_size = (g_bIsChihiro || g_bIsDebug) ? CONTIGUOUS_MEMORY_CHIHIRO_SIZE : CONTIGUOUS_MEMORY_XBOX_SIZE; d->vram_size = (g_bIsChihiro || g_bIsDebug) ? CONTIGUOUS_MEMORY_CHIHIRO_SIZE : CONTIGUOUS_MEMORY_XBOX_SIZE;
d->pramdac.core_clock_coeff = 0x00011c01; /* 189MHz...? */ d->pramdac.core_clock_coeff = 0x00011c01; /* 189MHz...? */

View File

@ -36,13 +36,13 @@ DEVICE_READ32(PFIFO)
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_CHID, d->pfifo.cache1.channel_id); SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_CHID, d->pfifo.cache1.channel_id);
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_MODE, d->pfifo.cache1.mode); SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_MODE, d->pfifo.cache1.mode);
break; break;
case NV_PFIFO_CACHE1_STATUS: { case NV_PFIFO_CACHE1_STATUS:
d->pfifo.cache1.cache_lock.lock(); d->pfifo.cache1.cache_lock.lock();
if (d->pfifo.cache1.cache.empty()) { if (d->pfifo.cache1.cache.empty()) {
result |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */ result |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */
} }
d->pfifo.cache1.cache_lock.unlock(); d->pfifo.cache1.cache_lock.unlock();
} break; break;
case NV_PFIFO_CACHE1_DMA_PUSH: case NV_PFIFO_CACHE1_DMA_PUSH:
SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS, SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS,
d->pfifo.cache1.dma_push_enabled); d->pfifo.cache1.dma_push_enabled);
@ -76,18 +76,18 @@ DEVICE_READ32(PFIFO)
result = d->pfifo.cache1.subroutine_return result = d->pfifo.cache1.subroutine_return
| d->pfifo.cache1.subroutine_active; | d->pfifo.cache1.subroutine_active;
break; break;
case NV_PFIFO_CACHE1_PULL0: { case NV_PFIFO_CACHE1_PULL0:
d->pfifo.cache1.cache_lock.lock(); d->pfifo.cache1.cache_lock.lock();
result = d->pfifo.cache1.pull_enabled; result = d->pfifo.cache1.pull_enabled;
d->pfifo.cache1.cache_lock.unlock(); d->pfifo.cache1.cache_lock.unlock();
} break; break;
case NV_PFIFO_CACHE1_ENGINE: { case NV_PFIFO_CACHE1_ENGINE:
d->pfifo.cache1.cache_lock.lock(); d->pfifo.cache1.cache_lock.lock();
for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) { for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
result |= d->pfifo.cache1.bound_engines[i] << (i * 2); result |= d->pfifo.cache1.bound_engines[i] << (i * 2);
} }
d->pfifo.cache1.cache_lock.unlock(); d->pfifo.cache1.cache_lock.unlock();
} break; break;
case NV_PFIFO_CACHE1_DMA_DCOUNT: case NV_PFIFO_CACHE1_DMA_DCOUNT:
result = d->pfifo.cache1.dcount; result = d->pfifo.cache1.dcount;
break; break;
@ -110,6 +110,8 @@ DEVICE_READ32(PFIFO)
DEVICE_WRITE32(PFIFO) DEVICE_WRITE32(PFIFO)
{ {
int i;
switch(addr) { switch(addr) {
case NV_PFIFO_INTR_0: case NV_PFIFO_INTR_0:
d->pfifo.pending_interrupts &= ~value; d->pfifo.pending_interrupts &= ~value;
@ -128,22 +130,31 @@ DEVICE_WRITE32(PFIFO)
assert(d->pfifo.cache1.channel_id < NV2A_NUM_CHANNELS); assert(d->pfifo.cache1.channel_id < NV2A_NUM_CHANNELS);
break; break;
case NV_PFIFO_CACHE1_DMA_PUSH: case NV_PFIFO_CACHE1_DMA_PUSH:
d->pfifo.cache1.dma_push_enabled = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS); d->pfifo.cache1.dma_push_enabled =
if (d->pfifo.cache1.dma_push_suspended && !GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS)) { GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS);
if (d->pfifo.cache1.dma_push_suspended
&& !GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS)) {
d->pfifo.cache1.dma_push_suspended = false; d->pfifo.cache1.dma_push_suspended = false;
pfifo_run_pusher(d); pfifo_run_pusher(d);
} }
d->pfifo.cache1.dma_push_suspended = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS); d->pfifo.cache1.dma_push_suspended =
GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS);
break; break;
case NV_PFIFO_CACHE1_DMA_STATE: case NV_PFIFO_CACHE1_DMA_STATE:
d->pfifo.cache1.method_nonincreasing = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE); d->pfifo.cache1.method_nonincreasing =
d->pfifo.cache1.method = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD) << 2; GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE);
d->pfifo.cache1.subchannel = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL); d->pfifo.cache1.method =
d->pfifo.cache1.method_count = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT); GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD) << 2;
d->pfifo.cache1.error = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_ERROR); d->pfifo.cache1.subchannel =
GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL);
d->pfifo.cache1.method_count =
GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT);
d->pfifo.cache1.error =
GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_ERROR);
break; break;
case NV_PFIFO_CACHE1_DMA_INSTANCE: case NV_PFIFO_CACHE1_DMA_INSTANCE:
d->pfifo.cache1.dma_instance = GET_MASK(value, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS_MASK) << 4; d->pfifo.cache1.dma_instance =
GET_MASK(value, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS_MASK) << 4;
break; break;
case NV_PFIFO_CACHE1_DMA_PUT: case NV_PFIFO_CACHE1_DMA_PUT:
d->user.channel_control[d->pfifo.cache1.channel_id].dma_put = value; d->user.channel_control[d->pfifo.cache1.channel_id].dma_put = value;
@ -152,12 +163,13 @@ DEVICE_WRITE32(PFIFO)
d->user.channel_control[d->pfifo.cache1.channel_id].dma_get = value; d->user.channel_control[d->pfifo.cache1.channel_id].dma_get = value;
break; break;
case NV_PFIFO_CACHE1_DMA_SUBROUTINE: case NV_PFIFO_CACHE1_DMA_SUBROUTINE:
d->pfifo.cache1.subroutine_return = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_RETURN_OFFSET); d->pfifo.cache1.subroutine_return =
d->pfifo.cache1.subroutine_active = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE); (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_RETURN_OFFSET);
d->pfifo.cache1.subroutine_active =
(value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
break; break;
case NV_PFIFO_CACHE1_PULL0: { case NV_PFIFO_CACHE1_PULL0:
d->pfifo.cache1.cache_lock.lock(); d->pfifo.cache1.cache_lock.lock();
if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS) if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS)
&& !d->pfifo.cache1.pull_enabled) { && !d->pfifo.cache1.pull_enabled) {
d->pfifo.cache1.pull_enabled = true; d->pfifo.cache1.pull_enabled = true;
@ -169,19 +181,21 @@ DEVICE_WRITE32(PFIFO)
d->pfifo.cache1.pull_enabled = false; d->pfifo.cache1.pull_enabled = false;
} }
d->pfifo.cache1.cache_lock.unlock(); d->pfifo.cache1.cache_lock.unlock();
} break; break;
case NV_PFIFO_CACHE1_ENGINE: { case NV_PFIFO_CACHE1_ENGINE:
d->pfifo.cache1.cache_lock.lock(); d->pfifo.cache1.cache_lock.lock();
for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) { for (i=0; i < NV2A_NUM_SUBCHANNELS; i++) {
d->pfifo.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3); d->pfifo.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3);
} }
d->pfifo.cache1.cache_lock.unlock(); d->pfifo.cache1.cache_lock.unlock();
} break; break;
case NV_PFIFO_CACHE1_DMA_DCOUNT: case NV_PFIFO_CACHE1_DMA_DCOUNT:
d->pfifo.cache1.dcount = (value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE); d->pfifo.cache1.dcount =
(value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE);
break; break;
case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW: case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW:
d->pfifo.cache1.get_jmp_shadow = (value & NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW_OFFSET); d->pfifo.cache1.get_jmp_shadow =
(value & NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW_OFFSET);
break; break;
case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW: case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW:
d->pfifo.cache1.rsvd_shadow = value; d->pfifo.cache1.rsvd_shadow = value;
@ -197,6 +211,7 @@ DEVICE_WRITE32(PFIFO)
DEVICE_WRITE32_END(PFIFO); DEVICE_WRITE32_END(PFIFO);
} }
/* pusher should be fine to run from a mimo handler /* pusher should be fine to run from a mimo handler
* whenever's it's convenient */ * whenever's it's convenient */
static void pfifo_run_pusher(NV2AState *d) { static void pfifo_run_pusher(NV2AState *d) {
@ -215,6 +230,7 @@ static void pfifo_run_pusher(NV2AState *d) {
if (!state->push_enabled) return; if (!state->push_enabled) return;
/* only handling DMA for now... */ /* only handling DMA for now... */
/* Channel running DMA */ /* Channel running DMA */
@ -230,12 +246,13 @@ static void pfifo_run_pusher(NV2AState *d) {
dma = (uint8_t*)nv_dma_map(d, state->dma_instance, &dma_len); dma = (uint8_t*)nv_dma_map(d, state->dma_instance, &dma_len);
printf("DMA pusher: max 0x%08X, 0x%08X - 0x%08X\n", NV2A_DPRINTF("DMA pusher: max 0x%08X, 0x%08X - 0x%08X\n",
dma_len, control->dma_get, control->dma_put); dma_len, control->dma_get, control->dma_put);
/* based on the convenient pseudocode in envytools */ /* based on the convenient pseudocode in envytools */
while (control->dma_get != control->dma_put) { while (control->dma_get != control->dma_put) {
if (control->dma_get >= dma_len) { if (control->dma_get >= dma_len) {
state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION; state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION;
break; break;
} }
@ -247,7 +264,7 @@ static void pfifo_run_pusher(NV2AState *d) {
/* data word of methods command */ /* data word of methods command */
state->data_shadow = word; state->data_shadow = word;
command = (CacheEntry*)calloc(1, sizeof(CacheEntry)); command = (CacheEntry*)malloc(sizeof(CacheEntry));
command->method = state->method; command->method = state->method;
command->subchannel = state->subchannel; command->subchannel = state->subchannel;
command->nonincreasing = state->method_nonincreasing; command->nonincreasing = state->method_nonincreasing;
@ -271,15 +288,13 @@ static void pfifo_run_pusher(NV2AState *d) {
/* old jump */ /* old jump */
state->get_jmp_shadow = control->dma_get; state->get_jmp_shadow = control->dma_get;
control->dma_get = word & 0x1fffffff; control->dma_get = word & 0x1fffffff;
printf("pb OLD_JMP 0x%08X\n", control->dma_get); NV2A_DPRINTF("pb OLD_JMP 0x%08X\n", control->dma_get);
} } else if ((word & 3) == 1) {
else if ((word & 3) == 1) {
/* jump */ /* jump */
state->get_jmp_shadow = control->dma_get; state->get_jmp_shadow = control->dma_get;
control->dma_get = word & 0xfffffffc; control->dma_get = word & 0xfffffffc;
printf("pb JMP 0x%08X\n", control->dma_get); NV2A_DPRINTF("pb JMP 0x%08X\n", control->dma_get);
} } else if ((word & 3) == 2) {
else if ((word & 3) == 2) {
/* call */ /* call */
if (state->subroutine_active) { if (state->subroutine_active) {
state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL; state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL;
@ -288,9 +303,8 @@ static void pfifo_run_pusher(NV2AState *d) {
state->subroutine_return = control->dma_get; state->subroutine_return = control->dma_get;
state->subroutine_active = true; state->subroutine_active = true;
control->dma_get = word & 0xfffffffc; control->dma_get = word & 0xfffffffc;
printf("pb CALL 0x%08X\n", control->dma_get); NV2A_DPRINTF("pb CALL 0x%08X\n", control->dma_get);
} } else if (word == 0x00020000) {
else if (word == 0x00020000) {
/* return */ /* return */
if (!state->subroutine_active) { if (!state->subroutine_active) {
state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN; state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN;
@ -298,9 +312,8 @@ static void pfifo_run_pusher(NV2AState *d) {
} }
control->dma_get = state->subroutine_return; control->dma_get = state->subroutine_return;
state->subroutine_active = false; state->subroutine_active = false;
printf("pb RET 0x%08X\n", control->dma_get); NV2A_DPRINTF("pb RET 0x%08X\n", control->dma_get);
} } else if ((word & 0xe0030003) == 0) {
else if ((word & 0xe0030003) == 0) {
/* increasing methods */ /* increasing methods */
state->method = word & 0x1fff; state->method = word & 0x1fff;
state->subchannel = (word >> 13) & 7; state->subchannel = (word >> 13) & 7;
@ -315,9 +328,8 @@ static void pfifo_run_pusher(NV2AState *d) {
state->method_count = (word >> 18) & 0x7ff; state->method_count = (word >> 18) & 0x7ff;
state->method_nonincreasing = true; state->method_nonincreasing = true;
state->dcount = 0; state->dcount = 0;
} } else {
else { NV2A_DPRINTF("pb reserved cmd 0x%08X - 0x%08X\n",
printf("pb reserved cmd 0x%08X - 0x%08X\n",
control->dma_get, word); control->dma_get, word);
state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD; state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD;
break; break;
@ -325,11 +337,11 @@ static void pfifo_run_pusher(NV2AState *d) {
} }
} }
printf("DMA pusher done: max 0x%08X, 0x%08X - 0x%08X\n", NV2A_DPRINTF("DMA pusher done: max 0x%08X, 0x%08X - 0x%08X\n",
dma_len, control->dma_get, control->dma_put); dma_len, control->dma_get, control->dma_put);
if (state->error) { if (state->error) {
printf("pb error: %d\n", state->error); NV2A_DPRINTF("pb error: %d\n", state->error);
assert(false); assert(false);
state->dma_push_suspended = true; state->dma_push_suspended = true;
@ -345,6 +357,8 @@ int pfifo_puller_thread(NV2AState *d)
Cache1State *state = &d->pfifo.cache1; Cache1State *state = &d->pfifo.cache1;
// glo_set_current(d->pgraph.gl_context);
while (true) { while (true) {
state->cache_lock.lock(); state->cache_lock.lock();
while (state->cache.empty() || !state->pull_enabled) { while (state->cache.empty() || !state->pull_enabled) {
@ -411,7 +425,8 @@ int pfifo_puller_thread(NV2AState *d)
switch (engine) { switch (engine) {
case ENGINE_GRAPHICS: case ENGINE_GRAPHICS:
pgraph_wait_fifo_access(d); pgraph_wait_fifo_access(d);
pgraph_method(d, command->subchannel, command->method, parameter); pgraph_method(d, command->subchannel,
command->method, parameter);
break; break;
default: default:
assert(false); assert(false);
@ -425,17 +440,17 @@ int pfifo_puller_thread(NV2AState *d)
free(command); free(command);
} }
d->pgraph.lock.unlock();
} }
d->pgraph.lock.unlock();
return 0; return 0;
} }
static uint32_t ramht_hash(NV2AState *d, uint32_t handle) static uint32_t ramht_hash(NV2AState *d, uint32_t handle)
{ {
unsigned int ramht_size = 1 << (GET_MASK(d->pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12); unsigned int ramht_size =
1 << (GET_MASK(d->pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
/* XXX: Think this is different to what nouveau calculates... */ /* XXX: Think this is different to what nouveau calculates... */
unsigned int bits = ffs(ramht_size) - 2; unsigned int bits = ffs(ramht_size) - 2;
@ -452,7 +467,8 @@ static uint32_t ramht_hash(NV2AState *d, uint32_t handle)
static RAMHTEntry ramht_lookup(NV2AState *d, uint32_t handle) static RAMHTEntry ramht_lookup(NV2AState *d, uint32_t handle)
{ {
unsigned int ramht_size = 1 << (GET_MASK(d->pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12); unsigned int ramht_size =
1 << (GET_MASK(d->pfifo.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE_MASK) + 12);
uint32_t hash = ramht_hash(d, handle); uint32_t hash = ramht_hash(d, handle);
assert(hash * 8 < ramht_size); assert(hash * 8 < ramht_size);
@ -475,4 +491,3 @@ static RAMHTEntry ramht_lookup(NV2AState *d, uint32_t handle)
return entry; return entry;
} }

File diff suppressed because it is too large Load Diff

View File

@ -44,8 +44,7 @@ DEVICE_WRITE32(PRAMDAC)
if (m == 0) { if (m == 0) {
d->pramdac.core_clock_freq = 0; d->pramdac.core_clock_freq = 0;
} } else {
else {
d->pramdac.core_clock_freq = (NV2A_CRYSTAL_FREQ * n) d->pramdac.core_clock_freq = (NV2A_CRYSTAL_FREQ * n)
/ (1 << p) / m; / (1 << p) / m;
} }

View File

@ -1,21 +1,13 @@
DEVICE_READ32(PRAMIN) DEVICE_READ32(PRAMIN)
{ {
DEVICE_READ32_SWITCH() { uint32_t result = *((uint32_t*)(d->pramin.ramin_ptr + addr));
default:
DEVICE_READ32_REG(pramin);
break;
}
DEVICE_READ32_END(PRAMIN); DEVICE_READ32_END(PRAMIN);
} }
DEVICE_WRITE32(PRAMIN) DEVICE_WRITE32(PRAMIN)
{ {
switch (addr) { *((uint32_t*)(d->pramin.ramin_ptr + addr)) = value;
default:
DEVICE_WRITE32_REG(pramin);
break;
}
DEVICE_WRITE32_END(PRAMIN); DEVICE_WRITE32_END(PRAMIN);
} }

View File

@ -1,15 +1,13 @@
/*
static void pvideo_vga_invalidate(NV2AState *d) static void pvideo_vga_invalidate(NV2AState *d)
{ {
int y1 = GET_MASK(d->pvideo.regs[NV_PVIDEO_POINT_OUT], int y1 = GET_MASK(d->pvideo.regs[NV_PVIDEO_POINT_OUT(0)],
NV_PVIDEO_POINT_OUT_Y); NV_PVIDEO_POINT_OUT_Y);
int y2 = y1 + GET_MASK(d->pvideo.regs[NV_PVIDEO_SIZE_OUT], int y2 = y1 + GET_MASK(d->pvideo.regs[NV_PVIDEO_SIZE_OUT(0)],
NV_PVIDEO_SIZE_OUT_HEIGHT); NV_PVIDEO_SIZE_OUT_HEIGHT);
NV2A_DPRINTF("pvideo_vga_invalidate %d %d\n", y1, y2); NV2A_DPRINTF("pvideo_vga_invalidate %d %d\n", y1, y2);
vga_invalidate_scanlines(&d->vga, y1, y2); // TODO : vga_invalidate_scanlines(&d->vga, y1, y2);
} }
*/
DEVICE_READ32(PVIDEO) DEVICE_READ32(PVIDEO)
{ {
DEVICE_READ32_SWITCH() { DEVICE_READ32_SWITCH() {
@ -30,13 +28,13 @@ DEVICE_WRITE32(PVIDEO)
switch (addr) { switch (addr) {
case NV_PVIDEO_BUFFER: case NV_PVIDEO_BUFFER:
d->pvideo.regs[addr] = value; d->pvideo.regs[addr] = value;
// TODO: vga.enable_overlay = true; // TODO : d->vga.enable_overlay = true;
// pvideo_vga_invalidate(d); pvideo_vga_invalidate(d);
break; break;
case NV_PVIDEO_STOP: case NV_PVIDEO_STOP:
d->pvideo.regs[NV_PVIDEO_BUFFER] = 0; d->pvideo.regs[NV_PVIDEO_BUFFER] = 0;
// TODO: vga.enable_overlay = false; // TODO : d->vga.enable_overlay = false;
//pvideo_vga_invalidate(d); pvideo_vga_invalidate(d);
break; break;
default: default:
DEVICE_WRITE32_REG(pvideo); DEVICE_WRITE32_REG(pvideo);

View File

@ -60,8 +60,7 @@ DEVICE_WRITE32(USER)
DEBUG_WRITE32_UNHANDLED(USER); DEBUG_WRITE32_UNHANDLED(USER);
break; break;
} }
} } else {
else {
/* PIO Mode */ /* PIO Mode */
assert(false); assert(false);
} }

View File

@ -57,12 +57,13 @@
#define NV_PGRAPH_SIZE 0x002000 #define NV_PGRAPH_SIZE 0x002000
#define NV_PCRTC_SIZE 0x001000 #define NV_PCRTC_SIZE 0x001000
#define NV_PRAMDAC_SIZE 0x001000 #define NV_PRAMDAC_SIZE 0x001000
#define NV_PRAMIN_ADDR 0x00700000
#define NV_PRAMIN_SIZE 0x100000
typedef xbaddr hwaddr; // Compatibility; Cxbx uses xbaddr, xqemu and OpenXbox use hwaddr typedef xbaddr hwaddr; // Compatibility; Cxbx uses xbaddr, xqemu and OpenXbox use hwaddr
typedef uint32_t value_t; // Compatibility; Cxbx values are uint32_t (xqemu and OpenXbox use uint64_t) typedef uint32_t value_t; // Compatibility; Cxbx values are uint32_t (xqemu and OpenXbox use uint64_t)
#define NV2A_DPRINTF printf // Compatibility; TODO : Replace this by something equivalent
#define NV2A_GL_DPRINTF EmuWarning // Compatibility; TODO : Replace this by something equivalent
#define VSH_TOKEN_SIZE 4 // Compatibility; TODO : Move this to nv2a_vsh.h
//#define MAX(a,b) ((a)>(b) ? (a) : (b)) // Compatibility
#define USE_TEXTURE_CACHE #define USE_TEXTURE_CACHE
@ -123,12 +124,27 @@ inline int SET_MASK(int v, int mask, int val) {
return (v) |= ((__val) << (ffs(__mask)-1)) & (__mask); return (v) |= ((__val) << (ffs(__mask)-1)) & (__mask);
} }
#define CASE_4(v, step) \ // Power-of-two CASE statements
case (v): \ #define CASE_1(v, step) case (v)
case (v)+(step) : \ #define CASE_2(v, step) CASE_1(v, step) : CASE_1(v + (step) * 1, step)
case (v)+(step) * 2: \ #define CASE_4(v, step) CASE_2(v, step) : CASE_2(v + (step) * 2, step)
case (v)+(step) * 3 #define CASE_8(v, step) CASE_4(v, step) : CASE_4(v + (step) * 4, step)
#define CASE_16(v, step) CASE_8(v, step) : CASE_8(v + (step) * 8, step)
#define CASE_32(v, step) CASE_16(v, step) : CASE_16(v + (step) * 16, step)
#define CASE_64(v, step) CASE_32(v, step) : CASE_32(v + (step) * 32, step)
#define CASE_128(v, step) CASE_64(v, step) : CASE_64(v + (step) * 64, step)
// Non-power-of-two CASE statements
#define CASE_3(v, step) CASE_2(v, step) : CASE_1(v + (step) * 2, step)
#define CASE_12(v, step) CASE_8(v, step) : CASE_4(v + (step) * 8, step)
#define CASE_13(v, step) CASE_8(v, step) : CASE_3(v + (step) * 8, step)
#define CASE_28(v, step) CASE_16(v, step) : CASE_12(v + (step) * 16, step)
#define CASE_29(v, step) CASE_16(v, step) : CASE_13(v + (step) * 16, step)
#define CASE_61(v, step) CASE_32(v, step) : CASE_29(v + (step) * 32, step)
#define CASE_78(v, step) CASE_64(v, step) : CASE_12(v + (step) * 64, step)
#define CASE_125(v, step) CASE_64(v, step) : CASE_61(v + (step) * 64, step)
#define CASE_132(v, step) CASE_128(v, step) : CASE_4(v + (step) * 128, step)
#define CASE_253(v, step) CASE_128(v, step) : CASE_125(v + (step) * 128, step)
#define NV2A_DEVICE(obj) \ #define NV2A_DEVICE(obj) \
OBJECT_CHECK(NV2AState, (obj), "nv2a") OBJECT_CHECK(NV2AState, (obj), "nv2a")
@ -339,7 +355,7 @@ typedef struct PGRAPHState {
bool enable_vertex_program_write; bool enable_vertex_program_write;
//uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE]; uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE];
uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4]; uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4];
bool vsh_constants_dirty[NV2A_VERTEXSHADER_CONSTANTS]; bool vsh_constants_dirty[NV2A_VERTEXSHADER_CONSTANTS];
@ -449,7 +465,6 @@ typedef struct NV2AState {
struct { struct {
uint8_t *ramin_ptr; uint8_t *ramin_ptr;
size_t ramin_size; size_t ramin_size;
uint32_t regs[NV_PRAMIN_SIZE]; // TODO : union
} pramin; } pramin;
// MemoryRegion mmio; // MemoryRegion mmio;
@ -458,7 +473,7 @@ typedef struct NV2AState {
struct { struct {
uint32_t pending_interrupts; uint32_t pending_interrupts;
uint32_t enabled_interrupts; uint32_t enabled_interrupts;
uint32_t regs[NV_PMC_SIZE]; // TODO : union uint32_t regs[NV_PMC_SIZE]; // Not in xqemu/openxbox? TODO : union
} pmc; } pmc;
struct { struct {
@ -479,7 +494,7 @@ typedef struct NV2AState {
uint32_t numerator; uint32_t numerator;
uint32_t denominator; uint32_t denominator;
uint32_t alarm_time; uint32_t alarm_time;
uint32_t regs[NV_PTIMER_SIZE]; // TODO : union uint32_t regs[NV_PTIMER_SIZE]; // Not in xqemu/openxbox? TODO : union
} ptimer; } ptimer;
struct { struct {
@ -492,7 +507,7 @@ typedef struct NV2AState {
uint32_t pending_interrupts; uint32_t pending_interrupts;
uint32_t enabled_interrupts; uint32_t enabled_interrupts;
hwaddr start; hwaddr start;
uint32_t regs[NV_PCRTC_SIZE]; // TODO : union uint32_t regs[NV_PCRTC_SIZE]; // Not in xqemu/openxbox? TODO : union
} pcrtc; } pcrtc;
struct { struct {
@ -500,7 +515,7 @@ typedef struct NV2AState {
uint64_t core_clock_freq; uint64_t core_clock_freq;
uint32_t memory_clock_coeff; uint32_t memory_clock_coeff;
uint32_t video_clock_coeff; uint32_t video_clock_coeff;
uint32_t regs[NV_PRAMDAC_SIZE]; // TODO : union uint32_t regs[NV_PRAMDAC_SIZE]; // Not in xqemu/openxbox? TODO : union
} pramdac; } pramdac;
struct { struct {
@ -511,9 +526,9 @@ typedef struct NV2AState {
struct { struct {
uint8_t cr_index; uint8_t cr_index;
uint8_t cr[256]; /* CRT registers */ uint8_t cr[256]; /* CRT registers */
} prmcio; } prmcio; // Not in xqemu/openxbox?
std::mutex io_lock; std::mutex io_lock; // TODO ? std::unique_lock<std::mutex>
//SDL_Window *sdl_window; //SDL_Window *sdl_window;
} NV2AState; } NV2AState;