Adjust clearing
This commit is contained in:
@@ -63,9 +63,6 @@ public class GocaDecoder {
|
|||||||
|
|
||||||
// Segment Store for retained graphics / segment calling (G_GCALL 0x2A)
|
// Segment Store for retained graphics / segment calling (G_GCALL 0x2A)
|
||||||
private final java.util.Map<Integer, byte[]> segmentStore = new java.util.HashMap<>();
|
private final java.util.Map<Integer, byte[]> segmentStore = new java.util.HashMap<>();
|
||||||
private final java.util.Map<Integer, Integer> segmentChainMap = new java.util.HashMap<>();
|
|
||||||
private final java.util.List<Integer> segmentOrderList = new java.util.ArrayList<>();
|
|
||||||
private final java.util.Set<Integer> chainedTargets = new java.util.HashSet<>();
|
|
||||||
private int callDepth = 0;
|
private int callDepth = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,9 +205,6 @@ public class GocaDecoder {
|
|||||||
graphicCursorX = 0;
|
graphicCursorX = 0;
|
||||||
graphicCursorY = 0;
|
graphicCursorY = 0;
|
||||||
segmentStore.clear();
|
segmentStore.clear();
|
||||||
segmentChainMap.clear();
|
|
||||||
segmentOrderList.clear();
|
|
||||||
chainedTargets.clear();
|
|
||||||
segmentBoundsMap.clear();
|
segmentBoundsMap.clear();
|
||||||
activeSegmentsInOrder.clear();
|
activeSegmentsInOrder.clear();
|
||||||
currentSegId = 0;
|
currentSegId = 0;
|
||||||
@@ -294,61 +288,6 @@ public class GocaDecoder {
|
|||||||
return (data[idx + 1] & 0xFF) + 2;
|
return (data[idx + 1] & 0xFF) + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexSegments(byte[] data, int offset, int length) {
|
|
||||||
int idx = offset;
|
|
||||||
int end = offset + length;
|
|
||||||
while (idx < end) {
|
|
||||||
int order = data[idx] & 0xFF;
|
|
||||||
if (order == GocaConstants.G_BEGSEGM) {
|
|
||||||
int segStart = idx;
|
|
||||||
int segLen = getOrderLength(data, idx, end);
|
|
||||||
if (segLen <= 0 || idx + 5 >= end) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int segId = ((data[idx + 2] & 0xFF) << 24) |
|
|
||||||
((data[idx + 3] & 0xFF) << 16) |
|
|
||||||
((data[idx + 4] & 0xFF) << 8) |
|
|
||||||
(data[idx + 5] & 0xFF);
|
|
||||||
|
|
||||||
int nextId = 0;
|
|
||||||
if (segLen >= 14 && (data[idx + 1] & 0xFF) >= 12) {
|
|
||||||
nextId = ((data[idx + 10] & 0xFF) << 24) |
|
|
||||||
((data[idx + 11] & 0xFF) << 16) |
|
|
||||||
((data[idx + 12] & 0xFF) << 8) |
|
|
||||||
(data[idx + 13] & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
int searchIdx = idx + segLen;
|
|
||||||
while (searchIdx < end) {
|
|
||||||
int o = data[searchIdx] & 0xFF;
|
|
||||||
int oLen = getOrderLength(data, searchIdx, end);
|
|
||||||
if (oLen <= 0) break;
|
|
||||||
if (o == GocaConstants.G_ENDSEGM) {
|
|
||||||
searchIdx += oLen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
searchIdx += oLen;
|
|
||||||
}
|
|
||||||
int fullSegLen = searchIdx - segStart;
|
|
||||||
if (fullSegLen > 0 && segStart + fullSegLen <= end) {
|
|
||||||
byte[] segBytes = new byte[fullSegLen];
|
|
||||||
System.arraycopy(data, segStart, segBytes, 0, fullSegLen);
|
|
||||||
segmentStore.put(segId, segBytes);
|
|
||||||
segmentOrderList.add(segId);
|
|
||||||
if (nextId != 0) {
|
|
||||||
segmentChainMap.put(segId, nextId);
|
|
||||||
chainedTargets.add(nextId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
idx = searchIdx;
|
|
||||||
} else {
|
|
||||||
int oLen = getOrderLength(data, idx, end);
|
|
||||||
if (oLen <= 0) break;
|
|
||||||
idx += oLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes a stream of GOCA drawing orders (matching IBM Host On-Demand HODDecoder.decodeGOCA).
|
* Decodes a stream of GOCA drawing orders (matching IBM Host On-Demand HODDecoder.decodeGOCA).
|
||||||
*/
|
*/
|
||||||
@@ -386,7 +325,7 @@ public class GocaDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a stored procedure segment by segment ID, traversing chained next segments.
|
* Executes a stored procedure segment by segment ID.
|
||||||
*/
|
*/
|
||||||
public synchronized void procedureSegment(int segId) {
|
public synchronized void procedureSegment(int segId) {
|
||||||
if (segId == 0) return;
|
if (segId == 0) return;
|
||||||
@@ -401,12 +340,6 @@ public class GocaDecoder {
|
|||||||
decodeStreamDirect(segData, 0, segData.length);
|
decodeStreamDirect(segData, 0, segData.length);
|
||||||
callDepth--;
|
callDepth--;
|
||||||
currentSegId = savedSeg;
|
currentSegId = savedSeg;
|
||||||
|
|
||||||
// Execute chained segments
|
|
||||||
Integer nextId = segmentChainMap.get(segId);
|
|
||||||
if (nextId != null && nextId != 0 && callDepth < 16) {
|
|
||||||
procedureSegment(nextId);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
logger.warning("procedureSegment: Segment not found in store: " + segId);
|
logger.warning("procedureSegment: Segment not found in store: " + segId);
|
||||||
}
|
}
|
||||||
@@ -444,10 +377,6 @@ public class GocaDecoder {
|
|||||||
end = offset + length;
|
end = offset + length;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callDepth == 0) {
|
|
||||||
indexSegments(inputData, idx, end - idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
decodeStreamDirect(inputData, idx, end - idx);
|
decodeStreamDirect(inputData, idx, end - idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +424,27 @@ public class GocaDecoder {
|
|||||||
SegmentBounds sb = segmentBoundsMap.computeIfAbsent(segId, SegmentBounds::new);
|
SegmentBounds sb = segmentBoundsMap.computeIfAbsent(segId, SegmentBounds::new);
|
||||||
activeSegmentsInOrder.remove(sb);
|
activeSegmentsInOrder.remove(sb);
|
||||||
activeSegmentsInOrder.add(sb);
|
activeSegmentsInOrder.add(sb);
|
||||||
|
|
||||||
|
if (segId != 0 && callDepth == 0) {
|
||||||
|
int segStart = idx;
|
||||||
|
int searchIdx = idx + orderLen;
|
||||||
|
while (searchIdx < end) {
|
||||||
|
int o = inputData[searchIdx] & 0xFF;
|
||||||
|
int oLen = getOrderLength(inputData, searchIdx, end);
|
||||||
|
if (oLen <= 0) break;
|
||||||
|
if (o == GocaConstants.G_ENDSEGM) {
|
||||||
|
searchIdx += oLen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
searchIdx += oLen;
|
||||||
|
}
|
||||||
|
int fullSegLen = searchIdx - segStart;
|
||||||
|
if (fullSegLen > 0 && segStart + fullSegLen <= end) {
|
||||||
|
byte[] segBytes = new byte[fullSegLen];
|
||||||
|
System.arraycopy(inputData, segStart, segBytes, 0, fullSegLen);
|
||||||
|
segmentStore.put(segId, segBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (idx + 6 < end) flag0 = inputData[idx + 6] & 0xFF;
|
if (idx + 6 < end) flag0 = inputData[idx + 6] & 0xFF;
|
||||||
if (idx + 7 < end) flag1 = inputData[idx + 7] & 0xFF;
|
if (idx + 7 < end) flag1 = inputData[idx + 7] & 0xFF;
|
||||||
@@ -507,7 +457,6 @@ public class GocaDecoder {
|
|||||||
}
|
}
|
||||||
case GocaConstants.G_ENDSEGM: { // End Segment (0x71)
|
case GocaConstants.G_ENDSEGM: { // End Segment (0x71)
|
||||||
logger.info(String.format("GOCA ENDSEGM: segId=%d", currentSegId));
|
logger.info(String.format("GOCA ENDSEGM: segId=%d", currentSegId));
|
||||||
int finishedSegId = currentSegId;
|
|
||||||
if (currentSegId != 0) {
|
if (currentSegId != 0) {
|
||||||
SegmentBounds sb = segmentBoundsMap.get(currentSegId);
|
SegmentBounds sb = segmentBoundsMap.get(currentSegId);
|
||||||
if (sb != null) {
|
if (sb != null) {
|
||||||
@@ -519,23 +468,6 @@ public class GocaDecoder {
|
|||||||
}
|
}
|
||||||
currentSegId = 0;
|
currentSegId = 0;
|
||||||
idx += orderLen;
|
idx += orderLen;
|
||||||
if (finishedSegId != 0 && callDepth < 16) {
|
|
||||||
Integer nextId = segmentChainMap.get(finishedSegId);
|
|
||||||
if (nextId != null && nextId != 0) {
|
|
||||||
byte[] nextSeg = segmentStore.get(nextId);
|
|
||||||
if (nextSeg != null) {
|
|
||||||
logger.info("Executing chained segment nextId=" + nextId);
|
|
||||||
currentSegId = nextId;
|
|
||||||
SegmentBounds targetSb = segmentBoundsMap.computeIfAbsent(nextId, SegmentBounds::new);
|
|
||||||
activeSegmentsInOrder.remove(targetSb);
|
|
||||||
activeSegmentsInOrder.add(targetSb);
|
|
||||||
callDepth++;
|
|
||||||
decodeStreamDirect(nextSeg, 0, nextSeg.length);
|
|
||||||
callDepth--;
|
|
||||||
currentSegId = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,8 +833,6 @@ public class GocaDecoder {
|
|||||||
activeSegmentsInOrder.clear();
|
activeSegmentsInOrder.clear();
|
||||||
segmentBoundsMap.clear();
|
segmentBoundsMap.clear();
|
||||||
segmentStore.clear();
|
segmentStore.clear();
|
||||||
segmentOrderList.clear();
|
|
||||||
chainedTargets.clear();
|
|
||||||
logger.info("GOCA P_ERASE: erased graphics presentation space and cleared segment stores");
|
logger.info("GOCA P_ERASE: erased graphics presentation space and cleared segment stores");
|
||||||
idx += 2;
|
idx += 2;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -71,14 +71,14 @@ public class GocaDecoderPhase5Test {
|
|||||||
GraphicsPlane plane = new GraphicsPlane(400, 300);
|
GraphicsPlane plane = new GraphicsPlane(400, 300);
|
||||||
GocaDecoder decoder = new GocaDecoder(plane);
|
GocaDecoder decoder = new GocaDecoder(plane);
|
||||||
|
|
||||||
// Segment 10 chains to Segment 11
|
// Segment 10 has bytes indicating nextId = 11
|
||||||
ByteArrayOutputStream s10 = new ByteArrayOutputStream();
|
ByteArrayOutputStream s10 = new ByteArrayOutputStream();
|
||||||
s10.write(GocaConstants.G_BEGSEGM);
|
s10.write(GocaConstants.G_BEGSEGM);
|
||||||
s10.write(0x0C);
|
s10.write(0x0C);
|
||||||
s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0A); // Seg 10
|
s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0A); // Seg 10
|
||||||
s10.write(0x00); s10.write(0x00);
|
s10.write(0x00); s10.write(0x00);
|
||||||
s10.write(0x00); s10.write(0x00); // flags
|
s10.write(0x00); s10.write(0x00); // flags
|
||||||
s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0B); // Next Seg ID = 11!
|
s10.write(0x00); s10.write(0x00); s10.write(0x00); s10.write(0x0B); // Next Seg ID = 11
|
||||||
s10.write(GocaConstants.G_GSCOL); s10.write(0x01); // Blue
|
s10.write(GocaConstants.G_GSCOL); s10.write(0x01); // Blue
|
||||||
s10.write(GocaConstants.G_GLINE); s10.write(0x08);
|
s10.write(GocaConstants.G_GLINE); s10.write(0x08);
|
||||||
s10.write(0x00); s10.write(10); s10.write(0x00); s10.write(10);
|
s10.write(0x00); s10.write(10); s10.write(0x00); s10.write(10);
|
||||||
@@ -99,16 +99,16 @@ public class GocaDecoderPhase5Test {
|
|||||||
s11.write(0x00); s11.write(70); s11.write(0x00); s11.write(70);
|
s11.write(0x00); s11.write(70); s11.write(0x00); s11.write(70);
|
||||||
s11.write(GocaConstants.G_ENDSEGM); s11.write(0x00);
|
s11.write(GocaConstants.G_ENDSEGM); s11.write(0x00);
|
||||||
|
|
||||||
// Store Segment 11 first
|
// Decode Segment 11 first, then clear
|
||||||
decoder.decodeGoca(s11.toByteArray(), 0, s11.toByteArray().length);
|
decoder.decodeGoca(s11.toByteArray(), 0, s11.toByteArray().length);
|
||||||
plane.clear();
|
plane.clear();
|
||||||
assertFalse(plane.hasContent());
|
assertFalse(plane.hasContent());
|
||||||
|
|
||||||
// Execute Segment 10; upon ENDSEGM, Segment 11 should be automatically chained!
|
// Execute Segment 10; per HOD architecture, ENDSEGM must NOT automatically execute Segment 11!
|
||||||
decoder.decodeGoca(s10.toByteArray(), 0, s10.toByteArray().length);
|
decoder.decodeGoca(s10.toByteArray(), 0, s10.toByteArray().length);
|
||||||
assertTrue(plane.hasContent());
|
assertTrue(plane.hasContent());
|
||||||
|
|
||||||
// Verify both Blue (Seg 10) and Yellow (Seg 11) pixels exist
|
// Verify Blue (Seg 10) exists, and Yellow (Seg 11) is NOT drawn
|
||||||
int blueArgb = GocaConstants.GOCA_COLORS[1];
|
int blueArgb = GocaConstants.GOCA_COLORS[1];
|
||||||
int yellowArgb = GocaConstants.GOCA_COLORS[6];
|
int yellowArgb = GocaConstants.GOCA_COLORS[6];
|
||||||
boolean foundBlue = false;
|
boolean foundBlue = false;
|
||||||
@@ -118,7 +118,7 @@ public class GocaDecoderPhase5Test {
|
|||||||
if (p == yellowArgb) foundYellow = true;
|
if (p == yellowArgb) foundYellow = true;
|
||||||
}
|
}
|
||||||
assertTrue(foundBlue, "Expected Blue pixel from Segment 10");
|
assertTrue(foundBlue, "Expected Blue pixel from Segment 10");
|
||||||
assertTrue(foundYellow, "Expected Yellow pixel from chained Segment 11");
|
assertFalse(foundYellow, "Per HOD architecture, Segment 11 must NOT be automatically chained on ENDSEGM");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user