ZDanger.java (6861B)
1 // Z Machine V3/V4/V5 Runtime 2 // 3 // Copyright 2002-2003, Brian Swetland <swetland@frotz.net> 4 // Available under a BSD-Style License. Share and Enjoy. 5 // 6 // glue between the runtime and the Danger UI 7 8 package net.frotz.zruntime; 9 10 import danger.app.DataStore; 11 import danger.app.Event; 12 import danger.ui.Menu; 13 import java.util.Random; 14 15 16 public class ZDanger extends ZScreen implements Runnable 17 { 18 ZDanger(ZWindow win, int width, int height) { 19 this.win = win; 20 this.w = width; 21 this.h = height; 22 screen = new byte[width*height]; 23 buffer = new byte[width]; 24 r = new Random(); 25 Clear(); 26 buffered = true; 27 win0h = height; 28 win1h = 0; 29 win1cx = 0; 30 win1cy = 0; 31 LF = new char[1]; 32 LF[0] = '\n'; 33 } 34 35 public int GetWidth() { return w; } 36 public int GetHeight() { return h; } 37 38 void Clear() { 39 for(int i = 0; i < w*h; i++) screen[i] = (byte) ' '; 40 cx = 0; 41 cy = h - 1; 42 } 43 44 public void SetStatus(char line[], int len) { 45 int i; 46 if(win1h > 0){ 47 int max = w-1; 48 if(len >= max) len = max; 49 for(i = 0; i < len; i++){ 50 screen[i+1] = (byte) line[i]; 51 } 52 screen[0] = (byte) ' '; 53 while(i < max) screen[1+i++] = (byte)' '; 54 win.invalidate(); 55 } 56 } 57 58 public void run() { 59 for(;;) { 60 byte[] data = win.GetGameFile(); 61 if(data == null) { 62 Clear(); 63 Print("no game file installed."); 64 break; 65 } 66 try { 67 zm = new ZMachine(this, data); 68 Clear(); 69 zm.run(); 70 } catch (Throwable t) { 71 System.err.println("ZMachine: exception "+t); 72 t.printStackTrace(); 73 } 74 } 75 } 76 77 public void SetWindow(int num) { 78 selected = num; 79 if(selected == 1){ 80 win1cx = 0; 81 win1cy = 0; 82 } else { 83 win.invalidate(); 84 } 85 } 86 public void SplitWindow(int height) { 87 win1h = height; 88 win0h = h - height; 89 } 90 public void EraseWindow(int num) { 91 if(num == -1) { 92 Clear(); 93 win1h = 0; 94 win0h = h; 95 cx = 0; 96 cy = 0; 97 win1cx = 0; 98 win1cy = 0; 99 selected = 0; 100 count = 0; 101 } 102 } 103 public void MoveCursor(int x, int y) { 104 /* upper left is 1,1 */ 105 x--; 106 y--; 107 108 /* gracefully deal with bogus locations */ 109 if(x < 0) x = 0; 110 if(y < 0) y = 0; 111 112 if(selected == 0){ 113 cx = x; 114 cy = win1h + y; 115 if(cx >= w) cx = w-1; 116 if(cy >= h) cy = h-1; 117 } else { 118 win1cx = x; 119 win1cy = y; 120 if(win1cx >= w) win1cx = w-1; 121 if(win1cy >= win1h) win1cy = win1h - 1; 122 } 123 } 124 125 public void Print(char data[], int len) { 126 int ptr = 0; 127 128 if(selected == 1){ 129 if(win1h == 0) return; 130 131 while(ptr < len){ 132 char ch = data[ptr++]; 133 134 if(ch == 13 || ch == 10){ 135 win1cy++; 136 win1cx=0; 137 } else { 138 screen[win1cx + win1cy * w] = (byte) ch; 139 win1cx++; 140 if(win1cx == w){ 141 if(win1cy + 1 < win1h){ 142 win1cy++; 143 win1cx = 0; 144 } else { 145 win1cx--; 146 } 147 } 148 } 149 if(win1cy >= win1h) win1cy = win1h - 1; 150 } 151 return; 152 } 153 154 if(!input_active) win.Transcript(data, 0, len); 155 156 while(ptr < len){ 157 char c = data[ptr]; 158 if((c == 13) || (c == 10)) { 159 DoNewLine(); 160 } else { 161 if(buffered) { 162 buffer[buflen++] = (byte) c; 163 if(buflen == w){ 164 int i; 165 for(i = buflen - 1; i > 0; i--){ 166 if(buffer[i] == ' ') { 167 int t = buflen; 168 buflen = i ; 169 DoNewLine(); 170 i++; 171 buflen = t - i; 172 System.arraycopy(buffer, i, buffer, 0, buflen); 173 i = -1; 174 break; 175 } 176 } 177 if(i != -1) DoNewLine(); 178 } 179 } else { 180 screen[cx + cy * w] = (byte) c; 181 cx ++; 182 if(cx == w) DoNewLine(); 183 } 184 } 185 ptr++; 186 } 187 win.invalidate(); 188 } 189 190 void Flush() { 191 if(selected == 0) { 192 if(buffered) { 193 System.arraycopy(buffer, 0, screen, cx + cy * w, buflen); 194 cx += buflen; 195 buflen = 0; 196 } 197 } 198 } 199 200 public void NewLine() { 201 if(!input_active) win.Transcript(LF,0,1); 202 DoNewLine(); 203 } 204 205 public void DoNewLine() { 206 Flush(); 207 208 cx = 0; 209 cy++; 210 if(cy == h){ 211 cy--; 212 scrollup(); 213 } 214 count++; 215 if(count == (win0h - 1)){ 216 int p = w * (h - 1); 217 screen[p+0] = (byte) '['; 218 screen[p+1] = (byte) 'M'; 219 screen[p+2] = (byte) 'O'; 220 screen[p+3] = (byte) 'R'; 221 screen[p+4] = (byte) 'E'; 222 screen[p+5] = (byte) ']'; 223 win.invalidate(); 224 synchronized (zm) { 225 paused = true; 226 try { 227 zm.wait(); 228 } catch (Throwable t) { 229 } 230 } 231 screen[p+0] = (byte) ' '; 232 screen[p+1] = (byte) ' '; 233 screen[p+2] = (byte) ' '; 234 screen[p+3] = (byte) ' '; 235 screen[p+4] = (byte) ' '; 236 screen[p+5] = (byte) ' '; 237 count = 0; 238 } 239 } 240 241 void scrollup() { 242 int i,p; 243 System.arraycopy(screen, (win1h+1) * w, screen, win1h*w, w * (win0h - 1)); 244 245 p = w * (h - 1); 246 for(i = 0; i < w; i++){ 247 screen[p++] = (byte) ' '; 248 } 249 250 } 251 252 public void Backspace() { 253 cx--; 254 if(cx < 0){ 255 cy--; 256 cx = w - 1; 257 } 258 screen[cx + cy * w] = (byte) ' '; 259 win.invalidate(); 260 } 261 262 public void KeyPress(char key) { 263 if(paused) { 264 synchronized(zm) { 265 paused = false; 266 zm.notify(); 267 } 268 return; 269 } 270 if(input_active) { 271 if(readchar == -1){ 272 readchar = (int) key; 273 synchronized(zm){ 274 input_active = false; 275 zm.notify(); 276 } 277 return; 278 } 279 switch(key){ 280 case 10: 281 case 13: 282 DoNewLine(); 283 synchronized(zm) { 284 input_active = false; 285 zm.notify(); 286 } 287 break; 288 case 8: 289 if(line_sz > 0) { 290 Backspace(); 291 line_sz--; 292 } 293 break; 294 default: 295 line[line_sz++] = key; 296 PrintChar(key); 297 } 298 } 299 } 300 301 public int Read(){ 302 win.invalidate(); 303 try { 304 synchronized(zm) { 305 input_active = true; 306 readchar = -1; 307 zm.wait(); 308 return readchar; 309 } 310 } catch (Throwable t){ 311 } 312 return 0; 313 } 314 315 public int ReadLine(char buffer[]) { 316 Flush(); 317 win.invalidate(); 318 count = 0; 319 try { 320 synchronized(zm) { 321 buffered = false; 322 line = buffer; 323 input_active = true; 324 line_sz = 0; 325 zm.wait(); 326 line = null; 327 buffered = true; 328 win.Transcript(buffer, 0, line_sz); 329 win.Transcript(LF, 0, 1); 330 return line_sz; 331 } 332 } catch (Throwable t) { 333 } 334 return 0; 335 } 336 337 public void Print(String s) { 338 // there ought to be a better way to do this. 339 char[] buf = new char[s.length()]; 340 s.getChars(0, s.length(), buf, 0); 341 Print(buf, s.length()); 342 } 343 344 public int Random(int limit) { 345 if((limit & 0x8000) != 0) { 346 r.setSeed(limit & 0x7fff); 347 return 0; 348 } 349 if(limit == 0) { 350 r = new Random(); 351 return 0; 352 } 353 return r.nextInt(limit) + 1; 354 } 355 356 public boolean Save(byte state[]) { 357 return win.Save(state); 358 } 359 public byte[] Restore() { 360 return win.Restore(); 361 } 362 363 int selected; 364 int readchar; 365 366 int win0h; 367 int win1h; 368 int win1cx; 369 int win1cy; 370 371 Random r; 372 byte screen[]; 373 byte buffer[]; 374 int buflen; 375 376 char line[]; 377 int line_sz; 378 ZWindow win; 379 int w,h; /* screen dimensions */ 380 int cx,cy; /* cursor position */ 381 int count; 382 383 boolean input_active; 384 boolean buffered; 385 boolean paused; 386 boolean running; 387 ZMachine zm; 388 389 char[] LF; 390 static final boolean TRACE = false; 391 392 }