VC3 Challenge - CP/M-80 Diamonds Author: Sergey Kiselev Category: Christmas Challenge System: CP/M-80, running on Intel 8080, Zilog Z80 and compatible processors Language: CP/M-80 Assembler Len source code: 1500 Len exe file: 128 Len code only: 64 Instructions: Exact steps will depend on the hardware or emulator used. Step 0: Set up your CP/M system or emulator Real hardware, e.g., RC2014-compatible system: Connect your CP/M system to your modern host system, e.g., Window or Linux. If you haven't aready, install a terminal emulator software capable of sending files using XMODEM protocol. Some examples are Tera Term for Windows and minicom with lrzsz package on Linux. Emulator: I used z80pack emulator (https://www.autometer.de/unix4fun/z80pack/) on Linux. Follow the instructions given under "Quickstart to run the Digital Research OS's" on the page above to build the emulator and run CP/M 2.2 in the emulator. Step 1: Get the source to your CP/M System If using a real CP/M hardware, e.g., RC2014-compatible system: Using XMODEM, transfer the source assembly code to your CP/M system: A> XM R DIAMONDS.ASM After typing the XM command above, find in the menu or use a hot key to open and send diamonds.asm file to the system. Or, if using an emulator (it also should work on real CP/M system): Run ED editor: A> ED DIAMONDS.ASM Type 'I' command (insert): : *i Open diamonds.asm in a text editor, and copy and paste the file to the emulator. Type Ctrl-Z to finish the entry. Type 'E' command to save the file and exit : *e It also might be possible to transfer the source code to the emulator or a real CP/M machine using disk copying/imaging tools. Step 2: Compile the source Use the following command to run the assembler: A> ASM DIAMONDS It might be necessary to specify the location of the ASM executable, e.g., if ASM.COM is located on disk B:, use: A> B:ASM DIAMONDS Step 3: Convert HEX to COM file Use the following command to convert the HEX file that assembler generated to executable COM file: A> LOAD DIAMONDS As in step 2, it might be necessary to specify LOAD.COM location, e.g.: A> B:LOAD DIAMONDS Step 4: Run the program Type DIAMONDS to run the program: A> DIAMONDS Description: The challenge with a straight-forward implementation of diamonds algorithm is that it uses divide/modulo operations that are not natively supported by Intel 8080 or Zilog Z80 CPUs. Instead, this program uses the following algorithm: The program has two nested loops that count from 19 to 1 to scan all the columns and rows. At each iteration of the inner loop a character - either a star or a space are printed on the screen. At each iteration of the outer loop a carriage return and a new line characters are printed, moving the cursor to the next line. In addition, there are two variables, kept in registers B and C respectively. B tells how many columns there are until the next '*', that form top-right to bottom-left lines in the diamonds. B is decremented at every step of the inner loop, and once it reaches 0, a '*' is printed, and B is reset to 6. C indicates how many columns there are from the '*' forming top-left to bottom-right lines in the diamonds to the '*' forming top-right to bottom-left lines (that B) indicates. When B == C, a '*' is printed. Note, that C value is constant for a given row. In case of 19 columns, the C value is decremented by 2 at the end of each row. If C reaches 0, it reset back to 6. Also note that if C=6 the '*' that form the top-right to bottom-left and top-left to bottom-right lines align, e.g., in rows 0, 3, 6, etc. If none of two conditions - B == 0 or B == C are true, a space is printed. (See diamonds.py for Python implementation showing the algorithm, it is a bit more human readable than the assembly code). Comments: The program can be easily ported to other Intel 8080 and Zilog Z80 systems. In this case PUTC subroutine will need to be replaced to write the character passed in register E to the console.