this repo has no description
1// MIT License
2
3// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
4
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#include "tools.h"
24
25#include <ctype.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdio.h>
29
30extern void tic_tool_poke4(void* addr, u32 index, u8 value);
31extern u8 tic_tool_peek4(const void* addr, u32 index);
32extern void tic_tool_poke2(void* addr, u32 index, u8 value);
33extern u8 tic_tool_peek2(const void* addr, u32 index);
34extern void tic_tool_poke1(void* addr, u32 index, u8 value);
35extern u8 tic_tool_peek1(const void* addr, u32 index);
36extern s32 tic_tool_sfx_pos(s32 speed, s32 ticks);
37extern u32 tic_rgba(const tic_rgb* c);
38extern s32 tic_modulo(s32 x, s32 m);
39
40static u32 getPatternData(const tic_track* track, s32 frame)
41{
42 u32 patternData = 0;
43 for(s32 b = 0; b < TRACK_PATTERNS_SIZE; b++)
44 patternData |= track->data[frame * TRACK_PATTERNS_SIZE + b] << (BITS_IN_BYTE * b);
45
46 return patternData;
47}
48
49s32 tic_tool_get_pattern_id(const tic_track* track, s32 frame, s32 channel)
50{
51 return (getPatternData(track, frame) >> (channel * TRACK_PATTERN_BITS)) & TRACK_PATTERN_MASK;
52}
53
54void tic_tool_set_pattern_id(tic_track* track, s32 frame, s32 channel, s32 pattern)
55{
56 u32 patternData = getPatternData(track, frame);
57 s32 shift = channel * TRACK_PATTERN_BITS;
58
59 patternData &= ~(TRACK_PATTERN_MASK << shift);
60 patternData |= pattern << shift;
61
62 for(s32 b = 0; b < TRACK_PATTERNS_SIZE; b++)
63 track->data[frame * TRACK_PATTERNS_SIZE + b] = (patternData >> (b * BITS_IN_BYTE)) & 0xff;
64}
65
66u32 tic_nearest_color(const tic_rgb* palette, const tic_rgb* color, s32 count)
67{
68 u32 min = -1;
69 s32 nearest, i = 0;
70
71 for(const tic_rgb *rgb = palette, *end = rgb + count; rgb < end; rgb++, i++)
72 {
73 s32 d[] = {color->r - rgb->r, color->g - rgb->g, color->b - rgb->b};
74
75 u32 dst = 0;
76 for(const s32 *v = d, *end = v + COUNT_OF(d); v < end; v++)
77 dst += (*v) * (*v);
78
79 if (dst < min)
80 {
81 min = dst;
82 nearest = i;
83 }
84 }
85
86 return nearest;
87}
88
89tic_blitpal tic_tool_palette_blit(const tic_palette* srcpal, tic80_pixel_color_format fmt)
90{
91 tic_blitpal pal;
92
93 const tic_rgb* src = srcpal->colors;
94 const tic_rgb* end = src + TIC_PALETTE_SIZE;
95 u8* dst = (u8*)pal.data;
96
97 while(src != end)
98 {
99 switch(fmt){
100 case TIC80_PIXEL_COLOR_BGRA8888:
101 *dst++ = src->b;
102 *dst++ = src->g;
103 *dst++ = src->r;
104 *dst++ = 0xff;
105 break;
106 case TIC80_PIXEL_COLOR_RGBA8888:
107 *dst++ = src->r;
108 *dst++ = src->g;
109 *dst++ = src->b;
110 *dst++ = 0xff;
111 break;
112 case TIC80_PIXEL_COLOR_ABGR8888:
113 *dst++ = 0xff;
114 *dst++ = src->b;
115 *dst++ = src->g;
116 *dst++ = src->r;
117 break;
118 case TIC80_PIXEL_COLOR_ARGB8888:
119 *dst++ = 0xff;
120 *dst++ = src->r;
121 *dst++ = src->g;
122 *dst++ = src->b;
123 break;
124 }
125 src++;
126 }
127
128 return pal;
129}
130
131bool tic_tool_has_ext(const char* name, const char* ext)
132{
133 return strcmp(name + strlen(name) - strlen(ext), ext) == 0;
134}
135
136s32 tic_tool_get_track_row_sfx(const tic_track_row* row)
137{
138 return (row->sfxhi << MUSIC_SFXID_LOW_BITS) | row->sfxlow;
139}
140
141void tic_tool_set_track_row_sfx(tic_track_row* row, s32 sfx)
142{
143 if(sfx >= SFX_COUNT) sfx = SFX_COUNT-1;
144
145 row->sfxhi = (sfx & 0x20) >> MUSIC_SFXID_LOW_BITS;
146 row->sfxlow = sfx & 0x1f;
147}
148
149bool tic_tool_empty(const void* buffer, s32 size)
150{
151 for(const u8 *ptr = buffer, *end = ptr + size; ptr < end;)
152 if(*ptr++)
153 return false;
154
155 return true;
156}
157
158bool tic_tool_flat4(const void* buffer, s32 size)
159{
160 u8 first = (*(u8*)buffer) & 0xf;
161 first |= first << 4;
162 for(const u8 *ptr = buffer, *end = ptr + size; ptr < end;)
163 if(*ptr++ != first)
164 return false;
165
166 return true;
167}
168
169bool tic_tool_noise(const tic_waveform* wave)
170{
171 return FLAT4(wave->data) && *wave->data % 0xff == 0;
172}
173
174void tic_tool_buf2str(const void* data, s32 size, char* str, bool flip)
175{
176 for(s32 i = 0; i < size; i++, str += 2)
177 {
178 sprintf(str, "%02x", ((u8*)data)[i]);
179 if(flip) SWAP(str[0], str[1], char);
180 }
181}
182
183void tic_tool_str2buf(const char* str, s32 size, void* buf, bool flip)
184{
185 char val[] = "0x00";
186 const char* ptr = str;
187
188 for(s32 i = 0; i < size/2; i++)
189 {
190 if(flip)
191 {
192 val[3] = *ptr++;
193 val[2] = *ptr++;
194 }
195 else
196 {
197 val[2] = *ptr++;
198 val[3] = *ptr++;
199 }
200
201 ((u8*)buf)[i] = (u8)strtol(val, NULL, 16);
202 }
203}
204
205const char* tic_tool_metatag(const char* code, const char* tag, const char* comment)
206{
207 const char* start = NULL;
208
209 {
210 char tagBuffer[128];
211
212 if(comment)
213 sprintf(tagBuffer, "%s %s:", comment, tag);
214 else
215 sprintf(tagBuffer, "%s:", tag);
216
217 if ((start = strstr(code, tagBuffer)))
218 start += strlen(tagBuffer);
219 }
220
221 static char value[128];
222 *value = '\0';
223
224 if (start)
225 {
226 const char* end = strstr(start, "\n");
227
228 if (end)
229 {
230 while (isspace(*start) && start < end) start++;
231 while (isspace(*(end - 1)) && end > start) end--;
232
233 const s32 size = MIN((s32)(end - start), sizeof value - 1);
234
235 memcpy(value, start, size);
236 value[size] = '\0';
237 }
238 }
239
240 return value;
241}