hzmachine

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

ZWindow.java (7373B)


      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 // Hiptop Application Main Window
      7 
      8 package net.frotz.zruntime;
      9 
     10 import danger.app.Resource;
     11 import danger.app.ResourceDatabase;
     12 import danger.app.Event;
     13 import danger.app.Registrar;
     14 import danger.app.IPCMessage;
     15 
     16 import danger.ui.ScreenWindow;
     17 import danger.ui.Font;
     18 import danger.ui.Pen;
     19 import danger.ui.Color;
     20 import danger.ui.Window;
     21 import danger.ui.TextField;
     22 import danger.ui.EditText;
     23 import danger.ui.PopupMenu;
     24 
     25 import danger.app.DataStore;
     26 
     27 public class ZWindow extends ScreenWindow implements Resources, Events
     28 {
     29 	public ZWindow(ZRuntime app) {
     30 		super("ZMachine");
     31 		setFullScreen(true);
     32 		font = Font.findFont("Fixed5x7");
     33 		CH = font.getAscent() + font.getDescent();
     34 		CA = font.getAscent();
     35 		CW = font.charWidth('M');
     36 		w = getWidth() / CW;
     37 		h = getHeight() / CH;
     38 		System.err.println("[ " + w + " x " + h + " ]");
     39 		scr = new ZDanger(this, w, h);
     40 		screen = scr.screen;
     41 		this.app = app;
     42 		rdb = app.getResources();
     43 		rdb.addToMenuFromResource(getActionMenu(),MENU_MAIN,this,null);
     44 	}
     45 
     46 	byte[] GetGameFile() {
     47 		int b;
     48 		Resource rsrc;
     49 		rsrc = app.getResource(1000,1000);
     50 
     51 		if(rsrc != null) {
     52 			b = rsrc.getSize();
     53 			System.err.println("Gamefile: "+b+" bytes");
     54 			byte[] data = new byte[b];
     55 			rsrc.getBytes(data, 0, b);
     56 			return data;
     57 		} else {
     58 			return null;
     59 		}
     60 	}
     61 
     62 	void ScrollLine(byte data[], int off) {
     63 	}
     64 
     65 	Window dw;
     66 	
     67 	public void Email(String subject, String body) {
     68 		IPCMessage msg = new IPCMessage();
     69 		msg.addItem("action", "send");
     70 		msg.addItem("subject", subject);
     71 		msg.addItem("body", body);
     72 		Registrar.sendMessage("Email", msg, null);
     73 	}
     74 	
     75 	public boolean receiveEvent(Event e) {
     76 		switch(e.type) {
     77 		case DO_VIEW_NOTEPAD:
     78 			if(notepad == null) {
     79 				notepad = rdb.getScreen(SCREEN_NOTEPAD, this);
     80 			}
     81 			dw = notepad;
     82 			dw.show();
     83 			break;
     84 		case DO_VIEW_TRANSCRIPT:
     85 			dw = rdb.getScreen(SCREEN_TRANSCRIPT,this);
     86 			((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).setText(transcript.toString());
     87 			dw.show();
     88 			break;
     89 		case NOTEPAD_DISMISS:
     90 		case TRANSCRIPT_DISMISS:
     91 			show();
     92 			dw.hide();
     93 			dw = null;
     94 			break;
     95 		case DO_EMAIL_NOTEPAD:
     96 			Email("Game Notepad",((EditText)dw.getDescendantWithID(ID_TEXT_NOTEPAD)).toString());
     97 			break;
     98 		case DO_EMAIL_TRANSCRIPT:
     99 			Email("Game Transcript",((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).toString());
    100 			break;
    101 		case DO_CLEAR_TRANSCRIPT:
    102 			transcript.setLength(0);
    103 			((EditText)dw.getDescendantWithID(ID_TEXT_TRANSCRIPT)).setText("");
    104 			break;
    105 		case DO_ABOUT:
    106 			(rdb.getDialog(DIALOG_ABOUT)).show();
    107 			break;
    108 		case DO_RESTORE:
    109 			dw = rdb.getDialog(DIALOG_RESTORE,this);
    110 			String[] gamelist = getSavedGames();
    111 			if((gamelist == null) || (gamelist.length == 0)) {
    112 				notifyEngine(false);
    113 				break;
    114 			} else {
    115 				PopupMenu pm = (PopupMenu) dw.getDescendantWithID(ID_NAME_RESTORE);
    116 		
    117 				for(int i = 0; i < gamelist.length; i++) {
    118 					if(gamelist[i] != null) {
    119 						System.err.println("Game["+i+"] = '"+gamelist[i]+"'");
    120 						pm.addItem(gamelist[i]);
    121 					}
    122 				}
    123 			}
    124 			dw.show();
    125 			break;
    126 		case DO_SAVE:
    127 			dw = rdb.getDialog(DIALOG_SAVE, this);
    128 			dw.show();
    129 			break;
    130 		case SAVE_CANCEL:
    131 		case RESTORE_CANCEL:
    132 			notifyEngine(false);
    133 			break;
    134 		case SAVE_OK:
    135 			TextField tf = (TextField) dw.getDescendantWithID(ID_NAME_SAVE);
    136 			savegame = tf.toString();
    137 			notifyEngine(true);
    138 			break;
    139 		case RESTORE_OK:
    140 			PopupMenu pm = ((PopupMenu) dw.getDescendantWithID(ID_NAME_RESTORE));
    141 			selection = pm.getValue();
    142 			notifyEngine(true);
    143 			break;
    144 		default:
    145 			return super.receiveEvent(e);
    146 		}
    147 		return true;
    148 	}
    149 	
    150 	public boolean eventKeyUp(char c, Event e) {
    151 		scr.KeyPress(c);
    152 		return true;
    153 	}
    154 
    155 	public boolean eventWidgetUp(int widget, Event event) {
    156 		switch(widget) {
    157 		case Event.DEVICE_BUTTON_BACK:
    158 			app.returnToLauncher();
    159 			return true;
    160 		default:
    161 			return super.eventWidgetUp(widget,event);
    162 		}
    163 	}
    164 	public void paint(Pen p) {
    165 		int i, off;
    166 		p.setFont(font);
    167 		int BG = Color.WHITE;
    168 		int FG = Color.BLACK;
    169 		int sh = scr.win1h;
    170 		
    171 		p.setColor(FG);
    172 		p.fillRect(0,0,w * CW,sh*CH);
    173 
    174 		p.setColor(BG);
    175 		for(i = 0, off = 0; i < sh; i++){
    176 			p.drawText(2, i * CH + CA, screen, off, w);
    177 			off += w;
    178 		}
    179 
    180 		p.fillRect(0, sh*CH, w*CW, h*CH);
    181 		p.setColor(FG);
    182 		for(; i < h; i++){
    183 			p.drawText(2, i * CH + CA, screen, off, w);
    184 			off += w;
    185 		}
    186 		p.setColor(BG);
    187 		p.fillRect(0, i*CH, getWidth(), getHeight());
    188 
    189 		if(scr.input_active){
    190 			p.setColor(Color.RED);
    191 			int x = scr.cx * CW + 2;
    192 			int y = scr.cy * CH;
    193 			p.fillRect(x, y, x + CW, y + CH);
    194 		}
    195 	}
    196 
    197 	public String[] getSavedGames() {
    198 		DataStore ds = getDataStore();
    199 		int i, j;
    200 		int count = ds.getRecordCount();
    201 		String[] out = new String[count];
    202 
    203 		for(i = 0; i < count; i++) {
    204 			byte[] data = ds.getRecordData(i);
    205 
    206 			if(data[0] == 'Z' && data[1] == '!' && data[2] == '1' && data[3] == '0'){
    207 				for(j = 32; j < 64; j++){
    208 					if(data[j] == 0) break;
    209 				}
    210 				out[i] = new String(data, 32, j-32);
    211 			} else {
    212 				out[i] = null;
    213 			}
    214 		}
    215 		return out;
    216 	}
    217 
    218 	public void saveGame(String gamename, byte[] data) {
    219 		int i,j,count;
    220 
    221 		DataStore ds = getDataStore();
    222 		
    223 		byte str[] = gamename.getBytes();
    224 		
    225 		data[0] = 'Z';
    226 		data[1] = '!';
    227 		data[2] = '1';
    228 		data[3] = '0';
    229 		
    230 		for(i = 4; i < 64; i++) data[i] = 0;
    231 
    232 		for(i = 0; i < str.length; i++){
    233 			if(i == 32) break;
    234 			data[32 + i] = str[i];
    235 		}
    236 
    237 		count = ds.getRecordCount();
    238 		for(i = 0; i < count; i++){
    239 			byte game[] = ds.getRecordData(i);
    240 			for(j = 0; j < 64; j++){
    241 				if(game[j] != data[j]) break;
    242 			}
    243 			if(j == 64){
    244 				ds.setRecordData(i, data);
    245 				return;
    246 			}
    247 		}
    248 
    249 		ds.addRecord(data);
    250 	}
    251 		
    252 	String usename = "SaveGame";
    253 	int count = 0;
    254 
    255 	DataStore getDataStore() {
    256 		DataStore ds = DataStore.findDataStore("saved-games");
    257 		if (ds == null) {
    258 			return DataStore.createDataStore("saved-games", true);
    259 		} else {
    260 			return ds;
    261 		}
    262 	}
    263 
    264 	boolean waitForUI() {
    265 		System.err.println("WaitForUI");
    266 		try {
    267 			synchronized(notify) {
    268 				success = false;
    269 				notify.wait();
    270 			}
    271 		} catch(Throwable t) {
    272 		}
    273 		System.err.println("DoneWaiting: " +success);
    274 		
    275 		return success;
    276 	}
    277 	
    278 	boolean success;
    279 	String savegame;
    280 	int selection;
    281 	
    282 	void notifyEngine(boolean status) {
    283 		synchronized(notify){
    284 			success = status;
    285 			notify.notify();
    286 		}
    287 	}
    288 
    289 	public boolean Save(byte[] state) {
    290 		sendEvent(DO_SAVE, 0, 0, null);
    291 		
    292 		savegame = null;
    293 		if(waitForUI() && (savegame != null) && (savegame.length() > 0)){
    294 			saveGame(savegame, state);
    295 			scr.Print("Saved game as '"+savegame+"'\n");
    296 		}
    297 		return true;
    298 	}
    299 
    300 	public byte[] Restore() {
    301 		selection = -1;
    302 		sendEvent(DO_RESTORE, 0, 0, null);
    303 		if(waitForUI() && (selection != -1)){
    304 			return getDataStore().getRecordData(selection);
    305 		} else {
    306 			return null;
    307 		}
    308 	}
    309 
    310 	public void show() {
    311 		super.show();
    312 		if(!scr.running){
    313 			scr.running = true;
    314 			(new Thread(scr,"ZMachine")).start();
    315 		}
    316 	}
    317 
    318 	public void Transcript(char data[], int off, int len) {
    319 		transcript.append(data, off, len);
    320 	}
    321 	
    322 	StringBuffer transcript = new StringBuffer(8192);
    323 	
    324 	final static int DO_RESTORE = 1;
    325 	final static int DO_SAVE = 2;
    326 	
    327 	Object notify = new Object();	
    328 
    329 	Font font;
    330 	ZDanger scr;
    331 	ZRuntime app;
    332 	Window notepad;
    333 	ResourceDatabase rdb;
    334 	int w,h;
    335 	int CW, CH, CA;
    336 	byte screen[];
    337 
    338 }
    339