Sonic CD shows Sega logo
[picodrive.git] / Pico / Misc.c
... / ...
CommitLineData
1// This is part of Pico Library\r
2\r
3// (c) Copyright 2006 notaz, All rights reserved.\r
4// Free for non-commercial use.\r
5\r
6// For commercial use, separate licencing terms must be obtained.\r
7\r
8\r
9#include "PicoInt.h"\r
10\r
11// H-counter table for hvcounter reads in 40col mode\r
12// based on Gens code\r
13const unsigned char hcounts_40[] = {\r
140x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,\r
150x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x13,0x14,\r
160x14,0x15,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,\r
170x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,\r
180x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28,\r
190x28,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2f,\r
200x2f,0x30,0x30,0x30,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x34,0x34,0x35,0x35,0x35,\r
210x36,0x36,0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3c,0x3c,\r
220x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43,\r
230x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x4a,\r
240x4a,0x4a,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,\r
250x51,0x51,0x52,0x52,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57,\r
260x57,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5e,\r
270x5e,0x5f,0x5f,0x5f,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64,\r
280x65,0x65,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,\r
290x6c,0x6c,0x6c,0x6d,0x6d,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x71,0x71,0x71,0x72,\r
300x72,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x79,\r
310x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f,\r
320x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x84,0x84,0x84,0x85,0x85,0x86,0x86,\r
330x86,0x87,0x87,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,\r
340x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x92,0x93,0x93,0x94,\r
350x94,0x94,0x95,0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,0x99,0x99,0x99,0x9a,0x9a,\r
360x9b,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1,\r
370xa1,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,0xa8,\r
380xa8,0xa9,0xa9,0xa9,0xaa,0xaa,0xab,0xab,0xab,0xac,0xac,0xad,0xad,0xae,0xae,0xae,\r
390xaf,0xaf,0xb0,0xb0,\r
400xe4,0xe4,0xe4,0xe5,0xe5,0xe6,0xe6,0xe6,0xe7,0xe7,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,\r
410xea,0xeb,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,\r
420xf1,0xf1,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,\r
430xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfe,0xfe,\r
440xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x05,\r
450x05,0x06,0x06,0x06,\r
460x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,\r
470x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,\r
48};\r
49\r
50// H-counter table for hvcounter reads in 32col mode\r
51const unsigned char hcounts_32[] = {\r
520x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,\r
530x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,\r
540x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,\r
550x15,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,\r
560x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,\r
570x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x26,0x26,\r
580x26,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,\r
590x2c,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x31,0x31,\r
600x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37,\r
610x37,0x37,0x38,0x38,0x38,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,\r
620x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,0x41,0x41,0x41,0x42,\r
630x42,0x42,0x43,0x43,0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,\r
640x48,0x48,0x48,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,\r
650x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,0x51,0x51,0x51,0x52,0x52,0x52,\r
660x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,\r
670x58,0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,\r
680x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,\r
690x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69,\r
700x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,\r
710x6f,0x6f,0x6f,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x74,0x74,\r
720x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x79,\r
730x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,\r
740x7f,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x83,0x84,0x84,0x84,0x85,\r
750x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,\r
760x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x90,\r
770x90,0x90,0x91,0x91,\r
780xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,0xea,0xea,0xeb,0xeb,0xeb,0xec,0xec,0xec,0xed,\r
790xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf2,0xf2,0xf2,\r
800xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf8,0xf8,\r
810xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,\r
820xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,\r
830x03,0x04,0x04,0x04,\r
840x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,\r
850x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,\r
86};\r
87\r
88// vcounter values for PicoFrameSimple \r
89const unsigned short vcounts[] = {\r
90 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,\r
91 8, 8, 9, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16,\r
92 16, 17, 17, 18, 18, 19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 24,\r
93 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, 32, 33,\r
94 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41,\r
95 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49,\r
96 50, 50, 51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, 58,\r
97 58, 59, 59, 60, 60, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66,\r
98 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 73, 73, 74, 74, 75,\r
99 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 83, 83,\r
100 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91,\r
101 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99,100,\r
102100,101,101,102,102,103,104,104,105,105,106,106,107,107,108,108,\r
103109,109,110,110,111,111,112,112,113,114,114,115,115,116,116,117,\r
104117,118,118,119,119,120,120,121,121,122,122,123,124,124,125,125,\r
105126,126,127,127,128,128,129,129,130,130,131,131,132,132,133,133,\r
106134,135,135,136,136,137,137,138,138,139,139,140,140,141,141,142,\r
107142,143,143,144,145,145,146,146,147,147,148,148,149,149,150,150,\r
108151,151,152,152,153,153,154,155,155,156,156,157,157,158,158,159,\r
109159,160,160,161,161,162,162,163,163,164,164,165,166,166,167,167,\r
110168,168,169,169,170,170,171,171,172,172,173,173,174,174,175,176,\r
111176,177,177,178,178,179,179,180,180,181,181,182,182,183,183,184,\r
112184,185,186,186,187,187,188,188,189,189,190,190,191,191,192,192,\r
113193,193,194,194,195,195,196,197,197,198,198,199,199,200,200,201,\r
114201,202,202,203,203,204,204,205,205,206,207,207,208,208,209,209,\r
115210,210,211,211,212,212,213,213,214,214,215,215,216,217,217,218,\r
116218,219,219,220,220,221,221,222,222,223,223,224,224,225,225,226,\r
117226,227,228,228,229,229,230,230,231,231,232,232,233,233,234,234,\r
118235,235,236,236,237,238,238,239,239,240,240,241,241,242,242,243,\r
119243,244,244,245,245,246,246,247,248,248,249,249,250,250,251,251,\r
120252,252,253,253,254,254,255,255,256,256,257,257,258,259,259,260,\r
121260,261,261,262,262,263,263,264,264,265,265,266,266,267,267,268,\r
122269,269,270,270,271,271,272,272,273,273,274,274,275,275,276,276,\r
123277,277,278,279,279,280,280,281,281,282,282,283,283,284,284,285,\r
124285,286,286,287,287,288,288,289,290,290,291,291,292,292,293,293,\r
125294,294,295,295,296,296,297,297,298,298,299,300,300,301,301,302,\r
126302,303,303,304,304,305,305,306,306,307,307,308,308,309,310,310,\r
127311,311,311,311,\r
128};\r
129\r
130\r
131// rarely used EEPROM SRAM code\r
132// known games which use this:\r
133// Wonder Boy in Monster World, Megaman - The Wily Wars (X24C01, 128 bytes)\r
134// NFL Quarterback Club*, Frank Thomas Big Hurt Baseball (X24C04?)\r
135// College Slam, Blockbuster World Video Game Championship II, NBA Jam (X24C04?)\r
136// HardBall '95\r
137\r
138// the above sports games use addr 0x200000 for SCL line (handled in Memory.c)\r
139\r
140unsigned int lastSSRamWrite = 0xffff0000;\r
141\r
142// sram_reg: LAtd sela (L=pending SCL, A=pending SDA, t=type(1==uses 0x200000 for SCL and 2K bytes),\r
143// d=SRAM was detected (header or by access), s=started, e=save is EEPROM, l=old SCL, a=old SDA)\r
144void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)\r
145{\r
146 unsigned int sreg = Pico.m.sram_reg, saddr = Pico.m.sram_addr, scyc = Pico.m.sram_cycle, ssa = Pico.m.sram_slave;\r
147\r
148 //dprintf("[%02x]", d);\r
149 sreg |= saddr&0xc000; // we store word count in add reg: dw?a aaaa ... (d=word count detected, w=words(0==use 2 words, else 1))\r
150 saddr&=0x1fff;\r
151\r
152 if(sreg & d & 2) {\r
153 // SCL was and is still high..\r
154 if((sreg & 1) && !(d&1)) {\r
155 // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter\r
156 //dprintf("-start-");\r
157 if(!(sreg&0x8000) && scyc >= 9) {\r
158 if(scyc != 28) sreg |= 0x4000; // 1 word\r
159 //dprintf("detected word count: %i", scyc==28 ? 2 : 1);\r
160 sreg |= 0x8000;\r
161 }\r
162 //saddr = 0;\r
163 scyc = 0;\r
164 sreg |= 8;\r
165 } else if(!(sreg & 1) && (d&1)) {\r
166 // SDA went high == stop command\r
167 //dprintf("-stop-");\r
168 sreg &= ~8;\r
169 }\r
170 }\r
171 else if((sreg & 8) && !(sreg & 2) && (d&2)) {\r
172 // we are started and SCL went high - next cycle\r
173 scyc++; // pre-increment\r
174 if(sreg & 0x20) {\r
175 // X24C02+\r
176 if((ssa&1) && scyc == 18) {\r
177 scyc = 9;\r
178 saddr++; // next address in read mode\r
179 if(sreg&0x4000) saddr&=0xff; else saddr&=0x1fff; // mask\r
180 }\r
181 else if((sreg&0x4000) && scyc == 27) scyc = 18;\r
182 else if(scyc == 36) scyc = 27;\r
183 } else {\r
184 // X24C01\r
185 if(scyc == 18) {\r
186 scyc = 9; // wrap\r
187 if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
188 }\r
189 }\r
190 //dprintf("scyc: %i", scyc);\r
191 }\r
192 else if((sreg & 8) && (sreg & 2) && !(d&2)) {\r
193 // we are started and SCL went low (falling edge)\r
194 if(sreg & 0x20) {\r
195 // X24C02+\r
196 if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
197 else if( (!(sreg&0x4000) && scyc > 27) || ((sreg&0x4000) && scyc > 18) ) {\r
198 if(!(ssa&1)) {\r
199 // data write\r
200 unsigned char *pm=SRam.data+saddr;\r
201 *pm <<= 1; *pm |= d&1;\r
202 if(scyc == 26 || scyc == 35) {\r
203 saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented\r
204 //dprintf("w done: %02x; addr inc: %x", *pm, saddr);\r
205 }\r
206 SRam.changed = 1;\r
207 }\r
208 } else if(scyc > 9) {\r
209 if(!(ssa&1)) {\r
210 // we latch another addr bit\r
211 saddr<<=1;\r
212 if(sreg&0x4000) saddr&=0xff; else saddr&=0x1fff; // mask\r
213 saddr|=d&1;\r
214 //if(scyc==17||scyc==26) dprintf("addr reg done: %x", saddr);\r
215 }\r
216 } else {\r
217 // slave address\r
218 ssa<<=1; ssa|=d&1;\r
219 //if(scyc==8) dprintf("slave done: %x", ssa);\r
220 }\r
221 } else {\r
222 // X24C01\r
223 if(scyc == 9); // ACK cycle, do nothing\r
224 else if(scyc > 9) {\r
225 if(!(saddr&1)) {\r
226 // data write\r
227 unsigned char *pm=SRam.data+(saddr>>1);\r
228 *pm <<= 1; *pm |= d&1;\r
229 if(scyc == 17) {\r
230 saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented\r
231 //dprintf("addr inc: %x", saddr>>1);\r
232 }\r
233 SRam.changed = 1;\r
234 }\r
235 } else {\r
236 // we latch another addr bit\r
237 saddr<<=1; saddr|=d&1; saddr&=0xff;\r
238 //if(scyc==8) dprintf("addr done: %x", saddr>>1);\r
239 }\r
240 }\r
241 }\r
242\r
243 sreg &= ~3; sreg |= d&3; // remember SCL and SDA\r
244 Pico.m.sram_reg = (unsigned char) sreg;\r
245 Pico.m.sram_addr = (unsigned short)(saddr|(sreg&0xc000));\r
246 Pico.m.sram_cycle= (unsigned char) scyc;\r
247 Pico.m.sram_slave= (unsigned char) ssa;\r
248}\r
249\r
250unsigned int SRAMReadEEPROM()\r
251{\r
252 unsigned int shift, d=0;\r
253 unsigned int sreg, saddr, scyc, ssa;\r
254\r
255 // flush last pending write\r
256 SRAMWriteEEPROM(Pico.m.sram_reg>>6);\r
257\r
258 sreg = Pico.m.sram_reg; saddr = Pico.m.sram_addr&0x1fff; scyc = Pico.m.sram_cycle; ssa = Pico.m.sram_slave;\r
259// if(!(sreg & 2) && (sreg&0x80)) scyc++; // take care of raising edge now to compensate lag\r
260\r
261 if(SekCyclesDoneT()-lastSSRamWrite < 46) {\r
262 // data was just written, there was no time to respond (used by sports games)\r
263 d = (sreg>>6)&1;\r
264 } else if((sreg & 8) && scyc > 9 && scyc != 18 && scyc != 27) {\r
265 // started and first command word received\r
266 shift = 17-scyc;\r
267 if(sreg & 0x20) {\r
268 // X24C02+\r
269 if(ssa&1) {\r
270 //dprintf("read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
271 d = (SRam.data[saddr]>>shift)&1;\r
272 }\r
273 } else {\r
274 // X24C01\r
275 if(saddr&1) {\r
276 d = (SRam.data[saddr>>1]>>shift)&1;\r
277 }\r
278 }\r
279 }\r
280 //else dprintf("r ack");\r
281\r
282 return d;\r
283}\r
284\r
285void SRAMUpdPending(unsigned int a, unsigned int d)\r
286{\r
287 unsigned int sreg = Pico.m.sram_reg;\r
288\r
289 if(!(a&1)) sreg|=0x20;\r
290\r
291 if(sreg&0x20) { // address through 0x200000\r
292 if(!(a&1)) {\r
293 sreg&=~0x80;\r
294 sreg|=d<<7;\r
295 } else {\r
296 sreg&=~0x40;\r
297 sreg|=(d<<6)&0x40;\r
298 }\r
299 } else {\r
300 sreg&=~0xc0;\r
301 sreg|=d<<6;\r
302 }\r
303\r
304 Pico.m.sram_reg = (unsigned char) sreg;\r
305}\r