chihiro.c: under the hood 3d accelerator changes [Samuele Zannoli]

-correct some errors
	-add more primitives to some graphic methods
	-add color mask support
	-method 0x100 (NOP) generates correct interrupt
	-some method parameters are readable from mmio registers
This commit is contained in:
yz70s 2015-08-28 09:59:54 +02:00
parent 017ebde24e
commit ece079aa74
2 changed files with 223 additions and 42 deletions

View File

@ -185,6 +185,7 @@ public:
memset(pfifo, 0, sizeof(pfifo)); memset(pfifo, 0, sizeof(pfifo));
memset(pcrtc, 0, sizeof(pcrtc)); memset(pcrtc, 0, sizeof(pcrtc));
memset(pmc, 0, sizeof(pmc)); memset(pmc, 0, sizeof(pmc));
memset(pgraph, 0, sizeof(pgraph));
memset(ramin, 0, sizeof(ramin)); memset(ramin, 0, sizeof(ramin));
computedilated(); computedilated();
objectdata = &(object_data_alloc()); objectdata = &(object_data_alloc());
@ -194,6 +195,7 @@ public:
enabled_vertex_attributes = 0; enabled_vertex_attributes = 0;
indexesleft_count = 0; indexesleft_count = 0;
vertex_pipeline = 4; vertex_pipeline = 4;
color_mask = 0xffffffff;
alpha_test_enabled = false; alpha_test_enabled = false;
alpha_reference = 0; alpha_reference = 0;
alpha_func = nv2a_renderer::ALWAYS; alpha_func = nv2a_renderer::ALWAYS;
@ -238,8 +240,10 @@ public:
} }
DECLARE_READ32_MEMBER(geforce_r); DECLARE_READ32_MEMBER(geforce_r);
DECLARE_WRITE32_MEMBER(geforce_w); DECLARE_WRITE32_MEMBER(geforce_w);
bool vblank_callback(screen_device &screen, bool state); void vblank_callback(screen_device &screen, bool state);
UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
bool update_interrupts();
void set_interrupt_device(pic8259_device *device);
void render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid); void render_texture_simple(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid);
void render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid); void render_color(INT32 scanline, const extent_t &extent, const nvidia_object_data &extradata, int threadid);
@ -303,10 +307,12 @@ public:
UINT32 pfifo[0x2000 / 4]; UINT32 pfifo[0x2000 / 4];
UINT32 pcrtc[0x1000 / 4]; UINT32 pcrtc[0x1000 / 4];
UINT32 pmc[0x1000 / 4]; UINT32 pmc[0x1000 / 4];
UINT32 pgraph[0x2000 / 4];
UINT32 ramin[0x100000 / 4]; UINT32 ramin[0x100000 / 4];
UINT32 dma_offset[2]; UINT32 dma_offset[2];
UINT32 dma_size[2]; UINT32 dma_size[2];
UINT8 *basemempointer; UINT8 *basemempointer;
pic8259_device *interruptdevice;
rectangle limits_rendertarget; rectangle limits_rendertarget;
UINT32 pitch_rendertarget; UINT32 pitch_rendertarget;
UINT32 pitch_depthbuffer; UINT32 pitch_depthbuffer;
@ -441,6 +447,7 @@ public:
int used; int used;
osd_lock *lock; osd_lock *lock;
} combiner; } combiner;
UINT32 color_mask;
bool alpha_test_enabled; bool alpha_test_enabled;
int alpha_func; int alpha_func;
int alpha_reference; int alpha_reference;

View File

@ -3,6 +3,7 @@
#include "emu.h" #include "emu.h"
#include "video/poly.h" #include "video/poly.h"
#include "bitmap.h" #include "bitmap.h"
#include "machine/pic8259.h"
#include "includes/chihiro.h" #include "includes/chihiro.h"
//#define LOG_NV2A //#define LOG_NV2A
@ -945,14 +946,20 @@ int nv2a_renderer::geforce_commandkind(UINT32 word)
UINT32 nv2a_renderer::geforce_object_offset(UINT32 handle) UINT32 nv2a_renderer::geforce_object_offset(UINT32 handle)
{ {
UINT32 h = ((((handle >> 11) ^ handle) >> 11) ^ handle) & 0x7ff; UINT32 h = ((((handle >> 11) ^ handle) >> 11) ^ handle) & 0x7ff;
UINT32 o = (pfifo[0x210 / 4] & 0x1f) << 8; // or 12 ? UINT32 o = (pfifo[0x210 / 4] & 0x1ff) << 8; // 0x1ff is not certain
UINT32 e = o + h * 8; // at 0xfd000000+0x00700000 UINT32 e = o + h * 8; // at 0xfd000000+0x00700000
UINT32 w; UINT32 w;
if (ramin[e / 4] != handle) if (ramin[e / 4] != handle) {
e = 0; // this should never happen
for (UINT32 aa = o / 4; aa < (sizeof(ramin) / 4); aa = aa + 2) {
if (ramin[aa] == handle) {
e = aa * 4;
}
}
}
w = ramin[e / 4 + 1]; w = ramin[e / 4 + 1];
return (w & 0xffff) * 0x10; return (w & 0xffff) * 0x10; // 0xffff is not certain
} }
void nv2a_renderer::geforce_read_dma_object(UINT32 handle, UINT32 &offset, UINT32 &size) void nv2a_renderer::geforce_read_dma_object(UINT32 handle, UINT32 &offset, UINT32 &size)
@ -1246,7 +1253,9 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color, UINT32 depth)
addr = rendertarget + (dilated0[dilate_rendertarget][x] + dilated1[dilate_rendertarget][y]); addr = rendertarget + (dilated0[dilate_rendertarget][x] + dilated1[dilate_rendertarget][y]);
else // type_rendertarget == LINEAR*/ else // type_rendertarget == LINEAR*/
addr = rendertarget + (pitch_rendertarget / 4)*y + x; addr = rendertarget + (pitch_rendertarget / 4)*y + x;
fbcolor = *addr; fbcolor = 0;
if (color_mask != 0)
fbcolor = *addr;
daddr=depthbuffer + (pitch_depthbuffer / 4)*y + x; daddr=depthbuffer + (pitch_depthbuffer / 4)*y + x;
deptsten = *daddr; deptsten = *daddr;
c[3] = color >> 24; c[3] = color >> 24;
@ -1772,8 +1781,12 @@ void nv2a_renderer::write_pixel(int x, int y, UINT32 color, UINT32 depth)
break; break;
} }
} }
fbcolor = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0]; if (color_mask != 0) {
*addr = fbcolor; UINT32 fbcolor_tmp;
fbcolor_tmp = (c[3] << 24) | (c[2] << 16) | (c[1] << 8) | c[0];
*addr = (fbcolor & ~color_mask) | (fbcolor_tmp & color_mask);
}
if (depth_write_enabled) if (depth_write_enabled)
dep = depth; dep = depth;
deptsten = (dep << 8) | sten; deptsten = (dep << 8) | sten;
@ -2233,6 +2246,9 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
maddress = method * 4; maddress = method * 4;
data = space.read_dword(address); data = space.read_dword(address);
channel[chanel][subchannel].object.method[method] = data; channel[chanel][subchannel].object.method[method] = data;
#ifdef LOG_NV2A
printf("A:%08X MTHD:%08X D:%08X\n\r",address,maddress,data);
#endif
if (maddress == 0x17fc) { if (maddress == 0x17fc) {
indexesleft_count = 0; indexesleft_count = 0;
indexesleft_first = 0; indexesleft_first = 0;
@ -2270,6 +2286,21 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
} }
wait(); wait();
} }
else if (type == nv2a_renderer::TRIANGLE_FAN) {
vertex_nv vert[3];
vertex_t xy[3];
read_vertices_0x1810(space, vert, offset, 2);
convert_vertices_poly(vert, xy, 2);
count = count - 2;
offset = offset + 2;
for (n = 0; n <= count; n++) {
read_vertices_0x1810(space, vert + (((n + 1) & 1) + 1), offset + n, 1);
convert_vertices_poly(vert + (((n + 1) & 1) + 1), xy + (((n + 1) & 1) + 1), 1);
render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[0], xy[(~(n + 1) & 1) + 1], xy[((n + 1) & 1) + 1]);
}
wait();
}
else if (type == nv2a_renderer::TRIANGLE_STRIP) { else if (type == nv2a_renderer::TRIANGLE_STRIP) {
vertex_nv vert[4]; vertex_nv vert[4];
vertex_t xy[4]; vertex_t xy[4];
@ -2311,9 +2342,6 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
// each dword after 1800 contains two 16 bit index values to select the vartices // each dword after 1800 contains two 16 bit index values to select the vartices
// each dword after 1808 contains a 32 bit index value to select the vartices // each dword after 1808 contains a 32 bit index value to select the vartices
type = channel[chanel][subchannel].object.method[0x17fc / 4]; type = channel[chanel][subchannel].object.method[0x17fc / 4];
#ifdef LOG_NV2A
printf("vertex %d %d %d\n\r", type, offset, count);
#endif
if (type == nv2a_renderer::QUADS) { if (type == nv2a_renderer::QUADS) {
while (1) { while (1) {
vertex_nv vert[4]; vertex_nv vert[4];
@ -2332,6 +2360,34 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
render_polygon<4>(limits_rendertarget, renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv render_polygon<4>(limits_rendertarget, renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv
} }
} }
else if (type == nv2a_renderer::TRIANGLE_FAN) {
if ((countlen * mult + indexesleft_count) >= 3) {
vertex_nv vert[3];
vertex_t xy[3];
int c, count;
if (mult == 1)
c = read_vertices_0x1808(space, vert, address, 2);
else
c = read_vertices_0x1800(space, vert, address, 2);
convert_vertices_poly(vert, xy, 2);
address = address + c * 4;
countlen = countlen - c;
count = countlen * mult + indexesleft_count;
for (n = 1; n <= count; n++) {
if (mult == 1)
c = read_vertices_0x1808(space, vert + ((n & 1) + 1), address, 1);
else
c = read_vertices_0x1800(space, vert + ((n & 1) + 1), address, 1);
convert_vertices_poly(vert + ((n & 1) + 1), xy + ((n & 1) + 1), 1);
address = address + c * 4;
countlen = countlen - c;
render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[0], xy[(~n & 1) + 1], xy[(n & 1) + 1]);
}
wait();
}
}
else if (type == nv2a_renderer::TRIANGLES) { else if (type == nv2a_renderer::TRIANGLES) {
while (1) { while (1) {
vertex_nv vert[3]; vertex_nv vert[3];
@ -2446,6 +2502,24 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
} }
wait(); wait();
} }
else if (type == nv2a_renderer::TRIANGLES) {
while (countlen > 0) {
vertex_nv vert[3];
vertex_t xy[3];
int c;
c = read_vertices_0x1818(space, vert, address, 3);
convert_vertices_poly(vert, xy, 3);
countlen = countlen - c;
if (countlen < 0) {
logerror("Method 0x1818 missing %d words to draw a complete primitive\n", -countlen);
countlen = 0;
break;
}
address = address + c * 3;
render_triangle(limits_rendertarget, renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv
}
}
else if (type == nv2a_renderer::TRIANGLE_STRIP) { else if (type == nv2a_renderer::TRIANGLE_STRIP) {
vertex_nv vert[4]; vertex_nv vert[4];
vertex_t xy[4]; vertex_t xy[4];
@ -2613,7 +2687,9 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
// clear colors // clear colors
UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4]; UINT32 color = channel[chanel][subchannel].object.method[0x1d90 / 4];
bm.fill(color); bm.fill(color);
//printf("clearscreen\n\r"); #ifdef LOG_NV2A
printf("clearscreen\n\r");
#endif
} }
if ((data & 0x03) == 3) { if ((data & 0x03) == 3) {
bitmap_rgb32 bm(depthbuffer, (limits_rendertarget.right() + 1) * m, (limits_rendertarget.bottom() + 1) * m, pitch_rendertarget / 4); // why *2 ? bitmap_rgb32 bm(depthbuffer, (limits_rendertarget.right() + 1) * m, (limits_rendertarget.bottom() + 1) * m, pitch_rendertarget / 4); // why *2 ?
@ -2649,19 +2725,28 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
dilate_rendertarget = dilatechose[(log2width_rendertarget << 4) + log2height_rendertarget]; dilate_rendertarget = dilatechose[(log2width_rendertarget << 4) + log2height_rendertarget];
} }
if (maddress == 0x020c) { if (maddress == 0x020c) {
// line size ?
pitch_rendertarget=data & 0xffff; pitch_rendertarget=data & 0xffff;
pitch_depthbuffer=(data >> 16) & 0xffff; pitch_depthbuffer=(data >> 16) & 0xffff;
//printf("Pitch color %04X zbuffer %04X\n\r",pitch_rendertarget,pitch_depthbuffer); #ifdef LOG_NV2A
printf("Pitch color %04X zbuffer %04X\n\r",pitch_rendertarget,pitch_depthbuffer);
#endif
countlen--; countlen--;
} }
if (maddress == 0x0100) { if (maddress == 0x0100) {
// just temporarily countlen--;
if ((data & 0x1f) == 1) { if (data != 0) {
data = data >> 5; pgraph[0x704 / 4] = 0x100;
data = data & 0x0ffffff0; pgraph[0x708 / 4] = data;
displayedtarget = (UINT32 *)direct_access_ptr(data); pgraph[0x100 / 4] |= 1;
pgraph[0x108 / 4] |= 1;
if (update_interrupts() == true)
interruptdevice->ir3_w(1); // IRQ 3
else
interruptdevice->ir3_w(0); // IRQ 3
return 2;
} }
else
return 0;
} }
if (maddress == 0x0130) { if (maddress == 0x0130) {
countlen--; countlen--;
@ -2670,16 +2755,32 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
else else
return 0; return 0;
} }
if (maddress == 0x1d8c) {
countlen--;
// it is used to specify the clear value for the depth buffer (zbuffer)
// but also as a parameter for interrupt routines
pgraph[0x1a88 / 4] = data;
}
if (maddress == 0x1d90) {
countlen--;
// it is used to specify the clear value for the color buffer
// but also as a parameter for interrupt routines
pgraph[0x186c / 4] = data;
}
if (maddress == 0x0210) { if (maddress == 0x0210) {
// framebuffer offset ? // framebuffer offset ?
rendertarget = (UINT32 *)direct_access_ptr(data); rendertarget = (UINT32 *)direct_access_ptr(data);
//printf("Render target at %08X\n\r",data); #ifdef LOG_NV2A
printf("Render target at %08X\n\r", data);
#endif
countlen--; countlen--;
} }
if (maddress == 0x0214) { if (maddress == 0x0214) {
// zbuffer offset ? // zbuffer offset ?
depthbuffer = (UINT32 *)direct_access_ptr(data); depthbuffer = (UINT32 *)direct_access_ptr(data);
//printf("Depth buffer at %08X\n\r",data); #ifdef LOG_NV2A
printf("Depth buffer at %08X\n\r",data);
#endif
if ((data == 0) || (data > 0x7ffffffc)) if ((data == 0) || (data > 0x7ffffffc))
depth_write_enabled = false; depth_write_enabled = false;
else if (channel[chanel][subchannel].object.method[0x035c / 4] != 0) else if (channel[chanel][subchannel].object.method[0x035c / 4] != 0)
@ -2709,6 +2810,18 @@ int nv2a_renderer::geforce_exec_method(address_space & space, UINT32 chanel, UIN
if (maddress == 0x0354) { if (maddress == 0x0354) {
depth_function = data; depth_function = data;
} }
if (maddress == 0x0358) {
//color_mask = data;
if (data & 0x000000ff)
data |= 0x000000ff;
if (data & 0x0000ff00)
data |= 0x0000ff00;
if (data & 0x00ff0000)
data |= 0x00ff0000;
if (data & 0xff000000)
data |= 0xff000000;
color_mask = data;
}
if (maddress == 0x035c) { if (maddress == 0x035c) {
UINT32 g = channel[chanel][subchannel].object.method[0x0214 / 4]; UINT32 g = channel[chanel][subchannel].object.method[0x0214 / 4];
depth_write_enabled = data != 0; depth_write_enabled = data != 0;
@ -3648,22 +3761,40 @@ void nv2a_renderer::combiner_compute_a_outputs(int stage_number)
combiner.function_Aop3 = MAX(MIN((combiner.function_Aop3 + biasa) * scalea, 1.0f), -1.0f); combiner.function_Aop3 = MAX(MIN((combiner.function_Aop3 + biasa) * scalea, 1.0f), -1.0f);
} }
bool nv2a_renderer::vblank_callback(screen_device &screen, bool state) void nv2a_renderer::vblank_callback(screen_device &screen, bool state)
{ {
//printf("vblank_callback\n\r"); #ifdef LOG_NV2A
if (state == true) printf("vblank_callback\n\r");
pcrtc[0x100 / 4] |= 1; #endif
else
pcrtc[0x100 / 4] &= ~1;
if (pcrtc[0x100 / 4] & pcrtc[0x140 / 4])
pmc[0x100 / 4] |= 0x1000000;
else
pmc[0x100 / 4] &= ~0x1000000;
if ((state == true) && (puller_waiting == 1)) { if ((state == true) && (puller_waiting == 1)) {
puller_waiting = 0; puller_waiting = 0;
puller_timer_work(NULL, 0); puller_timer_work(NULL, 0);
} }
if ((pmc[0x100 / 4] != 0) && (pmc[0x140 / 4] != 0)) { if (state == true) {
pcrtc[0x100 / 4] |= 1;
pcrtc[0x808 / 4] |= 0x10000;
}
else {
pcrtc[0x100 / 4] &= ~1;
pcrtc[0x808 / 4] &= ~0x10000;
}
if (update_interrupts() == true)
interruptdevice->ir3_w(1); // IRQ 3
else
interruptdevice->ir3_w(0); // IRQ 3
}
bool nv2a_renderer::update_interrupts()
{
if (pcrtc[0x100 / 4] & pcrtc[0x140 / 4])
pmc[0x100 / 4] |= 0x1000000;
else
pmc[0x100 / 4] &= ~0x1000000;
if (pgraph[0x100 / 4] & pgraph[0x140 / 4])
pmc[0x100 / 4] |= 0x1000;
else
pmc[0x100 / 4] &= ~0x1000;
if (((pmc[0x100 / 4] & 0x7fffffff) && (pmc[0x140 / 4] & 1)) || ((pmc[0x100 / 4] & 0x80000000) && (pmc[0x140 / 4] & 2))) {
// send interrupt // send interrupt
return true; return true;
} }
@ -3692,6 +3823,9 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
int countlen; int countlen;
int ret; int ret;
address_space *space = puller_space; address_space *space = puller_space;
#ifdef LOG_NV2A
UINT32 subch;
#endif
chanel = puller_channel; chanel = puller_channel;
subchannel = puller_subchannel; subchannel = puller_subchannel;
@ -3748,7 +3882,7 @@ TIMER_CALLBACK_MEMBER(nv2a_renderer::puller_timer_work)
} }
if (ret != 0) { if (ret != 0) {
puller_timer->enable(false); puller_timer->enable(false);
puller_waiting = 1; puller_waiting = ret;
return; return;
} }
} }
@ -3847,6 +3981,7 @@ READ32_MEMBER(nv2a_renderer::geforce_r)
//logerror("NV_2A: read PRAMIN[%06X] value %08X\n",offset*4-0x00700000,ret); //logerror("NV_2A: read PRAMIN[%06X] value %08X\n",offset*4-0x00700000,ret);
} }
else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) { else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) {
ret = pgraph[offset - 0x00400000 / 4];
//logerror("NV_2A: read PGRAPH[%06X] value %08X\n",offset*4-0x00400000,ret); //logerror("NV_2A: read PGRAPH[%06X] value %08X\n",offset*4-0x00400000,ret);
} }
else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) { else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) {
@ -3870,16 +4005,16 @@ READ32_MEMBER(nv2a_renderer::geforce_r)
//logerror("NV_2A: read channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,ret); //logerror("NV_2A: read channel[%02X,%d,%04X]=%08X\n",chanel,subchannel,suboffset*4,ret);
return ret; return ret;
} }
else
{
/* nothing */
}
//logerror("NV_2A: read at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,ret); //logerror("NV_2A: read at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,ret);
return ret; return ret;
} }
WRITE32_MEMBER(nv2a_renderer::geforce_w) WRITE32_MEMBER(nv2a_renderer::geforce_w)
{ {
UINT32 old;
bool update_int;
update_int = false;
if ((offset >= 0x00101000 / 4) && (offset < 0x00102000 / 4)) { if ((offset >= 0x00101000 / 4) && (offset < 0x00102000 / 4)) {
//logerror("NV_2A: write STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,data); //logerror("NV_2A: write STRAPS[%06X] mask %08X value %08X\n",offset*4-0x00101000,mem_mask,data);
} }
@ -3898,16 +4033,47 @@ WRITE32_MEMBER(nv2a_renderer::geforce_w)
//logerror("NV_2A: write PRAMIN[%06X]=%08X\n",offset*4-0x00700000,data & mem_mask); //logerror("NV_2A: write PRAMIN[%06X]=%08X\n",offset*4-0x00700000,data & mem_mask);
} }
else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) { else if ((offset >= 0x00400000 / 4) && (offset < 0x00402000 / 4)) {
int e = offset - 0x00400000 / 4;
if (e >= (sizeof(pgraph) / sizeof(UINT32)))
return;
old = pgraph[e];
COMBINE_DATA(pgraph + e);
if (e == 0x100 / 4) {
pgraph[e] = old & ~data;
if (data & 1)
pgraph[0x108 / 4] = 0;
update_int = true;
}
if (e == 0x140 / 4)
update_int = true;
if (e == 0x720 / 4) {
if ((data & 1) && (puller_waiting == 2)) {
puller_waiting = 0;
puller_timer->enable();
puller_timer->adjust(attotime::zero);
}
}
if ((e >= 0x900 / 4) && (e < 0xa00 / 4))
pgraph[e] = 0;
//logerror("NV_2A: write PGRAPH[%06X]=%08X\n",offset*4-0x00400000,data & mem_mask); //logerror("NV_2A: write PGRAPH[%06X]=%08X\n",offset*4-0x00400000,data & mem_mask);
} }
else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) { else if ((offset >= 0x00600000 / 4) && (offset < 0x00601000 / 4)) {
int e = offset - 0x00600000 / 4; int e = offset - 0x00600000 / 4;
if (e >= (sizeof(pcrtc) / sizeof(UINT32))) if (e >= (sizeof(pcrtc) / sizeof(UINT32)))
return; return;
old = pcrtc[e];
COMBINE_DATA(pcrtc + e); COMBINE_DATA(pcrtc + e);
if (e == 0x100 / 4) {
pcrtc[e] = old & ~data;
update_int = true;
}
if (e == 0x140 / 4)
update_int = true;
if (e == 0x800 / 4) { if (e == 0x800 / 4) {
displayedtarget = (UINT32 *)direct_access_ptr(data); displayedtarget = (UINT32 *)direct_access_ptr(pcrtc[e]);
//printf("crtc buffer %08X\n\r", data); #ifdef LOG_NV2A
printf("crtc buffer %08X\n\r", data);
#endif
} }
//logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask); //logerror("NV_2A: write PCRTC[%06X]=%08X\n",offset*4-0x00600000,data & mem_mask);
} }
@ -3922,9 +4088,6 @@ WRITE32_MEMBER(nv2a_renderer::geforce_w)
// 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each // 32 channels size 0x10000 each, 8 subchannels per channel size 0x2000 each
int chanel, subchannel, suboffset; int chanel, subchannel, suboffset;
//int method, count, handle, objclass; //int method, count, handle, objclass;
#ifdef LOG_NV2A
int subch;
#endif
suboffset = offset - 0x00800000 / 4; suboffset = offset - 0x00800000 / 4;
chanel = (suboffset >> (16 - 2)) & 31; chanel = (suboffset >> (16 - 2)) & 31;
@ -3959,6 +4122,12 @@ WRITE32_MEMBER(nv2a_renderer::geforce_w)
} }
//else //else
// logerror("NV_2A: write at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,data); // logerror("NV_2A: write at %08X mask %08X value %08X\n",0xfd000000+offset*4,mem_mask,data);
if (update_int == true) {
if (update_interrupts() == true)
interruptdevice->ir3_w(1); // IRQ 3
else
interruptdevice->ir3_w(0); // IRQ 3
}
} }
void nv2a_renderer::savestate_items() void nv2a_renderer::savestate_items()
@ -3971,3 +4140,8 @@ void nv2a_renderer::start(address_space *cpu_space)
puller_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nv2a_renderer::puller_timer_work), this), (void *)"NV2A Puller Timer"); puller_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nv2a_renderer::puller_timer_work), this), (void *)"NV2A Puller Timer");
puller_timer->enable(false); puller_timer->enable(false);
} }
void nv2a_renderer::set_interrupt_device(pic8259_device *device)
{
interruptdevice = device;
}