2 JPC-RR: A x86 PC Hardware Emulator
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
29 package org
.jpc
.pluginsaux
;
32 import static org
.jpc
.pluginsaux
.VGAFont
.vgaFontData
;
34 public class HUDRenderer
36 int[] backgroundBuffer
;
37 int elementsAllocated
;
41 volatile int lightAmp
;
44 volatile int gapBottom
;
45 volatile int gapRight
;
46 List
<RenderObject
> renderObjects
;
48 private abstract class RenderObject
50 abstract void render(int[] buffer
, int w
, int h
);
53 public HUDRenderer(int _flags
)
55 renderObjects
= new LinkedList
<RenderObject
>();
60 public synchronized void setBackground(int[] bg
, int w
, int h
)
62 if(elementsAllocated
< w
* h
) {
63 backgroundBuffer
= new int[w
* h
];
64 elementsAllocated
= w
* h
;
67 System
.arraycopy(bg
, 0, backgroundBuffer
, 0, w
* h
);
72 public synchronized int getRenderWidth()
74 return gapLeft
+ backgroundWidth
+ gapRight
;
77 public synchronized int getRenderHeight()
79 return gapTop
+ backgroundHeight
+ gapBottom
;
82 public synchronized void REMOTE_left_gap(int _flags
, int gap
)
84 if(((_flags
& flags
)) != flags
)
92 public synchronized void REMOTE_top_gap(int _flags
, int gap
)
94 if(((_flags
& flags
)) != flags
)
102 public synchronized void REMOTE_right_gap(int _flags
, int gap
)
104 if(((_flags
& flags
)) != flags
)
112 public synchronized void REMOTE_bottom_gap(int _flags
, int gap
)
114 if(((_flags
& flags
)) != flags
)
122 public synchronized void setLightAmplification(int factor
)
127 public synchronized int[] getFinishedAndReset()
130 int w
= getRenderWidth();
131 int h
= getRenderHeight();
133 ret
= new int[w
* h
];
136 for(int y
= 0; y
< backgroundHeight
; y
++)
137 System
.arraycopy(backgroundBuffer
, y
* backgroundWidth
, ret
, (y
+ gapTop
) * w
+ gapLeft
,
140 for(int y
= 0; y
< backgroundHeight
; y
++)
141 for(int x
= 0; x
< backgroundWidth
; x
++)
142 ret
[(y
+ gapTop
) * w
+ gapLeft
+ x
] = backgroundBuffer
[y
* backgroundWidth
+ x
] * lightAmp
;
145 for(RenderObject obj
: renderObjects
)
147 obj
.render(ret
, w
, h
);
148 renderObjects
.clear();
150 gapLeft
= gapRight
= gapTop
= gapBottom
= 0;
154 final void renderPixel(int[] buffer
, int bw
, int bh
, int x
, int y
, boolean state
, int fillR
, int fillG
,
155 int fillB
, int fillA
, int lineR
, int lineG
, int lineB
, int lineA
)
157 if(x
< 0 || y
< 0 || x
>= bw
|| y
>= bh
)
177 } else if(useA
== 255) {
178 buffer
[y
* bw
+ x
] = (useR
<< 16) | (useG
<< 8) | useB
;
180 int oldpx
= buffer
[y
* bw
+ x
];
181 float oldR
= (oldpx
>>> 16) & 0xFF;
182 float oldG
= (oldpx
>>> 8) & 0xFF;
183 float oldB
= oldpx
& 0xFF;
184 float fA
= (float)useA
/ 255;
185 useR
= (int)(useR
* fA
+ oldR
* (1 - fA
));
186 useG
= (int)(useG
* fA
+ oldG
* (1 - fA
));
187 useB
= (int)(useB
* fA
+ oldB
* (1 - fA
));
188 buffer
[y
* bw
+ x
] = (useR
<< 16) | (useG
<< 8) | useB
;
193 private class WhiteSolidBox
extends RenderObject
199 WhiteSolidBox(int _x
, int _y
, int _w
, int _h
)
207 void render(int[] buffer
, int bw
, int bh
)
209 for(int j
= y
; j
< y
+ h
; j
++) {
212 for(int i
= x
; i
< x
+ w
; i
++) {
215 buffer
[j
* bw
+ i
] = 0xFFFFFF;
221 public synchronized void REMOTE_white_solid_box(int _flags
, int x
, int y
, int w
, int h
)
223 if(((_flags
& flags
)) != flags
)
225 renderObjects
.add(new WhiteSolidBox(x
, y
, w
, h
));
228 private class Box
extends RenderObject
243 Box(int _x
, int _y
, int _w
, int _h
, int _thick
, int lr
, int lg
, int lb
, int la
, int fr
, int fg
, int fb
,
261 void render(int[] buffer
, int bw
, int bh
)
263 for(int j
= y
; j
< y
+ h
&& j
< bh
; j
++) {
266 for(int i
= x
; i
< x
+ w
&& i
< bw
; i
++) {
270 if(x
+ w
- i
- 1 < dist
)
271 dist
= x
+ w
- i
- 1;
272 if(y
+ h
- j
- 1 < dist
)
273 dist
= y
+ h
- j
- 1;
274 renderPixel(buffer
, bw
, bh
, i
, j
, dist
< thick
, fillR
, fillG
, fillB
, fillA
, lineR
, lineG
,
281 public synchronized void REMOTE_box(int _flags
, int _x
, int _y
, int _w
, int _h
, int _thick
, int lr
, int lg
,
282 int lb
, int la
, int fr
, int fg
, int fb
, int fa
)
284 if((_flags
& flags
) != flags
)
286 renderObjects
.add(new Box(_x
, _y
, _w
, _h
, _thick
, lr
, lg
, lb
, la
, fr
, fg
, fb
, fa
));
289 private class Circle
extends RenderObject
304 Circle(int _x
, int _y
, int _r
, int _thick
, int lr
, int lg
, int lb
, int la
, int fr
, int fg
, int fb
,
310 r2outer
= (long)_r
* _r
;
314 r2inner
= (long)(_r
- _thick
) * (_r
- _thick
);
325 void render(int[] buffer
, int bw
, int bh
)
327 for(int j
= y
- r
; j
< y
+ r
&& j
< bh
; j
++) {
330 for(int i
= x
- r
; i
< x
+ r
&& i
< bw
; i
++) {
335 long d
= ox
* ox
+ oy
* oy
;
338 renderPixel(buffer
, bw
, bh
, i
, j
, d
>= r2inner
, fillR
, fillG
, fillB
, fillA
, lineR
, lineG
,
345 public synchronized void REMOTE_circle(int _flags
, int _x
, int _y
, int _r
, int _thick
, int lr
, int lg
, int lb
,
346 int la
, int fr
, int fg
, int fb
, int fa
)
348 if((_flags
& flags
) != flags
)
350 renderObjects
.add(new Circle(_x
, _y
, _r
, _thick
, lr
, lg
, lb
, la
, fr
, fg
, fb
, fa
));
353 private class Bitmap
extends RenderObject
355 private static final int PIXELS_PER_ELEMENT
= 31;
371 Bitmap(int _x
, int _y
, String bmap
, int lr
, int lg
, int lb
, int la
, int fr
, int fg
, int fb
,
372 int fa
, boolean dummy
)
388 w
= bmap
.charAt(i
++);
390 w
= (w
& 0x7F) | (bmap
.charAt(i
++) << 7);
391 stride
= (w
+ PIXELS_PER_ELEMENT
- 1) / PIXELS_PER_ELEMENT
;
392 int rawbytes
= 4 * (w
/ PIXELS_PER_ELEMENT
);
393 rawbytes
+= ((w
% PIXELS_PER_ELEMENT
) + 7) / 8;
394 h
= (bmap
.length() - i
) / rawbytes
;
395 bitmapData
= new int[h
* stride
+ 2];
396 for(int j
= 0; j
< h
; j
++)
397 for(int k
= 0; k
< rawbytes
; k
++)
398 bitmapData
[j
* stride
+ k
/ 4] |= ((int)bmap
.charAt(i
++) << (8 * (k
% 4)));
399 } catch(Exception e
) {
400 System
.err
.println("Bitmap: Failed to parse bitmap: " + e
.getMessage());
405 Bitmap(int _x
, int _y
, String bmap
, int lr
, int lg
, int lb
, int la
, int fr
, int fg
, int fb
,
420 boolean newLine
= true;
421 for(int i
= 0; i
< bmap
.length(); i
++) {
422 char ch
= bmap
.charAt(i
);
441 stride
= (w
+ PIXELS_PER_ELEMENT
- 1) / PIXELS_PER_ELEMENT
;
442 bitmapData
= new int[h
* stride
+ 2];
446 for(int i
= 0; i
< bmap
.length(); i
++) {
447 char ch
= bmap
.charAt(i
);
462 bitmapData
[cy
* stride
+ cx
/ PIXELS_PER_ELEMENT
] |=
463 (1 << (cx
% PIXELS_PER_ELEMENT
));
471 void render(int[] buffer
, int bw
, int bh
)
473 if(bitmapData
== null)
476 int pixel
= bitmapData
[counter
];
477 int pixelModulus
= 0;
478 for(int j
= y
; j
< y
+ h
&& j
< bh
; j
++) {
479 for(int i
= x
; i
< x
+ w
; i
++) {
480 renderPixel(buffer
, bw
, bh
, i
, j
, ((pixel
>> pixelModulus
) & 1) != 0, fillR
, fillG
, fillB
,
481 fillA
, lineR
, lineG
, lineB
, lineA
);
483 if(pixelModulus
== PIXELS_PER_ELEMENT
) {
484 pixel
= bitmapData
[++counter
];
488 if(pixelModulus
> 0) {
489 pixel
= bitmapData
[++counter
];
496 private class VGAChargen
extends RenderObject
502 String vgaChargenString
;
512 VGAChargen(int _x
, int _y
, String text
, int lr
, int lg
, int lb
, int la
, int fr
, int fg
, int fb
,
513 int fa
, boolean _multiline
)
525 vgaChargenString
= text
;
526 multiline
= _multiline
;
529 final void renderPartial(int[] buffer
, int bw
, int bh
, int x
, int y
, long data
)
531 for(int i
= 0; i
< 64; i
++)
532 renderPixel(buffer
, bw
, bh
, x
+ 7 - (i
% 8), y
+ (i
/ 8), ((data
>>> i
) & 1) != 0, fillR
, fillG
, fillB
,
533 fillA
, lineR
, lineG
, lineB
, lineA
);
536 void render(int[] buffer
, int bw
, int bh
)
538 int xbase
= x
, ybase
= y
;
539 int len
= vgaChargenString
.length();
540 for(int i
= 0; i
< len
; i
++) {
541 int ch
= (int)vgaChargenString
.charAt(i
) & 0xFF;
542 if(multiline
&& (ch
== 13 || ch
== 10)) {
546 if(!(xbase
< -7 || ybase
< -15 || xbase
>= bw
|| ybase
>= bh
)) {
547 renderPartial(buffer
, bw
, bh
, xbase
, y
, vgaFontData
[2 * ch
+ 0]);
548 renderPartial(buffer
, bw
, bh
, xbase
, y
+ 8, vgaFontData
[2 * ch
+ 1]);
555 public synchronized void REMOTE_bitmap(int _flags
, int _x
, int _y
, String bmap
, int lr
, int lg
, int lb
, int la
,
556 int fr
, int fg
, int fb
, int fa
)
558 if((_flags
& flags
) != flags
)
560 renderObjects
.add(new Bitmap(_x
, _y
, bmap
, lr
, lg
, lb
, la
, fr
, fg
, fb
, fa
));
563 public synchronized void REMOTE_bitmap_binary(int _flags
, int _x
, int _y
, String bmap
, int lr
, int lg
, int lb
,
564 int la
, int fr
, int fg
, int fb
, int fa
)
566 if((_flags
& flags
) != flags
)
568 renderObjects
.add(new Bitmap(_x
, _y
, bmap
, lr
, lg
, lb
, la
, fr
, fg
, fb
, fa
, true));
571 public synchronized void REMOTE_vga_chargen(int _flags
, int _x
, int _y
, String text
, int lr
, int lg
, int lb
, int la
,
572 int fr
, int fg
, int fb
, int fa
, boolean multiline
)
574 if((_flags
& flags
) != flags
)
576 renderObjects
.add(new VGAChargen(_x
, _y
, text
, lr
, lg
, lb
, la
, fr
, fg
, fb
, fa
, multiline
));