├── LICENSE ├── README.txt ├── bin ├── SDL.dll ├── SDL_image.dll ├── libpng12-0.dll ├── snesconvert ├── snesconvert.exe └── zlib1.dll ├── main.c └── snesconvert.cbp /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | 2 | compilation 3 | gcc main.c -lSDL -lSDL_image -o snesconvert 4 | 5 | 6 | example : 7 | snesconvert myimage.png 8 | 9 | option : 10 | -2bpp forced 4colors 11 | -4bpp forced 16colors 12 | -8bpp forced 256colors 13 | -noalpha (if your image has no alpha) 14 | -palette (only palette) 15 | -paletteall (only palette but 1 pixel = 1 colors so square 16x16 pixel) 16 | -mode7 (for mode7 8bpp) 17 | -loadpalette (read palette extern,by default read palette.png or add second argument , your image should be 4/16/256x1 pixel) 18 | -asm 19 | -map 20 | 21 | -------------------------------------------------------------------------------- /bin/SDL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/SDL.dll -------------------------------------------------------------------------------- /bin/SDL_image.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/SDL_image.dll -------------------------------------------------------------------------------- /bin/libpng12-0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/libpng12-0.dll -------------------------------------------------------------------------------- /bin/snesconvert: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/snesconvert -------------------------------------------------------------------------------- /bin/snesconvert.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/snesconvert.exe -------------------------------------------------------------------------------- /bin/zlib1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kannagi/SNESConvert/e20ae67f9e271966b6602825f68722d4accf3f39/bin/zlib1.dll -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | 10 | #ifdef __MINGW32__ 11 | #undef main 12 | #endif 13 | 14 | 15 | void snes_convert(SDL_Surface *image,char *address,char *addresspal,int *option,int num); 16 | 17 | int main(int argc, char** argv) 18 | { 19 | SDL_Init(SDL_INIT_VIDEO); 20 | 21 | 22 | SDL_Surface *image,*copy; 23 | int n = 1,i,ok = 0; 24 | 25 | int option[10]; 26 | char address[500],addresspal[500],str[50]; 27 | 28 | for(i = 0; i < 10;i++) 29 | option[i] = 0; 30 | 31 | strcpy(addresspal,"palette.png"); 32 | address[0] = 0; 33 | 34 | for(i = 1; i < argc;i++) 35 | { 36 | if(argv[i][0] == '-') 37 | { 38 | if(strcmp(argv[i],"-2bpp") == 0) option[0] = 4; 39 | if(strcmp(argv[i],"-4bpp") == 0) option[0] = 16; 40 | if(strcmp(argv[i],"-8bpp") == 0) option[0] = 256; 41 | if(strcmp(argv[i],"-noalpha") == 0) option[1] = 1; 42 | if(strcmp(argv[i],"-palette") == 0) option[2] = 1; 43 | if(strcmp(argv[i],"-paletteall") == 0) option[2] = 3; 44 | if(strcmp(argv[i],"-mode7") == 0) option[2] = 2; 45 | if(strcmp(argv[i],"-asm") == 0) option[3] = 1; 46 | if(strcmp(argv[i],"-map") == 0) option[4] = 1; 47 | ok = 0; 48 | 49 | if(strcmp(argv[i],"-loadpalette") == 0) 50 | { 51 | option[2] = 4; 52 | ok = 1; 53 | } 54 | 55 | 56 | }else 57 | { 58 | if(ok == 0) strcpy(address,argv[i]); 59 | if(ok == 1) strcpy(addresspal,argv[i]); 60 | ok = 0; 61 | } 62 | } 63 | 64 | if(address[0] == 0) 65 | { 66 | printf("Enter a picture format .png,pcx,bmp, or jpg\n"); 67 | printf("bpp -4 or -16 for choose palette \n"); 68 | printf("Exemple :\nsnesconvert -4 myimage or snesconvert myimage (snesconvert choose auto -4 or -16)\n"); 69 | return 0; 70 | } 71 | 72 | image = IMG_Load(address); 73 | if(image == NULL) 74 | { 75 | printf("Image is not valide\n"); 76 | return 0; 77 | } 78 | 79 | copy = SDL_CreateRGBSurface(0,image->w,image->h,24,0,0,0,0); 80 | 81 | SDL_Rect rect; 82 | SDL_BlitSurface(image,NULL,copy,NULL); 83 | 84 | if(option[4] == 1) 85 | { 86 | SDL_FreeSurface(copy); 87 | copy = SDL_CreateRGBSurface(0,128,64,24,0,0,0,0); 88 | rect.w = 128; 89 | rect.h = 64; 90 | for(i = 0; i < 7;i++) 91 | { 92 | if(i < 4) 93 | { 94 | rect.x = 0; 95 | rect.y = i*64; 96 | }else 97 | { 98 | rect.x = 128; 99 | rect.y = (i-4)*64; 100 | 101 | if(i == 6) 102 | { 103 | rect.h = 128; 104 | SDL_FreeSurface(copy); 105 | copy = SDL_CreateRGBSurface(0,128,128,24,0,0,0,0); 106 | } 107 | } 108 | 109 | 110 | SDL_BlitSurface(image,&rect,copy,NULL); 111 | snes_convert(copy,address,addresspal,option,i); 112 | sprintf(str,"test_%d.bmp",i); 113 | SDL_SaveBMP(copy,str); 114 | } 115 | }else 116 | snes_convert(copy,address,addresspal,option,0); 117 | 118 | 119 | 120 | //SDL_SaveBMP(image,"test.bmp"); 121 | SDL_FreeSurface(copy); 122 | SDL_FreeSurface(image); 123 | SDL_Quit(); 124 | 125 | return 0; 126 | 127 | } 128 | 129 | int load_palette(SDL_Surface *image,unsigned char *palette,int noalpha) 130 | { 131 | int i,l; 132 | unsigned char *pixel = image->pixels; 133 | int taille = image->w*image->h*image->format->BytesPerPixel; 134 | unsigned char r,g,b; 135 | int n = 3 -(noalpha*3),black = 0,pal; 136 | 137 | for(i = 0;i < 0x300;i++) 138 | palette[i] = 0; 139 | 140 | for(i = 0;i < taille;i += image->format->BytesPerPixel) 141 | { 142 | r = pixel[i+0]; 143 | g = pixel[i+1]; 144 | b = pixel[i+2]; 145 | 146 | pal = 1; 147 | for(l = 0;l < 0x300;l+=3) 148 | { 149 | if(palette[l+0] == r && palette[l+1] == g && palette[l+2] == b) 150 | { 151 | pal = 0; 152 | break; 153 | } 154 | } 155 | 156 | if(pal == 1) 157 | { 158 | if( r == 0xFF && g == 0x00 && b == 0xFF) 159 | { 160 | palette[0] = r; 161 | palette[1] = g; 162 | palette[2] = b; 163 | }else 164 | { 165 | palette[n+0] = r; 166 | palette[n+1] = g; 167 | palette[n+2] = b; 168 | 169 | n +=3; 170 | } 171 | 172 | //printf("%d %d : %x %x %x\n",(i/3)%image->w,(i/3)/image->w,r,g,b); 173 | 174 | if(n >= 0x300) return n; 175 | }else 176 | { 177 | if(black == 0 && r == 0 && g == 0 && b == 0) 178 | { 179 | palette[n+0] = r; 180 | palette[n+1] = g; 181 | palette[n+2] = b; 182 | //printf("%d %d : %x %x %x\n",(i/3)%image->w,(i/3)/image->w,r,g,b); 183 | 184 | n +=3; 185 | black = 1; 186 | if(n >= 0x300) return n; 187 | } 188 | } 189 | 190 | 191 | } 192 | 193 | return n; 194 | } 195 | 196 | void load_paletteext(unsigned char *palette,char *addresspal) 197 | { 198 | int i; 199 | SDL_Surface *image,*copy; 200 | image = IMG_Load(addresspal); 201 | 202 | if(image == NULL) 203 | { 204 | printf("Image is not valide\n"); 205 | return; 206 | } 207 | for(i = 0;i < 768;i++) 208 | palette[i] = 0; 209 | 210 | copy = SDL_CreateRGBSurface(0,image->w,image->h,24,0,0,0,0); 211 | SDL_BlitSurface(image,NULL,copy,NULL); 212 | int n = 0; 213 | unsigned char *pixel = copy->pixels; 214 | 215 | for(i = 0;i < image->w*copy->format->BytesPerPixel;i += copy->format->BytesPerPixel) 216 | { 217 | palette[i+0] = pixel[i+0]; 218 | palette[i+1] = pixel[i+1]; 219 | palette[i+2] = pixel[i+2]; 220 | n+=3; 221 | } 222 | 223 | SDL_FreeSurface(copy); 224 | SDL_FreeSurface(image); 225 | } 226 | 227 | void tri_palette(SDL_Surface *image,int blocx,int blocy,unsigned char *pixel,unsigned char *palette,int *tiles) 228 | { 229 | int x,y,i,l; 230 | int n = 0; 231 | int r,v,b; 232 | 233 | 234 | for(y = blocy;y < blocy+8;y++) 235 | { 236 | for(x = blocx;x < blocx+8;x++) 237 | { 238 | i = (y*image->w*image->format->BytesPerPixel) + x*image->format->BytesPerPixel; 239 | r = pixel[i+0]; 240 | v = pixel[i+1]; 241 | b = pixel[i+2]; 242 | 243 | for(l = 0;l < 0x300;l+=3) 244 | { 245 | if(palette[l+0] == r && palette[l+1] == v && palette[l+2] == b) 246 | break; 247 | } 248 | 249 | 250 | tiles[n] = l/3; 251 | 252 | n++; 253 | } 254 | 255 | //printf("\n-------------------------------------------\n"); 256 | } 257 | } 258 | 259 | int write_rom(FILE *file,SDL_Surface *image,unsigned char *pixel,unsigned char *palette,int npal,int type,int bin) 260 | { 261 | int blocx,blocy; 262 | int tiles[64]; 263 | int snespixel[8]; 264 | int i,l; 265 | int x,y,size = 0; 266 | char str[500]; 267 | char sasm1[500]; 268 | char sasm2[500]; 269 | char sasm3[500]; 270 | char sasm4[500]; 271 | short binpixel[32]; 272 | char *cbinpixel = (char*)binpixel; 273 | 274 | blocx = 0; 275 | blocy = 0; 276 | 277 | if(bin == 0) fputs("\n",file); 278 | 279 | while(1) 280 | { 281 | tri_palette(image,blocx,blocy,pixel,palette,tiles); 282 | 283 | if(type == 0) //2,4,8 bpp 284 | { 285 | if(bin == 0) 286 | { 287 | sprintf(sasm1," .db "); 288 | sprintf(sasm2," .db "); 289 | sprintf(sasm3," .db "); 290 | sprintf(sasm4," .db "); 291 | } 292 | 293 | for(y = 0;y <8;y++) 294 | { 295 | for(i = 0;i < 8;i++) 296 | snespixel[i] = 0; 297 | 298 | for(x = 0;x < 8;x++) 299 | { 300 | i = tiles[x + (y*8)]; 301 | 302 | if(i > npal-1) i = 1+i%(npal-1); 303 | snespixel[0] += ( (i>>0) & 0x01 ) << (7 - x); 304 | snespixel[1] += ( (i>>1) & 0x01 ) << (7 - x); 305 | snespixel[2] += ( (i>>2) & 0x01 ) << (7 - x); 306 | snespixel[3] += ( (i>>3) & 0x01 ) << (7 - x); 307 | 308 | snespixel[4] += ( (i>>4) & 0x01 ) << (7 - x); 309 | snespixel[5] += ( (i>>5) & 0x01 ) << (7 - x); 310 | snespixel[6] += ( (i>>6) & 0x01 ) << (7 - x); 311 | snespixel[7] += ( (i>>7) & 0x01 ) << (7 - x); 312 | } 313 | 314 | if(bin == 0) 315 | { 316 | sprintf(str,"$%.2x,$%.2x,",snespixel[0],snespixel[1]); 317 | strcat(sasm1,str); 318 | 319 | if(npal > 4) 320 | { 321 | sprintf(str,"$%.2x,$%.2x,",snespixel[2],snespixel[3]); 322 | strcat(sasm2,str); 323 | } 324 | 325 | if(npal > 16) 326 | { 327 | sprintf(str,"$%.2x,$%.2x,",snespixel[4],snespixel[5]); 328 | strcat(sasm3,str); 329 | 330 | sprintf(str,"$%.2x,$%.2x,",snespixel[6],snespixel[7]); 331 | strcat(sasm4,str); 332 | } 333 | }else 334 | { 335 | binpixel[y] = snespixel[0] + (snespixel[1]<<8); 336 | binpixel[y+8] = snespixel[2] + (snespixel[3]<<8); 337 | binpixel[y+16] = snespixel[4] + (snespixel[5]<<8); 338 | binpixel[y+24] = snespixel[6] + (snespixel[7]<<8); 339 | } 340 | } 341 | 342 | if(bin == 0) 343 | { 344 | i = strlen(sasm1); 345 | sasm1[i-1] = 0; 346 | fputs(sasm1,file); 347 | fputs("\n",file); 348 | size += 16; 349 | 350 | if(npal > 4) 351 | { 352 | i = strlen(sasm2); 353 | sasm2[i-1] = 0; 354 | fputs(sasm2,file); 355 | fputs("\n",file); 356 | size += 16; 357 | } 358 | 359 | if(npal > 16) 360 | { 361 | i = strlen(sasm3); 362 | sasm3[i-1] = 0; 363 | fputs(sasm3,file); 364 | fputs("\n",file); 365 | 366 | i = strlen(sasm4); 367 | sasm4[i-1] = 0; 368 | fputs(sasm4,file); 369 | fputs("\n",file); 370 | size += 32; 371 | } 372 | }else 373 | { 374 | fwrite(binpixel,2 ,8,file); 375 | if(npal > 4) fwrite(&binpixel[8],2 ,8,file); 376 | if(npal > 16) fwrite(&binpixel[16],2 ,16,file); 377 | } 378 | 379 | 380 | 381 | }else //8pbb mode 7 382 | { 383 | if(bin == 0) sprintf(sasm1," .db"); 384 | for(y = 0;y <8;y++) 385 | { 386 | for(x = 0;x < 8;x++) 387 | { 388 | i = tiles[x + (y*8)]; 389 | 390 | if(bin == 0) 391 | { 392 | sprintf(str," $%.2x,",i); 393 | strcat(sasm1,str); 394 | }else 395 | { 396 | cbinpixel[x + (y*8)] = i; 397 | } 398 | } 399 | } 400 | 401 | if(bin == 0) 402 | { 403 | i = strlen(sasm1); 404 | sasm1[i-1] = 0; 405 | fputs(sasm1,file); 406 | fputs("\n",file); 407 | }else 408 | { 409 | fwrite(cbinpixel,1 ,64,file); 410 | } 411 | 412 | size += 64; 413 | 414 | } 415 | 416 | 417 | blocx += 8; 418 | if(blocx+8 >image->w) 419 | { 420 | blocx = 0; 421 | blocy += 8; 422 | } 423 | 424 | if(blocy+8 >image->h) break; 425 | } 426 | 427 | if(bin == 0) 428 | { 429 | fputs("\n",file); 430 | fputs("\n",file); 431 | } 432 | return size; 433 | } 434 | 435 | void output_filename(char *address,char *str) 436 | { 437 | int l = 0; 438 | int i = 0; 439 | while(address[i] != 0 && address[i] != '.' ) 440 | { 441 | str[l] = address[i]; 442 | l++; 443 | 444 | if(address[i] == '/' || address[i] == '\\') l = 0; 445 | i++; 446 | } 447 | str[l] = 0; 448 | } 449 | 450 | int write_pal(FILE *file,SDL_Surface *image,char *sstr,unsigned char *palette,unsigned char *pixel,int ncolor,int mode,int taille,int bin) 451 | { 452 | int i,n; 453 | int psize = 0; 454 | char str[100]; 455 | unsigned char color; 456 | int snespixel[4]; 457 | 458 | if(bin == 0) 459 | { 460 | sprintf(str,"pallette_%s:\n",sstr); 461 | fputs(str,file); 462 | sprintf(str," .db "); 463 | fputs(str,file); 464 | } 465 | 466 | if(mode == 3) 467 | { 468 | n = 0; 469 | for(i = 0;i < taille;i += image->format->BytesPerPixel) 470 | { 471 | palette[n+0] = pixel[i+0]; 472 | palette[n+1] = pixel[i+1]; 473 | palette[n+2] = pixel[i+2]; 474 | n +=3; 475 | if(n >= 0x300) break; 476 | } 477 | color = n/3; 478 | } 479 | 480 | 481 | for(i = 0;i < ncolor;i++) 482 | { 483 | n = i*3; 484 | 485 | if( (bin == 0) && (i != 0) )fputs(",",file); 486 | 487 | color = palette[n+2]/8; 488 | snespixel[0] = color; 489 | 490 | color = palette[n+1]/8; 491 | snespixel[0] += ( 0x07 & color) << 5; 492 | snespixel[1] = (0x18 & color) >> 3; 493 | 494 | color = palette[n+0]/8; 495 | snespixel[1] += color << 2; 496 | 497 | if(bin == 0) 498 | { 499 | sprintf(str,"$%.2x,$%.2x",snespixel[0],snespixel[1]); 500 | fputs(str,file); 501 | }else 502 | { 503 | fputc(snespixel[0],file); 504 | fputc(snespixel[1],file); 505 | } 506 | psize += 2; 507 | } 508 | 509 | return psize; 510 | } 511 | 512 | void write_end(FILE *file,int psize,int size) 513 | { 514 | char str[200]; 515 | 516 | fputs("\n",file); 517 | fputs("\n",file); 518 | fputs("\n",file); 519 | 520 | sprintf(str,";palette size octet : %d ,hexa $%.4x",psize,psize); 521 | fputs(str,file); 522 | fputs("\n",file); 523 | sprintf(str,";size octet : %d ,hexa $%.4x",size,size); 524 | fputs(str,file); 525 | 526 | fputs("\n",file); 527 | 528 | 529 | fclose(file); 530 | } 531 | 532 | 533 | void snes_convert(SDL_Surface *image,char *address,char *addresspal,int *option,int num) 534 | { 535 | FILE *file; 536 | int i,l,taille,ncolor = 0,type = 0; 537 | int x,y,size = 0,psize = 0; 538 | char str[200],sstr[200]; 539 | 540 | unsigned char palette[0x300]; 541 | for(i = 0;i < 0x300;i++) 542 | palette[i] = 0; 543 | 544 | int mode = option[2]; 545 | int bpp = option[0]; 546 | 547 | if(mode == 2) type = 1; 548 | 549 | unsigned char *pixel = image->pixels; 550 | 551 | taille = image->w*image->h*image->format->BytesPerPixel; 552 | 553 | ncolor = load_palette(image,palette,option[1])/3; 554 | 555 | //------------------------------- 556 | if(mode == 4) 557 | { 558 | load_paletteext(palette,addresspal); 559 | mode = 0; 560 | } 561 | 562 | //------------------------------- 563 | 564 | printf("color : %d\n",ncolor); 565 | if(bpp == 4) ncolor = 4; 566 | if(bpp == 16) ncolor = 16; 567 | if(bpp == 256) ncolor = 256; 568 | 569 | //------------------------------- 570 | output_filename(address,sstr); 571 | if(option[4] == 1) 572 | { 573 | if(option[3] == 1) sprintf(str,"%s_%d.asm",sstr,num); 574 | else sprintf(str,"%s_%d.spr",sstr,num); 575 | }else 576 | { 577 | if(option[3] == 1) sprintf(str,"%s.asm",sstr); 578 | else sprintf(str,"%s.spr",sstr); 579 | } 580 | if(option[3] == 1) file = fopen(str,"w"); 581 | else file = fopen(str,"wb"); 582 | 583 | if(mode == 0 || mode == 2 || mode == 4) 584 | size = write_rom(file,image,pixel,palette,ncolor,type,!option[3]); 585 | 586 | if(option[3] == 0) 587 | { 588 | fclose(file); 589 | sprintf(str,"%s.pal",sstr); 590 | if(option[4] == 1) sprintf(str,"%s_%d.pal",sstr,num); 591 | file = fopen(str,"wb"); 592 | } 593 | 594 | psize = write_pal(file,image,sstr,palette,pixel,ncolor,mode,taille,!option[3]); 595 | 596 | if(option[3] == 1) 597 | write_end(file,psize,size); 598 | else 599 | fclose(file); 600 | } 601 | 602 | -------------------------------------------------------------------------------- /snesconvert.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 43 | 44 | --------------------------------------------------------------------------------