1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.zmpp.vm;
24
25 import org.zmpp.base.MemoryReadAccess;
26
27 /***
28 * This class implements the print and print_ret instructions.
29 *
30 * @author Wei-ju Wu
31 * @version 1.0
32 */
33 public class PrintLiteralInstruction extends AbstractInstruction {
34
35 public static final int OP_PRINT = 0x02;
36 public static final int OP_PRINT_RET = 0x03;
37
38 /***
39 * The instruction address.
40 */
41 private int instructionAddress;
42
43 /***
44 * Memory access object.
45 */
46 private MemoryReadAccess memaccess;
47
48 /***
49 * Constructor.
50 *
51 * @param machineState the machine state reference
52 * @param opcode the opcode
53 * @param memaccess the memory access object
54 * @param instrAddress the instruction address
55 */
56 public PrintLiteralInstruction(Machine machineState, int opcode,
57 MemoryReadAccess memaccess, int instrAddress) {
58
59 super(machineState, opcode);
60
61 this.memaccess = memaccess;
62 instructionAddress = instrAddress;
63 }
64
65 /***
66 * {@inheritDoc}
67 */
68 public InstructionForm getInstructionForm() {
69
70 return InstructionForm.SHORT;
71 }
72
73 /***
74 * {@inheritDoc}
75 */
76 public OperandCount getOperandCount() {
77
78 return OperandCount.C0OP;
79 }
80
81 /***
82 * {@inheritDoc}
83 */
84 public void setLength(int length) {
85
86
87 }
88
89 /***
90 * {@inheritDoc}
91 */
92 public int getLength() {
93
94 return getLiteralLengthInBytes() + 1;
95 }
96
97 /***
98 * {@inheritDoc}
99 */
100 public void execute() {
101
102 getMachine().printZsciiString(instructionAddress + 1);
103 if (getOpcode() == OP_PRINT_RET) {
104
105 returnFromRoutine(TRUE);
106
107 } else if (getOpcode() == OP_PRINT) {
108
109 nextInstruction();
110
111 } else {
112
113 throwInvalidOpcode();
114 }
115 }
116
117 /***
118 * Returns the address of the literal.
119 *
120 * @return the address of the literal
121 */
122 public int getLiteralAddress() {
123
124 return instructionAddress + 1;
125 }
126
127 /***
128 * Determines the byte length of the ZSCII string literal.
129 *
130 * @return the length of the literal in bytes
131 */
132 private int getLiteralLengthInBytes() {
133
134 int currentAddress = instructionAddress + 1;
135 int zword = 0;
136
137 do {
138
139 zword = memaccess.readUnsignedShort(currentAddress);
140 currentAddress += 2;
141
142 } while ((zword & 0x8000) == 0);
143
144 return currentAddress - (instructionAddress + 1);
145 }
146 }