«Специалист» на Java

Обсуждение советского компьютера Фахiвець / Специалист и его развитие

Moderator: Lavr

User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

«Специалист» на Java

Post by Lavr »

Эмулятор «Специалист» на Java

В принципе его как такового не было... :wink: И его так бы и не было, если бы я его не написал. 8)

[spoiler=Код вставки Java-эмулятора в HTML-документ]

Code: Select all

<applet code="Spec1987.class" width="432" height="304" align="Center" archive="http://sgu-wap.narod.ru/SP_MX/SPECOLD/Spec.jar">
 <param name="borderWidth" value="24">
 <param name="sleepHack" value="5">
 <param name="showStats" value="No"><!-- -->
 <param name="snapshot" value="SABOTEUR.RKS"><!--  -->
<p>Sorry, this browser is not Java(tm) enabled.</p>
<p>It either cannot run Java(tm) applets, or the running of applets is currently
disabled in your browser.</p>
</applet>

Code: Select all

RESET SPECIALIST - PAUSE(BREAK)
SELECT FILE FROM URL - ALT+F1
(ВВЕСТИ ИМЯ ФАЙЛА:)
	 BABNIK.RKS
	 DOWNEART.RKS	
	 DUNGEON.RKS	
	 JET-SET.RKS	
	 MARS2.RKS	
	 PANGO.RKS	
	 PEREGON2.RKS	
	 SABOTEUR.RKS	
	 ZOOPARK.RKS
	 REDGRAF.RKS	 
И СПЕЦИАЛЬНО ДЛЯ ШУРИКА:
	 FORTH.RKS	
LOAD FILE FROM URL - ENTER
CANCELL - ESC
If loaded program don't start itself, use G0000 [Enter] 
REDGRAF.RKS = BASIC + GRAPH EDIT use G2000 [Enter]    
[/spoiler]Исходники доступны ЗДЕСЬ.

К действию меня сподвиг вот этот довольно давно существующий проект:
Jasper - ZX Spectrum Emulator by Adam Davidson & Andrew Pollard
http://www.liaquay.co.uk/spectrum/index.html

Image

Джентельмены Adam Davidson & Andrew Pollard люди не жадные и исходников
своих не прятали. Исходники и сейчас доступны здесь:
The source code is available online from http://www.odie.demon.co.uk/spectrum/jasp1_1j.zip.
The AMDProgressBar class was written by Adam Doppelt.
(специально проверил).
Исходники весьма понятны и очень мне помогли при эмуяции ZX Spectrum на
платформе J2M сотовых телефонов.

Задача очень культурно и неглупо разбита на классы:
Z80.class - эмуляция процессора;
Spectrum.class - эмуляция ZX Spectrum;
Jasper.class - интерфейс с браузером и др.;
AMDProgressBar.class - полоска внизу, позволяет регулировать скорость
эмуляции и др., в принципе без неё можно обойтись, поправив коды.

Код HTML совершенно прост:
[spoiler=Код HTML]

Code: Select all

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0046)http://www.spectrum.lovely.net/ --><HTML><HEAD><TITLE>ZX Spectrum Emulator</TITLE>
<META content="text/html; charset=windows-1251" http-equiv=Content-Type>
<META content="MSHTML 5.00.2614.3500" name=GENERATOR></HEAD>
<BODY bgColor=black link=red text=yellow vLink=lightgreen>
<CENTER>
<P><IMG alt="Coloured Line" src="ZX_Spectrum.files/linerain.gif"></P></CENTER>
<CENTER>
<H1>«Специалист» Emulator</H1>
<CENTER>
<P><IMG alt="Coloured Line" src="ZX_Spectrum.files/linerain.gif"></P></CENTER>
<CENTER>
<TABLE>
  <TBODY>
  <TR>
    <TD>
      <TABLE border=1>
        <TBODY>
        <TR>
          <TD><APPLET code=Jasper.class height=256 width=384>
          <PARAM NAME="snapshot" VALUE="DTE">
          <PARAM NAME="sleepHack" VALUE="5">
          <PARAM NAME="code" VALUE="Jasper.class">
          <PARAM NAME="height" VALUE="256">
          <PARAM NAME="width" VALUE="384">
                                       <p>Sorry, this browser is not Java(tm)
            enabled.</p><p>It either            cannot run Java(tm) applets, or
            the running of applets is currently            disabled in your
            browser.</p></APPLET> </TD></TR></TBODY></TABLE>
    <TD align=left vAlign=top><PRE><B>  Down To Earth</B>

 Left   Q,E,T,U,O
 Right  W,R,Y,I,P
 Jump   SPACE
</PRE></TD></TR></TBODY></TABLE></CENTER>
<CENTER>
<P><IMG alt="Coloured Line" src="ZX_Spectrum.files/linerain.gif"></P></CENTER>
</BODY></HTML>
[/spoiler]
И у меня всё это запросто работало под IE 5.0 без всяких претензий и с
тройным запасом по скорости.
Этого никак не скажешь о сегодняшних эмуляторах на JS:
http://code.google.com/p/radio86/
и вдохновляющий прототип:
http://jsspeccy.zxdemo.org/
И броузеры - им не броузеры, и скорости эмуляции как у спринтерских черепах...

Поскольку «Специалист» по идеологии очень близок к «ZX Spectrum», мне
хотелось написать его эмулятор самому. По моим прикидкам это всё вполне
осуществимо на основе имеющихся исходников.

Image

Если Ленин хотел реорганизовать рабкрин, то здесь придётся в основном
реорганизовать экран и карту памяти. :wink:

Вижу я, что всё по жизни сам не успеешь - возможно кому-то этот проект
будет интересен.

PS. Идеи глупо держать под подушкой, там они гниют и тухнут.
Хороший слоган!: http://easy-coding.blogspot.com/
Поэтому, кому надо - вот исходники «Специалиста» на Java.
Last edited by Lavr on 03 Feb 2013 08:09, edited 19 times in total.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Adam Davidson & Andrew Pollard wrote:

Code: Select all

E MODE             TAB
CAPS SHIFT         CONTROL
SYMBOL SHIFT       ALT,META
Интересно, что события клавиш-модификаторов ALT, CONTROL, SHIFT не поступают в окно Java-апплета... никак...:-?

Code: Select all

public final boolean doKey( boolean down, int ascii, int mods )
  { //---------- вызывается  handleEvent      ascii - код
    //----------                                         mods - модификатор
    //----------                               клавиши - модификаторы:
    boolean  CAPS = ((mods & Event.CTRL_MASK) != 0); //- Была нажата клавиша <Ctrl>
    boolean  SYMB = ((mods & Event.META_MASK) != 0); //- Была нажата мета-клавиша <Alt> Meta key
    boolean SHIFT = ((mods & Event.SHIFT_MASK)!= 0); //- Была нажата клавиша <Shift>
       showMessage( "mods :" + mods);
Ага... вот и люди тоже жалуются...
The trouble is, i cant get Mozilla to detect the Shift key at all. Im using: if (e.modifiers & Event.SHIFT_MASK) { } To detect it, and its not working. ...
http://forums.devarticles.com/javascrip ... -3044.html
User avatar
Shaos
Admin
Posts: 24008
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Lavr wrote:Напомните, куда в обычной Java идёт вывод:

Code: Select all

System.out.println(" Execute on 3.5 Mhz!"); 
только в отладчик чтоль?
В J2ME я этот вывод юзал для контроля параметров в отладке, а сейчас приходится заменять на:

Code: Select all

showStatus(" Execute on 3.5 Mhz!");
- вывод в статусную строку...
угу - стандартный поток вывода в апплете никуда не идёт, если в браузере апплет запущен - так что только showStatus...

по поводу клавиш-модификаторов - на то они и клавиши модификаторы, чтобы поступать ВМЕСТЕ с основной клавишей :)

и потом ты ссылаешься на форум по JavaScript - это несколько другое

приведи полный кусок кода - что ты пытаешься сделать, а то я с ходу не врубаюсь что за doKey у тебя такой
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos wrote:и потом ты ссылаешься на форум по JavaScript - это несколько другое
приведи полный кусок кода - что ты пытаешься сделать, а то я с ходу не врубаюсь что за doKey у тебя такой

Code: Select all

public boolean handleEvent( Event e ) {
...
 switch( e.id ){
                case Event.MOUSE_DOWN:
                     canvas.requestFocus();
                     return true;

                case Event.KEY_ACTION:

          //--- событие клавиатуры - КЛАВИША_НАЖАТА_
                case Event.KEY_PRESS:
//--- отладка ---------
//---                 char se = (char)e.key; //---
//---                String s = "Key PRESSed < "+ e.key +" >";
//---                showMessage( s );
//--- отладка ---------     doKey - вызываем отсюда...
                     return doKey( true, e.key, e.modifiers ); //--- пересчет клавиатуры в матрицу---

                case Event.KEY_ACTION_RELEASE:

          //--- событие клавиатуры - КЛАВИША_ОТПУЩЕНА_
                case Event.KEY_RELEASE:
//---------------------     doKey - вызываем отсюда...
                     return doKey( false, e.key, e.modifiers );//--- пересчет клавиатуры в матрицу---

                case Event.GOT_FOCUS:

                case Event.LOST_FOCUS:
                     resetKeyboard();
                     return true;
                    }
    return false;
  }

}
А вот тут уже:

Code: Select all

//--- пересчет клавиатуры в матрицу---
public final boolean doKey( boolean down, int ascii, int mods ) 
  { //---------- вызывается  handleEvent      ascii - код 
    //----------                                         mods - модификатор 
    //----------                               клавиши - модификаторы: 
    boolean  CAPS = ((mods & Event.CTRL_MASK) != 0); //- Была нажата клавиша <Ctrl> 
    boolean  SYMB = ((mods & Event.META_MASK) != 0); //- Была нажата мета-клавиша <Alt> Meta key 
    boolean SHIFT = ((mods & Event.SHIFT_MASK)!= 0); //- Была нажата клавиша <Shift> 
       showMessage( "mods :" + mods);
//---  Дальше неинтересно, т.к.int mods всегда = 0
showMessage( - это вывод в панельку апплета AMDProgressBar

Вот и у мужика код типичный:

Code: Select all

if (e.modifiers & Event.SHIFT_MASK) { } 
хотя и JavaScript, но сути это не меняет...
The trouble is, i cant get Mozilla to detect the Shift key at all.
Но "эффект" одинаков и в Опере и в ИЕ...

PS. Это вобщем-то непринципиально, но не даёт мне потестить прицепленный к "Спектруму" ВВ55 через randomise usr XXXXXX, где XXXXX - моя подпрограмма...
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

И кстати говоря, компилятор у меня ругается на метод handleEvent( Event e ) как на устаревший (Deprecated).
Решил поискать, на что же его заменили... Нет - так и советуют юзать его... :-?
Исполняющая система Java передает информацию о событии компоненте используя ее метод handleEvent() . Корректная форма для описания метода handleEvent() будет иметь следующий вид

Code: Select all

public boolean handleEvent(Event e)
http://www.javable.com/javaworld/08_96/01/
Java и обработка событий

С другой стороны в документе Deprecated List (Java 2 Platform SE v1.4.2) написано:
java.awt.Component.handleEvent(Event)
As of JDK version 1.1 replaced by processEvent(AWTEvent).
Но processEvent(AWTEvent) компилятор навовсе не хочет хавать никак, вываливаясь с ошибкой...
Чевойт, мне кажецца компиллер меня в заблуждение вводит неподецки... это ж не одно и то же... :(
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos, похоже на потерю фокуса ввода Канвасом из-за браузера.
Переписал тест клавиш вот так:

Code: Select all

//--- отладка ---------
                 char se = (char)e.key; //---
                String s = "Key PRESSed < "+ e.key +" >"+ String.valueOf(e.modifiers);
               showMessage( s );
//--- отладка ---------     doKey - вызываем отсюда...
Модификаторы отражаются как 1, 2 и 8... но порой пропадают... Не пойму закономерности.

PS. Похоже вот на что: нажимаю Alt + [Key]... Нажатый Alt, ещё без [Key] браузер считает относящимся к нему,
а когда нажат [Key] - то фокус ввода уже у браузера и апплет Alt + [Key] не получает...
Хотя когда получает - пауза чтоль короче между Alt и [Key]... не понял пока...


//------------------------------------------------------------------------------------
Shaos wrote:стандартный поток вывода в апплете никуда не идёт, если в браузере апплет запущен
Я в принципе догадался... но смутила меня книга Фролова "Программирование на Java":
Исходный текст приложения HelloJava

Исходный текст нашего первого приложения состоит всего из нескольких строк:

Code: Select all

public class HelloJava 
{
  public static void main(String args[]) 
  {
    System.out.println("Hello, Java!");
  }
}
По своей простоте он не уступает известной программе "Hello, world!", с которой обычно начинают изучение языка программирования C.
Бедняжки начинающие программёры ничего не увидят? :lol:
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos wrote:поставь печать на case Event.KEY_ACTION - может они туда летят как отдельные кнопки
Так обработчик-то на эти события один и тот-же. Он модификаторы печатает, когда они приходят.

Code: Select all

                case Event.KEY_ACTION:
          //--- событие клавиатуры - КЛАВИША_НАЖАТА_
                case Event.KEY_PRESS:
//--- отладка ---------
                 char se = (char)e.key; //---
                String s = "Key PRESSed < "+ e.key +" >"+ String.valueOf(e.modifiers);
               showMessage( s );
//--- отладка ---------     doKey - вызываем отсюда...
                  return doKey(true, e.key, e.modifiers ); //--- пересчет клавиатуры в матрицу--- 
Shaos wrote:я же говорил, они сами по себе не приходят, только с другой "нормальной" кнопкой
Так, собственно, и отслеживал, как видно по коду.
Подозреваю, что фокус ввода отслеживает и броузер как раз по модификаторам...
Очень похоже на правду т.к. если не нажать [Key], а Alt - отпустить, браузер ставит фокус в строку меню, а в строке статуса пишет сообщение "Команды работы с выделенными объектами".
Фокус ввода можно вернуть в апплет только мышью. Похоже браузер приоритетно отслеживает свои горячие клавиши...
Неприятный эффект. Ввести чтоль индикатор потери фокуса ввода в апплет...
Но тест эмуляции ВВ55 заставил работать.
Теперь свои ошибки надо выловить...
User avatar
Shaos
Admin
Posts: 24008
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

а - видимо специальные коды для винды (или приложения) перехватываются системой
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Гибрид "Специалист"-"ZX-Spectrum"

Post by Lavr »

"Специ-Spectrum" :D

Вот такой гибрид "Специалист"-а и "ZX-Spectrum"-а у меня сейчас работает
при отладке эмуляции параллельного порта 580ВВ55.

Image

"ZX-Spectrum" стартует по "Spectrum"овски, после чего командой
randomize usr 49152 (-> 0C000H) управление передаётся
на старт Монитора "Специалист"-а.
Порты при отладке выводятся в служебную строку .

Image

Текстовая панель сверху отображает дополнительную информацию по вводу-выводу.
В Мониторе "Специалист"-а перехвачена функция вывода на экран - 0C037H и
перенаправлена в ПЗУ "ZX-Spectrum"-а (RST 10H),

Code: Select all

  ORG  0C037h

  PUSH PSW
  MVI  A,02h
  CALL 1601h
  MOV  A,C
  CPI  20H
  JC   MT1
MT0:
  RST  10h
  POP  PSW
  RET
MT1:   CPI  0DH
  JZ   MT0
  POP  PSW
  RET
  END
так что отладка параллельного порта 580ВВ55 пойдёт при выводе контекста "Специалист"-а
на экран "ZX-Spectrum"-а функциями "ZX-Spectrum"-а, если всё склеится корректно... :wink:

PS. Неприятная матрица у "Специалиста" для эмуляции :( - либо русские символы
на месте, тогда английские не там, либо наоборот. Для игр более важнО взаимное
расположение клавиш...
:-?
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

"Специ-Spectrum"

Post by Lavr »

Всё "склеилось" корректно и на удивление заработало: :roll:

Image

Пришлось подправить патч Монитора "Специалист"-а по имитации функции вывода на экран - 0C037H:

Code: Select all

  ORG  0C037H

  PUSH PSW
  MOV  A,C
  CPI  20H
  JC   MT1
  CPI  7FH
  JNC  MT1
MT0:
  RST  10H
  POP  PSW
  RET
MT1:
  CPI 0DH
  JZ  MT0
  POP PSW
  RET

  END
Настройку канала экрана вынес на адрес 0C000H:

Code: Select all

  MVI  A,02h 
  CALL 1601h
Это достаточно сделать 1 раз.

Может HardWareMan знает зачем в функции 0C818H (вывод строки до 00H) каждый
символ сопровождают кодами 7FH, 08H? 08H - ещё куда ни шло, но что делает 7FH - не знаю.
"ZX-Spectrum" понимает этот код как "(с)"
Также вычистил русские символы сообщений Монитора - "ZX-Spectrum" их не любит...
Прикольный гибрид... :wink: я думал по жизни сделать "Специалист" с имитацией
экрана "ZX-Spectrum" и переключением с экраном "Специалист"-а, но... :(

Над отладкой порта ВВ55 работаю...
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

HardWareMan wrote:А код 7FH у Спеца - это забой (клавиша над ВК). Забой ксорит знакоместо на цвет экрана. Таким образом, получаем белые буквы на черном фоне или наоборот. Так как забой - это символ, нужно делать возврат каретки - 08H.
Понятно, только если быть точным, ты, вероятно, имел ввиду 08H - "курсор на 1 позицию влево"?
Поскольку "возврат каретки" - термин устоявшийся, и обозначает конкретно 0DH.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

А как под JAVA узнать раскладку клаваиатуры пользователя? Чтоб не получилось двух переключателей "РУС/ЛАТ" в апплете и браузере...
Один метод в Инете я нашел, но что-то это несколько не то, мне кажется, да и крупноват по сравнению с ВИН-АПИ, скажем:

Code: Select all

//--- Индикатор раскладки клавиатуры
//--- http://forum.sources.ru/index.php?showtopic=207232

import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.WeakHashMap;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class JInputLocaleIndicator extends JLabel {

    private static class MonitoringThread extends Thread {

        private static final long REFRESH_TIMEOUT = 1000L;

        public MonitoringThread() {
            setPriority(NORM_PRIORITY);
            setDaemon(true);
        }

        public void run() {
            while (!interrupted()) {
                synchronized (indicatorLists) {
                    for (Map.Entry<Window, List<JLabel>> entry : indicatorLists.entrySet()) {
                        Locale locale = entry.getKey().getInputContext().getLocale();
                        for (JLabel label : entry.getValue()) {
                            label.setText(locale.getLanguage());
                            label.setToolTipText(locale.getDisplayLanguage());
                        }
                    }
                }

                try {
                    Thread.sleep(REFRESH_TIMEOUT);
                }
                catch (InterruptedException thrown) {
                    break;
                }
            }
        }

    }

    private static Map<Window, List<JLabel>> indicatorLists = new WeakHashMap<Window, List<JLabel>>();

    static {
        MonitoringThread monitoringThread = new MonitoringThread();
        monitoringThread.start();
    }

    public JInputLocaleIndicator() {
        addHierarchyListener(
            new HierarchyListener() {
                public void hierarchyChanged(HierarchyEvent event) {
                    if ((event.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
                        Window window = SwingUtilities.getWindowAncestor(JInputLocaleIndicator.this);

                        synchronized (indicatorLists) {
                            List<JLabel> indicators = indicatorLists.get(window);

                            if (isDisplayable()) {
                                if (indicators == null) {
                                    indicatorLists.put(window, indicators = new ArrayList<JLabel>());
                                }

                                indicators.add(JInputLocaleIndicator.this);
                            }
                            else {
                                if (indicators != null) {
                                    indicators.remove(JInputLocaleIndicator.this);
                                }
                            }
                        }
                    }
                }
            }
        );
    }

    public static void main(String... args) {
        JFrame frame = new JFrame();
        JInputLocaleIndicator indicator = new JInputLocaleIndicator();

        frame.setLayout(
            new GridBagLayout()
        );

        frame.add(indicator);
        frame.setSize(512, 384);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}
User avatar
Shaos
Admin
Posts: 24008
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

там суть в двух строчках - они просто проверяют текущий язык в поле ввода
у тебя это не будет работать как надо во всех случаях, т.к. например запускающий твой эмуль может вообще не иметь русской раскладки, а скажем иметь японскую - и что, теперь ему нельзя русские буквы в эмуль вводить?
просто принимай коды клавиш и сам их транслируй в русский язык по состоянию некоего флага, который меняется по нажатию некоторой кнопки
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Shaos wrote:запускающий твой эмуль может вообще не иметь русской раскладки, а скажем иметь японскую - и что, теперь ему нельзя русские буквы в эмуль вводить?
просто принимай коды клавиш и сам их транслируй в русский язык по состоянию некоего флага, который меняется по нажатию некоторой кнопки
Это понятно, только отслеживать я хочу "английскую" и "неанглийскую". Шевцов у себя
хорошо учёл в эмуляторе, что либо русские символы на месте, тогда английские не там,
либо наоборот. Для игр более важнО взаимное расположение клавиш...
Если два переключения "РУС/ЛАТ" в компьютере и эмуляторе - это приводит к неприятным
эффектам...
Поэтому хотелось отследить переключение. Ну в принципе это действительно можно
отслеживать по кодам символов, только java, мне помнится, работает в Уникоде...
Это затруднит обработку нац.символов. Я отслежу русские, а другие - не отследятся.
В "Спектруме" - хорошо, отслеживают только первые 127 символов.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

JX-Speccy со звуком

Post by Lavr »

Джентльмены, если вас конечно не затруднит - протестируйте вот здесь
он-лайн версию JX-Speccy со звуком на повод качества звука:

http://www.gameszoo.net/jxspeccy/?mn=examples

У меня звук прерывистый и отвратительный, но может это из-за низкой
тактовой ноутбука? Если звук и у вас отвратителен - он отключается
тычком мыши в экранчик JX-Speccy и нажатием F9.

Заинтересовало - пока я 580ВВ55 эмулирую, может сразу звук приделать,
раз уж исходники там не жадничают...