Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
<!--{{{-->
<div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser excludeLists'></span></div>
<!--}}}-->
To get started with this blank [[TiddlyWiki]], you'll need to modify the following tiddlers:
* [[SiteTitle]] & [[SiteSubtitle]]: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* [[MainMenu]]: The menu (usually on the left)
* [[DefaultTiddlers]]: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
<<importTiddlers>>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml' />
<!--}}}-->
These [[InterfaceOptions]] for customising [[TiddlyWiki]] are saved in your browser

Your username for signing your edits. Write it as a [[WikiWord]] (eg [[JoeBloggs]])

<<option txtUserName>>
<<option chkSaveBackups>> [[SaveBackups]]
<<option chkAutoSave>> [[AutoSave]]
<<option chkRegExpSearch>> [[RegExpSearch]]
<<option chkCaseSensitiveSearch>> [[CaseSensitiveSearch]]
<<option chkAnimate>> [[EnableAnimations]]

----
Also see [[AdvancedOptions]]
<!--{{{-->
<div class='header' role='banner' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' role='navigation' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' role='navigation' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' role='complementary' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea' role='main'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected {color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:alpha(opacity=60);}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0; top:0;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0 3px 0 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0; padding-bottom:0;}

.fieldsetFix {border:0; padding:0; margin:1px 0px;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none !important;}
#displayArea {margin: 1em 1em 0em;}
noscript {display:none;} /* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
}
/*}}}*/
<!--{{{-->
<div class='toolbar' role='navigation' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
I love the interactive nature of Forth-like assemblers, but have issues with HyperStatic nature of the Forth labels.  In particular, it's impossible to have forward references and hyperstatic labels by definition - hyperstatic references "freeze" the current value of the reference, whereas  a forward reference expects to be fixed up.  Logistically, hyperstatic references present a "messy old code" problem where eventually danglers mess up your code requiring a batch recompile (which defeats the whole interactivity advantage).

For retro-dev work I am trying an alternate approach:
- A SciTE editor (untouched, except 'make' command enabled via .preferences)
- DASM assembler, format 2 (chunks preceded by ADDR SIZE words)
- a2send utility to upload binaries into the Apple
- boot utility to configure Apple2c after IN#2

This allows a pretty fast turnaround comparable to Forth-like environments while capitalizing on the 'batch' assembler.

I will report on how well this arrangement works.
[[ADT Pro|http://adtpro.sourceforge.net/]] is a disk transfer program for Apple2 and PC, using serial or network (who networks Apple2s?) connections...

The most amazing thing is that it will bootstrap a bare apple via serial... All you do is type IN#2, and a few minutes later it churns out a disk with itself on it. That made me really happy, and excited about the Apple2 again...

Unfortunately it does not run as a disk emulator - just a disk transfer utility.  I really want a full floppy emulator over serial...

ADT Pro inspired me to hack up GameInjector

See SerialPinouts
An old computer.  Who cares, you say?  I do.  Why?

''Engineer's machine for hobbyists''
Apple ][ has a unique place among the early computers.  It was created before the personal computer industry was in existence.  It was created by the good Steve for himself (and fellow hobbyists), and every part of it exists solely for technological, not marketing reasons.  It was created before the bad Steve and his kind figured out how to rape and pillage the defenseless masses.

''Positioned at the sweet spot''
8-bit computers, especially the 6502, hit the sweet spot of the memory size/complexity curve.  The 6502 code is incredibly dense, and 64KB is just enough to fit a reasonable application.   

''One man's opinion''
Apple ][, with all its limitations, presented a reasonable platform that could be understood in entirety by one person.  It was a joy to use, and a pleasure to program.

As a peaceful protest, (and just because I like it) I will continue using and programming my Apple II computer.  It' really good enough for most things I do and the marketing jerks can't reach it (and would not want to anyway).  I hope to eventually phase out my linux box for an Apple II with an augmented display or a modern derivative.  
[img[a2images/a2c.keys.png]]
|>|Examining Memory|h
|{{{adrs}}} |Examine the value contained in one location |
|{{{adrs1.adrs2}}} |Display the values contained in all locations between {{{adrs1}}} and {{{adrs2}}} |
|{{{RETURN}}} |Display the values in up to eight locations following the last opened location |
|>|Changing the Contents of Memory|h
|{{{adrs:val ...}}} |Store the values in consecutive memory locations starting at {{{adrs}}}. |
|{{{:val ...}}} |Store values in memory starting at the next changeable location. |
|>|Moving and Comparing|h
|color(red):{{{dest<start.end}}}M |Copy the values in the range {{{start.end}}} into the range beginning at {{{dest}}}. <br>''M=move'' |
|color(red):{{{dest<start.end}}}V |Compare the values in the range {{{start.end}}} to those in the range beginning at {{{dest}}}. <br>''V=verify'' |
|>|Saving and Loading via Cassette Tape|h
|color(red):{{{start.end}}}W |Write the values in the memory range {{{start.end}}} onto tape, preceded by a ten-second leader. <br>''W=write''|
|color(red):{{{start.end}}}R |Read values from tape, storing them in memory beginning at {{{start}}} and stopping at {{{end}}}. Prints "ERR" if an error occurs. <br>''R=read''|
|>|Running and Listing Programs|h
|color(red):{{{adrs}}}G |Transfer control to the machine language program beginning at {{{adrs}}}. <br>''G=go'' |
|color(red):{{{adrs}}}L |Disassemble and display 20 instructions, starting at {{{adrs}}}. Subsequent L's will display 20 more instructions each. <br>''L=list'' |
|>|Miscellaneous|h
|color(red):{{{adrs}}}S |Disassemble, display, and execute the instruction at {{{adrs}}}, and display the contents of the 6502's internal registers. Subsequent S's will display and execute successive instructions. ''S=step'' |
|color(red):{{{adrs}}}T |Step infinitely. The TRACE command stops only when it executes a BRK instruction or when you press RESET. <br>''T=trace'' |
|{{{Control-E}}} |Display the contents of the 6502's registers. <br>''E=examine'' |
|color(red):I |Set Inverse display mode<br>''I=inverse'' |
|color(red):N |Set Normal display mode. Also useful as a delimiter for putting multiple commands on one line.<br>''N=normal'' |
|{{{Control-B}}} |Enter the language currently installed in the Apple's ROM (cold start at $E000). <br>''B=boot''|
|{{{Control-C}}} |Reenter the language currently installed in the Apple's ROM (warm start at $E003). |
|color(red):{{{val1}}}+{{{val2}}} |Add the two values and print the result. |
|color(red):{{{val2}}}-{{{val1}}} |Subtract the second value from the first and print the result. |
|{{{slot Control-P}}} |Divert output to the device whose interface card in in slot number {{{slot}}}. If {{{slot}}}=0, then route output to the Apple's screen. |
|{{{slot Control-K}}} |Accept input from the device whose interface card is in slot number {{{slot}}}. If {slot}=0, then accept input from the Apple's keyboard. |
|{{{Control-Y}}} |Jump to the machine language subroutine at location $03F8. This lets you add your own commands to the Monitor. |
|>|Mini-Assembler|h
|${{{command}}}|Execute a Monitor command from the Mini-Assembler.|
|{{{FF69G}}} |Enter monitor|
Have an Apple Split
by Bob Bishop
Softalk, October 1982

Have you ever wanted to create a display with both lo-res graphics and hi-res graphics on the same screen? Or graphics with more than just four lines of text at the bottom? Or how about text with four lines of graphics?

As we all know, the Apple II has only five display formats. It can display all lo-res graphics, all hi-res graphics, all text, lo-res with four lines of text at the bottom, or hi-res with four lines of text at the bottom. The latter two formats are sometimes called mixed modes because they allow, in a very restricted way, the mixing of graphics and text. But, according to page 12 of the Apple II Reference Manual, "There is no way to display both graphics modes at the same time." Well, not only are there ways of displaying both graphics modes on the same screen, it is also possible to display any combination of modes!

The technique of mixing display modes by the process of screen splitting is familiar to programmers who've used the Apple III, the Atari 400 and 800 machines, and several other computers. These machines contain special hardware that helps detect what is referred to as vertical blanking and horizontal blanking. What is not generally known is that the blanking can be detected by the Apple II, even though it lacks the special hardware found in those other machines.

Example Program. Before jumping into a technical discussion of the hows and whys of screen splitting, let's look at an example of screen splitting on the Apple II. Listing 1 and listing 2 present a short Applesoft main program and a machine language subroutine that the program calls.

Take a few moments now to turn on your Apple and enter these two programs. Don't worry if you don't understand machine language. Just go into the Monitor from Basic by typing call-151 followed by the return key. Then start typing in the hexadecimal values for the listing 2 subroutine that starts at $0300:

{{{300:8D 52 C0 A9 E0 A2}}}

and so on followed by the return key.

Now run the Applesoft program. What do you see? (Nothing, if you didn't type in the listings correctly.) You should see a text message in the top half of the screen and lo-res color graphics in the bottom half. This is a display mode that's supposed to be impossible to create on a standard Apple II computer!

To understand how to do screen splitting on the Apple II, you must be familiar not only with 6502 machine language but also with how the Apple maps its memory onto the display screen. (The latter information can be found on pages 14 through 21 of the Apple II Reference Manual.) The essence of what we need to know about hi-res in particular is shown in figure 1. Each line of the display is forty bytes long from left to right, and there are 192 such lines from top to bottom. The memory mapping seems somewhat haphazard: consecutive memory locations don't map onto consecutive lines of the display. Finally, for each set of 128 bytes of display memory only 120 bytes (three lines' worth) are displayed. The remaining eight bytes of the 128-byte set are never seen and are therefore sometimes referred to as the "undisplayed" or "unused" bytes. These undisplayed bytes all lie, conceptually, just off the bottom right-hand edge of the display, as shown in figure 1.

Text and lo-res both map in a way similar to hi-res, except that each cluster of eight lines now comes from one set of forty bytes instead of eight sets, and instead of the screen buffer being located at $2000 through $3FFF it lies at $0400 through $07FF. (Compare the Apple II Reference Manual pages 16 and 18 with page 21.)

Some Preliminary Insights. Let's try a few experiments that might give us some clues as to how screen splitting can be accomplished. From Basic type the command call -151 (followed by return) to get into the Monitor. Next, clear the screen by issuing the """escape--shift-P""" sequence. Now type C051 followed by return. (Hitting return will always be assumed from now on.) The computer will probably display:

{{{C051- A0}}}

(If it doesn't, try typing C051 again.)

Typing C051 from the Monitor is the way to turn on text mode if the computer is displaying graphics. But since we're already in text mode, nothing much happens - nothing much except that the contents of $C051 are displayed. But $C051 isn't supposed to be a readable address; it's merely a screen switch. So what does it mean for $C051 to contain $A0? Is it just a coincidence that $A0 is the hex code for an ASCII blank, and that most of the screen is also blank? What would happen if we typed C054? Or C056? Again, we tend to get SA0 if the screen is mostly blank.

Let's try another experiment. Again from the Monitor, type:

{{{2000:73 2001<2000.3FFEM}}}

followed by.

{{{C050 C053 C057}}}

You should see some vertical hi-res lines with space for four lines of text at the bottom of the screen. Now type C050, or C053, or C054, or C057. Most of the time we now see $73 in the screen switch locations, and once in a while we see $A0. (Remember that the bottom four text lines on the screen are mostly blank.)

The results of the previous experiments suggest that by examining the screen switches we can somehow read the contents of at least part of the screen currently being displayed. But, to determine the time-history of what is being read, we must first find a way to "tag" the screen data and then sample the soft switches very quickly. Doing this would provide us with a cycle-by-cycle map of how the Apple's video is generated. In other words, we could determine which locations in memory the information in the screen switches is coming from during each clock cycle of the processor. Such a cycle-by-cycle map would be extremely useful in the implementation and understanding of screen splitting on the Apple II.

Tagging and Sampling a Hi-Res Screen. Now let's create a special hi-res display. We'll put zeros in the forty bytes of the hi-res memory buffer that correspond to line 0 and ones in all the bytes corresponding to line 1. Line 2 will contain all twos, and so on. In other words, line n will contain all n's, for n = 0 to 191 ($00 to $BF). But we still haven't tagged the undisplayed bytes in the bottom right-hand corner (screen lines 128 through 191). Let's fill these sixty-four sets of eight-byte "invisible" lines with the values $C0 through $FF. Then every byte in the primary hi-res display buffer ($2000 through $3FFF), whether displayed or not, will contain a known quantity from $00 to $FF. Listing 3 is a program for creating such a hi-res display of tagged screen data. Two versions are given; one in Integer Basic and one in Applesoft. Use Integer if you have it. It's faster.

Next we need to devise a way of quickly and uniformly sampling a screen switch over and over and saving each sample for later study. One way of doing this might be with a program like the following.
{{{
LDX #$00
LOOP LDA $C050
STA $1000,X
INX
BNE LOOP
}}}

This program is very short and straightforward, but it suffers from two major flaws: first, it does not provide the fastest possible sampling (because of the time required for index register operations). Second, it allows only 256 data points to be sampled and stored. If we try to remedy the second flaw by changing the method of storage to STA (indirect),Y we not only aggravate the first flaw but introduce delays into the loop that cause us to generate unevenly spaced samples after every two hundred fifty-sixth fetch.

The best approach is to create a sampling program of the form:
{{{
LDA $C050
STA $1000
LDA $C050
STA $1001
LDA $C050
STA $1002
}}}
and so on. There's no loop involved; an individual set of LDA and STA commands is used for each check. Such a program is quite long (six bytes per sample) but executes very quickly (one sample per eight machine cycles) and yields uniformly spaced data. The programs in listing 4 generate the machine language program just described. Again, use the Integer version if you have that language.

We're now ready for business. Having run the programs shown in listings 3 and listing 4, we have the tagged hi-res data starting at $2000 and the sampling program starting at $4000. We run the sampler by entering the Monitor and giving the command 4000G. After a brief flash of the screen the program terminates, leaving its collection of screen samples starting at $1000 in the Integer version or $8000 in the Applesoft version.

Figure 2 is a partial listing of the key results of the sampling program. The entire listing of all the samples is much longer. Interested readers are encouraged to generate their own complete set of data using the programs described above. Before we can begin interpreting these results, we must discuss some fundamental concepts about television video and the Apple.

Television Images. A standard television picture consists of 525 interlaced scan lines that start in the upper left-hand corner of the screen and end in the bottom-right. "Interlaced" means that the image on the screen is created by first scanning all the even lines of the picture and then going back and filling in all the odd lines. In each scan line, the electron beam starts at the left side of the display and travels across the screen to the right, displaying one line of the image as it moves. When the beam finishes at the right end of each scan line, it shuts off for a few microseconds while it repositions itself at the beginning of the next line to be scanned. This shut-off period is referred to as horizontal blanking (HBL). When the beam reaches the bottom of the screen and finishes scanning the last line, it again shuts off, this time for a few milliseconds while it repositions itself at the top of the display for the next frame of the image. This second turn-off period is referred to as vertical blanking (VBL). The total time required to complete one interlaced frame (including VBLs) is one-thirtieth of a second.

When the Apple computer was first being designed, it was discovered that a computer-generated interlaced video signal produced a display that had an objectionable flicker. So interlacing was not used, even though this meant that half of the potential vertical resolution would be lost. This lost spatial resolution allowed Apple to achieve increased temoral resolution; instead of generating only thirty video frames per second, the Apple generates sixty, because the Apple uses the interlace to display a new 192-line frame.

A second design consideration in the Apple II was the decision not to overscan the screen. "Overscanning" means that the image extends slightly beyond the four edges of the screen so that the picture fills the entire viewing area. Instead, so that information in the corners won't be lost, the Apple leaves a small dark border of unused screen in all of its display modes. This further reduces the number of visible scan lines in each frame, so that only 192 lines remain in the display.

The Apple transfers its video data to the screen at a rate of one byte per machine cycle. Each scan line requires a total of sixty-five cycles from HBL to HBL. Since the Apple produces a forty-column display (forty byes per line), we can deduce that twenty-five cycles of each scan line are spent in a turned-off state and forty cycles are spent turned on. But even when the video is turned off, the screen switches can still be sampled. What will they contain?

Interpreting the Sampled Results. Let's return to figure 2 to see what we can learn from our sampled data. Locations $119B through $119F all contain zeros. Our sampling program required eight cycles per sample.

Consequently, the five samples represent forty machine cycles - exactly the duration of the visible part of one scan line.

Since the top line of our display was the only line containing all zeros. we infer that the data stored at $119B represents the beginning of a video frame. After three strange bytes ($11A0-$11A2) we see five ones in a row. These apparently represent the next scan line down, followed by three more strange bytes, and so on.

Well, if we've identified the data that isn't strange as representing the visible portions of the scan lines, then it follows that the strange bytes must be coming during HBL, and that HBL maps from $81 lines ahead of the line just scanned. The fact that HBL seems to come from such a far-away place is confusing enough in itself, but why an odd number like $81 instead of a nice power of two or something (like $80)? Something about these results doesn't feel right; they just don't seem to make any sense.

Well, our decision to attribute HBL to the end of a scan line was simply one of convention. Since HBL occurs between scan lines, we could just as easily have attributed it to the beginning of a scan line.

Then our interpretation of the data in figure 2 would be that a scan line consists of its visible forty-cycle component preceded by its invisible twenty-five-cycle HBL component, which is mapped from $40 display lines earlier. This model assumes a circular screen; that is, if counting up $40 lines would take you off the top of the screen, continue counting up from the bottom.

If we interpret the data in this fashion, it soon becomes evident that: a complete sixty-five-cycle scan line consists of sixty-five consecutive bytes of display buffer memory that starts twenty-five bytes prior to the actual data to be displayed. (See figure 3.) We can even see the undisplayed bytes of the screen buffer (where we stored the values $C0 through $FF, remember?) in locations $119A, $11A2, and so on; they're right where we'd expect them to be.

If we now look at locations $17AB through $17AF in figure 2 we see that they all contain $BF, which represents the bottom line of the display.

Thus $17B0 must be the start of VBL. During VBL the data acts just as if it were starting a whole new frame from the beginning, but it never finishes this pseudo-frame. After getting one third of the way through the frame (to scan line $3F), it suddenly repeats the previous six scan lines ($3A through $3F) before aborting to begin the next true frame. Examine locations $1970 through $19FF in figure 2.

If we had done our tagging and sampling exercise using a lo-res or text screen instead, the results would have been similar. The only difference would have been that each row of sixty-five bytes in the display would be repeated eight times, since both text and lo-res "characters" are eight scan lines tall.

Example Program Revisited. Now that we have a better feeling for what's going on, let's go back and try to understand how the screen splitting example in listing 1 worked.

The for-next loop in lines 200 through 250 does three things:

1. Line 210 pokes the value $E0 into the middle line of text/low-res display.

2. Line 220 pokes the value $A0 into the bottom line of the display.

3. Lines 230 and 240 create a simple lo-res pattern of colored vertical lines.

After printing a text message (lines 300 through 310) in the top part of the screen, the program calls (in line 400) the machine language screen splitting subroutine located at $0300. Line 500 then keeps re-calling the subroutine so that screen splitting will continue. Screen splitting is a dynamic process; it requires a program to keep it working. If the program stops, screen splitting stops. Try hitting control-C and see what happens.

Now let's examine the machine language subroutine. Ironically, one of the first things we have to do to produce a mixed mode display is to turn off the mixed mode screen switch, $C052. Since we'll be doing our own mixing we don't want the Apple to confuse things by putting in its own mode switching. The rest of the routine consists of two virtually identical polling loops.

The first loop ($0305 through $030E) sets text mode by referencing screen switch $C051 and, at the same time, waits for four consecutive $E0s to be scanned. Where do these $E0s come from? From the middle of the display screen where they were poked by line 210 of the Applesoft program!

When the $E0s are detected, the subroutine enters the second pollng loop ($0311 through $031A). This loop sets lo-res graphics mode by referencing screen switch $C050 and then waits for four consecutive $A0s (from the bottom line of the display) to be scanned. Once the $A0s have been detected, the mode is set back to text (at location $031B) and the subroutine returns to the main program.

There are a few subtleties here that should be pointed out. Why, for example, do we require four consecutive occurrences of $A0 and $E0 instead of just one? The reason for this can be inferred from figure 3. We see that every displayed line also has apart of itself mapped into some other display line's twenty-five-cycle "invisible" HBL component. This complicates the problem of detecting where the beam is currently scanning on the display. How do we know whether the data being sampled is coming from a visible scan or from an invisible HBL? Well, a visible scan consists of forty cycles of data, while the invisible HBL can only be twenty-five cycles at most. So, by requiring several consecutive samples whose fetching times total more than twenty-five cycles duration, we will eliminate false triggerings from HBL. Be careful not to exceed forty cycles or you'll miss the visible data too.

The process of mode changing sometimes tends to produce small unsightly glitches on the display screen. To test this out, change the contents of location $0305 in our example program in listing 2 to be either a $03 or a $02 and see if it makes any difference in the display. You can see how it's a good idea to try to change modes during HBL (or VBL) rather than in the middle of a visible scan line.

Another subtlety in the example program lies in our choice of $A0 and $E0 as tag bytes. While any values could have been used as tags, the values $A0 and $E0 are especially useful because they both appear as blanks on a text screen. On a lo-res graphics screen they appear (in our example) as a row of black (or blank) over a row of color. Thus these values provide a convenient way of switching cleanly between text and graphics modes.

In Conclusion.

From our examination of the example program, we see that screen splitting consists of essentially two steps. First, the screen must be preformatted with "tagged" lines at the points where screen splitting is to occur (that is, the $A0 and $E0 lines in our example). Second, a machine language subroutine must be written that detects these tagged lines and then quickly switches display modes. But the process is far from being trivial, and it requires a certain amount of creativity and ingenuity to design screens that can be split cleanly and effectively. What are some applications of screen splitting? Well, it can provide for a little more variety and flexibility in display modes above and beyond the basic five that everyone knows about. To this end I have used screen splitting to create the opening displays for several commercially available games (Maxwell's Demon/Bishop's Square, from Datasoft, Inc.; Money Munchers, from DataMost).

In addition to splitting a screen, we can superimpose screens. For example, if we print some words on the primary text screen and plot some lo-res colors in the corresponding locations of the secondary lo-res screen, then by screen switching, we could produce text on top of a colored background (if we don't mind a little bit of flicker). Similarly, by combining the two hi-res pages in such a way that the primary page has all of its high bits off while the secondary page has all of its high bits on, we can generate true 560 x 192 hi-res graphics. It is then possible to write a hi-res character generator for this mode that, in effect, produces eighty columns of text (in hi-res) without benefit of an eighty-column card!

The possibilities arising from screen splitting seem quite exciting, to say the least. But there is, unfortunately, one fly in the ointment - the technique may not work on all Apples. Looking at the screen switches like we've been doing is called "reading the floating bus," and it's something that Apple Computer never intended to be done. Therefore, they make no guarantees that the data read in this manner will be meaningful, especially when certain peripheral cards are plugged into the expansion slots. In fact, this method of screen splitting doesn't work on the Apple III at all, even in emulation mode, because its bus doesn't float. But there seem to be very few Apple IIs in which the method can't be made to work when the incompatible peripherals are unplugged.

If you can't get screen splitting to work on your Apple, you might want to try running the machine language program shown in listing 5. Load a hi-res picture into the primary display buffer ($2000 through $3FFF), create any lo-res display on the primary lo-res screen, and then run the program at $1000.

This program is an example of screen splitting using nothing but timing loops. But there's no way to synchronize the splitting. So, each time you run the program, the split will occur at a different vertical position on the screen, depending on which scan line you just happen to catch the beam on. This program should work on all Apples.

----
The author would like to thank D. Kottke, R. Nicholson, and B. Smith of
Apple Computer for their helpfull discussions on Apple II video hardware
and L. Grossberger of Eclectic Electric for her suggestions and help in
preparing the diagrams for this article.
----
{{{
100 HOME
200 FOR K = 0 TO 39
210 POKE 1448 + K, 14 * 16
220 POKE 2000 + K, 10 * 16
230 COLOR= K + 4
240 VLIN 25,45 AT K
250 NEXT K
300 VTAB 6: HTAB 17
310 PRINT "APPLE II"
400 CALL 768
500 GOTO 400
}}}
        Listing 1.
----
{{{
0300- 8D 52 C0  STA $C052
0303- A9 E0     LDA #$E0
0305- A2 04     LDX #$04
0307- CD 51 C0  CMP $C051
030A- D0 F9     BNE $0305
030C- CA        DEX
030D- D0 F8     BNE $0307
030F- A9 A0     LDA #$A0
0311- A2 04     LDX #$04
0313- CD 50 C0  CMP $C050
0316- D0 F9     BNE $0311
0318- CA        DEX
0319- D0 F8     BNE $0313
031B- 8D 51 C0  STA $C051
031E- 60        RTS
}}}
        Listing 2.
----
{{{
100 FOR Y = 0 TO 191
110 GOSUB 1000
120 FOR X = 0 TO 39
130 POKE BASE + X,Y
140 NEXT X,Y
150 FOR Y = 128 TO 191
160 GOSUB 1000
170 FOR X = 40 TO 47
180 POKE BASE + X,Y + 64
190 NEXT X,Y
200 END
1000 L = Y:S = 0:Q = 0
1010 S = INT (L / 64)
1020 L = L - S * 64
1030 Q = INT (L / 8)
1040 L = L - Q * 8
1050 BASE = 8192 + 1024 * L + 128 * Q + 40 * S
1060 RETURN
}}}
        Listing 3 - Applesoft.
----
{{{
100 FOR Y = 0 TO 191
110 GOSUB 1000
120 FOR X = 0 TO 39
130 POKE BASE+X,Y
140 NEXT X,Y
150 FOR Y = 128 TO 191
160 GOSUB 1000
170 FOR X = 40 TO 47
180 POKE BASE+X,Y+64
190 NEXT X,Y
500 END
1000 BASE=8192+40*(Y/64)+1024*(Y MOD 8)+128*((Y MOD 64)/8): RETURN 
}}}
        Listing 3 - Integer Basic.
----
{{{
10 PC = 16384
20 POKE PC + 1,80: POKE PC + 4,82: POKE PC + 7,87
30 FOR K = 1 TO 3
40 POKE PC,141: POKE PC + 2,192
50 PC = PC + 3
60 NEXT K
100 FOR LOC = 32768 TO 34816
110 POKE PC,173
120 POKE PC + 1,80
130 POKE PC + 2,192
140 POKE PC + 3,141
150 HLOC = INT (LOC / 256)
160 LLOC = LOC - (HLOC * 256)
170 POKE PC + 4,LLOC
180 POKE PC + 5,HLOC
190 PC = PC + 6
200 NEXT LOC
210 POKE PC,141: POKE PC+1,81: POKE PC+2,192: POKE PC+3,96
}}}
        Listing 4 - Applesoft.
----
{{{
10 PC=16384: LOC=4096
20 LDA=10*16+13: STA=8*16+13: C050LO=5*16: C050HI=12*16: RTS=96 
40 POKE PC+1,C050LO: POKE PC+4,C050LO+2: POKE PC+7,C050LO+7
50 FOR K = 1 TO 3
60 POKE PC,STA: POKE PC+2,C050HI
70 PC=PC+3
80 NEXT K
100 FOR K=1 TO 2048
110 POKE PC+0,LDA
120 POKE PC+1,C050LO
130 POKE PC+2,C050HI
140 POKE PC+3,STA
150 POKE PC+4,LOC MOD 256
160 POKE PC+5,LOC/256
170 PC=PC+6: LOC=LOC+1
180 NEXT K
190 POKE PC,STA: POKE PC+1,C050LO+1: POKE PC+2,C050HI: POKE PC+3,RTS 
}}}
        Listing 4 - Integer Basic.
----
[img[a2images/BobBishop/Bishop.fig1.gif]]
        Fig.1
----
{{{
1120- B7 F7 37 37 37 37 B8 B8 
1128- B8 F8 38 38 38 38 B9 B9 
1130- B9 F9 39 39 39 39 BA BA 
1138- BA FA 3A 3A 3A 3A BB BB 
1140- BB BB FB 3B 3B 3B 3B BC 
1148- BC BC FC 3C 3C 3C 3C BD
1150- BD BD FD 3D 3D 3D 3D BE 
1158- BE BE FE 3E 3E 3E 3E BF
1160- BF BF FF 3F 3F 3F 3F BA
1168- BA BA FA 3A 3A 3A 3A BB 
1170- BB BB FB 3B 3B 3B 3B BC 
1178- BC BC FC 3C 3C 3C 3C BD
1180- BD BD BD FD 3D 3D 3D 3D
1188- BE BE BE FE 3E 3E 3E 3E 
1190- BF BF BF FF 3F 3F 3F 3F
1198- 80 80 C0 00 00 00 00 00 
11A0- 81 81 C1 01 01 01 01 01 
11A8- 82 82 C2 02 02 02 02 02
11B0- 83 83 C3 03 03 03 03 03 
11B8- 84 84 C4 04 04 04 04 04 
11C0- A5 85 85 C5 05 05 05 05 
11C8- 05 86 86 C6 06 06 06 06
11D0- 06 87 87 C7 07 07 07 07

1780- 7A 7A BA BA BA BA BA 7B 
1788- 7B 7B BB BB BB BB BB 7C 
1790- 7C 7C BC BC BC BC BC 7D
1798- 7D 7D 7D BD BD BD BD BD 
17A0- 7E 7E 7E BE BE BE BE BE 
17A8- 7F 7F 7F BF BF BF BF BF 
17B0- 80 80 80 C0 00 00 00 00 
17B8- 81 81 81 C1 01 01 01 01 
17C0- 82 82 82 C2 02 02 02 02 
17C8- 83 83 83 C3 03 03 03 03 
17D0- 84 84 84 C4 04 04 04 04 
17D8- A5 85 85 85 C5 05 05 05 
17E0- 05 86 86 86 C6 06 06 06 
17E8- 06 87 87 87 C7 07 07 07 
17F0- 07 88 88 88 C8 08 08 08 
17F8- 08 89 89 89 C9 09 09 09 

1970- B7 B7 F7 37 37 37 37 B8 
1978- B8 B8 F8 38 38 38 38 B9
1980- B9 B9 F9 39 39 39 39 BA
1988- BA BA FA 3A 3A 3A 3A BB
1990- BB BB FB 3B 3B 3B 3B BC 
1998- BC BC FC 3C 3C 3C 3C BD 
19A0- BD BD BD FD 3D 3D 3D 3D 
19A8- BE BE BE FE 3E 3E 3E 3E 
19B0- BF BF BF FF 3F 3F 3F 3F 
19B8- BA BA BA FA 3A 3A 3A 3A 
19C0- BB BB BB FB 3B 3B 3B 3B 
19C8- BC BC BC FC 3C 3C 3C 3C 
19D0- BD BD BD FD 3D 3D 3D 3D 
19D8- BE BE BE FE 3E 3E 3E 3E 
19E0- BF BF BF BF FF 3F 3F 3F
19E8- 3F 80 80 C0 00 00 00 00 
19F0- 00 81 81 C1 01 01 01 01 
19F8- 01 82 82 C2 02 02 02 02 
}}}
        Figure 2.
----
[img[a2images/BobBishop/Bishop.fig3.gif]]
        Fig.3
----
!!APPEND
Opens a DOS 3.3 file (See OPEN) and positions the file pointer at the end of the file
{{{APPEND filename, [Dn], [Sn], [Vn]}}}
Note:  D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  APPEND is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  APPEND cannot be used in immediate mode.
!!BLOAD
Retrieves a binary file from a DOS 3.3 disk and stores it in the specified section of memory.
{{{BLOAD filename, [Amemloc],  [Dn], [Sn], [Vn]}}}
Note:  If the A//memloc// option is absent, the specified file is placed in memory beginning at the memory location from which the file was saved (see BSAVE).  If the option is present, the file goes into memory at //memloc//. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!BRUN
Retrieves a machine language program from a DOS 3.3 disk, stores it in the specified section of memory, and executes it.
{{{BRUN filename, [Amemloc], [Dn], [Sn], [Vn]}}}
Note:  The file must be type B (binary) and must contain a 6502 machine language program. The A//memloc// option specifies where in memory to start storing the binary image.  If the location is absent, DOS uses the location from which the image came. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  
!!BSAVE
Saves part of the Apple II's memory as a binary image on a DOS 3.3 disk file.
{{{BSAVE filename, [Amemloc], [Llength],  [Dn], [Sn], [Vn]}}}
Note:  The A//memloc// parameter specifies the starting address of the memory section to save.  The L//length// parameter specifies the number of bytes to save.  The //length// must be an integer between 0 and 32767 (decimal) or its hexadecimal equivalent. If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  
!!CATALOG
Displays a list of all files on a DOS 3.3 disk.
{{{CATALOG,  [Dn], [Sn]}}}
Note:  CATALOG prints the volume number of the disk, followed by a list of files on the disk.  For each file, CATALOG prints a code letter indicating the type of file, then number of sectors required to store the file, and the name of the file.  An asterisk appears to the left of the file type if the file is locked.  The file types and their codes are as follows:
|!Code|!Meaning|
|A|Applesoft programs|
|B|Binary image files|
|I|Integer BASIC programs|
|T|Text files|
|R|Relocatable binary|
D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used. This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!CHAIN
Loads and runs an Integer BASIC program from a DOS 3.3 disk, without clearing the values of any variables or arrays.
{{{CHAIN filename, [Dn], [Sn], [Vn]}}}
Note:  If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode. 
!!CLOSE
Closes one or all open DOS 3.3 disk files.
{{{CLOSE  [filename]}}}
Note:  Closing a file writes anything being held in the file buffer to the disk file and then releases the file buffer.  You must close any file you have opened to avoid losing information it contains.  Specifying the //filename// closes only the named file.  CLOSE without a //filename//  closes all files, except a controlling EXEC file (if any).
!!DELETE
Erases a file from a DOS 3.3 disk.
{{{DELETE filename, [Dn], [Sn], [Vn]}}}
Note:  The file with the specified name is removed from the disk. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!EXEC
Treats a sequential-access DOS 3.3 file as a substitute for the keyboard.
{{{EXEC filename, [Rfield],  [Dn], [Sn], [Vn]}}}
Note:  A text file to be used with EXEC consists of some combination of BASIC commands.  When EXEC is executed, the first line of the specified file is read from the disk.  If the first line is a command, it is executed immediately.  If it is a program line, it is added to memory, just as if you had entered it directly from the keyboard.  If a keyboard INPUT statement is executed while an EXEC file is open, the response is taken from the EXEC file.  An EXEC file can be used to enter an entire program, list it, run it, save it on disk, change it, or to do anything else that can be done from the keyboard.  You can even use an EXEC file to create and execute a second EXEC file.  The R//field// option specifies a number of command lines (carriage return characters) to be skipped from the beginning of the file. When the last line in the file has been used, the EXEC file is automatically closed.  When an EXEC command is encountered in a controlling EXEC file, the original, controlling, file is closed and any further commands in it are ignored.  The new EXEC file is opened and used instead. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!IN#
Switches input to a specified input device.
{{{ IN# slot}}}
Note:  IN# redirects the input of subsequent INPUT or GET statements to a device attached to one of the numbered accessory card slots.
|!Number|!Addr|!Device |
|0|47182*|Display screen |
|1|49408|Slot 1 (serial or parallel adapter) |
|2|49664|Slot 2 (serial or parallel adapter) |
|3|49920|Slot 3 or IIe Auxiliary slot (80-column adapter) |
|4|50176|Slot 4 (Mouse - commands only) |
|5|50432|Slot 5 (Disk drives) |
|6|50688|Slot 6 (Disk drives) |
|7|50944|Slot 7 |
*64795 if ProDOS is disabled
!!INIT
Initializes a DOS 3.3 disk.
{{{INIT filename, [Dn], [Sn], [Vn]}}}
Note:  The program currently in memory is saved on the disk under the //filename// given.  This program becomes the "greeting program," and it is run automatically whenever the disk is booted.  The greeting program is usually titled "HELLO."  This is not required but it seems to be the generally accepted convention.  The disk is assigned the volume number specified in the INIT command.  If no volume is specified, the disk is assigned a volume of 254. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  INIT can only be used in immediate mode.
!!LOAD
Loads a program from a DOS 3.3 disk.
{{{LOAD filename, [Dn], [Sn], [Vn]}}}
Note:  The program with the name //filename// is loaded from the disk.  If the LOAD is successful, any program previously in memory is erased. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!LOCK
Protects a DOS 3.3 disk file against change.
{{{LOCK filename, [Dn], [Sn], [Vn]}}}
Note:  Once locked, a file cannot be deleted, changed, or renamed until it is unlocked (see UNLOCK).  No program can be saved using the name of the locked file.  A locked file is indicated in the disk catalog by an asterisk at the left of the file type. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!OPEN
Prepares a sequential or random-access DOS 3.3 disk text file for accessing.
{{{OPEN filename, [Llength], [Dn], [Sn], [Vn]}}}
Note:  If the named file does not exist, DOS 3.3 creates it.  If the file is already open, it is closed and then reopened.  The L//length// option specifies the record length of a random-access file.  The record length must be an integer constant between 1 and 32767.  If the option is absent, the file is opened as a sequential file. If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  OPEN cannot be used in immediate mode.
!!POSITION
Moves the DOS 3.3 disk file pointer the specified number of records ahead in its current position.
{{{POSITION filename, [Rfield]}}}
Note:  The R//field// option specifies a number of fields (carriage return characters) to be skipped in the file. This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  POSITION cannot be used in immediate mode. 
!!READ
Specifies a DOS 3.3 disk file from which subsequent INPUT and GET commands will obtain data.
{{{READ filename, [Rrecord], [Bbyte]}}}
Note:  The R//record// specifies the record number of a random access file.  If that option is absent, the file will be read as a sequential-access file.  The B//byte// option specifies a number of bytes (characters) to skip ahead before reading.  The numbers following B and R must be integer constants between 0 and 32767. This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  READ cannot be used in immediate mode.</P>
!!RENAME
Changes the name of a DOS 3.3 disk file without altering the file contents.
{{{RENAME old filename, new filename, [Dn], [Sn], [Vn]}}}
Note:  The file named //old pathname// is found on the disk and its name is changed to //new pathname//.  If the file is open, it is closed (see CLOSE).  The file is not affected in any other way.  If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!RUN
Loads and runs a program form a DOS 3.3 disk.
{{{RUN filename, [Dn], [Sn], [Vn]}}}
Note:  The program named //filename// is loaded from the disk and then run.  If the load is successful, any program previously in memory will be erased.  If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!SAVE
Saves the program currently in memory onto a DOS 3.3 disk.
{{{SAVE filename, [Dn ], [Sn], [Vn]}}}
Note:  If there is no file as named, a file is created with that name in the language of the current program, and the program currently in memory is saved.  If there is a file named //filename// in the same language as the current program, the contents of that file are erased and the current program is saved in its place.  If the //filename// exists but in a different language or with a different file type, the message FILE TYPE MISMATCH will occur. If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!UNLOCK
Unlocks a DOS 3.3 file, permitting it to be changed.
{{{UNLOCK filename, [Dn], [Sn], [Vn]}}}
Note:  Once unlocked, a file can be deleted, changed, or renamed. If the file does not exist on drive D//n// of slot S//n//, the FILE NOT FOUND error message is displayed.  If the disk in drive D//n// of slot S//n// is not volume V//n//, the VOLUME MISMATCH error results. D//n//, S//n//, and V//n// can be specified in any order.  If D//n// or S//n// is omitted, the last referenced drive or slot is used.  Volume number V0 is used if V//n// is absent.  This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.
!!WRITE
Specifies a DOS 3.3 disk file to which subsequent PRINT statements will send output.
{{{WRITE filename, [Rrecord], [Bbyte]}}}
Note:  The R//record// option specifies the record number of a random-access file.  If that option is absent, the file will be written to as a sequential-access file.  The B//byte// option specifies a number of bytes (characters) to skip ahead before writing.  The numbers following R and B must be integer constants between 0 and 32767. This is a DOS 3.3 command, requiring PRINT and CHR$(4) or CONTROL-D in programmed mode.  WRITE may not be used in immediate mode.
[[Index]]
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='editor' macro='edit title'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
|[img[a2images/a2.slot.gif]]|1|I/O SELECT|This line, normall high, will become low when the microprocessor references page $Cn, where n is the individual slot number. This signal becomes active druing 00 and will drive 10 LSTTL loads*. This signal is not present on peripheral connector 0 (II+)|
|~|2-17|"""A0-A15"""|The buffered address bus. The address on these lines becomes valid during 01 and remains valid through 00. These lines will each drive 5 LSTTL loads |
|~|18|R/W|Buffered Read/Write signal. This becomes valid at the same time the address bus does, and goes high during a read cycle and low during a write. This line can drive up to 2 LSTTL loads * |
|~|19|SYNC|On peripheral connector 7 ONLY, this pin is connected to the video timing generator's SYNC signal |
|~|20|I/O STROBE|This line goes low during 00 when the address bus contains an address between $C800 and $CFFF. This line will drive 4 LSTTL loads* |
|~|21|RDY|The 6502's RDY input. Pulling this line low during 01 will haldt the microprocessor, with the address bus holding the address of the current location being fetched |
|~|22|DMA|pulling this line low disables the 6502's address bus and halts the microprocessor. This line is held high a 3k resistor to +5v |
|~|23|INT OUT|Daisy-chained interrupt output to lower priority devices. This pin is usually connected to pin 28 (INT IN) |
|~|24|DMA OUT|Daisy-chained DMA output to lower priority devices. This pin is usually connected to pin 22 (DMA IN) |
|~|25|+5v|+5 volt power supply. 500mA current is available for ALL peripheral cards. |
|~|26|GND|System electrical ground |
|~|27|DMA IN|Daisy-chained DMA input from higher priority devices. Usually connected to pin 24 (DMA OUT) |
|~|28|INT IN|Daisy-chained interrupt input from higher priority devices. Usually connected to pin 23 (INT OUT) |
|~|29|NMI|"""Non-Maskable Interrupt""". When this line is pulled low the apple begins an interrupt cycle and jumps to the interrupt handling routine at  location $3FB |
|~|30|IRQ|Interrupt Request. When this line is pulled low the Apple begins an interrupt cycle only if the 6502's I (Interrupt disable) flag is not set.  If so, the 6502 will jump to the interrupt handling routine whose address is stored in locations $3FE and $3FF |
|~|31|RES|When this line is pulled low the microprocessor begins a RESET cycle (see page 36) |
|~|32|INH|When this line is pulled low, all ROMS on the Apple board are disable. This line is held high by a 2kn resistor to +5v |
|~|33|-12v|-12 volt power supply. Maximum current is 200mA for all peripheral boards. |
|~|34|-5v|-5 volt power supply. Maximum current is 200mA for all peripheral boards |
|~|35|COLOR REF|On peripheral connector 7 ONLY, this pin is connected to the 3.5Mhz """COLOR REFerence""" signal of the video generator |
|~|36|7M|7Mhz clock. This line will drive 2 LSTTL loads* |
|~|37|Q3|2Mhz asymetrical clock. This line will drive 2 LSTTL loads* |
|~|38|01|Microprocessor's phase one clock. This line will drive 2 LSTTL loads * |
|~|39|"""USER1"""|This line, when pulled low, disables ALL internal I/O address decoding** |
|~|40|00|Microprocessors phase zero clock. This line will drive 2 LSTTL loads* |
|~|41|DEVICE SELECT|This line becomes active (low) on each peripheral connector when the address bus is holding an address between """$C0n0""" and """$C0nF""", where n is the slot number plus $8. This line  will drive 10 LSTTL loads* |
|~|42-49|"""D0-D7"""|Buffered bi-directional data bus. The data on this line becomes valid 300nS into 00 on a write cycle, and should be stable no less than 100nS before the end of 00 on a read cycle. Each data line can drive one LSTTL load |
|~|50|+12v|+12 volt power supply. This can supply up to 250mA total for all peripheral cards |
|>|>|!SOFT SWITCH STATUS FLAGS| !0 | !1 |
|$C010|R7|AKD|keys free(clears strobe) |key pressed |
|$C011|R7|"""BSRBANK2"""|bank1 available |bank2 available |
|$C012|R7|BSRREADRAM|$D000-$FFFF active |BSR active for read |
|$C013|R7|RAMRD|main $0200-$BFFF active reads |aux active |
|$C014|R7|RAMWRT|main $0200-$BFFF active writes |aux writes |
|$C015|R7|INTCXROM|slot active |main $C100-$CFFF ROM active |
|$C016|R7|ALTZP|main available |aux $0000-$1FF+auxBSR |
|$C017|R7|"""SLOTC3ROM"""|main $C3 ROM active slot |$C3 ROM active |
|$C018|R7|80STORE|page2 video |page2 switches main/aux |
|$C019|R7|VERTBLANK|vertical retrace off |vertical retrace on |
|"""$C01A"""|R7|TEXT|graphics mode active |text mode is active |
|"""$C01B"""|R7|MIXED||mixed graphics & text |
|"""$C01C"""|R7|"""PAGE2"""||video page2 selected or aux |
|"""$C01D"""|R7|HIRES|low resolution |high resolution |
|"""$C01E"""|R7|ALTCHARSET|alt char set off |alt character set on |
|"""$C01F"""|R7|80COL|80 col display off |80 col display on |
GameInjector is a project inspired by [[a2gameserver|http://sourceforge.net/projects/a2gameserver/]] and [[gameserver|http://asciiexpress.net/gameserver/]], as well as the great ongoing work at [[Commodore Server|http://www.commodoreserver.com/]].  The idea is to eliminate long disk loads (I'll miss the clickety clack noise), reduce time and space resources taken up by copying, labeling and storing floppies, etc.<br>
Alas, a2gameserver ''doesn't work on linux'' and is ''buggy in windows''.  The asciiexpress one requires a cassette tape input not available on the 2c.  

I really wanted to have a serial game loader like a2gameserver, so I got rid of everything except for the game-loading monitor on the Apple II side and wrote some simple code to shove the monitor into the Apple, followed by displaying a menu of games ''on the host side''.  After a couple of days of hacking, GameInjector works pretty well.  It loads Apple Panic in about 6 seconds, start to finish on my """Apple IIc""".
HazMat is a minimal cross-development environment.  I dislike large IDEs.  Hazmat environment consists of three separate components:
* An interactive monitor running on the target (Apple II monitor is great!);
* A text editor modified to send the current line of text when <CTRL><ENTER> keys are pressed;
* An intermediary program that takes the lines from the editor, optionally transforms them, and sends them to the target monitor.

The current intermediary is a 6502 assembler with a passthrough mode for commands and BASIC.
!This site is a retrocomputing tiddlywiki containing:
!![[Apple II]]
|Memory|ZeroPage<br>SoftSwitches,SoftSwitches1|
|Software|[[Monitor|Apple ][ monitor]]<br>[[ADT Pro|ADTPro]]|
|Extension slots|[[Pinouts|ExtensionPinouts]]|
|Serial Port|[[Pinouts|SerialPinouts]]<br>[[<CTRL>codes|SerialCtrl]]<br>[[Initialization|Serial Port Initialization]]<br>[[Handshaking|SerialHandshaking]]<br>[[Bootstrapping|SerialBootstrap]]|
|Keyboard|[[KeyCodes]]|
|DOS|[[DOS 3.3 commands]]|
|Techniques|[[Bob Bishop's graphics|BobBishop]]<br>VideoTiming|
!!Interfacing
|"""USBSerial"""|[[USB Serial|UsbSerial]]<br>[[Linux-Remapping|Remapping the Serial Port]]|
!!Retrocomputing
|''SwanComputer'' |Countdown program based on the TV show "Lost" | Beta |
|HazMat |Tomorrow's technology for yesterday's machines| Prototype |
|Serial Loader |General-purpose serial loader for code development| Research |
|[[GameInjector]] |A serial port-based loader for games. PC and Hardware versions| [[Download|GameInjector/GameInjector.zip]]Prototype |
|[[FPGA Projects|FPGA/FPGA.html]]|"""FPGA-based retrocomputing"""||
Also, you may view this site by Tags (left column).


contact: info***@***apple2.x10.mx   Remove the asterisks first!
{{{
:10202E00216E016A0162215D217F218C017F01C336
:10203E0001260116022940022AAD0172022A9A02D5
:10204E0029D00229D6022A1402287D02284302270B
 ^ ^   ^ ^                               ^
 | |   | |                               |
 | |   | |       checksum----------------+
 | |   | +-------data bytes
 | |   +---------record type (00=data, 01=end of file) 
 | +-------------address for this line of data
 +---------------number of bytes of data in this line
}}}
Thanks to PJRC
The character names come from the American Standard Code for Interchange of Information. Certain peripherals or programs or functions, such as the BASIC function CHR$, may require the decimal values; certain peripherals or programs may require the hexadecimal values as well.

The fourth column in the table below is for simple keystrokes or those made with the SHIFT key held down; the fifth and sixth columns are for those made either with the CTRL key held down or with both the SHIFT and CTRL keys held down simultaneously.

NOTE: An asterisk next to keystrokes or character names means that the Apple II and Apple II Plus can't generate that character from its keyboard. The double asterisk indicates a special case.

The comments column defines the non-printing ASCII characters.
{{{
              Keystrokes  Holding down:     Comments
Char Dec  Hex  Regular   CTRL  SHIFT-CTRL

NUL   00  00                     @ **        null character
SOH   01  01               a     A           start of header
STX   02  02               b     B           start transmission
ETX   03  03               c     C           end of text
EOT   04  04               d     D           end of transmission
ENQ   05  05               e     E           enquire
ACK   06  06               f     F           acknowledge
BEL   07  07               g     G           bell
BS    08  08   Left-arrow  h     H           back space
HT    09  09   Tab         i     I           horizontal tab
LF    10  0A   Down-arrow  j     J           line feed
VT    11  0B   Up-arrow    k     K           vertical tab
FF    12  0C               l     L           form feed
CR    13  0D   Return      m     M           carriage return
SO    14  0E               n     N           shift out
SI    15  0F               o     O           shift in
DLE   16  10               p     P           data link escape
DC1   17  11               q     Q           device C 1
DC2   18  12               r     R           device C 2
DC3   19  13               s     S           device C 3
DC4   20  14               t     T           device C 4
NAK   21  15   Right-arrow u     U           negative acknowledge
SYN   22  16               v     V           synchronous idle
ETB   23  17               w     W           end of text block
CAN   24  18               x     X           cancel
EM    25  19               y     Y           end of medium
SUB   26  1A               z     Z           start subroutine
ESC   27  1B   Escape      [ *   { *         escape
FS    28  1C               \\ *   | *         file separator
GS    29  1D               ] *   } *         group separator
RS    30  1E                     ^           record separator
US    31  1F                     _ *         unit separator
SP    32  20   Space Bar                     space
!     33  21
"     34  22
#     35  23
$     36  24
%     37  25
&     38  26
'     39  27
(     40  28
)     41  29
*     42  2A
+     43  2B
,     44  2C
-     45  2D
/     47  2F
0     48  30
1     49  31
2     50  32
3     51  33
4     42  34
5     43  35
6     44  36
7     45  37
8     46  38
9     57  39
:     58  3A
;     59  3B
<     60  3C
=     61  3D
>     62  3E
?     63  3F
@     64  40
A     65  41
B     66  42
C     67  43
D     68  44
E     69  45
F     70  46
G     71  47
H     72  48
I     73  49
J     74  4A
K     75  4B
L     76  4C
M     77  4D
N     78  4E
O     79  4F
P     80  50
Q     81  51
R     82  52
S     83  53
T     84  54
U     85  55
V     86  56
W     87  57
X     88  58
Y     89  59
Z     90  5A
[ *   91  5B
\\ *   92  5C
] *   93  5D
^     94  5E
_ *   95  5F
` *   96  60
a     97  61
b     98  62
c     99  63
d    100  64
e    101  65
f    102  66
g    103  67
h    104  68
i    105  69
j    106  6A
k    107  6B
l    108  6C
m    109  6D
n    110  6E
o    111  6F
p    112  70
q    113  71
r    114  72
s    115  73
t    116  74
u    117  75
v    118  76
w    119  77
x    120  78
y    121  79
z    122  7A
{ *  123  7B
| *  124  7C
} *  125  7D
~ *  126  7E
DEL * 127  7F                                 Delete

*  The Apple II and Apple II Plus can't generate that charcter from the keyboard.
}}}
[[Index]]
|>|>|>|!MEMORY MANAGEMENT SOFT SWITCHES|
|$C000|W|80STOREOFF|Allow page2 to switch video page1 page2 |
|$C001|W|80STOREON|Allow page2 to switch main & aux video memory |
|$C002|W|RAMRDOFF|Read enable main memory from $0200-$BFFF |
|$C003|W|RAMDRON|Read enable aux memory from $0200-$BFFF |
|$C004|W|RAMWRTOFF|Write enable main memory from $0200-$BFFF |
|$C005|W|RAMWRTON|Write enable aux memory from $0200-$BFFF |
|$C006|W|INTCXROMOFF|Enable slot ROM from $C100-$CFFF |
|$C007|W|INTCXROMON|Enable main ROM from $C100-$CFFF |
|$C008|W|ALZTPOFF|Enable main memory from $0000-$01FF & avl BSR |
|$C009|W|ALTZPON|Enable aux memory from $0000-$01FF & avl BSR |
|"""$C00A"""|W|"""SLOTC3ROMOFF"""|Enable main ROM from $C300-"""$C3F"""F |
|"""$C00B"""|W|"""SLOTC3ROMON"""|Enable slot ROM from $C300-$"""C3FF""" |
0020-004F Zero page memory area used by the monitor
0100-01FF Stack
0200-02FF Input buffer
03D0-03FF System vectors
C000-C0FF I/O space. Don't even read memory in this area
          unless you know what you are doing.
C100-C7FF I/O firmware (usually ROM on cards in slots, or
          emulated slots). Some I/O cards may have I/O
          ports in this area (but not for the IIc).
C800-CFFF Bank-switched area used by I/O cards. It is safe
          to read this area in the IIc, but it has to be
          handled carefully in other machines.
 

The following areas must be handled carefully to avoid problems:

0050-00FF Zero page memory area used by Applesoft BASIC
0400-07FF Text screen and "screen holes", which contain
          system data
D000-FFFF ROM and bank-switched RAM ("language card").
          Don't write anything into this area, especially
          if you are running under ProDOS.
 

Other memory areas that you may need to be aware of:

0800-???? Applesoft BASIC programs normally go here,
          followed by variables
2000-3FFF Hires graphics buffer for page 1
4000-5FFF Hires graphics buffer for page 2
9600-BFFF Normally used by DOS 3.3 or ProDOS
????-95FF Normally used for strings in Applesoft BASIC

The hires graphics buffers are only an issue if you need to use
them. Under DOS 3.3 or ProDOS, the upper memory limit (9600) may
change depending on the use of the MAXFILES command under DOS or the
number of open files under ProDOS.
 

This leaves you with the following areas that you can usually play
with to your heart's content. There are some exceptions, but I've
covered enough for one article.

0000-001F This isn't entirely free, but is usually OK.
0300-03CF Often used for small machine code programs.
1000(ish)-7FFF(ish)

The last area varies wildly depending on the size of any BASIC program
and its variables.
<div id='header'>
</div>
<div id='sidebar'>
<div id='titleLine'></div>
<span id='siteTitle' refresh='content' tiddler='SiteTitle'></span>- <span id='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
Squeak and Pharo Smalltalks have a subtle problem with Linux serial port naming.  Pharo supports serial ports using the SerialPort class. openPort requires an integer port id; in linux it appends the port number to "/dev/ttyS".  My usb/serial cable comes up as /dev/ttyUSB0.  To map it into Pharo's space,
{{{
sudo rm /dev/ttyS5
}}}
Now, the following would work:
{{{
sudo ln -s /dev/ttyUSB0 /dev/ttyS5
}}}
''BUT'' the device may come up as ttyUSB1, or something else.  
''Solution''
udev rules! (I don't mean it rocks, just rules.)  Make sure to delete any /dev/ttyS5 files, then create a file /etc/udev/rules.d/97-local.rules containing the line:
{{{
kernel=="ttyUSB*", SYSFS{idVendor}=="067b", SYSFS{idProduct}=="2303", SYMLINK="ttyS5"
}}}

Now usbserial cable will always come up as /dev/ttyS5.  
''BUT'' On reboot the system may create /dev/ttyS5... Well, it doesn't but something has changed and the first insertion creates an incorrect ttyS5.  Removing and re-inserting fixes it.  Ah, the joys of a large OS.
Apple2c starts up in 300 baud.  

To set baud rate after IN#2, enter <ctrl-A> followed by 'xB' string.  Apple2c does not require a <return>.
|CODE|BAUD||CODE|BAUD|h
| 1B |50|| 9B |1800|
| 2B |75|| 10B |2400|
| 3B |110|| 11B |3600|
| 4B |135|| 12B |4800|
| 5B |150|| 13B |7200|
| 6B |300|| 14B |9600|
| 7B |600|| 15B |19200|
| 8B |1200|| 16B |115k|

GameServer does the following to bump the serial port to 115kbaud:
{{{
300:a9 10 8d ab c0 a9 0b 8d aa c0 ad a8 c0 60
}}}
This disassembles to:
{{{
0300-   A9 10       LDA  #$10
0302-   8D AB C0    STA  $C0AB
0305-   A9 0B       LDA  #$0B
0307-   8D AA C0    STA  $C0AA
030A-   AD A8 C0    STA  $C0A8
030D-  60                RTS.
}}}
Apple computers can be bootstrapped via the serial port much like ADTPro.  The process goes like this:
* You type "IN#2" on the Apple.
* The host sends "PR#2";
* The hosts ups the baud rate to 115200 on Apple IIc using a small assembly program or a control code (see [[Serial Port Initialization]])

The process is a little hindered by some quirks (Apple IIc).  Via the serial link the speed-bumping escape works in the monitor only.  In BASIC it works from the keyboard only.  I could not find a way to send <CTRL>B to reenter BASIC. 

It is safer to send a small machine-language program to 0x300.
For port 2, """CTRL-A""" is the "attention" escape.  For port 1, it's """CTRL-I"""

''Baud Rate Selection''
|CODE|BAUD||CODE|BAUD||CODE|BAUD||CODE|BAUD|h
|1B|50||5B|150||9B|1800||13B|7200|
|2B|75||6B|300||10B|2400||14B|9600|
|3B|110||7B|600||11B|3600||15B|19200|
|4B|135||8B|1200||12B|4800||16B|115k|

''Width and stop bits''
|CODE|DATA BITS|STOP BITS|h
|0|8|1|
|1|7|1|
|2|6|1|
|3|5|1|
|4|8|2|
|5|7|2|
|6|6|2|
|7|5|2|

I = Echo characters to screen.  Works well after PR#2.
K = Disable <LF> after <CR>.
L = Generate <LF> after <CR>.
R = Reset Port 1 and exit from serial port 1 firmware.
S = Send a 233 millisecond Break character
Z = Zap (ignore) further command characters (until CTRL-Reset or PR#1). Do not format output or insert carriage returns into output stream.

''nP = Set Parity corresponding to n.''
|n|Parity|
|0|none|
|1|odd|
|2|none|
|3|even|
|4|none|
|5|mark (1)|
|6|none|
|7|space (0)|
''T = Terminal Mode, port 2 only''
{{{
T         Enter terminal mode
B         Send BREAK signal
E D       Echo disable (full duplex)
E E       EEcchhoo  eennaabbllee  ((hhaallff  dduupplleexx)) 
S D       Disable special characters (ESC sends ESC)
S E       Enable special characters (ESC becomes a shift key)
0T        Change lowercase to uppercase
1T        Pass characters unchanged
2T        Display lowercase as uppercase inverse
3T        Pass lowercase, but display as inverse
X E       Enable XON/XOFF via ^R and ^T but not ^S
X D       Disable XON/XOF
Q         Quit terminal mode
}}}
Apple II serial ports do not support handshaking (or do they?  research...).  Workarounds:

!!Delay
Delaying after each character (depending on application) and each line works.  Different positions on the screen require different delays(!!!)...

!!Echo
Waiting for the sent character to echo is a viable substitute for handshaking.
|>|"""MiniDIN8"""| """DE-9""" | """DB-25""" | """RS-232""" |
| [img[a2images/apple2c.minidin8.png]] |5| 3 |     2   |  """TxD""" |
|~|3| 2 |     3   |  """RxD""" |
|~|4| 5 |     7   |  GND |
|~|8|~|~|~|
|~|1| 8 |     5   |  CTS |
|~|2| 7  |     4  |   RTS |
|~|~| 4  |  20   |  DTR |
|~|7| 1  |    8  |   DCD |

|>|DIN|Apple|Description||"""DB9"""| Wire Color|
|[img[a2images/din5df.gif]]| 1 | 1 | DTR | """HSKo Handshake out""" | 6,1 | Black |
|~| 4 | 2 | """TxD""" | Data out | 2 | White |
|~| 2 | 3 | GND | Signal ground | 5 | Bare |
|~| 5 | 4 | """RxD"""  | Data in | 3 | Yellow |
|~| 3 | 5 | DSR | """HSKi Handshake in (DSR)""" | 4 | Red |

ADTPro recommends disabling handshaking and wiring the cable as follows:
{{{
Laser/
 Apple
 DIN-5    DB-9  DB-25  RS-232
 Pin#     Pin#  Pin#    Name
 -----    ----  -----  ------
   4 ----- 3      2     TxD
   2 ----- 2      3     RxD
   3 ----- 5      7     GND
  1&5     (nc)   (nc)  (disables
  (nc)    7&8    4&5    hardware
  (nc)   1&4&6  6&8&20  handshaking)

 Within the DIN-5 shell, tie together pins:
 1&5

 If using DE-9: Within the DE-9 shell, tie together pins:
 1&4&6 and 7&8

 Or, if using DB-25: Within the DB-25 shell, tie together pins:
 6&8&20 and 4&5 
}}}
In reality, reversing 3 and 2 seems to work better.  This is apparenty the 'printer' cable.
For reference, here is the normal db9 serial port pinout
[img[a2images/din9.serial.png]]
{{{
DB-9 Pin 	Signal Name 	Dir 	Description 	IDC internal
 (newer)* 	IDC internal
(older)*
1 	CD 	<-- 	Carrier Detect 	1 	1
2 	RXD 	<-- 	Receive Data 	2 	3
3 	TXD 	--> 	Transmit Data 	3 	5
4 	DTR 	--> 	Data Terminal Ready 	4 	7
5 	GND 	--- 	System Ground 	5 	9
6 	DSR 	<-- 	Data Set Ready 	6 	2
7 	RTS 	--> 	Request to Send 	7 	4
8 	CTS 	<-- 	Clear to Send 	8 	6
9 	RI 	<-- 	Ring Indicator 	9 	8
}}}
Everything I know
Apple II
!!Soft Switches and Status Indicators
[img[a2images/memap.gif]]
|CLR80STORE|$C000|80STORE Off- disable 80-column memory mapping (Write) |
|SET80STORE|$C001|80STORE On- enable 80-column memory mapping (WR-only) |
|CLRAUXRD|$C002|read from main 48K (WR-only) |
|SETAUXRD|$C003|read from aux/alt 48K (WR-only) |
|CLRAUXWR|$C004|write to main 48K (WR-only) |
|SETAUXWR|$C005|write to aux/alt 48K (WR-only) |
|CLRCXROM|$C006|use ROM on cards (WR-only) |
|SETCXROM|$C007|use internal ROM (WR-only) |
|CLRAUXZP|$C008|use main zero page, stack, & LC (WR-only) |
|SETAUXZP|$C009|use alt zero page, stack, & LC (WR-only) |
|CLRC3ROM|$C00A|use internal Slot 3 ROM (WR-only) |
|SETC3ROM|$C00B|use external Slot 3 ROM (WR-only) |
|CLR80VID|$C00C|disable 80-column display mode (WR-only) |
|SET80VID|$C00D|enable 80-column display mode (WR-only) |
|CLRALTCH|$C00E|"""use main char set norm LC, Flash UC (WR-only)""" |
|SETALTCH|$C00F|use alt char set norm inverse, LC no Flash (WR-only) |
|READROM|$C082|ROM override |
|>|>|!Bank 2 selection |
|RROMWRAM2|$C081|Read ROM Write RAM |
|RDWRTLC2|$C083|Read RAM Write RAM |
|READRAM2|$C080|Read RAM no write |
|>|>|!Bank 1 selection |
|RROMWRAM1|C089|Read ROM Write RAM |
|RDWRTLC1|C08B|Read RAM Write RAM |
|READRAM1|C088|Read RAM no write |
|AUXMOVE|$C311|  f |
|>|>|!Bit seven of these Read Status locations is 1 if the condition is true |
|RDLCBNK2|$C011|reading from LC bank $Dx 2 |
|RDLCRAM|$C012|reading from LC RAM |
|RDRAMRD|$C013|reading from aux/alt 48K |
|RDRAMWR|$C014|writing to aux/alt 48K |
|RDCXROM|$C015|using internal Slot ROM |
|RDAUXZP|$C016|using Slot zero page, stack, & LC |
|RDC3ROM|$C017|using external (Slot) C3 ROM |
|RD80COL|$C018|80STORE is On- using 80-column memory mapping |
|RDVBLBAR|$C019|not VBL (VBL signal low) |
|RDTEXT|$C01A|using text mode |
|RDMIXED|$C01B|using mixed mode |
|RDPAGE2|$C01C|using text/graphics page2 |
|RDHIRES|$C01D|using Hi-res graphics mode |
|RDALTCH|$C01E|using alternate character set |
|RD80VID|$C01F|using 80-column display mode |
|TAPEOUT|$C020|toggle the cassette output |
|SPEAKER|$C030|toggle speaker diaphragm |
/----------------------------------------------------------------------------\
	   Apple //e Soft Switch, Status, and other I/O locations
\----------------------------------------------------------------------------/
<<tiddler MemoryManagementSoftSwitches>>
<<tiddler VideoSoftSwitches>>
<<tiddler FlagSoftSwitches>>
body{
 background: #f9f9f9 url(headbg.jpg) no-repeat top left;
}

#titleLine{
 display: block;
 background: transparent url(wiki.png) no-repeat 18px -7px;
 _background: transparent;
 height: 120px;
 _height: 135px;
 width: 150px;
 color: #000;
 border: 1px;
 padding: 0;
 margin: 0;
}

* html #titleLine{
 filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='wiki.png',sizingMethod='scale');
}

#contentWrapper #siteTitle a{
 display: inline;
 font-weight: bold;
 color: #000;
 font-size: 13px;
}

#siteSubtitle{
 padding: 0;
}

#siteTitle, #mainMenu{
 position: static;
}

#contentWrapper #sidebar{
 top: 0;
 left: 0;
}

#displayArea {
 margin: 0 0 0 15em;
}

#messageArea{
 position: fixed;
 top: 0;
 right: 0;
 font-size: 10px;
 border: 1px solid #aaa;
 background: #fff;
 z-index: 25;
}

#messageArea a:link{
 color: #002bb8;
 text-decoration: none;
}

#messageArea a:hover{
 text-decoration: underline;
}

.viewer{
 background: #fff;
 border: 1px solid #aaa;
 padding: 1em;
margin: 0;
}

.body{
 padding: 1px;
}

.title{
 background: #fff;
 border: 1px solid #aaa;
 display: inline;
 margin-left: .5em;
 padding: 2px .5em;
 border-bottom: 0;
 font-weight: bold;
 color: #000;
 font-size: 1.2em;
}

.toolbar{
 visibility: visible;
 display: inline;
 padding: 0;
 font-family: sans-serif;
}

.toolbar a.button:link,.toolbar a.button:visited{
 background: #fff;
 border: 1px solid #aaa;
 color:#002bb8;
 font-size: 11px;
 padding-bottom: 0;
 margin-right: .25em;
}

/* TiddlyPedia was Created by Clinton Checketts based on the Monobook skin of Wikipedia */

#contentWrapper .toolbar .button:hover{
 border-bottom: 1px solid #fff;
 background: #fff;
 color:#002bb8;
}

.toolbar a.button:hover{
 border-bottom: 1px solid #fff;
 background: #fff;
 color:#000;
}

#displayArea .viewer a,a.button:link,a.button:visited,
a.tiddlyLink:link,a.tiddlyLink:visited,
#sidebarOptions .sliderPanel a{
 color:#002bb8;
 background: transparent;
 border: 0;
}

.viewer a:hover,a.button:hover,a.button:active,
a.tiddlyLink:hover,a.tiddlyLink:active,
.viewer a.button:hover,
#sidebarOptions .sliderPanel a:hover{
 color:#002bb8;
 background: transparent;
 text-decoration: underline;
}

#mainMenu{
 font-family: sans-serif;
 text-align: left;
 font-size: x-small;
 width: 100%;
 margin: 0;
 padding: 0;
}

#mainMenu h1{
 font-size: 11px;
 font-weight: normal;
 padding: 0;
 margin: 0;
 background: transparent;
}

#mainMenu ul{
 font-size: 11px;
 border: 1px solid #aaa;
 padding: .25em 0;
 margin: 0;
 list-style-type: square;
 list-style-image: url(bullet.gif);
 background: #fff;
 width: 100%;
}

#mainMenu li{
 margin: 0 0 0 2em;
 padding: 0;
}

#contentWrapper #mainMenu a:link,#contentWrapper #mainMenu a:visited{
 color:#002bb8;
 padding: 0;
 margin: 0;
 background: transparent;
}

#mainMenu .externalLink {
 text-decoration: none;
}

#mainMenu .externalLink:hover {
 text-decoration: underline;
}

#sidebar{
 padding: .5em;
 font-family: sans-serif;
}

#sidebarOptions{
 border: 1px solid #aaa;
 background: #fff;
 margin-top: .5em;
 width: 100%;
}

#sidebar .sliderPanel{
 margin: 0;
}

#contentWrapper #sidebarOptions .button,#contentWrapper #sidebarOptions .button:hover{
 color:#002bb8;
 padding: .1em 0 .1em 2em;
 background: transparent url(bullet.gif) 10px -2px no-repeat;
}

#sidebarOptions input{
 width: 80%;
 margin: 0 .5em;
}

#sidebarTabs{
 background: #fff;
 margin-top: .5em;
 width: 100%;
}

#sidebarTabs .tabContents,#sidebarTabs .tabContents .tabContents{
 border: 1px solid #aaa;
 background: #fff;
}

#sidebarTabs .tabSelected,#sidebarTabs .tabcontents .tabSelected {
 background: #fff;
 border: 1px solid #aaa;
 border-bottom: 0;
 cursor: default;
 padding-bottom: 3px;
 color: #000;
}

#sidebarTabs .tabUnselected,#sidebarTabs .tabContents .tabUnselected{
 background: #aaa;
 padding-bottom: 0;
 color: #000; 
}

#contentWrapper #sidebarTabs .tiddlyLink,#contentWrapper #sidebarTabs .button,
#contentWrapper #sidebarTabs a.tiddlyLink:hover,#contentWrapper #sidebarTabs a.button:hover{
 background: transparent;
 color: #002bb8;
}

.footer{
 margin: -1em 0 1em 0; 
}

.footer .button:hover,.editorFooter .button:hover{
background: transparent;
 color: #002bb8;
 border-bottom: 1px solid #002bb8;
}

#popup{
 background: #e9e9e9;
 color: #000;
}

#popup hr{
 border-color: #aaa;
 background-color: #aaa;
}

#popup a{
 color: #000;
}

#popup a:hover,#contentWrapper #sidebarTabs #popup a:hover{
 background: #666;
 color: #fff;
 text-decoration: none;
}

#displayArea .tiddler a.tiddlyLinkNonExisting{
 color: #ba0000;
}

#displayArea .tiddler a.externalLink{
 text-decoration: none;
 color:#002bb8;
 padding-right: 1em;
 background: transparent url(external.png) 100% 50% no-repeat;
}

#displayArea .tiddler a.externalLink:hover{
 text-decoration: underline;
}

.viewer pre{
 background: #e9e9e9;
 border: 1px solid #666;
}

.viewer h1, .viewer h2, .viewer h3, .viewer h4, .viewer h5, .viewer h6{
 background: transparent;
 border-bottom: .2em solid #aaa;
}

#sidebar .sliderPanel{
 background: #e9e9e9;
}

#sidebar .sliderPanel input{width: auto;}

.tagged, .tagging, .listTitle{
 float: none;
 display: inline;
}

.tagged li, .tagging li,
.tagged ul, .tagging ul{
 display: inline;
}
I thoroughly enjoyed the  [[TV show Lost|http://en.wikipedia.org/wiki/Lost_%28TV_series%29]].   In the show, [[the Numbers|http://lostpedia.wikia.com/wiki/The_Numbers]] must be entered into the [[Swan Computer|http://lostpedia.wikia.com/wiki/Swan_computer]] (an Apple ][) to prevent a horrible disaster.

I created a quick and dirty Applesoft version to keep my family busy*.  The number verification code is trivial, but I took the liberty of incorporating the 108 minute countdown timer which made the program a challenge (try running a timer and editing numeric fields at the same time in Applesoft!)

The program is not clever or efficient in any way or form, but it sort of does the job.  The timing is not accurate - do not operate this program to run a doomsday device.

It is formatted for HazMat comments. In other environments, remove the lines starting with a '#' - they are comments.

* Unfortunately, the 15K squeal from the monitor is keeping children away from the Apple II.
{{{
# -------------------------------------------
# Initialize. MX,MH,ML=minutes, SH,SL=seconds
# -------------------------------------------
5 MX=1: MH=0: ML=8: SH=0: SL=0
10 X%=0: TIMER%=24
20 DIM NUM%(15)
30 for A=0 to 15: NUM%(A)=32:NEXT
50 NORMAL:HOME:PRINT ">:               ";  
# -------------------------------------------
# DE% is cursor blink delay (4 on 4 off)
# -------------------------------------------
100 IF DE% =0 then DE%=8
110 DE%=DE%-1
120 GOSUB 3000 
125 TIMER%=TIMER%-1: IF TIMER%=0 THEN TIMER%=24:GOSUB 5000:GOSUB 6000
130 goto 100
# --------------------------------------
# If in the last 4 minutes, allow input
# --------------------------------------
3000 IF MX=0 THEN IF MH=0 THEN IF ML<4 THEN GOTO 4000
3010 FOR Q=1 to 10: NEXT: RETURN
# --------------------------------------
# Get a keystroke
# --------------------------------------
4000 C%=PEEK(49152)
4010 IF C%<128 THEN  GOTO 4300
4020  POKE  49168,0
# --------------------------------------
# Process keystrokes
# --------------------------------------
4030 IF C%=149 THEN GOSUB 4200: GOTO 4400: REM RIGHT
4040 IF C%=136 THEN GOSUB 4200: GOTO 4500: REM LEFT
4050 IF C%=255 THEN GOSUB 4200: GOTO 4500: REM BS
4055 IF C%=160 THEN NUM%(X%)=32: GOSUB 4200:GOTO 4400 : REM SPACE
4057 IF C%=141 THEN GOSUB 7000: GOTO 4300
4060 IF C%<176 GOTO 4300
4070 IF C%>185 GOTO 4300
4080 NUM%(X%)=C%-128:  GOSUB 4200: GOTO 4400
# --------------------------------------
# Show inverse cursor
# --------------------------------------
4100 INVERSE: HTAB 3+X%: PRINT " "; :NORMAL: RETURN: REM SHOW CURSOR
# --------------------------------------
# Show actual value
# --------------------------------------
4200 NORMAL:HTAB 3+X%: PRINT CHR$(NUM%(X%));: RETURN
4299 rem blink logic
4300 IF DE%=0 THEN GOSUB 4100: RETURN
4310 IF DE%=4 THEN GOSUB 4200: RETURN
4320 RETURN
# --------------------------------------
# Increment X and proceed to blink logic
# --------------------------------------
4400 IF X%<15 THEN X%=X%+1
4410 GOTO 4300
# --------------------------------------
# Decrement X and proceed to blink logic
# --------------------------------------
4500 IF X%>0 THEN X%=X%-1
4510 GOTO 4300
# --------------------------------------
# UPDATE TIMER
# --------------------------------------
5000 IF MX=0 THEN IF MH=0 THEN IF ML<5 THEN PRINT CHR$(7) 
5001 IF SL>0 THEN SL=SL-1: RETURN
5005 SL=9 
5010 IF SH>0 THEN SH=SH-1: RETURN
5015 SH=5
5020 IF ML>0 THEN ML=ML-1:RETURN
5025 ML=9
5030 IF MH>0 THEN MH=MH-1: RETURN
5035 MH=9
5040 IF MX>0 THEN MX=MX-1: RETURN
5050 RETURN
# --------------------------------------
# DISPLAY TIMER
# --------------------------------------
6000 VTAB 1: HTAB 30 : ?MX;MH;ML;":";SH;SL; 
6010 VTAB 1: HTAB X
6010 RETURN
# --------------------------------------
# VERIFY 4 8 15 16 23 32
# --------------------------------------
7000 IF NUM%(0)<>52 THEN RETURN
7001 IF NUM%(1)<>32 THEN RETURN
7002 IF NUM%(2)<>56 THEN RETURN
7003 IF NUM%(3)<>32 THEN RETURN
7004 IF NUM%(4)<>49 THEN RETURN
7005 IF NUM%(5)<>53 THEN RETURN
7006 IF NUM%(6)<>32 THEN RETURN
7007 IF NUM%(7)<>49 THEN RETURN
7008 IF NUM%(8)<>54 THEN RETURN
7009 IF NUM%(9)<>32 THEN RETURN
7010 IF NUM%(10)<>50 THEN RETURN
7011 IF NUM%(11)<>51 THEN RETURN
7012 IF NUM%(12)<>32 THEN RETURN
7013 IF NUM%(13)<>52 THEN RETURN
7014 IF NUM%(14)<>50 THEN RETURN
7015 IF NUM%(15)<>32 THEN RETURN
7020 RUN
}}}
!Bringing up a UsbSerial port
Linux UsbSerial adapters will register as /dev/ttyUSB0 or something like it.  lsusb to check for details.

Install gtkterm and test the adapter by shorting pins 2 and 3 with a wire.

/dev/ttyUSBx may come up with admin permissions, requiring sudo for all apps that access it.  Do not chmod it, just add users to 'dialout' group:
{{{
sudo usermod -a -G dialout <username>
}}}

if '/dev/ttyUSB0 is locked' appears, just sudo rm the offending lock file in /var/lock


|>|>|>|!VIDEO SOFT SWITCHES |
|"""$C00C"""|W|80COLOFF|Turn off 80 column display |
|"""$C00D"""|W|80COLON|Turn on 80 column display |
|"""$C00E"""|W|ALTCHARSETOFF|Turn off alternate characters |
|"""$C00F"""|W|ALTCHARSETON|Turn on alternate characters |
|$C050|R/W|TEXTOFF|Select graphics mode |
|$C051|R/W|TEXTON|Select text mode |
|$C052|R/W|MIXEDOFF|Use full screen for graphics |
|$C053|R/W|MIXEDON|Use graphics with 4 lines of text |
|$C054|R/W|"""PAGE2OFF"""|Select panel display (or main video memoryv) |
|$C055|R/W|"""PAGE2ON"""|Select page2 display (or aux video memory) |
|$C056|R/W|HIRESOFF|Select low resolution graphics |
|$C057|R/W|HIRESON|Select high resolution graphics |
Reposted from http://rich12345.tripod.com (full of web tracking bugs)
[img[a2images/VideoTiming1.gif]]
The above drawing has an exaggerated, magnified view of the Apple II video screen being drawn.

Each Scan Line is represented by a red line.  The "Horizontal Blanks", or path the gun takes to get to the next line down, is represented by green.

There are 192 scan lines on an apple II screen.  You can get the point from the ammount I drew because each scan line is exactly the same.

The blue line is the VBL.  VerticalBlank period is the time when the gun is moving from the lower right of the screen, back up to the upper left to start drawing the screen again.

!!!Apple II video timing
The Apple II processor runs exactly 17030 cycles for each time the video screen is updated.
!!!Scan Lines
A scan line is a horizontal line drawn on the screen by the gun.  
 
Each scan line takes 65 cycles to 'draw'

40 bytes (7 bits diplayed in each byte.)
40*7 = 280 (HGR screen horizontal size )

1 cycle each byte, plus 25 cycles for gun 
to move down to next line ("Horizontal Blank")
40 X 1c + 25c = 65 cycles for each scan line

192SL * 65c = 12480 cycles to draw entire screen

It takes 17030 cycles for the gun to end up in the same place on the screen.

192 scan lines (HGR screen vertical size)
!!!Vertical Blank period
17030 - 12480 = 4550 cycles.

It takes the gun 4550 cycles to move from the lower right hand corner of the screen back up to the upper left.  This is called the Vertical BLank period.  It can be detected at $C019.  

$C019  Bit 7 of this location will be a 0 when the video beam is in the vertical retrace region.

You can test this from Assembly language using the BMI and BPL instructions.  You could test from BASIC by seeinf if $C019>127, but VBL is happening fast and BASIC isn't really fast enough to do anything with VBL.

!!!Unverified informaiton
The value at $c054 (and lots of the other video  switches) are equal to the byte being displayed
(this was posted to the Apple II newsgroup by  Nathan Fisher)

What could you use it for?  Does this mean the actual VALUE that is stored at a certain location?  (255 is stored at $2000.  When being drawn to the screen by the video circuitry, does this mean $C054 = 255?)

Let me know anything else about the Apple II video timing, and I'll add it to the page.

RDVBLBAR = $C019 ;not VBL (VBL signal low)

ReaD Vertical BLanking (active low). Bit 7 of this location will be a 0 then the video beam is in the vertical retrace region. This can be used to force updates of the video screen to be synchronised with the 50/60Hz refresh - ie you will never get a screen with half old data and half new displayed.  It can also be used to allow fancy split screen effects (ie 1/3 HIRES, 1/3 TEXT, 1/3 LORES or other combinations). It is not a softswitch, rather it is a status flag.

I agree with David's description, but I just wanted to add the following points about RDVBLBAR:

1. It doesn't exist on the original ][ or ][+, only the IIe and IIgs. 

2. The IIc uses this location for a different but related purpose: 
reading it returns a "VBL interrupt pending" flag and clears the flag. I think the polarity is inverted from the IIe: bit 7 set indicates that 
VBLInt is pending. You can't safely use this if the mouse firmware is active, because the mouse requires VBL itself.

3. If you have a mouse card in a ][, ][+ or IIe, it can be used to generate a vertical blanking interrupt. The same facility is provided by 
the mouse firmware in the IIc and IIgs.
<div class='title' macro='view title'></div>
<div class='toolbar' macro='toolbar -closeTiddler closeOthers +editTiddler permalink references jump'></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
{{{
         Apple II Zero Page Usage
                        Lo Nibble of Address
Hi
Nib  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
     --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 0 | A~  A~  A   A   A   A   -   -   -   -   A   A   A   AI  A   A
 1 | A   A   A   A   A   A   A   A   A   A   A   A   A   A   -   M*
 2 | M   M   M   M   M3  M   MA3 MA3 M3  M3  M3  M3  MA3 MA3 M3  MA3
 3 | MA  M   MA  MA3 M   M3  M3B M3B M3B M3B M~  M~  MA3~MA3~MA3~MA3~
 4 | M3~ M3~ M3~ M3~ M3~ M3~ M3~ M3~ M3~ M3~ I3~ I3~ I3~ I3~ M~  M
 5 | MA  MA  MA  MA  MA  MAI AI  AI  AI  AI  AI  AI  AI  AI  AI  AI
 6 | AI  AI  AI  AI  AI  AI  AI  AI3 AI3 AI3 AI3 AI  AI  AI  AI  AI3
 7 | AI3 AI  AI  AI3 AI3 AI  AI3 AI  AI  AI  AI  AI  AI  AI  AI  AI
 8 | AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI
 9 | AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI
 A | AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI3
 B | AI3 AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI
 C | AI  AI  AI  AI  AI  AI  AI  AI  AI  AI  AI3 AI3 AI3 AI3 I   I
 D | AI  AI  AI  AI  AI  AI  AI3 I   AI3 AI3 AI  AI  AI  AI  AI3 AI
 E | A   A   A   A   A   A   A   A   A   A   A   -   -   -   -   -
 F | A   A   A   A   A   A   A   A   A   A   -   -   -   -   I   AI

M = Used by Monitor; * used in early Apple IIe ROMs-- now free
A = Used by Applesoft BASIC
I = Used by Integer BASIC
3 = Used by DOS 3.3
~ = Used by ProDOS ($40-$4E is saved before and restored after use)
B = Used by ProDOS BASIC.SYSTEM (also uses all Applesoft locations)
- = Free; not used


}}}