Compare commits

...

7 Commits

Author SHA1 Message Date
Zane Kaminski ef6286d674 idk 2022-12-18 08:46:39 -05:00
Zane Kaminski 51d01f815f Update .gitignore 2022-04-29 12:50:17 -04:00
Zane Kaminski 636e73ff23 idk 2022-04-19 06:11:35 -04:00
Zane Kaminski 2cc1076981 Rename stuff to ROMBUS/RB 2021-08-07 13:20:49 -04:00
Zane Kaminski 3d1073a665 In baserom, change "GWRDisk" resource and driver name to "GWSDisk" 2021-08-07 13:20:35 -04:00
Zane Kaminski 147cb0600d Remove control panel 2021-08-07 13:20:31 -04:00
Zane Kaminski 55bc0eaeda Make write-only 2021-08-07 01:27:46 -04:00
41 changed files with 1366 additions and 1850 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
*.DS_Store
obj/
.vscode/c_cpp_properties.json
.vscode/settings.json

339
LICENSE Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) 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
this service 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 make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
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
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE 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.
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
convey 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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This 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.

152
Makefile
View File

@ -5,20 +5,12 @@ LD=$(PREFIX)-ld
OBJCOPY=$(PREFIX)-objcopy
OBJDUMP=$(PREFIX)-objdump
all: bin/IIxIIcxSE30/IIxIIcxSE30_8M.bin bin/IIci/IIci_8M.bin bin/IIfx/IIfx_8M.bin bin/IIsi/IIsi_8M.bin bin/GWSys71_8M.bin bin/GWSys6_8M.bin bin/GWSys7Diagnostics_8M.bin obj/rdisk.s obj/driver.s obj/driver_abs.sym
all: bin/ROMBUS_8M.bin obj/rombus.s obj/driver.s obj/driver_abs.sym
obj:
mkdir $@
mkdir -p $@
bin:
mkdir $@
bin/IIsi: bin
mkdir $@
bin/IIxIIcxSE30: bin
mkdir $@
bin/IIci: bin
mkdir $@
bin/IIfx: bin
mkdir $@
mkdir -p $@
obj/entry.o: entry.s obj
@ -28,14 +20,38 @@ obj/entry_rel.sym: obj obj/entry.o
$(OBJDUMP) -t obj/entry.o > $@
obj/rdisk.o: rdisk.c obj
$(CC) -Wall -march=68030 -c -Os $< -o $@
obj/spi.o: spi.c obj
$(CC) -Wall -march=68020 -c -Os $< -o $@
obj/spi_hal.o: spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rx8.o: spi_rx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rx16.o: spi_rx16.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_tx8.o: spi_tx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_tx16.o: spi_tx16.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rxtx8.o: spi_rxtx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_delay.o: spi_delay.s obj
$(AS) $< -o $@
obj/rdisk.s: obj obj/rdisk.o
$(OBJDUMP) -d obj/rdisk.o > $@
obj/driver.o: obj obj/entry.o obj/rdisk.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk.o
obj/rombus.o: rombus.c obj
$(CC) -Wall -march=68020 -c -Os $< -o $@
obj/rombus.s: obj obj/rombus.o
$(OBJDUMP) -d obj/rombus.o > $@
obj/driver.o: obj obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
obj/spi_rx8.o obj/spi_rx16.o \
obj/spi_tx8.o obj/spi_tx16.o \
obj/spi_rxtx8.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
obj/spi_rx8.o obj/spi_rx16.o \
obj/spi_tx8.o obj/spi_tx16.o \
obj/spi_rxtx8.o
obj/driver.s: obj obj/driver.o
$(OBJDUMP) -d obj/driver.o > $@
@ -43,11 +59,11 @@ obj/driver.s: obj obj/driver.o
obj/driver_abs.sym: obj obj/driver.o
$(OBJDUMP) -t obj/driver.o > $@
bin/driver.bin: bin obj/driver.o
$(OBJCOPY) -O binary obj/driver.o $@
bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
bin/baserom_rombus_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
cp roms/baserom.bin $@ # Copy base rom
# Patch driver
dd if=bin/driver.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
@ -59,107 +75,19 @@ bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_
cat obj/entry_rel.sym | grep "[0-9]\s*DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "[0-9]\s*DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
bin/baserom_romdisk_noramtest.bin: bin bin/baserom_romdisk_ramtest.bin
cp bin/baserom_romdisk_ramtest.bin $@ # Copy base rom
bin/baserom_rombus_noramtest.bin: bin bin/baserom_rombus_ramtest.bin
cp bin/baserom_rombus_ramtest.bin $@ # Copy base rom
# Disable RAM test
printf '\x4E\xD6' | dd of=$@ bs=1 seek=288736 count=2 conv=notrunc
printf '\x4E\xD6' | dd of=$@ bs=1 seek=289016 count=2 conv=notrunc
bin/GWSys71_8M.bin: bin bin/baserom_romdisk_noramtest.bin disks/RDisk7M5.dsk
bin/ROMBUS_8M.bin: bin bin/baserom_rombus_noramtest.bin disks/RDisk.dsk
# Copy base rom with ROM disk driver
cp bin/baserom_romdisk_noramtest.bin $@
# Patch ROM disk driver parameter table
printf '\x00\x01\x2A\x29' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
printf '\x40\x89\x2A\x14' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
cp bin/baserom_rombus_noramtest.bin $@
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
# Copy ROM disk image
dd if=disks/RDisk7M5.dsk of=$@ bs=1024 seek=512 conv=notrunc
bin/GWSys6_4M.bin: bin bin/baserom_romdisk_noramtest.bin disks/RDisk3M5.dsk
# Copy base rom with ROM disk driver
cp bin/baserom_romdisk_noramtest.bin $@
# Patch ROM disk driver parameter table
printf '\xFF\xFF\xFF\xFF' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
printf '\x00\x00\x00\x00' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
printf '\x00\x38\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
# Copy ROM disk image
dd if=disks/RDisk3M5.dsk of=$@ bs=1024 seek=512 conv=notrunc
bin/GWSys6_8M.bin: bin/GWSys6_4M.bin
cat bin/GWSys6_4M.bin > $@
cat bin/GWSys6_4M.bin >> $@
bin/GWSys7Diagnostics_8M.bin: bin bin/baserom_romdisk_ramtest.bin disks/RDisk7M5-diagnostics.dsk
# Copy base rom with ROM disk driver
cp bin/baserom_romdisk_ramtest.bin $@
# Patch ROM disk driver parameter table
printf '\xFF\xFF\xFF\xFF' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
printf '\x00\x00\x00\x00' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
# Copy ROM disk image
dd if=disks/RDisk7M5-diagnostics.dsk of=$@ bs=1024 seek=512 conv=notrunc
bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin: bin/IIxIIcxSE30 roms/IIxIIcxSE30.bin
cat roms/IIxIIcxSE30.bin > $@; cat roms/IIxIIcxSE30.bin >> $@
bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin
cat bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_512k.bin >> $@
bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin
cat bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_1M.bin >> $@
bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin
cat bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_2M.bin >> $@
bin/IIxIIcxSE30/IIxIIcxSE30_8M.bin: bin/IIxIIcxSE30 bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin
cat bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin > $@; cat bin/IIxIIcxSE30/IIxIIcxSE30_4M.bin >> $@
bin/IIci/IIci_1M.bin: bin/IIci roms/IIci.bin
cat roms/IIci.bin > $@; cat roms/IIci.bin >> $@
bin/IIci/IIci_2M.bin: bin/IIci bin/IIci/IIci_1M.bin
cat bin/IIci/IIci_1M.bin > $@; cat bin/IIci/IIci_1M.bin >> $@
bin/IIci/IIci_4M.bin: bin/IIci bin/IIci/IIci_2M.bin
cat bin/IIci/IIci_2M.bin > $@; cat bin/IIci/IIci_2M.bin >> $@
bin/IIci/IIci_8M.bin: bin/IIci bin/IIci/IIci_4M.bin
cat bin/IIci/IIci_4M.bin > $@; cat bin/IIci/IIci_4M.bin >> $@
bin/IIfx/IIfx_1M.bin: bin/IIfx roms/IIfx.bin
cat roms/IIfx.bin > $@; cat roms/IIfx.bin >> $@
bin/IIfx/IIfx_2M.bin: bin/IIfx bin/IIfx/IIfx_1M.bin
cat bin/IIfx/IIfx_1M.bin > $@; cat bin/IIfx/IIfx_1M.bin >> $@
bin/IIfx/IIfx_4M.bin: bin/IIfx bin/IIfx/IIfx_2M.bin
cat bin/IIfx/IIfx_2M.bin > $@; cat bin/IIfx/IIfx_2M.bin >> $@
bin/IIfx/IIfx_8M.bin: bin/IIfx bin/IIfx/IIfx_4M.bin
cat bin/IIfx/IIfx_4M.bin > $@; cat bin/IIfx/IIfx_4M.bin >> $@
bin/IIsi/IIsi_1M.bin: bin/IIsi roms/IIsi.bin
cat roms/IIsi.bin > $@; cat roms/IIsi.bin >> $@
bin/IIsi/IIsi_2M.bin: bin/IIsi bin/IIsi/IIsi_1M.bin
cat bin/IIsi/IIsi_1M.bin > $@; cat bin/IIsi/IIsi_1M.bin >> $@
bin/IIsi/IIsi_4M.bin: bin/IIsi bin/IIsi/IIsi_2M.bin
cat bin/IIsi/IIsi_2M.bin > $@; cat bin/IIsi/IIsi_2M.bin >> $@
bin/IIsi/IIsi_8M.bin: bin/IIsi bin/IIsi/IIsi_4M.bin
cat bin/IIsi/IIsi_4M.bin > $@; cat bin/IIsi/IIsi_4M.bin >> $@
dd if=disks/RDisk.dsk of=$@ bs=1024 seek=512 conv=notrunc
.PHONY: clean
clean:

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
#include "RDiskCP.h" static long RDiskCPMacDev() { int i; // Check signature and return 0 if doesn't match // Don't check for length byte at beginning or null byte at endss for (i = 1; i < sizeof(RDiskSigStr)-1; i++) { if (RDiskSigPtr[i] != RDiskSigStr[i]) { // If signature doesn't match, // fail if not holding R key if (!((*((char*)0x175)) & 0x80)) { return 0; } } } return 1; // Otherwise return 1 if signature matches } static void RDiskCPUpdate(DialogPtr cpDialog, short numItems) { GrafPtr savePort; Handle h; Rect r; short type; char startup, ram; // Get startup and ram from PRAM RDiskCPReadXPRam(1, 4, &startup); RDiskCPReadXPRam(1, 5, &ram); // Save GrafPort and set port to dialog before updating items GetPort(&savePort); SetPort(cpDialog); GetDItem(cpDialog, BootCheckbox+numItems, &type, &h, &r); SetCtlValue((ControlHandle)h, startup & 0x01 ? 1 : 0); GetDItem(cpDialog, MountCheckbox+numItems, &type, &h, &r); SetCtlValue((ControlHandle)h, !(startup & 0x02) && !(startup & 0x01) ? 1 : 0); HiliteControl((ControlHandle)h, startup & 0x01 ? 255 : 0); GetDItem(cpDialog, RAMCheckbox+numItems, &type, &h, &r); SetCtlValue((ControlHandle)h, ((startup & 0x01) || !(startup & 0x02)) && (ram & 0x01) ? 1 : 0); HiliteControl((ControlHandle)h, (startup & 0x01) || !(startup & 0x02) ? 0 : 255); GetDItem(cpDialog, DebugCheckbox+numItems, &type, &h, &r); SetCtlValue((ControlHandle)h, startup & 0x04 && (startup & 0x01) ? 1 : 0); HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskDBGDisPos ? 255 : 0); GetDItem(cpDialog, CDROMCheckbox+numItems, &type, &h, &r); SetCtlValue((ControlHandle)h, startup & 0x08 && (startup & 0x01) ? 1 : 0); HiliteControl((ControlHandle)h, !(startup & 0x01) || !*RDiskCDROMDisPos ? 255 : 0); // Restore old GrafPort SetPort(savePort); } static void RDiskCPHitDev(short message, short item, short numItems, short cpPrivateVal, EventRecord *theEvent, void *cdevStorageValue, DialogPtr cpDialog) { char startup, ram; RDiskCPReadXPRam(1, 4, &startup); RDiskCPReadXPRam(1, 5, &ram); switch (item - numItems) { case BootCheckbox: if (startup & 0x01) { startup &= 0x0F & ~0x01; } else { startup = startup & 0x0F | 0x01; } break; case MountCheckbox: if (!(startup & 0x01)) { if (startup & 0x02) { startup &= 0x0F & ~0x02; } else { startup = startup & 0x0F | 0x02; } } break; case RAMCheckbox: if ((startup & 0x01) || !(startup & 0x02)) { if (ram & 0x01) { ram = 0x00; } else { ram = 0x01; } } break; case DebugCheckbox: if (startup & 0x01) { if (startup & 0x04) { startup &= 0x0F & ~0x04; } else { startup = startup & 0x0F | 0x04; } } break; case CDROMCheckbox: if (startup & 0x01) { if (startup & 0x08) { startup &= 0x0F & ~0x08; } else { startup = startup & 0x0F | 0x08; } } break; }; RDiskCPWriteXPRam(1, 4, &startup); RDiskCPWriteXPRam(1, 5, &ram); RDiskCPUpdate(cpDialog, numItems); } static void RDiskCPInitDev(short message, short item, short numItems, short cpPrivateVal, EventRecord *theEvent, void *cdevStorageValue, DialogPtr cpDialog) { Str15 ramSize; Str255 dbgName = "\pMacsBug"; Str255 cdromName = "\pCD-ROM Ext."; int i; ramSize[0] = 2; if (RDiskCPMacDev()) { ramSize[1] = RDiskRAMReq[0]; ramSize[2] = RDiskRAMReq[1]; } else { ramSize[1] = '1'; ramSize[2] = '6'; } if (RDiskCPMacDev() && *RDiskDBGNamePos != 0) { for (i = 0; i < 255; i++) { dbgName[i] = (*RDiskDBGNamePos)[i]; } } if (RDiskCPMacDev() && *RDiskCDROMNamePos != 0) { for (i = 0; i < 255; i++) { cdromName[i] = (*RDiskCDROMNamePos)[i]; } } ParamText(ramSize, dbgName, cdromName, 0); } pascal long main(short message, short item, short numItems, short cpPrivateVal, EventRecord *theEvent, void *cdevStorageValue, DialogPtr cpDialog) { long ret = (long)cdevStorageValue; // Switch to our A4 world EnterCodeResource(); // Handle message switch (message) { case initDev: RDiskCPInitDev(message, item, numItems, cpPrivateVal, theEvent, cdevStorageValue, cpDialog); // (fall through to return cdevUnset) case closeDev: ret = cdevUnset; break; case macDev: ret = RDiskCPMacDev(); break; case updateDev: case activDev: case deactivDev: RDiskCPUpdate(cpDialog, numItems); break; case hitDev: RDiskCPHitDev(message, item, numItems, cpPrivateVal, theEvent, cdevStorageValue, cpDialog); break; }; // Restore old A4 world and return result ExitCodeResource(); return ret; }

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
#ifndef RDISKCP_H #define RDISKCP_H #include <A4Stuff.h> #define BootCheckbox 3 #define BootCaption 6 #define MountCheckbox 5 #define MountCaption 8 #define RAMCheckbox 7 #define RAMCaption 10 #define DebugCheckbox 13 #define DebugCaption 14 #define CDROMCheckbox 15 #define CDROMCaption 16 #define RDiskSigPtr ((char*)0x40851D90) #define RDiskSigStr "\5RDisk" // sizeof(RDiskSigStr) == 7 #define RDiskDBGNamePos ((char**)0x40851DA0) #define RDiskDBGDisPos ((char**)0x40851D98) #define RDiskDBGDisByte ((char*)0x40851DA8) #define RDiskCDROMNamePos ((char**)0x40851DA4) #define RDiskCDROMDisPos ((char**)0x40851D9C) #define RDiskCDROMDisByte ((char*)0x40851DA9) #define RDiskRAMReq ((char*)0x40851DAA) #pragma parameter __D0 RDiskCPReadXPRam(__D0, __D1, __A0) short RDiskCPReadXPRam(short size, short offset, char *where) = {0x4840, 0x3001, 0xA051}; #pragma parameter __D0 RDiskCPWriteXPRam(__D0, __D1, __A0) short RDiskCPWriteXPRam(short size, short offset, char *where) = {0x4840, 0x3001, 0xA052}; #endif

View File

@ -1 +0,0 @@
(This file must be converted with BinHex 4.0) :#9*%DA0V3e!ZD!"849K868e$3`%!!!!$q!!!!4j-8L0TCQjNC@BJ8N4*8dY$8&p )$50NC@CTEQ8J8N4*8dY$8&p)$3dMD@jME(9NC5!m3646G(9QCLjS2Jd0)f4PCQP ZC5"#Efpd3fKPBfYLEhJJ-`dMC'9QD@jP)%*[Eh4$BA"dD@pZ)$B0)f4PCQPZC5" 0Eh9ZG%0SC@0VBQpi)$80)f4PCQPZC5"0Eh9ZG%0KF(4TEfiJ1!dMC'9QD@jP)&* "680SC@0VBQpi)$F0)f4PCQPZC5"538e$BA"dD@pZ)$%`$50NC@CTEQ8J4'9LG@G $D'9MDf*[H#!a-`dMC'9QD@jP)%4PBR9R3f&`G'P[EL!a0!dMC'9QD@jP)%0%8Np 03fKPBfYLEhJJ-680)f4PCQPZC5"$4&*2680KF(4TEfiJ-6B0$50NC@CTEQ8J8N4 TFfY6D@G3G()J+#KMD'&b+LN`H$3`1$8a4$N`+3dMC'9QD@jP)&*%DA0V8fPR8h4 b)#*F09*%DA0V)L![,b"cDATPEfBS8N4TFfY6D@G6G()T)$dp)$F0$50NC@CTEQ8 J8N4TFfY%3NG1B@eP8'pc)#JSBfKKFLSU+6"i0$!i06&%36!T$50NC@CTEQ8J8N4 TFfY%3NG%DA03Eh-J+#KMD'&b+LST-(Jd-$Je-83j1#N0)f4PCQPZC5"54'PcDd4 #4d4TFd*jG'8J+#KMD'&b+LN`H$3`1$8a4%%i+3dMC'9QD@jP)&*%DA0V3d456de 1B@eP8'pc)#JSBfKKFLSU+6"i0$!i06&%363T$50NC@CTEQ8J8N4TFfY$4&*2684 TFe"[Fb!S+'0SBA)U+LN`H$3`1$8a4$P$+3dMC'9QD@jP)&*%DA0V3d456de%DA0 #HA4P)#JSBfKKFLST-(Jd-$Je-84"15N0)f4PCQPZC5"54'PcDe*"69*PF5!S+'0 SBA)U+6"i0$!i06&%38%T$3dMF(*KCfeK)("KFQ&YCA4PFL"IAd3`)&*%DA0V3e" 5C@&N@&"5B@dSAep%-#`JAep%-5`JAep"-#N0FfK[FR3J8N4TFfY$8&*PB@4B8&* KE5KcD'pbG#"cDATP,#"cD'pbG#"[CQCcCA3X)'0SBA)J+RGSCA*P+5!p$3Pl-(J d1$3`,#!`H$-`-$%X)$"i36!e-Adl$3dMF(*KCfeK)("KFQ&YCA4PFL"IAd3`)&* %DA0V3e"AFQPdC9K38Q&Y+&pI4$!X)&pI4$%X)&pI36!T$A0SEh*d)&*%DA0V3e" AFQPdC9K38Q&Y+(0SEh*d)(0THQ8X)(0SEh*d)'pQCR0PG#`JBfKKFL!UGfKPFQ8 T)$dJ$3Pl-(Jd1$3`,#!`H$-`-$%X)$"i36!e-Rdl$3dMC@jND@B0TQX!!!%!!!! "!!!!!!!!!!!H!3")9d*3!3+#i9Ve9d*D6eT2AH3$U#iH(f!+i6X#rFS*8N4TFfY $8#jS!J!!!%**6N&6594i!3!!!!"!!!!!!!!!3NP1390*9(J"!!!!!%!!!!!!!!! !!!!!!!!!!!!!!!$FrS,E!!!$q!!!!4i5#!%!!!#q%J-!!!!!!3j!CQ0,@8h)Z*P ,!33S8!%%mV5$!5#!@8d#5T!!CajB!M&m!)#e@8eB!L&mIrpX6`%GI'C2`p42CB- "@%qYBr)#3QhjVZ%45'd"qEa-!IqL%4!I!@FSi5-"qEK-!Iq8*!&R'Z%M!IQd6!( rKL6@i5-"qE"-!3!!!3!!!!%!!!!!!!!!!"i!!!!!!!!!!!!F!"lrrbjV:

View File

@ -1,126 +0,0 @@
(This file must be converted with BinHex 4.0)
:"e*%DA0V3e!!68e38Ne03d-"!*!$&[i!!!@q4cKMEfpX!*!$!3#3!a`!!"CU!!!
@KJ#3!hJ!N!-'!*!$1!!"!$!!!J!F!129M!#3"%#!QJS!!$2`!F92k!#3!f"@H2r
r!FkKH!!!"'`!N!-'!!)!N!-#!"`*6'PLFQ&bD@9c-CLRN!!!N"m#!"`*6'PLFQ&
bD@9c-CLRN!!!N"m#!#J!q2r`!*!&!G58!*!'-XB##!!!!3V,@!#3%#"YC@je!*!
%*!$Yr`%!!3#3$Jp$E'9KFL"'D@aP)'ePER8!N!3",3#3"3-!!3!#!*!$MJP54'P
cDd03,Q-!N"EFAP$i!3%!N!N#!!)!N!11$&*%DA0V3e!ZFR0bB`#3%paH5'J"!3#
3#30!!J!!$Qi06@&M5'9KC'9bFcBi5`#3%UZmEmN"!3#3#34!!J!!#rN*3646G(9
QCLjS!*!@Ul((UJ!"!*!*"3!#!*!$MJP54'PcDd03,QJ!N"EFAP"b!3%!N![%!!)
!AJ#3!`3!!4pG!!!%E!#3!`%!N!3*8N4TFfY$8#jM!*!C"J#3"3(FAP$i!*!$"+Z
aakS!N!-$Ula[b3#3!`AFAP"b!&`!AJ"R!!%!!3#3#3%!N!3-8N4TFfY$8#jbFh*
M!*!F!YaH5'J!N!5VX3#3"aK[b3l`!!AFA1kQ3cJ!N!J"$!$M4C!!!*!(!J#3#3(
rN!B!!J#3$8!!id@3!!%SLR#!5!#3"4)!3`!#!*!(5!#3!dJ!N!8)!!%!#!#3"L%
-!*!0*!$M4C!!!!5VXFHU!*!$!kZmEmN!N!-&h&j3FJ"F!*!(*!$M4C!!!*!A-!#
3"bJ!id@3!!!"!+3!%`$R!1hY2!#3"a!!N!m`!10&N!!!*!!!!R%"K3*f!!!#F3*
fIrm"K!*e!REqlEkY!*!'"@)!!!i)!*!$B!!!"D)!!!KQ!*!'"'`!N!F'!*!84@G
&E3#3!`%!N!-'rj!%!*!$&P*%DA0V!%9T!*!$!J#3!e!!N!-J!*!$&Nj@!!!LI%#
&(C&d!'!NF!!3-5!!3H`!!")`)!")JE*!C`i31!&e!N!!J'B%F!"J$&*#-%*`"E(
!CG4`!8jH6R@08N4TFfY$8%eKBd4PGJ!!4A3!N!-"!!%!N!-@!*!%4@N!N!-0!!!
"Y!#3!iJ!!!'B6PErkNMR%#!NEJ!)0Li!$(!"FJ4"l[rl5%!`!D"4F!&b"8(ZrqY
)3$!"S&&)E[rXU(3[#UKc,`S`!eC!2`")E[r`5'lrr%KZrr+TM5mZrr`),J!!rrY
Q"(!!B!*`!6m!U@-[#M!$@N!r!%KZrr")E[rm5'lrmUQ0,blrr!JZ!!(rqfF)##i
!!2rlC`4`!'!#F!%r!+PM,blrr!JZ!!$rqfB%F!"J"$!m!2mr!+PG,`S`!ej!2`"
)E[r`5'lrr%KZrr+TM5mZrr`3,[rl!N!!!fF)##i!!2rVCJ4`!'!#F!%r!+PM,bl
rr"!ZrrX#3!!$CJB`2!$rB!*`!$m!U9d[#R!0d%-r!%KZrr")E[rm5'lrmUQ0,bl
rr!JZ!!,rqfF)##i!!2rlCJ4`!'!#F!%r!+PM,blrr!JZ!!$rqfF%F!"J"$!m!2m
r!+PG,`T`$p"$2`")E[r`5'lrr%KZrr+TM5mZrr`),J!$rrYQ#!JZ!!$rqfB%F!"
J!R!"2`#TBbmZrr`),J!!rrYR"(!!B!3`2!$r2`#TA5mZrqbSFdcI"!K1ANjeM9*
%DA0V3e"9F'4KG'8!!%9T!*!$6`!!!9B!!!'X!!!'X8j@rrj`!A)%3HlrrdK!-!'
J8A!"FJ9"l[rq5%!`!D"4-#i!#T!!EJ!-9d"R'&9!Cca93'GUA8"R!!#)98"R!!#
`B!!!f"!Zrrm#3!!"C`S#,J!1rrpJ!!$%%#lrr`*!!!m!3!!"(8$rrf!!!,!3,[r
r!N!!!@B!!+33,[rr!N!!!QF+!Li!$IrrB!!!N!!3,[rr!N!!$`"!!!)G32rrB(`
3,[rr!N!!!fGb%#lrrJ*!!!&R"N)ZrrjJBKem!!(rrQ"D%#lrr`*!!!&R8"!Zrrm
#3!!%C`J#,J!,rrpJ2K!Zrrm#3!!2!%!!""e!rrpJ,"!Zrrm#3!!"Cb)3,[rr!N!
!#'F)!Li!"rrrB"!3,[rr!N!!$`"!!!JG32rrF!&b"%(Zrrp)3$!"S&*`!A)&3Hl
rrNK!-!'J8MmZ!!`[,J!B6U`!!%jH6R@08N4TFfY$8%KTG%4PGJ!!4B%!N!-0!!%
!!!&!!*!%4@N!N!04!*!$B!!!!Xi!!!XH6PErm#m+*(a!K4f4(A`!![r`6U`!!%U
!C`iGDJ!'rr%GDJ!(rr*J$"em!$(rm4em!$,rmNKZrr")H8#)!#T)H8#*,*C#TkQ
,*&p1ANjeMP*%DA0V3e"*EQPd4'9f!*!$4B%!N!-#!!%!N!-8!*!%4@S!N!06!*!
$XJ!!!di!!!dK6PB!!%MR(c!k,J!D1#i!&LiZ!"!QEJ!-*'i!##B,6U`!!#`!-!8
-3!!)BQM33$!l!!C1q`!#!")!4!!X!&i!1!!i!$J!AJ!`,`S[#bm(2bi!&$m%2bi
!'$m&6U`!!%r[!"4f!f!Z6U`!!#B!B#Br"#m+6U`!!&a2B"S[#Lm,,`Fr,J!82`3
r,J!B2`91V!!!6qm!&#!'`B`[3`!i60m-q%jH)&p2l`!86Y#%E@&TEJ#3!d@"!*!
$6`!"!*!$MJ#3"%@"!*!$$3!"!*!$G!#3"%@"!*!$!J!"!*!$D!#3"%@"!*!$83!
"!*!$A!#3"%@"!*!$9!!"!*!$)!#3"%9S8eP05!!!"%!!N!-8!*!9!3#3"aB!N!-
%!*!$2!#3!`S!N!18!*!$$J#3!m!!N!-L!!!"*J#3!c!!!!&F!*!$1J!!!9m!N!-
m!!!"PIq3"!!!!CB!!J#3!`2rN!2q!*!&#3#3!``!N!-,!*!&!J!"!*!'!CJ!N!-
3!!!#4!#3!ai!!!*R!*!$,!!!!XF!N!-b!!!#h!#3!cB!!!,b!*!$6!!!!bd!N!0
L!!!$C`#3!hJ!!!1M!*!$PJ!!!r!!N!1Z!!!%,J#3!m3!!!4S!*!$j!!!"+i!N!2
q!!!%l!!!!43!!!8S!!!"-J!!"A3!!!&+!!!&Y3!!!@!!!!Aa!!!"IJ!!"N!!!!'
@!!!'QJ!!!C`!!!DZrj!%!!!'V`!)!*!$$[q3!rS!N!8+!*!$53#3!`X!N!8$!*!
$5J#3!`F!![q3!qX!N!0,!*!$"`!#rj!$q`#3!d`!N!-,!!,rN!2`!*!$6Iq3!rF
!![q3!r)!N!-S!*!$C`!#rj!$r!#3!dlrN!2k!!,rN!2X!!%!N!B(+!#3!`3!!!G
a!*!$%J!!"j3!N!-J!!!(X`#3!d3!!!IN!*!$@!!!#"J!N!0S!!!)43#3!f`!!!K
P!*!$H!!!#)%!N!1-!!!)YJ#3!j`!!!MT!*!$RJ!!#3F!N!1S!!!*)3#3!lJ!!!P
&!*!$[J!!#@-!N!2!!!!*J`#3!mS!!!QF!*!$h!!!#G%!N!2X!!!+"!#3!qi!!!S
N!*!$q!!!#Md!!!%+!!!+FJ!!!4S!!!Uc!!!"+!!!#YF!!!%f!!!+p`!!!8)!!!X
Erj!%!!!,(!!&!*!$8!#3!`X"!J#3!`S!N!0*!*!$#`%#!*!$$!#3!`lrN!2k!3)
!N!-B!*!$5J#3!`F!![q3!ri!N!0,!*!$"`!#rj!%!!%!N!B,Q!#3!`B!!![I!*!
$$!!!$!8!N!-5!!!-&J#3!aS!!!`Z!*!$)!!!$&N!N!-Q!!!-K!#3!bJ!!!b1!*!
$,J!!$+)!N!-d!!!-Z3#3!dJ!!!dHrj!%!!!0(`!#!*!$!rq3!ri!N!8+!*!$8[q
3!qi!![q3!r!!!3#3"Jfq!*!$(!!!$F!!N!-H!!!0r`#3!b3!!!iS!*!$5!!!$N`
!N!0L!!!1q!#3!fB!!!mL!*!$EJ!!$hN!N!0f!!!2R`#3!hS!!!qj!*!$P!!!%'%
!N!1B!!!3GJ#3!j`!!"#$rj!%!!!3K!!*!*!$93#3!`X!N!8&!*!$8!#3!`X"!J#
3!aJ!N!0*!*!$#`#3"33!N!0@!*!$#`%#!*!$&!#3!eIrN!2Y!*!&"`#3!ed!N!0
N!*!&#`#3!`lrN!2k!*!&#J#3!ei!N!-$!*!&"J#3!em!N!-$!*!&!`!"rj!%!*!
$"J#3!`%!N!-(!!(rN!2m!*!$"J#3!`%!N!-'!!(rN!2l!*!$!J#3!`%!N!-'!!,
rN!2p!*!$"!#3!c)!"`#3!`ArN!2m!*!("[q3!rX!N!-'!*!$"`#3!fX!N!-)!*!
$#!#3!`%!N!--!*!$#3#3!fJ!N!-X!*!$#J#3!`B!N!-`!*!$#`#3!`B!N!-a!!$
rN!2q!!(rN!2p!!,rN!2h!*!$&J#3!`J!"!#3!aF!N!-,!*!('!#3!`X!N!-#!*!
$'3#3!`X!N!-%!*!$'J#3!`X!N!-'!!,rN!2i!*!$%J#3!`i!!`#3!a-!N!0Q!*!
(&!#3!`X!N!-%!*!$&Iq3!rF!N!-'!!,rN!2e!*!$(3#3!`S!!J#3!ai!N!-,!*!
((rq3!rF!N!-#!!$rN!2f!!,rN!2e!!(rN!2c!*!$#!#3!`%!N!-'!!,rN!2d!*!
$)J#3!`J!!3#3!b2rN!2c!*!&![q3!r)!N!-Q!*!$"!!#!*!$*`#3!`X!N!FS!*!
$#`#3!`)!!2q3!qm!!3#3!fS!![q3!r!!N!-l!*!$0!!0!*!$22q3!qm!N!Fprj!
$l`#3!`3!N!-qrj!$l`#3!`J!N!-rrj!$l`#3!``!N!0!rj!$l`#3!a!!N!0"rj!
$l`#3!a3!N!0#rj!$l`#3!aJ!N!0$rj!$l`#3!a`!N!0%rj!$l`#3!b!!N!0&rj!
$l`#3!b3!N!0'rj!$l`#3!bJ!N!0(rj!$l`#3!b`!N!0)rj!$l`#3!c!!!2q3!r%
!!Iq3!r!!![q3!rN!N!-2!*!$E!!D!*!$%!#3!`X!N!F4rj!$q!#3!`)!N!-Erj!
$p`#3!a!!N!-Frj!$pJ#3!aJ!N!-Jrj!$pJ#3!a`!N!-Krj!$p!#3!b!!N!-Nrj!
$p!#3!bJ!N!-Prj!$mJ#3!c!!N!-Trj!$mJ#3!c3!N!-U!*!$#`#3!cJ!N!-Vrj!
$p!#3!cS!N!-X!*!$#`#3!d)!N!-Y!*!$#`#3!d3!N!-Z!*!$"J#3!dB!N!-[!*!
$"`#3!dF!N!-`!*!$#`#3!dJ!N!-a!*!$#`#3!dS!N!-b!*!$!`#3!d`!N!-c!*!
$!`#3!e!!N!-d!*!$!`#3!e3!N!-e!*!$#`#3!eJ!N!-f!*!$#`#3!eS!N!-h!*!
$C`#3!e`!N!-i!*!$C`#3!f!!N!-j!*!$C`#3!f3!N!-krj!$m3#3!fJ!!2q3!rS
!!Iq3!rN!!Iq3!qi!N!-3!*!$!3#3!`B!![q3!q`!N!0B!*!$%!!&!*!$@3#3!`S
!N!G9!*!$!J#3!`)!N!0D!*!$!J#3!`B!N!0Erj!$mJ#3!`S!N!0F!*!$#J#3!`i
!!2q3!qd!!Iq3!q`$H%!b-3!"FP*%DA0V3e"0B@0%CAB!!k"SC()!!)&54'PcDdK
NFJ!$BA0TC`!$eh*KE9*PFA9TFQ9N!!(#F'&dBfK'D@aP6Q&YC3!$b("KG'0S4QP
XC8jKE@9@CA*TCRN!!Ie`BA4MD%CTE'9#HA4P!!0iF'&dBfK'D@aP3RPdC8*PCQp
bC3!#(h"KG'0S4QPXC8*jG'9"CR4PFJ!"D@N!!6e54'PcDd039A"NBA4P!!$jBh"
%D@&XEfF!!'0(FQ&Q8'pbG!!#X@4PGQPMC3!!6A"[FR4#DA4c!!)Q3QPd6@&`!!#
cBQ&cC8&NC()!!(jbEhG#HA4PF`!#+f*[G@jNF`!!Ie*PBh3!!bpdEh!!!!aXC@C
d!!)LBQpdG'pY!!(@FQPRD(3!!#4`Eh*d8Q9MG!!#-(CTFe*REJ!#$e*PCfP[EJ!
$3A*REP0THQ8!!mjbCfj#3Qpi!!1NBfaTF&*REJ!"Q@*V8'&d!!1U8'&dG'9bEJ!
$BA"KG!!$&'CTE'a3BA3!!F"`ENa[B`!"T&"[D@jd!!&fGJ!"D'J!!UY`EP0THQ8
!!KP`ENe[C'8!!Ip`EP"KG!!"&h"Z9QPc!!,HG(K'Efjd!!*9G(K'B@0P!!+jCQP
XE'9b!!)aG(K0Ef4P!!,MG(K6DATP!!1lFh"&H(4bB3!$AfCR3fpXEh)!!cKLDd0
[E'pb!!1pBfpXFN*TG!!#aR"KG&0dFQ9dBfJ!!h4`D@06BACP!!1KFQGZ8f&fC3!
!$("[E(P6BACP!!%bCh*KCP"bEf0c!!-M8843FQpMF`!!4h4PH(43FQpM!!#0E'P
ZC9"bEf-!!,PbC@0d8(*[B`!"$R*5C@0d8(*[B`!!N@pfB@a3FQpM!!-KBA*M8(*
[B`!!m("[E(P3FQpM!!1"FQGZ8(*[B`!!UQ*TG(03FQpM!!2ZBfpYE@9ZG&"bEf-
!!MYdH%ePBA03FQpM!!,NCf9d8'PM8(*[B`!#FA"eG&"TBe"bEf-!!'pZG@e*G'9
YF`!$BR*KE3!$KA0dBA*dGA!!!'pdHA"P!!&bFJ!!cA0KGQ93Eh*d!!''8N4TFfY
$8%KTG%4PGJ!!S'PdC@d!!U&54'PcDd035@jTG%4PGJ!$"A*KE90THQ8!!,0YB@P
Z!!"(8f9d3h9bFQ9ZG%%d!!0,E@9cFf&RC3!!2Q0`8(*TGQ&dC9CKE!!!E(4SC89
fC@jd!!1P4ACPER45C@0[FQ3!!0PhD'&d!!"6GfKPEJ!"6hGSCA*P!!%XE@pND@C
TCA*c!!$0Bf4PGP0dEh*KCf9@B@aeC3!"HQpXC%%d!!2UFQ9d!,kVZZX!N$d"!"J
!N!8@8N4TFfY$8%eKBd4PGJ!!!3!B!*!%!CK54'PcDd039A"NBA4P!!!"!"J!N!3
'X9*%DA0V3e")DA4%CAB!!!%!'J#3"!XH8N4TFfY$8%PZDA4%CAB!#J!"!"!!!3!
!$5&YB@PZ!-N!N!2Ym$`!!!%H!!!"$P"'E(-!N!AYm$3!!!)X!*!$a&"-Fh3!N!S
"(!#3!`*38f9Rrrm!N!NF!!!"!&"6C@F!!3#3#!2`!!!4iQpLDQ3IA3#3#"A5!*!
$Y'*bGh-IA3!!jf3!!!%!N!-%h!!!!p`!N!2L!*!$!@%!N!3"B3#3"!&K!*!%!@%
!N!3"B3#3!`G54'PcDd03!J#3!de08&*0680$!3$rN!3!N!84!!"069"568e$3`%
!rj!%!*!5h&c[Q`!!&[i!!!@q!!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#
3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&
K!*!%!@%!N!3"B3#3"!&K!*!%!@%!N!3"B3#3"!&K!*!%!J!$!*!$5J!"!!N'6@p
ZB@0[!*!F"!!S!!S"`J+!!#J!#J(#!S!!N"!"!*!%!J#3"5J!"!%!rrm!N!Mrr`'
3"3#3""i"!3#3#*QC!*!&-!!&!*!($8eKBdKPB@4PFR-f1%X!N"`+!!)!N!X8!!3
!N!J"!*!-$!!%!3!!!3!"!3#3"JF!!J#3#!F!!J#3"`)%!!)""d4bEh"XCA3!N2N
""P0[Fh9YD3#3q`S!"!#3#l`!"!!"#dGA)&*265"%DA0V!*!dFQ4cDf0NCAB!N%K
MC'9fm#!!N!HF!2B"2!(F!3#3!`[#!*!$MJ#3$!%!N!-%h!!!!p`!N!2L!10'b!U
S!*!$(!$5!!*`FQ9Q!!S!'R"@CA)!N!1H8e45)`#3!kS!!2rr!*!$"J#3"3(rr`#
3!eS!N!8#rrm!N!1'!*!&"rrr!*!$ZJ#3"32rr`#3!mJ!N!8%rrm!N!2J!*!&"[r
r!*!$m!#3"3Mrr`#3!rX!N!8*rrm!!!%'!*!&b2rr!!!$$J#3"3Arr`!!!a`!N"!
$m2rr!*!$9!#3"!p3FQpUC@0d)&CPFR0TEfkbk3:

View File

@ -1,34 +0,0 @@
(This file must be converted with BinHex 4.0)
:$&*%DA0V3e!ZFR0bB`"bFh*M8P0&4#'!!*!'#UM`C3#3"!%!N!-*N`!!#*-!!!%
98dP8C90*9%`"!*!'"BR#!3!,!90*9'96594-!J!-8N4TFfY$8#jbFh*M!J)!N!0
bFh*M8P0&4#'!rj!%!!"bFh*M8P0&4#'!rj!%!*!5h&c[T!#3"JUS8dP8C90*9%`
'!*!'"C'#!3!,!90*9'9`BA9Xr`#3"J@E3J%!#`&6594PFfKXBJ%!N!B&NS)"!!X
"8dP8CA0SE')#!*!'"C1#!J!,!90*9'9cD'aL!`#3"J@9JJ3!#`&6594PFfKXBJ3
!N!B&QB)!3!#3!`S!!Irr!&F!h`&#!*!$J!#382q3#2L)N!D2q)lSlSlSlSrrL*!
'M`rrN!F!N!Y!!*!8rrq!!CYY`!&rr`#3&[q3#(rr!*!%!3#38Iq3")!!!!'2(Ma
jL4)N5BN5*%Q*%L4*MaimHF!!!!&99G99Irprr`#3@2q3)(rrN!0rrj!$!*!+!J#
3r`#33[q3%2L)N!k2q)MZlSL1lZL)lZk)MZlSMrL)lZk)MZlSL1lZL)lZk)riL1l
ZL)lZk)MZlSL1lZL2q)MZlSL1lZL)lZk)MZlSMrL)lZk)MZlSL1lZL)lZk)rrL*!
1M`q"N!D2ri'3"Sm2rj!($rq3"`#3)`GMC'9f!*!'((*NFfX!N!-"4P*&4J#3"2!
J5801)`#3"2!J!*!$Z`#l!*!&)!!J%3'J!))"!!S!N!8J!##3!!!%!*!&)!!J!*!
&)!!J!*!&)!!J!*!Zrj!%J!!!!BmH2(Q*%L4*L4)N5BN5*%Q2(Maj`!!!!999e99
rrhrr!*!XS!#$r`#3!`3!!2rr!*!$63"0!*-!B!#9!8%4!D!!JU!!MJ%!#J#3"!,
3!N#B!"i!N`"J!*8"5!#6!'!!P3&"!*-!B!#9!8%!!!APL!'!!!APL!'!!+!!Mk!
!Jrm!!!%!N"B#Dp!!N+d#E2!!N$S#DJ!2!*!&!3!H!#8"')9*)*!54f&bFQ9dG#G
c)&G[FQYcD'p`$5#3%e*265"%DA0V)&0PG(4TEQGc!*!'!`%(!#-"*m!#!)!!N!8
V!&`!23%p"4*#Efpd)'CbEfdJ8Np0)'4TFfX!N!8j!'m!43%qL#&"E(GKHA-JBQp
[G#"cHA0dC@dJCR*[E5"56ddJC'PcDbi!N!C+!&`!A!%p"3j0Eh9ZG#"56ddJC'P
cD`#3"9J!E`"N!6k)+8e[G@jd)'4TFfXJGfKPEL"LEfpdD@jR)'CbEfdJEh4SCA)
JC(*TGQ8Z!*!'D3"F!(X"23824@jKBQaP)&*"65"NDA0V!*!'G`"[!)-"2SJU3@a
XEhFJGh*TG'PZCb"dEb"56ddJC'PcDbiJAM"03L"538dJFQ9a*f3Z!*!&cJ"F!0S
"2BJQ3fKKEQGPFb"hD@aX)(4KDf8JC@CQC@0d)'&QG'9b)(*PBQp[G#i!N!8R!&`
!+!%p`!)!J3#3"FS!A!$,!6h!!J#"!*!&L!"F!)N"2F!#!)%!N!@-!&`!QJ%p"3p
&EQ&LE'8JC'9LG@GRCA)!N!DD!'m!TJ%qL#*&EQ&LE'8J*eia*b"hD'9Z)'*[Eh4
TEQFJCR*[E5"56ddZ!*!&U`"F!,N"23894@jKBQaP)%0%,9*265"cGA"`Eh*d!*!
'Z3"[!-8"2SJL4@jKBQaP)#GH-LFJGfKPEL"LEfpdD@jR)'CbEfdJ8Np0,J!!!3#
3!`Q6!!!)N`!!!48!dqYN$CJ!N!-F!3B!#QjbBh3!N!0DD@0c0!#3!fCTBh-M!*!
$FNP$6L-!N!0q4P*&4J#3!iT#6N4-!*!$PQPME$3!N!1L8%P$9!!"!+jYB@0S!*!
$aR*NFfX!N!254%P86!#3!pl`)2rr!*!)m#$rr`#3!`i!N!6`)2rr!*!$NJ#3"2!
JrrmJ!!$@!*!%m#$rr`!!!pi!N!6`)2rr!!!$k3#3"2!Jrrm!!!(D!*!&J2rr!!!
%#3$6rVJ!JIrr!!!%d!$6rXM`)2rr!!!%b!#3#J8K!*!%m#$rr`!!"L8!drm!$Np
hEQ9b)(*PFfpeFQ0P8D8!:

BIN
bin/ROMBUS_8M.bin Executable file

Binary file not shown.

BIN
bin/baserom_rombus_ramtest.bin Executable file

Binary file not shown.

BIN
bin/driver.bin Executable file

Binary file not shown.

10
entry.s
View File

@ -32,25 +32,25 @@ dc.l 0x00780000
DOpen:
movem.l %A0-%A1, -(%SP)
bsr RDOpen
bsr RBOpen
movem.l (%SP)+, %A0-%A1
rts
DClose:
movem.l %A0-%A1, -(%SP)
bsr RDClose
bsr RBClose
movem.l (%SP)+, %A0-%A1
rts
DPrime:
movem.l %A0-%A1, -(%SP)
bsr RDPrime
bsr RBPrime
movem.l (%SP)+, %A0-%A1
bra.b IOReturn
DControl:
movem.l %A0-%A1, -(%SP)
bsr RDCtl
bsr RBCtl
movem.l (%SP)+, %A0-%A1
cmpi.w #killCode, kcsCode(%A0)
bne.b IOReturn
@ -58,7 +58,7 @@ DControl:
DStatus:
movem.l %A0-%A1, -(%SP)
bsr RDStat
bsr RBStat
movem.l (%SP)+, %A0-%A1
IOReturn:

View File

@ -1,89 +0,0 @@
# path to RETRO68
RETRO68=~/Retro68-build/toolchain
PREFIX=$(RETRO68)/bin/m68k-apple-macos
AS=$(PREFIX)-as
CC=$(PREFIX)-gcc
LD=$(PREFIX)-ld
OBJCOPY=$(PREFIX)-objcopy
OBJDUMP=$(PREFIX)-objdump
CFLAGS=-march=68030 -c -Os
all: bin/rom16M_swap.bin obj/rdisk7M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym
obj:
mkdir obj
bin:
mkdir bin
obj/entry.o: entry.s obj
$(AS) $< -o $@
obj/entry_rel.sym: obj obj/entry.o
$(OBJDUMP) -t obj/entry.o > $@
obj/rdisk7M5.o: rdisk.c obj
$(CC) -Wall -DRDiskSize=7864320 $(CFLAGS) $< -o $@
obj/rdisk7M5.s: obj obj/rdisk7M5.o
$(OBJDUMP) -d obj/rdisk7M5.o > $@
obj/spi.o: spi.c obj
$(CC) -Wall $(CFLAGS) $< -o $@
obj/spi.s: obj obj/spi.o
$(OBJDUMP) -d obj/spi.o > $@
obj/sdmmc.o: sdmmc.c obj
$(CC) -Wall $(CFLAGS) -Os $< -o $@
obj/sdmmc.s: obj obj/sdmmc.o
$(OBJDUMP) -d obj/sdmmc.o > $@
obj/driver7M5.o: obj obj/entry.o obj/rdisk7M5.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk7M5.o obj/spi.o obj/sdmmc.o
obj/driver7M5.s: obj obj/driver7M5.o
$(OBJDUMP) -d obj/driver7M5.o > $@
obj/driver_abs.sym: obj obj/driver7M5.o
$(OBJDUMP) -t obj/driver7M5.o > $@
bin/driver7M5.bin: bin obj/driver7M5.o
$(OBJCOPY) -O binary obj/driver7M5.o $@
bin/rom8M.bin: bin baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym obj/entry_rel.sym
cp baserom.bin $@ # Copy base rom
# Patch driver
dd if=bin/driver7M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
printf '\x78' | dd of=$@ bs=1 seek=335168 count=1 conv=notrunc # Set resource flags
printf '\x4F' | dd of=$@ bs=1 seek=335216 count=1 conv=notrunc # Set driver flags
cat obj/entry_rel.sym | grep "DOpen" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335224 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DPrime" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335226 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DControl" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335228 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
dd if=RDisk7M5.dsk of=$@ bs=1024 seek=512 count=7680 conv=notrunc # copy disk image
bin/rom8M_swap.bin: bin bin/rom8M.bin
dd if=bin/rom8M.bin of=$@ conv=swab # swap bytes
bin/iisi_swap.bin: bin iisi.bin
dd if=iisi.bin of=$@ conv=swab # swap bytes
bin/rom16M_swap.bin: bin/iisi_swap.bin bin/rom8M_swap.bin
cat bin/rom8M_swap.bin > $@
cat bin/iisi_swap.bin >> $@
.PHONY: clean
clean:
rm -fr bin obj

View File

@ -1,84 +0,0 @@
.EQU killCode, 1
.EQU noQueueBit, 9
.EQU kioTrap, 6
.EQU kioResult, 16
.EQU kcsCode, 26
.EQU JIODone, 0x08FC
.GLOBAL RDiskSig
.GLOBAL RDiskDBGNamePos
.GLOBAL RDiskDBGDisPos
.GLOBAL RDiskDBGDisByte
.GLOBAL RDiskCDRNamePos
.GLOBAL RDiskCDRDisPos
.GLOBAL RDiskCDRDisByte
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
RDiskSig:
.ascii "\5RDisk\0"
.align 4
RDiskDBGDisPos:
dc.l 0x00000031
RDiskCDRDisPos:
dc.l 0x00012CAF
RDiskDBGNameAddr:
dc.l 0x4088002A
RDiskCDRNameAddr:
dc.l 0x40892C96
RDiskDBGDisByte:
dc.b 0x44
RDiskCDRDisByte:
dc.b 0x44
RDiskRAMRequired:
.ascii "16"
.align 4
DOpen:
movem.l %A0-%A1, -(%SP)
bsr RDOpen
movem.l (%SP)+, %A0-%A1
rts
DClose:
movem.l %A0-%A1, -(%SP)
bsr RDClose
movem.l (%SP)+, %A0-%A1
rts
DPrime:
movem.l %A0-%A1, -(%SP)
bsr RDPrime
movem.l (%SP)+, %A0-%A1
bra.b IOReturn
DControl:
movem.l %A0-%A1, -(%SP)
bsr RDCtl
movem.l (%SP)+, %A0-%A1
cmpi.w #killCode, kcsCode(%A0)
bne.b IOReturn
rts
DStatus:
movem.l %A0-%A1, -(%SP)
bsr RDStat
movem.l (%SP)+, %A0-%A1
IOReturn:
move.w kioTrap(%A0), %D1
btst #noQueueBit, %D1
beq.b Queued
NotQueued:
tst.w %D0
ble.b ImmedRTS
clr.w %D0
ImmedRTS:
move.w %D0, kioResult(%A0)
rts
Queued:
move.l JIODone, -(%SP)
rts

View File

@ -1,361 +0,0 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include "rdisk.h"
// Decode keyboard/PRAM settings
static void RDDecodeSettings(Ptr recoveryEN, Ptr unmountEN, Ptr mountEN) {
// Read PRAM
char legacy_startup;
RBReadXPRAM(1, 4, &legacy_startup);
// Decode settings: boot from recovery, unmount (don't boot), mount (after boot)
if (RBIsRPressed()) { // R boots from ROM recovery
*recoveryEN = 1; // Enable recovery partition
*unmountEN = 0; // Unmount SD so we don't boot from it
*mountEN = 1; // Mount SD later
} else {
*recoveryEN = 0; // Disable recovery partition
if (legacy_startup & 0x10) { // Boot from SD disk
*unmountEN = 0; // Don't unmount so we boot from this drive
*mountEN = 0; // No need to mount later since we are boot disk
} else if (legacy_startup & 0x20) { // Mount SD disk under other boot volume
*unmountEN = 1; // Unmount to not boot from our disk
*mountEN = 1; // Mount in accRun
} else {
*unmountEN = 1; // Unmount
*mountEN = 0; // Don't mount again
}
}
}
// Switch to 32-bit mode and copy
#pragma parameter C24(__A0, __A1, __D0)
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
signed char mode = true32b;
SwapMMUMode(&mode);
BlockMove(sourcePtr, destPtr, byteCount);
SwapMMUMode(&mode);
}
// Switch to 32-bit mode and get
#pragma parameter __D0 G24(__A2)
char __attribute__ ((noinline)) G24(Ptr pos) {
long ret;
signed char mode = true32b;
SwapMMUMode(&mode);
ret = *pos; // Peek
SwapMMUMode(&mode);
return ret;
}
// Switch to 32-bit mode and set
#pragma parameter S24(__A2, __D3)
void __attribute__ ((noinline)) S24(Ptr pos, char patch) {
signed char mode = true32b;
SwapMMUMode(&mode);
*pos = patch; // Poke
SwapMMUMode(&mode);
}
// Figure out the first available drive number >= 5
static int RBFindDrvNum() {
DrvQElPtr dq;
int drvNum = 5;
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
}
return drvNum;
}
static void RBOpenRDisk(RDiskStorage_t *c) {
int drvNum;
// Find first available drive number for ROM recovery
drvNum = RBFindDrvNum();
// Set ROM recovery drive status
//c->rStatus.track = 0;
c->rStatus.writeProt = -1; // nonzero is write protected
c->rStatus.diskInPlace = 8; // 8 is nonejectable disk
c->rStatus.installed = 1; // drive installed
//c->rStatus.sides = 0;
//c->rStatus.qType = 1;
c->rStatus.dQDrive = drvNum;
//c->rStatus.dQFSID = 0;
c->rStatus.dQRefNum = d->dCtlRefNum;
c->rStatus.driveSize = RDiskSize / 512;
//c->rStatus.driveS1 = (RDiskSize / 512) >> 16;
// Decompress icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
char *src = &RDiskIconCompressed[0];
char *dst = &c->rIcon[0];
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
#endif
// Add RDisk to drive queue and return
RDiskAddDrive(c->rStatus.dQRefNum, drvNum, (DrvQElPtr)&c->rStatus.qLink);
}
static void RBOpenSDisk(RDiskStorage_t *c) {
int drvNum;
// Find first available drive number for SD disk
drvNum = RBFindDrvNum();
// Set SD disk drive status
//c->rStatus.track = 0;
c->rStatus.writeProt = 0; // 0 is writable
c->rStatus.diskInPlace = 8; // 8 is nonejectable disk
c->rStatus.installed = 1; // drive installed
//c->rStatus.sides = 0;
c->rStatus.qType = 1;
c->rStatus.dQDrive = drvNum;
//c->rStatus.dQFSID = 0;
c->rStatus.dQRefNum = d->dCtlRefNum;
c->rStatus.driveSize = SDiskSize / 512;
c->rStatus.driveS1 = (SDiskSize / 512) >> 16;
// Decompress icon
#ifdef SDISK_COMPRESS_ICON_ENABLE
char *src = &SDiskIconCompressed[0];
char *dst = &c->sIcon[0];
UnpackBits(&src, &dst, SDISK_ICON_SIZE);
#endif
// Add SDisk to drive queue and return
RDiskAddDrive(c->rstatus.dQRefNum, drvNum, (DrvQElPtr)&c->sStatus.qLink);
}
#pragma parameter __D0 RBOpen(__A0, __A1)
OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
char legacy_startup;
// Do nothing if already opened
if (d->dCtlStorage) { return noErr; }
// Do nothing if inhibited
RBReadXPRAM(1, 4, &legacy_startup);
if (legacy_startup & 0x40) { return noErr; }
// Allocate storage struct
d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t));
if (!d->dCtlStorage) { return openErr; }
// Lock our storage struct and get master pointer
HLock(d->dCtlStorage);
c = *(RDiskStorage_t**)d->dCtlStorage;
// Create RDisk and SDisk entries in drive queue, then return
RBOpenRDisk(c);
RBOpenSDisk(c);
return noErr;
}
// Init is called at beginning of first prime (read/write) call
static void RBInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
char recoveryEN, unmountEN, mountEN;
// Mark init done
c->initialized = 1;
// Decode settings
RDDecodeSettings(&recoveryEN, &unmountEN, &mountEN);
// Unmount if not booting from ROM disk
if (!recoveryEN) { c->rStatus.diskInPlace = 0; }
// Unmount if not booting from ROM disk
if (unmountEN) { c->SStatus.diskInPlace = 0; }
// If mount enabled, enable accRun to post disk inserted event later
if (mountEN) {
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
}
}
static OSErr RDPrime(IOParamPtr p, DCtlPtr d) {
// Get pointer to correct position in ROM disk buffer
Ptr disk = RDiskBuf + d->dCtlPosition;
// Return disk offline error if virtual disk not inserted
if (!c->rStatus.diskInPlace) { return offLinErr; }
// Bounds checking
if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize ||
d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; }
// Service read or write request
cmd = p->ioTrap & 0x00FF;
if (cmd == aRdCmd) {
if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); }
else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); }
} else if (cmd == aWrCmd) { return wPrErr;
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
// Update count and position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
static OSErr SDPrime(IOParamPtr p, DCtlPtr d) {
}
#pragma parameter __D0 RBPrime(__A0, __A1)
OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
char cmd;
// Return disk offline error if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Initialize if this is the first prime call
if (!c->initialized) { RBInit(p, d, c); }
if (p->ioVRefNum == c->sStatus.dQDrive) {
return SDPrime(p, d, c);
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
return RDPrime(p, d, c);
} else { return nsvErr; }
}
static OSErr RDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
// Handle control request based on csCode
switch (p->csCode) {
case kFormat: return controlErr;
case kVerify:
if (!c->rStatus.diskInPlace) { return controlErr; }
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->rStatus.diskInPlace) {
PostEvent(diskEvt, c->status.dQDrive);
}
return controlErr; // Eject not allowed so return error
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->rIcon;
#else
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
#endif
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x11 is ROM disk)
*(long*)p->csParam = 0x00000411;
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = RDiskSize / 512;
return noErr;
default: return controlErr;
}
}
static OSErr SDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
// Handle control request based on csCode
switch (p->csCode) {
case kFormat:
// FIXME: implement SD format
return controlErr;
case kVerify:
// FIXME: implement SD verify
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->sStatus.diskInPlace) {
PostEvent(diskEvt, c->sStatus.dQDrive);
}
return controlErr; // Eject not allowed so return error
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef SDISK_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->sIcon;
#else
*(Ptr*)p->csParam = (Ptr)SDiskIcon;
#endif
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x01 is unspecified drive)
*(long*)p->csParam = 0x00000401;
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = SDiskSize / 512;
return noErr;
default: return controlErr;
}
}
#pragma parameter __D0 RBCtl(__A0, __A1)
OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle control request based on csCode
switch (p->csCode) {
case killCode:
return noErr;
case accRun:
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
c->sStatus.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->sStatus.dQDrive); // Post disk inserted event
return noErr;
case 2351: // Post-boot
c->initialized = 1; // Skip initialization
d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
return noErr;
}
// Otherwise, dispatch to correct drive
if (p->ioVRefNum == c->sStatus.dQDrive) {
return SDCtl(p, d, c);
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
return RDCtl(p, d, c);
} else { return nsvErr; }
}
#pragma parameter __D0 RBStat(__A0, __A1)
OSErr RBStat(CntrlParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
// Otherwise, copy correct drive status
if (p->ioVRefNum == c->sStatus.dQDrive) {
BlockMove(&c->sStatus, &p->csParam, sizeof(DrvSts2));
} else if (p->ioVRefNum == c->rStatus.dQDrive) {
BlockMove(&c->rStatus, &p->csParam, sizeof(DrvSts2));
} else { return nsvErr; }
return noErr;
default: return statusErr;
}
}
#pragma parameter __D0 RBClose(__A0, __A1)
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
//RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage;
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}

View File

@ -1,179 +0,0 @@
#ifndef ROMBUS_H
#define ROMBUS_H
#define RDiskBuf ((char*)0x408C0000)
#define SDiskSize (0x80000000L)
#define BufPtr ((Ptr*)0x10C)
#define MemTop ((Ptr*)0x108)
#define MMU32bit ((char*)0xCB2)
#pragma parameter __D0 RBReadXPRAM(__D0, __D1, __A0)
OSErr RBReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
#pragma parameter __D0 RBAddDrive(__D1, __D0, __A0)
OSErr RBAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
static inline char RBIsRPressed() { return *((char*)0x175) & 0x80; }
typedef struct RBStorage_s {
DrvSts2 sStatus;
DrvSts2 rStatus;
char initialized;
} RBStorage_t;
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
typedef char (*RDiskPeek_t)(Ptr);
#define peek24(a, d) { RDiskPeek_t f = G24; d = f(a); }
typedef void (*RDiskPoke_t)(Ptr, char);
#define poke24(a, d) { RDiskPoke_t f = S24; f(a, d); }
#define RDISK_ICON_SIZE (285)
const char RDiskIcon[RDISK_ICON_SIZE] = {
// Icon
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b10000000, 0b00000000, 0b00000000, 0b00000001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001001, 0b00010010, 0b00100100, 0b01001001,
0b10001111, 0b00011110, 0b00111100, 0b01111001,
0b11000000, 0b00000000, 0b00000000, 0b00000001,
0b01010101, 0b01010101, 0b11010101, 0b01010101,
0b01111111, 0b11111111, 0b01111111, 0b11111111,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
// Mask
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b01111111, 0b11111111, 0b11111111, 0b11111111,
0b01111111, 0b11111111, 0b11111111, 0b11111111,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
};
#define SDISK_ICON_SIZE (283)
const char const SDiskIcon[SDISK_ICON_SIZE] = {
// Icon
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b00000000, 0b00000000, 0b00010000,
0b00000001, 0b00000001, 0b10000000, 0b11010000,
0b00000001, 0b01101101, 0b10110110, 0b11010000,
0b00000001, 0b01101101, 0b10110110, 0b11010000,
0b00000001, 0b01101101, 0b10110110, 0b11010000,
0b00000001, 0b01101101, 0b10110110, 0b11010000,
0b00000001, 0b01101101, 0b10110110, 0b11010000,
0b00000001, 0b00000000, 0b00000000, 0b00010000,
0b00000001, 0b00000000, 0b00000000, 0b00010000,
0b00000010, 0b00000000, 0b00000000, 0b00010000,
0b00000100, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001110, 0b00000000, 0b00000000, 0b00010000,
0b00000010, 0b00000000, 0b00000000, 0b00010000,
0b00000010, 0b00000000, 0b00000000, 0b00010000,
0b00000010, 0b00000000, 0b00000000, 0b00010000,
0b00000100, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001000, 0b00000000, 0b00000000, 0b00010000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
// Mask
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000001, 0b11111111, 0b11111111, 0b11110000,
0b00000011, 0b11111111, 0b11111111, 0b11110000,
0b00000111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00000011, 0b11111111, 0b11111111, 0b11110000,
0b00000011, 0b11111111, 0b11111111, 0b11110000,
0b00000011, 0b11111111, 0b11111111, 0b11110000,
0b00000111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00001111, 0b11111111, 0b11111111, 0b11110000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
25, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
'R', 'O', 'M', 'B', 'U', 'S', 0
};
#endif

View File

@ -1,220 +0,0 @@
#include "sdmmc.h"
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
#define INIT_PORT() init_port() /* Initialize MMC control port (CS/CLK/DI:output, DO:input) */
#define DLY_US(n) dly_us(n) /* Delay n microseconds */
#define FORWARD(d) forward(d) /* Data in-time processing function (depends on the project) */
/* Definitions for MMC/SDC command */
#define CMD0 (0x40+0) /* GO_IDLE_STATE */
#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */
#define CMD8 (0x40+8) /* SEND_IF_COND */
#define CMD16 (0x40+16) /* SET_BLOCKLEN */
#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */
#define CMD24 (0x40+24) /* WRITE_BLOCK */
#define CMD55 (0x40+55) /* APP_CMD */
#define CMD58 (0x40+58) /* READ_OCR */
/* Card type flags (CardType) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
static char CardType; /* 0:MMC, 1:SDv1, 2:SDv2, 3:Block addressing */
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static char send_cmd(char cmd, long arg)
{
char n, res;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
/* Select the card */
CS_H(); spi_rx();
CS_L(); spi_rx();
/* Send a command packet */
spi_tx(cmd); /* Start + Command index */
s((BYTE)(arg >> 24)); /* Argument[31..24] */
spi_tx((BYTE)(arg >> 16)); /* Argument[23..16] */
spi_tx((BYTE)(arg >> 8)); /* Argument[15..8] */
spi_tx((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
spi_tx(n);
/* Receive a command response */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do {
res = spi_rx();
} while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
sdstatus_t sdmmc_init()
{
char n, cmd, ty, buf[4];
uint tmr;
CS_H();
spi_skip(10); /* Dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
for (n = 0; n < 4; n++) buf[n] = spi_rx(); /* Get trailing return value of R7 resp */
if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (send_cmd(ACMD41, 1UL << 30) == 0) break;
DLY_US(1000);
}
if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
for (n = 0; n < 4; n++) buf[n] = spi_rx();
ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */
if (send_cmd(cmd, 0) == 0) break;
DLY_US(1000);
}
if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
ty = 0;
}
}
CardType = ty;
release_spi();
return ty ? 0 : STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read partial sector */
/*-----------------------------------------------------------------------*/
sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count)
{
DRESULT res;
char d;
uint bc, tmr;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
res = RES_ERROR;
if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */
tmr = 1000;
do { /* Wait for data packet in timeout of 100ms */
DLY_US(100);
d = spi_rx();
} while (d == 0xFF && --tmr);
if (d == 0xFE) { /* A data packet arrived */
bc = 514 - offset - count;
/* Skip leading bytes */
if (offset) spi_skip(offset);
/* Receive a part of the sector */
if (buff) { /* Store data to the memory */
do
*buff++ = spi_rx();
while (--count);
} else { /* Forward data to the outgoing stream */
do {
d = spi_rx();
FORWARD(d);
} while (--count);
}
/* Skip trailing bytes and CRC */
spi_skip(bc);
res = RES_OK;
}
}
release_spi();
return res;
}
/*-----------------------------------------------------------------------*/
/* Write partial sector */
/*-----------------------------------------------------------------------*/
sdresult_t sdmmc_writep(const Ptr buf, long sc)
{
DRESULT res;
UINT bc, tmr;
static UINT wc;
res = RES_ERROR;
if (buff) { /* Send data bytes */
bc = (UINT)sc;
while (bc && wc) { /* Send data bytes to the card */
spi_tx(*buff++);
wc--; bc--;
}
res = RES_OK;
} else {
if (sc) { /* Initiate sector write transaction */
if (!(CardType & CT_BLOCK)) sc *= 512; /* Convert to byte address if needed */
if (send_cmd(CMD24, sc) == 0) { /* WRITE_SINGLE_BLOCK */
spi_tx(0xFF); spi_tx(0xFE); /* Data block header */
wc = 512; /* Set byte counter */
res = RES_OK;
}
} else { /* Finalize sector write transaction */
bc = wc + 2;
while (bc--) spi_tx(0); /* Fill left bytes and CRC with zeros */
if ((spi_rx() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */
for (tmr = 10000; spi_rx() != 0xFF && tmr; tmr--) /* Wait for ready (max 1000ms) */
DLY_US(100);
if (tmr) res = RES_OK;
}
release_spi();
}
}
return res;
}

View File

@ -1,29 +0,0 @@
#ifndef SDMMC_H
#define SDMMC_H
/* Status of Disk Functions */
typedef char sdstatus_t;
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
/* Results of Disk Functions */
typedef enum sdmmc_result_e {
RES_OK = 0, /* 0: Function succeeded */
RES_ERROR, /* 1: Disk error */
RES_NOTRDY, /* 2: Not ready */
RES_PARERR /* 3: Invalid parameter */
} sdresult_t;
/*---------------------------------------*/
/* Prototypes for disk control functions */
/*---------------------------------------*/
sdstatus_t sdmmc_init();
sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count);
sdresult_t sdmmc_writep(const Ptr buf, long sc);
#endif

164
old/spi.c
View File

@ -1,164 +0,0 @@
#include "spi.h"
/*-------------------------------------------------------------------------*/
/* Platform dependent macros and functions needed to be modified */
/*-------------------------------------------------------------------------*/
#define CS_H() bset(P0) /* Set MMC CS "high" */
#define CS_L() bclr(P0) /* Set MMC CS "low" */
#define CK_H() bset(P1) /* Set MMC SCLK "high" */
#define CK_L() bclr(P1) /* Set MMC SCLK "low" */
#define DI_H() bset(P2) /* Set MMC DI "high" */
#define DI_L() bclr(P2) /* Set MMC DI "low" */
#define DO btest(P3) /* Test MMC DO (high:true, low:false) */
// Command listing
/* T16: Transfer 16-bit
* First, the 16-bit value encoded in the address bits A[17:2] is latched.
* The data output mux is set to the current RXR and the cycle completes.
* Shortly after /AS rises, the SPI transfer engine begins
* transferring the latched value.
*/
/* T16S: Transfer 16-bit Swapped
* Same as T16L but read data is byte-swapped.
*/
/* MERT: Measure Elapsed time and Reset Timer
* The elapsed time since the last MERT command is returned in D[31:24]
* and the timer is reset.
*/
/* SKIP1: Skip Clocks with MOSI "1"
*
*/
/* SKIP0: Skip Clocks with MOSI "0"
*
*/
/* T8S: Transfer 8-bit Swapped
* Same as T8 but read data is byte-swapped.
*/
/* T8: Transfer 8-bit
* First, the 8-bit value encoded in the address bits A[9:2] is latched.
* The data output mux is set to the current RXR and the cycle completes.
* Shortly after /AS rises, the SPI transfer engine begins
* transferring the latched value.
*/
/* WRC: Write Command
* The command encoded in address bits A[9:2] is sent to the command target
* corresponding to the address bits A[15:10].
* Command targets:
* $00 - Set bitbang
* A[2] - SCS value
*/
/* RDRXR: Read Receive Data Register
* The the current RXR is returned in D[31:16] and the cycle completes.
*/
/* RDRXRS: Read Receive Data Register Swapped
* Same as RDRXR but read data is byte-swapped.
*/
/* MAGIC: Write Command
* Write sequence $FF $00 $55 $AA $C1 $AD
* to enable registers at $40890000-$4097FFFF.
* Write anything else to disable them.
* Always reads 0xC1AD
*/
// SPI controller address map:
// 40940000-4097FFFF (256 kB, D[31:16]) T16S. Write transfer data in A[17:2].
// 40900000-4093FFFF (256 kB, D[31:16]) T16. Write transfer data in A[17:2].
// 408C0000-408FFFFF (320 kB) reserved
// 408A0000-408AFFFF ( 64 kB, D[31:24]) WRC. Write port address in A[15:10] and data in A[9:2].
// 40891C00-4089FFFF ( 55 kB) reserved
// 40892000-408923FF ( 1 kB, D[31:24]) MERT.
// 40891C00-40891FFF ( 1 kB) SKIP1. Write bytes to skip in A[9:2].
// 40891800-40891BFF ( 1 kB) SKIP0. Write bytes to skip in A[9:2].
// 40891400-408917FF ( 1 kB, D[31:16]) T8S. Write transfer data in A[9:2].
// 40891000-408913FF ( 1 kB, D[31:16]) T8. Write transfer data in A[9:2].
// 40890C00-40890FFF ( 1 kB, D[31:16]) RDRXRS.
// 40890800-40890BFF ( 1 kB, D[31:16]) RDRXR.
// 40890400-408907FF ( 1 kB) reserved
// 40890000-408903FF ( 1 kB, D[31:24]) MAGIC. Write magic numbers in A[9:2].
// 40880000-408FFFFF ( 64 kB, D[31:00]) ROMBUS driver data
#define RB_T16S(x) (*(volatile int*) (0x40940000 + ((x && 0xFFFF)<<02)) )
#define RB_T16(x) (*(volatile int*) (0x40900000 + ((x && 0xFFFF)<<02)) )
#define RB_RDS(a) (*(volatile char*) (0x408B0000 + ((a && 0x003F)<<10)) )
#define RB_WRC(a,d) (*(volatile char*) (0x408A0000 + ((a && 0x003F)<<10)
+ ((d && 0x00FF)<<02)) )
#define RB_MERT(x) (*(volatile char*) (0x40892000 + ((x && 0xFFFF)<<02)) )
#define RB_SKIP1(n) (*(volatile char*) (0x40891C00 + ((x && 0xFFFF)<<02)) )
#define RB_SKIP0(n) (*(volatile char*) (0x40891800 + ((x && 0xFFFF)<<02)) )
#define RB_T8S(x) (*(volatile int*) (0x40891400 + ((x && 0xFFFF)<<02)) )
#define RB_T8(x) (*(volatile int*) (0x40891000 + ((x && 0xFFFF)<<02)) )
#define RB_RDRXRS (*(volatile int*) (0x40890C00 + ((x && 0xFFFF)<<02)) )
#define RB_RDRXR (*(volatile int*) (0x40890800 + ((x && 0xFFFF)<<02)) )
#define RB_WRMOSI(x) (*(volatile char*) (0x40890400 + ((x && 0x0001)<<02)) )
#define RB_MAGIC(x) (*(volatile char*) (0x40890000 + ((x && 0xFFFF)<<02)) )
#define SPI_GET_MISO(d) (d & 1)
void spi_select() {
ret = *SPI_CMD_SEL0;
ret = *SPI_CMD_SEL1;
ret = *SPI_CMD_SEL2;
ret = *SPI_CMD_SEL3;
}
void spi_deselect() {
ret = *SPI_CMD_DES0;
ret = *SPI_CMD_DES1;
ret = *SPI_CMD_DES2;
ret = *SPI_CMD_DES3;
}
void spi_tx_slow(char d) {
for (int i = 0; i < 8; i++) {
*SPI_CMD_BBA((0 & 0x02) | (d & 0x01));
*SPI_CMD_BBA((1 & 0x02) | (d & 0x01));
d >>= 1;
}
*SPI_CMD_BBA((0 & 0x02) | (0 & 0x01));
}
char spi_rx_slow() {
char ret = 0;
for (int i = 0; i < 8; i++) {
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
ret = (ret << 1) + (*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)) & 1);
}
return ret;
}
void spi_skip_slow(int n) {
while (n-- > 0) {
for (int i = 0; i < 8; i++) {
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01));
}
}
*SPI_CMD_BBA((0 & 0x02) | (1 & 0x01));
}
void spi_tx_8(char d) {
*SPI_CMD_SH8(d);
}
char spi_rx_8() {
*SPI_CMD_SH8(0xFF);
return *SPI_CMD_RD & 0xFF;
}
void spi_tx_16(int d) {
*SPI_CMD_SH16(d);
}
int spi_rx_16() {
*SPI_CMD_SH16(0xFFFF);
return *SPI_CMD_RD & 0xFFFF;
}
void spi_skip(int n) {
while (n-- > 0) {
for (int i = 0; i < 8; i++) {
*SPI_CMD_SH8(0xFF);
}
}
}

View File

@ -1,17 +0,0 @@
#ifndef SPI_H
#define SPI_H
void spi_select();
void spi_deselect();
void spi_tx_slow(char d);
char spi_rx_slow();
void spi_skip_slow(int n);
void spi_tx_8(char d);
char spi_rx_8();
void spi_tx_16(int d);
int spi_rx_16();
void spi_skip(int n);
#endif

View File

@ -1,11 +0,0 @@
#ifndef RDISK_H
#define RDISK_H
#pragma parameter xfer_s_256(__A0, __A1)
void xfer_s_256(Ptr srcreg, Ptr destmem);
#pragma parameter xfer_s(__D0, __A0, __A1)
void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem);
#endif

View File

@ -1,34 +0,0 @@
.macro xfer_in from, to
move.w (%A0), (%A1)+
nop
nop
nop
.if \to-\from
xfer_in "(\from+1)"
.else
.endif
.endm
;pragma parameter xfer_s_256(__A0, __A1)
;void xfer_s_256(Ptr srcreg, Ptr destmem);
xfer_256:
movem.l %D0/%A1-%A2, -(%SP)
xfer_256_loop:
xfer_s_in 0, 255
xfer_256_end:
movem.l (%SP)+, %D0/%A1-%A2
;pragma parameter xfer_s(__D0, __A0, __A1)
;void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem);
xfer:
movem.l %D0/%A1-%A2, -(%SP)
andi.l #0xFF, %D0
subi.l #256, %D0
neg.l %D0
lsl.l #2, %D0
addi.l #xfer_256, %D0
movea.l %D0, %A2
jmp %A2

23
priv_syscall.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _PRIV_SYSCALL_H
#define _PRIV_SYSCALL_H
#include <Disks.h>
#include <OSUtils.h>
#pragma parameter __D0 PSReadXPRAM(__D0, __D1, __A0)
OSErr PSReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
#pragma parameter __D0 PSAddDrive(__D1, __D0, __A0)
OSErr PSAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
// Figure out the first available drive number >= 5
static int PSFindDrvNum() {
DrvQElPtr dq;
int drvNum = 5;
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
}
return drvNum;
}
#endif

353
rdisk.c
View File

@ -1,353 +0,0 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include "rdisk.h"
// Decode keyboard/PRAM settings
static void RDDecodeSettings(Ptr unmountEN, Ptr mountEN, Ptr ramEN, Ptr dbgEN, Ptr cdrEN) {
// Sample R and A keys repeatedly
char r = 0, a = 0;
long tmax = TickCount() + 60;
for (long i = 0; i < 1000000; i++) {
a |= RDiskIsAPressed();
r |= RDiskIsRPressed() | a;
if (r) { break; }
if (TickCount() > tmax) { break; }
}
// Read PRAM
char legacy_startup, legacy_ram;
RDiskReadXPRAM(1, 4, &legacy_startup);
RDiskReadXPRAM(1, 5, &legacy_ram);
// Decode settings: unmount (don't boot), mount (after boot), RAM disk
if (r) { // R boots from ROM disk
*unmountEN = 0; // Don't unmount so we boot from this drive
*mountEN = 0; // No need to mount later since we are boot disk
*ramEN = a; // A enables RAM disk
*dbgEN = 0;
*cdrEN = 0;
} else {
if (legacy_startup & 0x01) { // Boot from ROM disk
*unmountEN = 0; // Don't unmount so we boot from this drive
*mountEN = 0; // No need to mount later since we are boot disk
*ramEN = legacy_ram & 0x01; // Allocate RAM disk if bit 0 == 1
*dbgEN = legacy_startup & 0x04; // MacsBug enabled if bit 2 == 1
*cdrEN = legacy_startup & 0x08; // CD-ROM enabled if bit 3 == 1
} else if (!(legacy_startup & 0x02)) { // Mount ROM disk
*unmountEN = 1; // Unmount to not boot from our disk
*mountEN = 1; // Mount in accRun
*ramEN = legacy_ram & 0x01; // Allocate RAM disk if bit 0 == 1
*dbgEN = 1; // CD-ROM ext. always enabled in mount mode
*cdrEN = 1; // MacsBug always enabled in mount mode
} else {
*unmountEN = 1; // Unmount
*mountEN = 0; // Don't mount again
*ramEN = 0; // Don't allocate RAM disk
*dbgEN = 1; // CD-ROM ext. always enabled in unmount mode
*cdrEN = 1; // MacsBug always enabled in unmount mode
}
}
}
// Switch to 32-bit mode and copy
#pragma parameter C24(__A0, __A1, __D0)
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
signed char mode = true32b;
SwapMMUMode(&mode);
BlockMove(sourcePtr, destPtr, byteCount);
SwapMMUMode(&mode);
}
// Switch to 32-bit mode and get
#pragma parameter __D0 G24(__A2)
char __attribute__ ((noinline)) G24(Ptr pos) {
long ret;
signed char mode = true32b;
SwapMMUMode(&mode);
ret = *pos; // Peek
SwapMMUMode(&mode);
return ret;
}
// Switch to 32-bit mode and set
#pragma parameter S24(__A2, __D3)
void __attribute__ ((noinline)) S24(Ptr pos, char patch) {
signed char mode = true32b;
SwapMMUMode(&mode);
*pos = patch; // Poke
SwapMMUMode(&mode);
}
// Figure out the first available drive number >= 5
static int RDFindDrvNum() {
DrvQElPtr dq;
int drvNum = 5;
for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; }
}
return drvNum;
}
#pragma parameter __D0 RDOpen(__A0, __A1)
OSErr RDOpen(IOParamPtr p, DCtlPtr d) {
int drvNum;
RDiskStorage_t *c;
char legacy_startup;
// Do nothing if already opened
if (d->dCtlStorage) { return noErr; }
// Do nothing if inhibited
RDiskReadXPRAM(1, 4, &legacy_startup);
if (legacy_startup & 0x80) { return noErr; }
// Allocate storage struct
d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t));
if (!d->dCtlStorage) { return openErr; }
// Lock our storage struct and get master pointer
HLock(d->dCtlStorage);
c = *(RDiskStorage_t**)d->dCtlStorage;
// Find first available drive number
drvNum = RDFindDrvNum();
// Get debug and CD-ROM disable settings from ROM table
c->dbgDisByte = RDiskDBGDisByte;
c->cdrDisByte = RDiskCDRDisByte;
// Set drive status
//c->status.track = 0;
c->status.writeProt = -1; // nonzero is write protected
c->status.diskInPlace = 8; // 8 is nonejectable disk
c->status.installed = 1; // drive installed
//c->status.sides = 0;
//c->status.qType = 1;
c->status.dQDrive = drvNum;
//c->status.dQFSID = 0;
c->status.dQRefNum = d->dCtlRefNum;
c->status.driveSize = RDiskSize / 512;
//c->status.driveS1 = (RDiskSize / 512) >> 16;
// Decompress icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
char *src = &RDiskIconCompressed[0];
char *dst = &c->icon[0];
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
#endif
// Add drive to drive queue and return
RDiskAddDrive(c->status.dQRefNum, drvNum, (DrvQElPtr)&c->status.qLink);
return noErr;
}
// Init is called at beginning of first prime (read/write) call
static void RDInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) {
char unmountEN, mountEN, ramEN, dbgEN, cdrEN;
// Mark init done
c->initialized = 1;
// Decode settings
RDDecodeSettings(&unmountEN, &mountEN, &ramEN, &dbgEN, &cdrEN);
// If RAM disk enabled, try to allocate RAM disk buffer if not already
if (ramEN & !c->ramdisk) {
if (*MMU32bit) { // 32-bit mode
unsigned long minBufPtr, newBufPtr;
// Compute if there is enough high memory
minBufPtr = ((unsigned long)*MemTop / 2) + 1024;
newBufPtr = (unsigned long)*BufPtr - RDiskSize;
if (newBufPtr > minBufPtr && (unsigned long)*BufPtr > newBufPtr) {
// Allocate RAM disk buffer by lowering BufPtr
*BufPtr = (Ptr)newBufPtr;
// Set RAM disk buffer pointer.
c->ramdisk = *BufPtr;
// Copy ROM disk image to RAM disk
BlockMove(RDiskBuf, c->ramdisk, RDiskSize);
// Clearing write protect marks RAM disk enabled
c->status.writeProt = 0;
}
} else { // 24-bit mode
// Put RAM disk just past 8MB
c->ramdisk = (Ptr)(8 * 1024 * 1024);
// Copy ROM disk image to RAM disk
//FIXME: what if we don't have enough RAM?
// Will this wrap around and overwrite low memory?
// That's not the worst, since the system would just crash,
// but it would be better to switch to read-only status
copy24(RDiskBuf, c->ramdisk, RDiskSize);
// Clearing write protect marks RAM disk enabled
c->status.writeProt = 0;
}
}
// Patch
if (RDiskDBGDisPos < RDiskSize) {
if (c->ramdisk && !dbgEN) {
poke24(c->ramdisk + RDiskDBGDisPos, c->dbgDisByte);
} else if (dbgEN) {
peek24(RDiskBuf + RDiskDBGDisPos, c->dbgDisByte);
}
}
if (RDiskCDRDisPos < RDiskSize) {
if (c->ramdisk && !cdrEN) {
poke24(c->ramdisk + RDiskCDRDisPos, c->cdrDisByte);
} else if (cdrEN) {
peek24(RDiskBuf + RDiskCDRDisPos, c->cdrDisByte);
}
}
// Unmount if not booting from ROM disk
if (unmountEN) { c->status.diskInPlace = 0; }
// If mount enabled, enable accRun to post disk inserted event later
if (mountEN) {
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
}
}
#pragma parameter __D0 RDPrime(__A0, __A1)
OSErr RDPrime(IOParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
char cmd;
Ptr disk;
// Return disk offline error if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Initialize if this is the first prime call
if (!c->initialized) { RDInit(p, d, c); }
// Return disk offline error if virtual disk not inserted
if (!c->status.diskInPlace) { return offLinErr; }
// Get pointer to RAM or ROM disk buffer
disk = (c->ramdisk ? c->ramdisk : RDiskBuf) + d->dCtlPosition;
// Bounds checking
if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize ||
d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; }
// Service read or write request
cmd = p->ioTrap & 0x00FF;
if (cmd == aRdCmd) { // Read
// Read from disk into buffer.
if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); }
else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); }
if (!c->ramdisk && RDiskDBGDisPos >= d->dCtlPosition &&
RDiskDBGDisPos < d->dCtlPosition + p->ioReqCount) {
p->ioBuffer[RDiskDBGDisPos - d->dCtlPosition] = c->dbgDisByte;
}
if (!c->ramdisk && RDiskCDRDisPos >= d->dCtlPosition &&
RDiskCDRDisPos < d->dCtlPosition + p->ioReqCount) {
p->ioBuffer[RDiskCDRDisPos - d->dCtlPosition] = c->cdrDisByte;
}
} else if (cmd == aWrCmd) { // Write
// Fail if write protected or RAM disk buffer not set up
if (c->status.writeProt || !c->ramdisk) { return wPrErr; }
// Write from buffer into disk.
if (*MMU32bit) { BlockMove(p->ioBuffer, disk, p->ioReqCount); }
else { copy24(StripAddress(p->ioBuffer), disk, p->ioReqCount); }
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
// Update count and position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
#pragma parameter __D0 RDCtl(__A0, __A1)
OSErr RDCtl(CntrlParamPtr p, DCtlPtr d) {
RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle control request based on csCode
switch (p->csCode) {
case killCode:
return noErr;
case kFormat:
if (!c->status.diskInPlace || c->status.writeProt ||
!c->ramdisk) { return controlErr; }
long long z = 0;
Ptr pz;
if (*MMU32bit) { pz = (Ptr)&z; }
else { pz = StripAddress((Ptr)&z); }
for (int i = 0; i < 4095; i++) {
copy24(c->ramdisk + i * sizeof(z), pz, sizeof(z));
}
return noErr;
case kVerify:
if (!c->status.diskInPlace) { return controlErr; }
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->status.diskInPlace) {
PostEvent(diskEvt, c->status.dQDrive);
}
return controlErr; // Eject not allowed so return error
case accRun:
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
c->status.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->status.dQDrive); // Post disk inserted event
return noErr;
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef RDISK_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->icon;
#else
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
#endif
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk)
if (c->status.writeProt) { *(long*)p->csParam = 0x00000411; }
else { *(long*)p->csParam = 0x00000410; }
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = RDiskSize / 512;
return noErr;
case 2351: // Post-boot
c->initialized = 1; // Skip initialization
d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
return noErr;
default: return controlErr;
}
}
#pragma parameter __D0 RDStat(__A0, __A1)
OSErr RDStat(CntrlParamPtr p, DCtlPtr d) {
//RDiskStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
//c = *(RDiskStorage_t**)d->dCtlStorage;
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2));
return noErr;
default: return statusErr;
}
}
#pragma parameter __D0 RDClose(__A0, __A1)
OSErr RDClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
//RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage;
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}

252
rombus.c Normal file
View File

@ -0,0 +1,252 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include "rombus.h"
#include "spi.h"
#include "priv_syscall.h"
// Decode keyboard settings
static void RBDecodeKeySettings(RBStorage_t *c) {
// Sample R, S, X keys repeatedly
char r = 0, s = 0, x = 0;
long tmax = TickCount() + 60;
for (long i = 0; i < 1000000; i++) {
r |= IsRPressed();
s |= IsSPressed();
x |= IsXPressed();
if (r || s || x) { break; }
if (TickCount() > tmax) { break; }
}
// Decode settings
if (x) { // Unmount everything
c->unmountROMEN = 1;
c->unmountSDEN = 1;
c->mountROMEN = 0;
c->mountSDEN = 0;
} else if (s) { // Boot from SD, don't mount ROM
c->unmountROMEN = 1;
c->unmountSDEN = 0;
c->mountROMEN = 1;
c->mountSDEN = 0;
} else if (r) { // Boot from ROM, mount SD
c->unmountROMEN = 0;
c->unmountSDEN = 1;
c->mountROMEN = 0;
c->mountSDEN = 1;
}
}
// Decode PRAM settings
static OSErr RBDecodePRAMSettings(RBStorage_t *c) {
// Read PRAM
char legacy_startup, legacy_ram;
PSReadXPRAM(1, 4, &legacy_startup);
PSReadXPRAM(1, 5, &legacy_ram);
// Decoded settings
const char opt_disable = legacy_startup & (1<<7);
const char opt_boot_sd = legacy_startup & (1<<2);
const char opt_boot_rom = legacy_startup & (1<<0);
const char opt_mount_sd = legacy_startup & (1<<3);
const char opt_mount_rom = legacy_startup & (1<<4);
// Old settings for ROM SIMM (not used here)
//const char opt_old_mount_rom = !(legacy_startup & (1<<1));
//const char opt_old_ram = legacy_ram & (1<<0);
// Set based on decoded settings
if (opt_disable) { return -1; }
else {
c->unmountROMEN = !opt_boot_rom;
c->unmountSDEN = !opt_boot_sd;
c->mountROMEN = opt_mount_rom && !opt_boot_rom;
c->mountSDEN = opt_mount_sd && !opt_boot_sd;
}
return noErr;
}
// Switch to 32-bit mode and copy
#pragma parameter C24(__A0, __A1, __D0)
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
signed char mode = true32b;
SwapMMUMode(&mode);
BlockMove(sourcePtr, destPtr, byteCount);
SwapMMUMode(&mode);
}
#pragma parameter __D0 RBClose(__A0, __A1)
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}
#pragma parameter __D0 RBOpen(__A0, __A1)
OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
int drvNum;
RBStorage_t *c;
// Do nothing if already opened
if (d->dCtlStorage) { return noErr; }
// Allocate storage struct
d->dCtlStorage = NewHandleSysClear(sizeof(RBStorage_t));
if (!d->dCtlStorage) { return openErr; }
// Lock our storage struct and get master pointer
HLock(d->dCtlStorage);
c = *(RBStorage_t**)d->dCtlStorage;
// Do nothing if inhibited
if (RBDecodePRAMSettings(c) != noErr) {
RBClose(p, d);
return openErr;
}
// Iff mount enabled, enable accRun to post disk inserted event later
if (c->mountROMEN || c->mountSDEN) { d->dCtlFlags |= dNeedTimeMask; }
else { d->dCtlFlags &= ~dNeedTimeMask; }
// Set accRun delay
d->dCtlDelay = 150; // (150 ticks is 2.5 sec.)
// Find first available drive number
drvNum = PSFindDrvNum();
//TODO: set c->sdSize
// Set drive status
c->sdStatus.track = 0;
c->sdStatus.writeProt = 0; // nonzero is write protected
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
c->sdStatus.installed = 1; // drive installed
c->sdStatus.sides = 0;
c->sdStatus.qType = 1;
c->sdStatus.dQDrive = drvNum;
c->sdStatus.dQFSID = 0;
c->sdStatus.dQRefNum = d->dCtlRefNum;
c->sdStatus.driveSize = c->sdSize / 512;
c->sdStatus.driveS1 = (c->sdSize / 512) >> 16;
// Decompress icon
#ifdef RB_COMPRESS_ICON_ENABLE
char *src = &SDIconCompressed[0];
char *dst = &c->sd[0];
UnpackBits(&src, &dst, RB_ICON_SIZE);
#endif
// Add drive to drive queue and return
PSAddDrive(c->sdStatus.dQRefNum, drvNum, (DrvQElPtr)&c->sdStatus.qLink);
return noErr;
}
// Init is called at beginning of first prime (read/write) call
static void RBBootInit(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Mark init done
c->initialized = 1;
// Decode key settings
RBDecodeKeySettings(c);
// Unmount if not booting from ROM disk
if (c->unmountSDEN) { c->sdStatus.diskInPlace = 0; }
// Iff mount disabled, disable accRun
if (!c->mountSDEN || !c->mountROMEN) { d->dCtlFlags &= ~dNeedTimeMask; }
}
#pragma parameter __D0 RBPrime(__A0, __A1)
OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
RBStorage_t *c;
// Return disk offline error if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RBStorage_t**)d->dCtlStorage;
// Initialize if this is the first prime call
if (!c->initialized) { RBBootInit(p, d, c); }
// Return disk offline error if virtual disk not inserted
if (!c->sdStatus.diskInPlace) { return offLinErr; }
//TODO: Read/write
// Update count and position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
#pragma parameter __D0 RBCtl(__A0, __A1)
OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) {
RBStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RBStorage_t**)d->dCtlStorage;
// Handle control request based on csCode
switch (p->csCode) {
case kFormat:
if (!c->sdStatus.diskInPlace || c->sdStatus.writeProt) {
return controlErr;
}
//TODO: Format
return noErr;
case kVerify:
if (!c->sdStatus.diskInPlace) { return controlErr; }
return noErr;
case accRun:
c->initialized = 1; // Mark init done
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->sdStatus.dQDrive); // Post disk inserted event
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
return noErr;
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef RB_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->sd;
#else
*(Ptr*)p->csParam = (Ptr)RDiskIcon;
#endif
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk)
if (c->sdStatus.writeProt) { *(long*)p->csParam = 0x00000400; }
else { *(long*)p->csParam = 0x00000400; }
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = c->sdSize / 512;
return noErr;
case killCode: return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->sdStatus.diskInPlace) {
PostEvent(diskEvt, c->sdStatus.dQDrive);
}
return controlErr; // Eject not allowed so return error
default: return controlErr;
}
}
#pragma parameter __D0 RBStat(__A0, __A1)
OSErr RBStat(CntrlParamPtr p, DCtlPtr d) {
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2));
return noErr;
default: return statusErr;
}
}

View File

@ -1,9 +1,7 @@
#ifndef RDISK_H
#define RDISK_H
#ifndef _RDISK_H
#define _RDISK_H
#define RDiskBuf ((char*)0x40880000)
#define BufPtr ((Ptr*)0x10C)
#define MemTop ((Ptr*)0x108)
#define MMU32bit ((char*)0xCB2)
#define RDiskDBGDisPos (*(const unsigned long*)0x40851D98)
@ -12,42 +10,39 @@
#define RDiskCDRDisByte (*(const char*)0x40851DA9)
#define RDiskSize (*(const unsigned long*)0x40851DAC)
#define RDISK_COMPRESS_ICON_ENABLE
#define RB_COMPRESS_ICON_ENABLE
#pragma parameter __D0 RDiskReadXPRAM(__D0, __D1, __A0)
OSErr RDiskReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
static inline char IsRPressed() { return *((volatile char*)0x175) & 0x80; }
static inline char IsSPressed() { return *((volatile char*)0x174) & 0x02; }
static inline char IsXPressed() { return *((volatile char*)0x174) & 0x80; }
#pragma parameter __D0 RDiskAddDrive(__D1, __D0, __A0)
OSErr RDiskAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
static inline char RDiskIsRPressed() { return *((volatile char*)0x175) & 0x80; }
static inline char RDiskIsAPressed() { return *((volatile char*)0x174) & 0x01; }
#define RDISK_ICON_SIZE (285)
#define RB_ICON_SIZE (285)
typedef struct RDiskStorage_s {
DrvSts2 status;
DrvSts2 sdStatus;
long long sdSize;
char initialized;
#ifdef RDISK_COMPRESS_ICON_ENABLE
char icon[RDISK_ICON_SIZE+8];
char unmountSDEN;
char mountSDEN;
char unmountROMEN;
char mountROMEN;
#ifdef RB_COMPRESS_ICON_ENABLE
char sd[RB_ICON_SIZE+8];
#endif
} RDiskStorage_t;
} RBStorage_t;
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
typedef char (*RDiskPeek_t)(Ptr);
#define peek24(a, d) { RDiskPeek_t f = G24; d = f(a); }
typedef void (*RDiskPoke_t)(Ptr, char);
#define poke24(a, d) { RDiskPoke_t f = S24; f(a, d); }
#define PackBits_Repeat(count) (-1 * (count - 1))
#define PackBits_Literal(count) (count - 1)
#define RDISK_COMPRESSED_ICON_SIZE (87)
#ifdef RDISK_COMPRESS_ICON_ENABLE
#ifdef RB_COMPRESS_ICON_ENABLE
#include <Quickdraw.h>
const char RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
const char SDIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
PackBits_Repeat(76), 0b00000000, /*
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,
@ -130,7 +125,7 @@ const char RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = {
'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0
};
#else
const char RDiskIcon[RDISK_ICON_SIZE] = {
const char RDiskIcon[RB_ICON_SIZE] = {
// Icon
0b00000000, 0b00000000, 0b00000000, 0b00000000,
0b00000000, 0b00000000, 0b00000000, 0b00000000,

Binary file not shown.

129
spi.c Normal file
View File

@ -0,0 +1,129 @@
#include "spi.h"
#include "spi_hal.h"
static int _search_lt(char *buf, int stride, int threshold) {
for (int i = 1; i < 256; i++) {
if (buf[i * stride] < threshold) { return 1; }
}
return 0;
}
int _spi_hal_rx8_nops, _spi_hal_tx8_nops;
int _spi_hal_rx16_nops, _spi_hal_tx16_nops;
int _spi_hal_rxtx8_nops;
short *_spi_reg_rx16;
char *_spi_reg_tx16;
short *_spi_reg_rd16;
int spi_init(int swap) {
short buf16[256];
char *buf8 = (char*)&buf16;
for (int i = 0; i < 8; i++) {
spi_hal_rx8(SPI_REG_TIMER8, buf8, 256, i);
_spi_hal_rx8_nops = i;
_spi_hal_tx8_nops = i > 0 ? i - 1 : 0;
if (!_search_lt(buf8, 1, 8)) { break; }
}
for (int i = 0; i < 16; i++) {
spi_hal_rx16(SPI_REG_TIMER16, buf16, 256, i);
_spi_hal_rx16_nops = i;
_spi_hal_tx16_nops = i > 0 ? i - 1 : 0;
if (!_search_lt(buf8, 2, 8)) { break; }
}
for (int i = 0; i < 8; i++) {
spi_hal_rxtx8(SPI_REG_EMPTY, SPI_REG_TIMER16, buf8, buf8, 256, i);
_spi_hal_rxtx8_nops = i;
if (!_search_lt(buf8, 1, 8)) { break; }
}
_spi_reg_rx16 = swap ? SPI_REG_RX16S : SPI_REG_RX16;
_spi_reg_tx16 = swap ? SPI_REG_TX16S : SPI_REG_TX16;
_spi_reg_rd16 = swap ? SPI_REG_RD16S : SPI_REG_RD16;
return 0;
}
void spi_cs(int cs) {
if (cs) { SPI_REG_CSR_SET_CS(); }
else { SPI_REG_CSR_CLR_CS(); }
}
char spi_txrx8_slow(char txd) {
char rxd = 0;
for (int i = 7; i >= 0; i--) {
spi_delay(64);
SPI_REG_CSR_CLR_SCK();
spi_delay(64);
SPI_REG_SET_MOSI((txd >> i) & 1);
rxd = (rxd << 1) | SPI_REG_CSR_GET_MISO();
SPI_REG_CSR_SET_SCK();
}
spi_delay(64);
SPI_REG_CSR_CLR_SCK();
return rxd;
}
char spi_txrx8(char txd) {
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
return *SPI_REG_RD8;
}
char spi_rxtx8(char txd) {
char rxd = *SPI_REG_RD8;
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
return rxd;
}
#define UNROLL_LENGTH 5
void spi_rx(char txd, char *rxb, unsigned int length) {
if (length == 0) { return; } // Return if length 0
// Word-align rx pointer by transferring 0/1 bytes
if ((int)rxb & 1) {
*(rxb++) = spi_rxtx8(txd);
length--;
}
// Set tx pattern
reg_write16(SPI_REG_ST16, smear8to32(txd));
// Transfer all but 0-65 bytes
for (int i = length >> (UNROLL_LENGTH +1); i > 0; i--) {
// Transfer 2^UNROLL_LENGTH words (2 * 2^UNROLL_LENGTH bytes)
spi_hal_rx16(_spi_reg_rx16, rxb, UNROLL_LENGTH, _spi_hal_rx16_nops);
}
// Transfer remaining 1-32 words (2-64 bytes)
spi_hal_rx16(_spi_reg_rx16, rxb, length >> 1, _spi_hal_rx16_nops);
// Transfer remaining byte if any
if (length & 1) { *(rxb++) = spi_rxtx8(txd); }
}
void spi_tx(char *txb, unsigned int length) {
if (length == 0) { return; } // Return if length 0
// Word-align tx pointer by transferring 0/1 bytes
if ((int)txb & 1) {
spi_rxtx8(*(txb++));
length--;
}
// Transfer all but 0-65 bytes
for (; length > UNROLL_LENGTH; length -= UNROLL_LENGTH) {
spi_hal_tx16(_spi_reg_tx16, txb, UNROLL_LENGTH, _spi_hal_tx16_nops);
}
// Transfer remaining 1-32 words (2-64 bytes)
spi_hal_tx16(_spi_reg_tx16, txb, length >> 1, _spi_hal_tx16_nops);
// Transfer remaining byte if any
if (length & 1) { spi_rxtx8(*(txb++)); }
}
char spi_rd8() { return *SPI_REG_RD8; }
short spi_rd16() { return *_spi_reg_rd16; }

20
spi.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _SPI_H
#define _SPI_H
#include <stddef.h>
int spi_init();
void spi_cs(int cs);
char spi_txrx8_slow(char txd);
char spi_txrx8(char txd);
char spi_rxtx8(char txd);
void spi_tx(char *txb, unsigned int length);
void spi_rx(char txd, char *rxb, unsigned int length);
char spi_rd8();
short spi_rd16();
#endif

79
spi_hal.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef _SPI_HAL_H
#define _SPI_HAL_H
#pragma parameter spi_delay(__D0)
extern void spi_delay(char iterations);
#pragma parameter _reg_write8(__A0, __D0, __D1)
extern void _reg_write8(void *addr, char data, int tmp);
static inline void reg_write8(void *addr, char data) { _reg_write8(addr, data, 0); }
#pragma parameter _reg_write16(__A0, __D0, __D1)
extern void _reg_write16(void *addr, short data, int tmp);
static inline void reg_write16(void *addr, short data) { _reg_write16(addr, data, 0); }
#pragma parameter __D0 smear8to32(__D0)
extern long smear8to32(char data);
// Read transfer registers
#define SPI_REG_RX8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_RX16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RX16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RD8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_RD16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RD16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_TIMER8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_TIMER16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
// Write transfer registers
#define SPI_REG_TX8 ((char*) 0x00000000) // A[07:00]==arg
#define SPI_REG_TX16 ((char*) 0x00000000) // A[15:00]==arg
#define SPI_REG_TX16S ((char*) 0x00000000) // A[05:00]==arg
#define SPI_REG_ST16 ((char*) 0x00000000) // A[15:00]==arg
#define SPI_REG_EMPTY ((char*) 0x00000000)
// Control/status register (read/write)
#define SPI_REG_RD_CSR ((char*) 0x00000000)
#define SPI_REG_WR_CSR ((char*) 0x00000000)
#define SPI_REG_CSR_BIT_nDET (0)
#define SPI_REG_CSR_GET_nDET() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_nDET) & 1)
#define SPI_REG_CSR_BIT_MISO (1)
#define SPI_REG_CSR_GET_MISO() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_MISO) & 1)
#define SPI_REG_CSR_BIT_SCK (2)
#define SPI_REG_CSR_SET_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_SCK))
#define SPI_REG_CSR_CLR_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_SCK))
#define SPI_REG_CSR_BIT_CS (3)
#define SPI_REG_CSR_SET_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_CS))
#define SPI_REG_CSR_CLR_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_CS))
#define SPI_REG_SET_MOSI(x) reg_write16(SPI_REG_ST16, x ? 0xFFFF : 0x0000)
#pragma parameter _spi_hal_rx8(__A0, __A2, __A4, __D0, __D1, __D2)
extern void _spi_hal_rx8(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rx8(void *reg, void *rx, int length, int nops) {
_spi_hal_rx8(reg, rx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_rx16(__A0, __A2, __A4, __D0, __D1, __D2)
extern void _spi_hal_rx16(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rx16(void *reg, void *rx, int length, int nops) {
_spi_hal_rx16(reg, rx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_tx8(__A0, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_tx8(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_tx8(void *reg, void *tx, int length, int nops) {
_spi_hal_tx8(reg, tx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_tx16(__A0, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_tx16(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_tx16(void *reg, void *tx, int length, int nops) {
_spi_hal_tx16(reg, tx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_rxtx8(__A0, __A1, __A2, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, int length, int nops) {
_spi_hal_rxtx8(reg, read, rx, tx, 0, length, nops, 0);
}
#endif

49
spi_hal.s Normal file
View File

@ -0,0 +1,49 @@
.global spi_delay
.global _reg_write16
.global _reg_write8
.global smear8to32
* delay calling convention
* D0 - iterations
spi_delay:
subq.w #1, %D0
bne.b spi_delay
rts
* reg_write calling convention
* A0 - address
* D0 - data (clobbered)
* D1 - clobbered
_reg_write8:
move.l %A0, %D1
andi.l #0xFFFFFF00, %D1
andi.l #0x000000FF, %D0
or %D1, %D0
movea %D0, %A0
move.l (%A0), %D0
rts
_reg_write16:
move.l %A0, %D1
andi.l #0xFFFF0000, %D1
andi.l #0x0000FFFF, %D0
or %D1, %D0
movea %D0, %A0
move.l (%A0), %D0
rts
* smear8to32 calling convention
* D0 - data in/out
smear8to32:
andi.l #0xFF, %D0
move.l %D0, %D1
lsl.w #8, %D1
or.w %D1, %D0
lsl.w #8, %D1
or.w %D1, %D0
lsl.w #8, %D1
or.w %D1, %D0
rts

98
spi_hal_common.s Normal file
View File

@ -0,0 +1,98 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
* D2 - clobbered (save SR)
* D3 - clobbered (save CACR)
.macro spi_call table, maxnops
* Limit %D0 (length) to 1-256
subq.w #1, %D0
andi.l #0xFF, %D0
addq.w #1, %D0
* Limit %D1 (nops) based on maxnops
.if \maxnops == 1
andi.l #1, %D1
.elseif \maxnops == 3
andi.l #3, %D1
.elseif \maxnops == 7
andi.l #7, %D1
.elseif \maxnops == 15
andi.l #15, %D1
.elseif \maxnops != 0
.error
.endif
* Convert length to offset
* %D0 = -%D0 (-length)
neg.l %D0
* %D0 = %D0 + 256 (-length + 256)
add.l #256, %D0
.if \maxnops != 0
* Combine nops with offset to get lookup table index
* %D1 = %D1 * 4 * 256 (nops * 256)
lsl.l #8, %D1
* %D0 = %D0 + %D1 (offset + nops*256)
or.l %D1, %D0
.endif
* Get index of entry point from lookup table
* %D0 = table[%D0] (table[4*(length+nops*256)])
move.l (\table - ., %PC, %D0.w : 4), %D0
* Save status register and disable interrupts
move.w %SR, %D2
ori.w #0x0700, %SR
* Save CACR in %D3
movec %CACR, %D3
* Copy CACR to %D1
move.l %D3, %D1
* Clear CACR bits:
* DE ('040 enable data cache) (31)
* WA ('030 write allocate) (13)
* DBE ('030 data burst enable) (12)
* CD ('030 clear data cache) (11)
* CED ('030 clear entry in data cache) (10)
* FD ('030 freeze data cache) (9)
* ED ('030 enable data cache) (8)
andi.l #0x7FFFC0FF, %D1
* Set '030 CACR bits:
* FD (freeze data cache) (9)
ori.w #0x0200, %D1
* Move back into CACR
movec.l %D1, %CACR
* Jump to entry point
* (table + table[length*4 + nops*4*256])
jmp (\table - ., %PC, %D0.l)
* Return statement for use with parameter checking
ret: rts
.endm
.macro lookup_table base, nbase, stride, n
dc.l \nbase - \base
dc.l \nbase + \stride - \base
dc.l \nbase + \stride+\stride - \base
dc.l \nbase + \stride+\stride+\stride - \base
.if \n > 0
lookup_table \base, \nbase + \stride+\stride+\stride+\stride, \stride, \n-4
.endif
.endm
.macro unroll_table macro, nops, n
.rept \n
\macro \nops
.endr
move.w %D2, %SR
movec.l %D3, %CACR
rts
.endm

73
spi_rx16.s Normal file
View File

@ -0,0 +1,73 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_rx16
.include "spi_hal_common.s"
.macro _spi_hal_rx16_iteration nops
move.w (%A0), (%A2)+
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rx16:
spi_call _spi_hal_rx16_lookup, 15
.align 16
_spi_hal_rx16_lookup:
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_0, 2, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_1, 4, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_2, 6, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_3, 8, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_4, 10, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_5, 12, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_6, 14, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_7, 16, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_8, 18, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_9, 20, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_10, 22, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_11, 24, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_12, 26, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_13, 28, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_14, 30, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_15, 32, 256
.align 16
_spi_hal_rx16_table_0: unroll_table _spi_hal_rx16_iteration, 0, 256
.align 16
_spi_hal_rx16_table_1: unroll_table _spi_hal_rx16_iteration, 1, 256
.align 16
_spi_hal_rx16_table_2: unroll_table _spi_hal_rx16_iteration, 2, 256
.align 16
_spi_hal_rx16_table_3: unroll_table _spi_hal_rx16_iteration, 3, 256
.align 16
_spi_hal_rx16_table_4: unroll_table _spi_hal_rx16_iteration, 4, 256
.align 16
_spi_hal_rx16_table_5: unroll_table _spi_hal_rx16_iteration, 5, 256
.align 16
_spi_hal_rx16_table_6: unroll_table _spi_hal_rx16_iteration, 6, 256
.align 16
_spi_hal_rx16_table_7: unroll_table _spi_hal_rx16_iteration, 7, 256
.align 16
_spi_hal_rx16_table_8: unroll_table _spi_hal_rx16_iteration, 8, 256
.align 16
_spi_hal_rx16_table_9: unroll_table _spi_hal_rx16_iteration, 9, 256
.align 16
_spi_hal_rx16_table_10: unroll_table _spi_hal_rx16_iteration, 10, 256
.align 16
_spi_hal_rx16_table_11: unroll_table _spi_hal_rx16_iteration, 11, 256
.align 16
_spi_hal_rx16_table_12: unroll_table _spi_hal_rx16_iteration, 12, 256
.align 16
_spi_hal_rx16_table_13: unroll_table _spi_hal_rx16_iteration, 13, 256
.align 16
_spi_hal_rx16_table_14: unroll_table _spi_hal_rx16_iteration, 14, 256
.align 16
_spi_hal_rx16_table_15: unroll_table _spi_hal_rx16_iteration, 15, 256

49
spi_rx8.s Normal file
View File

@ -0,0 +1,49 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_rx8
.include "spi_hal_common.s"
.macro _spi_hal_rx8_iteration nops
move.b (%A0), (%A2)+
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rx8:
spi_call _spi_hal_rx8_lookup, 7
.align 16
_spi_hal_rx8_lookup:
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_0, 2, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_1, 4, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_2, 6, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_3, 8, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_4, 10, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_5, 12, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_6, 14, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_7, 16, 256
.align 16
_spi_hal_rx8_table_0: unroll_table _spi_hal_rx8_iteration, 0, 256
.align 16
_spi_hal_rx8_table_1: unroll_table _spi_hal_rx8_iteration, 1, 256
.align 16
_spi_hal_rx8_table_2: unroll_table _spi_hal_rx8_iteration, 2, 256
.align 16
_spi_hal_rx8_table_3: unroll_table _spi_hal_rx8_iteration, 3, 256
.align 16
_spi_hal_rx8_table_4: unroll_table _spi_hal_rx8_iteration, 4, 256
.align 16
_spi_hal_rx8_table_5: unroll_table _spi_hal_rx8_iteration, 5, 256
.align 16
_spi_hal_rx8_table_6: unroll_table _spi_hal_rx8_iteration, 6, 256
.align 16
_spi_hal_rx8_table_7: unroll_table _spi_hal_rx8_iteration, 7, 256

62
spi_rxtx8.s Normal file
View File

@ -0,0 +1,62 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
* spi single calling convention
* A0 - ROM register
* A1 - readback address
* D0 - data
* D1 - clobbered
.global _spi_hal_rxtx8
.global _spi_hal_rxtx8single
.include "spi_hal_common.s"
.macro _spi_hal_rxtx8_iteration nops
move.b (%A1), (%A2)+
move.b (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rxtx8:
spi_call _spi_hal_rxtx8_lookup, 7
_spi_hal_rxtx8_single:
move.b (%A1), %D0
move.b (%A0, %D1.W), %D1
rts
.align 16
_spi_hal_rxtx8_lookup:
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_0, 8, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_1, 10, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_2, 12, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_3, 14, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_4, 16, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_5, 18, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_6, 20, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_7, 22, 256
.align 16
_spi_hal_rxtx8_table_0: unroll_table _spi_hal_rxtx8_iteration, 0, 256
.align 16
_spi_hal_rxtx8_table_1: unroll_table _spi_hal_rxtx8_iteration, 1, 256
.align 16
_spi_hal_rxtx8_table_2: unroll_table _spi_hal_rxtx8_iteration, 2, 256
.align 16
_spi_hal_rxtx8_table_3: unroll_table _spi_hal_rxtx8_iteration, 3, 256
.align 16
_spi_hal_rxtx8_table_4: unroll_table _spi_hal_rxtx8_iteration, 4, 256
.align 16
_spi_hal_rxtx8_table_5: unroll_table _spi_hal_rxtx8_iteration, 5, 256
.align 16
_spi_hal_rxtx8_table_6: unroll_table _spi_hal_rxtx8_iteration, 6, 256
.align 16
_spi_hal_rxtx8_table_7: unroll_table _spi_hal_rxtx8_iteration, 7, 256

74
spi_tx16.s Normal file
View File

@ -0,0 +1,74 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_tx16
.include "spi_hal_common.s"
.macro _spi_hal_tx16_iteration nops
move.w (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_tx16:
spi_call _spi_hal_tx16_lookup, 15
.align 16
_spi_hal_tx16_lookup:
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_0, 6, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_1, 8, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_2, 10, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_3, 12, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_4, 14, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_5, 16, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_6, 18, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_7, 20, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_8, 22, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_9, 24, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_10, 26, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_11, 28, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_12, 30, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_13, 32, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_14, 34, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_15, 36, 256
.align 16
_spi_hal_tx16_table_0: unroll_table _spi_hal_tx16_iteration, 0, 256
.align 16
_spi_hal_tx16_table_1: unroll_table _spi_hal_tx16_iteration, 1, 256
.align 16
_spi_hal_tx16_table_2: unroll_table _spi_hal_tx16_iteration, 2, 256
.align 16
_spi_hal_tx16_table_3: unroll_table _spi_hal_tx16_iteration, 3, 256
.align 16
_spi_hal_tx16_table_4: unroll_table _spi_hal_tx16_iteration, 4, 256
.align 16
_spi_hal_tx16_table_5: unroll_table _spi_hal_tx16_iteration, 5, 256
.align 16
_spi_hal_tx16_table_6: unroll_table _spi_hal_tx16_iteration, 6, 256
.align 16
_spi_hal_tx16_table_7: unroll_table _spi_hal_tx16_iteration, 7, 256
.align 16
_spi_hal_tx16_table_8: unroll_table _spi_hal_tx16_iteration, 8, 256
.align 16
_spi_hal_tx16_table_9: unroll_table _spi_hal_tx16_iteration, 9, 256
.align 16
_spi_hal_tx16_table_10: unroll_table _spi_hal_tx16_iteration, 10, 256
.align 16
_spi_hal_tx16_table_11: unroll_table _spi_hal_tx16_iteration, 11, 256
.align 16
_spi_hal_tx16_table_12: unroll_table _spi_hal_tx16_iteration, 12, 256
.align 16
_spi_hal_tx16_table_13: unroll_table _spi_hal_tx16_iteration, 13, 256
.align 16
_spi_hal_tx16_table_14: unroll_table _spi_hal_tx16_iteration, 14, 256
.align 16
_spi_hal_tx16_table_15: unroll_table _spi_hal_tx16_iteration, 15, 256

50
spi_tx8.s Normal file
View File

@ -0,0 +1,50 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_tx8
.include "spi_hal_common.s"
.macro _spi_hal_tx8_iteration nops
move.b (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_tx8:
spi_call _spi_hal_tx8_lookup, 7
.align 16
_spi_hal_tx8_lookup:
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_0, 6, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_1, 8, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_2, 10, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_3, 12, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_4, 14, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_5, 16, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_6, 18, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_7, 20, 256
.align 16
_spi_hal_tx8_table_0: unroll_table _spi_hal_tx8_iteration, 0, 256
.align 16
_spi_hal_tx8_table_1: unroll_table _spi_hal_tx8_iteration, 1, 256
.align 16
_spi_hal_tx8_table_2: unroll_table _spi_hal_tx8_iteration, 2, 256
.align 16
_spi_hal_tx8_table_3: unroll_table _spi_hal_tx8_iteration, 3, 256
.align 16
_spi_hal_tx8_table_4: unroll_table _spi_hal_tx8_iteration, 4, 256
.align 16
_spi_hal_tx8_table_5: unroll_table _spi_hal_tx8_iteration, 5, 256
.align 16
_spi_hal_tx8_table_6: unroll_table _spi_hal_tx8_iteration, 6, 256
.align 16
_spi_hal_tx8_table_7: unroll_table _spi_hal_tx8_iteration, 7, 256