<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://oldwiki.cpcwiki.eu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=80.167.220.254</id>
		<title>CPCWiki - THE Amstrad CPC encyclopedia! - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://oldwiki.cpcwiki.eu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=80.167.220.254"/>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php/Special:Contributions/80.167.220.254"/>
		<updated>2026-08-28T13:10:31Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&amp;diff=15092</id>
		<title>Technical information about Locomotive BASIC</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Technical_information_about_Locomotive_BASIC&amp;diff=15092"/>
				<updated>2007-03-14T17:47:15Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The are two versions of Locomotive BASIC used in the Amstrad CPC and CPC+ computers. v1.0 is used by the CPC464, and v1.1 is used by the CPC664, CPC6128, CPC464+ and CPC6128+.&lt;br /&gt;
&lt;br /&gt;
== Passing parameters to a RSX (Resident System Extension) command or binary function ==&lt;br /&gt;
&lt;br /&gt;
A RSX (Resident System Extension) command is accessed through BASIC with a &amp;quot;|&amp;quot; character prefix. e.g. The &amp;quot;DIR&amp;quot; RSX, is accessed by &amp;quot;|DIR&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
A binary function is accessed through BASIC using the &amp;quot;CALL&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
Passing a string parameter:&lt;br /&gt;
&lt;br /&gt;
BASIC v1.0&lt;br /&gt;
 &lt;br /&gt;
a$=&amp;quot;A&amp;quot;:|DRIVE,@a$&lt;br /&gt;
&lt;br /&gt;
BASIC v1.1:&lt;br /&gt;
&lt;br /&gt;
|DRIVE,&amp;quot;A&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Additional keywords and variables in BASIC v1.1 ==&lt;br /&gt;
&lt;br /&gt;
* BASIC v1.1 has the following additional keywords:&lt;br /&gt;
&lt;br /&gt;
:* COPYCHR$&lt;br /&gt;
:* CURSOR&lt;br /&gt;
:* DEC$&lt;br /&gt;
:* FILL&lt;br /&gt;
:* FRAME&lt;br /&gt;
:* GRAPHICS&lt;br /&gt;
:* MASK &lt;br /&gt;
&lt;br /&gt;
* BASIC v1.1 has the following additional predefined variables:&lt;br /&gt;
&lt;br /&gt;
:* DERR &lt;br /&gt;
&lt;br /&gt;
== Entering BASIC programs ==&lt;br /&gt;
&lt;br /&gt;
A maximum of 255 characters can be entered for a single BASIC line.&lt;br /&gt;
&lt;br /&gt;
This is converted into the tokenised BASIC program which is more compact than the line entered. The BASIC keywords are converted into &amp;quot;tokens&amp;quot;, or 1-2 byte sequences which uniquely identify each keyword.&lt;br /&gt;
&lt;br /&gt;
== Structure of a BASIC program ==&lt;br /&gt;
&lt;br /&gt;
A BASIC program is stored in a tokenised format. Here the keywords are represented by 1 or 2 byte unique sequences.&lt;br /&gt;
&lt;br /&gt;
Each line of the BASIC program has the form:&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable|width: 700px; font-size: 2em;}}&lt;br /&gt;
|''Offset''||''Size''||''Description''&lt;br /&gt;
|-&lt;br /&gt;
|0||2||Length of line data in bytes (note 1)&lt;br /&gt;
|-&lt;br /&gt;
|2||2||16-bit decimal integer line number (note 2)&lt;br /&gt;
|-&lt;br /&gt;
|4||n||BASIC line encoded into tokens (note 3)&lt;br /&gt;
|-&lt;br /&gt;
|n+1||1||&amp;quot;0&amp;quot; the end of line marker (note 4)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Notes:'''&lt;br /&gt;
&lt;br /&gt;
* This 16-bit value has two functions:&lt;br /&gt;
:* if &amp;quot;0&amp;quot; it signals the end of the BASIC program. In this case, there is no furthur BASIC program lines or data.&lt;br /&gt;
:* otherwise, this value defines the length of the tokenised BASIC program line in bytes, and includes the 2 bytes defining this value, the 2 bytes defining the program line number, and the end of line marker. This number is stored in little endian notation with low byte followed by high byte. &lt;br /&gt;
* This 16-bit value defines the line number and exists if the length of line data in bytes is not &amp;quot;0&amp;quot;. A line number is a integer number in the range 1-65535. This number is stored in little endian notation with low byte followed by high byte.&lt;br /&gt;
* This data defines the tokenised BASIC program line and exists if the length of line data in bytes is not &amp;quot;0&amp;quot;. The length is dependant on the BASIC program line contents.&lt;br /&gt;
* This value defines the end of the tokenised BASIC line data and exists if the length of line data in bytes is not &amp;quot;0&amp;quot;. The BASIC interpreter looks for this token during the processing of this line, and if found, will stop execution and continue to the next line.&lt;br /&gt;
&lt;br /&gt;
== BASIC tokens ==&lt;br /&gt;
&lt;br /&gt;
This table list the BASIC tokens with no prefix byte.&lt;br /&gt;
&lt;br /&gt;
{|{{Prettytable|width: 700px; font-size: 2em;}}&lt;br /&gt;
|''Code (hexidecimal)''||''BASIC Keyword''&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;00||end of tokenised line marker&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;01||&amp;quot;:&amp;quot; statement seperator&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;02||integer variable definition (defined with &amp;quot;%&amp;quot; suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;03||string variable definition (defined with &amp;quot;$&amp;quot; suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;04||floating point variable definition (defined with &amp;quot;!&amp;quot; suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;05||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;06||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;07||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;08||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;09||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0a||var?&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0b||variable definition (no suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0c||variable definition (no suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0d||variable definition (no suffix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0e||number constant &amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;0f||number constant &amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;10||number constant &amp;quot;2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;11||number constant &amp;quot;3&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;12||number constant &amp;quot;4&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;13||number constant &amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;14||number constant &amp;quot;6&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;15||number constant &amp;quot;7&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;16||number constant &amp;quot;8&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;17||number constant &amp;quot;9&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;18||number constant &amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;19||8-bit integer decimal value&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1a||16-bit integer decimal value&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1b||16-bit integer binary value (with &amp;quot;&amp;amp;X&amp;quot; prefix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1c||16-bit integer hexadecimal value (with &amp;quot;&amp;amp;H&amp;quot; or &amp;quot;&amp;amp;&amp;quot; prefix)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1d||16-bit BASIC program line memory address pointer&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1e||16-bit integer BASIC line number&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;1f||floating point value&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;20||&amp;quot; &amp;quot; (space) symbol&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;21||ASCII &amp;quot;!&amp;quot; symbol&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;22||quoted string value&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;23-7b||ASCII printable symbols&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;7c||&amp;quot;|&amp;quot; symbol; prefix for RSX commands&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;80||[[AFTER]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;81||[[AUTO]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;82||[[BORDER]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;83||[[CALL]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;84||[[CAT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;85||[[CHAIN]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;86||[[CLEAR]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;87||[[CLG]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;88||[[CLOSEIN]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;89||[[CLOSEOUT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8a||[[CLS]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8b||[[CONT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8c||[[DATA]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8d||[[DEF]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8e||[[DEFINT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;8f||[[DEFREAL]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;90||[[DEFSTR]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;91||[[DEG]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;92||[[DELETE]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;93||[[DIM]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;94||[[DRAW]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;95||[[DRAWR]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;96||[[EDIT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;97||[[ELSE]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;98||[[END]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;99||[[ENT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9a||[[ENV]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9b||[[ERASE]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9c||[[ERROR]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9d||[[EVERY]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9e||[[FOR]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;9f||[[GOSUB]], [[GO SUB]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a0||[[GOTO]], [[GO TO]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a1||[[IF]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a2||[[INK]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a3||[[INPUT]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a4||[[KEY]]&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a5||LET&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a6||LINE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a7||LIST&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a8||LOAD&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;a9||LOCATE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;aa||MEMORY&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ab||MERGE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ac||MID$&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ad||MODE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ae||MOVE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;af||MOVER&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b0||NEXT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b1||NEW&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b2||ON&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b3||ON BREAK&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b4||ON ERROR GOTO, ON ERROR GO TO&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b5||SQ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b6||OPENIN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b7||OPENOUT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b8||ORIGIN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;b9||OUT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ba||PAPER&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;bb||PEN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;bc||PLOT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;bd||PLOTR&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;be||POKE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;bf||PRINT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c0||&amp;quot;'&amp;quot; symbol (same function as REM keyword)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c1||RAD&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c2||RANDOMIZE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c3||READ&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c4||RELEASE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c5||REM&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c6||RENUM&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c7||RESTORE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c8||RESUME&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;c9||RETURN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ca||RUN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;cb||SAVE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;cc||SOUND&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;cd||SPEED&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ce||STOP&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;cf||SYMBOL&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d0||TAG&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d1||TAGOFF&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d2||TROFF&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d3||TRON&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d4||WAIT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d5||WEND&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d6||WHILE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d7||WIDTH&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d8||WINDOW&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;d9||WRITE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;da||ZONE&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;db||DI&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;dc||EI&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;dd||FILL (v1.1)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;de||GRAPHICS (v1.1)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;df||MASK (v1.1)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e0||FRAME (v1.1)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e1||CURSOR (v1.1)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e2||(note 2)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e3||ERL&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e4||FN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e5||SPC&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e6||STEP&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e7||SWAP&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e8||(note 2)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;e9||(note 2)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ea||TAB&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;eb||THEN&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ec||TO&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ed||USING&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ee||&amp;gt; (greater than)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ef||= (equal)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f0||&amp;gt;=, &amp;gt; =, =&amp;gt; (greater or equal)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f1||&amp;lt; (less than)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f2||&amp;lt;&amp;gt;, &amp;lt; &amp;gt; (not equal)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f3||=&amp;lt;, &amp;lt;=, &amp;lt; = (less than or equal)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f4||+ (addition)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f5||- (subtraction or unary minus)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f6||* (multiplication)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f7||/ (division)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f8||^ (x to the power of y)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;f9||\ (integer division)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;fa||AND&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;fb||MOD&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;fc||OR&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;fd||XOR&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;fe||NOT&lt;br /&gt;
|-&lt;br /&gt;
|&amp;amp;ff||(prefix for additional keywords)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Notes:''&lt;br /&gt;
&lt;br /&gt;
* The &amp;amp;ff code is used as a prefix for more keywords. See the table below for the list of keywords using this prefix.&lt;br /&gt;
* &amp;amp;e2,&amp;amp;e8 and &amp;amp;e9 are not used&lt;br /&gt;
* &amp;amp;7c (&amp;quot;|&amp;quot;) is a character prefix used to identify a RSX command.&lt;br /&gt;
&lt;br /&gt;
e.g. &amp;quot;|DIR&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
An RSX is encoded in a BASIC program using the following structure:&lt;br /&gt;
&lt;br /&gt;
      Offset	Count	Description&lt;br /&gt;
      0	1	&amp;quot;|&amp;quot; character prefix&lt;br /&gt;
      1	1	8-bit byte offset to tokens following RSX name.&lt;br /&gt;
      2	x	RSX name. (Last character of name has bit 7 set to &amp;quot;1&amp;quot;, all other characters have bit 7 set to &amp;quot;0&amp;quot;)&lt;br /&gt;
* This token identifies a integer (16-bit) number. The two bytes following this token is the number, stored low byte then high byte. e.g. &amp;amp;19,&amp;amp;2d,&amp;amp;00 represents the integer number &amp;quot;&amp;amp;002d&amp;quot;=&amp;quot;45&amp;quot;.&lt;br /&gt;
* This token (&amp;amp;0B) is changed at run-time to &amp;amp;0D&lt;br /&gt;
* This token identifies a integer variable. 02,00,00,var name offset to number in program setup when program RUN. The variable name is stored directly, with bit 7 of the last character set.&lt;br /&gt;
* This token identifies a string variable. offset to string in program string stored AS IS with quotes around it.&lt;br /&gt;
* This token identifies a floating point number. Immediatly following the token are 5 bytes which define the number.&lt;br /&gt;
&lt;br /&gt;
      Offset	Count	Description&lt;br /&gt;
      0	1	&amp;amp;1f (note 1)&lt;br /&gt;
      1	5	Floating point number (note 2)&lt;br /&gt;
         1. This byte is the BASIC token identifying a floating point number&lt;br /&gt;
         2. These 5 bytes define the floating point number. &lt;br /&gt;
    * The space symbol is used as a command seperator&lt;br /&gt;
    * Variable definitions:&lt;br /&gt;
          o The variable definition has the following structure:&lt;br /&gt;
            Offset	Count	Description&lt;br /&gt;
            0	1	Token defining variable type&lt;br /&gt;
            2	2	16-bit Byte offset to variable value within tokenised BASIC program.&lt;br /&gt;
            4	x	Variable name&lt;br /&gt;
&lt;br /&gt;
            The 16-bit byte offset is initially set to 0, but is setup when the program is RUN. The offset is stored in little-endian format, with low byte followed by high byte.&lt;br /&gt;
          o The token byte defines the variable type (i.e. string, floating point, integer) and the suffix (&amp;quot;$&amp;quot;, none and &amp;quot;%&amp;quot;).&lt;br /&gt;
          o The variable name is stored in the program, with bit 7 of the last character set to &amp;quot;1&amp;quot;. e.g. The variable named &amp;quot;abc&amp;quot; will be encoded as 'a','b','c'+&amp;amp;80 &lt;br /&gt;
    * String values:&lt;br /&gt;
          o Each string value is prefixed with &amp;amp;22 token.&lt;br /&gt;
          o All strings must be enclosed by double quote symbols (&amp;quot;). This symbols define the start and end of the string value.&lt;br /&gt;
          o The string value can contain any symbol except the quote (&amp;quot;). i.e. 0-&amp;amp;21, and &amp;amp;23-&amp;amp;ff can be used. &lt;br /&gt;
    * After running a program, Tokens of &amp;quot;1d&amp;quot; with 16-bit BASIC program line pointers are changed to token &amp;quot;1e&amp;quot; with the 16-bit memory address of the BASIC line number in memory. &lt;br /&gt;
&lt;br /&gt;
This table list the BASIC tokens with a &amp;amp;ff prefix byte.&lt;br /&gt;
&lt;br /&gt;
Code&lt;br /&gt;
(hexidecimal)	BASIC keyword&lt;br /&gt;
&amp;amp;00	ABS&lt;br /&gt;
&amp;amp;01	ASC&lt;br /&gt;
&amp;amp;02	ATN&lt;br /&gt;
&amp;amp;03	CHR$&lt;br /&gt;
&amp;amp;04	CINT&lt;br /&gt;
&amp;amp;05	COS&lt;br /&gt;
&amp;amp;06	CREAL&lt;br /&gt;
&amp;amp;07	EXP&lt;br /&gt;
&amp;amp;08	FIX&lt;br /&gt;
&amp;amp;09	FRE&lt;br /&gt;
&amp;amp;0a	INKEY&lt;br /&gt;
&amp;amp;0b	INP&lt;br /&gt;
&amp;amp;0c	INT&lt;br /&gt;
&amp;amp;0d	JOY&lt;br /&gt;
&amp;amp;0e	LEN&lt;br /&gt;
&amp;amp;0f	LOG&lt;br /&gt;
&amp;amp;10	LOG10&lt;br /&gt;
&amp;amp;11	LOWER$&lt;br /&gt;
&amp;amp;12	PEEK&lt;br /&gt;
&amp;amp;13	REMAIN&lt;br /&gt;
&amp;amp;14	SGN&lt;br /&gt;
&amp;amp;15	SIN&lt;br /&gt;
&amp;amp;16	SPACE$&lt;br /&gt;
&amp;amp;17	SQ&lt;br /&gt;
&amp;amp;18	SQR&lt;br /&gt;
&amp;amp;19	STR$&lt;br /&gt;
&amp;amp;1a	TAN&lt;br /&gt;
&amp;amp;1b	UNT&lt;br /&gt;
&amp;amp;1c	UPPER$&lt;br /&gt;
&amp;amp;1d	VAL&lt;br /&gt;
 	(note 2)&lt;br /&gt;
&amp;amp;40	EOF&lt;br /&gt;
&amp;amp;41	ERR&lt;br /&gt;
&amp;amp;42	HIMEM&lt;br /&gt;
&amp;amp;43	INKEY$&lt;br /&gt;
&amp;amp;44	PI&lt;br /&gt;
&amp;amp;45	RND&lt;br /&gt;
&amp;amp;46	TIME&lt;br /&gt;
&amp;amp;47	XPOS&lt;br /&gt;
&amp;amp;48	YPOS&lt;br /&gt;
&amp;amp;49	DERR (v1.1)&lt;br /&gt;
 	(note 3)&lt;br /&gt;
&amp;amp;71	BIN$&lt;br /&gt;
&amp;amp;72	DEC$ (v1.1)&lt;br /&gt;
&amp;amp;73	HEX$&lt;br /&gt;
&amp;amp;74	INSTR&lt;br /&gt;
&amp;amp;75	LEFT$&lt;br /&gt;
&amp;amp;76	MAX&lt;br /&gt;
&amp;amp;77	MIN&lt;br /&gt;
&amp;amp;78	POS&lt;br /&gt;
&amp;amp;79	RIGHT$&lt;br /&gt;
&amp;amp;7a	ROUND&lt;br /&gt;
&amp;amp;7b	STRING$&lt;br /&gt;
&amp;amp;7c	TEST&lt;br /&gt;
&amp;amp;7d	TESTR&lt;br /&gt;
&amp;amp;7e	COPYCHR$ (v1.1)&lt;br /&gt;
&amp;amp;7f	VPOS&lt;br /&gt;
 	(note 4)&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
&lt;br /&gt;
* These codes are prefixed by &amp;amp;FF. e.g. The keyword &amp;quot;ABS&amp;quot; is stored as the following sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;amp;FF,&amp;amp;00&lt;br /&gt;
&lt;br /&gt;
* Codes &amp;amp;1e...&amp;amp;3f inclusive are not used&lt;br /&gt;
* Codes &amp;amp;4a...&amp;amp;6f inclusive are not used&lt;br /&gt;
* Codes &amp;amp;80...&amp;amp;ff inclusive are not used&lt;br /&gt;
&lt;br /&gt;
== Floating Point data definition ==&lt;br /&gt;
&lt;br /&gt;
A floating point number represents a number with both an integer and fractional part.&lt;br /&gt;
&lt;br /&gt;
In Amstrad BASIC, a floating point number is stored in base-2 in a normalized form:&lt;br /&gt;
&lt;br /&gt;
1 x 2&amp;lt;exponent&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The representation uses 5 bytes and is stored using the following structure:&lt;br /&gt;
&lt;br /&gt;
Byte 	0 	1 	2 	3 	4&lt;br /&gt;
Bit 	7 	6 	5 	4 	3 	2 	1 	0 	7 	6 	5 	4 	3 	2 	1 	0 	7 	6 	5 	4 	3 	2 	1 	0 	7 	6 	5 	4 	3 	2 	1 	0 	7 	6 	5 	4 	3 	2 	1 	0&lt;br /&gt;
Function 	mantissa (bits 23-16) 	mantissa (bits 15-8) 	mantissa (bits 7-0) 	sign 	mantissa (bits 30-24) 	exponent&lt;br /&gt;
&lt;br /&gt;
=== Sign ===&lt;br /&gt;
&lt;br /&gt;
The sign is represented by bit 7 of byte 3.&lt;br /&gt;
&lt;br /&gt;
The value of the sign bit indicates the sign of the floating point number.&lt;br /&gt;
&lt;br /&gt;
* If the sign bit is &amp;quot;1&amp;quot;, then the number is negative.&lt;br /&gt;
* If the sign bit is &amp;quot;0&amp;quot;, then the number is positive.&lt;br /&gt;
&lt;br /&gt;
=== Mantissa ===&lt;br /&gt;
&lt;br /&gt;
The mantissa holds the normalized number. The exponent is manipulated so that the most significant bit is always 1. Since it is always 1, it is not stored. It's value is implied by the representation.&lt;br /&gt;
&lt;br /&gt;
=== Exponent ===&lt;br /&gt;
&lt;br /&gt;
The exponent is 8-bit and is stored in byte 4.&lt;br /&gt;
&lt;br /&gt;
It is stored with a bias of 128.&lt;br /&gt;
&lt;br /&gt;
* 128-255 are positive exponents,&lt;br /&gt;
* 0-127 are negative exponents. &lt;br /&gt;
&lt;br /&gt;
To obtain the signed exponent, you must subtract 128 from the stored exponent.&lt;br /&gt;
&lt;br /&gt;
The minimum exponent is 0 and this describes a number of 2^-127.&lt;br /&gt;
&lt;br /&gt;
The maximum exponent is 255 and this describes a number of 2^128.&lt;br /&gt;
&lt;br /&gt;
== BASIC floating-point/real variables ==&lt;br /&gt;
&lt;br /&gt;
A floating point (real) variable describes a number with integer and fractional parts.&lt;br /&gt;
&lt;br /&gt;
* A integer variable is defined with a &amp;quot;!&amp;quot; character postfix.&lt;br /&gt;
&lt;br /&gt;
e.g.&lt;br /&gt;
&lt;br /&gt;
a! = 3.141592654&lt;br /&gt;
&lt;br /&gt;
* A real number uses 5 bytes of memory as storage. The format is described above.&lt;br /&gt;
* The address of a real variable can be found in BASIC by:&lt;br /&gt;
&lt;br /&gt;
PRINT @a!&lt;br /&gt;
&lt;br /&gt;
Where &amp;quot;a&amp;quot; should be replaced with the name of the variable.&lt;br /&gt;
&lt;br /&gt;
== BASIC integer variables ==&lt;br /&gt;
&lt;br /&gt;
A integer variable describes a whole number. i.e. a number without any fractional part.&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
&lt;br /&gt;
* A integer variable is defined with a &amp;quot;%&amp;quot; character postfix.&lt;br /&gt;
&lt;br /&gt;
e.g.&lt;br /&gt;
&lt;br /&gt;
a% = 3&lt;br /&gt;
&lt;br /&gt;
* A integer variable has a range of -32768 to 32767&lt;br /&gt;
* A integer variable always uses two bytes of memory as storage with the following format:&lt;br /&gt;
&lt;br /&gt;
Offset 	Length 	Description&lt;br /&gt;
0	2	Integer number&lt;br /&gt;
&lt;br /&gt;
* The address of the integer variable can be found in BASIC by:&lt;br /&gt;
&lt;br /&gt;
PRINT @a%&lt;br /&gt;
&lt;br /&gt;
where &amp;quot;a&amp;quot; should be replaced with the name of the variable.&lt;br /&gt;
&lt;br /&gt;
== BASIC string variables ==&lt;br /&gt;
&lt;br /&gt;
A string is a variable which contains a group of characters.&lt;br /&gt;
&lt;br /&gt;
NOTES:&lt;br /&gt;
&lt;br /&gt;
* A string variable is defined in BASIC with a &amp;quot;$&amp;quot; character postfix.&lt;br /&gt;
&lt;br /&gt;
e.g.&lt;br /&gt;
&lt;br /&gt;
a$ = &amp;quot;hello&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* A string variable is described internally by a &amp;quot;string descriptor block&amp;quot; which has the following structure:&lt;br /&gt;
&lt;br /&gt;
      Offset 	Length 	Description&lt;br /&gt;
      0	1	Length of string in bytes/characters&lt;br /&gt;
      1	2	Location of start of string&lt;br /&gt;
&lt;br /&gt;
* The address of the &amp;quot;string descriptor block&amp;quot; for the string variable can be found in BASIC by typing:&lt;br /&gt;
&lt;br /&gt;
PRINT @a$&lt;br /&gt;
&lt;br /&gt;
replacing &amp;quot;a$&amp;quot; with the name of the string variable.&lt;br /&gt;
&lt;br /&gt;
* A string uses a minimum of 3 bytes of storage (a 0 character length string) and a maximum of 258 bytes of storage. 3 bytes are used by the &amp;quot;string descriptor block&amp;quot;)&lt;br /&gt;
* A string variable can contain any ASCII character code in the range 0-255.&lt;br /&gt;
* A string variable can store a minimum of 0 characters and a maximum of 255 characters.&lt;br /&gt;
* The length of the string in characters is defined in the string descriptor block. The string does not have a termination character.&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15052</id>
		<title>Cassette data information</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15052"/>
				<updated>2007-03-13T23:05:18Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Recording a sound ==&lt;br /&gt;
&lt;br /&gt;
A sound is recorded by making a measurement of the amplitude of the sound at regular intervals which are defined by the &amp;quot;sample rate&amp;quot;. The act of taking the measurement is often called &amp;quot;sampling&amp;quot; and each measurement unit is called a &amp;quot;sample&amp;quot;. A file which contains samples is often called a &amp;quot;sound sample&amp;quot; or &amp;quot;audio sample&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;sample rate&amp;quot; defines the rate/frequency at which the measurements are taken. The higher the sample rate, the faster the measurements are taken, and the lower the sample rate, the slower the measurements are taken. The sample rate is described by the &amp;quot;Hz&amp;quot; unit of measurement. The &amp;quot;Hz&amp;quot; unit of measurement means &amp;quot;per second&amp;quot;. Therefore, a sample rate of 44010Hz means 44010 measurements are taken each second (this is one measurement every 1/44010 th of a second).&lt;br /&gt;
&lt;br /&gt;
If the &amp;quot;sample rate&amp;quot; is too low, then changes in the sound which occur between each measurement will not be measured. Therefore the faster the measurements are taken, the more accurate the recording will be, and therefore the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
It is worth noting that at high sample rates, because there are many more measurements taken, the resulting size of the file (containing the audio data) can be large.&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;sample&amp;quot; which uses 8-bits for storage can represent 256 distinct amplitude levels and a sample which uses 16-bits for storage can describe 65535 distinct amplitude levels. The higher the number of bits used by each sample for storage, the larger the range of distinct amplitude levels that can be represented. Therefore, the higher the number of bits used by each sample for storage, the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
All modern sound cards should support 8-bit and 16-bit samples and sample rates of 22050Hz and 44100Hz.&lt;br /&gt;
&lt;br /&gt;
Some sound cards will support a greater range of recording rates which can be lower and higher than these values.&lt;br /&gt;
&lt;br /&gt;
For samp2cdt you should save the file as &amp;quot;PCM&amp;quot; (&amp;quot;Pulse Code Modulation&amp;quot;). This is a uncompressed, unencoded storage representation. Each sample is a single measurement of the amplitude of the sound taken at a measurement point in time.&lt;br /&gt;
&lt;br /&gt;
Other representations such as &amp;quot;ADPCM&amp;quot; (&amp;quot;Amplitude Delta Pulse Code Modulation&amp;quot;), encode or compress the data to reduce the size of the audio file. Samp2cdt can't understand these representations, so please use &amp;quot;PCM&amp;quot; only.&lt;br /&gt;
&lt;br /&gt;
[[Image:wave1.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 1. An amplitude/time graph showing the waveform of the original sound''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave2.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 2. An amplitude/time graph showing the waveform of the original sound. The crosses indicate the amplitude measured at each sample time and the dotted lines indicate the the time of each measurement. The duration of time between each dotted line, defined by the sample rate, is equal to the duration of a sample. From this it can be seen that each sample has a finite and equal duration.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave3.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 3. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, the crosses indicate the amplitude measured at each sample time. The dotted line shows the waveform generated by sampling. The final value of each sample is defined to be the amplitude measured at the time of measurement.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave4.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 4. An amplitude/time graph showing the sampled waveform. This waveform was generated at a high sample rate, and therefore the resulting waveform has a shape which is similar to the original. This waveform is the type you can see in a audio recording program like Goldwave.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave5.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 5. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, this graph shows the amplitude of each measurement, and the dotted line indicates the time of measurement. This graph was created using a low sample rate. Notice that the time between each measurement is longer compared to Fig 2.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave6.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 6. An amplitude/time graph showing the waveform of the original sound. As in Fig 3, the crosses indicate the amplitude measured at each sample time, and the dotted line shows the waveform generated by sampling. This graph shows the resulting waveform generated using a low sample rate.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave7.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 7. An amplitude/time graph showing the sampled waveform. This waveform was generated at a low sample rate, and therefore the resulting waveform is much more coarse compared to Fig 4. Notice that although the general shape is similar to the original waveform, and much of the smoothness is is lost between the time of each measurement. The loss of smoothness also means loss of information since this waveform is not the same as the original. If you compare this graph against Fig 4 then you will see that the lower the sample rate, the more information is lost. The higher the sample rate, the less information is lost. Therefore, to record a sound, it is best to use a high sample rate''&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. The &amp;quot;Nyquist theory&amp;quot; states that in order to accuratly record a sound of a known frequency, you must use a recording frequency which is twice that frequency.&lt;br /&gt;
&lt;br /&gt;
i.e. to record a sound of 3000Hz, you must record using 6000Hz.&lt;br /&gt;
&lt;br /&gt;
If you use a lower frequency (e.g. 5000Hz), then the sound is not recorded accuratly.&lt;br /&gt;
&lt;br /&gt;
Most Amstrad loaders are between 300 to 2500Hz, therefore you should use a recording sample rate of at least 5000Hz. It is recommended to use one of the &amp;quot;common&amp;quot; sample rates. e.g. 22050Hz (22Khz) or 44100Hz (44.1Khz)&lt;br /&gt;
&lt;br /&gt;
2. There are two different representations to store the amplitude of the sample in a PCM audio file: unsigned or signed.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit unsigned sample has values between 0 and 255. In this range, 0 represents a low amplitudes, 255 a high amplitude, and the amplitudes increase linearly from 0 to 255.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit signed sample has values between -128 and 127. In this range, -128 represents a low amplitude, and 127 high amplitude, and the amplitudes increase linearly from -128 to 127.&lt;br /&gt;
&lt;br /&gt;
Both methods can represent the same data, so there is no advantage to using either. The original reason for the two methods is due to the original method to playback the sound. Modern sound cards can play both methods of data storage. &lt;br /&gt;
&lt;br /&gt;
== Duplication of cassettes ==&lt;br /&gt;
&lt;br /&gt;
When the writing of a program is completed a &amp;quot;master&amp;quot; cassette is created. This cassette contains a audio representation of the computer data.&lt;br /&gt;
&lt;br /&gt;
The master cassette is then duplicated, using a machine, onto many blank cassettes. These cassettes are packaged with instructions and distributed.&lt;br /&gt;
&lt;br /&gt;
It is also easy to make a copy of a cassette if you have a twin cassette system, where one cassette unit will play the sound and the other will record. A first generation copy taken from a original cassette could be considered a copy of a copy of the master cassette.&lt;br /&gt;
&lt;br /&gt;
Each time a cassette is copied however, additional noise may be introduced into the copied version. This noise is a mixture of noise from the original, and noise created by the machine making the copy. Therefore the sound on any cassette contains a mixture of noise and the sound of the computer data.&lt;br /&gt;
&lt;br /&gt;
A loader on the computer must therefore be able to identify the actual sound of the data from other sounds that are on the cassette. If it can't do this, then there will be loading errors.&lt;br /&gt;
&lt;br /&gt;
If you are transfering a cassette using samp2cdt, then you are advised to use an original (i.e. a cassette created directly from a master cassette), or a first generation copy (i.e. a cassette copied from an original).&lt;br /&gt;
&lt;br /&gt;
== Loader ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;loader&amp;quot; is the name given to a program that reads data from cassette into the computer memory.&lt;br /&gt;
&lt;br /&gt;
There is a &amp;quot;system&amp;quot; loader which is built into the Amstrad CPC ROM. This loader is activated when the computer is in cassette mode (note 1), and it can only understand one specific computer audio sound, the audio sound of the Amstrad CPC system data-blocks.&lt;br /&gt;
&lt;br /&gt;
To read other loading systems (e.g. a fast-loader), there must be a program on the cassette (a &amp;quot;pre-loader&amp;quot; or &amp;quot;boot loader&amp;quot; or sometimes refered to as &amp;quot;loader&amp;quot;), stored using the Amstrad CPC system loader, which when executed will be able to understand and load fast-loader data.&lt;br /&gt;
&lt;br /&gt;
This loader program is usually stored immediatly before any fast-loader blocks, and takes over from the system loader to load the remaining fast-loader blocks.&lt;br /&gt;
&lt;br /&gt;
|program for fast-loader| |fast-loader block(s)|&lt;br /&gt;
&lt;br /&gt;
So when a cassette is loaded the following occurs:&lt;br /&gt;
&lt;br /&gt;
1. system loader recognises and loads &amp;quot;program for fast-loader&amp;quot;.&lt;br /&gt;
2. &amp;quot;program for fast loader&amp;quot; takes control and loads the data from the fast-loader block(s) into computer memory&lt;br /&gt;
3. when loading has completed, the program is executed. &lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. a CPC without a disc interface (e.g. a CPC464, CPC464+ or KC Compact) will start-up in cassette mode. For a CPC with a disc interface attached (or internal), you must type |TAPE to enter cassette mode.&lt;br /&gt;
&lt;br /&gt;
You can test if the computer is operating in cassette mode by typing RUN&amp;quot;. If you see &amp;quot;Press PLAY then any key&amp;quot;, then the computer is operating in cassette mode. If there is an error, then the computer is not operating in cassette mode. &lt;br /&gt;
&lt;br /&gt;
== Amstrad cassette hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Reading ===&lt;br /&gt;
&lt;br /&gt;
The audio from the cassette is read from a cassette player through the Amstrad's cassette electronics.&lt;br /&gt;
&lt;br /&gt;
The Amstrad's cassette electronics converts the amplitude of the sound (a analogue signal) into a &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement (a digital signal). This measurement can then be read from bit 7 of port B of the PPI 8255 IC.&lt;br /&gt;
&lt;br /&gt;
[[Image:conv.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 8. This image shows the conversion of the audio waveform from the cassette into the digital representation by the Amstrad's cassette electronics. i.e. audio waveform (on cassette) -&amp;gt; Amstrad's cassette electronics -&amp;gt; 0 and 1 measurements''&lt;br /&gt;
&lt;br /&gt;
The resulting measurements can be read using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f5			;; I/O port address for PPI 8255 port B&lt;br /&gt;
				;; (PPI 8255 port B is operating as input.)&lt;br /&gt;
in a,(c)			;; read port B inputs&lt;br /&gt;
and %10000000			;; isolate bit 7 which contains the measurement.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This measurement is *not* the actual state of a data-bit, but represents a low (&amp;quot;0&amp;quot;) or high amplitude (&amp;quot;1&amp;quot;). In this document, the value of this measurement will be refered to as a &amp;quot;high&amp;quot; (&amp;quot;1&amp;quot;) or &amp;quot;low&amp;quot; (&amp;quot;0&amp;quot;) level.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. The CPC464 and CPC464+ have a cassette player built in. To connect a cassette player to the CPC664, CPC6128 or KC Compact then you must use a lead.&lt;br /&gt;
2. It is not known exactly how the amplitude of the sound from the cassette corresponds to the final &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement.&lt;br /&gt;
&lt;br /&gt;
samp2cdt uses a crude method to perform this conversion.&lt;br /&gt;
&lt;br /&gt;
For a 8-bit signed sample:&lt;br /&gt;
&lt;br /&gt;
* if the amplitude is 0..128, then the final measurement will be &amp;quot;1&amp;quot;.&lt;br /&gt;
* if the amplitude is -128..0 then the final measurement will be &amp;quot;0&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Writing ===&lt;br /&gt;
&lt;br /&gt;
A waveform is written to cassette using bit 5 of port C of the 8255 PPI IC. The waveform can only be defined by a high or low level, defined by the state of bit 5, which is then converted by the Amstrad's cassette electronics into a final output amplitude which is recorded onto cassette.&lt;br /&gt;
&lt;br /&gt;
A high level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
			;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
set 5,a			;; set cassette write output to high level &lt;br /&gt;
out (c),a		;; output level&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A low level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
			;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
res 5,a			;; set cassette write output to low level&lt;br /&gt;
out (c),a		;; output level&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The amplitude of the output waveform is not amplified, therefore if you wish to record the cassette audio direct from an Amstrad you will need to amplify the waveform.&lt;br /&gt;
&lt;br /&gt;
If the state of bit 5 is changed at a fixed frequency, then the graph of the state of bit 5 over time will be a square wave. However, the resulting audio written on the cassette will not be a perfect square wave because nature will attempt to convert the waveform into a sine wave.&lt;br /&gt;
Loading system audio waveform&lt;br /&gt;
&lt;br /&gt;
Every loading system on the Amstrad uses a serial bit-stream. i.e. a single bit of information is read at a time.&lt;br /&gt;
&lt;br /&gt;
This serial bit-stream is grouped into blocks of audio sound.&lt;br /&gt;
&lt;br /&gt;
Every loading system uses a basic structure to describe each audio block in the following order:&lt;br /&gt;
&lt;br /&gt;
|pilot|sync|data|trailer|&lt;br /&gt;
&lt;br /&gt;
'''pilot'''&lt;br /&gt;
&lt;br /&gt;
This is also refered to as &amp;quot;leader&amp;quot; by some documents.&lt;br /&gt;
&lt;br /&gt;
This is constructed from a repeated waveform often with a fixed number of repetitions defined by the loading system.&lt;br /&gt;
&lt;br /&gt;
The shape of the waveform is known by the loader program and this is used to identify the pilot waveform from other waveforms that may be present (e.g. noise).&lt;br /&gt;
&lt;br /&gt;
The pilot is often long, so that the loader doesn't need to see the start of the pilot waveform in order to load the block.&lt;br /&gt;
&lt;br /&gt;
The loader program will test the incoming waveform, checking it against the parameters defined for the pilot, before the waveform is accepted as the pilot waveform. (e.g. the number of repetitions must be some defined minimum value). The incoming waveform must fall within these specifications otherwise the waveform is not accepted as a pilot waveform. &lt;br /&gt;
&lt;br /&gt;
'''sync (&amp;quot;synchronisation&amp;quot;)'''&lt;br /&gt;
&lt;br /&gt;
The sync is a waveform which is different to the pilot, and this defines the end of the pilot and the start of the data. When this sync has been detected, the loader knows that there is data following, and that the loader is always at the same point in the data stream. i.e. the loader program is synchronised to a specific point in the data waveform.&lt;br /&gt;
&lt;br /&gt;
'''data'''&lt;br /&gt;
&lt;br /&gt;
This is the actual data which is composed of waveforms defining &amp;quot;0&amp;quot; and &amp;quot;1&amp;quot; data bits.&lt;br /&gt;
&lt;br /&gt;
The first element of the data may be a marker or id which may, for example, indicate the type of data in the block or the number of the block.&lt;br /&gt;
&lt;br /&gt;
The remaining bits will define the data and zero or more checksums.&lt;br /&gt;
&lt;br /&gt;
The whole data may consist of a single block with a single location and length (e.g. one block for a screen another for data), or multiple blocks each with their own location and length. (e.g. one block for screen and data)&lt;br /&gt;
&lt;br /&gt;
The location and lengths of the blocks may be in the data stream itself, or they may be in a preceeding block, or may be hard-coded into the loader program. &lt;br /&gt;
&lt;br /&gt;
'''trailer'''&lt;br /&gt;
&lt;br /&gt;
The trailer always follows the data. Some loaders may not have a trailer. The two main purposes of the trailer are to ensure that the waveform of the last data bit in the data is constructed correctly and to provide some time in which the loader can prepare for the next block.&lt;br /&gt;
&lt;br /&gt;
The exact definition of the loading systems's audio waveform is defined by the loader program.&lt;br /&gt;
&lt;br /&gt;
samp2cdt has a number of decoder algorithms which recognises the audio waveform of various loading systems. These decoders read the waveform using a similar method to the loader program itself. These decoders have been created by examining the instructions of each loader program and the graph of the waveform in a sound recording package.&lt;br /&gt;
&lt;br /&gt;
== Example of a typical loading system ==&lt;br /&gt;
&lt;br /&gt;
The data on cassette actually consists of changing 0 and 1 levels. (a &amp;quot;level&amp;quot; is a magnitude of a value). The loader measures the time between each &amp;quot;level transition&amp;quot; where a &amp;quot;level transition&amp;quot; is the change from a &amp;quot;0&amp;quot; to a &amp;quot;1&amp;quot; level or the change from a &amp;quot;1&amp;quot; to a &amp;quot;0&amp;quot; level. The level can be timed using the following Z80 instructions: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;; - keep testing the state of bit 7 of PPI 8255 port B &lt;br /&gt;
;; - update the counter to record the number of tests done &lt;br /&gt;
;; - when bit 7 of PPI 8255 port B changes state, stop testing. &lt;br /&gt;
;; counter will hold the total number of tests made. &lt;br /&gt;
;; &lt;br /&gt;
;; B = &amp;amp;F5 (I/O address of PPI 8255 input port B) &lt;br /&gt;
;; C = previous data read from PPI port B ld d,0 &lt;br /&gt;
;; initialise count to 0 .loop inc d &lt;br /&gt;
;; increment count in a,(c) &lt;br /&gt;
;; read input to PPI 8255 port B xor c &lt;br /&gt;
;; exclusive-or with previous data read from PPI 8255 port B and %10000000 &lt;br /&gt;
;; isolate bit 7 &lt;br /&gt;
;; if result is 0, then the state of bit 7 that has &lt;br /&gt;
;; been read is the same as the previous state. i.e. bit 7 has not changed state. &lt;br /&gt;
;; if result is not 0, then the state of bit 7 has changed. &lt;br /&gt;
;; e.g. if bit 7 was previously 1, it is now 0. if bit 7 was previously 0, it is now 1. jr z,loop &lt;br /&gt;
;; when execution reaches here we know that bit 7 has changed state and D &lt;br /&gt;
;; contains the number of tests.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Loader operation==&lt;br /&gt;
&lt;br /&gt;
The loader generally operates in this way:&lt;br /&gt;
&lt;br /&gt;
1. Time a wave. Is the duration of the wave within the minimum and maximum duration required for the pilot. If yes, go to 2, else go to 1.&lt;br /&gt;
&lt;br /&gt;
2. We might have seen a wave from the pilot signal. time a wave. Is the duration of this wave within the minimum and maximum duration required for the pilot. If yes, increment number of waves seen, go to 2, else go to 1.&lt;br /&gt;
&lt;br /&gt;
3. Have we seen the minimum number of pilot waves? Yes, go to 4, else go to 2. 4. time a wave. Is the duration of the wave within the minimum and maximum duration required for the sync? 2. Each Z80 instruction takes a finite time to execute. The execution time depends on the computer. If the timing of the Z80 instructions used by the test algorithm is known and predictable, then the time for each test can be calculated. Now, since the count represents the number of tests made before the condition is true (i.e. bit 7 changes state), the total time for the condition to be true, is the sum of the time for each test made. If each test always takes the same time, then the total time is the number of tests multiplied by the time for one test. In the Amstrad computer, all Z80 instructions execute in multiples of 1us (microsecond) regardless of their location in RAM. This fact simplifies this calculation.&lt;br /&gt;
Checksum&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;Checksum&amp;quot; is used to verify the loaded data.&lt;br /&gt;
&lt;br /&gt;
A Checksum is the result of the &amp;quot;checksum calculation&amp;quot; made on a block of data. The actual calculation can be different depending on the method chosen.&lt;br /&gt;
&lt;br /&gt;
There are two &amp;quot;Checksum&amp;quot;s.&lt;br /&gt;
&lt;br /&gt;
1. a stored &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the correct data. This is then stored with the data (e.g. before or after the data) when the master cassette is created.&lt;br /&gt;
2. a calculated &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the data read from the cassette. After the calculation is complete it is compared against the stored checksum. &lt;br /&gt;
&lt;br /&gt;
The stored and calculated &amp;quot;Checksums&amp;quot; are initialised with the same initial value and calculated using the same algorithm. Therefore, if the stored checksum matches the calculated checksum, it is assumed that the loaded data is identical to the original data. The data is verified to be correct.&lt;br /&gt;
&lt;br /&gt;
If the stored checksum doesn't match the calculated checksum, then there has been a error. One or more bit's of data is incorrect. The checksum is designed to detect errors only, and often it is not possible to know which bit or bits of data is incorrect and in this case it is not often possible to correct the errors to reproduce the correct data.&lt;br /&gt;
&lt;br /&gt;
A loader which has a checksum therefore is better than a loader that doesn't have a checksum, because the checksum will verify that the data is correct or incorrect.&lt;br /&gt;
&lt;br /&gt;
With a loader which doesn't have a checksum, you have no way to verify the data, and therefore you can't guarantee that the data is identical to the original.&lt;br /&gt;
&lt;br /&gt;
In this case, the only way to test that the data is correct is to make multiple transfers of the program and test each thoroughly (e.g. if the program is a game, you would play the game to the end), checking for graphic corruption and bugs. If all of the transfers operate the same, then you can assume that the data is correct.&lt;br /&gt;
&lt;br /&gt;
== Various Audio file formats ==&lt;br /&gt;
&lt;br /&gt;
There are numerous Audio file formats, each of which can store audio, but each has it's own structures and representation for the data.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;format&amp;quot; of a file describes the internal structure, order and encoding of the data within the file.&lt;br /&gt;
&lt;br /&gt;
Here is a list of the audio file formats supported by samp2cdt:&lt;br /&gt;
&lt;br /&gt;
* Windows Wave file (a file which has the &amp;quot;.wav&amp;quot; file extension) is the common file format used for audio sounds on computers running &amp;quot;Windows&amp;quot;.&lt;br /&gt;
* A Voice Wave file (a file which has the &amp;quot;.voc&amp;quot; file extension) was created by Creative for the original Soundblaster ISA sound card. This file format is used by the original voc2tzx utility which samp2cdt was developed from.&lt;br /&gt;
* A Audio Interchange file (a file which has the &amp;quot;.aiff&amp;quot; or &amp;quot;.aif&amp;quot; file extension) is the common file format used for audio sounds on the Mac computer.&lt;br /&gt;
* A file which has the &amp;quot;.iff&amp;quot; file extension is the common file format used for audio sounds by the Amiga computer.&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15044</id>
		<title>Cassette data information</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15044"/>
				<updated>2007-03-13T21:42:30Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Recording a sound ==&lt;br /&gt;
&lt;br /&gt;
A sound is recorded by making a measurement of the amplitude of the sound at regular intervals which are defined by the &amp;quot;sample rate&amp;quot;. The act of taking the measurement is often called &amp;quot;sampling&amp;quot; and each measurement unit is called a &amp;quot;sample&amp;quot;. A file which contains samples is often called a &amp;quot;sound sample&amp;quot; or &amp;quot;audio sample&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;sample rate&amp;quot; defines the rate/frequency at which the measurements are taken. The higher the sample rate, the faster the measurements are taken, and the lower the sample rate, the slower the measurements are taken. The sample rate is described by the &amp;quot;Hz&amp;quot; unit of measurement. The &amp;quot;Hz&amp;quot; unit of measurement means &amp;quot;per second&amp;quot;. Therefore, a sample rate of 44010Hz means 44010 measurements are taken each second (this is one measurement every 1/44010 th of a second).&lt;br /&gt;
&lt;br /&gt;
If the &amp;quot;sample rate&amp;quot; is too low, then changes in the sound which occur between each measurement will not be measured. Therefore the faster the measurements are taken, the more accurate the recording will be, and therefore the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
It is worth noting that at high sample rates, because there are many more measurements taken, the resulting size of the file (containing the audio data) can be large.&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;sample&amp;quot; which uses 8-bits for storage can represent 256 distinct amplitude levels and a sample which uses 16-bits for storage can describe 65535 distinct amplitude levels. The higher the number of bits used by each sample for storage, the larger the range of distinct amplitude levels that can be represented. Therefore, the higher the number of bits used by each sample for storage, the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
All modern sound cards should support 8-bit and 16-bit samples and sample rates of 22050Hz and 44100Hz.&lt;br /&gt;
&lt;br /&gt;
Some sound cards will support a greater range of recording rates which can be lower and higher than these values.&lt;br /&gt;
&lt;br /&gt;
For samp2cdt you should save the file as &amp;quot;PCM&amp;quot; (&amp;quot;Pulse Code Modulation&amp;quot;). This is a uncompressed, unencoded storage representation. Each sample is a single measurement of the amplitude of the sound taken at a measurement point in time.&lt;br /&gt;
&lt;br /&gt;
Other representations such as &amp;quot;ADPCM&amp;quot; (&amp;quot;Amplitude Delta Pulse Code Modulation&amp;quot;), encode or compress the data to reduce the size of the audio file. Samp2cdt can't understand these representations, so please use &amp;quot;PCM&amp;quot; only.&lt;br /&gt;
&lt;br /&gt;
[[Image:wave1.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 1. An amplitude/time graph showing the waveform of the original sound''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave2.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 2. An amplitude/time graph showing the waveform of the original sound. The crosses indicate the amplitude measured at each sample time and the dotted lines indicate the the time of each measurement. The duration of time between each dotted line, defined by the sample rate, is equal to the duration of a sample. From this it can be seen that each sample has a finite and equal duration.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave3.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 3. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, the crosses indicate the amplitude measured at each sample time. The dotted line shows the waveform generated by sampling. The final value of each sample is defined to be the amplitude measured at the time of measurement.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave4.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 4. An amplitude/time graph showing the sampled waveform. This waveform was generated at a high sample rate, and therefore the resulting waveform has a shape which is similar to the original. This waveform is the type you can see in a audio recording program like Goldwave.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave5.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 5. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, this graph shows the amplitude of each measurement, and the dotted line indicates the time of measurement. This graph was created using a low sample rate. Notice that the time between each measurement is longer compared to Fig 2.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave6.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 6. An amplitude/time graph showing the waveform of the original sound. As in Fig 3, the crosses indicate the amplitude measured at each sample time, and the dotted line shows the waveform generated by sampling. This graph shows the resulting waveform generated using a low sample rate.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave7.gif]]&lt;br /&gt;
&lt;br /&gt;
''Fig 7. An amplitude/time graph showing the sampled waveform. This waveform was generated at a low sample rate, and therefore the resulting waveform is much more coarse compared to Fig 4. Notice that although the general shape is similar to the original waveform, and much of the smoothness is is lost between the time of each measurement. The loss of smoothness also means loss of information since this waveform is not the same as the original. If you compare this graph against Fig 4 then you will see that the lower the sample rate, the more information is lost. The higher the sample rate, the less information is lost. Therefore, to record a sound, it is best to use a high sample rate''&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. The &amp;quot;Nyquist theory&amp;quot; states that in order to accuratly record a sound of a known frequency, you must use a recording frequency which is twice that frequency.&lt;br /&gt;
&lt;br /&gt;
i.e. to record a sound of 3000Hz, you must record using 6000Hz.&lt;br /&gt;
&lt;br /&gt;
If you use a lower frequency (e.g. 5000Hz), then the sound is not recorded accuratly.&lt;br /&gt;
&lt;br /&gt;
Most Amstrad loaders are between 300 to 2500Hz, therefore you should use a recording sample rate of at least 5000Hz. It is recommended to use one of the &amp;quot;common&amp;quot; sample rates. e.g. 22050Hz (22Khz) or 44100Hz (44.1Khz)&lt;br /&gt;
&lt;br /&gt;
2. There are two different representations to store the amplitude of the sample in a PCM audio file: unsigned or signed.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit unsigned sample has values between 0 and 255. In this range, 0 represents a low amplitudes, 255 a high amplitude, and the amplitudes increase linearly from 0 to 255.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit signed sample has values between -128 and 127. In this range, -128 represents a low amplitude, and 127 high amplitude, and the amplitudes increase linearly from -128 to 127.&lt;br /&gt;
&lt;br /&gt;
Both methods can represent the same data, so there is no advantage to using either. The original reason for the two methods is due to the original method to playback the sound. Modern sound cards can play both methods of data storage. &lt;br /&gt;
&lt;br /&gt;
== Duplication of cassettes ==&lt;br /&gt;
&lt;br /&gt;
When the writing of a program is completed a &amp;quot;master&amp;quot; cassette is created. This cassette contains a audio representation of the computer data.&lt;br /&gt;
&lt;br /&gt;
The master cassette is then duplicated, using a machine, onto many blank cassettes. These cassettes are packaged with instructions and distributed.&lt;br /&gt;
&lt;br /&gt;
It is also easy to make a copy of a cassette if you have a twin cassette system, where one cassette unit will play the sound and the other will record. A first generation copy taken from a original cassette could be considered a copy of a copy of the master cassette.&lt;br /&gt;
&lt;br /&gt;
Each time a cassette is copied however, additional noise may be introduced into the copied version. This noise is a mixture of noise from the original, and noise created by the machine making the copy. Therefore the sound on any cassette contains a mixture of noise and the sound of the computer data.&lt;br /&gt;
&lt;br /&gt;
A loader on the computer must therefore be able to identify the actual sound of the data from other sounds that are on the cassette. If it can't do this, then there will be loading errors.&lt;br /&gt;
&lt;br /&gt;
If you are transfering a cassette using samp2cdt, then you are advised to use an original (i.e. a cassette created directly from a master cassette), or a first generation copy (i.e. a cassette copied from an original).&lt;br /&gt;
&lt;br /&gt;
== Loader ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;loader&amp;quot; is the name given to a program that reads data from cassette into the computer memory.&lt;br /&gt;
&lt;br /&gt;
There is a &amp;quot;system&amp;quot; loader which is built into the Amstrad CPC ROM. This loader is activated when the computer is in cassette mode (note 1), and it can only understand one specific computer audio sound, the audio sound of the Amstrad CPC system data-blocks.&lt;br /&gt;
&lt;br /&gt;
To read other loading systems (e.g. a fast-loader), there must be a program on the cassette (a &amp;quot;pre-loader&amp;quot; or &amp;quot;boot loader&amp;quot; or sometimes refered to as &amp;quot;loader&amp;quot;), stored using the Amstrad CPC system loader, which when executed will be able to understand and load fast-loader data.&lt;br /&gt;
&lt;br /&gt;
This loader program is usually stored immediatly before any fast-loader blocks, and takes over from the system loader to load the remaining fast-loader blocks.&lt;br /&gt;
&lt;br /&gt;
|program for fast-loader| |fast-loader block(s)|&lt;br /&gt;
&lt;br /&gt;
So when a cassette is loaded the following occurs:&lt;br /&gt;
&lt;br /&gt;
1. system loader recognises and loads &amp;quot;program for fast-loader&amp;quot;.&lt;br /&gt;
2. &amp;quot;program for fast loader&amp;quot; takes control and loads the data from the fast-loader block(s) into computer memory&lt;br /&gt;
3. when loading has completed, the program is executed. &lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. a CPC without a disc interface (e.g. a CPC464, CPC464+ or KC Compact) will start-up in cassette mode. For a CPC with a disc interface attached (or internal), you must type |TAPE to enter cassette mode.&lt;br /&gt;
&lt;br /&gt;
You can test if the computer is operating in cassette mode by typing RUN&amp;quot;. If you see &amp;quot;Press PLAY then any key&amp;quot;, then the computer is operating in cassette mode. If there is an error, then the computer is not operating in cassette mode. &lt;br /&gt;
&lt;br /&gt;
== Amstrad cassette hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Reading ===&lt;br /&gt;
&lt;br /&gt;
The audio from the cassette is read from a cassette player through the Amstrad's cassette electronics.&lt;br /&gt;
&lt;br /&gt;
The Amstrad's cassette electronics converts the amplitude of the sound (a analogue signal) into a &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement (a digital signal). This measurement can then be read from bit 7 of port B of the PPI 8255 IC.&lt;br /&gt;
&lt;br /&gt;
[Picture showing the conversion process]&lt;br /&gt;
&lt;br /&gt;
[Fig 8. This image shows the conversion of the audio waveform from the cassette into the digital representation by the Amstrad's cassette electronics. i.e. audio waveform (on cassette) -&amp;gt; Amstrad's cassette electronics -&amp;gt; 0 and 1 measurements]&lt;br /&gt;
&lt;br /&gt;
The resulting measurements can be read using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f5			;; I/O port address for PPI 8255 port B&lt;br /&gt;
				;; (PPI 8255 port B is operating as input.)&lt;br /&gt;
in a,(c)			;; read port B inputs&lt;br /&gt;
and %10000000			;; isolate bit 7 which contains the measurement.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This measurement is *not* the actual state of a data-bit, but represents a low (&amp;quot;0&amp;quot;) or high amplitude (&amp;quot;1&amp;quot;). In this document, the value of this measurement will be refered to as a &amp;quot;high&amp;quot; (&amp;quot;1&amp;quot;) or &amp;quot;low&amp;quot; (&amp;quot;0&amp;quot;) level.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. The CPC464 and CPC464+ have a cassette player built in. To connect a cassette player to the CPC664, CPC6128 or KC Compact then you must use a lead.&lt;br /&gt;
2. It is not known exactly how the amplitude of the sound from the cassette corresponds to the final &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement.&lt;br /&gt;
&lt;br /&gt;
samp2cdt uses a crude method to perform this conversion.&lt;br /&gt;
&lt;br /&gt;
For a 8-bit signed sample:&lt;br /&gt;
&lt;br /&gt;
* if the amplitude is 0..128, then the final measurement will be &amp;quot;1&amp;quot;.&lt;br /&gt;
* if the amplitude is -128..0 then the final measurement will be &amp;quot;0&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
=== Writing ===&lt;br /&gt;
&lt;br /&gt;
A waveform is written to cassette using bit 5 of port C of the 8255 PPI IC. The waveform can only be defined by a high or low level, defined by the state of bit 5, which is then converted by the Amstrad's cassette electronics into a final output amplitude which is recorded onto cassette.&lt;br /&gt;
&lt;br /&gt;
A high level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
			;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
set 5,a			;; set cassette write output to high level &lt;br /&gt;
out (c),a		;; output level&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A low level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
			;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
res 5,a			;; set cassette write output to low level&lt;br /&gt;
out (c),a		;; output level&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The amplitude of the output waveform is not amplified, therefore if you wish to record the cassette audio direct from an Amstrad you will need to amplify the waveform.&lt;br /&gt;
&lt;br /&gt;
If the state of bit 5 is changed at a fixed frequency, then the graph of the state of bit 5 over time will be a square wave. However, the resulting audio written on the cassette will not be a perfect square wave because nature will attempt to convert the waveform into a sine wave.&lt;br /&gt;
Loading system audio waveform&lt;br /&gt;
&lt;br /&gt;
Every loading system on the Amstrad uses a serial bit-stream. i.e. a single bit of information is read at a time.&lt;br /&gt;
&lt;br /&gt;
This serial bit-stream is grouped into blocks of audio sound.&lt;br /&gt;
&lt;br /&gt;
Every loading system uses a basic structure to describe each audio block in the following order:&lt;br /&gt;
&lt;br /&gt;
|pilot|sync|data|trailer|&lt;br /&gt;
&lt;br /&gt;
'''pilot'''&lt;br /&gt;
&lt;br /&gt;
This is also refered to as &amp;quot;leader&amp;quot; by some documents.&lt;br /&gt;
&lt;br /&gt;
This is constructed from a repeated waveform often with a fixed number of repetitions defined by the loading system.&lt;br /&gt;
&lt;br /&gt;
The shape of the waveform is known by the loader program and this is used to identify the pilot waveform from other waveforms that may be present (e.g. noise).&lt;br /&gt;
&lt;br /&gt;
The pilot is often long, so that the loader doesn't need to see the start of the pilot waveform in order to load the block.&lt;br /&gt;
&lt;br /&gt;
The loader program will test the incoming waveform, checking it against the parameters defined for the pilot, before the waveform is accepted as the pilot waveform. (e.g. the number of repetitions must be some defined minimum value). The incoming waveform must fall within these specifications otherwise the waveform is not accepted as a pilot waveform. &lt;br /&gt;
&lt;br /&gt;
'''sync (&amp;quot;synchronisation&amp;quot;)'''&lt;br /&gt;
&lt;br /&gt;
The sync is a waveform which is different to the pilot, and this defines the end of the pilot and the start of the data. When this sync has been detected, the loader knows that there is data following, and that the loader is always at the same point in the data stream. i.e. the loader program is synchronised to a specific point in the data waveform.&lt;br /&gt;
&lt;br /&gt;
'''data'''&lt;br /&gt;
&lt;br /&gt;
This is the actual data which is composed of waveforms defining &amp;quot;0&amp;quot; and &amp;quot;1&amp;quot; data bits.&lt;br /&gt;
&lt;br /&gt;
The first element of the data may be a marker or id which may, for example, indicate the type of data in the block or the number of the block.&lt;br /&gt;
&lt;br /&gt;
The remaining bits will define the data and zero or more checksums.&lt;br /&gt;
&lt;br /&gt;
The whole data may consist of a single block with a single location and length (e.g. one block for a screen another for data), or multiple blocks each with their own location and length. (e.g. one block for screen and data)&lt;br /&gt;
&lt;br /&gt;
The location and lengths of the blocks may be in the data stream itself, or they may be in a preceeding block, or may be hard-coded into the loader program. &lt;br /&gt;
&lt;br /&gt;
'''trailer'''&lt;br /&gt;
&lt;br /&gt;
The trailer always follows the data. Some loaders may not have a trailer. The two main purposes of the trailer are to ensure that the waveform of the last data bit in the data is constructed correctly and to provide some time in which the loader can prepare for the next block.&lt;br /&gt;
&lt;br /&gt;
The exact definition of the loading systems's audio waveform is defined by the loader program.&lt;br /&gt;
&lt;br /&gt;
samp2cdt has a number of decoder algorithms which recognises the audio waveform of various loading systems. These decoders read the waveform using a similar method to the loader program itself. These decoders have been created by examining the instructions of each loader program and the graph of the waveform in a sound recording package.&lt;br /&gt;
&lt;br /&gt;
== Example of a typical loading system ==&lt;br /&gt;
&lt;br /&gt;
The data on cassette actually consists of changing 0 and 1 levels. (a &amp;quot;level&amp;quot; is a magnitude of a value). The loader measures the time between each &amp;quot;level transition&amp;quot; where a &amp;quot;level transition&amp;quot; is the change from a &amp;quot;0&amp;quot; to a &amp;quot;1&amp;quot; level or the change from a &amp;quot;1&amp;quot; to a &amp;quot;0&amp;quot; level. The level can be timed using the following Z80 instructions: ;; - keep testing the state of bit 7 of PPI 8255 port B ;; - update the counter to record the number of tests done ;; - when bit 7 of PPI 8255 port B changes state, stop testing. ;; counter will hold the total number of tests made. ;; ;; B = &amp;amp;F5 (I/O address of PPI 8255 input port B) ;; C = previous data read from PPI port B ld d,0 ;; initialise count to 0 .loop inc d ;; increment count in a,(c) ;; read input to PPI 8255 port B xor c ;; exclusive-or with previous data read from PPI 8255 port B and %10000000 ;; isolate bit 7 ;; if result is 0, then the state of bit 7 that has ;; been read is the same as the previous state. i.e. bit 7 has not changed state. ;; if result is not 0, then the state of bit 7 has changed. ;; e.g. if bit 7 was previously 1, it is now 0. if bit 7 was previously 0, it is now 1. jr z,loop ;; when execution reaches here we know that bit 7 has changed state and D ;; contains the number of tests.&lt;br /&gt;
&lt;br /&gt;
== Loader operation==&lt;br /&gt;
&lt;br /&gt;
The loader generally operates in this way:&lt;br /&gt;
&lt;br /&gt;
1. time a wave. Is the duration of the wave within the minimum and maximum duration required for the pilot. If yes, go to 2, else go to 1.&lt;br /&gt;
&lt;br /&gt;
2. We might have seen a wave from the pilot signal. time a wave. Is the duration of this wave within the minimum and maximum duration required for the pilot. If yes, increment number of waves seen, go to 2, else go to 1.&lt;br /&gt;
&lt;br /&gt;
3. Have we seen the minimum number of pilot waves? Yes, go to 4, else go to 2. 4. time a wave. Is the duration of the wave within the minimum and maximum duration required for the sync? 2. Each Z80 instruction takes a finite time to execute. The execution time depends on the computer. If the timing of the Z80 instructions used by the test algorithm is known and predictable, then the time for each test can be calculated. Now, since the count represents the number of tests made before the condition is true (i.e. bit 7 changes state), the total time for the condition to be true, is the sum of the time for each test made. If each test always takes the same time, then the total time is the number of tests multiplied by the time for one test. In the Amstrad computer, all Z80 instructions execute in multiples of 1us (microsecond) regardless of their location in RAM. This fact simplifies this calculation.&lt;br /&gt;
Checksum&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;Checksum&amp;quot; is used to verify the loaded data.&lt;br /&gt;
&lt;br /&gt;
A Checksum is the result of the &amp;quot;checksum calculation&amp;quot; made on a block of data. The actual calculation can be different depending on the method chosen.&lt;br /&gt;
&lt;br /&gt;
There are two &amp;quot;Checksum&amp;quot;s.&lt;br /&gt;
&lt;br /&gt;
1. a stored &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the correct data. This is then stored with the data (e.g. before or after the data) when the master cassette is created.&lt;br /&gt;
2. a calculated &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the data read from the cassette. After the calculation is complete it is compared against the stored checksum. &lt;br /&gt;
&lt;br /&gt;
The stored and calculated &amp;quot;Checksums&amp;quot; are initialised with the same initial value and calculated using the same algorithm. Therefore, if the stored checksum matches the calculated checksum, it is assumed that the loaded data is identical to the original data. The data is verified to be correct.&lt;br /&gt;
&lt;br /&gt;
If the stored checksum doesn't match the calculated checksum, then there has been a error. One or more bit's of data is incorrect. The checksum is designed to detect errors only, and often it is not possible to know which bit or bits of data is incorrect and in this case it is not often possible to correct the errors to reproduce the correct data.&lt;br /&gt;
&lt;br /&gt;
A loader which has a checksum therefore is better than a loader that doesn't have a checksum, because the checksum will verify that the data is correct or incorrect.&lt;br /&gt;
&lt;br /&gt;
With a loader which doesn't have a checksum, you have no way to verify the data, and therefore you can't guarantee that the data is identical to the original.&lt;br /&gt;
&lt;br /&gt;
In this case, the only way to test that the data is correct is to make multiple transfers of the program and test each thoroughly (e.g. if the program is a game, you would play the game to the end), checking for graphic corruption and bugs. If all of the transfers operate the same, then you can assume that the data is correct.&lt;br /&gt;
Various Audio file formats&lt;br /&gt;
&lt;br /&gt;
There are numerous Audio file formats, each of which can store audio, but each has it's own structures and representation for the data.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;format&amp;quot; of a file describes the internal structure, order and encoding of the data within the file.&lt;br /&gt;
&lt;br /&gt;
Here is a list of the audio file formats supported by samp2cdt:&lt;br /&gt;
&lt;br /&gt;
* Windows Wave file (a file which has the &amp;quot;.wav&amp;quot; file extension) is the common file format used for audio sounds on computers running &amp;quot;Windows&amp;quot;.&lt;br /&gt;
* A Voice Wave file (a file which has the &amp;quot;.voc&amp;quot; file extension) was created by Creative for the original Soundblaster ISA sound card. This file format is used by the original voc2tzx utility which samp2cdt was developed from.&lt;br /&gt;
* A Audio Interchange file (a file which has the &amp;quot;.aiff&amp;quot; or &amp;quot;.aif&amp;quot; file extension) is the common file format used for audio sounds on the Mac computer.&lt;br /&gt;
* A file which has the &amp;quot;.iff&amp;quot; file extension is the common file format used for audio sounds by the Amiga computer.&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15043</id>
		<title>Cassette data information</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Cassette_data_information&amp;diff=15043"/>
				<updated>2007-03-13T21:32:42Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Recording a sound ==&lt;br /&gt;
&lt;br /&gt;
A sound is recorded by making a measurement of the amplitude of the sound at regular intervals which are defined by the &amp;quot;sample rate&amp;quot;. The act of taking the measurement is often called &amp;quot;sampling&amp;quot; and each measurement unit is called a &amp;quot;sample&amp;quot;. A file which contains samples is often called a &amp;quot;sound sample&amp;quot; or &amp;quot;audio sample&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;sample rate&amp;quot; defines the rate/frequency at which the measurements are taken. The higher the sample rate, the faster the measurements are taken, and the lower the sample rate, the slower the measurements are taken. The sample rate is described by the &amp;quot;Hz&amp;quot; unit of measurement. The &amp;quot;Hz&amp;quot; unit of measurement means &amp;quot;per second&amp;quot;. Therefore, a sample rate of 44010Hz means 44010 measurements are taken each second (this is one measurement every 1/44010 th of a second).&lt;br /&gt;
&lt;br /&gt;
If the &amp;quot;sample rate&amp;quot; is too low, then changes in the sound which occur between each measurement will not be measured. Therefore the faster the measurements are taken, the more accurate the recording will be, and therefore the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
It is worth noting that at high sample rates, because there are many more measurements taken, the resulting size of the file (containing the audio data) can be large.&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;sample&amp;quot; which uses 8-bits for storage can represent 256 distinct amplitude levels and a sample which uses 16-bits for storage can describe 65535 distinct amplitude levels. The higher the number of bits used by each sample for storage, the larger the range of distinct amplitude levels that can be represented. Therefore, the higher the number of bits used by each sample for storage, the higher the quality of sound that can be recorded.&lt;br /&gt;
&lt;br /&gt;
All modern sound cards should support 8-bit and 16-bit samples and sample rates of 22050Hz and 44100Hz.&lt;br /&gt;
&lt;br /&gt;
Some sound cards will support a greater range of recording rates which can be lower and higher than these values.&lt;br /&gt;
&lt;br /&gt;
For samp2cdt you should save the file as &amp;quot;PCM&amp;quot; (&amp;quot;Pulse Code Modulation&amp;quot;). This is a uncompressed, unencoded storage representation. Each sample is a single measurement of the amplitude of the sound taken at a measurement point in time.&lt;br /&gt;
&lt;br /&gt;
Other representations such as &amp;quot;ADPCM&amp;quot; (&amp;quot;Amplitude Delta Pulse Code Modulation&amp;quot;), encode or compress the data to reduce the size of the audio file. Samp2cdt can't understand these representations, so please use &amp;quot;PCM&amp;quot; only.&lt;br /&gt;
&lt;br /&gt;
[[Image:wave1.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 1. An amplitude/time graph showing the waveform of the original sound'''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave2.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 2. An amplitude/time graph showing the waveform of the original sound. The crosses indicate the amplitude measured at each sample time and the dotted lines indicate the the time of each measurement. The duration of time between each dotted line, defined by the sample rate, is equal to the duration of a sample. From this it can be seen that each sample has a finite and equal duration.''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave3.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 3. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, the crosses indicate the amplitude measured at each sample time. The dotted line shows the waveform generated by sampling. The final value of each sample is defined to be the amplitude measured at the time of measurement.'''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave4.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 4. An amplitude/time graph showing the sampled waveform. This waveform was generated at a high sample rate, and therefore the resulting waveform has a shape which is similar to the original. This waveform is the type you can see in a audio recording program like Goldwave.'''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave5.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 5. An amplitude/time graph showing the waveform of the original sound. As in Fig 2, this graph shows the amplitude of each measurement, and the dotted line indicates the time of measurement. This graph was created using a low sample rate. Notice that the time between each measurement is longer compared to Fig 2.'''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave6.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 6. An amplitude/time graph showing the waveform of the original sound. As in Fig 3, the crosses indicate the amplitude measured at each sample time, and the dotted line shows the waveform generated by sampling. This graph shows the resulting waveform generated using a low sample rate.'''&lt;br /&gt;
&lt;br /&gt;
[[Image:wave7.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Fig 7. An amplitude/time graph showing the sampled waveform. This waveform was generated at a low sample rate, and therefore the resulting waveform is much more coarse compared to Fig 4. Notice that although the general shape is similar to the original waveform, and much of the smoothness is is lost between the time of each measurement. The loss of smoothness also means loss of information since this waveform is not the same as the original. If you compare this graph against Fig 4 then you will see that the lower the sample rate, the more information is lost. The higher the sample rate, the less information is lost. Therefore, to record a sound, it is best to use a high sample rate'''&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
1. The &amp;quot;Nyquist theory&amp;quot; states that in order to accuratly record a sound of a known frequency, you must use a recording frequency which is twice that frequency.&lt;br /&gt;
&lt;br /&gt;
i.e. to record a sound of 3000Hz, you must record using 6000Hz.&lt;br /&gt;
&lt;br /&gt;
If you use a lower frequency (e.g. 5000Hz), then the sound is not recorded accuratly.&lt;br /&gt;
&lt;br /&gt;
Most Amstrad loaders are between 300 to 2500Hz, therefore you should use a recording sample rate of at least 5000Hz. It is recommended to use one of the &amp;quot;common&amp;quot; sample rates. e.g. 22050Hz (22Khz) or 44100Hz (44.1Khz)&lt;br /&gt;
&lt;br /&gt;
2. There are two different representations to store the amplitude of the sample in a PCM audio file: unsigned or signed.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit unsigned sample has values between 0 and 255. In this range, 0 represents a low amplitudes, 255 a high amplitude, and the amplitudes increase linearly from 0 to 255.&lt;br /&gt;
&lt;br /&gt;
* A 8-bit signed sample has values between -128 and 127. In this range, -128 represents a low amplitude, and 127 high amplitude, and the amplitudes increase linearly from -128 to 127.&lt;br /&gt;
&lt;br /&gt;
Both methods can represent the same data, so there is no advantage to using either. The original reason for the two methods is due to the original method to playback the sound. Modern sound cards can play both methods of data storage. &lt;br /&gt;
&lt;br /&gt;
== Duplication of cassettes ==&lt;br /&gt;
&lt;br /&gt;
When the writing of a program is completed a &amp;quot;master&amp;quot; cassette is created. This cassette contains a audio representation of the computer data.&lt;br /&gt;
&lt;br /&gt;
The master cassette is then duplicated, using a machine, onto many blank cassettes. These cassettes are packaged with instructions and distributed.&lt;br /&gt;
&lt;br /&gt;
It is also easy to make a copy of a cassette if you have a twin cassette system, where one cassette unit will play the sound and the other will record. A first generation copy taken from a original cassette could be considered a copy of a copy of the master cassette.&lt;br /&gt;
&lt;br /&gt;
Each time a cassette is copied however, additional noise may be introduced into the copied version. This noise is a mixture of noise from the original, and noise created by the machine making the copy. Therefore the sound on any cassette contains a mixture of noise and the sound of the computer data.&lt;br /&gt;
&lt;br /&gt;
A loader on the computer must therefore be able to identify the actual sound of the data from other sounds that are on the cassette. If it can't do this, then there will be loading errors.&lt;br /&gt;
&lt;br /&gt;
If you are transfering a cassette using samp2cdt, then you are advised to use an original (i.e. a cassette created directly from a master cassette), or a first generation copy (i.e. a cassette copied from an original).&lt;br /&gt;
&lt;br /&gt;
== Loader ==&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;loader&amp;quot; is the name given to a program that reads data from cassette into the computer memory.&lt;br /&gt;
&lt;br /&gt;
There is a &amp;quot;system&amp;quot; loader which is built into the Amstrad CPC ROM. This loader is activated when the computer is in cassette mode (note 1), and it can only understand one specific computer audio sound, the audio sound of the Amstrad CPC system data-blocks.&lt;br /&gt;
&lt;br /&gt;
To read other loading systems (e.g. a fast-loader), there must be a program on the cassette (a &amp;quot;pre-loader&amp;quot; or &amp;quot;boot loader&amp;quot; or sometimes refered to as &amp;quot;loader&amp;quot;), stored using the Amstrad CPC system loader, which when executed will be able to understand and load fast-loader data.&lt;br /&gt;
&lt;br /&gt;
This loader program is usually stored immediatly before any fast-loader blocks, and takes over from the system loader to load the remaining fast-loader blocks.&lt;br /&gt;
&lt;br /&gt;
|program for fast-loader| |fast-loader block(s)|&lt;br /&gt;
&lt;br /&gt;
So when a cassette is loaded the following occurs:&lt;br /&gt;
&lt;br /&gt;
# system loader recognises and loads &amp;quot;program for fast-loader&amp;quot;.&lt;br /&gt;
# &amp;quot;program for fast loader&amp;quot; takes control and loads the data from the fast-loader block(s) into computer memory&lt;br /&gt;
# when loading has completed, the program is executed. &lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
# a CPC without a disc interface (e.g. a CPC464, CPC464+ or KC Compact) will start-up in cassette mode. For a CPC with a disc interface attached (or internal), you must type |TAPE to enter cassette mode.&lt;br /&gt;
&lt;br /&gt;
You can test if the computer is operating in cassette mode by typing RUN&amp;quot;. If you see &amp;quot;Press PLAY then any key&amp;quot;, then the computer is operating in cassette mode. If there is an error, then the computer is not operating in cassette mode. &lt;br /&gt;
&lt;br /&gt;
== Amstrad cassette hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Reading ===&lt;br /&gt;
&lt;br /&gt;
The audio from the cassette is read from a cassette player through the Amstrad's cassette electronics.&lt;br /&gt;
&lt;br /&gt;
The Amstrad's cassette electronics converts the amplitude of the sound (a analogue signal) into a &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement (a digital signal). This measurement can then be read from bit 7 of port B of the PPI 8255 IC.&lt;br /&gt;
&lt;br /&gt;
[Picture showing the conversion process]&lt;br /&gt;
&lt;br /&gt;
[Fig 8. This image shows the conversion of the audio waveform from the cassette into the digital representation by the Amstrad's cassette electronics. i.e. audio waveform (on cassette) -&amp;gt; Amstrad's cassette electronics -&amp;gt; 0 and 1 measurements]&lt;br /&gt;
&lt;br /&gt;
The resulting measurements can be read using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ld b,&amp;amp;f5			;; I/O port address for PPI 8255 port B&lt;br /&gt;
				;; (PPI 8255 port B is operating as input.)&lt;br /&gt;
in a,(c)			;; read port B inputs&lt;br /&gt;
and %10000000			;; isolate bit 7 which contains the measurement.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This measurement is *not* the actual state of a data-bit, but represents a low (&amp;quot;0&amp;quot;) or high amplitude (&amp;quot;1&amp;quot;). In this document, the value of this measurement will be refered to as a &amp;quot;high&amp;quot; (&amp;quot;1&amp;quot;) or &amp;quot;low&amp;quot; (&amp;quot;0&amp;quot;) level.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
   1. The CPC464 and CPC464+ have a cassette player built in. To connect a cassette player to the CPC664, CPC6128 or KC Compact then you must use a lead.&lt;br /&gt;
   2. It is not known exactly how the amplitude of the sound from the cassette corresponds to the final &amp;quot;0&amp;quot; or &amp;quot;1&amp;quot; measurement.&lt;br /&gt;
&lt;br /&gt;
      samp2cdt uses a crude method to perform this conversion.&lt;br /&gt;
&lt;br /&gt;
      For a 8-bit signed sample:&lt;br /&gt;
          * if the amplitude is 0..128, then the final measurement will be &amp;quot;1&amp;quot;.&lt;br /&gt;
          * if the amplitude is -128..0 then the final measurement will be &amp;quot;0&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
=== Writing ===&lt;br /&gt;
&lt;br /&gt;
A waveform is written to cassette using bit 5 of port C of the 8255 PPI IC. The waveform can only be defined by a high or low level, defined by the state of bit 5, which is then converted by the Amstrad's cassette electronics into a final output amplitude which is recorded onto cassette.&lt;br /&gt;
&lt;br /&gt;
A high level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
				;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
set 5,a			;; set cassette write output to high level &lt;br /&gt;
out (c),a			;; output level&lt;br /&gt;
&lt;br /&gt;
A low level can be written using the following Z80 instructions:&lt;br /&gt;
&lt;br /&gt;
ld b,&amp;amp;f6		;; I/O port address for PPI 8255 port C&lt;br /&gt;
				;; (PPI 8255 port C is operating as output.)&lt;br /&gt;
&lt;br /&gt;
res 5,a			;; set cassette write output to low level&lt;br /&gt;
out (c),a			;; output level&lt;br /&gt;
&lt;br /&gt;
The amplitude of the output waveform is not amplified, therefore if you wish to record the cassette audio direct from an Amstrad you will need to amplify the waveform.&lt;br /&gt;
&lt;br /&gt;
If the state of bit 5 is changed at a fixed frequency, then the graph of the state of bit 5 over time will be a square wave. However, the resulting audio written on the cassette will not be a perfect square wave because nature will attempt to convert the waveform into a sine wave.&lt;br /&gt;
Loading system audio waveform&lt;br /&gt;
&lt;br /&gt;
Every loading system on the Amstrad uses a serial bit-stream. i.e. a single bit of information is read at a time.&lt;br /&gt;
&lt;br /&gt;
This serial bit-stream is grouped into blocks of audio sound.&lt;br /&gt;
&lt;br /&gt;
Every loading system uses a basic structure to describe each audio block in the following order:&lt;br /&gt;
&lt;br /&gt;
|pilot|sync|data|trailer|&lt;br /&gt;
&lt;br /&gt;
pilot&lt;br /&gt;
    This is also refered to as &amp;quot;leader&amp;quot; by some documents.&lt;br /&gt;
&lt;br /&gt;
    This is constructed from a repeated waveform often with a fixed number of repetitions defined by the loading system.&lt;br /&gt;
&lt;br /&gt;
    The shape of the waveform is known by the loader program and this is used to identify the pilot waveform from other waveforms that may be present (e.g. noise).&lt;br /&gt;
&lt;br /&gt;
    The pilot is often long, so that the loader doesn't need to see the start of the pilot waveform in order to load the block.&lt;br /&gt;
&lt;br /&gt;
    The loader program will test the incoming waveform, checking it against the parameters defined for the pilot, before the waveform is accepted as the pilot waveform. (e.g. the number of repetitions must be some defined minimum value). The incoming waveform must fall within these specifications otherwise the waveform is not accepted as a pilot waveform. &lt;br /&gt;
sync (&amp;quot;synchronisation&amp;quot;)&lt;br /&gt;
    The sync is a waveform which is different to the pilot, and this defines the end of the pilot and the start of the data. When this sync has been detected, the loader knows that there is data following, and that the loader is always at the same point in the data stream. i.e. the loader program is synchronised to a specific point in the data waveform.&lt;br /&gt;
data&lt;br /&gt;
    This is the actual data which is composed of waveforms defining &amp;quot;0&amp;quot; and &amp;quot;1&amp;quot; data bits.&lt;br /&gt;
&lt;br /&gt;
    The first element of the data may be a marker or id which may, for example, indicate the type of data in the block or the number of the block.&lt;br /&gt;
&lt;br /&gt;
    The remaining bits will define the data and zero or more checksums.&lt;br /&gt;
&lt;br /&gt;
    The whole data may consist of a single block with a single location and length (e.g. one block for a screen another for data), or multiple blocks each with their own location and length. (e.g. one block for screen and data)&lt;br /&gt;
&lt;br /&gt;
    The location and lengths of the blocks may be in the data stream itself, or they may be in a preceeding block, or may be hard-coded into the loader program. &lt;br /&gt;
trailer&lt;br /&gt;
    The trailer always follows the data. Some loaders may not have a trailer. The two main purposes of the trailer are to ensure that the waveform of the last data bit in the data is constructed correctly and to provide some time in which the loader can prepare for the next block.&lt;br /&gt;
&lt;br /&gt;
The exact definition of the loading systems's audio waveform is defined by the loader program.&lt;br /&gt;
&lt;br /&gt;
samp2cdt has a number of decoder algorithms which recognises the audio waveform of various loading systems. These decoders read the waveform using a similar method to the loader program itself. These decoders have been created by examining the instructions of each loader program and the graph of the waveform in a sound recording package.&lt;br /&gt;
Example of a typical loading system&lt;br /&gt;
The data on cassette actually consists of changing 0 and 1 levels. (a &amp;quot;level&amp;quot; is a magnitude of a value). The loader measures the time between each &amp;quot;level transition&amp;quot; where a &amp;quot;level transition&amp;quot; is the change from a &amp;quot;0&amp;quot; to a &amp;quot;1&amp;quot; level or the change from a &amp;quot;1&amp;quot; to a &amp;quot;0&amp;quot; level. The level can be timed using the following Z80 instructions: ;; - keep testing the state of bit 7 of PPI 8255 port B ;; - update the counter to record the number of tests done ;; - when bit 7 of PPI 8255 port B changes state, stop testing. ;; counter will hold the total number of tests made. ;; ;; B = &amp;amp;F5 (I/O address of PPI 8255 input port B) ;; C = previous data read from PPI port B ld d,0 ;; initialise count to 0 .loop inc d ;; increment count in a,(c) ;; read input to PPI 8255 port B xor c ;; exclusive-or with previous data read from PPI 8255 port B and %10000000 ;; isolate bit 7 ;; if result is 0, then the state of bit 7 that has ;; been read is the same as the previous state. i.e. bit 7 has not changed state. ;; if result is not 0, then the state of bit 7 has changed. ;; e.g. if bit 7 was previously 1, it is now 0. if bit 7 was previously 0, it is now 1. jr z,loop ;; when execution reaches here we know that bit 7 has changed state and D ;; contains the number of tests.&lt;br /&gt;
Loader operation&lt;br /&gt;
The loader generally operates in this way: 1. time a wave. Is the duration of the wave within the minimum and maximum duration required for the pilot. If yes, go to 2, else go to 1. 2. We might have seen a wave from the pilot signal. time a wave. Is the duration of this wave within the minimum and maximum duration required for the pilot. If yes, increment number of waves seen, go to 2, else go to 1. 3. Have we seen the minimum number of pilot waves? Yes, go to 4, else go to 2. 4. time a wave. Is the duration of the wave within the minimum and maximum duration required for the sync? 2. Each Z80 instruction takes a finite time to execute. The execution time depends on the computer. If the timing of the Z80 instructions used by the test algorithm is known and predictable, then the time for each test can be calculated. Now, since the count represents the number of tests made before the condition is true (i.e. bit 7 changes state), the total time for the condition to be true, is the sum of the time for each test made. If each test always takes the same time, then the total time is the number of tests multiplied by the time for one test. In the Amstrad computer, all Z80 instructions execute in multiples of 1us (microsecond) regardless of their location in RAM. This fact simplifies this calculation.&lt;br /&gt;
Checksum&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;Checksum&amp;quot; is used to verify the loaded data.&lt;br /&gt;
&lt;br /&gt;
A Checksum is the result of the &amp;quot;checksum calculation&amp;quot; made on a block of data. The actual calculation can be different depending on the method chosen.&lt;br /&gt;
&lt;br /&gt;
There are two &amp;quot;Checksum&amp;quot;s.&lt;br /&gt;
&lt;br /&gt;
1. a stored &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the correct data. This is then stored with the data (e.g. before or after the data) when the master cassette is created.&lt;br /&gt;
2. a calculated &amp;quot;Checksum&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is the result of the &amp;quot;checksum calculation&amp;quot; calculated from the data read from the cassette. After the calculation is complete it is compared against the stored checksum. &lt;br /&gt;
&lt;br /&gt;
The stored and calculated &amp;quot;Checksums&amp;quot; are initialised with the same initial value and calculated using the same algorithm. Therefore, if the stored checksum matches the calculated checksum, it is assumed that the loaded data is identical to the original data. The data is verified to be correct.&lt;br /&gt;
&lt;br /&gt;
If the stored checksum doesn't match the calculated checksum, then there has been a error. One or more bit's of data is incorrect. The checksum is designed to detect errors only, and often it is not possible to know which bit or bits of data is incorrect and in this case it is not often possible to correct the errors to reproduce the correct data.&lt;br /&gt;
&lt;br /&gt;
A loader which has a checksum therefore is better than a loader that doesn't have a checksum, because the checksum will verify that the data is correct or incorrect.&lt;br /&gt;
&lt;br /&gt;
With a loader which doesn't have a checksum, you have no way to verify the data, and therefore you can't guarantee that the data is identical to the original.&lt;br /&gt;
&lt;br /&gt;
In this case, the only way to test that the data is correct is to make multiple transfers of the program and test each thoroughly (e.g. if the program is a game, you would play the game to the end), checking for graphic corruption and bugs. If all of the transfers operate the same, then you can assume that the data is correct.&lt;br /&gt;
Various Audio file formats&lt;br /&gt;
&lt;br /&gt;
There are numerous Audio file formats, each of which can store audio, but each has it's own structures and representation for the data.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;format&amp;quot; of a file describes the internal structure, order and encoding of the data within the file.&lt;br /&gt;
&lt;br /&gt;
Here is a list of the audio file formats supported by samp2cdt:&lt;br /&gt;
&lt;br /&gt;
* Windows Wave file (a file which has the &amp;quot;.wav&amp;quot; file extension) is the common file format used for audio sounds on computers running &amp;quot;Windows&amp;quot;.&lt;br /&gt;
* A Voice Wave file (a file which has the &amp;quot;.voc&amp;quot; file extension) was created by Creative for the original Soundblaster ISA sound card. This file format is used by the original voc2tzx utility which samp2cdt was developed from.&lt;br /&gt;
* A Audio Interchange file (a file which has the &amp;quot;.aiff&amp;quot; or &amp;quot;.aif&amp;quot; file extension) is the common file format used for audio sounds on the Mac computer.&lt;br /&gt;
* A file which has the &amp;quot;.iff&amp;quot; file extension is the common file format used for audio sounds by the Amiga computer.&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Screen_Splitting&amp;diff=14859</id>
		<title>Programming:CPC Plus Screen Splitting</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Screen_Splitting&amp;diff=14859"/>
				<updated>2007-03-12T14:35:05Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
;; This example shows how to split the screen using the CPC+&lt;br /&gt;
;; If you want to do the same effect on the CPC, then you will&lt;br /&gt;
;; need to use the &amp;quot;rupture&amp;quot;/&amp;quot;vertical splitting&amp;quot; technique.&lt;br /&gt;
;;&lt;br /&gt;
;; This example is designed for CPC+ only and will&lt;br /&gt;
;; not work on CPC or KC Compact.&lt;br /&gt;
;;&lt;br /&gt;
;;;; This example will compile with the MAXAM assembler&lt;br /&gt;
;; or the built-in assembler of WinAPE32.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; NOTE - For this example to work, the code must not&lt;br /&gt;
;; be in the range &amp;amp;4000-&amp;amp;7fff inclusive. The ASIC registers&lt;br /&gt;
;; are paged into this range, and the code would not be&lt;br /&gt;
;; visible to the CPU if it was also in this range.&lt;br /&gt;
org &amp;amp;8000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; STEP 1 - Unlock CPC+ additional features&lt;br /&gt;
;; unlock asic to gain access to asic registers&lt;br /&gt;
&lt;br /&gt;
di&lt;br /&gt;
ld b,&amp;amp;bc&lt;br /&gt;
ld hl,sequence&lt;br /&gt;
ld e,17&lt;br /&gt;
.seq &lt;br /&gt;
ld a,(hl)&lt;br /&gt;
out (c),a&lt;br /&gt;
inc hl&lt;br /&gt;
dec e&lt;br /&gt;
jr nz,seq&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------&lt;br /&gt;
;; STEP 2 - Set display start address for display before split&lt;br /&gt;
&lt;br /&gt;
;; this address corresponds to a start of &amp;amp;c000&lt;br /&gt;
ld hl,&amp;amp;3000&lt;br /&gt;
&lt;br /&gt;
;; set display start address (high)&lt;br /&gt;
ld bc,&amp;amp;bc0c&lt;br /&gt;
out (c),c&lt;br /&gt;
inc b&lt;br /&gt;
out (c),h&lt;br /&gt;
&lt;br /&gt;
;; set display start address (low)&lt;br /&gt;
ld bc,&amp;amp;bc0d&lt;br /&gt;
out (c),c&lt;br /&gt;
inc b&lt;br /&gt;
out (c),l&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------------&lt;br /&gt;
;; STEP 3 - Set display start address for display after split&lt;br /&gt;
;;&lt;br /&gt;
;; - The split is refreshed by the ASIC, so as soon as it has been initialised&lt;br /&gt;
;;   it will remain active until it is disabled (by writing 0 as the scan-line for the split)&lt;br /&gt;
;;   No extra CPU time is required to maintain the split.&lt;br /&gt;
;;&lt;br /&gt;
;; - The split address is defined the same as the CRTC display start address&lt;br /&gt;
;;&lt;br /&gt;
;; - The split address is in the same order as the CRTC display start address &lt;br /&gt;
;;   (high byte followed by low byte)&lt;br /&gt;
&lt;br /&gt;
;; page-in asic registers to &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;; set scan-line that split will activate on&lt;br /&gt;
ld a,100&lt;br /&gt;
ld (&amp;amp;6801),a&lt;br /&gt;
&lt;br /&gt;
;; set screen address of split:&lt;br /&gt;
;; this address corresponds to start of &amp;amp;4000&lt;br /&gt;
ld hl,&amp;amp;1000&lt;br /&gt;
&lt;br /&gt;
ld a,h&lt;br /&gt;
ld (&amp;amp;6802),a&lt;br /&gt;
ld a,l&lt;br /&gt;
ld (&amp;amp;6803),a&lt;br /&gt;
&lt;br /&gt;
;; page-out asic registers&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------&lt;br /&gt;
;; this is the sequence to unlock the ASIC extra features&lt;br /&gt;
.sequence&lt;br /&gt;
defb &amp;amp;ff,&amp;amp;00,&amp;amp;ff,&amp;amp;77,&amp;amp;b3,&amp;amp;51,&amp;amp;a8,&amp;amp;d4,&amp;amp;62,&amp;amp;39,&amp;amp;9c,&amp;amp;46,&amp;amp;2b,&amp;amp;15,&amp;amp;8a,&amp;amp;cd,&amp;amp;ee&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Hardware_Sprites&amp;diff=14858</id>
		<title>Programming:CPC Plus Hardware Sprites</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Hardware_Sprites&amp;diff=14858"/>
				<updated>2007-03-12T14:33:56Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
;; This example shows a CPC+ hardware sprite.&lt;br /&gt;
;;&lt;br /&gt;
;; This example is designed for CPC+ only and will&lt;br /&gt;
;; not work on CPC or KC Compact.&lt;br /&gt;
;;&lt;br /&gt;
;;&lt;br /&gt;
;; This example will compile with the MAXAM assembler&lt;br /&gt;
;; or the built-in assembler of WinAPE32.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; NOTE - For this example to work, the code must not&lt;br /&gt;
;; be in the range &amp;amp;4000-&amp;amp;7fff inclusive. The ASIC registers&lt;br /&gt;
;; are paged into this range, and the code would not be&lt;br /&gt;
;; visible to the CPU if it was also in this range.&lt;br /&gt;
org &amp;amp;8000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; STEP 1 - Unlock CPC+ additional features&lt;br /&gt;
;; unlock asic to gain access to asic registers&lt;br /&gt;
&lt;br /&gt;
di&lt;br /&gt;
ld b,&amp;amp;bc&lt;br /&gt;
ld hl,sequence&lt;br /&gt;
ld e,17&lt;br /&gt;
.seq &lt;br /&gt;
ld a,(hl)&lt;br /&gt;
out (c),a&lt;br /&gt;
inc hl&lt;br /&gt;
dec e&lt;br /&gt;
jr nz,seq&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; STEP 2 - Setup sprite pixel data&lt;br /&gt;
;;&lt;br /&gt;
;; The ASIC has internal &amp;quot;RAM&amp;quot; used to store the sprite pixel&lt;br /&gt;
;; data. If you want to change the pixel data for a sprite&lt;br /&gt;
;; then you need to copy new data into the internal &amp;quot;RAM&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
;; page-in asic registers to &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;; stored sprite pixel data&lt;br /&gt;
ld hl,sprite_pixel_data&lt;br /&gt;
&lt;br /&gt;
;; address of sprite 0 pixel data&lt;br /&gt;
;; sprite 0 pixel data is in the range &amp;amp;4000-&amp;amp;4100&lt;br /&gt;
ld de,&amp;amp;4000&lt;br /&gt;
&lt;br /&gt;
;; length of pixel data for a single sprite (16x16 = 256)&lt;br /&gt;
ld bc,&amp;amp;100&lt;br /&gt;
ldir&lt;br /&gt;
&lt;br /&gt;
;; page-out asic registers&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; STEP 3 - Setup sprite palette&lt;br /&gt;
;;&lt;br /&gt;
;; The sprites use a single 15 entry sprite palette.&lt;br /&gt;
;; pen 0 is ALWAYS transparent.&lt;br /&gt;
;;&lt;br /&gt;
;; The sprite palette is different to the screen palette.&lt;br /&gt;
&lt;br /&gt;
;; page-in asic registers to &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;; copy colours into ASIC sprite palette registers&lt;br /&gt;
ld hl,sprite_colours&lt;br /&gt;
ld de,&amp;amp;6422&lt;br /&gt;
ld bc,15*2&lt;br /&gt;
ldir&lt;br /&gt;
&lt;br /&gt;
;; page-out asic registers&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; STEP 4 - Setup sprite properties&lt;br /&gt;
;;&lt;br /&gt;
;; Each sprite has properties which define the x,y coordinates &lt;br /&gt;
;; and x,y magnification.&lt;br /&gt;
&lt;br /&gt;
;; page-in asic registers to &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; set x coordinate for sprite 0&lt;br /&gt;
ld hl,100&lt;br /&gt;
ld (&amp;amp;6000),hl&lt;br /&gt;
&lt;br /&gt;
;; set y coordinate for sprite 0&lt;br /&gt;
ld hl,100&lt;br /&gt;
ld (&amp;amp;6002),hl&lt;br /&gt;
&lt;br /&gt;
;; set sprite x and y magnification&lt;br /&gt;
;; x magnification = 1&lt;br /&gt;
;; y magnification = 1&lt;br /&gt;
ld a,%0101&lt;br /&gt;
ld (&amp;amp;6004),a&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; page-out asic registers&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;--------------------------------------------------&lt;br /&gt;
;; - there is two bytes per colour.&lt;br /&gt;
;; - these are stored in a form that can be written direct &lt;br /&gt;
;; to the CPC+ colour palette registers (i.e. xGRB)&lt;br /&gt;
;; - pen 0 is always transparent and doesn't have a entry&lt;br /&gt;
;; in the CPC+ palette&lt;br /&gt;
&lt;br /&gt;
.sprite_colours&lt;br /&gt;
defw &amp;amp;0111			;; colour for sprite pen 1&lt;br /&gt;
defw &amp;amp;0222			;; colour for sprite pen 2&lt;br /&gt;
defw &amp;amp;0333			;; colour for sprite pen 3&lt;br /&gt;
defw &amp;amp;0444			;; colour for sprite pen 4&lt;br /&gt;
defw &amp;amp;0555			;; colour for sprite pen 5&lt;br /&gt;
defw &amp;amp;0666			;; colour for sprite pen 6&lt;br /&gt;
defw &amp;amp;0777			;; colour for sprite pen 7&lt;br /&gt;
defw &amp;amp;0888			;; colour for sprite pen 8&lt;br /&gt;
defw &amp;amp;0999			;; colour for sprite pen 9&lt;br /&gt;
defw &amp;amp;0aaa			;; colour for sprite pen 10&lt;br /&gt;
defw &amp;amp;0bbb			;; colour for sprite pen 11&lt;br /&gt;
defw &amp;amp;0ccc			;; colour for sprite pen 12&lt;br /&gt;
defw &amp;amp;0ddd			;; colour for sprite pen 13&lt;br /&gt;
defw &amp;amp;0eee			;; colour for sprite pen 14&lt;br /&gt;
defw &amp;amp;0fff			;; colour for sprite pen 15&lt;br /&gt;
&lt;br /&gt;
;;---------------------------------------------&lt;br /&gt;
;; - there is one pixel per byte (bits 3..0 of each byte define the palette index for this pixel)&lt;br /&gt;
;; - these bytes are stored in a form that can be written direct to the ASIC&lt;br /&gt;
;; sprite pixel data&lt;br /&gt;
.sprite_pixel_data&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 0&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 1&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 2&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 3&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 4&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 5&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 6&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 7&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 8&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 9&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 10&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 11&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 12&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 13&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 14&lt;br /&gt;
defb &amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00,&amp;amp;00		;; line 15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------&lt;br /&gt;
;; this is the sequence to unlock the ASIC extra features&lt;br /&gt;
.sequence&lt;br /&gt;
defb &amp;amp;ff,&amp;amp;00,&amp;amp;ff,&amp;amp;77,&amp;amp;b3,&amp;amp;51,&amp;amp;a8,&amp;amp;d4,&amp;amp;62,&amp;amp;39,&amp;amp;9c,&amp;amp;46,&amp;amp;2b,&amp;amp;15,&amp;amp;8a,&amp;amp;cd,&amp;amp;ee&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Vertical_scroll&amp;diff=14857</id>
		<title>Programming:CPC Plus Vertical scroll</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Vertical_scroll&amp;diff=14857"/>
				<updated>2007-03-12T13:37:34Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
;; This example shows how to scroll the screen vertically using the&lt;br /&gt;
;; CPC+ &amp;quot;soft&amp;quot; hardware scroll. This scroll is smooth because it will scroll&lt;br /&gt;
;; a scanline at a time.&lt;br /&gt;
;;&lt;br /&gt;
;; This example will only work on the CPC+.&lt;br /&gt;
;;&lt;br /&gt;
;; The scroll is made by changing the start of the screen using the CRTC,&lt;br /&gt;
;; (which will scroll the screen vertically by the number of scanlines defined by register 9),&lt;br /&gt;
;; and a scan-line adjustment defined using the CPC+ &amp;quot;soft&amp;quot; hardware scroll register.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; The location of this code is important. It must not be located&lt;br /&gt;
;; between &amp;amp;4000-&amp;amp;7fff.&lt;br /&gt;
org &amp;amp;8000&lt;br /&gt;
nolist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; unlock asic to gain access to asic registers&lt;br /&gt;
di&lt;br /&gt;
ld b,&amp;amp;bc&lt;br /&gt;
ld hl,sequence&lt;br /&gt;
ld e,17&lt;br /&gt;
.seq &lt;br /&gt;
ld a,(hl)&lt;br /&gt;
out (c),a&lt;br /&gt;
inc hl&lt;br /&gt;
dec e&lt;br /&gt;
jr nz,seq&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; install a interrupt handler&lt;br /&gt;
;;&lt;br /&gt;
;; We install our own interrupt handler for this reason:&lt;br /&gt;
;; - To stop the firmware interrupt from being executed, this will&lt;br /&gt;
;; ensure that our direct access to the hardware will not be interrupted&lt;br /&gt;
;; by the firmware, and that the values we write are not re-written by&lt;br /&gt;
;; the firmware.&lt;br /&gt;
&lt;br /&gt;
di								;; disable interrupts&lt;br /&gt;
im 1							;; set interrupt mode 1 (jump to &amp;amp;0038 when interrupt occurs)&lt;br /&gt;
ld hl,&amp;amp;c9fb						;; EI:RET&lt;br /&gt;
ld (&amp;amp;0038),hl					;; &amp;amp;0038 is executed&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; main loop&lt;br /&gt;
&lt;br /&gt;
.main_loop&lt;br /&gt;
;; wait for start of vsync. This test assumes that the start of the vsync&lt;br /&gt;
;; has not yet happened.&lt;br /&gt;
&lt;br /&gt;
ld b,&amp;amp;f5&lt;br /&gt;
.ml2&lt;br /&gt;
in a,(c)&lt;br /&gt;
rra&lt;br /&gt;
jr nc,ml2&lt;br /&gt;
&lt;br /&gt;
;; The vsync has just started, we can safely setup the scroll&lt;br /&gt;
;; without the display being effected.&lt;br /&gt;
&lt;br /&gt;
;;-----------------------------------------------------------------------&lt;br /&gt;
;; update vertical scan-line scroll adjustment&lt;br /&gt;
&lt;br /&gt;
;; page in ASIC ram&lt;br /&gt;
;; ASIC registers will be paged into memory range &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;; get scan-line scroll adjustment&lt;br /&gt;
ld a,(scanline_offset)&lt;br /&gt;
;; shift into bits required for writing to hardware&lt;br /&gt;
add a,a&lt;br /&gt;
add a,a&lt;br /&gt;
add a,a&lt;br /&gt;
add a,a&lt;br /&gt;
;; write to &amp;quot;soft&amp;quot; hardware scroll register of CPC+&lt;br /&gt;
ld (&amp;amp;6804),a&lt;br /&gt;
&lt;br /&gt;
;; page out ASIC ram&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;-----------------------------------------------------------------------&lt;br /&gt;
;; update CRTC with scroll offset&lt;br /&gt;
&lt;br /&gt;
ld hl,(scroll_offset)		;; get scroll offset&lt;br /&gt;
&lt;br /&gt;
ld a,h&lt;br /&gt;
or &amp;amp;30					;; This defines the &amp;quot;base&amp;quot; of the screen in 16k units.&lt;br /&gt;
						;; &amp;amp;00 -&amp;gt; screen uses &amp;amp;0000-&amp;amp;3fff&lt;br /&gt;
						;; &amp;amp;10 -&amp;gt; screen uses &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
						;; &amp;amp;20 -&amp;gt; screen uses &amp;amp;8000-&amp;amp;bfff&lt;br /&gt;
						;; &amp;amp;30 -&amp;gt; screen uses &amp;amp;c000-&amp;amp;ffff&lt;br /&gt;
ld h,a&lt;br /&gt;
&lt;br /&gt;
ld bc,&amp;amp;bc0c				;; select CRTC register 12&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
inc b					;; B = &amp;amp;BD&lt;br /&gt;
out (c),h				;; write to CRTC register 12&lt;br /&gt;
&lt;br /&gt;
dec b&lt;br /&gt;
inc c					;; BC = &amp;amp;BC0D&lt;br /&gt;
out (c),c				;; select CRTC register 13&lt;br /&gt;
&lt;br /&gt;
inc b&lt;br /&gt;
out (c),l				;; write to CRTC register 13&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
;; we need to wait long enough for the VSYNC signal to finish, so that the&lt;br /&gt;
;; test at the beginning of this loop will synchronise with the *start* of the&lt;br /&gt;
;; vsync. &lt;br /&gt;
&lt;br /&gt;
;; this first HALT will catch the interrupt that occurs two scanlines from&lt;br /&gt;
;; the start of the VSYNC, the second will delay a furthur 52 scanlines. The maximum&lt;br /&gt;
;; duration for the VSYNC is 16 scanlines.&lt;br /&gt;
halt&lt;br /&gt;
&lt;br /&gt;
halt&lt;br /&gt;
&lt;br /&gt;
;; update the scroll ready for the next update of the display&lt;br /&gt;
call scroll_up&lt;br /&gt;
&lt;br /&gt;
;; loop&lt;br /&gt;
jp main_loop&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; adjust scroll parameters to scroll the screen up&lt;br /&gt;
;;&lt;br /&gt;
;; Each CRTC character is 8 scanlines tall, therefore the CRTC scroll offset &lt;br /&gt;
;; will scroll the screen up by 8 scanlines at a time.&lt;br /&gt;
;;&lt;br /&gt;
;; We use the CPC+ &amp;quot;soft&amp;quot; hardware scroll to set the scanline offset within&lt;br /&gt;
;; each CRTC character.&lt;br /&gt;
;;&lt;br /&gt;
;; The CPC+ &amp;quot;soft&amp;quot; hardware scroll is updated for every scanlines.&lt;br /&gt;
;; The CRTC scroll offset is only updated once for every 8 scanlines.&lt;br /&gt;
&lt;br /&gt;
.scroll_up&lt;br /&gt;
&lt;br /&gt;
;; get scanline offset&lt;br /&gt;
ld a,(scanline_offset)&lt;br /&gt;
inc a&lt;br /&gt;
;; ensure it is in range&lt;br /&gt;
and &amp;amp;7&lt;br /&gt;
;; store scanline offset&lt;br /&gt;
ld (scanline_offset),a&lt;br /&gt;
cp 0&lt;br /&gt;
ret nz&lt;br /&gt;
&lt;br /&gt;
;; by now we have scrolled through 8 scanlines using the CPC+ &amp;quot;soft&amp;quot; hardware&lt;br /&gt;
;; scroll, now we need to update the screen start address &lt;br /&gt;
&lt;br /&gt;
;; get the crtc scroll offset&lt;br /&gt;
ld hl,(scroll_offset)&lt;br /&gt;
&lt;br /&gt;
ld bc,40						;; this is the same as the value written to CRTC register 1&lt;br /&gt;
								;; and defines the width of the display in CRTC characters.&lt;br /&gt;
add hl,bc&lt;br /&gt;
&lt;br /&gt;
ld a,h							;; ensure the scroll offset is in the range &amp;amp;300-&amp;amp;3ff&lt;br /&gt;
and &amp;amp;3&lt;br /&gt;
ld h,a&lt;br /&gt;
&lt;br /&gt;
;; store the crtc scroll offset&lt;br /&gt;
ld (scroll_offset),hl&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; scroll offset of the screen to be written to CRTC register 12 and 13&lt;br /&gt;
;; This value is defined in &amp;quot;CRTC&amp;quot; characters.&lt;br /&gt;
.scroll_offset&lt;br /&gt;
defw 0&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; holds a number between 0 and 7 which is the scanline adjustment&lt;br /&gt;
;; for the scroll&lt;br /&gt;
.scanline_offset&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; this is the sequence to unlock the ASIC extra features&lt;br /&gt;
.sequence&lt;br /&gt;
defb &amp;amp;ff,&amp;amp;00,&amp;amp;ff,&amp;amp;77,&amp;amp;b3,&amp;amp;51,&amp;amp;a8,&amp;amp;d4,&amp;amp;62,&amp;amp;39,&amp;amp;9c,&amp;amp;46,&amp;amp;2b,&amp;amp;15,&amp;amp;8a,&amp;amp;cd,&amp;amp;ee&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	<entry>
		<id>https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Horizontal_scroll&amp;diff=14856</id>
		<title>Programming:CPC Plus Horizontal scroll</title>
		<link rel="alternate" type="text/html" href="https://oldwiki.cpcwiki.eu/index.php?title=Programming:CPC_Plus_Horizontal_scroll&amp;diff=14856"/>
				<updated>2007-03-12T13:36:28Z</updated>
		
		<summary type="html">&lt;p&gt;80.167.220.254: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
;; This example shows how to scroll the screen horizonatally using the&lt;br /&gt;
;; CPC+ &amp;quot;soft&amp;quot; hardware scroll. This scroll is smooth because it will scroll&lt;br /&gt;
;; a pixel at a time.&lt;br /&gt;
;;&lt;br /&gt;
;; This example will only work on the CPC+.&lt;br /&gt;
;;&lt;br /&gt;
;; The scroll is made by changing the start of the screen using the CRTC,&lt;br /&gt;
;; (which will scroll the screen vertically by the number of scanlines defined by register 9),&lt;br /&gt;
;; and a scan-line adjustment defined using the CPC+ &amp;quot;soft&amp;quot; hardware scroll register.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; The location of this code is important. It must not be located&lt;br /&gt;
;; between &amp;amp;4000-&amp;amp;7fff.&lt;br /&gt;
org &amp;amp;8000&lt;br /&gt;
nolist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; unlock asic to gain access to asic registers&lt;br /&gt;
di&lt;br /&gt;
ld b,&amp;amp;bc&lt;br /&gt;
ld hl,sequence&lt;br /&gt;
ld e,17&lt;br /&gt;
.seq &lt;br /&gt;
ld a,(hl)&lt;br /&gt;
out (c),a&lt;br /&gt;
inc hl&lt;br /&gt;
dec e&lt;br /&gt;
jr nz,seq&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; install a interrupt handler&lt;br /&gt;
;;&lt;br /&gt;
;; We install our own interrupt handler for this reason:&lt;br /&gt;
;; - To stop the firmware interrupt from being executed, this will&lt;br /&gt;
;; ensure that our direct access to the hardware will not be interrupted&lt;br /&gt;
;; by the firmware, and that the values we write are not re-written by&lt;br /&gt;
;; the firmware.&lt;br /&gt;
&lt;br /&gt;
di								;; disable interrupts&lt;br /&gt;
im 1							;; set interrupt mode 1 (jump to &amp;amp;0038 when interrupt occurs)&lt;br /&gt;
ld hl,&amp;amp;c9fb						;; EI:RET&lt;br /&gt;
ld (&amp;amp;0038),hl					;; &amp;amp;0038 is executed&lt;br /&gt;
ei&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; main loop&lt;br /&gt;
&lt;br /&gt;
.main_loop&lt;br /&gt;
;; wait for start of vsync. This test assumes that the start of the vsync&lt;br /&gt;
;; has not yet happened.&lt;br /&gt;
&lt;br /&gt;
ld b,&amp;amp;f5&lt;br /&gt;
.ml2&lt;br /&gt;
in a,(c)&lt;br /&gt;
rra&lt;br /&gt;
jr nc,ml2&lt;br /&gt;
&lt;br /&gt;
;; The vsync has just started, we can safely setup the scroll&lt;br /&gt;
;; without the display being effected.&lt;br /&gt;
&lt;br /&gt;
;;-----------------------------------------------------------------------&lt;br /&gt;
;; update vertical scan-line scroll adjustment&lt;br /&gt;
&lt;br /&gt;
;; page in ASIC ram&lt;br /&gt;
;; ASIC registers will be paged into memory range &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
ld bc,&amp;amp;7fb8&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;; get scan-line scroll adjustment&lt;br /&gt;
ld a,(horz_pixel_offset)&lt;br /&gt;
;; bits  3..0 define the horizontal pixel scroll offset&lt;br /&gt;
;; bits 6..4 define the vertical scanline scroll offset&lt;br /&gt;
&lt;br /&gt;
;; write to &amp;quot;soft&amp;quot; hardware scroll register of CPC+&lt;br /&gt;
ld (&amp;amp;6804),a&lt;br /&gt;
&lt;br /&gt;
;; page out ASIC ram&lt;br /&gt;
ld bc,&amp;amp;7fa0&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
;;-----------------------------------------------------------------------&lt;br /&gt;
;; update CRTC with scroll offset&lt;br /&gt;
&lt;br /&gt;
ld hl,(scroll_offset)		;; get scroll offset&lt;br /&gt;
&lt;br /&gt;
ld a,h&lt;br /&gt;
or &amp;amp;30					;; This defines the &amp;quot;base&amp;quot; of the screen in 16k units.&lt;br /&gt;
						;; &amp;amp;00 -&amp;gt; screen uses &amp;amp;0000-&amp;amp;3fff&lt;br /&gt;
						;; &amp;amp;10 -&amp;gt; screen uses &amp;amp;4000-&amp;amp;7fff&lt;br /&gt;
						;; &amp;amp;20 -&amp;gt; screen uses &amp;amp;8000-&amp;amp;bfff&lt;br /&gt;
						;; &amp;amp;30 -&amp;gt; screen uses &amp;amp;c000-&amp;amp;ffff&lt;br /&gt;
ld h,a&lt;br /&gt;
&lt;br /&gt;
ld bc,&amp;amp;bc0c				;; select CRTC register 12&lt;br /&gt;
out (c),c&lt;br /&gt;
&lt;br /&gt;
inc b					;; B = &amp;amp;BD&lt;br /&gt;
out (c),h				;; write to CRTC register 12&lt;br /&gt;
&lt;br /&gt;
dec b&lt;br /&gt;
inc c					;; BC = &amp;amp;BC0D&lt;br /&gt;
out (c),c				;; select CRTC register 13&lt;br /&gt;
&lt;br /&gt;
inc b&lt;br /&gt;
out (c),l				;; write to CRTC register 13&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
;; we need to wait long enough for the VSYNC signal to finish, so that the&lt;br /&gt;
;; test at the beginning of this loop will synchronise with the *start* of the&lt;br /&gt;
;; vsync. &lt;br /&gt;
&lt;br /&gt;
;; this first HALT will catch the interrupt that occurs two scanlines from&lt;br /&gt;
;; the start of the VSYNC, the second will delay a furthur 52 scanlines. The maximum&lt;br /&gt;
;; duration for the VSYNC is 16 scanlines.&lt;br /&gt;
halt&lt;br /&gt;
&lt;br /&gt;
halt&lt;br /&gt;
&lt;br /&gt;
;; update the scroll ready for the next update of the display&lt;br /&gt;
call scroll_right&lt;br /&gt;
&lt;br /&gt;
;; loop&lt;br /&gt;
jp main_loop&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; adjust scroll parameters to scroll the screen right&lt;br /&gt;
;;&lt;br /&gt;
;; Each CRTC character is 2 bytes.&lt;br /&gt;
;;&lt;br /&gt;
;; In mode 0 there are 2 pixels per byte, there are 4 pixels for each CRTC character.&lt;br /&gt;
;; In mode 1 there are 4 pixels per byte, there are 8 pixels for each CRTC character.&lt;br /&gt;
;; In mode 2 there are 8 pixels per byte, there are 16 pixels for each CRTC character.&lt;br /&gt;
;;&lt;br /&gt;
;; The horizontal pixel scroll offset is defined for mode 2 resolution.&lt;br /&gt;
;; Pixels in mode 1 are twice the width of mode 2 pixels.&lt;br /&gt;
;; Pixels in mode 0 are four times the width of mode 2 pixels.&lt;br /&gt;
;;&lt;br /&gt;
;; The horizontal pixel scroll offset is updated for every pixel.&lt;br /&gt;
;; The CRTC scroll offset is updated for every CRTC character (every 16 pixels in mode 2&lt;br /&gt;
;; OR every 8 pixels in mode 1 OR every 4 pixels in mode 0).&lt;br /&gt;
&lt;br /&gt;
.scroll_right&lt;br /&gt;
;; get horizontal pixel scroll offset&lt;br /&gt;
ld a,(horz_pixel_offset)&lt;br /&gt;
&lt;br /&gt;
sub 1							;; increments for pixel scrolling:&lt;br /&gt;
								;; 1 for mode 2&lt;br /&gt;
								;; 2 for mode 1&lt;br /&gt;
								;; 4 for mode 0&lt;br /&gt;
and &amp;amp;f&lt;br /&gt;
ld (horz_pixel_offset),a&lt;br /&gt;
cp 0&lt;br /&gt;
ret nz&lt;br /&gt;
&lt;br /&gt;
;; by now we have scrolled through:&lt;br /&gt;
;; - 16 pixels in mode 2&lt;br /&gt;
;; - 8 pixels in mode 1&lt;br /&gt;
;; - 4 pixels in mode 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;; get the crtc scroll offset&lt;br /&gt;
ld hl,(scroll_offset)&lt;br /&gt;
&lt;br /&gt;
inc hl							;; update offset&lt;br /&gt;
&lt;br /&gt;
ld a,h							;; ensure the scroll offset is in the range &amp;amp;300-&amp;amp;3ff&lt;br /&gt;
and &amp;amp;3&lt;br /&gt;
ld h,a&lt;br /&gt;
&lt;br /&gt;
;; store the crtc scroll offset&lt;br /&gt;
ld (scroll_offset),hl&lt;br /&gt;
ret&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; scroll offset of the screen to be written to CRTC register 12 and 13&lt;br /&gt;
;; This value is defined in &amp;quot;CRTC&amp;quot; characters.&lt;br /&gt;
.scroll_offset&lt;br /&gt;
defw 0&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; holds a number between 0 and 15 which is the pixel offset &lt;br /&gt;
;; for the scroll&lt;br /&gt;
.horz_pixel_offset&lt;br /&gt;
defb 0&lt;br /&gt;
&lt;br /&gt;
;;----------------------------------------------------------------------&lt;br /&gt;
;; this is the sequence to unlock the ASIC extra features&lt;br /&gt;
.sequence&lt;br /&gt;
defb &amp;amp;ff,&amp;amp;00,&amp;amp;ff,&amp;amp;77,&amp;amp;b3,&amp;amp;51,&amp;amp;a8,&amp;amp;d4,&amp;amp;62,&amp;amp;39,&amp;amp;9c,&amp;amp;46,&amp;amp;2b,&amp;amp;15,&amp;amp;8a,&amp;amp;cd,&amp;amp;ee&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>80.167.220.254</name></author>	</entry>

	</feed>