optimizations, fixes, hacks, psp, ...
[picodrive.git] / Pico / Misc.c
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
13 const unsigned char hcounts_40[] = {\r
14 0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,\r
15 0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x13,0x14,\r
16 0x14,0x15,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,\r
17 0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,\r
18 0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28,\r
19 0x28,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2f,\r
20 0x2f,0x30,0x30,0x30,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x34,0x34,0x35,0x35,0x35,\r
21 0x36,0x36,0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3c,0x3c,\r
22 0x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43,\r
23 0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x4a,\r
24 0x4a,0x4a,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,\r
25 0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57,\r
26 0x57,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5e,\r
27 0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64,\r
28 0x65,0x65,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,\r
29 0x6c,0x6c,0x6c,0x6d,0x6d,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x71,0x71,0x71,0x72,\r
30 0x72,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x79,\r
31 0x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f,\r
32 0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x84,0x84,0x84,0x85,0x85,0x86,0x86,\r
33 0x86,0x87,0x87,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,\r
34 0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x92,0x93,0x93,0x94,\r
35 0x94,0x94,0x95,0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,0x99,0x99,0x99,0x9a,0x9a,\r
36 0x9b,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1,\r
37 0xa1,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,0xa8,\r
38 0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,0xab,0xab,0xab,0xac,0xac,0xad,0xad,0xae,0xae,0xae,\r
39 0xaf,0xaf,0xb0,0xb0,\r
40 0xe4,0xe4,0xe4,0xe5,0xe5,0xe6,0xe6,0xe6,0xe7,0xe7,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,\r
41 0xea,0xeb,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1,\r
42 0xf1,0xf1,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,\r
43 0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfe,0xfe,\r
44 0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x05,\r
45 0x05,0x06,0x06,0x06,\r
46 0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,\r
47 0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,\r
48 };\r
49 \r
50 // H-counter table for hvcounter reads in 32col mode\r
51 const unsigned char hcounts_32[] = {\r
52 0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,\r
53 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,\r
54 0x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,\r
55 0x15,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,\r
56 0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,\r
57 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x26,0x26,\r
58 0x26,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,\r
59 0x2c,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x31,0x31,\r
60 0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37,\r
61 0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,\r
62 0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,0x41,0x41,0x41,0x42,\r
63 0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,\r
64 0x48,0x48,0x48,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,\r
65 0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,0x51,0x51,0x51,0x52,0x52,0x52,\r
66 0x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,\r
67 0x58,0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,\r
68 0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,\r
69 0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69,\r
70 0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,\r
71 0x6f,0x6f,0x6f,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x74,0x74,\r
72 0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x79,\r
73 0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,\r
74 0x7f,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x83,0x84,0x84,0x84,0x85,\r
75 0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,\r
76 0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x90,\r
77 0x90,0x90,0x91,0x91,\r
78 0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,0xea,0xea,0xeb,0xeb,0xeb,0xec,0xec,0xec,0xed,\r
79 0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf2,0xf2,0xf2,\r
80 0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf8,0xf8,\r
81 0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,\r
82 0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,\r
83 0x03,0x04,0x04,0x04,\r
84 0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a,\r
85 0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,\r
86 };\r
87 \r
88 // vcounter values for PicoFrameSimple\r
89 const 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
102 100,101,101,102,102,103,104,104,105,105,106,106,107,107,108,108,\r
103 109,109,110,110,111,111,112,112,113,114,114,115,115,116,116,117,\r
104 117,118,118,119,119,120,120,121,121,122,122,123,124,124,125,125,\r
105 126,126,127,127,128,128,129,129,130,130,131,131,132,132,133,133,\r
106 134,135,135,136,136,137,137,138,138,139,139,140,140,141,141,142,\r
107 142,143,143,144,145,145,146,146,147,147,148,148,149,149,150,150,\r
108 151,151,152,152,153,153,154,155,155,156,156,157,157,158,158,159,\r
109 159,160,160,161,161,162,162,163,163,164,164,165,166,166,167,167,\r
110 168,168,169,169,170,170,171,171,172,172,173,173,174,174,175,176,\r
111 176,177,177,178,178,179,179,180,180,181,181,182,182,183,183,184,\r
112 184,185,186,186,187,187,188,188,189,189,190,190,191,191,192,192,\r
113 193,193,194,194,195,195,196,197,197,198,198,199,199,200,200,201,\r
114 201,202,202,203,203,204,204,205,205,206,207,207,208,208,209,209,\r
115 210,210,211,211,212,212,213,213,214,214,215,215,216,217,217,218,\r
116 218,219,219,220,220,221,221,222,222,223,223,224,224,225,225,226,\r
117 226,227,228,228,229,229,230,230,231,231,232,232,233,233,234,234,\r
118 235,235,236,236,237,238,238,239,239,240,240,241,241,242,242,243,\r
119 243,244,244,245,245,246,246,247,248,248,249,249,250,250,251,251,\r
120 252,252,253,253,254,254,255,255,256,256,257,257,258,259,259,260,\r
121 260,261,261,262,262,263,263,264,264,265,265,266,266,267,267,268,\r
122 269,269,270,270,271,271,272,272,273,273,274,274,275,275,276,276,\r
123 277,277,278,279,279,280,280,281,281,282,282,283,283,284,284,285,\r
124 285,286,286,287,287,288,288,289,290,290,291,291,292,292,293,293,\r
125 294,294,295,295,296,296,297,297,298,298,299,300,300,301,301,302,\r
126 302,303,303,304,304,305,305,306,306,307,307,308,308,309,310,310,\r
127 311,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 \r
135 // (see Genesis Plus for Wii/GC code and docs for info,\r
136 //  full game list and better code).\r
137 \r
138 unsigned int lastSSRamWrite = 0xffff0000;\r
139 \r
140 // sram_reg: LAtd sela (L=pending SCL, A=pending SDA, t=(unused),\r
141 //                      d=SRAM was detected (header or by access), s=started, e=save is EEPROM, l=old SCL, a=old SDA)\r
142 PICO_INTERNAL void SRAMWriteEEPROM(unsigned int d) // ???? ??la (l=SCL, a=SDA)\r
143 {\r
144   unsigned int sreg = Pico.m.sram_reg, saddr = Pico.m.eeprom_addr, scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave;\r
145 \r
146   elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1,\r
147     (d&2)>>1, d&1, SekCyclesDoneT()-lastSSRamWrite);\r
148   saddr&=0x1fff;\r
149 \r
150   if(sreg & d & 2) {\r
151     // SCL was and is still high..\r
152     if((sreg & 1) && !(d&1)) {\r
153       // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter\r
154       elprintf(EL_EEPROM, "eeprom: -start-");\r
155       //saddr = 0;\r
156       scyc = 0;\r
157       sreg |= 8;\r
158     } else if(!(sreg & 1) && (d&1)) {\r
159       // SDA went high == stop command\r
160       elprintf(EL_EEPROM, "eeprom: -stop-");\r
161       sreg &= ~8;\r
162     }\r
163   }\r
164   else if((sreg & 8) && !(sreg & 2) && (d&2))\r
165   {\r
166     // we are started and SCL went high - next cycle\r
167     scyc++; // pre-increment\r
168     if(SRam.eeprom_type) {\r
169       // X24C02+\r
170       if((ssa&1) && scyc == 18) {\r
171         scyc = 9;\r
172         saddr++; // next address in read mode\r
173         /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask\r
174       }\r
175       else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18;\r
176       else if(scyc == 36) scyc = 27;\r
177     } else {\r
178       // X24C01\r
179       if(scyc == 18) {\r
180         scyc = 9;  // wrap\r
181         if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode\r
182       }\r
183     }\r
184     elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc);\r
185   }\r
186   else if((sreg & 8) && (sreg & 2) && !(d&2))\r
187   {\r
188     // we are started and SCL went low (falling edge)\r
189     if(SRam.eeprom_type) {\r
190       // X24C02+\r
191       if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles\r
192       else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) {\r
193         if(!(ssa&1)) {\r
194           // data write\r
195           unsigned char *pm=SRam.data+saddr;\r
196           *pm <<= 1; *pm |= d&1;\r
197           if(scyc == 26 || scyc == 35) {\r
198             saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented\r
199             elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm);\r
200           }\r
201           SRam.changed = 1;\r
202         }\r
203       } else if(scyc > 9) {\r
204         if(!(ssa&1)) {\r
205           // we latch another addr bit\r
206           saddr<<=1;\r
207           if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask\r
208           saddr|=d&1;\r
209           if(scyc==17||scyc==26) {\r
210             elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr);\r
211             if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too\r
212           }\r
213         }\r
214       } else {\r
215         // slave address\r
216         ssa<<=1; ssa|=d&1;\r
217         if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa);\r
218       }\r
219     } else {\r
220       // X24C01\r
221       if(scyc == 9); // ACK cycle, do nothing\r
222       else if(scyc > 9) {\r
223         if(!(saddr&1)) {\r
224           // data write\r
225           unsigned char *pm=SRam.data+(saddr>>1);\r
226           *pm <<= 1; *pm |= d&1;\r
227           if(scyc == 17) {\r
228             saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented\r
229             elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm);\r
230           }\r
231           SRam.changed = 1;\r
232         }\r
233       } else {\r
234         // we latch another addr bit\r
235         saddr<<=1; saddr|=d&1; saddr&=0xff;\r
236         if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1);\r
237       }\r
238     }\r
239   }\r
240 \r
241   sreg &= ~3; sreg |= d&3; // remember SCL and SDA\r
242   Pico.m.sram_reg    = (unsigned char) sreg;\r
243   Pico.m.eeprom_cycle= (unsigned char) scyc;\r
244   Pico.m.eeprom_slave= (unsigned char) ssa;\r
245   Pico.m.eeprom_addr = (unsigned short)saddr;\r
246 }\r
247 \r
248 PICO_INTERNAL_ASM unsigned int SRAMReadEEPROM(void)\r
249 {\r
250   unsigned int shift, d;\r
251   unsigned int sreg, saddr, scyc, ssa, interval;\r
252 \r
253   // flush last pending write\r
254   SRAMWriteEEPROM(Pico.m.sram_reg>>6);\r
255 \r
256   sreg = Pico.m.sram_reg; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave;\r
257   interval = SekCyclesDoneT()-lastSSRamWrite;\r
258   d = (sreg>>6)&1; // use SDA as "open bus"\r
259 \r
260   // NBA Jam is nasty enough to read <before> raising the SCL and starting the new cycle.\r
261   // this is probably valid because data changes occur while SCL is low and data can be read\r
262   // before it's actual cycle begins.\r
263   if (!(sreg&0x80) && interval >= 24) {\r
264     elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval);\r
265     scyc++;\r
266   }\r
267 \r
268   if (!(sreg & 8)); // not started, use open bus\r
269   else if (scyc == 9 || scyc == 18 || scyc == 27) {\r
270     elprintf(EL_EEPROM, "eeprom: r ack");\r
271     d = 0;\r
272   } else if (scyc > 9 && scyc < 18) {\r
273     // started and first command word received\r
274     shift = 17-scyc;\r
275     if (SRam.eeprom_type) {\r
276       // X24C02+\r
277       if (ssa&1) {\r
278         elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg);\r
279         if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]);\r
280         d = (SRam.data[saddr]>>shift)&1;\r
281       }\r
282     } else {\r
283       // X24C01\r
284       if (saddr&1) {\r
285         elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg);\r
286         if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]);\r
287         d = (SRam.data[saddr>>1]>>shift)&1;\r
288       }\r
289     }\r
290   }\r
291 \r
292   return (d << SRam.eeprom_bit_out);\r
293 }\r
294 \r
295 PICO_INTERNAL void SRAMUpdPending(unsigned int a, unsigned int d)\r
296 {\r
297   unsigned int d1, sreg = Pico.m.sram_reg;\r
298 \r
299   if (!((SRam.eeprom_abits^a)&1))\r
300   {\r
301     // SCL\r
302     sreg &= ~0x80;\r
303     d1 = (d >> SRam.eeprom_bit_cl) & 1;\r
304     sreg |= d1<<7;\r
305   }\r
306   if (!(((SRam.eeprom_abits>>1)^a)&1))\r
307   {\r
308     // SDA in\r
309     sreg &= ~0x40;\r
310     d1 = (d >> SRam.eeprom_bit_in) & 1;\r
311     sreg |= d1<<6;\r
312   }\r
313 \r
314   Pico.m.sram_reg = (unsigned char) sreg;\r
315 }\r
316 \r
317 \r
318 #ifndef _ASM_MISC_C\r
319 typedef struct\r
320 {\r
321         int b0;\r
322         int b1;\r
323         int b2;\r
324         int b3;\r
325         int b4;\r
326         int b5;\r
327         int b6;\r
328         int b7;\r
329 } intblock;\r
330 \r
331 PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count)\r
332 {\r
333         if ((((int)dest | (int)src) & 3) == 0)\r
334         {\r
335                 if (count >= 32) {\r
336                         memcpy32((int *)dest, (int *)src, count/2);\r
337                         count&=1;\r
338                 } else {\r
339                         for (; count >= 2; count -= 2, dest+=2, src+=2)\r
340                                 *(int *)dest = *(int *)src;\r
341                 }\r
342         }\r
343         while (count--)\r
344                 *dest++ = *src++;\r
345 }\r
346 \r
347 \r
348 PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count)\r
349 {\r
350         unsigned char *src_ = src;\r
351 \r
352         for (; count; count--, src_ += 2)\r
353                 *dest++ = (src_[0] << 8) | src_[1];\r
354 }\r
355 \r
356 #ifndef _ASM_MISC_C_AMIPS\r
357 PICO_INTERNAL_ASM void memcpy32(int *dest, int *src, int count)\r
358 {\r
359         intblock *bd = (intblock *) dest, *bs = (intblock *) src;\r
360 \r
361         for (; count >= sizeof(*bd)/4; count -= sizeof(*bd)/4)\r
362                 *bd++ = *bs++;\r
363 \r
364         dest = (int *)bd; src = (int *)bs;\r
365         while (count--)\r
366                 *dest++ = *src++;\r
367 }\r
368 \r
369 \r
370 PICO_INTERNAL_ASM void memset32(int *dest, int c, int count)\r
371 {\r
372         for (; count >= 8; count -= 8, dest += 8)\r
373                 dest[0] = dest[1] = dest[2] = dest[3] =\r
374                 dest[4] = dest[5] = dest[6] = dest[7] = c;\r
375 \r
376         while (count--)\r
377                 *dest++ = c;\r
378 }\r
379 void memset32_uncached(int *dest, int c, int count) { memset32(dest, c, count); }\r
380 #endif\r
381 #endif\r
382 \r