2 // This file is part of the PicoDrive Megadrive Emulator
\r
4 // This code is licensed under the GNU General Public License version 2.0 and the MAME License.
\r
5 // You can choose the license that has the most advantages for you.
\r
7 // SVN repository can be found at http://code.google.com/p/cyclone68000/
\r
11 static inline void AutoIncrement()
\r
13 Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]);
\r
16 static void VideoWrite(unsigned int d)
\r
19 unsigned short sd=(unsigned short)d;
\r
22 if (a&1) d=((d<<8)&0xff00)|(d>>8); // If address is odd, bytes are swapped
\r
25 switch (Pico.video.type)
\r
27 case 1: Pico.vram [a&0x7fff]=sd; break;
\r
28 case 3: Pico.cram [a&0x003f]=sd; Pico.m.dirtyPal=1; break;
\r
29 case 5: Pico.vsram[a&0x003f]=sd; break;
\r
35 static unsigned int VideoRead()
\r
37 unsigned int a=0,d=0;
\r
39 a=Pico.video.addr; a>>=1;
\r
41 switch (Pico.video.type)
\r
43 case 0: d=Pico.vram [a&0x7fff]; break;
\r
44 case 8: d=Pico.cram [a&0x003f]; break;
\r
45 case 4: d=Pico.vsram[a&0x003f]; break;
\r
52 static int GetDmaSource()
\r
54 struct PicoVideo *pvid=&Pico.video;
\r
56 source =pvid->reg[0x15]<<1;
\r
57 source|=pvid->reg[0x16]<<9;
\r
58 source|=pvid->reg[0x17]<<17;
\r
62 static int GetDmaLength()
\r
64 struct PicoVideo *pvid=&Pico.video;
\r
66 // 16-bit words to transfer:
\r
67 len =pvid->reg[0x13];
\r
68 len|=pvid->reg[0x14]<<8;
\r
72 static void DmaSlow(int source,int len)
\r
76 if (source>=0x800000 && source<0xe00000) return; // Invalid source address
\r
78 /// Clip Cram DMA size (Todds Adventures in Slime World):
\r
79 if (Pico.video.type==3) { max=0x80-Pico.video.addr; if (len>max) len=max; }
\r
83 VideoWrite(PicoRead16(source));
\r
88 static void DmaCopy(int source,int len)
\r
92 len>>=1; // Length specifies number of bytes
\r
96 VideoWrite(Pico.vram[source&0x7fff]);
\r
101 static void DmaFill(int data)
\r
105 len=GetDmaLength();
\r
107 for (i=0;i<len+1;i++) VideoWrite(data);
\r
110 static void CommandDma()
\r
112 struct PicoVideo *pvid=&Pico.video;
\r
113 int len=0,method=0,source=0;
\r
115 if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled
\r
117 len=GetDmaLength();
\r
119 method=pvid->reg[0x17]>>6;
\r
120 source=GetDmaSource();
\r
121 if (method< 2) DmaSlow(source,len); // 68000 to VDP
\r
122 if (method==3) DmaCopy(source,len); // VRAM Copy
\r
125 static void CommandChange()
\r
127 struct PicoVideo *pvid=&Pico.video;
\r
128 unsigned int cmd=0,addr=0;
\r
132 // Get type of transfer 0xc0000030 (v/c/vsram read/write)
\r
133 pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30));
\r
135 // Get address 0x3fff0003
\r
136 addr =(cmd>>16)&0x3fff;
\r
137 addr|=(cmd<<14)&0xc000;
\r
138 pvid->addr=(unsigned short)addr;
\r
141 if (cmd&0x80) CommandDma();
\r
144 void PicoVideoWrite(unsigned int a,unsigned int d)
\r
146 struct PicoVideo *pvid=&Pico.video;
\r
149 d=(unsigned short)d;
\r
151 if (a==0x00) // Data port 0 or 2
\r
153 if (pvid->pending) CommandChange();
\r
156 // If a DMA fill has been set up, do it
\r
157 if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2)
\r
168 if (a==0x04) // Command port 4 or 6
\r
172 // Low word of command:
\r
173 pvid->command&=0xffff0000;
\r
180 if ((d&0xc000)==0x8000)
\r
183 int num=(d>>8)&0x1f;
\r
184 pvid->reg[num]=(unsigned char)d;
\r
188 // High word of command:
\r
189 pvid->command&=0x0000ffff;
\r
190 pvid->command|=d<<16;
\r
195 unsigned int PicoVideoRead(unsigned int a)
\r
201 if (a==0x00) { d=VideoRead(); goto end; }
\r
205 d=Pico.video.status;
\r
207 // Toggle fifo full empty:
\r
208 if (Pico.m.rotate&4) d|=0x3520; else d|=0x3620;
\r
209 if (Pico.m.rotate&2) d|=0x0004; // Toggle in/out of H-Blank
\r
212 if (Pico.m.pal) d|=1; // PAL screen
\r
217 if ((a&0x1c)==0x08)
\r
219 if (Pico.m.scanline>-64) d=Pico.m.scanline; // HV-Counter
\r
220 else d=Pico.m.rotate++; // Fudge
\r