license info added to Pico directory
[cyclone68000.git] / Pico / VideoPort.cpp
CommitLineData
15eb0001 1\r
4abeeb4b 2// This file is part of the PicoDrive Megadrive Emulator\r
3\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
6\r
7// SVN repository can be found at http://code.google.com/p/cyclone68000/\r
8\r
15eb0001 9#include "PicoInt.h"\r
10\r
11static inline void AutoIncrement()\r
12{\r
13 Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]);\r
14}\r
15\r
16static void VideoWrite(unsigned int d)\r
17{\r
18 unsigned int a=0;\r
19 unsigned short sd=(unsigned short)d;\r
20\r
21 a=Pico.video.addr;\r
22 if (a&1) d=((d<<8)&0xff00)|(d>>8); // If address is odd, bytes are swapped\r
23 a>>=1;\r
24\r
25 switch (Pico.video.type)\r
26 {\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
30 }\r
31 \r
32 AutoIncrement();\r
33}\r
34\r
35static unsigned int VideoRead()\r
36{\r
37 unsigned int a=0,d=0;\r
38\r
39 a=Pico.video.addr; a>>=1;\r
40\r
41 switch (Pico.video.type)\r
42 {\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
46 }\r
47 \r
48 AutoIncrement();\r
49 return d;\r
50}\r
51\r
52static int GetDmaSource()\r
53{\r
54 struct PicoVideo *pvid=&Pico.video;\r
55 int source=0;\r
56 source =pvid->reg[0x15]<<1;\r
57 source|=pvid->reg[0x16]<<9;\r
58 source|=pvid->reg[0x17]<<17;\r
59 return source;\r
60}\r
61\r
62static int GetDmaLength()\r
63{\r
64 struct PicoVideo *pvid=&Pico.video;\r
65 int len=0;\r
66 // 16-bit words to transfer:\r
67 len =pvid->reg[0x13];\r
68 len|=pvid->reg[0x14]<<8;\r
69 return len;\r
70}\r
71\r
72static void DmaSlow(int source,int len)\r
73{\r
74 int i=0,max=0;\r
75\r
76 if (source>=0x800000 && source<0xe00000) return; // Invalid source address\r
77\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
80\r
81 for (i=0;i<len;i++)\r
82 {\r
83 VideoWrite(PicoRead16(source));\r
84 source+=2;\r
85 }\r
86}\r
87\r
88static void DmaCopy(int source,int len)\r
89{\r
90 int i=0;\r
91\r
92 len>>=1; // Length specifies number of bytes\r
93\r
94 for (i=0;i<len;i++)\r
95 {\r
96 VideoWrite(Pico.vram[source&0x7fff]);\r
97 source+=2;\r
98 }\r
99}\r
100\r
101static void DmaFill(int data)\r
102{\r
103 int len=0,i=0;\r
104 \r
105 len=GetDmaLength();\r
106\r
107 for (i=0;i<len+1;i++) VideoWrite(data);\r
108}\r
109\r
110static void CommandDma()\r
111{\r
112 struct PicoVideo *pvid=&Pico.video;\r
113 int len=0,method=0,source=0;\r
114\r
115 if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled\r
116\r
117 len=GetDmaLength();\r
118\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
123}\r
124\r
125static void CommandChange()\r
126{\r
127 struct PicoVideo *pvid=&Pico.video;\r
128 unsigned int cmd=0,addr=0;\r
129\r
130 cmd=pvid->command;\r
131\r
132 // Get type of transfer 0xc0000030 (v/c/vsram read/write)\r
133 pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30));\r
134\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
139\r
140 // Check for dma:\r
141 if (cmd&0x80) CommandDma();\r
142}\r
143\r
144void PicoVideoWrite(unsigned int a,unsigned int d)\r
145{\r
146 struct PicoVideo *pvid=&Pico.video;\r
147\r
148 a&=0x1c;\r
149 d=(unsigned short)d;\r
150\r
151 if (a==0x00) // Data port 0 or 2\r
152 { \r
153 if (pvid->pending) CommandChange();\r
154 pvid->pending=0;\r
155\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
158 {\r
159 DmaFill(d);\r
160 }\r
161 else\r
162 {\r
163 VideoWrite(d);\r
164 }\r
165 return;\r
166 }\r
167\r
168 if (a==0x04) // Command port 4 or 6\r
169 {\r
170 if (pvid->pending)\r
171 {\r
172 // Low word of command:\r
173 pvid->command&=0xffff0000;\r
174 pvid->command|=d;\r
175 pvid->pending=0;\r
176 CommandChange();\r
177 return;\r
178 }\r
179\r
180 if ((d&0xc000)==0x8000)\r
181 {\r
182 // Register write:\r
183 int num=(d>>8)&0x1f;\r
184 pvid->reg[num]=(unsigned char)d;\r
185 return;\r
186 }\r
187\r
188 // High word of command:\r
189 pvid->command&=0x0000ffff;\r
190 pvid->command|=d<<16;\r
191 pvid->pending=1;\r
192 }\r
193}\r
194\r
195unsigned int PicoVideoRead(unsigned int a)\r
196{\r
197 unsigned int d=0;\r
198 \r
199 a&=0x1c;\r
200\r
201 if (a==0x00) { d=VideoRead(); goto end; }\r
202\r
203 if (a==0x04)\r
204 {\r
205 d=Pico.video.status;\r
206\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
210 Pico.m.rotate++;\r
211\r
212 if (Pico.m.pal) d|=1; // PAL screen\r
213\r
214 goto end;\r
215 }\r
216\r
217 if ((a&0x1c)==0x08)\r
218 {\r
219 if (Pico.m.scanline>-64) d=Pico.m.scanline; // HV-Counter\r
220 else d=Pico.m.rotate++; // Fudge\r
221\r
222 d&=0xff; d<<=8;\r
223 goto end;\r
224 }\r
225\r
226end:\r
227\r
228 return d;\r
229}\r