Fix most warnings from GCJ
[jpcrr.git] / org / jpc / plugins / RAWVideoDumper.java
blob37713708bbbd5ff567e508500564c32e98b085d9
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009 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.pluginsaux.HUDRenderer;
37 import org.jpc.pluginsbase.Plugins;
38 import org.jpc.pluginsbase.Plugin;
39 import static org.jpc.Misc.errorDialog;
40 import static org.jpc.Misc.parseStringToComponents;
42 public class RAWVideoDumper implements Plugin
44 private volatile VGADigitalOut videoOut;
45 private volatile Clock clock;
46 private volatile boolean signalCheck;
47 private volatile boolean shuttingDown;
48 private volatile boolean shutDown;
49 private Thread worker;
50 private volatile boolean pcRunStatus;
51 private volatile long internalTime;
52 private volatile long lastSaveTime;
53 private volatile long lastInternalTimeUpdate;
54 private OutputStream rawOutputStream;
55 private HUDRenderer renderer;
57 public RAWVideoDumper(Plugins pluginManager, String args) throws IOException
59 Map<String, String> params = parseStringToComponents(args);
60 String rawOutput = params.get("rawoutput");
61 if(rawOutput == null)
62 throw new IOException("Raw output setting (rawoutput) required for PNGDumper");
63 if(rawOutput != null) {
64 try {
65 rawOutputStream = new DeflaterOutputStream(new FileOutputStream(rawOutput));
66 } catch(Exception e) {
67 System.err.println("Error: Failed to open raw output file.");
70 shuttingDown = false;
71 shutDown = false;
72 pcRunStatus = false;
73 internalTime = 0;
74 lastInternalTimeUpdate = 0;
75 lastSaveTime = 0;
76 renderer = new HUDRenderer();
80 public void eci_hud_left_gap(Integer flags, Integer gap)
82 if((flags.intValue() & 2) != 0)
83 renderer.setLeftGap(gap);
86 public void eci_hud_top_gap(Integer flags, Integer gap)
88 if((flags.intValue() & 2) != 0)
89 renderer.setTopGap(gap);
92 public void eci_hud_right_gap(Integer flags, Integer gap)
94 if((flags.intValue() & 2) != 0)
95 renderer.setRightGap(gap);
98 public void eci_hud_bottom_gap(Integer flags, Integer gap)
100 if((flags.intValue() & 2) != 0)
101 renderer.setBottomGap(gap);
104 public void eci_hud_white_solid_box(Integer flags, Integer x, Integer y, Integer w, Integer h)
106 if((flags.intValue() & 2) != 0)
107 renderer.whiteSolidBox(x.intValue(), y.intValue(), w.intValue(), h.intValue());
110 public void eci_hud_box(Integer flags, Integer x, Integer y, Integer w, Integer h, Integer thick, Integer lr,
111 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
113 if((flags.intValue() & 2) != 0)
114 renderer.box(x, y, w, h, thick, lr, lg, lb, la, fr, fg, fb, fa);
117 public void eci_hud_circle(Integer flags, Integer x, Integer y, Integer r, Integer thick, Integer lr,
118 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
120 if((flags.intValue() & 2) != 0)
121 renderer.circle(x, y, r, thick, lr, lg, lb, la, fr, fg, fb, fa);
124 public void eci_hud_bitmap(Integer flags, Integer x, Integer y, String bmap, Integer lr,
125 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
127 if((flags.intValue() & 2) != 0)
128 renderer.bitmap(x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa);
131 public void eci_hud_bitmap_binary(Integer flags, Integer x, Integer y, String bmap, Integer lr,
132 Integer lg, Integer lb, Integer la, Integer fr, Integer fg, Integer fb, Integer fa)
134 if((flags.intValue() & 2) != 0)
135 renderer.bitmapBinary(x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa);
138 public boolean systemShutdown()
140 if(pcRunStatus)
141 return false; //Don't shut down until after PC.
143 shuttingDown = true;
144 if(worker != null) {
145 worker.interrupt();
146 synchronized(this) {
147 notifyAll();
148 while(!shutDown)
149 try {
150 wait();
151 } catch(Exception e) {
155 return true;
158 public void reconnect(PC pc)
160 VGADigitalOut previousOutput = videoOut;
162 //Bump it a little.
163 videoOut = null;
164 worker.interrupt();
165 while(!signalCheck)
168 if(previousOutput != null)
169 previousOutput.unsubscribeOutput(this);
171 synchronized(this) {
172 if(pc != null) {
173 videoOut = pc.getVideoOutput();
174 clock = (Clock)pc.getComponent(Clock.class);
175 } else {
176 videoOut = null;
177 clock = null;
180 if(videoOut != null)
181 videoOut.subscribeOutput(this);
183 notifyAll();
187 public void pcStarting()
189 pcRunStatus = true;
190 lastInternalTimeUpdate = clock.getTime();
193 public void pcStopping()
195 pcRunStatus = false;
196 long newUpdate = clock.getTime();
197 internalTime += (newUpdate - lastInternalTimeUpdate);
198 lastInternalTimeUpdate = newUpdate;
201 public void main()
203 int frame = 0;
204 long frameTime;
205 int[] saveBuffer = null;
206 worker = Thread.currentThread();
207 while(!shuttingDown) {
208 synchronized(this) {
209 while(videoOut == null && !shuttingDown)
210 try {
211 signalCheck = true;
212 wait();
213 signalCheck = false;
214 } catch(Exception e) {
216 if(shuttingDown)
217 break;
219 if(videoOut.waitOutput(this)) {
220 try {
221 int w = videoOut.getWidth();
222 int h = videoOut.getHeight();
223 renderer.setBackground(videoOut.getDisplayBuffer(), w, h);
224 videoOut.releaseOutputWaitAll(this);
225 w = renderer.getRenderWidth();
226 h = renderer.getRenderHeight();
227 saveBuffer = renderer.getFinishedAndReset();
228 if(saveBuffer == null || w == 0 || h == 0) {
229 continue; //Image not usable.
231 frame++;
232 frameTime = (clock.getTime() - lastInternalTimeUpdate) + internalTime;
234 long offset = frameTime - lastSaveTime;
235 int offsetWords = (int)(offset / 0xFFFFFFFFL + 1);
236 byte[] frameHeader = new byte[4 * offsetWords + 4];
237 frameHeader[4 * offsetWords + 0] = (byte)(w >>> 8);
238 frameHeader[4 * offsetWords + 1] = (byte)w;
239 frameHeader[4 * offsetWords + 2] = (byte)(h >>> 8);
240 frameHeader[4 * offsetWords + 3] = (byte)h;
241 for(int i = 0; i < 4 * offsetWords - 4; i++)
242 frameHeader[i] = (byte)-1;
243 offset = offset % 0xFFFFFFFFL;
244 frameHeader[4 * offsetWords - 4] = (byte)(offset >>> 24);
245 frameHeader[4 * offsetWords - 3] = (byte)(offset >>> 16);
246 frameHeader[4 * offsetWords - 2] = (byte)(offset >>> 8);
247 frameHeader[4 * offsetWords - 1] = (byte)offset;
248 rawOutputStream.write(frameHeader);
249 byte[] frameLine = new byte[4 * w];
250 for(int y = 0; y < h; y++) {
251 for(int x = 0; x < w; x++) {
252 int px = saveBuffer[y * w + x];
253 frameLine[4 * x + 0] = 0;
254 frameLine[4 * x + 1] = (byte)(px >>> 16);
255 frameLine[4 * x + 2] = (byte)(px >>> 8);
256 frameLine[4 * x + 3] = (byte)px;
258 rawOutputStream.write(frameLine);
260 System.err.println("Informational: Saved frame #" + frame + ": " + w + "x" + h + " <" +
261 frameTime + ">.");
262 lastSaveTime = frameTime;
263 } catch(IOException e) {
264 System.err.println("Warning: Failed to save screenshot image!");
265 errorDialog(e, "Failed to save screenshot", null, "Dismiss");
271 if(rawOutputStream != null) {
272 try {
273 rawOutputStream.flush();
274 rawOutputStream.close();
275 } catch(IOException e) {
276 System.err.println("Warning: Failed to close video output stream!");
277 errorDialog(e, "Failed to close video output", null, "Dismiss");
281 synchronized(this) {
282 shutDown = true;
283 notifyAll();