1 /* Copyright 2003-2005 Guillaume Duhamel
2 Copyright 2004 Lawrence Sebald
3 Copyright 2004-2006 Theo Berkau
4
5 This file is part of Yabause.
6
7 Yabause is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Yabause is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Yabause; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /*! \file vdp1.c
23 \brief VDP1 emulation functions.
24 */
25
26
27 #include <stdlib.h>
28 #include "vdp1.h"
29 #include "debug.h"
30 #include "scu.h"
31 #include "vdp2.h"
32 #include "vidsoft.h"
33 #include "threads.h"
34 #include "sh2core.h"
35
36 u8 * Vdp1Ram;
37 u8 * Vdp1FrameBuffer;
38
39 VideoInterface_struct *VIDCore=NULL;
40 extern VideoInterface_struct *VIDCoreList[];
41 int VideoUseGL = 1;
42
43 //////////////////////////////////////////////////////////////////////////////
44
Vdp1RamReadByte(u32 addr)45 u8 FASTCALL Vdp1RamReadByte(u32 addr) {
46 addr &= 0x7FFFF;
47 return T1ReadByte(Vdp1Ram, addr);
48 }
49
50 //////////////////////////////////////////////////////////////////////////////
51
Vdp1RamReadWord(u32 addr)52 u16 FASTCALL Vdp1RamReadWord(u32 addr) {
53 addr &= 0x7FFFF;
54 return T1ReadWord(Vdp1Ram, addr);
55 }
56
57 //////////////////////////////////////////////////////////////////////////////
58
Vdp1RamReadLong(u32 addr)59 u32 FASTCALL Vdp1RamReadLong(u32 addr) {
60 addr &= 0x7FFFF;
61 return T1ReadLong(Vdp1Ram, addr);
62 }
63
64 //////////////////////////////////////////////////////////////////////////////
65
Vdp1RamWriteByte(u32 addr,u8 val)66 void FASTCALL Vdp1RamWriteByte(u32 addr, u8 val) {
67 addr &= 0x7FFFF;
68 T1WriteByte(Vdp1Ram, addr, val);
69 }
70
71 //////////////////////////////////////////////////////////////////////////////
72
Vdp1RamWriteWord(u32 addr,u16 val)73 void FASTCALL Vdp1RamWriteWord(u32 addr, u16 val) {
74 addr &= 0x7FFFF;
75 T1WriteWord(Vdp1Ram, addr, val);
76 }
77
78 //////////////////////////////////////////////////////////////////////////////
79
Vdp1RamWriteLong(u32 addr,u32 val)80 void FASTCALL Vdp1RamWriteLong(u32 addr, u32 val) {
81 addr &= 0x7FFFF;
82 T1WriteLong(Vdp1Ram, addr, val);
83 }
84
85 //////////////////////////////////////////////////////////////////////////////
86
Vdp1FrameBufferReadByte(u32 addr)87 u8 FASTCALL Vdp1FrameBufferReadByte(u32 addr) {
88 addr &= 0x3FFFF;
89 if (VIDCore->Vdp1ReadFrameBuffer){
90 u8 val;
91 VIDCore->Vdp1ReadFrameBuffer(0, addr, &val);
92 return val;
93 }
94 return T1ReadByte(Vdp1FrameBuffer, addr);
95 }
96
97 //////////////////////////////////////////////////////////////////////////////
98
Vdp1FrameBufferReadWord(u32 addr)99 u16 FASTCALL Vdp1FrameBufferReadWord(u32 addr) {
100 addr &= 0x3FFFF;
101 if (VIDCore->Vdp1ReadFrameBuffer){
102 u16 val;
103 VIDCore->Vdp1ReadFrameBuffer(1, addr, &val);
104 return val;
105 }
106 return T1ReadWord(Vdp1FrameBuffer, addr);
107 }
108
109 //////////////////////////////////////////////////////////////////////////////
110
Vdp1FrameBufferReadLong(u32 addr)111 u32 FASTCALL Vdp1FrameBufferReadLong(u32 addr) {
112 addr &= 0x3FFFF;
113 if (VIDCore->Vdp1ReadFrameBuffer){
114 u32 val;
115 VIDCore->Vdp1ReadFrameBuffer(2, addr, &val);
116 return val;
117 }
118 return T1ReadLong(Vdp1FrameBuffer, addr);
119 }
120
121 //////////////////////////////////////////////////////////////////////////////
122
Vdp1FrameBufferWriteByte(u32 addr,u8 val)123 void FASTCALL Vdp1FrameBufferWriteByte(u32 addr, u8 val) {
124 addr &= 0x3FFFF;
125
126 if (VIDCore->Vdp1WriteFrameBuffer)
127 {
128 VIDCore->Vdp1WriteFrameBuffer(0, addr, val);
129 return;
130 }
131
132 T1WriteByte(Vdp1FrameBuffer, addr, val);
133 }
134
135 //////////////////////////////////////////////////////////////////////////////
136
Vdp1FrameBufferWriteWord(u32 addr,u16 val)137 void FASTCALL Vdp1FrameBufferWriteWord(u32 addr, u16 val) {
138 addr &= 0x3FFFF;
139
140 if (VIDCore->Vdp1WriteFrameBuffer)
141 {
142 VIDCore->Vdp1WriteFrameBuffer(1, addr, val);
143 return;
144 }
145
146 T1WriteWord(Vdp1FrameBuffer, addr, val);
147 }
148
149 //////////////////////////////////////////////////////////////////////////////
150
Vdp1FrameBufferWriteLong(u32 addr,u32 val)151 void FASTCALL Vdp1FrameBufferWriteLong(u32 addr, u32 val) {
152 addr &= 0x3FFFF;
153
154 if (VIDCore->Vdp1WriteFrameBuffer)
155 {
156 VIDCore->Vdp1WriteFrameBuffer(2, addr, val);
157 return;
158 }
159
160 T1WriteLong(Vdp1FrameBuffer, addr, val);
161 }
162
163 //////////////////////////////////////////////////////////////////////////////
164
Sh2Vdp1RamReadByte(SH2_struct * sh,u32 addr)165 u8 FASTCALL Sh2Vdp1RamReadByte(SH2_struct *sh, u32 addr) {
166 return Vdp1RamReadByte(addr);
167 }
168
169 //////////////////////////////////////////////////////////////////////////////
170
Sh2Vdp1RamReadWord(SH2_struct * sh,u32 addr)171 u16 FASTCALL Sh2Vdp1RamReadWord(SH2_struct *sh, u32 addr) {
172 return Vdp1RamReadWord(addr);
173 }
174
175 //////////////////////////////////////////////////////////////////////////////
176
Sh2Vdp1RamReadLong(SH2_struct * sh,u32 addr)177 u32 FASTCALL Sh2Vdp1RamReadLong(SH2_struct *sh, u32 addr) {
178 return Vdp1RamReadLong(addr);
179 }
180
181 //////////////////////////////////////////////////////////////////////////////
182
Sh2Vdp1RamWriteByte(SH2_struct * sh,u32 addr,u8 val)183 void FASTCALL Sh2Vdp1RamWriteByte(SH2_struct *sh, u32 addr, u8 val) {
184 Vdp1RamWriteByte(addr, val);
185 }
186
187 //////////////////////////////////////////////////////////////////////////////
188
Sh2Vdp1RamWriteWord(SH2_struct * sh,u32 addr,u16 val)189 void FASTCALL Sh2Vdp1RamWriteWord(SH2_struct *sh, u32 addr, u16 val) {
190 Vdp1RamWriteWord(addr, val);
191 }
192
193 //////////////////////////////////////////////////////////////////////////////
194
Sh2Vdp1RamWriteLong(SH2_struct * sh,u32 addr,u32 val)195 void FASTCALL Sh2Vdp1RamWriteLong(SH2_struct *sh, u32 addr, u32 val) {
196 Vdp1RamWriteLong(addr, val);
197 }
198
199 //////////////////////////////////////////////////////////////////////////////
200
Sh2Vdp1FrameBufferReadByte(SH2_struct * sh,u32 addr)201 u8 FASTCALL Sh2Vdp1FrameBufferReadByte(SH2_struct *sh, u32 addr) {
202 return Vdp1FrameBufferReadByte(addr);
203 }
204
205 //////////////////////////////////////////////////////////////////////////////
206
Sh2Vdp1FrameBufferReadWord(SH2_struct * sh,u32 addr)207 u16 FASTCALL Sh2Vdp1FrameBufferReadWord(SH2_struct *sh, u32 addr) {
208 return Vdp1FrameBufferReadWord(addr);
209 }
210
211 //////////////////////////////////////////////////////////////////////////////
212
Sh2Vdp1FrameBufferReadLong(SH2_struct * sh,u32 addr)213 u32 FASTCALL Sh2Vdp1FrameBufferReadLong(SH2_struct *sh, u32 addr) {
214 return Vdp1FrameBufferReadLong(addr);
215 }
216
217 //////////////////////////////////////////////////////////////////////////////
218
Sh2Vdp1FrameBufferWriteByte(SH2_struct * sh,u32 addr,u8 val)219 void FASTCALL Sh2Vdp1FrameBufferWriteByte(SH2_struct *sh, u32 addr, u8 val) {
220 Vdp1FrameBufferWriteByte(addr, val);
221 }
222
223 //////////////////////////////////////////////////////////////////////////////
224
Sh2Vdp1FrameBufferWriteWord(SH2_struct * sh,u32 addr,u16 val)225 void FASTCALL Sh2Vdp1FrameBufferWriteWord(SH2_struct *sh, u32 addr, u16 val) {
226 Vdp1FrameBufferWriteWord(addr, val);
227 }
228
229 //////////////////////////////////////////////////////////////////////////////
230
Sh2Vdp1FrameBufferWriteLong(SH2_struct * sh,u32 addr,u32 val)231 void FASTCALL Sh2Vdp1FrameBufferWriteLong(SH2_struct *sh, u32 addr, u32 val) {
232 Vdp1FrameBufferWriteLong(addr, val);
233 }
234
235 //////////////////////////////////////////////////////////////////////////////
236
237 Vdp1 * Vdp1Regs;
238 Vdp1External_struct Vdp1External;
239
240 //////////////////////////////////////////////////////////////////////////////
241
Vdp1Init(void)242 int Vdp1Init(void) {
243 if ((Vdp1Regs = (Vdp1 *) malloc(sizeof(Vdp1))) == NULL)
244 return -1;
245
246 if ((Vdp1Ram = T1MemoryInit(0x80000)) == NULL)
247 return -1;
248
249 // Allocate enough memory for two frames
250 if ((Vdp1FrameBuffer = T1MemoryInit(0x80000)) == NULL)
251 return -1;
252
253 Vdp1External.disptoggle = 1;
254
255 return 0;
256 }
257
258 //////////////////////////////////////////////////////////////////////////////
259
Vdp1DeInit(void)260 void Vdp1DeInit(void) {
261 if (Vdp1Regs)
262 free(Vdp1Regs);
263 Vdp1Regs = NULL;
264
265 if (Vdp1Ram)
266 T1MemoryDeInit(Vdp1Ram);
267 Vdp1Ram = NULL;
268
269 if (Vdp1FrameBuffer)
270 T1MemoryDeInit(Vdp1FrameBuffer);
271 Vdp1FrameBuffer = NULL;
272 }
273
274 //////////////////////////////////////////////////////////////////////////////
275
VideoInit(int coreid)276 int VideoInit(int coreid) {
277 return VideoChangeCore(coreid);
278 }
279
280 //////////////////////////////////////////////////////////////////////////////
281
VideoChangeCore(int coreid)282 int VideoChangeCore(int coreid)
283 {
284 int i;
285
286 // Make sure the old core is freed
287 VideoDeInit();
288
289 // So which core do we want?
290 if (coreid == VIDCORE_DEFAULT)
291 coreid = 0; // Assume we want the first one
292
293 // Go through core list and find the id
294 for (i = 0; VIDCoreList[i] != NULL; i++)
295 {
296 if (VIDCoreList[i]->id == coreid)
297 {
298 // Set to current core
299 VIDCore = VIDCoreList[i];
300 break;
301 }
302 }
303
304 if (VIDCore == NULL)
305 return -1;
306
307 if (VIDCore->Init() != 0)
308 return -1;
309
310 // Reset resolution/priority variables
311 if (Vdp2Regs)
312 {
313 VIDCore->Vdp1Reset();
314 }
315
316 return 0;
317 }
318
319 //////////////////////////////////////////////////////////////////////////////
320
VideoDeInit(void)321 void VideoDeInit(void) {
322 if (VIDCore)
323 VIDCore->DeInit();
324 VIDCore = NULL;
325 }
326
327 //////////////////////////////////////////////////////////////////////////////
328
Vdp1Reset(void)329 void Vdp1Reset(void) {
330 Vdp1Regs->PTMR = 0;
331 Vdp1Regs->MODR = 0x1000; // VDP1 Version 1
332 VIDCore->Vdp1Reset();
333 }
334
335 //////////////////////////////////////////////////////////////////////////////
336
Vdp1ReadByte(u32 addr)337 u8 FASTCALL Vdp1ReadByte(u32 addr) {
338 addr &= 0xFF;
339 LOG("trying to byte-read a Vdp1 register\n");
340 return 0;
341 }
342
343 //////////////////////////////////////////////////////////////////////////////
344
Vdp1ReadWord(u32 addr)345 u16 FASTCALL Vdp1ReadWord(u32 addr) {
346 addr &= 0xFF;
347 switch(addr) {
348 case 0x10:
349 LOG("Read EDSR %X\n", Vdp1Regs->EDSR );
350 return Vdp1Regs->EDSR;
351 case 0x12:
352 return Vdp1Regs->LOPR;
353 case 0x14:
354 return Vdp1Regs->COPR;
355 case 0x16:
356 return 0x1000 | ((Vdp1Regs->PTMR & 2) << 7) | ((Vdp1Regs->FBCR & 0x1E) << 3) | (Vdp1Regs->TVMR & 0xF);
357 default:
358 LOG("trying to read a Vdp1 write-only register\n");
359 }
360 return 0;
361 }
362
363 //////////////////////////////////////////////////////////////////////////////
364
Vdp1ReadLong(u32 addr)365 u32 FASTCALL Vdp1ReadLong(u32 addr) {
366 addr &= 0xFF;
367 LOG("trying to long-read a Vdp1 register - %08X\n", addr);
368 return 0;
369 }
370
371 //////////////////////////////////////////////////////////////////////////////
372
Vdp1WriteByte(u32 addr,UNUSED u8 val)373 void FASTCALL Vdp1WriteByte(u32 addr, UNUSED u8 val) {
374 addr &= 0xFF;
375 LOG("trying to byte-write a Vdp1 register - %08X\n", addr);
376 }
377
378
379
380 //////////////////////////////////////////////////////////////////////////////
381
Vdp1WriteWord(u32 addr,u16 val)382 void FASTCALL Vdp1WriteWord(u32 addr, u16 val) {
383 addr &= 0xFF;
384 switch(addr) {
385 case 0x0:
386 Vdp1Regs->TVMR = val;
387 break;
388 case 0x2:
389 Vdp1Regs->FBCR = val;
390 if ((Vdp1Regs->FBCR & 3) == 3)
391 {
392 Vdp1External.manualchange = 1;
393 }
394 else if ((Vdp1Regs->FBCR & 3) == 2)
395 Vdp1External.manualerase = 1;
396 break;
397 case 0x4:
398 Vdp1Regs->COPR = 0;
399 Vdp1Regs->PTMR = val;
400 if (val == 1) Vdp1Draw();
401 break;
402 case 0x6:
403 Vdp1Regs->EWDR = val;
404 break;
405 case 0x8:
406 Vdp1Regs->EWLR = val;
407 break;
408 case 0xA:
409 Vdp1Regs->EWRR = val;
410 break;
411 case 0xC:
412 Vdp1Regs->ENDR = val;
413 break;
414 default:
415 LOG("trying to write a Vdp1 read-only register - %08X\n", addr);
416 }
417 }
418
419 //////////////////////////////////////////////////////////////////////////////
420
Vdp1WriteLong(u32 addr,UNUSED u32 val)421 void FASTCALL Vdp1WriteLong(u32 addr, UNUSED u32 val) {
422 addr &= 0xFF;
423 LOG("trying to long-write a Vdp1 register - %08X\n", addr);
424 }
425
426 //////////////////////////////////////////////////////////////////////////////
427
Sh2Vdp1ReadByte(SH2_struct * sh,u32 addr)428 u8 FASTCALL Sh2Vdp1ReadByte(SH2_struct *sh, u32 addr) {
429 return Vdp1ReadByte(addr);
430 }
431
432 //////////////////////////////////////////////////////////////////////////////
433
Sh2Vdp1ReadWord(SH2_struct * sh,u32 addr)434 u16 FASTCALL Sh2Vdp1ReadWord(SH2_struct *sh, u32 addr) {
435 return Vdp1ReadWord(addr);
436 }
437
438 //////////////////////////////////////////////////////////////////////////////
439
Sh2Vdp1ReadLong(SH2_struct * sh,u32 addr)440 u32 FASTCALL Sh2Vdp1ReadLong(SH2_struct *sh, u32 addr) {
441 return Vdp1ReadLong(addr);
442 }
443
444 //////////////////////////////////////////////////////////////////////////////
445
Sh2Vdp1WriteByte(SH2_struct * sh,u32 addr,UNUSED u8 val)446 void FASTCALL Sh2Vdp1WriteByte(SH2_struct *sh, u32 addr, UNUSED u8 val) {
447 Vdp1WriteByte(addr, val);
448 }
449
450 //////////////////////////////////////////////////////////////////////////////
451
Sh2Vdp1WriteWord(SH2_struct * sh,u32 addr,u16 val)452 void FASTCALL Sh2Vdp1WriteWord(SH2_struct *sh, u32 addr, u16 val) {
453 Vdp1WriteWord(addr, val);
454 }
455
456 //////////////////////////////////////////////////////////////////////////////
457
Sh2Vdp1WriteLong(SH2_struct * sh,u32 addr,UNUSED u32 val)458 void FASTCALL Sh2Vdp1WriteLong(SH2_struct *sh, u32 addr, UNUSED u32 val) {
459 Vdp1WriteLong(addr, val);
460 }
461
462 //////////////////////////////////////////////////////////////////////////////
463
Vdp1DrawCommands(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)464 void Vdp1DrawCommands(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
465 {
466 u16 command = T1ReadWord(ram, regs->addr);
467 u32 commandCounter = 0;
468 u32 returnAddr = 0xffffffff;
469
470 while (!(command & 0x8000) && commandCounter < 2000) { // fix me
471 // First, process the command
472 if (!(command & 0x4000)) { // if (!skip)
473 switch (command & 0x000F) {
474 case 0: // normal sprite draw
475 VIDCore->Vdp1NormalSpriteDraw(ram, regs, back_framebuffer);
476 break;
477 case 1: // scaled sprite draw
478 VIDCore->Vdp1ScaledSpriteDraw(ram, regs, back_framebuffer);
479 break;
480 case 2: // distorted sprite draw
481 case 3: /* this one should be invalid, but some games
482 (Hardcore 4x4 for instance) use it instead of 2 */
483 VIDCore->Vdp1DistortedSpriteDraw(ram, regs, back_framebuffer);
484 break;
485 case 4: // polygon draw
486 VIDCore->Vdp1PolygonDraw(ram, regs, back_framebuffer);
487 break;
488 case 5: // polyline draw
489 case 7: // undocumented mirror
490 VIDCore->Vdp1PolylineDraw(ram, regs, back_framebuffer);
491 break;
492 case 6: // line draw
493 VIDCore->Vdp1LineDraw(ram, regs, back_framebuffer);
494 break;
495 case 8: // user clipping coordinates
496 case 11: // undocumented mirror
497 VIDCore->Vdp1UserClipping(ram, regs);
498 break;
499 case 9: // system clipping coordinates
500 VIDCore->Vdp1SystemClipping(ram, regs);
501 break;
502 case 10: // local coordinate
503 VIDCore->Vdp1LocalCoordinate(ram, regs);
504 break;
505 default: // Abort
506 VDP1LOG("vdp1\t: Bad command: %x\n", command);
507 regs->EDSR |= 2;
508 VIDCore->Vdp1DrawEnd();
509 regs->LOPR = regs->addr >> 3;
510 regs->COPR = regs->addr >> 3;
511 return;
512 }
513 }
514
515 // Next, determine where to go next
516 switch ((command & 0x3000) >> 12) {
517 case 0: // NEXT, jump to following table
518 regs->addr += 0x20;
519 break;
520 case 1: // ASSIGN, jump to CMDLINK
521 regs->addr = T1ReadWord(ram, regs->addr + 2) * 8;
522 break;
523 case 2: // CALL, call a subroutine
524 if (returnAddr == 0xFFFFFFFF)
525 returnAddr = regs->addr + 0x20;
526
527 regs->addr = T1ReadWord(ram, regs->addr + 2) * 8;
528 break;
529 case 3: // RETURN, return from subroutine
530 if (returnAddr != 0xFFFFFFFF) {
531 regs->addr = returnAddr;
532 returnAddr = 0xFFFFFFFF;
533 }
534 else
535 regs->addr += 0x20;
536 break;
537 }
538
539 command = T1ReadWord(ram, regs->addr);
540 commandCounter++;
541 }
542 }
543
544 //ensure that registers are set correctly
Vdp1FakeDrawCommands(u8 * ram,Vdp1 * regs)545 void Vdp1FakeDrawCommands(u8 * ram, Vdp1 * regs)
546 {
547 u16 command = T1ReadWord(ram, regs->addr);
548 u32 commandCounter = 0;
549 u32 returnAddr = 0xffffffff;
550
551 while (!(command & 0x8000) && commandCounter < 2000) { // fix me
552 // First, process the command
553 if (!(command & 0x4000)) { // if (!skip)
554 switch (command & 0x000F) {
555 case 0: // normal sprite draw
556 case 1: // scaled sprite draw
557 case 2: // distorted sprite draw
558 case 3: /* this one should be invalid, but some games
559 (Hardcore 4x4 for instance) use it instead of 2 */
560 case 4: // polygon draw
561 case 5: // polyline draw
562 case 6: // line draw
563 case 7: // undocumented polyline draw mirror
564 break;
565 case 8: // user clipping coordinates
566 case 11: // undocumented mirror
567 VIDCore->Vdp1UserClipping(ram, regs);
568 break;
569 case 9: // system clipping coordinates
570 VIDCore->Vdp1SystemClipping(ram, regs);
571 break;
572 case 10: // local coordinate
573 VIDCore->Vdp1LocalCoordinate(ram, regs);
574 break;
575 default: // Abort
576 VDP1LOG("vdp1\t: Bad command: %x\n", command);
577 regs->EDSR |= 2;
578 VIDCore->Vdp1DrawEnd();
579 regs->LOPR = regs->addr >> 3;
580 regs->COPR = regs->addr >> 3;
581 return;
582 }
583 }
584
585 // Next, determine where to go next
586 switch ((command & 0x3000) >> 12) {
587 case 0: // NEXT, jump to following table
588 regs->addr += 0x20;
589 break;
590 case 1: // ASSIGN, jump to CMDLINK
591 regs->addr = T1ReadWord(ram, regs->addr + 2) * 8;
592 break;
593 case 2: // CALL, call a subroutine
594 if (returnAddr == 0xFFFFFFFF)
595 returnAddr = regs->addr + 0x20;
596
597 regs->addr = T1ReadWord(ram, regs->addr + 2) * 8;
598 break;
599 case 3: // RETURN, return from subroutine
600 if (returnAddr != 0xFFFFFFFF) {
601 regs->addr = returnAddr;
602 returnAddr = 0xFFFFFFFF;
603 }
604 else
605 regs->addr += 0x20;
606 break;
607 }
608
609 command = T1ReadWord(ram, regs->addr);
610 commandCounter++;
611 }
612 }
613
Vdp1Draw(void)614 void Vdp1Draw(void)
615 {
616 if (!Vdp1External.disptoggle)
617 {
618 Vdp1NoDraw();
619 return;
620 }
621
622 Vdp1Regs->addr = 0;
623
624 // beginning of a frame
625 // BEF <- CEF
626 // CEF <- 0
627 Vdp1Regs->EDSR >>= 1;
628 /* this should be done after a frame change or a plot trigger */
629 Vdp1Regs->COPR = 0;
630
631 VIDCore->Vdp1DrawStart();
632
633 // we set two bits to 1
634 Vdp1Regs->EDSR |= 2;
635 Vdp1Regs->COPR = Vdp1Regs->addr >> 3;
636 ScuSendDrawEnd();
637 VIDCore->Vdp1DrawEnd();
638 }
639
640 //////////////////////////////////////////////////////////////////////////////
641
Vdp1NoDraw(void)642 void Vdp1NoDraw(void) {
643 // beginning of a frame (ST-013-R3-061694 page 53)
644 // BEF <- CEF
645 // CEF <- 0
646 Vdp1Regs->EDSR >>= 1;
647 /* this should be done after a frame change or a plot trigger */
648 Vdp1Regs->COPR = 0;
649
650 Vdp1FakeDrawCommands(Vdp1Ram, Vdp1Regs);
651
652 // we set two bits to 1
653 Vdp1Regs->EDSR |= 2;
654 ScuSendDrawEnd();
655 Vdp1External.manualchange = 0;
656 }
657
658 //////////////////////////////////////////////////////////////////////////////
659
Vdp1ReadCommand(vdp1cmd_struct * cmd,u32 addr,u8 * ram)660 void FASTCALL Vdp1ReadCommand(vdp1cmd_struct *cmd, u32 addr, u8* ram) {
661 cmd->CMDCTRL = T1ReadWord(ram, addr);
662 cmd->CMDLINK = T1ReadWord(ram, addr + 0x2);
663 cmd->CMDPMOD = T1ReadWord(ram, addr + 0x4);
664 cmd->CMDCOLR = T1ReadWord(ram, addr + 0x6);
665 cmd->CMDSRCA = T1ReadWord(ram, addr + 0x8);
666 cmd->CMDSIZE = T1ReadWord(ram, addr + 0xA);
667 cmd->CMDXA = T1ReadWord(ram, addr + 0xC);
668 cmd->CMDYA = T1ReadWord(ram, addr + 0xE);
669 cmd->CMDXB = T1ReadWord(ram, addr + 0x10);
670 cmd->CMDYB = T1ReadWord(ram, addr + 0x12);
671 cmd->CMDXC = T1ReadWord(ram, addr + 0x14);
672 cmd->CMDYC = T1ReadWord(ram, addr + 0x16);
673 cmd->CMDXD = T1ReadWord(ram, addr + 0x18);
674 cmd->CMDYD = T1ReadWord(ram, addr + 0x1A);
675 cmd->CMDGRDA = T1ReadWord(ram, addr + 0x1C);
676 }
677
678 //////////////////////////////////////////////////////////////////////////////
679
Vdp1SaveState(FILE * fp)680 int Vdp1SaveState(FILE *fp)
681 {
682 int offset;
683 IOCheck_struct check = { 0, 0 };
684 #ifdef IMPROVED_SAVESTATES
685 int i = 0;
686 u8 back_framebuffer[0x40000] = { 0 };
687 #endif
688
689 offset = StateWriteHeader(fp, "VDP1", 1);
690
691 // Write registers
692 ywrite(&check, (void *)Vdp1Regs, sizeof(Vdp1), 1, fp);
693
694 // Write VDP1 ram
695 ywrite(&check, (void *)Vdp1Ram, 0x80000, 1, fp);
696
697 #ifdef IMPROVED_SAVESTATES
698 for (i = 0; i < 0x40000; i++)
699 back_framebuffer[i] = Vdp1FrameBufferReadByte(i);
700
701 ywrite(&check, (void *)back_framebuffer, 0x40000, 1, fp);
702 #endif
703 return StateFinishHeader(fp, offset);
704 }
705
706 //////////////////////////////////////////////////////////////////////////////
707
Vdp1LoadState(FILE * fp,UNUSED int version,int size)708 int Vdp1LoadState(FILE *fp, UNUSED int version, int size)
709 {
710 IOCheck_struct check = { 0, 0 };
711 #ifdef IMPROVED_SAVESTATES
712 int i = 0;
713 u8 back_framebuffer[0x40000] = { 0 };
714 #endif
715
716 // Read registers
717 yread(&check, (void *)Vdp1Regs, sizeof(Vdp1), 1, fp);
718
719 // Read VDP1 ram
720 yread(&check, (void *)Vdp1Ram, 0x80000, 1, fp);
721
722 #ifdef IMPROVED_SAVESTATES
723 yread(&check, (void *)back_framebuffer, 0x40000, 1, fp);
724
725 for (i = 0; i < 0x40000; i++)
726 Vdp1FrameBufferWriteByte(i, back_framebuffer[i]);
727 #endif
728 return size;
729 }
730
731 //////////////////////////////////////////////////////////////////////////////
732
Vdp1DebugGetCommandNumberAddr(u32 number)733 static u32 Vdp1DebugGetCommandNumberAddr(u32 number)
734 {
735 u32 addr = 0;
736 u32 returnAddr = 0xFFFFFFFF;
737 u32 commandCounter = 0;
738 u16 command;
739
740 command = T1ReadWord(Vdp1Ram, addr);
741
742 while (!(command & 0x8000) && commandCounter != number)
743 {
744 // Make sure we're still dealing with a valid command
745 if ((command & 0x000C) == 0x000C)
746 // Invalid, abort
747 return 0xFFFFFFFF;
748
749 // Determine where to go next
750 switch ((command & 0x3000) >> 12)
751 {
752 case 0: // NEXT, jump to following table
753 addr += 0x20;
754 break;
755 case 1: // ASSIGN, jump to CMDLINK
756 addr = T1ReadWord(Vdp1Ram, addr + 2) * 8;
757 break;
758 case 2: // CALL, call a subroutine
759 if (returnAddr == 0xFFFFFFFF)
760 returnAddr = addr + 0x20;
761
762 addr = T1ReadWord(Vdp1Ram, addr + 2) * 8;
763 break;
764 case 3: // RETURN, return from subroutine
765 if (returnAddr != 0xFFFFFFFF) {
766 addr = returnAddr;
767 returnAddr = 0xFFFFFFFF;
768 }
769 else
770 addr += 0x20;
771 break;
772 }
773
774 if (addr > 0x7FFE0)
775 return 0xFFFFFFFF;
776 command = T1ReadWord(Vdp1Ram, addr);
777 commandCounter++;
778 }
779
780 if (commandCounter == number)
781 return addr;
782 else
783 return 0xFFFFFFFF;
784 }
785
786 //////////////////////////////////////////////////////////////////////////////
787
Vdp1DebugGetCommandNumberName(u32 number,char * outstring)788 void Vdp1DebugGetCommandNumberName(u32 number, char *outstring)
789 {
790 u32 addr;
791 u16 command;
792 char *command_name;
793
794 *outstring = '\0';
795
796 if ((addr = Vdp1DebugGetCommandNumberAddr(number)) != 0xFFFFFFFF)
797 {
798 command = T1ReadWord(Vdp1Ram, addr);
799
800 if (command & 0x8000) {
801 outstring = "Draw End";
802 return;
803 }
804
805 // Figure out command name
806 switch (command & 0x000F)
807 {
808 case 0:
809 command_name = "Normal Sprite";
810 break;
811 case 1:
812 command_name = "Scaled Sprite";
813 break;
814 case 2:
815 command_name = "Distorted Sprite";
816 break;
817 case 3:
818 command_name = "Distorted Sprite *";
819 break;
820 case 4:
821 command_name = "Polygon";
822 break;
823 case 5:
824 command_name = "Polyline";
825 break;
826 case 6:
827 command_name = "Line";
828 break;
829 case 7:
830 command_name = "Polyline *";
831 break;
832 case 8:
833 command_name = "User Clipping Coordinates";
834 break;
835 case 9:
836 command_name = "System Clipping Coordinates";
837 break;
838 case 10:
839 command_name = "Local Coordinates";
840 break;
841 case 11:
842 command_name = "User Clipping Coordinates *";
843 break;
844 default:
845 outstring = "Bad command";
846 return;
847 }
848
849 sprintf(outstring, "%03u %s", number, command_name);
850 }
851 }
852
853 //////////////////////////////////////////////////////////////////////////////
854
Vdp1DebugCommand(u32 number,char * outstring)855 void Vdp1DebugCommand(u32 number, char *outstring)
856 {
857 u16 command;
858 vdp1cmd_struct cmd;
859 u32 addr;
860
861 if ((addr = Vdp1DebugGetCommandNumberAddr(number)) == 0xFFFFFFFF)
862 return;
863
864 command = T1ReadWord(Vdp1Ram, addr);
865
866 if (command & 0x8000)
867 {
868 // Draw End
869 outstring[0] = 0x00;
870 return;
871 }
872
873 if (command & 0x4000)
874 {
875 AddString(outstring, "Command is skipped\r\n");
876 return;
877 }
878
879 Vdp1ReadCommand(&cmd, addr, Vdp1Ram);
880
881 switch (cmd.CMDCTRL & 0x000F)
882 {
883 case 0:
884 AddString(outstring, "Normal Sprite\r\n");
885 AddString(outstring, "x = %d, y = %d\r\n", cmd.CMDXA, cmd.CMDYA);
886 break;
887 case 1:
888 AddString(outstring, "Scaled Sprite\r\n");
889
890 AddString(outstring, "Zoom Point: ");
891
892 switch ((cmd.CMDCTRL >> 8) & 0xF)
893 {
894 case 0x0:
895 AddString(outstring, "Only two coordinates\r\n");
896 break;
897 case 0x5:
898 AddString(outstring, "Upper-left\r\n");
899 break;
900 case 0x6:
901 AddString(outstring, "Upper-center\r\n");
902 break;
903 case 0x7:
904 AddString(outstring, "Upper-right\r\n");
905 break;
906 case 0x9:
907 AddString(outstring, "Center-left\r\n");
908 break;
909 case 0xA:
910 AddString(outstring, "Center-center\r\n");
911 break;
912 case 0xB:
913 AddString(outstring, "Center-right\r\n");
914 break;
915 case 0xC:
916 AddString(outstring, "Lower-left\r\n");
917 break;
918 case 0xE:
919 AddString(outstring, "Lower-center\r\n");
920 break;
921 case 0xF:
922 AddString(outstring, "Lower-right\r\n");
923 break;
924 default: break;
925 }
926
927 if (((cmd.CMDCTRL >> 8) & 0xF) == 0)
928 {
929 AddString(outstring, "xa = %d, ya = %d, xc = %d, yc = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXC, cmd.CMDYC);
930 }
931 else
932 {
933 AddString(outstring, "xa = %d, ya = %d, xb = %d, yb = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
934 }
935
936 break;
937 case 2:
938 AddString(outstring, "Distorted Sprite\r\n");
939 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
940 AddString(outstring, "x3 = %d, y3 = %d, x4 = %d, y4 = %d\r\n", cmd.CMDXC, cmd.CMDYC, cmd.CMDXD, cmd.CMDYD);
941 break;
942 case 3:
943 AddString(outstring, "Distorted Sprite *\r\n");
944 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
945 AddString(outstring, "x3 = %d, y3 = %d, x4 = %d, y4 = %d\r\n", cmd.CMDXC, cmd.CMDYC, cmd.CMDXD, cmd.CMDYD);
946 break;
947 case 4:
948 AddString(outstring, "Polygon\r\n");
949 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
950 AddString(outstring, "x3 = %d, y3 = %d, x4 = %d, y4 = %d\r\n", cmd.CMDXC, cmd.CMDYC, cmd.CMDXD, cmd.CMDYD);
951 break;
952 case 5:
953 AddString(outstring, "Polyline\r\n");
954 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
955 AddString(outstring, "x3 = %d, y3 = %d, x4 = %d, y4 = %d\r\n", cmd.CMDXC, cmd.CMDYC, cmd.CMDXD, cmd.CMDYD);
956 break;
957 case 6:
958 AddString(outstring, "Line\r\n");
959 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
960 break;
961 case 7:
962 AddString(outstring, "Polyline *\r\n");
963 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXB, cmd.CMDYB);
964 AddString(outstring, "x3 = %d, y3 = %d, x4 = %d, y4 = %d\r\n", cmd.CMDXC, cmd.CMDYC, cmd.CMDXD, cmd.CMDYD);
965 break;
966 case 8:
967 AddString(outstring, "User Clipping\r\n");
968 AddString(outstring, "x1 = %d, y1 = %d, x2 = %d, y2 = %d\r\n", cmd.CMDXA, cmd.CMDYA, cmd.CMDXC, cmd.CMDYC);
969 break;
970 case 9:
971 AddString(outstring, "System Clipping\r\n");
972 AddString(outstring, "x1 = 0, y1 = 0, x2 = %d, y2 = %d\r\n", cmd.CMDXC, cmd.CMDYC);
973 break;
974 case 10:
975 AddString(outstring, "Local Coordinates\r\n");
976 AddString(outstring, "x = %d, y = %d\r\n", cmd.CMDXA, cmd.CMDYA);
977 break;
978 default:
979 AddString(outstring, "Invalid command\r\n");
980 return;
981 }
982
983 // Only Sprite commands use CMDSRCA, CMDSIZE
984 if (!(cmd.CMDCTRL & 0x000C))
985 {
986 AddString(outstring, "Texture address = %08X\r\n", ((unsigned int)cmd.CMDSRCA) << 3);
987 AddString(outstring, "Texture width = %d, height = %d\r\n", (cmd.CMDSIZE & 0x3F00) >> 5, cmd.CMDSIZE & 0xFF);
988 AddString(outstring, "Texture read direction: ");
989
990 switch ((cmd.CMDCTRL >> 4) & 0x3)
991 {
992 case 0:
993 AddString(outstring, "Normal\r\n");
994 break;
995 case 1:
996 AddString(outstring, "Reversed horizontal\r\n");
997 break;
998 case 2:
999 AddString(outstring, "Reversed vertical\r\n");
1000 break;
1001 case 3:
1002 AddString(outstring, "Reversed horizontal and vertical\r\n");
1003 break;
1004 default: break;
1005 }
1006 }
1007
1008 // Only draw commands use CMDPMOD
1009 if (!(cmd.CMDCTRL & 0x0008))
1010 {
1011 if (cmd.CMDPMOD & 0x8000)
1012 {
1013 AddString(outstring, "MSB set\r\n");
1014 }
1015
1016 if (cmd.CMDPMOD & 0x1000)
1017 {
1018 AddString(outstring, "High Speed Shrink Enabled\r\n");
1019 }
1020
1021 if (!(cmd.CMDPMOD & 0x0800))
1022 {
1023 AddString(outstring, "Pre-clipping Enabled\r\n");
1024 }
1025
1026 if (cmd.CMDPMOD & 0x0400)
1027 {
1028 AddString(outstring, "User Clipping Enabled\r\n");
1029 AddString(outstring, "Clipping Mode = %d\r\n", (cmd.CMDPMOD >> 9) & 0x1);
1030 }
1031
1032 if (cmd.CMDPMOD & 0x0100)
1033 {
1034 AddString(outstring, "Mesh Enabled\r\n");
1035 }
1036
1037 if (!(cmd.CMDPMOD & 0x0080))
1038 {
1039 AddString(outstring, "End Code Enabled\r\n");
1040 }
1041
1042 if (!(cmd.CMDPMOD & 0x0040))
1043 {
1044 AddString(outstring, "Transparent Pixel Enabled\r\n");
1045 }
1046
1047 AddString(outstring, "Color mode: ");
1048
1049 switch ((cmd.CMDPMOD >> 3) & 0x7)
1050 {
1051 case 0:
1052 AddString(outstring, "4 BPP(16 color bank)\r\n");
1053 AddString(outstring, "Color bank: %08X\r\n", (cmd.CMDCOLR << 3));
1054 break;
1055 case 1:
1056 AddString(outstring, "4 BPP(16 color LUT)\r\n");
1057 AddString(outstring, "Color lookup table: %08X\r\n", (cmd.CMDCOLR << 3));
1058 break;
1059 case 2:
1060 AddString(outstring, "8 BPP(64 color bank)\r\n");
1061 AddString(outstring, "Color bank: %08X\r\n", (cmd.CMDCOLR << 3));
1062 break;
1063 case 3:
1064 AddString(outstring, "8 BPP(128 color bank)\r\n");
1065 AddString(outstring, "Color bank: %08X\r\n", (cmd.CMDCOLR << 3));
1066 break;
1067 case 4:
1068 AddString(outstring, "8 BPP(256 color bank)\r\n");
1069 AddString(outstring, "Color bank: %08X\r\n", (cmd.CMDCOLR << 3));
1070 break;
1071 case 5:
1072 AddString(outstring, "15 BPP(RGB)\r\n");
1073
1074 // Only non-textured commands
1075 if (cmd.CMDCTRL & 0x0004)
1076 {
1077 AddString(outstring, "Non-textured color: %04X\r\n", cmd.CMDCOLR);
1078 }
1079 break;
1080 default: break;
1081 }
1082
1083 AddString(outstring, "Color Calc. mode: ");
1084
1085 switch (cmd.CMDPMOD & 0x7)
1086 {
1087 case 0:
1088 AddString(outstring, "Replace\r\n");
1089 break;
1090 case 1:
1091 AddString(outstring, "Cannot overwrite/Shadow\r\n");
1092 break;
1093 case 2:
1094 AddString(outstring, "Half-luminance\r\n");
1095 break;
1096 case 3:
1097 AddString(outstring, "Replace/Half-transparent\r\n");
1098 break;
1099 case 4:
1100 AddString(outstring, "Gouraud Shading\r\n");
1101 AddString(outstring, "Gouraud Shading Table = %08X\r\n", ((unsigned int)cmd.CMDGRDA) << 3);
1102 break;
1103 case 6:
1104 AddString(outstring, "Gouraud Shading + Half-luminance\r\n");
1105 AddString(outstring, "Gouraud Shading Table = %08X\r\n", ((unsigned int)cmd.CMDGRDA) << 3);
1106 break;
1107 case 7:
1108 AddString(outstring, "Gouraud Shading/Gouraud Shading + Half-transparent\r\n");
1109 AddString(outstring, "Gouraud Shading Table = %08X\r\n", ((unsigned int)cmd.CMDGRDA) << 3);
1110 break;
1111 default: break;
1112 }
1113 }
1114 }
1115
1116 //////////////////////////////////////////////////////////////////////////////
1117
1118 #if defined WORDS_BIGENDIAN
1119 #define SAT2YAB1(alpha,temp) (alpha | (temp & 0x7C00) << 1 | (temp & 0x3E0) << 14 | (temp & 0x1F) << 27)
1120 #else
1121 #define SAT2YAB1(alpha,temp) (alpha << 24 | (temp & 0x1F) << 3 | (temp & 0x3E0) << 6 | (temp & 0x7C00) << 9)
1122 #endif
1123
1124 #if defined WORDS_BIGENDIAN
1125 #define SAT2YAB2(alpha,dot1,dot2) (((dot2 & 0xFF) << 24) | ((dot2 & 0xFF00) << 8) | ((dot1 & 0xFF) << 8) | alpha)
1126 #else
1127 #define SAT2YAB2(alpha,dot1,dot2) (alpha << 24 | ((dot1 & 0xFF) << 16) | (dot2 & 0xFF00) | (dot2 & 0xFF))
1128 #endif
1129
ColorRamGetColor(u32 colorindex)1130 static u32 ColorRamGetColor(u32 colorindex)
1131 {
1132 switch(Vdp2Internal.ColorMode)
1133 {
1134 case 0:
1135 case 1:
1136 {
1137 u32 tmp;
1138 colorindex <<= 1;
1139 tmp = T2ReadWord(Vdp2ColorRam, colorindex & 0xFFF);
1140 return SAT2YAB1(0xFF, tmp);
1141 }
1142 case 2:
1143 {
1144 u32 tmp1, tmp2;
1145 colorindex <<= 2;
1146 colorindex &= 0xFFF;
1147 tmp1 = T2ReadWord(Vdp2ColorRam, colorindex);
1148 tmp2 = T2ReadWord(Vdp2ColorRam, colorindex+2);
1149 return SAT2YAB2(0xFF, tmp1, tmp2);
1150 }
1151 default: break;
1152 }
1153
1154 return 0;
1155 }
1156
1157 //////////////////////////////////////////////////////////////////////////////
1158
CheckEndcode(int dot,int endcode,int * code)1159 static INLINE int CheckEndcode(int dot, int endcode, int *code)
1160 {
1161 if (dot == endcode)
1162 {
1163 code[0]++;
1164 if (code[0] == 2)
1165 {
1166 code[0] = 0;
1167 return 2;
1168 }
1169 return 1;
1170 }
1171
1172 return 0;
1173 }
1174
1175 //////////////////////////////////////////////////////////////////////////////
1176
DoEndcode(int count,u32 * charAddr,u32 ** textdata,int width,int xoff,int oddpixel,int pixelsize)1177 static INLINE int DoEndcode(int count, u32 *charAddr, u32 **textdata, int width, int xoff, int oddpixel, int pixelsize)
1178 {
1179 if (count > 1)
1180 {
1181 float divisor = (float)(8 / pixelsize);
1182
1183 if(divisor != 0)
1184 charAddr[0] += (int)((float)(width - xoff + oddpixel) / divisor);
1185 memset(textdata[0], 0, sizeof(u32) * (width - xoff));
1186 textdata[0] += (width - xoff);
1187 return 1;
1188 }
1189 else
1190 *textdata[0]++ = 0;
1191
1192 return 0;
1193 }
1194
1195 //////////////////////////////////////////////////////////////////////////////
1196
Vdp1DebugTexture(u32 number,int * w,int * h)1197 u32 *Vdp1DebugTexture(u32 number, int *w, int *h)
1198 {
1199 u16 command;
1200 vdp1cmd_struct cmd;
1201 u32 addr;
1202 u32 *texture;
1203 u32 charAddr;
1204 u32 dot;
1205 u8 SPD;
1206 u32 alpha;
1207 u32 *textdata;
1208 int isendcode=0;
1209 int code=0;
1210 int ret;
1211
1212 if ((addr = Vdp1DebugGetCommandNumberAddr(number)) == 0xFFFFFFFF)
1213 return NULL;
1214
1215 command = T1ReadWord(Vdp1Ram, addr);
1216
1217 if (command & 0x8000)
1218 // Draw End
1219 return NULL;
1220
1221 if (command & 0x4000)
1222 // Command Skipped
1223 return NULL;
1224
1225 Vdp1ReadCommand(&cmd, addr, Vdp1Ram);
1226
1227 switch (cmd.CMDCTRL & 0x000F)
1228 {
1229 case 0: // Normal Sprite
1230 case 1: // Scaled Sprite
1231 case 2: // Distorted Sprite
1232 case 3: // Distorted Sprite *
1233 w[0] = (cmd.CMDSIZE & 0x3F00) >> 5;
1234 h[0] = cmd.CMDSIZE & 0xFF;
1235
1236 if ((texture = (u32 *)malloc(sizeof(u32) * w[0] * h[0])) == NULL)
1237 return NULL;
1238
1239 if (!(cmd.CMDPMOD & 0x80))
1240 {
1241 isendcode = 1;
1242 code = 0;
1243 }
1244 else
1245 isendcode = 0;
1246 break;
1247 case 4: // Polygon
1248 case 5: // Polyline
1249 case 6: // Line
1250 case 7: // Polyline *
1251 // Do 1x1 pixel
1252 w[0] = 1;
1253 h[0] = 1;
1254 if ((texture = (u32 *)malloc(sizeof(u32))) == NULL)
1255 return NULL;
1256
1257 if (cmd.CMDCOLR & 0x8000)
1258 texture[0] = SAT2YAB1(0xFF, cmd.CMDCOLR);
1259 else
1260 texture[0] = ColorRamGetColor(cmd.CMDCOLR);
1261
1262 return texture;
1263 case 8: // User Clipping
1264 case 9: // System Clipping
1265 case 10: // Local Coordinates
1266 case 11: // User Clipping *
1267 return NULL;
1268 default: // Invalid command
1269 return NULL;
1270 }
1271
1272 charAddr = cmd.CMDSRCA * 8;
1273 SPD = ((cmd.CMDPMOD & 0x40) != 0);
1274 alpha = 0xFF;
1275 textdata = texture;
1276
1277 switch((cmd.CMDPMOD >> 3) & 0x7)
1278 {
1279 case 0:
1280 {
1281 // 4 bpp Bank mode
1282 u32 colorBank = cmd.CMDCOLR;
1283 u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
1284 u16 i;
1285
1286 for(i = 0;i < h[0];i++)
1287 {
1288 u16 j;
1289 j = 0;
1290 while(j < w[0])
1291 {
1292 dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
1293
1294 // Pixel 1
1295 if (isendcode && (ret = CheckEndcode(dot >> 4, 0xF, &code)) > 0)
1296 {
1297 if (DoEndcode(ret, &charAddr, &textdata, w[0], j, 0, 4))
1298 break;
1299 }
1300 else
1301 {
1302 if (((dot >> 4) == 0) && !SPD) *textdata++ = 0;
1303 else *textdata++ = ColorRamGetColor(((dot >> 4) | colorBank) + colorOffset);
1304 }
1305
1306 j += 1;
1307
1308 // Pixel 2
1309 if (isendcode && (ret = CheckEndcode(dot & 0xF, 0xF, &code)) > 0)
1310 {
1311 if (DoEndcode(ret, &charAddr, &textdata, w[0], j, 1, 4))
1312 break;
1313 }
1314 else
1315 {
1316 if (((dot & 0xF) == 0) && !SPD) *textdata++ = 0;
1317 else *textdata++ = ColorRamGetColor(((dot & 0xF) | colorBank) + colorOffset);
1318 }
1319
1320 j += 1;
1321 charAddr += 1;
1322 }
1323 }
1324 break;
1325 }
1326 case 1:
1327 {
1328 // 4 bpp LUT mode
1329 u32 temp;
1330 u32 colorLut = cmd.CMDCOLR * 8;
1331 u16 i;
1332
1333 for(i = 0;i < h[0];i++)
1334 {
1335 u16 j;
1336 j = 0;
1337 while(j < w[0])
1338 {
1339 dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
1340
1341 if (isendcode && (ret = CheckEndcode(dot >> 4, 0xF, &code)) > 0)
1342 {
1343 if (DoEndcode(ret, &charAddr, &textdata, w[0], j, 0, 4))
1344 break;
1345 }
1346 else
1347 {
1348 if (((dot >> 4) == 0) && !SPD)
1349 *textdata++ = 0;
1350 else
1351 {
1352 temp = T1ReadWord(Vdp1Ram, ((dot >> 4) * 2 + colorLut) & 0x7FFFF);
1353 if (temp & 0x8000)
1354 *textdata++ = SAT2YAB1(0xFF, temp);
1355 else
1356 *textdata++ = ColorRamGetColor(temp);
1357 }
1358 }
1359
1360 j += 1;
1361
1362 if (isendcode && (ret = CheckEndcode(dot & 0xF, 0xF, &code)) > 0)
1363 {
1364 if (DoEndcode(ret, &charAddr, &textdata, w[0], j, 1, 4))
1365 break;
1366 }
1367 else
1368 {
1369 if (((dot & 0xF) == 0) && !SPD)
1370 *textdata++ = 0;
1371 else
1372 {
1373 temp = T1ReadWord(Vdp1Ram, ((dot & 0xF) * 2 + colorLut) & 0x7FFFF);
1374 if (temp & 0x8000)
1375 *textdata++ = SAT2YAB1(0xFF, temp);
1376 else
1377 *textdata++ = ColorRamGetColor(temp);
1378 }
1379 }
1380
1381 j += 1;
1382
1383 charAddr += 1;
1384 }
1385 }
1386 break;
1387 }
1388 case 2:
1389 {
1390 // 8 bpp(64 color) Bank mode
1391 u32 colorBank = cmd.CMDCOLR;
1392 u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
1393
1394 u16 i, j;
1395
1396 for(i = 0;i < h[0];i++)
1397 {
1398 for(j = 0;j < w[0];j++)
1399 {
1400 dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF) & 0x3F;
1401 charAddr++;
1402
1403 if ((dot == 0) && !SPD) *textdata++ = 0;
1404 else *textdata++ = ColorRamGetColor((dot | colorBank) + colorOffset);
1405 }
1406 }
1407 break;
1408 }
1409 case 3:
1410 {
1411 // 8 bpp(128 color) Bank mode
1412 u32 colorBank = cmd.CMDCOLR;
1413 u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
1414 u16 i, j;
1415
1416 for(i = 0;i < h[0];i++)
1417 {
1418 for(j = 0;j < w[0];j++)
1419 {
1420 dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF) & 0x7F;
1421 charAddr++;
1422
1423 if ((dot == 0) && !SPD) *textdata++ = 0;
1424 else *textdata++ = ColorRamGetColor((dot | colorBank) + colorOffset);
1425 }
1426 }
1427 break;
1428 }
1429 case 4:
1430 {
1431 // 8 bpp(256 color) Bank mode
1432 u32 colorBank = cmd.CMDCOLR;
1433 u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
1434 u16 i, j;
1435
1436 for(i = 0;i < h[0];i++)
1437 {
1438 for(j = 0;j < w[0];j++)
1439 {
1440 dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
1441 charAddr++;
1442
1443 if ((dot == 0) && !SPD) *textdata++ = 0;
1444 else *textdata++ = ColorRamGetColor((dot | colorBank) + colorOffset);
1445 }
1446 }
1447 break;
1448 }
1449 case 5:
1450 {
1451 // 16 bpp Bank mode
1452 u16 i, j;
1453
1454 for(i = 0;i < h[0];i++)
1455 {
1456 for(j = 0;j < w[0];j++)
1457 {
1458 dot = T1ReadWord(Vdp1Ram, charAddr & 0x7FFFF);
1459
1460 if (isendcode && (ret = CheckEndcode(dot, 0x7FFF, &code)) > 0)
1461 {
1462 if (DoEndcode(ret, &charAddr, &textdata, w[0], j, 0, 16))
1463 break;
1464 }
1465 else
1466 {
1467 //if (!(dot & 0x8000) && (Vdp2Regs->SPCTL & 0x20)) printf("mixed mode\n");
1468 if (!(dot & 0x8000) && !SPD) *textdata++ = 0;
1469 else *textdata++ = SAT2YAB1(0xFF, dot);
1470 }
1471
1472 charAddr += 2;
1473 }
1474 }
1475 break;
1476 }
1477 default:
1478 break;
1479 }
1480
1481 return texture;
1482 }
1483
1484 //////////////////////////////////////////////////////////////////////////////
1485
ToggleVDP1(void)1486 void ToggleVDP1(void)
1487 {
1488 Vdp1External.disptoggle ^= 1;
1489 }
1490
1491 //////////////////////////////////////////////////////////////////////////////
1492 // Dummy Video Interface
1493 //////////////////////////////////////////////////////////////////////////////
1494 int VIDDummyInit(void);
1495 void VIDDummyDeInit(void);
1496 void VIDDummyResize(unsigned int, unsigned int, int);
1497 int VIDDummyIsFullscreen(void);
1498 int VIDDummyVdp1Reset(void);
1499 void VIDDummyVdp1DrawStart(void);
1500 void VIDDummyVdp1DrawEnd(void);
1501 void VIDDummyVdp1NormalSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1502 void VIDDummyVdp1ScaledSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1503 void VIDDummyVdp1DistortedSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1504 void VIDDummyVdp1PolygonDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1505 void VIDDummyVdp1PolylineDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1506 void VIDDummyVdp1LineDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer);
1507 void VIDDummyVdp1UserClipping(u8 * ram, Vdp1 * regs);
1508 void VIDDummyVdp1SystemClipping(u8 * ram, Vdp1 * regs);
1509 void VIDDummyVdp1LocalCoordinate(u8 * ram, Vdp1 * regs);
1510 int VIDDummyVdp2Reset(void);
1511 void VIDDummyVdp2DrawStart(void);
1512 void VIDDummyVdp2DrawEnd(void);
1513 void VIDDummyVdp2DrawScreens(void);
1514 void VIDDummyGetGlSize(int *width, int *height);
1515 void VIDDummVdp1ReadFrameBuffer(u32 type, u32 addr, void * out);
1516 void VIDDummVdp1WriteFrameBuffer(u32 type, u32 addr, u32 val);
1517 void VIDDummyGetNativeResolution(int *width, int * height, int *interlace);
1518 void VIDDummyVdp2DispOff(void);
1519
1520 VideoInterface_struct VIDDummy = {
1521 VIDCORE_DUMMY,
1522 "Dummy Video Interface",
1523 VIDDummyInit,
1524 VIDDummyDeInit,
1525 VIDDummyResize,
1526 VIDDummyIsFullscreen,
1527 VIDDummyVdp1Reset,
1528 VIDDummyVdp1DrawStart,
1529 VIDDummyVdp1DrawEnd,
1530 VIDDummyVdp1NormalSpriteDraw,
1531 VIDDummyVdp1ScaledSpriteDraw,
1532 VIDDummyVdp1DistortedSpriteDraw,
1533 VIDDummyVdp1PolygonDraw,
1534 VIDDummyVdp1PolylineDraw,
1535 VIDDummyVdp1LineDraw,
1536 VIDDummyVdp1UserClipping,
1537 VIDDummyVdp1SystemClipping,
1538 VIDDummyVdp1LocalCoordinate,
1539 VIDDummVdp1ReadFrameBuffer,
1540 VIDDummVdp1WriteFrameBuffer,
1541 VIDDummyVdp2Reset,
1542 VIDDummyVdp2DrawStart,
1543 VIDDummyVdp2DrawEnd,
1544 VIDDummyVdp2DrawScreens,
1545 VIDDummyGetGlSize,
1546 VIDDummyGetNativeResolution,
1547 VIDDummyVdp2DispOff,
1548 };
1549
1550 //////////////////////////////////////////////////////////////////////////////
1551
VIDDummyInit(void)1552 int VIDDummyInit(void)
1553 {
1554 return 0;
1555 }
1556
1557 //////////////////////////////////////////////////////////////////////////////
1558
VIDDummyDeInit(void)1559 void VIDDummyDeInit(void)
1560 {
1561 }
1562
1563 //////////////////////////////////////////////////////////////////////////////
1564
VIDDummyResize(UNUSED unsigned int i,UNUSED unsigned int j,UNUSED int on)1565 void VIDDummyResize(UNUSED unsigned int i, UNUSED unsigned int j, UNUSED int on)
1566 {
1567 }
1568
1569 //////////////////////////////////////////////////////////////////////////////
1570
VIDDummyIsFullscreen(void)1571 int VIDDummyIsFullscreen(void)
1572 {
1573 return 0;
1574 }
1575
1576 //////////////////////////////////////////////////////////////////////////////
1577
VIDDummyVdp1Reset(void)1578 int VIDDummyVdp1Reset(void)
1579 {
1580 return 0;
1581 }
1582
1583 //////////////////////////////////////////////////////////////////////////////
1584
VIDDummyVdp1DrawStart(void)1585 void VIDDummyVdp1DrawStart(void)
1586 {
1587 }
1588
1589 //////////////////////////////////////////////////////////////////////////////
1590
VIDDummyVdp1DrawEnd(void)1591 void VIDDummyVdp1DrawEnd(void)
1592 {
1593 }
1594
1595 //////////////////////////////////////////////////////////////////////////////
1596
VIDDummyVdp1NormalSpriteDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1597 void VIDDummyVdp1NormalSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1598 {
1599 }
1600
1601 //////////////////////////////////////////////////////////////////////////////
1602
VIDDummyVdp1ScaledSpriteDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1603 void VIDDummyVdp1ScaledSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1604 {
1605 }
1606
1607 //////////////////////////////////////////////////////////////////////////////
1608
VIDDummyVdp1DistortedSpriteDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1609 void VIDDummyVdp1DistortedSpriteDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1610 {
1611 }
1612
1613 //////////////////////////////////////////////////////////////////////////////
1614
VIDDummyVdp1PolygonDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1615 void VIDDummyVdp1PolygonDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1616 {
1617 }
1618
1619 //////////////////////////////////////////////////////////////////////////////
1620
VIDDummyVdp1PolylineDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1621 void VIDDummyVdp1PolylineDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1622 {
1623 }
1624
1625 //////////////////////////////////////////////////////////////////////////////
1626
VIDDummyVdp1LineDraw(u8 * ram,Vdp1 * regs,u8 * back_framebuffer)1627 void VIDDummyVdp1LineDraw(u8 * ram, Vdp1 * regs, u8* back_framebuffer)
1628 {
1629 }
1630
1631 //////////////////////////////////////////////////////////////////////////////
1632
VIDDummyVdp1UserClipping(u8 * ram,Vdp1 * regs)1633 void VIDDummyVdp1UserClipping(u8 * ram, Vdp1 * regs)
1634 {
1635 }
1636
1637 //////////////////////////////////////////////////////////////////////////////
1638
VIDDummyVdp1SystemClipping(u8 * ram,Vdp1 * regs)1639 void VIDDummyVdp1SystemClipping(u8 * ram, Vdp1 * regs)
1640 {
1641 }
1642
1643 //////////////////////////////////////////////////////////////////////////////
1644
VIDDummyVdp1LocalCoordinate(u8 * ram,Vdp1 * regs)1645 void VIDDummyVdp1LocalCoordinate(u8 * ram, Vdp1 * regs)
1646 {
1647 }
1648
1649 //////////////////////////////////////////////////////////////////////////////
1650
VIDDummyVdp2Reset(void)1651 int VIDDummyVdp2Reset(void)
1652 {
1653 return 0;
1654 }
1655
1656 //////////////////////////////////////////////////////////////////////////////
1657
VIDDummyVdp2DrawStart(void)1658 void VIDDummyVdp2DrawStart(void)
1659 {
1660 }
1661
1662 //////////////////////////////////////////////////////////////////////////////
1663
VIDDummyVdp2DrawEnd(void)1664 void VIDDummyVdp2DrawEnd(void)
1665 {
1666 }
1667
1668 //////////////////////////////////////////////////////////////////////////////
1669
VIDDummyVdp2DrawScreens(void)1670 void VIDDummyVdp2DrawScreens(void)
1671 {
1672 }
1673
1674 //////////////////////////////////////////////////////////////////////////////
1675
VIDDummyGetGlSize(int * width,int * height)1676 void VIDDummyGetGlSize(int *width, int *height)
1677 {
1678 *width = 0;
1679 *height = 0;
1680 }
1681
1682 //////////////////////////////////////////////////////////////////////////////
1683
VIDDummVdp1ReadFrameBuffer(u32 type,u32 addr,void * out)1684 void VIDDummVdp1ReadFrameBuffer(u32 type, u32 addr, void * out)
1685 {
1686 }
1687
1688 //////////////////////////////////////////////////////////////////////////////
1689
VIDDummVdp1WriteFrameBuffer(u32 type,u32 addr,u32 val)1690 void VIDDummVdp1WriteFrameBuffer(u32 type, u32 addr, u32 val)
1691 {
1692 }
1693
1694 //////////////////////////////////////////////////////////////////////////////
1695
VIDDummyGetNativeResolution(int * width,int * height,int * interlace)1696 void VIDDummyGetNativeResolution(int *width, int * height, int * interlace)
1697 {
1698 *width = 0;
1699 *height = 0;
1700 *interlace = 0;
1701 }
1702
1703 //////////////////////////////////////////////////////////////////////////////
1704
VIDDummyVdp2DispOff(void)1705 void VIDDummyVdp2DispOff(void)
1706 {
1707 }
1708
1709 //////////////////////////////////////////////////////////////////////////////
1710
VideoDisableGL(void)1711 void VideoDisableGL(void)
1712 {
1713 VideoUseGL = 0;
1714 }
1715