| 1 | Buchla 700 Firmware | 
|---|
| 2 | ------------------- | 
|---|
| 3 |  | 
|---|
| 4 | This repository, buchla-68k.git, contains a port of the Buchla 700 | 
|---|
| 5 | firmware source code to a modern GCC-based cross-compilation | 
|---|
| 6 | environment. | 
|---|
| 7 |  | 
|---|
| 8 | The resulting executable code needs to be run on emulated Buchla 700 | 
|---|
| 9 | hardware, such as the one in the companion repository, buchla-emu.git. | 
|---|
| 10 |  | 
|---|
| 11 | The source code was originally released on Aaron Lanterman's Buchla | 
|---|
| 12 | 700 Preservation Page: | 
|---|
| 13 |  | 
|---|
| 14 | http://lanterman.ece.gatech.edu/buchla700/ | 
|---|
| 15 |  | 
|---|
| 16 | Aaron seems to have received the source code directly from Lynx Crowe, | 
|---|
| 17 | the developer. | 
|---|
| 18 |  | 
|---|
| 19 | The licensing conditions are a little vague; Lynx released the source | 
|---|
| 20 | code "for noncommercial personal and educational use" and "as-is with | 
|---|
| 21 | no guarantees of completeness or correctness." | 
|---|
| 22 |  | 
|---|
| 23 | While our modifications are in the public domain, Lynx's request still | 
|---|
| 24 | applies to the underlying original code. Please respect that. | 
|---|
| 25 |  | 
|---|
| 26 | Note that this is just the code that runs on the Buchla 700's Motorola | 
|---|
| 27 | 68k CPU: | 
|---|
| 28 |  | 
|---|
| 29 | 1. The BIOS and ROMP debug monitor. | 
|---|
| 30 |  | 
|---|
| 31 | 2. The MIDAS VII GUI-driven editing and control software. | 
|---|
| 32 |  | 
|---|
| 33 | In particular, there's no code for anything related to the actual | 
|---|
| 34 | sound generation. | 
|---|
| 35 |  | 
|---|
| 36 |  | 
|---|
| 37 | Building with a GCC cross-compiler | 
|---|
| 38 | ---------------------------------- | 
|---|
| 39 |  | 
|---|
| 40 | *** Setting up the cross-toolchain | 
|---|
| 41 |  | 
|---|
| 42 | To build the code, you need a cross-toolchain, i.e., GCC and binutils, | 
|---|
| 43 | for the m68k-none-elf target. Let us show you, how we built the one | 
|---|
| 44 | that we use, binutils 2.28 and GCC 6.3.0. It lives in /opt/cross-m68k. | 
|---|
| 45 |  | 
|---|
| 46 | First, binutils: | 
|---|
| 47 |  | 
|---|
| 48 | tar jxvf binutils-2.28.tar.bz2 | 
|---|
| 49 | cd binutils-2.28 | 
|---|
| 50 |  | 
|---|
| 51 | mkdir build | 
|---|
| 52 | cd build | 
|---|
| 53 |  | 
|---|
| 54 | ../configure --prefix=/opt/cross-m68k --target=m68k-none-elf | 
|---|
| 55 |  | 
|---|
| 56 | make -j2 | 
|---|
| 57 | make install | 
|---|
| 58 |  | 
|---|
| 59 | Second, GCC: | 
|---|
| 60 |  | 
|---|
| 61 | # Important! Otherwise, the GCC build won't find the binutils that | 
|---|
| 62 | # we just made! | 
|---|
| 63 |  | 
|---|
| 64 | export PATH="/opt/cross-m68k/bin:${PATH}" | 
|---|
| 65 |  | 
|---|
| 66 | tar jxvf gcc-6.3.0.tar.bz2 | 
|---|
| 67 | cd gcc-6.3.0 | 
|---|
| 68 |  | 
|---|
| 69 | mkdir build | 
|---|
| 70 | cd build | 
|---|
| 71 |  | 
|---|
| 72 | ../configure --prefix=/opt/cross-m68k --target=m68k-none-elf \ | 
|---|
| 73 | --enable-languages=c --without-headers | 
|---|
| 74 |  | 
|---|
| 75 | # Don't build everything, because features like GCC's stack | 
|---|
| 76 | # protector will otherwise cause trouble. | 
|---|
| 77 |  | 
|---|
| 78 | make -j2 all-gcc all-target-libgcc | 
|---|
| 79 | make install-gcc install-target-libgcc | 
|---|
| 80 |  | 
|---|
| 81 | Now, as we put /opt/cross-m68k/bin in our PATH, we should be able to | 
|---|
| 82 | run the cross-compiler as follows: | 
|---|
| 83 |  | 
|---|
| 84 | user@host:~$ m68k-none-elf-gcc --version | 
|---|
| 85 | m68k-none-elf-gcc (GCC) 6.3.0 | 
|---|
| 86 | Copyright (C) 2016 Free Software Foundation, Inc. | 
|---|
| 87 | This is free software; see the source for copying conditions.  There is NO | 
|---|
| 88 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|---|
| 89 |  | 
|---|
| 90 | user@host:~$ | 
|---|
| 91 |  | 
|---|
| 92 | *** Cross-compiling the source code | 
|---|
| 93 |  | 
|---|
| 94 | Once you have the cross-toolchain in place, invoke | 
|---|
| 95 |  | 
|---|
| 96 | make bios.abs | 
|---|
| 97 |  | 
|---|
| 98 | from the top-level directory of this repository to build the BIOS and | 
|---|
| 99 | ROMP debug monitor. | 
|---|
| 100 |  | 
|---|
| 101 | To build MIDAS VII, invoke | 
|---|
| 102 |  | 
|---|
| 103 | make midas.abs | 
|---|
| 104 |  | 
|---|
| 105 | instead. | 
|---|
| 106 |  | 
|---|
| 107 |  | 
|---|
| 108 | Building with Alcyon C | 
|---|
| 109 | ---------------------- | 
|---|
| 110 |  | 
|---|
| 111 | Lynx developed the Buchla 700 firmware on an 68k-based Atari system | 
|---|
| 112 | with the Alcyon C compiler, assembler, and linker from Atari's TOS | 
|---|
| 113 | Developer Kit. | 
|---|
| 114 |  | 
|---|
| 115 | If you want to relive this experience, you can do so thanks to the | 
|---|
| 116 | Hatari emulator, which emulates a suitable Atari system. Here's the | 
|---|
| 117 | idea: | 
|---|
| 118 |  | 
|---|
| 119 | * The hatari/c subdirectory contains the Atari C compiler, | 
|---|
| 120 | assembler, and linker. It is turned into a hard drive image for | 
|---|
| 121 | the emulator's C: drive. | 
|---|
| 122 |  | 
|---|
| 123 | * The hatari/d subdirectory is shared with the emulator, i.e., it is | 
|---|
| 124 | not turned into a hard drive image. It is the emulator's D: drive. | 
|---|
| 125 |  | 
|---|
| 126 | Any changes to this directory from inside the emulator are | 
|---|
| 127 | instantaneously visible outside the emulator, and vice versa. We | 
|---|
| 128 | use this as a means of communication between these two worlds. | 
|---|
| 129 |  | 
|---|
| 130 | The subdirectories under hatari/d contain links to the original | 
|---|
| 131 | source code files. In addition, the compiled results go to | 
|---|
| 132 | hatari/d/out. | 
|---|
| 133 |  | 
|---|
| 134 | * We have a Python script (hatari/rem.py) that acts as a remote | 
|---|
| 135 | control for the emulator. It issues the commands required to | 
|---|
| 136 | compile or assemble the source code files. | 
|---|
| 137 |  | 
|---|
| 138 | You PATH needs to be set, such that the shell can find the Hatari | 
|---|
| 139 | executable: | 
|---|
| 140 |  | 
|---|
| 141 | user@host:~$ hatari --version | 
|---|
| 142 |  | 
|---|
| 143 | Hatari v2.0.0 - the Atari ST, STE, TT and Falcon emulator. | 
|---|
| 144 |  | 
|---|
| 145 | Hatari is free software licensed under the GNU General Public License. | 
|---|
| 146 |  | 
|---|
| 147 | user@host:~$ | 
|---|
| 148 |  | 
|---|
| 149 | We use Hatari 2.0.0 with version 0.9.8 of the open-source TOS | 
|---|
| 150 | replacement EmuTOS. | 
|---|
| 151 |  | 
|---|
| 152 | Now you need to run two things in parallel, the remote control Python | 
|---|
| 153 | script as well as the Hatari emulator. The Python script goes | 
|---|
| 154 | first. In one shell window, invoke | 
|---|
| 155 |  | 
|---|
| 156 | make rem | 
|---|
| 157 |  | 
|---|
| 158 | from the top-level directory of the repository to start the | 
|---|
| 159 | script. The script then waits for the emulator to come up and connect | 
|---|
| 160 | to it. Now run Hatari. In another shell window, invoke | 
|---|
| 161 |  | 
|---|
| 162 | make emu | 
|---|
| 163 |  | 
|---|
| 164 | from the top-level directory of the repository. This creates a hard | 
|---|
| 165 | drive image from hatari/c and starts the emulator with appropriate | 
|---|
| 166 | command line options. | 
|---|
| 167 |  | 
|---|
| 168 | When the EmuTOS desktop comes up, open the C:\BIN folder and run | 
|---|
| 169 | SH.TTP without any parameters. This opens a Unix-like shell, the Okami | 
|---|
| 170 | Shell. This is the shell that the Python script expects to control. | 
|---|
| 171 |  | 
|---|
| 172 | Now, back in the window with the Python script, press the enter | 
|---|
| 173 | key. This tells the Python script to start sending commands to the | 
|---|
| 174 | shell in the emulator. | 
|---|
| 175 |  | 
|---|
| 176 | Compiling the C and assembly language files of the source code takes | 
|---|
| 177 | quite a while. Once the process is complete, the hatari/d/out | 
|---|
| 178 | directory contains the following files: | 
|---|
| 179 |  | 
|---|
| 180 | * C source code (.c) files get compiled into assembly language | 
|---|
| 181 | source code (.s) files, and then assembled into object (.o) files. | 
|---|
| 182 |  | 
|---|
| 183 | We keep both, .s and .o files. This proved useful when porting the | 
|---|
| 184 | original source code to the cross-toolchain, because we could | 
|---|
| 185 | compare the compiler output of the cross-toolchain to the original | 
|---|
| 186 | output of the Alcyon C toolchain. | 
|---|
| 187 |  | 
|---|
| 188 | This made us realize, for example, that Alcyon C uses 16-bit int | 
|---|
| 189 | values, whereas GCC defaults to 32-bit int values. | 
|---|
| 190 |  | 
|---|
| 191 | * Assembly language source code (.s) files get assembled into object | 
|---|
| 192 | (.o) files. We keep those, too. | 
|---|
| 193 |  | 
|---|
| 194 | * Some of the object files (.o) get archived into static library | 
|---|
| 195 | (.a) files. | 
|---|
| 196 |  | 
|---|
| 197 | * bios.abs, which is the BIOS and ROMP debug monitor. | 
|---|
| 198 |  | 
|---|
| 199 | * midas.abs is notably absent. Its object (.o) files are all there, | 
|---|
| 200 | but our Atari TOS Developer Kit is newer than Lynx's and it comes | 
|---|
| 201 | with a different linker (aln), which is not entirely compatible | 
|---|
| 202 | with the older linker that Lynx used (link68). | 
|---|
| 203 |  | 
|---|
| 204 | While it would be possible to get linking to work with aln, we | 
|---|
| 205 | decided to focus our attention on the cross-toolchain instead. | 
|---|
| 206 |  | 
|---|
| 207 | For your convenience, all the .s, .o, and .a files, as well as | 
|---|
| 208 | bios.abs can also be found in the alcyon subdirectory of this | 
|---|
| 209 | repository. Just in case you are interested in them, but would prefer | 
|---|
| 210 | not to go through the emulator exercise. | 
|---|
| 211 |  | 
|---|
| 212 |  | 
|---|
| 213 | Pitfalls | 
|---|
| 214 | -------- | 
|---|
| 215 |  | 
|---|
| 216 | There are a few differences between the Alcyon compiler and a | 
|---|
| 217 | modern-day GCC cross-compiler for the Motorola 68k. | 
|---|
| 218 |  | 
|---|
| 219 | * Alcyon uses 16-bit integers, whereas GCC defaults to 32-bit | 
|---|
| 220 | integers. That's why we pass the -mshort option to GCC. | 
|---|
| 221 |  | 
|---|
| 222 | * The Alcyon compiler's ABI assumes that registers A2 and D2 are | 
|---|
| 223 | saved by the caller of a function, if needed. GCC, however, | 
|---|
| 224 | assumes that it's the called function that is responsible for | 
|---|
| 225 | preserving A2 and D2. | 
|---|
| 226 |  | 
|---|
| 227 | Right now, we work around this issue by passing the -ffixed-d2 and | 
|---|
| 228 | -ffixed-a2 options to GCC. This prevents GCC from using these two | 
|---|
| 229 | registers at all when generating code. | 
|---|
| 230 |  | 
|---|
| 231 | Ultimately, we should fix the hand-written assembly language | 
|---|
| 232 | functions to preserve A2 and D2, so that GCC code generation can | 
|---|
| 233 | use all registers. | 
|---|