Merge branch '#341'
This commit is contained in:
		
							
								
								
									
										125
									
								
								src/console.c
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								src/console.c
									
									
									
									
									
								
							@@ -565,6 +565,22 @@ static char* saveTextSection(char* ptr, const char* data)
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char* saveTextSectionBank(char* ptr, const char* comment, const char* tag, const char* data)
 | 
			
		||||
{
 | 
			
		||||
	if(strlen(data) == 0)
 | 
			
		||||
		return ptr;
 | 
			
		||||
 | 
			
		||||
	sprintf(ptr, "%s <%s>\n", comment, tag);
 | 
			
		||||
	ptr += strlen(ptr);
 | 
			
		||||
 | 
			
		||||
	ptr = saveTextSection(ptr, data);
 | 
			
		||||
 | 
			
		||||
	sprintf(ptr, "%s </%s>\n\n", comment, tag);
 | 
			
		||||
	ptr += strlen(ptr);
 | 
			
		||||
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char* saveBinaryBuffer(char* ptr, const char* comment, const void* data, s32 size, s32 row, bool flip)
 | 
			
		||||
{
 | 
			
		||||
	if(bufferEmpty(data, size)) 
 | 
			
		||||
@@ -599,38 +615,58 @@ static char* saveBinarySection(char* ptr, const char* comment, const char* tag,
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {char* tag; s32 count; s32 offset; s32 size; bool flip;} BinarySection;
 | 
			
		||||
typedef struct {char* tag; s32 count; s32 offset; s32 size;} BinarySection;
 | 
			
		||||
static const BinarySection BinarySections[] = 
 | 
			
		||||
{
 | 
			
		||||
	{"PALETTE", 	1, 					offsetof(tic_cartridge, palette.data), 					sizeof(tic_palette), false},
 | 
			
		||||
	{"TILES", 		TIC_BANK_SPRITES, 	offsetof(tic_cartridge, bank0.tiles), 					sizeof(tic_tile), true},
 | 
			
		||||
	{"SPRITES", 	TIC_BANK_SPRITES, 	offsetof(tic_cartridge, bank0.sprites), 				sizeof(tic_tile), true},
 | 
			
		||||
	{"MAP", 		TIC_MAP_HEIGHT, 	offsetof(tic_cartridge, bank0.map), 					TIC_MAP_WIDTH, true},
 | 
			
		||||
	{"WAVES", 		ENVELOPES_COUNT, 	offsetof(tic_cartridge, bank0.sfx.waveform.envelopes), 	sizeof(tic_waveform), true},
 | 
			
		||||
	{"SFX", 		SFX_COUNT, 			offsetof(tic_cartridge, bank0.sfx.data), 				sizeof(tic_sound_effect), true},
 | 
			
		||||
	{"PATTERNS", 	MUSIC_PATTERNS, 	offsetof(tic_cartridge, bank0.music.patterns), 			sizeof(tic_track_pattern), true},
 | 
			
		||||
	{"TRACKS", 		MUSIC_TRACKS, 		offsetof(tic_cartridge, bank0.music.tracks), 			sizeof(tic_track), true},
 | 
			
		||||
	{"TILES", 		TIC_BANK_SPRITES, 	offsetof(tic_bank, tiles), 			sizeof(tic_tile)},
 | 
			
		||||
	{"SPRITES", 	TIC_BANK_SPRITES, 	offsetof(tic_bank, sprites), 		sizeof(tic_tile)},
 | 
			
		||||
	{"MAP", 		TIC_MAP_HEIGHT, 	offsetof(tic_bank, map), 			TIC_MAP_WIDTH},
 | 
			
		||||
	{"WAVES", 		ENVELOPES_COUNT, 	offsetof(tic_bank, sfx.waveform), 	sizeof(tic_waveform)},
 | 
			
		||||
	{"SFX", 		SFX_COUNT, 			offsetof(tic_bank, sfx.samples), 	sizeof(tic_sample)},
 | 
			
		||||
	{"PATTERNS", 	MUSIC_PATTERNS, 	offsetof(tic_bank, music.patterns), sizeof(tic_track_pattern)},
 | 
			
		||||
	{"TRACKS", 		MUSIC_TRACKS, 		offsetof(tic_bank, music.tracks), 	sizeof(tic_track)},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void makeTag(const char* tag, char* out, s32 bank)
 | 
			
		||||
{
 | 
			
		||||
	if(bank) sprintf(out, "%s%i", tag, bank);
 | 
			
		||||
	else strcpy(out, tag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static s32 saveProject(Console* console, void* buffer, const char* comment)
 | 
			
		||||
{
 | 
			
		||||
	tic_mem* tic = console->tic;
 | 
			
		||||
 | 
			
		||||
	char* stream = buffer;
 | 
			
		||||
	char* ptr = saveTextSection(stream, tic->cart.bank0.code.data);
 | 
			
		||||
	char tag[16];
 | 
			
		||||
 | 
			
		||||
	for(s32 b = 1; b < TIC_BANKS; b++)
 | 
			
		||||
	{
 | 
			
		||||
		makeTag("CODE", tag, b);
 | 
			
		||||
		ptr = saveTextSectionBank(ptr, comment, tag, tic->cart.banks[b].code.data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
 | 
			
		||||
	{
 | 
			
		||||
		const BinarySection* section = &BinarySections[i];
 | 
			
		||||
		ptr = saveBinarySection(ptr, comment, section->tag, section->count, (u8*)&tic->cart + section->offset, section->size, section->flip);
 | 
			
		||||
 | 
			
		||||
		for(s32 b = 0; b < TIC_BANKS; b++)
 | 
			
		||||
		{
 | 
			
		||||
			makeTag(section->tag, tag, b);
 | 
			
		||||
 | 
			
		||||
			ptr = saveBinarySection(ptr, comment, tag, section->count, 
 | 
			
		||||
				(u8*)&tic->cart.banks[b] + section->offset, section->size, true);
 | 
			
		||||
		}
 | 
			
		||||
	}		
 | 
			
		||||
 | 
			
		||||
	saveBinarySection(ptr, comment, "COVER", 1, &tic->cart.cover, tic->cart.cover.size + sizeof(s32), true);
 | 
			
		||||
	ptr = saveBinarySection(ptr, comment, "PALETTE", 1, &tic->cart.palette, sizeof(tic_palette), false);
 | 
			
		||||
	ptr = saveBinarySection(ptr, comment, "COVER", 1, &tic->cart.cover, tic->cart.cover.size + sizeof(s32), true);
 | 
			
		||||
 | 
			
		||||
	return strlen(stream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool loadTextSection(const char* project, const char* comment, void* dst, s32 size)
 | 
			
		||||
static bool loadTextSection(const char* project, const char* comment, char* dst, s32 size)
 | 
			
		||||
{
 | 
			
		||||
	bool done = false;
 | 
			
		||||
 | 
			
		||||
@@ -639,10 +675,25 @@ static bool loadTextSection(const char* project, const char* comment, void* dst,
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		char tagbuf[64];
 | 
			
		||||
		char tag[16];
 | 
			
		||||
 | 
			
		||||
		for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
 | 
			
		||||
		{
 | 
			
		||||
			sprintf(tagbuf, "\n%s <%s>\n", comment, BinarySections[i].tag);
 | 
			
		||||
			for(s32 b = 0; b < TIC_BANKS; b++)
 | 
			
		||||
			{
 | 
			
		||||
				makeTag(BinarySections[i].tag, tag, b);
 | 
			
		||||
 | 
			
		||||
				sprintf(tagbuf, "\n%s <%s>\n", comment, tag);
 | 
			
		||||
 | 
			
		||||
				const char* ptr = SDL_strstr(project, tagbuf);
 | 
			
		||||
 | 
			
		||||
				if(ptr && ptr < end)
 | 
			
		||||
					end = ptr;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		{
 | 
			
		||||
			sprintf(tagbuf, "\n%s <PALETTE>\n", comment);
 | 
			
		||||
 | 
			
		||||
			const char* ptr = SDL_strstr(project, tagbuf);
 | 
			
		||||
 | 
			
		||||
@@ -660,6 +711,32 @@ static bool loadTextSection(const char* project, const char* comment, void* dst,
 | 
			
		||||
	return done;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool loadTextSectionBank(const char* project, const char* comment, const char* tag, char* dst, s32 size)
 | 
			
		||||
{
 | 
			
		||||
	char tagbuf[64];
 | 
			
		||||
	sprintf(tagbuf, "%s <%s>\n", comment, tag);
 | 
			
		||||
 | 
			
		||||
	const char* start = SDL_strstr(project, tagbuf);
 | 
			
		||||
	bool done = false;
 | 
			
		||||
 | 
			
		||||
	if(start)
 | 
			
		||||
	{
 | 
			
		||||
		start += strlen(tagbuf);
 | 
			
		||||
 | 
			
		||||
		sprintf(tagbuf, "\n%s </%s>", comment, tag);
 | 
			
		||||
		const char* end = SDL_strstr(start, tagbuf);
 | 
			
		||||
 | 
			
		||||
		if(end > start)
 | 
			
		||||
		{
 | 
			
		||||
			SDL_memcpy(dst, start, SDL_min(size, end - start));
 | 
			
		||||
			
 | 
			
		||||
			done = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return done;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool loadBinarySection(const char* project, const char* comment, const char* tag, s32 count, void* dst, s32 size, bool flip)
 | 
			
		||||
{
 | 
			
		||||
	char tagbuf[64];
 | 
			
		||||
@@ -737,16 +814,34 @@ static bool loadProject(Console* console, const char* name, const char* data, s3
 | 
			
		||||
			SDL_memcpy(&cart->palette, &tic->config.palette.data, sizeof(tic_palette));
 | 
			
		||||
 | 
			
		||||
			const char* comment = projectComment(name);
 | 
			
		||||
			char tag[16];
 | 
			
		||||
 | 
			
		||||
			if(loadTextSection(project, comment, cart->bank0.code.data, sizeof(tic_code)))
 | 
			
		||||
				done = true;
 | 
			
		||||
 | 
			
		||||
			for(s32 b = 1; b < TIC_BANKS; b++)
 | 
			
		||||
			{
 | 
			
		||||
				makeTag("CODE", tag, b);
 | 
			
		||||
 | 
			
		||||
				if(loadTextSectionBank(project, comment, tag, cart->banks[b].code.data, sizeof(tic_code)))
 | 
			
		||||
					done = true;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for(s32 i = 0; i < COUNT_OF(BinarySections); i++)
 | 
			
		||||
			{
 | 
			
		||||
				const BinarySection* section = &BinarySections[i];
 | 
			
		||||
				if(loadBinarySection(project, comment, section->tag, section->count, (u8*)cart + section->offset, section->size, section->flip))
 | 
			
		||||
 | 
			
		||||
				for(s32 b = 0; b < TIC_BANKS; b++)
 | 
			
		||||
				{
 | 
			
		||||
					makeTag(section->tag, tag, b);
 | 
			
		||||
 | 
			
		||||
					if(loadBinarySection(project, comment, tag, section->count, (u8*)&cart->banks[b] + section->offset, section->size, true))
 | 
			
		||||
						done = true;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if(loadBinarySection(project, comment, "PALETTE", 1, &cart->palette, sizeof(tic_palette), false))
 | 
			
		||||
				done = true;
 | 
			
		||||
 | 
			
		||||
			if(loadBinarySection(project, comment, "COVER", 1, &cart->cover, -1, true))
 | 
			
		||||
				done = true;
 | 
			
		||||
@@ -2143,7 +2238,7 @@ static void onConsoleRamCommand(Console* console, const char* param)
 | 
			
		||||
		{offsetof(tic_ram, persistent), 				"PERSISTENT MEMORY"},
 | 
			
		||||
		{offsetof(tic_ram, registers), 					"SOUND REGISTERS"},
 | 
			
		||||
		{offsetof(tic_ram, sfx.waveform), 				"WAVEFORMS"},
 | 
			
		||||
		{offsetof(tic_ram, sfx.data), 					"SFX"},
 | 
			
		||||
		{offsetof(tic_ram, sfx.samples),				"SFX"},
 | 
			
		||||
		{offsetof(tic_ram, music.patterns.data), 		"MUSIC PATTERNS"},
 | 
			
		||||
		{offsetof(tic_ram, music.tracks.data), 			"MUSIC TRACKS"},
 | 
			
		||||
		{offsetof(tic_ram, music_pos), 					"MUSIC POS"},
 | 
			
		||||
 
 | 
			
		||||
@@ -257,7 +257,7 @@ static duk_ret_t duk_sfx(duk_context* duk)
 | 
			
		||||
	{
 | 
			
		||||
		if(index >= 0)
 | 
			
		||||
		{
 | 
			
		||||
			tic_sound_effect* effect = memory->ram.sfx.data + index;
 | 
			
		||||
			tic_sample* effect = memory->ram.sfx.samples.data + index;
 | 
			
		||||
 | 
			
		||||
			note = effect->note;
 | 
			
		||||
			octave = effect->octave;
 | 
			
		||||
@@ -703,9 +703,9 @@ static duk_ret_t duk_sync(duk_context* duk)
 | 
			
		||||
{
 | 
			
		||||
	tic_mem* memory = (tic_mem*)getDukMachine(duk);
 | 
			
		||||
 | 
			
		||||
	bool toCart = duk_is_null_or_undefined(duk, 0) ? true : duk_to_boolean(duk, 0);
 | 
			
		||||
	const char* section = duk_is_null_or_undefined(duk, 1) ? NULL : duk_to_string(duk, 1);
 | 
			
		||||
	s32 bank = duk_is_null_or_undefined(duk, 2) ? 0 : duk_to_int(duk, 2);
 | 
			
		||||
	const char* section = duk_is_null_or_undefined(duk, 0) ? NULL : duk_to_string(duk, 0);
 | 
			
		||||
	s32 bank = duk_is_null_or_undefined(duk, 1) ? 0 : duk_to_int(duk, 1);
 | 
			
		||||
	bool toCart = duk_is_null_or_undefined(duk, 2) ? false : duk_to_boolean(duk, 2);
 | 
			
		||||
 | 
			
		||||
	if(bank >= 0 && bank < TIC_BANKS)
 | 
			
		||||
		memory->api.sync(memory, section, bank, toCart);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/luaapi.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/luaapi.c
									
									
									
									
									
								
							@@ -682,7 +682,7 @@ static s32 lua_sfx(lua_State* lua)
 | 
			
		||||
		{
 | 
			
		||||
			if (index >= 0)
 | 
			
		||||
			{
 | 
			
		||||
				tic_sound_effect* effect = memory->ram.sfx.data + index;
 | 
			
		||||
				tic_sample* effect = memory->ram.sfx.samples.data + index;
 | 
			
		||||
 | 
			
		||||
				note = effect->note;
 | 
			
		||||
				octave = effect->octave;
 | 
			
		||||
@@ -747,21 +747,21 @@ static s32 lua_sync(lua_State* lua)
 | 
			
		||||
{
 | 
			
		||||
	tic_mem* memory = (tic_mem*)getLuaMachine(lua);
 | 
			
		||||
 | 
			
		||||
	bool toCart = true;
 | 
			
		||||
	bool toCart = false;
 | 
			
		||||
	const char* section = NULL;
 | 
			
		||||
	s32 bank = 0;
 | 
			
		||||
 | 
			
		||||
	if(lua_gettop(lua) >= 1)
 | 
			
		||||
	{
 | 
			
		||||
		toCart = lua_toboolean(lua, 1);
 | 
			
		||||
		section = lua_tostring(lua, 1);
 | 
			
		||||
 | 
			
		||||
		if(lua_gettop(lua) >= 2)
 | 
			
		||||
		{
 | 
			
		||||
			section = lua_tostring(lua, 2);
 | 
			
		||||
			bank = getLuaNumber(lua, 2);
 | 
			
		||||
 | 
			
		||||
			if(lua_gettop(lua) >= 3)
 | 
			
		||||
			{
 | 
			
		||||
				bank = getLuaNumber(lua, 3);
 | 
			
		||||
				toCart = lua_toboolean(lua, 3);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								src/sfx.c
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								src/sfx.c
									
									
									
									
									
								
							@@ -104,9 +104,9 @@ static void drawSwitch(Sfx* sfx, s32 x, s32 y, const char* label, s32 value, voi
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static tic_sound_effect* getEffect(Sfx* sfx)
 | 
			
		||||
static tic_sample* getEffect(Sfx* sfx)
 | 
			
		||||
{
 | 
			
		||||
	return sfx->src->data + sfx->index;
 | 
			
		||||
	return sfx->src->samples.data + sfx->index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void setIndex(Sfx* sfx, s32 delta)
 | 
			
		||||
@@ -116,7 +116,7 @@ static void setIndex(Sfx* sfx, s32 delta)
 | 
			
		||||
 | 
			
		||||
static void setSpeed(Sfx* sfx, s32 delta)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	effect->speed += delta;
 | 
			
		||||
 | 
			
		||||
@@ -129,14 +129,14 @@ static void drawTopPanel(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
	drawSwitch(sfx, x, y, "IDX", sfx->index, setIndex);
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	drawSwitch(sfx, x += Gap, y, "SPD", effect->speed, setSpeed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void setLoopStart(Sfx* sfx, s32 delta)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
	tic_sound_loop* loop = effect->loops + sfx->canvasTab;
 | 
			
		||||
 | 
			
		||||
	loop->start += delta;
 | 
			
		||||
@@ -146,7 +146,7 @@ static void setLoopStart(Sfx* sfx, s32 delta)
 | 
			
		||||
 | 
			
		||||
static void setLoopSize(Sfx* sfx, s32 delta)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
	tic_sound_loop* loop = effect->loops + sfx->canvasTab;
 | 
			
		||||
 | 
			
		||||
	loop->size += delta;
 | 
			
		||||
@@ -160,7 +160,7 @@ static void drawLoopPanel(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
	enum {Gap = 2};
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
	tic_sound_loop* loop = effect->loops + sfx->canvasTab;
 | 
			
		||||
 | 
			
		||||
	drawSwitch(sfx, x, y += Gap + TIC_FONT_HEIGHT, "", loop->size, setLoopSize);
 | 
			
		||||
@@ -248,7 +248,7 @@ static void drawWaveButtons(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
				if(checkMouseClick(&iconRect, SDL_BUTTON_LEFT))
 | 
			
		||||
				{
 | 
			
		||||
					tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
					tic_sample* effect = getEffect(sfx);
 | 
			
		||||
					for(s32 c = 0; c < SFX_TICKS; c++)
 | 
			
		||||
						effect->data[c].wave = i;
 | 
			
		||||
				}
 | 
			
		||||
@@ -270,7 +270,7 @@ static void drawWaveButtons(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
	// draw full icon
 | 
			
		||||
	{
 | 
			
		||||
		tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
		tic_sample* effect = getEffect(sfx);
 | 
			
		||||
		u8 start = effect->data[0].wave;
 | 
			
		||||
		bool full = true;
 | 
			
		||||
		for(s32 c = 1; c < SFX_TICKS; c++)
 | 
			
		||||
@@ -310,7 +310,7 @@ static void drawCanvasTabs(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
		sfx->tic->api.text(sfx->tic, Labels[i], rect.x, rect.y, i == sfx->canvasTab ? (tic_color_white) : (tic_color_dark_gray));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	switch(sfx->canvasTab)
 | 
			
		||||
	{
 | 
			
		||||
@@ -372,7 +372,7 @@ static void drawCanvas(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
	SDL_Rect rect = {x, y, CANVAS_WIDTH, CANVAS_HEIGHT};
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	if(checkMousePos(&rect))
 | 
			
		||||
	{
 | 
			
		||||
@@ -447,7 +447,7 @@ static void drawCanvas(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
static void drawPiano(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	static const s32 ButtonIndixes[] = {0, 2, 4, 5, 7, 9, 11, 1, 3, -1, 6, 8, 10};
 | 
			
		||||
 | 
			
		||||
@@ -514,7 +514,7 @@ static void drawPiano(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
 | 
			
		||||
static void drawOctavePanel(Sfx* sfx, s32 x, s32 y)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	static const char Label[] = "OCT";
 | 
			
		||||
	sfx->tic->api.text(sfx->tic, Label, x, y, (tic_color_white));
 | 
			
		||||
@@ -545,7 +545,7 @@ static void playSound(Sfx* sfx)
 | 
			
		||||
{
 | 
			
		||||
	if(sfx->play.active)
 | 
			
		||||
	{
 | 
			
		||||
		tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
		tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
		if(sfx->play.note != effect->note)
 | 
			
		||||
		{
 | 
			
		||||
@@ -573,8 +573,8 @@ static void redo(Sfx* sfx)
 | 
			
		||||
 | 
			
		||||
static void copyToClipboard(Sfx* sfx)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	toClipboard(effect, sizeof(tic_sound_effect), true);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
	toClipboard(effect, sizeof(tic_sample), true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void copyWaveToClipboard(Sfx* sfx)
 | 
			
		||||
@@ -585,8 +585,8 @@ static void copyWaveToClipboard(Sfx* sfx)
 | 
			
		||||
 | 
			
		||||
static void resetSfx(Sfx* sfx)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	memset(effect, 0, sizeof(tic_sound_effect));
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
	memset(effect, 0, sizeof(tic_sample));
 | 
			
		||||
 | 
			
		||||
	history_add(sfx->history);
 | 
			
		||||
}
 | 
			
		||||
@@ -613,9 +613,9 @@ static void cutWaveToClipboard(Sfx* sfx)
 | 
			
		||||
 | 
			
		||||
static void copyFromClipboard(Sfx* sfx)
 | 
			
		||||
{
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	if(fromClipboard(effect, sizeof(tic_sound_effect), true, false))
 | 
			
		||||
	if(fromClipboard(effect, sizeof(tic_sample), true, false))
 | 
			
		||||
		history_add(sfx->history);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -660,7 +660,7 @@ static void processKeyboard(Sfx* sfx)
 | 
			
		||||
				keyboardButton = i;        
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	if(keyboardButton >= 0)
 | 
			
		||||
	{
 | 
			
		||||
@@ -808,7 +808,7 @@ static void drawSfxToolbar(Sfx* sfx)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tic_sound_effect* effect = getEffect(sfx);
 | 
			
		||||
	tic_sample* effect = getEffect(sfx);
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		static const char* Notes[] = SFX_NOTES;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										76
									
								
								src/studio.c
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								src/studio.c
									
									
									
									
									
								
							@@ -204,12 +204,12 @@ static struct
 | 
			
		||||
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
		Code* 	code 	[TIC_EDITOR_BANKS];
 | 
			
		||||
		Sprite* sprite 	[TIC_EDITOR_BANKS];
 | 
			
		||||
		Map* 	map 	[TIC_EDITOR_BANKS];
 | 
			
		||||
		Sfx* 	sfx 	[TIC_EDITOR_BANKS];
 | 
			
		||||
		Music* 	music 	[TIC_EDITOR_BANKS];
 | 
			
		||||
	} editor;
 | 
			
		||||
		Code* 	code;
 | 
			
		||||
		Sprite* sprite;
 | 
			
		||||
		Map* 	map;
 | 
			
		||||
		Sfx* 	sfx;
 | 
			
		||||
		Music* 	music;
 | 
			
		||||
	} editor[TIC_EDITOR_BANKS];
 | 
			
		||||
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
@@ -332,7 +332,7 @@ tic_map* getBankMap()
 | 
			
		||||
 | 
			
		||||
void playSystemSfx(s32 id)
 | 
			
		||||
{
 | 
			
		||||
	const tic_sound_effect* effect = &studio.tic->config.bank0.sfx.data[id];
 | 
			
		||||
	const tic_sample* effect = &studio.tic->config.bank0.sfx.samples.data[id];
 | 
			
		||||
	studio.tic->api.sfx_ex(studio.tic, id, effect->note, effect->octave, -1, 0, MAX_VOLUME, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -777,31 +777,31 @@ void setStudioEvent(StudioEvent event)
 | 
			
		||||
	{
 | 
			
		||||
	case TIC_CODE_MODE: 	
 | 
			
		||||
		{
 | 
			
		||||
			Code* code = studio.editor.code[studio.bank.index.code];
 | 
			
		||||
			Code* code = studio.editor[studio.bank.index.code].code;
 | 
			
		||||
			code->event(code, event); 			
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_SPRITE_MODE:	
 | 
			
		||||
		{
 | 
			
		||||
			Sprite* sprite = studio.editor.sprite[studio.bank.index.sprites];
 | 
			
		||||
			Sprite* sprite = studio.editor[studio.bank.index.sprites].sprite;
 | 
			
		||||
			sprite->event(sprite, event); 
 | 
			
		||||
		}
 | 
			
		||||
	break;
 | 
			
		||||
	case TIC_MAP_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Map* map = studio.editor.map[studio.bank.index.map];
 | 
			
		||||
			Map* map = studio.editor[studio.bank.index.map].map;
 | 
			
		||||
			map->event(map, event);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_SFX_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Sfx* sfx = studio.editor.sfx[studio.bank.index.sfx];
 | 
			
		||||
			Sfx* sfx = studio.editor[studio.bank.index.sfx].sfx;
 | 
			
		||||
			sfx->event(sfx, event);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_MUSIC_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Music* music = studio.editor.music[studio.bank.index.music];
 | 
			
		||||
			Music* music = studio.editor[studio.bank.index.music].music;
 | 
			
		||||
			music->event(music, event);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
@@ -879,7 +879,7 @@ void drawBitIcon(s32 x, s32 y, const u8* ptr, u8 color)
 | 
			
		||||
 | 
			
		||||
static void initWorldMap()
 | 
			
		||||
{
 | 
			
		||||
	initWorld(studio.world, studio.tic, studio.editor.map[studio.bank.index.map]);
 | 
			
		||||
	initWorld(studio.world, studio.tic, studio.editor[studio.bank.index.map].map);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void initRunMode()
 | 
			
		||||
@@ -1093,11 +1093,11 @@ static void initModules()
 | 
			
		||||
 | 
			
		||||
	for(s32 i = 0; i < TIC_EDITOR_BANKS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		initCode(studio.editor.code[i], studio.tic, &tic->cart.banks[i].code);
 | 
			
		||||
		initSprite(studio.editor.sprite[i], studio.tic, &tic->cart.banks[i].tiles);
 | 
			
		||||
		initMap(studio.editor.map[i], studio.tic, &tic->cart.banks[i].map);
 | 
			
		||||
		initSfx(studio.editor.sfx[i], studio.tic, &tic->cart.banks[i].sfx);
 | 
			
		||||
		initMusic(studio.editor.music[i], studio.tic, &tic->cart.banks[i].music);
 | 
			
		||||
		initCode(studio.editor[i].code, studio.tic, &tic->cart.banks[i].code);
 | 
			
		||||
		initSprite(studio.editor[i].sprite, studio.tic, &tic->cart.banks[i].tiles);
 | 
			
		||||
		initMap(studio.editor[i].map, studio.tic, &tic->cart.banks[i].map);
 | 
			
		||||
		initSfx(studio.editor[i].sfx, studio.tic, &tic->cart.banks[i].sfx);
 | 
			
		||||
		initMusic(studio.editor[i].music, studio.tic, &tic->cart.banks[i].music);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	initWorldMap();
 | 
			
		||||
@@ -1800,7 +1800,7 @@ static bool processShortcuts(SDL_KeyboardEvent* event)
 | 
			
		||||
	case SDLK_ESCAPE:
 | 
			
		||||
	case SDLK_AC_BACK:
 | 
			
		||||
		{
 | 
			
		||||
			Code* code = studio.editor.code[studio.bank.index.code];
 | 
			
		||||
			Code* code = studio.editor[studio.bank.index.code].code;
 | 
			
		||||
 | 
			
		||||
			if(studio.mode == TIC_CODE_MODE && code->mode != TEXT_EDIT_MODE)
 | 
			
		||||
			{
 | 
			
		||||
@@ -1938,7 +1938,7 @@ SDL_Event* pollEvent()
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
				{
 | 
			
		||||
					Code* code = studio.editor.code[studio.bank.index.code];
 | 
			
		||||
					Code* code = studio.editor[studio.bank.index.code].code;
 | 
			
		||||
					studio.console->codeLiveReload.reload(studio.console, code->src);
 | 
			
		||||
					if(studio.console->codeLiveReload.active && code->update)
 | 
			
		||||
						code->update(code);
 | 
			
		||||
@@ -2103,14 +2103,14 @@ static void blitTexture()
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_SPRITE_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Sprite* sprite = studio.editor.sprite[studio.bank.index.sprites];
 | 
			
		||||
			Sprite* sprite = studio.editor[studio.bank.index.sprites].sprite;
 | 
			
		||||
			overlap = sprite->overlap;
 | 
			
		||||
			data = sprite;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_MAP_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Map* map = studio.editor.map[studio.bank.index.map];		
 | 
			
		||||
			Map* map = studio.editor[studio.bank.index.map].map;
 | 
			
		||||
			overlap = map->overlap;
 | 
			
		||||
			data = map;
 | 
			
		||||
		}
 | 
			
		||||
@@ -2307,31 +2307,31 @@ static void renderStudio()
 | 
			
		||||
	case TIC_RUN_MODE: 		studio.run->tick(studio.run); break;
 | 
			
		||||
	case TIC_CODE_MODE: 	
 | 
			
		||||
		{
 | 
			
		||||
			Code* code = studio.editor.code[studio.bank.index.code];
 | 
			
		||||
			Code* code = studio.editor[studio.bank.index.code].code;
 | 
			
		||||
			code->tick(code);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_SPRITE_MODE:	
 | 
			
		||||
		{
 | 
			
		||||
			Sprite* sprite = studio.editor.sprite[studio.bank.index.sprites];
 | 
			
		||||
			Sprite* sprite = studio.editor[studio.bank.index.sprites].sprite;
 | 
			
		||||
			sprite->tick(sprite);		
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_MAP_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Map* map = studio.editor.map[studio.bank.index.map];
 | 
			
		||||
			Map* map = studio.editor[studio.bank.index.map].map;
 | 
			
		||||
			map->tick(map);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_SFX_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Sfx* sfx = studio.editor.sfx[studio.bank.index.sfx];
 | 
			
		||||
			Sfx* sfx = studio.editor[studio.bank.index.sfx].sfx;
 | 
			
		||||
			sfx->tick(sfx);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case TIC_MUSIC_MODE:
 | 
			
		||||
		{
 | 
			
		||||
			Music* music = studio.editor.music[studio.bank.index.music];
 | 
			
		||||
			Music* music = studio.editor[studio.bank.index.music].music;
 | 
			
		||||
			music->tick(music);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
@@ -2527,7 +2527,7 @@ static void updateSystemFont()
 | 
			
		||||
 | 
			
		||||
void studioConfigChanged()
 | 
			
		||||
{
 | 
			
		||||
	Code* code = studio.editor.code[studio.bank.index.code];
 | 
			
		||||
	Code* code = studio.editor[studio.bank.index.code].code;
 | 
			
		||||
	if(code->update)
 | 
			
		||||
		code->update(code);
 | 
			
		||||
 | 
			
		||||
@@ -2614,11 +2614,11 @@ static void onFSInitialized(FileSystem* fs)
 | 
			
		||||
	{
 | 
			
		||||
		for(s32 i = 0; i < TIC_EDITOR_BANKS; i++)
 | 
			
		||||
		{
 | 
			
		||||
			studio.editor.code[i] 		= SDL_malloc(sizeof(Code));
 | 
			
		||||
			studio.editor.sprite[i]	= SDL_malloc(sizeof(Sprite));
 | 
			
		||||
			studio.editor.map[i] 		= SDL_malloc(sizeof(Map));
 | 
			
		||||
			studio.editor.sfx[i] 		= SDL_malloc(sizeof(Sfx));
 | 
			
		||||
			studio.editor.music[i] 	= SDL_malloc(sizeof(Music));
 | 
			
		||||
			studio.editor[i].code	= SDL_malloc(sizeof(Code));
 | 
			
		||||
			studio.editor[i].sprite	= SDL_malloc(sizeof(Sprite));
 | 
			
		||||
			studio.editor[i].map 	= SDL_malloc(sizeof(Map));
 | 
			
		||||
			studio.editor[i].sfx 	= SDL_malloc(sizeof(Sfx));
 | 
			
		||||
			studio.editor[i].music 	= SDL_malloc(sizeof(Music));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		studio.start 	= SDL_malloc(sizeof(Start));
 | 
			
		||||
@@ -2726,11 +2726,11 @@ s32 main(s32 argc, char **argv)
 | 
			
		||||
	{
 | 
			
		||||
		for(s32 i = 0; i < TIC_EDITOR_BANKS; i++)
 | 
			
		||||
		{
 | 
			
		||||
			SDL_free(studio.editor.code[i]);
 | 
			
		||||
			SDL_free(studio.editor.sprite[i]);
 | 
			
		||||
			SDL_free(studio.editor.map[i]);
 | 
			
		||||
			SDL_free(studio.editor.sfx[i]);
 | 
			
		||||
			SDL_free(studio.editor.music[i]);
 | 
			
		||||
			SDL_free(studio.editor[i].code);
 | 
			
		||||
			SDL_free(studio.editor[i].sprite);
 | 
			
		||||
			SDL_free(studio.editor[i].map);
 | 
			
		||||
			SDL_free(studio.editor[i].sfx);
 | 
			
		||||
			SDL_free(studio.editor[i].music);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		SDL_free(studio.start);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										89
									
								
								src/tic.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								src/tic.c
									
									
									
									
									
								
							@@ -53,7 +53,7 @@ typedef enum
 | 
			
		||||
	CHUNK_TEMP,		// 6
 | 
			
		||||
	CHUNK_TEMP2, 	// 7
 | 
			
		||||
	CHUNK_TEMP3,	// 8
 | 
			
		||||
	CHUNK_SOUND,	// 9
 | 
			
		||||
	CHUNK_SAMPLES,	// 9
 | 
			
		||||
	CHUNK_WAVEFORM,	// 10
 | 
			
		||||
	CHUNK_TEMP4,	// 11
 | 
			
		||||
	CHUNK_PALETTE, 	// 12
 | 
			
		||||
@@ -64,13 +64,16 @@ typedef enum
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	ChunkType type:8;
 | 
			
		||||
	u32 size:24;
 | 
			
		||||
	ChunkType type:5;
 | 
			
		||||
	u32 bank:TIC_BANK_BITS;
 | 
			
		||||
	u32 size:16; // max chunk size is 64K
 | 
			
		||||
	u32 temp:8;
 | 
			
		||||
} Chunk;
 | 
			
		||||
 | 
			
		||||
STATIC_ASSERT(rom_chunk_size, sizeof(Chunk) == 4);
 | 
			
		||||
STATIC_ASSERT(tic_bank_bits, TIC_BANK_BITS == 3);
 | 
			
		||||
STATIC_ASSERT(tic_chunk_size, sizeof(Chunk) == 4);
 | 
			
		||||
STATIC_ASSERT(tic_map, sizeof(tic_map) < 1024*32);
 | 
			
		||||
STATIC_ASSERT(tic_sound_effect, sizeof(tic_sound_effect) == 66);
 | 
			
		||||
STATIC_ASSERT(tic_sample, sizeof(tic_sample) == 66);
 | 
			
		||||
STATIC_ASSERT(tic_track_pattern, sizeof(tic_track_pattern) == 3*MUSIC_PATTERN_ROWS);
 | 
			
		||||
STATIC_ASSERT(tic_track, sizeof(tic_track) == 3*MUSIC_FRAMES+3);
 | 
			
		||||
STATIC_ASSERT(tic_vram, sizeof(tic_vram) == TIC_VRAM_SIZE);
 | 
			
		||||
@@ -357,7 +360,7 @@ static void channelSfx(tic_mem* memory, s32 index, s32 note, s32 octave, s32 dur
 | 
			
		||||
	if(index >= 0)
 | 
			
		||||
	{
 | 
			
		||||
		struct {s8 speed:SFX_SPEED_BITS;} temp = {speed};
 | 
			
		||||
		c->speed = speed == temp.speed ? speed : machine->sound.sfx->data[index].speed;
 | 
			
		||||
		c->speed = speed == temp.speed ? speed : machine->sound.sfx->samples.data[index].speed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// start index of idealized piano
 | 
			
		||||
@@ -1061,7 +1064,7 @@ static void sfx(tic_mem* memory, s32 index, s32 freq, Channel* channel, tic_soun
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const tic_sound_effect* effect = &machine->sound.sfx->data[index];
 | 
			
		||||
	const tic_sample* effect = &machine->sound.sfx->samples.data[index];
 | 
			
		||||
	s32 pos = ++channel->tick;
 | 
			
		||||
 | 
			
		||||
	s8 speed = channel->speed;
 | 
			
		||||
@@ -1325,26 +1328,29 @@ static void initCover(tic_mem* tic)
 | 
			
		||||
 | 
			
		||||
static void api_sync(tic_mem* tic, const char* section, s32 bank, bool toCart)
 | 
			
		||||
{
 | 
			
		||||
	static const struct {const char* name; s32 cart; s32 ram; s32 size;} Sections[] = 
 | 
			
		||||
	static const struct {const char* name; s32 bank; s32 ram; s32 size;} Sections[] = 
 | 
			
		||||
	{
 | 
			
		||||
		{"tiles", 	offsetof(tic_cartridge, bank0.tiles), 	offsetof(tic_ram, tiles), 			sizeof(tic_tiles)},
 | 
			
		||||
		{"sprites", offsetof(tic_cartridge, bank0.sprites), 	offsetof(tic_ram, sprites), 		sizeof(tic_tiles)},
 | 
			
		||||
		{"map", 	offsetof(tic_cartridge, bank0.map), 		offsetof(tic_ram, map), 			sizeof(tic_map)},
 | 
			
		||||
		{"sfx", 	offsetof(tic_cartridge, bank0.sfx), 		offsetof(tic_ram, sfx), 			sizeof(tic_sfx)},
 | 
			
		||||
		{"music", 	offsetof(tic_cartridge, bank0.music), 	offsetof(tic_ram, music), 			sizeof(tic_music)},
 | 
			
		||||
		{"tiles", 	offsetof(tic_bank, tiles), 		offsetof(tic_ram, tiles), 	sizeof(tic_tiles)},
 | 
			
		||||
		{"sprites", offsetof(tic_bank, sprites),	offsetof(tic_ram, sprites), sizeof(tic_tiles)},
 | 
			
		||||
		{"map", 	offsetof(tic_bank, map), 		offsetof(tic_ram, map), 	sizeof(tic_map)},
 | 
			
		||||
		{"sfx", 	offsetof(tic_bank, sfx), 		offsetof(tic_ram, sfx), 	sizeof(tic_sfx)},
 | 
			
		||||
		{"music", 	offsetof(tic_bank, music), 		offsetof(tic_ram, music), 	sizeof(tic_music)},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	assert(bank >= 0 && bank < TIC_BANKS);
 | 
			
		||||
 | 
			
		||||
	s32 bankOffset = bank * sizeof(tic_bank);
 | 
			
		||||
 | 
			
		||||
	for(s32 i = 0; i < COUNT_OF(Sections); i++)
 | 
			
		||||
	{
 | 
			
		||||
		if(section == NULL || (section && strcmp(section, Sections[i].name) == 0))
 | 
			
		||||
			toCart
 | 
			
		||||
				? memcpy((u8*)&tic->cart + Sections[i].cart + bankOffset, (u8*)&tic->ram + Sections[i].ram, Sections[i].size)
 | 
			
		||||
				: memcpy((u8*)&tic->ram + Sections[i].ram, (u8*)&tic->cart + Sections[i].cart + bankOffset, Sections[i].size);
 | 
			
		||||
				? memcpy((u8*)&tic->cart.banks[bank] + Sections[i].bank, (u8*)&tic->ram + Sections[i].ram, Sections[i].size)
 | 
			
		||||
				: memcpy((u8*)&tic->ram + Sections[i].ram, (u8*)&tic->cart.banks[bank] + Sections[i].bank, Sections[i].size);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if(section == NULL || (section && strcmp(section, "pal") == 0))
 | 
			
		||||
		toCart
 | 
			
		||||
			? memcpy(&tic->cart.palette, &tic->ram.vram.palette, sizeof(tic_palette))
 | 
			
		||||
			: memcpy(&tic->ram.vram.palette, &tic->cart.palette, sizeof(tic_palette));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cart2ram(tic_mem* memory)
 | 
			
		||||
@@ -1607,14 +1613,14 @@ static void api_load(tic_cartridge* cart, const u8* buffer, s32 size, bool palet
 | 
			
		||||
 | 
			
		||||
		switch(chunk.type)
 | 
			
		||||
		{
 | 
			
		||||
		case CHUNK_TILES: 		LOAD_CHUNK(cart->bank0.tiles); 					break;
 | 
			
		||||
		case CHUNK_SPRITES: 	LOAD_CHUNK(cart->bank0.sprites); 				break;
 | 
			
		||||
		case CHUNK_MAP: 		LOAD_CHUNK(cart->bank0.map); 					break;
 | 
			
		||||
		case CHUNK_CODE: 		LOAD_CHUNK(cart->bank0.code); 							break;
 | 
			
		||||
		case CHUNK_SOUND: 		LOAD_CHUNK(cart->bank0.sfx.data); 				break;
 | 
			
		||||
		case CHUNK_WAVEFORM:	LOAD_CHUNK(cart->bank0.sfx.waveform);			break;
 | 
			
		||||
		case CHUNK_MUSIC:		LOAD_CHUNK(cart->bank0.music.tracks.data); 		break;
 | 
			
		||||
		case CHUNK_PATTERNS:	LOAD_CHUNK(cart->bank0.music.patterns.data); 	break;
 | 
			
		||||
		case CHUNK_TILES: 		LOAD_CHUNK(cart->banks[chunk.bank].tiles); 			break;
 | 
			
		||||
		case CHUNK_SPRITES: 	LOAD_CHUNK(cart->banks[chunk.bank].sprites); 		break;
 | 
			
		||||
		case CHUNK_MAP: 		LOAD_CHUNK(cart->banks[chunk.bank].map); 			break;
 | 
			
		||||
		case CHUNK_CODE: 		LOAD_CHUNK(cart->banks[chunk.bank].code); 			break;
 | 
			
		||||
		case CHUNK_SAMPLES: 	LOAD_CHUNK(cart->banks[chunk.bank].sfx.samples); 	break;
 | 
			
		||||
		case CHUNK_WAVEFORM:	LOAD_CHUNK(cart->banks[chunk.bank].sfx.waveform); 	break;
 | 
			
		||||
		case CHUNK_MUSIC:		LOAD_CHUNK(cart->banks[chunk.bank].music.tracks); 	break;
 | 
			
		||||
		case CHUNK_PATTERNS:	LOAD_CHUNK(cart->banks[chunk.bank].music.patterns);	break;
 | 
			
		||||
		case CHUNK_PALETTE:		
 | 
			
		||||
			if(palette)
 | 
			
		||||
				LOAD_CHUNK(cart->palette);
 | 
			
		||||
@@ -1649,11 +1655,11 @@ static s32 calcBufferSize(const void* buffer, s32 size)
 | 
			
		||||
	return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u8* saveFixedChunk(u8* buffer, ChunkType type, const void* from, s32 size)
 | 
			
		||||
static u8* saveFixedChunk(u8* buffer, ChunkType type, const void* from, s32 size, s32 bank)
 | 
			
		||||
{
 | 
			
		||||
	if(size)
 | 
			
		||||
	{
 | 
			
		||||
		Chunk chunk = {type, size};
 | 
			
		||||
		Chunk chunk = {.type = type, .bank = bank, .size = size};
 | 
			
		||||
		memcpy(buffer, &chunk, sizeof(Chunk));
 | 
			
		||||
		buffer += sizeof(Chunk);
 | 
			
		||||
		memcpy(buffer, from, size);
 | 
			
		||||
@@ -1663,30 +1669,33 @@ static u8* saveFixedChunk(u8* buffer, ChunkType type, const void* from, s32 size
 | 
			
		||||
	return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u8* saveChunk(u8* buffer, ChunkType type, const void* from, s32 size)
 | 
			
		||||
static u8* saveChunk(u8* buffer, ChunkType type, const void* from, s32 size, s32 bank)
 | 
			
		||||
{
 | 
			
		||||
	s32 chunkSize = calcBufferSize(from, size);
 | 
			
		||||
 | 
			
		||||
	return saveFixedChunk(buffer, type, from, chunkSize);
 | 
			
		||||
	return saveFixedChunk(buffer, type, from, chunkSize, bank);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static s32 api_save(const tic_cartridge* cart, u8* buffer)
 | 
			
		||||
{
 | 
			
		||||
	u8* start = buffer;
 | 
			
		||||
 | 
			
		||||
	#define SAVE_CHUNK(id, from) saveChunk(buffer, id, &from, sizeof(from))
 | 
			
		||||
	#define SAVE_CHUNK(ID, FROM, BANK) saveChunk(buffer, ID, &FROM, sizeof(FROM), BANK)
 | 
			
		||||
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_TILES, 	cart->bank0.tiles);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_SPRITES, 	cart->bank0.sprites);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_MAP, 		cart->bank0.map);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_CODE, 	cart->bank0.code);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_SOUND, 	cart->bank0.sfx.data);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_WAVEFORM, cart->bank0.sfx.waveform);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_PATTERNS, cart->bank0.music.patterns.data);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_MUSIC, 	cart->bank0.music.tracks.data);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_PALETTE, 	cart->palette);
 | 
			
		||||
	for(s32 i = 0; i < TIC_BANKS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_TILES, 	cart->banks[i].tiles, 			i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_SPRITES, 	cart->banks[i].sprites, 		i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_MAP, 		cart->banks[i].map, 			i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_CODE, 	cart->banks[i].code, 			i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_SAMPLES, 	cart->banks[i].sfx.samples, 	i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_WAVEFORM, cart->banks[i].sfx.waveform, 	i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_PATTERNS, cart->banks[i].music.patterns, 	i);
 | 
			
		||||
		buffer = SAVE_CHUNK(CHUNK_MUSIC, 	cart->banks[i].music.tracks, 	i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buffer = saveFixedChunk(buffer, CHUNK_COVER, cart->cover.data, cart->cover.size);
 | 
			
		||||
	buffer = SAVE_CHUNK(CHUNK_PALETTE, 	cart->palette, 0);
 | 
			
		||||
	buffer = saveFixedChunk(buffer, CHUNK_COVER, cart->cover.data, cart->cover.size, 0);
 | 
			
		||||
 | 
			
		||||
	#undef SAVE_CHUNK
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/tic.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/tic.h
									
									
									
									
									
								
							@@ -107,7 +107,8 @@
 | 
			
		||||
 | 
			
		||||
#define TIC_CODE_SIZE (0x10000)
 | 
			
		||||
 | 
			
		||||
#define TIC_BANKS 8
 | 
			
		||||
#define TIC_BANK_BITS 3
 | 
			
		||||
#define TIC_BANKS (1 << TIC_BANK_BITS)
 | 
			
		||||
 | 
			
		||||
#define SFX_NOTES {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-"}
 | 
			
		||||
 | 
			
		||||
@@ -203,7 +204,7 @@ typedef struct
 | 
			
		||||
		tic_sound_loop loops[4];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
} tic_sound_effect;
 | 
			
		||||
} tic_sample;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
@@ -250,10 +251,15 @@ typedef struct
 | 
			
		||||
	tic_track data[MUSIC_TRACKS];
 | 
			
		||||
} tic_tracks;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	tic_sample data[SFX_COUNT];
 | 
			
		||||
} tic_samples;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	tic_waveforms waveform;
 | 
			
		||||
	tic_sound_effect data[SFX_COUNT];
 | 
			
		||||
	tic_samples samples;
 | 
			
		||||
}tic_sfx;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user