hzmachine

Hiptop Z Machine
git clone http://frotz.net/git/hzmachine.git
Log | Files | Refs | LICENSE

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 }