/*
	bdump.c
	file bit-map dump utility
	参考:例解Ｃ言語テキスト　桐山清著　共立出版
	use LSI-C 3.30 試食版
	lcc bdump -ltinymin.obj -lintlib -ldoslib
	1993/10/29
	1993/11/01
*/

#define COPYLEFT "file bit-map dump utility v0.02 (c) calo"
#define USAGE "usage: bdump [-/opt] filename\n"\
"<opt> h/? : this mes.   o: 先頭からのオフセット    b: ブロックサイズ \n"\
"         w: ビット幅    s: スタートブロック        e: エンドブロック \n"\
"         c: 文字列表示  p: 標準エラー出力の抑制"

#include <stdio.h>
#include <stdlib.h>

#ifdef DEBUG
#define D(f) f
#else 
#define D(f)
#endif 

#define C_Y "\33[33m"
#define C_S "\33[36m"
#define C_m "\33[m"
#define SEN "===================="

typedef unsigned char byte;
typedef unsigned short int uint;
typedef unsigned long int ulong;
enum p { OFF, ON };

int help( char *fn, char *errmes );
int bdump( FILE *fp, ulong ofs, uint buf, uint bitw, uint ks, uint ke,
		enum p serr );
void sjb( FILE *fp, ulong ofs, uint buf, uint bitw,
		enum p serr, unsigned char *s);

void main( int argc, char **argv ){
	FILE *fp;
	int i;
	ulong ofs;
	uint bitw,bufsz,ks,ke;
	enum p serr = OFF;
	int fnn = NULL, cfc = NULL;
	/* 24dot font */
	ofs = 16 + 2;		/* 32,48,60dot 16 */
	bufsz = 24*24/8 + 2;	/* 32,48dot dot*dot/8 60dot 60*64/8 */
	ks = 1411; /* 漢字 '亜'  4419:'弌' */
	ke = 8835; /* データ終わり */
	bitw = 24;		/* 32,48,64 */

	if(argc==1) help( argv[0],NULL );
	for (i=1;i<argc;i++) {
		if( argv[i][0] == '-' || argv[i][0] == '/' ){
			switch (argv[i][1]) {
			case 'o':case 'O': /* header offset */
				ofs = atol( argv[i+1] );
				i++;
				break;
			case 'b':case 'B': /* buffer size */
				bufsz = atoi( argv[i+1] );
				bufsz = ( bufsz < 1 ) ? 1 : bufsz ;
				i++;
				break;
			case 'w':case 'W': /* bit-map width */
				if((bitw = atoi( argv[i+1] ))==0)
					help( argv[0],"w:０ビットはあかん.");
				i++;
				break;
			case 's':case 'S': /* start */
				ks = atoi( argv[i+1] );
				i++;
				break;
			case 'e':case 'E': /* end */
				ke = atoi( argv[i+1] );
				i++;
				break;
			case 'c':case 'C': /* 文字列表示 */
				cfc = i+1;
				i++;
			case 'p':case 'P': /* stderr */
				serr = ON;
				break;
			case 'h':case 'H': case '?':
				help( argv[0],NULL );
			default:
				help( argv[0],"option error." );
			}
		} else {

		D(fprintf(stderr,"%s\n",argv[i] ));

			if(fnn == NULL ) fnn = i;
		}
	}
	if( fnn == NULL ) help( argv[0],"filename missing.");
	if((fp=fopen( argv[fnn] , "r+b" ))==NULL )
				help( argv[0],"file open error." );

	if( cfc == NULL ){
		bdump(fp,ofs,bufsz,bitw,ks,ke,serr);
	} else {
		sjb(fp,ofs,bufsz,bitw,serr,argv[cfc]);
	}
				

#ifdef DEBUG
	fprintf(stderr,"ofs:%lu buf:%lu bit:%u ks:%lu ke:%lu\n",
			ofs,     bufsz,  bitw,   ks,    ke );
	if( fp != NULL ) fclose( fp );
	return;
#endif 

	fclose( fp );
}

int help( char *fn, char *errmes ){
	fprintf(stderr,"%s :"COPYLEFT"\n",fn);
	if(errmes!=NULL) fprintf(stderr,"Eroor: %s\n",errmes);
	fprintf(stderr,USAGE);
	exit(1);
}

int bdump( FILE *fp, ulong ofs, uint buf, uint bitw, uint ks, uint ke,
		enum p serr ){
	uint x,y;
	signed long int k;
	byte *ft,*buff,s[100],f;

	buff = (byte *) calloc( buf,sizeof(byte) );
	if(buff==NULL){
		fprintf(stderr,"バッファ確保出来ません.\n");
		return;
	}
	ft = buff;
	
	D(fprintf(stderr,"ofs:%lu buf:%lu bit:%u ks:%lu ke:%lu\n",
			ofs,     buf,   bitw,   ks,    ke ));
	
	for(k=ks;;k++){
		if((kbhit()!=0)&&(serr==OFF)) switch (getch()) {
			case 28: /* → */
				k += 100;
				break;
			case 29: /* ← */
				printf("o:");
				scanf("%lu",&ofs);
				printf("w:");
				scanf("%u",&bitw);
				D(printf("ofs:%lu bitw:%u\n",ofs,bitw));
				D(getch());
				if( bitw == 0 ) bitw = 1;
				break;
			case 30: /* ↑ */
				printf("block no.:");
				scanf("%lu",&k);
				break;
			case 31: /* ↓ */
				k = -1;
				break;
			default:
				;
		}
		if(k<0) break;
		if(k>ke) break;
		if(fseek(fp,(long)(k-1)*buf+ofs,SEEK_SET)!=NULL){
			fprintf(stderr,"範囲指定エラー\n");
			k = ks;
			continue;
		}
		if(fread(buff,buf,1,fp)!=1){
			fprintf(stderr,"読み込みエラー\n");
			break;
		}

	D(fprintf(stderr,"[%x]-----------------------------------\n",ft));

 		for (f=0x80,ft=buff,y=0;y<(buf*8/bitw);y++) {
			for (x=0;x<bitw;x++) {
				*(s+x) = (( *(ft) & f ) ? '*' : '.' );
				f >>= 1;
				if( f == 0 ){f = 0x80; ft++;}
			}
			*(s+x) = '\0';
			printf("%s\n",s);
		}

		if( serr == OFF )
			fprintf(stderr,
			C_Y SEN C_S "[block:%4lu]" C_Y SEN C_m ,k);
		printf( "\n" );
	}
	free(buff);
}

void sjb( FILE *fp, ulong ofs, uint buf, uint bitw,
		enum p serr, unsigned char *s){
	uint sh,sl;
	int i;
	
	for (i=0;s[i]!=NULL;i++) {
		sh = s[i];
		if( sh < 0x81 ) continue;
		sl = s[++i];
		if( sl < 0x3f ) continue;
		/* シフトＪＩＳから ブロックアドレスを求める */
		sh -= ( sh > 0x9f ) ? 0xc1 : 0x81 ;
		sl -= ( sl > 0x7f ) ? 0x40 : 0x3f ;
		sh = sh * 188 + sl;
		bdump(fp,ofs,buf,bitw,sh,sh,serr);
	}
}
