license info at top of Cyclone source files
[cyclone68000.git] / Pico / VideoPort.cpp
CommitLineData
15eb0001 1\r
2#include "PicoInt.h"\r
3\r
4static inline void AutoIncrement()\r
5{\r
6 Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]);\r
7}\r
8\r
9static void VideoWrite(unsigned int d)\r
10{\r
11 unsigned int a=0;\r
12 unsigned short sd=(unsigned short)d;\r
13\r
14 a=Pico.video.addr;\r
15 if (a&1) d=((d<<8)&0xff00)|(d>>8); // If address is odd, bytes are swapped\r
16 a>>=1;\r
17\r
18 switch (Pico.video.type)\r
19 {\r
20 case 1: Pico.vram [a&0x7fff]=sd; break;\r
21 case 3: Pico.cram [a&0x003f]=sd; Pico.m.dirtyPal=1; break;\r
22 case 5: Pico.vsram[a&0x003f]=sd; break;\r
23 }\r
24 \r
25 AutoIncrement();\r
26}\r
27\r
28static unsigned int VideoRead()\r
29{\r
30 unsigned int a=0,d=0;\r
31\r
32 a=Pico.video.addr; a>>=1;\r
33\r
34 switch (Pico.video.type)\r
35 {\r
36 case 0: d=Pico.vram [a&0x7fff]; break;\r
37 case 8: d=Pico.cram [a&0x003f]; break;\r
38 case 4: d=Pico.vsram[a&0x003f]; break;\r
39 }\r
40 \r
41 AutoIncrement();\r
42 return d;\r
43}\r
44\r
45static int GetDmaSource()\r
46{\r
47 struct PicoVideo *pvid=&Pico.video;\r
48 int source=0;\r
49 source =pvid->reg[0x15]<<1;\r
50 source|=pvid->reg[0x16]<<9;\r
51 source|=pvid->reg[0x17]<<17;\r
52 return source;\r
53}\r
54\r
55static int GetDmaLength()\r
56{\r
57 struct PicoVideo *pvid=&Pico.video;\r
58 int len=0;\r
59 // 16-bit words to transfer:\r
60 len =pvid->reg[0x13];\r
61 len|=pvid->reg[0x14]<<8;\r
62 return len;\r
63}\r
64\r
65static void DmaSlow(int source,int len)\r
66{\r
67 int i=0,max=0;\r
68\r
69 if (source>=0x800000 && source<0xe00000) return; // Invalid source address\r
70\r
71 /// Clip Cram DMA size (Todds Adventures in Slime World):\r
72 if (Pico.video.type==3) { max=0x80-Pico.video.addr; if (len>max) len=max; }\r
73\r
74 for (i=0;i<len;i++)\r
75 {\r
76 VideoWrite(PicoRead16(source));\r
77 source+=2;\r
78 }\r
79}\r
80\r
81static void DmaCopy(int source,int len)\r
82{\r
83 int i=0;\r
84\r
85 len>>=1; // Length specifies number of bytes\r
86\r
87 for (i=0;i<len;i++)\r
88 {\r
89 VideoWrite(Pico.vram[source&0x7fff]);\r
90 source+=2;\r
91 }\r
92}\r
93\r
94static void DmaFill(int data)\r
95{\r
96 int len=0,i=0;\r
97 \r
98 len=GetDmaLength();\r
99\r
100 for (i=0;i<len+1;i++) VideoWrite(data);\r
101}\r
102\r
103static void CommandDma()\r
104{\r
105 struct PicoVideo *pvid=&Pico.video;\r
106 int len=0,method=0,source=0;\r
107\r
108 if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled\r
109\r
110 len=GetDmaLength();\r
111\r
112 method=pvid->reg[0x17]>>6;\r
113 source=GetDmaSource();\r
114 if (method< 2) DmaSlow(source,len); // 68000 to VDP\r
115 if (method==3) DmaCopy(source,len); // VRAM Copy\r
116}\r
117\r
118static void CommandChange()\r
119{\r
120 struct PicoVideo *pvid=&Pico.video;\r
121 unsigned int cmd=0,addr=0;\r
122\r
123 cmd=pvid->command;\r
124\r
125 // Get type of transfer 0xc0000030 (v/c/vsram read/write)\r
126 pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30));\r
127\r
128 // Get address 0x3fff0003\r
129 addr =(cmd>>16)&0x3fff;\r
130 addr|=(cmd<<14)&0xc000;\r
131 pvid->addr=(unsigned short)addr;\r
132\r
133 // Check for dma:\r
134 if (cmd&0x80) CommandDma();\r
135}\r
136\r
137void PicoVideoWrite(unsigned int a,unsigned int d)\r
138{\r
139 struct PicoVideo *pvid=&Pico.video;\r
140\r
141 a&=0x1c;\r
142 d=(unsigned short)d;\r
143\r
144 if (a==0x00) // Data port 0 or 2\r
145 { \r
146 if (pvid->pending) CommandChange();\r
147 pvid->pending=0;\r
148\r
149 // If a DMA fill has been set up, do it\r
150 if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2)\r
151 {\r
152 DmaFill(d);\r
153 }\r
154 else\r
155 {\r
156 VideoWrite(d);\r
157 }\r
158 return;\r
159 }\r
160\r
161 if (a==0x04) // Command port 4 or 6\r
162 {\r
163 if (pvid->pending)\r
164 {\r
165 // Low word of command:\r
166 pvid->command&=0xffff0000;\r
167 pvid->command|=d;\r
168 pvid->pending=0;\r
169 CommandChange();\r
170 return;\r
171 }\r
172\r
173 if ((d&0xc000)==0x8000)\r
174 {\r
175 // Register write:\r
176 int num=(d>>8)&0x1f;\r
177 pvid->reg[num]=(unsigned char)d;\r
178 return;\r
179 }\r
180\r
181 // High word of command:\r
182 pvid->command&=0x0000ffff;\r
183 pvid->command|=d<<16;\r
184 pvid->pending=1;\r
185 }\r
186}\r
187\r
188unsigned int PicoVideoRead(unsigned int a)\r
189{\r
190 unsigned int d=0;\r
191 \r
192 a&=0x1c;\r
193\r
194 if (a==0x00) { d=VideoRead(); goto end; }\r
195\r
196 if (a==0x04)\r
197 {\r
198 d=Pico.video.status;\r
199\r
200 // Toggle fifo full empty:\r
201 if (Pico.m.rotate&4) d|=0x3520; else d|=0x3620;\r
202 if (Pico.m.rotate&2) d|=0x0004; // Toggle in/out of H-Blank\r
203 Pico.m.rotate++;\r
204\r
205 if (Pico.m.pal) d|=1; // PAL screen\r
206\r
207 goto end;\r
208 }\r
209\r
210 if ((a&0x1c)==0x08)\r
211 {\r
212 if (Pico.m.scanline>-64) d=Pico.m.scanline; // HV-Counter\r
213 else d=Pico.m.rotate++; // Fudge\r
214\r
215 d&=0xff; d<<=8;\r
216 goto end;\r
217 }\r
218\r
219end:\r
220\r
221 return d;\r
222}\r