<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.temlib.org/AtariForumWiki/index.php?action=history&amp;feed=atom&amp;title=Introduction_to_the_STE</id>
	<title>Introduction to the STE - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.temlib.org/AtariForumWiki/index.php?action=history&amp;feed=atom&amp;title=Introduction_to_the_STE"/>
	<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;action=history"/>
	<updated>2026-05-02T04:04:48Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.2</generator>
	<entry>
		<id>https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14518&amp;oldid=prev</id>
		<title>&gt;Wongck at 02:25, 25 March 2012</title>
		<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14518&amp;oldid=prev"/>
		<updated>2012-03-25T02:25:46Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;amp;diff=14518&amp;amp;oldid=14517&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>&gt;Wongck</name></author>
	</entry>
	<entry>
		<id>https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14517&amp;oldid=prev</id>
		<title>&gt;Wongck at 04:26, 19 February 2012</title>
		<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14517&amp;oldid=prev"/>
		<updated>2012-02-19T04:26:18Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 00:26, 19 February 2012&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l395&quot;&gt;Line 395:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 395:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;FF8924  xxxx xxxx xxxx xxxx  RW  MICROWIRE Mask register&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;FF8924  xxxx xxxx xxxx xxxx  RW  MICROWIRE Mask register&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Back to [[Programming]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Programming]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Programming]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>&gt;Wongck</name></author>
	</entry>
	<entry>
		<id>https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14516&amp;oldid=prev</id>
		<title>&gt;Silver Surfer: wiki format</title>
		<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14516&amp;oldid=prev"/>
		<updated>2007-09-01T21:01:38Z</updated>

		<summary type="html">&lt;p&gt;wiki format&lt;/p&gt;
&lt;a href=&quot;https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;amp;diff=14516&amp;amp;oldid=14515&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>&gt;Silver Surfer</name></author>
	</entry>
	<entry>
		<id>https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14515&amp;oldid=prev</id>
		<title>&gt;Tompee at 11:50, 15 October 2006</title>
		<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14515&amp;oldid=prev"/>
		<updated>2006-10-15T11:50:52Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 07:50, 15 October 2006&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l635&quot;&gt;Line 635:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 635:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;FF8924  xxxx xxxx xxxx xxxx  RW  MICROWIRE Mask register&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;FF8924  xxxx xxxx xxxx xxxx  RW  MICROWIRE Mask register&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Programming]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>&gt;Tompee</name></author>
	</entry>
	<entry>
		<id>https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14514&amp;oldid=prev</id>
		<title>&gt;Ggn at 12:25, 13 September 2006</title>
		<link rel="alternate" type="text/html" href="https://www.temlib.org/AtariForumWiki/index.php?title=Introduction_to_the_STE&amp;diff=14514&amp;oldid=prev"/>
		<updated>2006-09-13T12:25:40Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
Atari STE Hardware documentation, taken from the developer information, and&lt;br /&gt;
altered to correspond more to observed facts than the original documentation.&lt;br /&gt;
&lt;br /&gt;
                       INTRODUCTION TO THE STE&lt;br /&gt;
&lt;br /&gt;
The Atari STE is an enhanced version of the ST with the following changes:&lt;br /&gt;
&lt;br /&gt;
                               GRAPHICS&lt;br /&gt;
&lt;br /&gt;
The colour pallete has been expanded to 4096 colours from 512.  Support for&lt;br /&gt;
Vertical and Horizontal scrolling has been added to the hardware.&lt;br /&gt;
&lt;br /&gt;
                                SOUND&lt;br /&gt;
&lt;br /&gt;
Stereo 8-bit DMA sound has been added to the system along with volume and tone&lt;br /&gt;
control.&lt;br /&gt;
&lt;br /&gt;
                             CONTROLLERS&lt;br /&gt;
&lt;br /&gt;
New controllers ports have been added to allow keypad type joysticks, analog&lt;br /&gt;
paddies and a light pen.&lt;br /&gt;
&lt;br /&gt;
                         GENLOCK AND THE STE&lt;br /&gt;
&lt;br /&gt;
The ST (and STE) chip set have the ability to accept external sync.  This is&lt;br /&gt;
controlled by bit 0 at FF820A, as documented in the ST Hardware Specification.&lt;br /&gt;
This was done to allow the synchronization Å of the ST video with an external&lt;br /&gt;
source (a process usually known as GENLOCK).  However, in order to do this&lt;br /&gt;
reliably the system clock must also be phase-locked (or synchonized in some&lt;br /&gt;
other way) to the imput sync signals.  No way to do this was provided in the&lt;br /&gt;
ST, as a result the only GENLOCKs available are internal modifications (usually&lt;br /&gt;
for the MEGA).&lt;br /&gt;
&lt;br /&gt;
The STE allows this to be done without opening the case.  To inject a system&lt;br /&gt;
clock ground pin three (GPO) on the monitor connector and then inject the clock&lt;br /&gt;
into pin 4 (mono direct).  The internal frequency of this clock is 32.215905 MHz&lt;br /&gt;
(NTSC) and 31.922046 MHz (PAL).&lt;br /&gt;
&lt;br /&gt;
Note:  DO NOT SWITCH CLOCK SOURCE WHILE THE SYSTEM IS ACTIVE.&lt;br /&gt;
       (As a result of this GPO is no longer available).&lt;br /&gt;
&lt;br /&gt;
                              JOY STICKS&lt;br /&gt;
&lt;br /&gt;
Four new joystick ports are added.  These ports are controlled Å directly by the&lt;br /&gt;
68000.  The current state may be sampled at any time by reading the locations.&lt;br /&gt;
Joystick 0 and Joystick 2 direction bits are read/write.  If written to they&lt;br /&gt;
will be driven until a read is performed.  Similarly, they will not be driven&lt;br /&gt;
after a read until a write is performed.&lt;br /&gt;
&lt;br /&gt;
                               PADDLES&lt;br /&gt;
&lt;br /&gt;
One pair of paddles can be plugged into Joystick 0 (Paddle 0).  A second set&lt;br /&gt;
can be plugged into Joystick 1 (Paddle 1).  The current position of each of the&lt;br /&gt;
four paddles is reported at these locations.  The fire buttons are the same as&lt;br /&gt;
for the respective joystick.  The triggers for the paddles are read as bits one&lt;br /&gt;
and two of FF9202 (JOY 0 Left and Right).&lt;br /&gt;
&lt;br /&gt;
                           LIGHT GUN / PEN&lt;br /&gt;
&lt;br /&gt;
A light gun or pen can be plugged into Joystick 0.  The current position that&lt;br /&gt;
the gun or pen is pointing to is reported by these registers.  The position is&lt;br /&gt;
accurate to within (X direction only):&lt;br /&gt;
&lt;br /&gt;
                        4 Pixels in 320*200 Mode&lt;br /&gt;
                        8 Pixels in 640*200 Mode&lt;br /&gt;
                       16 Pixels in 640*400 Mode&lt;br /&gt;
&lt;br /&gt;
Accurate to 1 pixel in the Y direction in all modes.  Accuracies do not account&lt;br /&gt;
for the quality of the light gun or pen.  Note that the X position is given in&lt;br /&gt;
pixels for 320*200 only.  In order to get correct results in 640*200 mode this&lt;br /&gt;
number needs to be shifted left one bit and in 640*400 mode this number needs to&lt;br /&gt;
be shifted left two bits.&lt;br /&gt;
&lt;br /&gt;
             HOW TO IMPLEMENT FINE SCROLLING ON THE STE.&lt;br /&gt;
&lt;br /&gt;
Three new registers are provided to implement fine-scrolling and split screen&lt;br /&gt;
displays:&lt;br /&gt;
&lt;br /&gt;
1) HSCROLL - This register contains the pixel scroll offset.  If it is zero,&lt;br /&gt;
   this is the same as an ordinary ST.  If it is non-zero, it indicates which&lt;br /&gt;
   data bits constitute the first pixel from the first data word(S) of a given&lt;br /&gt;
   line by this register.&lt;br /&gt;
&lt;br /&gt;
2) LINEWID - This register indicates the number of extra words of data (beyond&lt;br /&gt;
   that required by an ordinary ST at the same resolution) which represents a&lt;br /&gt;
   single display line.  If it is zero, this is the same as an ordinary ST.  If&lt;br /&gt;
   it is non-zero, that many additional words of data will constitute a single&lt;br /&gt;
   video line (thus allowing virtual screens wider than the displayed screen).&lt;br /&gt;
   CAUTION: In fact, this register contains the word offset which the display&lt;br /&gt;
   processor will add to the video display address to point to the next line.&lt;br /&gt;
   If you are actively scrolling (HSCROLL &amp;lt;&amp;gt; 0), this register should contain&lt;br /&gt;
   the additional width of a display line minus one data fetch (in low&lt;br /&gt;
   resolution one data fetch would be four words, one word for monochrome, etc).&lt;br /&gt;
&lt;br /&gt;
3) VBASELO - This register contains the low-order byte of the video display base&lt;br /&gt;
   address.  It can be altered at any time and will not affect the display until&lt;br /&gt;
   the next vertical blank interrupt.&lt;br /&gt;
&lt;br /&gt;
The following registers have been changed on the STE to allow greater control&lt;br /&gt;
over the display:&lt;br /&gt;
&lt;br /&gt;
1) VIDEO ADDRESS COUNTER - Now read/write.  Allows update of the video refresh&lt;br /&gt;
address during the frame.  The effect is immediate, therefore it should be&lt;br /&gt;
reloaded carefully (or during blanking) to provide reliable results.&lt;br /&gt;
&lt;br /&gt;
2) COLOUR PALLETE - A fourth bit of resolution is added to each colour.  Note&lt;br /&gt;
that the least significant bit is added above the old most significant bit to&lt;br /&gt;
remain compatible with the ST.&lt;br /&gt;
&lt;br /&gt;
These registers, when used in combination, can provide several video effects.&lt;br /&gt;
In this document we will discuss only fine-scrolling and split-scrolling &lt;br /&gt;
displays.&lt;br /&gt;
&lt;br /&gt;
FINE SCROLLING:&lt;br /&gt;
Many games use horizontal and vertical scrolling techniques to provide virtual&lt;br /&gt;
playfields which are larger than a single screen.  We will first discuss&lt;br /&gt;
vertical scrolling (line-wise), then horizontal scrolling (pixel-wise) and&lt;br /&gt;
finally the example program &amp;quot;neowall.s&amp;quot; which combines both.&lt;br /&gt;
&lt;br /&gt;
VERTICAL SCROLLING:&lt;br /&gt;
To scroll line-wise, we simply alter the video display address by one line each&lt;br /&gt;
time we wish to scroll one line.  This is done at vertical blank interrupt time&lt;br /&gt;
by writing to the three eight-bit video display address registers to define&lt;br /&gt;
a twenty-four bit pointer to memory.  Naturally, additional data must be &lt;br /&gt;
available to be displayed.  We might imagine this as a tall, skinny screen&lt;br /&gt;
which we are opening onto for the user. The video display address registers&lt;br /&gt;
define where this window will start.&lt;br /&gt;
&lt;br /&gt;
HORIZONTAL SCROLLING: &lt;br /&gt;
To scroll horizontally we might also adjust the video display address. If that&lt;br /&gt;
was all we did, we would find that the screen would jump sideways in sixteen&lt;br /&gt;
pixel incements.  To achieve smooth pixel-wise scrolling we must use the HSCROLL&lt;br /&gt;
register to select where within each sixteen pixel block we wish to start &lt;br /&gt;
displaying data to the screen.  Finally, we must adjust the LINEWID register to&lt;br /&gt;
reflect both the fact that each line of video data is wider than a single &lt;br /&gt;
display line and any display processor fetch incurred by a non-zero value of&lt;br /&gt;
HSCROLL.  All this is done at vertical blank interrupt time.  Naturally,&lt;br /&gt;
additional data must be available to be displayed.  We might imagine this is&lt;br /&gt;
an extremely wide screen which we are opening a window onto for the user.&lt;br /&gt;
These registers define where this window will start.&lt;br /&gt;
&lt;br /&gt;
FOR EXAMPLE:&lt;br /&gt;
The program &amp;quot;neowall.s&amp;quot; reads in nine NEOchrome picture files, organizes them&lt;br /&gt;
into a three by three grid and allows the user to scroll both horizontally and&lt;br /&gt;
vertically over the images.  The heart of this program (the only interesting&lt;br /&gt;
thing about it actually) is the vertical blank interrupt server.  This routine&lt;br /&gt;
first determines the pixel offset and loads it into HSCROLL.  The LINEWID&lt;br /&gt;
register is now set to indicate that each virtual line is three times longer&lt;br /&gt;
than the actual display width.  If we are now actively scrolling, this amount&lt;br /&gt;
is reduced to reflect the additional four-plane data fetch which will be &lt;br /&gt;
caused by the scrolling.  Finally the video display address is computed to&lt;br /&gt;
designate a window onto the grid of pictures.  This twenty-four-bit address&lt;br /&gt;
determines where the upper left corner of the displayed region begins in&lt;br /&gt;
memory.  Thus, every frame an arbitrary portion of the total image is selected&lt;br /&gt;
for display.  The speed and resolution of this scrolling technique is limited&lt;br /&gt;
only by the dexterity of the user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SPLIT SCREEN:&lt;br /&gt;
In many applications it is desirable to subdivide the screen into several&lt;br /&gt;
independent regions.  On the STE you may reload some video registers on a &lt;br /&gt;
line-by-line besis (using horizontal blanking interrupts) to split the screen&lt;br /&gt;
vertically into multiple independent regions.  A single screen no longer need&lt;br /&gt;
be a contiguous block of storage, but could be composed of dozens of strips&lt;br /&gt;
which might reside in memory in any other.  The same data could be repeated on&lt;br /&gt;
one or more display lines.  Individual regions might each have their own &lt;br /&gt;
individual data and scrolling directions.&lt;br /&gt;
&lt;br /&gt;
FOR EXAMPLE:&lt;br /&gt;
The program &amp;quot;hscroll.s&amp;quot; reads in a NEOchrome picture file and duplicates each&lt;br /&gt;
line of the image.  This, combined with the proper use of LINWID, effectively&lt;br /&gt;
places two copies of the same picture side-by-side.  Next, both vertical and &lt;br /&gt;
horizontal blanking interrupt vectors are captured and the horizontal blanking&lt;br /&gt;
interrupt is enabled in counter mode.  To prevent flicker caused by keyboard&lt;br /&gt;
input, the IKBD/MIDI interrupt priority is lowered below that of the HBL &lt;br /&gt;
interrupt.  Note that the program 'main loop' doesn't even call the BIOS to&lt;br /&gt;
check the keyboard, since the BIOS sets the IPL up causes flicker by locking&lt;br /&gt;
out horizontal interrupts - this may cause trouble for programs in the real&lt;br /&gt;
world.  The screen is effectively divided into ten regions which scroll&lt;br /&gt;
independently of one another.  There are two ten-element arrays which contain&lt;br /&gt;
the base address of each region and its current scroll offset.  At vertical&lt;br /&gt;
blank interrupt time we compute the final display values for each region in&lt;br /&gt;
advance and store them into a third array.  We then initialize the display&lt;br /&gt;
processor for the first region and request an interrupt every twenty lines &lt;br /&gt;
(actually every twenty horizontal blankings).  During each horizontal interrupt&lt;br /&gt;
service, we quickly reload the video display address registers and the HSCROLL&lt;br /&gt;
register.  This must be done immediately - before the display processor has&lt;br /&gt;
time to start the current line or garbage may result.  Note that horizontal&lt;br /&gt;
blank interrupts are triggered by the display processor having finished reading&lt;br /&gt;
the previous data line.  You have approximately 144 machine cycles to reload&lt;br /&gt;
the HSCROLL and video display registers before they will be used again by the&lt;br /&gt;
display processor finishes reading the data for the current display line.  We&lt;br /&gt;
then pre-compute the data we will need for the next horizontal interrupt to&lt;br /&gt;
shave few more cycles off the critical path and exit.&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
                      STE DIGITIZED SOUND OVERVIEW&lt;br /&gt;
&lt;br /&gt;
Sound  is stored in memory as digitized samples.  Each sample is a number, &lt;br /&gt;
from -128 to +127, which represents displacement of the speaker from the&lt;br /&gt;
&amp;quot;neutral&amp;quot; or middle possition.  During horizontal blanking (transparent&lt;br /&gt;
to the processor) the DMA sound chip fetches samples from memory and provides&lt;br /&gt;
them to a digital-to-analog canverter (DCA) at one of several constant&lt;br /&gt;
rates, programmable as (approximately) 50KHz (kilohertz), 25 Khz, 12.5KHz,&lt;br /&gt;
and 6.25KHz.  This rate is called the sample frequency.&lt;br /&gt;
&lt;br /&gt;
The output of the DAC is then filtered to a frequency equal to 40% of the&lt;br /&gt;
sample frequency by a four-pole switched low-pass filter.  This program&lt;br /&gt;
&amp;quot;anti-aliasing&amp;quot; of the sound data in a sample- frequency-sensitive way.&lt;br /&gt;
The signal is further filtered by a two-pole fixed frequency (16KHz)&lt;br /&gt;
low-pass filter and provided to a National LMC1992 Volume/Tone Controller.&lt;br /&gt;
Finally, the output is available at an RCA-style output jack on the back &lt;br /&gt;
of the computer.  This can be fed into an amplifier, and then to speakers,&lt;br /&gt;
headphones, or tape recorders.&lt;br /&gt;
 &lt;br /&gt;
There are two channels which behave as described above; they are intended&lt;br /&gt;
to be used as the left and right channels of a stereo system when using the&lt;br /&gt;
audio outputs of the machine.  A monophonic mode is provided which will &lt;br /&gt;
send the same sample data to each channel.&lt;br /&gt;
&lt;br /&gt;
The stereo sound output is also mixed onto the standard ST audio output&lt;br /&gt;
sent to the monitor's speaker.  The ST's GI sound chip output can be mixed&lt;br /&gt;
to the monitor and to both stereo output jacks as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                            DATA FORMAT&lt;br /&gt;
&lt;br /&gt;
Each sample is stored as a signed eight-bit quantity, where - 128 (80 hex) &lt;br /&gt;
means full negative displacement of the speaker, and 127 (7F hex) means full&lt;br /&gt;
positive displacement.  In some stereo mode, each word represents two&lt;br /&gt;
samples: the upper byte is the sample for the left channel, and the lower &lt;br /&gt;
byte is the sample for the right channel.  In mono mode each byte is one&lt;br /&gt;
sample.  However, the samples are always fetched a word at a time, so only&lt;br /&gt;
an even number of mono samples can be played.&lt;br /&gt;
&lt;br /&gt;
A group of samples is called a &amp;quot;frame&amp;quot;.  A frame may be played once or can&lt;br /&gt;
automatically be repeated forever (until sotpped).  A frame is described by&lt;br /&gt;
its start and end addresses.  The end address of a frame is actually the&lt;br /&gt;
address of the first byte in memory beyond the frame; a frame starting at&lt;br /&gt;
address 21100 which is 10 bytes long has an end address of 21110.&lt;br /&gt;
&lt;br /&gt;
Note:  a zero can be written to the DMA sound control register at any&lt;br /&gt;
time to stop playback immediately.&lt;br /&gt;
&lt;br /&gt;
                        PROGRAMMING CONSIDERATIONS&lt;br /&gt;
&lt;br /&gt;
The simplest way to produce a sound is to assemble a frame in memory,&lt;br /&gt;
write the start address of the frame into the Frame Start Address register,&lt;br /&gt;
and the end address of the frame into the Frame End address register, set&lt;br /&gt;
the Mode register appropriately (set stereo to mono, and the sample &lt;br /&gt;
frequency), and write a one into the Sound DMA Control register.  The frame&lt;br /&gt;
will play once, then stop.&lt;br /&gt;
&lt;br /&gt;
To produce continuous sound, and link frames together, more elaborate &lt;br /&gt;
techniques are required.&lt;br /&gt;
&lt;br /&gt;
The DMA sound chip produces a signal called &amp;quot;DMA sound active&amp;quot; which is one&lt;br /&gt;
when the chip is playing sounds, and a zero when it's not.  When a frame ends &lt;br /&gt;
in the repeat mode (mode 3), there is a transition from &amp;quot;active&amp;quot; to &amp;quot;idle&amp;quot;&lt;br /&gt;
and back again on this signal.  The signal is presented as the external input&lt;br /&gt;
to MFP Timer A.  You can put Timer A into Event Count mode and use it to &lt;br /&gt;
generate an interrupt, for example when a frame has played a given number&lt;br /&gt;
of timees.  Because of the design of the MFP, the active edge for this signal&lt;br /&gt;
must be the same as the input on GPIP 14, which is the interrupt line from&lt;br /&gt;
the keyboard and MIDI interfaces.  It is, and the Active Edge Register is &lt;br /&gt;
already programmed for that, so you need not worry about that if you use &lt;br /&gt;
Timer A to count frames.&lt;br /&gt;
&lt;br /&gt;
The DMA Sound Chip's mode 3 (repeat mode) ensures seamless linkage of frames, &lt;br /&gt;
because the start and end registers are actually double-buffered.  When you&lt;br /&gt;
write to these resisters, what you write really goes into a &amp;quot;holding area&amp;quot;.&lt;br /&gt;
The contents of the holding area go into the true registers at the end of the&lt;br /&gt;
current frame.  (Actually, they go in when the chip is idle, which means right&lt;br /&gt;
away if the chip was idle to begin with.)&lt;br /&gt;
&lt;br /&gt;
If you have two frames which you want played in succession, you can write the &lt;br /&gt;
start and end address of the first frame into the chip, then set its control &lt;br /&gt;
register to 3.  The first frame will begin playing.  You can then immediately&lt;br /&gt;
write the start and end addresses of the second frame into the chip: they will&lt;br /&gt;
be held in the holding area until the first frame finishes, then they'll be&lt;br /&gt;
copied into the true registers and the second frame will play.  The interrupt&lt;br /&gt;
between frames will still happen, so you can tell when the first frame has&lt;br /&gt;
finished.  Then, for instance, you can write the start and end registers for&lt;br /&gt;
the start of the third frame, knowing that it will begin as soon as the second &lt;br /&gt;
frame has finished.  You could even write new data into the first frame and&lt;br /&gt;
write its start and end address into the chip; this kind of ping-pong&lt;br /&gt;
effect is rather like double-buffering of a graphics display.&lt;br /&gt;
&lt;br /&gt;
Here is an example of using Timer A in Event Count mode to play a controlled&lt;br /&gt;
series of frames.  Suppose you have three frames, A, B and C, and you want to&lt;br /&gt;
play frame A three times, then frame B five times, and finally frame C twice.&lt;br /&gt;
The sequence of steps below will accomplish this.  Numbered steps are carried&lt;br /&gt;
out by your program; the bracketed descriptions are of things which are&lt;br /&gt;
happening as a result.&lt;br /&gt;
&lt;br /&gt;
        1.  Set Timer A to event count mode, and its counter to 2 (not 3)&lt;br /&gt;
&lt;br /&gt;
        2.  Write Frame A's start and end addresses into the registers.&lt;br /&gt;
&lt;br /&gt;
        3.  Write a 3 to the sound DMA control register.  [Play begins.]  Go&lt;br /&gt;
            do something else until interrupted.&lt;br /&gt;
&lt;br /&gt;
            [At the end of the sound repition of Frame A, the timer's &lt;br /&gt;
            interrupt fires.  At the same time, frame A begins its third&lt;br /&gt;
            repetition.]&lt;br /&gt;
&lt;br /&gt;
        4.  Write Frame B's start and end addresses into the DMA sound chip.&lt;br /&gt;
            These values will be held until the third repetition of Frame A&lt;br /&gt;
            finishes.&lt;br /&gt;
&lt;br /&gt;
        5.  Set Timer A's count register to 5, then go away until &lt;br /&gt;
            interrupted.&lt;br /&gt;
&lt;br /&gt;
            [When the current repetition finishes, the start and end&lt;br /&gt;
            registers are loaded fron the holding area, and Frame B will&lt;br /&gt;
            begin playing.  The end of play signal will cause Timer A to &lt;br /&gt;
            count from 5 to 4.  At the end of Frame B's fourth repetition,&lt;br /&gt;
            its fifth will start, the timer will count down from 1 to 0,&lt;br /&gt;
            and the interrupt will occur.]&lt;br /&gt;
&lt;br /&gt;
        6.  Write frame C's start and end addresses into the registers, and&lt;br /&gt;
            program Timer A to count to 2.  Go away until interrupted.&lt;br /&gt;
&lt;br /&gt;
            [When the current repetition (B's fifth) finishes, the start&lt;br /&gt;
            and end registers are loaded from the holding area, and Frame C&lt;br /&gt;
            will begin playing.  The end-of-frame signal causes Timer A to&lt;br /&gt;
            count down from 2 to 1.  When Frame C finishes its first&lt;br /&gt;
            repetition, Timer A counts down from 1 to 0 and interrupts.]&lt;br /&gt;
&lt;br /&gt;
        7.  Write a 1 to the DMA Sound Control Register to play the current&lt;br /&gt;
            frame, then stop.  Disable TimerA and mask its interrupt.&lt;br /&gt;
            You're done.&lt;br /&gt;
&lt;br /&gt;
As you can see you program the timer to interrupt after one repetition less&lt;br /&gt;
than the number of times you want a frame to play.  That is so you can set up&lt;br /&gt;
the next frame while the DMA sound chip is playing the last repetition of the &lt;br /&gt;
current frame.  This ensures seamless linkage of frames.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                    INTERRUPTS WITHOUT TIMER A&lt;br /&gt;
        &lt;br /&gt;
Besides going to the external input signal of Timer A, the DMA-sound-active&lt;br /&gt;
signal, true high, is exclusive-ORed with the monochrome-detect signal, and&lt;br /&gt;
together they form the GPIP 17 input to the M68901 MFP.  The intent of this &lt;br /&gt;
is to provide for interrupt-driven sound drivers without using up the last&lt;br /&gt;
general-purpose timer in the MFP.  It is a little trickier to use, however.&lt;br /&gt;
For one thing, it causes the interrupt at the end of every frame, not after&lt;br /&gt;
a specified number of frames.  For another, the &amp;quot;interesting&amp;quot; edge on this&lt;br /&gt;
signal depends on what kind of monitor you have.&lt;br /&gt;
&lt;br /&gt;
On an ST, monochrme monitors ground the mono-detect signal, so when you read&lt;br /&gt;
the bit in the MFP you get a zero.  Colour monitors do not ground it, so it&lt;br /&gt;
reads as a one.  When the DMA sound is idle (0), this is still the case.&lt;br /&gt;
However, when the sound is active (1), the mono-detect signal is inverted by&lt;br /&gt;
the XOR, so the bit in the MFP reads the opposite way.  (the one place where&lt;br /&gt;
the OS reads this bit as at VBLANK time, to see if you've changed monitors.&lt;br /&gt;
The ROMs on any machine with DMA sound are approprietely modified, so you&lt;br /&gt;
need not worry about this.)&lt;br /&gt;
&lt;br /&gt;
If you want to use the mono-detect / DMA interrupt signal, you have to set up &lt;br /&gt;
the active-edge register in the MFP to cause the interrupt at the right time.&lt;br /&gt;
The interesting edge on the DMA signal is the falling edge, that is, from &lt;br /&gt;
active to idle; this happens when a frame finishes.  If you have a monochrome&lt;br /&gt;
monitor, this edge is seen as a transition from 1 to 0 on MFP bit 17.&lt;br /&gt;
However, with a colour monitor, the edge will be seen as a transition from&lt;br /&gt;
0 to 1.  Therefore, you have to program the MFP's active-edge regisrer&lt;br /&gt;
differently depending on which monitor you have.  Make sure the DMA sound is &lt;br /&gt;
idle (write a zero to the control register), then check MFP 17: if it's one,&lt;br /&gt;
you have a colour monitor, and you need to see the rising edge.  If it's&lt;br /&gt;
zreo, you have a monochrome monitor, and you need to see the falling edge.&lt;br /&gt;
&lt;br /&gt;
The DMA sound active signal goes from &amp;quot;active&amp;quot; to &amp;quot;idle&amp;quot; when a frame &lt;br /&gt;
finishes.  If it was playing in mode one, it stays &amp;quot;idle&amp;quot; and the control&lt;br /&gt;
register reverts to zero.  If it was playing in mode 3 the signal goes&lt;br /&gt;
back to &amp;quot;active&amp;quot; as the next frame begins.  In this case, the signal is&lt;br /&gt;
actually in the &amp;quot;idle&amp;quot; state for a very short time, but the MFP catches it&lt;br /&gt;
and causes the interrupt, so don't worry.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                      ADDITIONAL CONSIDERATIONS&lt;br /&gt;
&lt;br /&gt;
Regardless of how you manage your interrupts, there is more you should know:&lt;br /&gt;
the signal goes from &amp;quot;active&amp;quot; to &amp;quot;idle&amp;quot; when the DMA sound chip has fetched&lt;br /&gt;
the last sample in the frame.  There is a four-word FIFO in the chip,&lt;br /&gt;
however, so it will be eight sample-times (four in stereo mode) before the&lt;br /&gt;
sound actually finishes.  If you are using mode 1, you can use this time to&lt;br /&gt;
set up the chip with the start and end addresses of the next frame, so it &lt;br /&gt;
will start as soon as the current one ends.  However, if the interrupt&lt;br /&gt;
should be postponed for four or eight sample-times, you could miss your &lt;br /&gt;
chance to start the sound seamlessly.  Therefore, for seamless linkage,&lt;br /&gt;
use the pre-loading technique described above.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                          MICROWIRE INTERFACE&lt;br /&gt;
&lt;br /&gt;
The MICROWIRE interface provided to talk to the national LMC1992 Computer&lt;br /&gt;
Controlled Volume / Tone Control is a general purpose MICROWIRE interface&lt;br /&gt;
to allow the future addition of other MICROWIRE devices.  For this reason,&lt;br /&gt;
the following description of its use will make no assumptions about the &lt;br /&gt;
device being addressed.&lt;br /&gt;
&lt;br /&gt;
The MICROWIRE bus is a three wire serial connection and protocol designed to&lt;br /&gt;
allow multiple devices to be individually addresses by the controller. The&lt;br /&gt;
lengh of the serial data straem depends on the destination device.  In &lt;br /&gt;
general, the stream consists of N bits of address, followed by zero or more &lt;br /&gt;
don't care bits, followed by M bits of data.  The hardware interface&lt;br /&gt;
provided consists of two 16 bit read/write registers: one data register&lt;br /&gt;
which contains the actual bit stream to be shifted out, and one mask register&lt;br /&gt;
which indicates which bits are valid.&lt;br /&gt;
&lt;br /&gt;
Let's consider a mythical device which requires two address bits and one data &lt;br /&gt;
bit.  For this device the total bit stream is three bits (minimum).  Any &lt;br /&gt;
three bits of the register pair may be used.  However, since the most &lt;br /&gt;
significant bit is shifted first, the commanmd will be received by the device&lt;br /&gt;
soonest if the three most if the three most significant bits are used.  Let's&lt;br /&gt;
assume: 01 is the devise's address, D is the data to be written, and X's are&lt;br /&gt;
don't cares.  Then all of the following register combinations will provide &lt;br /&gt;
the same information to the device.&lt;br /&gt;
&lt;br /&gt;
1110 0000 0000 0000 Mask&lt;br /&gt;
01DX XXXX XXXX XXXX Data&lt;br /&gt;
&lt;br /&gt;
0000 0000 0000 0111 Mask&lt;br /&gt;
XXXX XXXX XXXX X01D Data&lt;br /&gt;
&lt;br /&gt;
0000 0001 1100 0000 Mask&lt;br /&gt;
XXXX XXX0 1DXX XXXX Data&lt;br /&gt;
&lt;br /&gt;
0000 1100 0001 0000 Mask&lt;br /&gt;
XXXX 01XX XXXD XXXX Data&lt;br /&gt;
&lt;br /&gt;
1100 0000 0000 0001 Mask&lt;br /&gt;
01XX XXXX XXXX XXXD Data&lt;br /&gt;
&lt;br /&gt;
As you can see, the address bits must be contigious, and so must the data&lt;br /&gt;
bits, but they don't have to be contiguous with each other.&lt;br /&gt;
&lt;br /&gt;
The mask register must be written before the data register.  Sending&lt;br /&gt;
commences when the data register is written and takes approximately 16usec.&lt;br /&gt;
Subsequent writes to the data and mask registers are blocked until sending&lt;br /&gt;
is complete.  Reading the registers while sending is in progress will&lt;br /&gt;
return a snapshot of the shift register shifting the data and mask out.&lt;br /&gt;
This means that you know it is safe to send the next command when these&lt;br /&gt;
registers (or either one) return to thier original state.  Note that the&lt;br /&gt;
mask register does not need to be rewritten if it is already correct.  &lt;br /&gt;
That is, when sending a series of commands the mask register only needs&lt;br /&gt;
to be written once.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                       VOLUME AND TONE CONTROL&lt;br /&gt;
&lt;br /&gt;
The LMC1992 is used to provide volume and tone control.  Before you go and&lt;br /&gt;
find a data sheet for this part, be warned that we do not use all of its &lt;br /&gt;
features.  Commands for the features we do use are listed below.&lt;br /&gt;
&lt;br /&gt;
Communication with this device is achieved using the MICROWIRE interface.&lt;br /&gt;
See MICROWIRE INTERFACE the section for details.  The device has a two&lt;br /&gt;
bit address field, address = 10, and a nine bit data field.  There is no&lt;br /&gt;
way to reading the current setting.&lt;br /&gt;
&lt;br /&gt;
                    VOLUME / TONE CONTROLLER COMMANDS&lt;br /&gt;
&lt;br /&gt;
Device address = 10 (Address precedes command)&lt;br /&gt;
&lt;br /&gt;
Data field&lt;br /&gt;
&lt;br /&gt;
001 DDD DDD Set Master Volume&lt;br /&gt;
    000 000 -80 dB&lt;br /&gt;
    010 100 -40 dB&lt;br /&gt;
    101 XXX  0 dB&lt;br /&gt;
&lt;br /&gt;
101 XDD DDD Set Left Channel Volume&lt;br /&gt;
     00 000 -40 dB&lt;br /&gt;
     01 010 -20 dB&lt;br /&gt;
     10 1XX  0 dB&lt;br /&gt;
&lt;br /&gt;
100 XDD DDD Set Right Channel Volume&lt;br /&gt;
     00 000 -40 dB&lt;br /&gt;
     01 010 -20 dB&lt;br /&gt;
     10 1XX  0 dB&lt;br /&gt;
&lt;br /&gt;
010 XXD DDD Set Treble&lt;br /&gt;
      0 000 -12 dB&lt;br /&gt;
      0 100  0 dB (Flat)&lt;br /&gt;
      1 100 =12 dB&lt;br /&gt;
&lt;br /&gt;
001 XXD DDD Set Base&lt;br /&gt;
      0 000 -12 dB&lt;br /&gt;
      0 110  0 dB (Flat)&lt;br /&gt;
      1 100 +12 dB&lt;br /&gt;
&lt;br /&gt;
000 XXX XDD Set Mix&lt;br /&gt;
         00 -12 dB&lt;br /&gt;
         01 Mix GI sound chip output&lt;br /&gt;
         10 Do not mix GI sound chip output&lt;br /&gt;
         11 reserved&lt;br /&gt;
&lt;br /&gt;
Note: The volume controls attenuate in 2 dB streps.  The tone controls&lt;br /&gt;
attenuate in 2 dB steps at 50 kHz (Note that these frequencies may change).&lt;br /&gt;
&lt;br /&gt;
      USING THE MICROWIRE INTERFACE AND THE VOLUME/TONE CONTROL CHIP&lt;br /&gt;
&lt;br /&gt;
The MICROWIRE interface is not hard to use: once you get it right, you'll &lt;br /&gt;
never have to figure it out again.&lt;br /&gt;
&lt;br /&gt;
The easiest way to use it is to ignore the flexibility, and just use one&lt;br /&gt;
form for all commands.  Since the Volume/Tone chip is the only device, and &lt;br /&gt;
it has a total of 11 bits of address and data, your mask should be $07ff.&lt;br /&gt;
If you're picky, you can use $ffe0, because the high-order bits are shifted&lt;br /&gt;
out first, but it adds conceptual complexity.  With a mask of $07ff, the&lt;br /&gt;
lower 9 bits of the data register are used for the data, and the next higher&lt;br /&gt;
two bits are for the address:&lt;br /&gt;
&lt;br /&gt;
        Mask:   %0000 0111 1111 1111&lt;br /&gt;
        Data:   %xxxx x10d dddd dddd&lt;br /&gt;
&lt;br /&gt;
Replace the d's with the command code and its data.  For example, this&lt;br /&gt;
combination sets the master volume to $14:&lt;br /&gt;
&lt;br /&gt;
        Mask:   %0000 0111 1111 1111&lt;br /&gt;
        Data:   %xxxx x100 1101 0100&lt;br /&gt;
&lt;br /&gt;
The other important concept you must understand is that the bits shift out&lt;br /&gt;
of these registers as soon as you write the data, and it takes an appreciable&lt;br /&gt;
time (16 usec) to finish.  You can't attempt another write until the first &lt;br /&gt;
one is finished.  If you read either register while it's being shifted out,&lt;br /&gt;
you will see a &amp;quot;snapshot&amp;quot; of the data being shifted.  You know the shifting&lt;br /&gt;
is complete when the mask returns to its original value.  (This theory is&lt;br /&gt;
wrong if you use a mask which equals its original value sometime during the&lt;br /&gt;
shifting, but $07ff never does.)&lt;br /&gt;
&lt;br /&gt;
Assuming you write $07ff into the mask register ahead of time, the following&lt;br /&gt;
routine can be used to write new data from the D0 register to the volume/tone&lt;br /&gt;
control chip.&lt;br /&gt;
&lt;br /&gt;
        MWMASK  equ $ffff8924&lt;br /&gt;
        MWDATA  equ $ffff8922&lt;br /&gt;
        &lt;br /&gt;
        mwwrite:&lt;br /&gt;
             cmp.w      #$07ff,MWMASK  ; wait for prev to finish&lt;br /&gt;
             bne.s      mwwrite        ; loop until equal&lt;br /&gt;
             move.w     d0,MWDATA      ; write the data&lt;br /&gt;
             rts                       ; and return&lt;br /&gt;
&lt;br /&gt;
The purpose of the loop at the beginning is to wait until previous write&lt;br /&gt;
completes.&lt;br /&gt;
&lt;br /&gt;
This loop is at the beginning of the routine, not at the end because waiting&lt;br /&gt;
at the end would always force a sixteen usec delay.  Even if it has been longer&lt;br /&gt;
than that since the last write.&lt;br /&gt;
&lt;br /&gt;
-------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
                        NEW CONTROLLER PINOUT&lt;br /&gt;
&lt;br /&gt;
Arrangement (Looking towards STE):&lt;br /&gt;
                                               &lt;br /&gt;
                             5  4  3  2  1  &lt;br /&gt;
                            10  9  8  7  6                                   &lt;br /&gt;
                            15 14 13 12 11  &lt;br /&gt;
                                               &lt;br /&gt;
Connections (PORT A):&lt;br /&gt;
&lt;br /&gt;
1:  UP 0	5:  PAD 0Y	9:  GND	       13:  LT 2&lt;br /&gt;
2:  DN 0	6:  FIRE 0     10:  FIRE 2     14:  RT 2&lt;br /&gt;
3:  LT 0        7:  +5v        11:  UP 2       15:  PAD 0X&lt;br /&gt;
4:  RT 0        8:  n/c        12:  DN 2      &lt;br /&gt;
&lt;br /&gt;
Connections (PORT B):&lt;br /&gt;
&lt;br /&gt;
1:  UP 1	5:  PAD 1Y	9:  GND	       13:  LT 3&lt;br /&gt;
2:  DN 1	6:  FIRE 1     10:  FIRE 3     14:  RT 3&lt;br /&gt;
3:  LT 1        7:  +5v        11:  UP 3       15:  PAD 1X&lt;br /&gt;
4:  RT 1        8:  n/c        12:  DN 3      &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                     CONTROLLER MEMORY LOCATIONS&lt;br /&gt;
&lt;br /&gt;
FF9201             ---- 3120  RO  Fire Buttons&lt;br /&gt;
FF9202   UDLR UDLR UDLR UDLR  RW  Joystick 3/2/1/0 Directions&lt;br /&gt;
FF9211             xxxx xxxx  RO  X-Paddle 0&lt;br /&gt;
FF9213             xxxx xxxx  RO  Y-Paddle 0&lt;br /&gt;
FF9215             xxxx xxxx  RO  X-Paddle 1&lt;br /&gt;
FF9217             xxxx xxxx  RO  Y-Paddle 1&lt;br /&gt;
FF9220   ---- --xx xxxx xxxx  RO  Light Gun X-Pos&lt;br /&gt;
FF9222   ---- --xx xxxx xxxx  RO  Light Gun Y-Pos&lt;br /&gt;
&lt;br /&gt;
                     VIDEO REGISTER MODIFICATIONS&lt;br /&gt;
&lt;br /&gt;
FF8205             --xx xxxx  RW  Video Address High&lt;br /&gt;
FF8207             xxxx xxxx  RW  Video Address Mid&lt;br /&gt;
FF8209             xxxx xxx-  RW  Video Address Low&lt;br /&gt;
&lt;br /&gt;
FF820D             xxxx xxx-  RW  Video Base Address Low&lt;br /&gt;
FF820F             xxxx xxxx  RW  Over-Length Line Width&lt;br /&gt;
FF8264             ---- xxxx  RW  Undocumented HSCROLL register: no extra fetch&lt;br /&gt;
FF8265             ---- xxxx  RW  Documented HSCROLL register&lt;br /&gt;
&lt;br /&gt;
FF8240+  ---- 0321 0321 0321  RW  Red/Green/Blue Colour settings&lt;br /&gt;
&lt;br /&gt;
                             DMA SOUND REGISTERS&lt;br /&gt;
&lt;br /&gt;
FF8901             ---- --cc  RW  Sound DMA Control&lt;br /&gt;
&lt;br /&gt;
     cc:&lt;br /&gt;
     00   Sound DMA disabled (reset state).&lt;br /&gt;
     01   Sound DMA enabled, disable at end of frame.&lt;br /&gt;
     11   Sound DMA enabled, repeat frame forever.&lt;br /&gt;
&lt;br /&gt;
FF8903             --xx xxxx  RW  Frame Base Address (high)&lt;br /&gt;
FF8905             xxxx xxxx  RW  Frame Base Address (middle)&lt;br /&gt;
FF8907             xxxx xxx-  RW  Frame Base Address (low)&lt;br /&gt;
&lt;br /&gt;
FF8909             --xx xxxx  RO  Frame Address Counter (high)&lt;br /&gt;
FF890B             xxxx xxxx  RO  Frame Address Counter (middle)&lt;br /&gt;
FF890D             xxxx xxx-  RO  Frame Address Counter (low)&lt;br /&gt;
&lt;br /&gt;
FF890F             --xx xxxx  RW  Frame End Address (high)&lt;br /&gt;
FF8911             xxxx xxxx  RW  Frame End Address (middle)&lt;br /&gt;
FF8913             xxxx xxx-  RW  Frame End Address (low)&lt;br /&gt;
FF8921             m--- --rr  RW  Sound Mode Control&lt;br /&gt;
&lt;br /&gt;
     rr:&lt;br /&gt;
     00   6258 Hz sample rate (reset state)&lt;br /&gt;
     01  12517 Hz sample rate&lt;br /&gt;
     10  25033 Hz sample rate&lt;br /&gt;
     11  50066 Hz sample rate&lt;br /&gt;
     m:&lt;br /&gt;
     0    Stereo Mode (reset state)&lt;br /&gt;
     1    Mono Mode&lt;br /&gt;
&lt;br /&gt;
FF8922  xxxx xxxx xxxx xxxx  RW  MICROWIRE Data register&lt;br /&gt;
FF8924  xxxx xxxx xxxx xxxx  RW  MICROWIRE Mask register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>&gt;Ggn</name></author>
	</entry>
</feed>