/****************************************************************
	    Set bomb data  for CAR RACE  version 1.21
		  Programmed by Y.Nishida
					[ Apr.20, 1990 ]
 ****************************************************************/

#include	<stdio.h>
#include	<memory.h>
#include	<strings.h>
#include	<ctype.h>

#define		unchar		unsigned char
#define		unshort		unsigned short
#define		TRUE		1
#define		FALSE		0
#define		BOMBCHR1	0xc8
#define		BOMBCHR2	0xca

#define		MAXPNL		0x6000
#define		MAXSLT		0x8000
#define		MAXROM		0x1e00
#define		MAXWLD		0x0200
#define		MAXBOMB		64

#define		high(n)		(((n)>>8)&0xff)
#define		low(n)		((n)&0xff)

unchar	pnlbuf[MAXPNL] ;		/* panel buffer		*/
unchar	sltbuf[MAXSLT] ;		/* slit data buffer	*/
unchar	wldbuf[MAXWLD] ;		/* world data buffer	*/
unchar	rombuf[MAXROM] ;		/* room data buffer	*/

struct	STACK {
		int	posx ;		/* bomb position x	*/
		int	posy ;		/* bomb position y	*/
		int	room ;		/* bomb room pointer	*/
		int	slit ;		/* bomb slit pointer	*/
	} bomb[MAXBOMB] ;

int	bombct = 0 ;			/* bomb counter		*/
int	romcnt = 0 ;			/* room	counter		*/

int	romptr ;			/* room data pointer	*/
int	sltptr ;			/* slit data pointer	*/
int	pnlptr ;			/* panel data pointer	*/
int	sltofs ;			/* slit buffer offset	*/


main( argc,argv )
int	argc ;
char	**argv ;
{
	FILE	*fp ;
	char	pnl_name[65] ;
	char	wld_name[65] ;
	char	slt_name[65] ;
	char	dat_name[65] ;

	puts( "\nSet bomb data  for CAR RACE  version 1.21" ) ;
	if ( argc != 4 ) {
		fputs( "usage: setbomb <slit address> <panel name> <map name>\n",stderr ) ;
		exit( 1 ) ;
	}
	sltofs = getaddr( *(++argv)) ;

	strcpy( pnl_name,*(++argv)) ;
	strcat( pnl_name,".PNL" ) ;
	readpnl( pnl_name ) ;

	strcpy( wld_name,*(++argv)) ;
	strcat( wld_name,".WLD" ) ;
	readwld( wld_name ) ;

	strcpy( slt_name,*argv ) ;
	strcat( slt_name,".SLT" ) ;
	readslt( slt_name ) ;

	set_bomb() ;

	strcat( wld_name,"2" ) ;
	makewld( wld_name ) ;
	exit ( 0 ) ;
}

/****************************************************************/
/*	Set bomb main						*/
/****************************************************************/

set_bomb()
{
	struct	STACK	*ptr ;
	int	sltadr = 0x4000 ;
	int	ct ;

	push_pos() ;
	if ( bombct ) {
		for ( ptr=bomb,ct=0 ; ct<bombct ; ptr++,ct++ ) {
			rombuf[ptr->room+0] =  low( sltadr ) ;
			rombuf[ptr->room+1] = high( sltadr ) ;
			sltadr += 32 ;
			printf( "slit %2d: room $%04X    slit = $%04X\n", ct,ptr->room,ptr->slit ) ;
		}
	}
	else {
		puts( "undefined bomb panel" ) ;
	}
}

/***************  push bomb position  **************************/

push_pos()
{
	int	loc_x,loc_y,sltpos ;

	for ( loc_y=0x0200 ; loc_y<0x0e00 ; loc_y+=0x10 ) {
		for ( loc_x=0x0010 ; loc_x<0x1df0 ; loc_x+=0x10 ) {
			sltpos = search( loc_x,loc_y ) ;

			if ( pnlbuf[pnlptr+3] == BOMBCHR1 || pnlbuf[pnlptr+2] == BOMBCHR2 ) {
				if ( bombct == MAXBOMB ) {
					puts( "too meny bomb." ) ;
					exit( 1 ) ;
				}
				bomb[bombct].posx = loc_x ;
				bomb[bombct].posy = loc_y ;
				bomb[bombct].room = romptr + sltpos ;
				bomb[bombct].slit = sltptr + sltofs ;
				bombct ++ ;
				loc_x = ( loc_x & 0x1f00 ) + 0x0100 ;
				sch_room( loc_x,loc_y ) ;
			}
		}
	}
}

/***************  search panel  *********************************/

search( loc_x,loc_y )
int	loc_x,loc_y ;
{
	int	sltpos,pnlpos,roomct ;

	sltpos = ( loc_y & 0x00f0 ) >> 3 ;
	pnlpos = ( loc_x & 0x00f0 ) >> 3 ;
	roomct = (( loc_y & 0x0f00 )) >> 3 | (( loc_x & 0x1f00 ) >> 8 ) ;

	romptr = wldbuf[roomct] << 5 ;
	sltptr = rombuf[romptr+sltpos] + rombuf[romptr+sltpos+1] * 256 - sltofs ;
	pnlptr = sltbuf[sltptr+pnlpos] + sltbuf[sltptr+pnlpos+1] * 256 ;
	return ( sltpos ) ;
}

/***************  search the same room  ************************/

sch_room( loc_x,loc_y )
int	loc_x,loc_y ;
{
	int	room,roomct ;

	roomct = (( loc_y & 0x0f00 )) >> 3 | (( loc_x & 0x1f00 ) >> 8 ) ;
	room   = wldbuf[roomct-1] ;

	while ( roomct < MAXWLD ) {
		if ( wldbuf[roomct] == room ) {
			printf( "found the same room. ($%02X)    create new room. ($%02X)\n",room,romcnt ) ;
			wldbuf[roomct] = romcnt ;
			memcpy( &rombuf[romcnt*32],&rombuf[room*32],32 ) ;
			romcnt++ ;
		}
		roomct++ ;
	}
}

/****************************************************************/
/*	get slit start address					*/
/****************************************************************/

int getaddr( str )
char	*str ;
{
	int	ch,nn=0 ;

	ch = *str ;
	while ( isxdigit( ch )) {
		     if ( ch <= '9' ) ch -= '0' ;
		else if ( ch <= 'F' ) ch -= 'A'-10 ;
		else		      ch -= 'a'-10 ;
		nn = nn * 16 + ch ;
		ch = *++str ;
	}
	return ( nn ) ;
}

/****************************************************************/
/*	Read panel data						*/
/****************************************************************/

readpnl( fname )
char	*fname ;
{
	FILE	*rp ;
	unchar	*pt ;
	int	cc ;

	if (( rp = fopen( fname,"r" )) == NULL ) {
		perror( fname ) ;
		exit( 1 ) ;
	}
	printf( "read panel data.\t\"%s\"\n", fname ) ;

	pt = pnlbuf ;
	while (( cc = fgetc( rp )) != EOF ) *pt++ = cc ;
	fclose( rp ) ;
}

/****************************************************************/
/*	Read world data						*/
/****************************************************************/

readwld( fname )
char	*fname ;
{
	FILE	*rp ;
	unchar	*pt ;
	int	ct ;

	if (( rp = fopen( fname,"r" )) == NULL ) {
		perror( fname ) ;
		exit( 1 ) ;
	}
	printf( "read world data.\t\"%s\"\n", fname ) ;

	pt = wldbuf ;
	for ( ct=0 ; ct<0x200 ; ct++ ) *pt++ = fgetc( rp ) ;

	pt = rombuf ;
	while ( fread( pt,sizeof(char),32,rp ) == 32 ) {
		pt += 32 ;
		romcnt ++ ;
	}
	fclose( rp ) ;
}

/****************************************************************/
/*	Read slit data						*/
/****************************************************************/

readslt( fname )
char	*fname ;
{
	FILE	*rp ;
	unchar	*pt ;
	int	cc ;

	if (( rp = fopen( fname,"r" )) == NULL ) {
		perror( fname ) ;
		exit( 1 ) ;
	}
	printf( "read  slit data.\t\"%s\"\n", fname ) ;

	pt = sltbuf ;
	while (( cc = fgetc( rp )) != EOF ) *pt++ = cc ;
	fclose( rp ) ;
}

/****************************************************************/
/*	Write world data					*/
/****************************************************************/

makewld( fname )
char	*fname ;
{
	FILE	*wp ;
	unchar	*pt ;
	int	ct ;

	if (( wp = fopen( fname,"w" )) == NULL ) {
		perror( fname ) ;
		exit( 1 ) ;
	}
	printf( "write world data.\t\"%s\"\n", fname ) ;

	for ( pt=wldbuf,ct=0 ; ct<MAXWLD ; pt++,ct++ ) {
		fputc( *pt,wp ) ;
	}
	for ( pt=rombuf,ct=0 ; ct<romcnt ; pt+=32,ct++ ) {
		fwrite( pt,sizeof(char),32,wp ) ;
	}
	fclose( wp ) ;
}
