Merge branch '#374'

This commit is contained in:
BADIM-PC\Vadim 2017-11-19 18:46:20 +03:00
commit dba2665fef
6 changed files with 345 additions and 363 deletions

View File

@ -144,9 +144,9 @@ static s32 getLinesCount(Code* code)
static void removeInvalidChars(char* code)
{
// remove \r symbol
char* s; char* d;
for(s = d = code; (*d = *s); d += (*s++ != '\r'));
// remove \r symbol
char* s; char* d;
for(s = d = code; (*d = *s); d += (*s++ != '\r'));
}
static void updateEditor(Code* code)
@ -648,7 +648,7 @@ static void pageDown(Code* code)
s32 line = 0;
getCursorPosition(code, &column, &line);
s32 lines = getLinesCount(code);
setCursorPosition(code, column, line < lines - TEXT_BUFFER_HEIGHT ? line + TEXT_BUFFER_HEIGHT : lines);
setCursorPosition(code, column, line < lines - TEXT_BUFFER_HEIGHT ? line + TEXT_BUFFER_HEIGHT : lines);
}
static bool replaceSelection(Code* code)

View File

@ -62,8 +62,6 @@ static struct
.fast = false,
};
static const char CartExt[] = ".tic";
static const char DefaultLuaTicPath[] = TIC_LOCAL "default.tic";
static const char DefaultMoonTicPath[] = TIC_LOCAL "default_moon.tic";
static const char DefaultJSTicPath[] = TIC_LOCAL "default_js.tic";
@ -85,7 +83,7 @@ static const char* getName(const char* name, const char* ext)
static const char* getCartName(const char* name)
{
return getName(name, CartExt);
return getName(name, CART_EXT);
}
static void scrollBuffer(char* buffer)
@ -342,12 +340,12 @@ static bool onConsoleLoadSectionCommand(Console* console, const char* param)
for(s32 i = 0; i < COUNT_OF(Sections); i++)
{
sprintf(buf, "%s %s", CartExt, Sections[i]);
sprintf(buf, "%s %s", CART_EXT, Sections[i]);
char* pos = SDL_strstr(param, buf);
if(pos)
{
pos[sizeof(CartExt) - 1] = 0;
pos[sizeof(CART_EXT) - 1] = 0;
const char* name = getCartName(param);
s32 size = 0;
void* data = fsLoadFile(console->fs, name, &size);
@ -509,6 +507,237 @@ static void onCartLoaded(Console* console, const char* name)
}
#if defined(TIC80_PRO)
static const char* getProjectName(const char* name)
{
return getName(name, PROJECT_EXT);
}
static void buf2str(const void* data, s32 size, char* ptr, bool flip)
{
enum {Len = 2};
for(s32 i = 0; i < size; i++, ptr+=Len)
{
sprintf(ptr, "%02x", ((u8*)data)[i]);
if(flip)
{
char tmp = ptr[0];
ptr[0] = ptr[1];
ptr[1] = tmp;
}
}
}
static bool bufferEmpty(const u8* data, s32 size)
{
for(s32 i = 0; i < size; i++)
if(*data++)
return false;
return true;
}
static char* saveTextSection(char* ptr, const char* tag, const char* data)
{
if(strlen(data) == 0)
return ptr;
sprintf(ptr, "-- <%s>\n%s\n-- </%s>\n", tag, data, tag);
ptr += strlen(ptr);
return ptr;
}
static char* saveBinaryBuffer(char* ptr, const void* data, s32 size, s32 row, bool flip)
{
if(bufferEmpty(data, size))
return ptr;
sprintf(ptr, "-- %03i:", row);
ptr += strlen(ptr);
buf2str(data, size, ptr, flip);
ptr += strlen(ptr);
sprintf(ptr, "\n");
ptr += strlen(ptr);
return ptr;
}
static char* saveBinarySection(char* ptr, const char* tag, s32 count, const void* data, s32 size, bool flip)
{
if(bufferEmpty(data, size * count))
return ptr;
sprintf(ptr, "\n-- <%s>\n", tag);
ptr += strlen(ptr);
for(s32 i = 0; i < count; i++, data = (u8*)data + size)
ptr = saveBinaryBuffer(ptr, data, size, i, flip);
sprintf(ptr, "-- </%s>\n", tag);
ptr += strlen(ptr);
return ptr;
}
typedef struct {char* tag; s32 count; s32 offset; s32 size; bool flip;} BinarySection;
static const BinarySection BinarySections[] =
{
{"PALETTE", 1, offsetof(tic_cartridge, palette.data), sizeof(tic_palette), false},
{"TILES", TIC_BANK_SPRITES, offsetof(tic_cartridge, gfx.tiles), sizeof(tic_tile), true},
{"SPRITES", TIC_BANK_SPRITES, offsetof(tic_cartridge, gfx.sprites), sizeof(tic_tile), true},
{"MAP", TIC_MAP_HEIGHT, offsetof(tic_cartridge, gfx.map), TIC_MAP_WIDTH, true},
{"WAVES", ENVELOPES_COUNT, offsetof(tic_cartridge,sound.sfx.waveform.envelopes), sizeof(tic_waveform), true},
{"SFX", SFX_COUNT, offsetof(tic_cartridge, sound.sfx.data), sizeof(tic_sound_effect), true},
{"PATTERNS", MUSIC_PATTERNS, offsetof(tic_cartridge, sound.music.patterns), sizeof(tic_track_pattern), true},
{"TRACKS", MUSIC_TRACKS, offsetof(tic_cartridge, sound.music.tracks), sizeof(tic_track), true},
};
static s32 saveProject(Console* console, void* buffer)
{
tic_mem* tic = console->tic;
char* stream = buffer;
char* ptr = saveTextSection(stream, "CODE", tic->cart.code.data);
for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
{
const BinarySection* section = &BinarySections[i];
ptr = saveBinarySection(ptr, section->tag, section->count, (u8*)&tic->cart + section->offset, section->size, section->flip);
}
saveBinarySection(ptr, "COVER", 1, &tic->cart.cover, tic->cart.cover.size + sizeof(s32), true);
return strlen(stream);
}
static void loadTextSection(const char* project, const char* tag, void* dst, s32 size)
{
char tagbuf[64];
sprintf(tagbuf, "-- <%s>\n", tag);
const char* start = SDL_strstr(project, tagbuf);
if(start)
{
start += strlen(tagbuf);
if(start < project + strlen(project))
{
sprintf(tagbuf, "\n-- </%s>", tag);
const char* end = SDL_strstr(start, tagbuf);
if(end > start)
SDL_memcpy(dst, start, SDL_min(size, end - start));
}
}
}
static void loadBinarySection(const char* project, const char* tag, s32 count, void* dst, s32 size, bool flip)
{
char tagbuf[64];
sprintf(tagbuf, "-- <%s>\n", tag);
const char* start = SDL_strstr(project, tagbuf);
if(start)
{
start += strlen(tagbuf);
sprintf(tagbuf, "\n-- </%s>", tag);
const char* end = SDL_strstr(start, tagbuf);
if(end > start)
{
const char* ptr = start;
if(size > 0)
{
while(ptr < end)
{
static char lineStr[] = "999";
memcpy(lineStr, ptr + sizeof("-- ") - 1, sizeof lineStr - 1);
s32 index = SDL_atoi(lineStr);
if(index < count)
{
ptr += sizeof("-- 999:") - 1;
str2buf(ptr, size*2, (u8*)dst + size*index, flip);
ptr += size*2 + 1;
}
}
}
else
{
ptr += sizeof("-- 999:") - 1;
str2buf(ptr, end - ptr, (u8*)dst, flip);
}
}
}
}
static bool loadProject(Console* console, const char* data, s32 size, tic_cartridge* dst)
{
tic_mem* tic = console->tic;
char* project = (char*)SDL_malloc(size+1);
bool done = false;
if(project)
{
SDL_memcpy(project, data, size);
project[size] = '\0';
// remove all the '\r' chars
{
char *s, *d;
for(s = d = project; (*d = *s); d += (*s++ != '\r'));
}
tic_cartridge* cart = (tic_cartridge*)SDL_malloc(sizeof(tic_cartridge));
if(cart)
{
SDL_memset(cart, 0, sizeof(tic_cartridge));
SDL_memcpy(&cart->palette, &tic->config.palette.data, sizeof(tic_palette));
loadTextSection(project, "CODE", cart->code.data, sizeof(tic_code));
for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
{
const BinarySection* section = &BinarySections[i];
loadBinarySection(project, section->tag, section->count, (u8*)cart + section->offset, section->size, section->flip);
}
loadBinarySection(project, "COVER", 1, &cart->cover, -1, true);
SDL_memcpy(dst, cart, sizeof(tic_cartridge));
SDL_free(cart);
done = true;
}
SDL_free(project);
}
return done;
}
static bool hasExt(const char* name, const char* ext)
{
return strstr(name, ext) == name + strlen(name) - strlen(ext);
}
#endif
static void onConsoleLoadCommandConfirmed(Console* console, const char* param)
{
if(onConsoleLoadSectionCommand(console, param)) return;
@ -532,9 +761,27 @@ static void onConsoleLoadCommandConfirmed(Console* console, const char* param)
SDL_free(data);
}
else
else
{
#if defined(TIC80_PRO)
const char* name = getProjectName(param);
void* data = fsLoadFile(console->fs, name, &size);
if(data)
{
loadProject(console, data, size, &console->tic->cart);
onCartLoaded(console, name);
SDL_free(data);
}
else
{
printBack(console, "\ncart loading error");
}
#else
printBack(console, "\ncart loading error");
#endif
}
}
else printBack(console, "\ncart name is missing");
@ -1562,345 +1809,6 @@ static void onConsoleExportCommand(Console* console, const char* param)
#endif
#if defined(TIC80_PRO)
static const char* getProjectName(const char* name)
{
return getName(name, ".ticp");
}
static void buf2str(const void* data, s32 size, char* ptr, bool flip)
{
enum {Len = 2};
for(s32 i = 0; i < size; i++, ptr+=Len)
{
sprintf(ptr, "%02x", ((u8*)data)[i]);
if(flip)
{
char tmp = ptr[0];
ptr[0] = ptr[1];
ptr[1] = tmp;
}
}
}
static bool bufferEmpty(const u8* data, s32 size)
{
for(s32 i = 0; i < size; i++)
if(*data++)
return false;
return true;
}
static char* saveTextSection(char* ptr, const char* tag, const char* data)
{
if(strlen(data) == 0)
return ptr;
sprintf(ptr, "-- <%s>\n%s\n-- </%s>\n", tag, data, tag);
ptr += strlen(ptr);
return ptr;
}
static char* saveBinaryBuffer(char* ptr, const void* data, s32 size, s32 row, bool flip)
{
if(bufferEmpty(data, size))
return ptr;
sprintf(ptr, "-- %03i:", row);
ptr += strlen(ptr);
buf2str(data, size, ptr, flip);
ptr += strlen(ptr);
sprintf(ptr, "\n");
ptr += strlen(ptr);
return ptr;
}
static char* saveBinarySection(char* ptr, const char* tag, s32 count, const void* data, s32 size, bool flip)
{
if(bufferEmpty(data, size * count))
return ptr;
sprintf(ptr, "\n-- <%s>\n", tag);
ptr += strlen(ptr);
for(s32 i = 0; i < count; i++, data = (u8*)data + size)
ptr = saveBinaryBuffer(ptr, data, size, i, flip);
sprintf(ptr, "-- </%s>\n", tag);
ptr += strlen(ptr);
return ptr;
}
typedef struct {char* tag; s32 count; s32 offset; s32 size; bool flip;} BinarySection;
static const BinarySection BinarySections[] =
{
{"PALETTE", 1, offsetof(tic_cartridge, palette.data), sizeof(tic_palette), false},
{"TILES", TIC_BANK_SPRITES, offsetof(tic_cartridge, gfx.tiles), sizeof(tic_tile), true},
{"SPRITES", TIC_BANK_SPRITES, offsetof(tic_cartridge, gfx.sprites), sizeof(tic_tile), true},
{"MAP", TIC_MAP_HEIGHT, offsetof(tic_cartridge, gfx.map), TIC_MAP_WIDTH, true},
{"WAVES", ENVELOPES_COUNT, offsetof(tic_cartridge,sound.sfx.waveform.envelopes), sizeof(tic_waveform), true},
{"SFX", SFX_COUNT, offsetof(tic_cartridge, sound.sfx.data), sizeof(tic_sound_effect), true},
{"PATTERNS", MUSIC_PATTERNS, offsetof(tic_cartridge, sound.music.patterns), sizeof(tic_track_pattern), true},
{"TRACKS", MUSIC_TRACKS, offsetof(tic_cartridge, sound.music.tracks), sizeof(tic_track), true},
};
static CartSaveResult saveProject(Console* console, const char* name)
{
tic_mem* tic = console->tic;
bool success = false;
if(name && strlen(name))
{
char* stream = (char*)SDL_malloc(sizeof(tic_cartridge) * 3);
if(stream)
{
char* ptr = saveTextSection(stream, "CODE", tic->cart.code.data);
for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
{
const BinarySection* section = &BinarySections[i];
ptr = saveBinarySection(ptr, section->tag, section->count, (u8*)&tic->cart + section->offset, section->size, section->flip);
}
saveBinarySection(ptr, "COVER", 1, &tic->cart.cover, tic->cart.cover.size + sizeof(s32), true);
name = getProjectName(name);
s32 size = strlen(stream);
if(size && fsSaveFile(console->fs, name, stream, size, true))
{
strcpy(console->romName, name);
success = true;
studioRomSaved();
}
SDL_free(stream);
}
}
else if (strlen(console->romName))
{
return saveProject(console, console->romName);
}
else return CART_SAVE_MISSING_NAME;
return success ? CART_SAVE_OK : CART_SAVE_ERROR;
}
static void onConsoleSaveProjectCommandConfirmed(Console* console, const char* param)
{
CartSaveResult rom = saveProject(console, param);
if(rom == CART_SAVE_OK)
{
printBack(console, "\nproject ");
printFront(console, console->romName);
printBack(console, " saved!\n");
}
else if(rom == CART_SAVE_MISSING_NAME)
printBack(console, "\nproject name is missing\n");
else
printBack(console, "\nproject saving error");
commandDone(console);
}
static void onConsoleSaveProjectCommand(Console* console, const char* param)
{
if(param && strlen(param) && fsExistsFile(console->fs, getProjectName(param)))
{
static const char* Rows[] =
{
"THE PROJECT",
"ALREADY EXISTS",
"",
"DO YOU WANT TO",
"OVERWRITE IT?",
};
confirmCommand(console, Rows, COUNT_OF(Rows), param, onConsoleSaveProjectCommandConfirmed);
}
else
{
onConsoleSaveProjectCommandConfirmed(console, param);
}
}
static void loadTextSection(const char* project, const char* tag, void* dst, s32 size)
{
char tagbuf[64];
sprintf(tagbuf, "-- <%s>\n", tag);
const char* start = SDL_strstr(project, tagbuf);
if(start)
{
start += strlen(tagbuf);
if(start < project + strlen(project))
{
sprintf(tagbuf, "\n-- </%s>", tag);
const char* end = SDL_strstr(start, tagbuf);
if(end > start)
SDL_memcpy(dst, start, SDL_min(size, end - start));
}
}
}
static void loadBinarySection(const char* project, const char* tag, s32 count, void* dst, s32 size, bool flip)
{
char tagbuf[64];
sprintf(tagbuf, "-- <%s>\n", tag);
const char* start = SDL_strstr(project, tagbuf);
if(start)
{
start += strlen(tagbuf);
sprintf(tagbuf, "\n-- </%s>", tag);
const char* end = SDL_strstr(start, tagbuf);
if(end > start)
{
const char* ptr = start;
if(size > 0)
{
while(ptr < end)
{
static char lineStr[] = "999";
memcpy(lineStr, ptr + sizeof("-- ") - 1, sizeof lineStr - 1);
s32 index = SDL_atoi(lineStr);
if(index < count)
{
ptr += sizeof("-- 999:") - 1;
str2buf(ptr, size*2, (u8*)dst + size*index, flip);
ptr += size*2 + 1;
}
}
}
else
{
ptr += sizeof("-- 999:") - 1;
str2buf(ptr, end - ptr, (u8*)dst, flip);
}
}
}
}
static bool loadProject(Console* console, const char* data, s32 size)
{
tic_mem* tic = console->tic;
char* project = (char*)SDL_malloc(size+1);
bool done = false;
if(project)
{
SDL_memcpy(project, data, size);
project[size] = '\0';
tic_cartridge* cart = (tic_cartridge*)SDL_malloc(sizeof(tic_cartridge));
if(cart)
{
SDL_memset(cart, 0, sizeof(tic_cartridge));
SDL_memcpy(&cart->palette, &tic->config.palette.data, sizeof(tic_palette));
loadTextSection(project, "CODE", cart->code.data, sizeof(tic_code));
for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
{
const BinarySection* section = &BinarySections[i];
loadBinarySection(project, section->tag, section->count, (u8*)cart + section->offset, section->size, section->flip);
}
loadBinarySection(project, "COVER", 1, &cart->cover, -1, true);
SDL_memcpy(&tic->cart, cart, sizeof(tic_cartridge));
SDL_free(cart);
done = true;
}
SDL_free(project);
}
return done;
}
static void onConsoleLoadProjectCommandConfirmed(Console* console, const char* param)
{
if(param)
{
s32 size = 0;
const char* name = getProjectName(param);
void* data = fsLoadFile(console->fs, name, &size);
if(data && loadProject(console, data, size))
{
strcpy(console->romName, name);
studioRomLoaded();
printBack(console, "\nproject ");
printFront(console, console->romName);
printBack(console, " loaded!\nuse ");
printFront(console, "RUN");
printBack(console, " command to run it\n");
SDL_free(data);
}
else
{
printBack(console, "\nproject loading error");
}
}
else printBack(console, "\nproject name is missing");
commandDone(console);
}
static void onConsoleLoadProjectCommand(Console* console, const char* param)
{
if(studioCartChanged())
{
static const char* Rows[] =
{
"YOU HAVE",
"UNSAVED CHANGES",
"",
"DO YOU REALLY WANT",
"TO LOAD PROJECT?",
};
confirmCommand(console, Rows, COUNT_OF(Rows), param, onConsoleLoadProjectCommandConfirmed);
}
else
{
onConsoleLoadProjectCommandConfirmed(console, param);
}
}
#endif
static CartSaveResult saveCartName(Console* console, const char* name)
{
tic_mem* tic = console->tic;
@ -1909,7 +1817,7 @@ static CartSaveResult saveCartName(Console* console, const char* name)
if(name && strlen(name))
{
u8* buffer = (u8*)SDL_malloc(sizeof(tic_cartridge));
u8* buffer = (u8*)SDL_malloc(sizeof(tic_cartridge) * 3);
if(buffer)
{
@ -1922,16 +1830,25 @@ static CartSaveResult saveCartName(Console* console, const char* name)
}
else
{
s32 size = tic->api.save(&tic->cart, buffer);
s32 size = 0;
name = getCartName(name);
#if defined(TIC80_PRO)
if(hasExt(name, PROJECT_EXT))
{
size = saveProject(console, buffer);
}
else
#endif
{
name = getCartName(name);
size = tic->api.save(&tic->cart, buffer);
}
if(size && fsSaveFile(console->fs, name, buffer, size, true))
{
strcpy(console->romName, name);
success = true;
studioRomSaved();
}
}
@ -2204,10 +2121,6 @@ static const struct
{"new", NULL, "create new cart", onConsoleNewCommand},
{"load", NULL, "load cart", onConsoleLoadCommand},
{"save", NULL, "save cart", onConsoleSaveCommand},
#if defined(TIC80_PRO)
{"loadp", NULL, "load project", onConsoleLoadProjectCommand},
{"savep", NULL, "save project", onConsoleSaveProjectCommand},
#endif
{"run", NULL, "run loaded cart", onConsoleRunCommand},
{"resume", NULL, "resume run cart", onConsoleResumeCommand},
{"dir", "ls", "show list of files", onConsoleDirCommand},
@ -2660,7 +2573,17 @@ static void cmdLoadCart(Console* console, const char* name)
if(data)
{
loadCart(console->tic, &embed.file, data, size, true);
#if defined(TIC80_PRO)
if(hasExt(name, PROJECT_EXT))
{
loadProject(console, data, size, &embed.file);
}
else
#endif
{
loadCart(console->tic, &embed.file, data, size, true);
}
embed.yes = true;
SDL_free(data);
@ -2800,6 +2723,13 @@ void initConsole(Console* console, tic_mem* tic, FileSystem* fs, Config* config,
.tic = tic,
.config = config,
.load = onConsoleLoadCommandConfirmed,
#if defined(TIC80_PRO)
.loadProject = loadProject,
#else
.loadProject = NULL,
#endif
.error = error,
.trace = trace,
.tick = tick,

View File

@ -90,6 +90,7 @@ struct Console
bool showGameMenu;
void(*load)(Console*, const char* name);
bool(*loadProject)(Console*, const char* data, s32 size, tic_cartridge* dst);
void(*error)(Console*, const char*);
void(*trace)(Console*, const char*, u8 color);
void(*tick)(Console*);

View File

@ -60,6 +60,9 @@
#define KEYMAP_DAT "keymap.dat"
#define KEYMAP_DAT_PATH TIC_LOCAL KEYMAP_DAT
#define CART_EXT ".tic"
#define PROJECT_EXT ".ticp"
typedef struct
{
struct

View File

@ -155,6 +155,7 @@ struct MenuItem
s32 id;
tic_screen* cover;
bool dir;
bool project;
};
typedef struct
@ -372,13 +373,29 @@ static void replace(char* src, const char* what, const char* with)
}
}
static bool hasExt(const char* name, const char* ext)
{
return strstr(name, ext) == name + strlen(name) - strlen(ext);
}
static void cutExt(char* name, const char* ext)
{
name[strlen(name)-strlen(ext)] = '\0';
}
static bool addMenuItem(const char* name, const char* info, s32 id, void* ptr, bool dir)
{
AddMenuItem* data = (AddMenuItem*)ptr;
static const char CartExt[] = ".tic";
static const char CartExt[] = CART_EXT;
static const char ProjectExt[] = PROJECT_EXT;
if(dir || (strstr(name, CartExt) == name + strlen(name) - sizeof(CartExt)+1))
if(dir
|| hasExt(name, CartExt)
#if defined(TIC80_PRO)
|| hasExt(name, ProjectExt)
#endif
)
{
MenuItem* item = &data->items[data->count++];
@ -394,7 +411,15 @@ static bool addMenuItem(const char* name, const char* info, s32 id, void* ptr, b
{
item->label = SDL_strdup(name);
item->label[strlen(item->label)-sizeof(CartExt)+1] = '\0';
if(hasExt(name, CartExt))
cutExt(item->label, CartExt);
else
{
cutExt(item->label, ProjectExt);
item->project = true;
}
replace(item->label, "&amp;", "&");
replace(item->label, "&#39;", "'");
@ -509,7 +534,10 @@ static void loadCover(Surf* surf)
if(cart)
{
tic->api.load(cart, data, size, true);
if(hasExt(item->name, PROJECT_EXT))
surf->console->loadProject(surf->console, data, size, cart);
else
tic->api.load(cart, data, size, true);
if(cart->cover.size)
updateMenuItemCover(surf, cart->cover.data, cart->cover.size);
@ -617,7 +645,26 @@ static void onPlayCart(Surf* surf)
{
MenuItem* item = &surf->menu.items[surf->menu.pos];
surf->console->load(surf->console, item->name);
if(item->project)
{
tic_cartridge* cart = SDL_malloc(sizeof(tic_cartridge));
if(cart)
{
s32 size = 0;
void* data = fsLoadFile(surf->fs, item->name, &size);
surf->console->loadProject(surf->console, data, size, cart);
SDL_memcpy(&surf->tic->cart, cart, sizeof(tic_cartridge));
studioRomLoaded();
SDL_free(cart);
}
}
else
surf->console->load(surf->console, item->name);
runGameFromSurf();
}

View File

@ -153,6 +153,7 @@ static void setPixel(tic_machine* machine, s32 x, s32 y, u8 color)
{
if(x < machine->state.clip.l || y < machine->state.clip.t || x >= machine->state.clip.r || y >= machine->state.clip.b) return;
// TODO: check color bounds here
tic_tool_poke4(machine->memory.ram.vram.screen.data, y * TIC80_WIDTH + x, tic_tool_peek4(machine->memory.ram.vram.mapping, color));
}