diff --git a/src/Brunni/VirtualFile.c b/src/Brunni/VirtualFile.c new file mode 100644 index 00000000..d4c583c7 --- /dev/null +++ b/src/Brunni/VirtualFile.c @@ -0,0 +1,353 @@ +#include "common.h" + +/* + Note: seek ne retourne plus rien! +*/ + +VIRTUAL_FILE_SOURCE *VirtualFileSources[VF_MAX_SOURCES]; +int VirtualFileSourcesNb = 0; +int VF_MEMORY = -1; +//List of files for RAM based devices +OSL_VIRTUALFILENAME *osl_virtualFileList; +//Number of entries +int osl_virtualFileListNumber = 0; +//For system use +int osl_virtualFileListSize; +int osl_defaultVirtualFileSource = -1; +const char *osl_tempFileName = "*tmp*"; +OSL_VIRTUALFILENAME osl_tempFile; + +#define DEFAULT_TABLE_SIZE 128 + + +//Enregistre une nouvelle source +int VirtualFileRegisterSource(VIRTUAL_FILE_SOURCE *vfs) { + //Espace libre? + if (VirtualFileSourcesNb >= VF_MAX_SOURCES) + return -1; + //Ajoute la source + VirtualFileSources[VirtualFileSourcesNb] = vfs; + return VirtualFileSourcesNb++; +} + +VIRTUAL_FILE *VirtualFileOpen(void *param1, int param2, int type, int mode) { + VIRTUAL_FILE *f = NULL; + if (type == VF_AUTO) { + if (param2 == 0) { + OSL_VIRTUALFILENAME *file = oslFindFileInVirtualFilenameList((const char*)param1, type); + if (file) { + param1 = file->data; + param2 = file->size; + type = *file->type; + } + else + type = osl_defaultVirtualFileSource; + } + } + + if (type >= 0) { + f = (VIRTUAL_FILE*)malloc(sizeof(*f)); + if (f) { + memset(f, 0, sizeof(*f)); + f->type = type; + if (!VirtualFileGetSource(f)->fOpen(param1, param2, type, mode, f)) { + free(f); + f = NULL; + } + } + } + return f; +} + +int VirtualFileClose(VIRTUAL_FILE *f) { + int result = VirtualFileGetSource(f)->fClose(f); + if (result) + free(f); + return result; +} + +/* + SOURCE 1 par défaut: Mémoire +*/ + +int vfsMemOpen(void *param1, int param2, int type, int mode, VIRTUAL_FILE* f) { + //Tous les modes sont supportés mais pas très bien pour l'instant, ne vous amusez pas à écrire et lire en même temps +// if (mode != VF_O_READ || mode != VK_O_WRITE) +// return 0; + + //C'est un nom de fichier? + if (param2 == 0) { + OSL_VIRTUALFILENAME *file = oslFindFileInVirtualFilenameList((const char*)param1, type); + if (file) { + param1 = file->data; + param2 = file->size; + } + } + + //Initialisation du bloc mémoire + f->offset = 0; + f->ioPtr = param1; + f->maxSize = param2; + return 1; +} + +int vfsMemClose(VIRTUAL_FILE *f) { + return 1; +} + +int vfsMemWrite(const void *ptr, size_t size, size_t n, VIRTUAL_FILE* f) { + int realSize = size * n, writeSize = 0; + if (f->ioPtr) { + //Débordement? + writeSize = oslMin(realSize, f->maxSize - f->offset); + if (writeSize > 0) { + memcpy((char*)f->ioPtr + f->offset, ptr, writeSize); + //Brunni: ??? this is probably wrong ??? (08.07.2007) +// f->offset += realSize; + f->offset += writeSize; + } + } + return writeSize; +} + +int vfsMemRead(void *ptr, size_t size, size_t n, VIRTUAL_FILE* f) { + int readSize = 0, realSize = size * n; + + if (f->ioPtr) { + //min => pour éviter les débordements + readSize = oslMin(realSize, f->maxSize - f->offset); + if (readSize > 0) { + memcpy(ptr, (char*)f->ioPtr + f->offset, readSize); + //Brunni: Removed (08.07.2007) +// f->offset += realSize; + f->offset += readSize; + } + } + return readSize; +} + +int vfsMemGetc(VIRTUAL_FILE *f) { + unsigned char car; + //Pour la sécurité, quand même un cas à part pour les fichiers + if (VirtualFileRead(&car, sizeof(car), 1, f) < 1) + return -1; + else + return (int)car; +} + +int vfsMemPutc(int caractere, VIRTUAL_FILE *f) { + unsigned char car = caractere; + if (VirtualFileWrite(&car, sizeof(car), 1, f) < 1) + return -1; + else + return caractere; +} + +char *vfsMemGets(char *str, int maxLen, VIRTUAL_FILE *f) { + const int blockSize = 16; + int offset = 0, i, size; + while(1) { + size = VirtualFileRead(str + offset, 1, oslMin(maxLen - offset, blockSize), f); + if (offset + size < maxLen) + str[offset + size] = 0; + for (i=offset;i= offset + blockSize) { + char temp[1]; + int tempSize; + tempSize = VirtualFileRead(temp, 1, 1, f); + //Prochain caractère est un \n? + if (!(tempSize > 0 && temp[0] == '\n')) + //Sinon on annule + i--; + } + else { + if (str[i + 1] == '\n') + i++; + } + //Retourne le pointeur + VirtualFileSeek(f, -size + (i - offset) + 1, SEEK_CUR); + return str; + } + else if (str[i] == '\n') { + str[i] = 0; + //ATTENTION: MODIFIE DE -blockSize + i à -blockSize + i + 1, à vérifier!!! + VirtualFileSeek(f, -blockSize + i + 1, SEEK_CUR); + //Retourne le pointeur + return str; + } + } + offset += blockSize; + } + return str; +} + +void vfsMemPuts(const char *s, VIRTUAL_FILE *f) { + VirtualFileWrite(s, strlen(s), 1, f); +} + +void vfsMemSeek(VIRTUAL_FILE *f, int offset, int whence) { +// int oldOffset = f->offset; + if (f->ioPtr) { + if (whence == SEEK_SET) + f->offset = offset; + else if (whence == SEEK_CUR) + f->offset += offset; + else if (whence == SEEK_END) + f->offset = f->maxSize + offset; + f->offset = oslMax(oslMin(f->offset, f->maxSize), 0); + } +// return oldOffset; +} + +int vfsMemTell(VIRTUAL_FILE *f) { + return f->offset; +} + +int vfsMemEof(VIRTUAL_FILE *f) { + return (f->offset < f->maxSize); +} + +VIRTUAL_FILE_SOURCE vfsMemory = { + vfsMemOpen, + vfsMemClose, + vfsMemRead, + vfsMemWrite, + vfsMemGetc, + vfsMemPutc, + vfsMemGets, + vfsMemPuts, + vfsMemSeek, + vfsMemTell, + vfsMemEof, +}; + +//Définit la liste de fichiers pour les sources basées sur la mémoire +/*void oslSetVirtualFilenameList(OSL_VIRTUALFILENAME *vfl, int numberOfEntries) { + osl_virtualFileList = vfl; + osl_virtualFileListNumber = numberOfEntries; +}*/ + +//Adds files to the list +int oslAddVirtualFileList(OSL_VIRTUALFILENAME *vfl, int numberOfEntries) { + //Need to allocate more? + if (numberOfEntries + osl_virtualFileListNumber > osl_virtualFileListSize) { + int finalSize = numberOfEntries + osl_virtualFileListNumber; + OSL_VIRTUALFILENAME *v; + //Align (we are only reallocating this by blocks of DEFAULT_TABLE_SIZE) + if (finalSize % DEFAULT_TABLE_SIZE > 0) + finalSize = finalSize - finalSize % DEFAULT_TABLE_SIZE + DEFAULT_TABLE_SIZE; + v = (OSL_VIRTUALFILENAME*)realloc(osl_virtualFileList, finalSize * sizeof(OSL_VIRTUALFILENAME)); + if (v) { + osl_virtualFileList = v; + osl_virtualFileListSize = finalSize; + } + else + //Failed + return 0; + } + //Copy the new entries + memcpy(osl_virtualFileList + osl_virtualFileListNumber, vfl, numberOfEntries * sizeof(OSL_VIRTUALFILENAME)); + osl_virtualFileListNumber += numberOfEntries; + return 1; +} + +void oslRemoveVirtualFileList(OSL_VIRTUALFILENAME *vfl, int numberOfEntries) { + int i; + for (i=0;i<=osl_virtualFileListNumber-numberOfEntries;i++) { + //Try to find it in the list + if (!memcmp(osl_virtualFileList + i, vfl, numberOfEntries * sizeof(OSL_VIRTUALFILENAME))) { + //Décale le tout + if (osl_virtualFileListNumber - i - numberOfEntries > 0) + memmove(osl_virtualFileList + i, osl_virtualFileList + i + numberOfEntries, osl_virtualFileListNumber - i - numberOfEntries); + osl_virtualFileListNumber -= numberOfEntries; + } + } +} + + +OSL_VIRTUALFILENAME *oslFindFileInVirtualFilenameList(const char *fname, int type) { + int i; + OSL_VIRTUALFILENAME *file; + if (fname) { + //Skip the first / that means root for libFat + if (fname[0] == '/') + fname++; + for (i=-1;i impossible + if (!file->type) + continue; + //Compare the type and the file name + if ((type == *file->type || type == VF_AUTO) + && !strcmp(fname, file->name)) + return file; + } + } + return NULL; +} + +void VirtualFileInit() { + //On enregistre les sources par défaut + if (VF_MEMORY < 0) + VF_MEMORY = VirtualFileRegisterSource(&vfsMemory); + if (VF_FILE < 0) + VF_FILE = oslInitVfsFile(); + //By default, load from files + oslSetDefaultVirtualFileSource(VF_FILE); + + //Allocate data for the virtual file list + osl_virtualFileListSize = DEFAULT_TABLE_SIZE; + osl_virtualFileListNumber = 0; + //I suppose it never fails + osl_virtualFileList = (OSL_VIRTUALFILENAME*)malloc(DEFAULT_TABLE_SIZE * sizeof(OSL_VIRTUALFILENAME)); + + osl_tempFile.name = osl_tempFileName; + osl_tempFile.type = NULL; +} + +//Par blocs de 4 ko +#define BLOCK_SIZE (4 << 10) + +//Lit un fichier entier vers la mémoire +void *oslReadEntireFileToMemory(VIRTUAL_FILE *f, int *fileSize) { + void *block = NULL; + int add = 0; + int size = 0, readSize, finalSize = 0; + + do { + size += BLOCK_SIZE; + if (block) + block = realloc(block, size); + else + block = malloc(size); + + //L'allocation a échoué? + if (!block) + return NULL; + + readSize = VirtualFileRead((char*)block + add, 1, BLOCK_SIZE, f); + add += BLOCK_SIZE; + finalSize += readSize; + } while (readSize >= BLOCK_SIZE); + + if (fileSize) + *fileSize = finalSize; + return block; +} + +void oslSetTempFileData(void *data, int size, int *type) { + osl_tempFile.data = data; + osl_tempFile.size = size; + osl_tempFile.type = type; +} + diff --git a/src/Brunni/VirtualFile.h b/src/Brunni/VirtualFile.h new file mode 100644 index 00000000..5b0add18 --- /dev/null +++ b/src/Brunni/VirtualFile.h @@ -0,0 +1,360 @@ +/*! \file VirtualFile.h + \brief + Virtual File support for Oldschool Library. + This API is meant to be an universal mean to manipulate every file source possible as you can define your own. +*/ + +#ifndef __OSL_VIRTUALFILE_H__ +#define __OSL_VIRTUALFILE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @defgroup virtualfile Virtual Files + + Virtual File support for OSLib. + This API is meant to be an universal mean to manipulate every file source possible as you can define your own. + @{ +*/ + +/** Virtual File type. */ +typedef struct { + void *ioPtr; //!< User data for IO processing (usually a pointer to data, FILE*, usw.) + unsigned short type; //!< Virtual file type (source number). + unsigned long userData; //!< Additional data + int offset, maxSize; //!< Internal variables for memory-based (RAM / ROM) sources +} VIRTUAL_FILE; + +/** Enumeration describing the available file open modes. Please note that some sources do not support some modes like READWRITE or WRITE, in +this case they'll fail when an attempt to open a file in one of these modes is made. The resulting file returned by VirtualFileOpen will be NULL. */ +enum VF_OPEN_MODES { + VF_O_READ, //!< Read only + VF_O_READWRITE, //!< Read & Write + VF_O_WRITE //!< Write only +}; +//enum {SEEK_SET, SEEK_CUR, SEEK_END}; + +/** Structure of a Virtual File Source. */ +typedef struct { + /** + Open a file. + + Return 1 if anything went well, or 0 to throw an error (the opening will be cancelled and NULL will be returned to the user). + */ + int (*fOpen)(void *param1, int param2, int type, int mode, VIRTUAL_FILE* f); + + /** + Close a file. + + Return 1 if anything went well, 0 to throw an error. + */ + int (*fClose)(VIRTUAL_FILE *f); + + /** + Read in a file. + + Returns the number of bytes effectively read. + */ + int (*fRead)(void *ptr, size_t size, size_t n, VIRTUAL_FILE* f); + + /** + Write in a file + + Returns the number of bytes effectively written. + */ + int (*fWrite)(const void *ptr, size_t size, size_t n, VIRTUAL_FILE* f); + + /** + Read a single character. + + Returns the next character (byte) in the file. + */ + int (*fGetc)(VIRTUAL_FILE *f); + + /** + Write a single character + + Writes a single character. Returns the character value if anything went well, -1 else. + */ + int (*fPutc)(int caractere, VIRTUAL_FILE *f); + + /** + Read a string + + Reads a string to the buffer pointed to by str, of a maximum size of maxLen. Returns a pointer to the read string (str in general). + Reading stops to the next carriage return found (\\n). The routine should handle correctly the following sequences by reading them + entirely: \\r, \\r\\n, \\n. If a \\r is found, you should read the following byte and rewind one byte behind if it's not a \\n. + If you cannot afford a rewind, then keep the next character in cache and return it to the next read. + */ + char* (*fGets)(char *str, int maxLen, VIRTUAL_FILE *f); + + /** + Write a string + + Writes an entire string to the file. + */ + void (*fPuts)(const char *s, VIRTUAL_FILE *f); + + /** + Moving in the file + + Sets the current file position and returns the old one. The whence parameter uses the same values as stdio (SEEK_SET, SEEK_CUR, SEEK_END). + */ + void (*fSeek)(VIRTUAL_FILE *f, int offset, int whence); + + /** + Get current file position + + Returns the current pointer position in the file. You can then use VirtualFileSeek(f, position, SEEK_SET) to return to it. + */ + int (*fTell)(VIRTUAL_FILE *f); + + /** + End of file + + Returns true (1) if it's the end of the file, false (0) else. + */ + int (*fEof)(VIRTUAL_FILE *f); + +} VIRTUAL_FILE_SOURCE; + +/** Virtual file list item. Used for RAM based devices. */ +typedef struct { + const char *name; //!< Virtual file name + void *data; //!< RAM data block + int size; //!< Block data size + int *type; //!< Associated source (e.g. &VF_MEMORY). Don't forget the &, which is there so you can pass a variable which is not known at compile time (virtual file sources are registered upon start, so the compiler doesn't know the ID it will be given in advance). +} OSL_VIRTUALFILENAME; + +/** Initializes the virtual filesystem. Done by default by OSLib, so there is no need to call it by yourself. */ +void VirtualFileInit(); + +/** Open a new file. + \param param1 + Pointer to a string representing the file name. + \param type + File type. By default, can be: + - VF_MEMORY: read/write from a memory block + - VF_FILE: read from standard stdio routines. + \param mode + One of VF_OPEN_MODES. +*/ +VIRTUAL_FILE *VirtualFileOpen(void *param1, int param2, int type, int mode); +/** Closes an open file. */ +int VirtualFileClose(VIRTUAL_FILE *f); + + +/** @defgroup virtualfile_io I/O routines + + Routines for reading / writing to a virtual file. Make sure to check the Virtual File main page to know how to open files, etc. + @{ +*/ + +/** Writes in a file and returns the number of bytes effectively written. */ +#define VirtualFileWrite(ptr, size, n, f) (VirtualFileGetSource(f)->fWrite(ptr, size, n, f)) +/** Reads in a file and returns the number of bytes effectively read. */ +#define VirtualFileRead(ptr, size, n, f) (VirtualFileGetSource(f)->fRead(ptr, size, n, f)) +/** Reads a single character. Returns the next character (byte) in the file. */ +#define VirtualFileGetc(f) (VirtualFileGetSource(f)->fGetc(f)) +/** Writes a single character. Returns the character value if anything went well, -1 else. */ +#define VirtualFilePutc(caractere, f) (VirtualFileGetSource(f)->fPutc(caractere, f)) +/** Reads a string to the buffer pointed to by str, of a maximum size of maxLen. Returns a pointer to the read string (str in general). + +Reading stops to the next carriage return found (\\n, \\r\\n or \\r), supporting files created by every OS (I think). */ +#define VirtualFileGets(str, maxLen, f) (VirtualFileGetSource(f)->fGets(str, maxLen, f)) +/** Writes a string to the file. */ +#define VirtualFilePuts(s, f) (VirtualFileGetSource(f)->fPuts(s, f)) +/** Sets the current file position and returns the old one. The whence parameter uses the same values as stdio (SEEK_SET, SEEK_CUR, SEEK_END). */ +#define VirtualFileSeek(f, offset, whence) (VirtualFileGetSource(f)->fSeek(f, offset, whence)) +/** Returns the current file pointer. */ +#define VirtualFileTell(f) (VirtualFileGetSource(f)->fTell(f)) +/** Returns true (1) if it's the end of the file, false (0) else. */ +#define VirtualFileEof(f) (VirtualFileGetSource(f)->fEof(f)) + +/** @} */ // end of virtualfile_io + + +/** Adds a new file source to the virtual file system. + + \param vfs + Must be a pointer to a valid VIRTUAL_FILE_SOURCE interface containing all your functions for handling the file source. + \return + Returns the identifier of your source or -1 if it has failed. You can then use this ID as a file type (parameter for VirtualFileOpen). */ +int VirtualFileRegisterSource(VIRTUAL_FILE_SOURCE *vfs); + +/* UNSUPPORTED! SEE oslAddVirtualFileList INSTEAD! + + Registers a file list for RAM based devices (such as VF_MEMORY). + \param vfl + List of files (each file is a UL_VIRTUALFILENAME item) +*/ +//void oslSetVirtualFilenameList(OSL_VIRTUALFILENAME *vfl, int numberOfEntries); + +/** Call this function in your virtual file source OPEN handler, if it's a RAM based device and param2 == 0 (means null size, impossible). +It will return a UL_VIRTUALFILENAME where you can get a pointer to the data and their size. Note that the return value can be NULL if the file has not been found or an error occured (e.g. fname is NULL). */ +OSL_VIRTUALFILENAME *oslFindFileInVirtualFilenameList(const char *fname, int type); + +//Maximum number of sources +#define VF_MAX_SOURCES 16 +//Gets a pointer to the virtual file source associated to a file +#define VirtualFileGetSource(vf) (VirtualFileSources[(vf)->type]) +//List of virtual file sources +extern VIRTUAL_FILE_SOURCE *VirtualFileSources[VF_MAX_SOURCES]; +extern int VirtualFileSourcesNb; +extern OSL_VIRTUALFILENAME *osl_virtualFileList; +extern int osl_virtualFileListNumber; +extern int osl_defaultVirtualFileSource; +extern const char *osl_tempFileName; + +/** Reads an entire file to memory and returns a pointer to the memory block. The block memory usage is stepped by 4 kB, so even a 1 kB file will take 16 kB, so this function is not recommended for opening a lot of small files. The bloc must be freed (using free) once you've finished with it! + \param f + Pointer to an open virtual file. + \param size + Pointer to an integer that will contain the number of bytes read from the file. Can be NULL (in this case the value is discarded). + +\code +int size; +VIRTUAL_FILE *f; +char *data; +//Open a file +f = VirtualFileOpen("test.txt", 0, VF_AUTO, VF_O_READ); +//Read it entirely to RAM +data = oslReadEntireFileToMemory(f, &size); +//Print each character +for (i=0;i +#include +#include +#include +#include "VirtualFile.h" +#include + +#define oslMin(x, y) (((x)<(y))?(x):(y)) +#define oslMax(x, y) (((x)>(y))?(x):(y)) + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +#include "config.h" + +//Dans gbGfx.cpp +extern void tilePalReinit(); +void tilePalInit(); + + diff --git a/src/Brunni/config.cpp b/src/Brunni/config.cpp new file mode 100644 index 00000000..4e866f7f --- /dev/null +++ b/src/Brunni/config.cpp @@ -0,0 +1,1193 @@ +//Brunni's portable config system (qui déchire trop sa race... hem en fait non) +#include "config.h" +#include "../../src/System.h" +#include "../../src/NLS.h" +#include "../../src/gb/GB.h" +#include "../../src/gb/gbCheats.h" +#include "../../src/gb/gbGlobals.h" +#include "../../src/gb/gbMemory.h" +#include "../../src/gb/gbSGB.h" +#include "../../src/gb/gbSound.h" + +int gblConfigAutoShowCrc=0; +int retourScript; +int arretdurgence=0; +char *trouveLabel=NULL, chneLabel[1000]; +enum types_objets {TYPE_FONCTION, TYPE_ENTIER, TYPE_BOOL, TYPE_CHAINE, TYPE_REEL, TYPE_OBJET, TYPE_TABLEAU}; +//Indique que ce n'est pas sauvé automatiquement +#define FLAG_NOSAVE 0x1 +//Pas encore utilisé +#define FLAG_CALLBACK 0x2 +//Pas sauver pour les fichiers de config des jeux +#define FLAG_NOSAVEGAME 0x4 + +//Octets utilisés pour les types +#define MASQUE_TYPE 15 +//Taille max (0 à 15: 0 = 1, 1 = 2, 2 = 3, 4 = 16, etc.) +#define TYPE_MAXSIZE(x) ((x) << 4) +#define TYPE_MAXSIZE_MASK(flags) ((flags >> 4) & 15) +#define ScriptErrorEx(...) { char __str[1000]; sprintf(__str , __VA_ARGS__); ScriptError(__str); } + +void ScriptError(char *msg); + +VIRTUAL_FILE *gblFichierConfig; +int bModeWideCrLf=1; +int gblIndice; +char gblVarName[TAILLE_MAX_CHAINES]; +enum {FCT_SET=1, FCT_GET, FCT_SET_BEFORE, FCT_SET_AFTER}; +char tempValue[TAILLE_MAX_CHAINES]; +int GetEntier(char *valeur); +int atox(char *chn); +char *ProchArgEntier(char *ptr); +char *GetChaine(char **dest); +#define SAUTE_ESPACES(ptr) { while(*ptr==' ' || *ptr==' ') ptr++; } + +int myMessageBox(const char *msg, const char *title, int buttons) { + return MessageBox(NULL, msg, title, buttons); +} + + +char *FctFin(int type, char *ptr) { + arretdurgence=1; + return NULL; +} + +char *FctGoto(int type, char *ptr) { + //Note: les labels ne peuvent être qu'en dessous + char *nom = GetChaine(&ptr); + if (nom) { + strcpy(chneLabel, nom); + trouveLabel = chneLabel; + } + return NULL; +} + +char *FctFaire(int type, char *ptr) { + char *nom, *fct; + nom=GetChaine(&ptr); + while(*ptr!=',' && *ptr!=':' && *ptr) + ptr++; + if (*ptr) + ptr++; + while(*ptr!='\"' && *ptr) + ptr++; + fct = GetChaine(&ptr); + if (nom) { + if (!OuvreFichierConfig(nom, fct)) { + ScriptErrorEx("Unable to execute the specified file: %s", nom); + } + } + else + ScriptError("Function: Do\nFilename not defined correctly (don't forget the quote marks)"); + return NULL; +} + +char *FctMsgBox(int type, char *ptr) { + char *chne, *label, *tmp, *titre; + + chne=GetChaine(&ptr); + if (!chne) + chne = "Breakpoint defined here (MsgBox without argument)."; + + titre = "User message"; + +//prochArg: + if (*ptr==',') + ptr++; + while(*ptr==' ' || *ptr==' ') ptr++; + + tmp=GetChaine(&ptr); + + label=NULL; + + if (!tmp) { + if (!strncmp(ptr, "else goto ", 10)) + label=ptr+10; + } + else { + titre=tmp; +// goto prochArg; + } + + if (myMessageBox(chne, titre, MB_OKCANCEL) == 0) { + if (label) { + strcpy(chneLabel,label); + trouveLabel=chneLabel; + } + else + arretdurgence=1; + } + return NULL; +} + +extern byte tilePalList[384]; +extern short tilePalPalette[NB_PALETTES][4]; +extern byte tilePalCrc[384 / 8]; +extern short tileMapTileList[384]; +char gblColorItPaletteFileName[MAX_PATH]; + +void FctColorIt_SetPalette(int type, char *ptr) { + int palNo = GetEntier(ptr), color, i; + if (palNo < 0 || palNo >= NB_PALETTES) + return; + for (i=0;i<4;i++) { + ptr = ProchArgEntier(ptr); + if (*ptr) { + color = GetEntier(ptr) | 0xff000000; + gbPalette[palNo * 4 + i] = oslConvertColor(OSL_PF_5551, OSL_PF_8888, color); + } + } +// gb_invalidate_palette(palNo); +} + +void FctColorIt_AddTileRule(int type, char *ptr) { + int tileStart = 0, tileEnd = 0, palNo, i; + + //Récupère les arguments + if (*ptr == '+') { + tileStart = 128; + ptr++; + } + tileStart += GetEntier(ptr); + ptr = ProchArgEntier(ptr); + //+tileno signifie que c'est une tile dans la zone haute de la VRAM (+128) + if (*ptr == '+') { + tileEnd = 128; + ptr++; + } + tileEnd += GetEntier(ptr); + ptr = ProchArgEntier(ptr); + if (*ptr) + palNo = GetEntier(ptr); + else { + //Only two args => the second is the palette number + palNo = tileEnd; + tileEnd = tileStart; + } + + //Vérifie que les valeurs fournies sont correctes + if (tileStart < 0 || tileStart >= 384 || tileEnd < 0 || tileEnd >= 384 || palNo < 0 || palNo >= NB_PALETTES) + return; + + //Définit les palettes des tiles + for (i=tileStart;i<=tileEnd;i++) + tilePalList[i] = palNo; +} + +void FctColorIt_AddTileCrc(int type, char *ptr) { + int tileStart = 0, tileEnd = 0; + //Récupère les arguments + if (*ptr == '+') { + tileStart = 128; + ptr++; + } + tileStart += GetEntier(ptr); + ptr = ProchArgEntier(ptr); + //+tileno signifie que c'est une tile dans la zone haute de la VRAM (+128) + if (*ptr == '+') { + tileEnd = 128; + ptr++; + } + tileEnd += GetEntier(ptr); + if (tileStart < 0 || tileStart >= 384 || tileEnd < 0 || tileEnd >= 384) + return; + //Savoir si une tile a son crc compté: + //(tilePalCrc[tileNo >> 8] & (1 << (tileNo & 7))) + for (;tileStart<=tileEnd;tileStart++) + tilePalCrc[tileStart >> 3] |= 1 << (tileStart & 7); +} + +//Additional RAM for custom tiles - needed on VBA only, other emulators can use the space reserved for GBC (bank 1) +u8 *getGbExtVramAddr() { + //Allocate memory if it doesn't exists + if (!gbExternalVram) + gbExternalVram = (u8*)malloc(0x2000); + return gbExternalVram; +} + +void FctColorIt_SetTilesetData(int type, char *ptr) { + int tileNo = 0, i, j; + char *text; + char mode = 'N'; + u8 *tilePtr; + //We need to do this with VBA because of the separate GB/GBC handling + u8 *extVram = getGbExtVramAddr(); + + //Récupère les arguments + if (*ptr == '+') { + tileNo = 128; + ptr++; + } + tileNo += GetEntier(ptr); + + if (tileNo < 0 || tileNo >= 384) + return; + + ptr = ProchArgEntier(ptr); + if (*ptr == 'l') { + ptr++; + mode = 'L'; + while (*ptr == ' ' || *ptr == ' ') + ptr++; + } + text = GetChaine(&ptr); + if (!text) + return; + + //We have two VRAM banks just like the game boy color, the second one being used for the custom tileset. +// tileNo += 512; + tilePtr = (u8*)extVram + (tileNo << 4); + + //Mode normal: données RAW au format GB + if (mode == 'N') { + //16 bytes per tile + for (i=0;i<16;i++) { + //Récupération d'un nombre (doublet) hexadécimal + u8 value1, value2; + do { + value1 = *text++; + } while (value1 == ' '); + if (!value1) + break; + do { + value2 = *text++; + } while (value2 == ' '); + if (!value2) + break; + if (value1 >= 'a' && value1 <= 'f') + value1 -= 'a' - ('9' + 1); + if (value2 >= 'a' && value2 <= 'f') + value2 -= 'a' - ('9' + 1); + value1 -= '0'; + value2 -= '0'; + + //Store the final value + *tilePtr++ = value2 + (value1 << 4); + } + } + else if (mode == 'L') { + //8*8 pixels per tile + for (j=0;j<8;j++) { + for (i=7;i>=0;i--) { + //Récupération d'un nombre + u8 value; + do { + value = *text++; + } while (value == ' '); + + //Affectation des bits selon la valeur (1 à 4) + if (value == '0' || value == '3') + tilePtr[0] |= 1 << i; + else + tilePtr[0] &= ~(1 << i); + + if (value == '2' || value == '3') + tilePtr[1] |= 1 << i; + else + tilePtr[1] &= ~(1 << i); + } + + //2 bytes per line + tilePtr += 2; + } + } +} + +void FctColorIt_SetTile(int type, char *ptr) { + int tileStart = 0, tileEnd = 0, newTile = 0; + int redo = 2; + + //Récupère les arguments + if (*ptr == '+') { + tileStart = 128; + ptr++; + } + tileStart += GetEntier(ptr); + ptr = ProchArgEntier(ptr); + + tileEnd = tileStart; + while (redo--) { + //Récupère les arguments + if (*ptr == 'o') //o like original (original tileset) + ptr++, newTile = 0; + else + newTile = 512; + if (*ptr == '+') { + newTile += 128; + ptr++; + } + newTile += GetEntier(ptr); + ptr = ProchArgEntier(ptr); + + //Un troisième argument? + if (*ptr) + //Ne pas prendre si 512 a été ajouté car ça n'est valable que pour newTile + tileEnd = newTile & 511; + else + redo = 0; + } + + if (tileStart < 0 || tileStart >= 384 || tileEnd < 0 || tileEnd >= 384 || newTile < 0 || newTile >= 384 + 512) + return; + + for (;tileStart<=tileEnd;) + tileMapTileList[tileStart++] = newTile++; +} + +/*const IDENTIFICATEUR objGameBoy[]= { + {"colorization", &menuConfig.gameboy.colorization, TYPE_ENTIER, FLAG_NOSAVEGAME}, + {"palette", &menuConfig.gameboy.palette, TYPE_CHAINE}, + {"gbType", &menuConfig.gameboy.gbType, TYPE_ENTIER}, +};*/ + +const IDENTIFICATEUR objColorIt[]= { + //ColorIt.setPalette palNo, palColor0, palColor1, palColor2, palColor3 + {"setPalette", FctColorIt_SetPalette, TYPE_FONCTION}, + //ColorIt.addTileRule tileStart, tileEnd, palNo + {"addTileRule", FctColorIt_AddTileRule, TYPE_FONCTION}, + //ColorIt.addTileCrc tileNo + {"addTileCrc", FctColorIt_AddTileCrc, TYPE_FONCTION}, + //ColorIt.setTileData tileNo, "hextiledata" + {"setTilesetData", FctColorIt_SetTilesetData, TYPE_FONCTION}, + //ColorIt.setTile tileNo, newTileNo + {"setTile", FctColorIt_SetTile, TYPE_FONCTION}, + //Automatically displays the VRAM CRC when the VRAM changes + {"autoShowVramCrc", &gblConfigAutoShowCrc, TYPE_BOOL}, +}; + +//INFOS_OBJET infoObjGameBoy[]={numberof(objGameBoy), objGameBoy}; +INFOS_OBJET infoObjColorIt[]={numberof(objColorIt), objColorIt}; + +const IDENTIFICATEUR objets[]= { +// {"gameboy", infoObjGameBoy, TYPE_OBJET}, + {"colorit", infoObjColorIt, TYPE_OBJET, FLAG_NOSAVE}, + + //Standard du langage + {"end", FctFin, TYPE_FONCTION, FLAG_NOSAVE}, + {"msgbox", FctMsgBox, TYPE_FONCTION, FLAG_NOSAVE}, + {"goto", FctGoto, TYPE_FONCTION, FLAG_NOSAVE}, + {"do", FctFaire, TYPE_FONCTION, FLAG_NOSAVE}, +}; + +//Un objet qui les contient tous +INFOS_OBJET infoObjMain[]={numberof(objets), objets}; + +//Comparaison entre une chaîne à casse basse et mixte +int strlwrmixcmp(const char *lower, const char *mix) { + while(*lower || *mix) { + char c = *mix; + if (c >= 'A' && c <= 'Z') + c += 32; + if (c != *lower) + return -1; + lower++, mix++; + } + return 0; +} + +void ScriptBegin() { +} + +void ScriptEnd() { +} + +int atox(char *chn) { + int i; + int n; + int v; + char *deb; + deb=chn; + while((*chn>='0' && *chn<='9') || (*chn>='a' && *chn<='f') || (*chn>='A' && *chn<='F')) + chn++; + chn--; + i=1; + n=0; + while(chn>=deb) { + v=*(chn)-48; + if (v>=17+32) v-=39; + if (v>=17) v-=7; + n+=i*v; + i*=16; + chn--; + } + return n; +} + +//Idem mais en binaire +int atob(char *chn) { + int i; + int n; + int v; + char *deb; + deb=chn; + while(*chn=='0' || *chn=='1') + chn++; + chn--; + i=1; + n=0; + while(chn>=deb) { + v=*(chn)-48; + n+=i*v; + i*=2; + chn--; + } + return n; +} + +char *ProchArgEntier(char *ptr) { + int compteParentheses=0; + + while(1) { + if (*ptr==0) + break; + if (*ptr=='(') + compteParentheses++; + if (compteParentheses==0) { + if (*ptr==',' || *ptr==' ' || *ptr==')') { + ptr++; + break; + } + } + if (*ptr==')') + compteParentheses--; + ptr++; + } + while(*ptr==' ' || *ptr==' ') + ptr++; + return ptr; +} + +int GetEntier(char *valeur) { + int r,v,b; + + if ((*valeur<'0' || *valeur>'9') && *valeur != '-') { + if (*valeur=='t' || *valeur=='v') + return 1; + else if (*valeur=='f') + return 0; + else if (!strncmp(valeur,"rgb",3)) { + valeur+=3; + while(*valeur!='(' && *valeur) valeur++; + if (!(*valeur)) + return 0; + valeur++; + r=GetEntier(valeur); + valeur=ProchArgEntier(valeur); + v=atoi(valeur); + valeur=ProchArgEntier(valeur); + b=GetEntier(valeur); + return RGB(r,v,b); + } + return 0; + } + if (*valeur=='0') { + valeur++; + if (*valeur=='x') + return atox(valeur+1); + else if (*valeur=='b') { + return atob(valeur+1); + } + else + return atoi(valeur-1); + } + return atoi(valeur); +} + +char *GetChaine(char **dest) { + char *retour, *chne; + chne=*dest; + if (*chne=='\"') { + chne++; + retour=chne; + while(*chne!='\"' && *chne) + chne++; + } + else if (*chne=='\'') { + chne++; + retour=chne; + while(*chne!='\'' && *chne) + chne++; + } + else if (*chne=='*') { + chne++; + retour=chne; + while(*chne!='*' && *chne) + chne++; + } + else + //Chaîne telle quelle + return chne; + if (!(*chne)) + return NULL; + *chne=0; + *dest=chne+1; + return retour; +} + +const IDENTIFICATEUR *TrouveIdentificateur(const IDENTIFICATEUR *source, int taille, char *objet) +{ + int i, bNotFound = 0; + if (!source) { + source = (const IDENTIFICATEUR*)objets; + taille = sizeof(objets)/sizeof(objets[0]); + bNotFound = 1; + } + //Trouve la référence d'objet dans la table + for (i=0;itype & MASQUE_TYPE) { + case TYPE_FONCTION: + //Depuis que je m'amuse sur GBA avec ce genre de trucs, ça me semble déjà plus sûr comme méthode. Ne vous inquiétez pas si vous trouvez ça sale :p + laFonction=(char* (*)(int, char*))id->handle; + laFonction(FCT_SET, ptr); + break; + + case TYPE_ENTIER: + case TYPE_BOOL: + val=GetEntier(ptr); + *(int*)id->handle=val; + break; + case TYPE_REEL: + *(double*)id->handle=atof(ptr); + break; + + case TYPE_CHAINE: + arg=GetChaine(&ptr); + if (arg) { + int maxSize = 1 << TYPE_MAXSIZE_MASK(id->type); + ptr=(char*)id->handle; + for (i=0;ihandle; + + switch (id->type & MASQUE_TYPE) { + case TYPE_FONCTION: + //Depuis que je m'amuse sur GBA avec ce genre de trucs, ça me semble déjà plus sûr comme méthode. Ne vous inquiétez pas si vous trouvez ça sale :p + laFonction=(char* (*)(int, char*))id->handle; + return laFonction(FCT_GET, NULL); + + case TYPE_ENTIER: + sprintf(tempValue, "%i", *(int*)id->handle); + return tempValue; + + case TYPE_BOOL: + strcpy(tempValue, (*(int*)id->handle) ? "true" : "false"); + return tempValue; + + case TYPE_TABLEAU: + char tempValueTab[TAILLE_MAX_CHAINES]; + strcpy(tempValueTab, "{"); + for (i=0;itaille;i++) { + IDENTIFICATEUR ident; + char *val; + int maxSize; + switch (it->type & MASQUE_TYPE) { + case TYPE_ENTIER: + case TYPE_BOOL: + ident.handle = (int*)it->tableau+i; + break; + case TYPE_CHAINE: + maxSize = 1 << TYPE_MAXSIZE_MASK(it->type); + ident.handle = (char *)it->tableau + maxSize * i; + break; + case TYPE_REEL: + ident.handle = (double*)it->tableau+i; + break; + } + ident.nom = NULL; + ident.type = it->type; + val = GetVariableValue(&ident, 1); + if (val) { + strcat(tempValueTab, val); + //Sépare les éléments d'une virgule, sauf le dernier + if (i < it->taille - 1) + strcat(tempValueTab, ", "); + } + } + strcpy(tempValue, tempValueTab); + strcat(tempValue, "}"); + return tempValue; + + case TYPE_REEL: + sprintf(tempValue, "%f", *(float*)id->handle); + return tempValue; + + case TYPE_CHAINE: + if (!withQuotes) + return (char*)id->handle; + else { + strcpy(tempValue, "\""); + strcat(tempValue, (char*)id->handle); + strcat(tempValue, "\""); + return tempValue; + } + + default: + return NULL; + } +} + +int OuvreFichierConfig(char *nom_fichier, char *fonction) { + VIRTUAL_FILE *f; + + retourScript=1; + + if (!(*nom_fichier)) + return 0; + + f = VirtualFileOpen((void*)nom_fichier, 0, VF_FILE, VF_O_READ); + if (!f) + return 0; + + return ExecScript(f,fonction, NULL); +} + +//Command: si FILE == NULL +int ExecScript(VIRTUAL_FILE *f, char *fonction, char *command) { + char str[1000], objet[1000], commande[1000], *ptr, tmp[4096], fonction_reel[1000]; + int i,j, type; + void *handle; + INFOS_OBJET *infos; + int indice; + const IDENTIFICATEUR *idObjet, *idEnCours; + int tailleEnCours; + + arretdurgence=0; + + retourScript=1; + + if (fonction) { //Une fonction sur laquelle se brancher? + strcpy(fonction_reel, fonction); + fonction = fonction_reel; + //Pas case sensitive, bien entendu :p + for (ptr=fonction;*ptr;ptr++) + if (*ptr>='A' && *ptr<='Z') + *ptr+=32; + } + + trouveLabel=fonction; + + ScriptBegin(); + + while(f?(!VirtualFileEof(f)):(*command)) { + if (arretdurgence) + break; + if (f) + VirtualFileGets(str,sizeof(str),f); + else { + i=0; + while(*command != ';' && *command && i='A' && str[i]<='Z') + str[i]+=32; + + if (str[i]=='\"') { + i++; + while(str[i] && (str[i]!='\"' || (str[i-1]=='\\' && str[i]=='\"'))) + i++; + if (!str[i]) + break; + } + else if (str[i]=='\'') { + i++; + while(str[i] && (str[i]!='\'' || (str[i-1]=='\\' && str[i]=='\''))) + i++; + if (!str[i]) + break; + } + else if (str[i]=='*') { + i++; + while(str[i] && (str[i]!='*' || (str[i-1]=='\\' && str[i]=='*'))) + i++; + if (!str[i]) + break; + } + else if (str[i]=='#' || str[i]==';') { + str[i]=0; + if (i>0) { + i--; + while(str[i]==' ' || str[i]==' ' && i>=0) + str[i--]=0; + } + goto parsingTermine; + } + } + i--; + +parsingTermine: + if (str[i]==':' && !trouveLabel) //Label trouvé! + continue; + + idEnCours = NULL; + tailleEnCours = 0; + i = 0; + indice = -1; + +continueParse: + j = 0; + //Sauter les espaces/tabs éventuels + while(str[i]==' ' || str[i]==' ') + i++; + + //Bon, c'est pas le tout, mais on a un label à trouver nous! + if (trouveLabel) { + if (str[i]=='_') + i++; + j=i; + while(!(str[i]==':' && str[i+1]==0) && str[i]) + i++; + if (!str[i]) //Pas un label + continue; + str[i]=0; + if (strlwrmixcmp(str+j, trouveLabel)) //Pas le bon label + continue; + trouveLabel=NULL; //Label trouvé -> plus à rechercher. + continue; + } + + //Après, récupérer l'objet de la commande (opérande gauche) + while(str[i] && str[i]!=' ' && str[i]!=' ' && str[i]!='.' && str[i]!='=' && str[i]!='[') + objet[j++]=str[i++]; + + //Si ça n'a pas été terminé par un point + while(str[i]!='[' && str[i]!='.' && str[i]!='=' && str[i] && str[i]!=' ') i++; + + //Termine la chaîne + objet[j]=0; + + //L'objet est faux? + if (!objet[0]) + continue; + + //Permet ensuite de savoir si aucune commande n'a été donnée + commande[0]=0; + + if (str[i]=='=' || str[i]==' ' || str[i]=='.' || str[i]=='[') //Pas de méthode + goto sauteEspaces; + + //Fin de chaîne -> seul un objet est spécifié + if (!str[i]) + goto sauteEspaces; + + //Saute les espaces + while(str[i]==' ' || str[i]==' ') i++; + +//commande: + //Après, récupérer la commande à exécuter (opérande droite) + j=0; + while(str[i] && str[i]!=' ' && str[i]!=' ' && str[i]!='=' && str[i]!='[') + commande[j++]=str[i++]; + + //Termine la chaîne + commande[j]=0; + + //Sauter les espaces/tabulations qui viennent ensuite +sauteEspaces: + if (str[i]==' ' || str[i]==' ') { + while(str[i]==' ' || str[i]==' ') + i++; + } + + if (str[i]=='.') { + i++; +// goto commande; + } + if (str[i]=='=') { + i++; + goto sauteEspaces; + } + if (str[i]=='[') { + i++; + indice=GetEntier(str+i); + while(str[i] && str[i]!=']') + i++; + if (str[i]) { + i++; + goto sauteEspaces; + } + } + + //On est prêt pour exécuter une commande! + ptr=str+i; + + handle=NULL; + gblFichierConfig = f; + + idObjet = TrouveIdentificateur(idEnCours, tailleEnCours, objet); + + //Aucun résultat + if (!idObjet) { + if (idEnCours) + sprintf(tmp, "The property %s doesn't exist.", objet); + else + sprintf(tmp, "The identifier %s doesn't exist.", objet); + ScriptError(tmp); + arretdurgence = 1; + continue; + } + else { + handle = idObjet->handle; + type = idObjet->type; + } + + gblIndice=indice; + + if (type==TYPE_OBJET) { + infos = (INFOS_OBJET*)handle; + + idEnCours = infos->objet; + tailleEnCours = infos->taille; + goto continueParse; + } + + if (type==TYPE_TABLEAU) { + INFOS_TABLEAU *it; + it = (INFOS_TABLEAU*)handle; + if (indice < 0) { + if (*ptr == '{') { + //Callback avant +// if (idObjet->flags & FLAG_CALLBACK) +// return ((char* (*)(int, char*))idObjet->handle2)(FCT_SET_BEFORE, ptr); + //Saute le { + ptr++; + SAUTE_ESPACES(ptr); + //CHAÎNES PAS TESTÉES!!!! + for (i=0;itaille;i++) { + char *val = NULL, value[TAILLE_MAX_CHAINES]; + handle = NULL; + //Plus rien + if (!(*ptr)) + break; + + switch (it->type & MASQUE_TYPE) { + case TYPE_ENTIER: + handle=(int*)it->tableau+i; + val = value; + sprintf(value, "%i", GetEntier(ptr)); + ptr = ProchArgEntier(ptr); + break; + + case TYPE_BOOL: + handle=(int*)it->tableau+i; + val = value; + strcpy(value, GetEntier(ptr) ? "true" : "false"); + ptr = ProchArgEntier(ptr); + break; + + case TYPE_CHAINE: + ; + int maxSize = 1 << TYPE_MAXSIZE_MASK(it->type); + handle = (char *)it->tableau + maxSize * i; + val = GetChaine(&ptr); + break; + } + + if (handle && val) { + IDENTIFICATEUR ident; + ident.nom = NULL; + ident.type = it->type; + ident.handle = handle; + SetVariableValue(&ident, val); + } + } + //Callback après + if (idObjet->flags & FLAG_CALLBACK) + ((char* (*)(int, char*))idObjet->handle2)(FCT_SET_AFTER, NULL); + } + else { + //Le tableau ne peut être évalué (erreur de syntaxe) + if (idObjet->flags & FLAG_CALLBACK) + ((char* (*)(int, char*))idObjet->handle2)(FCT_SET, ptr); + else + goto error1; + } + } + else { + IDENTIFICATEUR ident; + int maxSize = 1 << TYPE_MAXSIZE_MASK(it->type); + + if (indice < 0 || indice >= it->taille) { +error1: + if (indice == -1) + sprintf(tmp,"Array %s.\nSyntax error.", objet, indice); + else + sprintf(tmp,"Array %s.\nThe subscript (%i) is out of bounds.", objet, indice); + ScriptError(tmp); + continue; + } + + switch (it->type & MASQUE_TYPE) { + case TYPE_ENTIER: + case TYPE_BOOL: + ident.handle=(int*)it->tableau+indice; + break; + + case TYPE_CHAINE: + ident.handle = (char *)it->tableau + maxSize * indice; + break; + + case TYPE_REEL: + ident.handle=(double*)it->tableau+indice; + break; + + default: + //Vous devriez pouvoir adapter pour d'autres types sans trop de problèmes ;) + sprintf(tmp, "The array %s has an uncomputable type.", objet); + ScriptError(tmp); + continue; + } + ident.nom = NULL; + ident.type = it->type; + SetVariableValue(&ident, ptr); + //Callback éventuel + if (idObjet->flags & FLAG_CALLBACK) + ((char* (*)(int, char*))idObjet->handle2)(FCT_SET_AFTER, NULL); + } + continue; + } + + SetVariableValue(idObjet, ptr); + //Callback éventuel + if (idObjet->flags & FLAG_CALLBACK) + ((char* (*)(int, char*))idObjet->handle2)(FCT_SET_AFTER, NULL); +// if (arretdurgence) +// break; + } + + ScriptEnd(); + if (f) + VirtualFileClose(f); + return (trouveLabel == NULL); +} + +const IDENTIFICATEUR *GetVariableAddress(char *str) { + char objet[1000], *ptr; + int i,j, type; + void *handle; + INFOS_OBJET *infos; + int indice; + const IDENTIFICATEUR *idObjet, *idEnCours; + int tailleEnCours; + + idEnCours = NULL; + tailleEnCours = 0; + i = indice = 0; + +continueParse: + j = 0; + //Sauter les espaces/tabs éventuels + while(str[i]==' ' || str[i]==' ') + i++; + + //Après, récupérer l'objet de la commande (opérande gauche) + while(str[i] && str[i]!=' ' && str[i]!=' ' && str[i]!='.' && str[i]!='[') + objet[j++]=str[i++]; + + //Si ça n'a pas été terminé par un point + while(str[i]!='[' && str[i]!='.' && str[i] && str[i]!=' ') i++; + + //Termine la chaîne + objet[j]=0; + + //L'objet est faux? + if (!objet[0]) + return NULL; + + if (str[i]==' ' || str[i]=='.' || str[i]=='[') //Pas de méthode + goto sauteEspaces; + + //Fin de chaîne -> seul un objet est spécifié + if (!str[i]) + goto sauteEspaces; + + //Saute les espaces + while(str[i]==' ' || str[i]==' ') i++; + + //Sauter les espaces/tabulations qui viennent ensuite +sauteEspaces: + if (str[i]==' ' || str[i]==' ') { + while(str[i]==' ' || str[i]==' ') + i++; + } + + if (str[i]=='.') { + i++; +// goto commande; + } + if (str[i]=='[') { + i++; + indice=GetEntier(str+i)-1; + while(str[i] && str[i]!=']') + i++; + if (str[i]) { + i++; + goto sauteEspaces; + } + } + + //On est prêt pour exécuter une commande! + ptr=str+i; + + handle=NULL; + + idObjet = TrouveIdentificateur(idEnCours, tailleEnCours, objet); + + //Aucun résultat + if (!idObjet) { + return NULL; + } + else { + handle = idObjet->handle; + type = idObjet->type; + } + + gblIndice=indice; + + if (type==TYPE_OBJET) { + infos = (INFOS_OBJET*)handle; + + idEnCours = infos->objet; + tailleEnCours = infos->taille; + goto continueParse; + } + return idObjet; +} + +void ScriptError(char *msg) { + myMessageBox(msg, "Script error", MB_OK); + arretdurgence = 1; +} + + +/** ADDITIONAL CODE */ +int oslConvertColor(int pfDst, int pfSrc, int color) { + int r=0, g=0, b=0, a=0; + if (pfSrc == pfDst) + return color; + if (pfSrc == OSL_PF_8888) + oslRgbaGet8888(color, r, g, b, a); + else if (pfSrc == OSL_PF_5650) + oslRgbGet5650f(color, r, g, b), a = 0xff; + else if (pfSrc == OSL_PF_5551) + oslRgbaGet5551f(color, r, g, b, a); + else if (pfSrc == OSL_PF_4444) + oslRgbaGet4444f(color, r, g, b, a); + if (pfDst == OSL_PF_8888) + color = RGBA(r, g, b, a); + else if (pfDst == OSL_PF_5650) + color = RGB16(r, g, b); + else if (pfDst == OSL_PF_5551) + color = RGBA15(r, g, b, a); + else if (pfDst == OSL_PF_4444) + color = RGBA12(r, g, b, a); + return color; +} + +int fileExists(char *fileName) { + VIRTUAL_FILE *f; + int success = 0; + f = VirtualFileOpen(fileName, 0, VF_FILE, VF_O_READ); + if (f) { + success = 1; + VirtualFileClose(f); + } + return success; +} + +void GetJustFileName(char *dst, char *src) { + int i, lastPt = -1; + for (i=0;src[i];i++) { + if (src[i] == '.') + lastPt = i; + dst[i] = src[i]; + } + if (lastPt >= 0) + dst[lastPt] = 0; +} + +int CheckFichierPalette(char *file) { + //Try to open ROM-specific palette file + GetJustFileName(gblColorItPaletteFileName, file); + strcat(gblColorItPaletteFileName, ".pal.ini"); + + if (!fileExists(gblColorItPaletteFileName)) { + //Search in the shared folder, using the cart name +/* sprintf(gblColorItPaletteFileName, "COLORPAK/%s.pal.ini", info.cart_name); + if (!fileExists(gblColorItPaletteFileName)) { + //If it still doesn't exists, use the file name + char temp[MAX_PATH], *fname; + fname = extractFilePath(menuFileSelectFileName, temp, 1); + GetJustFileName(temp, fname); + sprintf(gblColorItPaletteFileName, "COLORPAK/%s.pal.ini", temp); + }*/ + } + return fileExists(gblColorItPaletteFileName); +} + +void OuvreFichierPalette(int crc, char *fonction) { + if (gblModeColorIt) { + if (fonction) + OuvreFichierConfig(gblColorItPaletteFileName, fonction); + else { + char tempCrc[100]; + sprintf(tempCrc, "[%08x]", crc); + tilePalReinit(); + //Si la section correspondant au crc actuel n'existe pas, on utilise le profil par défaut [default]. + if (!OuvreFichierConfig(gblColorItPaletteFileName, tempCrc)) + OuvreFichierConfig(gblColorItPaletteFileName, "[default]"); + } + } +} + +char *extractFilePath(char *file, char *dstPath, int level) { + int i, curLevel = 0; + char *fileName = dstPath; + + strcpy(dstPath, file); + //Remove the last '/' character, so that we get the path in nameTemp and the file name in ptrFileName + for (i=strlen(dstPath) - 1; i>=0; i--) { + if (dstPath[i] == '/' || dstPath[i] == '\\') { + if (curLevel == 0) + fileName = dstPath + i + 1; + //Suppression de level slashs + if (++curLevel >= level) { + dstPath[i] = 0; + break; + } + } + } + + return fileName; +} + diff --git a/src/Brunni/config.h b/src/Brunni/config.h new file mode 100644 index 00000000..ca90480c --- /dev/null +++ b/src/Brunni/config.h @@ -0,0 +1,93 @@ +#ifndef PSP_CONFIG_H +#define PSP_CONFIG_H + +#include "common.h" + +typedef unsigned long OSL_COLOR; + +//For game boy ColorIt. +#define NB_PALETTES 48 + +#ifdef RGB + #undef RGB +#endif + +/** Pixelformats (color types / modes). */ +enum OSL_PIXELFORMATS { + OSL_PF_5650, //!< 16 bits, 5 bits per component, except green which has 6, no alpha + OSL_PF_5551, //!< 15 bits, 5 bits per component, 1 alpha bit + OSL_PF_4444, //!< 12 bits, 4 bits per component, 4 alpha bits + OSL_PF_8888, //!< 32 bits, 8 bits per component, 8 alpha bits + OSL_PF_4BIT, //!< Paletted format, 4 bits (16 colors), cannot be set as drawbuffer + OSL_PF_8BIT //!< Paletted format, 8 bits (256 colors), cannot be set as drawbuffer +}; + +/** Creates a 32-bit opaque color. */ +#define RGB(r,v,b) ((r) | ((v)<<8) | ((b)<<16) | (0xff<<24)) +/** Creates a 32-bit color. 32-bit colors is what all OSLib calls asking for a color want. Use RGB if you don't want to bother about alpha (semi transparency). */ +#define RGBA(r,v,b,a) ((r) | ((v)<<8) | ((b)<<16) | ((a)<<24)) +/** Creates a 12-bit color with 3 coefficients (red, green, blue). Alpha is set to the maximum (opaque). The r, v, b values can be from 0 to 255, they're divided to match the 12-bit pixel format. */ +#define RGB12(r,v,b) ((((b)>>4)<<8) | (((v)>>4)<<4) | ((r)>>4) | (0xf<<12)) +/** Creates a 12-bit color with 4 coefficients (red, green, blue, alpha). */ +#define RGBA12(r,v,b,a) ((((a)>>4)<<12) | (((b)>>4)<<8) | (((v)>>4)<<4) | ((r)>>4)) +/** Creates a 15-bit opaque color. */ +#define RGB15(r,v,b) ((((b)>>3)<<10) | (((v)>>3)<<5) | ((r)>>3) | (1<<15)) +/** Creates a 15-bit color with alpha. */ +#define RGBA15(r,v,b,a) ((((a)>>7)<<15) | (((b)>>3)<<10) | (((v)>>3)<<5) | ((r)>>3)) +/** Creates a 16-bit color. */ +#define RGB16(r,v,b) ((((b)>>3)<<11) | (((v)>>2)<<5) | ((r)>>3)) + +#define oslRgbaGet8888(data, r, g, b, a) ((r)=((data)&0xff), (g)=(((data)>>8)&0xff), (b)=(((data)>>16)&0xff), (a)=(((data)>>24)&0xff)) +#define oslRgbaGet4444(data, r, g, b, a) ((r)=((data)&0xf)<<4, (g)=(((data)>>4)&0xf)<<4, (b)=(((data)>>8)&0xf)<<4, (a)=(((data)>>12)&0xf)<<4) +#define oslRgbaGet5551(data, r, g, b, a) ((r)=((data)&0x1f)<<3, (g)=(((data)>>5)&0x1f)<<3, (b)=(((data)>>10)&0x1f)<<3, (a)=(((data)>>15)&0x1)<<7) +#define oslRgbGet5650(data, r, g, b) ((r)=((data)&0x1f)<<3, (g)=(((data)>>5)&0x3f)<<2, (b)=(((data)>>11)&0x1f)<<3) + +#define oslRgbaGet4444f(data, r, g, b, a) ((r)=((data)&0xf)<<4 | ((data)&0xf), (g)=(((data)>>4)&0xf)<<4 | (((data)>>4)&0xf), (b)=(((data)>>8)&0xf)<<4 | (((data)>>8)&0xf), (a)=(((data)>>12)&0xf)<<4 | (((data)>>12)&0xf)) +#define oslRgbaGet5551f(data, r, g, b, a) ((r)=((data)&0x1f)<<3 | ((data)&0x1f)>>2, (g)=(((data)>>5)&0x1f)<<3 | (((data)>>5)&0x1f)>>2, (b)=(((data)>>10)&0x1f)<<3 | (((data)>>10)&0x1f)>>2, (a)=(((data)>>15)&0x1)*255) +#define oslRgbGet5650f(data, r, g, b) ((r)=((data)&0x1f)<<3 | ((data)&0x1f)>>2, (g)=(((data)>>5)&0x3f)<<2 | (((data)>>5)&0x3f)>>4, (b)=(((data)>>11)&0x1f)<<3 | (((data)>>10)&0x1f)>>2) + +#define numberof(a) (sizeof(a)/sizeof(*(a))) + +typedef struct { + char *nom; + void *handle; + unsigned char type, flags; + void *handle2; +} IDENTIFICATEUR; + +typedef struct { + int taille; + const IDENTIFICATEUR *objet; +} INFOS_OBJET; + +typedef struct { + int taille; + int type; + const void *tableau; +} INFOS_TABLEAU; + +//Dans un tableau, toutes les chaînes ont cette taille!!! +#define TAILLE_MAX_CHAINES 512 +enum {SAVETYPE_DEFAULT, SAVETYPE_GAME, SAVETYPE_CHANGESONLY}; + +extern int gblIndice; +extern char menuDefaultExecute[TAILLE_MAX_CHAINES]; +extern int gblModeColorIt; +extern char gblColorItPaletteFileName[MAX_PATH]; +extern int gblConfigAutoShowCrc; + +extern int ExecScript(VIRTUAL_FILE *f, char *fonction, char *command); +extern void SetVariableValue(const IDENTIFICATEUR *id, char *ptr); +extern char *GetVariableValue(const IDENTIFICATEUR *id, int withQuotes); +extern const IDENTIFICATEUR *GetVariableAddress(char *str); +extern int OuvreFichierConfig(char *nom_fichier, char *fonction); +extern char *GetChaine(char **dest); +//extern u32 GetAddedColor(int color, int value); +extern void ScriptSave(const char *filename, int type); +extern int oslConvertColor(int pfDst, int pfSrc, int color); +extern int CheckFichierPalette(char *file); +extern void OuvreFichierPalette(int crc, char *fonction); +extern u8 *getGbExtVramAddr(); +extern char *extractFilePath(char *file, char *dstPath, int level); + +#endif diff --git a/src/Brunni/gb.h b/src/Brunni/gb.h new file mode 100644 index 00000000..b21fd404 --- /dev/null +++ b/src/Brunni/gb.h @@ -0,0 +1,3 @@ +void gb_invalidate_all_colors(); +void gb_invalidate_palette(int palNo); + diff --git a/src/Brunni/vfsFile.c b/src/Brunni/vfsFile.c new file mode 100644 index 00000000..eeb9a340 --- /dev/null +++ b/src/Brunni/vfsFile.c @@ -0,0 +1,84 @@ +#include "common.h" + +/* + SOURCE VFS: file +*/ + +#define FLAG_EOF 1 + +int VF_FILE = -1; + +#define _file_ ((FILE*)f->ioPtr) + +int vfsFileOpen(void *param1, int param2, int type, int mode, VIRTUAL_FILE* f) { + char *stdMode = "rb"; + if (mode == VF_O_WRITE) + stdMode = "wb"; + else if (mode == VF_O_READWRITE) + stdMode = "a+"; + + f->ioPtr = (void*)fopen((char*)param1, stdMode); + return (int)f->ioPtr; +} + +int vfsFileClose(VIRTUAL_FILE *f) { + fclose(_file_); + return 1; +} + +int vfsFileWrite(const void *ptr, size_t size, size_t n, VIRTUAL_FILE* f) { + return fwrite(ptr, size, n, _file_); +} + +int vfsFileRead(void *ptr, size_t size, size_t n, VIRTUAL_FILE* f) { + return fread(ptr, size, n, _file_); +} + +int vfsFileGetc(VIRTUAL_FILE *f) { + return fgetc(_file_); +} + +int vfsFilePutc(int caractere, VIRTUAL_FILE *f) { + return fputc(caractere, _file_); +} + +char *vfsFileGets(char *str, int maxLen, VIRTUAL_FILE *f) { + return vfsMemGets(str, maxLen, f); +} + +void vfsFilePuts(const char *s, VIRTUAL_FILE *f) { + fputs(s, _file_); +} + +void vfsFileSeek(VIRTUAL_FILE *f, int offset, int whence) { + fseek(_file_, offset, whence); +} + +int vfsFileTell(VIRTUAL_FILE *f) { + return ftell(_file_); +} + +int vfsFileEof(VIRTUAL_FILE *f) { + return feof(_file_); +} + +VIRTUAL_FILE_SOURCE vfsFile = { + vfsFileOpen, + vfsFileClose, + vfsFileRead, + vfsFileWrite, + vfsFileGetc, + vfsFilePutc, + vfsFileGets, + vfsFilePuts, + vfsFileSeek, + vfsFileTell, + vfsFileEof, +}; + +int oslInitVfsFile() { + VF_FILE = VirtualFileRegisterSource(&vfsFile); + return VF_FILE; +} + + diff --git a/src/agb/GBA.cpp b/src/agb/GBA.cpp index 7ce5b828..91cdf2ef 100644 --- a/src/agb/GBA.cpp +++ b/src/agb/GBA.cpp @@ -25,7 +25,7 @@ #include "GBAcpu.h" #include "GBAinline.h" #include "../Globals.h" -#include "GBAGFX.h" +#include "GBAGfx.h" #include "../EEprom.h" #include "../Flash.h" #include "../Sound.h" diff --git a/src/agb/GBAGfx.h b/src/agb/GBAGfx.h index 0c82ec2e..e2632ae0 100644 --- a/src/agb/GBAGfx.h +++ b/src/agb/GBAGfx.h @@ -22,7 +22,7 @@ #define VBA_GFX_H #include "GBA.h" -#include "gbaGfx.h" +#include "GBAGfx.h" #include "../Globals.h" #include "../Port.h" diff --git a/src/dmg/GB.cpp b/src/dmg/GB.cpp index 110bd315..9f4abab5 100644 --- a/src/dmg/GB.cpp +++ b/src/dmg/GB.cpp @@ -4011,6 +4011,12 @@ void gbCleanUp() gbSgbShutdown(); + //Brunni/ + if (gbExternalVram != NULL) { + free(gbExternalVram); + gbExternalVram = NULL; + } + if(gbVram != NULL) { free(gbVram); gbVram = NULL; diff --git a/src/dmg/gbGfx.cpp b/src/dmg/gbGfx.cpp index 2fc20040..468a46ac 100644 --- a/src/dmg/gbGfx.cpp +++ b/src/dmg/gbGfx.cpp @@ -17,11 +17,63 @@ // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include - +#include "../Brunni/common.h" #include "../agb/GBA.h" #include "gbGlobals.h" #include "gbSGB.h" +/** BRUNNI ADDED CODE **/ +int gblModeColorIt=0; +byte tilePalList[384]; +short tilePalPalette[NB_PALETTES][4]; +byte tilePalCrc[384 / 8]; +short tileMapTileList[384]; +int gb_lastVramCrc; +u8 *gbExternalVram; + +void tilePalReinit() { + int i; + memset(tilePalList, 0, sizeof(tilePalList)); + for (i=0;i> 3] & (1 << (i & 7))) + crc = crc32(crc, vram + i * 16, 16); + } + return crc; +} + +void exiting_lcdc() { + //Do nothing in GBC mode (VBA uses another VRAM address) + if (!gblModeColorIt || gbCgbMode) + return; + + u32 crc = tileMapGetVramChecksum(); + if (crc != gb_lastVramCrc /*|| gblConfigAutoShowCrc*/) { + OuvreFichierPalette(crc, NULL); + if (gblConfigAutoShowCrc) { + char temp[256]; + sprintf(temp, "New VRAM CRC: %08x", crc); + systemScreenMessage(temp); + } + gb_lastVramCrc = crc; + } +} + +/** END BRUNNI **/ + u8 gbInvertTab[256] = { 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0, 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, @@ -66,14 +118,19 @@ void gbRenderLine() memset(gbLineMix, 0, sizeof(gbLineMix)); u8 * bank0; u8 * bank1; + //Brunni/ + u8 * externalVram = NULL; if(gbCgbMode) { bank0 = &gbVram[0x0000]; bank1 = &gbVram[0x2000]; } else { bank0 = &gbMemory[0x8000]; bank1 = NULL; + //Brunni/ Additional memory for custom tiles - we should have done just like the GBC, two banks + if (gblModeColorIt) + externalVram = getGbExtVramAddr(); } - + int tile_map = 0x1800; if((register_LCDC & 8) != 0) tile_map = 0x1c00; @@ -128,6 +185,25 @@ void gbRenderLine() u8 tile_a = 0; u8 tile_b = 0; + u8 colorItPaletteNb = 0, colorItUseExtVram = 0; + + //Brunni/ Pattern change (custom tile) + if (gblModeColorIt) { + //Brunni/ Get the tile number (+128 if LCDC bit4 is zero) + s16 tilenb = (tile_pattern >> 4) + tile; + colorItPaletteNb = tilePalList[tilenb]; + + //Brunni/ Select the associated custom tile + tilenb = tileMapTileList[tilenb]; + + //Brunni/ Does it use additional GB vram? ("bank 1") + if (tilenb >= 512) + colorItUseExtVram = 1, tilenb -= 512; + + //Brunni/ Nothing to do => return to the normal range (within current bank) + tilenb -= (tile_pattern >> 4); + tile_pattern_address = tile_pattern + tilenb * 16 + by * 2; + } if(attrs & 0x40) { tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; @@ -136,6 +212,11 @@ void gbRenderLine() if(attrs & 0x08) { tile_a = bank1[tile_pattern_address++]; tile_b = bank1[tile_pattern_address]; + } + else if (colorItUseExtVram) { + //Brunni/ "bank 1" (additional GB vram) + tile_a = externalVram[tile_pattern_address++]; + tile_b = externalVram[tile_pattern_address]; } else { tile_a = bank0[tile_pattern_address++]; tile_b = bank0[tile_pattern_address]; @@ -170,6 +251,10 @@ void gbRenderLine() c = c + 4*palette; } + + //Brunni/ Find the right palette + if (gblModeColorIt) + c += 4 * colorItPaletteNb; } gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF; @@ -323,6 +408,25 @@ void gbRenderLine() while(x < 160) { u8 tile_a = 0; u8 tile_b = 0; + u8 colorItPaletteNb = 0, colorItUseExtVram = 0; + + //Brunni/ Define the actual palette and custom pattern for this tile + if (gblModeColorIt) { + //Brunni/ Get the tile number (+128 if LCDC bit4 is zero) + s16 tilenb = (tile_pattern >> 4) + tile; + colorItPaletteNb = tilePalList[tilenb]; + + //Brunni/ Select the associated custom tile + tilenb = tileMapTileList[tilenb]; + + //Brunni/ Does it use additional GB vram? ("bank 1") + if (tilenb >= 512) + colorItUseExtVram = 1, tilenb -= 512; + + //Brunni/ Nothing to do => return to the normal range (within current bank) + tilenb -= (tile_pattern >> 4); + tile_pattern_address = tile_pattern + tilenb * 16 + by * 2; + } if(attrs & 0x40) { tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2; @@ -331,6 +435,11 @@ void gbRenderLine() if(attrs & 0x08) { tile_a = bank1[tile_pattern_address++]; tile_b = bank1[tile_pattern_address]; + } + else if (colorItUseExtVram) { + //Brunni/ "bank 1" (additional GB vram) + tile_a = externalVram[tile_pattern_address++]; + tile_b = externalVram[tile_pattern_address]; } else { tile_a = bank0[tile_pattern_address++]; tile_b = bank0[tile_pattern_address]; @@ -367,6 +476,9 @@ void gbRenderLine() c = c + 4*palette; } + //Brunni/ Find the right palette + if (gblModeColorIt) + c += 4 * colorItPaletteNb; } gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c] & 0x7FFF] : gbPalette[c] & 0x7FFF; @@ -424,6 +536,8 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, { u8 * bank0; u8 * bank1; + //Brunni/ + u8 * externalVram = NULL; if(gbCgbMode) { if(register_VBK & 1) { bank0 = &gbVram[0x0000]; @@ -435,6 +549,8 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, } else { bank0 = &gbMemory[0x8000]; bank1 = NULL; + if (gblModeColorIt) + externalVram = getGbExtVramAddr(); } int init = 0x0000; @@ -461,10 +577,27 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, int address = init + tile * 16 + 2*t; int a = 0; int b = 0; + u8 colorItPaletteNb = 0, colorItUseExtVram = 0; + + //Brunni/ Define the actual palette and custom pattern for this tile + if (gblModeColorIt) { + //Brunni/ Get the tile number (+128 if LCDC bit4 is zero) + colorItPaletteNb = tilePalList[tile]; + //Brunni/ Associated custom tile + tile = tileMapTileList[tile]; + //Brunni/ Same way as BGs => additional GB vram + if (tile >= 512) + colorItUseExtVram = 1, tile -= 512; + address = init + tile * 16 + 2*t; + } if(gbCgbMode && (flags & 0x08)) { a = bank1[address++]; b = bank1[address++]; + } else if (colorItUseExtVram) { + //Brunni/ "bank 1" (additional GB vram) + a = externalVram[address++]; + b = externalVram[address++]; } else { a = bank0[address++]; b = bank0[address++]; @@ -538,6 +671,11 @@ void gbDrawSpriteTile(int tile, int x,int y,int t, int flags, c = c + 4*palette; } else { + //Brunni/ Set the color palette + if (gblModeColorIt) + c += 4 * colorItPaletteNb; + else + //Brunni/ Normal GB behaviour (first 4 colors for the BG, etc.) c += 4; } } @@ -590,6 +728,9 @@ void gbDrawSprites(bool draw) } count++; + } else if(!size && t >= 0 && t < 8) { + gbDrawSpriteTile(tile, x-8, yc, t, flags,size,i); + count++; } } // sprite limit reached! diff --git a/src/dmg/gbGlobals.h b/src/dmg/gbGlobals.h index d214d0d3..ef9a8838 100644 --- a/src/dmg/gbGlobals.h +++ b/src/dmg/gbGlobals.h @@ -34,6 +34,8 @@ extern u8 *gbWram; extern u8 *gbMemory; extern u16 *gbLineBuffer; extern u8 *gbTAMA5ram; +//Brunni/ Used for custom tiles +extern u8 *gbExternalVram; extern u8 *gbMemoryMap[16]; @@ -85,5 +87,7 @@ extern int gbDmaTicks; extern void gbRenderLine(); extern void gbDrawSprites(bool); +//Brunni/ Needs to be called when the screen switches from "blank" to "normal" +extern void exiting_lcdc(); extern u8 (*gbSerialFunction)(u8); diff --git a/src/win32/AccelEditor.cpp b/src/win32/AccelEditor.cpp index a44aa653..1590c335 100644 --- a/src/win32/AccelEditor.cpp +++ b/src/win32/AccelEditor.cpp @@ -177,6 +177,7 @@ void AccelEditor::OnAssign() CAccelsOb* pAccel; WORD wIDCommand; POSITION pos; + int index; WORD wKey; bool bCtrl, bAlt, bShift; @@ -199,10 +200,10 @@ void AccelEditor::OnAssign() m_alreadyAffected.SetWindowText(pCmdAccel->m_szCommand); m_key.SetSel(0, -1); return; // abort - } - } - } - + } + } + } + // OK, we can add the accel key in the currently selected group index = m_commands.GetCurSel(); if (index == LB_ERR) diff --git a/src/win32/MainWnd.cpp b/src/win32/MainWnd.cpp index 0c8548d7..760d39ad 100644 --- a/src/win32/MainWnd.cpp +++ b/src/win32/MainWnd.cpp @@ -30,7 +30,7 @@ #include "Reg.h" #include "WinResUtil.h" #include "Logging.h" - +#include "../Brunni/common.h" #include "../System.h" #include "../AutoBuild.h" #include "../cheatSearch.h" @@ -54,6 +54,8 @@ static char THIS_FILE[] = __FILE__; extern void remoteCleanUp(); extern int gbHardware; +//Brunni/ Routine that checks when the configuration file has been modified +void startCheckRoutine(char *fullFileName); ///////////////////////////////////////////////////////////////////////////// // MainWnd @@ -535,6 +537,21 @@ bool MainWnd::FileRun() theApp.romSize = size; } } + + //Brunni/ Try to load the palette configuration file + VirtualFileInit(); + if (theApp.gbColorization) { + gblModeColorIt = CheckFichierPalette(theApp.szFile.GetBuffer()); + if (gblModeColorIt) { + char name[2048]; + OuvreFichierPalette(0, "init"); + _fullpath(name, gblColorItPaletteFileName, 1024); + //Brunni/ To be informed when the file changes + startCheckRoutine(name); + } + } + else + gblModeColorIt = 0; } else { int size = CPULoadRom(theApp.szFile); if(!size) @@ -1238,7 +1255,8 @@ void MainWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) } } else { theApp.wasPaused = true; - if(theApp.pauseWhenInactive) { + //Brunni/ Always disable this in ColorIt debug mode + if(theApp.pauseWhenInactive && !gblConfigAutoShowCrc) { if(emulating) { soundPause(); } diff --git a/src/win32/VBA.cpp b/src/win32/VBA.cpp index 0b091217..88a34cce 100644 --- a/src/win32/VBA.cpp +++ b/src/win32/VBA.cpp @@ -45,7 +45,7 @@ #include "../Util.h" #include "../dmg/gbGlobals.h" #include "../dmg/gbPrinter.h" - +#include "../Brunni/common.h" /* Link ---------------------*/ #include "../agb/GBALink.h" @@ -2656,3 +2656,64 @@ void Sm60FPS_Sleep() } } } + +//Brunni/ Check when the configuration file is modified +void FileCheckThread(void* fname) +{ + char *fileName; + char dirName[1024]; + + fileName = extractFilePath((char*)fname, dirName, 1); + + HANDLE hDir = CreateFile((char*)dirName, // File name + FILE_LIST_DIRECTORY, // access (read/write) mode + FILE_SHARE_READ|FILE_SHARE_DELETE, // share mode + NULL, // security descriptor + OPEN_EXISTING, // how to create + FILE_FLAG_BACKUP_SEMANTICS, // file attributes + NULL // file with attributes to copy + ); + + FILE_NOTIFY_INFORMATION Buffer[1024]; + DWORD BytesReturned; + while (ReadDirectoryChangesW( + hDir, // handle to directory + &Buffer, // read results buffer + sizeof(Buffer), // length of buffer + FALSE, // monitoring option + FILE_NOTIFY_CHANGE_SECURITY| + FILE_NOTIFY_CHANGE_CREATION| + FILE_NOTIFY_CHANGE_LAST_ACCESS| + FILE_NOTIFY_CHANGE_LAST_WRITE| + FILE_NOTIFY_CHANGE_SIZE| + FILE_NOTIFY_CHANGE_ATTRIBUTES| + FILE_NOTIFY_CHANGE_DIR_NAME| + FILE_NOTIFY_CHANGE_FILE_NAME, // filter conditions + &BytesReturned, // bytes returned + NULL, // overlapped buffer + NULL // completion routine + )) + { + int i=0; + do { + CString str = CString(Buffer[i].FileName).Left(Buffer[i].FileNameLength / 2); + if (!str.Compare(fileName)) { + //C'est le bon fichier + if (Buffer[0].Action == FILE_ACTION_MODIFIED) { + gb_lastVramCrc = 0; + exiting_lcdc(); + } + } + /* m_Sec.Lock(); + int item = pList1->InsertItem(pList1->GetItemCount(), CString(Buffer[i].FileName).Left(Buffer[i].FileNameLength / 2) + " - " + helper_txt ); + pList1->SetItemText(item, 1, tm.Format("%Y/%m/%d/ - %H:%M:%S"));*/ + // m_Sec.Unlock(); + } while (!Buffer[++i].NextEntryOffset); + } +} + +void startCheckRoutine(char *fullFileName) { + //Begin checking for an update of the file + _beginthread(FileCheckThread, 0, fullFileName); +} +