/Users/petercappello/NetBeansProjects/56-2014/56-2014-5-Gala/src/GVM.java |
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Arrays;
Graphics Virtual Machine
@author
public class GVM
{
private final static int DATA_MEMORY_SIZE = 100;
private final static int OPCODE = 0;
private final static int OPERAND = 1;
public final static int STOP = 0;
public final static int SET = 1;
public final static int LOAD = 2;
public final static int STORE = 3;
public final static int ADD = 4;
public final static int ZERO = 5;
public final static int GOTO = 6;
public final static int SETCOLOR = 7;
public final static int DRAWLINE = 8;
public final static int DRAWRECT = 9;
public final static int FILLRECT = 10;
public final static int DRAWOVAL = 11;
public final static int FILLOVAL = 12;
public final static int ACC = 0;
public final static int X = 1;
public final static int Y = 2;
public final static int WIDTH = 3;
public final static int HEIGHT = 4;
public final static int RED = 5;
public final static int GREEN = 6;
public final static int BLUE = 7;
final static int IMAGE_SIZE = 800;
private final Image image;
private final Graphics graphics;
private final int[] dataMemory = new int[ DATA_MEMORY_SIZE ];
private int[][] programMemory;
private int instructionAddress;
private Color color;
GVM()
{
image = new BufferedImage( IMAGE_SIZE, IMAGE_SIZE, BufferedImage.TYPE_INT_RGB );
graphics = image.getGraphics();
graphics.setColor( Color.white );
graphics.fillRect( 0, 0, IMAGE_SIZE, IMAGE_SIZE );
color = Color.black;
graphics.setColor( color );
}
public Image getImage() { return image; }
int[][] getProgramMemory() { return programMemory; }
void load( int[][] programMemory )
{
this.programMemory = programMemory;
Arrays.fill( dataMemory, 0 );
instructionAddress = 0;
}
void step()
{
if ( programMemory[ instructionAddress ][ OPCODE] != STOP )
{
executeInstruction( programMemory[ instructionAddress ] );
}
else
{
instructionAddress = 0;
System.out.print(" STOP. " );
}
}
void run()
{
while ( programMemory[ instructionAddress ][ OPCODE] != STOP )
{
executeInstruction( programMemory[ instructionAddress ] );
}
instructionAddress = 0;
System.out.println(" Program has executed a STOP instruction. " );
}
private void executeInstruction( int[] instruction )
{
System.out.println( "instruction address: " + instructionAddress
+ " OPCODE: " + instruction[ OPCODE ]
+ " "
+ instructionToString( instruction ) );
int nextInstructionAddress = instructionAddress + 1;
switch ( instruction[ OPCODE ] )
{
case SET:
dataMemory[ ACC ] = instruction[ OPERAND ];
break;
case LOAD:
dataMemory[ ACC ] = dataMemory[ instruction[ OPERAND ] ];
break;
case STORE:
dataMemory[ instruction[ OPERAND ] ] = dataMemory[ ACC ];
break;
case ADD:
dataMemory[ ACC ] += dataMemory[ instruction[ OPERAND ] ];
break;
case ZERO:
if ( dataMemory[ ACC ] != 0 )
{
nextInstructionAddress = instruction[ OPERAND ];
}
break;
case GOTO:
nextInstructionAddress = instruction[ OPERAND ];
break;
case SETCOLOR:
color = new Color( dataMemory[ RED ], dataMemory[ GREEN ], dataMemory[ BLUE ] );
graphics.setColor( color );
break;
case DRAWLINE:
graphics.drawLine( dataMemory[ X ], dataMemory[ Y ], dataMemory[ X ] + dataMemory[ WIDTH ], dataMemory[ Y ] + dataMemory[ HEIGHT ] );
break;
case DRAWRECT:
graphics.drawRect( dataMemory[ X ], dataMemory[ Y ], dataMemory[ WIDTH ], dataMemory[ HEIGHT ] );
break;
case FILLRECT:
graphics.fillRect( dataMemory[ X ], dataMemory[ Y ], dataMemory[ WIDTH ], dataMemory[ HEIGHT ] );
break;
case DRAWOVAL:
graphics.drawOval( dataMemory[ X ], dataMemory[ Y ], dataMemory[ WIDTH ], dataMemory[ HEIGHT ] );
break;
case FILLOVAL:
graphics.fillOval( dataMemory[ X ], dataMemory[ Y ], dataMemory[ WIDTH ], dataMemory[ HEIGHT ] );
break;
default :
assert false : "Invalid operation code: " + instruction[ OPCODE ];
}
instructionAddress = nextInstructionAddress;
}
private String instructionToString( int[] instruction )
{
StringBuilder string = new StringBuilder();
string.append( opcodeMnemonics[ instruction[ OPCODE ] ] ).append( ' ');
switch ( instruction[ OPCODE ] )
{
case SET: case GOTO:
string.append( instruction[ OPERAND ] );
break;
case LOAD:
string.append(instruction[ OPERAND ]).append(" memory cell value: ").append( dataMemory[ instruction[ OPERAND ] ]);
break;
case STORE:
string.append(dataMemory[ ACC ]).append(" in memory cell ").append(instruction[ OPERAND ]).append(" cell: ").append( dataMemory[ ACC ]);
break;
case ADD:
string.append("datamemory[ ").append(instruction[ OPERAND ]).append(" ] of value: ").append( instruction[ OPERAND ] ).append(" to ACC: ").append( dataMemory[ ACC ]);
break;
case ZERO:
string.append("ACC: [ ").append( dataMemory[ ACC ]).append( " ] ");
if ( dataMemory[ ACC ] != 0 )
{
string.append(" branching to ").append( instruction[ OPERAND ]);
}
break;
case SETCOLOR:
string.append( color );
break;
case DRAWLINE: case DRAWRECT: case FILLRECT: case DRAWOVAL: case FILLOVAL:
string.append(" X: ").append(dataMemory[ X ]).append(" Y: ").append(dataMemory[ Y ]).append(" W: ").append(dataMemory[ WIDTH ]).append(" H: ").append(dataMemory[ HEIGHT ]);
break;
default :
assert false : "Invalid operation code: " + instruction[ OPCODE ];
}
return string.toString();
}
private final String[] opcodeMnemonics =
{
"stop",
"set",
"load",
"store",
"add",
"zero",
"goto",
"setcColor",
"drawLine",
"drawRect",
"fillRect",
"drawOval",
"fillOval"
};
}