mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-07 23:13:13 -06:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80d52d824c |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
||||
# Leave all line endings alone!
|
||||
* -text
|
||||
@@ -1,8 +0,0 @@
|
||||
@echo off
|
||||
if exist *.bin del *.bin
|
||||
if exist *.com del *.com
|
||||
if exist *.img del *.img
|
||||
if exist *.rom del *.rom
|
||||
if exist *.pdf del *.pdf
|
||||
if exist *.log del *.log
|
||||
if exist *.eeprom del *.eeprom
|
||||
@@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -1,107 +0,0 @@
|
||||
***********************************************************************
|
||||
*** ***
|
||||
*** R o m W B W ***
|
||||
*** ***
|
||||
*** Z80/Z180 System Software ***
|
||||
*** ***
|
||||
***********************************************************************
|
||||
|
||||
This directory ("Binary") is part of the RomWBW System Software
|
||||
distribution archive. It contains the completed binary outputs of
|
||||
the build process. As described below, these files are used to
|
||||
assemble a working RetroBrew Computers system.
|
||||
|
||||
The files in this directory are created by the build process that is
|
||||
documented in the ReadMe.txt file in the Source directory. When
|
||||
released the directory is populated with the default output files.
|
||||
However, the output of custom builds will be placed in this directory
|
||||
as well.
|
||||
|
||||
ROM Firmware Images (<plt>_<cfg>.rom)
|
||||
-------------------------------------
|
||||
|
||||
The files with a ".rom" extension are binary images ready to program
|
||||
into an appropriate PROM. These files are named with the format
|
||||
<plt>_<cfg>.rom. <plt> refers to the primary platform such as Zeta,
|
||||
N8, Mark IV, etc. <cfg> refers to the specific configuration. When
|
||||
released, there will be a standard configuration ("std") for each
|
||||
platform. So, for example, the file called MK4_std.rom is a ROM
|
||||
image for the Mark IV with the standard configuration. If a custom
|
||||
configuration called "custom" is created and built, a new file called
|
||||
MK4_custom.rom will be added to this directory.
|
||||
|
||||
Documentation of the pre-built ROM Images is contained in the
|
||||
RomList.txt file.
|
||||
|
||||
ROM Executable Images (<plt>_<cfg>.com)
|
||||
---------------------------------------
|
||||
|
||||
When a ROM image (".rom") is created, an executable version of the
|
||||
ROM is also created. These files have the same naming convention as
|
||||
the ROM Image files, but have the extension ".com". These files can
|
||||
be copied to a working system and run like a normal application.
|
||||
|
||||
When run on the target system, they install in RAM just like they had
|
||||
been programmed into the ROM. This allows a new ROM build to be
|
||||
tested without reprogramming the actual ROM.
|
||||
|
||||
ROM Binary Images (<plt>_<cfg>.img)
|
||||
-----------------------------------
|
||||
|
||||
Also when a ROM image is created, a third variation of the ROM is
|
||||
created again with the same naming convention, but with the extension
|
||||
of .img. These files are similar to the .com files in that they can
|
||||
be used to test a ROM build without actually programming a new ROM.
|
||||
The .img files are specifically for loading via UNA from a FAT file
|
||||
system. The functionality of the UNA FAT file system loader is
|
||||
beyond the scope of this document.
|
||||
|
||||
VDU ROM Image (vdu.rom)
|
||||
-----------------------
|
||||
|
||||
The VDU video board requires a dedicated onboard ROM containing the
|
||||
font data. The "vdu.rom" file contains the binary data to program
|
||||
onto that chip.
|
||||
|
||||
Disk Images (fd*.img, hd*.img)
|
||||
------------------------------
|
||||
|
||||
RomWBW includes a mechanism for generating floppy disk and hard disk
|
||||
binary images that are ready to copy directly to a floppy, hard disk,
|
||||
CF Card, or SD Card which will then be ready for use in any
|
||||
RomWBW-based system.
|
||||
|
||||
Essentially, these files contain prepared floppy and hard disk images
|
||||
with a large set of programs and related files. By copying the
|
||||
contents of these files to appropriate media as described below, you
|
||||
can quickly create ready-to-use media.
|
||||
|
||||
The fd*.img files are floppy disk images. They are sized for 1.44MB
|
||||
floppy media and can be copied to actual floppy disks using
|
||||
RawWriteWin (as long as you have access to a floppy drive on your
|
||||
Windows computer). The resulting floppy disks will be usable on any
|
||||
RomWBW-based system with floppy drive(s).
|
||||
|
||||
Likewise, the hd*.img files are hard disk images. Each file is
|
||||
intended to be copied to the start of any type of hard disk media
|
||||
(typically a CF Card or SD Card). The resulting media will be usable
|
||||
on any RomWBW-based system that accepts the corresponding media type.
|
||||
|
||||
Note that the contents of the floppy/hard disk images are created by
|
||||
the BuildImages.cmd script in the Source directory. Additional
|
||||
information on how to generate custom disk images is found in the
|
||||
Source\Images directory.
|
||||
|
||||
Propeller ROM Images (*.eeprom)
|
||||
-------------------------------
|
||||
|
||||
The files with and extension of ".eeprom" contain the binary images
|
||||
to be programmed into the Propeller-based boards. The list below
|
||||
indicates which file targets each of the Propeller board variants:
|
||||
|
||||
ParPortProp ParPortProp.eeprom
|
||||
PropIO V1 PropIO.eeprom
|
||||
PropIO V2 PropIO2.eeprom
|
||||
|
||||
Refer to the board documentation of the boards for more information
|
||||
on how to program the EEPROMs on these boards.
|
||||
@@ -1,111 +0,0 @@
|
||||
***********************************************************************
|
||||
*** ***
|
||||
*** R o m W B W ***
|
||||
*** ***
|
||||
*** Z80/Z180 System Software ***
|
||||
*** ***
|
||||
***********************************************************************
|
||||
|
||||
This directory ("Binary") is part of the RomWBW System Software
|
||||
distribution archive. Refer to the ReadMe.txt file in this
|
||||
directory for more information on the overall contents of the
|
||||
directory.
|
||||
|
||||
When distributed, RomWBW contains a set of pre-built ROM images that
|
||||
are ready to program onto the EEPROM of any of the Z80/Z180 based
|
||||
RetroBrew Computers CPU boards. Additionally, any custom built ROM
|
||||
images will be placed in this directory.
|
||||
|
||||
All of the pre-built ROM images are 512KB. This size is compatible
|
||||
with all of the Z80/Z180 systems. Some systems can accept different
|
||||
size ROM images. Creating alternative sizes requires a custom ROM
|
||||
build (see ReadMe.txt in the Source directory).
|
||||
|
||||
It is critical that the right ROM Imgae be selected for the target
|
||||
platform being used. The table below indicates the correct ROM
|
||||
image to use for each platform:
|
||||
|
||||
SBC V1/V2 SBC_std.rom
|
||||
Zeta V1 ZETA_std.rom
|
||||
Zeta V2 ZETA2_std.rom
|
||||
N8 N8_std.rom
|
||||
Mark IV MK4_std.rom
|
||||
|
||||
You will find there is one additional ROM image called
|
||||
"UNA_std.rom". This ROM image is an UNA-based RomWBW ROM image. As
|
||||
such, this ROM image can be used on any Z80/Z180 platform supported
|
||||
by John Coffman's UNA BIOS. Refer to RetroBrew Computers Wiki for
|
||||
more information on UNA hardware support.
|
||||
|
||||
For each of the ROM Images (".rom"), there are corresponding files
|
||||
with the extensions of ".com" and ".img". The .com variant can be
|
||||
copied to a functional RomWBW-based system and executed like a
|
||||
normal application under CP/M or Z-System. This will load the new
|
||||
ROM on-the-fly. It is an excellent way to test a ROM Image before
|
||||
actually burning it. Similarly, the .img files can be loaded using
|
||||
the UNA FAT loader for testing.
|
||||
|
||||
All of the standard ROM Images are configured with:
|
||||
- 512KB ROM Disk
|
||||
- 512KB RAM Disk
|
||||
- 38.4Kbps baud serial console
|
||||
- Auto-discovery of all serial ports
|
||||
|
||||
All hard disk type devices (IDE, PPIDE, CF Card, SD Card) will be
|
||||
automatically assigned two drive letters per device. The drive
|
||||
letters will refer to the first 2 slices of the device. The ASSIGN
|
||||
command can be used to display and reassign drives to disk devices
|
||||
and slices as desired.
|
||||
|
||||
Standard ROM Image Notes
|
||||
------------------------
|
||||
|
||||
The standard ROM images will detect and install support for certain
|
||||
devices and peripherals that are on-board or frequently used with
|
||||
each platform as documented below. If the device or peripheral is
|
||||
not detected at boot, the ROM will simply bypass support
|
||||
appropriately.
|
||||
|
||||
SBC:
|
||||
- Includes support for PPIDE/CF Card(s) connected to on-board
|
||||
parallel port.
|
||||
- Includes support for CVDU and VGA3 boards. If detected at
|
||||
startup, support for video and keyboard is installed
|
||||
including VT-100/ANSI terminal emulation.
|
||||
- Auto-detects PropIO or PropIO V2 and installs associated
|
||||
video, keyboard and SD Card support if present.
|
||||
- If PropIO, PropIO V2, CVDU, or VGA hardware is detected,
|
||||
initial console output is determined by JP2. If JP2 is
|
||||
shorted, console will go to on-board serial port, if JP2
|
||||
is open, console will go to the detected video and keyboard
|
||||
ports.
|
||||
- SBC V1 has a known race condition in the bank switching
|
||||
circuit which is likely to cause system instability. SBC
|
||||
V2 does not have this issue.
|
||||
|
||||
ZETA/ZETA2:
|
||||
- Includes support for on-board floppy disk controller and
|
||||
two attached floppy disks.
|
||||
- Auto-detects ParPortProp and includes support for it if it
|
||||
is attached.
|
||||
- If ParPortProp is installed, initial console output is
|
||||
determined by JP1. If JP1 is shorted, console will go to
|
||||
on-board serial port, if JP1 is open, console will go to
|
||||
ParPortProp video and keyboard ports.
|
||||
|
||||
N8:
|
||||
- Includes support for on-board floppy disk controller and
|
||||
two attached floppy disks.
|
||||
- Includes support for on-board TMS9918 video and keyboard
|
||||
including VT-100/ANSI terminal emulation.
|
||||
- Includes support for on-board SD Card as hard disk and
|
||||
assumes a production level N8 board (date code >= 2312).
|
||||
|
||||
MK4:
|
||||
- Includes support for on-board IDE port (CF Card via adapter).
|
||||
- Includes support for on-board SD Card port.
|
||||
- Auto-detects PropIO or PropIO V2 and installs associated
|
||||
video, keyboard and SD Card support if present.
|
||||
- Includes support for CVDU and VGA3 boards. If detected at
|
||||
startup, support for video and keyboard is installed
|
||||
including VT-100/ANSI terminal emulation.
|
||||
4
BuildCommon.cmd
Normal file
4
BuildCommon.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
setlocal
|
||||
cd Source
|
||||
call BuildCommon %*
|
||||
9
Clean.cmd
Normal file
9
Clean.cmd
Normal file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
pushd Source && call Clean && popd
|
||||
|
||||
if exist *.img del *.img /Q
|
||||
if exist debug.log del debug.log
|
||||
|
||||
if exist Output\*.* del Output\*.* /Q
|
||||
340
Doc/Build.txt
Normal file
340
Doc/Build.txt
Normal file
@@ -0,0 +1,340 @@
|
||||
Building a Custom ROM
|
||||
---------------------
|
||||
|
||||
At present, the build environment assumes you are running
|
||||
a current version of Microsoft Windows (either 32-bit or
|
||||
64-bit).
|
||||
|
||||
If you are using Linux, David Giles has contributed a Linux
|
||||
makefile that should work for you. Please read the
|
||||
LinuxBuild.txt file for more information.
|
||||
|
||||
All required tools are included in the distribution. You
|
||||
should not need anything other than what comes as part of
|
||||
Windows or as part of the distribution.
|
||||
|
||||
In summary, the process involves the 4 steps below:
|
||||
|
||||
1) Create/update configuration file
|
||||
|
||||
2) Update/Add/Delete any files you want incorporated in
|
||||
the ROM Disk
|
||||
|
||||
3) Run the build script (or makefile if you prefer) and
|
||||
confirm there are no errors.
|
||||
|
||||
4) Burn the resultant ROM image and try it.
|
||||
|
||||
The process is really very simple. In fact, you can
|
||||
essentially skip steps 1 & 2 if you want to try simply
|
||||
building one of the existing configurations.
|
||||
|
||||
Each of the 4 steps above is described in more detail
|
||||
below.
|
||||
|
||||
1. Create/Update Configuration File
|
||||
-----------------------------------
|
||||
|
||||
The settings for a build are primarily controled by
|
||||
a configuration file that is included in the build
|
||||
process. In order to customize your settings, you
|
||||
need to modify an existing configuration file or
|
||||
create your own.
|
||||
|
||||
If you look in the Source directory, you will see
|
||||
a series of files named config_xxxx_yyyy.asm. Each of
|
||||
them corresponds to one of the standard configurations
|
||||
listed in the ROMList.txt file.
|
||||
|
||||
You have two choices. You can simply modify the existing
|
||||
configuration file that is closest to your situation, or
|
||||
you can copy it to a new config_xxxx_yyyy.asm file and modify
|
||||
that. I recommend that you copy one to your own name so
|
||||
that you will always have the unmodified standard configuration
|
||||
files left in place. So, for example, you could just
|
||||
copy config_ZETA_std.asm to config_ZETA_wayne.asm. You MUST
|
||||
name your config file as config_xxxx_yyyy.asm. The xxxx's
|
||||
must match your platform (N8VEM, ZETA, N8, S2I, or S100).
|
||||
The yyyy's can be whatever you want.
|
||||
|
||||
The config files are simply text files with various
|
||||
settings. Open your target config file with your
|
||||
favorite text editor and modify the settings as desired.
|
||||
|
||||
Unfortunately, I have not yet documented each of the
|
||||
settings in detail; that will be a separate document
|
||||
provided in the future. However, there are comments
|
||||
in the config file that will probably be sufficient
|
||||
for the most part.
|
||||
|
||||
2. Update/Add/Delete ROM Disk Files
|
||||
-----------------------------------
|
||||
|
||||
The files that are included on the ROM Disk of your
|
||||
ROM are copied from a set of directories during the
|
||||
build process. This allows you to have complete
|
||||
flexibility over the files you want included in your
|
||||
ROM.
|
||||
|
||||
If you look at the RomDsk directory, you will see
|
||||
a variety of subdirectories. These subdirectories
|
||||
contain the files that will be included in the
|
||||
ROM disk. The build process will determine
|
||||
which subdirectories to include files from based
|
||||
on the following rules:
|
||||
|
||||
First, all files from either std_512 or std_1024 will
|
||||
be incuded depending on on the size of the ROM you
|
||||
are building. If you are building a 512KB ROM, then
|
||||
all the files from std_512KB will be included. If you
|
||||
are building a 1MB ROM, then all the files from std_1024KB
|
||||
will be included. Essentialy, the files in std_1204KB are
|
||||
a superset of the ones in std_512KB because there is more
|
||||
space available for the ROM drive.
|
||||
|
||||
Second, all files from the directory that corresponds to
|
||||
your configuration file will be included. If you build
|
||||
the "ZETA_std" configuration, all files in cfg_ZETA_std will
|
||||
be added. Note that these files will be in addition
|
||||
to the files from the std_XXXKB directory.
|
||||
|
||||
If you created your own config file (like config_ZETA_wayne.asm
|
||||
described above), you MUST create a subdirectory within
|
||||
the RomDsk directory and populate it with the files
|
||||
you want added. Normally, you would include the
|
||||
files from the original standard config. So, if
|
||||
you created config_ZETA_wayne.asm from config_ZETA_std.asm,
|
||||
then you would create a subdirectory in RomDsk called
|
||||
cfg_ZETA_wayne and copy all the files from cfg_ZETA_std to
|
||||
cfg_ZETA_wayne.
|
||||
|
||||
3. Run the Build Process
|
||||
------------------------
|
||||
|
||||
NOTE: The process described here is the more commonly
|
||||
used build script. If you wish to use a makefile
|
||||
instead, refer to the comments in the makefile in
|
||||
the Source directory as an alternative to the
|
||||
process described here.
|
||||
|
||||
The build involves running commands at the command
|
||||
prompt. From a Command Prompt window, you will need
|
||||
to change to the high level directory for the build.
|
||||
Normally, you would be changing to the RomWBW directory
|
||||
unless you renamed it.
|
||||
|
||||
First, you will need to build the components that are
|
||||
common to all configurations. These components do not
|
||||
require any configuration. To build these, use the
|
||||
following commands and ensure that they complete
|
||||
without error:
|
||||
|
||||
BuildZCPR-DJ
|
||||
BuildApps2
|
||||
|
||||
To run the main build and be prompted for required information,
|
||||
just enter "Build". You will be prompted for the information
|
||||
described below and the build should run. If an error is
|
||||
encountered, the build should stop and display an error
|
||||
in red text.
|
||||
|
||||
If you immediately receive the error "the execution of
|
||||
scripts is disabled on this system", then you will need to
|
||||
change the PowerShell Execution-Polcy to "RemoteSigned".
|
||||
To do this, you need to right-click on FixPowerShell.cmd and
|
||||
choose "Run as Administrator" to make the change. If is
|
||||
critical that you right-click and use "Run as Administrator"
|
||||
or the change will not work (you will get an error
|
||||
indicating "Access to the registry denied" if you fail to
|
||||
use "Run as Administrator".
|
||||
|
||||
The build script will prompt you for the following information
|
||||
which you will need to provide (don't worry, it is simple):
|
||||
|
||||
Platform:
|
||||
|
||||
Respond with the name of the platform that you are targeting.
|
||||
It must be one of N8VEM, ZETA, N8, S2I, or S100.
|
||||
|
||||
Configuration:
|
||||
|
||||
Respond with the name of the configuration you wish to build.
|
||||
A list of all available configurations is displayed for your
|
||||
convenience. For example, if you are building the provided
|
||||
ZETA_std configuration, just enter "std". If you have created a
|
||||
custom configuration as described above, you would enter
|
||||
"wayne".
|
||||
|
||||
ROM Size [512|1024]:
|
||||
|
||||
Respond with either "512" for a 512KB ROM build or "1024" for a
|
||||
1MB ROM build. Only the two choices are possible at this time.
|
||||
It is important that you choose a ROM size that is no larger than
|
||||
the szie of the ROM you will ultimately be burning. This is
|
||||
dependant on your hardware.
|
||||
|
||||
At this point, the build should run and you will see output related
|
||||
to the assembler runs and some utility invocations. Just review
|
||||
the output for any obvioius errors. Normally, all errors will
|
||||
cause the build to stop immediately and display an error message
|
||||
in red.
|
||||
|
||||
You will see some lines in the output indicating the amount of
|
||||
space variouis components have taken. You should check these
|
||||
to make sure you do not see any negative numbers which would
|
||||
indicate that you have included too many features/drivers for
|
||||
the available memory space. Here are examples of the lines
|
||||
showing the space used:
|
||||
|
||||
DATA space remaining: 39 bytes.
|
||||
BOOT LOADER space remaining: 3503 bytes.
|
||||
CBIOS space remaining: 161 bytes.
|
||||
DBGMON space remaining: 860 bytes.
|
||||
ROMX space remaining: 8191 bytes.
|
||||
BOOT LOADER space remaining: 3503 bytes.
|
||||
|
||||
4. Deploy the ROM
|
||||
-----------------
|
||||
|
||||
If you look in the Output directory. You should find the following files:
|
||||
|
||||
<config>.rom - binary ROM image to burn to EEPROM
|
||||
<config>.sys - system image that can be written to the start of a
|
||||
disk to enable boot from disk functionality
|
||||
<config>.com - executable version of the system image that can be
|
||||
copied via xmodem to a running system to test
|
||||
the build.
|
||||
|
||||
The actual ROM image is the file ending in .rom. It should be exactly
|
||||
512KB or 1MB depending on the ROM size you chose. Simply burn the .rom
|
||||
image to your ROM and install it in your hardware.
|
||||
|
||||
Specifying Build Options on Command Line
|
||||
----------------------------------------
|
||||
|
||||
If you don't want to be prompted for the options to the "Build"
|
||||
command, you can specify the options right on the command line.
|
||||
|
||||
For example:
|
||||
|
||||
Build ZETA std 512
|
||||
|
||||
In this case, you will not be prompted. This is useful if you
|
||||
wish to automate your build process.
|
||||
|
||||
Example Build Run
|
||||
-----------------
|
||||
|
||||
C:\Users\WWarthen\Projects\N8VEM\Build\RomWBW>Build.cmd
|
||||
Platform [N8VEM|ZETA|N8|S2I|S100]: ZETA
|
||||
Configurations available:
|
||||
> ppp
|
||||
> std
|
||||
Configuration: std
|
||||
ROM Size [512|1024]: 512
|
||||
|
||||
Building ZETA_std: 512KB ROM configuration std for Z80...
|
||||
|
||||
tasm -t80 -g3 ccpb03.asm cp.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 bdosb01.asm dos.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 syscfg.asm syscfg.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 -dBLD_SYS=SYS_CPM cbios.asm cbios.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
INFOLIST occupies 18 bytes.
|
||||
UTIL occupies 484 bytes.
|
||||
FD_DATA occupies 340 bytes.
|
||||
PPIDE_DATA occupies 1116 bytes.
|
||||
CBIOS space remaining: 2092 bytes.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 dbgmon.asm dbgmon.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
DBGMON space remaining: 795 bytes.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 prefix.asm prefix.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 bootrom.asm bootrom.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 bootapp.asm bootapp.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 loader.asm loader.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
LOADER space remaining: 1205 bytes.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 pgzero.asm pgzero.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 hbios.asm hbios.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
UART occupies 146 bytes.
|
||||
FD occupies 2071 bytes.
|
||||
PPIDE occupies 809 bytes.
|
||||
HBIOS space remaining: 24428 bytes.
|
||||
STACK space remaining: 145 bytes.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 hbfill.asm hbfill.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
Configuration: ZETA Z80 SBC, FLOPPY (AUTOSIZE), PPIDE (STD)
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
tasm -t80 -g3 romfill.asm romfill.bin
|
||||
TASM Z80 Assembler. Version 3.2 September, 2001.
|
||||
Copyright (C) 2001 Squak Valley Software
|
||||
tasm: pass 1 complete.
|
||||
tasm: pass 2 complete.
|
||||
tasm: Number of errors = 0
|
||||
Building ZETA_std output files...
|
||||
Building 512KB ZETA_std ROM disk data file...
|
||||
|
||||
C:\Users\WWarthen\Projects\N8VEM\Build\RomWBW>
|
||||
Binary file not shown.
@@ -1,49 +1,3 @@
|
||||
Version 2.8.3
|
||||
-------------
|
||||
- WBW: Added MODE command
|
||||
- WBW: Removed obsolete 1200.COM, 9600.COM, and 38400.COM
|
||||
- WBW: New XM.COM that automatically adapts to primary port of platform
|
||||
- WBW: XM.COM now handles 38400 baud at 4MHz
|
||||
- WBW: Removed obsolete XM versions: XM5.COM, XM-A0.COM, XM-A1.COM
|
||||
|
||||
Version 2.8.2
|
||||
-------------
|
||||
- WBW: Adjusted VGA3 register setup per John's recommendations
|
||||
|
||||
Version 2.8.1
|
||||
-------------
|
||||
- WBW: Fix FDISK80
|
||||
- WBW: Upgrade to latest production UNA 2.1-45
|
||||
|
||||
Version 2.8.0
|
||||
-------------
|
||||
- WBW: Add support for VGA3 board
|
||||
|
||||
Version 2.7.1
|
||||
-------------
|
||||
- WBW: Replace ZX with XP compatible build (no functional changes)
|
||||
- WBW: Reset BDOS serial number on warm start
|
||||
- WBW: Turn off DRAM refresh on Z180 (fixes Z180 CPU speed detection)
|
||||
|
||||
Version 2.7.0
|
||||
-------------
|
||||
- WBW: Memory page reorganization
|
||||
- WBW: Support for Zeta 2 (from Sergey Kiselev)
|
||||
- WBW: Support loading from image file (UNA FSFAT)
|
||||
- WBW: Dynamic CPU speed detection
|
||||
|
||||
Version 2.6.5
|
||||
-------------
|
||||
- WBW: Yet more DS1302 clock driver delay mods
|
||||
|
||||
Version 2.6.4
|
||||
-------------
|
||||
- WBW: Yet more DS1302 clock driver delay mods
|
||||
|
||||
Version 2.6.3
|
||||
-------------
|
||||
- WBW: DS1302 clock driver modified to observe proper delays
|
||||
|
||||
Version 2.6.2
|
||||
-------------
|
||||
- WBW: ASSIGN.COM substantially improved to map all drive types
|
||||
|
||||
Binary file not shown.
@@ -5,21 +5,21 @@
|
||||
= Warning =
|
||||
|
||||
FLASH4 has been tested and confirmed working on:
|
||||
* N8VEM SBCv2
|
||||
* N8VEM N8-2312
|
||||
* N8VEM Mark IV SBC
|
||||
* DX-Designs P112
|
||||
* ZETA SBC v2
|
||||
* SBCv2
|
||||
* N8-2312
|
||||
* Mark IV SBC
|
||||
|
||||
However it remains somewhat experimental. If it works for you, please let me
|
||||
know. If it breaks please also let me know so I can fix it!
|
||||
know. If it breaks please also let me know so I can fix it! Until it is more
|
||||
widely tested please ensure you have some other means to reprogram your flash
|
||||
ROM before exclusively trusting FLASH4.
|
||||
|
||||
|
||||
= Introduction =
|
||||
|
||||
FLASH4 is a CP/M program which can read, write and verify Flash ROM contents to
|
||||
or from an image file stored on a CP/M filesystem. It is intended for in-system
|
||||
programming of Flash ROM chips on Z80 and Z180 systems.
|
||||
programming of Flash ROM chips on N8VEM Z80 and Z180 systems.
|
||||
|
||||
FLASH4 aims to support a range of Flash ROM chips. Ideally I would like to
|
||||
support all Flash ROM chips that are in use in Z80/Z180 N8VEM machines. If
|
||||
@@ -46,26 +46,23 @@ the "srec_cat" program from SRecord:
|
||||
$ srec_cat image.hex -intel -fill 0xFF 0 0x80000 -output image.bin -binary
|
||||
$ srec_cat image.bin -binary -output image.hex -intel
|
||||
|
||||
FLASH4 can use several different methods to access the Flash ROM chip. The best
|
||||
FLASH4 can use three different methods to access the Flash ROM chip. The best
|
||||
available method is determined automatically at run time. Alternatively you may
|
||||
provide a command-line option to force the use of a specific method.
|
||||
|
||||
The first two methods use bank switching to map sections of the ROM into the
|
||||
CPU address space. FLASH4 will detect the presence of RomWBW or UNA BIOS and
|
||||
use the bank switching methods they provide.
|
||||
use the bank switching methods they provide.
|
||||
|
||||
On P112 systems the P112 B/P BIOS is detected and P112 bank switching is used.
|
||||
|
||||
If no bank switching method can be auto-detected, and the system has a Z180
|
||||
CPU, FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This
|
||||
does not require any bank switching but it is slower and will not work on all
|
||||
platforms.
|
||||
If neither RomWBW nor UNA BIOS is detected and the system has a Z180 CPU,
|
||||
FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This does not
|
||||
require any bank switching but it is slower and will not work on all platforms.
|
||||
|
||||
Z180 DMA access requires the flash ROM to be linearly mapped into the lower
|
||||
region of physical memory, as it is on the Mark IV SBC (for example). The
|
||||
N8-2312 has additional memory mapping hardware, consequently Z180 DMA access on
|
||||
the N8-2312 is NOT SUPPORTED and if forced will corrupt the contents of RAM;
|
||||
use one of the supported bank switching methods instead.
|
||||
region of physical memory, as it is on the Mark IV SBC. The N8-2312 has
|
||||
additional memory mapping hardware, consequently Z180 DMA access on the N8-2312
|
||||
is NOT SUPPORTED and if forced will corrupt the contents of RAM; use bank
|
||||
switched access instead.
|
||||
|
||||
Z180 DMA access requires the Z180 CPU I/O base control register configured to
|
||||
locate the internal I/O addresses at 0x40 (ie ICR bits IOA7, IOA6 = 0, 1).
|
||||
@@ -96,27 +93,13 @@ If your ROM chip is larger than the image you wish to write, use the "/PARTIAL"
|
||||
the image file must be an exact multiple of 32KB in length. The portion of the
|
||||
ROM not occupied by the image file is left either unmodified or erased.
|
||||
|
||||
If you are using an ROM/EPROM/EEPROM chip which cannot be programmed in-system,
|
||||
FLASH4 will not be able to recognise it, however the software can still
|
||||
usefully READ and VERIFY the chip. Use the "/ROM" command line option to enable
|
||||
"READ" or "VERIFY" mode with unrecognised chips. This mode assumes a 512K ROM
|
||||
is fitted; smaller ROMs will be treated as a 512K ROM with the data repated
|
||||
multiple times -- with a 256K chip the data is repeated twice, four times for a
|
||||
128K chip, etc.
|
||||
|
||||
One of the following optional command line arguments may be specified at the
|
||||
end of the command line to force FLASH4 to use a particular method to access
|
||||
the flash ROM chip:
|
||||
|
||||
BIOS interfaces:
|
||||
/ROMWBW For ROMWBW BIOS version 2.6 and later
|
||||
/ROMWBWOLD For ROMWBW BIOS version 2.5 and earlier
|
||||
/UNABIOS For UNA BIOS
|
||||
|
||||
Direct hardware interfaces:
|
||||
/Z180DMA For Z180 DMA
|
||||
/P112 For DX-Designs P112
|
||||
/N8VEMSBC For N8VEM SBC (v1, v2), Zeta (v1) SBC
|
||||
/ROMWBW
|
||||
/UNABIOS
|
||||
/Z180DMA
|
||||
|
||||
If no option is specified FLASH4 attempts to determine the best available
|
||||
method automatically.
|
||||
@@ -1,42 +0,0 @@
|
||||
***********************************************************************
|
||||
*** ***
|
||||
*** R o m W B W ***
|
||||
*** ***
|
||||
*** Z80/Z180 System Software ***
|
||||
*** ***
|
||||
***********************************************************************
|
||||
|
||||
This directory ("Doc") is part of the RomWBW System Software
|
||||
distribution archive. It contains documentation for components of
|
||||
the system.
|
||||
|
||||
CPM Manual:
|
||||
|
||||
The original DRI CP/M 2.x Operating System Manual. This should be
|
||||
considered the primary reference for system operation. The section
|
||||
on CP/M 2 Alteration can be ignored since this work has already been
|
||||
completed as part of the RomWBW distribution.
|
||||
|
||||
FDisk Manual:
|
||||
|
||||
The operational manual for John Coffman's hard disk partitioning
|
||||
program. This program is included in RomWBW as FDISK80.
|
||||
|
||||
RomWBW Architecture:
|
||||
|
||||
Document describing the architecture of the RomWBW HBIOS. It
|
||||
includes reference information for the HBIOS calls.
|
||||
|
||||
ZCPR Manual:
|
||||
|
||||
ZCPR is the command proccessor portion of Z-System. This is the
|
||||
manual for ZCPR 1.x as included in RomWBW. The installation
|
||||
instructions can be ignored since that work has already been
|
||||
completed as part of the RomWBW distribution.
|
||||
|
||||
ZSDOS Manual:
|
||||
|
||||
ZSDOS is the DOS portion of Z-System. This is the manual fo ZSDOS
|
||||
1.x as included in RomWBW. The installation instructions can be
|
||||
ignored since that work has already been completed as part of the
|
||||
RomWBW distribution.
|
||||
BIN
Doc/Reference/cpm22-m.pdf
Normal file
BIN
Doc/Reference/cpm22-m.pdf
Normal file
Binary file not shown.
@@ -1,6 +1,3 @@
|
||||
|
||||
|
||||
|
||||
ZCPR - A Z80 Replacement for the CP/M CCP
|
||||
|
||||
|
||||
@@ -8,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
\textbf{Documentation on ZCPR - A Z80 Replacement for the CP/M CCP}
|
||||
Documentation on ZCPR - A Z80 Replacement for the CP/M CCP
|
||||
|
||||
|
||||
|
||||
@@ -71,7 +68,7 @@
|
||||
|
||||
|
||||
|
||||
\textbf{Documentation on ZCPR - A Z80 Replacement for the CP/M CCP}
|
||||
Documentation on ZCPR - A Z80 Replacement for the CP/M CCP
|
||||
|
||||
|
||||
|
||||
@@ -241,7 +238,6 @@
|
||||
integration is the placement of the new ZCPR onto disk in the
|
||||
proper place so that it will be loaded with the rest of CP/M on
|
||||
cold boot and executed properly.
|
||||
|
||||
To find the original CCP, you typically have to locate it by
|
||||
its appearance. It is probably stored contiguously on disk, so,
|
||||
once it is found, a sequential overwrite is all that is required.
|
||||
@@ -259,6 +255,7 @@
|
||||
CCP. The CCP will probably start on an even page or half-page
|
||||
address (like 900H, 980H, 1100H, etc).
|
||||
|
||||
|
||||
Page 4
|
||||
|
||||
|
||||
@@ -371,7 +368,7 @@
|
||||
-^C <-- Return to CP/M; I know that CPRLOC will be
|
||||
BD00H and the IMAGE offset is 1100H
|
||||
|
||||
B>ed cpr.asm \{edit ZCPR here and place CPRLOC=BD00H\}#
|
||||
B>ed cpr.asm {edit ZCPR here and place CPRLOC=BD00H}#
|
||||
-- Detail Left Out --
|
||||
|
||||
B>mac cpr $pz sz <-- Now to assemble the CPR
|
||||
@@ -747,7 +744,7 @@
|
||||
To illustrate this command hierarchy search, consider the
|
||||
following examples:
|
||||
|
||||
Example 1: DEFUSR equ 0 \{default user number is 0\}
|
||||
Example 1: DEFUSR equ 0 {default user number is 0}
|
||||
|
||||
B10> <-- User is on Drive B:, User Number 10
|
||||
B10>ASM TEST.BBZ <-- User wishes to assemble TEST.ASM in
|
||||
@@ -813,9 +810,9 @@
|
||||
issued from the console (or Indirect Command File):
|
||||
|
||||
B10>WM TEST2.TXT
|
||||
^ ^ ^-------- File to be edited
|
||||
| +----------- Invoke the WM.COM file (Word Master editor)
|
||||
+--------------- User is on Drive B: in User Area 10
|
||||
\ \ \__ File to be edited
|
||||
\ \__ Invoke the WM.COM file (Word Master editor)
|
||||
\__ User is on Drive B: in User Area 10
|
||||
|
||||
Results:
|
||||
ZCPR searches B: User 10, B: User 0, and A: User 0 for
|
||||
@@ -823,8 +820,8 @@
|
||||
back into B: User 10, and executes it.
|
||||
|
||||
B10>MBASIC
|
||||
^ ^----- Invoke the MBASIC.COM file (MBASIC Interpreter)
|
||||
+--------- User is on Drive B: in User Area 10
|
||||
\ \__ Invoke the MBASIC.COM file (MBASIC Interpreter)
|
||||
\__ User is on Drive B: in User Area 10
|
||||
|
||||
Results:
|
||||
ZCPR searches B: User 10 and B: User 0 for MBASIC.COM;
|
||||
@@ -833,8 +830,8 @@
|
||||
in the previous example.
|
||||
|
||||
B10>TEST
|
||||
^ ^--- Invoke the TEST.COM file (TEST program)
|
||||
+------- User is on Drive B: in User Area 10
|
||||
\ \__ Invoke the TEST.COM file (TEST program)
|
||||
\__ User is on Drive B: in User Area 10
|
||||
|
||||
Results:
|
||||
ZCPR searches B: User 10 for TEST.COM; it finds
|
||||
@@ -843,8 +840,8 @@
|
||||
then loaded and executed as described above.
|
||||
|
||||
B10>TEST2
|
||||
| +--- Invoke the TEST2.COM file (TEST2 program)
|
||||
+------- User is on Drive B: in User Area 10
|
||||
\ \__ Invoke the TEST2.COM file (TEST2 program)
|
||||
\__ User is on Drive B: in User Area 10
|
||||
|
||||
Results:
|
||||
ZCPR searches B: User 10, B: User 0, and A: User 0 for
|
||||
@@ -1381,4 +1378,10 @@
|
||||
|
||||
|
||||
|
||||
Page 21
|
||||
Page 21
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
BIN
Doc/Source/Bank Switched Memory.vsd
Normal file
BIN
Doc/Source/Bank Switched Memory.vsd
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -14,7 +14,7 @@ Beyond the construction and integration of the actual DOS itself, the majority o
|
||||
|
||||
The remainder of this document details the changes I made as I went along. In all cases, my goal was to keep the result as close to the original distribution as possible. I started by copying all of the files from the distribution (contained in zsdos2.zip) into Support\ZSDOS. From there I tested, modified, updated, and customized as documented below. Finally, I cherry picked files that made sense to include on the ZSystem ROM disks.
|
||||
|
||||
1. CLOCKS.DAT has been updated to include the RomWBW clock driver, HBCLK. I have also added the SIMHCLOK clock driver.
|
||||
1. CLOCKS.DAT has been updated to include the N8VEM clock drivers, N8VEMCLK AND N8CLK. I have also added the SIMHCLOK clock driver.
|
||||
|
||||
2. STAMPS.DAT has been replaced with an updated version. The update was called STAMPS11.DAT and was found on the Walnut Creek CP/M CDROM. The original version has a bug that prevents RSX (resident system extension) mode to load properly.
|
||||
|
||||
29
FixPowerShell.cmd
Normal file
29
FixPowerShell.cmd
Normal file
@@ -0,0 +1,29 @@
|
||||
@echo off
|
||||
echo By default, PowerShell is configured to block the
|
||||
echo execution of unsigned scripts on your local system.
|
||||
echo This command file will attempt to modify your
|
||||
echo PowerShell ExecutionPolicy to "Unrestricted"
|
||||
echo which means that local scripts can be run without
|
||||
echo being signed. This is required to use the RomWBW
|
||||
echo build process.
|
||||
echo.
|
||||
PowerShell -command Write-Host "Your PowerShell ExecutionPolicy is currently set to: `'(Get-ExecutionPolicy)`'"
|
||||
echo.
|
||||
echo In order to modify the ExecutionPolicy, this command
|
||||
echo file *MUST* be run with administrator privileges.
|
||||
echo Generally, this means you want to right-click the
|
||||
echo command file called FixPowerShell.cmd and choose
|
||||
echo "Run as Administrator". If you attempt to continue
|
||||
echo without administrator privileges, the modification
|
||||
echo will fail with an error message, but no harm is done.
|
||||
echo.
|
||||
choice /m "Do you want to proceed"
|
||||
if errorlevel 2 goto :eof
|
||||
echo.
|
||||
echo Attempting to change Execution Policy...
|
||||
echo.
|
||||
PowerShell Set-ExecutionPolicy Unrestricted
|
||||
echo.
|
||||
PowerShell -command Write-Host "Your new PowerShell ExecutionPolicy is now set to: `'(Get-ExecutionPolicy)`'"
|
||||
echo.
|
||||
pause
|
||||
BIN
Hardware/ParPortProp/ParPortProp.eeprom
Normal file
BIN
Hardware/ParPortProp/ParPortProp.eeprom
Normal file
Binary file not shown.
Binary file not shown.
@@ -122,18 +122,19 @@ PUB clrbtm(ColorVal) | i
|
||||
repeat i from 36 to rows - 1 'was 35
|
||||
colors[i] := $0000 + ColorVal
|
||||
|
||||
PUB cls1(VerStr) | i
|
||||
PUB cls1(c,screencolor,pcport,ascii,CR) | i,x,y
|
||||
|
||||
longfill(@screen[0], $20202020, chars / 4)
|
||||
|
||||
clrbtm(TURQUOISE)
|
||||
|
||||
inverse := 1
|
||||
statprint(36, 0, VerStr)
|
||||
inverse := 0
|
||||
|
||||
repeat i from 37 to (rows - 1)
|
||||
statprint(i,0, string(" "))
|
||||
statprint(36,0, string(" N8VEM ParPortProp | RomWBW v0.92"))
|
||||
inverse := 0
|
||||
statprint(37,0, string(" "))
|
||||
statprint(38,0, string(" "))
|
||||
statprint(39,0, string(" "))
|
||||
|
||||
|
||||
{{
|
||||
@@ -151,7 +152,7 @@ PUB cls1(VerStr) | i
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" "))
|
||||
str(string(" propIO V 0.91 "))
|
||||
inverse := 0
|
||||
str(string("Baud Rate: "))
|
||||
i:= BR[6]
|
||||
@@ -214,7 +215,7 @@ PUB clsupdate(c,screencolor,PCPORT,ascii,CR) | i,x,y,locold
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" "))
|
||||
str(string(" propIO V 0.81 "))
|
||||
inverse := 0
|
||||
xloc := 0
|
||||
yloc :=37
|
||||
@@ -25,9 +25,6 @@ CON
|
||||
ERR_3v3_NOT_SUPPORTED = -2
|
||||
ERR_OCR_FAILED = -3
|
||||
ERR_BLOCK_NOT_LONG_ALIGNED = -4
|
||||
ERR_CRC_ONOFF_FAILED = -5
|
||||
ERR_STATUS_FAILED = -6
|
||||
ERR_CSD_FAILED = -7
|
||||
'...
|
||||
' These errors are for the assembly engine...they are negated inside, and need to be <= 511
|
||||
ERR_ASM_NO_READ_TOKEN = 100
|
||||
@@ -61,17 +58,14 @@ CON
|
||||
' buffer size for my debug cmd log
|
||||
'LOG_SIZE = 256<<1
|
||||
|
||||
|
||||
{
|
||||
VAR
|
||||
'long SPI_engine_cog
|
||||
'' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
'long SPI_command ' "t", "r", "w", 0 =>done, <0 => error | pin mask
|
||||
'long SPI_block_index ' which 512-byte block to read/write | cnt at init
|
||||
'long SPI_buffer_address ' where to get/put the data in Hub RAM | unused
|
||||
|
||||
'long SPI_capacity
|
||||
'byte SPI_csdbuf[16]
|
||||
|
||||
long SPI_engine_cog
|
||||
' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
long SPI_command ' "t", "r", "w", 0 =>done, <0 => error | pin mask
|
||||
long SPI_block_index ' which 512-byte block to read/write | cnt at init
|
||||
long SPI_buffer_address ' where to get/put the data in Hub RAM | unused
|
||||
'}
|
||||
DAT
|
||||
'' I'm placing these variables in a DAT section to make this driver a singleton.
|
||||
'' If for some reason you really need more than one driver (e.g. if you have more
|
||||
@@ -82,9 +76,6 @@ SPI_command long 0 ' "t", "r", "w", 0 =>done, <0 => error
|
||||
SPI_block_index long 0 ' which 512-byte block to read/write | cnt at init
|
||||
SPI_buffer_address long 0 ' where to get/put the data in Hub RAM | unused
|
||||
|
||||
SPI_capacity long 0
|
||||
SPI_csdbuf byte 0 [16]
|
||||
|
||||
{
|
||||
VAR
|
||||
' for debug ONLY
|
||||
@@ -124,12 +115,6 @@ PUB writeblock( block_index, buffer_address )
|
||||
if SPI_command < 0
|
||||
abort SPI_command
|
||||
|
||||
PUB getcapacity
|
||||
Result := SPI_capacity
|
||||
|
||||
PUB getcsd( buffer_address )
|
||||
bytemove(buffer_address, @SPI_csdbuf, 16)
|
||||
|
||||
PUB get_seconds
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
@@ -154,8 +139,6 @@ PUB start_explicit( DO, CLK, DI, CS ) : card_type | tmp, i
|
||||
}}
|
||||
' Start from scratch
|
||||
stop
|
||||
' Reset card capacity
|
||||
SPI_capacity := 0
|
||||
' clear my log buffer
|
||||
{
|
||||
bytefill( @log_cmd_resp, 0, LOG_SIZE+1 )
|
||||
@@ -234,48 +217,10 @@ PUB start_explicit( DO, CLK, DI, CS ) : card_type | tmp, i
|
||||
repeat while send_cmd_slow( CMD1, 0, $F9 )
|
||||
' some SD or MMC cards may have the wrong block size, set it here
|
||||
send_cmd_slow( CMD16, 512, $15 )
|
||||
|
||||
' card is mounted, make sure the CRC is turned off
|
||||
if send_cmd_slow( CMD59, 0, $91 ) <> 0
|
||||
crash( ERR_CRC_ONOFF_FAILED )
|
||||
|
||||
' check card status
|
||||
if send_cmd_slow ( CMD13, 0, $FF) <> 0
|
||||
crash( ERR_STATUS_FAILED )
|
||||
read_slow ' swallow second byte of status
|
||||
|
||||
' get card capacity
|
||||
if send_cmd_slow ( CMD9, 0, $FF) <> 0
|
||||
crash( ERR_CSD_FAILED )
|
||||
i := 32 ' arbitrary timeout
|
||||
repeat while (read_slow <> $FE)
|
||||
if i == 0
|
||||
crash( ERR_CSD_FAILED )
|
||||
repeat i from 0 to 15 ' 16 bytes of CSD data
|
||||
SPI_csdbuf[i] := read_slow
|
||||
read_slow ' discard CRC - first byte
|
||||
read_slow ' discard CRC - second byte
|
||||
|
||||
case (card_type)
|
||||
type_MMC, type_SD:
|
||||
tmp := SPI_csdbuf[9]
|
||||
tmp := (tmp << 8) | SPI_csdbuf[10]
|
||||
i := ((tmp >> 7) & $07) ' c_size_mult
|
||||
tmp := SPI_csdbuf[5]
|
||||
i += tmp & $0F ' mask out read_bl_len and add to c_size_mult
|
||||
tmp := SPI_csdbuf[6] & $03
|
||||
tmp := (tmp << 8) | SPI_csdbuf[7]
|
||||
tmp := (tmp << 8) | SPI_csdbuf[8]
|
||||
tmp := (tmp >> 6) ' c_size
|
||||
SPI_capacity := ((tmp + 1) << (2 + i)) >> 9
|
||||
type_SDHC:
|
||||
tmp := SPI_csdbuf[7] & $3F
|
||||
tmp := (tmp << 8) | SPI_csdbuf[8]
|
||||
tmp := (tmp << 8) | SPI_csdbuf[9]
|
||||
SPI_capacity := (tmp + 1) * 1024
|
||||
other:
|
||||
SPI_capacity := 0
|
||||
|
||||
send_cmd_slow( CMD59, 0, $91 )
|
||||
' check the status
|
||||
'send_cmd_slow( CMD13, 0, $0D )
|
||||
' done with the SPI bus for now
|
||||
outa |= maskCS
|
||||
' set my counter modes for super fast SPI operation
|
||||
BIN
Hardware/ParPortProp/TstPPP.com
Normal file
BIN
Hardware/ParPortProp/TstPPP.com
Normal file
Binary file not shown.
BIN
Hardware/PropIO/PropIO.eeprom
Normal file
BIN
Hardware/PropIO/PropIO.eeprom
Normal file
Binary file not shown.
BIN
Hardware/PropIO/Spin/Keyboard.spin
Normal file
BIN
Hardware/PropIO/Spin/Keyboard.spin
Normal file
Binary file not shown.
BIN
Hardware/PropIO/Spin/Parallax Serial Terminal.spin
Normal file
BIN
Hardware/PropIO/Spin/Parallax Serial Terminal.spin
Normal file
Binary file not shown.
Binary file not shown.
704
Hardware/PropIO/Spin/VGA_1024.spin
Normal file
704
Hardware/PropIO/Spin/VGA_1024.spin
Normal file
@@ -0,0 +1,704 @@
|
||||
'' VGA_1024.spin
|
||||
''
|
||||
'' MODIFIED BY VINCE BRIEL FOR POCKETERM FEATURES
|
||||
'' MODIIFED BY JEFF LEDGER / AKA OLDBITCOLLECTOR
|
||||
''
|
||||
|
||||
CON
|
||||
cols = 80 '128 ' number of screen columns
|
||||
lcols = cols / 4 ' number of long in columns
|
||||
rows = 40 '64 ' number of screen rows
|
||||
chars = rows*cols ' number of screen characters
|
||||
esc = $CB ' keyboard esc char
|
||||
rowsnow = 36 ' adjusted for split screen effect
|
||||
maxChars = rowsnow*cols ' adjusted value for split screen effect
|
||||
lastChar = maxChars / 4 ' last screen position in longs adjusted for split
|
||||
lastLine = (rowsnow - 1) * cols ' character position of last row
|
||||
cols1 = 81 ' adjusted value for 80th character
|
||||
TURQUOISE = $29
|
||||
|
||||
OBJ
|
||||
vga : "vga_Hires_Text"
|
||||
|
||||
VAR
|
||||
byte screen[chars] ' screen character buffer
|
||||
byte tmpl[cols] ' temporary line buffer
|
||||
word colors[rows] ' color specs for each screen row (see ColorPtr description above)
|
||||
byte cursor[6] ' cursor info array (see CursorPtr description above)
|
||||
long sync, loc, xloc, yloc ' sync used by VGA routine, others are local screen pointers
|
||||
long kbdreq ' global val of kbdflag
|
||||
long BR[8]
|
||||
long Brate
|
||||
byte inverse
|
||||
byte invs
|
||||
byte state ' Current state of state machine
|
||||
word pos ' Current Position on the screen
|
||||
word oldpos ' Previous location of cursor before update
|
||||
word regionTop, regionBot ' Scroll region top/bottom
|
||||
long arg0 ' First argument of escape sequence
|
||||
long arg1 ' Second argument of escape sequence
|
||||
byte lastc ' Last displayed char
|
||||
word statpos
|
||||
long vgabasepin
|
||||
|
||||
PUB start(BasePin) | i, char
|
||||
vgabasepin := BasePin
|
||||
|
||||
''init screen colors to gold on blue
|
||||
repeat i from 0 to rows - 1
|
||||
colors[i] := $08F0 '$2804 (if you want cyan on blue)
|
||||
|
||||
''init cursor attributes
|
||||
cursor[2] := %110 ' init cursor to underscore with slow blink
|
||||
BR[0]:=300
|
||||
BR[1]:=1200
|
||||
BR[2]:=2400
|
||||
BR[3]:=4800
|
||||
BR[4]:=9600
|
||||
BR[5]:=19200
|
||||
BR[6]:=38400
|
||||
BR[7]:=57600
|
||||
BR[8]:=115200
|
||||
xloc := cursor[0] := 0
|
||||
yloc := cursor[1] := 0
|
||||
loc := xloc + yloc*cols
|
||||
|
||||
pos := 0
|
||||
regionTop := 0
|
||||
regionBot := 35 * cols
|
||||
state := 0
|
||||
statpos := 37 * cols
|
||||
|
||||
PUB vidon
|
||||
if (!vga.start(vgabasepin, @screen, @colors, @cursor, @sync))
|
||||
return false
|
||||
|
||||
waitcnt(clkfreq * 1 + cnt) 'wait 1 second for cogs to start
|
||||
|
||||
|
||||
PUB vidoff
|
||||
vga.stop
|
||||
|
||||
|
||||
PUB inv(c)
|
||||
inverse:=c
|
||||
|
||||
PUB color(colorVal) | i
|
||||
repeat i from 0 to rows - 1
|
||||
colors[i] := $0000 | colorVal
|
||||
|
||||
PUB cursorset(c) | i
|
||||
i:=%000
|
||||
if c == 1
|
||||
i:= %001
|
||||
if c == 2
|
||||
i:= %010
|
||||
if c == 3
|
||||
i:= %011
|
||||
if c == 4
|
||||
i:= %101
|
||||
if c == 5
|
||||
i:= %110
|
||||
if c == 6
|
||||
i:= %111
|
||||
if c == 7
|
||||
i:= %000
|
||||
cursor[2] := i
|
||||
|
||||
PUB bin(value, digits)
|
||||
|
||||
'' Print a binary number, specify number of digits
|
||||
|
||||
repeat while digits > 32
|
||||
outc("0")
|
||||
digits--
|
||||
|
||||
value <<= 32 - digits
|
||||
|
||||
repeat digits
|
||||
outc((value <-= 1) & 1 + "0")
|
||||
|
||||
|
||||
PUB clrbtm(ColorVal) | i
|
||||
repeat i from 36 to rows - 1 'was 35
|
||||
colors[i] := $0000 + ColorVal
|
||||
|
||||
PUB cls1(c,screencolor,pcport,ascii,CR) | i,x,y
|
||||
|
||||
longfill(@screen[0], $20202020, chars / 4)
|
||||
|
||||
clrbtm(TURQUOISE)
|
||||
|
||||
inverse := 1
|
||||
|
||||
statprint(36,0, string(" N8VEM PropIO | RomWBW v0.94"))
|
||||
inverse := 0
|
||||
statprint(37,0, string(" "))
|
||||
statprint(38,0, string(" "))
|
||||
statprint(39,0, string(" "))
|
||||
|
||||
|
||||
{{
|
||||
x :=xloc
|
||||
y := yloc
|
||||
invs := inverse
|
||||
''clrbtm(TURQUOISE)
|
||||
longfill(@screen, $20202020, chars/4)
|
||||
xloc := 0
|
||||
yloc :=0
|
||||
loc := xloc + yloc*cols
|
||||
repeat 80
|
||||
outc(32)
|
||||
xloc := 0
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" propIO V 0.91 "))
|
||||
inverse := 0
|
||||
str(string("Baud Rate: "))
|
||||
i:= BR[6]
|
||||
dec(i)
|
||||
str(string(" "))
|
||||
xloc := 18
|
||||
loc := xloc + yloc*cols
|
||||
str(string("Color "))
|
||||
str(string("PC Port: "))
|
||||
if pcport == 1
|
||||
str(string("OFF "))
|
||||
if pcport == 0
|
||||
str(string("ON "))
|
||||
str(string(" Force 7 bit: "))
|
||||
if ascii == 0
|
||||
str(string("NO "))
|
||||
if ascii == 1
|
||||
str(string("YES "))
|
||||
str(string(" Cursor CR W/LF: "))
|
||||
if CR == 1
|
||||
str(string("YES"))
|
||||
if CR == 0
|
||||
str(string("NO "))
|
||||
outc(13)
|
||||
outc(10)
|
||||
|
||||
inverse:=1
|
||||
xloc := 6
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F1"))
|
||||
xloc := 19
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F2"))
|
||||
xloc := 30
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F3"))
|
||||
xloc := 46
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F4"))
|
||||
xloc := 58
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F5"))
|
||||
xloc := 70
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F6"))
|
||||
inverse := invs
|
||||
xloc := cursor[0] := x 'right & left was 0
|
||||
yloc := cursor[1] := y 'from top was 1
|
||||
loc := xloc + yloc*cols
|
||||
}}
|
||||
|
||||
PUB clsupdate(c,screencolor,PCPORT,ascii,CR) | i,x,y,locold
|
||||
|
||||
invs := inverse
|
||||
locold := loc
|
||||
x := xloc
|
||||
y := yloc
|
||||
''(TURQUOISE)
|
||||
xloc := 0
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" propIO V 0.81 "))
|
||||
inverse := 0
|
||||
xloc := 0
|
||||
yloc :=37
|
||||
loc := xloc + yloc*cols
|
||||
str(string("Baud Rate: "))
|
||||
i:= BR[6]
|
||||
dec(i)
|
||||
str(string(" "))
|
||||
xloc := 18
|
||||
loc := xloc + yloc*cols
|
||||
|
||||
str(string("Color "))
|
||||
str(string("PC Port: "))
|
||||
if pcport == 1
|
||||
str(string("OFF "))
|
||||
if pcport == 0
|
||||
str(string("ON "))
|
||||
str(string(" Force 7 bit: "))
|
||||
if ascii == 0
|
||||
str(string("NO "))
|
||||
if ascii == 1
|
||||
str(string("YES "))
|
||||
str(string(" Cursor CR W/LF: "))
|
||||
if CR == 1
|
||||
str(string("YES"))
|
||||
if CR == 0
|
||||
str(string("NO "))
|
||||
xloc := 0
|
||||
yloc :=38
|
||||
loc := xloc + yloc*cols
|
||||
inverse:=1
|
||||
xloc := 6
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F1"))
|
||||
xloc := 19
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F2"))
|
||||
xloc := 30
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F3"))
|
||||
xloc := 46
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F4"))
|
||||
xloc := 58
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F5"))
|
||||
xloc := 70
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F6"))
|
||||
inverse := invs
|
||||
xloc := cursor[0] := x
|
||||
yloc := cursor[1] := y
|
||||
' loc := xloc + yloc*cols
|
||||
loc := locold
|
||||
|
||||
PUB dec(value) | i
|
||||
|
||||
'' Print a decimal number
|
||||
|
||||
if value < 0
|
||||
-value
|
||||
outc("-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if value => i
|
||||
outc(value/i + "0")
|
||||
value //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
outc("0")
|
||||
i /= 10
|
||||
|
||||
PUB hex(value, digits)
|
||||
|
||||
'' Print a hexadecimal number, specify number of digits
|
||||
|
||||
repeat while digits > 8
|
||||
outc("0")
|
||||
digits--
|
||||
|
||||
value <<= (8 - digits) << 2
|
||||
|
||||
repeat digits
|
||||
outc(lookupz((value <-= 4) & $f : "0".."9", "A".."F"))
|
||||
|
||||
|
||||
PUB str(string_ptr)
|
||||
|
||||
'' Print a zero terminated string
|
||||
|
||||
repeat strsize(string_ptr)
|
||||
process_char(byte[string_ptr++])
|
||||
|
||||
PUB statprint(r, c, str1) | x, ptr
|
||||
|
||||
ptr := r * cols + c
|
||||
repeat x from 0 to STRSIZE(str1) - 1
|
||||
putc(ptr++, BYTE[str1 + x])
|
||||
|
||||
PUB statnum(r, c, num1) | i, ptr
|
||||
|
||||
ptr := r * cols + c
|
||||
|
||||
if num1 < 0
|
||||
-num1
|
||||
putc(ptr++,"-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if num1 => i
|
||||
putc(ptr++, (num1/i +"0"))
|
||||
num1 //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
putc(ptr++, "0")
|
||||
i /= 10
|
||||
|
||||
PUB putc(position, c)
|
||||
if inverse
|
||||
c |= $80
|
||||
screen[position] := c
|
||||
|
||||
PUB cls
|
||||
longfill (@screen, $20202020, lastChar)
|
||||
|
||||
PUB fullcls
|
||||
longfill(@screen, $20202020, 800)
|
||||
|
||||
PUB setInverse(val)
|
||||
inverse := val
|
||||
|
||||
PUB setInv(c)
|
||||
if c == 7
|
||||
setInverse(1)
|
||||
else
|
||||
setInverse(0)
|
||||
|
||||
PUB clEOL(position) | count
|
||||
count := cols - (position // cols)
|
||||
bytefill(@screen + position, $20, count)
|
||||
|
||||
PUB clBOL(position) | count
|
||||
count := position // cols
|
||||
bytefill(@screen + position - count, $20, count)
|
||||
|
||||
PUB delLine(position) | src, count
|
||||
position -= position // cols
|
||||
|
||||
src := position + cols
|
||||
|
||||
count := (maxChars - src) / 4
|
||||
|
||||
if count > 0
|
||||
longmove(@screen + position, @screen + src, count)
|
||||
|
||||
longfill(@screen + lastLine, $20202020, lcols)
|
||||
|
||||
PUB clEOS(position)
|
||||
cleol(position)
|
||||
position += cols - (position // cols)
|
||||
repeat while position < maxChars
|
||||
longfill(@screen + position, $20202020, lcols)
|
||||
pos += cols
|
||||
|
||||
PUB setCursorPos(position)
|
||||
cursor[0] := position // cols
|
||||
cursor[1] := position / cols
|
||||
|
||||
PUB insLine(position) | base, nxt
|
||||
base := position - (position // cols)
|
||||
position := lastLine
|
||||
repeat while position > base
|
||||
nxt := position - cols
|
||||
longmove(@screen + position, @screen + nxt, lcols)
|
||||
position := nxt
|
||||
clEOL(base)
|
||||
|
||||
PUB insChar(position) | count
|
||||
count := (cols - (position // cols)) - 1
|
||||
bytemove(@tmpl, @screen + position, count)
|
||||
screen[position] := " "
|
||||
bytemove(@screen + position + 1, @tmpl, count)
|
||||
|
||||
PUB delChar(position) | count
|
||||
count := (cols - (position // cols)) - 1
|
||||
bytemove(@screen + position, @screen + position + 1, count)
|
||||
screen[position + count] := " "
|
||||
|
||||
PRI inRegion : answer
|
||||
answer := (pos => regionTop) AND (pos < regionBot)
|
||||
|
||||
PRI scrollUp
|
||||
delLine(regionTop)
|
||||
if regionBot < maxChars
|
||||
insLine(regionBot)
|
||||
|
||||
PRI scrollDown
|
||||
if regionBot < maxChars
|
||||
delLine(regionBot)
|
||||
insLine(regionTop)
|
||||
|
||||
PRI ansi(c) | x, defVal
|
||||
|
||||
state := 0
|
||||
|
||||
if (c <> "r") AND (c <> "J") AND (c <> "m") AND (c <> "K")
|
||||
if arg0 == -1
|
||||
arg0 := 1
|
||||
if arg1 == -1
|
||||
arg1 := 1
|
||||
|
||||
case c
|
||||
"@":
|
||||
repeat while arg0-- > 0
|
||||
insChar(pos)
|
||||
|
||||
"b":
|
||||
repeat while arg0-- > 0
|
||||
outc(lastc)
|
||||
|
||||
"d":
|
||||
if (arg0 < 1) OR (arg0 > rows)
|
||||
arg0 := rows
|
||||
pos := ((arg0 - 1) * cols) + (pos // cols)
|
||||
|
||||
"m":
|
||||
setInv(arg0)
|
||||
if arg1 <> -1
|
||||
setInv(arg1)
|
||||
|
||||
"r":
|
||||
if arg0 < 1
|
||||
arg0 := 1
|
||||
elseif arg0 > cols
|
||||
arg0 := cols
|
||||
if arg1 < 1
|
||||
arg1 := 1
|
||||
elseif arg1 > cols
|
||||
arg1 := cols
|
||||
if arg1 < arg0
|
||||
arg1 := arg0
|
||||
|
||||
regionTop := (arg0 - 1) * cols
|
||||
regionBot := arg1 * cols
|
||||
pos := 0
|
||||
|
||||
"A":
|
||||
repeat while arg0-- > 0
|
||||
pos -= cols
|
||||
if pos < 0
|
||||
pos += cols
|
||||
return
|
||||
|
||||
"B":
|
||||
repeat while arg0-- > 0
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
return
|
||||
|
||||
"C":
|
||||
repeat while arg0-- > 0
|
||||
pos += 1
|
||||
if pos => maxChars
|
||||
pos -= 1
|
||||
return
|
||||
|
||||
"D":
|
||||
repeat while arg0-- > 0
|
||||
pos -= 1
|
||||
if pos < 0
|
||||
pos := 0
|
||||
return
|
||||
|
||||
"G":
|
||||
if (arg0 < 1) OR (arg0 > cols)
|
||||
arg0 := cols
|
||||
pos := (pos - (pos // cols)) + (arg0 - 1)
|
||||
|
||||
"H", "f":
|
||||
if arg0 =< 0
|
||||
arg0 := 1
|
||||
if arg1 =< 0
|
||||
arg1 := 1
|
||||
pos := (cols * (arg0 - 1)) + (arg1 - 1)
|
||||
if pos < 0
|
||||
pos := 0
|
||||
if pos => maxChars
|
||||
pos := maxChars - 1
|
||||
|
||||
"J":
|
||||
if arg0 == 1
|
||||
clBOL(pos)
|
||||
x := pos - cols
|
||||
x -= x // cols
|
||||
repeat while x => 0
|
||||
clEOL(x)
|
||||
x -= cols
|
||||
return
|
||||
|
||||
if arg0 == 2
|
||||
pos := 0
|
||||
|
||||
clEOL(pos)
|
||||
x := pos + cols
|
||||
x -= (x // cols)
|
||||
repeat while x < maxChars
|
||||
clEOL(x)
|
||||
x += cols
|
||||
|
||||
"K":
|
||||
if arg0 == -1
|
||||
clEOL(pos)
|
||||
elseif arg0 == 1
|
||||
clBOL(pos)
|
||||
else
|
||||
clEOL(pos - (pos // cols))
|
||||
|
||||
"L":
|
||||
if inRegion
|
||||
repeat while arg0-- > 0
|
||||
if regionBot < maxChars
|
||||
delLine(regionBot)
|
||||
insLine(pos)
|
||||
|
||||
"M":
|
||||
if inRegion
|
||||
repeat while arg0-- > 0
|
||||
delLine(pos)
|
||||
if regionBot < maxChars
|
||||
insLine(regionBot)
|
||||
|
||||
"P":
|
||||
repeat while arg0--
|
||||
delChar(pos)
|
||||
|
||||
PRI outc(c)
|
||||
|
||||
putc(pos++, lastc := c)
|
||||
if pos == regionBot
|
||||
scrollUp
|
||||
pos -= cols
|
||||
elseif pos == maxChars
|
||||
pos := lastLine
|
||||
|
||||
PUB process_char(c)
|
||||
|
||||
case state
|
||||
|
||||
0:
|
||||
if c > 127
|
||||
c := $20
|
||||
|
||||
if c => $20
|
||||
outc(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == $1B
|
||||
state := 1
|
||||
return
|
||||
|
||||
if c == $0D
|
||||
pos := pos - (pos // cols)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == $0A
|
||||
if inRegion
|
||||
pos += cols
|
||||
if pos => regionBot
|
||||
scrollUp
|
||||
pos -= cols
|
||||
else
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == 9
|
||||
pos += (8 - (pos // 8))
|
||||
|
||||
if pos => maxChars
|
||||
pos := lastLine
|
||||
delLine(0)
|
||||
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == 8
|
||||
if pos > 0
|
||||
pos -= 1
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
1:
|
||||
case c
|
||||
"[":
|
||||
arg0 := arg1 := -1
|
||||
state := 2
|
||||
return
|
||||
|
||||
"P":
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
|
||||
"K":
|
||||
if pos > 0
|
||||
pos -= 1
|
||||
|
||||
"H":
|
||||
pos -= cols
|
||||
if pos < 0
|
||||
pos += cols
|
||||
|
||||
"D":
|
||||
if inRegion
|
||||
scrollUp
|
||||
|
||||
"M":
|
||||
if inRegion
|
||||
scrollDown
|
||||
|
||||
"G":
|
||||
pos := 0
|
||||
|
||||
"(":
|
||||
state := 5
|
||||
return
|
||||
|
||||
state := 0
|
||||
return
|
||||
|
||||
2:
|
||||
if (c => "0") AND (c =< "9")
|
||||
if arg0 == -1
|
||||
arg0 := c - "0"
|
||||
else
|
||||
arg0 := (arg0 * 10) + (c - "0")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
state := 3
|
||||
return
|
||||
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
3:
|
||||
if (c => "0") AND (c =< "9")
|
||||
if arg1 == -1
|
||||
arg1 := c - "0"
|
||||
else
|
||||
arg1 := (arg1 * 10) + (c - "0")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
state := 4
|
||||
return
|
||||
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
4:
|
||||
if (c => "0") AND (c =< "9")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
return
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
5:
|
||||
state := 0
|
||||
return
|
||||
|
||||
return
|
||||
BIN
Hardware/PropIO/Spin/VGA_HiRes_Text.spin
Normal file
BIN
Hardware/PropIO/Spin/VGA_HiRes_Text.spin
Normal file
Binary file not shown.
920
Hardware/PropIO/Spin/safe_spi.spin
Normal file
920
Hardware/PropIO/Spin/safe_spi.spin
Normal file
@@ -0,0 +1,920 @@
|
||||
{{
|
||||
SPI interface routines for SD & SDHC & MMC cards
|
||||
|
||||
Jonathan "lonesock" Dummer
|
||||
version 0.3.0 2009 July 19
|
||||
|
||||
Using multiblock SPI mode exclusively.
|
||||
|
||||
This is the "SAFE" version...uses
|
||||
* 1 instruction per bit writes
|
||||
* 2 instructions per bit reads
|
||||
|
||||
For the fsrw project:
|
||||
fsrw.sf.net
|
||||
}}
|
||||
|
||||
CON
|
||||
' possible card types
|
||||
type_MMC = 1
|
||||
type_SD = 2
|
||||
type_SDHC = 3
|
||||
|
||||
' Error codes
|
||||
ERR_CARD_NOT_RESET = -1
|
||||
ERR_3v3_NOT_SUPPORTED = -2
|
||||
ERR_OCR_FAILED = -3
|
||||
ERR_BLOCK_NOT_LONG_ALIGNED = -4
|
||||
'...
|
||||
' These errors are for the assembly engine...they are negated inside, and need to be <= 511
|
||||
ERR_ASM_NO_READ_TOKEN = 100
|
||||
ERR_ASM_BLOCK_NOT_WRITTEN = 101
|
||||
' NOTE: errors -128 to -255 are reserved for reporting R1 response errors
|
||||
'...
|
||||
ERR_SPI_ENGINE_NOT_RUNNING = -999
|
||||
ERR_CARD_BUSY_TIMEOUT = -1000
|
||||
|
||||
' SDHC/SD/MMC command set for SPI
|
||||
CMD0 = $40+0 ' GO_IDLE_STATE
|
||||
CMD1 = $40+1 ' SEND_OP_COND (MMC)
|
||||
ACMD41 = $C0+41 ' SEND_OP_COND (SDC)
|
||||
CMD8 = $40+8 ' SEND_IF_COND
|
||||
CMD9 = $40+9 ' SEND_CSD
|
||||
CMD10 = $40+10 ' SEND_CID
|
||||
CMD12 = $40+12 ' STOP_TRANSMISSION
|
||||
CMD13 = $40+13 ' SEND_STATUS
|
||||
ACMD13 = $C0+13 ' SD_STATUS (SDC)
|
||||
CMD16 = $40+16 ' SET_BLOCKLEN
|
||||
CMD17 = $40+17 ' READ_SINGLE_BLOCK
|
||||
CMD18 = $40+18 ' READ_MULTIPLE_BLOCK
|
||||
CMD23 = $40+23 ' SET_BLOCK_COUNT (MMC)
|
||||
ACMD23 = $C0+23 ' SET_WR_BLK_ERASE_COUNT (SDC)
|
||||
CMD24 = $40+24 ' WRITE_BLOCK
|
||||
CMD25 = $40+25 ' WRITE_MULTIPLE_BLOCK
|
||||
CMD55 = $40+55 ' APP_CMD
|
||||
CMD58 = $40+58 ' READ_OCR
|
||||
CMD59 = $40+59 ' CRC_ON_OFF
|
||||
|
||||
' buffer size for my debug cmd log
|
||||
'LOG_SIZE = 256<<1
|
||||
|
||||
{
|
||||
VAR
|
||||
long SPI_engine_cog
|
||||
' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
long SPI_command ' "t", "r", "w", 0 =>done, <0 => error | pin mask
|
||||
long SPI_block_index ' which 512-byte block to read/write | cnt at init
|
||||
long SPI_buffer_address ' where to get/put the data in Hub RAM | unused
|
||||
'}
|
||||
DAT
|
||||
'' I'm placing these variables in a DAT section to make this driver a singleton.
|
||||
'' If for some reason you really need more than one driver (e.g. if you have more
|
||||
'' than a single SD socket), move these back into VAR.
|
||||
SPI_engine_cog long 0
|
||||
' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
SPI_command long 0 ' "t", "r", "w", 0 =>done, <0 => error | unused
|
||||
SPI_block_index long 0 ' which 512-byte block to read/write | cnt at init
|
||||
SPI_buffer_address long 0 ' where to get/put the data in Hub RAM | unused
|
||||
|
||||
{
|
||||
VAR
|
||||
' for debug ONLY
|
||||
byte log_cmd_resp[LOG_SIZE+1]
|
||||
PUB get_log_pointer
|
||||
return @log_cmd_resp
|
||||
'}
|
||||
|
||||
PUB start( basepin )
|
||||
{{
|
||||
This is a compatibility wrapper, and requires that the pins be
|
||||
both consecutive, and in the order DO CLK DI CS.
|
||||
}}
|
||||
return start_explicit( basepin, basepin+1, basepin+2, basepin+3 )
|
||||
|
||||
PUB readblock( block_index, buffer_address )
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
if (buffer_address & 3)
|
||||
abort ERR_BLOCK_NOT_LONG_ALIGNED
|
||||
SPI_block_index := block_index
|
||||
SPI_buffer_address := buffer_address
|
||||
SPI_command := "r"
|
||||
repeat while SPI_command == "r"
|
||||
if SPI_command < 0
|
||||
abort SPI_command
|
||||
|
||||
PUB writeblock( block_index, buffer_address )
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
if (buffer_address & 3)
|
||||
abort ERR_BLOCK_NOT_LONG_ALIGNED
|
||||
SPI_block_index := block_index
|
||||
SPI_buffer_address := buffer_address
|
||||
SPI_command := "w"
|
||||
repeat while SPI_command == "w"
|
||||
if SPI_command < 0
|
||||
abort SPI_command
|
||||
|
||||
PUB get_seconds
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
SPI_command := "t"
|
||||
repeat while SPI_command == "t"
|
||||
' secods are in SPI_block_index, remainder is in SPI_buffer_address
|
||||
return SPI_block_index
|
||||
|
||||
PUB get_milliseconds : ms
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
SPI_command := "t"
|
||||
repeat while SPI_command == "t"
|
||||
' secods are in SPI_block_index, remainder is in SPI_buffer_address
|
||||
ms := SPI_block_index * 1000
|
||||
ms += SPI_buffer_address * 1000 / clkfreq
|
||||
|
||||
PUB start_explicit( DO, CLK, DI, CS ) : card_type | tmp, i
|
||||
{{
|
||||
Do all of the card initialization in SPIN, then hand off the pin
|
||||
information to the assembly cog for hot SPI block R/W action!
|
||||
}}
|
||||
' Start from scratch
|
||||
stop
|
||||
' clear my log buffer
|
||||
{
|
||||
bytefill( @log_cmd_resp, 0, LOG_SIZE+1 )
|
||||
dbg_ptr := @log_cmd_resp
|
||||
dbg_end := dbg_ptr + LOG_SIZE
|
||||
'}
|
||||
' wait ~4 milliseconds
|
||||
waitcnt( 500 + (clkfreq>>8) + cnt )
|
||||
' (start with cog variables, _BEFORE_ loading the cog)
|
||||
pinDO := DO
|
||||
maskDO := |< DO
|
||||
pinCLK := CLK
|
||||
pinDI := DI
|
||||
maskDI := |< DI
|
||||
maskCS := |< CS
|
||||
adrShift := 9 ' block = 512 * index, and 512 = 1<<9
|
||||
' pass the output pin mask via the command register
|
||||
maskAll := maskCS | (|<pinCLK) | maskDI
|
||||
dira |= maskAll
|
||||
' get the card in a ready state: set DI and CS high, send => 74 clocks
|
||||
outa |= maskAll
|
||||
repeat 4096
|
||||
outa[CLK]~~
|
||||
outa[CLK]~
|
||||
' time-hack
|
||||
SPI_block_index := cnt
|
||||
' reset the card
|
||||
tmp~
|
||||
repeat i from 0 to 9
|
||||
if tmp <> 1
|
||||
tmp := send_cmd_slow( CMD0, 0, $95 )
|
||||
if (tmp & 4)
|
||||
' the card said CMD0 ("go idle") was invalid, so we're possibly stuck in read or write mode
|
||||
if i & 1
|
||||
' exit multiblock read mode
|
||||
repeat 4
|
||||
read_32_slow ' these extra clocks are required for some MMC cards
|
||||
send_slow( $FD, 8 ) ' stop token
|
||||
read_32_slow
|
||||
repeat while read_slow <> $FF
|
||||
else
|
||||
' exit multiblock read mode
|
||||
send_cmd_slow( CMD12, 0, $61 )
|
||||
if tmp <> 1
|
||||
' the reset command failed!
|
||||
crash( ERR_CARD_NOT_RESET )
|
||||
' Is this a SD type 2 card?
|
||||
if send_cmd_slow( CMD8, $1AA, $87 ) == 1
|
||||
' Type2 SD, check to see if it's a SDHC card
|
||||
tmp := read_32_slow
|
||||
' check the supported voltage
|
||||
if (tmp & $1FF) <> $1AA
|
||||
crash( ERR_3v3_NOT_SUPPORTED )
|
||||
' try to initialize the type 2 card with the High Capacity bit
|
||||
repeat while send_cmd_slow( ACMD41, |<30, $77 )
|
||||
' the card is initialized, let's read back the High Capacity bit
|
||||
if send_cmd_slow( CMD58, 0, $FD ) <> 0
|
||||
crash( ERR_OCR_FAILED )
|
||||
' get back the data
|
||||
tmp := read_32_slow
|
||||
' check the bit
|
||||
if tmp & |<30
|
||||
card_type := type_SDHC
|
||||
adrShift := 0
|
||||
else
|
||||
card_type := type_SD
|
||||
else
|
||||
' Either a type 1 SD card, or it's MMC, try SD 1st
|
||||
if send_cmd_slow( ACMD41, 0, $E5 ) < 2
|
||||
' this is a type 1 SD card (1 means busy, 0 means done initializing)
|
||||
card_type := type_SD
|
||||
repeat while send_cmd_slow( ACMD41, 0, $E5 )
|
||||
else
|
||||
' mark that it's MMC, and try to initialize
|
||||
card_type := type_MMC
|
||||
repeat while send_cmd_slow( CMD1, 0, $F9 )
|
||||
' some SD or MMC cards may have the wrong block size, set it here
|
||||
send_cmd_slow( CMD16, 512, $15 )
|
||||
' card is mounted, make sure the CRC is turned off
|
||||
send_cmd_slow( CMD59, 0, $91 )
|
||||
' check the status
|
||||
'send_cmd_slow( CMD13, 0, $0D )
|
||||
' done with the SPI bus for now
|
||||
outa |= maskCS
|
||||
' set my counter modes for super fast SPI operation
|
||||
' writing: NCO single-ended mode, output on DI
|
||||
writeMode := (%00100 << 26) | (DI << 0)
|
||||
' reading
|
||||
'readMode := (%11000 << 26) | (DO << 0) | (CLK << 9)
|
||||
' clock
|
||||
'clockLineMode := (%00110 << 26) | (CLK << 0) ' DUTY, 25% duty cycle
|
||||
' clock
|
||||
clockLineMode := (%00100 << 26) | (CLK << 0) ' NCO, 50% duty cycle
|
||||
' how many bytes (8 clocks, >>3) fit into 1/2 of a second (>>1), 4 clocks per instruction (>>2)?
|
||||
N_in8_500ms := clkfreq >> constant(1+2+3)
|
||||
' how long should we wait before auto-exiting any multiblock mode?
|
||||
idle_limit := 125 ' ms, NEVER make this > 1000
|
||||
idle_limit := clkfreq / (1000 / idle_limit) ' convert to counts
|
||||
' Hand off control to the assembly engine's cog
|
||||
bufAdr := @SPI_buffer_address
|
||||
sdAdr := @SPI_block_index
|
||||
SPI_command := 0 ' just make sure it's not 1
|
||||
' start my driver cog and wait till I hear back that it's done
|
||||
SPI_engine_cog := cognew( @SPI_engine_entry, @SPI_command ) + 1
|
||||
if( SPI_engine_cog == 0 )
|
||||
crash( ERR_SPI_ENGINE_NOT_RUNNING )
|
||||
repeat while SPI_command <> -1
|
||||
' and we no longer need to control any pins from here
|
||||
dira &= !maskAll
|
||||
' the return variable is card_type
|
||||
|
||||
PUB release
|
||||
{{
|
||||
I do not want to abort if the cog is not
|
||||
running, as this is called from stop, which
|
||||
is called from start/ [8^)
|
||||
}}
|
||||
if SPI_engine_cog
|
||||
SPI_command := "z"
|
||||
repeat while SPI_command == "z"
|
||||
|
||||
PUB stop
|
||||
{{
|
||||
kill the assembly driver cog.
|
||||
}}
|
||||
release
|
||||
if SPI_engine_cog
|
||||
cogstop( SPI_engine_cog~ - 1 )
|
||||
|
||||
PRI crash( abort_code )
|
||||
{{
|
||||
In case of Bad Things(TM) happening,
|
||||
exit as gracefully as possible.
|
||||
}}
|
||||
' and we no longer need to control any pins from here
|
||||
dira &= !maskAll
|
||||
' and report our error
|
||||
abort abort_code
|
||||
|
||||
PRI send_cmd_slow( cmd, val, crc ) : reply | time_stamp
|
||||
{{
|
||||
Send down a command and return the reply.
|
||||
Note: slow is an understatement!
|
||||
Note: this uses the assembly DAT variables for pin IDs,
|
||||
which means that if you run this multiple times (say for
|
||||
multiple SD cards), these values will change for each one.
|
||||
But this is OK as all of these functions will be called
|
||||
during the initialization only, before the PASM engine is
|
||||
running.
|
||||
}}
|
||||
' if this is an application specific command, handle it
|
||||
if (cmd & $80)
|
||||
' ACMD<n> is the command sequense of CMD55-CMD<n>
|
||||
cmd &= $7F
|
||||
reply := send_cmd_slow( CMD55, 0, $65 )
|
||||
if (reply > 1)
|
||||
return reply
|
||||
' the CS line needs to go low during this operation
|
||||
outa |= maskCS
|
||||
outa &= !maskCS
|
||||
' give the card a few cocks to finish whatever it was doing
|
||||
read_32_slow
|
||||
' send the command byte
|
||||
send_slow( cmd, 8 )
|
||||
' send the value long
|
||||
send_slow( val, 32 )
|
||||
' send the CRC byte
|
||||
send_slow( crc, 8 )
|
||||
' is this a CMD12?, if so, stuff byte
|
||||
if cmd == CMD12
|
||||
read_slow
|
||||
' read back the response (spec declares 1-8 reads max for SD, MMC is 0-8)
|
||||
time_stamp := 9
|
||||
repeat
|
||||
reply := read_slow
|
||||
while( reply & $80 ) and ( time_stamp-- )
|
||||
' done, and 'reply' is already pre-loaded
|
||||
{
|
||||
if dbg_ptr < (dbg_end-1)
|
||||
byte[dbg_ptr++] := cmd
|
||||
byte[dbg_ptr++] := reply
|
||||
if (cmd&63) == 13
|
||||
' get the second byte
|
||||
byte[dbg_ptr++] := cmd
|
||||
byte[dbg_ptr++] := read_slow
|
||||
'}
|
||||
|
||||
PRI send_slow( value, bits_to_send )
|
||||
value ><= bits_to_send
|
||||
repeat bits_to_send
|
||||
outa[pinCLK]~
|
||||
outa[pinDI] := value
|
||||
value >>= 1
|
||||
outa[pinCLK]~~
|
||||
|
||||
PRI read_32_slow : r
|
||||
repeat 4
|
||||
r <<= 8
|
||||
r |= read_slow
|
||||
|
||||
PRI read_slow : r
|
||||
{{
|
||||
Read back 8 bits from the card
|
||||
}}
|
||||
' we need the DI line high so a read can occur
|
||||
outa[pinDI]~~
|
||||
' get 8 bits (remember, r is initialized to 0 by SPIN)
|
||||
repeat 8
|
||||
outa[pinCLK]~
|
||||
outa[pinCLK]~~
|
||||
r += r + ina[pinDO]
|
||||
' error check
|
||||
if( (cnt - SPI_block_index) > (clkfreq << 2) )
|
||||
crash( ERR_CARD_BUSY_TIMEOUT )
|
||||
|
||||
DAT
|
||||
{{
|
||||
This is the assembly engine for doing fast block
|
||||
reads and writes. This is *ALL* it does!
|
||||
}}
|
||||
ORG 0
|
||||
SPI_engine_entry
|
||||
' Counter A drives data out
|
||||
mov ctra,writeMode
|
||||
' Counter B will always drive my clock line
|
||||
mov ctrb,clockLineMode
|
||||
' set our output pins to match the pin mask
|
||||
mov dira,maskAll
|
||||
' handshake that we now control the pins
|
||||
neg user_request,#1
|
||||
wrlong user_request,par
|
||||
' start my seconds' counter here
|
||||
mov last_time,cnt
|
||||
|
||||
waiting_for_command
|
||||
' update my seconds counter, but also track the idle
|
||||
' time so we can to release the card after timeout.
|
||||
call #handle_time
|
||||
' read the command, and make sure it's from the user (> 0)
|
||||
rdlong user_request,par
|
||||
cmps user_request,#0 wz,wc
|
||||
if_be jmp #waiting_for_command
|
||||
' handle our card based commands
|
||||
cmp user_request,#"r" wz
|
||||
if_z jmp #read_ahead
|
||||
cmp user_request,#"w" wz
|
||||
if_z jmp #write_behind
|
||||
cmp user_request,#"z" wz
|
||||
if_z jmp #release_card
|
||||
' time requests are handled differently
|
||||
cmp user_request,#"t" wz ' time
|
||||
if_z wrlong seconds,sdAdr ' seconds goes into the SD index register
|
||||
if_z wrlong dtime,bufAdr ' the remainder goes into the buffer address register
|
||||
' in all other cases, clear the user's request
|
||||
mov user_request,#0
|
||||
wrlong user_request,par
|
||||
jmp #waiting_for_command
|
||||
|
||||
|
||||
release_card
|
||||
mov user_cmd,#"z" ' request a release
|
||||
neg lastIndexPlus,#1 ' reset the last block index
|
||||
neg user_idx,#1 ' and make this match it
|
||||
call #handle_command
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
jmp #waiting_for_command
|
||||
|
||||
read_ahead
|
||||
rdlong user_idx,sdAdr
|
||||
' if the correct block is not already loaded, load it
|
||||
mov tmp1,user_idx
|
||||
add tmp1,#1
|
||||
cmp tmp1,lastIndexPlus wz
|
||||
if_z cmp lastCommand,#"r" wz
|
||||
if_z jmp #:get_on_with_it
|
||||
mov user_cmd,#"r"
|
||||
call #handle_command
|
||||
:get_on_with_it
|
||||
' copy the data up into Hub RAM
|
||||
movi transfer_long,#%000010_000 'set to wrlong
|
||||
call #hub_cog_transfer
|
||||
' signify that the data is ready, Spin can continue
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
' request the next block
|
||||
mov user_cmd,#"r"
|
||||
add user_idx,#1
|
||||
call #handle_command
|
||||
' done
|
||||
jmp #waiting_for_command
|
||||
|
||||
write_behind
|
||||
rdlong user_idx,sdAdr
|
||||
' copy data in from Hub RAM
|
||||
movi transfer_long,#%000010_001 'set to rdlong
|
||||
call #hub_cog_transfer
|
||||
' signify that we have the data, Spin can continue
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
' write out the block
|
||||
mov user_cmd,#"w"
|
||||
call #handle_command
|
||||
' done
|
||||
jmp #waiting_for_command
|
||||
|
||||
{{
|
||||
Set user_cmd and user_idx before calling this
|
||||
}}
|
||||
handle_command
|
||||
' Can we stay in the old mode? (address = old_address+1) && (old mode == new_mode)
|
||||
cmp lastIndexPlus,user_idx wz
|
||||
if_z cmp user_cmd,lastCommand wz
|
||||
if_z jmp #:execute_block_command
|
||||
' we fell through, must exit the old mode! (except if the old mode was "release")
|
||||
cmp lastCommand,#"w" wz
|
||||
if_z call #stop_mb_write
|
||||
cmp lastCommand,#"r" wz
|
||||
if_z call #stop_mb_read
|
||||
' and start up the new mode!
|
||||
cmp user_cmd,#"w" wz
|
||||
if_z call #start_mb_write
|
||||
cmp user_cmd,#"r" wz
|
||||
if_z call #start_mb_read
|
||||
cmp user_cmd,#"z" wz
|
||||
if_z call #release_DO
|
||||
:execute_block_command
|
||||
' track the (new) last index and command
|
||||
mov lastIndexPlus,user_idx
|
||||
add lastIndexPlus,#1
|
||||
mov lastCommand,user_cmd
|
||||
' do the block read or write or terminate!
|
||||
cmp user_cmd,#"w" wz
|
||||
if_z call #write_single_block
|
||||
cmp user_cmd,#"r" wz
|
||||
if_z call #read_single_block
|
||||
cmp user_cmd,#"z" wz
|
||||
if_z mov user_cmd,#0
|
||||
' done
|
||||
handle_command_ret
|
||||
ret
|
||||
|
||||
{=== these PASM functions get me in and out of multiblock mode ===}
|
||||
release_DO
|
||||
' we're already out of multiblock mode, so
|
||||
' deselect the card and send out some clocks
|
||||
or outa,maskCS
|
||||
call #in8
|
||||
call #in8
|
||||
' if you are using pull-up resistors, and need all
|
||||
' lines tristated, then uncomment the following line.
|
||||
' for Cluso99
|
||||
'mov dira,#0
|
||||
release_DO_ret
|
||||
ret
|
||||
|
||||
start_mb_read
|
||||
movi block_cmd,#CMD18<<1
|
||||
call #send_SPI_command_fast
|
||||
start_mb_read_ret
|
||||
ret
|
||||
|
||||
stop_mb_read
|
||||
movi block_cmd,#CMD12<<1
|
||||
call #send_SPI_command_fast
|
||||
call #busy_fast
|
||||
stop_mb_read_ret
|
||||
ret
|
||||
|
||||
start_mb_write
|
||||
movi block_cmd,#CMD25<<1
|
||||
call #send_SPI_command_fast
|
||||
start_mb_write_ret
|
||||
ret
|
||||
|
||||
stop_mb_write
|
||||
call #busy_fast
|
||||
' only some cards need these extra clocks
|
||||
mov tmp1,#16
|
||||
:loopity
|
||||
call #in8
|
||||
djnz tmp1,#:loopity
|
||||
' done with hack
|
||||
movi phsa,#$FD<<1
|
||||
call #out8
|
||||
call #in8 ' stuff byte
|
||||
call #busy_fast
|
||||
stop_mb_write_ret
|
||||
ret
|
||||
|
||||
send_SPI_command_fast
|
||||
' make sure we have control of the output lines
|
||||
mov dira,maskAll
|
||||
' make sure the CS line transitions low
|
||||
or outa,maskCS
|
||||
andn outa,maskCS
|
||||
' 8 clocks
|
||||
call #in8
|
||||
' send the data
|
||||
mov phsa,block_cmd ' do which ever block command this is (already in the top 8 bits)
|
||||
call #out8 ' write the byte
|
||||
mov phsa,user_idx ' read in the desired block index
|
||||
shl phsa,adrShift ' this will multiply by 512 (bytes/sector) for MMC and SD
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
' bogus CRC value
|
||||
call #in8 ' in8 looks like out8 with $FF
|
||||
' CMD12 requires a stuff byte
|
||||
shr block_cmd,#24
|
||||
cmp block_cmd,#CMD12 wz
|
||||
if_z call #in8 ' 8 clocks
|
||||
' get the response
|
||||
mov tmp1,#9
|
||||
:cmd_response
|
||||
call #in8
|
||||
test readback,#$80 wc,wz
|
||||
if_c djnz tmp1,#:cmd_response
|
||||
if_nz neg user_cmd,readback
|
||||
' done
|
||||
send_SPI_command_fast_ret
|
||||
ret
|
||||
|
||||
|
||||
busy_fast
|
||||
mov tmp1,N_in8_500ms
|
||||
:still_busy
|
||||
call #in8
|
||||
cmp readback,#$FF wz
|
||||
if_nz djnz tmp1,#:still_busy
|
||||
busy_fast_ret
|
||||
ret
|
||||
|
||||
|
||||
out8
|
||||
andn outa,maskDI
|
||||
'movi phsb,#%11_0000000
|
||||
mov phsb,#0
|
||||
movi frqb,#%01_0000000
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
mov frqb,#0
|
||||
' don't shift out the final bit...already sent, but be aware
|
||||
' of this when sending consecutive bytes (send_cmd, for e.g.)
|
||||
out8_ret
|
||||
ret
|
||||
|
||||
{
|
||||
in8
|
||||
or outa,maskDI
|
||||
mov ctra,readMode
|
||||
' Start my clock
|
||||
mov frqa,#1<<7
|
||||
mov phsa,#0
|
||||
movi phsb,#%11_0000000
|
||||
movi frqb,#%01_0000000
|
||||
' keep reading in my value, one bit at a time! (Kuneko - "Wh)
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
mov frqb,#0 ' stop the clock
|
||||
mov readback,phsa
|
||||
mov frqa,#0
|
||||
mov ctra,writeMode
|
||||
in8_ret
|
||||
ret
|
||||
}
|
||||
in8
|
||||
neg phsa,#1' DI high
|
||||
mov readback,#0
|
||||
' set up my clock, and start it
|
||||
movi phsb,#%011_000000
|
||||
movi frqb,#%001_000000
|
||||
' keep reading in my value
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
mov frqb,#0 ' stop the clock
|
||||
rcl readback,#1
|
||||
mov phsa,#0 'DI low
|
||||
in8_ret
|
||||
ret
|
||||
|
||||
|
||||
' this is called more frequently than 1 Hz, and
|
||||
' is only called when the user command is 0.
|
||||
handle_time
|
||||
mov tmp1,cnt ' get the current timestamp
|
||||
add idle_time,tmp1 ' add the current time to my idle time counter
|
||||
sub idle_time,last_time ' subtract the last time from my idle counter (hence delta)
|
||||
add dtime,tmp1 ' add to my accumulator,
|
||||
sub dtime,last_time ' and subtract the old (adding delta)
|
||||
mov last_time,tmp1 ' update my "last timestamp"
|
||||
rdlong tmp1,#0 ' what is the clock frequency?
|
||||
cmpsub dtime,tmp1 wc ' if I have more than a second in my accumulator
|
||||
addx seconds,#0 ' then add it to "seconds"
|
||||
' this part is to auto-release the card after a timeout
|
||||
cmp idle_time,idle_limit wz,wc
|
||||
if_b jmp #handle_time_ret ' don't clear if we haven't hit the limit
|
||||
mov user_cmd,#"z" ' we can't overdo it, the command handler makes sure
|
||||
neg lastIndexPlus,#1 ' reset the last block index
|
||||
neg user_idx,#1 ' and make this match it
|
||||
call #handle_command ' release the card, but don't mess with the user's request register
|
||||
handle_time_ret
|
||||
ret
|
||||
|
||||
hub_cog_transfer
|
||||
' setup for all 4 passes
|
||||
mov ctrb,clockXferMode
|
||||
mov frqb,#1
|
||||
rdlong buf_ptr,bufAdr
|
||||
mov ops_left,#4
|
||||
movd transfer_long,#speed_buf
|
||||
four_transfer_passes
|
||||
' sync to the Hub RAM access
|
||||
rdlong tmp1,tmp1
|
||||
' how many long to move on this pass? (512 bytes / 4)longs / 4 passes
|
||||
mov tmp1,#(512 / 4 / 4)
|
||||
' get my starting address right (phsb is incremented 1 per clock, so 16 each Hub access)
|
||||
mov phsb,buf_ptr
|
||||
' write the longs, stride 4...low 2 bits of phsb are ignored
|
||||
transfer_long
|
||||
rdlong 0-0,phsb
|
||||
add transfer_long,incDest4
|
||||
djnz tmp1,#transfer_long
|
||||
' go back to where I started, but advanced 1 long
|
||||
sub transfer_long,decDestNminus1
|
||||
' offset my Hub pointer by one long per pass
|
||||
add buf_ptr,#4
|
||||
' do all 4 passes
|
||||
djnz ops_left,#four_transfer_passes
|
||||
' restore the counter mode
|
||||
mov frqb,#0
|
||||
mov phsb,#0
|
||||
mov ctrb,clockLineMode
|
||||
hub_cog_transfer_ret
|
||||
ret
|
||||
|
||||
|
||||
read_single_block
|
||||
' where am I sending the data?
|
||||
movd :store_read_long,#speed_buf
|
||||
mov ops_left,#128
|
||||
' wait until the card is ready
|
||||
mov tmp1,N_in8_500ms
|
||||
:get_resp
|
||||
call #in8
|
||||
cmp readback,#$FE wz
|
||||
if_nz djnz tmp1,#:get_resp
|
||||
if_nz neg user_cmd,#ERR_ASM_NO_READ_TOKEN
|
||||
if_nz jmp #read_single_block_ret
|
||||
' set DI high
|
||||
neg phsa,#1
|
||||
' read the data
|
||||
mov ops_left,#128
|
||||
:read_loop
|
||||
mov tmp1,#4
|
||||
movi phsb,#%011_000000
|
||||
:in_byte
|
||||
' Start my clock
|
||||
movi frqb,#%001_000000
|
||||
' keep reading in my value, BACKWARDS! (Brilliant idea by Tom Rokicki!)
|
||||
test maskDO,ina wc
|
||||
rcl readback,#8
|
||||
test maskDO,ina wc
|
||||
muxc readback,#2
|
||||
test maskDO,ina wc
|
||||
muxc readback,#4
|
||||
test maskDO,ina wc
|
||||
muxc readback,#8
|
||||
test maskDO,ina wc
|
||||
muxc readback,#16
|
||||
test maskDO,ina wc
|
||||
muxc readback,#32
|
||||
test maskDO,ina wc
|
||||
muxc readback,#64
|
||||
test maskDO,ina wc
|
||||
mov frqb,#0 ' stop the clock
|
||||
muxc readback,#128
|
||||
' go back for more
|
||||
djnz tmp1,#:in_byte
|
||||
' make it...NOT backwards [8^)
|
||||
rev readback,#0
|
||||
:store_read_long
|
||||
mov 0-0,readback ' due to some counter weirdness, we need this mov
|
||||
add :store_read_long,const512
|
||||
djnz ops_left,#:read_loop
|
||||
|
||||
' set DI low
|
||||
mov phsa,#0
|
||||
|
||||
' now read 2 trailing bytes (CRC)
|
||||
call #in8 ' out8 is 2x faster than in8
|
||||
call #in8 ' and I'm not using the CRC anyway
|
||||
' give an extra 8 clocks in case we pause for a long time
|
||||
call #in8 ' in8 looks like out8($FF)
|
||||
|
||||
' all done successfully
|
||||
mov idle_time,#0
|
||||
mov user_cmd,#0
|
||||
read_single_block_ret
|
||||
ret
|
||||
|
||||
write_single_block
|
||||
' where am I getting the data? (all 512 bytes / 128 longs of it?)
|
||||
movs :write_loop,#speed_buf
|
||||
' read in 512 bytes (128 longs) from Hub RAM and write it to the card
|
||||
mov ops_left,#128
|
||||
' just hold your horses
|
||||
call #busy_fast
|
||||
' $FC for multiblock, $FE for single block
|
||||
movi phsa,#$FC<<1
|
||||
call #out8
|
||||
mov phsb,#0 ' make sure my clock accumulator is right
|
||||
'movi phsb,#%11_0000000
|
||||
:write_loop
|
||||
' read 4 bytes
|
||||
mov phsa,speed_buf
|
||||
add :write_loop,#1
|
||||
' a long in LE order is DCBA
|
||||
rol phsa,#24 ' move A7 into position, so I can do the swizzled version
|
||||
movi frqb,#%010000000 ' start the clock (remember A7 is already in place)
|
||||
rol phsa,#1 ' A7 is going out, at the end of this instr, A6 is in place
|
||||
rol phsa,#1 ' A5
|
||||
rol phsa,#1 ' A4
|
||||
rol phsa,#1 ' A3
|
||||
rol phsa,#1 ' A2
|
||||
rol phsa,#1 ' A1
|
||||
rol phsa,#1 ' A0
|
||||
rol phsa,#17 ' B7
|
||||
rol phsa,#1 ' B6
|
||||
rol phsa,#1 ' B5
|
||||
rol phsa,#1 ' B4
|
||||
rol phsa,#1 ' B3
|
||||
rol phsa,#1 ' B2
|
||||
rol phsa,#1 ' B1
|
||||
rol phsa,#1 ' B0
|
||||
rol phsa,#17 ' C7
|
||||
rol phsa,#1 ' C6
|
||||
rol phsa,#1 ' C5
|
||||
rol phsa,#1 ' C4
|
||||
rol phsa,#1 ' C3
|
||||
rol phsa,#1 ' C2
|
||||
rol phsa,#1 ' C1
|
||||
rol phsa,#1 ' C0
|
||||
rol phsa,#17 ' D7
|
||||
rol phsa,#1 ' D6
|
||||
rol phsa,#1 ' D5
|
||||
rol phsa,#1 ' D4
|
||||
rol phsa,#1 ' D3
|
||||
rol phsa,#1 ' D2
|
||||
rol phsa,#1 ' D1
|
||||
rol phsa,#1 ' D0 will be in place _after_ this instruction
|
||||
mov frqb,#0 ' shuts the clock off, _after_ this instruction
|
||||
djnz ops_left,#:write_loop
|
||||
' write out my two (bogus, using $FF) CRC bytes
|
||||
call #in8
|
||||
call #in8
|
||||
' now read response (I need this response, so can't spoof using out8)
|
||||
call #in8
|
||||
and readback,#$1F
|
||||
cmp readback,#5 wz
|
||||
if_z mov user_cmd,#0 ' great
|
||||
if_nz neg user_cmd,#ERR_ASM_BLOCK_NOT_WRITTEN ' oops
|
||||
' send out another 8 clocks
|
||||
call #in8
|
||||
' all done
|
||||
mov idle_time,#0
|
||||
write_single_block_ret
|
||||
ret
|
||||
|
||||
|
||||
{=== Assembly Interface Variables ===}
|
||||
pinDO long 0 ' pin is controlled by a counter
|
||||
pinCLK long 0 ' pin is controlled by a counter
|
||||
pinDI long 0 ' pin is controlled by a counter
|
||||
maskDO long 0 ' mask for reading the DO line from the card
|
||||
maskDI long 0 ' mask for setting the pin high while reading
|
||||
maskCS long 0 ' mask = (1<<pin), and is controlled directly
|
||||
maskAll long 0
|
||||
adrShift long 9 ' will be 0 for SDHC, 9 for MMC & SD
|
||||
bufAdr long 0 ' where in Hub RAM is the buffer to copy to/from?
|
||||
sdAdr long 0 ' where on the SD card does it read/write?
|
||||
writeMode long 0 ' the counter setup in NCO single ended, clocking data out on pinDI
|
||||
'clockOutMode long 0 ' the counter setup in NCO single ended, driving the clock line on pinCLK
|
||||
N_in8_500ms long 1_000_000 ' used for timeout checking in PASM
|
||||
'readMode long 0
|
||||
clockLineMode long 0
|
||||
clockXferMode long %11111 << 26
|
||||
const512 long 512
|
||||
const1024 long 1024
|
||||
incDest4 long 4 << 9
|
||||
decDestNminus1 long (512 / 4 - 1) << 9
|
||||
|
||||
{=== Initialized PASM Variables ===}
|
||||
seconds long 0
|
||||
dtime long 0
|
||||
idle_time long 0
|
||||
idle_limit long 0
|
||||
|
||||
{=== Multiblock State Machine ===}
|
||||
lastIndexPlus long -1 ' state handler will check against lastIndexPlus, which will not have been -1
|
||||
lastCommand long 0 ' this will never be the last command.
|
||||
|
||||
{=== Debug Logging Pointers ===}
|
||||
{
|
||||
dbg_ptr long 0
|
||||
dbg_end long 0
|
||||
'}
|
||||
|
||||
{=== Assembly Scratch Variables ===}
|
||||
ops_left res 1 ' used as a counter for bytes, words, longs, whatever (start w/ # byte clocks out)
|
||||
readback res 1 ' all reading from the card goes through here
|
||||
tmp1 res 1 ' this may get used in all subroutines...don't use except in lowest
|
||||
user_request res 1 ' the main command variable, read in from Hub: "r"-read single, "w"-write single
|
||||
user_cmd res 1 ' used internally to handle actual commands to be executed
|
||||
user_idx res 1 ' the pointer to the Hub RAM where the data block is/goes
|
||||
block_cmd res 1 ' one of the SD/MMC command codes, no app-specific allowed
|
||||
buf_ptr res 1 ' moving pointer to the Hub RAM buffer
|
||||
last_time res 1 ' tracking the timestamp
|
||||
|
||||
{{
|
||||
496 longs is my total available space in the cog,
|
||||
and I want 128 longs for eventual use as one 512-
|
||||
byte buffer. This gives me a total of 368 longs
|
||||
to use for umount, and a readblock and writeblock
|
||||
for both Hub RAM and Cog buffers.
|
||||
}}
|
||||
speed_buf res 128 ' 512 bytes to be used for read-ahead / write-behind
|
||||
|
||||
'fit 467
|
||||
FIT 496
|
||||
|
||||
'' MIT LICENSE
|
||||
{{
|
||||
' Permission is hereby granted, free of charge, to any person obtaining
|
||||
' a copy of this software and associated documentation files
|
||||
' (the "Software"), to deal in the Software without restriction,
|
||||
' including without limitation the rights to use, copy, modify, merge,
|
||||
' publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
' and to permit persons to whom the Software is furnished to do so,
|
||||
' subject to the following conditions:
|
||||
'
|
||||
' The above copyright notice and this permission notice shall be included
|
||||
' in all copies or substantial portions of the Software.
|
||||
'
|
||||
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
' EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
' MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
' IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
' CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
' TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
' SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
}}
|
||||
BIN
Hardware/PropIO2/PropIO2.eeprom
Normal file
BIN
Hardware/PropIO2/PropIO2.eeprom
Normal file
Binary file not shown.
1
Hardware/PropIO2/Spin/E555_SPKEngine.spin
Normal file
1
Hardware/PropIO2/Spin/E555_SPKEngine.spin
Normal file
@@ -0,0 +1 @@
|
||||
{{
|
||||
BIN
Hardware/PropIO2/Spin/Keyboard.spin
Normal file
BIN
Hardware/PropIO2/Spin/Keyboard.spin
Normal file
Binary file not shown.
BIN
Hardware/PropIO2/Spin/Parallax Serial Terminal.spin
Normal file
BIN
Hardware/PropIO2/Spin/Parallax Serial Terminal.spin
Normal file
Binary file not shown.
Binary file not shown.
704
Hardware/PropIO2/Spin/VGA_1024.spin
Normal file
704
Hardware/PropIO2/Spin/VGA_1024.spin
Normal file
@@ -0,0 +1,704 @@
|
||||
'' VGA_1024.spin
|
||||
''
|
||||
'' MODIFIED BY VINCE BRIEL FOR POCKETERM FEATURES
|
||||
'' MODIIFED BY JEFF LEDGER / AKA OLDBITCOLLECTOR
|
||||
''
|
||||
|
||||
CON
|
||||
cols = 80 '128 ' number of screen columns
|
||||
lcols = cols / 4 ' number of long in columns
|
||||
rows = 40 '64 ' number of screen rows
|
||||
chars = rows*cols ' number of screen characters
|
||||
esc = $CB ' keyboard esc char
|
||||
rowsnow = 36 ' adjusted for split screen effect
|
||||
maxChars = rowsnow*cols ' adjusted value for split screen effect
|
||||
lastChar = maxChars / 4 ' last screen position in longs adjusted for split
|
||||
lastLine = (rowsnow - 1) * cols ' character position of last row
|
||||
cols1 = 81 ' adjusted value for 80th character
|
||||
TURQUOISE = $29
|
||||
|
||||
OBJ
|
||||
vga : "vga_Hires_Text"
|
||||
|
||||
VAR
|
||||
byte screen[chars] ' screen character buffer
|
||||
byte tmpl[cols] ' temporary line buffer
|
||||
word colors[rows] ' color specs for each screen row (see ColorPtr description above)
|
||||
byte cursor[6] ' cursor info array (see CursorPtr description above)
|
||||
long sync, loc, xloc, yloc ' sync used by VGA routine, others are local screen pointers
|
||||
long kbdreq ' global val of kbdflag
|
||||
long BR[8]
|
||||
long Brate
|
||||
byte inverse
|
||||
byte invs
|
||||
byte state ' Current state of state machine
|
||||
word pos ' Current Position on the screen
|
||||
word oldpos ' Previous location of cursor before update
|
||||
word regionTop, regionBot ' Scroll region top/bottom
|
||||
long arg0 ' First argument of escape sequence
|
||||
long arg1 ' Second argument of escape sequence
|
||||
byte lastc ' Last displayed char
|
||||
word statpos
|
||||
long vgabasepin
|
||||
|
||||
PUB start(BasePin) | i, char
|
||||
vgabasepin := BasePin
|
||||
|
||||
''init screen colors to gold on blue
|
||||
repeat i from 0 to rows - 1
|
||||
colors[i] := $08F0 '$2804 (if you want cyan on blue)
|
||||
|
||||
''init cursor attributes
|
||||
cursor[2] := %110 ' init cursor to underscore with slow blink
|
||||
BR[0]:=300
|
||||
BR[1]:=1200
|
||||
BR[2]:=2400
|
||||
BR[3]:=4800
|
||||
BR[4]:=9600
|
||||
BR[5]:=19200
|
||||
BR[6]:=38400
|
||||
BR[7]:=57600
|
||||
BR[8]:=115200
|
||||
xloc := cursor[0] := 0
|
||||
yloc := cursor[1] := 0
|
||||
loc := xloc + yloc*cols
|
||||
|
||||
pos := 0
|
||||
regionTop := 0
|
||||
regionBot := 35 * cols
|
||||
state := 0
|
||||
statpos := 37 * cols
|
||||
|
||||
PUB vidon
|
||||
if (!vga.start(vgabasepin, @screen, @colors, @cursor, @sync))
|
||||
return false
|
||||
|
||||
waitcnt(clkfreq * 1 + cnt) 'wait 1 second for cogs to start
|
||||
|
||||
|
||||
PUB vidoff
|
||||
vga.stop
|
||||
|
||||
|
||||
PUB inv(c)
|
||||
inverse:=c
|
||||
|
||||
PUB color(colorVal) | i
|
||||
repeat i from 0 to rows - 1
|
||||
colors[i] := $0000 | colorVal
|
||||
|
||||
PUB cursorset(c) | i
|
||||
i:=%000
|
||||
if c == 1
|
||||
i:= %001
|
||||
if c == 2
|
||||
i:= %010
|
||||
if c == 3
|
||||
i:= %011
|
||||
if c == 4
|
||||
i:= %101
|
||||
if c == 5
|
||||
i:= %110
|
||||
if c == 6
|
||||
i:= %111
|
||||
if c == 7
|
||||
i:= %000
|
||||
cursor[2] := i
|
||||
|
||||
PUB bin(value, digits)
|
||||
|
||||
'' Print a binary number, specify number of digits
|
||||
|
||||
repeat while digits > 32
|
||||
outc("0")
|
||||
digits--
|
||||
|
||||
value <<= 32 - digits
|
||||
|
||||
repeat digits
|
||||
outc((value <-= 1) & 1 + "0")
|
||||
|
||||
|
||||
PUB clrbtm(ColorVal) | i
|
||||
repeat i from 36 to rows - 1 'was 35
|
||||
colors[i] := $0000 + ColorVal
|
||||
|
||||
PUB cls1(c,screencolor,pcport,ascii,CR) | i,x,y
|
||||
|
||||
longfill(@screen[0], $20202020, chars / 4)
|
||||
|
||||
clrbtm(TURQUOISE)
|
||||
|
||||
inverse := 1
|
||||
|
||||
statprint(36,0, string(" N8VEM PropIO V2 | RomWBW v0.94"))
|
||||
inverse := 0
|
||||
statprint(37,0, string(" "))
|
||||
statprint(38,0, string(" "))
|
||||
statprint(39,0, string(" "))
|
||||
|
||||
|
||||
{{
|
||||
x :=xloc
|
||||
y := yloc
|
||||
invs := inverse
|
||||
''clrbtm(TURQUOISE)
|
||||
longfill(@screen, $20202020, chars/4)
|
||||
xloc := 0
|
||||
yloc :=0
|
||||
loc := xloc + yloc*cols
|
||||
repeat 80
|
||||
outc(32)
|
||||
xloc := 0
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" propIO V 0.91 "))
|
||||
inverse := 0
|
||||
str(string("Baud Rate: "))
|
||||
i:= BR[6]
|
||||
dec(i)
|
||||
str(string(" "))
|
||||
xloc := 18
|
||||
loc := xloc + yloc*cols
|
||||
str(string("Color "))
|
||||
str(string("PC Port: "))
|
||||
if pcport == 1
|
||||
str(string("OFF "))
|
||||
if pcport == 0
|
||||
str(string("ON "))
|
||||
str(string(" Force 7 bit: "))
|
||||
if ascii == 0
|
||||
str(string("NO "))
|
||||
if ascii == 1
|
||||
str(string("YES "))
|
||||
str(string(" Cursor CR W/LF: "))
|
||||
if CR == 1
|
||||
str(string("YES"))
|
||||
if CR == 0
|
||||
str(string("NO "))
|
||||
outc(13)
|
||||
outc(10)
|
||||
|
||||
inverse:=1
|
||||
xloc := 6
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F1"))
|
||||
xloc := 19
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F2"))
|
||||
xloc := 30
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F3"))
|
||||
xloc := 46
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F4"))
|
||||
xloc := 58
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F5"))
|
||||
xloc := 70
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F6"))
|
||||
inverse := invs
|
||||
xloc := cursor[0] := x 'right & left was 0
|
||||
yloc := cursor[1] := y 'from top was 1
|
||||
loc := xloc + yloc*cols
|
||||
}}
|
||||
|
||||
PUB clsupdate(c,screencolor,PCPORT,ascii,CR) | i,x,y,locold
|
||||
|
||||
invs := inverse
|
||||
locold := loc
|
||||
x := xloc
|
||||
y := yloc
|
||||
''(TURQUOISE)
|
||||
xloc := 0
|
||||
yloc :=36
|
||||
loc := xloc + yloc*cols
|
||||
inverse := 1
|
||||
str(string(" propIO V 0.81 "))
|
||||
inverse := 0
|
||||
xloc := 0
|
||||
yloc :=37
|
||||
loc := xloc + yloc*cols
|
||||
str(string("Baud Rate: "))
|
||||
i:= BR[6]
|
||||
dec(i)
|
||||
str(string(" "))
|
||||
xloc := 18
|
||||
loc := xloc + yloc*cols
|
||||
|
||||
str(string("Color "))
|
||||
str(string("PC Port: "))
|
||||
if pcport == 1
|
||||
str(string("OFF "))
|
||||
if pcport == 0
|
||||
str(string("ON "))
|
||||
str(string(" Force 7 bit: "))
|
||||
if ascii == 0
|
||||
str(string("NO "))
|
||||
if ascii == 1
|
||||
str(string("YES "))
|
||||
str(string(" Cursor CR W/LF: "))
|
||||
if CR == 1
|
||||
str(string("YES"))
|
||||
if CR == 0
|
||||
str(string("NO "))
|
||||
xloc := 0
|
||||
yloc :=38
|
||||
loc := xloc + yloc*cols
|
||||
inverse:=1
|
||||
xloc := 6
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F1"))
|
||||
xloc := 19
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F2"))
|
||||
xloc := 30
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F3"))
|
||||
xloc := 46
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F4"))
|
||||
xloc := 58
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F5"))
|
||||
xloc := 70
|
||||
loc := xloc + yloc*cols
|
||||
str(string("F6"))
|
||||
inverse := invs
|
||||
xloc := cursor[0] := x
|
||||
yloc := cursor[1] := y
|
||||
' loc := xloc + yloc*cols
|
||||
loc := locold
|
||||
|
||||
PUB dec(value) | i
|
||||
|
||||
'' Print a decimal number
|
||||
|
||||
if value < 0
|
||||
-value
|
||||
outc("-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if value => i
|
||||
outc(value/i + "0")
|
||||
value //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
outc("0")
|
||||
i /= 10
|
||||
|
||||
PUB hex(value, digits)
|
||||
|
||||
'' Print a hexadecimal number, specify number of digits
|
||||
|
||||
repeat while digits > 8
|
||||
outc("0")
|
||||
digits--
|
||||
|
||||
value <<= (8 - digits) << 2
|
||||
|
||||
repeat digits
|
||||
outc(lookupz((value <-= 4) & $f : "0".."9", "A".."F"))
|
||||
|
||||
|
||||
PUB str(string_ptr)
|
||||
|
||||
'' Print a zero terminated string
|
||||
|
||||
repeat strsize(string_ptr)
|
||||
process_char(byte[string_ptr++])
|
||||
|
||||
PUB statprint(r, c, str1) | x, ptr
|
||||
|
||||
ptr := r * cols + c
|
||||
repeat x from 0 to STRSIZE(str1) - 1
|
||||
putc(ptr++, BYTE[str1 + x])
|
||||
|
||||
PUB statnum(r, c, num1) | i, ptr
|
||||
|
||||
ptr := r * cols + c
|
||||
|
||||
if num1 < 0
|
||||
-num1
|
||||
putc(ptr++,"-")
|
||||
|
||||
i := 1_000_000_000
|
||||
|
||||
repeat 10
|
||||
if num1 => i
|
||||
putc(ptr++, (num1/i +"0"))
|
||||
num1 //= i
|
||||
result~~
|
||||
elseif result or i == 1
|
||||
putc(ptr++, "0")
|
||||
i /= 10
|
||||
|
||||
PUB putc(position, c)
|
||||
if inverse
|
||||
c |= $80
|
||||
screen[position] := c
|
||||
|
||||
PUB cls
|
||||
longfill (@screen, $20202020, lastChar)
|
||||
|
||||
PUB fullcls
|
||||
longfill(@screen, $20202020, 800)
|
||||
|
||||
PUB setInverse(val)
|
||||
inverse := val
|
||||
|
||||
PUB setInv(c)
|
||||
if c == 7
|
||||
setInverse(1)
|
||||
else
|
||||
setInverse(0)
|
||||
|
||||
PUB clEOL(position) | count
|
||||
count := cols - (position // cols)
|
||||
bytefill(@screen + position, $20, count)
|
||||
|
||||
PUB clBOL(position) | count
|
||||
count := position // cols
|
||||
bytefill(@screen + position - count, $20, count)
|
||||
|
||||
PUB delLine(position) | src, count
|
||||
position -= position // cols
|
||||
|
||||
src := position + cols
|
||||
|
||||
count := (maxChars - src) / 4
|
||||
|
||||
if count > 0
|
||||
longmove(@screen + position, @screen + src, count)
|
||||
|
||||
longfill(@screen + lastLine, $20202020, lcols)
|
||||
|
||||
PUB clEOS(position)
|
||||
cleol(position)
|
||||
position += cols - (position // cols)
|
||||
repeat while position < maxChars
|
||||
longfill(@screen + position, $20202020, lcols)
|
||||
pos += cols
|
||||
|
||||
PUB setCursorPos(position)
|
||||
cursor[0] := position // cols
|
||||
cursor[1] := position / cols
|
||||
|
||||
PUB insLine(position) | base, nxt
|
||||
base := position - (position // cols)
|
||||
position := lastLine
|
||||
repeat while position > base
|
||||
nxt := position - cols
|
||||
longmove(@screen + position, @screen + nxt, lcols)
|
||||
position := nxt
|
||||
clEOL(base)
|
||||
|
||||
PUB insChar(position) | count
|
||||
count := (cols - (position // cols)) - 1
|
||||
bytemove(@tmpl, @screen + position, count)
|
||||
screen[position] := " "
|
||||
bytemove(@screen + position + 1, @tmpl, count)
|
||||
|
||||
PUB delChar(position) | count
|
||||
count := (cols - (position // cols)) - 1
|
||||
bytemove(@screen + position, @screen + position + 1, count)
|
||||
screen[position + count] := " "
|
||||
|
||||
PRI inRegion : answer
|
||||
answer := (pos => regionTop) AND (pos < regionBot)
|
||||
|
||||
PRI scrollUp
|
||||
delLine(regionTop)
|
||||
if regionBot < maxChars
|
||||
insLine(regionBot)
|
||||
|
||||
PRI scrollDown
|
||||
if regionBot < maxChars
|
||||
delLine(regionBot)
|
||||
insLine(regionTop)
|
||||
|
||||
PRI ansi(c) | x, defVal
|
||||
|
||||
state := 0
|
||||
|
||||
if (c <> "r") AND (c <> "J") AND (c <> "m") AND (c <> "K")
|
||||
if arg0 == -1
|
||||
arg0 := 1
|
||||
if arg1 == -1
|
||||
arg1 := 1
|
||||
|
||||
case c
|
||||
"@":
|
||||
repeat while arg0-- > 0
|
||||
insChar(pos)
|
||||
|
||||
"b":
|
||||
repeat while arg0-- > 0
|
||||
outc(lastc)
|
||||
|
||||
"d":
|
||||
if (arg0 < 1) OR (arg0 > rows)
|
||||
arg0 := rows
|
||||
pos := ((arg0 - 1) * cols) + (pos // cols)
|
||||
|
||||
"m":
|
||||
setInv(arg0)
|
||||
if arg1 <> -1
|
||||
setInv(arg1)
|
||||
|
||||
"r":
|
||||
if arg0 < 1
|
||||
arg0 := 1
|
||||
elseif arg0 > cols
|
||||
arg0 := cols
|
||||
if arg1 < 1
|
||||
arg1 := 1
|
||||
elseif arg1 > cols
|
||||
arg1 := cols
|
||||
if arg1 < arg0
|
||||
arg1 := arg0
|
||||
|
||||
regionTop := (arg0 - 1) * cols
|
||||
regionBot := arg1 * cols
|
||||
pos := 0
|
||||
|
||||
"A":
|
||||
repeat while arg0-- > 0
|
||||
pos -= cols
|
||||
if pos < 0
|
||||
pos += cols
|
||||
return
|
||||
|
||||
"B":
|
||||
repeat while arg0-- > 0
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
return
|
||||
|
||||
"C":
|
||||
repeat while arg0-- > 0
|
||||
pos += 1
|
||||
if pos => maxChars
|
||||
pos -= 1
|
||||
return
|
||||
|
||||
"D":
|
||||
repeat while arg0-- > 0
|
||||
pos -= 1
|
||||
if pos < 0
|
||||
pos := 0
|
||||
return
|
||||
|
||||
"G":
|
||||
if (arg0 < 1) OR (arg0 > cols)
|
||||
arg0 := cols
|
||||
pos := (pos - (pos // cols)) + (arg0 - 1)
|
||||
|
||||
"H", "f":
|
||||
if arg0 =< 0
|
||||
arg0 := 1
|
||||
if arg1 =< 0
|
||||
arg1 := 1
|
||||
pos := (cols * (arg0 - 1)) + (arg1 - 1)
|
||||
if pos < 0
|
||||
pos := 0
|
||||
if pos => maxChars
|
||||
pos := maxChars - 1
|
||||
|
||||
"J":
|
||||
if arg0 == 1
|
||||
clBOL(pos)
|
||||
x := pos - cols
|
||||
x -= x // cols
|
||||
repeat while x => 0
|
||||
clEOL(x)
|
||||
x -= cols
|
||||
return
|
||||
|
||||
if arg0 == 2
|
||||
pos := 0
|
||||
|
||||
clEOL(pos)
|
||||
x := pos + cols
|
||||
x -= (x // cols)
|
||||
repeat while x < maxChars
|
||||
clEOL(x)
|
||||
x += cols
|
||||
|
||||
"K":
|
||||
if arg0 == -1
|
||||
clEOL(pos)
|
||||
elseif arg0 == 1
|
||||
clBOL(pos)
|
||||
else
|
||||
clEOL(pos - (pos // cols))
|
||||
|
||||
"L":
|
||||
if inRegion
|
||||
repeat while arg0-- > 0
|
||||
if regionBot < maxChars
|
||||
delLine(regionBot)
|
||||
insLine(pos)
|
||||
|
||||
"M":
|
||||
if inRegion
|
||||
repeat while arg0-- > 0
|
||||
delLine(pos)
|
||||
if regionBot < maxChars
|
||||
insLine(regionBot)
|
||||
|
||||
"P":
|
||||
repeat while arg0--
|
||||
delChar(pos)
|
||||
|
||||
PRI outc(c)
|
||||
|
||||
putc(pos++, lastc := c)
|
||||
if pos == regionBot
|
||||
scrollUp
|
||||
pos -= cols
|
||||
elseif pos == maxChars
|
||||
pos := lastLine
|
||||
|
||||
PUB process_char(c)
|
||||
|
||||
case state
|
||||
|
||||
0:
|
||||
if c > 127
|
||||
c := $20
|
||||
|
||||
if c => $20
|
||||
outc(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == $1B
|
||||
state := 1
|
||||
return
|
||||
|
||||
if c == $0D
|
||||
pos := pos - (pos // cols)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == $0A
|
||||
if inRegion
|
||||
pos += cols
|
||||
if pos => regionBot
|
||||
scrollUp
|
||||
pos -= cols
|
||||
else
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == 9
|
||||
pos += (8 - (pos // 8))
|
||||
|
||||
if pos => maxChars
|
||||
pos := lastLine
|
||||
delLine(0)
|
||||
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
if c == 8
|
||||
if pos > 0
|
||||
pos -= 1
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
1:
|
||||
case c
|
||||
"[":
|
||||
arg0 := arg1 := -1
|
||||
state := 2
|
||||
return
|
||||
|
||||
"P":
|
||||
pos += cols
|
||||
if pos => maxChars
|
||||
pos -= cols
|
||||
|
||||
"K":
|
||||
if pos > 0
|
||||
pos -= 1
|
||||
|
||||
"H":
|
||||
pos -= cols
|
||||
if pos < 0
|
||||
pos += cols
|
||||
|
||||
"D":
|
||||
if inRegion
|
||||
scrollUp
|
||||
|
||||
"M":
|
||||
if inRegion
|
||||
scrollDown
|
||||
|
||||
"G":
|
||||
pos := 0
|
||||
|
||||
"(":
|
||||
state := 5
|
||||
return
|
||||
|
||||
state := 0
|
||||
return
|
||||
|
||||
2:
|
||||
if (c => "0") AND (c =< "9")
|
||||
if arg0 == -1
|
||||
arg0 := c - "0"
|
||||
else
|
||||
arg0 := (arg0 * 10) + (c - "0")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
state := 3
|
||||
return
|
||||
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
3:
|
||||
if (c => "0") AND (c =< "9")
|
||||
if arg1 == -1
|
||||
arg1 := c - "0"
|
||||
else
|
||||
arg1 := (arg1 * 10) + (c - "0")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
state := 4
|
||||
return
|
||||
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
4:
|
||||
if (c => "0") AND (c =< "9")
|
||||
return
|
||||
|
||||
if c == ";"
|
||||
return
|
||||
ansi(c)
|
||||
setCursorPos(pos)
|
||||
return
|
||||
|
||||
5:
|
||||
state := 0
|
||||
return
|
||||
|
||||
return
|
||||
BIN
Hardware/PropIO2/Spin/VGA_HiRes_Text.spin
Normal file
BIN
Hardware/PropIO2/Spin/VGA_HiRes_Text.spin
Normal file
Binary file not shown.
920
Hardware/PropIO2/Spin/safe_spi.spin
Normal file
920
Hardware/PropIO2/Spin/safe_spi.spin
Normal file
@@ -0,0 +1,920 @@
|
||||
{{
|
||||
SPI interface routines for SD & SDHC & MMC cards
|
||||
|
||||
Jonathan "lonesock" Dummer
|
||||
version 0.3.0 2009 July 19
|
||||
|
||||
Using multiblock SPI mode exclusively.
|
||||
|
||||
This is the "SAFE" version...uses
|
||||
* 1 instruction per bit writes
|
||||
* 2 instructions per bit reads
|
||||
|
||||
For the fsrw project:
|
||||
fsrw.sf.net
|
||||
}}
|
||||
|
||||
CON
|
||||
' possible card types
|
||||
type_MMC = 1
|
||||
type_SD = 2
|
||||
type_SDHC = 3
|
||||
|
||||
' Error codes
|
||||
ERR_CARD_NOT_RESET = -1
|
||||
ERR_3v3_NOT_SUPPORTED = -2
|
||||
ERR_OCR_FAILED = -3
|
||||
ERR_BLOCK_NOT_LONG_ALIGNED = -4
|
||||
'...
|
||||
' These errors are for the assembly engine...they are negated inside, and need to be <= 511
|
||||
ERR_ASM_NO_READ_TOKEN = 100
|
||||
ERR_ASM_BLOCK_NOT_WRITTEN = 101
|
||||
' NOTE: errors -128 to -255 are reserved for reporting R1 response errors
|
||||
'...
|
||||
ERR_SPI_ENGINE_NOT_RUNNING = -999
|
||||
ERR_CARD_BUSY_TIMEOUT = -1000
|
||||
|
||||
' SDHC/SD/MMC command set for SPI
|
||||
CMD0 = $40+0 ' GO_IDLE_STATE
|
||||
CMD1 = $40+1 ' SEND_OP_COND (MMC)
|
||||
ACMD41 = $C0+41 ' SEND_OP_COND (SDC)
|
||||
CMD8 = $40+8 ' SEND_IF_COND
|
||||
CMD9 = $40+9 ' SEND_CSD
|
||||
CMD10 = $40+10 ' SEND_CID
|
||||
CMD12 = $40+12 ' STOP_TRANSMISSION
|
||||
CMD13 = $40+13 ' SEND_STATUS
|
||||
ACMD13 = $C0+13 ' SD_STATUS (SDC)
|
||||
CMD16 = $40+16 ' SET_BLOCKLEN
|
||||
CMD17 = $40+17 ' READ_SINGLE_BLOCK
|
||||
CMD18 = $40+18 ' READ_MULTIPLE_BLOCK
|
||||
CMD23 = $40+23 ' SET_BLOCK_COUNT (MMC)
|
||||
ACMD23 = $C0+23 ' SET_WR_BLK_ERASE_COUNT (SDC)
|
||||
CMD24 = $40+24 ' WRITE_BLOCK
|
||||
CMD25 = $40+25 ' WRITE_MULTIPLE_BLOCK
|
||||
CMD55 = $40+55 ' APP_CMD
|
||||
CMD58 = $40+58 ' READ_OCR
|
||||
CMD59 = $40+59 ' CRC_ON_OFF
|
||||
|
||||
' buffer size for my debug cmd log
|
||||
'LOG_SIZE = 256<<1
|
||||
|
||||
{
|
||||
VAR
|
||||
long SPI_engine_cog
|
||||
' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
long SPI_command ' "t", "r", "w", 0 =>done, <0 => error | pin mask
|
||||
long SPI_block_index ' which 512-byte block to read/write | cnt at init
|
||||
long SPI_buffer_address ' where to get/put the data in Hub RAM | unused
|
||||
'}
|
||||
DAT
|
||||
'' I'm placing these variables in a DAT section to make this driver a singleton.
|
||||
'' If for some reason you really need more than one driver (e.g. if you have more
|
||||
'' than a single SD socket), move these back into VAR.
|
||||
SPI_engine_cog long 0
|
||||
' these are used for interfacing with the assembly engine | temporary initialization usage
|
||||
SPI_command long 0 ' "t", "r", "w", 0 =>done, <0 => error | unused
|
||||
SPI_block_index long 0 ' which 512-byte block to read/write | cnt at init
|
||||
SPI_buffer_address long 0 ' where to get/put the data in Hub RAM | unused
|
||||
|
||||
{
|
||||
VAR
|
||||
' for debug ONLY
|
||||
byte log_cmd_resp[LOG_SIZE+1]
|
||||
PUB get_log_pointer
|
||||
return @log_cmd_resp
|
||||
'}
|
||||
|
||||
PUB start( basepin )
|
||||
{{
|
||||
This is a compatibility wrapper, and requires that the pins be
|
||||
both consecutive, and in the order DO CLK DI CS.
|
||||
}}
|
||||
return start_explicit( basepin, basepin+1, basepin+2, basepin+3 )
|
||||
|
||||
PUB readblock( block_index, buffer_address )
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
if (buffer_address & 3)
|
||||
abort ERR_BLOCK_NOT_LONG_ALIGNED
|
||||
SPI_block_index := block_index
|
||||
SPI_buffer_address := buffer_address
|
||||
SPI_command := "r"
|
||||
repeat while SPI_command == "r"
|
||||
if SPI_command < 0
|
||||
abort SPI_command
|
||||
|
||||
PUB writeblock( block_index, buffer_address )
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
if (buffer_address & 3)
|
||||
abort ERR_BLOCK_NOT_LONG_ALIGNED
|
||||
SPI_block_index := block_index
|
||||
SPI_buffer_address := buffer_address
|
||||
SPI_command := "w"
|
||||
repeat while SPI_command == "w"
|
||||
if SPI_command < 0
|
||||
abort SPI_command
|
||||
|
||||
PUB get_seconds
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
SPI_command := "t"
|
||||
repeat while SPI_command == "t"
|
||||
' secods are in SPI_block_index, remainder is in SPI_buffer_address
|
||||
return SPI_block_index
|
||||
|
||||
PUB get_milliseconds : ms
|
||||
if SPI_engine_cog == 0
|
||||
abort ERR_SPI_ENGINE_NOT_RUNNING
|
||||
SPI_command := "t"
|
||||
repeat while SPI_command == "t"
|
||||
' secods are in SPI_block_index, remainder is in SPI_buffer_address
|
||||
ms := SPI_block_index * 1000
|
||||
ms += SPI_buffer_address * 1000 / clkfreq
|
||||
|
||||
PUB start_explicit( DO, CLK, DI, CS ) : card_type | tmp, i
|
||||
{{
|
||||
Do all of the card initialization in SPIN, then hand off the pin
|
||||
information to the assembly cog for hot SPI block R/W action!
|
||||
}}
|
||||
' Start from scratch
|
||||
stop
|
||||
' clear my log buffer
|
||||
{
|
||||
bytefill( @log_cmd_resp, 0, LOG_SIZE+1 )
|
||||
dbg_ptr := @log_cmd_resp
|
||||
dbg_end := dbg_ptr + LOG_SIZE
|
||||
'}
|
||||
' wait ~4 milliseconds
|
||||
waitcnt( 500 + (clkfreq>>8) + cnt )
|
||||
' (start with cog variables, _BEFORE_ loading the cog)
|
||||
pinDO := DO
|
||||
maskDO := |< DO
|
||||
pinCLK := CLK
|
||||
pinDI := DI
|
||||
maskDI := |< DI
|
||||
maskCS := |< CS
|
||||
adrShift := 9 ' block = 512 * index, and 512 = 1<<9
|
||||
' pass the output pin mask via the command register
|
||||
maskAll := maskCS | (|<pinCLK) | maskDI
|
||||
dira |= maskAll
|
||||
' get the card in a ready state: set DI and CS high, send => 74 clocks
|
||||
outa |= maskAll
|
||||
repeat 4096
|
||||
outa[CLK]~~
|
||||
outa[CLK]~
|
||||
' time-hack
|
||||
SPI_block_index := cnt
|
||||
' reset the card
|
||||
tmp~
|
||||
repeat i from 0 to 9
|
||||
if tmp <> 1
|
||||
tmp := send_cmd_slow( CMD0, 0, $95 )
|
||||
if (tmp & 4)
|
||||
' the card said CMD0 ("go idle") was invalid, so we're possibly stuck in read or write mode
|
||||
if i & 1
|
||||
' exit multiblock read mode
|
||||
repeat 4
|
||||
read_32_slow ' these extra clocks are required for some MMC cards
|
||||
send_slow( $FD, 8 ) ' stop token
|
||||
read_32_slow
|
||||
repeat while read_slow <> $FF
|
||||
else
|
||||
' exit multiblock read mode
|
||||
send_cmd_slow( CMD12, 0, $61 )
|
||||
if tmp <> 1
|
||||
' the reset command failed!
|
||||
crash( ERR_CARD_NOT_RESET )
|
||||
' Is this a SD type 2 card?
|
||||
if send_cmd_slow( CMD8, $1AA, $87 ) == 1
|
||||
' Type2 SD, check to see if it's a SDHC card
|
||||
tmp := read_32_slow
|
||||
' check the supported voltage
|
||||
if (tmp & $1FF) <> $1AA
|
||||
crash( ERR_3v3_NOT_SUPPORTED )
|
||||
' try to initialize the type 2 card with the High Capacity bit
|
||||
repeat while send_cmd_slow( ACMD41, |<30, $77 )
|
||||
' the card is initialized, let's read back the High Capacity bit
|
||||
if send_cmd_slow( CMD58, 0, $FD ) <> 0
|
||||
crash( ERR_OCR_FAILED )
|
||||
' get back the data
|
||||
tmp := read_32_slow
|
||||
' check the bit
|
||||
if tmp & |<30
|
||||
card_type := type_SDHC
|
||||
adrShift := 0
|
||||
else
|
||||
card_type := type_SD
|
||||
else
|
||||
' Either a type 1 SD card, or it's MMC, try SD 1st
|
||||
if send_cmd_slow( ACMD41, 0, $E5 ) < 2
|
||||
' this is a type 1 SD card (1 means busy, 0 means done initializing)
|
||||
card_type := type_SD
|
||||
repeat while send_cmd_slow( ACMD41, 0, $E5 )
|
||||
else
|
||||
' mark that it's MMC, and try to initialize
|
||||
card_type := type_MMC
|
||||
repeat while send_cmd_slow( CMD1, 0, $F9 )
|
||||
' some SD or MMC cards may have the wrong block size, set it here
|
||||
send_cmd_slow( CMD16, 512, $15 )
|
||||
' card is mounted, make sure the CRC is turned off
|
||||
send_cmd_slow( CMD59, 0, $91 )
|
||||
' check the status
|
||||
'send_cmd_slow( CMD13, 0, $0D )
|
||||
' done with the SPI bus for now
|
||||
outa |= maskCS
|
||||
' set my counter modes for super fast SPI operation
|
||||
' writing: NCO single-ended mode, output on DI
|
||||
writeMode := (%00100 << 26) | (DI << 0)
|
||||
' reading
|
||||
'readMode := (%11000 << 26) | (DO << 0) | (CLK << 9)
|
||||
' clock
|
||||
'clockLineMode := (%00110 << 26) | (CLK << 0) ' DUTY, 25% duty cycle
|
||||
' clock
|
||||
clockLineMode := (%00100 << 26) | (CLK << 0) ' NCO, 50% duty cycle
|
||||
' how many bytes (8 clocks, >>3) fit into 1/2 of a second (>>1), 4 clocks per instruction (>>2)?
|
||||
N_in8_500ms := clkfreq >> constant(1+2+3)
|
||||
' how long should we wait before auto-exiting any multiblock mode?
|
||||
idle_limit := 125 ' ms, NEVER make this > 1000
|
||||
idle_limit := clkfreq / (1000 / idle_limit) ' convert to counts
|
||||
' Hand off control to the assembly engine's cog
|
||||
bufAdr := @SPI_buffer_address
|
||||
sdAdr := @SPI_block_index
|
||||
SPI_command := 0 ' just make sure it's not 1
|
||||
' start my driver cog and wait till I hear back that it's done
|
||||
SPI_engine_cog := cognew( @SPI_engine_entry, @SPI_command ) + 1
|
||||
if( SPI_engine_cog == 0 )
|
||||
crash( ERR_SPI_ENGINE_NOT_RUNNING )
|
||||
repeat while SPI_command <> -1
|
||||
' and we no longer need to control any pins from here
|
||||
dira &= !maskAll
|
||||
' the return variable is card_type
|
||||
|
||||
PUB release
|
||||
{{
|
||||
I do not want to abort if the cog is not
|
||||
running, as this is called from stop, which
|
||||
is called from start/ [8^)
|
||||
}}
|
||||
if SPI_engine_cog
|
||||
SPI_command := "z"
|
||||
repeat while SPI_command == "z"
|
||||
|
||||
PUB stop
|
||||
{{
|
||||
kill the assembly driver cog.
|
||||
}}
|
||||
release
|
||||
if SPI_engine_cog
|
||||
cogstop( SPI_engine_cog~ - 1 )
|
||||
|
||||
PRI crash( abort_code )
|
||||
{{
|
||||
In case of Bad Things(TM) happening,
|
||||
exit as gracefully as possible.
|
||||
}}
|
||||
' and we no longer need to control any pins from here
|
||||
dira &= !maskAll
|
||||
' and report our error
|
||||
abort abort_code
|
||||
|
||||
PRI send_cmd_slow( cmd, val, crc ) : reply | time_stamp
|
||||
{{
|
||||
Send down a command and return the reply.
|
||||
Note: slow is an understatement!
|
||||
Note: this uses the assembly DAT variables for pin IDs,
|
||||
which means that if you run this multiple times (say for
|
||||
multiple SD cards), these values will change for each one.
|
||||
But this is OK as all of these functions will be called
|
||||
during the initialization only, before the PASM engine is
|
||||
running.
|
||||
}}
|
||||
' if this is an application specific command, handle it
|
||||
if (cmd & $80)
|
||||
' ACMD<n> is the command sequense of CMD55-CMD<n>
|
||||
cmd &= $7F
|
||||
reply := send_cmd_slow( CMD55, 0, $65 )
|
||||
if (reply > 1)
|
||||
return reply
|
||||
' the CS line needs to go low during this operation
|
||||
outa |= maskCS
|
||||
outa &= !maskCS
|
||||
' give the card a few cocks to finish whatever it was doing
|
||||
read_32_slow
|
||||
' send the command byte
|
||||
send_slow( cmd, 8 )
|
||||
' send the value long
|
||||
send_slow( val, 32 )
|
||||
' send the CRC byte
|
||||
send_slow( crc, 8 )
|
||||
' is this a CMD12?, if so, stuff byte
|
||||
if cmd == CMD12
|
||||
read_slow
|
||||
' read back the response (spec declares 1-8 reads max for SD, MMC is 0-8)
|
||||
time_stamp := 9
|
||||
repeat
|
||||
reply := read_slow
|
||||
while( reply & $80 ) and ( time_stamp-- )
|
||||
' done, and 'reply' is already pre-loaded
|
||||
{
|
||||
if dbg_ptr < (dbg_end-1)
|
||||
byte[dbg_ptr++] := cmd
|
||||
byte[dbg_ptr++] := reply
|
||||
if (cmd&63) == 13
|
||||
' get the second byte
|
||||
byte[dbg_ptr++] := cmd
|
||||
byte[dbg_ptr++] := read_slow
|
||||
'}
|
||||
|
||||
PRI send_slow( value, bits_to_send )
|
||||
value ><= bits_to_send
|
||||
repeat bits_to_send
|
||||
outa[pinCLK]~
|
||||
outa[pinDI] := value
|
||||
value >>= 1
|
||||
outa[pinCLK]~~
|
||||
|
||||
PRI read_32_slow : r
|
||||
repeat 4
|
||||
r <<= 8
|
||||
r |= read_slow
|
||||
|
||||
PRI read_slow : r
|
||||
{{
|
||||
Read back 8 bits from the card
|
||||
}}
|
||||
' we need the DI line high so a read can occur
|
||||
outa[pinDI]~~
|
||||
' get 8 bits (remember, r is initialized to 0 by SPIN)
|
||||
repeat 8
|
||||
outa[pinCLK]~
|
||||
outa[pinCLK]~~
|
||||
r += r + ina[pinDO]
|
||||
' error check
|
||||
if( (cnt - SPI_block_index) > (clkfreq << 2) )
|
||||
crash( ERR_CARD_BUSY_TIMEOUT )
|
||||
|
||||
DAT
|
||||
{{
|
||||
This is the assembly engine for doing fast block
|
||||
reads and writes. This is *ALL* it does!
|
||||
}}
|
||||
ORG 0
|
||||
SPI_engine_entry
|
||||
' Counter A drives data out
|
||||
mov ctra,writeMode
|
||||
' Counter B will always drive my clock line
|
||||
mov ctrb,clockLineMode
|
||||
' set our output pins to match the pin mask
|
||||
mov dira,maskAll
|
||||
' handshake that we now control the pins
|
||||
neg user_request,#1
|
||||
wrlong user_request,par
|
||||
' start my seconds' counter here
|
||||
mov last_time,cnt
|
||||
|
||||
waiting_for_command
|
||||
' update my seconds counter, but also track the idle
|
||||
' time so we can to release the card after timeout.
|
||||
call #handle_time
|
||||
' read the command, and make sure it's from the user (> 0)
|
||||
rdlong user_request,par
|
||||
cmps user_request,#0 wz,wc
|
||||
if_be jmp #waiting_for_command
|
||||
' handle our card based commands
|
||||
cmp user_request,#"r" wz
|
||||
if_z jmp #read_ahead
|
||||
cmp user_request,#"w" wz
|
||||
if_z jmp #write_behind
|
||||
cmp user_request,#"z" wz
|
||||
if_z jmp #release_card
|
||||
' time requests are handled differently
|
||||
cmp user_request,#"t" wz ' time
|
||||
if_z wrlong seconds,sdAdr ' seconds goes into the SD index register
|
||||
if_z wrlong dtime,bufAdr ' the remainder goes into the buffer address register
|
||||
' in all other cases, clear the user's request
|
||||
mov user_request,#0
|
||||
wrlong user_request,par
|
||||
jmp #waiting_for_command
|
||||
|
||||
|
||||
release_card
|
||||
mov user_cmd,#"z" ' request a release
|
||||
neg lastIndexPlus,#1 ' reset the last block index
|
||||
neg user_idx,#1 ' and make this match it
|
||||
call #handle_command
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
jmp #waiting_for_command
|
||||
|
||||
read_ahead
|
||||
rdlong user_idx,sdAdr
|
||||
' if the correct block is not already loaded, load it
|
||||
mov tmp1,user_idx
|
||||
add tmp1,#1
|
||||
cmp tmp1,lastIndexPlus wz
|
||||
if_z cmp lastCommand,#"r" wz
|
||||
if_z jmp #:get_on_with_it
|
||||
mov user_cmd,#"r"
|
||||
call #handle_command
|
||||
:get_on_with_it
|
||||
' copy the data up into Hub RAM
|
||||
movi transfer_long,#%000010_000 'set to wrlong
|
||||
call #hub_cog_transfer
|
||||
' signify that the data is ready, Spin can continue
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
' request the next block
|
||||
mov user_cmd,#"r"
|
||||
add user_idx,#1
|
||||
call #handle_command
|
||||
' done
|
||||
jmp #waiting_for_command
|
||||
|
||||
write_behind
|
||||
rdlong user_idx,sdAdr
|
||||
' copy data in from Hub RAM
|
||||
movi transfer_long,#%000010_001 'set to rdlong
|
||||
call #hub_cog_transfer
|
||||
' signify that we have the data, Spin can continue
|
||||
mov user_request,user_cmd
|
||||
wrlong user_request,par
|
||||
' write out the block
|
||||
mov user_cmd,#"w"
|
||||
call #handle_command
|
||||
' done
|
||||
jmp #waiting_for_command
|
||||
|
||||
{{
|
||||
Set user_cmd and user_idx before calling this
|
||||
}}
|
||||
handle_command
|
||||
' Can we stay in the old mode? (address = old_address+1) && (old mode == new_mode)
|
||||
cmp lastIndexPlus,user_idx wz
|
||||
if_z cmp user_cmd,lastCommand wz
|
||||
if_z jmp #:execute_block_command
|
||||
' we fell through, must exit the old mode! (except if the old mode was "release")
|
||||
cmp lastCommand,#"w" wz
|
||||
if_z call #stop_mb_write
|
||||
cmp lastCommand,#"r" wz
|
||||
if_z call #stop_mb_read
|
||||
' and start up the new mode!
|
||||
cmp user_cmd,#"w" wz
|
||||
if_z call #start_mb_write
|
||||
cmp user_cmd,#"r" wz
|
||||
if_z call #start_mb_read
|
||||
cmp user_cmd,#"z" wz
|
||||
if_z call #release_DO
|
||||
:execute_block_command
|
||||
' track the (new) last index and command
|
||||
mov lastIndexPlus,user_idx
|
||||
add lastIndexPlus,#1
|
||||
mov lastCommand,user_cmd
|
||||
' do the block read or write or terminate!
|
||||
cmp user_cmd,#"w" wz
|
||||
if_z call #write_single_block
|
||||
cmp user_cmd,#"r" wz
|
||||
if_z call #read_single_block
|
||||
cmp user_cmd,#"z" wz
|
||||
if_z mov user_cmd,#0
|
||||
' done
|
||||
handle_command_ret
|
||||
ret
|
||||
|
||||
{=== these PASM functions get me in and out of multiblock mode ===}
|
||||
release_DO
|
||||
' we're already out of multiblock mode, so
|
||||
' deselect the card and send out some clocks
|
||||
or outa,maskCS
|
||||
call #in8
|
||||
call #in8
|
||||
' if you are using pull-up resistors, and need all
|
||||
' lines tristated, then uncomment the following line.
|
||||
' for Cluso99
|
||||
'mov dira,#0
|
||||
release_DO_ret
|
||||
ret
|
||||
|
||||
start_mb_read
|
||||
movi block_cmd,#CMD18<<1
|
||||
call #send_SPI_command_fast
|
||||
start_mb_read_ret
|
||||
ret
|
||||
|
||||
stop_mb_read
|
||||
movi block_cmd,#CMD12<<1
|
||||
call #send_SPI_command_fast
|
||||
call #busy_fast
|
||||
stop_mb_read_ret
|
||||
ret
|
||||
|
||||
start_mb_write
|
||||
movi block_cmd,#CMD25<<1
|
||||
call #send_SPI_command_fast
|
||||
start_mb_write_ret
|
||||
ret
|
||||
|
||||
stop_mb_write
|
||||
call #busy_fast
|
||||
' only some cards need these extra clocks
|
||||
mov tmp1,#16
|
||||
:loopity
|
||||
call #in8
|
||||
djnz tmp1,#:loopity
|
||||
' done with hack
|
||||
movi phsa,#$FD<<1
|
||||
call #out8
|
||||
call #in8 ' stuff byte
|
||||
call #busy_fast
|
||||
stop_mb_write_ret
|
||||
ret
|
||||
|
||||
send_SPI_command_fast
|
||||
' make sure we have control of the output lines
|
||||
mov dira,maskAll
|
||||
' make sure the CS line transitions low
|
||||
or outa,maskCS
|
||||
andn outa,maskCS
|
||||
' 8 clocks
|
||||
call #in8
|
||||
' send the data
|
||||
mov phsa,block_cmd ' do which ever block command this is (already in the top 8 bits)
|
||||
call #out8 ' write the byte
|
||||
mov phsa,user_idx ' read in the desired block index
|
||||
shl phsa,adrShift ' this will multiply by 512 (bytes/sector) for MMC and SD
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
rol phsa,#1
|
||||
call #out8 ' move out the 1st MSB '
|
||||
' bogus CRC value
|
||||
call #in8 ' in8 looks like out8 with $FF
|
||||
' CMD12 requires a stuff byte
|
||||
shr block_cmd,#24
|
||||
cmp block_cmd,#CMD12 wz
|
||||
if_z call #in8 ' 8 clocks
|
||||
' get the response
|
||||
mov tmp1,#9
|
||||
:cmd_response
|
||||
call #in8
|
||||
test readback,#$80 wc,wz
|
||||
if_c djnz tmp1,#:cmd_response
|
||||
if_nz neg user_cmd,readback
|
||||
' done
|
||||
send_SPI_command_fast_ret
|
||||
ret
|
||||
|
||||
|
||||
busy_fast
|
||||
mov tmp1,N_in8_500ms
|
||||
:still_busy
|
||||
call #in8
|
||||
cmp readback,#$FF wz
|
||||
if_nz djnz tmp1,#:still_busy
|
||||
busy_fast_ret
|
||||
ret
|
||||
|
||||
|
||||
out8
|
||||
andn outa,maskDI
|
||||
'movi phsb,#%11_0000000
|
||||
mov phsb,#0
|
||||
movi frqb,#%01_0000000
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
rol phsa,#1
|
||||
mov frqb,#0
|
||||
' don't shift out the final bit...already sent, but be aware
|
||||
' of this when sending consecutive bytes (send_cmd, for e.g.)
|
||||
out8_ret
|
||||
ret
|
||||
|
||||
{
|
||||
in8
|
||||
or outa,maskDI
|
||||
mov ctra,readMode
|
||||
' Start my clock
|
||||
mov frqa,#1<<7
|
||||
mov phsa,#0
|
||||
movi phsb,#%11_0000000
|
||||
movi frqb,#%01_0000000
|
||||
' keep reading in my value, one bit at a time! (Kuneko - "Wh)
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
shr frqa,#1
|
||||
mov frqb,#0 ' stop the clock
|
||||
mov readback,phsa
|
||||
mov frqa,#0
|
||||
mov ctra,writeMode
|
||||
in8_ret
|
||||
ret
|
||||
}
|
||||
in8
|
||||
neg phsa,#1' DI high
|
||||
mov readback,#0
|
||||
' set up my clock, and start it
|
||||
movi phsb,#%011_000000
|
||||
movi frqb,#%001_000000
|
||||
' keep reading in my value
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
rcl readback,#1
|
||||
test maskDO,ina wc
|
||||
mov frqb,#0 ' stop the clock
|
||||
rcl readback,#1
|
||||
mov phsa,#0 'DI low
|
||||
in8_ret
|
||||
ret
|
||||
|
||||
|
||||
' this is called more frequently than 1 Hz, and
|
||||
' is only called when the user command is 0.
|
||||
handle_time
|
||||
mov tmp1,cnt ' get the current timestamp
|
||||
add idle_time,tmp1 ' add the current time to my idle time counter
|
||||
sub idle_time,last_time ' subtract the last time from my idle counter (hence delta)
|
||||
add dtime,tmp1 ' add to my accumulator,
|
||||
sub dtime,last_time ' and subtract the old (adding delta)
|
||||
mov last_time,tmp1 ' update my "last timestamp"
|
||||
rdlong tmp1,#0 ' what is the clock frequency?
|
||||
cmpsub dtime,tmp1 wc ' if I have more than a second in my accumulator
|
||||
addx seconds,#0 ' then add it to "seconds"
|
||||
' this part is to auto-release the card after a timeout
|
||||
cmp idle_time,idle_limit wz,wc
|
||||
if_b jmp #handle_time_ret ' don't clear if we haven't hit the limit
|
||||
mov user_cmd,#"z" ' we can't overdo it, the command handler makes sure
|
||||
neg lastIndexPlus,#1 ' reset the last block index
|
||||
neg user_idx,#1 ' and make this match it
|
||||
call #handle_command ' release the card, but don't mess with the user's request register
|
||||
handle_time_ret
|
||||
ret
|
||||
|
||||
hub_cog_transfer
|
||||
' setup for all 4 passes
|
||||
mov ctrb,clockXferMode
|
||||
mov frqb,#1
|
||||
rdlong buf_ptr,bufAdr
|
||||
mov ops_left,#4
|
||||
movd transfer_long,#speed_buf
|
||||
four_transfer_passes
|
||||
' sync to the Hub RAM access
|
||||
rdlong tmp1,tmp1
|
||||
' how many long to move on this pass? (512 bytes / 4)longs / 4 passes
|
||||
mov tmp1,#(512 / 4 / 4)
|
||||
' get my starting address right (phsb is incremented 1 per clock, so 16 each Hub access)
|
||||
mov phsb,buf_ptr
|
||||
' write the longs, stride 4...low 2 bits of phsb are ignored
|
||||
transfer_long
|
||||
rdlong 0-0,phsb
|
||||
add transfer_long,incDest4
|
||||
djnz tmp1,#transfer_long
|
||||
' go back to where I started, but advanced 1 long
|
||||
sub transfer_long,decDestNminus1
|
||||
' offset my Hub pointer by one long per pass
|
||||
add buf_ptr,#4
|
||||
' do all 4 passes
|
||||
djnz ops_left,#four_transfer_passes
|
||||
' restore the counter mode
|
||||
mov frqb,#0
|
||||
mov phsb,#0
|
||||
mov ctrb,clockLineMode
|
||||
hub_cog_transfer_ret
|
||||
ret
|
||||
|
||||
|
||||
read_single_block
|
||||
' where am I sending the data?
|
||||
movd :store_read_long,#speed_buf
|
||||
mov ops_left,#128
|
||||
' wait until the card is ready
|
||||
mov tmp1,N_in8_500ms
|
||||
:get_resp
|
||||
call #in8
|
||||
cmp readback,#$FE wz
|
||||
if_nz djnz tmp1,#:get_resp
|
||||
if_nz neg user_cmd,#ERR_ASM_NO_READ_TOKEN
|
||||
if_nz jmp #read_single_block_ret
|
||||
' set DI high
|
||||
neg phsa,#1
|
||||
' read the data
|
||||
mov ops_left,#128
|
||||
:read_loop
|
||||
mov tmp1,#4
|
||||
movi phsb,#%011_000000
|
||||
:in_byte
|
||||
' Start my clock
|
||||
movi frqb,#%001_000000
|
||||
' keep reading in my value, BACKWARDS! (Brilliant idea by Tom Rokicki!)
|
||||
test maskDO,ina wc
|
||||
rcl readback,#8
|
||||
test maskDO,ina wc
|
||||
muxc readback,#2
|
||||
test maskDO,ina wc
|
||||
muxc readback,#4
|
||||
test maskDO,ina wc
|
||||
muxc readback,#8
|
||||
test maskDO,ina wc
|
||||
muxc readback,#16
|
||||
test maskDO,ina wc
|
||||
muxc readback,#32
|
||||
test maskDO,ina wc
|
||||
muxc readback,#64
|
||||
test maskDO,ina wc
|
||||
mov frqb,#0 ' stop the clock
|
||||
muxc readback,#128
|
||||
' go back for more
|
||||
djnz tmp1,#:in_byte
|
||||
' make it...NOT backwards [8^)
|
||||
rev readback,#0
|
||||
:store_read_long
|
||||
mov 0-0,readback ' due to some counter weirdness, we need this mov
|
||||
add :store_read_long,const512
|
||||
djnz ops_left,#:read_loop
|
||||
|
||||
' set DI low
|
||||
mov phsa,#0
|
||||
|
||||
' now read 2 trailing bytes (CRC)
|
||||
call #in8 ' out8 is 2x faster than in8
|
||||
call #in8 ' and I'm not using the CRC anyway
|
||||
' give an extra 8 clocks in case we pause for a long time
|
||||
call #in8 ' in8 looks like out8($FF)
|
||||
|
||||
' all done successfully
|
||||
mov idle_time,#0
|
||||
mov user_cmd,#0
|
||||
read_single_block_ret
|
||||
ret
|
||||
|
||||
write_single_block
|
||||
' where am I getting the data? (all 512 bytes / 128 longs of it?)
|
||||
movs :write_loop,#speed_buf
|
||||
' read in 512 bytes (128 longs) from Hub RAM and write it to the card
|
||||
mov ops_left,#128
|
||||
' just hold your horses
|
||||
call #busy_fast
|
||||
' $FC for multiblock, $FE for single block
|
||||
movi phsa,#$FC<<1
|
||||
call #out8
|
||||
mov phsb,#0 ' make sure my clock accumulator is right
|
||||
'movi phsb,#%11_0000000
|
||||
:write_loop
|
||||
' read 4 bytes
|
||||
mov phsa,speed_buf
|
||||
add :write_loop,#1
|
||||
' a long in LE order is DCBA
|
||||
rol phsa,#24 ' move A7 into position, so I can do the swizzled version
|
||||
movi frqb,#%010000000 ' start the clock (remember A7 is already in place)
|
||||
rol phsa,#1 ' A7 is going out, at the end of this instr, A6 is in place
|
||||
rol phsa,#1 ' A5
|
||||
rol phsa,#1 ' A4
|
||||
rol phsa,#1 ' A3
|
||||
rol phsa,#1 ' A2
|
||||
rol phsa,#1 ' A1
|
||||
rol phsa,#1 ' A0
|
||||
rol phsa,#17 ' B7
|
||||
rol phsa,#1 ' B6
|
||||
rol phsa,#1 ' B5
|
||||
rol phsa,#1 ' B4
|
||||
rol phsa,#1 ' B3
|
||||
rol phsa,#1 ' B2
|
||||
rol phsa,#1 ' B1
|
||||
rol phsa,#1 ' B0
|
||||
rol phsa,#17 ' C7
|
||||
rol phsa,#1 ' C6
|
||||
rol phsa,#1 ' C5
|
||||
rol phsa,#1 ' C4
|
||||
rol phsa,#1 ' C3
|
||||
rol phsa,#1 ' C2
|
||||
rol phsa,#1 ' C1
|
||||
rol phsa,#1 ' C0
|
||||
rol phsa,#17 ' D7
|
||||
rol phsa,#1 ' D6
|
||||
rol phsa,#1 ' D5
|
||||
rol phsa,#1 ' D4
|
||||
rol phsa,#1 ' D3
|
||||
rol phsa,#1 ' D2
|
||||
rol phsa,#1 ' D1
|
||||
rol phsa,#1 ' D0 will be in place _after_ this instruction
|
||||
mov frqb,#0 ' shuts the clock off, _after_ this instruction
|
||||
djnz ops_left,#:write_loop
|
||||
' write out my two (bogus, using $FF) CRC bytes
|
||||
call #in8
|
||||
call #in8
|
||||
' now read response (I need this response, so can't spoof using out8)
|
||||
call #in8
|
||||
and readback,#$1F
|
||||
cmp readback,#5 wz
|
||||
if_z mov user_cmd,#0 ' great
|
||||
if_nz neg user_cmd,#ERR_ASM_BLOCK_NOT_WRITTEN ' oops
|
||||
' send out another 8 clocks
|
||||
call #in8
|
||||
' all done
|
||||
mov idle_time,#0
|
||||
write_single_block_ret
|
||||
ret
|
||||
|
||||
|
||||
{=== Assembly Interface Variables ===}
|
||||
pinDO long 0 ' pin is controlled by a counter
|
||||
pinCLK long 0 ' pin is controlled by a counter
|
||||
pinDI long 0 ' pin is controlled by a counter
|
||||
maskDO long 0 ' mask for reading the DO line from the card
|
||||
maskDI long 0 ' mask for setting the pin high while reading
|
||||
maskCS long 0 ' mask = (1<<pin), and is controlled directly
|
||||
maskAll long 0
|
||||
adrShift long 9 ' will be 0 for SDHC, 9 for MMC & SD
|
||||
bufAdr long 0 ' where in Hub RAM is the buffer to copy to/from?
|
||||
sdAdr long 0 ' where on the SD card does it read/write?
|
||||
writeMode long 0 ' the counter setup in NCO single ended, clocking data out on pinDI
|
||||
'clockOutMode long 0 ' the counter setup in NCO single ended, driving the clock line on pinCLK
|
||||
N_in8_500ms long 1_000_000 ' used for timeout checking in PASM
|
||||
'readMode long 0
|
||||
clockLineMode long 0
|
||||
clockXferMode long %11111 << 26
|
||||
const512 long 512
|
||||
const1024 long 1024
|
||||
incDest4 long 4 << 9
|
||||
decDestNminus1 long (512 / 4 - 1) << 9
|
||||
|
||||
{=== Initialized PASM Variables ===}
|
||||
seconds long 0
|
||||
dtime long 0
|
||||
idle_time long 0
|
||||
idle_limit long 0
|
||||
|
||||
{=== Multiblock State Machine ===}
|
||||
lastIndexPlus long -1 ' state handler will check against lastIndexPlus, which will not have been -1
|
||||
lastCommand long 0 ' this will never be the last command.
|
||||
|
||||
{=== Debug Logging Pointers ===}
|
||||
{
|
||||
dbg_ptr long 0
|
||||
dbg_end long 0
|
||||
'}
|
||||
|
||||
{=== Assembly Scratch Variables ===}
|
||||
ops_left res 1 ' used as a counter for bytes, words, longs, whatever (start w/ # byte clocks out)
|
||||
readback res 1 ' all reading from the card goes through here
|
||||
tmp1 res 1 ' this may get used in all subroutines...don't use except in lowest
|
||||
user_request res 1 ' the main command variable, read in from Hub: "r"-read single, "w"-write single
|
||||
user_cmd res 1 ' used internally to handle actual commands to be executed
|
||||
user_idx res 1 ' the pointer to the Hub RAM where the data block is/goes
|
||||
block_cmd res 1 ' one of the SD/MMC command codes, no app-specific allowed
|
||||
buf_ptr res 1 ' moving pointer to the Hub RAM buffer
|
||||
last_time res 1 ' tracking the timestamp
|
||||
|
||||
{{
|
||||
496 longs is my total available space in the cog,
|
||||
and I want 128 longs for eventual use as one 512-
|
||||
byte buffer. This gives me a total of 368 longs
|
||||
to use for umount, and a readblock and writeblock
|
||||
for both Hub RAM and Cog buffers.
|
||||
}}
|
||||
speed_buf res 128 ' 512 bytes to be used for read-ahead / write-behind
|
||||
|
||||
'fit 467
|
||||
FIT 496
|
||||
|
||||
'' MIT LICENSE
|
||||
{{
|
||||
' Permission is hereby granted, free of charge, to any person obtaining
|
||||
' a copy of this software and associated documentation files
|
||||
' (the "Software"), to deal in the Software without restriction,
|
||||
' including without limitation the rights to use, copy, modify, merge,
|
||||
' publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
' and to permit persons to whom the Software is furnished to do so,
|
||||
' subject to the following conditions:
|
||||
'
|
||||
' The above copyright notice and this permission notice shall be included
|
||||
' in all copies or substantial portions of the Software.
|
||||
'
|
||||
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
' EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
' MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
' IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
' CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
' TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
' SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
}}
|
||||
@@ -7,6 +7,8 @@ Contents
|
||||
|
||||
VDU\vdu.rom: ROM image for VDU onboard EPROM
|
||||
|
||||
Prop\PropIO.eeprom: PropIO firmware for use with RomWBW
|
||||
Prop\PropIO2.eeprom: PropIO V2 firmware for use with RomWBW
|
||||
Prop\ParPortProp.eeprom: ParPortProp firmware for use with RomWBW
|
||||
PropIO\PropIO.eeprom: PropIO firmware for use with RomWBW
|
||||
|
||||
PropIO2\PropIO2.eeprom: PropIO V2 firmware for use with RomWBW
|
||||
|
||||
ParPortProp\ParPortProp.eeprom: ParPortProp firmware for use with RomWBW
|
||||
401
ReadMe.txt
401
ReadMe.txt
@@ -1,266 +1,169 @@
|
||||
***********************************************************************
|
||||
*** ***
|
||||
*** R o m W B W ***
|
||||
*** ***
|
||||
*** Z80/Z180 System Software ***
|
||||
*** ***
|
||||
***********************************************************************
|
||||
************************************************************
|
||||
*** R o m W B W ***
|
||||
*** ***
|
||||
*** System Software for N8VEM Z80 Projects ***
|
||||
************************************************************
|
||||
|
||||
Wayne Warthen (wwarthen@gmail.com)
|
||||
Version 2.8.3, 2017-08-23
|
||||
https://www.retrobrewcomputers.org/
|
||||
Builders: Wayne Warthen (wwarthen@gmail.com)
|
||||
Douglas Goodall (douglas_goodall@mac.com)
|
||||
David Giles (vk5dg@internode.on.net)
|
||||
|
||||
RomWBW is a ROM-based implementation of CP/M-80 2.2 and Z-System for
|
||||
all RetroBrew Computers Z80/Z180 hardware platforms including SBC
|
||||
1/2, Zeta 1/2, N8, and Mark IV. Virtually all RetroBrew hardware is
|
||||
supported including floppy, hard disk (IDE, CF Card, SD Card), Video,
|
||||
and keyboard. VT-100 terminal emulation is built-in.
|
||||
Updated: 2014-09-19
|
||||
Version: 2.6.2
|
||||
|
||||
The RomWBW ROM loads and runs the built-in operating systems directly
|
||||
from the ROM and includes a selection of standard/useful applications
|
||||
accessed via a ROM disk drive. A RAM disk drive is also provided
|
||||
to allow temporary file storage.
|
||||
This is an adaptation of CP/M-80 2.2 and ZSDOS/ZCPR
|
||||
targeting ROMs for all N8VEM Z80 hardware variations
|
||||
including SBC, Zeta, N8, and Mark IV.
|
||||
|
||||
Pre-built ROM images are included for all platforms. Detailed system
|
||||
customization is achieved by making simple modifications to a
|
||||
configuration file and running a build script to generate a custom
|
||||
ROM image. All source and build tools are included in the
|
||||
distribution. As distributed, the build scripts run under any modern
|
||||
32 or 64 bit version of Microsoft Windows.
|
||||
|
||||
John Coffman's UNA hardware BIOS is fully supported by RomWBW. In the
|
||||
case of UNA, a single ROM image (pre-built) is used for all supported
|
||||
platforms and is customized using a ROM-based setup program. See the
|
||||
UNA section below for more information.
|
||||
|
||||
Quick Start
|
||||
-----------
|
||||
|
||||
A pre-built ROM image is included for each of the hardware platforms
|
||||
supported. These ROM images are found in the Binary directory of the
|
||||
distribution and have a file extension of ".rom". Simply program the
|
||||
ROM of your system with the appropriate ROM image. Please see the
|
||||
RomList.txt file in the Binary directory for details on selecting the
|
||||
correct ROM image for your system and platform specific information.
|
||||
|
||||
Connect a serial terminal or computer with terminal emulation
|
||||
software to the primary RS-232 port of your CPU board. A null-modem
|
||||
connection is generally required. Set the line characteristics to
|
||||
38400 baud, 8 data bits, 1 stop bit, no parity, and no flow control.
|
||||
Select VT-100 terminal emulation.
|
||||
|
||||
Upon power-up, your terminal should display a sign-on banner within 2
|
||||
seconds followed by hardware inventory and discovery information.
|
||||
When hardware initialization is completed, a boot loader prompt
|
||||
allows you to choose a ROM-based operating system, system monitor, or
|
||||
boot from a disk device.
|
||||
|
||||
CPU Speed
|
||||
---------
|
||||
|
||||
RomWBW ROM images support virtually any CPU speed your system is
|
||||
running. However, there are some hardware-oriented caveats to be
|
||||
aware of.
|
||||
|
||||
The use of high density floppy disks requires a CPU speed of 8 MHz or
|
||||
greater.
|
||||
|
||||
The latest X-Modem file transfer programs (XM.COM, XM-A0.COM, and
|
||||
XM-A1.COM) require a CPU speeed of 6 MHz or greater to support the
|
||||
default RomWBW serial port speed of 38400 baud. Older variants of
|
||||
the X-Modem programs are included (XM5.COM, XM5-A0, and XM5-A1) which
|
||||
will handle 38400 baud on system running down to 4 MHz.
|
||||
|
||||
Upgrading from Previous Versions
|
||||
--------------------------------
|
||||
|
||||
Program a new ROM chip from an image in the new distribution. Install
|
||||
the new ROM chip and boot your system. At the boot loader "Boot:"
|
||||
prompt, select either CP/M or Z-System to load the OS from ROM.
|
||||
|
||||
If you have spare rom chips for your system, it is always safest to
|
||||
keep your existing, work rom chip and program a new one so that you
|
||||
can return to the old one if the new one does not work properly.
|
||||
|
||||
If you use a customized ROM image, it is recommended that you first
|
||||
try the pre-built ROM image first and then move on to generating a
|
||||
custom image.
|
||||
|
||||
It is entirely possible to reprogram your system ROM using the FLASH
|
||||
utility from Will Sowerbutts on your ROM drive (B:). In this case,
|
||||
you would need to transfer the new ROM image to your system using
|
||||
X-Modem. Obviously, there is some risk to this approach since any
|
||||
issues with the programming or ROM image could result in a
|
||||
non-functional system.
|
||||
|
||||
If your system has any bootable drives, then update the OS image on
|
||||
each drive using SYSCOPY. For example, if C: is a bootable drive
|
||||
with the Z-System OS, you would update the OS image on this drive
|
||||
with the command:
|
||||
|
||||
B>SYSCOPY C:=B:ZSYS.SYS
|
||||
|
||||
If you have copies of any of the system utilities on drives other
|
||||
than the ROM disk drive, you need to copy the latest version of the
|
||||
programs from the ROM drive (B:) to any drives containing these
|
||||
programs. For example, if you have a copy of the ASSIGN.COM program
|
||||
on C:, you would update it from the new ROM using the COPY command:
|
||||
|
||||
B>COPY B:ASSIGN.COM C:
|
||||
|
||||
The following programs are maintained with the ROM images and all
|
||||
copies of these programs should be updated when upgrading to a new
|
||||
ROM version:
|
||||
|
||||
- ASSIGN.COM
|
||||
- FORMAT.COM
|
||||
- OSLDR.COM
|
||||
- SYSCOPY.COM
|
||||
- TALK.COM
|
||||
- FD.COM
|
||||
- XM*.COM
|
||||
|
||||
UNA Hardware BIOS
|
||||
-----------------
|
||||
|
||||
John Coffman has produced a new generation of hardware BIOS called
|
||||
UNA. In addition to the classic ROM images, RomWBW comes with a
|
||||
UNA-based image that combines the UNA BIOS with the RomWBW OS
|
||||
implementations and applications.
|
||||
|
||||
UNA is customized dynamically using a ROM based setup routine and the
|
||||
setup is persisted in the system NVRAM of the RTC chip. This means
|
||||
that a single UNA-based ROM image can be used on most of the
|
||||
RetroBrew platforms and is easily customized. UNA also supports FAT
|
||||
file system access that can be used for in-situ ROM programming and
|
||||
loading system images.
|
||||
|
||||
While John is likely to enhance UNA over time, there are currently a
|
||||
few things that UNA does not support:
|
||||
|
||||
- Floppy Drives
|
||||
- Video/Keyboard/Terminal Emulation
|
||||
- Zeta 1 and N8 Systems
|
||||
- Some older support boards
|
||||
|
||||
If you wish to try the UNA variant of RomWBW, then just program your
|
||||
ROM with the ROM image called "UNA_std.rom" in the Binary directory.
|
||||
This one image is suitable on all of the platforms and hardware UNA
|
||||
supports.
|
||||
|
||||
Please refer to the RetroBrew Computers Wiki for more information on
|
||||
UNA.
|
||||
|
||||
CP/M vs. Z-System
|
||||
-----------------
|
||||
|
||||
There are two OS variants included in this distribution and you may
|
||||
choose which one you prefer to use. Both variants are now included
|
||||
in the pre-built ROM images. You will be given the choice to boot
|
||||
either CP/M or Z-System at startup.
|
||||
|
||||
The traditional Digital Research (DRI) CP/M OS is the first choice.
|
||||
The Doc directory contains a manual for CP/M usage ("CPM
|
||||
Manual.pdf"). If you are new to the RetroBrew Computer systems, I
|
||||
would currently recommend using the CP/M variant to start with simply
|
||||
because it has gone through more testing and you are less likely to
|
||||
encounter problems.
|
||||
|
||||
The other choice is to use the most popular non-DRI CP/M "clone"
|
||||
which is generally referred to as Z-System. It is intended to be
|
||||
functionally equivalent to CP/M and should run all CP/M 2.2 code. It
|
||||
is optimized for the Z80 CPU (as opposed to 8080 for CP/M) and has
|
||||
some potentially useful improvements. Please refer to "ZSDOS
|
||||
Manual.pdf" and "ZCPR Manual.pdf" in the Doc directory for more
|
||||
information on Z-System usage.
|
||||
|
||||
ROM Customization
|
||||
-----------------
|
||||
|
||||
The pre-built ROM images are configured for the basic capabilities of
|
||||
each platform. If you add board(s) to your system, you will need to
|
||||
customize your ROM image to include support for the added board(s).
|
||||
|
||||
Essentially, the creation of a custom ROM is accomplished by updating
|
||||
a small configuration file, then running a script to compile the
|
||||
software and generate the custom ROM image. At this time, the build
|
||||
process runs on Windows 32 or 64 bit versions. All tools (compilers,
|
||||
assemblers, etc.) are included in the distribution, so it is not
|
||||
necessary to setup a build environment on your computer.
|
||||
|
||||
For those who are interested in more than basic system customization,
|
||||
note that all source code is included (including the operating
|
||||
systems).
|
||||
|
||||
Note that the ROM customization process does not apply to UNA. All
|
||||
UNA customization is performed within the ROM setup script.
|
||||
|
||||
Complete documentation of the customization process is found in the
|
||||
ReadMe.txt file in the Source directory.
|
||||
|
||||
Source Code Respository
|
||||
-----------------------
|
||||
|
||||
All source code and distributions are maintained on GitHub at
|
||||
"https://github.com/wwarthen/RomWBW". Code contributions are very
|
||||
welcome.
|
||||
|
||||
Distribution Directory Layout
|
||||
-----------------------------
|
||||
|
||||
The RomWBW distribution is a compressed zip archive file organized in
|
||||
a set of directories. Each of these directories has it's own
|
||||
ReadMe.txt file describing the contents in detail. In summary, these
|
||||
directories are:
|
||||
|
||||
Binary: The final output files of the build process are placed
|
||||
here. Most importantly, are the ROM images with the
|
||||
file names ending in ".rom".
|
||||
|
||||
Doc: Contains various detailed documentation including the
|
||||
operating systems, RomWBW architecture, etc.
|
||||
|
||||
Source: Contains the source code files used to build the software
|
||||
and ROM images.
|
||||
|
||||
Tools: Contains the MS Windows programs that are used by the
|
||||
build process or that may be useful in setting up your
|
||||
system.
|
||||
NOTE: This is very much a work-in-progress. It is
|
||||
severely lacking appropriate documentation. I am
|
||||
happy to answer questions and provide support though.
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
While I have heavily modified much of the code, I want to acknowledge
|
||||
that much of the work is derived or copied from the work of others in
|
||||
the RetroBrew Computers project including Andrew Lynch, Dan Werner,
|
||||
Max Scane, David Giles, John Coffman, and probably many others I am
|
||||
not clearly aware of (let me know if I omitted someone!).
|
||||
While I have heavily modified much of the code, I want
|
||||
to acknowledge that much of this is derived or
|
||||
copied from the work of others in the N8VEM
|
||||
project including Andrew Lynch, Dan Werner, Max Scane,
|
||||
David Giles, John Coffman, and probably many others
|
||||
I am not clearly aware of (let me know if I omitted
|
||||
someone!).
|
||||
|
||||
I especially want to credit Douglas Goodall for contributing code,
|
||||
time, testing, and advice. He created an entire suite of application
|
||||
programs to enhance the use of RomWBW. However, he is looking for
|
||||
someone to continue the maintenance of these applications and they
|
||||
have become unusable due to changes within RomWBW. As of RomWBW 2.6,
|
||||
these applications are no longer provided.
|
||||
I especially want to credit Douglas Goodall for
|
||||
contributing code, time, testing, and advice. He created
|
||||
an entire suite of application programs to enhance the
|
||||
use of RomWBW. However, he is looking for someone to
|
||||
continue the maintenance of these applications and
|
||||
they have become unusable due to changes within
|
||||
RomWBW. As of RomWBW 2.6, these applications are
|
||||
no longer provided.
|
||||
|
||||
David Giles has contributed support for the CSIO support in the SD
|
||||
Card driver.
|
||||
David Giles has contributed support for building the
|
||||
ROM under Linux and the CSIO support in the SD Card driver.
|
||||
|
||||
The UNA BIOS is a product of John Coffman.
|
||||
|
||||
Getting Assistance
|
||||
Usage Instructions
|
||||
------------------
|
||||
|
||||
The best way to get assistance with RomWBW or any aspect of the
|
||||
RetroBrew Computers projects is via the community forum at
|
||||
"https://www.retrobrewcomputers.org/forum/".
|
||||
The distribution includes many pre-built ROM
|
||||
images in the Output directory. The simplest way of
|
||||
using this ROM is to simply pick the pre-built ROM
|
||||
that most closely matches your preferences, burn it,
|
||||
and use it.
|
||||
|
||||
Also feel free to email Wayne Warthen at wwarthen@gmail.com.
|
||||
Refer to the file called RomList.txt for a complete
|
||||
list of the ROMs that are included and the required
|
||||
hardware configuration that they support.
|
||||
|
||||
To Do
|
||||
Upgrading from Previous Versions
|
||||
--------------------------------
|
||||
|
||||
Burn a new ROM image appropriate for your system
|
||||
and boot under that new ROM. You may want to use
|
||||
a different ROM chip in case the new version does
|
||||
not work.
|
||||
|
||||
If you are using "boot from disk", you will need
|
||||
to update the OS image on all drives you boot from.
|
||||
To do this, use SYSCOPY. Something like this
|
||||
would make sense:
|
||||
|
||||
B:SYSCOPY C:=B:ZSYS.SYS
|
||||
|
||||
CPU Speed & Baud Rate
|
||||
---------------------
|
||||
|
||||
The startup serial port baud rate in all pre-built
|
||||
RomWBW variants is 38.4Kbps. While this speed is
|
||||
nice in that it provides great display and file
|
||||
transfer performance, it does push the limits of
|
||||
slower hardware. Specifically, XModem v12.5 (the
|
||||
default XM.COM) on the distribution is unable to
|
||||
service the serial port fast enough if the CPU is
|
||||
running at 4MHz. Your options are to 1) use the
|
||||
old version of XModem (XM5.COM), put a faster CPU
|
||||
oscillator in your system (6MHz or above), or
|
||||
3) decrease the baud rate by building a custom
|
||||
ROM.
|
||||
|
||||
UNA Variant
|
||||
-----------
|
||||
|
||||
RomWBW will now run under it's native BIOS (HBIOS) or
|
||||
under UNA BIOS (UBIOS). There are pre-built ROM
|
||||
images for UNA in the Output directory.
|
||||
|
||||
CP/M vs. ZSystem
|
||||
----------------
|
||||
|
||||
There are two OS variants included in this distribution
|
||||
and you may choose which one you prefer to use.
|
||||
|
||||
The traditional Digital Research (DRI) CP/M code is the first
|
||||
choice. The Doc
|
||||
directory contains a manual for CP/M usage (cpm22-m.pdf).
|
||||
If you are new to the N8VEM systems, I would currently
|
||||
recommend using the CP/M variant to start with simply
|
||||
because they have gone through more testing and you
|
||||
are less likely to encounter problems.
|
||||
|
||||
The other choice is to use the most popular non-DRI
|
||||
CP/M "clone" which is generally referred to as
|
||||
ZSystem. These are intended to be
|
||||
functionally equivalent to CP/M and should run all
|
||||
CP/M 2.2 code. They are optimized for the Z80 CPU
|
||||
(as opposed to 8080 for CP/M) and have some potentially
|
||||
useful improvements. Please refer to the Doc directory
|
||||
and look at the files for zsdos and zcpr (zsdos.pdf &
|
||||
zcpr.doc as well as ZSystem.txt).
|
||||
|
||||
Both variants are now included in the pre-built ROM images.
|
||||
You will be given the choice to boot either CP/M or
|
||||
ZSystem at startup.
|
||||
|
||||
Building a Custom ROM
|
||||
---------------------
|
||||
|
||||
I strongly suggest you start with burning one of the
|
||||
pre-built ROMs and making sure that works first. Once
|
||||
you have gotten past that hurdle, you should consider
|
||||
building a custom ROM. It is very easy and the
|
||||
distribution comes with everything that is needed to
|
||||
run a build on a Windows 32 bit or 64 bit system --
|
||||
basically Windows XP or above. There is also a
|
||||
Linux build now available.
|
||||
|
||||
Creating a custom ROM allows you to customize a lot
|
||||
of useful stuff like adding support for a DSKY if
|
||||
you have one.
|
||||
|
||||
Please refer to the Build.txt file in the Doc directory
|
||||
for detailed instructions for building a custom ROM. If
|
||||
you are using Linux, also read the LinuxBuild.txt file.
|
||||
|
||||
Formatting Media
|
||||
----------------
|
||||
|
||||
<TBD>
|
||||
|
||||
Creating Bootable Media
|
||||
-----------------------
|
||||
|
||||
<TBD>
|
||||
|
||||
Using Slices on Mass Storage Devices
|
||||
------------------------------------
|
||||
|
||||
<TBD>
|
||||
|
||||
Managing Console I/O
|
||||
--------------------
|
||||
|
||||
<TBD>
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Formatting Media
|
||||
- Making a Disk Bootable
|
||||
- Assigning disks/slices to drives
|
||||
- Managing the Console
|
||||
I realize these instructions are very minimal. I am happy to answer
|
||||
questions. You will find the Google Group 'N8VEM' to be a great
|
||||
source of information as well.
|
||||
221
RomList.txt
Normal file
221
RomList.txt
Normal file
@@ -0,0 +1,221 @@
|
||||
You should find the following ROM
|
||||
images in the Output driectory.
|
||||
Refer to the descriptions below to select
|
||||
one that matches your hardware
|
||||
configuration, burn it, and use it.
|
||||
|
||||
Note that there are no longer separate
|
||||
ROM images for CP/M and ZSystem. Both
|
||||
OS variants are now imbedded in the ROM
|
||||
image and you are given the ability to
|
||||
choose the one you want to boot at
|
||||
startup.
|
||||
|
||||
Note that all builds are now set for 512KB ROMs.
|
||||
The builds will work fine in 1MB ROMs. If you
|
||||
want to use the full 1MB ROM address space, just
|
||||
do a cutom build.
|
||||
|
||||
Note that all builds are now set for 38.4Kbps
|
||||
baud rate on the console with 8 data bits, no
|
||||
parity, and 1 stop bit. The baud rate can be
|
||||
changed in the config file if you want to do a
|
||||
custom build.
|
||||
|
||||
N8VEM_std.rom for N8VEM Z80 SBC V1/V2:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- Drives A:=ROM, B:=RAM
|
||||
|
||||
N8VEM_diskio.rom for N8VEM Z80 SBC V1/V2 + DISKIO:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via DISKIO
|
||||
- IDE support via DISKIO
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=IDE0-00, F:=IDE0-01, G:=IDE0-02, H:=IDE0-03
|
||||
|
||||
N8VEM_dide.rom for N8VEM Z80 SBC V1/V2 + DUAL IDE:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via DISKIO
|
||||
- IDE support via DISKIO
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=IDE0-00, F:=IDE0-01, G:=IDE0-02, H:=IDE0-03
|
||||
|
||||
N8VEM_diskio3.rom for N8VEM Z80 SBC V1/V2 + DISKIO3:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via DISKIO3
|
||||
- IDE support via DISKIO3
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=IDE0-00, F:=IDE0-01, G:=IDE0-02, H:=IDE0-03
|
||||
|
||||
N8VEM_diskio3+cvdu.rom for N8VEM Z80 SBC V1/V2 + DISKIO3:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via DISKIO3
|
||||
- IDE support via DISKIO3
|
||||
- ColorVDU board support
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=IDE0-00, F:=IDE0-01, G:=IDE0-02, H:=IDE0-03
|
||||
- NOTE: Console defaults to CRT & PS/2 Keyboard. Short JP2
|
||||
(one bit input port) to use the serial port as the console.
|
||||
|
||||
N8VEM_ppide.rom for N8VEM Z80 SBC V1/V2 + PPIDE:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- IDE support via DISKIO
|
||||
- Drives A:=ROM, B:=RAM, C:=PPIDE0-00, D:=PPIDE0-01, E:=PPIDE0-02, F:=PPIDE0-03
|
||||
|
||||
N8VEM_ppisd.rom for N8VEM Z80 SBC V1/V2 + PPISD:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- PPISD support
|
||||
- Drives A:=ROM, B:=RAM, C:=SD0-00, D:=SD0-01, E:=SD0-02, F:=SD0-03
|
||||
|
||||
N8VEM_dsd.rom for N8VEM Z80 SBC V1/V2 + Dual SD:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Dual SD support
|
||||
- Drives A:=ROM, B:=RAM, C:=SD0-00, D:=SD0-01, E:=SD0-02, F:=SD0-03
|
||||
|
||||
N8VEM_propio.rom for N8VEM Z80 SBC V1/V2 + PROPIO:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- SD Card support via PropIO
|
||||
- VGA console support via PropIO
|
||||
- PS/2 Keyboard support via PropIO
|
||||
- Drives A:=ROM, B:=RAM, C:=PRPSD0-00, D:=PRPSD0-01, E:=PRPSD0-02, F:=PRPSD0-03
|
||||
- WARNING: You must use the RomWBW specific firmware
|
||||
for the Propeller found in the Support directory!
|
||||
- NOTE: Console defaults to VGA & PS/2 Keyboard. Short JP2
|
||||
(one bit input port) to use the serial port as the console.
|
||||
|
||||
N8VEM_mfp.rom for N8VEM Z80 SBC V1/V2:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy)
|
||||
- Drives A:=ROM, B:=RAM, C:=PPIDE0-00, D:=PPIDE0-01, E:=PPIDE0-02, F:=PPIDE0-03
|
||||
- IDE support via Multifunction / PIC
|
||||
- Second UART via Multifunction / PIC
|
||||
|
||||
N8VEM_ci.rom for N8VEM Z80 SBC V1/V2:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- Drives A:=ROM, B:=RAM
|
||||
- Cassette Interface mapped to RDR/PUN
|
||||
|
||||
N8VEM_simh.rom for N8VEM SIMH Simulator:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- Drives A:=ROM, B:=RAM, C:=HDSK0-00, D:=HDSK0-01, E:=HDSK0-02, F:=HDSK0-03
|
||||
|
||||
N8VEM_rf.rom for N8VEM Z80 SBC V1/2 + RAM Flopppy:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- RAM Floppy support
|
||||
- Drives A:=ROM, B:=RAM, C:=RF0, D:=RF1
|
||||
|
||||
N8VEM_vdu.rom for N8VEM Z80 SBC V1/V2:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- VDU board support
|
||||
- Drives A:=ROM, B:=RAM
|
||||
- NOTE: Console defaults to CRT & PS/2 Keyboard. Short JP2
|
||||
(one bit input port) to use the serial port as the console.
|
||||
|
||||
N8VEM_cvdu.rom for N8VEM Z80 SBC V1/V2:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- ColorVDU board support
|
||||
- Drives A:=ROM, B:=RAM
|
||||
- NOTE: Console defaults to CRT & PS/2 Keyboard. Short JP2
|
||||
(one bit input port) to use the serial port as the console.
|
||||
|
||||
ZETA_std.rom for Zeta Z80 SBC:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via built-in FDC
|
||||
- PPIDE support via built-in PPI
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=PPIDE00-0, F:=PPIDE0-01, G:=PPIDE0-02, H:=PPIDE0-03
|
||||
|
||||
ZETA_ppp.rom for Zeta Z80 SBC w/ ParPortProp:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via built-in FDC
|
||||
- SD Card support via ParPortProp
|
||||
- VGA console support via ParPortProp
|
||||
- PS/2 Keyboard support via ParPortProp
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=PPPSD0-00, F:=PPPSD0-01, F:=PPPSD0-02, G:=PPPSD0-03
|
||||
- WARNING: You must use the RomWBW specific firmware
|
||||
for the Propeller found in the Support directory!
|
||||
- NOTE: Console defaults to VGA & PS/2 Keyboard. Short JP1 (CONFIG)
|
||||
to use the serial port as the console.
|
||||
|
||||
N8_2511.rom for N8 2511 Z180:
|
||||
- Assumes oscillator frequency of 18.432MHz
|
||||
- CPU clock at X1 (18.432MHz)
|
||||
- 512KB ROM, 1MB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via built-in FDC
|
||||
- SD card support via built-in SD card slot
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=SD0-00, F:=SD0-01, G:=SD0-02, H:=SD0-03
|
||||
|
||||
N8_2312.rom for N8 2312 Z180:
|
||||
- Assumes oscillator frequency of 18.432MHz
|
||||
- CPU clock at X1 (18.432MHz)
|
||||
- 512KB ROM, 1MB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk
|
||||
- Floppy support via built-in FDC
|
||||
- SD card support via built-in SD card slot
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=SD0-00, F:=SD0-01, G:=SD0-02, H:=SD0-03
|
||||
|
||||
MK4_std.rom for Mark IV Z180 SBC:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- Onboard SD Card
|
||||
- Onboard IDE
|
||||
- Drives A:=ROM, B:=RAM, C:=SD0-0, D:=SD0-1, E:=IDE0-00, F:=IDE0-01
|
||||
|
||||
MK4_diskio3.rom for Mark IV Z180 SBC:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- Floppy support via DISKIO3
|
||||
- IDE support via DISKIO3
|
||||
- Drives A:=ROM, B:=RAM, C:=FD0, D:=FD1, E:=IDE0-00, F:=IDE0-01, G:=IDE0-02, H:=IDE0-03
|
||||
|
||||
MK4_propio.rom for Mark IV Z180 SBC:
|
||||
- 512KB ROM, 512KB RAM
|
||||
- 38.4KB serial console baud rate
|
||||
- Basic ROM/RAM disk (no floppy/IDE)
|
||||
- SD Card support via PropIO
|
||||
- VGA console support via PropIO
|
||||
- PS/2 Keyboard support via PropIO
|
||||
- Drives A:=ROM, B:=RAM, C:=PRPSD0-00, D:=PRPSD0-01, E:=PRPSD0-02, F:=PRPSD0-03
|
||||
- WARNING: You must use the RomWBW specific firmware
|
||||
for the Propeller found in the Support directory!
|
||||
- NOTE: Console defaults to VGA & PS/2 Keyboard. Short JP2
|
||||
(one bit input port) to use the serial port as the console.
|
||||
|
||||
UNA_std.rom for all UNA support platforms (SBC V1/2, Zeta, N8, Mark IV)
|
||||
- 512KB ROM
|
||||
- Initial baud rate is 9600, but can be configured
|
||||
- Resources are managed dynamically by UNA BIOS
|
||||
- Refer to UNA project for more details
|
||||
@@ -1,12 +1,18 @@
|
||||
; $Id: n8vem 1969 2008-06-26 05:57:30Z hharte $
|
||||
;
|
||||
; SIMH/AltairZ80 Configuration file for the N8VEM SBC
|
||||
; http://groups.google.com/group/n8vem/web/n8vem-single-board-computer-home-page
|
||||
;
|
||||
; Copyright (c) 2008 Howard M. Harte
|
||||
|
||||
set cpu z80
|
||||
;set throttle 4K
|
||||
set cpu noaltairrom
|
||||
set n8vem enabled
|
||||
;set n8vem enabled debug=verbose
|
||||
set n8vem enabled debug=verbose
|
||||
set debug debug.log
|
||||
|
||||
; Console
|
||||
; set console telnet=23
|
||||
set console telnet=23
|
||||
|
||||
; Configure Serial Port (Basic polled 16550 UART)
|
||||
set sio tty
|
||||
@@ -22,9 +28,9 @@ echo ROM Image: '%1'
|
||||
attach n8vem0 %1
|
||||
|
||||
; hard disks
|
||||
;set hdsk debug=read;write;verbose
|
||||
attach hdsk0 ..\..\Binary\hd0.img
|
||||
attach hdsk1 ..\..\Binary\hd1.img
|
||||
set hdsk debug=read;write;verbose
|
||||
attach hdsk0 hd0.img
|
||||
attach hdsk1 hd1.img
|
||||
set hdsk0 format=HDSK
|
||||
set hdsk1 format=HDSK
|
||||
set hdsk0 geom=T:520/N:256/S:512
|
||||
@@ -32,14 +38,6 @@ set hdsk1 geom=T:520/N:256/S:512
|
||||
set hdsk0 wrtenb
|
||||
set hdsk1 wrtenb
|
||||
|
||||
; enable timer interrupt, 50Hz
|
||||
; DDT, SID, etc. use the normal IM 1 vector 6 ($38)
|
||||
; for breakpoints so we use vector 6 ($30)
|
||||
d timd 20
|
||||
;d timh 38
|
||||
d timh 30
|
||||
set simh timeron
|
||||
|
||||
; start emulation
|
||||
echo
|
||||
go
|
||||
1232
Source/Apps/Assign - Copy.asm
Normal file
1232
Source/Apps/Assign - Copy.asm
Normal file
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,6 @@
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; Change Log:
|
||||
; 2016-03-21 [WBW] Updated for HBIOS 2.8
|
||||
; 2016-04-08 [WBW] Determine key memory addresses dynamically
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; ToDo:
|
||||
@@ -39,7 +37,7 @@ bdos .equ $0005 ; BDOS invocation vector
|
||||
stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp
|
||||
;
|
||||
rmj .equ 2 ; CBIOS version - major
|
||||
rmn .equ 8 ; CBIOS version - minor
|
||||
rmn .equ 6 ; CBIOS version - minor
|
||||
;
|
||||
;===============================================================================
|
||||
; Code Section
|
||||
@@ -78,11 +76,11 @@ exit: ; clean up and return to command processor
|
||||
;
|
||||
init:
|
||||
;
|
||||
; locate start of cbios (function jump table)
|
||||
; locate cbios function table address
|
||||
ld hl,(restart+1) ; load address of CP/M restart vector
|
||||
ld de,-3 ; adjustment for start of table
|
||||
add hl,de ; HL now has start of table
|
||||
ld (bioloc),hl ; save it
|
||||
ld (cbftbl),hl ; save it
|
||||
;
|
||||
; get location of config data and verify integrity
|
||||
ld hl,stamp ; HL := adr or RomWBW zero page stamp
|
||||
@@ -134,60 +132,23 @@ init:
|
||||
ld c,a ; set BC := 0A
|
||||
ld b,0 ; ... so BC is length to copy
|
||||
ldir ; do the copy
|
||||
;
|
||||
; determine end of CBIOS (assume HBIOS for now)
|
||||
ld hl,($FFFE) ; get proxy start address
|
||||
ld (bioend),hl ; save as CBIOS end address
|
||||
;
|
||||
; check for UNA (UBIOS)
|
||||
ld a,($FFFD) ; fixed location of UNA API vector
|
||||
cp $C3 ; jp instruction?
|
||||
ld a,($fffd) ; fixed location of UNA API vector
|
||||
cp $c3 ; jp instruction?
|
||||
jr nz,initx ; if not, not UNA
|
||||
ld hl,($FFFE) ; get jp address
|
||||
ld hl,($fffe) ; get jp address
|
||||
ld a,(hl) ; get byte at target address
|
||||
cp $FD ; first byte of UNA push ix instruction
|
||||
cp $fd ; first byte of UNA push ix instruction
|
||||
jr nz,initx ; if not, not UNA
|
||||
inc hl ; point to next byte
|
||||
ld a,(hl) ; get next byte
|
||||
cp $E5 ; second byte of UNA push ix instruction
|
||||
cp $e5 ; second byte of UNA push ix instruction
|
||||
jr nz,initx ; if not, not UNA
|
||||
ld hl,unamod ; point to UNA mode flag
|
||||
ld (hl),$FF ; set UNA mode flag
|
||||
ld c,$F1 ; UNA func: Get HMA
|
||||
rst 08 ; call UNA, HL := UNA proxy start address
|
||||
ld (bioend),hl ; save as CBIOS end address
|
||||
ld (hl),$ff ; set UNA mode
|
||||
;
|
||||
initx:
|
||||
; compute size of CBIOS
|
||||
ld hl,(bioend) ; HL := end address
|
||||
ld de,(bioloc) ; DE := starting address
|
||||
xor a ; clear carry
|
||||
sbc hl,de ; subtract to get size in HL
|
||||
ld (biosiz),hl ; and save it
|
||||
;
|
||||
; establish heap limit
|
||||
ld hl,(bioend) ; HL := end of CBIOS address
|
||||
ld de,-$40 ; allow 40 bytes for CBIOS stack
|
||||
add hl,de ; adjust
|
||||
ld (heaplim),hl ; save it
|
||||
;
|
||||
#if 0
|
||||
ld a,' '
|
||||
call crlf
|
||||
ld bc,(bioloc)
|
||||
call prthexword
|
||||
call prtchr
|
||||
ld bc,(bioend)
|
||||
call prthexword
|
||||
call prtchr
|
||||
ld bc,(maploc)
|
||||
call prthexword
|
||||
call prtchr
|
||||
ld bc,(heaplim)
|
||||
call prthexword
|
||||
|
||||
#endif
|
||||
;
|
||||
; return success
|
||||
xor a ; signal success
|
||||
ret ; return
|
||||
@@ -313,7 +274,7 @@ usage:
|
||||
call crlf2 ; blank line
|
||||
ld de,msguse ; point to usage message
|
||||
call prtstr ; print it
|
||||
or $FF ; signal no action performed
|
||||
or $ff ; signal no action performed
|
||||
ret ; and return
|
||||
;
|
||||
devlist:
|
||||
@@ -322,24 +283,28 @@ devlist:
|
||||
or a ; set flags
|
||||
jr nz,devlstu ; do UNA mode dev list
|
||||
;
|
||||
ld b,$F8 ; hbios func: sysget
|
||||
ld c,$10 ; sysget subfunc: diocnt
|
||||
rst 08 ; call hbios, E := device count
|
||||
ld b,e ; use device count for loop count
|
||||
ld b,$1a ; hbios func: diodevcnt
|
||||
rst 08 ; call hbios, device count to B
|
||||
ld c,0 ; use C for device index
|
||||
devlist1:
|
||||
call crlf ; formatting
|
||||
ld de,indent ; indent
|
||||
call prtstr ; ... to look nice
|
||||
push bc ; preserve loop control
|
||||
ld a,c ; device to A
|
||||
ld b,$1b ; hbios func: diodevinf
|
||||
rst 08 ; call hbios, return device/unit in C
|
||||
ld a,c ; device/unit to A
|
||||
push af ; save it
|
||||
call prtdev ; print device mnemonic
|
||||
pop af ; get device/unit back
|
||||
and $0f ; isolate unit num
|
||||
call prtdecb ; append unit num
|
||||
ld a,':' ; colon for device/unit format
|
||||
call prtchr ; print it
|
||||
pop bc ; restore loop control
|
||||
inc c ; next device index
|
||||
djnz devlist1 ; loop as needed
|
||||
or $FF ; signal no action taken
|
||||
or $ff ; signal no action taken
|
||||
ret ; done
|
||||
;
|
||||
devlstu:
|
||||
@@ -374,19 +339,19 @@ devlstu1:
|
||||
;
|
||||
install:
|
||||
; capture CBIOS snapshot and stack frame for error recovery
|
||||
ld hl,(bioloc) ; start of CBIOS
|
||||
ld hl,$e600 ; start of CBIOS
|
||||
ld de,$8000 ; save it here
|
||||
ld bc,(biosiz) ; size of CBIOS
|
||||
ld bc,$fc00 - $e600 ; size of CBIOS
|
||||
ldir ; save it
|
||||
ld (xstksav),sp ; save stack frame
|
||||
; clear CBIOS buffer area
|
||||
ld hl,(maploc) ; start fill at drive map
|
||||
ld a,(bioend + 1) ; msb of CBIOS end address to A
|
||||
ld a,$FC ; stop when msb is $FC
|
||||
install1:
|
||||
ld e,0 ; fill with null
|
||||
ld (hl),e ; fill next byte
|
||||
inc hl ; point to next byte
|
||||
cp h ; is H == msb of CBIOS end address?
|
||||
cp h ; is H == $FC?
|
||||
jr nz,install1 ; if not, loop
|
||||
;
|
||||
; determine the drive map entry count
|
||||
@@ -422,13 +387,15 @@ install3:
|
||||
ld de,(maploc) ; target is CBIOS map loc
|
||||
ldir ; do it
|
||||
;
|
||||
; set start of memory allocation heap
|
||||
ld (heaptop),de ; DE has next byte available
|
||||
; set start of allocation memory
|
||||
ld (buftop),de ; DE has next byte available
|
||||
;
|
||||
; allocate directory buffer
|
||||
ld hl,128 ; size of directory buffer
|
||||
ld bc,128 ; size of directory buffer
|
||||
call alloc ; allocate the space
|
||||
jp c,instovf ; handle overflow error
|
||||
jp nz,instovf ; handle overflow error
|
||||
push bc ; move mem pointer
|
||||
pop hl ; ... to hl
|
||||
ld (dirbuf),hl ; ... and save in dirbuf
|
||||
;
|
||||
dph_init:
|
||||
@@ -445,22 +412,22 @@ dph_init:
|
||||
dph_init1:
|
||||
; no DPH if drive not assigned
|
||||
ld a,(hl)
|
||||
cp $FF
|
||||
cp $ff
|
||||
jr nz,dph_init2
|
||||
ld de,0 ; not assigned, use DPH pointer of zero
|
||||
jr dph_init3
|
||||
;
|
||||
dph_init2:
|
||||
ld a,(hl) ; unit to A
|
||||
push bc ; save loop control
|
||||
push hl ; save drive map pointer
|
||||
ld hl,16 ; size of a DPH structure
|
||||
ld bc,16 ; size of a DPH structure
|
||||
call alloc ; allocate space for dph
|
||||
jp c,instovf ; handle overflow error
|
||||
push hl ; save DPH location
|
||||
push hl ; move DPH location
|
||||
jp nz,instovf ; handle overflow error
|
||||
push bc ; save DPH location
|
||||
push bc ; move DPH location
|
||||
pop de ; ... to DE
|
||||
call makdph ; make the DPH, unit in A from above
|
||||
ld a,(hl) ; device/unit to A
|
||||
call makdph ; make the DPH
|
||||
pop de ; restore DPH pointer to DE
|
||||
pop hl ; restore drive map pointer to HL
|
||||
pop bc ; restore loop control
|
||||
@@ -479,8 +446,8 @@ dph_init3:
|
||||
call crlf2
|
||||
ld de,indent
|
||||
call prtstr
|
||||
ld hl,(heaplim) ; subtract high water
|
||||
ld de,(heaptop) ; ... from top of cbios
|
||||
ld hl,$fc00 - $40 ; subtract high water
|
||||
ld de,(buftop) ; ... from top of cbios
|
||||
or a ; ... with cf clear
|
||||
sbc hl,de ; ... so hl gets bytes free
|
||||
call prtdecw ; print it
|
||||
@@ -537,7 +504,7 @@ makdphwbw: ; determine appropriate dpb (WBW mode)
|
||||
ld e,2 ; assume ram
|
||||
cp $00+1 ; ram?
|
||||
jr z,makdph0 ; yes, jump ahead
|
||||
and $F0 ; ignore unit nibble now
|
||||
and $f0 ; ignore unit nibble now
|
||||
ld e,6 ; assume floppy
|
||||
cp $10 ; floppy?
|
||||
jr z,makdph0 ; yes, jump ahead
|
||||
@@ -580,57 +547,19 @@ makdph1:
|
||||
dec de ; ... prefix data (cks & als buf sizes)
|
||||
call makdph2 ; handle cks buf, then fall thru for als buf
|
||||
ret nz ; bail out on error
|
||||
|
||||
;makdph2:
|
||||
; ex de,hl ; point hl to cks/als size adr
|
||||
; ld c,(hl) ; bc := cks/als size
|
||||
; inc hl ; ... and bump
|
||||
; ld b,(hl) ; ... past
|
||||
; inc hl ; ... cks/als size
|
||||
; ex de,hl ; bc and hl roles restored
|
||||
; ld a,b ; check to see
|
||||
; or c ; ... if bc is zero
|
||||
; jr z,makdph3 ; if zero, bypass alloc, use zero for address
|
||||
; call alloc ; alloc bc bytes, address returned in bc
|
||||
; jp nz,instovf ; handle overflow error
|
||||
;makdph3:
|
||||
; ld (hl),c ; save cks/als buf
|
||||
; inc hl ; ... address in
|
||||
; ld (hl),b ; ... dph and bump
|
||||
; inc hl ; ... to next dph entry
|
||||
; xor a ; signal success
|
||||
; ret
|
||||
|
||||
makdph2:
|
||||
; DE = address of CKS or ALS buf to allocate
|
||||
; HL = address of field in DPH to get allocated address
|
||||
push hl ; save DPH field ptr
|
||||
pop bc ; into BC
|
||||
;
|
||||
; HL := alloc size, DE bumped
|
||||
ex de,hl
|
||||
ld e,(hl) ; get size to allocate
|
||||
inc hl ; ...
|
||||
ld d,(hl) ; ... into HL
|
||||
inc hl ; and bump DE
|
||||
ex de,hl
|
||||
;
|
||||
; check for size of zero, special case
|
||||
ld a,h ; check to see
|
||||
or l ; ... if hl is zero
|
||||
jr z,makdph3 ; if so, jump ahead using hl as address
|
||||
;
|
||||
; allocate memory
|
||||
call alloc ; do the allocation
|
||||
jp c,instovf ; bail out on overflow
|
||||
|
||||
ex de,hl ; point hl to cks/als size adr
|
||||
ld c,(hl) ; bc := cks/als size
|
||||
inc hl ; ... and bump
|
||||
ld b,(hl) ; ... past
|
||||
inc hl ; ... cks/als size
|
||||
ex de,hl ; bc and hl roles restored
|
||||
ld a,b ; check to see
|
||||
or c ; ... if bc is zero
|
||||
jr z,makdph3 ; if zero, bypass alloc, use zero for address
|
||||
call alloc ; alloc bc bytes, address returned in bc
|
||||
jp nz,instovf ; handle overflow error
|
||||
makdph3:
|
||||
; swap hl and bc
|
||||
push bc ; bc -> (sp)
|
||||
ex (sp),hl ; (sp) -> hl, hl -> (sp)
|
||||
pop bc ; (sp) -> bc
|
||||
;
|
||||
; save allocated address
|
||||
ld (hl),c ; save cks/als buf
|
||||
inc hl ; ... address in
|
||||
ld (hl),b ; ... dph and bump
|
||||
@@ -644,30 +573,40 @@ instovf:
|
||||
; restore stack frame and CBIOS image
|
||||
ld sp,(xstksav) ; restore stack frame
|
||||
ld hl,$8000 ; start of CBIOS image buffer
|
||||
ld de,(bioloc) ; start of CBIOS
|
||||
ld bc,(biosiz) ; size of CBIOS
|
||||
ld de,$e600 ; start of CBIOS
|
||||
ld bc,$fc00 - $e600 ; size of CBIOS
|
||||
ldir ; restore it
|
||||
jp errovf
|
||||
;
|
||||
; Allocate HL bytes from heap
|
||||
; Return pointer to allocated memory in HL
|
||||
; On overflow error, C set
|
||||
;
|
||||
alloc:
|
||||
push de ; save de so we can use it for work reg
|
||||
ld de,(heaptop) ; get current heap top
|
||||
push de ; and save for return value
|
||||
add hl,de ; add requested space, hl := new heap top
|
||||
jr c,allocx ; test for cpu memory space overflow
|
||||
ld de,(heaplim) ; load de with heap limit
|
||||
ex de,hl ; de=new heaptop, hl=heaplim
|
||||
sbc hl,de ; heaplim - heaptop
|
||||
jr c,allocx ; c set on overflow error
|
||||
; allocation succeeded, commit new heaptop
|
||||
ld (heaptop),de ; save new heaptop
|
||||
allocx:
|
||||
pop hl ; return value to hl
|
||||
pop de ; recover de
|
||||
;
|
||||
; allocate bc bytes from buf pool, return starting
|
||||
; address in bc. leave all other regs alone except a
|
||||
; z for success, nz for failure
|
||||
;
|
||||
push de ; save original de
|
||||
push hl ; save original hl
|
||||
ld hl,(buftop) ; hl := current buffer top
|
||||
push hl ; save as start of new buffer
|
||||
push bc ; get byte count
|
||||
pop de ; ... into de
|
||||
add hl,de ; add it to buffer top
|
||||
ld a,$ff ; assume overflow failure
|
||||
jr c,alloc1 ; if overflow, bypass with a == $ff
|
||||
push hl ; save it
|
||||
ld de,$10000 - $FC00 + $40 ; setup de for overflow test
|
||||
add hl,de ; check for overflow
|
||||
pop hl ; recover hl
|
||||
ld a,$ff ; assume failure
|
||||
jr c,alloc1 ; if overflow, continue with a == $ff
|
||||
ld (buftop),hl ; save new top
|
||||
inc a ; signal success
|
||||
;
|
||||
alloc1:
|
||||
pop bc ; buf start address to bc
|
||||
pop hl ; restore original hl
|
||||
pop de ; restore original de
|
||||
or a ; signal success
|
||||
ret
|
||||
;
|
||||
; Scan drive map table for integrity
|
||||
@@ -679,7 +618,7 @@ valid:
|
||||
ld b,16 - 1 ; loop one less times than num entries
|
||||
;
|
||||
; check that drive A: is assigned
|
||||
ld a,$FF ; value that indicates unassigned
|
||||
ld a,$ff ; value that indicates unassigned
|
||||
cp (hl) ; compare to A: value
|
||||
jp z,errnoa ; handle failure
|
||||
;
|
||||
@@ -705,11 +644,11 @@ valid2: ; setup for inner loop
|
||||
;
|
||||
valid3: ; inner loop
|
||||
; bypass unassigned drives (only need to test 1)
|
||||
ld a,(hl) ; get first drive unit in A
|
||||
cp $FF ; unassigned?
|
||||
ld a,(hl) ; get first drive device/unit in A
|
||||
cp $ff ; unassigned?
|
||||
jr z,valid4 ; yes, skip
|
||||
;
|
||||
; compare unit/slice values
|
||||
; compare device/unit/slice values
|
||||
ld a,(de) ; first byte to A
|
||||
cp (hl) ; compare
|
||||
jr nz,valid4 ; if not equal, continue loop
|
||||
@@ -753,7 +692,7 @@ drvdel:
|
||||
rlca ; ... as drive num * 4
|
||||
call addhl ; get final table offset
|
||||
; wipe out the drive letter
|
||||
ld a,$FF ; dev/unit := $FF (unassigned)
|
||||
ld a,$ff ; dev/unit := $FF (unassigned)
|
||||
ld (hl),a ; do it
|
||||
xor a ; zero accum
|
||||
inc hl ; slice := 0
|
||||
@@ -829,7 +768,7 @@ drvswap:
|
||||
xor a ; signal success
|
||||
ret ; exit
|
||||
;
|
||||
; Assign drive to specified unit/slice
|
||||
; Assign drive to specified device/unit/slice
|
||||
;
|
||||
drvmap:
|
||||
; check for UNA mode
|
||||
@@ -862,46 +801,32 @@ drvmap1: ; loop through device table looking for a match
|
||||
djnz drvmap1 ; and loop
|
||||
jp errdev
|
||||
;
|
||||
drvmap2:
|
||||
; convert index to device type id
|
||||
ld a,c ; index to accum
|
||||
drvmap2: ; verify the unit is eligible for assignment (hard disk unit only!)
|
||||
ld a,c ; get the specified device number
|
||||
; call chktyp ; check it
|
||||
; jp nz,errtyp ; abort with bad unit error
|
||||
;
|
||||
; construct the requested dph table entry
|
||||
ld a,c ; C has device num
|
||||
rlca ; move it to upper nibble
|
||||
rlca ; ...
|
||||
rlca ; ...
|
||||
rlca ; ...
|
||||
ld (device),a ; save as device id
|
||||
ld c,a ; stash it back in C
|
||||
ld a,(unit) ; get the unit number
|
||||
or c ; combine device and unit
|
||||
ld c,a ; and save in C
|
||||
ld a,(slice) ; get the slice
|
||||
ld b,a ; and save in B
|
||||
;
|
||||
; loop thru hbios units looking for device type/unit match
|
||||
ld b,$F8 ; hbios func: sysget
|
||||
ld c,$10 ; sysget subfunc: diocnt
|
||||
rst 08 ; call hbios, E := device count
|
||||
ld b,e ; use device count for loop count
|
||||
ld c,0 ; use C for device index
|
||||
drvmap3:
|
||||
push bc ; preserve loop control
|
||||
ld b,$17 ; hbios func: diodevice
|
||||
rst 08 ; call hbios, D := device, E := unit
|
||||
pop bc ; restore loop control
|
||||
ld a,(device)
|
||||
cp d
|
||||
jr nz,drvmap4
|
||||
ld a,(unit)
|
||||
cp e
|
||||
jr z,drvmap5 ; match, continue, C = BIOS unit
|
||||
drvmap4:
|
||||
; continue looping
|
||||
inc c
|
||||
djnz drvmap3
|
||||
jp errdev ; invalid device specified
|
||||
; check for valid device/unit (supported by BIOS)
|
||||
push bc ; save device/unit/slice
|
||||
ld a,c ; device/unit to A
|
||||
call chkdev ; device/unit OK?
|
||||
pop bc ; restore device/unit/slice
|
||||
; jp nz,errdev ; invalid device specified
|
||||
ret nz
|
||||
;
|
||||
drvmap5:
|
||||
; check for valid unit (supported by BIOS)
|
||||
push bc ; save unit
|
||||
ld a,c ; unit to A
|
||||
call chkdev ; check validity
|
||||
pop bc ; restore unit
|
||||
ret nz ; bail out on error
|
||||
|
||||
; resolve the CBIOS DPH table entry
|
||||
ld a,(dstdrv) ; dest drv num to A
|
||||
call chkdrv ; valid drive?
|
||||
@@ -912,11 +837,10 @@ drvmap5:
|
||||
call addhl ; adjust HL to point to entry
|
||||
ld (dstptr),hl ; save it
|
||||
;
|
||||
; shove updated unit/slice into the entry
|
||||
ld (hl),c ; save unit byte
|
||||
; shove updated device/unit/slice into the entry
|
||||
ld (hl),c ; save device/unit byte
|
||||
inc hl ; bump to next byte
|
||||
ld a,(slice)
|
||||
ld (hl),a ; save slice
|
||||
ld (hl),b ; save slice
|
||||
;
|
||||
; finish up
|
||||
ld a,(dstdrv) ; get the destination drive
|
||||
@@ -987,7 +911,14 @@ drvmapu1:
|
||||
call addhl ; adjust HL to point to entry
|
||||
ld (dstptr),hl ; save it
|
||||
;
|
||||
; shove updated unit/slice into the entry
|
||||
; ; verify the drive letter being assigned is a hard disk
|
||||
; ld a,(hl) ; get the device/unit byte
|
||||
; push hl ; save pointer
|
||||
; call chktypu ; check it
|
||||
; pop hl ; recover pointer
|
||||
; jp nz,errtyp ; abort with bad device type error
|
||||
;
|
||||
; shove updated device/unit/slice into the entry
|
||||
ld a,(unit) ; get specified unit
|
||||
ld (hl),a ; save it
|
||||
inc hl ; next byte is slice
|
||||
@@ -1009,17 +940,15 @@ showall:
|
||||
ld c,0 ; map index (drive letter)
|
||||
;
|
||||
ld a,b ; load count
|
||||
or $FF ; signal no action
|
||||
or $ff ; signal no action
|
||||
ret z ; bail out if zero
|
||||
;
|
||||
showall1: ; loop
|
||||
ld a,c ;
|
||||
push bc ; save loop control
|
||||
call showass
|
||||
pop bc ; restore loop control
|
||||
inc c
|
||||
djnz showall1
|
||||
or $FF
|
||||
or $ff
|
||||
ret
|
||||
;
|
||||
; Display drive letter assignment IF it is assigned
|
||||
@@ -1033,8 +962,8 @@ showass:
|
||||
rlca
|
||||
rlca
|
||||
call addhl ; HL = address of drive map table entry
|
||||
ld a,(hl) ; get unit value
|
||||
cp $FF ; compare to unassigned value
|
||||
ld a,(hl) ; get device/unit value
|
||||
cp $ff ; compare to unassigned value
|
||||
ld a,c ; recover original drive num
|
||||
ret z ; bail out if unassigned drive
|
||||
; fall thru to display drive
|
||||
@@ -1068,15 +997,16 @@ showone:
|
||||
call prtchr ; print it
|
||||
;
|
||||
; render the map entry
|
||||
ld a,(hl) ; load unit
|
||||
ld a,(hl) ; load device/unit
|
||||
cp $FF ; empty?
|
||||
ret z ; yes, bypass
|
||||
push hl ; preserve HL
|
||||
call prtdev ; print device mnemonic
|
||||
ld a,':' ; colon for device/unit format
|
||||
call prtchr ; print it
|
||||
pop hl ; recover HL
|
||||
ld a,(hl) ; load device/unit again
|
||||
and $0f ; isolate unit num
|
||||
call prtdecb ; print it
|
||||
inc hl ; point to slice num
|
||||
ld a,':' ; colon to separate slice
|
||||
call prtchr ; print it
|
||||
ld a,(hl) ; load slice num
|
||||
call prtdecb ; print it
|
||||
;
|
||||
@@ -1085,11 +1015,11 @@ showone:
|
||||
; Force BDOS to reset (logout) all drives
|
||||
;
|
||||
drvrst:
|
||||
ld c,$0D ; BDOS Reset Disk function
|
||||
ld c,$0d ; BDOS Reset Disk function
|
||||
call bdos ; do it
|
||||
;
|
||||
ld c,$25 ; BDOS Reset Multiple Drives
|
||||
ld de,$FFFF ; all drives
|
||||
ld de,$ffff ; all drives
|
||||
call bdos ; do it
|
||||
;
|
||||
xor a ; signal success
|
||||
@@ -1103,16 +1033,11 @@ prtdev:
|
||||
or a ; set flags
|
||||
ld a,e ; put device num back
|
||||
jr nz,prtdevu ; print device in UNA mode
|
||||
ld b,$17 ; hbios func: diodevice
|
||||
ld c,a ; unit to C
|
||||
rst 08 ; call hbios, D := device, E := unit
|
||||
push de ; save results
|
||||
ld a,d ; device to A
|
||||
rrca ; isolate high nibble (device)
|
||||
rrca ; ...
|
||||
rrca ; ...
|
||||
rrca ; ... into low nibble
|
||||
and $0F ; mask out undesired bits
|
||||
and $0f ; mask out undesired bits
|
||||
push hl ; save HL
|
||||
add a,a ; multiple A by two for word table
|
||||
ld hl,devtbl ; point to start of device name table
|
||||
@@ -1123,63 +1048,54 @@ prtdev:
|
||||
ld e,a ; ...
|
||||
call prtstr ; print the device nmemonic
|
||||
pop hl ; restore HL
|
||||
pop de ; get device/unit data back
|
||||
ld a,e ; device id to a
|
||||
call prtdecb ; print it
|
||||
ret ; done
|
||||
;
|
||||
prtdevu:
|
||||
ld e,a ; save unit num in E
|
||||
push bc
|
||||
push de
|
||||
push hl
|
||||
;
|
||||
; UNA mode version of print device
|
||||
ld b,a ; B := unit num
|
||||
push bc ; save for later
|
||||
ld c,$48 ; UNA func: get disk type
|
||||
rst 08 ; call UNA
|
||||
ld a,d ; disk type to A
|
||||
pop bc ; get unit num back in C
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
;
|
||||
; pick string based on disk type
|
||||
cp $40 ; RAM/ROM?
|
||||
jr z,prtdevu1 ; if so, handle it
|
||||
cp $41 ; IDE?
|
||||
ld de,udevide ; load string
|
||||
jr z,prtdevu2 ; if IDE, print and return
|
||||
jp z,prtstr ; if IDE, print and return
|
||||
cp $42 ; PPIDE?
|
||||
ld de,udevppide ; load string
|
||||
jr z,prtdevu2 ; if PPIDE, print and return
|
||||
jp z,prtstr ; if PPIDE, print and return
|
||||
cp $43 ; SD?
|
||||
ld de,udevsd ; load string
|
||||
jr z,prtdevu2 ; if SD, print and return
|
||||
jp z,prtstr ; if SD, print and return
|
||||
cp $44 ; DSD?
|
||||
ld de,udevdsd ; load string
|
||||
jr z,prtdevu2 ; if DSD, print and return
|
||||
jp z,prtstr ; if DSD, print and return
|
||||
ld de,udevunk ; load string for unknown
|
||||
jr prtdevu2 ; and print it
|
||||
jp prtstr ; and print it
|
||||
;
|
||||
prtdevu1:
|
||||
; handle RAM/ROM
|
||||
push bc ; save unit num
|
||||
push bc
|
||||
push hl
|
||||
ld b,e ; unit num to B
|
||||
ld c,$45 ; UNA func: get disk info
|
||||
ld de,$9000 ; 512 byte buffer *** FIX!!! ***
|
||||
rst 08 ; call UNA
|
||||
bit 7,b ; test RAM drive bit
|
||||
pop bc ; restore unit num
|
||||
ld de,udevrom ; load string
|
||||
jr z,prtdevu2 ; print and return
|
||||
ld de,udevram ; load string
|
||||
jr prtdevu2 ; print and return
|
||||
;
|
||||
prtdevu2:
|
||||
call prtstr ; print the device nmemonic
|
||||
ld a,b ; get the unit num back
|
||||
call prtdecb ; append it
|
||||
pop hl
|
||||
pop de
|
||||
pop bc
|
||||
ret
|
||||
ld de,udevrom ; load string
|
||||
jp z,prtstr ; print and return
|
||||
ld de,udevram ; load string
|
||||
jp prtstr ; print and return
|
||||
;
|
||||
; Check that specified drive num is valid
|
||||
;
|
||||
@@ -1189,32 +1105,36 @@ chkdrv:
|
||||
cp a ; set Z to signal good
|
||||
ret ; and return
|
||||
;
|
||||
; Check that the unit value in A is valid
|
||||
; Check that the device/unit value in A is valid
|
||||
; according to active BIOS support.
|
||||
;
|
||||
;
|
||||
chkdev: ; HBIOS variant
|
||||
push af ; save incoming unit
|
||||
ld b,$F8 ; hbios func: sysget
|
||||
ld c,$10 ; sysget subfunc: diocnt
|
||||
rst 08 ; call hbios, E := device count
|
||||
pop af ; restore incoming unit
|
||||
cp e ; compare to unit count
|
||||
jp nc,errdev ; if too high, error
|
||||
push af ; save incoming device/unit
|
||||
ld b,$1a ; hbios func: diodevcnt
|
||||
rst 08 ; call hbios, device count to B
|
||||
ld c,0 ; use C for device index
|
||||
pop af ; restore incoming device/unit
|
||||
chkdev1:
|
||||
push bc ; preserve loop control
|
||||
push af ; save incoming device/unit
|
||||
ld b,$1b ; hbios func: diodevinf
|
||||
rst 08 ; call hbios, return device/unit in C
|
||||
pop af ; restore incoming device/unit
|
||||
cp c ; match to device/unit from BIOS list?
|
||||
pop bc ; restore loop control
|
||||
jr z,chkdev2 ; yes, match
|
||||
inc c ; next device list entry
|
||||
djnz chkdev1 ; loop as needed
|
||||
jp errdev ; no match, handle error
|
||||
;
|
||||
; get device/unit info
|
||||
ld b,$17 ; hbios func: diodevice
|
||||
ld c,a ; unit to C
|
||||
rst 08 ; call hbios, D := device, E := unit
|
||||
ld a,d ; device to A
|
||||
;
|
||||
; check slice support
|
||||
chkdev2: ; check slice support
|
||||
cp $30 ; A has device/unit, in hard disk range?
|
||||
jr c,chkdev1 ; if not hard disk, check slice val
|
||||
jr c,chkdev3 ; if not hard disk, check slice val
|
||||
xor a ; otherwise, signal OK
|
||||
ret
|
||||
;
|
||||
chkdev1: ; not a hard disk, make sure slice == 0
|
||||
chkdev3: ; not a hard disk, make sure slice == 0
|
||||
ld a,(slice) ; get specified slice
|
||||
or a ; set flags
|
||||
jp nz,errslc ; invalid slice error
|
||||
@@ -1328,7 +1248,7 @@ hexascii:
|
||||
; Convert low nibble of A to ascii hex
|
||||
;
|
||||
hexconv:
|
||||
and $0F ; low nibble only
|
||||
and $0f ; low nibble only
|
||||
add a,$90
|
||||
daa
|
||||
adc a,$40
|
||||
@@ -1422,7 +1342,7 @@ delim: or a
|
||||
ret z
|
||||
cp ':' ; colon
|
||||
ret z
|
||||
cp $3B ; semicolon
|
||||
cp $3b ; semicolon
|
||||
ret z
|
||||
cp '<' ; less than
|
||||
ret z
|
||||
@@ -1520,14 +1440,14 @@ strcmp:
|
||||
; The CBIOS function offset must be stored in the byte
|
||||
; following the call instruction. ex:
|
||||
; call cbios
|
||||
; .db $0C ; offset of CONOUT CBIOS function
|
||||
; .db $0c ; offset of CONOUT CBIOS function
|
||||
;
|
||||
cbios:
|
||||
ex (sp),hl
|
||||
ld a,(hl) ; get the function offset
|
||||
inc hl ; point past value following call instruction
|
||||
ex (sp),hl ; put address back at top of stack and recover HL
|
||||
ld hl,(bioloc) ; address of CBIOS function table to HL
|
||||
ld hl,(cbftbl) ; address of CBIOS function table to HL
|
||||
call addhl ; determine specific function address
|
||||
jp (hl) ; invoke CBIOS
|
||||
;
|
||||
@@ -1623,20 +1543,16 @@ err1: ; without the leading crlf
|
||||
;
|
||||
err2: ; without the string
|
||||
; call crlf ; print newline
|
||||
or $FF ; signal error
|
||||
or $ff ; signal error
|
||||
ret ; done
|
||||
;
|
||||
;===============================================================================
|
||||
; Storage Section
|
||||
;===============================================================================
|
||||
;
|
||||
;
|
||||
bioloc .dw 0 ; CBIOS starting address
|
||||
bioend .dw 0 ; CBIOS ending address
|
||||
biosiz .dw 0 ; CBIOS size (in bytes)
|
||||
cbftbl .dw 0 ; address of CBIOS function table
|
||||
maploc .dw 0 ; location of CBIOS drive map table
|
||||
dpbloc .dw 0 ; location of CBIOS DPB map table
|
||||
;
|
||||
drives:
|
||||
dstdrv .db 0 ; destination drive
|
||||
srcdrv .db 0 ; source drive
|
||||
@@ -1644,7 +1560,7 @@ device .db 0 ; source device
|
||||
unit .db 0 ; source unit
|
||||
slice .db 0 ; source slice
|
||||
;
|
||||
unamod .db 0 ; $FF indicates UNA UBIOS active
|
||||
unamod .db 0 ; $ff indicates UNA UBIOS active
|
||||
modcnt .db 0 ; count of drive map modifications
|
||||
;
|
||||
srcptr .dw 0 ; source pointer for copy
|
||||
@@ -1652,9 +1568,7 @@ dstptr .dw 0 ; destination pointer for copy
|
||||
tmpent .fill 4,0 ; space to save a table entry
|
||||
tmpstr .fill 9,0 ; temporary string of up to 8 chars, zero term
|
||||
;
|
||||
heaptop .dw 0 ; current address of top of heap memory
|
||||
heaplim .dw 0 ; heap limit address
|
||||
;
|
||||
buftop .dw 0 ; memory allocation buffer top
|
||||
dirbuf .dw 0 ; directory buffer location
|
||||
;
|
||||
mapwrk .fill (4 * 16),$FF ; working copy of drive map
|
||||
@@ -1701,10 +1615,10 @@ stack .equ $ ; stack top
|
||||
; Messages
|
||||
;
|
||||
indent .db " ",0
|
||||
msgban1 .db "ASSIGN v1.0c for RomWBW CP/M 2.2, 21-Apr-2016",0
|
||||
msgban1 .db "ASSIGN v1.0 for RomWBW CP/M 2.2, 19-Sep-2014",0
|
||||
msghb .db " (HBIOS Mode)",0
|
||||
msgub .db " (UBIOS Mode)",0
|
||||
msgban2 .db "Copyright 2016, Wayne Warthen, GNU GPL v3",0
|
||||
msgban2 .db "Copyright 2014, Wayne Warthen, GNU GPL v3",0
|
||||
msguse .db "Usage: ASSIGN D:[=[{D:|<device>[<unitnum>]:[<slicenum>]}]][,...]",13,10
|
||||
.db " ex. ASSIGN (display all active assignments)",13,10
|
||||
.db " ASSIGN /? (display version and usage)",13,10
|
||||
@@ -1729,4 +1643,4 @@ msgnoa .db "Drive A: is unassigned, aborting!",0
|
||||
msgdos .db "DOS error, return code=0x",0
|
||||
msgmem .db " Disk Buffer Bytes Free",0
|
||||
;
|
||||
.end
|
||||
.end
|
||||
@@ -15,17 +15,13 @@ call :asm SysCopy || goto :eof
|
||||
call :asm Assign || goto :eof
|
||||
call :asm Format || goto :eof
|
||||
call :asm Talk || goto :eof
|
||||
call :asm OSLdr || goto :eof
|
||||
call :asm Mode || goto :eof
|
||||
|
||||
zx Z80ASM -SYSGEN/F
|
||||
|
||||
setlocal & cd XM125 && call Build || exit /b 1 & endlocal
|
||||
|
||||
goto :eof
|
||||
|
||||
:asm
|
||||
echo.
|
||||
echo Building %1...
|
||||
tasm -t80 -g3 -fFF %1.asm %1.com %1.lst
|
||||
tasm -t80 -b -g3 -fFF %1.asm %1.com %1.lst
|
||||
goto :eof
|
||||
@@ -1,8 +1,4 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
if exist *.bin del *.bin
|
||||
if exist *.com del *.com
|
||||
if exist *.lst del *.lst
|
||||
|
||||
setlocal & cd XM125 && call Clean || exit /b 1 & endlocal
|
||||
if exist *.lst del *.lst
|
||||
@@ -1,79 +0,0 @@
|
||||
;
|
||||
;==================================================================================================
|
||||
; DECODE 32-BIT VALUES FROM A 5-BIT SHIFT-ENCODED VALUE
|
||||
;==================================================================================================
|
||||
;
|
||||
; Copyright (C) 2014 John R. Coffman. All rights reserved.
|
||||
; Provided for hobbyist use on the Z180 SBC Mark IV board.
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU General Public License as published by
|
||||
; the Free Software Foundation, either version 3 of the License, or
|
||||
; (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; THE FUNCTION(S) IN THIS FILE ARE BASED ON LIKE FUNCTIONS CREATED BY JOHN COFFMAN
|
||||
; IN HIS UNA BIOS PROJECT. THEY ARE INCLUDED HERE BASED ON GPLV3 PERMISSIBLE USE.
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; An encoded value (V) is defined as V = C * 2^X * 3^Y
|
||||
; where C is a prearranged constant, X is 0 or 1 and Y is 0-15
|
||||
; The encoded value is stored as 5 bits: YXXXX
|
||||
; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; DECODE
|
||||
;
|
||||
; Enter with:
|
||||
; HL = word to be decoded (5-bits) FXXXX
|
||||
; F=extra 3 factor, XXXX=shift factor, reg H must be zero
|
||||
; DE = encode divisor OSC_DIV = 3, or BAUD_DIV = 75
|
||||
;
|
||||
; Exit with:
|
||||
; DE:HL = decoded value
|
||||
; A = non-zero on error
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
decode:
|
||||
ld a,h ; set to test
|
||||
ld c,$ff ; presume error condition
|
||||
or a ; test for zero
|
||||
jr nz,decode9 ; not an encoded value
|
||||
ld a,l ; get low order 5 bits
|
||||
cp 32 ; test for error
|
||||
jr nc,decode9 ; error return if not below
|
||||
; argument hl is validated
|
||||
ld h,d
|
||||
ld l,e ; copy to hl
|
||||
cp 16
|
||||
jr c,decode2 ; if < 16, no 3 factor
|
||||
add hl,de ; introduce factor of 3
|
||||
add hl,de ; **
|
||||
decode2:
|
||||
ld de,0 ; zero the high order
|
||||
and 15 ; mask to 4 bits
|
||||
jr z,decode8 ; good exit
|
||||
ld c,b ; save b-reg
|
||||
ld b,a ;
|
||||
decode3:
|
||||
add hl,hl ; shift left by 1, set carry
|
||||
rl e
|
||||
rl d ; **
|
||||
djnz decode3
|
||||
ld b,c ; restore b-reg
|
||||
decode8:
|
||||
ld c,0 ; signal good return
|
||||
decode9:
|
||||
ld a,c ; error code test
|
||||
or a ; error code in reg-c and z-flag
|
||||
ret
|
||||
@@ -1,75 +0,0 @@
|
||||
;
|
||||
;==================================================================================================
|
||||
; ENCODE 32-BIT VALUES TO A 5-BIT SHIFT-ENCODED VALUE
|
||||
;==================================================================================================
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; An encoded value (V) is defined as V = C * 2^X * 3^Y
|
||||
; where C is a prearranged constant, Y is 0 or 1 and X is 0-15
|
||||
; The encoded value is stored as 5 bits: YXXXX
|
||||
; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ENCODE
|
||||
;
|
||||
; Enter with:
|
||||
; DE:HL = dword value to be encoded
|
||||
; C = divisor (0 < C < 256)
|
||||
; encode divisor OSC_DIV = 3, or BAUD_DIV = 75
|
||||
;
|
||||
; Exit with:
|
||||
; C = encoded value
|
||||
; A = non-zero on error
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
encode:
|
||||
; incoming value of zero is a failure
|
||||
call encode5 ; test DE:HL for zero
|
||||
jr z,encode4 ; if zero, failure return
|
||||
;
|
||||
; apply encoding divisor
|
||||
call div32x8 ; DE:HL / C (remainder in A)
|
||||
or a ; set flags to test for zero
|
||||
ret nz ; error if not evenly divisible
|
||||
;
|
||||
; test divide by 3 to see if it is possible
|
||||
push de ; save working
|
||||
push hl ; ... value
|
||||
ld c,3 ; divide by 3
|
||||
call div32x8 ; ... test
|
||||
pop hl ; restore working
|
||||
pop de ; ... value
|
||||
;
|
||||
; implmement divide by 3 if possible
|
||||
ld c,$00 ; init result in c w/ div 3 flag clear
|
||||
or a ; set flags to test for remainder
|
||||
jr nz,encode2 ; jump if it failed
|
||||
;
|
||||
; if divide by 3 worked, do it again for real
|
||||
ld c,3 ; setup to divide by 3 again
|
||||
call div32x8 ; do it
|
||||
ld c,$10 ; init result in c w/ div 3 flag set
|
||||
;
|
||||
encode2:
|
||||
; loop to determine power of 2
|
||||
ld b,16 ; can only represent up to 2^15
|
||||
encode3:
|
||||
srl d ; right shift de:hl into carry
|
||||
rr e ; ...
|
||||
rr h ; ...
|
||||
rr l ; ...
|
||||
jr c,encode5 ; if carry, then done, c has result
|
||||
inc c ; bump the result value
|
||||
djnz encode3 ; keep shifting if possible
|
||||
encode4:
|
||||
or $ff ; signal error
|
||||
ret ; and done
|
||||
;
|
||||
encode5:
|
||||
; test de:hl for zero (sets zf, clobbers a)
|
||||
ld a,h
|
||||
or l
|
||||
or d
|
||||
or e
|
||||
ret ; ret w/ Z set if DE:HL == 0
|
||||
@@ -5,210 +5,24 @@
|
||||
; AUTHOR: WAYNE WARTHEN (wwarthen@gmail.com)
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; Usage:
|
||||
; FORMAT D:
|
||||
; ex: FORMAT (display version and usage)
|
||||
; FORMAT /? (display version and usage)
|
||||
; FORMAT C: (format drive C:)
|
||||
; CHANGELOG:
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; Change Log:
|
||||
; TODO:
|
||||
;
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; ToDo:
|
||||
; 1) Actually implement this
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
;===============================================================================
|
||||
; Definitions
|
||||
; MAIN PROGRAM PROCEDURE
|
||||
;===============================================================================
|
||||
;
|
||||
stksiz .equ $40 ; Working stack size
|
||||
.ORG 00100H
|
||||
RET
|
||||
;
|
||||
restart .equ $0000 ; CP/M restart vector
|
||||
bdos .equ $0005 ; BDOS invocation vector
|
||||
;;
|
||||
;stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp
|
||||
STACKSAV .DW 0
|
||||
STACKSIZ .EQU 40H ; WE ARE A STACK PIG
|
||||
.FILL STACKSIZ,0
|
||||
STACK .EQU $
|
||||
;
|
||||
rmj .equ 2 ; CBIOS version - major
|
||||
rmn .equ 8 ; CBIOS version - minor
|
||||
;
|
||||
;===============================================================================
|
||||
; Code Section
|
||||
;===============================================================================
|
||||
;
|
||||
;
|
||||
.org $100
|
||||
;
|
||||
; setup stack (save old value)
|
||||
ld (stksav),sp ; save stack
|
||||
ld sp,stack ; set new stack
|
||||
;
|
||||
; initialization
|
||||
call init ; initialize
|
||||
jr nz,exit ; abort if init fails
|
||||
;
|
||||
; do the real work
|
||||
call process ; parse and process command line
|
||||
jr nz,exit ; done if error or no action
|
||||
;
|
||||
exit: ; clean up and return to command processor
|
||||
call crlf ; formatting
|
||||
ld sp,(stksav) ; restore stack
|
||||
jp restart ; return to CP/M via restart
|
||||
ret ; return to CP/M w/o restart
|
||||
;
|
||||
; Initialization
|
||||
;
|
||||
init:
|
||||
;
|
||||
; locate start of cbios (function jump table)
|
||||
ld hl,(restart+1) ; load address of CP/M restart vector
|
||||
ld de,-3 ; adjustment for start of table
|
||||
add hl,de ; HL now has start of table
|
||||
ld (bioloc),hl ; save it
|
||||
;
|
||||
; check for UNA (UBIOS)
|
||||
ld a,($FFFD) ; fixed location of UNA API vector
|
||||
cp $C3 ; jp instruction?
|
||||
jr nz,initx ; if not, not UNA
|
||||
ld hl,($FFFE) ; get jp address
|
||||
ld a,(hl) ; get byte at target address
|
||||
cp $FD ; first byte of UNA push ix instruction
|
||||
jr nz,initx ; if not, not UNA
|
||||
inc hl ; point to next byte
|
||||
ld a,(hl) ; get next byte
|
||||
cp $E5 ; second byte of UNA push ix instruction
|
||||
jr nz,initx ; if not, not UNA
|
||||
ld hl,unamod ; point to UNA mode flag
|
||||
ld (hl),$FF ; set UNA mode flag
|
||||
;
|
||||
initx:
|
||||
;
|
||||
xor a
|
||||
ret
|
||||
;
|
||||
; Process command line
|
||||
;
|
||||
process:
|
||||
jr usage
|
||||
;
|
||||
xor a
|
||||
ret
|
||||
;
|
||||
usage:
|
||||
;
|
||||
call crlf ; formatting
|
||||
ld de,msgban1 ; point to version message part 1
|
||||
call prtstr ; print it
|
||||
ld a,(unamod) ; get UNA flag
|
||||
or a ; set flags
|
||||
ld de,msghb ; point to HBIOS mode message
|
||||
call z,prtstr ; if not UNA, say so
|
||||
ld de,msgub ; point to UBIOS mode message
|
||||
call nz,prtstr ; if UNA, say so
|
||||
call crlf ; formatting
|
||||
ld de,msgban2 ; point to version message part 2
|
||||
call prtstr ; print it
|
||||
call crlf2 ; blank line
|
||||
ld de,msguse ; point to usage message
|
||||
call prtstr ; print it
|
||||
xor a ; signal success
|
||||
ret ; and return
|
||||
;
|
||||
; Print character in A without destroying any registers
|
||||
;
|
||||
prtchr:
|
||||
push bc ; save registers
|
||||
push de
|
||||
push hl
|
||||
ld e,a ; character to print in E
|
||||
ld c,$02 ; BDOS function to output a character
|
||||
call bdos ; do it
|
||||
pop hl ; restore registers
|
||||
pop de
|
||||
pop bc
|
||||
ret
|
||||
;
|
||||
; Print a zero terminated string at (HL) without destroying any registers
|
||||
;
|
||||
prtstr:
|
||||
push de
|
||||
;
|
||||
prtstr1:
|
||||
ld a,(de) ; get next char
|
||||
or a
|
||||
jr z,prtstr2
|
||||
call prtchr
|
||||
inc de
|
||||
jr prtstr1
|
||||
;
|
||||
prtstr2:
|
||||
pop de ; restore registers
|
||||
ret
|
||||
;
|
||||
; Start a new line
|
||||
;
|
||||
crlf2:
|
||||
call crlf ; two of them
|
||||
crlf:
|
||||
push af ; preserve AF
|
||||
ld a,13 ; <CR>
|
||||
call prtchr ; print it
|
||||
ld a,10 ; <LF>
|
||||
call prtchr ; print it
|
||||
pop af ; restore AF
|
||||
ret
|
||||
;
|
||||
; Invoke CBIOS function
|
||||
; The CBIOS function offset must be stored in the byte
|
||||
; following the call instruction. ex:
|
||||
; call cbios
|
||||
; .db $0C ; offset of CONOUT CBIOS function
|
||||
;
|
||||
cbios:
|
||||
ex (sp),hl
|
||||
ld a,(hl) ; get the function offset
|
||||
inc hl ; point past value following call instruction
|
||||
ex (sp),hl ; put address back at top of stack and recover HL
|
||||
ld hl,(bioloc) ; address of CBIOS function table to HL
|
||||
call addhl ; determine specific function address
|
||||
jp (hl) ; invoke CBIOS
|
||||
;
|
||||
; Add the value in A to HL (HL := HL + A)
|
||||
;
|
||||
addhl:
|
||||
add a,l ; A := A + L
|
||||
ld l,a ; Put result back in L
|
||||
ret nc ; if no carry, we are done
|
||||
inc h ; if carry, increment H
|
||||
ret ; and return
|
||||
;
|
||||
; Jump indirect to address in HL
|
||||
;
|
||||
jphl:
|
||||
jp (hl)
|
||||
;
|
||||
;===============================================================================
|
||||
; Storage Section
|
||||
;===============================================================================
|
||||
;
|
||||
bioloc .dw 0 ; CBIOS starting address
|
||||
;
|
||||
unamod .db 0 ; $FF indicates UNA UBIOS active
|
||||
;
|
||||
stksav .dw 0 ; stack pointer saved at start
|
||||
.fill stksiz,0 ; stack
|
||||
stack .equ $ ; stack top
|
||||
;
|
||||
msgban1 .db "FORMAT v0.1 for RomWBW CP/M 2.2, 24-Apr-2016",0
|
||||
msghb .db " (HBIOS Mode)",0
|
||||
msgub .db " (UBIOS Mode)",0
|
||||
msgban2 .db "Copyright 2016, Wayne Warthen, GNU GPL v3",0
|
||||
msguse .db "FORMAT command is not yet implemented!",13,10,13,10
|
||||
.db "Use FD command to physically format floppy diskettes",13,10
|
||||
.db "Use CLRDIR command to (re)initialize directories",13,10
|
||||
.db "Use SYSCOPY command to make disks bootable",13,10
|
||||
.db "Use FDISK80 command to partition mass storage media",0
|
||||
;
|
||||
.end
|
||||
.END
|
||||
|
||||
1039
Source/Apps/Mode.asm
1039
Source/Apps/Mode.asm
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,6 @@
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; Change Log:
|
||||
; 2016-04-24 [WBW] Updated to preserve MBR partition table
|
||||
;_______________________________________________________________________________
|
||||
;
|
||||
; ToDo:
|
||||
@@ -32,8 +31,7 @@ stksiz .equ $40 ; we are a stack pig
|
||||
restart .equ $0000 ; CP/M restart vector
|
||||
bdos .equ $0005 ; BDOS invocation vector
|
||||
;
|
||||
imgbuf .equ $900 ; load point for system image (from original SYSGEN)
|
||||
mbrbuf .equ imgbuf+$4000 ; load point for MBR storage
|
||||
buf .equ $900 ; load point for system image (from original SYSGEN)
|
||||
;
|
||||
;===============================================================================
|
||||
; Code Section
|
||||
@@ -144,16 +142,16 @@ confirm:
|
||||
ld de,sconf3
|
||||
call prtstr
|
||||
;
|
||||
; get input (imgbuf is used for temp storage)
|
||||
; get input
|
||||
ld c,$0A ; get console buffer
|
||||
ld de,imgbuf ; into buf
|
||||
ld de,buf ; into buf
|
||||
ld a,1 ; max of 1 character
|
||||
ld (de),a ; set up buffer
|
||||
call bdos ; invoke BDOS
|
||||
ld a,(imgbuf+1) ; get num chars entered
|
||||
ld a,(buf+1) ; get num chars entered
|
||||
dec a ; check that we got exactly one char
|
||||
jr nz,confirm ; bad input, re-prompt
|
||||
ld a,(imgbuf+2) ; get the character
|
||||
ld a,(buf+2) ; get the character
|
||||
and $DF ; force upper case
|
||||
cp 'Y' ; compare to Y
|
||||
ret ; return with Z set appropriately
|
||||
@@ -192,7 +190,7 @@ rdfil:
|
||||
ld (rwfun),a ; save bdos function
|
||||
ld a,12 ; start with 1536 byte header (12 records)
|
||||
ld (reccnt),a ; init record counter
|
||||
ld hl,imgbuf ; start of buffer
|
||||
ld hl,buf ; start of buffer
|
||||
ld (bufptr),hl ; init buffer pointer
|
||||
call rwfil ; read the header
|
||||
ret nz ; abort on error (no need to close file)
|
||||
@@ -239,7 +237,7 @@ wrfil1: ; create target file
|
||||
ld (rwfun),a ; save bdos function
|
||||
ld a,(imgsiz) ; number of records to read
|
||||
ld (reccnt),a ; init record counter
|
||||
ld hl,imgbuf ; start of buffer
|
||||
ld hl,buf ; start of buffer
|
||||
ld (bufptr),hl ; init buffer pointer
|
||||
call rwfil ; do it
|
||||
ret nz ; abort on error
|
||||
@@ -331,36 +329,7 @@ wrdsk:
|
||||
; force return to go through disk reset
|
||||
ld hl,resdsk ; load address of reset disk routine
|
||||
push hl ; and put it on the stack
|
||||
; setup to read existing MBR
|
||||
ld a,(destfcb) ; get the drive
|
||||
dec a ; adjust for zero indexing
|
||||
call setdsk ; setup disk
|
||||
ret nz ; abort on error
|
||||
ld hl,mbrbuf ; override to read
|
||||
ld (bufptr),hl ; ... into MBR buffer
|
||||
ld a,4 ; 4 records = 1 512 byte sector
|
||||
; set function to read
|
||||
ld hl,(cbftbl) ; get address of CBIOS function table
|
||||
ld a,$27 ; $27 is CBIOS READ entry offset
|
||||
call addhl ; set HL to resultant entry point
|
||||
ld (actfnc),hl ; save it
|
||||
; read the existing MBR into memory
|
||||
call rwdsk ; read the sector
|
||||
ret nz ; abort on error
|
||||
; test for valid partition table ($55, $AA at offset $1FE)
|
||||
ld hl,(mbrbuf+$1FE); HL := signature
|
||||
ld a,$55 ; load expected value of first byte
|
||||
cp l ; check for proper value
|
||||
jr nz,wrdsk1 ; mismatch, ignore old partition table
|
||||
ld a,$AA ; load expected value of second byte
|
||||
cp h ; check for proper value
|
||||
jr nz,wrdsk1 ; mismatch, ignore old partition table
|
||||
; valid MBR, copy existing partition table over to new image
|
||||
ld hl,mbrbuf+$1BE ; copy from MBR offset of existing MBR
|
||||
ld de,imgbuf+$1BE ; copy to MBR offset of new image
|
||||
ld bc,$40 ; size of MBR
|
||||
ldir ; do it
|
||||
wrdsk1: ; setup to write the image from memory to disk
|
||||
; set drive for subsequent writes
|
||||
ld a,(destfcb) ; get the drive
|
||||
dec a ; adjust for zero indexing
|
||||
call setdsk ; setup disk
|
||||
@@ -427,7 +396,7 @@ setdsk:
|
||||
ld hl,0
|
||||
ld (acttrk),hl ; active track := 0
|
||||
ld (actsec),hl ; active sector := 0
|
||||
ld hl,imgbuf ; assume r/w to image buffer
|
||||
ld hl,buf
|
||||
ld (bufptr),hl ; reset buffer pointer
|
||||
;
|
||||
xor a ; signal success
|
||||
@@ -489,14 +458,14 @@ jphl: jp (hl) ; indirect jump
|
||||
;
|
||||
chkhdr:
|
||||
; check signature
|
||||
ld hl,(imgbuf+$580) ; get signature
|
||||
ld hl,(buf+$580) ; get signature
|
||||
ld de,$A55A ; signature value
|
||||
or a ; clear CF
|
||||
sbc hl,de ; compare
|
||||
jp nz,errsig ; invalid signature
|
||||
; compute the image size (does not include size of header)
|
||||
ld hl,(imgbuf+$5FC) ; get CPM_END
|
||||
ld de,(imgbuf+$5FA) ; get CPM_LOC
|
||||
ld hl,(buf+$5FC) ; get CPM_END
|
||||
ld de,(buf+$5FA) ; get CPM_LOC
|
||||
or a ; clear CF
|
||||
sbc hl,de ; image size := CPM_END - CPM_LOC
|
||||
xor a ; signal success
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set TOOLS=..\..\..\Tools
|
||||
|
||||
set PATH=%TOOLS%\zx;%PATH%
|
||||
|
||||
set ZXBINDIR=%TOOLS%\cpm\bin\
|
||||
set ZXLIBDIR=%TOOLS%\cpm\lib\
|
||||
set ZXINCDIR=%TOOLS%\cpm\include\
|
||||
|
||||
zx mac xmdm125
|
||||
zx slr180 -xmhb/HF
|
||||
zx mload25 XM=xmdm125,xmhb
|
||||
|
||||
rem set PROMPT=[Build] %PROMPT%
|
||||
rem %comspec%
|
||||
|
||||
move /Y XM.com ..
|
||||
@@ -1,7 +0,0 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
if exist *.hex del *.hex
|
||||
if exist *.prn del *.prn
|
||||
if exist *.lst del *.lst
|
||||
if exist xm.com del xm.com
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,361 +0,0 @@
|
||||
;=======================================================================
|
||||
;
|
||||
; XMHB.Z80 - XMODEMXX PATCH FILE FOR ROMWBW HBIOS
|
||||
;
|
||||
; Wayne Warthen - wwarthen@gmail.com
|
||||
; Updated: 2017-08-09
|
||||
;
|
||||
;=======================================================================
|
||||
;
|
||||
; Overlay file is Z80, build with M80:
|
||||
; M80 =XMHB
|
||||
; L80 XMHB,XMHB/N/X/E
|
||||
;
|
||||
.Z80
|
||||
ASEG
|
||||
;
|
||||
NO EQU 0
|
||||
YES EQU NOT NO
|
||||
;
|
||||
ERRDET EQU NO ; detect parity/framing/overrun errs
|
||||
;
|
||||
BASE EQU 100H ; start of cp/m normal program area
|
||||
;
|
||||
;=======================================================================
|
||||
;
|
||||
; Jump table: The jump table must be in exactly the same sequence as the
|
||||
; one in XMODEM. Note the ORG of 103H - This jump table has no jump to
|
||||
; 'BEGIN'.
|
||||
;
|
||||
ORG BASE + 3 ;start after 'JMP BEGIN'
|
||||
;
|
||||
JP CONOUT ;must be 00000h if not used, see below
|
||||
JP MINIT ;initialization routine (if needed)
|
||||
JP UNINIT ;undo whatever 'MINIT' did (or return)
|
||||
JPTBL:
|
||||
JP SENDR ;send character (via pop psw)
|
||||
JP CAROK ;test for carrier
|
||||
JP MDIN ;receive data byte
|
||||
JP GETCHR ;get character from modem
|
||||
JP RCVRDY ;check receive ready
|
||||
JP SNDRDY ;check send ready
|
||||
JP SPEED ;get speed value for file transfer time
|
||||
JP EXTRA1 ;extra for custom routine
|
||||
JP EXTRA2 ;extra for custom routine
|
||||
JP EXTRA3 ;extra for custom routine
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Output character to console
|
||||
;
|
||||
CONOUT EQU 0 ; not used
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Initialize modem
|
||||
;
|
||||
; This procedure has been usurped to dynamically detect the type
|
||||
; of system we are running on and install the *real* jump table
|
||||
; entries as appropriate.
|
||||
;
|
||||
MINIT:
|
||||
; Get system type
|
||||
LD D,2
|
||||
LD E,2
|
||||
MLT DE
|
||||
BIT 2,E ; bit 2 wil be set if mlt happend
|
||||
LD HL,U_JPTBL ; assume Z80 (UART)
|
||||
LD A,10 ; assume 10MHz CPU in case of Z80
|
||||
JR Z,MINIT2 ; yes, Z80, do vector copy
|
||||
LD HL,A_JPTBL ; otherwise Z180 (ASCI)
|
||||
LD A,20 ; assume 20MHz CPU in case of Z180
|
||||
;
|
||||
MINIT2:
|
||||
; Copy real vectors into active jump table
|
||||
LD DE,JPTBL
|
||||
LD BC,7 * 3 ; copy 7 3-byte entries
|
||||
LDIR
|
||||
;
|
||||
; Check for UNA (UBIOS)
|
||||
LD A,(0FFFDH) ; fixed location of UNA API vector
|
||||
CP 0C3H ; jp instruction?
|
||||
JR NZ,MINIT3 ; if not, not UNA
|
||||
LD HL,(0FFFEH) ; get jp address
|
||||
LD A,(HL) ; get byte at target address
|
||||
CP 0FDH ; first byte of UNA push ix instruction
|
||||
JR NZ,MINIT3 ; if not, not UNA
|
||||
INC HL ; point to next byte
|
||||
LD A,(HL) ; get next byte
|
||||
CP 0E5H ; second byte of UNA push ix instruction
|
||||
JR NZ,MINIT3 ; if not, not UNA
|
||||
;
|
||||
; Get CPU speed from UNA
|
||||
LD C,0F8H ; UNA BIOS Get PHI function
|
||||
RST 08 ; Returns speed in Hz in DE:HL
|
||||
LD A,E ; Hack to get approx speed in MHz
|
||||
SRL A ; ... by dividing by 1,048,576
|
||||
SRL A ; ...
|
||||
SRL A ; ...
|
||||
SRL A ; ...
|
||||
INC A ; Fix up for value truncation
|
||||
RET ; done
|
||||
;
|
||||
MINIT3:
|
||||
; Not UNA, use HBIOS for CPU speed lookup
|
||||
LD B,0F8H ; HBIOS SYSGET function 0xF8
|
||||
LD C,0F0H ; CPUINFO subfunction 0xF0
|
||||
RST 08 ; do it, L := CPU speed in MHz
|
||||
LD A,L ; move it to A
|
||||
RET ; done
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Uninitialize modem
|
||||
;
|
||||
UNINIT:
|
||||
RET ; not initialized, so no 'UN-INITIALIZE'
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; The following are all dummy routines that are unused because MINIT
|
||||
; dynamically installs the real jump table.
|
||||
;
|
||||
SENDR:
|
||||
CAROK:
|
||||
MDIN:
|
||||
GETCHR:
|
||||
RCVRDY:
|
||||
SNDRDY:
|
||||
SPEED:
|
||||
EXTRA1:
|
||||
EXTRA2:
|
||||
EXTRA3:
|
||||
RET
|
||||
;
|
||||
;=======================================================================
|
||||
;=======================================================================
|
||||
;
|
||||
; Standard RBC Projects 8250-like UART port @ 68H
|
||||
;
|
||||
; Will be used for all RBC Z80 systems.
|
||||
;
|
||||
;=======================================================================
|
||||
;=======================================================================
|
||||
;
|
||||
; UART port constants
|
||||
;
|
||||
U_BASE EQU 68H ; UART base port
|
||||
U_DATP EQU U_BASE + 0 ; data in port
|
||||
U_DATO EQU U_BASE + 0 ; data out port
|
||||
U_CTLP EQU U_BASE + 5 ; control/status port
|
||||
U_SNDB EQU 20H ; bit to test for send ready
|
||||
U_SNDR EQU 20H ; value when ready to send
|
||||
U_RCVB EQU 01H ; bit to test for receive ready
|
||||
U_RCVR EQU 01H ; value when ready to receive
|
||||
U_PARE EQU 04H ; bit for parity error
|
||||
U_OVRE EQU 02H ; bit for overrun error
|
||||
U_FRME EQU 08H ; bit for framing error
|
||||
;
|
||||
; Following jump table is dynamically patched into real jump
|
||||
; table at program startup. See MINIT above. Note that only a
|
||||
; subset of the jump table is overlaid (SENDR to SPEED).
|
||||
;
|
||||
U_JPTBL:
|
||||
JP U_SENDR ; send character (via pop psw)
|
||||
JP U_CAROK ; test for carrier
|
||||
JP U_MDIN ; receive data byte
|
||||
JP U_GETCHR ; get character from modem
|
||||
JP U_RCVRDY ; check receive ready
|
||||
JP U_SNDRDY ; check send ready
|
||||
JP U_SPEED ; get speed value for file transfer time
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Send character on top of stack
|
||||
;
|
||||
U_SENDR:
|
||||
POP AF ; get character to send from stack
|
||||
OUT (U_DATO),A ; send to port
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test and rep;ort carrier status, Z set if carrier present
|
||||
;
|
||||
U_CAROK:
|
||||
XOR A ; not used, always indicate present
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Get a character (assume character ready has already been tested)
|
||||
;
|
||||
U_MDIN:
|
||||
U_GETCHR:
|
||||
IN A,(U_DATP) ; read character from port
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test for character ready to receive, Z = ready
|
||||
; Error code returned in A register
|
||||
; *** Error code does not seem to be used ***
|
||||
;
|
||||
U_RCVRDY:
|
||||
IN A,(U_CTLP) ; get modem status
|
||||
;
|
||||
IF ERRDET
|
||||
;
|
||||
; With error detection (slower)
|
||||
PUSH BC ; save scratch register
|
||||
PUSH AF ; save full status on stack
|
||||
AND U_FRME | U_OVRE | U_PARE ; isolate line err bits
|
||||
LD B,A ; save err status in B
|
||||
POP AF ; get full status back
|
||||
AND U_RCVB ; isolate ready bit
|
||||
CP U_RCVR ; test it (set flags)
|
||||
LD A,B ; get the error code back
|
||||
POP BC ; restore scratch register
|
||||
;
|
||||
ELSE
|
||||
;
|
||||
; No error detection (faster)
|
||||
AND U_RCVB ; isolate ready bit
|
||||
CP U_RCVR ; test it (set flags)
|
||||
LD A,0 ; report no line errors
|
||||
;
|
||||
ENDIF
|
||||
;
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test for ready to send a character, Z = ready
|
||||
;
|
||||
U_SNDRDY:
|
||||
IN A,(U_CTLP) ; get status
|
||||
AND U_SNDB ; isolate transmit ready bit
|
||||
CP U_SNDR ; test for ready value
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Report baud rate (index into SPTBL returned in regsiter A)
|
||||
;
|
||||
U_SPEED:
|
||||
LD A,8 ; arbitrarily return 9600 baud
|
||||
RET
|
||||
;
|
||||
;=======================================================================
|
||||
;=======================================================================
|
||||
;
|
||||
; Standard RBC Projects Z180 primary ASCI port
|
||||
;
|
||||
; Will be used for all RBC Z180 systems.
|
||||
;
|
||||
;=======================================================================
|
||||
;=======================================================================
|
||||
;
|
||||
; ASCI port constants
|
||||
;
|
||||
A_DATP EQU 48H ;Z180 TSR - ASCI receive data port
|
||||
A_DATO EQU 46H ;Z180 TDR - ASCI transmit data port
|
||||
A_CTLP EQU 44H ;Z180 STAT - ASCI status port
|
||||
A_CTL2 EQU 40H ;Z180 CNTLA - ASCI control port
|
||||
A_SNDB EQU 02H ;Z180 STAT:TDRE - xmit data reg empty bit
|
||||
A_SNDR EQU 02H ;Z180 STAT:TDRE - xmit data reg empty value
|
||||
A_RCVB EQU 80H ;Z180 STAT:RDRF - rcv data reg full bit
|
||||
A_RCVR EQU 80H ;Z180 STAT:RDRF - rcv data reg full value
|
||||
A_PARE EQU 20H ;Z180 STAT:PE - parity error bit
|
||||
A_OVRE EQU 40H ;Z180 STAT:OVRN - overrun error bit
|
||||
A_FRME EQU 10H ;Z180 STAT:FE - framing error bit
|
||||
;
|
||||
; Following jump table is dynamically patched over initial jump
|
||||
; table at program startup. See MINIT above. Note that only a
|
||||
; subset of the jump table is overlaid (SENDR to SPEED).
|
||||
;
|
||||
A_JPTBL:
|
||||
JP A_SENDR ;send character (via pop psw)
|
||||
JP A_CAROK ;test for carrier
|
||||
JP A_MDIN ;receive data byte
|
||||
JP A_GETCHR ;get character from modem
|
||||
JP A_RCVRDY ;check receive ready
|
||||
JP A_SNDRDY ;check send ready
|
||||
JP A_SPEED ;get speed value for file transfer time
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Send character on top of stack
|
||||
;
|
||||
A_SENDR:
|
||||
POP AF ; get character to send from stack
|
||||
OUT0 (A_DATO),A ; send to port
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test and rep;ort carrier status, Z set if carrier present
|
||||
;
|
||||
A_CAROK:
|
||||
XOR A ; not used, always indicate present
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Get a character (assume character ready has already been tested)
|
||||
;
|
||||
A_MDIN:
|
||||
A_GETCHR:
|
||||
IN0 A,(A_DATP) ; read character from port
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test for character ready to receive, Z = ready
|
||||
; Error code returned in A register
|
||||
; *** Error code does not seem to be used ***
|
||||
;
|
||||
A_RCVRDY:
|
||||
IN0 A,(A_CTLP) ; get modem status
|
||||
PUSH BC ; save scratch register
|
||||
PUSH AF ; save full status on stack
|
||||
AND A_FRME | A_OVRE | A_PARE ; isolate line err bits
|
||||
LD B,A ; save err status in B
|
||||
|
||||
; Z180 ASCI ports will stall if there are errors.
|
||||
; Error bits are NOT cleared by merely reading
|
||||
; the status register. Below, bit 3 of ASCI
|
||||
; control register is written with a zero to
|
||||
; clear error(s) if needed.
|
||||
JP Z,A_RCVRDY2 ; if no errs, continue
|
||||
IN0 A,(A_CTL2) ; get current control register
|
||||
AND 0F7H ; force err reset bit to zero
|
||||
OUT0 (A_CTL2),A ; write control register
|
||||
|
||||
A_RCVRDY2:
|
||||
POP AF ; get full status back
|
||||
AND A_RCVB ; isolate ready bit
|
||||
CP A_RCVR ; test it (set flags)
|
||||
LD A,B ; get the error code back
|
||||
POP BC ; restore scratch register
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Test for ready to send a character, Z = ready
|
||||
;
|
||||
A_SNDRDY:
|
||||
IN A,(A_CTLP) ; get status
|
||||
AND A_SNDB ; isolate transmit ready bit
|
||||
CP A_SNDR ; test for ready value
|
||||
RET
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
;
|
||||
; Report baud rate (index into SPTBL returned in regsiter A)
|
||||
;
|
||||
A_SPEED:
|
||||
LD A,8 ; arbitrarily return 9600 baud
|
||||
RET
|
||||
;
|
||||
END
|
||||
@@ -1,104 +0,0 @@
|
||||
;;
|
||||
;; make a bcd number from a binary number
|
||||
;; 32 bit binary number in hl:bc, result stored at (de)
|
||||
;; de is preserved, all other regs destroyed
|
||||
;;
|
||||
;bin2bcd:
|
||||
; push ix ; save ix
|
||||
; push bc ; move bc
|
||||
; pop ix ; ... to ix
|
||||
; ld c,32 ; loop for 32 bits of binary dword
|
||||
;;
|
||||
;bin2bcd0:
|
||||
; ; outer loop (once for each bit in binary number)
|
||||
; ld b,5 ; loop for 5 bytes of result
|
||||
; push de ; save de
|
||||
; add ix,ix ; left shift next bit from hl:ix
|
||||
; adc hl,hl ; ... into carry
|
||||
;;
|
||||
;bin2bcd1:
|
||||
; ; inner loop (once for each byte of bcd number)
|
||||
; ld a,(de) ; get it
|
||||
; adc a,a ; double it w/ carry
|
||||
; daa ; decimal adjust
|
||||
; ld (de),a ; save it
|
||||
; inc de ; point to next bcd byte
|
||||
; djnz bin2bcd1 ; loop thru all bcd bytes
|
||||
;;
|
||||
; ; remainder of outer loop
|
||||
; pop de ; recover de
|
||||
; dec c ; dec bit counter
|
||||
; jr nz,bin2bcd0 ; loop till done with all bits
|
||||
; pop ix ; restore ix
|
||||
;
|
||||
; make a bcd number from a binary number
|
||||
; 32 bit binary number in de:hl, result stored at (bc)
|
||||
; on output hl = bcd buf adr
|
||||
;
|
||||
bin2bcd:
|
||||
push ix ; save ix
|
||||
; convert from de:hl -> (bc) to hl:ix -> (de)
|
||||
; hl -> ix, de -> hl, bc -> de
|
||||
ex de,hl
|
||||
push de
|
||||
pop ix
|
||||
push bc
|
||||
pop de
|
||||
;
|
||||
ld c,32 ; loop for 32 bits of binary dword
|
||||
;
|
||||
bin2bcd0:
|
||||
; outer loop (once for each bit in binary number)
|
||||
ld b,5 ; loop for 5 bytes of result
|
||||
push de ; save de
|
||||
add ix,ix ; left shift next bit from hl:ix
|
||||
adc hl,hl ; ... into carry
|
||||
;
|
||||
bin2bcd1:
|
||||
; inner loop (once for each byte of bcd number)
|
||||
ld a,(de) ; get it
|
||||
adc a,a ; double it w/ carry
|
||||
daa ; decimal adjust
|
||||
ld (de),a ; save it
|
||||
inc de ; point to next bcd byte
|
||||
djnz bin2bcd1 ; loop thru all bcd bytes
|
||||
;
|
||||
; remainder of outer loop
|
||||
pop de ; recover de
|
||||
dec c ; dec bit counter
|
||||
jr nz,bin2bcd0 ; loop till done with all bits
|
||||
ex de,hl ; hl -> bcd buf
|
||||
pop ix ; restore ix
|
||||
ret
|
||||
;
|
||||
; print contents of 5 byte bcd number at (hl)
|
||||
; with leading zero suppression
|
||||
; all regs destroyed
|
||||
;
|
||||
prtbcd:
|
||||
inc hl ; bump hl to point to
|
||||
inc hl ; ...
|
||||
inc hl ; ...
|
||||
inc hl ; ... last byte of bcd
|
||||
ld b,5 ; loop for 5 bytes
|
||||
ld c,0 ; start by suppressing leading zeroes
|
||||
;
|
||||
prtbcd1:
|
||||
; loop to print one bcd byte (two digits)
|
||||
xor a ; clear accum
|
||||
rld ; rotate first nibble into a
|
||||
call prtbcd2 ; print it
|
||||
xor a ; clear accum
|
||||
rld ; rotate second nibble into a
|
||||
call prtbcd2 ; print it
|
||||
dec hl ; point to prior byte
|
||||
djnz prtbcd1 ; loop till done
|
||||
ret ; return
|
||||
;
|
||||
prtbcd2:
|
||||
; subroutine to print a digit in a
|
||||
cp c ; compare incoming to c
|
||||
ret z ; if equal, suppressing, abort
|
||||
dec c ; make c negative to stop suppression
|
||||
add a,'0' ; offset to printable value
|
||||
jp prtchr ; exit via character out
|
||||
1
Source/BIOS/Blank1024KB-UNALOAD.dat
Normal file
1
Source/BIOS/Blank1024KB-UNALOAD.dat
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user