2626#include "studio/config.h"
2727#include "console.h"
2828#include "menu.h"
29- #include "ext/gif.h"
3029#include "ext/png.h"
3130
3231#if defined(TIC80_PRO )
@@ -57,7 +56,7 @@ struct SurfItem
5756{
5857 char * label ;
5958 char * name ;
60- char * hash ;
59+ char * url ;
6160 s32 id ;
6261 tic_screen * cover ;
6362
@@ -140,7 +139,7 @@ static void drawBottomToolbar(Surf* surf, s32 x, s32 y)
140139
141140#ifdef CAN_OPEN_URL
142141
143- if (surf -> menu .count > 0 && getMenuItem (surf )-> hash )
142+ if (surf -> menu .count > 0 && getMenuItem (surf )-> url )
144143 {
145144 enum {Gap = 10 , TipX = 134 , SelectWidth = 54 };
146145
@@ -204,7 +203,7 @@ static bool addMenuItem(const char* name, const char* title, const char* hash, s
204203 * item = (SurfItem )
205204 {
206205 .name = strdup (name ),
207- .hash = hash ? strdup (hash ) : NULL ,
206+ .url = hash ? strdup (hash ) : NULL ,
208207 .id = id ,
209208 .dir = dir ,
210209 };
@@ -271,7 +270,7 @@ static void resetMenu(Surf* surf)
271270
272271 free (item -> name );
273272
274- FREE (item -> hash );
273+ FREE (item -> url );
275274 FREE (item -> cover );
276275 FREE (item -> label );
277276 FREE (item -> palette );
@@ -290,29 +289,52 @@ static void updateMenuItemCover(Surf* surf, s32 pos, const u8* cover, s32 size)
290289{
291290 SurfItem * item = & surf -> menu .items [pos ];
292291
293- gif_image * image = gif_read_data ( cover , size );
292+ png_img img = png_read (( png_buffer ){( u8 * ) cover , size }, NULL );
294293
295- if (image )
294+ if (img . data ) SCOPE ( free ( img . data ) )
296295 {
297296 item -> cover = malloc (sizeof (tic_screen ));
298297 item -> palette = malloc (sizeof (tic_palette ));
299298
300- if (image -> width == TIC80_WIDTH
301- && image -> height == TIC80_HEIGHT
302- && image -> colors <= TIC_PALETTE_SIZE )
299+ if (img .width == TIC80_WIDTH && img .height == TIC80_HEIGHT )
303300 {
304- memcpy (item -> palette , image -> palette , image -> colors * sizeof (tic_rgb ));
301+ // collect unique colors (assuming the image is 16-color indexed)
302+ tic_palette unique_colors = {0 };
303+ u8 num_colors = 0 ;
305304
306305 for (s32 i = 0 ; i < TIC80_WIDTH * TIC80_HEIGHT ; i ++ )
307- tic_tool_poke4 (item -> cover -> data , i , image -> buffer [i ]);
306+ {
307+ png_rgba pixel = img .pixels [i ];
308+ tic_rgb color = {pixel .r , pixel .g , pixel .b };
309+ u8 index = TIC_PALETTE_SIZE ;
310+
311+ // find existing color
312+ for (u8 j = 0 ; j < num_colors ; j ++ )
313+ if (memcmp (& unique_colors .colors [j ], & color , sizeof (tic_rgb )) == 0 )
314+ {
315+ index = j ;
316+ break ;
317+ }
318+
319+ // add new color if not found and palette not full
320+ if (index == TIC_PALETTE_SIZE && num_colors < TIC_PALETTE_SIZE )
321+ {
322+ unique_colors .colors [num_colors ] = color ;
323+ index = num_colors ++ ;
324+ }
325+
326+ // set pixel index (default to 0 if palette full)
327+ tic_tool_poke4 (item -> cover -> data , i , index < TIC_PALETTE_SIZE ? index : 0 );
328+ }
329+
330+ // set palette from collected colors
331+ memcpy (item -> palette , & unique_colors , sizeof (tic_palette ));
308332 }
309333 else
310334 {
311335 memset (item -> cover , 0 , sizeof (tic_screen ));
312336 memset (item -> palette , 0 , sizeof (tic_palette ));
313337 }
314-
315- gif_close (image );
316338 }
317339}
318340
@@ -355,8 +377,10 @@ static void requestCover(Surf* surf, SurfItem* item)
355377 CoverLoadingData coverLoadingData = {surf , surf -> menu .pos };
356378 tic_fs_dir (surf -> fs , coverLoadingData .dir );
357379
358- const char * hash = item -> hash ;
359- sprintf (coverLoadingData .cachePath , TIC_CACHE "%s.gif" , hash );
380+ const char * url = item -> url ;
381+ const char * hash = md5str (item -> url , strlen (item -> url ));
382+
383+ sprintf (coverLoadingData .cachePath , TIC_CACHE "%s.png" , hash );
360384
361385 {
362386 s32 size = 0 ;
@@ -366,13 +390,19 @@ static void requestCover(Surf* surf, SurfItem* item)
366390 {
367391 updateMenuItemCover (surf , surf -> menu .pos , data , size );
368392 free (data );
393+ return ;
369394 }
370395 }
371396
372397 char path [TICNAME_MAX ];
373- sprintf (path , "/cart/%s/cover.gif" , hash );
398+ strcpy (path , url );
399+ char * pos = strrchr (path , '.' );
374400
375- tic_net_get (surf -> net , path , coverLoaded , MOVE (coverLoadingData ));
401+ if (pos )
402+ {
403+ strcpy (pos , "/cover.png" );
404+ tic_net_get (surf -> net , path , coverLoaded , MOVE (coverLoadingData ));
405+ }
376406}
377407
378408static void loadCover (Surf * surf )
@@ -429,7 +459,7 @@ static void loadCover(Surf* surf)
429459 free (data );
430460 }
431461 }
432- else if (item -> hash && !item -> cover )
462+ else if (item -> url && !item -> cover )
433463 {
434464 requestCover (surf , item );
435465 }
@@ -577,9 +607,9 @@ static void onLoadCommandConfirmed(Studio* studio, bool yes, void* data)
577607 Surf * surf = data ;
578608 SurfItem * item = getMenuItem (surf );
579609
580- if (item -> hash )
610+ if (item -> url )
581611 {
582- surf -> console -> loadByHash (surf -> console , item -> name , item -> hash , NULL , onCartLoaded , surf );
612+ surf -> console -> loadByHash (surf -> console , item -> name , item -> url , NULL , onCartLoaded , surf );
583613 }
584614 else
585615 {
@@ -706,8 +736,14 @@ static void processGamepad(Surf* surf)
706736 if (!item -> dir )
707737 {
708738 char url [TICNAME_MAX ];
709- sprintf (url , TIC_WEBSITE "/play?cart=%i" , item -> id );
710- tic_sys_open_url (url );
739+ strcpy (url , TIC_WEBSITE );
740+ strcat (url , item -> url );
741+ char * pos = strrchr (url , '.' );
742+ if (pos )
743+ {
744+ * pos = 0 ;
745+ tic_sys_open_url (url );
746+ }
711747 }
712748 }
713749#endif
0 commit comments