1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "emulator.h"
7 #include "audio/blip_buf.h"
8 #include "dbvz.h"
9 #include "m5XXBus.h"
10 #include "sed1376.h"
11 #include "ads7846.h"
12 #include "pdiUsbD12.h"
13 #include "sdCard.h"
14 #include "silkscreen.h"
15 #include "portability.h"
16 #if defined(EMU_SUPPORT_PALM_OS5)
17 #include "tungstenT3Bus.h"
18 #include "pxa260/pxa260.h"
19 #include "tps65010.h"
20 #include "tsc2101.h"
21 #include "w86l488.h"
22 #endif
23
24
25 //Memory map of Palm m515
26 //0x00000000<->0x00FFFFFF RAM, CSC0 as RAS0, CSC1 as RAS1, CSD0 as CAS0 and CSD1 as CAS1
27 //0x10000000<->0x103FFFFF ROM, CSA0, at address 0x00000000 during boot, palmos41-en-m515.rom, substitute "en" for your language code
28 //0x10400000<->0x10400003 USB, CSA1
29 //0x1FF80000<->0x1FF800B3 SED1376(Display Controller) Registers, CSB0
30 //0x1FFA0000<->0x1FFB3FFF SED1376(Display Controller) Framebuffer, CSB0, this is not the same as the Palm framebuffer which is always 16 bit color,
31 //this buffer must be processed depending on whats in the SED1376 registers, the result is the Palm framebuffer
32 //0xFFFFF000<->0xFFFFFDFF Hardware Registers
33 //0xFFFFFE00<->0xFFFFFFFF Bootloader, only reads from UART into RAM and jumps to it, never executed in consumer Palms
34
35 //Memory map of Tungsten T3
36 //Boot address ranges, these are changed with the MMU after boot
37 //0x00000000<->0x003FFFFF ROM
38 //0xA0000000<->0xA3FFFFFF RAM
39 //Post boot address ranges:
40 //0x00000000<->0x003FFFFF RAM
41 //0x20000000<->0x20FFFFFF ROM
42 //TODO: add other chips
43
44 //VGhpcyBlbXVsYXRvciBpcyBkZWRpY2F0ZWQgdG8gdGhlIGJvdmluZSBtb28gY293cyB0aGF0IG1vby4=
45
46
47 static bool emulatorInitialized = false;
48
49 #if defined(EMU_SUPPORT_PALM_OS5)
50 bool palmEmulatingTungstenT3;
51 #endif
52 bool palmEmulatingM500;
53 uint8_t* palmRam;
54 uint8_t* palmRom;
55 input_t palmInput;
56 sd_card_t palmSdCard;
57 misc_hw_t palmMisc;
58 uint16_t* palmFramebuffer;
59 uint16_t palmFramebufferWidth;
60 uint16_t palmFramebufferHeight;
61 int16_t* palmAudio;
62 blip_t* palmAudioResampler;
63 double palmCycleCounter;//can be greater then 0 if too many cycles where run
64 double palmClockMultiplier;//used by the emulator to overclock the emulated Palm
65 bool palmSyncRtc;//doesnt go in save states, its a property of the session not the device
66 bool palmAllowInvalidBehavior;//doesnt go in save states, its a property of the session not the device
67 void (*palmIrSetPortProperties)(serial_port_properties_t* properties);//configure port I/O behavior, used for proxyed native I/R connections
68 uint32_t (*palmIrDataSize)(void);//returns the current number of bytes in the hosts IR receive FIFO
69 uint16_t (*palmIrDataReceive)(void);//called by the emulator to read the hosts IR receive FIFO
70 void (*palmIrDataSend)(uint16_t data);//called by the emulator to send IR data
71 void (*palmIrDataFlush)(void);//called by the emulator to delete all data in the hosts IR receive FIFO
72 void (*palmSerialSetPortProperties)(serial_port_properties_t* properties);//configure port I/O behavior, used for proxyed native serial connections
73 uint32_t (*palmSerialDataSize)(void);//returns the current number of bytes in the hosts serial receive FIFO
74 uint16_t (*palmSerialDataReceive)(void);//called by the emulator to read the hosts serial receive FIFO
75 void (*palmSerialDataSend)(uint16_t data);//called by the emulator to send serial data
76 void (*palmSerialDataFlush)(void);//called by the emulator to delete all data in the hosts serial receive FIFO
77 void (*palmGetRtcFromHost)(uint8_t* writeBack);//[0] = hours, [1] = minutes, [2] = seconds
78
79
patchOsRom(uint32_t address,char * patch)80 static void patchOsRom(uint32_t address, char* patch){
81 uint32_t offset;
82 uint32_t patchBytes = strlen(patch) / 2;//1 char per nibble
83 uint32_t swapBegin = address & 0xFFFFFFFE;
84 uint32_t swapSize = patchBytes / sizeof(uint16_t) + 1;
85 char conv[5] = "0xXX";
86
87 #if defined(EMU_SUPPORT_PALM_OS5)
88 if(!palmEmulatingTungstenT3)
89 #endif
90 swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
91 for(offset = 0; offset < patchBytes; offset++){
92 conv[2] = patch[offset * 2];
93 conv[3] = patch[offset * 2 + 1];
94 palmRom[address + offset] = strtol(conv, NULL, 0);
95 }
96 #if defined(EMU_SUPPORT_PALM_OS5)
97 if(!palmEmulatingTungstenT3)
98 #endif
99 swap16BufferIfLittle(&palmRom[swapBegin], swapSize);
100 }
101
102
emulatorInit(uint8_t emulatedDevice,uint8_t * palmRomData,uint32_t palmRomSize,uint8_t * palmBootloaderData,uint32_t palmBootloaderSize,bool syncRtc,bool allowInvalidBehavior)103 uint32_t emulatorInit(uint8_t emulatedDevice, uint8_t* palmRomData, uint32_t palmRomSize, uint8_t* palmBootloaderData, uint32_t palmBootloaderSize, bool syncRtc, bool allowInvalidBehavior){
104 if(emulatorInitialized)
105 return EMU_ERROR_RESOURCE_LOCKED;
106
107 palmSyncRtc = syncRtc;
108 palmAllowInvalidBehavior = allowInvalidBehavior;
109
110 if(!palmRomData || palmRomSize < 0x8)
111 return EMU_ERROR_INVALID_PARAMETER;
112
113 palmIrSetPortProperties = NULL;
114 palmIrDataSize = NULL;
115 palmIrDataReceive = NULL;
116 palmIrDataSend = NULL;
117 palmIrDataFlush = NULL;
118 palmSerialSetPortProperties = NULL;
119 palmSerialDataSize = NULL;
120 palmSerialDataReceive = NULL;
121 palmSerialDataSend = NULL;
122 palmSerialDataFlush = NULL;
123 palmGetRtcFromHost = NULL;
124
125 #if defined(EMU_SUPPORT_PALM_OS5)
126 palmEmulatingTungstenT3 = emulatedDevice == EMU_DEVICE_TUNGSTEN_T3;
127
128 if(palmEmulatingTungstenT3){
129 //emulating Tungsten T3
130 bool dynarecInited = false;
131
132 dynarecInited = pxa260Init(&palmRom, &palmRam);
133 palmFramebuffer = malloc(320 * 480 * sizeof(uint16_t));
134 palmAudio = malloc(AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(int16_t));
135 palmAudioResampler = blip_new(AUDIO_SAMPLE_RATE);//have 1 second of samples
136 if(!palmFramebuffer || !palmAudio || !palmAudioResampler || !dynarecInited){
137 free(palmFramebuffer);
138 free(palmAudio);
139 blip_delete(palmAudioResampler);
140 pxa260Deinit();
141 return EMU_ERROR_OUT_OF_MEMORY;
142 }
143 memcpy(palmRom, palmRomData, FAST_MIN(palmRomSize, TUNGSTEN_T3_ROM_SIZE));
144 if(palmRomSize < TUNGSTEN_T3_ROM_SIZE)
145 memset(palmRom + palmRomSize, 0x00, TUNGSTEN_T3_ROM_SIZE - palmRomSize);
146 memset(palmRam, 0x00, TUNGSTEN_T3_RAM_SIZE);
147 memset(palmFramebuffer, 0x00, 320 * 480 * sizeof(uint16_t));//TODO:PXA260 code doesnt always output a picture like my SED1376 code, so clear the buffer to prevent garbage from being displayed before the first render
148 memset(palmAudio, 0x00, AUDIO_SAMPLES_PER_FRAME * 2/*channels*/ * sizeof(int16_t));
149 memset(&palmInput, 0x00, sizeof(palmInput));
150 memset(&palmMisc, 0x00, sizeof(palmMisc));
151 memset(&palmSdCard, 0x00, sizeof(palmSdCard));
152 palmFramebufferWidth = 320;
153 palmFramebufferHeight = 480;
154 palmMisc.batteryLevel = 100;
155 palmCycleCounter = 0.0;
156 palmClockMultiplier = 1.00 - TUNGSTEN_T3_CPU_PERCENT_WAITING;
157
158 //initialize components, I dont think theres much in a Tungsten T3
159 pxa260Framebuffer = palmFramebuffer;
160 blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
161
162 patchOsRom(0x333EC6, "0000");//blocks out the slot driver
163 patchOsRom(0x205C, "0000A0E1");//blocks idle loop jump with NOP
164
165 //reset everything
166 emulatorSoftReset();
167 pxa260SetRtc(0, 0, 0, 0);
168 }
169 else{
170 #endif
171 //emulating Palm m515 or m500
172 palmEmulatingM500 = emulatedDevice == EMU_DEVICE_PALM_M500;
173
174 //allocate buffers, add 4 to memory regions to prevent SIGSEGV from accessing off the end
175 palmRom = malloc(M5XX_ROM_SIZE + 4);
176 palmRam = malloc((palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE) + 4);
177 palmFramebuffer = malloc(160 * 220 * sizeof(uint16_t));
178 palmAudio = malloc(AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(int16_t));
179 palmAudioResampler = blip_new(AUDIO_SAMPLE_RATE);//have 1 second of samples
180 if(!palmRom || !palmRam || !palmFramebuffer || !palmAudio || !palmAudioResampler){
181 free(palmRom);
182 free(palmRam);
183 free(palmFramebuffer);
184 free(palmAudio);
185 blip_delete(palmAudioResampler);
186 return EMU_ERROR_OUT_OF_MEMORY;
187 }
188
189 //set default values
190 memcpy(palmRom, palmRomData, FAST_MIN(palmRomSize, M5XX_ROM_SIZE));
191 if(palmRomSize < M5XX_ROM_SIZE)
192 memset(palmRom + palmRomSize, 0x00, M5XX_ROM_SIZE - palmRomSize);
193 swap16BufferIfLittle(palmRom, M5XX_ROM_SIZE / sizeof(uint16_t));
194 memset(palmRam, 0x00, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
195 dbvzLoadBootloader(palmBootloaderData, palmBootloaderSize);
196 memcpy(palmFramebuffer + 160 * 160, silkscreen160x60, 160 * 60 * sizeof(uint16_t));
197 memset(palmAudio, 0x00, AUDIO_SAMPLES_PER_FRAME * 2/*channels*/ * sizeof(int16_t));
198 memset(&palmInput, 0x00, sizeof(palmInput));
199 memset(&palmMisc, 0x00, sizeof(palmMisc));
200 memset(&palmSdCard, 0x00, sizeof(palmSdCard));
201 palmFramebufferWidth = 160;
202 palmFramebufferHeight = 220;
203 palmMisc.batteryLevel = 100;
204 palmCycleCounter = 0.0;
205 palmClockMultiplier = 1.00 - DBVZ_CPU_PERCENT_WAITING;
206 if(palmEmulatingM500){
207 dbvzFramebuffer = palmFramebuffer;
208 dbvzFramebufferWidth = 160;
209 dbvzFramebufferHeight = 160;
210 }
211 else{
212 sed1376Framebuffer = palmFramebuffer;
213 sed1376FramebufferWidth = 160;
214 sed1376FramebufferHeight = 160;
215 }
216
217 //initialize components
218 blip_set_rates(palmAudioResampler, DBVZ_AUDIO_MAX_CLOCK_RATE, AUDIO_SAMPLE_RATE);
219
220 //reset everything
221 emulatorSoftReset();
222 dbvzSetRtc(0, 0, 0, 0);//RTCTIME and DAYR are not cleared by reset, clear them manually in case the frontend doesnt set the RTC
223 #if defined(EMU_SUPPORT_PALM_OS5)
224 }
225 #endif
226
227 emulatorInitialized = true;
228
229 return EMU_ERROR_NONE;
230 }
231
emulatorDeinit(void)232 void emulatorDeinit(void){
233 if(emulatorInitialized){
234 #if defined(EMU_SUPPORT_PALM_OS5)
235 if(!palmEmulatingTungstenT3){
236 #endif
237 free(palmRom);
238 free(palmRam);
239 #if defined(EMU_SUPPORT_PALM_OS5)
240 }
241 #endif
242 free(palmFramebuffer);
243 free(palmAudio);
244 blip_delete(palmAudioResampler);
245 #if defined(EMU_SUPPORT_PALM_OS5)
246 if(palmEmulatingTungstenT3)
247 pxa260Deinit();
248 #endif
249 free(palmSdCard.flashChipData);
250 emulatorInitialized = false;
251 }
252 }
253
emulatorHardReset(void)254 void emulatorHardReset(void){
255 //equivalent to taking the battery out and putting it back in
256 #if defined(EMU_SUPPORT_PALM_OS5)
257 if(palmEmulatingTungstenT3){
258 memset(palmRam, 0x00, TUNGSTEN_T3_RAM_SIZE);
259 emulatorSoftReset();
260 sdCardReset();
261 pxa260SetRtc(0, 0, 0, 0);
262 }
263 else{
264 #endif
265 memset(palmRam, 0x00, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
266 emulatorSoftReset();
267 sdCardReset();
268 dbvzSetRtc(0, 0, 0, 0);
269 #if defined(EMU_SUPPORT_PALM_OS5)
270 }
271 #endif
272 }
273
emulatorSoftReset(void)274 void emulatorSoftReset(void){
275 //equivalent to pushing the reset button on the back of the device
276 #if defined(EMU_SUPPORT_PALM_OS5)
277 if(palmEmulatingTungstenT3){
278 pxa260Reset();
279 tps65010Reset();
280 tsc2101Reset(true);
281 w86l488Reset();
282 }
283 else{
284 #endif
285 if(!palmEmulatingM500)
286 sed1376Reset();
287 ads7846Reset();
288 pdiUsbD12Reset();
289 dbvzReset();
290 //sdCardReset() should not be called here, the SD card does not have a reset line and should only be reset by a power cycle
291 #if defined(EMU_SUPPORT_PALM_OS5)
292 }
293 #endif
294 }
295
emulatorSetRtc(uint16_t days,uint8_t hours,uint8_t minutes,uint8_t seconds)296 void emulatorSetRtc(uint16_t days, uint8_t hours, uint8_t minutes, uint8_t seconds){
297 #if defined(EMU_SUPPORT_PALM_OS5)
298 if(palmEmulatingTungstenT3)
299 pxa260SetRtc(days, hours, minutes, seconds);
300 else
301 #endif
302 dbvzSetRtc(days, hours, minutes, seconds);
303 }
304
emulatorSetCpuSpeed(double speed)305 void emulatorSetCpuSpeed(double speed){
306 #if defined(EMU_SUPPORT_PALM_OS5)
307 if(palmEmulatingTungstenT3)
308 palmClockMultiplier = speed * (1.00 - TUNGSTEN_T3_CPU_PERCENT_WAITING);
309 else
310 #endif
311 palmClockMultiplier = speed * (1.00 - DBVZ_CPU_PERCENT_WAITING);
312 }
313
emulatorGetStateSize(void)314 uint32_t emulatorGetStateSize(void){
315 uint32_t size = 0;
316
317 size += sizeof(uint32_t);//save state version
318 size += sizeof(uint32_t);//palmEmuFeatures.info
319 size += sizeof(uint64_t);//palmSdCard.flashChipSize, needs to be done first to verify the malloc worked
320 size += sizeof(uint16_t) * 2;//palmFramebuffer(Width/Height)
321 #if defined(EMU_SUPPORT_PALM_OS5)
322 if(palmEmulatingTungstenT3){
323 size += pxa260StateSize();
324 size += TUNGSTEN_T3_RAM_SIZE;//system RAM buffer
325 }
326 else{
327 #endif
328 size += dbvzStateSize();
329 if(!palmEmulatingM500)
330 size += sed1376StateSize();
331 size += ads7846StateSize();
332 size += pdiUsbD12StateSize();
333 size += palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE;//system RAM buffer
334 #if defined(EMU_SUPPORT_PALM_OS5)
335 }
336 #endif
337 size += sizeof(uint8_t) * 7;//palmMisc
338 size += sizeof(uint32_t) * 4;//palmEmuFeatures.(src/dst/size/value)
339 size += sizeof(uint64_t);//palmSdCard.command
340 size += sizeof(uint8_t) * 7;//palmSdCard.(commandBitsRemaining/runningCommand/commandIsAcmd/allowInvalidCrc/chipSelect/receivingCommand/inIdleState)
341 size += sizeof(uint16_t) * 2;//palmSdCard.response(Read/Write)Position
342 size += sizeof(int8_t);//palmSdCard.responseReadPositionBit
343 size += sizeof(uint32_t) * 3;//palmSdCard.runningCommandVars
344 size += SD_CARD_BLOCK_DATA_PACKET_SIZE;//palmSdCard.runningCommandPacket
345 size += SD_CARD_RESPONSE_FIFO_SIZE;//palmSdCard.responseFifo
346 size += 16 * 2;//palmSdCard.sdInfo.csd/cid
347 size += 8;//palmSdCard.sdInfo.scr
348 size += sizeof(uint32_t);//palmSdCard.sdInfo.ocr
349 size += sizeof(uint8_t);//palmSdCard.sdInfo.writeProtectSwitch
350 size += palmSdCard.flashChipSize;//palmSdCard.flashChipData
351
352 return size;
353 }
354
emulatorSaveState(uint8_t * data,uint32_t size)355 bool emulatorSaveState(uint8_t* data, uint32_t size){
356 uint32_t offset = 0;
357 uint8_t index;
358
359 if(size < emulatorGetStateSize())
360 return false;//state cant fit
361
362 //state validation, wont load states that are not from the same state version
363 #if defined(EMU_SUPPORT_PALM_OS5)
364 writeStateValue32(data + offset, SAVE_STATE_VERSION | palmEmulatingTungstenT3 * SAVE_STATE_FOR_TUNGSTEN_T3 | palmEmulatingM500 * SAVE_STATE_FOR_M500);
365 #else
366 writeStateValue32(data + offset, SAVE_STATE_VERSION | palmEmulatingM500 * SAVE_STATE_FOR_M500);
367 #endif
368 offset += sizeof(uint32_t);
369
370 //SD card size
371 writeStateValue64(data + offset, palmSdCard.flashChipSize);
372 offset += sizeof(uint64_t);
373
374 //screen state
375 writeStateValue16(data + offset, palmFramebufferWidth);
376 offset += sizeof(uint16_t);
377 writeStateValue16(data + offset, palmFramebufferHeight);
378 offset += sizeof(uint16_t);
379
380 #if defined(EMU_SUPPORT_PALM_OS5)
381 if(palmEmulatingTungstenT3){
382 //chips
383 pxa260SaveState(data + offset);
384 offset += pxa260StateSize();
385
386 //memory
387 memcpy(data + offset, palmRam, TUNGSTEN_T3_RAM_SIZE);
388 offset += TUNGSTEN_T3_RAM_SIZE;
389 }
390 else{
391 #endif
392 //chips
393 dbvzSaveState(data + offset);
394 offset += dbvzStateSize();
395 if(!palmEmulatingM500){
396 sed1376SaveState(data + offset);
397 offset += sed1376StateSize();
398 }
399 ads7846SaveState(data + offset);
400 offset += ads7846StateSize();
401 pdiUsbD12SaveState(data + offset);
402 offset += pdiUsbD12StateSize();
403
404 //memory
405 memcpy(data + offset, palmRam, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
406 swap16BufferIfLittle(data + offset, (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE) / sizeof(uint16_t));
407 offset += palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE;
408 #if defined(EMU_SUPPORT_PALM_OS5)
409 }
410 #endif
411
412 //misc
413 writeStateValue8(data + offset, palmMisc.greenLed);
414 offset += sizeof(uint8_t);
415 writeStateValue8(data + offset, palmMisc.lcdOn);
416 offset += sizeof(uint8_t);
417 writeStateValue8(data + offset, palmMisc.backlightLevel);
418 offset += sizeof(uint8_t);
419 writeStateValue8(data + offset, palmMisc.vibratorOn);
420 offset += sizeof(uint8_t);
421 writeStateValue8(data + offset, palmMisc.batteryCharging);
422 offset += sizeof(uint8_t);
423 writeStateValue8(data + offset, palmMisc.batteryLevel);
424 offset += sizeof(uint8_t);
425 writeStateValue8(data + offset, palmMisc.dataPort);
426 offset += sizeof(uint8_t);
427
428 //SD card
429 writeStateValue64(data + offset, palmSdCard.command);
430 offset += sizeof(uint64_t);
431 writeStateValue8(data + offset, palmSdCard.commandBitsRemaining);
432 offset += sizeof(uint8_t);
433 writeStateValue8(data + offset, palmSdCard.runningCommand);
434 offset += sizeof(uint8_t);
435 for(index = 0; index < 3; index++){
436 writeStateValue32(data + offset, palmSdCard.runningCommandVars[index]);
437 offset += sizeof(uint32_t);
438 }
439 memcpy(data + offset, palmSdCard.runningCommandPacket, SD_CARD_BLOCK_DATA_PACKET_SIZE);
440 offset += SD_CARD_BLOCK_DATA_PACKET_SIZE;
441 memcpy(data + offset, palmSdCard.responseFifo, SD_CARD_RESPONSE_FIFO_SIZE);
442 offset += SD_CARD_RESPONSE_FIFO_SIZE;
443 writeStateValue16(data + offset, palmSdCard.responseReadPosition);
444 offset += sizeof(uint16_t);
445 writeStateValue8(data + offset, palmSdCard.responseReadPositionBit);
446 offset += sizeof(int8_t);
447 writeStateValue16(data + offset, palmSdCard.responseWritePosition);
448 offset += sizeof(uint16_t);
449 writeStateValue8(data + offset, palmSdCard.commandIsAcmd);
450 offset += sizeof(uint8_t);
451 writeStateValue8(data + offset, palmSdCard.allowInvalidCrc);
452 offset += sizeof(uint8_t);
453 writeStateValue8(data + offset, palmSdCard.chipSelect);
454 offset += sizeof(uint8_t);
455 writeStateValue8(data + offset, palmSdCard.receivingCommand);
456 offset += sizeof(uint8_t);
457 writeStateValue8(data + offset, palmSdCard.inIdleState);
458 offset += sizeof(uint8_t);
459 memcpy(data + offset, palmSdCard.sdInfo.csd, 16);
460 offset += 16;
461 memcpy(data + offset, palmSdCard.sdInfo.cid, 16);
462 offset += 16;
463 memcpy(data + offset, palmSdCard.sdInfo.scr, 8);
464 offset += 8;
465 writeStateValue32(data + offset, palmSdCard.sdInfo.ocr);
466 offset += sizeof(uint32_t);
467 writeStateValue8(data + offset, palmSdCard.sdInfo.writeProtectSwitch);
468 offset += sizeof(uint8_t);
469 memcpy(data + offset, palmSdCard.flashChipData, palmSdCard.flashChipSize);
470 offset += palmSdCard.flashChipSize;
471
472 return true;
473 }
474
emulatorLoadState(uint8_t * data,uint32_t size)475 bool emulatorLoadState(uint8_t* data, uint32_t size){
476 uint32_t offset = 0;
477 uint8_t index;
478 uint32_t stateSdCardSize;
479 uint8_t* stateSdCardBuffer;
480
481 //state validation, wont load states that are not from the same state version
482 #if defined(EMU_SUPPORT_PALM_OS5)
483 if(readStateValue32(data + offset) != (SAVE_STATE_VERSION | palmEmulatingTungstenT3 * SAVE_STATE_FOR_TUNGSTEN_T3 | palmEmulatingM500 * SAVE_STATE_FOR_M500))
484 return false;
485 #else
486 if(readStateValue32(data + offset) != (SAVE_STATE_VERSION | palmEmulatingM500 * SAVE_STATE_FOR_M500))
487 return false;
488 #endif
489 offset += sizeof(uint32_t);
490
491 //SD card size, the malloc when loading can make it fail, make sure if it fails the emulator state doesnt change
492 stateSdCardSize = readStateValue64(data + offset);
493 stateSdCardBuffer = stateSdCardSize > 0 ? malloc(stateSdCardSize) : NULL;
494 if(stateSdCardSize > 0 && !stateSdCardBuffer)
495 return false;
496 offset += sizeof(uint64_t);
497
498 //screen state
499 palmFramebufferWidth = readStateValue16(data + offset);
500 offset += sizeof(uint16_t);
501 palmFramebufferHeight = readStateValue16(data + offset);
502 offset += sizeof(uint16_t);
503
504 #if defined(EMU_SUPPORT_PALM_OS5)
505 if(palmEmulatingTungstenT3){
506 //chips
507 pxa260LoadState(data + offset);
508 offset += pxa260StateSize();
509
510 //memory
511 memcpy(palmRam, data + offset, TUNGSTEN_T3_RAM_SIZE);
512 offset += TUNGSTEN_T3_RAM_SIZE;
513 }
514 else{
515 #endif
516 //chips
517 dbvzLoadState(data + offset);
518 offset += dbvzStateSize();
519 if(!palmEmulatingM500){
520 sed1376LoadState(data + offset);
521 offset += sed1376StateSize();
522 }
523 ads7846LoadState(data + offset);
524 offset += ads7846StateSize();
525 pdiUsbD12LoadState(data + offset);
526 offset += pdiUsbD12StateSize();
527
528 //memory
529 memcpy(palmRam, data + offset, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
530 swap16BufferIfLittle(palmRam, (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE) / sizeof(uint16_t));
531 offset += palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE;
532 #if defined(EMU_SUPPORT_PALM_OS5)
533 }
534 #endif
535
536 //misc
537 palmMisc.greenLed = readStateValue8(data + offset);
538 offset += sizeof(uint8_t);
539 palmMisc.lcdOn = readStateValue8(data + offset);
540 offset += sizeof(uint8_t);
541 palmMisc.backlightLevel = readStateValue8(data + offset);
542 offset += sizeof(uint8_t);
543 palmMisc.vibratorOn = readStateValue8(data + offset);
544 offset += sizeof(uint8_t);
545 palmMisc.batteryCharging = readStateValue8(data + offset);
546 offset += sizeof(uint8_t);
547 palmMisc.batteryLevel = readStateValue8(data + offset);
548 offset += sizeof(uint8_t);
549 palmMisc.dataPort = readStateValue8(data + offset);
550 offset += sizeof(uint8_t);
551
552 //SD card
553 palmSdCard.command = readStateValue64(data + offset);
554 offset += sizeof(uint64_t);
555 palmSdCard.commandBitsRemaining = readStateValue8(data + offset);
556 offset += sizeof(uint8_t);
557 palmSdCard.runningCommand = readStateValue8(data + offset);
558 offset += sizeof(uint8_t);
559 for(index = 0; index < 3; index++){
560 palmSdCard.runningCommandVars[index] = readStateValue32(data + offset);
561 offset += sizeof(uint32_t);
562 }
563 memcpy(palmSdCard.runningCommandPacket, data + offset, SD_CARD_BLOCK_DATA_PACKET_SIZE);
564 offset += SD_CARD_BLOCK_DATA_PACKET_SIZE;
565 memcpy(palmSdCard.responseFifo, data + offset, SD_CARD_RESPONSE_FIFO_SIZE);
566 offset += SD_CARD_RESPONSE_FIFO_SIZE;
567 palmSdCard.responseReadPosition = readStateValue16(data + offset);
568 offset += sizeof(uint16_t);
569 palmSdCard.responseReadPositionBit = readStateValue8(data + offset);
570 offset += sizeof(int8_t);
571 palmSdCard.responseWritePosition = readStateValue16(data + offset);
572 offset += sizeof(uint16_t);
573 palmSdCard.commandIsAcmd = readStateValue8(data + offset);
574 offset += sizeof(uint8_t);
575 palmSdCard.allowInvalidCrc = readStateValue8(data + offset);
576 offset += sizeof(uint8_t);
577 palmSdCard.chipSelect = readStateValue8(data + offset);
578 offset += sizeof(uint8_t);
579 palmSdCard.receivingCommand = readStateValue8(data + offset);
580 offset += sizeof(uint8_t);
581 palmSdCard.inIdleState = readStateValue8(data + offset);
582 offset += sizeof(uint8_t);
583 memcpy(palmSdCard.sdInfo.csd, data + offset, 16);
584 offset += 16;
585 memcpy(palmSdCard.sdInfo.cid, data + offset, 16);
586 offset += 16;
587 memcpy(palmSdCard.sdInfo.scr, data + offset, 8);
588 offset += 8;
589 palmSdCard.sdInfo.ocr = readStateValue32(data + offset);
590 offset += sizeof(uint32_t);
591 palmSdCard.sdInfo.writeProtectSwitch = readStateValue8(data + offset);
592 offset += sizeof(uint8_t);
593 if(palmSdCard.flashChipData)
594 free(palmSdCard.flashChipData);
595 palmSdCard.flashChipData = stateSdCardBuffer;
596 palmSdCard.flashChipSize = stateSdCardSize;
597 memcpy(palmSdCard.flashChipData, data + offset, stateSdCardSize);
598 offset += stateSdCardSize;
599
600 //some modules depend on all the state memory being loaded before certian required actions can occur(refreshing cached data, freeing memory blocks)
601 dbvzLoadStateFinished();
602
603 return true;
604 }
605
emulatorGetRamSize(void)606 uint32_t emulatorGetRamSize(void){
607 #if defined(EMU_SUPPORT_PALM_OS5)
608 if(palmEmulatingTungstenT3)
609 return TUNGSTEN_T3_RAM_SIZE;
610 #endif
611 return palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE;
612 }
613
emulatorSaveRam(uint8_t * data,uint32_t size)614 bool emulatorSaveRam(uint8_t* data, uint32_t size){
615 #if defined(EMU_SUPPORT_PALM_OS5)
616 if(palmEmulatingTungstenT3){
617 if(size < TUNGSTEN_T3_RAM_SIZE)
618 return false;
619
620 memcpy(data, palmRam, TUNGSTEN_T3_RAM_SIZE);
621 }
622 else{
623 #endif
624 if(size < (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE))
625 return false;
626
627 memcpy(data, palmRam, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
628 swap16BufferIfLittle(data, (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE) / sizeof(uint16_t));
629 #if defined(EMU_SUPPORT_PALM_OS5)
630 }
631 #endif
632
633 return true;
634 }
635
emulatorLoadRam(uint8_t * data,uint32_t size)636 bool emulatorLoadRam(uint8_t* data, uint32_t size){
637 #if defined(EMU_SUPPORT_PALM_OS5)
638 if(palmEmulatingTungstenT3){
639 if(size < TUNGSTEN_T3_RAM_SIZE)
640 return false;
641
642 memcpy(palmRam, data, TUNGSTEN_T3_RAM_SIZE);
643 }
644 else{
645 #endif
646 if(size < (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE))
647 return false;
648
649 memcpy(palmRam, data, palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE);
650 swap16BufferIfLittle(palmRam, (palmEmulatingM500 ? M500_RAM_SIZE : M515_RAM_SIZE) / sizeof(uint16_t));
651 #if defined(EMU_SUPPORT_PALM_OS5)
652 }
653 #endif
654
655 return true;
656 }
657
emulatorInsertSdCard(uint8_t * data,uint32_t size,sd_card_info_t * sdInfo)658 uint32_t emulatorInsertSdCard(uint8_t* data, uint32_t size, sd_card_info_t* sdInfo){
659 //from the no name SD card that came instered in my test device
660 static const sd_card_info_t defaultSdInfo = {
661 {0x00, 0x2F, 0x00, 0x32, 0x5F, 0x59, 0x83, 0xB8, 0x6D, 0xB7, 0xFF, 0x9F, 0x96, 0x40, 0x00, 0x00},//csd
662 {0x1D, 0x41, 0x44, 0x53, 0x44, 0x20, 0x20, 0x20, 0x10, 0xA0, 0x50, 0x33, 0xA4, 0x00, 0x81, 0x00},//cid
663 {0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//scr
664 0x01FF8000,//ocr
665 false//writeProtectSwitch
666 };
667
668 //SD card is currently inserted
669 if(palmSdCard.flashChipData)
670 return EMU_ERROR_RESOURCE_LOCKED;
671
672 //no 0 sized chips, max out at 2gb SD card, Palms cant handle higher than that anyway because of incompatibility with FAT32 and SDHC
673 if(size == 0x00000000 || size > 0x20000000)
674 return EMU_ERROR_INVALID_PARAMETER;
675
676 //add SD_CARD_BLOCK_SIZE to buffer to prevent buffer overflows
677 palmSdCard.flashChipSize = size;
678 palmSdCard.flashChipData = malloc(palmSdCard.flashChipSize + SD_CARD_BLOCK_SIZE);
679 if(!palmSdCard.flashChipData){
680 palmSdCard.flashChipSize = 0x00000000;
681 return EMU_ERROR_OUT_OF_MEMORY;
682 }
683
684 //copy over buffer data
685 if(data)
686 memcpy(palmSdCard.flashChipData, data, size);
687 else
688 memset(palmSdCard.flashChipData, 0x00, size);
689
690 //clear the padding block
691 memset(palmSdCard.flashChipData + palmSdCard.flashChipSize, 0x00, SD_CARD_BLOCK_SIZE);
692
693 //reinit SD card
694 if(sdInfo)
695 palmSdCard.sdInfo = *sdInfo;
696 else
697 palmSdCard.sdInfo = defaultSdInfo;
698 sdCardReset();
699
700 return EMU_ERROR_NONE;
701 }
702
emulatorGetSdCardSize(void)703 uint32_t emulatorGetSdCardSize(void){
704 if(!palmSdCard.flashChipData)
705 return 0;
706
707 return palmSdCard.flashChipSize;
708 }
709
emulatorGetSdCardData(uint8_t * data,uint32_t size)710 uint32_t emulatorGetSdCardData(uint8_t* data, uint32_t size){
711 if(!palmSdCard.flashChipData)
712 return EMU_ERROR_RESOURCE_LOCKED;
713
714 if(size < palmSdCard.flashChipSize)
715 return EMU_ERROR_OUT_OF_MEMORY;
716
717 memcpy(data, palmSdCard.flashChipData, palmSdCard.flashChipSize);
718
719 return EMU_ERROR_NONE;
720 }
721
emulatorEjectSdCard(void)722 void emulatorEjectSdCard(void){
723 //clear SD flash chip, this disables the SD card control chip too
724 if(palmSdCard.flashChipData){
725 free(palmSdCard.flashChipData);
726 palmSdCard.flashChipData = NULL;
727 palmSdCard.flashChipSize = 0x00000000;
728 }
729 }
730
emulatorRunFrame(void)731 void emulatorRunFrame(void){
732 uint16_t index;
733
734 #if defined(EMU_SUPPORT_PALM_OS5)
735 if(palmEmulatingTungstenT3){
736 pxa260Execute(true);
737
738 /*
739 //backlight level, 0% = 1/4 color intensity, 50% = 1/2 color intensity, 100% = full color intensity
740 switch(palmMisc.backlightLevel){
741 case 0:
742 MULTITHREAD_LOOP(index) for(index = 0; index < 320 * 480; index++){
743 palmFramebuffer[index] >>= 2;
744 palmFramebuffer[index] &= 0x39E7;
745 }
746 break;
747
748 case 50:
749 MULTITHREAD_LOOP(index) for(index = 0; index < 320 * 480; index++){
750 palmFramebuffer[index] >>= 1;
751 palmFramebuffer[index] &= 0x7BEF;
752 }
753 break;
754
755 case 100:
756 //nothing
757 break;
758
759 default:
760 //TODO: the T3 supports full range backlight intensity, need to calculate the value here
761 debugLog("Unsupported backlight value\n");
762 break;
763 }
764 */
765 }
766 else{
767 #endif
768 //CPU
769 dbvzExecute();
770
771 //LCD controller
772 if(palmEmulatingM500){
773 dbvzLcdRender();
774
775 if(palmMisc.backlightLevel == 100){
776 MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
777 uint16_t greenChannel = (palmFramebuffer[index] & 0x07E0) + 0x00C0;
778 palmFramebuffer[index] = palmFramebuffer[index] & 0xF81F | FAST_MIN(greenChannel, 0x07E0);
779 }
780 }
781 }
782 else{
783 sed1376Render();
784
785 //backlight level, 0% = 1/4 color intensity, 50% = 1/2 color intensity, 100% = full color intensity
786 switch(palmMisc.backlightLevel){
787 case 0:
788 MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
789 palmFramebuffer[index] >>= 2;
790 palmFramebuffer[index] &= 0x39E7;
791 }
792 break;
793
794 case 50:
795 MULTITHREAD_LOOP(index) for(index = 0; index < 160 * 160; index++){
796 palmFramebuffer[index] >>= 1;
797 palmFramebuffer[index] &= 0x7BEF;
798 }
799 break;
800
801 case 100:
802 //nothing
803 break;
804
805 default:
806 debugLog("Invalid backlight value\n");
807 break;
808 }
809 }
810
811 #if defined(EMU_SUPPORT_PALM_OS5)
812 }
813 #endif
814 }
815
emulatorSkipFrame(void)816 void emulatorSkipFrame(void){
817 //runs frame without rendering the screen
818 #if defined(EMU_SUPPORT_PALM_OS5)
819 if(palmEmulatingTungstenT3){
820 pxa260Execute(false);
821 }
822 else{
823 #endif
824 //CPU
825 dbvzExecute();
826
827 //LCD controller, skip this
828 #if defined(EMU_SUPPORT_PALM_OS5)
829 }
830 #endif
831 }
832