2 // This file is part of the PicoDrive Megadrive Emulator
\r
4 // Copyright (c) 2011 FinalDave (emudave (at) gmail.com)
\r
6 // This code is licensed under the GNU General Public License version 2.0 and the MAME License.
\r
7 // You can choose the license that has the most advantages for you.
\r
9 // SVN repository can be found at http://code.google.com/p/cyclone68000/
\r
11 #include "PicoInt.h"
\r
13 static inline void AutoIncrement()
\r
15 Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]);
\r
18 static void VideoWrite(unsigned int d)
\r
21 unsigned short sd=(unsigned short)d;
\r
24 if (a&1) d=((d<<8)&0xff00)|(d>>8); // If address is odd, bytes are swapped
\r
27 switch (Pico.video.type)
\r
29 case 1: Pico.vram [a&0x7fff]=sd; break;
\r
30 case 3: Pico.cram [a&0x003f]=sd; Pico.m.dirtyPal=1; break;
\r
31 case 5: Pico.vsram[a&0x003f]=sd; break;
\r
37 static unsigned int VideoRead()
\r
39 unsigned int a=0,d=0;
\r
41 a=Pico.video.addr; a>>=1;
\r
43 switch (Pico.video.type)
\r
45 case 0: d=Pico.vram [a&0x7fff]; break;
\r
46 case 8: d=Pico.cram [a&0x003f]; break;
\r
47 case 4: d=Pico.vsram[a&0x003f]; break;
\r
54 static int GetDmaSource()
\r
56 struct PicoVideo *pvid=&Pico.video;
\r
58 source =pvid->reg[0x15]<<1;
\r
59 source|=pvid->reg[0x16]<<9;
\r
60 source|=pvid->reg[0x17]<<17;
\r
64 static int GetDmaLength()
\r
66 struct PicoVideo *pvid=&Pico.video;
\r
68 // 16-bit words to transfer:
\r
69 len =pvid->reg[0x13];
\r
70 len|=pvid->reg[0x14]<<8;
\r
74 static void DmaSlow(int source,int len)
\r
78 if (source>=0x800000 && source<0xe00000) return; // Invalid source address
\r
80 /// Clip Cram DMA size (Todds Adventures in Slime World):
\r
81 if (Pico.video.type==3) { max=0x80-Pico.video.addr; if (len>max) len=max; }
\r
85 VideoWrite(PicoRead16(source));
\r
90 static void DmaCopy(int source,int len)
\r
94 len>>=1; // Length specifies number of bytes
\r
98 VideoWrite(Pico.vram[source&0x7fff]);
\r
103 static void DmaFill(int data)
\r
107 len=GetDmaLength();
\r
109 for (i=0;i<len+1;i++) VideoWrite(data);
\r
112 static void CommandDma()
\r
114 struct PicoVideo *pvid=&Pico.video;
\r
115 int len=0,method=0,source=0;
\r
117 if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled
\r
119 len=GetDmaLength();
\r
121 method=pvid->reg[0x17]>>6;
\r
122 source=GetDmaSource();
\r
123 if (method< 2) DmaSlow(source,len); // 68000 to VDP
\r
124 if (method==3) DmaCopy(source,len); // VRAM Copy
\r
127 static void CommandChange()
\r
129 struct PicoVideo *pvid=&Pico.video;
\r
130 unsigned int cmd=0,addr=0;
\r
134 // Get type of transfer 0xc0000030 (v/c/vsram read/write)
\r
135 pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30));
\r
137 // Get address 0x3fff0003
\r
138 addr =(cmd>>16)&0x3fff;
\r
139 addr|=(cmd<<14)&0xc000;
\r
140 pvid->addr=(unsigned short)addr;
\r
143 if (cmd&0x80) CommandDma();
\r
146 void PicoVideoWrite(unsigned int a,unsigned int d)
\r
148 struct PicoVideo *pvid=&Pico.video;
\r
151 d=(unsigned short)d;
\r
153 if (a==0x00) // Data port 0 or 2
\r
155 if (pvid->pending) CommandChange();
\r
158 // If a DMA fill has been set up, do it
\r
159 if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2)
\r
170 if (a==0x04) // Command port 4 or 6
\r
174 // Low word of command:
\r
175 pvid->command&=0xffff0000;
\r
182 if ((d&0xc000)==0x8000)
\r
185 int num=(d>>8)&0x1f;
\r
186 pvid->reg[num]=(unsigned char)d;
\r
190 // High word of command:
\r
191 pvid->command&=0x0000ffff;
\r
192 pvid->command|=d<<16;
\r
197 unsigned int PicoVideoRead(unsigned int a)
\r
203 if (a==0x00) { d=VideoRead(); goto end; }
\r
207 d=Pico.video.status;
\r
209 // Toggle fifo full empty:
\r
210 if (Pico.m.rotate&4) d|=0x3520; else d|=0x3620;
\r
211 if (Pico.m.rotate&2) d|=0x0004; // Toggle in/out of H-Blank
\r
214 if (Pico.m.pal) d|=1; // PAL screen
\r
219 if ((a&0x1c)==0x08)
\r
221 if (Pico.m.scanline>-64) d=Pico.m.scanline; // HV-Counter
\r
222 else d=Pico.m.rotate++; // Fudge
\r