/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.video.vgahw;
import java.awt.image.IndexColorModel;
import org.jnode.system.resource.MemoryResource;
import org.jnode.util.NumberUtils;
/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class VgaState {
// private static final Logger log = Logger.getLogger(VgaState.class);
private final int[] seq;
private final int[] crt;
private final int[] gra;
private final int[] att;
private int misc;
private IndexColorModel palette;
private byte[] fonts;
private static final int FONT_STATE_SIZE = 0x9600;
protected static final int DEF_SEQ_LENGTH = 5;
protected static final int DEF_CRT_LENGTH = 25;
protected static final int DEF_GRA_LENGTH = 9;
protected static final int DEF_ATT_LENGTH = 21;
protected static final int DEF_MISC = 0xE3;
/**
* Create a new instance
*/
public VgaState() {
this((IndexColorModel) null);
}
/**
* Create a new instance
*/
public VgaState(IndexColorModel cm) {
this(DEF_SEQ_LENGTH, DEF_CRT_LENGTH, DEF_GRA_LENGTH, DEF_ATT_LENGTH, DEF_MISC, cm);
}
/**
* Create a new instance
*/
public VgaState(int numSeq, int numCrt, int numGra, int numAtt, int misc, IndexColorModel cm) {
seq = new int[numSeq];
crt = new int[numCrt];
gra = new int[numGra];
att = new int[numAtt];
this.misc = misc;
this.palette = cm;
}
/**
* Create a new instance
*/
public VgaState(int[] seq, int[] crt, int[] gra, int[] att, int misc, IndexColorModel cm) {
this.seq = copy(seq);
this.crt = copy(crt);
this.gra = copy(gra);
this.att = copy(att);
this.misc = misc;
this.palette = cm;
}
/**
* Create a new instance
*/
public VgaState(VgaState src) {
seq = copy(src.seq);
crt = copy(src.crt);
gra = copy(src.gra);
att = copy(src.att);
this.misc = src.misc;
}
/** Get a seq register from this state */
public int getSEQ(int index) {
return seq[index];
}
/** Set a seq regsiter in this state */
public void setSEQ(int index, int value) {
seq[index] = value;
}
/** Get a crt register from this state */
public int getCRT(int index) {
return crt[index];
}
/** Set a crt regsiter in this state */
public void setCRT(int index, int value) {
crt[index] = value;
}
/** Get a gra register from this state */
public int getGRA(int index) {
return gra[index];
}
/** Set a gra regsiter in this state */
public void setGRA(int index, int value) {
gra[index] = value;
}
/** Get a att register from this state */
public int getATT(int index) {
return att[index];
}
/** Set a att regsiter in this state */
public void setATT(int index, int value) {
att[index] = value;
}
/** Get the misc register in this state */
public int getMISC() {
return misc;
}
/** Set the misc register in this state */
public void setMISC(int value) {
this.misc = value;
}
public boolean isColorMode() {
return ((misc & 1) == 1);
}
/**
* Save the state of the VGA-system to this object.
*
* @param io
*/
public void saveFromVGA(VgaIO io) {
savePalette(io);
saveFont(io);
saveCRT(io);
saveATT(io);
saveGRA(io);
saveSEQ(io);
misc = io.getMISC();
}
/**
* Restore this state to the VGA system
*
* @param io
*/
public void restoreToVGA(VgaIO io) {
if (isColorMode()) {
VgaUtils.setColorMode(io);
} else {
VgaUtils.setMonoMode(io);
}
restoreFont(io);
io.setMISC(misc);
restoreSEQ(io);
restoreCRT(io);
restoreGRA(io);
restoreATT(io);
io.getSTAT();
restorePalette(io);
}
private final void saveATT(VgaIO io) {
for (int i = 0; i < att.length; i++) {
att[i] = io.getATT(i);
}
}
protected void saveCRT(VgaIO io) {
for (int i = 0; i < crt.length; i++) {
crt[i] = io.getCRT(i);
}
}
private final void saveGRA(VgaIO io) {
for (int i = 0; i < gra.length; i++) {
gra[i] = io.getGRAF(i);
}
}
private final void saveSEQ(VgaIO io) {
for (int i = 0; i < seq.length; i++) {
seq[i] = io.getSEQ(i);
}
}
private final void restoreSEQ(VgaIO io) {
io.setSEQ(0, 1);
for (int i = 1; i < seq.length; i++) {
io.setSEQ(i, seq[i]);
}
io.setSEQ(0, 3);
}
protected void restoreCRT(VgaIO io) {
io.setCRT(0x11, (io.getCRT(0x11) & 0x7F));
for (int i = 0; i < crt.length; i++) {
io.setCRT(i, crt[i]);
}
}
private final void restoreGRA(VgaIO io) {
for (int i = 0; i < gra.length; i++) {
io.setGRAF(i, gra[i]);
}
}
private final void restoreATT(VgaIO io) {
for (int i = 0; i < att.length; i++) {
io.setATT(i, att[i]);
}
}
private static final int[] copy(int[] src) {
final int dst[] = new int[src.length];
System.arraycopy(src, 0, dst, 0, src.length);
return dst;
}
protected void savePalette(VgaIO io) {
// log.debug("savePalette", new Exception("Trace"));
final int size = getPaletteSize(io);
final byte[] r = new byte[size];
final byte[] g = new byte[size];
final byte[] b = new byte[size];
for (int i = size - 1; i >= 0; i--) {
getPaletteEntry(io, i, r, g, b);
}
// log.debug("Save-Size:" + size + ", R=" + NumberUtils.hex(r));
palette = new IndexColorModel(8/* 32 *//* 6 */, size, r, g, b);
}
/**
* Gets the length of the palette.
*
* @param io
* @return the palette size
*/
protected int getPaletteSize(VgaIO io) {
return 256;
}
protected void restorePalette(VgaIO io) {
if (palette != null) {
// log.debug("restorePalette", new Exception("Trace"));
final int size = Math.min(256, palette.getMapSize());
// log.debug("size=" + size + ", pal.mapsize=" +
// palette.getMapSize());
final byte[] r = new byte[size];
final byte[] g = new byte[size];
final byte[] b = new byte[size];
palette.getReds(r);
palette.getGreens(g);
palette.getBlues(b);
// log.debug("Restore-Size:" + size + ", R=" + NumberUtils.hex(r));
for (int i = size - 1; i >= 0; i--) {
setPaletteEntry(io, i, r[i] & 0xff, g[i] & 0xff, b[i] & 0xff);
}
}
}
protected void setPaletteEntry(VgaIO io, int colorIndex, int r, int g, int b) {
io.setDACWriteIndex(colorIndex);
io.setDACData(r);
io.setDACData(g);
io.setDACData(b);
}
protected void getPaletteEntry(VgaIO io, int colorIndex, byte[] r, byte[] g, byte[] b) {
io.setDACReadIndex(colorIndex);
r[colorIndex] = (byte) io.getDACData();
g[colorIndex] = (byte) io.getDACData();
b[colorIndex] = (byte) io.getDACData();
}
/* save the fonts */
protected void saveFont(VgaIO io) {
if (fonts == null) {
fonts = new byte[FONT_STATE_SIZE * 4];
}
final MemoryResource vgaMem = io.getVideoMem();
int ofs = 0;
final int oldSeq2 = io.getSEQ(2);
final int oldSeq4 = io.getSEQ(4);
final int oldGra4 = io.getGRAF(4);
final int oldGra5 = io.getGRAF(5);
final int oldGra6 = io.getGRAF(6);
io.setSEQ(4, 0x06);
io.setGRAF(5, 0);
io.setGRAF(6, 0x05);
io.setSEQ(2, 1);
io.setGRAF(4, 0);
vgaMem.getBytes(0, fonts, ofs, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 2);
io.setGRAF(4, 1);
vgaMem.getBytes(0, fonts, ofs, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 4);
io.setGRAF(4, 2);
vgaMem.getBytes(0, fonts, ofs, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 8);
io.setGRAF(4, 3);
vgaMem.getBytes(0, fonts, ofs, FONT_STATE_SIZE);
// restore
io.setSEQ(2, oldSeq2);
io.setSEQ(4, oldSeq4);
io.setGRAF(4, oldGra4);
io.setGRAF(5, oldGra5);
io.setGRAF(6, oldGra6);
}
private void restoreFont(VgaIO io) {
if (fonts != null) {
final MemoryResource vgaMem = io.getVideoMem();
int ofs = 0;
final int oldSeq2 = io.getSEQ(0x02);
final int oldSeq4 = io.getSEQ(0x04);
final int oldGra1 = io.getGRAF(0x01);
final int oldGra3 = io.getGRAF(0x03);
final int oldGra5 = io.getGRAF(0x05);
final int oldGra8 = io.getGRAF(0x08);
io.setSEQ(4, 0x06);
io.setGRAF(1, 0);
io.setGRAF(3, 0);
io.setGRAF(5, 0);
io.setGRAF(8, 0xFF);
io.setSEQ(2, 1);
io.setGRAF(4, 0);
vgaMem.setBytes(fonts, ofs, 0, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 2);
io.setGRAF(4, 1);
vgaMem.setBytes(fonts, ofs, 0, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 4);
io.setGRAF(4, 2);
vgaMem.setBytes(fonts, ofs, 0, FONT_STATE_SIZE);
ofs += FONT_STATE_SIZE;
io.setSEQ(2, 8);
io.setGRAF(4, 3);
vgaMem.setBytes(fonts, ofs, 0, FONT_STATE_SIZE);
// restore
io.setSEQ(2, oldSeq2);
io.setSEQ(4, oldSeq4);
io.setGRAF(1, oldGra1);
io.setGRAF(3, oldGra3);
io.setGRAF(5, oldGra5);
io.setGRAF(8, oldGra8);
}
}
public String toString() {
return "VGA[SEQ:" + NumberUtils.hex(seq, 2) + ", CRT:" + NumberUtils.hex(crt, 2) +
", GRA:" + NumberUtils.hex(gra, 2) + ", ATT:" + NumberUtils.hex(att, 2) +
", MISC:" + NumberUtils.hex(misc, 2);
}
}