package com.jopdesign.tools;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class JopDisplay extends Frame implements Runnable, KeyListener, MouseListener, MouseMotionListener {
public static final int FRAME_WIDTH = 640;
public static final int WIDTH = 320;
public static final int FRAME_HEIGHT = 480;
public static final int HEIGHT = 240;
private static final int BASE_ADDRESS = 0x78500;
private int kb_ctrl_reg = 0x00;
private int kb_data_reg = 0x00;
private int kb_scancode_reg = 0x00;
private int mouse_flag_reg = 0x00;
private int mouse_x_inc_reg = 0x00;
private int mouse_y_inc_reg = 0x00;
private int last_x=0x00;
private int last_y=0x00;
public static final int IO_BASE = 0xffffff80;
public static final int KB_CTRL = IO_BASE + 0x30 + 0;
public static final int KB_DATA = IO_BASE + 0x30 + 1;
public static final int KB_SCANCODE = IO_BASE + 0x30 + 2;
private static final int MSK_PARITY_ERR = 0x01;
private static final int MSK_RCV_RDY = 0x02;
private static final int MSK_SND_RDY = 0x04;
private static final int MSK_CAPS_LOCK = 0x08;
private static final int MSK_SCC_RDY = 0x10;
private static final int MSK_KEY_REL = 0x20;
public static final int MOUSE_STATUS = IO_BASE+0x40+0;
public static final int MOUSE_FLAG = IO_BASE+0x40+1;
public static final int MOUSE_X_INC = IO_BASE+0x40+2;
public static final int MOUSE_Y_INC = IO_BASE+0x40+3;
public static final int MSK_DTA_RDY = 0x01;
public static final int MSK_BTN_LEFT = 0x02;
public static final int MSK_BTN_RIGHT = 0x04;
public static final int MSK_BTN_MIDDLE = 0x08;
public static final int MSK_X_OVFLOW = 0x10;
public static final int MSK_Y_OVFLOW = 0x20;
private IOSimMin io;
private FrameBuffer fb = FrameBuffer.CreateInstance();
private Thread t;
public JopDisplay()
{
super("JOP Simulation Display Output");
this.io = io;
fb.setFocusTraversalKeysEnabled(false); // we want tab keys!
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
t.interrupt();
fb.disable();
e.getWindow().setVisible(false);
JopSim.exit = true;
try {
Thread.currentThread().sleep(1000); // really dirty
} catch(Exception ex) {
}
e.getWindow().dispose();
}
});
fb.addKeyListener(this);
fb.addMouseListener(this);
fb.addMouseMotionListener(this);
this.setResizable(false);
this.setVisible(true);
Insets i = this.getInsets();
int width = FRAME_WIDTH + i.left + i.right;
int height = FRAME_HEIGHT + i.top + i.bottom;
this.setSize(width, height);
this.add(fb, BorderLayout.CENTER);
t = new Thread(this);
t.start();
}
public void keyPressed(KeyEvent e) {
kb_data_reg = e.getKeyChar();
kb_scancode_reg = e.getKeyCode();
kb_ctrl_reg |= MSK_RCV_RDY | MSK_SCC_RDY;
}
public void keyReleased(KeyEvent e) {
kb_ctrl_reg |= MSK_SCC_RDY | MSK_KEY_REL;
kb_scancode_reg = e.getKeyCode();
}
public void keyTyped(KeyEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
mouse_flag_reg |= MSK_DTA_RDY;
switch(e.getButton()){
case MouseEvent.BUTTON1:
mouse_flag_reg |= MSK_BTN_LEFT;
break;
case MouseEvent.BUTTON2:
mouse_flag_reg |= MSK_BTN_RIGHT;
break;
case MouseEvent.BUTTON3:
mouse_flag_reg |= MSK_BTN_MIDDLE;
break;
default:
}
}
public void mouseReleased(MouseEvent e) {
mouse_flag_reg |= MSK_DTA_RDY;
switch(e.getButton()){
case MouseEvent.BUTTON1:
mouse_flag_reg &= ~MSK_BTN_LEFT;
break;
case MouseEvent.BUTTON2:
mouse_flag_reg &= ~MSK_BTN_RIGHT;
break;
case MouseEvent.BUTTON3:
mouse_flag_reg &= ~MSK_BTN_MIDDLE;
break;
default:
}
}
public void mouseDragged(MouseEvent e) {
mouse_flag_reg |= MSK_DTA_RDY;
int tmp_x = e.getX();
int tmp_y = e.getY();
mouse_x_inc_reg += tmp_x - last_x;
mouse_y_inc_reg += tmp_y - last_y;
last_x = tmp_x;
last_y = tmp_y;
}
public void mouseMoved(MouseEvent e) {
mouse_flag_reg |= MSK_DTA_RDY;
int tmp_x = e.getX();
int tmp_y = e.getY();
mouse_x_inc_reg += tmp_x - last_x;
mouse_y_inc_reg += tmp_y - last_y;
last_x = tmp_x;
last_y = tmp_y;
}
public int read(int addr)
{
int tmp;
switch(addr) {
case KB_CTRL:
tmp = kb_ctrl_reg;
kb_ctrl_reg = 0x00;
return tmp;
case KB_DATA:
return kb_data_reg;
case KB_SCANCODE:
return kb_scancode_reg;
case MOUSE_STATUS:
return 0x00;
case MOUSE_FLAG:
tmp = mouse_flag_reg;
mouse_flag_reg &= ~MSK_DTA_RDY;
return tmp;
case MOUSE_X_INC:
tmp = mouse_x_inc_reg;
mouse_x_inc_reg = 0;
return tmp;
case MOUSE_Y_INC:
tmp = mouse_y_inc_reg;
mouse_y_inc_reg = 0;
return tmp;
default:
}
return 0x00;
}
public boolean write(int addr, int data)
{
if(addr < BASE_ADDRESS || addr >= (BASE_ADDRESS + WIDTH*HEIGHT/4) )
return false;
int tmp = ((data&0xff)<<24)+((data&0xff00)<<8)+((data&0xff0000)>>8)+((data>>24)&0xff);
data = tmp;
tmp = addr;
addr = (addr-BASE_ADDRESS)<<2;
addr = (FRAME_WIDTH-WIDTH)/2 + (addr%WIDTH) + FRAME_WIDTH * ((FRAME_HEIGHT-HEIGHT)/2 + (addr/WIDTH));
fb.setPixelWord(addr>>2, data);
if(tmp == ((BASE_ADDRESS + WIDTH*HEIGHT/4) - 1)) { // redraw when last 4 pixels are written
fb.Draw();
}
return true;
}
public void run()
{
try {
while((!Thread.currentThread().isInterrupted()))
{
//fb.Draw();
Thread.sleep(1000);
}
} catch(Exception e) {
}
}
}