1 // #define ALLEGRO_STATICLINK
10 volatile int target_game_time
= 0;
15 unsigned char * mem
= 0;
24 //int offset = 1322704;
35 int skipmode
= 0; // 0 = skip bytes after picture , 1 = skip bytes after each bitplane
40 int palsearchmode
= 2;
42 char pmoder
[4] = { 'S', 'X', 'E', 'A' };
58 int bplorder
[8] = {0,1,2,3,4,5,6,7};
60 char gotottt
[256] = "Go To BYTE:";
62 DIALOG goto_dialog
[] =
64 /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) */
65 { d_billwin_proc
, 0, 0, 180, 60, 255, 0, 0, 0,
66 BW_BUFFEREDUPDATE
, 0, gotottt
},
68 { d_billbutton_proc
, 100, 28, 70, 15, 255, 0, 27, D_EXIT
, 0, 0, "DONE"},
70 { d_billedit_proc
, 10, 30, 70, 12, 0, 0, 0, 0, 8, 0, goto_num
},
72 { NULL
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
}
75 char save_name
[255] = "p.bmp";
76 char save_x
[255] = "1";
77 char save_y
[255] = "1";
78 char save_border
[255] = "0";
79 char save_bcolor
[255] = "253";
81 DIALOG save_dialog
[] =
83 /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) */
84 { d_billwin_proc
, 0, 0, 320, 130, 255, 0, 0, 0,
85 BW_BUFFEREDUPDATE
, 0, "Save Picture(s)" },
87 { d_billbutton_proc
, 210, 105, 70, 15, 255, 0, 27, D_EXIT
, 0, 0, "EXIT"},
89 { d_billtext_proc
, 10, 23, 0, 0, 0, 0, 0, 0, 0, 0, "Filename:" },
90 { d_billedit_proc
, 90, 21, 220, 12, 0, 0, 0, 0, 200, 0, save_name
},
92 { d_billtext_proc
, 10, 50, 0, 0, 0, 0, 0, 0, 0, 0, "Pictures in X:" },
93 { d_billedit_proc
, 130, 48, 40, 12, 0, 0, 0, 0, 8, 0, save_x
},
95 { d_billtext_proc
, 10, 70, 0, 0, 0, 0, 0, 0, 0, 0, "Pictures in Y:" },
96 { d_billedit_proc
, 130, 68, 40, 12, 0, 0, 0, 0, 8, 0, save_y
},
98 { d_billtext_proc
, 190, 40, 0, 0, 0, 0, 0, 0, 0, 0, "Save Direction:" },
99 { d_billradio_proc
, 190, 55, 60, 12, 0, 0, 0,D_SELECTED
, 0, 0, "Left -> Right" },
100 { d_billradio_proc
, 190, 70, 60, 12, 0, 0, 0, 0, 0, 0, "Up -> Down" },
102 { d_billbutton_proc
, 40, 105, 70, 15, 255, 0, 27, D_EXIT
, 0, 0, "SAVE"},
104 { d_billtext_proc
, 10, 90, 0, 0, 0, 0, 0, 0, 0, 0, "Border Around:" },
105 { d_billedit_proc
, 130, 88, 40, 12, 0, 0, 0, 0, 8, 0, save_border
},
107 { d_billtext_proc
, 185, 90, 0, 0, 0, 0, 0, 0, 0, 0, "Colour:" },
108 { d_billedit_proc
, 250, 88, 40, 12, 0, 0, 0, 0, 8, 0, save_bcolor
},
110 { NULL
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
}
113 int getpixelcol(int pos
, int x
, int y
)
123 for (i
=0; i
< 8; i
++)
128 for (i
=0; i
< bits
; i
++)
133 // Amiga type bitplanes
134 p
= pos
+(blXSize
*blYSize
)*(i
);
135 nn
= x
+(y
*(blXSize
*8));
140 nn
= x
+(bits
*y
*(blXSize
*8));
143 // mode == 2 // Amiga Sprite !!!
147 nn
= x
+((2*y
)*(blXSize
*8));
151 p
= pos
+blXSize
*(i
-2)+(blYSize
*blXSize
)*2;
152 nn
= x
+((2*y
)*(blXSize
*8));
156 // mode == 3 // CPC gfx for Bat-Man / HoH
158 nn
= x
+((2*y
)*(blXSize
*8));
161 // mode ==4 // CPC gfx for Ultimate games
162 p
= pos
+(x
/4)+(blXSize
*y
*2);
182 if (mem
[p
+byte1
] & (1 << bit1
))
197 for (i
=0; i
< bits
; i
++)
199 if (bit
[bplorder
[i
]])
207 void drawbitmap(BITMAP
* bmp
, int pos
, int xx
, int yy
)
209 for (int x
= 0; x
< blXSize
*8; x
++)
211 for (int y
= 0; y
< blYSize
; y
++)
213 putpixel(bmp
, xx
+x
, yy
+y
, getpixelcol(pos
, x
, y
));
224 for (int y
=0; y
< numY
; y
++)
226 for (int x
=0; x
< numX
; x
++)
228 xx
= x
*(blXSize
*8+hole
);
229 yy
= legend
+y
*(blYSize
+hole
);
231 drawbitmap(bitmap
, pos
, xx
, yy
);
232 // pos+=((blXSize*blYSize)*bits)+skip;
235 pos
+=((blXSize
*blYSize
)*bits
)+skip
;
239 pos
+=((blXSize
*blYSize
+skip
)*bits
);
249 xx
= scrW
-(blXSize
*8*2+4);
250 yy
= scrH
-(blYSize
*2+4);
260 stretch_blit(bitmap
, bitmap
, 0, legend
, blXSize
*8, blYSize
, xx
+2, yy
+2, blXSize
*8*2, blYSize
*2);
261 rect(bitmap
,xx
,yy
,scrW
-1,scrH
-1,makecol(0,0,255));
262 rect(bitmap
,xx
+1,yy
+1,scrW
-2,scrH
-2,253);
265 static BITMAPINFO
*get_bitmap_info(BITMAP
* bitmap
, PALETTE pal
)
271 bi
= (BITMAPINFO
*)malloc(sizeof(BITMAPINFO
) + sizeof(RGBQUAD
) * 256);
275 ZeroMemory(&bi
->bmiHeader
, sizeof(BITMAPINFOHEADER
));
277 bi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
278 bi
->bmiHeader
.biBitCount
= 8;
279 bi
->bmiHeader
.biPlanes
= 1;
280 bi
->bmiHeader
.biWidth
= bitmap
->w
;
281 bi
->bmiHeader
.biHeight
= -bitmap
->h
;
282 bi
->bmiHeader
.biClrUsed
= 256;
283 bi
->bmiHeader
.biCompression
= BI_RGB
;
286 for (x
= 0; x
< 256; x
++) {
287 bi
->bmiColors
[x
].rgbRed
= _rgb_scale_6
[pal
[x
].r
];
288 bi
->bmiColors
[x
].rgbGreen
= _rgb_scale_6
[pal
[x
].g
];
289 bi
->bmiColors
[x
].rgbBlue
= _rgb_scale_6
[pal
[x
].b
];
290 bi
->bmiColors
[x
].rgbReserved
= 0;
298 static BYTE
*get_dib(BITMAP
* bitmap
)
307 pitch
= (pitch
+ 3) & ~3; /* align on dword */
309 pixels
= (BYTE
*) malloc(bitmap
->h
* pitch
);
313 /* this code will probably need optimalization. if anybody can
314 * optimalize it, do so!
316 for (y
= 0; y
< bitmap
->h
; y
++) {
317 memcpy(pixels
+ y
* pitch
, bitmap
->line
[y
], bitmap
->w
);
323 HBITMAP
convert_bitmap_to_hbitmap2(BITMAP
* bitmap
)
328 HPALETTE hpal
, holdpal
;
331 pixels
= get_dib(bitmap
);
333 /* when we have DIB, we can convert it to DDB */
336 bi
= get_bitmap_info(bitmap
, _current_palette
);
338 hpal
= convert_palette_to_hpalette(_current_palette
);
339 holdpal
= SelectPalette(hdc
, hpal
, TRUE
);
341 hbmp
= CreateDIBitmap(hdc
, &bi
->bmiHeader
, CBM_INIT
, pixels
, bi
, DIB_RGB_COLORS
);
342 ReleaseDC(NULL
, hdc
);
344 SelectPalette(hdc
, holdpal
, TRUE
);
354 void copyBitmapToClipboard(BITMAP
*bmp
) {
356 if (OpenClipboard(win_get_window())) {
357 if (EmptyClipboard()) {
358 HBITMAP hbmp
= convert_bitmap_to_hbitmap2(bmp
);
360 if (!SetClipboardData(CF_BITMAP
, hbmp
)) {
372 BITMAP
* bm
= create_bitmap(blXSize
*8, blYSize
);
374 blit(bitmap
, bm
, 0, legend
, 0, 0, blXSize
*8, blYSize
);
376 copyBitmapToClipboard(bm
);
384 clear_to_color(bitmap
, 253);
388 numX
= scrW
/(blXSize
*8+hole
);
389 numY
= (scrH
-legend
)/(blYSize
+hole
);
436 textprintf(bitmap
, font
, 0, 0, 254, "Off:%7i Siz: X:%4i Y:%4i Bit:%i Vis.X:%2i Y:%2i Pal%c:%7i Mode:%s Skip-%c:%4i Order:%c %i%i%i%i%i%i%i%i", offset
,blXSize
*8, blYSize
, bits
, numX
, numY
, pmoder
[palsearchmode
], palfound
, moder
, skipmoder
, skip
, rev
,
437 bplorder
[7], bplorder
[6], bplorder
[5], bplorder
[4], bplorder
[3], bplorder
[2], bplorder
[1], bplorder
[0] );
446 blit(bitmap
, screen
, 0, 0, 0, 0, scrW
, scrH
);
452 for (int i
=0; i
< 256; i
++)
454 pal
[i
].r
= rand()%64;
455 pal
[i
].g
= rand()%64;
456 pal
[i
].b
= rand()%64;
458 pal
[1].r
= pal
[1].g
= pal
[1].b
= 0;
459 pal
[0].r
= pal
[0].g
= pal
[0].b
= 63;
460 pal
[254].r
= pal
[254].g
= pal
[254].b
= 0;
461 pal
[253].r
= pal
[253].g
= pal
[253].b
= 50;
464 int parse_number(char * str
)
472 sscanf(str
, "%d", &t
);
478 sprintf(gotottt
, "Go To BYTE:");
480 sprintf(goto_num
, "%i", offset
);
483 init_moveable(goto_dialog
);
487 do_dialog (goto_dialog
, 0);
489 shutdown_moveable(goto_dialog
);
493 offset
= parse_number(goto_num
);
498 sprintf(gotottt
, "Skip Value:");
500 sprintf(goto_num
, "%i", offset
);
503 init_moveable(goto_dialog
);
507 do_dialog (goto_dialog
, 0);
509 shutdown_moveable(goto_dialog
);
513 skip
= parse_number(goto_num
);
516 void prepare_save_name()
523 strcpy(temp
, save_name
);
526 while (t
>= 0 && temp
[t
] != '.')
534 if (temp
[t
-1] >= '0' && temp
[t
-1] <= '9' &&
535 temp
[t
-2] >= '0' && temp
[t
-2] <= '9' &&
536 temp
[t
-3] >= '0' && temp
[t
-3] <= '9')
543 strcat(temp
, "000.bmp");
548 sprintf(temp2
, "%03i.bmp", contin_save
);
553 strcpy(save_name
,temp
);
567 init_moveable(save_dialog
);
571 t
= do_dialog (save_dialog
, 0);
573 shutdown_moveable(save_dialog
);
579 int numX
= parse_number(save_x
);
580 int numY
= parse_number(save_y
);
581 int border
= parse_number(save_border
);
582 int bcolor
= parse_number(save_bcolor
);
591 bool direction
= false;
592 if (save_dialog
[9].flags
& D_SELECTED
)
596 int xs
= (blXSize
*8+border
)*numX
;
597 int ys
= (blYSize
+border
)*numY
;
599 BITMAP
* temp
= create_bitmap(xs
, ys
);
601 clear_to_color(temp
, bcolor
);
608 for (int x
=0; x
< numX
; x
++)
610 for (int y
=0; y
< numY
; y
++)
612 xx
= x
*(blXSize
*8+border
);
613 yy
= y
*(blYSize
+border
);
615 drawbitmap(temp
, pos
, xx
, yy
);
616 pos
+=(blXSize
*blYSize
)*bits
+skip
;
622 for (int y
=0; y
< numY
; y
++)
624 for (int x
=0; x
< numX
; x
++)
626 xx
= x
*(blXSize
*8+border
);
627 yy
= y
*(blYSize
+border
);
629 drawbitmap(temp
, pos
, xx
, yy
);
630 pos
+=(blXSize
*blYSize
)*bits
+skip
;
635 if (exists(save_name
))
637 if ( billalert("Question!",
638 "This file already exists !",
639 "Do you want to overwrite it ?",
640 "NO", "YES", 27, 0) == 2)
642 save_bmp(save_name
, temp
, pal
);
643 destroy_bitmap(temp
);
647 save_bmp(save_name
, temp
, pal
);
648 destroy_bitmap(temp
);
654 // Simpler method to find palettes !
656 while (!found
&& ttt
< fsize
-64)
658 if (mem
[ttt
] == 0x01 && mem
[ttt
+1] == 0x80 && mem
[ttt
+4] == 0x01 && mem
[ttt
+5] == 0x82)
664 for (int i
=0; i
< 32; i
++)
692 // More advanced method to find palettes !
694 bool nomorecols
= false;
697 for (int i
=0; i
< 32; i
++)
702 while (!found
&& ttt
< fsize
-64)
704 if (mem
[ttt
+0] == 0x01 && mem
[ttt
+1] >= 0x80 && mem
[ttt
+1] <=0x9f &&
705 mem
[ttt
+4] == 0x01 && mem
[ttt
+5] >= 0x80 && mem
[ttt
+5] <=0x9f &&
706 mem
[ttt
+8] == 0x01 && mem
[ttt
+9] >= 0x80 && mem
[ttt
+9] <=0x9f &&
707 mem
[ttt
+12] == 0x01 && mem
[ttt
+13] >= 0x80 && mem
[ttt
+13] <=0x9f)
718 while (ttt
+(i
*4) < fsize
-2 && !ended
)
720 if (mem
[ttt
+(i
*4)+0] == 0xff && mem
[ttt
+(i
*4)+1] == 0xff)
726 if (mem
[ttt
+1+(i
*4)] >= 0x80 && mem
[ttt
+1+(i
*4)] <= 0xbf)
728 colind
= (mem
[ttt
+1+(i
*4)]-0x80)>>1;
729 if (!colfound
[colind
])
731 colfound
[colind
] = true;
732 c1
= mem
[ttt
+2+(i
*4)];
733 c2
= mem
[ttt
+3+(i
*4)];
779 int find_chunk(char * name
)
786 if (!memcmp(name
, &mem
[pos
], 4))
791 add
= mem
[pos
+4]*256*256*256+mem
[pos
+5]*256*256+mem
[pos
+6]*256+mem
[pos
+7]+4;
803 // Grab the palette from the snapshot
805 pos
= find_chunk("CHIP");
808 palfound
= pos
+4+8+4+0x0180 - (64 + 12*8);
809 for (int i
=0; i
< 63; i
++)
814 c1
= mem
[palfound
+i
*2];
815 c2
= mem
[palfound
+i
*2+1];
834 // Grab the AGA palette from the snapshot
836 pos
= find_chunk("AGAC");
840 for (int i
=0; i
< 256; i
++)
844 r
= mem
[palfound
+i
*4+1];
845 g
= mem
[palfound
+i
*4+2];
846 b
= mem
[palfound
+i
*4+3];
857 void getpalettefile()
863 int ret
= billfile_select("Select BMP file", buf
, "bmp");
866 f
= fopen(buf
, "rt");
869 t
= load_bmp(buf
, pal
);
879 int main(int argc
, char *argv
[])
882 install_allegro(SYSTEM_AUTODETECT
, &errno
, atexit
);
886 if(install_keyboard())
889 allegro_message("Error installing keyboard handler.\nExiting");
893 if(0 > set_gfx_mode(GFX_SAFE
, scrW
, scrH
, 0, 0))
896 allegro_message("Error setting graphics mode.\nExiting");
904 // bill_init_smallpal(17);
911 billfile_select("Select file", buf
, NULL
);
915 strcpy(buf
, argv
[1]);
917 file
= fopen(buf
, "rb");
920 fsize
= file_size(buf
);
923 mem
= (unsigned char *) malloc(fsize
);
926 fread((void *) mem
, 1, fsize
, file
);
933 bitmap
= create_bitmap(scrW
, scrH
);
937 centre_dialog(goto_dialog
);
938 centre_dialog(save_dialog
);
940 while (keyp
!= KEY_ESC
)
945 if (keyp
>= KEY_0
&& keyp
<= KEY_8
)
948 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
951 if (bplorder
[nn
] < 0)
959 if (bplorder
[nn
] > 7)
973 pal
[0].r
= pal
[0].b
= 63;
988 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
990 if (offset
>= (blXSize
*8*modeskip
) )
992 offset
-=blXSize
*8*modeskip
;
997 if (offset
>= blXSize
*modeskip
)
999 offset
-=blXSize
*modeskip
;
1004 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1006 if (offset
< (fsize
-blXSize
*8*modeskip
))
1008 offset
+=blXSize
*8*modeskip
;
1013 if (offset
< fsize
-(blXSize
*modeskip
))
1015 offset
+=blXSize
*modeskip
;
1020 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1022 if (offset
>= (blXSize
*blYSize
*bits
)+skip
)
1024 offset
-=(blXSize
*blYSize
*bits
)+skip
;
1036 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1038 if (offset
< fsize
-((blXSize
*blYSize
*bits
)+skip
))
1040 offset
+=(blXSize
*blYSize
*bits
)+skip
;
1064 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1074 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1106 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1116 switch (palsearchmode
)
1134 switch (palsearchmode
)
1158 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1168 if (key
[KEY_LSHIFT
] || key
[KEY_RSHIFT
])
1195 if (palsearchmode
== 4)
1214 if (key
[KEY_LCONTROL
] || key
[KEY_RCONTROL
])
1223 destroy_bitmap(bitmap
);