/****************************************************************************
*									    *	
*                          	Copper Snooper				    *	
*                          						    *
*	             Copyright 1986 by The 4th Works, Inc.		    *
*									    *	
*		        	written by:				    *	
*		        	Steve Ahlstrom				    *	
*		        	Dan Moore				    *	
*									    *	
*									    *	
*     This program may be redistributed only with the permission of	    *	
*     one or both of the authors and with this header intact.		    *	
*									    *	
*	--------------------------------------------------------	    *	
*									    *	
*     This program will bring up a high resolution interlaced screen	    *	
*     part way down the video display and in front of the WorkBench	    *	
*     screen.  It will then write a commented listing of the Copper	    *	
*     list for the current display to the currently logged drive.	    *	
*     This file is named Copper.Listing.   If you wish to disassemble       *
*     a WorkBench Copper List change the value of the MYSCREEN define       *
*     to 0 (zero).							    *
*									    *
*     Compiled with Manx Aztec C.  The makefile for this program is	    *
*     below -- it presumes you have created a precompiled header file       *
*     named INCLUDES.PRE.						    *
*     									    *
*     ---------------------------------------------------------------       *
*     									    *
*     .c.o:								    *
*     									    *	
*	cc +IIncludes.pre -o $@ $*.c					    *
*									    *
*	copper: copper.o						    *
*		ln copper.o -o copper -lc				    *	
*									    *
*	copper.o: copper.c						    *
*		cc +IIncludes.pre -Z9000 -o copper.o copper.c		    *
*									    *
****************************************************************************/


/****************************************************************************
*									    *	
*                           I N C L U D E S                                 * 
*									    *
****************************************************************************/

#include "stdio.h"

#include "exec/types.h"
#include "intuition/intuition.h"
#include "libraries/dos.h"
#include "defines.h"
#include "graphics/copper.h"

/* Set this to non-zero to use a custom screen; 0 for WorkBench screen */
#define MYSCREEN 1

/****************************************************************************
*									    *	
*           I N T U I T I O N   G L O B A L   V A R I A B L E S             *
*									    *
****************************************************************************/
 
struct IntuitionBase *IntuitionBase;
struct GfxBase	     *GfxBase;
struct Screen *Screen;
struct cprlist *CopList;

FILE *dest;

char copyright[] = "Copper Snooper\nCopyright 1986 by The 4th Works, Inc.\n";
char nv[] = "NOT VALID";

char *regs[] = {"BLTDDAT: Blitter destination early read (dummy address)",
		"DMACONR: DMA ctrl (and blitter status) read",	
		"VPORS:   Read vert most sig. bit (and frame flop)",
		"VHPOSR:  Read vert and horz pos. of beam",
		"DSKDATR: Disk data early read (dummy address)",
		"JOY0DAT: Joystick/mouse 0 data (vert, horz)",
		"JOY1DAT: Joystick/mouse 1 data (vert, horz)",
		"CLXDAT:  Collision data reg. (read and clear)",
		"ADKCONR: Audio, disk ctrl reg. read",
		"POT0DAT: Pot counter pair 0 data (vert, horz)",
		"POT1DAT: Pot counter pair 1 data (vert, horz)",
		"POTINP:  Pot pin data read",
		"SERDATR: Serial port data and status read",
		"DSKBYTR: Disk data byte and status read",
		"INTENAR: Interrupt enable bits read",
		"INTREQR: Interrupt request bits read",
		"DSKPTH:  Disk pointer (high 3 bits)",
		"DSKPTL:  Disk pointer (low 15 bits)",
		"DSKLEN:  Disk length",
		"DSKDAT:  Disk DMA data write",
		"REFPTR:  Refresh pointer",
		"VPOSW:   Write vert most sig. bit (and frame flop)",
		"VHPOSW:  Write vert and horz pos. of beam",
		"COPCON:  Coprocessor ctrl reg. (CDANG)",
		"SERDAT:  Serial port data and stop bits write",
		"SERPER:  Serial port period and ctrl",
		"POTGO:   Pot count start, pot pin drive enable and data",
		"JOYTEST: Write to all 4 joystick/mouse counters at once",
		"STREQU:  Strobe for horz sync with VB and EQU",
		"STRVBL:  Strobe for horz sync with VB (vertical blank)",
		"STRHOR:  Strobe for horz sync",
		"STRLONG: Strobe for identification of long horz line",
		"BLTCON0: Blitter ctrl reg. 0",
		"BLTCON1: Blitter ctrl reg. 1",
		"BLTAFWM: Blitter first word mask for source A",
		"BLTALWM: Blitter last word mask for source A",		
		"BLPCPTH: Blitter pointer to source C (high 3 bits)",
		"BLTCPTL: Blitter pointer to source C (low 15 bits)",
		"BLTBPTH: Blitter pointer to source B (high 3 bits)",
		"BLTBPTL: Blitter pointer to source B (low 15 bits)",
		"BLTAPTH: Blitter pointer to source A (high 3 bits)",
		"BLTAPTL: Blitter pointer to source A (low 15 bits)",
		"BLTDPTH: Blitter pointer to source D (hi 3 bits)",
		"BLTDPTL: Blitter pointer to source D (low 15 bits)",
		"BLTSIZE: Blitter start and size (window width, height",
		nv,	
		nv,	
		nv,
		"BLTCMOD: Blitter modulo for source C",
		"BLTBMOD: Blitter modulo for source B",
		"BLTAMOD: Blitter modulo for source A",
		"BLTDMOD: Blitter modulo for source D",
		nv,	
		nv,	
		nv,	
		nv,
		"BLTCDAT: Blitter source C data reg.",
		"BLTBDAT: Blitter source B data reg.",
		"BLTADAT: Blitter source A data reg.",
		nv,
		nv,
		nv,	
		nv,	
		"DSKSYNC: Disk sync pattern reg. for disk read",
		"COP1LCH: Coprocessor first location reg. (high 3 bits)",
		"COP1LCL: Coprocessor first location reg. (low 15 bits)",
		"COP2LCH: Coprocessor second location reg. (high 3 bits)",
		"COP2LCL: Coprocessor second location reg. (low 15 bits)",		
		"COPJMP1: Coprocessor restart at first location",
		"COPJMP2: Coprocessor restart at second location",
		"COPINS:  Coprocessor instruction fetch identify",
		"DIWSTRT: Display window start (upper left vert-horz pos)",
		"DIWSTOP: Display window stop (lower right vert-horz pos)",
		"DDFSTRT: Display bit plane data fetch start (horz pos)",
		"DDFSTOP: Display bit plane data fetch stop (horz pos)",
		"DMACON:  DMA ctrl write (clear or set)",
		"CLXCON:  Collision ctrl",
		"INTENA:  Interrupt enable bits (clear or set)",
		"INTREQ:  Interrupt request bits (clear or set)",
		"ADKCON:  Audio, disk, UART ctrl",
		"AUD0LCH: Audio channel 0 location (high 3 bits)",
		"AUD0LCL: Audio channel 0 location (low 15 bits)",
		"AUD0LEN: Audio channel 0 length",
		"AUD0PER: Audio channel 0 period",	
		"AUD0VOL: Audio channel 0 volume",
		"AUD0DAT: Audio channel 0 data",
		nv,	
		nv,
		"AUD1LCH: Audio channel 1 location (high 3 bits)",
		"AUD1LCL: Audio channel 1 location (low 15 bits)",
		"AUD1LEN: Audio channel 1 length",
		"AUD1PER: Audio channel 1 period",	
		"AUD1VOL: Audio channel 1 volume",
		"AUD1DAT: Audio channel 1 data",
		nv,	
		nv,
		"AUD2LCH: Audio channel 2 location (high 3 bits)",
		"AUD2LCL: Audio channel 2 location (low 15 bits)",
		"AUD2LEN: Audio channel 2 length",
		"AUD2PER: Audio channel 2 period",	
		"AUD2VOL: Audio channel 2 volume",
		"AUD2DAT: Audio channel 2 data",
		nv,	
		nv,
		"AUD3LCH: Audio channel 3 location (high 3 bits)",
		"AUD3LCL: Audio channel 3 location (low 15 bits)",
		"AUD3LEN: Audio channel 3 length",
		"AUD3PER: Audio channel 3 period",	
		"AUD3VOL: Audio channel 3 volume",
		"AUD3DAT: Audio channel 3 data",
		nv,	
		nv,
		"BPL1PTH: Bit plane 1 pointer (high 3 bits)",
		"BPL1PTL: Bit plane 1 pointer (low 15 bits)",
		"BPL2PTH: Bit plane 2 pointer (high 3 bits)",
		"BPL2PTL: Bit plane 2 pointer (low 15 bits)",
		"BPL3PTH: Bit plane 3 pointer (high 3 bits)",
		"BPL3PTL: Bit plane 3 pointer (low 15 bits)",
		"BPL4PTH: Bit plane 4 pointer (high 3 bits)",
		"BPL4PTL: Bit plane 4 pointer (low 15 bits)",
		"BPL5PTH: Bit plane 5 pointer (high 3 bits)",
		"BPL5PLT: Bit plane 5 pointer (low 15 bits)",
		"BPL6PTH: Bit plane 6 pointer (high 3 bits)",
		"BPL6PTL: Bit plane 6 pointer (low 15 bits)",
		nv,	
		nv,	
		nv,	
		nv,
		"BPLCON0: Bit plane ctrl reg. (misc ctrl bits)",
		"BPLCON1: Bit plane ctrl reg. (scroll value PF1, PF2)",
		"BPLCON2: Bit plane ctrl reg. (priority ctrl)",
		nv,
		"BPL1MOD: Bit plane modulo (odd planes)",
		"BPL2MOD: Bit plane modulo (even planes)",
		nv,	
		nv,
		"BPL1DAT: Bit plane 1 data (parallel to serial convert)",
		"BPL2DAT: Bit plane 2 data (parallel to serial convert)",
		"BPL3DAT: Bit plane 3 data (parallel to serial convert)",
		"BPL4DAT: Bit plane 4 data (parallel to serial convert)",
		"BLP5DAT: Bit plane 5 data (parallel to serial convert)",
		"BPL6DAT: Bit plane 6 data (parallel to serial convert)",
		nv,	
		nv,
		"SPR0PTH: Sprite 0 pointer (high 3 bits)",
		"SPR0PTL: Sprite 0 pointer (low 15 bits)",
		"SPR1PTH: Sprite 1 pointer (high 3 bits)",
		"SPR1PTL: Sprite 1 pointer (low 15 bits)",
		"SPR2PTH: Sprite 2 pointer (high 3 bits)",
		"SPR2PTL: Sprite 2 pointer (low 15 bits)",
		"SPR3PTH: Sprite 3 pointer (high 3 bits)",
		"SPR3PTL: Sprite 3 pointer (low 15 bits)",
		"SPR4PTH: Sprite 4 pointer (high 3 bits)",
		"SPR4PTL: Sprite 4 pointer (low 15 bits)",
		"SPR5PTH: Sprite 5 pointer (high 3 bits)",
		"SPR5PTL: Sprite 5 pointer (low 15 bits)",
		"SPR6PTH: Sprite 6 pointer (high 3 bits)",
		"SPR6PTL: Sprite 6 pointer (low 15 bits)",
		"SPR7PTH: Sprite 7 pointer (high 3 bits)",
		"SPR7PTL: Sprite 7 pointer (low 15 bits)",
		"SPR0POS: Sprite 0 vert-horz start pos. data",
		"SPR0CTL: Sprite 0 vert stop pos. and ctrl data",
		"SPR0DATA:Sprite 0 image data reg. A",
		"SPR0DATB:Sprite 0 image data reg. B",		
		"SPR1POS: Sprite 1 vert-horz start pos. data",
		"SPR1CTL: Sprite 1 vert stop pos. and ctrl data",
		"SPR1DATA:Sprite 1 image data reg. A",
		"SPR1DATB:Sprite 1 image data reg. B",		
		"SPR2POS: Sprite 2 vert-horz start pos. data",
		"SPR2CTL: Sprite 2 vert stop pos. and ctrl data",
		"SPR2DATA:Sprite 2 image data reg. A",
		"SPR2DATB:Sprite 2 image data reg. B",		
		"SPR3POS: Sprite 3 vert-horz start pos. data",
		"SPR3CTL: Sprite 3 vert stop pos. and ctrl data",
		"SPR3DATA:Sprite 3 image data reg. A",
		"SPR3DATB:Sprite 3 image data reg. B",		
		"SPR4POS: Sprite 4 vert-horz start pos. data",
		"SPR4CTL: Sprite 4 vert stop pos. and ctrl data",
		"SPR4DATA:Sprite 4 image data reg. A",
		"SPR4DATB:Sprite 4 image data reg. B",		
		"SPR5POS: Sprite 5 vert-horz start pos. data",
		"SPR5CTL: Sprite 5 vert stop pos. and ctrl data",
		"SPR5DATA:Sprite 5 image data reg. A",
		"SPR5DATB:Sprite 5 image data reg. B",		
		"SPR6POS: Sprite 6 vert-horz start pos. data",
		"SPR6CTL: Sprite 6 vert stop pos. and ctrl data",
		"SPR6DATA:Sprite 6 image data reg. A",
		"SPR6DATB:Sprite 6 image data reg. B",		
		"SPR7POS: Sprite 7 vert-horz start pos.",
		"SPR7CTL: Sprite 7 vert stop pos. and ctrl data",
		"SPR7DATA:Sprite 7 image data reg. A",
		"SPR7DATB:Sprite 7 image data reg. B",		
		"COLOR00: Color table 00",
		"COLOR01: Color table 01",
		"COLOR02: Color table 02",
		"COLOR03: Color table 03",
		"COLOR04: Color table 04",
		"COLOR05: Color table 05",
		"COLOR06: Color table 06",
		"COLOR07: Color table 07",
		"COLOR08: Color table 08",
		"COLOR09: Color table 09",
		"COLOR10: Color table 10",
		"COLOR11: Color table 11",
		"COLOR12: Color table 12",
		"COLOR13: Color table 13",
		"COLOR14: Color table 14",
		"COLOR15: Color table 15",
		"COLOR16: Color table 16",
		"COLOR17: Color table 17",
		"COLOR18: Color table 18",
		"COLOR19: Color table 19",
		"COLOR20: Color table 20", 
		"COLOR21: Color table 21",
		"COLOR22: Color table 22",
		"COLOR23: Color table 23",
		"COLOR24: Color table 24",
		"COLOR25: Color table 25",
		"COLOR26: Color table 26",
		"COLOR27: Color table 27",
		"COLOR28: Color table 28",
		"COLOR29: Color table 29",
		"COLOR30: Color table 30",
		"COLOR31: Color tabel 31"
	       };		

/***********************************************************************/

VOID
Disassemble(clist)
struct cprlist *clist;
{
     register int i = clist->MaxCount;
     register WORD *c_data = (WORD *) clist->start, cmd, vp, hp, ve, he;

     while (i--) {
     	if (((cmd = *c_data++) & 0x01) == 0) { /* move command */
     		cmd &= 0x01fe;
		fprintf(dest,"MOVE $%04x to $%03x (%s)\n", *c_data++, cmd, regs[cmd/2]); 
	}	
        else { /* either a skip or a wait */
		vp = (cmd & 0xff00) >> 8;
		hp = (cmd & 0x00fe) >> 1;
		ve = (*c_data & 0x7f00) >> 8;
		he = (*c_data & 0x00fe) >> 1;

		if (*c_data & 0x01) /* wait or skip */
			fprintf(dest,"SKIP");
		else
			fprintf(dest,"WAIT");

		if (ve)
			fprintf(dest," vp = %d ($%x)", vp, ve);

		if (he)
			fprintf(dest," hp = %d ($%x)", hp, he);

		if ((*c_data++ & 0x8000) == 0)
			fprintf(dest," blitter done");
		fprintf(dest,"\n");
	}	
     }
}

/****************************************************************************/

VOID
Open_The_Screen()
{
     struct NewScreen NS;
     int i;
     
     IntuitionBase = (struct IntuitionBase *)   
                   OpenLibrary("intuition.library", INTUITION_REV);
     if(!IntuitionBase)
          exit(0);

     NS.LeftEdge       =   0;
     NS.TopEdge        =   100;
     NS.Width          =   640;
     NS.Height         =   400;
     NS.Depth	       =   1;	
     NS.DetailPen      =   0;
     NS.BlockPen       =   1;
     NS.ViewModes      = HIRES | LACE;	
     NS.Type	       = CUSTOMSCREEN;
     NS.Font	       = NULL;
     NS.DefaultTitle   = (UBYTE *) "Copyright 1986 by The 4th Works, Inc.";
     NS.Gadgets	       = NULL;
     NS.CustomBitMap   = NULL;
     
     if((Screen = (struct Screen *) OpenScreen(&NS)) == NULL)
          exit(0);
}

/****************************************************************************/

VOID
Close_The_Screen()
{
    CloseScreen(Screen);
    CloseLibrary(IntuitionBase);
}

/****************************************************************************/
        
int
main()
{
     int i;

     puts(copyright);
     
     GfxBase = (struct GfxBase *)
		   OpenLibrary("graphics.library", INTUITION_REV);
     if(!GfxBase)
	return(FALSE);
 
#if MYSCREEN
 
 	        	/*-----------------------------*/
 
     Open_The_Screen(); /* Comment this out if you want to disassemble */
     			/* the Copper List for a Workbench screen      */

 	        	/*-----------------------------*/

#endif


     dest = fopen("copper.listing", "w");

     fprintf(dest, copyright);	

     CopList = GfxBase->ActiView->LOFCprList;	
     fprintf(dest,"\nCopper dissassembly\nStart Addr = $%lx Size = $%x\n\n", CopList->start, CopList->MaxCount);          
 
     Disassemble(CopList);
     
     CopList = GfxBase->ActiView->SHFCprList;
     
     if (CopList) {
	fprintf(dest,"\n\n *** SECOND COPPER LIST ***\n");
	fprintf(dest,"Start Addr = $%lx Size = $%x\n\n", CopList->start, CopList->MaxCount);
	Disassemble(CopList);
     }
     else
	fprintf(dest,"\n\n *** No second Copper List ***\n\n");

     fprintf(dest,"\nEnd of Copper List\n");
	
#if MYSCREEN 
 
 	        	/*-----------------------------*/
 
     Close_The_Screen(); /* Comment this out if you want to disassemble */
     			/* the Copper List for a Workbench screen      */

 	        	/*-----------------------------*/
 	        	
#endif
	
    CloseLibrary(GfxBase);

    fprintf(dest, "\n\n");
	
    fclose(dest);
} 

