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