1 // license:BSD-3-Clause
2 // copyright-holders:smf
3 /*
4  * PlayStation GPU emulator
5  *
6  * Copyright 2003-2014 smf
7  *
8  */
9 
10 #include "emu.h"
11 #include "cpu/psx/psx.h"
12 #include "video/psx.h"
13 
14 #include "screen.h"
15 
16 
17 #define STOP_ON_ERROR ( 0 )
18 
19 #define VERBOSE_LEVEL ( 0 )
20 
21 // device type definition
22 DEFINE_DEVICE_TYPE(CXD8514Q,  cxd8514q_device,  "cxd8514q",  "CXD8514Q GPU") // VRAM
23 DEFINE_DEVICE_TYPE(CXD8538Q,  cxd8538q_device,  "cxd8538q",  "CXD8538Q GPU") // VRAM
24 DEFINE_DEVICE_TYPE(CXD8561Q,  cxd8561q_device,  "cxd8561q",  "CXD8561Q GPU") // SGRAM
25 DEFINE_DEVICE_TYPE(CXD8561BQ, cxd8561bq_device, "cxd8561bq", "CXD8561BQ GPU") // SGRAM
26 DEFINE_DEVICE_TYPE(CXD8561CQ, cxd8561cq_device, "cxd8561cq", "CXD8561CQ GPU") // SGRAM
27 DEFINE_DEVICE_TYPE(CXD8654Q,  cxd8654q_device,  "cxd8654q",  "CXD8654Q GPU") // SGRAM
28 
psxgpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)29 psxgpu_device::psxgpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
30 	: psxgpu_device(mconfig, type, tag, owner, clock)
31 {
32 	set_vram_size(vram_size);
33 	cpu->gpu_read().set(tag, FUNC(psxgpu_device::read));
34 	cpu->gpu_write().set(tag, FUNC(psxgpu_device::write));
35 	cpu->subdevice<psxdma_device>("dma")->install_read_handler(2, psxdma_device::read_delegate(&psxgpu_device::dma_read, this));
36 	cpu->subdevice<psxdma_device>("dma")->install_write_handler(2, psxdma_device::write_delegate(&psxgpu_device::dma_write, this));
37 	vblank_callback().set(*cpu->subdevice<psxirq_device>("irq"), FUNC(psxirq_device::intin0));
38 }
39 
psxgpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)40 psxgpu_device::psxgpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
41 	: device_t(mconfig, type, tag, owner, clock)
42 	, device_video_interface(mconfig, *this)
43 	, device_palette_interface(mconfig, *this)
44 	, m_vblank_handler(*this)
45 {
46 }
47 
device_start()48 void psxgpu_device::device_start()
49 {
50 	m_vblank_handler.resolve_safe();
51 
52 	screen().register_vblank_callback(vblank_state_delegate(&psxgpu_device::vblank, this));
53 
54 	for( int n_colour = 0; n_colour < 0x10000; n_colour++ )
55 	{
56 		set_pen_color( n_colour, pal555(n_colour,0, 5, 10) );
57 	}
58 
59 	if (type() == CXD8538Q)
60 	{
61 		psx_gpu_init( 1 );
62 	}
63 	else
64 	{
65 		psx_gpu_init( 2 );
66 	}
67 }
68 
device_reset()69 void psxgpu_device::device_reset()
70 {
71 	gpu_reset();
72 }
73 
cxd8514q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)74 cxd8514q_device::cxd8514q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
75 	: psxgpu_device(mconfig, CXD8514Q, tag, owner, clock, vram_size, cpu)
76 {
77 }
78 
cxd8514q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)79 cxd8514q_device::cxd8514q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
80 	: psxgpu_device(mconfig, CXD8514Q, tag, owner, clock)
81 {
82 }
83 
cxd8538q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)84 cxd8538q_device::cxd8538q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
85 	: psxgpu_device(mconfig, CXD8538Q, tag, owner, clock, vram_size, cpu)
86 {
87 }
88 
cxd8538q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)89 cxd8538q_device::cxd8538q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
90 	: psxgpu_device(mconfig, CXD8538Q, tag, owner, clock)
91 {
92 }
93 
cxd8561q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)94 cxd8561q_device::cxd8561q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
95 	: psxgpu_device(mconfig, CXD8561Q, tag, owner, clock, vram_size, cpu)
96 {
97 }
98 
cxd8561q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)99 cxd8561q_device::cxd8561q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
100 	: psxgpu_device(mconfig, CXD8561Q, tag, owner, clock)
101 {
102 }
103 
cxd8561bq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)104 cxd8561bq_device::cxd8561bq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
105 	: psxgpu_device(mconfig, CXD8561BQ, tag, owner, clock, vram_size, cpu)
106 {
107 }
108 
cxd8561bq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)109 cxd8561bq_device::cxd8561bq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
110 	: psxgpu_device(mconfig, CXD8561BQ, tag, owner, clock)
111 {
112 }
113 
cxd8561cq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)114 cxd8561cq_device::cxd8561cq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
115 	: psxgpu_device(mconfig, CXD8561CQ, tag, owner, clock, vram_size, cpu)
116 {
117 }
118 
cxd8561cq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)119 cxd8561cq_device::cxd8561cq_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
120 	: psxgpu_device(mconfig, CXD8561CQ, tag, owner, clock)
121 {
122 }
123 
cxd8654q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t vram_size,psxcpu_device * cpu)124 cxd8654q_device::cxd8654q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t vram_size, psxcpu_device *cpu)
125 	: psxgpu_device(mconfig, CXD8654Q, tag, owner, clock, vram_size, cpu)
126 {
127 }
128 
cxd8654q_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)129 cxd8654q_device::cxd8654q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
130 	: psxgpu_device(mconfig, CXD8654Q, tag, owner, clock)
131 {
132 }
133 
134 static const int m_p_n_nextpointlist4[] = { 1, 3, 0, 2 };
135 static const int m_p_n_prevpointlist4[] = { 2, 0, 3, 1 };
136 static const int m_p_n_nextpointlist4b[] = { 0, 3, 1, 2 };
137 static const int m_p_n_prevpointlist4b[] = { 0, 2, 3, 1 };
138 static const int m_p_n_nextpointlist3[] = { 1, 2, 0 };
139 static const int m_p_n_prevpointlist3[] = { 2, 0, 1 };
140 
141 #define SINT11( x ) ( ( (int32_t)( x ) << 21 ) >> 21 )
142 
143 #define COORD_X( a ) ( a.sw.l )
144 #define COORD_Y( a ) ( a.sw.h )
145 #define SIZE_W( a ) ( a.w.l )
146 #define SIZE_H( a ) ( a.w.h )
147 #define BGR_C( a ) ( a.b.h3 )
148 #define BGR_B( a ) ( a.b.h2 )
149 #define BGR_G( a ) ( a.b.h )
150 #define BGR_R( a ) ( a.b.l )
151 #define TEXTURE_V( a ) ( a.b.h )
152 #define TEXTURE_U( a ) ( a.b.l )
153 
verboselog(device_t & device,int n_level,const char * s_fmt,...)154 static inline void ATTR_PRINTF(3,4) verboselog( device_t& device, int n_level, const char *s_fmt, ... )
155 {
156 	if( VERBOSE_LEVEL >= n_level )
157 	{
158 		va_list v;
159 		char buf[ 32768 ];
160 		va_start( v, s_fmt );
161 		vsprintf( buf, s_fmt, v );
162 		va_end( v );
163 		device.logerror( "%s: %s", device.machine().describe_context(), buf );
164 	}
165 }
166 
167 #if PSXGPU_DEBUG_VIEWER
168 
DebugMeshInit()169 void psxgpu_device::DebugMeshInit()
170 {
171 	int width = screen().width();
172 	int height = screen().height();
173 
174 	m_debug.b_mesh = 0;
175 	m_debug.b_texture = 0;
176 	m_debug.n_interleave = -1;
177 	m_debug.b_clear = 1;
178 	m_debug.n_coord = 0;
179 	m_debug.n_skip = 0;
180 	m_debug.mesh = std::make_unique<bitmap_ind16>(width, height );
181 }
182 
DebugMesh(int n_coordx,int n_coordy)183 void psxgpu_device::DebugMesh( int n_coordx, int n_coordy )
184 {
185 	int width = screen().width();
186 	int height = screen().height();
187 
188 	n_coordx += m_n_displaystartx;
189 	n_coordy += n_displaystarty;
190 
191 	if( m_debug.b_clear )
192 	{
193 		m_debug.mesh->fill(0x0000);
194 		m_debug.b_clear = 0;
195 	}
196 
197 	int n_coord;
198 	int n_colour = 0x1f;
199 
200 	for( n_coord = 0; n_coord < m_debug.n_coord; n_coord++ )
201 	{
202 		if( n_coordx != m_debug.n_coordx[ n_coord ] ||
203 			n_coordy != m_debug.n_coordy[ n_coord ] )
204 		{
205 			break;
206 		}
207 	}
208 
209 	if( n_coord == m_debug.n_coord && m_debug.n_coord > 1 )
210 	{
211 		n_colour = 0xffff;
212 	}
213 
214 	for( n_coord = 0; n_coord < m_debug.n_coord; n_coord++ )
215 	{
216 		int32_t n_xstart = m_debug.n_coordx[ n_coord ];
217 		int32_t n_xend = n_coordx;
218 		int32_t n_xlen;
219 		if( n_xend > n_xstart )
220 		{
221 			n_xlen = n_xend - n_xstart;
222 		}
223 		else
224 		{
225 			n_xlen = n_xstart - n_xend;
226 		}
227 
228 		int32_t n_ystart = m_debug.n_coordy[ n_coord ];
229 		int32_t n_yend = n_coordy;
230 		int32_t n_ylen;
231 		if( n_yend > n_ystart )
232 		{
233 			n_ylen = n_yend - n_ystart;
234 		}
235 		else
236 		{
237 			n_ylen = n_ystart - n_yend;
238 		}
239 
240 		int32_t n_len;
241 		if( n_xlen > n_ylen )
242 		{
243 			n_len = n_xlen;
244 		}
245 		else
246 		{
247 			n_len = n_ylen;
248 		}
249 
250 		PAIR n_x; n_x.sw.h = n_xstart; n_x.sw.l = 0;
251 		PAIR n_y; n_y.sw.h = n_ystart; n_y.sw.l = 0;
252 
253 		if( n_len == 0 )
254 		{
255 			n_len = 1;
256 		}
257 
258 		int32_t n_dx = (int32_t)( ( n_xend << 16 ) - n_x.d ) / n_len;
259 		int32_t n_dy = (int32_t)( ( n_yend << 16 ) - n_y.d ) / n_len;
260 
261 		while( n_len > 0 )
262 		{
263 			if( (int16_t)n_x.w.h >= 0 &&
264 				(int16_t)n_y.w.h >= 0 &&
265 				(int16_t)n_x.w.h <= width - 1 &&
266 				(int16_t)n_y.w.h <= height - 1 )
267 			{
268 				if( m_debug.mesh->pix( n_y.w.h, n_x.w.h ) != 0xffff )
269 					m_debug.mesh->pix( n_y.w.h, n_x.w.h ) = n_colour;
270 			}
271 
272 			n_x.d += n_dx;
273 			n_y.d += n_dy;
274 			n_len--;
275 		}
276 	}
277 
278 	if( m_debug.n_coord < DEBUG_COORDS )
279 	{
280 		m_debug.n_coordx[ m_debug.n_coord ] = n_coordx;
281 		m_debug.n_coordy[ m_debug.n_coord ] = n_coordy;
282 		m_debug.n_coord++;
283 	}
284 }
285 
DebugMeshEnd()286 void psxgpu_device::DebugMeshEnd()
287 {
288 	m_debug.n_coord = 0;
289 }
290 
DebugCheckKeys()291 void psxgpu_device::DebugCheckKeys()
292 {
293 	if( machine().input().code_pressed_once( KEYCODE_M ) )
294 	{
295 		m_debug.b_mesh = !m_debug.b_mesh;
296 		updatevisiblearea();
297 	}
298 
299 	if( machine().input().code_pressed_once( KEYCODE_V ) )
300 	{
301 		m_debug.b_texture = !m_debug.b_texture;
302 		updatevisiblearea();
303 	}
304 
305 	if( machine().input().code_pressed_once( KEYCODE_I ) )
306 	{
307 		if( m_debug.b_texture )
308 		{
309 			m_debug.n_interleave++;
310 
311 			if( m_debug.n_interleave == 2 )
312 				m_debug.n_interleave = -1;
313 
314 			if( m_debug.n_interleave == -1 )
315 				popmessage( "interleave off" );
316 			else if( m_debug.n_interleave == 0 )
317 				popmessage( "4 bit interleave" );
318 			else if( m_debug.n_interleave == 1 )
319 				popmessage( "8 bit interleave" );
320 		}
321 		else
322 		{
323 			m_debug.n_skip++;
324 
325 			if( m_debug.n_skip > 15 )
326 				m_debug.n_skip = 0;
327 
328 			popmessage( "debug skip %d", m_debug.n_skip );
329 		}
330 	}
331 
332 #if 0
333 	if( machine().input().code_pressed_once( KEYCODE_D ) )
334 	{
335 		FILE *f = fopen( "dump.txt", "w" );
336 		for( int n_y = 256; n_y < 512; n_y++ )
337 			for( int n_x = 640; n_x < 1024; n_x++ )
338 				fprintf( f, "%04u,%04u = %04x\n", n_y, n_x, p_p_vram[ n_y ][ n_x ] );
339 		fclose( f );
340 	}
341 	if( machine().input().code_pressed_once( KEYCODE_S ) )
342 	{
343 		popmessage( "saving..." );
344 
345 		FILE *f = fopen( "VRAM.BIN", "wb" );
346 		for( int n_y = 0; n_y < 1024; n_y++ )
347 			fwrite( p_p_vram[ n_y ], 1024 * 2, 1, f );
348 		fclose( f );
349 	}
350 	if( machine().input().code_pressed_once( KEYCODE_L ) )
351 	{
352 		popmessage( "loading..." );
353 
354 		FILE *f = fopen( "VRAM.BIN", "rb" );
355 		for( int n_y = 0; n_y < 1024; n_y++ )
356 			fread( p_p_vram[ n_y ], 1024 * 2, 1, f );
357 		fclose( f );
358 	}
359 #endif
360 }
361 
DebugMeshDisplay(bitmap_rgb32 & bitmap,const rectangle & cliprect)362 int psxgpu_device::DebugMeshDisplay( bitmap_rgb32 &bitmap, const rectangle &cliprect )
363 {
364 	if( m_debug.b_mesh )
365 	{
366 		for( int y = cliprect.min_y; y <= cliprect.max_y; y++ )
367 			draw_scanline16( bitmap, cliprect.min_x, y, cliprect.max_x + 1 - cliprect.min_x, &m_debug.mesh->pix( y ), pens() );
368 	}
369 
370 	m_debug.b_clear = 1;
371 	return m_debug.b_mesh;
372 }
373 
DebugTextureDisplay(bitmap_rgb32 & bitmap)374 int psxgpu_device::DebugTextureDisplay( bitmap_rgb32 &bitmap )
375 {
376 	if( m_debug.b_texture )
377 	{
378 		int width = screen().width();
379 		int height = screen().height();
380 
381 		for( int n_y = 0; n_y < height; n_y++ )
382 		{
383 			uint16_t p_n_interleave[ 1024 ];
384 
385 			for( int n_x = 0; n_x < width; n_x++ )
386 			{
387 				int n_xi;
388 				int n_yi;
389 
390 				if( m_debug.n_interleave == 0 )
391 				{
392 					n_xi = ( n_x & ~0x3c ) + ( ( n_y << 2 ) & 0x3c );
393 					n_yi = ( n_y & ~0xf ) + ( ( n_x >> 2 ) & 0xf );
394 				}
395 				else if( m_debug.n_interleave == 1 )
396 				{
397 					n_xi = ( n_x & ~0x78 ) + ( ( n_x << 3 ) & 0x40 ) + ( ( n_y << 3 ) & 0x38 );
398 					n_yi = ( n_y & ~0x7 ) + ( ( n_x >> 4 ) & 0x7 );
399 				}
400 				else
401 				{
402 					n_xi = n_x;
403 					n_yi = n_y;
404 				}
405 
406 				p_n_interleave[ n_x ] = p_p_vram[ n_yi ][ n_xi ];
407 			}
408 
409 			draw_scanline16( bitmap, 0, n_y, width, p_n_interleave, pens() );
410 		}
411 	}
412 
413 	return m_debug.b_texture;
414 }
415 
416 #endif
417 
updatevisiblearea()418 void psxgpu_device::updatevisiblearea()
419 {
420 	rectangle visarea;
421 	double refresh;
422 
423 	if( ( n_gpustatus & ( 1 << 0x14 ) ) != 0 )
424 	{
425 		/* pal */
426 		refresh = 50; // TODO: it's not exactly 50Hz
427 		switch( ( n_gpustatus >> 0x13 ) & 1 )
428 		{
429 		case 0:
430 			n_screenheight = 256;
431 			break;
432 		case 1:
433 			n_screenheight = 512;
434 			break;
435 		}
436 	}
437 	else
438 	{
439 		/* ntsc */
440 		// refresh rate derived from 53.693175MHz
441 		// TODO: emulate display timings at lower level
442 		switch( ( n_gpustatus >> 0x13 ) & 1 )
443 		{
444 		case 0:
445 			refresh = 59.8260978565;
446 			n_screenheight = 240;
447 			break;
448 		case 1:
449 			refresh = 59.9400523286;
450 			n_screenheight = 480;
451 			break;
452 		}
453 	}
454 	switch( ( n_gpustatus >> 0x11 ) & 3 )
455 	{
456 	case 0:
457 		switch( ( n_gpustatus >> 0x10 ) & 1 )
458 		{
459 		case 0:
460 			n_screenwidth = 256;
461 			break;
462 		case 1:
463 			n_screenwidth = 368;
464 			break;
465 		}
466 		break;
467 	case 1:
468 		switch( ( n_gpustatus >> 0x10 ) & 1 )
469 		{
470 		case 0:
471 			n_screenwidth = 320;
472 			break;
473 		case 1:
474 			n_screenwidth = 384;
475 			break;
476 		}
477 		break;
478 	case 2:
479 		n_screenwidth = 512;
480 		break;
481 	case 3:
482 		n_screenwidth = 640;
483 		break;
484 	}
485 
486 #if PSXGPU_DEBUG_VIEWER
487 	if( m_debug.b_mesh || m_debug.b_texture )
488 	{
489 		n_screenheight = 1024;
490 		n_screenwidth = 1024;
491 	}
492 #endif
493 
494 	visarea.set(0, n_screenwidth - 1, 0, n_screenheight - 1);
495 	screen().configure(n_screenwidth, n_screenheight, visarea, HZ_TO_ATTOSECONDS(refresh));
496 }
497 
psx_gpu_init(int n_gputype)498 void psxgpu_device::psx_gpu_init( int n_gputype )
499 {
500 	int width = 1024;
501 	int height = ( vramSize / width ) / sizeof( uint16_t );
502 
503 	m_n_gputype = n_gputype;
504 
505 #if PSXGPU_DEBUG_VIEWER
506 	DebugMeshInit();
507 #endif
508 
509 	n_gpustatus = 0x14802000;
510 	n_gpuinfo = 0;
511 	n_gpu_buffer_offset = 0;
512 	n_lightgun_x = 0;
513 	n_lightgun_y = 0;
514 	b_reverseflag = 0;
515 
516 	p_vram = make_unique_clear<uint16_t[]>(width * height );
517 
518 	for( int n_line = 0; n_line < 1024; n_line++ )
519 	{
520 		p_p_vram[ n_line ] = &p_vram[ ( n_line % height ) * width ];
521 	}
522 
523 	for( int n_level = 0; n_level < MAX_LEVEL; n_level++ )
524 	{
525 		for( int n_shade = 0; n_shade < MAX_SHADE; n_shade++ )
526 		{
527 			/* shaded */
528 			int n_shaded = ( n_level * n_shade ) / MID_SHADE;
529 			if( n_shaded > MAX_LEVEL - 1 )
530 			{
531 				n_shaded = MAX_LEVEL - 1;
532 			}
533 			p_n_redshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
534 			p_n_greenshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded << 5;
535 			p_n_blueshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded << 10;
536 
537 			/* 1/4 x transparency */
538 			n_shaded = ( n_level * n_shade ) / MID_SHADE;
539 			n_shaded >>= 2;
540 			if( n_shaded > MAX_LEVEL - 1 )
541 			{
542 				n_shaded = MAX_LEVEL - 1;
543 			}
544 			p_n_f025[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
545 
546 			/* 1/2 x transparency */
547 			n_shaded = ( n_level * n_shade ) / MID_SHADE;
548 			n_shaded >>= 1;
549 			if( n_shaded > MAX_LEVEL - 1 )
550 			{
551 				n_shaded = MAX_LEVEL - 1;
552 			}
553 			p_n_f05[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
554 
555 			/* 1 x transparency */
556 			n_shaded = ( n_level * n_shade ) / MID_SHADE;
557 			if( n_shaded > MAX_LEVEL - 1 )
558 			{
559 				n_shaded = MAX_LEVEL - 1;
560 			}
561 			p_n_f1[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
562 		}
563 	}
564 
565 	for( int n_level = 0; n_level < 0x10000; n_level++ )
566 	{
567 		p_n_redlevel[ n_level ] = ( n_level & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
568 		p_n_greenlevel[ n_level ] = ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
569 		p_n_bluelevel[ n_level ] = ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
570 
571 		/* 0.5 * background */
572 		p_n_redb05[ n_level ] = ( ( n_level & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
573 		p_n_greenb05[ n_level ] = ( ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
574 		p_n_blueb05[ n_level ] = ( ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
575 
576 		/* 1 * background */
577 		p_n_redb1[ n_level ] = ( n_level & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
578 		p_n_greenb1[ n_level ] = ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
579 		p_n_blueb1[ n_level ] = ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
580 
581 		/* 24bit color */
582 		p_n_g0r0[ n_level ] = ( ( ( n_level >> 8 ) & 0xff ) << 8 ) | ( ( ( n_level >> 0 ) & 0xff ) << 16 );
583 		p_n_b0[ n_level ] = ( ( n_level >> 0 ) & 0xff ) << 0;
584 		p_n_r1[ n_level ] = ( ( n_level >> 8 ) & 0xff ) << 16;
585 		p_n_b1g1[ n_level ] = ( ( ( n_level >> 8 ) & 0xff ) << 0 ) | ( ( ( n_level >> 0 ) & 0xff ) << 8 );
586 	}
587 
588 	for( int n_level = 0; n_level < MAX_LEVEL; n_level++ )
589 	{
590 		for( int n_level2 = 0; n_level2 < MAX_LEVEL; n_level2++ )
591 		{
592 			/* add transparency */
593 			int n_shaded = ( n_level + n_level2 );
594 			if( n_shaded > MAX_LEVEL - 1 )
595 			{
596 				n_shaded = MAX_LEVEL - 1;
597 			}
598 			p_n_redaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded;
599 			p_n_greenaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 5;
600 			p_n_blueaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 10;
601 
602 			/* sub transparency */
603 			n_shaded = ( n_level - n_level2 );
604 			if( n_shaded < 0 )
605 			{
606 				n_shaded = 0;
607 			}
608 			p_n_redsubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded;
609 			p_n_greensubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 5;
610 			p_n_bluesubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 10;
611 		}
612 	}
613 
614 	save_pointer(NAME(p_vram), width * height );
615 	save_item(NAME(m_packet.n_entry));
616 	save_item(NAME(n_gpu_buffer_offset));
617 	save_item(NAME(n_vramx));
618 	save_item(NAME(n_vramy));
619 	save_item(NAME(n_twy));
620 	save_item(NAME(n_twx));
621 	save_item(NAME(n_tww));
622 	save_item(NAME(n_drawarea_x1));
623 	save_item(NAME(n_drawarea_y1));
624 	save_item(NAME(n_drawarea_x2));
625 	save_item(NAME(n_drawarea_y2));
626 	save_item(NAME(n_horiz_disstart));
627 	save_item(NAME(n_horiz_disend));
628 	save_item(NAME(n_vert_disstart));
629 	save_item(NAME(n_vert_disend));
630 	save_item(NAME(b_reverseflag));
631 	save_item(NAME(n_drawoffset_x));
632 	save_item(NAME(n_drawoffset_y));
633 	save_item(NAME(m_n_displaystartx));
634 	save_item(NAME(n_displaystarty));
635 	save_item(NAME(n_gpustatus));
636 	save_item(NAME(n_gpuinfo));
637 	save_item(NAME(n_lightgun_x));
638 	save_item(NAME(n_lightgun_y));
639 	save_item(NAME(m_n_tx));
640 	save_item(NAME(m_n_ty));
641 	save_item(NAME(n_abr));
642 	save_item(NAME(n_tp));
643 	save_item(NAME(n_ix));
644 	save_item(NAME(n_iy));
645 	save_item(NAME(n_ti));
646 	save_item(NAME(m_draw_stp));
647 	save_item(NAME(m_check_stp));
648 }
649 
device_post_load()650 void psxgpu_device::device_post_load()
651 {
652 	updatevisiblearea();
653 }
654 
update_screen(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)655 uint32_t psxgpu_device::update_screen(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
656 {
657 	uint32_t n_x;
658 	uint32_t n_y;
659 	int n_top;
660 	int n_line;
661 	int n_lines;
662 	int n_left;
663 	int n_column;
664 	int n_columns;
665 	int n_displaystartx;
666 	int n_overscantop;
667 	int n_overscanleft;
668 
669 #if PSXGPU_DEBUG_VIEWER
670 	if( DebugMeshDisplay( bitmap, cliprect ) )
671 	{
672 		return 0;
673 	}
674 	if( DebugTextureDisplay( bitmap ) )
675 	{
676 		return 0;
677 	}
678 #endif
679 
680 	if( ( n_gpustatus & ( 1 << 0x17 ) ) != 0 )
681 	{
682 		/* todo: only draw to necessary area */
683 		bitmap.fill(0, cliprect);
684 	}
685 	else
686 	{
687 		if( b_reverseflag )
688 		{
689 			n_displaystartx = ( 1023 - m_n_displaystartx );
690 			/* todo: make this flip the screen, in the meantime.. */
691 			n_displaystartx -= ( n_screenwidth - 1 );
692 		}
693 		else
694 		{
695 			n_displaystartx = m_n_displaystartx;
696 		}
697 
698 		if( ( n_gpustatus & ( 1 << 0x14 ) ) != 0 )
699 		{
700 			/* pal */
701 			n_overscantop = 0x23;
702 			n_overscanleft = 0x27e;
703 		}
704 		else
705 		{
706 			/* ntsc */
707 			n_overscantop = 0x10;
708 			n_overscanleft = 0x260;
709 		}
710 
711 		n_top = (int32_t)n_vert_disstart - n_overscantop;
712 		n_lines = (int32_t)n_vert_disend - (int32_t)n_vert_disstart;
713 		if( n_top < 0 )
714 		{
715 			n_y = -n_top;
716 			n_lines += n_top;
717 		}
718 		else
719 		{
720 			n_y = 0;
721 
722 			/* draw top border */
723 			rectangle clip(cliprect.left(), cliprect.right(), cliprect.top(), n_top);
724 			bitmap.fill(0, clip);
725 		}
726 		if( ( n_gpustatus & ( 1 << 0x16 ) ) != 0 )
727 		{
728 			/* interlaced */
729 			n_lines *= 2;
730 		}
731 		if( n_lines > n_screenheight - ( n_y + n_top ) )
732 		{
733 			n_lines = n_screenheight - ( n_y + n_top );
734 		}
735 		else
736 		{
737 			/* draw bottom border */
738 			rectangle clip(cliprect.left(), cliprect.right(), n_y + n_top + n_lines, cliprect.bottom());
739 			bitmap.fill(0, clip);
740 		}
741 
742 		n_left = ( ( (int32_t)n_horiz_disstart - n_overscanleft ) * (int32_t)n_screenwidth ) / 2560;
743 		n_columns = ( ( ( (int32_t)n_horiz_disend - n_horiz_disstart ) * (int32_t)n_screenwidth ) / 2560 );
744 		if( n_left < 0 )
745 		{
746 			n_x = -n_left;
747 			n_columns += n_left;
748 		}
749 		else
750 		{
751 			n_x = 0;
752 
753 			/* draw left border */
754 			rectangle clip(cliprect.left(), n_x + n_left, cliprect.top(), cliprect.bottom());
755 			bitmap.fill(0, clip);
756 		}
757 		if( n_columns > n_screenwidth - ( n_x + n_left ) )
758 		{
759 			n_columns = n_screenwidth - ( n_x + n_left );
760 		}
761 		else
762 		{
763 			/* draw right border */
764 			rectangle clip(n_x + n_left + n_columns, cliprect.right(), cliprect.top(), cliprect.bottom());
765 			bitmap.fill(0, clip);
766 		}
767 
768 		if( ( n_gpustatus & ( 1 << 0x15 ) ) != 0 )
769 		{
770 			/* 24bit */
771 			n_line = n_lines;
772 			while( n_line > 0 )
773 			{
774 				uint16_t *p_n_src = p_p_vram[ n_y + n_displaystarty ] + 3 * n_x + n_displaystartx;
775 				uint32_t *p_n_dest = &bitmap.pix(n_y + n_top, n_x + n_left);
776 
777 				n_column = n_columns;
778 				while( n_column > 0 )
779 				{
780 					uint32_t n_g0r0 = *( p_n_src++ );
781 					uint32_t n_r1b0 = *( p_n_src++ );
782 					uint32_t n_b1g1 = *( p_n_src++ );
783 
784 					*( p_n_dest++ ) = p_n_g0r0[ n_g0r0 ] | p_n_b0[ n_r1b0 ];
785 					n_column--;
786 					if( n_column > 0 )
787 					{
788 						*( p_n_dest++ ) = p_n_r1[ n_r1b0 ] | p_n_b1g1[ n_b1g1 ];
789 						n_column--;
790 					}
791 				}
792 				n_y++;
793 				n_line--;
794 			}
795 		}
796 		else
797 		{
798 			/* 15bit */
799 			n_line = n_lines;
800 			while( n_line > 0 )
801 			{
802 				draw_scanline16( bitmap, n_x + n_left, n_y + n_top, n_columns, p_p_vram[ ( n_y + n_displaystarty ) & 1023 ] + n_x + n_displaystartx, pens() );
803 				n_y++;
804 				n_line--;
805 			}
806 		}
807 	}
808 	return 0;
809 }
810 
811 #define WRITE_PIXEL( p ) \
812 	{ \
813 		if( !m_check_stp || ( *( p_vram ) & 0x8000 ) == 0 ) \
814 		{ \
815 			if( m_draw_stp ) \
816 				*( p_vram ) = ( p ) | 0x8000; \
817 			else \
818 				*( p_vram ) = p; \
819 		} \
820 	}
821 
822 /*
823 type 1
824 f  e| d| c  b| a  9| 8  7| 6  5| 4| 3  2  1  0
825     |ti|     |   tp|  abr|   ty|  |         tx
826 */
827 
828 /*
829 type 2
830 f  e| d  c| b| a  9| 8  7| 6  5| 4| 3  2  1  0
831     |iy|ix|ty|     |   tp|  abr|ty|         tx
832 */
833 
decode_tpage(uint32_t tpage)834 void psxgpu_device::decode_tpage( uint32_t tpage )
835 {
836 	if( m_n_gputype == 2 )
837 	{
838 		n_gpustatus = ( n_gpustatus & 0xffff7800 ) | ( tpage & 0x7ff ) | ( ( tpage & 0x800 ) << 4 );
839 
840 		m_n_tx = ( tpage & 0x0f ) << 6;
841 		m_n_ty = ( ( tpage & 0x10 ) << 4 ) | ( ( tpage & 0x800 ) >> 2 );
842 		n_abr = ( tpage & 0x60 ) >> 5;
843 		n_tp = ( tpage & 0x180 ) >> 7;
844 		n_ix = ( tpage & 0x1000 ) >> 12;
845 		n_iy = ( tpage & 0x2000 ) >> 13;
846 		n_ti = 0;
847 		if( ( tpage & ~0x39ff ) != 0 )
848 		{
849 			verboselog( *this, 1, "not handled: draw mode %08x\n", tpage & ~0x39ff );
850 		}
851 		if( n_tp == 3 )
852 		{
853 			verboselog( *this, 0, "not handled: tp == 3\n" );
854 		}
855 	}
856 	else
857 	{
858 		// TODO: confirm status bits on real type 1 gpu
859 		n_gpustatus = ( n_gpustatus & 0xffffe000 ) | ( tpage & 0x1fff );
860 
861 		m_n_tx = ( tpage & 0x0f ) << 6;
862 		m_n_ty = ( ( tpage & 0x60 ) << 3 );
863 		n_abr = ( tpage & 0x180 ) >> 7;
864 		n_tp = ( tpage & 0x600 ) >> 9;
865 		n_ti = ( tpage & 0x2000 ) >> 13;
866 		n_ix = 0;
867 		n_iy = 0;
868 		if( ( tpage & ~0x27ef ) != 0 )
869 		{
870 			verboselog( *this, 1, "not handled: draw mode %08x\n", tpage & ~0x27ef );
871 		}
872 		if( n_tp == 3 )
873 		{
874 			verboselog( *this, 0, "not handled: tp == 3\n" );
875 		}
876 		else if( n_tp == 2 && n_ti != 0 )
877 		{
878 			verboselog( *this, 0, "not handled: interleaved 15 bit texture\n" );
879 		}
880 	}
881 }
882 
883 #define SPRITESETUP \
884 	int n_dv; \
885 	if( n_iy != 0 ) \
886 	{ \
887 		n_dv = -1; \
888 	} \
889 	else \
890 	{ \
891 		n_dv = 1; \
892 	} \
893 	int n_du; \
894 	if( n_ix != 0 ) \
895 	{ \
896 		n_du = -1; \
897 	} \
898 	else \
899 	{ \
900 		n_du = 1; \
901 	}
902 
903 #define TRANSPARENCYSETUP \
904 	uint16_t *p_n_f = p_n_f1; \
905 	uint16_t *p_n_redb = p_n_redb1; \
906 	uint16_t *p_n_greenb = p_n_greenb1; \
907 	uint16_t *p_n_blueb = p_n_blueb1; \
908 	uint16_t *p_n_redtrans = p_n_redaddtrans; \
909 	uint16_t *p_n_greentrans = p_n_greenaddtrans; \
910 	uint16_t *p_n_bluetrans = p_n_blueaddtrans; \
911 	\
912 	switch( n_cmd & 0x02 ) \
913 	{ \
914 	case 0x02: \
915 		switch( n_abr ) \
916 		{ \
917 		case 0x00: \
918 			p_n_f = p_n_f05; \
919 			p_n_redb = p_n_redb05; \
920 			p_n_greenb = p_n_greenb05; \
921 			p_n_blueb = p_n_blueb05; \
922 			p_n_redtrans = p_n_redaddtrans; \
923 			p_n_greentrans = p_n_greenaddtrans; \
924 			p_n_bluetrans = p_n_blueaddtrans; \
925 			verboselog( *this, 2, "Transparency Mode: 0.5*B + 0.5*F\n" ); \
926 			break; \
927 		case 0x01: \
928 			p_n_f = p_n_f1; \
929 			p_n_redb = p_n_redb1; \
930 			p_n_greenb = p_n_greenb1; \
931 			p_n_blueb = p_n_blueb1; \
932 			p_n_redtrans = p_n_redaddtrans; \
933 			p_n_greentrans = p_n_greenaddtrans; \
934 			p_n_bluetrans = p_n_blueaddtrans; \
935 			verboselog( *this, 2, "Transparency Mode: 1.0*B + 1.0*F\n" ); \
936 			break; \
937 		case 0x02: \
938 			p_n_f = p_n_f1; \
939 			p_n_redb = p_n_redb1; \
940 			p_n_greenb = p_n_greenb1; \
941 			p_n_blueb = p_n_blueb1; \
942 			p_n_redtrans = p_n_redsubtrans; \
943 			p_n_greentrans = p_n_greensubtrans; \
944 			p_n_bluetrans = p_n_bluesubtrans; \
945 			verboselog( *this, 2, "Transparency Mode: 1.0*B - 1.0*F\n" ); \
946 			break; \
947 		case 0x03: \
948 			p_n_f = p_n_f025; \
949 			p_n_redb = p_n_redb1; \
950 			p_n_greenb = p_n_greenb1; \
951 			p_n_blueb = p_n_blueb1; \
952 			p_n_redtrans = p_n_redaddtrans; \
953 			p_n_greentrans = p_n_greenaddtrans; \
954 			p_n_bluetrans = p_n_blueaddtrans; \
955 			verboselog( *this, 2, "Transparency Mode: 1.0*B + 0.25*F\n" ); \
956 			break; \
957 		} \
958 		break; \
959 	}
960 
961 #define SOLIDSETUP \
962 	TRANSPARENCYSETUP
963 
964 #define TEXTURESETUP \
965 	int n_tx = m_n_tx; \
966 	int n_ty = m_n_ty; \
967 	uint16_t *p_clut = p_p_vram[ n_cluty ] + n_clutx; \
968 	switch( n_tp ) \
969 	{ \
970 	case 0: \
971 		n_tx += n_twx >> 2; \
972 		n_ty += n_twy; \
973 		break; \
974 	case 1: \
975 		n_tx += n_twx >> 1; \
976 		n_ty += n_twy; \
977 		break; \
978 	case 2: \
979 		n_tx += n_twx >> 0; \
980 		n_ty += n_twy; \
981 		break; \
982 	} \
983 	TRANSPARENCYSETUP
984 
985 #define FLATPOLYGONUPDATE
986 #define FLATRECTANGEUPDATE
987 #define GOURAUDPOLYGONUPDATE \
988 	n_r.d += n_dr; \
989 	n_g.d += n_dg; \
990 	n_b.d += n_db;
991 
992 #define SOLIDFILL( PIXELUPDATE ) \
993 	if( n_distance > ( (int32_t)n_drawarea_x2 - drawx ) + 1 ) \
994 	{ \
995 		n_distance = ( n_drawarea_x2 - drawx ) + 1; \
996 	} \
997 	uint16_t *p_vram = p_p_vram[ drawy ] + drawx; \
998 	\
999 	switch( n_cmd & 0x02 ) \
1000 	{ \
1001 	case 0x00: \
1002 		/* transparency off */ \
1003 		while( n_distance > 0 ) \
1004 		{ \
1005 			WRITE_PIXEL( \
1006 				p_n_redshade[ MID_LEVEL | n_r.w.h ] | \
1007 				p_n_greenshade[ MID_LEVEL | n_g.w.h ] | \
1008 				p_n_blueshade[ MID_LEVEL | n_b.w.h ] ) \
1009 			p_vram++; \
1010 			PIXELUPDATE \
1011 			n_distance--; \
1012 		} \
1013 		break; \
1014 	case 0x02: \
1015 		/* transparency on */ \
1016 		while( n_distance > 0 ) \
1017 		{ \
1018 			WRITE_PIXEL( \
1019 				p_n_redtrans[ p_n_f[ MID_LEVEL | n_r.w.h ] | p_n_redb[ *( p_vram ) ] ] | \
1020 				p_n_greentrans[ p_n_f[ MID_LEVEL | n_g.w.h ] | p_n_greenb[ *( p_vram ) ] ] | \
1021 				p_n_bluetrans[ p_n_f[ MID_LEVEL | n_b.w.h ] | p_n_blueb[ *( p_vram ) ] ] ) \
1022 			p_vram++; \
1023 			PIXELUPDATE \
1024 			n_distance--; \
1025 		} \
1026 		break; \
1027 	}
1028 
1029 #define FLATTEXTUREDPOLYGONUPDATE \
1030 	n_u.d += n_du; \
1031 	n_v.d += n_dv;
1032 
1033 #define GOURAUDTEXTUREDPOLYGONUPDATE \
1034 	n_r.d += n_dr; \
1035 	n_g.d += n_dg; \
1036 	n_b.d += n_db; \
1037 	n_u.d += n_du; \
1038 	n_v.d += n_dv;
1039 
1040 #define FLATTEXTUREDRECTANGLEUPDATE \
1041 	n_u += n_du;
1042 
1043 #define TEXTURE_LOOP \
1044 	while( n_distance > 0 ) \
1045 	{
1046 #define TEXTURE_ENDLOOP \
1047 	}
1048 
1049 #define TEXTURE4BIT( TXV, TXU ) \
1050 	TEXTURE_LOOP \
1051 		uint16_t n_bgr = p_clut[ ( *( p_p_vram[ n_ty + TXV ] + n_tx + ( TXU >> 2 ) ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f ];
1052 
1053 #define TEXTURE8BIT( TXV, TXU ) \
1054 	TEXTURE_LOOP \
1055 		uint16_t n_bgr = p_clut[ ( *( p_p_vram[ n_ty + TXV ] + n_tx + ( TXU >> 1 ) ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff ];
1056 
1057 #define TEXTURE15BIT( TXV, TXU ) \
1058 	TEXTURE_LOOP \
1059 		uint16_t n_bgr = *( p_p_vram[ n_ty + TXV ] + n_tx + TXU );
1060 
1061 #define TEXTUREWINDOW4BIT( TXV, TXU ) TEXTURE4BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1062 #define TEXTUREWINDOW8BIT( TXV, TXU ) TEXTURE8BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1063 #define TEXTUREWINDOW15BIT( TXV, TXU ) TEXTURE15BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1064 
1065 #define TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
1066 	TEXTURE_LOOP \
1067 		int n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); \
1068 		int n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); \
1069 		uint16_t n_bgr = p_clut[ ( *( p_p_vram[ n_ty + n_yi ] + n_tx + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f ];
1070 
1071 #define TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
1072 	TEXTURE_LOOP \
1073 		int n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); \
1074 		int n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); \
1075 		uint16_t n_bgr = p_clut[ ( *( p_p_vram[ n_ty + n_yi ] + n_tx + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff ];
1076 
1077 #define TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
1078 	TEXTURE_LOOP \
1079 		int n_xi = TXU; \
1080 		int n_yi = TXV; \
1081 		uint16_t n_bgr = *( p_p_vram[ n_ty + n_yi ] + n_tx + n_xi );
1082 
1083 #define TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) TEXTUREINTERLEAVED4BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1084 #define TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) TEXTUREINTERLEAVED8BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1085 #define TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) TEXTUREINTERLEAVED15BIT( ( TXV & n_twh ), ( TXU & n_tww ) )
1086 
1087 #define SHADEDPIXEL( PIXELUPDATE ) \
1088 		if( n_bgr != 0 ) \
1089 		{ \
1090 			WRITE_PIXEL( \
1091 				p_n_redshade[ p_n_redlevel[ n_bgr ] | n_r.w.h ] | \
1092 				p_n_greenshade[ p_n_greenlevel[ n_bgr ] | n_g.w.h ] | \
1093 				p_n_blueshade[ p_n_bluelevel[ n_bgr ] | n_b.w.h ] | \
1094 				( n_bgr & 0x8000 ) ) \
1095 		} \
1096 		p_vram++; \
1097 		PIXELUPDATE \
1098 		n_distance--; \
1099 	TEXTURE_ENDLOOP
1100 
1101 #define TRANSPARENTPIXEL( PIXELUPDATE ) \
1102 		if( n_bgr != 0 ) \
1103 		{ \
1104 			if( ( n_bgr & 0x8000 ) != 0 ) \
1105 			{ \
1106 				WRITE_PIXEL( \
1107 					p_n_redtrans[ p_n_f[ p_n_redlevel[ n_bgr ] | n_r.w.h ] | p_n_redb[ *( p_vram ) ] ] | \
1108 					p_n_greentrans[ p_n_f[ p_n_greenlevel[ n_bgr ] | n_g.w.h ] | p_n_greenb[ *( p_vram ) ] ] | \
1109 					p_n_bluetrans[ p_n_f[ p_n_bluelevel[ n_bgr ] | n_b.w.h ] | p_n_blueb[ *( p_vram ) ] ] | \
1110 					0x8000 ) \
1111 			} \
1112 			else \
1113 			{ \
1114 				WRITE_PIXEL( \
1115 					p_n_redshade[ p_n_redlevel[ n_bgr ] | n_r.w.h ] | \
1116 					p_n_greenshade[ p_n_greenlevel[ n_bgr ] | n_g.w.h ] | \
1117 					p_n_blueshade[ p_n_bluelevel[ n_bgr ] | n_b.w.h ] ) \
1118 			} \
1119 		} \
1120 		p_vram++; \
1121 		PIXELUPDATE \
1122 		n_distance--; \
1123 	TEXTURE_ENDLOOP
1124 
1125 #define TEXTUREFILL( PIXELUPDATE, TXU, TXV ) \
1126 	if( n_distance > ( (int32_t)n_drawarea_x2 - drawx ) + 1 ) \
1127 	{ \
1128 		n_distance = ( n_drawarea_x2 - drawx ) + 1; \
1129 	} \
1130 	uint16_t *p_vram = p_p_vram[ drawy ] + drawx; \
1131 	\
1132 	if( n_ti != 0 ) \
1133 	{ \
1134 		/* interleaved texture */ \
1135 		if( n_twh != 255 || \
1136 			n_tww != 255 || \
1137 			n_twx != 0 || \
1138 			n_twy != 0 ) \
1139 		{ \
1140 			/* texture window */ \
1141 			switch( n_cmd & 0x02 ) \
1142 			{ \
1143 			case 0x00: \
1144 				/* shading */ \
1145 				switch( n_tp ) \
1146 				{ \
1147 				case 0: \
1148 					/* 4 bit clut */ \
1149 					TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) \
1150 					SHADEDPIXEL( PIXELUPDATE ) \
1151 					break; \
1152 				case 1: \
1153 					/* 8 bit clut */ \
1154 					TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) \
1155 					SHADEDPIXEL( PIXELUPDATE ) \
1156 					break; \
1157 				case 2: \
1158 					/* 15 bit */ \
1159 					TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) \
1160 					SHADEDPIXEL( PIXELUPDATE ) \
1161 					break; \
1162 				} \
1163 				break; \
1164 			case 0x02: \
1165 				/* semi transparency */ \
1166 				switch( n_tp ) \
1167 				{ \
1168 				case 0: \
1169 					/* 4 bit clut */ \
1170 					TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) \
1171 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1172 					break; \
1173 				case 1: \
1174 					/* 8 bit clut */ \
1175 					TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) \
1176 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1177 					break; \
1178 				case 2: \
1179 					/* 15 bit */ \
1180 					TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) \
1181 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1182 					break; \
1183 				} \
1184 				break; \
1185 			} \
1186 		} \
1187 		else \
1188 		{ \
1189 			/* no texture window */ \
1190 			switch( n_cmd & 0x02 ) \
1191 			{ \
1192 			case 0x00: \
1193 				/* shading */ \
1194 				switch( n_tp ) \
1195 				{ \
1196 				case 0: \
1197 					/* 4 bit clut */ \
1198 					TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
1199 					SHADEDPIXEL( PIXELUPDATE ) \
1200 					break; \
1201 				case 1: \
1202 					/* 8 bit clut */ \
1203 					TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
1204 					SHADEDPIXEL( PIXELUPDATE ) \
1205 					break; \
1206 				case 2: \
1207 					/* 15 bit */ \
1208 					TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
1209 					SHADEDPIXEL( PIXELUPDATE ) \
1210 					break; \
1211 				} \
1212 				break; \
1213 			case 0x02: \
1214 				/* semi transparency */ \
1215 				switch( n_tp ) \
1216 				{ \
1217 				case 0: \
1218 					/* 4 bit clut */ \
1219 					TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
1220 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1221 					break; \
1222 				case 1: \
1223 					/* 8 bit clut */ \
1224 					TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
1225 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1226 					break; \
1227 				case 2: \
1228 					/* 15 bit */ \
1229 					TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
1230 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1231 					break; \
1232 				} \
1233 				break; \
1234 			} \
1235 		} \
1236 	} \
1237 	else \
1238 	{ \
1239 		/* standard texture */ \
1240 		if( n_twh != 255 || \
1241 			n_tww != 255 || \
1242 			n_twx != 0 || \
1243 			n_twy != 0 ) \
1244 		{ \
1245 			/* texture window */ \
1246 			switch( n_cmd & 0x02 ) \
1247 			{ \
1248 			case 0x00: \
1249 				/* shading */ \
1250 				switch( n_tp ) \
1251 				{ \
1252 				case 0: \
1253 					/* 4 bit clut */ \
1254 					TEXTUREWINDOW4BIT( TXV, TXU ) \
1255 					SHADEDPIXEL( PIXELUPDATE ) \
1256 					break; \
1257 				case 1: \
1258 					/* 8 bit clut */ \
1259 					TEXTUREWINDOW8BIT( TXV, TXU ) \
1260 					SHADEDPIXEL( PIXELUPDATE ) \
1261 					break; \
1262 				case 2: \
1263 					/* 15 bit */ \
1264 					TEXTUREWINDOW15BIT( TXV, TXU ) \
1265 					SHADEDPIXEL( PIXELUPDATE ) \
1266 					break; \
1267 				} \
1268 				break; \
1269 			case 0x02: \
1270 				/* semi transparency */ \
1271 				switch( n_tp ) \
1272 				{ \
1273 				case 0: \
1274 					/* 4 bit clut */ \
1275 					TEXTUREWINDOW4BIT( TXV, TXU ) \
1276 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1277 					break; \
1278 				case 1: \
1279 					/* 8 bit clut */ \
1280 					TEXTUREWINDOW8BIT( TXV, TXU ) \
1281 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1282 					break; \
1283 				case 2: \
1284 					/* 15 bit */ \
1285 					TEXTUREWINDOW15BIT( TXV, TXU ) \
1286 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1287 					break; \
1288 				} \
1289 				break; \
1290 			} \
1291 		} \
1292 		else \
1293 		{ \
1294 			/* no texture window */ \
1295 			switch( n_cmd & 0x02 ) \
1296 			{ \
1297 			case 0x00: \
1298 				/* shading */ \
1299 				switch( n_tp ) \
1300 				{ \
1301 				case 0: \
1302 					TEXTURE4BIT( TXV, TXU ) \
1303 					SHADEDPIXEL( PIXELUPDATE ) \
1304 					break; \
1305 				case 1: \
1306 					/* 8 bit clut */ \
1307 					TEXTURE8BIT( TXV, TXU ) \
1308 					SHADEDPIXEL( PIXELUPDATE ) \
1309 					break; \
1310 				case 2: \
1311 					/* 15 bit */ \
1312 					TEXTURE15BIT( TXV, TXU ) \
1313 					SHADEDPIXEL( PIXELUPDATE ) \
1314 					break; \
1315 				} \
1316 				break; \
1317 			case 0x02: \
1318 				/* semi transparency */ \
1319 				switch( n_tp ) \
1320 				{ \
1321 				case 0: \
1322 					/* 4 bit clut */ \
1323 					TEXTURE4BIT( TXV, TXU ) \
1324 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1325 					break; \
1326 				case 1: \
1327 					/* 8 bit clut */ \
1328 					TEXTURE8BIT( TXV, TXU ) \
1329 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1330 					break; \
1331 				case 2: \
1332 					/* 15 bit */ \
1333 					TEXTURE15BIT( TXV, TXU ) \
1334 					TRANSPARENTPIXEL( PIXELUPDATE ) \
1335 					break; \
1336 				} \
1337 				break; \
1338 			} \
1339 		} \
1340 	}
1341 
1342 #define GET_COORD( a ) \
1343 	a.sw.l = SINT11( COORD_X( a ) ); \
1344 	a.sw.h = SINT11( COORD_Y( a ) );
1345 
CullVertex(int a,int b)1346 static inline int CullVertex( int a, int b )
1347 {
1348 	int d = a - b;
1349 	if( d < -1023 || d > 1023 )
1350 	{
1351 		return 1;
1352 	}
1353 
1354 	return 0;
1355 }
1356 
1357 #define CULLPOINT( PacketType, p1, p2 ) \
1358 ( \
1359 	CullVertex( COORD_Y( m_packet.PacketType.vertex[ p1 ].n_coord ), COORD_Y( m_packet.PacketType.vertex[ p2 ].n_coord ) ) || \
1360 	CullVertex( COORD_X( m_packet.PacketType.vertex[ p1 ].n_coord ), COORD_X( m_packet.PacketType.vertex[ p2 ].n_coord ) ) \
1361 )
1362 
1363 #define CULLTRIANGLE( PacketType, start ) \
1364 ( \
1365 	CULLPOINT( PacketType, start, start + 1 ) || CULLPOINT( PacketType, start + 1, start + 2 ) || CULLPOINT( PacketType, start + 2, start ) \
1366 )
1367 
1368 #define FINDTOPLEFT( PacketType ) \
1369 	for( int n_point = 0; n_point < n_points; n_point++ ) \
1370 	{ \
1371 		GET_COORD( m_packet.PacketType.vertex[ n_point ].n_coord ); \
1372 	} \
1373 	\
1374 	const int *p_n_rightpointlist; \
1375 	const int *p_n_leftpointlist; \
1376 	int n_leftpoint = 0; \
1377 	if( n_points == 4 ) \
1378 	{ \
1379 		if( CULLTRIANGLE( PacketType, 0 ) ) \
1380 		{ \
1381 			if( CULLTRIANGLE( PacketType, 1 ) ) \
1382 			{ \
1383 				return; \
1384 			} \
1385 			\
1386 			p_n_rightpointlist = m_p_n_nextpointlist4b; \
1387 			p_n_leftpointlist = m_p_n_prevpointlist4b; \
1388 			n_leftpoint++; \
1389 		} \
1390 		else if( CULLTRIANGLE( PacketType, 1 ) ) \
1391 		{ \
1392 			p_n_rightpointlist = m_p_n_nextpointlist3; \
1393 			p_n_leftpointlist = m_p_n_prevpointlist3; \
1394 			n_points--; \
1395 		} \
1396 		else \
1397 		{ \
1398 			p_n_rightpointlist = m_p_n_nextpointlist4; \
1399 			p_n_leftpointlist = m_p_n_prevpointlist4; \
1400 		} \
1401 	} \
1402 	else if( CULLTRIANGLE( PacketType, 0 ) ) \
1403 	{ \
1404 		return; \
1405 	} \
1406 	else \
1407 	{ \
1408 		p_n_rightpointlist = m_p_n_nextpointlist3; \
1409 		p_n_leftpointlist = m_p_n_prevpointlist3; \
1410 	} \
1411 	\
1412 	for( int n_point = n_leftpoint + 1; n_point < n_points; n_point++ ) \
1413 	{ \
1414 		if( COORD_Y( m_packet.PacketType.vertex[ n_point ].n_coord ) < COORD_Y( m_packet.PacketType.vertex[ n_leftpoint ].n_coord ) || \
1415 			( COORD_Y( m_packet.PacketType.vertex[ n_point ].n_coord ) == COORD_Y( m_packet.PacketType.vertex[ n_leftpoint ].n_coord ) && \
1416 			COORD_X( m_packet.PacketType.vertex[ n_point ].n_coord ) < COORD_X( m_packet.PacketType.vertex[ n_leftpoint ].n_coord ) ) ) \
1417 		{ \
1418 			n_leftpoint = n_point; \
1419 		} \
1420 	} \
1421 	int n_rightpoint = n_leftpoint;
1422 
FlatPolygon(int n_points)1423 void psxgpu_device::FlatPolygon( int n_points )
1424 {
1425 #if PSXGPU_DEBUG_VIEWER
1426 	if( m_debug.n_skip == 1 )
1427 	{
1428 		return;
1429 	}
1430 	for( int n_point = 0; n_point < n_points; n_point++ )
1431 	{
1432 		DebugMesh( SINT11( COORD_X( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_y );
1433 	}
1434 	DebugMeshEnd();
1435 #endif
1436 
1437 	uint8_t n_cmd = BGR_C( m_packet.FlatPolygon.n_bgr );
1438 
1439 	PAIR n_cx1; n_cx1.d = 0;
1440 	PAIR n_cx2; n_cx2.d = 0;
1441 
1442 	SOLIDSETUP
1443 
1444 	PAIR n_r; n_r.w.h = BGR_R( m_packet.FlatPolygon.n_bgr ); n_r.w.l = 0;
1445 	PAIR n_g; n_g.w.h = BGR_G( m_packet.FlatPolygon.n_bgr ); n_g.w.l = 0;
1446 	PAIR n_b; n_b.w.h = BGR_B( m_packet.FlatPolygon.n_bgr ); n_b.w.l = 0;
1447 
1448 	FINDTOPLEFT( FlatPolygon )
1449 
1450 	int32_t n_dx1 = 0;
1451 	int32_t n_dx2 = 0;
1452 
1453 	int16_t n_y = COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord );
1454 
1455 	for( ;; )
1456 	{
1457 		if( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) )
1458 		{
1459 			while( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
1460 			{
1461 				n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1462 				if( n_leftpoint == n_rightpoint )
1463 				{
1464 					break;
1465 				}
1466 			}
1467 
1468 			n_cx1.sw.h = COORD_X( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.sw.l = 0;
1469 			n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1470 
1471 			int32_t n_distance = COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
1472 			if( n_distance < 1 )
1473 			{
1474 				break;
1475 			}
1476 
1477 			n_dx1 = (int32_t)( ( COORD_X( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
1478 		}
1479 
1480 		if( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) )
1481 		{
1482 			while( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
1483 			{
1484 				n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1485 				if( n_rightpoint == n_leftpoint )
1486 				{
1487 					break;
1488 				}
1489 			}
1490 
1491 			n_cx2.sw.h = COORD_X( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.sw.l = 0;
1492 			n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1493 
1494 			int32_t n_distance = COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
1495 			if( n_distance < 1 )
1496 			{
1497 				break;
1498 			}
1499 
1500 			n_dx2 = (int32_t)( ( COORD_X( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
1501 		}
1502 
1503 		int drawy = n_y + n_drawoffset_y;
1504 
1505 		if( (int16_t)n_cx1.sw.h != (int16_t)n_cx2.sw.h && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
1506 		{
1507 			int16_t n_x;
1508 			int32_t n_distance;
1509 
1510 			if( (int16_t)n_cx1.sw.h < (int16_t)n_cx2.sw.h )
1511 			{
1512 				n_x = n_cx1.sw.h;
1513 				n_distance = (int16_t)n_cx2.sw.h - n_x;
1514 			}
1515 			else
1516 			{
1517 				n_x = n_cx2.sw.h;
1518 				n_distance = (int16_t)n_cx1.sw.h - n_x;
1519 			}
1520 
1521 			int drawx = n_x + n_drawoffset_x;
1522 
1523 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
1524 			{
1525 				n_distance -= ( n_drawarea_x1 - drawx );
1526 				drawx = n_drawarea_x1;
1527 			}
1528 
1529 			SOLIDFILL( FLATPOLYGONUPDATE )
1530 		}
1531 
1532 		n_cx1.d += n_dx1;
1533 		n_cx2.d += n_dx2;
1534 		n_y++;
1535 	}
1536 }
1537 
FlatTexturedPolygon(int n_points)1538 void psxgpu_device::FlatTexturedPolygon( int n_points )
1539 {
1540 #if PSXGPU_DEBUG_VIEWER
1541 	if( m_debug.n_skip == 2 )
1542 	{
1543 		return;
1544 	}
1545 	for( int n_point = 0; n_point < n_points; n_point++ )
1546 	{
1547 		DebugMesh( SINT11( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_y );
1548 	}
1549 	DebugMeshEnd();
1550 #endif
1551 
1552 	uint8_t n_cmd = BGR_C( m_packet.FlatTexturedPolygon.n_bgr );
1553 
1554 	uint32_t n_clutx = ( m_packet.FlatTexturedPolygon.vertex[ 0 ].n_texture.w.h & 0x3f ) << 4;
1555 	uint32_t n_cluty = ( m_packet.FlatTexturedPolygon.vertex[ 0 ].n_texture.w.h >> 6 ) & 0x3ff;
1556 
1557 	PAIR n_cx1; n_cx1.d = 0;
1558 	PAIR n_cu1; n_cu1.d = 0;
1559 	PAIR n_cv1; n_cv1.d = 0;
1560 	PAIR n_cx2; n_cx2.d = 0;
1561 	PAIR n_cu2; n_cu2.d = 0;
1562 	PAIR n_cv2; n_cv2.d = 0;
1563 
1564 	decode_tpage( m_packet.FlatTexturedPolygon.vertex[ 1 ].n_texture.w.h );
1565 	TEXTURESETUP
1566 
1567 	PAIR n_r; n_r.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.FlatTexturedPolygon.n_bgr ); n_r.w.l = 0;
1568 	PAIR n_g; n_g.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.FlatTexturedPolygon.n_bgr ); n_g.w.l = 0;
1569 	PAIR n_b; n_b.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.FlatTexturedPolygon.n_bgr ); n_b.w.l = 0;
1570 
1571 	FINDTOPLEFT( FlatTexturedPolygon )
1572 
1573 	int32_t n_dx1 = 0;
1574 	int32_t n_dx2 = 0;
1575 	int32_t n_du1 = 0;
1576 	int32_t n_du2 = 0;
1577 	int32_t n_dv1 = 0;
1578 	int32_t n_dv2 = 0;
1579 
1580 	int16_t n_y = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord );
1581 
1582 	for( ;; )
1583 	{
1584 		if( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) )
1585 		{
1586 			while( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
1587 			{
1588 				n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1589 				if( n_leftpoint == n_rightpoint )
1590 				{
1591 					break;
1592 				}
1593 			}
1594 
1595 			n_cx1.sw.h = COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.sw.l = 0;
1596 			n_cu1.w.h = TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cu1.w.l = 0;
1597 			n_cv1.w.h = TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cv1.w.l = 0;
1598 			n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1599 
1600 			int32_t n_distance = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
1601 			if( n_distance < 1 )
1602 			{
1603 				break;
1604 			}
1605 
1606 			n_dx1 = (int32_t)( ( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
1607 			n_du1 = (int32_t)( ( TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cu1.d ) / n_distance;
1608 			n_dv1 = (int32_t)( ( TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cv1.d ) / n_distance;
1609 		}
1610 
1611 		if( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) )
1612 		{
1613 			while( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
1614 			{
1615 				n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1616 				if( n_rightpoint == n_leftpoint )
1617 				{
1618 					break;
1619 				}
1620 			}
1621 
1622 			n_cx2.sw.h = COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.sw.l = 0;
1623 			n_cu2.w.h = TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cu2.w.l = 0;
1624 			n_cv2.w.h = TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cv2.w.l = 0;
1625 			n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1626 
1627 			int32_t n_distance = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
1628 			if( n_distance < 1 )
1629 			{
1630 				break;
1631 			}
1632 
1633 			n_dx2 = (int32_t)( ( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
1634 			n_du2 = (int32_t)( ( TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cu2.d ) / n_distance;
1635 			n_dv2 = (int32_t)( ( TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cv2.d ) / n_distance;
1636 		}
1637 
1638 		int drawy = n_y + n_drawoffset_y;
1639 
1640 		if( (int16_t)n_cx1.sw.h != (int16_t)n_cx2.sw.h && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
1641 		{
1642 			int16_t n_x;
1643 			int32_t n_distance;
1644 			PAIR n_u;
1645 			PAIR n_v;
1646 			int32_t n_du;
1647 			int32_t n_dv;
1648 
1649 			if( (int16_t)n_cx1.sw.h < (int16_t)n_cx2.sw.h )
1650 			{
1651 				n_x = n_cx1.sw.h;
1652 				n_distance = (int16_t)n_cx2.sw.h - n_x;
1653 
1654 				n_u.d = n_cu1.d;
1655 				n_v.d = n_cv1.d;
1656 				n_du = (int32_t)( n_cu2.d - n_cu1.d ) / n_distance;
1657 				n_dv = (int32_t)( n_cv2.d - n_cv1.d ) / n_distance;
1658 			}
1659 			else
1660 			{
1661 				n_x = n_cx2.sw.h;
1662 				n_distance = (int16_t)n_cx1.sw.h - n_x;
1663 
1664 				n_u.d = n_cu2.d;
1665 				n_v.d = n_cv2.d;
1666 				n_du = (int32_t)( n_cu1.d - n_cu2.d ) / n_distance;
1667 				n_dv = (int32_t)( n_cv1.d - n_cv2.d ) / n_distance;
1668 			}
1669 
1670 			int drawx = n_x + n_drawoffset_x;
1671 
1672 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
1673 			{
1674 				n_u.d += n_du * ( n_drawarea_x1 - drawx );
1675 				n_v.d += n_dv * ( n_drawarea_x1 - drawx );
1676 				n_distance -= ( n_drawarea_x1 - drawx );
1677 				drawx = n_drawarea_x1;
1678 			}
1679 
1680 			TEXTUREFILL( FLATTEXTUREDPOLYGONUPDATE, n_u.w.h, n_v.w.h );
1681 		}
1682 
1683 		n_cx1.d += n_dx1;
1684 		n_cu1.d += n_du1;
1685 		n_cv1.d += n_dv1;
1686 		n_cx2.d += n_dx2;
1687 		n_cu2.d += n_du2;
1688 		n_cv2.d += n_dv2;
1689 		n_y++;
1690 	}
1691 }
1692 
GouraudPolygon(int n_points)1693 void psxgpu_device::GouraudPolygon( int n_points )
1694 {
1695 #if PSXGPU_DEBUG_VIEWER
1696 	if( m_debug.n_skip == 3 )
1697 	{
1698 		return;
1699 	}
1700 	for( int n_point = 0; n_point < n_points; n_point++ )
1701 	{
1702 		DebugMesh( SINT11( COORD_X( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_y );
1703 	}
1704 	DebugMeshEnd();
1705 #endif
1706 
1707 	uint8_t n_cmd = BGR_C( m_packet.GouraudPolygon.vertex[ 0 ].n_bgr );
1708 
1709 	PAIR n_cx1; n_cx1.d = 0;
1710 	PAIR n_cr1; n_cr1.d = 0;
1711 	PAIR n_cg1; n_cg1.d = 0;
1712 	PAIR n_cb1; n_cb1.d = 0;
1713 	PAIR n_cx2; n_cx2.d = 0;
1714 	PAIR n_cr2; n_cr2.d = 0;
1715 	PAIR n_cg2; n_cg2.d = 0;
1716 	PAIR n_cb2; n_cb2.d = 0;
1717 
1718 	SOLIDSETUP
1719 
1720 	FINDTOPLEFT( GouraudPolygon )
1721 
1722 	int32_t n_dx1 = 0;
1723 	int32_t n_dx2 = 0;
1724 	int32_t n_dr1 = 0;
1725 	int32_t n_dr2 = 0;
1726 	int32_t n_dg1 = 0;
1727 	int32_t n_dg2 = 0;
1728 	int32_t n_db1 = 0;
1729 	int32_t n_db2 = 0;
1730 
1731 	int16_t n_y = COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord );
1732 
1733 	for( ;; )
1734 	{
1735 		if( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) )
1736 		{
1737 			while( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
1738 			{
1739 				n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1740 				if( n_leftpoint == n_rightpoint )
1741 				{
1742 					break;
1743 				}
1744 			}
1745 
1746 			n_cx1.sw.h = COORD_X( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.sw.l = 0;
1747 			n_cr1.w.h = BGR_R( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cr1.w.l = 0;
1748 			n_cg1.w.h = BGR_G( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cg1.w.l = 0;
1749 			n_cb1.w.h = BGR_B( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cb1.w.l = 0;
1750 			n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1751 
1752 			int32_t n_distance = COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
1753 			if( n_distance < 1 )
1754 			{
1755 				break;
1756 			}
1757 
1758 			n_dx1 = (int32_t)( ( COORD_X( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
1759 			n_dr1 = (int32_t)( ( BGR_R( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cr1.d ) / n_distance;
1760 			n_dg1 = (int32_t)( ( BGR_G( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cg1.d ) / n_distance;
1761 			n_db1 = (int32_t)( ( BGR_B( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cb1.d ) / n_distance;
1762 		}
1763 
1764 		if( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) )
1765 		{
1766 			while( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
1767 			{
1768 				n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1769 				if( n_rightpoint == n_leftpoint )
1770 				{
1771 					break;
1772 				}
1773 			}
1774 
1775 			n_cx2.sw.h = COORD_X( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.sw.l = 0;
1776 			n_cr2.w.h = BGR_R( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cr2.w.l = 0;
1777 			n_cg2.w.h = BGR_G( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cg2.w.l = 0;
1778 			n_cb2.w.h = BGR_B( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cb2.w.l = 0;
1779 			n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1780 
1781 			int32_t n_distance = COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
1782 			if( n_distance < 1 )
1783 			{
1784 				break;
1785 			}
1786 
1787 			n_dx2 = (int32_t)( ( COORD_X( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
1788 			n_dr2 = (int32_t)( ( BGR_R( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cr2.d ) / n_distance;
1789 			n_dg2 = (int32_t)( ( BGR_G( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cg2.d ) / n_distance;
1790 			n_db2 = (int32_t)( ( BGR_B( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cb2.d ) / n_distance;
1791 		}
1792 
1793 		int drawy = n_y + n_drawoffset_y;
1794 
1795 		if( (int16_t)n_cx1.sw.h != (int16_t)n_cx2.sw.h && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
1796 		{
1797 			int16_t n_x;
1798 			int32_t n_distance;
1799 			PAIR n_r;
1800 			PAIR n_g;
1801 			PAIR n_b;
1802 			int32_t n_dr;
1803 			int32_t n_dg;
1804 			int32_t n_db;
1805 
1806 			if( (int16_t)n_cx1.sw.h < (int16_t)n_cx2.sw.h )
1807 			{
1808 				n_x = n_cx1.sw.h;
1809 				n_distance = (int16_t)n_cx2.sw.h - n_x;
1810 
1811 				n_r.d = n_cr1.d;
1812 				n_g.d = n_cg1.d;
1813 				n_b.d = n_cb1.d;
1814 				n_dr = (int32_t)( n_cr2.d - n_cr1.d ) / n_distance;
1815 				n_dg = (int32_t)( n_cg2.d - n_cg1.d ) / n_distance;
1816 				n_db = (int32_t)( n_cb2.d - n_cb1.d ) / n_distance;
1817 			}
1818 			else
1819 			{
1820 				n_x = n_cx2.sw.h;
1821 				n_distance = (int16_t)n_cx1.sw.h - n_x;
1822 
1823 				n_r.d = n_cr2.d;
1824 				n_g.d = n_cg2.d;
1825 				n_b.d = n_cb2.d;
1826 				n_dr = (int32_t)( n_cr1.d - n_cr2.d ) / n_distance;
1827 				n_dg = (int32_t)( n_cg1.d - n_cg2.d ) / n_distance;
1828 				n_db = (int32_t)( n_cb1.d - n_cb2.d ) / n_distance;
1829 			}
1830 
1831 			int drawx = n_x + n_drawoffset_x;
1832 
1833 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
1834 			{
1835 				n_r.d += n_dr * ( n_drawarea_x1 - drawx );
1836 				n_g.d += n_dg * ( n_drawarea_x1 - drawx );
1837 				n_b.d += n_db * ( n_drawarea_x1 - drawx );
1838 				n_distance -= ( n_drawarea_x1 - drawx );
1839 				drawx = n_drawarea_x1;
1840 			}
1841 
1842 			SOLIDFILL( GOURAUDPOLYGONUPDATE )
1843 		}
1844 
1845 		n_cx1.d += n_dx1;
1846 		n_cr1.d += n_dr1;
1847 		n_cg1.d += n_dg1;
1848 		n_cb1.d += n_db1;
1849 		n_cx2.d += n_dx2;
1850 		n_cr2.d += n_dr2;
1851 		n_cg2.d += n_dg2;
1852 		n_cb2.d += n_db2;
1853 		n_y++;
1854 	}
1855 }
1856 
GouraudTexturedPolygon(int n_points)1857 void psxgpu_device::GouraudTexturedPolygon( int n_points )
1858 {
1859 #if PSXGPU_DEBUG_VIEWER
1860 	if( m_debug.n_skip == 4 )
1861 	{
1862 		return;
1863 	}
1864 	for( int n_point = 0; n_point < n_points; n_point++ )
1865 	{
1866 		DebugMesh( SINT11( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) ) + n_drawoffset_y );
1867 	}
1868 	DebugMeshEnd();
1869 #endif
1870 
1871 	uint8_t n_cmd = BGR_C( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_bgr );
1872 
1873 	uint32_t n_clutx = ( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_texture.w.h & 0x3f ) << 4;
1874 	uint32_t n_cluty = ( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_texture.w.h >> 6 ) & 0x3ff;
1875 
1876 	PAIR n_cx1; n_cx1.d = 0;
1877 	PAIR n_cr1; n_cr1.d = 0;
1878 	PAIR n_cg1; n_cg1.d = 0;
1879 	PAIR n_cb1; n_cb1.d = 0;
1880 	PAIR n_cu1; n_cu1.d = 0;
1881 	PAIR n_cv1; n_cv1.d = 0;
1882 	PAIR n_cx2; n_cx2.d = 0;
1883 	PAIR n_cr2; n_cr2.d = 0;
1884 	PAIR n_cg2; n_cg2.d = 0;
1885 	PAIR n_cb2; n_cb2.d = 0;
1886 	PAIR n_cu2; n_cu2.d = 0;
1887 	PAIR n_cv2; n_cv2.d = 0;
1888 
1889 	decode_tpage( m_packet.GouraudTexturedPolygon.vertex[ 1 ].n_texture.w.h );
1890 	TEXTURESETUP
1891 
1892 	FINDTOPLEFT( GouraudTexturedPolygon )
1893 
1894 	int32_t n_dx1 = 0;
1895 	int32_t n_dx2 = 0;
1896 	int32_t n_du1 = 0;
1897 	int32_t n_du2 = 0;
1898 	int32_t n_dr1 = 0;
1899 	int32_t n_dr2 = 0;
1900 	int32_t n_dg1 = 0;
1901 	int32_t n_dg2 = 0;
1902 	int32_t n_db1 = 0;
1903 	int32_t n_db2 = 0;
1904 	int32_t n_dv1 = 0;
1905 	int32_t n_dv2 = 0;
1906 
1907 	int16_t n_y = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord );
1908 
1909 	for( ;; )
1910 	{
1911 		if( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) )
1912 		{
1913 			while( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
1914 			{
1915 				n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1916 				if( n_leftpoint == n_rightpoint )
1917 				{
1918 					break;
1919 				}
1920 			}
1921 
1922 			n_cx1.sw.h = COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.sw.l = 0;
1923 			n_cr1.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cr1.w.l = 0;
1924 			n_cg1.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cg1.w.l = 0;
1925 			n_cb1.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cb1.w.l = 0;
1926 			n_cu1.w.h = TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cu1.w.l = 0;
1927 			n_cv1.w.h = TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cv1.w.l = 0;
1928 			n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
1929 
1930 			int32_t n_distance = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
1931 			if( n_distance < 1 )
1932 			{
1933 				break;
1934 			}
1935 
1936 			n_dx1 = (int32_t)( ( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
1937 			n_dr1 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cr1.d ) / n_distance;
1938 			n_dg1 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cg1.d ) / n_distance;
1939 			n_db1 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cb1.d ) / n_distance;
1940 			n_du1 = (int32_t)( ( TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cu1.d ) / n_distance;
1941 			n_dv1 = (int32_t)( ( TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cv1.d ) / n_distance;
1942 		}
1943 
1944 		if( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) )
1945 		{
1946 			while( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
1947 			{
1948 				n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1949 				if( n_rightpoint == n_leftpoint )
1950 				{
1951 					break;
1952 				}
1953 			}
1954 
1955 			n_cx2.sw.h = COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.sw.l = 0;
1956 			n_cr2.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cr2.w.l = 0;
1957 			n_cg2.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cg2.w.l = 0;
1958 			n_cb2.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cb2.w.l = 0;
1959 			n_cu2.w.h = TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cu2.w.l = 0;
1960 			n_cv2.w.h = TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cv2.w.l = 0;
1961 			n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
1962 
1963 			int32_t n_distance = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
1964 			if( n_distance < 1 )
1965 			{
1966 				break;
1967 			}
1968 
1969 			n_dx2 = (int32_t)( ( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
1970 			n_dr2 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cr2.d ) / n_distance;
1971 			n_dg2 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cg2.d ) / n_distance;
1972 			n_db2 = n_cmd & 0x01 ? 0 : (int32_t)( ( BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cb2.d ) / n_distance;
1973 			n_du2 = (int32_t)( ( TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cu2.d ) / n_distance;
1974 			n_dv2 = (int32_t)( ( TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cv2.d ) / n_distance;
1975 		}
1976 
1977 		int drawy = n_y + n_drawoffset_y;
1978 
1979 		if( (int16_t)n_cx1.sw.h != (int16_t)n_cx2.sw.h && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
1980 		{
1981 			int16_t n_x;
1982 			int32_t n_distance;
1983 			PAIR n_r;
1984 			PAIR n_g;
1985 			PAIR n_b;
1986 			PAIR n_u;
1987 			PAIR n_v;
1988 			int32_t n_dr;
1989 			int32_t n_dg;
1990 			int32_t n_db;
1991 			int32_t n_du;
1992 			int32_t n_dv;
1993 
1994 			if( (int16_t)n_cx1.sw.h < (int16_t)n_cx2.sw.h )
1995 			{
1996 				n_x = n_cx1.sw.h;
1997 				n_distance = (int16_t)n_cx2.sw.h - n_x;
1998 
1999 				n_r.d = n_cr1.d;
2000 				n_g.d = n_cg1.d;
2001 				n_b.d = n_cb1.d;
2002 				n_u.d = n_cu1.d;
2003 				n_v.d = n_cv1.d;
2004 				n_dr = (int32_t)( n_cr2.d - n_cr1.d ) / n_distance;
2005 				n_dg = (int32_t)( n_cg2.d - n_cg1.d ) / n_distance;
2006 				n_db = (int32_t)( n_cb2.d - n_cb1.d ) / n_distance;
2007 				n_du = (int32_t)( n_cu2.d - n_cu1.d ) / n_distance;
2008 				n_dv = (int32_t)( n_cv2.d - n_cv1.d ) / n_distance;
2009 			}
2010 			else
2011 			{
2012 				n_x = n_cx2.sw.h;
2013 				n_distance = (int16_t)n_cx1.sw.h - n_x;
2014 
2015 				n_r.d = n_cr2.d;
2016 				n_g.d = n_cg2.d;
2017 				n_b.d = n_cb2.d;
2018 				n_u.d = n_cu2.d;
2019 				n_v.d = n_cv2.d;
2020 				n_dr = (int32_t)( n_cr1.d - n_cr2.d ) / n_distance;
2021 				n_dg = (int32_t)( n_cg1.d - n_cg2.d ) / n_distance;
2022 				n_db = (int32_t)( n_cb1.d - n_cb2.d ) / n_distance;
2023 				n_du = (int32_t)( n_cu1.d - n_cu2.d ) / n_distance;
2024 				n_dv = (int32_t)( n_cv1.d - n_cv2.d ) / n_distance;
2025 			}
2026 
2027 			int drawx = n_x + n_drawoffset_x;
2028 
2029 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2030 			{
2031 				n_r.d += n_dr * ( n_drawarea_x1 - drawx );
2032 				n_g.d += n_dg * ( n_drawarea_x1 - drawx );
2033 				n_b.d += n_db * ( n_drawarea_x1 - drawx );
2034 				n_u.d += n_du * ( n_drawarea_x1 - drawx );
2035 				n_v.d += n_dv * ( n_drawarea_x1 - drawx );
2036 				n_distance -= ( n_drawarea_x1 - drawx );
2037 				drawx = n_drawarea_x1;
2038 			}
2039 
2040 			TEXTUREFILL( GOURAUDTEXTUREDPOLYGONUPDATE, n_u.w.h, n_v.w.h );
2041 		}
2042 
2043 		n_cx1.d += n_dx1;
2044 		n_cr1.d += n_dr1;
2045 		n_cg1.d += n_dg1;
2046 		n_cb1.d += n_db1;
2047 		n_cu1.d += n_du1;
2048 		n_cv1.d += n_dv1;
2049 		n_cx2.d += n_dx2;
2050 		n_cr2.d += n_dr2;
2051 		n_cg2.d += n_dg2;
2052 		n_cb2.d += n_db2;
2053 		n_cu2.d += n_du2;
2054 		n_cv2.d += n_dv2;
2055 		n_y++;
2056 	}
2057 }
2058 
MonochromeLine()2059 void psxgpu_device::MonochromeLine()
2060 {
2061 #if PSXGPU_DEBUG_VIEWER
2062 	if( m_debug.n_skip == 5 )
2063 	{
2064 		return;
2065 	}
2066 	DebugMesh( SINT11( COORD_X( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) ) + n_drawoffset_y );
2067 	DebugMesh( SINT11( COORD_X( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) ) + n_drawoffset_y );
2068 	DebugMeshEnd();
2069 #endif
2070 
2071 	int32_t n_xstart = SINT11( COORD_X( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) );
2072 	int32_t n_xend = SINT11( COORD_X( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) );
2073 	int32_t n_ystart = SINT11( COORD_Y( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) );
2074 	int32_t n_yend = SINT11( COORD_Y( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) );
2075 
2076 	uint8_t n_cmd = BGR_C( m_packet.MonochromeLine.n_bgr );
2077 	uint8_t n_r = BGR_R( m_packet.MonochromeLine.n_bgr );
2078 	uint8_t n_g = BGR_G( m_packet.MonochromeLine.n_bgr );
2079 	uint8_t n_b = BGR_B( m_packet.MonochromeLine.n_bgr );
2080 
2081 	TRANSPARENCYSETUP
2082 
2083 	int32_t n_xlen;
2084 	if( n_xend > n_xstart )
2085 	{
2086 		n_xlen = n_xend - n_xstart;
2087 	}
2088 	else
2089 	{
2090 		n_xlen = n_xstart - n_xend;
2091 	}
2092 
2093 	int32_t n_ylen;
2094 	if( n_yend > n_ystart )
2095 	{
2096 		n_ylen = n_yend - n_ystart;
2097 	}
2098 	else
2099 	{
2100 		n_ylen = n_ystart - n_yend;
2101 	}
2102 
2103 	int32_t n_len;
2104 	if( n_xlen > n_ylen )
2105 	{
2106 		n_len = n_xlen;
2107 	}
2108 	else
2109 	{
2110 		n_len = n_ylen;
2111 	}
2112 
2113 	if( n_len == 0 )
2114 	{
2115 		n_len = 1;
2116 	}
2117 
2118 	PAIR n_x; n_x.sw.h = n_xstart; n_x.sw.l = 0;
2119 	PAIR n_y; n_y.sw.h = n_ystart; n_y.sw.l = 0;
2120 
2121 	int32_t n_dx = (int32_t)( ( n_xend << 16 ) - n_x.d ) / n_len;
2122 	int32_t n_dy = (int32_t)( ( n_yend << 16 ) - n_y.d ) / n_len;
2123 
2124 	while( n_len > 0 )
2125 	{
2126 		int drawx = n_x.sw.h + n_drawoffset_x;
2127 		int drawy = n_y.sw.h + n_drawoffset_y;
2128 
2129 		if( drawx >= (int32_t)n_drawarea_x1 && drawy >= (int32_t)n_drawarea_y1 &&
2130 			drawx <= (int32_t)n_drawarea_x2 && drawy <= (int32_t)n_drawarea_y2 )
2131 		{
2132 			uint16_t *p_vram = p_p_vram[ drawy ] + drawx;
2133 
2134 			switch( n_cmd & 0x02 )
2135 			{
2136 			case 0x00:
2137 				/* transparency off */
2138 				WRITE_PIXEL(
2139 					p_n_redshade[ MID_LEVEL | n_r ] |
2140 					p_n_greenshade[ MID_LEVEL | n_g ] |
2141 					p_n_blueshade[ MID_LEVEL | n_b ] )
2142 				break;
2143 			case 0x02:
2144 				/* transparency on */
2145 				WRITE_PIXEL(
2146 					p_n_redtrans[ p_n_f[ MID_LEVEL | n_r ] | p_n_redb[ *( p_vram ) ] ] |
2147 					p_n_greentrans[ p_n_f[ MID_LEVEL | n_g ] | p_n_greenb[ *( p_vram ) ] ] |
2148 					p_n_bluetrans[ p_n_f[ MID_LEVEL | n_b ] | p_n_blueb[ *( p_vram ) ] ] )
2149 				break;
2150 			}
2151 		}
2152 
2153 		n_x.d += n_dx;
2154 		n_y.d += n_dy;
2155 		n_len--;
2156 	}
2157 }
2158 
GouraudLine()2159 void psxgpu_device::GouraudLine()
2160 {
2161 #if PSXGPU_DEBUG_VIEWER
2162 	if( m_debug.n_skip == 6 )
2163 	{
2164 		return;
2165 	}
2166 	DebugMesh( SINT11( COORD_X( m_packet.GouraudLine.vertex[ 0 ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.GouraudLine.vertex[ 0 ].n_coord ) ) + n_drawoffset_y );
2167 	DebugMesh( SINT11( COORD_X( m_packet.GouraudLine.vertex[ 1 ].n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.GouraudLine.vertex[ 1 ].n_coord ) ) + n_drawoffset_y );
2168 	DebugMeshEnd();
2169 #endif
2170 
2171 	uint8_t n_cmd = BGR_C( m_packet.GouraudLine.vertex[ 0 ].n_bgr );
2172 
2173 	TRANSPARENCYSETUP
2174 
2175 	int32_t n_xstart = SINT11( COORD_X( m_packet.GouraudLine.vertex[ 0 ].n_coord ) );
2176 	int32_t n_ystart = SINT11( COORD_Y( m_packet.GouraudLine.vertex[ 0 ].n_coord ) );
2177 	PAIR n_cr1; n_cr1.w.h = BGR_R( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cr1.w.l = 0;
2178 	PAIR n_cg1; n_cg1.w.h = BGR_G( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cg1.w.l = 0;
2179 	PAIR n_cb1; n_cb1.w.h = BGR_B( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cb1.w.l = 0;
2180 
2181 	int32_t n_xend = SINT11( COORD_X( m_packet.GouraudLine.vertex[ 1 ].n_coord ) );
2182 	int32_t n_yend = SINT11( COORD_Y( m_packet.GouraudLine.vertex[ 1 ].n_coord ) );
2183 	PAIR n_cr2; n_cr2.w.h = BGR_R( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cr2.w.l = 0;
2184 	PAIR n_cg2; n_cg2.w.h = BGR_G( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cg2.w.l = 0;
2185 	PAIR n_cb2; n_cb2.w.h = BGR_B( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cb2.w.l = 0;
2186 
2187 
2188 	PAIR n_x; n_x.sw.h = n_xstart; n_x.sw.l = 0;
2189 	PAIR n_y; n_y.sw.h = n_ystart; n_y.sw.l = 0;
2190 	PAIR n_r; n_r.d = n_cr1.d;
2191 	PAIR n_g; n_g.d = n_cg1.d;
2192 	PAIR n_b; n_b.d = n_cb1.d;
2193 
2194 	int32_t n_xlen;
2195 	if( n_xend > n_xstart )
2196 	{
2197 		n_xlen = n_xend - n_xstart;
2198 	}
2199 	else
2200 	{
2201 		n_xlen = n_xstart - n_xend;
2202 	}
2203 
2204 	int32_t n_ylen;
2205 	if( n_yend > n_ystart )
2206 	{
2207 		n_ylen = n_yend - n_ystart;
2208 	}
2209 	else
2210 	{
2211 		n_ylen = n_ystart - n_yend;
2212 	}
2213 
2214 	int32_t n_distance;
2215 	if( n_xlen > n_ylen )
2216 	{
2217 		n_distance = n_xlen;
2218 	}
2219 	else
2220 	{
2221 		n_distance = n_ylen;
2222 	}
2223 
2224 	if( n_distance == 0 )
2225 	{
2226 		n_distance = 1;
2227 	}
2228 
2229 	int32_t n_dx = (int32_t)( ( n_xend << 16 ) - n_x.sd ) / n_distance;
2230 	int32_t n_dy = (int32_t)( ( n_yend << 16 ) - n_y.sd ) / n_distance;
2231 	int32_t n_dr = (int32_t)( n_cr2.d - n_cr1.d ) / n_distance;
2232 	int32_t n_dg = (int32_t)( n_cg2.d - n_cg1.d ) / n_distance;
2233 	int32_t n_db = (int32_t)( n_cb2.d - n_cb1.d ) / n_distance;
2234 
2235 	while( n_distance > 0 )
2236 	{
2237 		int drawx = n_x.sw.h + n_drawoffset_x;
2238 		int drawy = n_y.sw.h + n_drawoffset_y;
2239 
2240 		if( drawx >= (int32_t)n_drawarea_x1 && drawy >= (int32_t)n_drawarea_y1 &&
2241 			drawx <= (int32_t)n_drawarea_x2 && drawy <= (int32_t)n_drawarea_y2 )
2242 		{
2243 			uint16_t *p_vram = p_p_vram[ drawy ] + drawx;
2244 
2245 			switch( n_cmd & 0x02 )
2246 			{
2247 			case 0x00:
2248 				/* transparency off */
2249 				WRITE_PIXEL(
2250 					p_n_redshade[ MID_LEVEL | n_r.w.h ] |
2251 					p_n_greenshade[ MID_LEVEL | n_g.w.h ] |
2252 					p_n_blueshade[ MID_LEVEL | n_b.w.h ] )
2253 				break;
2254 			case 0x02:
2255 				/* transparency on */
2256 				WRITE_PIXEL(
2257 					p_n_redtrans[ p_n_f[ MID_LEVEL | n_r.w.h ] | p_n_redb[ *( p_vram ) ] ] |
2258 					p_n_greentrans[ p_n_f[ MID_LEVEL | n_g.w.h ] | p_n_greenb[ *( p_vram ) ] ] |
2259 					p_n_bluetrans[ p_n_f[ MID_LEVEL | n_b.w.h ] | p_n_blueb[ *( p_vram ) ] ] )
2260 				break;
2261 			}
2262 		}
2263 
2264 		n_x.sd += n_dx;
2265 		n_y.sd += n_dy;
2266 		n_r.d += n_dr;
2267 		n_g.d += n_dg;
2268 		n_b.d += n_db;
2269 		n_distance--;
2270 	}
2271 }
2272 
FrameBufferRectangleDraw()2273 void psxgpu_device::FrameBufferRectangleDraw()
2274 {
2275 #if PSXGPU_DEBUG_VIEWER
2276 	if( m_debug.n_skip == 7 )
2277 	{
2278 		return;
2279 	}
2280 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) );
2281 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + SIZE_W( m_packet.FlatRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) );
2282 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + SIZE_H( m_packet.FlatRectangle.n_size ) );
2283 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + SIZE_W( m_packet.FlatRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + SIZE_H( m_packet.FlatRectangle.n_size ) );
2284 	DebugMeshEnd();
2285 #endif
2286 
2287 	PAIR n_r; n_r.w.h = BGR_R( m_packet.FlatRectangle.n_bgr ); n_r.w.l = 0;
2288 	PAIR n_g; n_g.w.h = BGR_G( m_packet.FlatRectangle.n_bgr ); n_g.w.l = 0;
2289 	PAIR n_b; n_b.w.h = BGR_B( m_packet.FlatRectangle.n_bgr ); n_b.w.l = 0;
2290 
2291 	int16_t n_y = COORD_Y( m_packet.FlatRectangle.n_coord );
2292 	int32_t n_h = SIZE_H( m_packet.FlatRectangle.n_size );
2293 
2294 	while( n_h > 0 )
2295 	{
2296 		int16_t n_x = COORD_X( m_packet.FlatRectangle.n_coord );
2297 		int32_t n_distance = SIZE_W( m_packet.FlatRectangle.n_size );
2298 
2299 		while( n_distance > 0 )
2300 		{
2301 			p_p_vram[ n_y & 1023 ][ n_x & 1023 ] =
2302 				p_n_redshade[ MID_LEVEL | n_r.w.h ] |
2303 				p_n_greenshade[ MID_LEVEL | n_g.w.h ] |
2304 				p_n_blueshade[ MID_LEVEL | n_b.w.h ];
2305 			n_x++;
2306 			n_distance--;
2307 		}
2308 
2309 		n_y++;
2310 		n_h--;
2311 	}
2312 }
2313 
FlatRectangle()2314 void psxgpu_device::FlatRectangle()
2315 {
2316 #if PSXGPU_DEBUG_VIEWER
2317 	if( m_debug.n_skip == 8 )
2318 	{
2319 		return;
2320 	}
2321 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_y );
2322 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_x + SIZE_W( m_packet.FlatRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_y );
2323 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_y + SIZE_H( m_packet.FlatRectangle.n_size ) );
2324 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_x + SIZE_W( m_packet.FlatRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) ) + n_drawoffset_y + SIZE_H( m_packet.FlatRectangle.n_size ) );
2325 	DebugMeshEnd();
2326 #endif
2327 
2328 	uint8_t n_cmd = BGR_C( m_packet.FlatRectangle.n_bgr );
2329 
2330 	SOLIDSETUP
2331 
2332 	PAIR n_r; n_r.w.h = BGR_R( m_packet.FlatRectangle.n_bgr ); n_r.w.l = 0;
2333 	PAIR n_g; n_g.w.h = BGR_G( m_packet.FlatRectangle.n_bgr ); n_g.w.l = 0;
2334 	PAIR n_b; n_b.w.h = BGR_B( m_packet.FlatRectangle.n_bgr ); n_b.w.l = 0;
2335 
2336 	int16_t n_x = SINT11( COORD_X( m_packet.FlatRectangle.n_coord ) );
2337 	int16_t n_y = SINT11( COORD_Y( m_packet.FlatRectangle.n_coord ) );
2338 	int32_t n_h = SIZE_H( m_packet.FlatRectangle.n_size );
2339 
2340 	while( n_h > 0 )
2341 	{
2342 		int32_t n_distance = SIZE_W( m_packet.FlatRectangle.n_size );
2343 		int drawy = n_y + n_drawoffset_y;
2344 
2345 		if( n_distance > 0 && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
2346 		{
2347 			int drawx = n_x + n_drawoffset_x;
2348 
2349 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2350 			{
2351 				n_distance -= ( n_drawarea_x1 - drawx );
2352 				drawx = n_drawarea_x1;
2353 			}
2354 
2355 			SOLIDFILL( FLATRECTANGEUPDATE )
2356 		}
2357 
2358 		n_y++;
2359 		n_h--;
2360 	}
2361 }
2362 
FlatRectangle8x8()2363 void psxgpu_device::FlatRectangle8x8()
2364 {
2365 #if PSXGPU_DEBUG_VIEWER
2366 	if( m_debug.n_skip == 9 )
2367 	{
2368 		return;
2369 	}
2370 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_y );
2371 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_x + 8, SINT11( COORD_Y( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_y );
2372 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_y + 8 );
2373 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_x + 8, SINT11( COORD_Y( m_packet.FlatRectangle8x8.n_coord ) ) + n_drawoffset_y + 8 );
2374 	DebugMeshEnd();
2375 #endif
2376 
2377 	uint8_t n_cmd = BGR_C( m_packet.FlatRectangle8x8.n_bgr );
2378 
2379 	SOLIDSETUP
2380 
2381 	PAIR n_r; n_r.w.h = BGR_R( m_packet.FlatRectangle8x8.n_bgr ); n_r.w.l = 0;
2382 	PAIR n_g; n_g.w.h = BGR_G( m_packet.FlatRectangle8x8.n_bgr ); n_g.w.l = 0;
2383 	PAIR n_b; n_b.w.h = BGR_B( m_packet.FlatRectangle8x8.n_bgr ); n_b.w.l = 0;
2384 
2385 	int16_t n_x = SINT11( COORD_X( m_packet.FlatRectangle8x8.n_coord ) );
2386 	int16_t n_y = SINT11( COORD_Y( m_packet.FlatRectangle8x8.n_coord ) );
2387 	int32_t n_h = 8;
2388 
2389 	while( n_h > 0 )
2390 	{
2391 		int32_t n_distance = 8;
2392 		int drawy = n_y + n_drawoffset_y;
2393 
2394 		if( n_distance > 0 && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
2395 		{
2396 			int drawx = n_x + n_drawoffset_x;
2397 
2398 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2399 			{
2400 				n_distance -= ( n_drawarea_x1 - drawx );
2401 				drawx = n_drawarea_x1;
2402 			}
2403 
2404 			SOLIDFILL( FLATRECTANGEUPDATE )
2405 		}
2406 
2407 		n_y++;
2408 		n_h--;
2409 	}
2410 }
2411 
FlatRectangle16x16()2412 void psxgpu_device::FlatRectangle16x16()
2413 {
2414 #if PSXGPU_DEBUG_VIEWER
2415 	if( m_debug.n_skip == 10 )
2416 	{
2417 		return;
2418 	}
2419 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_y );
2420 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_x + 16, SINT11( COORD_Y( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_y );
2421 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_y + 16 );
2422 	DebugMesh( SINT11( COORD_X( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_x + 16, SINT11( COORD_Y( m_packet.FlatRectangle16x16.n_coord ) ) + n_drawoffset_y + 16 );
2423 	DebugMeshEnd();
2424 #endif
2425 
2426 	uint8_t n_cmd = BGR_C( m_packet.FlatRectangle16x16.n_bgr );
2427 
2428 	SOLIDSETUP
2429 
2430 	PAIR n_r; n_r.w.h = BGR_R( m_packet.FlatRectangle16x16.n_bgr ); n_r.w.l = 0;
2431 	PAIR n_g; n_g.w.h = BGR_G( m_packet.FlatRectangle16x16.n_bgr ); n_g.w.l = 0;
2432 	PAIR n_b; n_b.w.h = BGR_B( m_packet.FlatRectangle16x16.n_bgr ); n_b.w.l = 0;
2433 
2434 	int16_t n_x = SINT11( COORD_X( m_packet.FlatRectangle16x16.n_coord ) );
2435 	int16_t n_y = SINT11( COORD_Y( m_packet.FlatRectangle16x16.n_coord ) );
2436 	int32_t n_h = 16;
2437 
2438 	while( n_h > 0 )
2439 	{
2440 		int32_t n_distance = 16;
2441 		int drawy = n_y + n_drawoffset_y;
2442 
2443 		if( n_distance > 0 && n_y >= (int32_t)n_drawarea_y1 && n_y <= (int32_t)n_drawarea_y2 )
2444 		{
2445 			int drawx = n_x + n_drawoffset_x;
2446 
2447 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2448 			{
2449 				n_distance -= ( n_drawarea_x1 - drawx );
2450 				drawx = n_drawarea_x1;
2451 			}
2452 
2453 			SOLIDFILL( FLATRECTANGEUPDATE )
2454 		}
2455 
2456 		n_y++;
2457 		n_h--;
2458 	}
2459 }
2460 
FlatTexturedRectangle()2461 void psxgpu_device::FlatTexturedRectangle()
2462 {
2463 #if PSXGPU_DEBUG_VIEWER
2464 	if( m_debug.n_skip == 11 )
2465 	{
2466 		return;
2467 	}
2468 	DebugMesh( SINT11( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_y );
2469 	DebugMesh( SINT11( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_x + SIZE_W( m_packet.FlatTexturedRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_y );
2470 	DebugMesh( SINT11( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_y + SIZE_H( m_packet.FlatTexturedRectangle.n_size ) );
2471 	DebugMesh( SINT11( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_x + SIZE_W( m_packet.FlatTexturedRectangle.n_size ), SINT11( COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) ) + n_drawoffset_y + SIZE_H( m_packet.FlatTexturedRectangle.n_size ) );
2472 	DebugMeshEnd();
2473 #endif
2474 
2475 	uint8_t n_cmd = BGR_C( m_packet.FlatTexturedRectangle.n_bgr );
2476 
2477 	uint32_t n_clutx = ( m_packet.FlatTexturedRectangle.n_texture.w.h & 0x3f ) << 4;
2478 	uint32_t n_cluty = ( m_packet.FlatTexturedRectangle.n_texture.w.h >> 6 ) & 0x3ff;
2479 
2480 	TEXTURESETUP
2481 	SPRITESETUP
2482 
2483 	PAIR n_r; n_r.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.FlatTexturedRectangle.n_bgr ); n_r.w.l = 0;
2484 	PAIR n_g; n_g.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.FlatTexturedRectangle.n_bgr ); n_g.w.l = 0;
2485 	PAIR n_b; n_b.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.FlatTexturedRectangle.n_bgr ); n_b.w.l = 0;
2486 
2487 	int16_t n_x = SINT11( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) );
2488 	int16_t n_y = SINT11( COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) );
2489 	uint8_t n_v = TEXTURE_V( m_packet.FlatTexturedRectangle.n_texture );
2490 	uint32_t n_h = SIZE_H( m_packet.FlatTexturedRectangle.n_size );
2491 
2492 	while( n_h > 0 )
2493 	{
2494 		uint8_t n_u = TEXTURE_U( m_packet.FlatTexturedRectangle.n_texture );
2495 		int16_t n_distance = SIZE_W( m_packet.FlatTexturedRectangle.n_size );
2496 		int drawy = n_y + n_drawoffset_y;
2497 
2498 		if( n_distance > 0 && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
2499 		{
2500 			int drawx = n_x + n_drawoffset_x;
2501 
2502 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2503 			{
2504 				n_u += ( n_drawarea_x1 - drawx ) * n_du;
2505 				n_distance -= ( n_drawarea_x1 - drawx );
2506 				drawx = n_drawarea_x1;
2507 			}
2508 
2509 			TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
2510 		}
2511 
2512 		n_v += n_dv;
2513 		n_y++;
2514 		n_h--;
2515 	}
2516 }
2517 
Sprite8x8()2518 void psxgpu_device::Sprite8x8()
2519 {
2520 #if PSXGPU_DEBUG_VIEWER
2521 	if( m_debug.n_skip == 12 )
2522 	{
2523 		return;
2524 	}
2525 	DebugMesh( SINT11( COORD_X( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_y );
2526 	DebugMesh( SINT11( COORD_X( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_x + 7, SINT11( COORD_Y( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_y );
2527 	DebugMesh( SINT11( COORD_X( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_y + 7 );
2528 	DebugMesh( SINT11( COORD_X( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_x + 7, SINT11( COORD_Y( m_packet.Sprite8x8.n_coord ) ) + n_drawoffset_y + 7 );
2529 	DebugMeshEnd();
2530 #endif
2531 
2532 	uint8_t n_cmd = BGR_C( m_packet.Sprite8x8.n_bgr );
2533 
2534 	uint32_t n_clutx = ( m_packet.Sprite8x8.n_texture.w.h & 0x3f ) << 4;
2535 	uint32_t n_cluty = ( m_packet.Sprite8x8.n_texture.w.h >> 6 ) & 0x3ff;
2536 
2537 	TEXTURESETUP
2538 	SPRITESETUP
2539 
2540 	PAIR n_r; n_r.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.Sprite8x8.n_bgr ); n_r.w.l = 0;
2541 	PAIR n_g; n_g.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.Sprite8x8.n_bgr ); n_g.w.l = 0;
2542 	PAIR n_b; n_b.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.Sprite8x8.n_bgr ); n_b.w.l = 0;
2543 
2544 	int16_t n_x = SINT11( COORD_X( m_packet.Sprite8x8.n_coord ) );
2545 	int16_t n_y = SINT11( COORD_Y( m_packet.Sprite8x8.n_coord ) );
2546 	uint8_t n_v = TEXTURE_V( m_packet.Sprite8x8.n_texture );
2547 	uint32_t n_h = 8;
2548 
2549 	while( n_h > 0 )
2550 	{
2551 		uint8_t n_u = TEXTURE_U( m_packet.Sprite8x8.n_texture );
2552 		int16_t n_distance = 8;
2553 
2554 		int drawy = n_y + n_drawoffset_y;
2555 
2556 		if( n_distance > 0 && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
2557 		{
2558 			int drawx = n_x + n_drawoffset_x;
2559 
2560 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2561 			{
2562 				n_u += ( n_drawarea_x1 - drawx ) * n_du;
2563 				n_distance -= ( n_drawarea_x1 - drawx );
2564 				drawx = n_drawarea_x1;
2565 			}
2566 
2567 			TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
2568 		}
2569 
2570 		n_v += n_dv;
2571 		n_y++;
2572 		n_h--;
2573 	}
2574 }
2575 
Sprite16x16()2576 void psxgpu_device::Sprite16x16()
2577 {
2578 #if PSXGPU_DEBUG_VIEWER
2579 	if( m_debug.n_skip == 13 )
2580 	{
2581 		return;
2582 	}
2583 	DebugMesh( SINT11( COORD_X( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_y );
2584 	DebugMesh( SINT11( COORD_X( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_x + 7, SINT11( COORD_Y( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_y );
2585 	DebugMesh( SINT11( COORD_X( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_y + 7 );
2586 	DebugMesh( SINT11( COORD_X( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_x + 7, SINT11( COORD_Y( m_packet.Sprite16x16.n_coord ) ) + n_drawoffset_y + 7 );
2587 	DebugMeshEnd();
2588 #endif
2589 
2590 	uint8_t n_cmd = BGR_C( m_packet.Sprite16x16.n_bgr );
2591 
2592 	uint32_t n_clutx = ( m_packet.Sprite16x16.n_texture.w.h & 0x3f ) << 4;
2593 	uint32_t n_cluty = ( m_packet.Sprite16x16.n_texture.w.h >> 6 ) & 0x3ff;
2594 
2595 	TEXTURESETUP
2596 	SPRITESETUP
2597 
2598 	PAIR n_r; n_r.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.Sprite16x16.n_bgr ); n_r.w.l = 0;
2599 	PAIR n_g; n_g.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.Sprite16x16.n_bgr ); n_g.w.l = 0;
2600 	PAIR n_b; n_b.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.Sprite16x16.n_bgr ); n_b.w.l = 0;
2601 
2602 	int16_t n_x = SINT11( COORD_X( m_packet.Sprite16x16.n_coord ) );
2603 	int16_t n_y = SINT11( COORD_Y( m_packet.Sprite16x16.n_coord ) );
2604 	uint8_t n_v = TEXTURE_V( m_packet.Sprite16x16.n_texture );
2605 	uint32_t n_h = 16;
2606 
2607 	while( n_h > 0 )
2608 	{
2609 		uint8_t n_u = TEXTURE_U( m_packet.Sprite16x16.n_texture );
2610 		int16_t n_distance = 16;
2611 
2612 		int drawy = n_y + n_drawoffset_y;
2613 
2614 		if( n_distance > 0 && drawy >= (int32_t)n_drawarea_y1 && drawy <= (int32_t)n_drawarea_y2 )
2615 		{
2616 			int drawx = n_x + n_drawoffset_x;
2617 
2618 			if( ( (int32_t)n_drawarea_x1 - drawx ) > 0 )
2619 			{
2620 				n_u += ( n_drawarea_x1 - drawx ) * n_du;
2621 				n_distance -= ( n_drawarea_x1 - drawx );
2622 				drawx = n_drawarea_x1;
2623 			}
2624 
2625 			TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
2626 		}
2627 
2628 		n_v += n_dv;
2629 		n_y++;
2630 		n_h--;
2631 	}
2632 }
2633 
Dot()2634 void psxgpu_device::Dot()
2635 {
2636 #if PSXGPU_DEBUG_VIEWER
2637 	if( m_debug.n_skip == 14 )
2638 	{
2639 		return;
2640 	}
2641 	DebugMesh( SINT11( COORD_X( m_packet.Dot.vertex.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.Dot.vertex.n_coord ) ) + n_drawoffset_y );
2642 	DebugMeshEnd();
2643 #endif
2644 
2645 	uint8_t n_cmd = BGR_C( m_packet.Dot.n_bgr );
2646 	uint8_t n_r = BGR_R( m_packet.Dot.n_bgr );
2647 	uint8_t n_g = BGR_G( m_packet.Dot.n_bgr );
2648 	uint8_t n_b = BGR_B( m_packet.Dot.n_bgr );
2649 	int32_t n_x = SINT11( COORD_X( m_packet.Dot.vertex.n_coord ) );
2650 	int32_t n_y = SINT11( COORD_Y( m_packet.Dot.vertex.n_coord ) );
2651 
2652 	TRANSPARENCYSETUP
2653 
2654 	int drawx = n_x + n_drawoffset_x;
2655 	int drawy = n_y + n_drawoffset_y;
2656 
2657 	if( drawx >= (int32_t)n_drawarea_x1 && drawy >= (int32_t)n_drawarea_y1 &&
2658 		drawx <= (int32_t)n_drawarea_x2 && drawy <= (int32_t)n_drawarea_y2 )
2659 	{
2660 		uint16_t *p_vram = p_p_vram[ drawy ] + drawx;
2661 
2662 		switch( n_cmd & 0x02 )
2663 		{
2664 		case 0x00:
2665 			/* transparency off */
2666 			WRITE_PIXEL(
2667 				p_n_redshade[ MID_LEVEL | n_r ] |
2668 				p_n_greenshade[ MID_LEVEL | n_g ] |
2669 				p_n_blueshade[ MID_LEVEL | n_b ] )
2670 			break;
2671 		case 0x02:
2672 			/* transparency on */
2673 			WRITE_PIXEL(
2674 				p_n_redtrans[ p_n_f[ MID_LEVEL | n_r ] | p_n_redb[ *( p_vram ) ] ] |
2675 				p_n_greentrans[ p_n_f[ MID_LEVEL | n_g ] | p_n_greenb[ *( p_vram ) ] ] |
2676 				p_n_bluetrans[ p_n_f[ MID_LEVEL | n_b ] | p_n_blueb[ *( p_vram ) ] ] )
2677 			break;
2678 		}
2679 	}
2680 }
2681 
TexturedDot()2682 void psxgpu_device::TexturedDot()
2683 {
2684 #if PSXGPU_DEBUG_VIEWER
2685 	if (m_debug.n_skip == 15)
2686 	{
2687 		return;
2688 	}
2689 	DebugMesh( SINT11( COORD_X( m_packet.TexturedDot.vertex.n_coord ) ) + n_drawoffset_x, SINT11( COORD_Y( m_packet.TexturedDot.vertex.n_coord ) ) + n_drawoffset_y );
2690 	DebugMeshEnd();
2691 #endif
2692 
2693 	uint8_t n_cmd = BGR_C( m_packet.TexturedDot.n_bgr );
2694 
2695 	PAIR n_r; n_r.w.h = n_cmd & 0x01 ? 0x80 : BGR_R( m_packet.TexturedDot.n_bgr ); n_r.w.l = 0;
2696 	PAIR n_g; n_g.w.h = n_cmd & 0x01 ? 0x80 : BGR_G( m_packet.TexturedDot.n_bgr ); n_g.w.l = 0;
2697 	PAIR n_b; n_b.w.h = n_cmd & 0x01 ? 0x80 : BGR_B( m_packet.TexturedDot.n_bgr ); n_b.w.l = 0;
2698 
2699 	int32_t n_x = SINT11( COORD_X( m_packet.TexturedDot.vertex.n_coord ) );
2700 	int32_t n_y = SINT11( COORD_Y( m_packet.TexturedDot.vertex.n_coord ) );
2701 	uint8_t n_u = TEXTURE_U(m_packet.TexturedDot.vertex.n_texture );
2702 	uint8_t n_v = TEXTURE_V(m_packet.TexturedDot.vertex.n_texture );
2703 	uint32_t n_clutx = ( m_packet.TexturedDot.vertex.n_texture.w.h & 0x3f ) << 4;
2704 	uint32_t n_cluty = ( m_packet.TexturedDot.vertex.n_texture.w.h >> 6 ) & 0x3ff;
2705 
2706 	TEXTURESETUP
2707 
2708 	int32_t n_distance = 1;
2709 
2710 	int drawx = n_x + n_drawoffset_x;
2711 	int drawy = n_y + n_drawoffset_y;
2712 
2713 	if( drawx >= (int32_t)n_drawarea_x1 && drawy >= (int32_t)n_drawarea_y1 &&
2714 		drawx <= (int32_t)n_drawarea_x2 && drawy <= (int32_t)n_drawarea_y2 )
2715 	{
2716 		TEXTUREFILL( {}, n_u, n_v );
2717 	}
2718 }
2719 
MoveImage()2720 void psxgpu_device::MoveImage()
2721 {
2722 #if PSXGPU_DEBUG_VIEWER
2723 	if( m_debug.n_skip == 16 )
2724 	{
2725 		return;
2726 	}
2727 	DebugMesh( SINT11( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) ), SINT11( COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) );
2728 	DebugMesh( SINT11( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) + SIZE_W( m_packet.MoveImage.n_size ), SINT11( COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) );
2729 	DebugMesh( SINT11( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) ), SINT11( COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) + SIZE_H( m_packet.MoveImage.n_size ) );
2730 	DebugMesh( SINT11( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) + SIZE_W( m_packet.MoveImage.n_size ), SINT11( COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) ) + SIZE_H( m_packet.MoveImage.n_size ) );
2731 	DebugMeshEnd();
2732 #endif
2733 
2734 	int16_t n_srcy = COORD_Y( m_packet.MoveImage.vertex[ 0 ].n_coord );
2735 	int16_t n_dsty = COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord );
2736 	int16_t n_h = SIZE_H( m_packet.MoveImage.n_size );
2737 
2738 	while( n_h > 0 )
2739 	{
2740 		int16_t n_srcx = COORD_X( m_packet.MoveImage.vertex[ 0 ].n_coord );
2741 		int16_t n_dstx = COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord );
2742 		int16_t n_w = SIZE_W( m_packet.MoveImage.n_size );
2743 
2744 		while( n_w > 0 )
2745 		{
2746 			uint16_t *p_vram = p_p_vram[ n_dsty & 1023 ] + ( n_dstx & 1023 );
2747 			WRITE_PIXEL( *( p_p_vram[ n_srcy & 1023 ] + ( n_srcx & 1023 ) ) )
2748 			n_srcx++;
2749 			n_dstx++;
2750 			n_w--;
2751 		}
2752 
2753 		n_srcy++;
2754 		n_dsty++;
2755 		n_h--;
2756 	}
2757 }
2758 
dma_write(uint32_t * p_n_psxram,uint32_t n_address,int32_t n_size)2759 void psxgpu_device::dma_write( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size )
2760 {
2761 	gpu_write( &p_n_psxram[ n_address / 4 ], n_size );
2762 }
2763 
gpu_write(uint32_t * p_ram,int32_t n_size)2764 void psxgpu_device::gpu_write( uint32_t *p_ram, int32_t n_size )
2765 {
2766 	while( n_size > 0 )
2767 	{
2768 		uint32_t data = *( p_ram );
2769 
2770 		verboselog( *this, 2, "PSX Packet #%u %08x\n", n_gpu_buffer_offset, data );
2771 		m_packet.n_entry[ n_gpu_buffer_offset ] = data;
2772 		switch( m_packet.n_entry[ 0 ] >> 24 )
2773 		{
2774 		case 0x00:
2775 			verboselog( *this, 1, "not handled: GPU Command 0x00: (%08x)\n", data );
2776 			break;
2777 		case 0x01:
2778 			verboselog( *this, 1, "not handled: clear cache\n" );
2779 			break;
2780 		case 0x02:
2781 			if( n_gpu_buffer_offset < 2 )
2782 			{
2783 				n_gpu_buffer_offset++;
2784 			}
2785 			else
2786 			{
2787 				verboselog( *this, 1, "%02x: frame buffer rectangle %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
2788 					m_packet.n_entry[ 1 ] & 0xffff, m_packet.n_entry[ 1 ] >> 16, m_packet.n_entry[ 2 ] & 0xffff, m_packet.n_entry[ 2 ] >> 16 );
2789 				FrameBufferRectangleDraw();
2790 				n_gpu_buffer_offset = 0;
2791 			}
2792 			break;
2793 		case 0x20:
2794 		case 0x21:
2795 		case 0x22:
2796 		case 0x23:
2797 			if( n_gpu_buffer_offset < 3 )
2798 			{
2799 				n_gpu_buffer_offset++;
2800 			}
2801 			else
2802 			{
2803 				verboselog( *this, 1, "%02x: monochrome 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2804 				FlatPolygon( 3 );
2805 				n_gpu_buffer_offset = 0;
2806 			}
2807 			break;
2808 		case 0x24:
2809 		case 0x25:
2810 		case 0x26:
2811 		case 0x27:
2812 			if( n_gpu_buffer_offset < 6 )
2813 			{
2814 				n_gpu_buffer_offset++;
2815 			}
2816 			else
2817 			{
2818 				verboselog( *this, 1, "%02x: textured 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2819 				FlatTexturedPolygon( 3 );
2820 				n_gpu_buffer_offset = 0;
2821 			}
2822 			break;
2823 		case 0x28:
2824 		case 0x29:
2825 		case 0x2a:
2826 		case 0x2b:
2827 			if( n_gpu_buffer_offset < 4 )
2828 			{
2829 				n_gpu_buffer_offset++;
2830 			}
2831 			else
2832 			{
2833 				verboselog( *this, 1, "%02x: monochrome 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2834 				FlatPolygon( 4 );
2835 				n_gpu_buffer_offset = 0;
2836 			}
2837 			break;
2838 		case 0x2c:
2839 		case 0x2d:
2840 		case 0x2e:
2841 		case 0x2f:
2842 			if( n_gpu_buffer_offset < 8 )
2843 			{
2844 				n_gpu_buffer_offset++;
2845 			}
2846 			else
2847 			{
2848 				verboselog( *this, 1, "%02x: textured 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2849 				FlatTexturedPolygon( 4 );
2850 				n_gpu_buffer_offset = 0;
2851 			}
2852 			break;
2853 		case 0x30:
2854 		case 0x31:
2855 		case 0x32:
2856 		case 0x33:
2857 			if( n_gpu_buffer_offset < 5 )
2858 			{
2859 				n_gpu_buffer_offset++;
2860 			}
2861 			else
2862 			{
2863 				verboselog( *this, 1, "%02x: gouraud 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2864 				GouraudPolygon( 3 );
2865 				n_gpu_buffer_offset = 0;
2866 			}
2867 			break;
2868 		case 0x34:
2869 		case 0x35:
2870 		case 0x36:
2871 		case 0x37:
2872 			if( n_gpu_buffer_offset < 8 )
2873 			{
2874 				n_gpu_buffer_offset++;
2875 			}
2876 			else
2877 			{
2878 				verboselog( *this, 1, "%02x: gouraud textured 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2879 				GouraudTexturedPolygon( 3 );
2880 				n_gpu_buffer_offset = 0;
2881 			}
2882 			break;
2883 		case 0x38:
2884 		case 0x39:
2885 		case 0x3a:
2886 		case 0x3b:
2887 			if( n_gpu_buffer_offset < 7 )
2888 			{
2889 				n_gpu_buffer_offset++;
2890 			}
2891 			else
2892 			{
2893 				verboselog( *this, 1, "%02x: gouraud 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2894 				GouraudPolygon( 4 );
2895 				n_gpu_buffer_offset = 0;
2896 			}
2897 			break;
2898 		case 0x3c:
2899 		case 0x3d:
2900 		case 0x3e:
2901 		case 0x3f:
2902 			if( n_gpu_buffer_offset < 11 )
2903 			{
2904 				n_gpu_buffer_offset++;
2905 			}
2906 			else
2907 			{
2908 				verboselog( *this, 1, "%02x: gouraud textured 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
2909 				GouraudTexturedPolygon( 4 );
2910 				n_gpu_buffer_offset = 0;
2911 			}
2912 			break;
2913 		case 0x40:
2914 		case 0x41:
2915 		case 0x42:
2916 		case 0x43:
2917 			if( n_gpu_buffer_offset < 2 )
2918 			{
2919 				n_gpu_buffer_offset++;
2920 			}
2921 			else
2922 			{
2923 				verboselog( *this, 1, "%02x: monochrome line\n", m_packet.n_entry[ 0 ] >> 24 );
2924 				MonochromeLine();
2925 				n_gpu_buffer_offset = 0;
2926 			}
2927 			break;
2928 		case 0x48:
2929 		case 0x4a:
2930 		case 0x4c:
2931 		case 0x4e:
2932 			if( n_gpu_buffer_offset < 3 )
2933 			{
2934 				n_gpu_buffer_offset++;
2935 			}
2936 			else
2937 			{
2938 				verboselog( *this, 1, "%02x: monochrome polyline\n", m_packet.n_entry[ 0 ] >> 24 );
2939 				MonochromeLine();
2940 				if( ( m_packet.n_entry[ 3 ] & 0xf000f000 ) != 0x50005000 )
2941 				{
2942 					m_packet.n_entry[ 1 ] = m_packet.n_entry[ 2 ];
2943 					m_packet.n_entry[ 2 ] = m_packet.n_entry[ 3 ];
2944 					n_gpu_buffer_offset = 3;
2945 				}
2946 				else
2947 				{
2948 					n_gpu_buffer_offset = 0;
2949 				}
2950 			}
2951 			break;
2952 		case 0x50:
2953 		case 0x51:
2954 		case 0x52:
2955 		case 0x53:
2956 			if( n_gpu_buffer_offset < 3 )
2957 			{
2958 				n_gpu_buffer_offset++;
2959 			}
2960 			else
2961 			{
2962 				verboselog( *this, 1, "%02x: gouraud line\n", m_packet.n_entry[ 0 ] >> 24 );
2963 				GouraudLine();
2964 				n_gpu_buffer_offset = 0;
2965 			}
2966 			break;
2967 		case 0x58:
2968 		case 0x5a:
2969 		case 0x5c:
2970 		case 0x5e:
2971 			if( n_gpu_buffer_offset < 5 &&
2972 				( n_gpu_buffer_offset != 4 || ( m_packet.n_entry[ 4 ] & 0xf000f000 ) != 0x50005000 ) )
2973 			{
2974 				n_gpu_buffer_offset++;
2975 			}
2976 			else
2977 			{
2978 				verboselog( *this, 1, "%02x: gouraud polyline\n", m_packet.n_entry[ 0 ] >> 24 );
2979 				GouraudLine();
2980 				if( ( m_packet.n_entry[ 4 ] & 0xf000f000 ) != 0x50005000 )
2981 				{
2982 					m_packet.n_entry[ 0 ] = ( m_packet.n_entry[ 0 ] & 0xff000000 ) | ( m_packet.n_entry[ 2 ] & 0x00ffffff );
2983 					m_packet.n_entry[ 1 ] = m_packet.n_entry[ 3 ];
2984 					m_packet.n_entry[ 2 ] = m_packet.n_entry[ 4 ];
2985 					m_packet.n_entry[ 3 ] = m_packet.n_entry[ 5 ];
2986 					n_gpu_buffer_offset = 4;
2987 				}
2988 				else
2989 				{
2990 					n_gpu_buffer_offset = 0;
2991 				}
2992 			}
2993 			break;
2994 		case 0x60:
2995 		case 0x61:
2996 		case 0x62:
2997 		case 0x63:
2998 			if( n_gpu_buffer_offset < 2 )
2999 			{
3000 				n_gpu_buffer_offset++;
3001 			}
3002 			else
3003 			{
3004 				verboselog( *this, 1, "%02x: rectangle %d,%d %d,%d\n",
3005 					m_packet.n_entry[ 0 ] >> 24,
3006 					(int16_t)( m_packet.n_entry[ 1 ] & 0xffff ), (int16_t)( m_packet.n_entry[ 1 ] >> 16 ),
3007 					(int16_t)( m_packet.n_entry[ 2 ] & 0xffff ), (int16_t)( m_packet.n_entry[ 2 ] >> 16 ) );
3008 				FlatRectangle();
3009 				n_gpu_buffer_offset = 0;
3010 			}
3011 			break;
3012 		case 0x64:
3013 		case 0x65:
3014 		case 0x66:
3015 		case 0x67:
3016 			if( n_gpu_buffer_offset < 3 )
3017 			{
3018 				n_gpu_buffer_offset++;
3019 			}
3020 			else
3021 			{
3022 				verboselog( *this, 1, "%02x: sprite %d,%d %u,%u %08x, %08x\n",
3023 					m_packet.n_entry[ 0 ] >> 24,
3024 					(int16_t)( m_packet.n_entry[ 1 ] & 0xffff ), (int16_t)( m_packet.n_entry[ 1 ] >> 16 ),
3025 					m_packet.n_entry[ 3 ] & 0xffff, m_packet.n_entry[ 3 ] >> 16,
3026 					m_packet.n_entry[ 0 ], m_packet.n_entry[ 2 ] );
3027 				FlatTexturedRectangle();
3028 				n_gpu_buffer_offset = 0;
3029 			}
3030 			break;
3031 		case 0x68:
3032 		case 0x69:
3033 		case 0x6a:
3034 		case 0x6b:
3035 			if( n_gpu_buffer_offset < 1 )
3036 			{
3037 				n_gpu_buffer_offset++;
3038 			}
3039 			else
3040 			{
3041 				verboselog( *this, 1, "%02x: dot %d,%d %08x\n",
3042 					m_packet.n_entry[ 0 ] >> 24,
3043 					(int16_t)( m_packet.n_entry[ 1 ] & 0xffff ), (int16_t)( m_packet.n_entry[ 1 ] >> 16 ),
3044 					m_packet.n_entry[ 0 ] & 0xffffff );
3045 				Dot();
3046 				n_gpu_buffer_offset = 0;
3047 			}
3048 			break;
3049 		case 0x6c:
3050 		case 0x6d:
3051 		case 0x6e:
3052 		case 0x6f:
3053 			if (n_gpu_buffer_offset < 2)
3054 			{
3055 				n_gpu_buffer_offset++;
3056 			}
3057 			else
3058 			{
3059 				verboselog(*this, 1, "%02x: textured dot %d,%d %08x\n",
3060 					m_packet.n_entry[ 0 ] >> 24,
3061 					(int16_t)( m_packet.n_entry[ 1 ] & 0xffff ), (int16_t)( m_packet.n_entry[ 1 ] >> 16 ),
3062 					m_packet.n_entry[ 0 ] & 0xffffff );
3063 				TexturedDot();
3064 				n_gpu_buffer_offset = 0;
3065 			}
3066 			break;
3067 		case 0x70:
3068 		case 0x71:
3069 		case 0x72:
3070 		case 0x73:
3071 			/* 8*8 rectangle */
3072 			if( n_gpu_buffer_offset < 1 )
3073 			{
3074 				n_gpu_buffer_offset++;
3075 			}
3076 			else
3077 			{
3078 				verboselog( *this, 1, "%02x: 16x16 rectangle %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
3079 					m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ] );
3080 				FlatRectangle8x8();
3081 				n_gpu_buffer_offset = 0;
3082 			}
3083 			break;
3084 		case 0x74:
3085 		case 0x75:
3086 		case 0x76:
3087 		case 0x77:
3088 			if( n_gpu_buffer_offset < 2 )
3089 			{
3090 				n_gpu_buffer_offset++;
3091 			}
3092 			else
3093 			{
3094 				verboselog( *this, 1, "%02x: 8x8 sprite %08x %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
3095 					m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ] );
3096 				Sprite8x8();
3097 				n_gpu_buffer_offset = 0;
3098 			}
3099 			break;
3100 		case 0x78:
3101 		case 0x79:
3102 		case 0x7a:
3103 		case 0x7b:
3104 			/* 16*16 rectangle */
3105 			if( n_gpu_buffer_offset < 1 )
3106 			{
3107 				n_gpu_buffer_offset++;
3108 			}
3109 			else
3110 			{
3111 				verboselog( *this, 1, "%02x: 16x16 rectangle %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
3112 					m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ] );
3113 				FlatRectangle16x16();
3114 				n_gpu_buffer_offset = 0;
3115 			}
3116 			break;
3117 		case 0x7c:
3118 		case 0x7d:
3119 		case 0x7e:
3120 		case 0x7f:
3121 			if( n_gpu_buffer_offset < 2 )
3122 			{
3123 				n_gpu_buffer_offset++;
3124 			}
3125 			else
3126 			{
3127 				verboselog( *this, 1, "%02x: 16x16 sprite %08x %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
3128 					m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ] );
3129 				Sprite16x16();
3130 				n_gpu_buffer_offset = 0;
3131 			}
3132 			break;
3133 		case 0x80:
3134 			if( n_gpu_buffer_offset < 3 )
3135 			{
3136 				n_gpu_buffer_offset++;
3137 			}
3138 			else
3139 			{
3140 				verboselog( *this, 1, "move image in frame buffer %08x %08x %08x %08x\n", m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ], m_packet.n_entry[ 3 ] );
3141 				MoveImage();
3142 				n_gpu_buffer_offset = 0;
3143 			}
3144 			break;
3145 		case 0xa0:
3146 			if( n_gpu_buffer_offset < 3 )
3147 			{
3148 				n_gpu_buffer_offset++;
3149 			}
3150 			else
3151 			{
3152 				for( int n_pixel = 0; n_pixel < 2; n_pixel++ )
3153 				{
3154 					verboselog( *this, 2, "send image to framebuffer ( pixel %u,%u = %u )\n",
3155 						( n_vramx + m_packet.n_entry[ 1 ] ) & 1023,
3156 						( n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ) & 1023,
3157 						data & 0xffff );
3158 
3159 					uint16_t *p_vram = p_p_vram[ ( n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ) & 1023 ] + ( ( n_vramx + m_packet.n_entry[ 1 ] ) & 1023 );
3160 					WRITE_PIXEL( data & 0xffff )
3161 					n_vramx++;
3162 					if( n_vramx >= ( m_packet.n_entry[ 2 ] & 0xffff ) )
3163 					{
3164 						n_vramx = 0;
3165 						n_vramy++;
3166 						if( n_vramy >= ( m_packet.n_entry[ 2 ] >> 16 ) )
3167 						{
3168 							verboselog( *this, 1, "%02x: send image to framebuffer %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
3169 								m_packet.n_entry[ 1 ] & 0xffff, ( m_packet.n_entry[ 1 ] >> 16 ),
3170 								m_packet.n_entry[ 2 ] & 0xffff, ( m_packet.n_entry[ 2 ] >> 16 ) );
3171 							n_gpu_buffer_offset = 0;
3172 							n_vramx = 0;
3173 							n_vramy = 0;
3174 							break;
3175 						}
3176 					}
3177 					data >>= 16;
3178 				}
3179 			}
3180 			break;
3181 		case 0xc0:
3182 			if( n_gpu_buffer_offset < 2 )
3183 			{
3184 				n_gpu_buffer_offset++;
3185 			}
3186 			else
3187 			{
3188 				verboselog( *this, 1, "%02x: copy image from frame buffer\n", m_packet.n_entry[ 0 ] >> 24 );
3189 				n_gpustatus |= ( 1L << 0x1b );
3190 			}
3191 			break;
3192 		case 0xe1:
3193 			verboselog( *this, 1, "%02x: draw mode %06x\n", m_packet.n_entry[ 0 ] >> 24,
3194 				m_packet.n_entry[ 0 ] & 0xffffff );
3195 			decode_tpage( m_packet.n_entry[ 0 ] & 0xffffff );
3196 			break;
3197 		case 0xe2:
3198 			n_twy = ( ( ( m_packet.n_entry[ 0 ] >> 15 ) & 0x1f ) << 3 );
3199 			n_twx = ( ( ( m_packet.n_entry[ 0 ] >> 10 ) & 0x1f ) << 3 );
3200 			n_twh = 255 - ( ( ( m_packet.n_entry[ 0 ] >> 5 ) & 0x1f ) << 3 );
3201 			n_tww = 255 - ( ( m_packet.n_entry[ 0 ] & 0x1f ) << 3 );
3202 			verboselog( *this, 1, "%02x: texture window %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
3203 				n_twx, n_twy, n_tww, n_twh );
3204 			break;
3205 		case 0xe3:
3206 			n_drawarea_x1 = m_packet.n_entry[ 0 ] & 1023;
3207 			if( m_n_gputype == 2 )
3208 			{
3209 				n_drawarea_y1 = ( m_packet.n_entry[ 0 ] >> 10 ) & 1023;
3210 			}
3211 			else
3212 			{
3213 				n_drawarea_y1 = ( m_packet.n_entry[ 0 ] >> 12 ) & 1023;
3214 			}
3215 			verboselog( *this, 1, "%02x: drawing area top left %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
3216 				n_drawarea_x1, n_drawarea_y1 );
3217 			break;
3218 		case 0xe4:
3219 			n_drawarea_x2 = m_packet.n_entry[ 0 ] & 1023;
3220 			if( m_n_gputype == 2 )
3221 			{
3222 				n_drawarea_y2 = ( m_packet.n_entry[ 0 ] >> 10 ) & 1023;
3223 			}
3224 			else
3225 			{
3226 				n_drawarea_y2 = ( m_packet.n_entry[ 0 ] >> 12 ) & 1023;
3227 			}
3228 			verboselog( *this, 1, "%02x: drawing area bottom right %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
3229 				n_drawarea_x2, n_drawarea_y2 );
3230 			break;
3231 		case 0xe5:
3232 			n_drawoffset_x = SINT11( m_packet.n_entry[ 0 ] & 2047 );
3233 			if( m_n_gputype == 2 )
3234 			{
3235 				n_drawoffset_y = SINT11( ( m_packet.n_entry[ 0 ] >> 11 ) & 2047 );
3236 			}
3237 			else
3238 			{
3239 				n_drawoffset_y = SINT11( ( m_packet.n_entry[ 0 ] >> 12 ) & 2047 );
3240 			}
3241 			verboselog( *this, 1, "%02x: drawing offset %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
3242 				n_drawoffset_x, n_drawoffset_y );
3243 			break;
3244 		case 0xe6:
3245 			m_draw_stp = BIT( data, 0 );
3246 			m_check_stp = BIT( data, 1 );
3247 			// TODO: confirm status bits on real type 1 gpu
3248 			n_gpustatus &= ~( 3L << 0xb );
3249 			n_gpustatus |= ( data & 0x03 ) << 0xb;
3250 			verboselog( *this, 1, "mask setting %d\n", m_packet.n_entry[ 0 ] & 3 );
3251 			break;
3252 		default:
3253 #if defined( MAME_DEBUG )
3254 			popmessage( "unknown GPU packet %08x", m_packet.n_entry[ 0 ] );
3255 #endif
3256 			verboselog( *this, 0, "unknown GPU packet %08x (%08x)\n", m_packet.n_entry[ 0 ], data );
3257 #if ( STOP_ON_ERROR )
3258 			n_gpu_buffer_offset = 1;
3259 #endif
3260 			break;
3261 		}
3262 		p_ram++;
3263 		n_size--;
3264 	}
3265 }
3266 
write(offs_t offset,uint32_t data,uint32_t mem_mask)3267 void psxgpu_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
3268 {
3269 	switch( offset )
3270 	{
3271 	case 0x00:
3272 		gpu_write( &data, 1 );
3273 		break;
3274 	case 0x01:
3275 		switch( data >> 24 )
3276 		{
3277 		case 0x00:
3278 			gpu_reset();
3279 			break;
3280 		case 0x01:
3281 			verboselog( *this, 1, "not handled: reset command buffer\n" );
3282 			n_gpu_buffer_offset = 0;
3283 			break;
3284 		case 0x02:
3285 			verboselog( *this, 1, "not handled: reset irq\n" );
3286 			break;
3287 		case 0x03:
3288 			n_gpustatus &= ~( 1L << 0x17 );
3289 			n_gpustatus |= ( data & 0x01 ) << 0x17;
3290 			break;
3291 		case 0x04:
3292 			verboselog( *this, 1, "dma setup %d\n", data & 3 );
3293 			n_gpustatus &= ~( 3L << 0x1d );
3294 			n_gpustatus |= ( data & 0x03 ) << 0x1d;
3295 			n_gpustatus &= ~( 1L << 0x19 );
3296 			if( ( data & 3 ) == 1 || ( data & 3 ) == 2 )
3297 			{
3298 				n_gpustatus |= ( 1L << 0x19 );
3299 			}
3300 			break;
3301 		case 0x05:
3302 			m_n_displaystartx = data & 1023;
3303 			if( m_n_gputype == 2 )
3304 			{
3305 				n_displaystarty = ( data >> 10 ) & 1023;
3306 			}
3307 			else
3308 			{
3309 				n_displaystarty = ( data >> 12 ) & 1023;
3310 			}
3311 			verboselog( *this, 1, "start of display area %d %d\n", m_n_displaystartx, n_displaystarty );
3312 			break;
3313 		case 0x06:
3314 			n_horiz_disstart = data & 4095;
3315 			n_horiz_disend = ( data >> 12 ) & 4095;
3316 			verboselog( *this, 1, "horizontal display range %d %d\n", n_horiz_disstart, n_horiz_disend );
3317 			break;
3318 		case 0x07:
3319 			n_vert_disstart = data & 1023;
3320 			n_vert_disend = ( data >> 10 ) & 2047;
3321 			verboselog( *this, 1, "vertical display range %d %d\n", n_vert_disstart, n_vert_disend );
3322 			break;
3323 		case 0x08:
3324 			verboselog( *this, 1, "display mode %02x\n", data & 0xff );
3325 			n_gpustatus &= ~( 127L << 0x10 );
3326 			n_gpustatus |= ( data & 0x3f ) << 0x11; /* width 0 + height + videmode + isrgb24 + isinter */
3327 			n_gpustatus |= ( ( data & 0x40 ) >> 0x06 ) << 0x10; /* width 1 */
3328 			if( m_n_gputype == 1 )
3329 			{
3330 				b_reverseflag = ( data >> 7 ) & 1;
3331 			}
3332 			updatevisiblearea();
3333 			break;
3334 		case 0x09:
3335 			verboselog( *this, 1, "not handled: GPU Control 0x09: %08x\n", data );
3336 			break;
3337 		case 0x0d:
3338 			verboselog( *this, 1, "reset lightgun coordinates %08x\n", data );
3339 			n_lightgun_x = 0;
3340 			n_lightgun_y = 0;
3341 			break;
3342 		case 0x10:
3343 			switch( data & 0xff )
3344 			{
3345 			case 0x03:
3346 				if( m_n_gputype == 2 )
3347 				{
3348 					n_gpuinfo = n_drawarea_x1 | ( n_drawarea_y1 << 10 );
3349 				}
3350 				else
3351 				{
3352 					n_gpuinfo = n_drawarea_x1 | ( n_drawarea_y1 << 12 );
3353 				}
3354 				verboselog( *this, 1, "GPU Info - Draw area top left %08x\n", n_gpuinfo );
3355 				break;
3356 			case 0x04:
3357 				if( m_n_gputype == 2 )
3358 				{
3359 					n_gpuinfo = n_drawarea_x2 | ( n_drawarea_y2 << 10 );
3360 				}
3361 				else
3362 				{
3363 					n_gpuinfo = n_drawarea_x2 | ( n_drawarea_y2 << 12 );
3364 				}
3365 				verboselog( *this, 1, "GPU Info - Draw area bottom right %08x\n", n_gpuinfo );
3366 				break;
3367 			case 0x05:
3368 				if( m_n_gputype == 2 )
3369 				{
3370 					n_gpuinfo = ( n_drawoffset_x & 2047 ) | ( ( n_drawoffset_y & 2047 ) << 11 );
3371 				}
3372 				else
3373 				{
3374 					n_gpuinfo = ( n_drawoffset_x & 2047 ) | ( ( n_drawoffset_y & 2047 ) << 12 );
3375 				}
3376 				verboselog( *this, 1, "GPU Info - Draw offset %08x\n", n_gpuinfo );
3377 				break;
3378 			case 0x07:
3379 				n_gpuinfo = m_n_gputype;
3380 				verboselog( *this, 1, "GPU Info - GPU Type %08x\n", n_gpuinfo );
3381 				break;
3382 			case 0x08:
3383 				n_gpuinfo = n_lightgun_x | ( n_lightgun_y << 16 );
3384 				verboselog( *this, 1, "GPU Info - lightgun coordinates %08x\n", n_gpuinfo );
3385 				break;
3386 			default:
3387 				verboselog( *this, 0, "GPU Info - unknown request (%08x)\n", data );
3388 				n_gpuinfo = 0;
3389 				break;
3390 			}
3391 			break;
3392 		case 0x20:
3393 			verboselog( *this, 1, "not handled: GPU Control 0x20: %08x\n", data );
3394 			break;
3395 		default:
3396 #if defined( MAME_DEBUG )
3397 			popmessage( "unknown GPU command %08x", data );
3398 #endif
3399 			verboselog( *this, 0, "gpu_w( %08x ) unknown GPU command\n", data );
3400 			break;
3401 		}
3402 		break;
3403 	default:
3404 		verboselog( *this, 0, "gpu_w( %08x, %08x, %08x ) unknown register\n", offset, data, mem_mask );
3405 		break;
3406 	}
3407 }
3408 
3409 
dma_read(uint32_t * p_n_psxram,uint32_t n_address,int32_t n_size)3410 void psxgpu_device::dma_read( uint32_t *p_n_psxram, uint32_t n_address, int32_t n_size )
3411 {
3412 	gpu_read( &p_n_psxram[ n_address / 4 ], n_size );
3413 }
3414 
gpu_read(uint32_t * p_ram,int32_t n_size)3415 void psxgpu_device::gpu_read( uint32_t *p_ram, int32_t n_size )
3416 {
3417 	while( n_size > 0 )
3418 	{
3419 		if( ( n_gpustatus & ( 1L << 0x1b ) ) != 0 )
3420 		{
3421 			PAIR data;
3422 
3423 			verboselog( *this, 2, "copy image from frame buffer ( %d, %d )\n", n_vramx, n_vramy );
3424 			data.d = 0;
3425 			for( int n_pixel = 0; n_pixel < 2; n_pixel++ )
3426 			{
3427 				data.w.l = data.w.h;
3428 				data.w.h = *( p_p_vram[ ( n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ) & 0x3ff ] + ( ( n_vramx + ( m_packet.n_entry[ 1 ] & 0xffff ) ) & 0x3ff ) );
3429 				n_vramx++;
3430 				if( n_vramx >= ( m_packet.n_entry[ 2 ] & 0xffff ) )
3431 				{
3432 					n_vramx = 0;
3433 					n_vramy++;
3434 					if( n_vramy >= ( m_packet.n_entry[ 2 ] >> 16 ) )
3435 					{
3436 						verboselog( *this, 1, "copy image from frame buffer end\n" );
3437 						n_gpustatus &= ~( 1L << 0x1b );
3438 						n_gpu_buffer_offset = 0;
3439 						n_vramx = 0;
3440 						n_vramy = 0;
3441 						if( n_pixel == 0 )
3442 						{
3443 							data.w.l = data.w.h;
3444 							data.w.h = 0;
3445 						}
3446 						break;
3447 					}
3448 				}
3449 			}
3450 			*( p_ram ) = data.d;
3451 		}
3452 		else
3453 		{
3454 			verboselog( *this, 2, "read GPU info (%08x)\n", n_gpuinfo );
3455 			*( p_ram ) = n_gpuinfo;
3456 		}
3457 		p_ram++;
3458 		n_size--;
3459 	}
3460 }
3461 
read(offs_t offset,uint32_t mem_mask)3462 uint32_t psxgpu_device::read(offs_t offset, uint32_t mem_mask)
3463 {
3464 	uint32_t data;
3465 
3466 	switch( offset )
3467 	{
3468 	case 0x00:
3469 		gpu_read( &data, 1 );
3470 		break;
3471 	case 0x01:
3472 		data = n_gpustatus;
3473 		verboselog( *this, 1, "read GPU status (%08x)\n", data );
3474 		break;
3475 	default:
3476 		verboselog( *this, 0, "gpu_r( %08x, %08x ) unknown register\n", offset, mem_mask );
3477 		data = 0;
3478 		break;
3479 	}
3480 	return data;
3481 }
3482 
vblank(screen_device & screen,bool vblank_state)3483 void psxgpu_device::vblank(screen_device &screen, bool vblank_state)
3484 {
3485 	if( vblank_state )
3486 	{
3487 #if PSXGPU_DEBUG_VIEWER
3488 		DebugCheckKeys();
3489 #endif
3490 
3491 		n_gpustatus ^= ( 1L << 31 );
3492 		m_vblank_handler(1);
3493 	}
3494 }
3495 
gpu_reset()3496 void psxgpu_device::gpu_reset()
3497 {
3498 	verboselog( *this, 1, "reset gpu\n" );
3499 	n_gpu_buffer_offset = 0;
3500 	n_gpustatus = 0x14802000;
3501 	n_drawarea_x1 = 0;
3502 	n_drawarea_y1 = 0;
3503 	n_drawarea_x2 = 1023;
3504 	n_drawarea_y2 = 1023;
3505 	n_drawoffset_x = 0;
3506 	n_drawoffset_y = 0;
3507 	m_n_displaystartx = 0;
3508 	n_displaystarty = 0;
3509 	n_horiz_disstart = 0x260;
3510 	n_horiz_disend = 0xc60;
3511 	n_vert_disstart = 0x010;
3512 	n_vert_disend = 0x100;
3513 	n_vramx = 0;
3514 	n_vramy = 0;
3515 	n_twx = 0;
3516 	n_twy = 0;
3517 	n_twh = 255;
3518 	n_tww = 255;
3519 	m_draw_stp = false;
3520 	m_check_stp = false;
3521 	updatevisiblearea();
3522 }
3523 
lightgun_set(int n_x,int n_y)3524 void psxgpu_device::lightgun_set( int n_x, int n_y )
3525 {
3526 	n_lightgun_x = n_x;
3527 	n_lightgun_y = n_y;
3528 }
3529 
3530 //-------------------------------------------------
3531 //  device_config_complete - perform any
3532 //  operations now that the configuration is
3533 //  complete
3534 //-------------------------------------------------
3535 
device_config_complete()3536 void psxgpu_device::device_config_complete()
3537 {
3538 	if (!has_screen())
3539 		return;
3540 
3541 	if (!screen().refresh_attoseconds())
3542 	{
3543 		screen().set_refresh_hz(60);
3544 		screen().set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */);
3545 		screen().set_size(1024, 1024);
3546 		screen().set_visarea(0, 639, 0, 479);
3547 	}
3548 
3549 	if (!screen().has_screen_update())
3550 		screen().set_screen_update(*this, FUNC(psxgpu_device::update_screen));
3551 }
3552