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