UtilRetro.cpp 7.15 KB
Newer Older
kode54's avatar
kode54 committed
1
2
3
4
5
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "NLS.h"
6
#include "System.h"
kode54's avatar
kode54 committed
7
#include "Util.h"
8
#include "common/Port.h"
retro-wertz's avatar
retro-wertz committed
9
#include "common/ConfigManager.h"
kode54's avatar
kode54 committed
10
11
12
13
14
15
#include "gba/Flash.h"
#include "gba/GBA.h"
#include "gba/Globals.h"
#include "gba/RTC.h"

#include "gb/gbGlobals.h"
16
#include "gba/gbafilter.h"
kode54's avatar
kode54 committed
17
18

#ifndef _MSC_VER
19
#include <strings.h>
kode54's avatar
kode54 committed
20
21
22
#define _stricmp strcasecmp
#endif // ! _MSC_VER

23
// Because Configmanager was introduced, this has to be done.
retro-wertz's avatar
retro-wertz committed
24
25
26
27
28
29
30
31
int  rtcEnabled          = 0;
int  cpuDisableSfx       = 0;
int  skipBios            = 0;
int  saveType            = 0;
int  cpuSaveType         = 0;
int  skipSaveGameBattery = 0;
int  skipSaveGameCheats  = 0;
int  useBios             = 0;
32
int  cheatsEnabled       = 0;
retro-wertz's avatar
retro-wertz committed
33
34
35
36
37
38
39
int  layerSettings       = 0xff00;
int  layerEnable         = 0xff00;
bool speedup             = false;
bool parseDebug          = false;
bool speedHack           = false;
bool mirroringEnable     = false;
bool cpuIsMultiBoot      = false;
40
41
42
43

const char* loadDotCodeFile;
const char* saveDotCodeFile;

retro-wertz's avatar
retro-wertz committed
44
45
46
47
extern int systemColorDepth;
extern int systemRedShift;
extern int systemGreenShift;
extern int systemBlueShift;
48

kode54's avatar
kode54 committed
49
50
51
extern uint16_t systemColorMap16[0x10000];
extern uint32_t systemColorMap32[0x10000];

retro-wertz's avatar
retro-wertz committed
52
53
54
55
56
57
58
59
60
61
62
63
const char gb_image_header[] =
{
   static_cast<const char>
   (
      0xce, 0xed, 0x66, 0x66, 0xcc, 0x0d, 0x00, 0x0b, 0x03, 0x73, 0x00,
      0x83, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x08, 0x11, 0x1f, 0x88, 0x89,
      0x00, 0x0e, 0xdc, 0xcc, 0x6e, 0xe6, 0xdd, 0xdd, 0xd9, 0x99, 0xbb,
      0xbb, 0x67, 0x63, 0x6e, 0x0e, 0xec, 0xcc, 0xdd, 0xdc, 0x99, 0x9f,
      0xbb, 0xb9, 0x33, 0x3e
   )
};

64
bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix)
kode54's avatar
kode54 committed
65
{
66
    return false;
kode54's avatar
kode54 committed
67
68
}

69
void utilPutDword(uint8_t* p, uint32_t value)
kode54's avatar
kode54 committed
70
{
71
72
73
74
    *p++ = value & 255;
    *p++ = (value >> 8) & 255;
    *p++ = (value >> 16) & 255;
    *p = (value >> 24) & 255;
kode54's avatar
kode54 committed
75
76
}

77
void utilPutWord(uint8_t* p, uint16_t value)
kode54's avatar
kode54 committed
78
{
79
80
    *p++ = value & 255;
    *p = (value >> 8) & 255;
kode54's avatar
kode54 committed
81
82
}

83
bool utilWriteBMPFile(const char* fileName, int w, int h, uint8_t* pix)
kode54's avatar
kode54 committed
84
{
85
    return false;
kode54's avatar
kode54 committed
86
87
88
89
}

extern bool cpuIsMultiBoot;

90
bool utilIsGBAImage(const char* file)
kode54's avatar
kode54 committed
91
{
92
93
94
95
96
97
98
99
100
101
102
103
    cpuIsMultiBoot = false;
    if (strlen(file) > 4) {
        const char* p = strrchr(file, '.');

        if (p != NULL) {
            if ((_stricmp(p, ".agb") == 0) || (_stricmp(p, ".gba") == 0) || (_stricmp(p, ".bin") == 0) || (_stricmp(p, ".elf") == 0))
                return true;
            if (_stricmp(p, ".mb") == 0) {
                cpuIsMultiBoot = true;
                return true;
            }
        }
kode54's avatar
kode54 committed
104
105
    }

106
    return false;
kode54's avatar
kode54 committed
107
108
}

109
bool utilIsGBImage(const char* file)
kode54's avatar
kode54 committed
110
{
111
112
113
	FILE *fp;
	bool ret = false;
	char buffer[47];
retro-wertz's avatar
retro-wertz committed
114
	if (!file || !(fp = fopen (file, "r")))		//TODO more checks here (does file exist, is it a file, a symlink or a blockdevice)
115
116
117
118
119
120
121
122
123
		return ret;
	fseek (fp, 0, SEEK_END);
	if (ftell (fp) >= 0x8000) {			//afaik there can be no gb-rom smaller than this
		fseek (fp, 0x104, SEEK_SET);
		fread (buffer, sizeof (char), 47, fp);
		ret = !memcmp (buffer, gb_image_header, 47);
	}
	fclose (fp);
	return ret;
kode54's avatar
kode54 committed
124
125
126
}

// strip .gz or .z off end
127
void utilStripDoubleExtension(const char* file, char* buffer)
kode54's avatar
kode54 committed
128
{
129
130
    if (buffer != file) // allows conversion in place
        strcpy(buffer, file);
kode54's avatar
kode54 committed
131
132
}

133
static bool utilIsImage(const char* file)
kode54's avatar
kode54 committed
134
{
135
    return utilIsGBAImage(file) || utilIsGBImage(file);
kode54's avatar
kode54 committed
136
137
}

138
IMAGE_TYPE utilFindType(const char* file)
kode54's avatar
kode54 committed
139
{
retro-wertz's avatar
retro-wertz committed
140
    //char buffer[2048];
141
142
143
144
145
    if (!utilIsImage(file)) // TODO: utilIsArchive() instead?
    {
        return IMAGE_UNKNOWN;
    }
    return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
kode54's avatar
kode54 committed
146
147
148
149
}

static int utilGetSize(int size)
{
Zach Bacon's avatar
Zach Bacon committed
150
151
152
153
  int res = 1;
  while(res < size)
    res <<= 1;
  return res;
kode54's avatar
kode54 committed
154
155
}

Zach Bacon's avatar
Zach Bacon committed
156
uint8_t *utilLoad(const char *file, bool (*accept)(const char *), uint8_t *data, int &size)
kode54's avatar
kode54 committed
157
{
Zach Bacon's avatar
Zach Bacon committed
158
	FILE *fp = NULL;
retro-wertz's avatar
retro-wertz committed
159
	//char *buf = NULL;
Zach Bacon's avatar
Zach Bacon committed
160
161

	fp = fopen(file,"rb");
retro-wertz's avatar
retro-wertz committed
162
	if(!fp) return NULL;
Zach Bacon's avatar
Zach Bacon committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
	fseek(fp, 0, SEEK_END); //go to end
	size = ftell(fp); // get position at end (length)
	rewind(fp);

	uint8_t *image = data;
	if(image == NULL)
	{
		//allocate buffer memory if none was passed to the function
		image = (uint8_t *)malloc(utilGetSize(size));
		if(image == NULL)
		{
			systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
					"data");
			return NULL;
		}
	}

   fread(image, 1, size, fp); // read into buffer
	fclose(fp);
	return image;
kode54's avatar
kode54 committed
183
184
}

Zach Bacon's avatar
Zach Bacon committed
185
void utilGBAFindSave(const uint8_t *data, const int size)
kode54's avatar
kode54 committed
186
{
Zach Bacon's avatar
Zach Bacon committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  uint32_t *p = (uint32_t *)data;
  uint32_t *end = (uint32_t *)(data + size);
  int saveType = 0;
  int flashSize = 0x10000;
  bool rtcFound = false;

  while(p  < end) {
    uint32_t d = READ32LE(p);

    if(d == 0x52504545) {
      if(memcmp(p, "EEPROM_", 7) == 0) {
        if(saveType == 0)
          saveType = 3;
      }
    } else if (d == 0x4D415253) {
      if(memcmp(p, "SRAM_", 5) == 0) {
        if(saveType == 0)
          saveType = 1;
      }
    } else if (d == 0x53414C46) {
      if(memcmp(p, "FLASH1M_", 8) == 0) {
        if(saveType == 0) {
          saveType = 2;
          flashSize = 0x20000;
kode54's avatar
kode54 committed
211
        }
Zach Bacon's avatar
Zach Bacon committed
212
213
214
215
216
217
218
219
220
      } else if(memcmp(p, "FLASH", 5) == 0) {
        if(saveType == 0) {
          saveType = 2;
          flashSize = 0x10000;
        }
      }
    } else if (d == 0x52494953) {
      if(memcmp(p, "SIIRTC_V", 8) == 0)
        rtcFound = true;
kode54's avatar
kode54 committed
221
    }
Zach Bacon's avatar
Zach Bacon committed
222
223
224
225
226
227
228
229
230
231
    p++;
  }
  // if no matches found, then set it to NONE
  if(saveType == 0) {
    saveType = 5;
  }

  rtcEnable(rtcFound);
  cpuSaveType = saveType;
  flashSetSize(flashSize);
kode54's avatar
kode54 committed
232
233
234
235
}

void utilUpdateSystemColorMaps(bool lcd)
{
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    switch (systemColorDepth) {
    case 16: {
        for (int i = 0; i < 0x10000; i++) {
            systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | (((i & 0x3e0) >> 5) << systemGreenShift) | (((i & 0x7c00) >> 10) << systemBlueShift);
        }
        if (lcd)
            gbafilter_pal(systemColorMap16, 0x10000);
    } break;
    case 24:
    case 32: {
        for (int i = 0; i < 0x10000; i++) {
            systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | (((i & 0x3e0) >> 5) << systemGreenShift) | (((i & 0x7c00) >> 10) << systemBlueShift);
        }
        if (lcd)
            gbafilter_pal32(systemColorMap32, 0x10000);
    } break;
kode54's avatar
kode54 committed
252
253
254
255
    }
}

// Check for existence of file.
256
bool utilFileExists(const char* filename)
kode54's avatar
kode54 committed
257
{
258
259
260
261
262
263
264
    FILE* f = fopen(filename, "r");
    if (f == NULL) {
        return false;
    } else {
        fclose(f);
        return true;
    }
kode54's avatar
kode54 committed
265
266
267
}

// Not endian safe, but VBA itself doesn't seem to care, so hey <_<
268
void utilWriteIntMem(uint8_t*& data, int val)
kode54's avatar
kode54 committed
269
{
270
271
    memcpy(data, &val, sizeof(int));
    data += sizeof(int);
kode54's avatar
kode54 committed
272
273
}

274
void utilWriteMem(uint8_t*& data, const void* in_data, unsigned size)
kode54's avatar
kode54 committed
275
{
276
277
    memcpy(data, in_data, size);
    data += size;
kode54's avatar
kode54 committed
278
279
}

280
void utilWriteDataMem(uint8_t*& data, variable_desc* desc)
kode54's avatar
kode54 committed
281
{
282
283
284
285
    while (desc->address) {
        utilWriteMem(data, desc->address, desc->size);
        desc++;
    }
kode54's avatar
kode54 committed
286
287
}

288
int utilReadIntMem(const uint8_t*& data)
kode54's avatar
kode54 committed
289
{
290
291
292
293
    int res;
    memcpy(&res, data, sizeof(int));
    data += sizeof(int);
    return res;
kode54's avatar
kode54 committed
294
295
}

296
void utilReadMem(void* buf, const uint8_t*& data, unsigned size)
kode54's avatar
kode54 committed
297
{
298
299
    memcpy(buf, data, size);
    data += size;
kode54's avatar
kode54 committed
300
301
}

302
void utilReadDataMem(const uint8_t*& data, variable_desc* desc)
kode54's avatar
kode54 committed
303
{
304
305
306
307
    while (desc->address) {
        utilReadMem(desc->address, data, desc->size);
        desc++;
    }
kode54's avatar
kode54 committed
308
}