/* ** Bobi - The Ultimate Amiga Bob Manipulator ** ** Generate.c - Assembler Source, Biärfile oder Objektmodul generieren ** ** COPYRIGHT (C) 1989-1993 BY CHRISTIAN A. WEBER, ZUERICH, SWITZERLAND. ** ALL RIGHTS RESERVED. NO PART OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, ** OR TRANSMITTED IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN ** PERMISSION OF THE AUTHOR. NO WARRANTY. USE AT YOUR OWN RISK. */ #include #include #include #include #include #include #include "HunkDefs.h" #include "GenerateWindow.h" #include "Bobi.h" #include "BobStructure.h" extern struct MyBob *BobTable[]; extern struct Screen *mainscreen; extern WORD numbobs; extern UWORD mainpalette[]; extern char idstring[],outputname[],sectionname[],LabelGadgetSIBuff[]; extern WORD outputflags; extern char arexxfilename[]; extern BYTE arexxflag; static BPTR file; static LONG filesize; /**************************************************************************** ** Daten in File schreiben und filesize erhöhen */ static void MyWrite(void *adr,LONG len) { Write(file,adr,len); filesize += len; } /**************************************************************************** ** C formatierter String auf ein File ausgeben, filesize erhöhen */ static void fputf(char *text,...) { char buf[256]; va_list args; va_start(args,text); vsprintf(buf,text,args); MyWrite(buf,strlen(buf)); va_end(args); } /**************************************************************************** ** Langwort in File schreiben */ static void fputl(LONG loy) { MyWrite(&loy,4); } /**************************************************************************** ** Wort in File schreiben */ static void fputw(UWORD woy) { MyWrite(&woy,2); } /**************************************************************************** ** Symbolnamen mit Länge und Typ im Objektmodul-Format ausgeben */ static void fputsym(char *string,LONG type) { LONG len; char buf[200]; ClearMem(buf,200); len = (strlen(string)+3)>>2; type |= len; MyWrite(&type,4); strcpy(buf,string); MyWrite(buf,len<<2); } /**************************************************************************** ** String mit Länge im Objektmodul-Format ausgeben */ static void fpuths(char *string) { fputsym(string,0); } /**************************************************************************** ** Bob-Maske berechnen mitels OR-Verknüpfung aller Planes */ static void CalculateMask(struct MyBob *bob) { WORD *sptr,*dptr; long i,j; if(bob->Mask) FreeMem(bob->Mask,bob->PlaneSize); if(bob->Mask=AllocMem(bob->PlaneSize,MEMF_CLEAR)) { for(i=0; iDepth; i++) { sptr = (WORD *)bob->Planes[i]; dptr = (WORD *)bob->Mask; for(j=bob->PlaneSize; j>0; j-=2) *(dptr++) |= *(sptr++); } } else ShowMonoReq2("No memory to create bob mask!"); } /**************************************************************************** ** PlanePick und PlaneOnOff berechnen */ static void CalculatePlanePick(struct MyBob *bob) { WORD *sptr,*dptr; long i,j,x; bob->PlanePick = (1<Depth)-1; bob->PlaneOnOff = 0; for(i=0; iDepth; ++i) { sptr = (WORD *)bob->Planes[i]; for(j=bob->PlaneSize,x=0; j>0; j-=2) x |= *sptr++; if(x) { sptr = (WORD *)bob->Planes[i]; dptr = (WORD *)bob->Mask; for(j=bob->PlaneSize; j>0; j-=2) { if(*dptr++ != *sptr++) goto notequal; } bob->PlanePick &= ~(1<PlaneOnOff |= (1<PlanePick &= ~(1<PlaneSize; x = bob->PlanePick; while(x) { if(x&1) size += bob->PlaneSize; x>>=1; } return size; } /**************************************************************************** ** Totalen Speicherplatzbedarf eines Sprites berechnen */ static LONG TotSpriteSize(struct MyBob *bob) { LONG x,size; size = sizeof(struct BobData); for(x=0; xWidth; x+=16) { size += 4*sizeof(LONG); /* 2x 1 LONG Koords, 1 LONG Endmarkierung */ size += bob->Height*2*4; /* 2 Sprites (attached) x 2 WORDs pro Zeile */ } return size; } /**************************************************************************** ** Ein Bob ins File schreiben */ static void RawDumpBob(struct MyBob *bob) { struct BobData bd; long i; bd.Width = bob->Width; bd.Height = bob->Height; bd.X0 = bob->X0; bd.Y0 = bob->Y0; bd.CollX0 = bob->CollX0-bob->X0; bd.CollY0 = bob->CollY0-bob->Y0; bd.CollX1 = bob->CollX1-bob->X0; bd.CollY1 = bob->CollY1-bob->Y0; bd.PlanePick = bob->PlanePick; bd.PlaneOnOff = bob->PlaneOnOff; bd.Flags = bob->Flags & (~BOB_PRIVATEMASK); bd.WordSize = bob->BytesPerRow/2+1; bd.PlaneSize = bob->PlaneSize; bd.TotalSize = TotBobSize(bob); MyWrite(&bd,sizeof(bd)); if(outputflags & OF_BOBMASK) { MyWrite(bob->Mask,bob->PlaneSize); } for(i=0; iDepth; ++i) { if(bob->PlanePick&(1<Planes[i],bob->PlaneSize); } } /**************************************************************************** ** count Bytes ab ptr als Assembler Source ausgeben (DC.L/DC.W) */ static void AsmHexDump(ULONG *ptr, long count) { long i,rest; rest = count%4; count /= 4; for(i=1; count>0; count--,++i) { if(i==1) fputf("\tDC.L\t$%08lx",*ptr++); else fputf(",$%08lx",*ptr++); if((i==6) || (count==1)) { fputf("\n"); i=0; } } if(rest==2) fputf("\tDC.W\t$%04lx\n",*(UWORD *)ptr); fputf("\n"); } /**************************************************************************** ** Ein Bob als Assembler-Source ausgeben */ static void AsmDumpBob(struct MyBob *bob,WORD num) { long i; if(*(bob->SourceLabel)) fputf("\n\t*** Bob %ld : Header & Mask\n\n%s:\n",num,bob->SourceLabel); else fputf("\n\t*** Bob %ld : Header & Mask\n\n",num); fputf("\tDC.W\t%ld,%ld,%ld,%ld,",bob->Width,bob->Height,bob->X0,bob->Y0); fputf("%ld,%ld,%ld,%ld,",bob->CollX0-bob->X0,bob->CollY0-bob->Y0, bob->CollX1-bob->X0,bob->CollY1-bob->Y0); fputf("$%04lx,$%04lx,%ld,%ld,%ld\n",(bob->PlanePick<<8)+bob->PlaneOnOff, bob->Flags,bob->BytesPerRow/2+1,bob->PlaneSize,TotBobSize(bob)); if(outputflags&OF_BOBMASK) { AsmHexDump((ULONG *)bob->Mask,bob->PlaneSize); } fputf("\t*** Bob %ld : %ld Planes\n\n",num,bob->Depth); for(i=0; iDepth; ++i) { if(bob->PlanePick & (1<Planes[i],bob->PlaneSize); else if(bob->PlaneOnOff & (1<Width-1)/16+1,bob->SourceLabel); fputf("\tDC.W\t%ld,%ld,%ld,%ld,",bob->Width,bob->Height,bob->X0,bob->Y0); fputf("%ld,%ld,%ld,%ld,",bob->CollX0-bob->X0,bob->CollY0-bob->Y0, bob->CollX1-bob->X0,bob->CollY1-bob->Y0); fputf("$%04lx,$%04lx,%ld,%ld,%ld\n",(bob->PlanePick<<8)+bob->PlaneOnOff, bob->Flags,bob->BytesPerRow/2+1,bob->PlaneSize,TotSpriteSize(bob)); if(bob->Width>16) fputf("\tDC.L\t%s.1,%s.2,%s.3,%s.4\n\n",bob->SourceLabel, bob->SourceLabel,bob->SourceLabel,bob->SourceLabel); else fputf("\tDC.L\t%s.1,%s.2\n\n",bob->SourceLabel,bob->SourceLabel); for(x=0; x < ((bob->Width-1)/16+1); ++x) { fputf("%s.%ld:\n",bob->SourceLabel,2*x+1); fputf("\tDC.W\t$0000,$0000\t; Koordinaten\n"); for(y=0; yHeight; ++y) { w1=*(UWORD *)(bob->Planes[0]+y*bob->BytesPerRow+2*x); w2=*(UWORD *)(bob->Planes[1]+y*bob->BytesPerRow+2*x); fputf("\tDC.W\t$%04lx,$%04lx\n",w1,w2); } fputf("\tDC.W\t$0000,$0000\t; End-Markierung\n\n\n"); fputf("%s.%ld:\n",bob->SourceLabel,2*x+2); fputf("\tDC.W\t$0000,$0000\t; Koordinaten\n"); for(y=0; yHeight; ++y) { w1=*(UWORD *)(bob->Planes[2]+y*bob->BytesPerRow+2*x); w2=*(UWORD *)(bob->Planes[3]+y*bob->BytesPerRow+2*x); fputf("\tDC.W\t$%04lx,$%04lx\n",w1,w2); } fputf("\tDC.W\t$0000,$0000\t; End-Markierung\n\n\n"); } } /**************************************************************************** ** Assembler-Source generieren */ static void GenerateAssemblerSource(void) { WORD i; struct DateStamp date; char datebuf[32]; if(file=Open(outputname,MODE_NEWFILE)) { DateStamp(&date); ConvertDate(&date,datebuf); fputf("* Source generated on %s by %s\n\n\tSECTION\t%s,DATA_C\n\n",datebuf,idstring,sectionname); if(outputflags & OF_COLORTABLE) { fputf("\tXDEF\tColorPalette\nColorPalette:\n"); AsmHexDump((ULONG *)mainpalette,2*32); } if(outputflags & OF_BOBDATA) { if(outputflags & OF_GENERATEBOBS) { fputf("* Bob structure: WORD Width, Height, X0, Y0, Collision X0/Y0/X1/Y1\n" "* BYTE PlanePick, PlaneOnOff\n" "* WORD Flags, WORDSize+1, PlaneSize, TotalSize\n\n"); } for(i=0; iSourceLabel); else fputf(",%s",BobTable[i]->SourceLabel); if((i%4)==3) fputf("\n"); } fputf("\n"); for(i=0; i>=2; if(file=Open(outputname,MODE_NEWFILE)) { filesize=0; fputl(HUNK_UNIT); fpuths(idstring); if(outputflags & OF_COLORTABLE) { fputl(HUNK_NAME); fpuths(sectionname); fputl(HUNK_DATA); fputl(64>>2); MyWrite(mainpalette,2*32); fputl(HUNK_EXT); fputsym("ColorPalette",EXT_DEF); fputl(0); fputl(0); fputl(HUNK_END); } if(outputflags & OF_BOBDATA) { fputl(HUNK_NAME); fpuths(sectionname); fputl(HUNK_DATA|HUNKF_CHIP); fputl(datasize); for(i=0; iSourceLabel)) /* Nur Symbols mit Länge >0 */ { fputsym(BobTable[i]->SourceLabel,EXT_DEF); fputl(offset); } offset += TotBobSize(BobTable[i]); } fputl(0); fputl(HUNK_END); } Close(file); } else ShowFileError(outputname); } /**************************************************************************** ** Assembler-Include-File der Bob-Offsets generieren */ static void GenerateHeaderFile(void) { char name[256],datebuf[32]; struct DateStamp date; LONG len,offset=0; if(!strnicmp(outputname,"/DISK/",6)) strcpy(name,outputname+6); /* '/DISK/'-Anfang ignorieren */ else strcpy(name,outputname); len=strlen(name); if(name[len-2]=='.') name[len-1]='i'; else { name[len] = '.' ; name[len+1] = 'i' ; name[len+2] = '\0'; } if(file=Open(name,MODE_NEWFILE)) { DateStamp(&date); ConvertDate(&date,datebuf); fputf("* Header file generated on %s by %s\n",datebuf,idstring); if(outputflags & OF_COLORTABLE) offset=2*32; if(outputflags & OF_BOBDATA) { LONG i; char sizelabel[100]; for(i=0; iSourceLabel)) /* Nur Symbols mit Länge >0 */ { char *sym=BobTable[i]->SourceLabel; if(BobTable[i]->Flags & BODF_ANIMKEY) fputf("\n"); fputf("%s:",sym); if(strlen(sym)<7) Write(file,"\t",1); if(strlen(sym)<15) Write(file,"\t",1); else Write(file," ",1); fputf("EQU\t%ld\n",offset); } offset += TotBobSize(BobTable[i]); } strcpy(sizelabel,LabelGadgetSIBuff); if(!strnicmp(sizelabel+strlen(sizelabel)-3,"%ld",3)) sizelabel[strlen(sizelabel)-3]='\0'; fputf("\n%s_FILESIZE:\tEQU\t%ld\n",sizelabel,offset+4); } Close(file); } else ShowFileError(name); } /**************************************************************************** ** outputflags neu berechnen aus den Gadget-Werten */ static void GetOutputFlags(void) { outputflags = 0; if(GenerateBobsGadget.Flags & SELECTED) outputflags |= OF_GENERATEBOBS; else outputflags |= OF_GENERATESPRITES; if(AssemGadget.Flags & SELECTED) outputflags |= OF_ASSEMBLER; else if(ObjectGadget.Flags & SELECTED) outputflags |= OF_OBJECT; else outputflags |= OF_RAWDATA; if(ColorGadget.Flags & SELECTED) outputflags |= OF_COLORTABLE; if(BobDataGadget.Flags & SELECTED) outputflags |= OF_BOBDATA; if(MaskGadget.Flags & SELECTED) outputflags |= OF_BOBMASK; } /**************************************************************************** ** Gadget-Flags gemäss outputflags setzen */ static void SetOutputFlags(void) { if(outputflags & OF_GENERATEBOBS) { GenerateBobsGadget.Flags |= SELECTED; } else { GenerateBobsGadget.Flags &= ~SELECTED; } if(outputflags & OF_GENERATESPRITES) { GenerateSpritesGadget.Flags |= SELECTED; MaskGadget.Flags &= ~SELECTED; MaskGadget.Flags |= GADGDISABLED; } else { GenerateSpritesGadget.Flags &= ~SELECTED; MaskGadget.Flags |= SELECTED; MaskGadget.Flags &= ~GADGDISABLED; } if(outputflags & OF_ASSEMBLER) AssemGadget.Flags |= SELECTED; else AssemGadget.Flags &= ~SELECTED; if(outputflags & OF_OBJECT) ObjectGadget.Flags |= SELECTED; else ObjectGadget.Flags &= ~SELECTED; if(outputflags & OF_RAWDATA) { RawDataGadget.Flags |= SELECTED; SectionNameGadget.Flags |= GADGDISABLED; } else { RawDataGadget.Flags &= ~SELECTED; SectionNameGadget.Flags &= ~GADGDISABLED; } if(outputflags & OF_COLORTABLE) ColorGadget.Flags |= SELECTED; else ColorGadget.Flags &= ~SELECTED; if(outputflags & OF_BOBDATA) BobDataGadget.Flags |= SELECTED; else BobDataGadget.Flags &= ~SELECTED; if(outputflags & OF_BOBMASK) MaskGadget.Flags |= SELECTED; else MaskGadget.Flags &= ~SELECTED; } /**************************************************************************** ** Menuitem oder ARexx-Kommando: Generate code */ void GenerateCodeFunc() { int flag; LockWindows(); if(outputflags == 0) outputflags = OF_RAWDATA | OF_OBJECT | OF_BOBDATA | OF_BOBMASK; if(arexxflag) { strcpy(outputname,arexxfilename); flag = 1; } else { struct Window *w; struct IntuiMessage *msg; NewWindowStructure1.Screen = mainscreen; FileNameGadgetSInfo.Buffer = outputname; SectionNameGadgetSInfo.Buffer = sectionname; SetOutputFlags(); if(w=OpenWindow(&NewWindowStructure1)) { PrintIText(w->RPort,&IntuiTextList1,0L,0L); flag=0; do { WaitPort(w->UserPort); msg=(struct IntuiMessage *)GetMsg(w->UserPort); if(msg->Class == CLOSEWINDOW) { flag = -1; } else if(msg->Class == GADGETUP) { if(msg->IAddress == (APTR)&OKGadget) { flag = 1; } else if(msg->IAddress == (APTR)&CancelGadget) { flag = -1; } } else if(msg->Class == GADGETDOWN) { if(msg->IAddress == (APTR)&GenerateBobsGadget) { SelectGadget(w,&GenerateBobsGadget); DeselectGadget(w,&GenerateSpritesGadget); OnGadget(&MaskGadget,w,0); OnGadget(&ObjectGadget,w,0); OnGadget(&RawDataGadget,w,0); SelectGadget(w,&MaskGadget); } else if(msg->IAddress == (APTR)&GenerateSpritesGadget) { SelectGadget(w,&GenerateSpritesGadget); DeselectGadget(w,&GenerateBobsGadget); DeselectGadget(w,&MaskGadget); SelectGadget(w,&AssemGadget); OffGadget(&MaskGadget,w,0); OffGadget(&ObjectGadget,w,0); OffGadget(&RawDataGadget,w,0); } else if(msg->IAddress == (APTR)&AssemGadget) { SelectGadget(w,&AssemGadget); DeselectGadget(w,&ObjectGadget); DeselectGadget(w,&RawDataGadget); OnGadget(&SectionNameGadget,w,0); } else if(msg->IAddress == (APTR)&ObjectGadget) { DeselectGadget(w,&AssemGadget); SelectGadget(w,&ObjectGadget); DeselectGadget(w,&RawDataGadget); OnGadget(&SectionNameGadget,w,0); } else if(msg->IAddress == (APTR)&RawDataGadget) { DeselectGadget(w,&AssemGadget); DeselectGadget(w,&ObjectGadget); SelectGadget(w,&RawDataGadget); OffGadget(&SectionNameGadget,w,0); } } } while(!flag); CloseWindow(w); GetOutputFlags(); } else { ShowMonoReq2("Can't open window!"); goto error; } } /* not ARexx */ if(flag>0) /* Falls OK-Gadget angeklickt */ { int i; for(i=0; i