Copy Link
Add to Bookmark
Report

OVERSCAN.S

atari's profile picture
Published in 
atari
 · 29 Nov 2020

Wir zeigten Ihnen inAusgabe5/89desST-Magazins,wie man mit Hilfe eines einfachen Umschalters, zweier Dioden, zwei Widerständen, einem Transistor und einem Pufferkondensator, die zusammen nicht mehr als 3 DM kosten oder noch in derBastelkiste vorhanden sind, dem Atari einen 67024 Bytes ( 59640 Bytesdavon sichtbar; Angabe gilt für den Farbmodus ) großen Bildschirmspeicherbeschert.

Das bedeutet: Im Low-Resolution-Mode stehen jetzt 420 * 284 Punkte bei weiterhin 16 Farben pro Punkt und im Mid-Res-Mode sogar 840 * 284 Punkte mit 4 Farben pro Punkt zur VerfÅgung.(Neue Hardwareauflîsung; kann durch unsere Software an die MonitorverhÑltnisse angepasst werden) Im Monochromen Modus gibt der ST durch unsere Modifikation nun 800*500 Pixel aus, von denen der SM 124 ohne Umbau allerdings nur rund 688*480 Pixel anzeigen kann. Deshalb beschrÑnkt unsere Software die Grîûe des Screens auf diese kleinere Auflîsung(einstellbar ab Hyperscreen.PRG Version 1.5).

Man hat damit nun nicht mehr nur ein Bildschirmfenster, sondern ein ausgefÅlltes Bild ohne stîrenden Rand auf einem Fersehschirm oder Farbmonitorund auf dem SM 124 ein deutlich grîûeres "Arbeitsfenster". Beim Amiga, der das schon von Hause aus durch seine Hardware kann, nennt man diesen Modus: "Hyperscreen".

Der Atari kann nun also auch bildfÅllend Pixelgrafik darstellen, so daû man ihn jetzt auch professionell im Desktop-Video-Bereich, z.B. zusammen mit einem Genlock-Interface einsetzen kann, um vielleicht am unteren Rand eines Videobildes noch einen Scrolltext einzublenden, der dann aber wirklich vom rechten bis zum linken Rand der Bildrîhre durchlÑuft und nicht wie sonst immer nur im Bildschirmfenster des Ataris erscheint.

Der Farb-Grafik-Aufbau eines ST-Video-Bildesim 50 Hertz-Mode sieht folgendermaûen aus:
Das ST-Video-Bild besteht aus 313 Zeilen, die 50 mal in der Sekunde geschrieben werden.
Es wird ohne Zeilensprungverfahren (Interlace; Fachbegriff aus der Fernsehtechnik fÅr HalbbildverkÑmmung) gearbeitet; zwei Halbilder liegen alsogenau aufeinander. Die ersten 39 Bildzeilen werden vom Atari normalerweiseohne Pixelgrafik, nur mit der Hintergrundfarbe (Farbpalette 0) dargestellt.
Danach kommen dann 200 Bildzeilen, wo jede Zeile links am Rand mit der Hintergrundfarbe beginnt, dann in der Mitte die Pixelgrafik (320 oder 640 Pixel, je nach Mode) anzeigt wird und am rechten Rand wieder mit der Hintergrundfarbe aufhîrt.
Die darauffolgenden 45 Zeilen, die den unteren Rand darstellen, werden normalerweise wieder ohne Pixelgafik, nur mit der Hintergrundfarbe dargestellt.
Das ergibt dann das typische grÅne Desktop-Bild mit dem weiûen Rand (Rahmen), wenn ohne Accessories und Desktop-Info eingeschaltet wird.
Der weiûe Rand (Rahmen) ist dabei die Hintergrundfarbe (Farbpalettenregister 0).
Die letzten 29 Zeilen von den 313 Zeilen werden durch das von dem Glue- Baustein erzeugtem "Blank"-Signal dunkel ausgetastet. ÄSie stellen also das vertikale Austastsignal dar (vertikale AustastlÅcke) und sind somit nicht auf dem Fernseher oder Monitor sichtbar.

Dies hattendie TEX-Leute auchschon inihremArtikelimST-Magazin beschrieben.Sieschalteten auch den rechten Rand ab, um dort Pixelgrafik darzustellen, so trieb es die TNT-Crew noch ein StÅck weiter und prÑsentierte auch den linken Rand mit Pixelgrafik!!!

Wow!, dachte ich mir, wenn die Jungs es schaffen, den Atari per Software so zu Åberlisten, etwas darzustellen, was hardwaremÑûig eigentlich gar nicht vorgesehen ist, dann mÅûte das doch auch durch einen kleinen Hardwareeingriff(-umbau) mîglich sein, ohne daû dafÅr komplizierte und zeitraubende Interrupt- und VideoadreûzÑhlersynchronisierung wie bei der Softwareversion notwendig ist!
Auûerdem wollte ich auch mal wissen, was fÅr interne Signale durch diese neuen Demoprogramme verÑndert werden, wie also die Hardware durch die Software ausgetrickst wird!

Gesagt, getan!

Nur mit einem Schaltplan vom ST und einem Osziloskop bewaffnet und mit Hilfe derneuen Demos durchforstete ich mit dem Tastkopf erst einmal die Shiftergegend und stellte auf einmal fest, daû sich z.B. beim Hin- und Herschaltendes Amigademos zwischen "Hyperscreenmode" und Normal-Mode das DE (Display-Enable)-Signal Ñnderte.

Das muûte es sein!

Das Display Enable Signal ist also zustÑndig fÅr das Darstellen von Pixelgrafik in einer Video- (Display-)Zeile.
Immer wenn es auf "High" steht wird Pixelgrafik vom Shifter ausgegeben, geht es auf "Low", dann wird nur noch die Hintergrundfarbe dargestellt.

Die TEX- und TNT-Programmierer hatten es also geschafft, das High-Low (Puls-Pausen-)VerhÑltnis von diesem Signal zu Ñndern, so daû in jeder Videozeile das DE-Signal lÑnger und schon eher(LT-PRG) auf High steht, so daû jede Zeile mehr Pixelgrafik als die normalen 320 bzw. 640 Pixel ausgibt.

Das Display-Enable Signal wird, wie auch die anderen zum Fersehbildaufbau benîtigten Signale (Blank, HSync, VSync), vom Kleisterbaustein (GLUE) erzeugt.
Es geht vom GLUE aus gleichzeitig zur MMU, zum Shifter und zum Timer B-Eingang vom MFP-Baustein (zum ZÑhlen der Zeilen durch Interrupt).

Der Bildaufbau im Farbmodus bei 50 Hz spielt sich folgendermaûen ab :

Mit dem vertikalen Synchron-Signal, das vom Glue nicht nur an die Monitorbuchse, sondern auch an die MMU geht, wird an die interne ZÑhlerkette inder MMU die Anfangsadresse des Bildschirmspeichers im Ram fÅrs nÑchsteHalbbild (313 Zeilen) Åbergeben(Aus den + Adressen FF8201 und FF8203geholt).
Wird das Display-Enable Signal jetzt High, so wird dadurch in der MMU das DCYC(Display-Cycle-Clock) Signal wirksam, das aus dem Ram die ÄVideodisplay-Informationen (Pixelgrafik) immer 16 bitweise in den Shifter transferiert (clocked). (öber den Load-Eingang des Shifters) Dabei wird die ZÑhlerkette in der MMU immer weiter hoch gezÑhlt.(wird im Video- Adreû-ZÑhler FF8205/07/09 registriert) Bleibt das Display_Enable Signal jetzt lÑnger high, dann wird insgesammt auch mehr Speicher von der MMU als Bildschirmspeicher adressiert und in den Shifter als Pixelgrafik-Display Åbergeben.
Das CMPCS-Signal (Color map chip select), das auch von der MMU generiert wird und zum Shifter an den CS(Chip Select)-Eingang gefÅhrt wird, Ñndert sich Åbrigens nur, wenn die Farbpalettenregister im Shifter mit neuen Werten geladen werden sollen.
Schlieûlich tastet das vom GLUE generierte BLANK-Signal das vom RGB-Widerstands-D/A-Netzwerk kommende Farbsignal in den horizontalen RÅcklÑufen jeder Zeile und in den ganzen 29 Zeilen des vertikalen Bildsynchronimpulses aus (dunkel).

Die softwaremÑûigen Tricks arbeiten nun so, daû durch interruptgesteuerte Umschaltung der Bildfrequenz in bestimmten Fernsehzeilen, das vom GLUE erzeugte DE-Signal lÑnger auf "high" in einer Zeile steht. Dieses Ergebnis kann man natÅrlich auch dadurch erreichen, daû man statt dem DE-Signal ein anderes Signal zur MMU und zum Shifter fÅhrt und zwar solch ein Signal, daû bereits das geeignete Puls-Pausen-VerhÑltnis besitzt. Dann braucht man nicht mehr die rechenzeitintensiven Synchronisationstricks per Software und man kann sogar mit der neuen Hyperscreen-Auflîsungunter GEM arbeiten!

Nun muûte nur noch ein entsprechendes Signal im Rechner gefunden werden, daû ein geeignetes Puls-Pausen-VerhÑltnis aufwies, um es als neues DE-Signal verwendet werden zu kînnen.

Ich durchtrennte also auf der Rechnerplatine die Verbindung, die die MMU und den Shifter mit dem normalen DE-Signal versorgt (siehe Bilder 1,2 und 6) und legte an diese alten DE-EingÑnge(Pin 52 der MMU und Pin 37 des Shifters) erst einmal nur "high"-Pegel (+5 Volt).

Es klappte tatsÑchlich!

Nach dem Einschalten des Rechners sah man im oberen Teil des Bildschirms, ungefÑhr bis zur HÑlfte des Bildschirms wild verteilte bunte Pixels von links nach rechts herÅber, jetzt aber ohne stîrenden Rand.

Im unteren Bereich aber erschienen merkwÅrdige sechszehner Pixelgruppen, die dauernd ihre Farben wechselten.
Ich dachte erst, dieser untere Bereich wÅrde fehlerhaft dargestellt, bis mich dann Karsten auf die Idee brachte, das kînnten doch die Datenbus~ signale seien!Richtig!
Der 1 MByte ST plaziert ja beim Einschalten seinen Bildschirmspeicher ganz am oberen Ende des Speicherraums.
Mit dem Umbau braucht er nun ja mehr Bildschirm- Speicher zum Auslesen, da am oberen Ende aber nur 32 KBytes vorhanden sind, werden nach diesen 32 KBytes nur noch undefinierte Datenbussignale auf dem Monitor ausgegeben.

Na also: Nach Herunterlegen der Bildschirm-Speicher-Anfangs-Adresse in den Speicherzellen FF8201 und FF8203 war von diesen wild umhertanzenden ÄDatenbussignalen nichts mehr zu sehen und der ganze Bildschirm war nun mit Pixelgrafik gefÅllt!!!

Allerdings konnte man natÅrlich nicht mehr das Desktop sehen, da mit der neuen Bildschirmspeicheranordnung nicht mehr dieselben Pixels wie vorher Åbereinanderlagen und darum also nur bunte Pixels Åber den ganzen Bildschirm verteilt zu erkennen waren. (durch andere Aufteilung der Bitplanes)
Wir versuchten daher erst einmal das alte RAM_TOS von 1985 zu patchen, um wieder unter GEM jetzt mit Hyperscreen zu arbeiten.
FÅr die Anpassung des GEMs auf der alten Ram-TOS Diskette gab es dann aber eine Schwierigkeit: die einzelnen Fersehzeilen durften nur maximal 255 Bytes Bildschirmspeicher besitzen und die Anzahl der Bytes muûte durch 4 teilbar sein, damit man das verÑnderte GEM in den beiden Auflîsungen der Farbmodi installieren konnte. (Die BeschrÑnkung auf die 255 Bytes pro Zeile gilt Åbrigens fÅr das neue TOS 1.4 nicht mehr!)

Da dies mit der simplen Lîsung des einfach auf "high" legen der beiden EingÑnge nicht zutrifft und dadurch auch im horizontalen ZeilenrÅcklauf zuviele Pixels ausgegeben wurden, die man aber durch das Austasten des Blank-Signals gar nicht auf dem Monitor sah (Speicherplatzverschwendung), muûte also ein besseres Signal gefunden werden!
Nach Experimentieren mit dem HSync-Signal (kein einwandfreier 60 Hz- Betrieb mîglich), dem Blank-Signal (es bleibt noch ein kleiner linker Rand sichtbar, 60 Hertz mit "zerfranstem" linken Rand) und dem VSync-Signal (zuviele Bytes im ZeilenrÅcklauf = Speicherplatzverschwendung), wurde schlieûlich das gemischte Synchronsignal ( Composite Sync, das aus einer UND-VerknÅpfung von HSync und VSync besteht) gefunden, das die Anforderungen erfÅllt.

Leider kann es nur auf die beiden oben besprochenen EingÑnge (alte DE-EingÑnge von Shifter und MMU) gelegt werden. Legt man das Synchronsignal auch auf den Timer B-Eingang vom MFP 68901 (Pin 20), wo das normale DE-Signal auch anliegt, dann kann der ST nicht mehr nach einem Reset oder nach dem Einschalten booten.
Das liegt wahrscheinlich an den Initialisierungsroutinen im Rom-Tos, da der ST beim Starten auf 60 Hz anfÑngt und dann vielleicht zuviele Interrupts Åber den Timer B bekommt.
Das stîrt aber auch nicht weiter, denn man kann ja auch durch den HBL- Interrupt die Zeilen zÑhlen, um z.B. nach jeder Zeile die Farbpaletten umzuladen und damit in jeder Zeile 16 neue Farben anzeigen zu kînnen. (FÅr spezielle Farbvideoeffekte)

Der Betrieb des OVERSCAN-Mode

Man kann problemlos wÑhrend des Betriebs des STs zwischen den Modi umschalten, ohne daû der Rechner abstÅrzt. Es kann lediglich ab und zu vorkommen, daû beim Umschalten, bedingt durch Prellen des Schalters, die Farbpaletten verschoben sind. Das lÑût sich aber durch nochmaliges Hin- und Herschalten wieder beheben.
Man muû natÅrlich nach dem Umschalten von Normal-Mode auf Hyperscreen eine entsprechende Software einsetzen, damit man nicht nur "Pixel-MÅll" auf dem Bildschirm sieht (wie schon oben erwÑhnt, liegen die Bitplanes im Hyperscreen-Mode anders Åbereinander ).
ÄDaher hat Karsten das Hyperscreen.PRG geschrieben, das im Auto-Ordner der Harddisk oder Bootdisk steht und beim Hochfahren des Rechners das GEM mit den negativen Line A-Variablen so patcht, daû man auch mit den neuen Auflîsungen mit der gewohnten GEM Shell arbeiten kann.
Es lÑuft allerdings nur mit dem Blitter-ROMTOS, dem neuen ROMTOS 1.4, dem BETA-RAMTOS und dem Developer-RAMTOS 1.4 .
Es funktioniert nicht mit dem alten 1985er ROMTOS!!!

Beim Hochfahren des Rechners kann es manchmal zu Farbpalettenverschiebung kommen. Das tritt aber nur sehr selten auf und auch nur beim Einschalten des Rechners, so daû man dann durch nochmaliges Hin- und Herschalten wieder die richtige Farbpalette einstellen kann. Ist der Rechner erst einmal richtig gestartet, so bringt ihn nichts mehr durcheinander. (Einzige Ausnahme: Hin- und Herschalten zwischen 50 und 60 Hertz mit dem "ChangeHertz.PRG"; man muû sich aber unter OVERSCAN wegen der unterschied~ lichen Bildgrîûen sowieso fÅr eine bestimmte Bildfrequenz im Farbmodus entscheiden und das wird hier in Europa 50 Hertz sein, da man ja etwas auf Video aufnehmen mîchte)

Ab der Version 1.5 vom Hyperscreen.PRG kann man durch DrÅcken der Control Taste beim Hochfahren des Programms in ein InstallationsmenÅ gelangen, bei dem man dann softwaremÑûig, unabhÑngig von der durch den Umbau vor~ gegebenen neuen Hardwareauflîsung, die Auflîsung einstellen und abspeichern kann.
Denn bei einem werksmÑûig eingestellten Fernseher gehen einige von den 284 Zeilen oben und unten als AnzeigeflÑche verloren, da diese schon hinter dem Bildrîhrenrahmen verschwinden und auch in der Breite ist der Fernseher so eingestellt, daû die ganz links und rechts liegenden Punkte nicht mehr zu sehen sind.
Durch das InstallationsmenÅ kann man also die neue Hyperscreen-Bildschirm~ grîûe begrenzen und an seinen eigenen Monitor anpassen, so daû man noch alles sieht oder aber auch den Screen so groû einstellen, daû erst der Bildrîhrenrand die Begrenzung bildet.

Damit besteht aber auch die Mîglichkeit, Objekte von allen Seiten vom Rand der Bildrîhre bis zum gegenÅberliegenden Rand laufen zu lassen, so daû man wirklich ein flÑchenfÅllendes Bild vor sich.
Gerade im Desktop-Video-Bereich sieht das dann richtig professionell aus und nicht mehr nach Home-Computer!

Es kann dadurch aber auch sein, daû Sie die MenÅleiste gar nicht mehr sehen, weil sie jetzt zu weit oben liegt. Keine Angst, sie ist aber trotzdem noch da.
Sie brauchen nur einmal mit der Maus ganz nach oben zu fahren und Sie werden sehen, wie sich die MenÅleistenwindows nach unten aufklappen werden!

Von nun an kann man dann mit einem ganz neuen GefÅhl mit dem grîûeren Desktop arbeiten.

Der Aufbau des Bildschirmspeichers beim Hyperscreen-Mode
in den Farbmodi bei 50 Hertz (neue Hardwareauflîsung,
Ä kann durch das Hyperscreen.PRG verÑndert werden!)

Wie schon oben erwÑhnt, benîtigt der neue Hyperscreen-Bildschirmspeicher im Farbmodus durch die Hardware-Modifizierung 67024 Bytes. Davon sind aller~ dings nur maximal 59640 Bytes sichtbar (also 840*284 oder 420*284 Punkte; Mid- bzw. Low-Resolution-Modus).
Woher kommen nun aber die 7384 Bytes Differenz zwischen dem sichtbaren (beim optimal eingestellten Monitor) und dem wirklich gebrauchten Bildschirm-Speicher ?
Das liegt daran, daû durch das Composite Synchron-Signal in der horizontalen AustastlÅcke noch in jeder Fernsehzeile 26 Bytes dargestellt werden, die aber durch das Blank-Signal ausgetastet werden und damit nicht sichtbar sind.
Das horizontale Austastsignal in dem Composite Synchron-Signal ist nÑmlich kÅrzer als das des Blank-Signals. Folglich werden auch noch im Anfang des RÅcklaufs in jeder Zeile Pixel zum Shifter aus dem RAM Åbertragen. Das stîrt aber weiter nicht, da man sie nicht sieht und diese ca. 7KBytes ja auch nicht unbedingt bei Bildern auf Diskette mit abgespeichert werden mÅssen.
Beim Auslesen und Einschreiben von Daten vom oder in den Bildschirm~ speicher mÅssen dann eben 26 Bytes in jeder Zeile Åbersprungen werden! Wenn es auf diese ÅberschÅssigen ca. 7 kBytes nicht ankommt, kann man aus GeschwindigkeitsgrÅnden diese ja auch mit abspeichern. Das ist von der Software-Seite aus gesehen auch einfacher und auûerdem kann man dort ja noch prima Zusatzinformationen zum Bild speichern, wie z.B. Farbpaletten oder Texthinweise etc.

Eine Fersehzeile besteht im Hyperscreen-Mode bei 50 Hz Bildfrequenz jetzt also aus 236 Bytes. (Bei 60 Hz sind es nur 234 Bytes) 210 Bytes sind sichtbar. Das macht im Midres-Modus 840 Pixel, im Lowres 420 Punkte.
Bei 284 Zeilen sind das dann 284 * 236 Bytes(210 Bytes) = 67024 Bytes (59640 Bytes).

Eine zweite Sache muû auch noch erwÑhnt werden, die bei der Lîsung mit dem Composite-Synchron-Signal noch nicht so ganz perfekt ist:

Da die vertikale AustastlÅcke im Composite Synchron-Signal sehr viel kÅrzer als im Blank-Signal ist, werden auch schon im vertikalen Strahlen~ rÅcklauf Pixel ausgegeben. (die DE-EingÑnge sind dann durch das Composite Synchron-Signal schon wieder auf "high" geschaltet) Diese Pixel sind wiederum durch das Austasten des Blank-Signals nicht sichtbar.
Dadurch ergibt sich aber ein Offset von 5876 Bytes, so daû in den Adressen FF8201 und FF8203 (Bildschirmspeicheranfang) eine, um diese 5876 Bytes verringerte Anfangsadresse, geschrieben werden muû.
Dabei setzt man mit diesen 2 Adressen allerdings den Bildschirmspeicher nur auf eine 256 Bytes genaue Anfangsadresse ( nur High- und Mid-Byte kann im Video.bas-Register gesetzt werden), die Feinpositionierung geschieht dann im Hyperscreen.PRG.

Eine öbersicht Åber die Hyperscreen-Bildschirmspeicher-Aufteilung, wie sie durch das neue Composite-Sync-Signal erzeugt wird, zeigt Bild 7.

ÄMan hÑtte sich allerdings auch mit Hilfe einiger Flip-Flops und ZÑhler~ bausteine ein besseres Signal, als das Composite-Synchron-Signal als neues DE-Signal zusammen setzen kînnen, dann wÑre der Umbau aber gleich viel komplizierter geworden und die Akzeptanz unter den Usern und Programmierern wÑre gesunken.
Denn statt dem Einbau eines einfachen Umschalters, hÑtte nun eine Platine bestÅckt und eingebaut werden mÅssen. Ferner wÑre das auch mit einigen Mehrkosten verbunden gewesen.

Auûerdem sehe ich die Anwendung sowieso eher in solchen erweiterten Programmen, wie z.B. der Cyber-Studio-Serie, die ihre eigenen schnellen Zeichenroutinen besitzen,so daû es nun mit dem CAD-3D-PRG und einem angepaûten Cyberpaint mîglich wÑre, Objekte wie beim Amiga Åber den ganzen Bildschirm fliegen zu lassen.
Mit diesen schon jetzt sehr fÑhigen Programmen, kînnte man dann richtig professionell aussehende Computeranimationen erstellen. (ohne stîrenden Rand)

Hiermit seien also Tom Hudson und Jim Kent aufgerufen, ihre tollen Programme mîglichst schnell an den neuen Hyperscreen-Modus anzupassen.

WÑre dann noch ein Zusatzprogramm vorhanden, das Deltaanimationen kontinuierlich von einer Harddisk in Realtime nachladen und gleichzeitig abspielen wÅrde, dann ist es nicht schwer, sich vorzustellen, was fÅr eindrucksvolle Filme man z.B. mit einer 100 MByte Harddisk realisieren kînnte!
WÑre das Animationsprogramm dann noch Åber Midi-Clock und Song-Position- Pointer mit einem Musiksequenzer (z.B. einem zweiten Atari ST) synchronisierbar, dann stÑnde einer Realtime-Multimedia-Show nichts mehr im Wege.

Hier sollen nun noch ein paar grundsÑtzliche Bemerkungen
Åber den Unterschied von 50 und 60 Hertz Betrieb im neuen Hyperscreen-Modus erfolgen :
Die HardwareÑnderung mit dem Composite-Synchron-Signal lÑût auch einen 60 Hertz Betrieb zu, allerdings keine GEM-SHELL, da 234 Bytes pro Fernsehzei~ le nicht ganzzahlig durch 4 teilbar ist. Man kann sich aber seine eigenen Applikationen programmieren , die dann die Farbpaletten in jeder Zeile richtig setzen und somit z.B. auch ein Konvertierungs-Programm von Hyperscreen-Bildern von 50 auf 60 Hertz schreiben. Im Augenblick ist das Hyperscreen.PRG nur auf 50 Hertz-Betrieb im Farbmodus eingestellt.
Das hat folgenden Grund : Im 60 Hertz Betrieb werden vom Atari im Hyperscreen-
Modus hardwarebedingt nur 238 sichtbare Zeilen dargestellt und 25 Zeilen im BildrÅcklauf ausgetastet. Das ergibt dann die 263 Zeilen fÅr ein Halbbild im NTSC-System (amerikanische Fernsehnorm).
Auûerdem stimmt die dargestellte Bytezahl in einer Fernsehzeile nicht mit dem 50 Hertz-Modus Åberein (statt 236 Bytes nur 234), so daû das Desktop~ bild wegen der dann nicht mehr Åbereinanderliegenden Bitplanes verzerrt dargestellt wÅrde.
éhnlich ist es auch bei dem Farbmalprogramm "Spectrum 512", dessen 60 Hertz-Version mit 50 Hz betrachtet auch nur "Pixel-MÅll" auf den Bild~ schirm bringt.

Die HardwareÑnderung mit dem Composite-Synchron-Signal lÑût bei 60 Hertz Betrieb dann allerdings keine GEM-SHELL zu, da 234 Bytes pro Fernsehzeile nicht ganzzahlig durch 4 teilbar sind. Man kann sich aber seine eigenen Applikationen programmieren , die bei 60 Hertz dann die Farbpaletten in jeder Zeile richtig setzen und kann sich somit z.B. auch ein Konvertierungs-Programm schreiben, das die Hyperscreen-Bilder von 50 auf 60 Hertz umrechnet.

Hier in Europa nehmen ja die Videorecorder auch nur Bilder im 50 Hertz Betrieb auf, so daû fÅr uns eigentlich erst einmal der 50 Hertz Betrieb ausschlaggebend ist.

Allerdings wird sich genau wie beim Amiga, die Situation einstellen , daû Programme in 2 verschiedenen Versionen erscheinen werden, eine "PAL"- und eine "NTSC"- Version.
Im PAL-Mode hat man dann 46 sichtbare Zeilen mehr fÅr die Bilder, muû aber mit der Flimmerei des 50 Hertz-Betriebes kÑmpfen!

Es kann nur gehofft werden, daû sich die europÑischen VorschlÑge des Eureka-High-Definition-TVs nicht durchsetzen werden, beim zukÅnftigen hochauflîsenden Fernsehen auch wieder 50 Hertz-Bildfrequenz einzufÅhren, denn wer schon einmal lÑnger im 50 Hertz-Betrieb im Farbmodus programmiert hat, weiû ein Lied Åber die rechteckigen Augen zu singen.
60 Hertz Bildwechselfrequenz sind einfach viel ruhiger.
Wird aber doch HDTV wieder mit 50 Hertz bei uns eingefÅhrt, so werden sich die zukÅnftigen Farbgrafikcomputer auch wieder daran halten mÅssen,um z.B. Grafikanimationen auf HDTV-Video aufnehmen zu kînnen. So hat man beim Programmieren wieder das Flackern vor den Augen! Da aber eine neue Fernsehnorm bestimmt Åber 20 Jahre bestehen bleibt, kann man nur hoffen, daû das nicht passieren wird! Bei einer einheitlichen Weltfernsehnorm mit 60 Hertz Bildfrequenz kînnte man endlich auch einmal Videocassetten mit Freunden z.B. aus der USA aus~ tauschen, ohne die umstÑndliche und mit immensen Kosten verbundene Normen~ konvertierung.
(was beim Telefon (die einheitliche Norm) geschafft wurde, mÅûte doch auch beim Fernsehen gehen)

Technisch gesehen und ohne finanzielle Mehrkosten ist der 60 Hertz Betrieb auch bei uns in Europa Åberhaupt kein Problem mehr, denn die meisten bestehenden Fernseher lassen sich z.B. Åber die Scart-Buchse als öbergangs~ lîsung auch einwandfrei mit 60 Hertz Bildfrequenz betreiben, wie man es ja mit Hilfe des Ataris ganz leicht zeigen kann! Anscheinend haben das aber die Eureka_HDTV-Freaks noch nicht so ganz mitbekommen.

Hyperscreen- (Hyperscreen-) Betrieb im Monochrome Modus

Wenn man im S/W-Modus bei umgelegtem Hyperscreen-Schalter den Rechner ein~ schaltet, fallen einem sofort zuerst die weiûen RÅcklaufstrahlen des SM 124 Monitors auf, die auûer dem "PixelmÅll" des Datenbusses (siehe oben) auf dem Display zu sehen sind.
Das liegt daran, daû im S/W-Modus der SM124 Monitor kein Blank-Signal Ägeliefert bekommt, so daû der ST sonst normalerweise selber durch ein geeignetes Puls-Pausen-VerhÑltnis des DE-Signals fÅr die dunkle Austastung des RÅcklaufs des Elektronenstrahls sorgt. Weil wir das aber geÑndert haben, sieht man nun aber auch die horizontalen und vertikalen RÅcklaufstrahlen.
Ende September 1988, als wir die erste Farbversion vom Hyperscreen-Modus ent~ wickelten, dachten wir, daû mit dem Composite Sync Signal als DE-Signal Ersatz der S/W-Modus nicht erweitert werden kînne und wir begnÅgten uns mit der Farbversion.
Dann kam mir aber auf einmal Anfang Januar 1989 die Idee, einfach mal den ganzen Bildschirmspeicherbereich auf Hex FF zu setzen: Und siehe da, der ganze Bildschirm war schwarz, es waren auch keine RÅcklaufstrahlen mehr zu sehen!!!
Man konnte also durch auf $FF- Setzen der angezeigten Bytes, die schon im RÅcklauf-Strahl saûen, diesen Teil der angezeigten Pixel "unsichtbar" machen! Mit diesem Trick konnte nun die eigentliche Hardwareausgabe von 800*500 Pixel durch das Composite Sync Signal, die der SM124 nicht verkraftet und deshalb die RÑnder als weiûe sichtbare RÅcklaufstrahlen "klappt" und an~ zeigt, durch softwaremÑûige Verkleinerung unterdrÅckt werden! Durch das InstallationsmenÅ vom Hyperscreen.PRG (ab Version 1.5) hat sich ge~ zeigt, daû ein guter werksmÑûig eingestellter SM124 ca. 688*480 Pixel auf diese Weise anzeigen kann.


Literatur :

  1. Schaltplan Atari 520 ST
  2. 2Data Becker: Atari ST Intern
  3. Technische Mitteilungen: Hardwareinformation Nr. 4 Steckerbelegung der MonitorausgÑnge (Composite Sync- NachrÅstung) ; Atari Corp., Raunheim
  4. "Auûer Rand und Band mit Hyperscreen", Artikels im Mai und Juni 1989 Heft vom ST68000-Magazin, Markt und Technik Verlag

Berlin, den 30.6.1989 (C) COPYRIGHT 1988,1989 und 1990 by Stefan Hartmann


Stefan Hartmann
Electronic Research and Development
Keplerstrasse 11 B
Ä1000 Berlin 10
West-Germany
Tel. und BTX : 030 / 344 23 66
e-mail on Compuserve-ID: 72017,3216

Projekt des Monats:
Hyperscreen (Hyperscreen) fÅr 3 DM

Bauanleitung und ErklÑrung der Funktionsweise eines
"xtended graphics mode" fÅr die Atari ST Computer

von Stefan Hartmann (Hardware und Artikel) und
Karsten Isakovic (Softwareprogrammierung)

OVERROM.LST

 ' OVERROM.BAS   Version 1.0   Karsten Isakovic, Berlin 25.05.89 
' GFA-Basic
'
Print Chr$(244);" ROM-TOS Source Patch ";Chr$(244)
Print Chr$(245);" by K.Isakovic ";Chr$(245)
Print
Input "Filename -> ",Name$
Print
If Name$=""
Print "ERROR : No Filename "
Else
If Exist(Name$)
Open "U",#1,Name$
Flag=0
@Test_old(&H1263E)
@Test_old(&H12682)
If Flag=0
@Write_new(&H1263E)
@Write_new(&H12682)
Print "OK , TOS now modified !"
Else
Flag=0
@Test_new(&H1263E)
@Test_new(&H12682)
If Flag=0
Print "OK , TOS already modified !"
Else
Print "ERROR : No correct German ROM-TOS 1.4 Source-File"
Endif
Endif
Close #1
Else
Print "ERROR : ";Name$;" not found !"
Endif
Endif
Print
Print "Goodbye"
Input Ende$
Edit
Procedure Write_new(Off) ! Write $CEC0E84F
Seek #1,Off
Out #1,&HCE
Out #1,&HC0
Out #1,&HE8
Out #1,&H4F
Return
Procedure Test_old(Off) ! Test $E848CEC0
Seek #1,Off
Flag=Flag+(&HE8<>Inp(#1)) ! GFA : True = -1 , False = 0
Flag=Flag+(&H48<>Inp(#1))
Flag=Flag+(&HCE<>Inp(#1))
Flag=Flag+(&HC0<>Inp(#1))
Return
Procedure Test_new(Off) ! Test $CEC0E84F
Seek #1,Off
Flag=Flag+(&HCE<>Inp(#1)) ! GFA : True = -1 , False = 0
Flag=Flag+(&HC0<>Inp(#1))
Flag=Flag+(&HE8<>Inp(#1))
Flag=Flag+(&H4F<>Inp(#1))
Return

OVERSCAN.S

 ;----------------------------------------------------; 
; ;
; OVERSCAN.S Version 1.6 ;
; Bernd Gebauer ,Berlin 31.05.89 ;
; Karsten Isakovic,Berlin 07.07.89 ;
; ;
; RAMTOS 1.4 / BETATOS / ROMTOS 1.4 / BLITTER TOS ;
; ------------------------------------------------- ;
; ;
; GFA-Assembler 1.2 ;
; ;
;----------------------------------------------------;


; ------------ NEGATIVE LINE-A VARIABLEN -------------

M_POS_HX = -$358
WKXRez = -$2b4
WKYRez = -$2b2
CUR_X = -$158
CUR_Y = -$156
CUR_FLAG = -$154
MOUSE_FLAG = -$153
SAVE_LEN = -$14a
v_cel_ht = -$2e
v_cel_mx = -$2c
v_cel_my = -$2a
v_cel_wr = -$28
v_cur_add = -$22
v_cur_of = -$1e
v_cur_x = -$1c
v_cur_y = -$1a
v_rez_hz = -$c
v_rez_vt = -4
bytes_lin = -2
; ---------- LINE-A VARIABLEN ------------------------

v_planes = 0
width = 2
col_bit0 = $18
col_bit1 = $1a
col_bit2 = $1c
col_bit3 = $1e
lstlin = $20
lnmask = $22
wmode = $24
x1 = $26
y1 = $28
x2 = $2a
y2 = $2c
patptr = $2e
patmsk = $32
mfill = $34
clip = $36

; ----------------- HARDWARE + TOS -------------------

gemdos = 1
bios = 13
xbios = 14
Pterm0 = 0 ; Gemdos
Cconin = 1 ; Gemdos
Cnecin = 8 ; Gemdos
Cconws = 9 ; Gemdos
Dgetdrv = 25 ; Gemdos
Ptermres = 49 ; Gemdos
Fopen = 61 ; Gemdos
Fclose = 62 ; Gemdos
Fwrite = 64 ; Gemdos
Fseek = 66 ; Gemdos
Pterm = 76 ; Gemdos
Kbshift = 11 ; bios
Physbase = 2 ; xbios
Setscreen = 5 ; xbios
Supexec = 38 ; xbios
Dosound = 32 ; xbios
dostrap = $84
gemtrap = $88
xbiostrap = $b8
memtop = $436
defshiftmd = $44b
sshiftmd = $44c
v_bas_add = $44e
_nvbls = $454
_vblqueue = $456
dumpflag = $4ee
sysbase = $4f2
hardcopy = $502
vid_bashigh = $ff8201
vid_basmid = $ff8203
vid_ismid = $ff8207
vid_pal3 = $ff8246
vid_palF = $ff825e
add_len = $9000

.TEXT
main: bra.s Start_of_Code ; Zum Anfang springen

;#############################################################
;#
;# Die Tabelle der BildschirmWerte
;#
;#############################################################
ScreenTab: .DC.w 400,832,672 ; X-Auflîsung Low,Mid,High
.DC.w 280,280,480 ; Y-Auflîsung
.DC.w 236,236,100 ; Bytes pro Zeile
.DC.l -$1600,-$1600,$2000 ; VideoAdd <> Memtop Offset
.DC.l 252,248,9800 ; v_bas_add <> Memtop Offset
.DC.w 320,640,640 ; Alte X-Auflîsung
.DC.w 200,200,400 ; Alte Y-Auflîsung
TruePhys: .DC.w 0 ; Physbase Emulation aus
ActivateKey: .DC.b 9,0 ; Hardcopy Taste
;#############################################################
;#
;# Das Hauptprogramm
;#
;#############################################################

Start_of_Code: movea.l 4(sp),a5 ; Basepointer einrichten
lea.l $100(a5),sp ; Stack einrichten

pea do_setup(pc) ; Test und Installation im
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ; Ergebnis in inst_ok
addq.l #6,sp

move.w inst_ok,d0
tst.w d0 ; war Installation erfolgreich ?
bne not_ok ; leider nein, raus

move.w #Dgetdrv,-(sp) ; Bootlaufwerk holen
trap #gemdos ;
addq.l #2,sp ;
lea.l save_name(pc),a0 ;
add.b d0,(a0) ; und einstellen

move.w #-1,-(sp) ; Irgendeine Sondertaste gedrÅckt
move.w #Kbshift,-(sp) ;
trap #bios ;
addq.l #4,sp ;
tst.w d0
beq DoIntro
bsr UserInstall
bra DoTitle
DoIntro: bsr Intro ; GrowBox und Sound ausgeben
DoTitle: pea msg_title(pc) ; Titelzeile ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
pea msg_installed(pc) ; 'Installiert' Meldung ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp

clr.w -(sp) ; Resident beenden
lea.l _ende(pc),a0 ; Programmende
suba.l a5,a0 ; - Programmanfang
move.l a0,-(sp) ; = Programmlaenge
move.w #Ptermres,-(sp)
trap #gemdos
;-----------------------------------------------------
not_ok: pea msg_title(pc) ; Titelzeile ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
move.w inst_ok,d0
cmpi.w #1,d0 ; war's das falsche TOS ?
bne main_2 ; nein -> Kein Overscan-Modus

pea msg_notactive(pc) ; 'Nicht aktiviert' Meldung ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
bra Goodbye ; einfach beenden
;-----------------------------
main_2: cmpi.w #2,d0
bne main_3
pea msg_noTos(pc) ; 'Falsches TOS' Meldung ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
bra wait_key ; einfach beenden
;-----------------------------
main_3: pea msg_already(pc) ; 'Schon installiert' Meldung
move.w #Cconws,-(sp) ; ausgeben
trap #gemdos
addq.l #6,sp ; und
;-----------------------------
wait_key: move.w #Cnecin,-(sp) ; Auf Tastendruck warten
trap #gemdos
addq.l #2,sp
;-----------------------------
Goodbye: clr.w -(sp) ; Programm beenden (Returncode 0)
trap #gemdos

;############################################################
;#
;# Die Installations-Routine
;#
;#############################################################

do_setup: movem.l d0-d7/a0-a6,-(sp)
move.w #3,inst_ok ; Status : schon installiert

movea.l dostrap,a0 ; GemDos-Trap nach OVERSCAN absuchen

tstXBRA: cmpi.l #'XBRA',-12(a0) ; XBRA ?
bne noXBRA ; nein -> Ende der Vektorkette
cmpi.l #'OVER',-8(a0) ; OVER ?
beq EndSetup ; ja -> Schon Installiert !
movea.l -4(a0),a0 ;
bra tstXBRA ; weiter suchen

noXBRA: move.w #2,inst_ok ; Status : falsches TOS
;---------------------------- auf richtige TOS-Version testen

sf BadTos ; TOS als ok annehmen

testBETATOS: movea.l #$170ee,a0 ;-------- Ist es BETA-RAMTOS ?
cmpi.l #$cec0e84f,(a0) ; schon gepatched ?
beq isBETA ; ja
cmpi.l #$e848cec0,(a0) ; LSR #4,D0 / MULU D0,D7 ?
bne testRAMTOS1_4 ; nein -> RAMTOS1.4
move.l #$cec0e84f,$170ee ; MULU D0,D7 / LSR #4,D7
isBETA: movea.l $5232,a0 ; A0 = Zeiger auf MemAllocList
bra TOSok ;

testRAMTOS1_4: movea.l #$17192,a0 ;-------- Ist es RAMTOS 1.4 ?
cmpi.l #$cec0e84f,(a0) ; schon gepatched ?
beq isRAMTOS1_4
cmpi.l #$e848cec0,(a0) ;
bne testROMTOS1_4 ; nein -> ROMTOS1.4
move.l #$cec0e84f,$17192 ; 1. mal Scrollfehler
isRAMTOS1_4: move.l #$cec0e84f,$171d6 ; 2. mal Scrollfehler beheben
movea.l $5232,a0 ; A0 = Zeiger auf MemAllocList
bra TOSok ;

testROMTOS1_4: movea.l sysbase,a1 ;-------- Ist es ROMTOS 1.4 ?
cmpi.w #$0104,2(a1) ; os_version testen
bne testTOS1_2 ; nein -> TOS 1.2 (BlitterTOS)
movea.l $532c,a0 ; A0 = Zeiger auf MemAllocList
bra TOSok ;

testTOS1_2: cmpi.w #$0102,2(a1) ;-------- Ist es TOS 1.2 ?
bne EndSetup ; nein -> falsches TOS -> ENDE
st BadTos ; BlitterTOS -> Flag setzen
movea.l $7e92,a0 ; A0 = Zeiger auf MemAllocList

TOSok: move.w #1,inst_ok ; Status : Nicht im OVERSCAN-Modus
;---------------------------------------------
; Ist der Schalter umgelegt (OVERSCAN aktiv) ?
; Es wird gewartet, bis der VideoadresszÑhler bis zum Ende
; der normalen Bildschirmseite hochgezÑhlt hat.
; Dann wird getestet, ob er auf den Anfang zurÅckspringt.
; Tut er das nicht, ist OVERSCAN aktiv.
clr.w d0
move.b vid_basmid,d0 ;
move.w d0,d1 ;
addi.w #$7d,d1 ;
Wait1: cmp.b vid_ismid,d1 ;
bne Wait1 ;
Wait2: cmp.b vid_ismid,d1 ;
beq Wait2 ;
cmp.b vid_ismid,d0 ;
beq EndSetup ; Nicht aktiv -> Beenden

clr.w inst_ok ; Status : OVERSCAN aktiv

move.l v_bas_add,StartBasAdd ; Startaddr des Bildschirms

move.l memtop,d0 ; Letzte beschreibbare Addresse
addi.l #$8000,d0 ; bestimmen und merken
move.l d0,MemEnd ;

subi.l #add_len,8(a0) ; Belegten Speicherblock
subi.l #add_len,memtop ; ... verkÅrzen

tst.b BadTos ; BlitterTOS ?
beq no_extra_buff ; nein, weiter
subi.l #32768,8(a0) ; 32K Sicherheitpuffer ...
subi.l #32768,memtop ; ... vor Bildspeicher anlegen
no_extra_buff:
clr.w d0
move.b sshiftmd,d0
move.w d0,Reso ; Auflîsung merken
.DC.w $a000 ; LineA init
move.l d0,LineA ; Zeiger auf LineA Variablen
move.l memtop,MyMemtop ; AltenWert sichern
bsr SetOverscan ; Overscan Werte einstellen
;
; Diese einmalige Initialisieren der Werte reicht nicht aus,
; da sie beim Starten vom AES wieder zurÅckgesetzt werden.
; Wir mÅssen also die Werte kurz nach v_opnwk nochmal setzen
;
;----------------------> ALSO GEM-Routine (AES/VDI) umleiten
lea.l OldVec(pc),a0 ; Alten GemTrapVektor retten
move.l gemtrap,(a0) ;
lea.l MyGem(pc),a0 ;
move.l a0,gemtrap ; und neuen Vektor eintragen
tst.b BadTos ; BlitterTOS ?
beq NoSlot ; nein -> Nicht in VBL einhÑngen

move.w _nvbls,d0 ; Anzahl Routinen in _vblqueue
lsl.w #2,d0 ; mal sizeof(long)
movea.l _vblqueue,a0 ; Zeiger auf _vblqueue
moveq.l #4,d1 ; ersten Slot auslassen
TestSlot: tst.l 0(a0,d1.w) ; ist Eintrag frei ?
beq.s SlotFound ; ja, gefunden
addq.w #4,d1 ; offset fÅr nÑchsten Slot
cmp.w d0,d1 ; Ende der Liste ?
bne.s TestSlot ; nein, nÑchsten Slot testen
bra NoSlot ; keinen freien Slot gefunden, raus
SlotFound:
lea.l MyVB(pc),a1 ; eigene VBL-Routine ...
move.l a1,0(a0,d1.w) ; ... in Slot eintragen
NoSlot:
;---------------------------- Gemdos umleiten
lea.l OldDos(pc),a0 ; Alten GemdosVektor retten
move.l dostrap,(a0) ;
lea.l MyDos(pc),a0 ;
move.l a0,dostrap ; und neuen Vektor eintragen
;---------------------------- Xbios umleiten
lea.l OldXbios(pc),a0 ; Alten XbiosVektor retten
move.l xbiostrap,(a0) ;
lea.l MyXbios(pc),a0 ;
move.l a0,xbiostrap ; und neune Vektor eintragen
;---------------------------- Hardcopy-Routine umleiten
lea.l OldHard(pc),a0 ; Alten HardcopyVektor retten
move.l hardcopy,(a0) ;
lea.l MyHard(pc),a0 ;
move.l a0,hardcopy ; und neuen Vektor eintragen

sf GemStarted
EndSetup: movem.l (sp)+,d0-d7/a0-a6
rts

;#############################################################
;#
;# Die umgebogenen Traps und Vektoren
;# ----------------------------------
;# MyGem AES/VDI Trap
;# MyDos GEMDOS Trap
;# MyXbios XBIOS TRAP
;# MyHard Hardcopy-Vektor
;# MyVB VerticalBlank-Vektor (nur bei BlitterTOS )
;# MyMouse Mouse-Vektor (nur bei BlitterTOS)
;#
;################################################ GEM- TRAP

; XBRA-Protokoll
.DC.b "XBRAOVER" ; !! Ja, das ist alles !!
OldVec: .DC.l 0
MyGem: cmpi.w #$73,d0 ; Ist es ein VDI-Aufruf ?
bne NotMyGem ; nein -> weiter
movea.l d1,a0 ; Addresse der VDI-Parameterfelder
move.l 12(a0),WorkOut ; WorkOut-Zeiger speichern
movea.l (a0),a0 ; VDI-Control[0] = VDI-Befehlscode
cmpi.w #1,(a0) ; ist es Open-WorkStation ?
bne NotMyGem ; nein-> weiter
movea.l d1,a0
movea.l 4(a0),a0 ; WorkIn-Zeiger
cmpi.w #5,(a0) ; WorkIn[0] gleich Screen ?
bge NotMyGem ; nein -> weiter
;-------------> NACH !!! 'v_opnwk()' in Patchroutine springen
move.l 2(sp),Back ; Orginal RÅcksprungadresse merken
lea.l PatchIt(pc),a0 ; RÅcksprung auf 'PatchIt' ...
move.l a0,2(sp) ; ... umleiten
NotMyGem: movea.l OldVec(pc),a0 ; Orginal GEM-Routine ...
jmp (a0) ; ... ausfÅhren
;----------------------------------------------------------
PatchIt: bsr SetOverscan ; LineA Werte nochmal eintragen

move.w #-1,-(sp) ; Auf rechte Schifttaste testen
move.w #Kbshift,-(sp) ;
trap #bios ;
addq.l #4,sp ;
tst.w d0
beq PatchCont

bsr UserInstall

PatchCont: bsr ClearScreen ; Rand lîschen
pea msg_erase(pc) ; und Mitte auf Weiss
move.w #Cconws,-(sp) ;
trap #gemdos ;
addq.l #6,sp ;
st GemStarted ; Okay GEM lÑuft
movea.l WorkOut,a0 ; Adresse des Workout-Feldes
move.w RezX,0(a0) ; Work_out[0] = Breite
move.w RezY,2(a0) ; Work_out[1] = Hîhe

move.w VPlanes,d0 ; Farben Vorgeben
cmpi.w #4,d0
bne PatchMid
move.w #200,78(a0)
move.w #16,26(a0)
bra PatchEnd
PatchMid: cmpi.w #2,d0
bne PatchHigh
move.w #200,78(a0)
move.w #4,26(a0)
bra PatchEnd
PatchHigh:
move.w #2,78(a0)
move.w #2,26(a0)

PatchEnd: move.l Back,-(sp) ; Zum 'v_opnwk()' - Aufrufer
rts ; zurÅckspringen
;################################################ GEMDOS-Trap
.DC.b "XBRAOVER"
OldDos: .DC.l 0
MyDos: move.w (sp),d0 ; Je nachdem ob GEMDOS vom
btst #13,d0 ; Supervisor- oder User-modus
bne no_super ; aufgerufen wurde sind die
move.l usp,a0 ; Parameter auf dem entsprechendem
bra tst_term ; Stack
no_super: lea.l 6(sp),a0
tst_term: cmpi.w #Pterm0,(a0) ; Der Overscan-Modus wird
beq TermFound ; NACH jedem Programm nocheinmal
cmpi.w #Pterm,(a0) ; neu installiert, da viele
bne NoTerm ; Programme den Bildschirm umsetzen
TermFound: movem.l d0-d7/a0-a6,-(sp) ; oder direkt beschreiben.
bsr SetOverscan ;
bsr ClearScreen ;
NoClear: movem.l (sp)+,d0-d7/a0-a6
NoTerm: movea.l OldDos(pc),a0
jmp (a0)
;################################################ XBIOS-Trap
.DC.b "XBRAOVER"
OldXbios: .DC.l 0
MyXbios: move.w TruePhys,d0
beq No_Xbios
move.w (sp),d0 ; Je nachdem ob XBIOS vom
btst #13,d0 ; Supervisor- oder User-modus
bne no_x_super ; aufgerufen wurde sind die
move.l usp,a0 ; Parameter auf dem entsprechendem
bra tst_phys ; Stack
no_x_super: lea.l 6(sp),a0
tst_phys: cmpi.w #Physbase,(a0) ; Beim Physbase-Aufruf wird
beq PhysFound ;
No_Xbios: movea.l OldXbios(pc),a0
jmp (a0)
PhysFound: move.l v_bas_add,d0 ; v_bas_add zurÅckgegeben
rte
;################################################ HARDCOPY-Vec
.DC.b "XBRAOVER" ; HARDCOPY
OldHard: .DC.l 0 ;
MyHard: move.w #-1,-(sp) ; Auf Shift ALT/HELP testen
move.w #Kbshift,-(sp) ;
trap #bios ;
addq.l #4,sp ;
cmp.b ActivateKey,d0 ; ja -> eigene Routine
beq NewHard ;
movea.l OldHard(pc),a0 ; nein -> alte Routine anspringen
jmp (a0) ;
;------------------------------------------
NewHard: movem.l d0-d7/a0-a6,-(sp)
bsr SetOverscan ; Overscan Werte nochmal setzen
bsr ClearScreen ; BilschirmrÑnder lîschen
DoNotClear: move.w #-1,dumpflag ; Hardcopy-DumpFlag lîschen
EndHard: movem.l (sp)+,d0-d7/a0-a6
rts ; zurÅck
;################################################ VBL-Vektor
.DC.b "XBRAOVER" ; VerticalBlank nur bei BLITTER-TOS
.DC.l 0
MyVB: tst.b GemStarted ; LÑuft GEM schon
beq.s MyVB_1 ; nein, raus

movea.l _vblqueue,a0 ; in VBL-Slot 0 schon ...
tst.l (a0) ; ... GEM-Mausroutine installiert ?
beq.s MyVB_1 ; nein, raus

pea MyMouse(pc) ; durch eigene Mausroutine ...
move.l (sp)+,(a0) ; ... ersetzen

; ???????????????????????????
movea.l MouseVec,a0
cmpi.l #$fcfe82,(a0)
bne.s MyVB_1
move.w sr,-(sp)
ori.w #$700,sr
move.l #$fcfe8c,(a0)
move.w (sp)+,sr
MyVB_1: rts
;################################################ MOUSE-Vektor
.DC.b "XBRAOVER" ; MouseVec nur bei BLITTER-TOS
.DC.l 0
MyMouse: move.w sr,-(sp) ; Alte Interruptmaske merken
ori.w #$0700,sr ; alle Interrupts sperren

movea.l LineA,a0 ; Zeiger auf LineA Variablen
bclr #0,CUR_FLAG(a0) ; !0 -> Maus neu zeichnen ?
beq.s MyMouse_2 ; nein, raus

clr.l d0
clr.l d1
move.w CUR_X(a0),d0 ; Maus X-Position holen
move.w CUR_Y(a0),d1 ; Maus Y-Position holen
move.w (sp)+,sr ; wieder Interrupts zulassen
tst.b MOUSE_FLAG(a0) ; !0 -> Mausinterrupt ein ?
bne.s MyMouse_1 ; ja, raus

movem.w d0/d1,-(sp) ; Register retten

lea.l SAVE_LEN(a0),a2 ; Zeiger auf LineA SpriteSaveBuffer
bsr UndrawSprite ; Mauszeiger lîschen

movem.w (sp)+,d0/d1 ; Register restaurieren

movea.l LineA,a0
lea.l SAVE_LEN(a0),a2 ; Zeiger auf LineA SpriteSaveBuffer
lea.l M_POS_HX(a0),a0 ; SDB-Zeiger fÅr LineA-MausSprite
bsr DrawSprite ; Mauszeiger neu zeichnen
MyMouse_1:
rts ; raus
MyMouse_2:
move.w (sp)+,sr ; wieder Interrupts zulassen
rts ; raus


;#############################################################
;#
;# Die wichtigsten Unterprogramme
;# ------------------------------
;# SetOverscan LineA und Auflîsung initialisieren
;# ClearScreen Nur BildschirmRÑnder auf Schwarz
;# ClearFullScreen Ganzen Bildschirmspeicher lîschen
;#
;#############################################################

SetOverscan: clr.l d2
move.b sshiftmd,d2 ; Aktuelle Aufîsung
move.w d2,Reso ; merken
add.w d2,d2 ; mal 2 als Word-Offset in Tabelle
lea.l ScreenTab(pc),a0 ; TabellenZeiger holen
move.w 0(a0,d2.w),RezX ; X-Auflîsung
move.w 6(a0,d2.w),RezY ; Y-Auflîsung
move.w 12(a0,d2.w),BpL ; Bytes pro Zeile
add.w d2,d2 ; mal 2 als Long-Offset
move.l 18(a0,d2.w),d0 ; Offset MEMTOP <> VIDEO_ADD
move.l 30(a0,d2.w),d1 ; Offset MEMTOP <> V_BAS_ADD
move.w d1,Offset ; merken
;---------------------------- Videoaddresse auf 'memtop + D0'
move.l MyMemtop,v_bas_add
tst.b BadTos ; Bei BlitterTOS
beq no_buff_1 ; hinter Sicherheits-
addi.l #32768,v_bas_add ; Puffer beginnen
no_buff_1:
add.l d0,v_bas_add
move.b v_bas_add+1,vid_bashigh ; Addresse setzen
move.b v_bas_add+2,vid_basmid
move.l v_bas_add,VidAdd ; und merken
;---------------------------- v_bas_ad auf 'memtop + D1' setzen
move.l MyMemtop,v_bas_add
tst.b BadTos ; Bei BlitterTOS
beq no_buff_2 ; hinter Sicherheitspuffer
addi.l #32768,v_bas_add ;
no_buff_2:
add.l d1,v_bas_add ; v_bas_add setzen
move.l v_bas_add,BasAdd ; und merken
;--------------- Werte in den negativen LineA Variablen anpassen
movea.l LineA,a0 ; LineA Zeiger holen
move.w RezX,v_rez_hz(a0) ; Breite setzen
move.w RezX,WKXRez(a0) ;
subi.w #1,WKXRez(a0) ; Breite-1
move.w RezY,v_rez_vt(a0) ; Hîhe setzen
move.w RezY,WKYRez(a0) ;
subi.w #1,WKYRez(a0) ; Hîhe-1
move.w BpL,bytes_lin(a0) ; Bytes pro Zeile setzen
move.w BpL,width(a0) ;
move.w RezX,d0 ;
asr.w #3,d0 ;
subq.w #1,d0 ; Breite/8 -1
move.w d0,v_cel_mx(a0) ; -> Anzahl Buchstaben pro Zeile
clr.l d0 ;
move.w RezY,d0 ;
divu.w v_cel_ht(a0),d0 ;
subq.w #1,d0 ; Hîhe/Buchstabenhîhe -1
move.w d0,v_cel_my(a0) ; -> Anzahl Buchstabenzeilen
move.w v_cel_ht(a0),d0 ;
mulu.w BpL,d0 ; AnzBuchstaben*BytesProZeile
move.w d0,v_cel_wr(a0) ; -> BlocklÑnge fÅr Scrolling
move.w v_planes(a0),VPlanes ; Anzahl der Farbebenen
tst.b BadTos ; BLITTER-TOS ?
beq setLineA_1 ; nein -> fertig
;-----------------------------
move.w #3,MonPLine
move.b sshiftmd,d0
cmpi.b #1,d0
bgt setLineA_1
move.w #2,MonPLine
tst.b d0
bne setLineA_1
move.w #1,MonPLine
setLineA_1: bsr ResetCursor ; Neue CursorAddresse bestimmen
rts
;-----------------------------
CallSetOverscan:
move.w sr,d0
btst #13,d0
beq DoCallOver
bra SetOverscan
DoCallOver: pea SetOverscan(pc) ; im
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;#############################################################
ClearScreen: bsr BlackColor ; Lîschfarbe holen in D0
move.l d0,d4 ;
;-----------------------------
movea.l VidAdd,a1 ; Oberen Rand lîschen
movea.l BasAdd,a0 ;
subq.l #2,a0 ; Falls HIGH_OFF nicht /4 teilbar
Hflp: move.l d4,(a1)+ ; Vor dem Bildschirm RÅcklauf
cmpa.l a0,a1 ; Pixel auf Schwarz setzen
blt Hflp ;
;-----------------------------
move.w Reso,d5 ;
movea.l BasAdd,a0 ; Links & Rechts im RÅcklauf lîschen
clr.l d0 ; Den ungenutzten Bereich im
clr.l d1 ; RÅcklauf auf Schwarz setzen
move.w BpL,d0 ; Bytes pro Zeile - Pixel/xxx
move.w RezX,d1 ;
addq.w #1,d5
asr.w d5,d1 ; >>3:High >>2:Mid >>1:Low
sub.w d1,d0 ;
move.w RezY,d2 ; Hîhe des Bereichs
subq.w #1,d2 ;
subq.w #1,d0 ;
Hlp1: adda.l d1,a0 ; Normalen Bildbereich Åberspringen
move.w d0,d3 ;
Hlp2: move.b d4,(a0)+ ; Bereich lîschen
dbf d3,Hlp2 ;
dbf d2,Hlp1 ;
;-----------------------------
move.l a0,d0 ; Unteren Bildrand lîschen
bclr #0,d0 ; Zeiger auf gerade Addresse
movea.l d0,a0 ; bringen
move.l MemEnd,d1 ; Anzahl der zulîschenden Blîcke
sub.l d0,d1 ; Speicherende minus ZeigerAddr
asr.l #4,d1 ; durch 16 (BlocklÑnge)
subq.l #1,d1 ; minus 1 (wegen dbf)
;-----------------------------
Hlp3: move.l d4,(a0)+ ; auf Schwarz lîschen
move.l d4,(a0)+ ;
move.l d4,(a0)+ ;
move.l d4,(a0)+ ;
dbf d1,Hlp3 ;
rts ; fertig
;-----------------------------
CallClearScreen:
move.w sr,d0
btst #13,d0
beq DoCallClearSc
bra ClearScreen
DoCallClearSc: pea ClearScreen(pc) ; im
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;#############################################################
; Gesamten Bildspeicher lîschen (auf schwarz)
; Lîschfarbe bestimmen
ClearFullScreen:
bsr BlackColor ; Lîschwert holen in D0
move.l #$8000,d1 ; LÑnge des alten Bildschirmspeichers
addi.l #add_len,d1 ; plus Erweiterung
lsr.l #4,d1 ; geteilt durch 16L
subq.l #1,d1 ; minus 1 wegen dbf
;-----------------------------
movea.l MyMemtop,a0 ; ab MEMTOP lîschen
tst.b BadTos ; BlitterTOS ?
beq sc_clp ; Sicherheitspuffer beachten
adda.l #32768,a0 ; alte LÑnge
;-----------------------------
sc_clp: move.l d0,(a0)+ ;
move.l d0,(a0)+ ;
move.l d0,(a0)+ ;
move.l d0,(a0)+ ;
dbf d1,sc_clp ; die nÑchsten 16 Bytes
bsr ResetCursor
rts ; fertig
;-----------------------------
CallClearFull:
move.w sr,d0
btst #13,d0
beq DoCallClearFu
bra ClearFullScreen
DoCallClearFu: pea ClearFullScreen(pc) ; im
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;-----------------------------
BlackColor: move.l #-1,d0 ; erstmal FÅllwert $FFFFFFFF
move.w Reso,d1 ; Bildschirmmodus ...
cmpi.w #2,d1 ; ... Monochrom ?
bne NotWhite ; nein, weiter
btst #0,$ff8241 ; Inverse Monochrome ?
bne NotWhite ; nein, Farbe richtig
not.l d0 ; sonst FÅllwert $0
NotWhite: rts
;-----------------------------
CallBlackColor:
move.w sr,d0
btst #13,d0
beq DoCallBlackCo
bra BlackColor
DoCallBlackCo: pea BlackColor(pc) ; im
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;#############################################################
; Retten des alten SchirmInhaltes in den neuen OVERSCAN Bildschirm
;
ScreenSave: movem.l d0-d7/a0-a6,-(sp) ;
movea.l StartBasAdd,a0 ; Bildschirmspeicher kurz
movea.l MyMemtop,a1 ; vor MemTop kopieren !
suba.l #$8000,a1 ;
move.l #1000,d0
ScSaveLoop: movem.l (a0)+,d1-d7/a2
movem.l d1-d7/a2,(a1)
lea.l 32(a1),a1 ; 32 Bytes transportieren
dbf d0,ScSaveLoop
movem.l (sp)+,d0-d7/a0-a6
rts
;---------------------------------------------------------
ScreenCopy: movem.l d0-d7,-(sp) ;
movea.l BasAdd,a0 ; Bildschirmspeicher wieder
movea.l MyMemtop,a1 ; zurÅckkopieren
suba.l #$8000,a1 ;
move.w #160,d0 ; Alte Breite in BYTE D0
move.w #200,d1 ; Alte Hîhe D1
cmpi.w #2,Reso ;
bne CopyNoHigh ;
move.w #80,d0 ; High-Reso
move.w #400,d1 ;
CopyNoHigh: clr.l d2 ;
move.w BpL,d2 ; Neue Bytes Pro Line D3
sub.w d0,d2 ; Differenz Neue-Alte
asr.w #2,d0 ; /4 -> Longs
subq.w #1,d0 ; wegen dbf -> LONGs to copy
subq.w #1,d1 ; Lines to Copy
subq.w #1,d2 ; Rest zu lîschen

CopyLoop: move.w d0,d3 ;
Copy_1: move.l (a1)+,(a0)+ ; Alten Schirm kopieren
dbf d3,Copy_1 ;
move.w d2,d3 ;
Copy_2: clr.b (a0)+ ;
dbf d3,Copy_2 ; Zeile bis Ende lîschen
dbf d1,CopyLoop ;

bsr CallClearScreen
bsr ResetCursor ; CursorAddr bestimmen
movem.l (sp)+,d0-d7
rts
;#####################################################################
; Neue CursorAddresse bestimmen
;
ResetCursor: movea.l LineA,a0 ;
move.l BasAdd,v_cur_add(a0) ; Neue Addresse
move.w v_cur_y(a0),d0 ; = V_bas_add
mulu.w v_cel_wr(a0),d0 ;
add.l d0,v_cur_add(a0) ; + y * cel_wr
move.w v_cur_x(a0),d0 ;
bclr.l #0,d0 ; + x^1 * v_planes
mulu.w v_planes(a0),d0 ;
add.l d0,v_cur_add(a0) ; + x^1 * planes
move.w v_cur_x(a0),d0 ;
andi.l #$fffe,d0 ;
add.w d0,v_cur_add(a0) ; + x&1
clr.l d0 ;
move.w v_cur_of(a0),d0 ;
add.l d0,v_cur_add(a0) ; + cursor_offset
rts
;#############################################################
;#
;# INTRO GrowBox Effekt und Sound
;#
;#############################################################

Intro: bsr ScreenSave
pea SoundTab(pc) ; Sound abspielen
move.w #Dosound,-(sp)
trap #xbios
addq.l #6,sp
;-----------------------------
clr.w d0
bsr set_color
move.w Reso,d5 ; Aktuelle Aufîsung
add.w d5,d5 ; mal 2 als Word-Offset in Tabelle
lea.l ScreenTab(pc),a0
move.w RezX,d6 ; D6 = (Breite - AlteBreite)/2
cmp.w 42(a0,d5.w),d6 ; Neue Breite kleiner als Alte ?
blt EndIntro ; ja -> Nur Schirm kopieren
sub.w 42(a0,d5.w),d6
asr.w #1,d6
move.w d6,d0 ; als X1
move.w d0,d2
add.w 42(a0,d5.w),d2 ; X2 = X1 + AlteAuflîsung
move.w RezY,d7 ; D7 = (Hîhe - AlteHîhe )/2
cmp.w 48(a0,d5.w),d7 ; Neue Hîhe kleiner als Alte ?
blt EndIntro ; ja -> Nur Schirm kopieren
sub.w 48(a0,d5.w),d7
asr.w #1,d7
move.w d7,d1 ; als Y1
move.w d1,d3
add.w 48(a0,d5.w),d3 ; Y2 = Y1 + AlteAuflîsung
move.w d6,Dx ; Alle Werte abspeichern
move.w d7,Dy ;
move.w d0,Xa ;
move.w d1,Ya ;
move.w d2,Xe ;
move.w d3,Ye ;

movem.l d0-d7/a0-a6,-(sp)
bsr CallClearFull
movem.l (sp)+,d0-d7/a0-a6

bsr draw_rect ; Das gefÅllte Rechteck zeichnen
;-------------------------------------------------------------
move.w d6,Max ; In welche Richtung ist der
cmp.w d6,d7 ; Zugewinn am grîûten ?
blt grow_box ;
move.w d7,Max ;
grow_box: move.w #1,d6 ; Zaehler
grow_loop:
clr.w d7 ; Schleife fÅr die grîûer werdenden
move.w Dx,d4 ; Rechtecke. Die Bewegung soll
mulu.w d6,d4 ; proportional verlaufen...
divu.w Max,d4 ; ...deswegen der ganze Hermann
move.w Dy,d5 ;
mulu.w d6,d5
divu.w Max,d5

cmpi.w #0,d0 ; X links oben
beq no_d0
move.w Xa,d0
sub.w d4,d0
addq.w #1,d7
no_d0: cmpi.w #0,d1 ; Y links oben
beq no_d1
move.w Ya,d1
sub.w d5,d1
addq.w #1,d7
no_d1: cmp.w RezX,d2 ; X rechts unten
beq no_d2
move.w Xe,d2
add.w d4,d2
addq.w #1,d7
no_d2: cmp.w RezY,d3 ; Y rechts unten
beq no_d3
move.w Ye,d3
add.w d5,d3
addq.w #1,d7
no_d3: bsr draw_box ; das Rechteck zeichnen
;-----------------------------
addq.w #1,d6 ;
tst.w d7 ; Solange sich noch was Ñndert
bne grow_loop ; die Rechteckschleife wiederholen

EndIntro: bsr ResetCursor
bra ScreenCopy

;-----------------------------
set_color: movea.l LineA,a0 ; Farbe setzen
move.w d0,col_bit0(a0) ;
move.w d0,col_bit1(a0) ;
move.w d0,col_bit2(a0) ;
move.w d0,col_bit3(a0) ;
rts
;---------------------------------
draw_box: movea.l LineA,a0 ; Ein Rechteck aus Linien zeichnen
clr.w wmode(a0) ; d0/d1 linke obere Ecke
move.w #$ffff,lnmask(a0) ; d2/d3 rechte untere Ecke
move.w #1,lstlin(a0)
move.w d0,x1(a0)
move.w d1,y1(a0)
move.w d2,x2(a0)
move.w d1,y2(a0)
bsr draw_line ; Oben
movea.l LineA,a0
move.w d2,x1(a0)
move.w d1,y1(a0)
move.w d2,x2(a0)
move.w d3,y2(a0)
bsr draw_line ; Rechts
movea.l LineA,a0
move.w d2,x1(a0)
move.w d3,y1(a0)
move.w d0,x2(a0)
move.w d3,y2(a0)
bsr draw_line ; Unten
movea.l LineA,a0
move.w d0,x1(a0)
move.w d1,y1(a0)
move.w d0,x2(a0)
move.w d3,y2(a0)
bsr draw_line ; Links
rts
;-----------------------------
draw_diag: movea.l LineA,a0 ; Diagonalen zeichnen
move.w d0,x1(a0) ;
move.w d1,y1(a0) ; Parameter wie oben
move.w d2,x2(a0) ;
move.w d3,y2(a0)
bsr draw_line ; Diagonale links
movea.l LineA,a0
move.w d2,x1(a0)
move.w d1,y1(a0)
move.w d0,x2(a0)
move.w d3,y2(a0)
bsr draw_line ; Diagonale rechts
EndBox: rts
;-----------------------------
draw_line: movem.l d0-d7,-(sp) ; Einzelne Linie Ziehen
.DC.w $a003
movem.l (sp)+,d0-d7
rts
;-----------------------------
pattern: .DC.w $ffff ; Fuellmuster
;-----------------------------
draw_rect: movem.l d0-d7,-(sp) ; Ein Rechteck zeichnen
movea.l LineA,a0 ;
move.w #1,mfill(a0) ; d0/d1 linke obere Ecke
clr.w wmode(a0) ; d2/d3 rechte untere Ecke
move.w d0,x1(a0)
move.w d1,y1(a0)
move.w d2,x2(a0)
move.w d3,y2(a0)
lea.l pattern(pc),a1
move.l a1,patptr(a0)
move.w #1,patmsk(a0)
clr.w clip(a0)
.DC.w $a005
movem.l (sp)+,d0-d7
rts

;#############################################################
;#
;# OVERSCAN - Einstellung
;#
;#############################################################

UserInstall: bsr UserInit ; Initialisieren
UserLoop: move.w #0,d0 ; Wiederhole
bsr DrawSetup ;
bsr WriteSetup ; Zeichne Kreuz und Werte
bsr GetKey ; Hole Taste
move.w #1,d0 ;
bsr DrawSetup ; Lîsche Kreuz
bsr ChangeSetup ; Bearbeite Taste
tst.w UserSave ;
beq UserLoop ; Bis EndeFlag gesetzt
bra UserExit ; Meldung ausgeben
;------------------------------------------------------------
UserInit: bsr CallClearFull ; Schirm lîschen
bsr CallClearPal ; Farbregister 3 lîschen
move.w Reso,ResoSave ; Startauflîsung merken
bsr InitReso
clr.w UserSave
bsr Do_Help ; HilfsText
bra CallClearFull ; und wieder schwarz
;--------------------------------------------
UserExit: pea msg_erase(pc) ; Bildschirm lîschen & CursorHome
move.w #Cconws,-(sp) ;
trap #gemdos ;
addq.l #6,sp ;
move.w UserSave,d0
cmpi.w #1,d0 ; 1 -> Nicht gespeichert
bne tstNotFound
pea msg_nosave(pc) ;
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
bra UserContinue
;----------------------
tstNotFound: cmpi.w #2,d0 ; 2 -> Datei nicht gefunden
bne Saved ;
pea save_name(pc) ; Datei-Name ausgeben
move.w #Cconws,-(sp) ;
trap #gemdos ;
addq.l #6,sp ;
pea msg_notfound(pc) ;
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
move.w #Cnecin,-(sp) ; Tastendruck abwarten
trap #gemdos
addq.l #2,sp
bra UserContinue
;--------------------------
Saved: pea msg_save(pc) ; 3 -> Alles gespeichert
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
UserContinue: move.w Reso,d0
cmp.w ResoSave,d0
bne NoRestorePal
bsr CallRestorePal ; Farbregister 3 zurÅck
NoRestorePal: rts
;-----------------------------
GetKey: move.w #Cnecin,-(sp)
trap #gemdos
addq.l #2,sp
swap.w d0 ; ScanCode
move.w d0,UserKey
rts
;-----------------------------
ChangeSetup: move.w UserKey,d0 ; Auf Tastendruck reagieren
cmpi.w #16,d0 ; Q
bne NoQ
move.w #1,UserSave
bra ChangeClear
NoQ: cmpi.w #31,d0 ; S
bne NoS
bra Do_Save
NoS: cmpi.w #98,d0 ; Help
bne NoHelp
bsr Do_Help
bra ChangeClear
NoHelp: cmpi.w #75,d0 ; LinksPfeil
bne NoLeft
bra Do_Left
NoLeft: cmpi.w #77,d0 ; RechtsPfeil
bne NoRight
bra Do_Right
NoRight: cmpi.w #72,d0 ; RaufPfeil
bne NoUp
bra Do_Up
NoUp: cmpi.w #80,d0 ; RunterPfeil
bne NoDown
bra Do_Down
NoDown: cmpi.w #101,d0 ; /
bne NoDiv
bsr Do_Div
bra ChangeClear
NoDiv: cmpi.w #102,d0 ; *
bne NoMul
bsr Do_Mul
bra ChangeClear
NoMul: cmpi.w #74,d0 ; -
bne NoSub
bsr Do_Sub
bra ChangeClear
NoSub: cmpi.w #78,d0 ; +
bne NoAdd
bsr Do_Add
bra ChangeClear
NoAdd: cmpi.w #25,d0 ; P
bne NoP
bsr Do_Phys
bra ChangeClear
NoP: cmpi.w #46,d0 ; C
bne NoC
bsr Do_Activ
bra ChangeClear
NoC: cmpi.w #35,d0 ; H
bne NoH
bsr ResoChangeTest
bne ChangeClear
move.w #2,d0
bra SetScreenReso
NoH: cmpi.w #50,d0 ; M
bne NoM
bsr ResoChangeTest
bne ChangeClear
move.w #1,d0
bra SetScreenReso
NoM: cmpi.w #38,d0 ; L
bne EndChange
bsr ResoChangeTest
bne ChangeClear
move.w #0,d0
bra SetScreenReso

EndChange: rts
ChangeClear: bra CallClearFull
;----------------------------------------------
ClearPal: move.w vid_pal3,Pal3Save ; Farbregister 3 retten
move.w vid_palF,PalFSave
clr.w vid_pal3 ; auf schwarz setzen
clr.w vid_palF
rts
CallClearPal: move.w sr,d0
btst #13,d0
beq DoCallClearPa
bra ClearPal
DoCallClearPa: pea ClearPal(pc) ; Farbregister 3 lîschen
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;----------------------------------------------
RestorePal: move.w Pal3Save,vid_pal3 ; Farbregister 3 zurÅck
move.w PalFSave,vid_palF
rts
CallRestorePal:
move.w sr,d0
btst #13,d0
beq DoCallRestore
bra RestorePal
DoCallRestore: pea RestorePal(pc) ; Farbregister 3 lîschen
move.w #Supexec,-(sp) ; Supervisormodus durchfÅhren
trap #xbios ;
addq.l #6,sp
rts
;----------------------------------------------
InitReso: move.w #8,Y_Inc
move.w Reso,d0 ; Aktuelle Auflîsung
cmpi.w #2,d0 ;
bne NoHighReso ;
move.w #16,Y_Inc ; Y-Inkrement feststellen
;-----------------------------
NoHighReso: move.l #8,d1 ;
tst.w d0
beq InitOffset
asr.l d0,d1 ;
InitOffset: move.l d1,Off_Inc ; Offset-Inkrement festlegen
;-----------------------------
clr.l d1 ; Max X/Y feststellen
move.w d0,d1 ;
addq.w #1,d1 ;
move.w #1,d2 ;
asl.w d1,d2 ; 1 << (Reso+)
mulu.w BpL,d2 ;
move.w d2,X_Max ; MaxX = Bpl * 1<<(Reso+1)
move.l MemEnd,d1 ;
sub.l MyMemtop,d1 ;
divu.w BpL,d1 ; MaxY = SpeicherlÑnge/BytePerLine
move.w d1,Y_Max ;
move.w #320,X_Min ;
move.w #160,Y_Min ;
cmpi.w #2,d0 ;
bne InitPointer ;
move.w #320,Y_Min ;
;-----------------------------
InitPointer: add.w d0,d0 ; Words
lea.l ScreenTab(pc),a0 ; Breite/Hîhe/Offset Pointer
lea.l 0(a0,d0.w),a1 ; ermitteln
move.l a1,X_Add
lea.l 6(a0,d0.w),a1
move.l a1,Y_Add
add.w d0,d0 ; Longs
lea.l 30(a0,d0.w),a1
move.l a1,Off_Add
rts
;-----------------------------
Do_Save: bsr CallClearFull ; Schirm lîschen
move.w #2,UserSave ; Nicht gefunden Flag setzen


move.w #1,-(sp) ; Fopen('\AUTO\OVERSCAN.PRG',1)
pea save_name(pc) ;
move.w #Fopen,-(sp)
trap #gemdos ;
addq.l #8,sp ;
tst.w d0 ; Gefunden ?
bmi EndSave ; nein -> ende
move.w #3,UserSave ; Flag setzen...
move.w d0,Handle ; Dateihandle merken
clr.w -(sp) ;
move.w Handle,-(sp) ; Header Åberlesen
move.l #30,-(sp) ;
move.w #Fseek,-(sp) ; Fseek(30,Handle,0)
trap #gemdos ;
lea.l $a(sp),sp ;
pea ScreenTab(pc) ; ScreenTab speichern
move.l #60,-(sp) ;
move.w Handle,-(sp) ;
move.w #Fwrite,-(sp) ; Fwrite(Handle,60L,ScreenTab)
trap #gemdos ;
lea.l $c(sp),sp ;
move.w Handle,-(sp) ;
move.w #Fclose,-(sp) ; Fclose(Handle)
trap #gemdos ;
addq.l #4,sp ;
EndSave: rts
;----------------------------------------------------
Do_Help: pea msg_help(pc) ; Hilfstext ausgeben
move.w #Cconws,-(sp)
trap #gemdos
addq.l #6,sp
move.w #Cnecin,-(sp)
trap #gemdos
addq.l #2,sp ; Tastendruck abwarten
rts
;-----------------------------
Do_Left: move.w X_Min,d0 ; Breite vermindern
cmp.w RezX,d0
bge End_Left
movea.l X_Add,a0
subi.w #16,(a0)
bsr CallSetOversc

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT