Merge branch '#374'
This commit is contained in:
		
							
								
								
									
										632
									
								
								src/console.c
									
									
									
									
									
								
							
							
						
						
									
										632
									
								
								src/console.c
									
									
									
									
									
								
							@@ -62,8 +62,6 @@ static struct
 | 
				
			|||||||
	.fast = false,
 | 
						.fast = false,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char CartExt[] = ".tic";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char DefaultLuaTicPath[] = TIC_LOCAL "default.tic";
 | 
					static const char DefaultLuaTicPath[] = TIC_LOCAL "default.tic";
 | 
				
			||||||
static const char DefaultMoonTicPath[] = TIC_LOCAL "default_moon.tic";
 | 
					static const char DefaultMoonTicPath[] = TIC_LOCAL "default_moon.tic";
 | 
				
			||||||
static const char DefaultJSTicPath[] = TIC_LOCAL "default_js.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)
 | 
					static const char* getCartName(const char* name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return getName(name, CartExt);
 | 
						return getName(name, CART_EXT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void scrollBuffer(char* buffer)
 | 
					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++)
 | 
							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);
 | 
								char* pos = SDL_strstr(param, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(pos)
 | 
								if(pos)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				pos[sizeof(CartExt) - 1] = 0;
 | 
									pos[sizeof(CART_EXT) - 1] = 0;
 | 
				
			||||||
				const char* name = getCartName(param);
 | 
									const char* name = getCartName(param);
 | 
				
			||||||
				s32 size = 0;
 | 
									s32 size = 0;
 | 
				
			||||||
				void* data = fsLoadFile(console->fs, name, &size);
 | 
									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)
 | 
					static void onConsoleLoadCommandConfirmed(Console* console, const char* param)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(onConsoleLoadSectionCommand(console, param)) return;
 | 
						if(onConsoleLoadSectionCommand(console, param)) return;
 | 
				
			||||||
@@ -534,8 +763,26 @@ static void onConsoleLoadCommandConfirmed(Console* console, const char* param)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		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");
 | 
									printBack(console, "\ncart loading error");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
								printBack(console, "\ncart loading error");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else printBack(console, "\ncart name is missing");
 | 
						else printBack(console, "\ncart name is missing");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1562,345 +1809,6 @@ static void onConsoleExportCommand(Console* console, const char* param)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#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)
 | 
					static CartSaveResult saveCartName(Console* console, const char* name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tic_mem* tic = console->tic;
 | 
						tic_mem* tic = console->tic;
 | 
				
			||||||
@@ -1909,7 +1817,7 @@ static CartSaveResult saveCartName(Console* console, const char* name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if(name && strlen(name))
 | 
						if(name && strlen(name))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		u8* buffer = (u8*)SDL_malloc(sizeof(tic_cartridge));
 | 
							u8* buffer = (u8*)SDL_malloc(sizeof(tic_cartridge) * 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(buffer)
 | 
							if(buffer)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -1922,16 +1830,25 @@ static CartSaveResult saveCartName(Console* console, const char* name)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				s32 size = tic->api.save(&tic->cart, buffer);
 | 
									s32 size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TIC80_PRO)
 | 
				
			||||||
 | 
									if(hasExt(name, PROJECT_EXT))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										size = saveProject(console, buffer);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
					#endif					
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
					name = getCartName(name);
 | 
										name = getCartName(name);
 | 
				
			||||||
 | 
										size = tic->api.save(&tic->cart, buffer);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(size && fsSaveFile(console->fs, name, buffer, size, true))
 | 
									if(size && fsSaveFile(console->fs, name, buffer, size, true))
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					strcpy(console->romName, name);
 | 
										strcpy(console->romName, name);
 | 
				
			||||||
					success = true;
 | 
										success = true;
 | 
				
			||||||
					studioRomSaved();
 | 
										studioRomSaved();
 | 
				
			||||||
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2204,10 +2121,6 @@ static const struct
 | 
				
			|||||||
	{"new", 	NULL, "create new cart",			onConsoleNewCommand},
 | 
						{"new", 	NULL, "create new cart",			onConsoleNewCommand},
 | 
				
			||||||
	{"load", 	NULL, "load cart", 					onConsoleLoadCommand},
 | 
						{"load", 	NULL, "load cart", 					onConsoleLoadCommand},
 | 
				
			||||||
	{"save", 	NULL, "save cart",	 				onConsoleSaveCommand},
 | 
						{"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},
 | 
						{"run",		NULL, "run loaded cart",			onConsoleRunCommand},
 | 
				
			||||||
	{"resume",	NULL, "resume run cart",			onConsoleResumeCommand},
 | 
						{"resume",	NULL, "resume run cart",			onConsoleResumeCommand},
 | 
				
			||||||
	{"dir",		"ls", "show list of files", 		onConsoleDirCommand},
 | 
						{"dir",		"ls", "show list of files", 		onConsoleDirCommand},
 | 
				
			||||||
@@ -2659,8 +2572,18 @@ static void cmdLoadCart(Console* console, const char* name)
 | 
				
			|||||||
	void* data = fsReadFile(name, &size);
 | 
						void* data = fsReadFile(name, &size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(data)
 | 
						if(data)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
					#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);
 | 
								loadCart(console->tic, &embed.file, data, size, true);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		embed.yes = true;
 | 
							embed.yes = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		SDL_free(data);
 | 
							SDL_free(data);
 | 
				
			||||||
@@ -2800,6 +2723,13 @@ void initConsole(Console* console, tic_mem* tic, FileSystem* fs, Config* config,
 | 
				
			|||||||
		.tic = tic,
 | 
							.tic = tic,
 | 
				
			||||||
		.config = config,
 | 
							.config = config,
 | 
				
			||||||
		.load = onConsoleLoadCommandConfirmed,
 | 
							.load = onConsoleLoadCommandConfirmed,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TIC80_PRO)
 | 
				
			||||||
 | 
							.loadProject = loadProject,
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
							.loadProject = NULL,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		.error = error,
 | 
							.error = error,
 | 
				
			||||||
		.trace = trace,
 | 
							.trace = trace,
 | 
				
			||||||
		.tick = tick,
 | 
							.tick = tick,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,6 +90,7 @@ struct Console
 | 
				
			|||||||
	bool showGameMenu;
 | 
						bool showGameMenu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void(*load)(Console*, const char* name);
 | 
						void(*load)(Console*, const char* name);
 | 
				
			||||||
 | 
						bool(*loadProject)(Console*, const char* data, s32 size, tic_cartridge* dst);
 | 
				
			||||||
	void(*error)(Console*, const char*);
 | 
						void(*error)(Console*, const char*);
 | 
				
			||||||
	void(*trace)(Console*, const char*, u8 color);
 | 
						void(*trace)(Console*, const char*, u8 color);
 | 
				
			||||||
	void(*tick)(Console*);
 | 
						void(*tick)(Console*);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,6 +60,9 @@
 | 
				
			|||||||
#define KEYMAP_DAT "keymap.dat"
 | 
					#define KEYMAP_DAT "keymap.dat"
 | 
				
			||||||
#define KEYMAP_DAT_PATH TIC_LOCAL KEYMAP_DAT
 | 
					#define KEYMAP_DAT_PATH TIC_LOCAL KEYMAP_DAT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CART_EXT ".tic"
 | 
				
			||||||
 | 
					#define PROJECT_EXT ".ticp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct
 | 
						struct
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										53
									
								
								src/surf.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								src/surf.c
									
									
									
									
									
								
							@@ -155,6 +155,7 @@ struct MenuItem
 | 
				
			|||||||
	s32 id;
 | 
						s32 id;
 | 
				
			||||||
	tic_screen* cover;
 | 
						tic_screen* cover;
 | 
				
			||||||
	bool dir;
 | 
						bool dir;
 | 
				
			||||||
 | 
						bool project;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					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)
 | 
					static bool addMenuItem(const char* name, const char* info, s32 id, void* ptr, bool dir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	AddMenuItem* data = (AddMenuItem*)ptr;
 | 
						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++];
 | 
							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 = 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, "&", "&");
 | 
								replace(item->label, "&", "&");
 | 
				
			||||||
			replace(item->label, "'", "'");
 | 
								replace(item->label, "'", "'");
 | 
				
			||||||
@@ -509,6 +534,9 @@ static void loadCover(Surf* surf)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if(cart)
 | 
								if(cart)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 | 
									if(hasExt(item->name, PROJECT_EXT))
 | 
				
			||||||
 | 
										surf->console->loadProject(surf->console, data, size, cart);
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
					tic->api.load(cart, data, size, true);
 | 
										tic->api.load(cart, data, size, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(cart->cover.size)
 | 
									if(cart->cover.size)
 | 
				
			||||||
@@ -617,6 +645,25 @@ static void onPlayCart(Surf* surf)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	MenuItem* item = &surf->menu.items[surf->menu.pos];
 | 
						MenuItem* item = &surf->menu.items[surf->menu.pos];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
							surf->console->load(surf->console, item->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	runGameFromSurf();
 | 
						runGameFromSurf();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
						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));
 | 
						tic_tool_poke4(machine->memory.ram.vram.screen.data, y * TIC80_WIDTH + x, tic_tool_peek4(machine->memory.ram.vram.mapping, color));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user