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