Add mode where font data is read from VGA BIOS data
[jpcrr.git] / org / jpc / plugins / RAWDumper.java
blob45521b7f49ff909d86d2ac971257b12953269f8a
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009-2010 H. Ilari Liusvaara
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as published by
10 the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 Based on JPC x86 PC Hardware emulator,
22 A project from the Physics Dept, The University of Oxford
24 Details about original JPC can be found at:
26 www-jpc.physics.ox.ac.uk
30 package org.jpc.plugins;
32 import java.io.*;
33 import java.util.*;
34 import java.util.zip.*;
35 import org.jpc.emulator.*;
36 import org.jpc.output.*;
37 import org.jpc.pluginsaux.HUDRenderer;
38 import org.jpc.pluginsbase.Plugins;
39 import org.jpc.pluginsbase.Plugin;
40 import static org.jpc.Misc.errorDialog;
41 import static org.jpc.Misc.parseStringToComponents;
43 public class RAWDumper implements Plugin
45 class DumpFrameFilter implements OutputStatic.FrameFilter
47 OutputFrameImage lastVideoFrame;
48 short videoChannel;
49 boolean gotFrame;
50 long lastTimestamp;
52 public DumpFrameFilter()
56 public OutputFrame doFilter(OutputFrame f, short channel)
58 gotFrame = true;
59 lastTimestamp = f.getTime();
60 if(!(f instanceof OutputFrameImage))
61 return f;
62 //This is video frame. Save and cancel it.
63 lastVideoFrame = (OutputFrameImage)f;
64 videoChannel = channel;
65 return null;
70 private volatile OutputClient videoOut;
71 private volatile OutputStatic connector;
72 private volatile boolean shuttingDown;
73 private volatile boolean shutDown;
74 private volatile boolean pcRunStatus;
75 private PC pc;
76 private Thread worker;
77 private OutputStream rawOutputStream;
78 private DumpFrameFilter filter;
79 private HUDRenderer renderer;
81 public RAWDumper(Plugins pluginManager, String args) throws IOException
83 Map<String, String> params = parseStringToComponents(args);
84 String rawOutput = params.get("rawoutput");
85 if(rawOutput == null)
86 throw new IOException("Raw output setting (rawoutput) required for PNGDumper");
87 if(rawOutput != null) {
88 try {
89 rawOutputStream = new FileOutputStream(rawOutput);
90 } catch(Exception e) {
91 System.err.println("Error: Failed to open raw output file.");
92 throw new IOException("Can't open dumpfile '" + rawOutput + "':" + e.getMessage());
95 shuttingDown = false;
96 shutDown = false;
97 pcRunStatus = false;
98 connector = pluginManager.getOutputConnector();
99 videoOut = new OutputClient(connector);
100 filter = new DumpFrameFilter();
101 renderer = new HUDRenderer();
105 public void eci_hud_left_gap(Integer flags, Integer gap)
107 if((flags.intValue() & 2) != 0)
108 renderer.setLeftGap(gap);
111 public void eci_hud_top_gap(Integer flags, Integer gap)
113 if((flags.intValue() & 2) != 0)
114 renderer.setTopGap(gap);
117 public void eci_hud_right_gap(Integer flags, Integer gap)
119 if((flags.intValue() & 2) != 0)
120 renderer.setRightGap(gap);
123 public void eci_hud_bottom_gap(Integer flags, Integer gap)
125 if((flags.intValue() & 2) != 0)
126 renderer.setBottomGap(gap);
129 public void eci_hud_white_solid_box(Integer flags, Integer x, Integer y, Integer w, Integer h)
131 if((flags.intValue() & 2) != 0)
132 renderer.whiteSolidBox(x.intValue(), y.intValue(), w.intValue(), h.intValue());
135 public void eci_hud_box(Integer flags, Integer x, Integer y, Integer w, Integer h, Integer thick, Integer lr,
136 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
138 if((flags.intValue() & 2) != 0)
139 renderer.box(x, y, w, h, thick, lr, lg, lb, la, fr, fg, fb, fa);
142 public void eci_hud_circle(Integer flags, Integer x, Integer y, Integer r, Integer thick, Integer lr,
143 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
145 if((flags.intValue() & 2) != 0)
146 renderer.circle(x, y, r, thick, lr, lg, lb, la, fr, fg, fb, fa);
149 public void eci_hud_bitmap(Integer flags, Integer x, Integer y, String bmap, Integer lr,
150 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
152 if((flags.intValue() & 2) != 0)
153 renderer.bitmap(x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa);
156 public void eci_hud_bitmap_binary(Integer flags, Integer x, Integer y, String bmap, Integer lr,
157 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
159 if((flags.intValue() & 2) != 0)
160 renderer.bitmapBinary(x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa);
163 public void eci_hud_vga_chargen(Integer flags, Integer x, Integer y, String text, Integer lr,
164 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
166 if((flags.intValue() & 2) != 0)
167 renderer.vgaChargen(x, y, text, lr, lg, lb, la, fr, fg, fb, fa, pc);
170 public void eci_hud_set_vga_chargen(Integer flags, Integer addr)
172 if((flags.intValue() & 2) != 0)
173 renderer.setVGAChargen(addr);
176 public boolean systemShutdown()
178 if(pcRunStatus) {
179 return false; //Don't shut down until after PC.
182 shuttingDown = true;
183 if(worker != null) {
184 synchronized(this) {
185 worker.interrupt();
186 while(!shutDown)
187 try {
188 wait();
189 } catch(Exception e) {
193 return true;
196 public void reconnect(PC _pc)
198 pcRunStatus = false;
199 pc = _pc;
202 public void pcStarting()
204 pcRunStatus = true;
207 public void pcStopping()
209 pcRunStatus = false;
212 public void main()
214 int frame = 0;
215 worker = Thread.currentThread();
216 boolean first = true;
217 while(!shuttingDown) {
218 if(shuttingDown)
219 break;
221 if(videoOut.aquire()) {
222 synchronized(this) {
223 try {
224 long base;
225 if(first)
226 rawOutputStream.write(connector.makeChannelTable());
227 first = false;
228 base = connector.writeFrames(rawOutputStream, filter);
229 OutputFrameImage lastFrame = filter.lastVideoFrame;
230 if(lastFrame == null) {
231 videoOut.releaseWaitAll();
232 continue;
234 int w = lastFrame.getWidth();
235 int h = lastFrame.getHeight();
236 renderer.setBackground(lastFrame.getImageData(), w, h);
237 videoOut.releaseWaitAll();
238 w = renderer.getRenderWidth();
239 h = renderer.getRenderHeight();
240 int[] saveBuffer = renderer.getFinishedAndReset();
241 frame++;
242 long time = filter.lastTimestamp;
243 if(base > time)
244 time = base;
245 lastFrame = new OutputFrameImage(time, (short)w, (short)h, saveBuffer);
246 rawOutputStream.write(lastFrame.dump(filter.videoChannel, base));
247 System.err.println("Informational: Saved frame #" + frame + ": " + w + "x" + h + " <" +
248 time + ">.");
249 } catch(IOException e) {
250 System.err.println("Warning: Failed to save screenshot image!");
251 errorDialog(e, "Failed to save screenshot", null, "Dismiss");
258 try {
259 if(filter.gotFrame)
260 connector.writeFrames(rawOutputStream, null);
261 } catch(IOException e) {
262 System.err.println("Warning: Failed to close video output stream!");
263 errorDialog(e, "Failed to close video output", null, "Dismiss");
266 if(videoOut != null)
267 videoOut.detach();
269 if(rawOutputStream != null) {
270 try {
271 rawOutputStream.flush();
272 rawOutputStream.close();
273 } catch(IOException e) {
274 System.err.println("Warning: Failed to close video output stream!");
275 errorDialog(e, "Failed to close video output", null, "Dismiss");
279 synchronized(this) {
280 shutDown = true;
281 notifyAll();