Showing posts with label CP/M. Show all posts
Showing posts with label CP/M. Show all posts

Wednesday, June 11, 2014

Abandoned Farmhouse Adventure now in Google Play Store

Back in April 2012, I wrote a text adventure game  as an experiment to try out the CC65 C compiler on the Briel Replica 1 computer  (an Apple 1 replica). Because it was written in C, it also ran under Linux, and any platform that supported a reasonable C compiler. I also ported it  to the Briel Altair 8800 computer running CP/M using the BDS C compiler.

When the Raspberry Pi store opened, I packaged it and submitted it as one of the first applications in the Raspberry Pi store.

Later, I made a GUI version using the Qt Toolkit , which is portable to a number of platforms. I intend to release the Qt version into the Raspberry Pi store, but have not gotten around to doing that yet.

With Qt now supporting Android, I tried building it for Android to run on a tablet, and it worked almost flawlessly without any changes. I made a few small tweaks for Android, and packaged it for the Google Play store. It is now available as a free Android application.

Android Version of The Abandoned Farmhouse Adventure
I doubt that any application before has run on an Apple 1, CP/M, Linux desktop, Raspberry Pi, and Android tablet - devices that span almost 40 years of computing and differences in computing power of several thousand times.

Saturday, April 19, 2014

Running dBASE II on CP/M

A viewer of my YouTube video on running various CP/M applications on the Briel Altair 8800 kit suggested I look at dBASE II. dBASE II was one of the first database management systems for microcomputers. I'm not particularly interested in databases, but I thought I would give it a try.

I downloaded dBASE 4.1 from www.retroarchive.org. I unzipped it, copied the files to an SD card, booted up CP/M, and copied all files to an empty CP/M B: drive.


While it runs out of the box, running INSTALL will let you configure the terminal type and use it in full screen mode. From the install program, you pick a VT-100 terminal type that should work with the Briel Altair's display. A session is shown below.

B>install

dBASE II INSTALLATION PROGRAM  VER 3.0

ARE FULL SCREEN OPERATIONS WANTED (Y/N)? y

  dBASE II INSTALLATION PROGRAM  VER 3.0
                 MENU #1

A -ADDS VIEWPOINT   M -HP 2621
B -ADM-31           N -INTERCOLOR
C -ADM-3A           O -KAYPRO II
D -APPLE ///        P -NEC PC-8000/1
E -APPLE II 40 COL  Q -NS ADVANTAGE
F -CROMEMCO 3102    R -OSBORNE I
G -DIALOG 81        S -PERKIN ELMER 11
H -EAGLE AVL        T -SANYO MBC 3000
I -GNAT-SYSTEM 10   U -SOROC
J -HAZELTINE 1500   V -SPERRY UTS 40
K -HEATH 89         W -SUPERBRAIN
L -HP 125                          

     X - MENU #2
     Y - MODIFY PREVIOUS INSTALLATION
     Z - USER SUPPLIED TERMINAL COMMANDS

SELECT TERMINAL TYPE: X

   dBASE II INSTALLATION PROGRAM  VER 3.0
               MENU #2

A -TELEVIDEO                   
B -TOSHIBA T100                
C -TOSHIBA T250                 
D -TRS-80 (FMG)                 
E -TRS-80 II (P&T)              
F -TRS-80 III                   
G -VECTOR GRAPHICS              
H -VISUAL-100                   
I -VPD-80                       
J -VT-100                       
K -XEROX 820                   

     X - MENU #1
     Y - MODIFY PREVIOUS INSTALLATION
     Z - USER SUPPLIED TERMINAL COMMANDS

SELECT TERMINAL TYPE: J

CHANGE MACRO, DATE, ETC. (Y/N)? N

TYPE "Y" TO SAVE, ANY OTHER KEY TO ABORT INSTALL
Y
SAVING INSTALLATION PARAMETERS

B>

Running DBASE will start the application. The HELP command will display general information on the application and more details on each command. Below is a short session.

B>dbase

ENTER TODAYS DATE  OR RETURN FOR NONE 
 (MM/DD/YY) :04/19/14

Copyright (C) 1982 RSP Inc.

***  dBASE II     Ver 2.4  1 April, 1983

 Type 'HELP', 'HELP dBASE', or a command  

. help dbase

       HELP TEXT FILE DBASEMSG.TXT VERSION 1.12 FOR dBASE II v2.4
                Copyright 1983 Ashton-Tate and RSP, Inc.

        written by Wayne Ratliff, Jim Taylor, and Howard Dickler

                         INTRODUCTION
     
     This entry is intended to give you on-line information about your dBASE 
II  Database  Management  System.   It  explains the  disk  files  you  have 
received,  and  gives suggestions on tapping the power now available to  you 
for  data  management.   Using  the on-line HELP in  conjunction  with  your 
Manual,   you will soon be creating databases and writing command procedures 
to do your work. 

                    >>>>> type any key to continue <<<<<
WAITING 

                       HOW TO USE THE 'HELP' FACILITY

     Information about your dBASE  II  system can be obtained by typing 
HELP and any of the following key words: (e.g. HELP NEW )

          UTILITIES      FULL-SCREEN    LIMITS    BACKUP  
          INSTALL        NEW            ERRORS    CP/M
          EXAMPLES       FUNCTIONS      DBASE     HELP       RUNTIME
               (or any dBASE II command)

     dBASE will then look up the entry for the key word and display it.   If 
there is no information on the subject then dBASE will say "NO HELP MESSAGES 
FOUND".   When there is more text to display beyond what's shown,  then  you 
will see the word 

WAITING  (like this)

                   >>>>>  type any key to continue. <<<<<

WAITING 

. list
NO DATABASE FILE IN USE, ENTER FILENAME: invent.dbf

00001  123456 QUIRKY LITTLE QWARK     99.00   230.00   23  100 
00002  258741 PORTABLE POOL          450.00   999.99   20   40 
00003  258963 ELEPHANT COLLAR          3.00    15.00    3   10 
00004  123345 HOUSE WRAPPER           45.00   100.00  200  100 

. display structure

STRUCTURE FOR FILE:  B:INVENT  .DBF
NUMBER OF RECORDS:   00004
DATE OF LAST UPDATE: 03/09/83
PRIMARY USE DATABASE
FLD       NAME      TYPE WIDTH   DEC
001     PRD:NMBR     C    006          
002     PRD:DESC     C    020          
003     PRD:COST     N    007    002   
004     PRD:PRIC     N    007    002   
005     ONHAND       N    003          
006     ONORDR       N    003          
** TOTAL **             00047

. list

00001  123456 QUIRKY LITTLE QWARK     99.00   230.00   23  100 
00002  258741 PORTABLE POOL          450.00   999.99   20   40 
00003  258963 ELEPHANT COLLAR          3.00    15.00    3   10 
00004  123345 HOUSE WRAPPER           45.00   100.00  200  100 
00005  998783 My widget               13.99    24.50   10   99 
00006  988765 Brand new car            0.00     0.00    1  999 

. quit
*** END RUN     dBASE II     ***

Thw screen shot below shows adding new a database record in full screen mode with the APPEND command.



dBASE was quite innovative for its time and was one of the "killer applications" that drove the adoption of early microcomputers for business use. You can learn more from this Wikipedia article. The company behind dBASE is still in business and can be found at dbase.com.

Wednesday, April 16, 2014

My Text Adventure Game Running on CP/M

After a couple more hours of work and I have my Abandoned Farmhouse text adventure game ported to CP/M using the BDS C compiler. The changes were similar to those needed for the Yum game, and included some changes for the available string functions and initialization of some large arrays.

I haven't played the game to completion but it seems to be working well. You can find source code and a CP/M binary here.

Below is a transcript of playing a short game.


B>advent
                      Abandoned Farmhouse Adventure
                            By Jeff Tranter

Your four-year-old grandson has gone missing and was last seen headed in the
direction of the abandoned family farm. It's a dangerous place to play. You
have to find him before he gets hurt, and it will be getting dark soon...

? help
Valid Commands:
Go east/west/north/south/up/down
Look
Use object
Examine object
Take object
Drop object
Inventory
Help
Quit
You can abbreviate commands and directions to the first letter.
Type just the first letter of a direction to move.
? i
You are carrying:
  flashlight
? l
You are at the door to the house.
You see:
  key
  bottle
You can go: east west
? drop flashlight
Dropped flashlight.
? t key
Took key.
? t bottle
Took bottle.
? n
You can't go north from here.
? l
You are at the door to the house.
You see:
  flashlight
You can go: east west
? w
You are in the kitchen.
? l
You are in the kitchen.
You see:
  candybar
You can go: south east down
? t candybar
Took candybar.
? w
You can't go west from here.
? l
You are in the kitchen.
You see:
  nothing special
You can go: south east down
? s
You are in the dining room.
? l
You are in the dining room.
You see:
  stale meat
You can go: north west
? u stale meat
The meat looked and tasted bad. You feel very sick and pass out.
Game over after 7 turns.
Do you want to play again (y/n)? n

B>

Wednesday, March 19, 2014

The Briel Altair 8800: External Serial Port/Console

A new feature included in the most recent build of Altair 8800 systems is an external serial port. It allows the console to be a serial port rather than the on-board VGA or composite video display and PS/2 keyboard.


It consists of a small card which plugs into the expansion connector. The board can piggyback on top of the RAM card if you have one installed in the expansion connector (you don't need the RAM disk board to use it). The board has a small ribbon cable and 9-pin serial port connector which can be installed on the rear panel in a cutout which is provided in the most recent build of systems. (If you want to buy a serial board and back panel for an existing Altair 8800, contact Vince Briel about pricing and availability.)


The serial board circuitry only consists of a MAX232 level shifter and connectors. The actual serial port is on the main 8800 motherboard. The serial board just converts it to and from RS-232 voltage levels and routes it out to the rear connector.

To use it, connect the serial port to a serial terminal or computer serial port running terminal emulation software (I use the Minicom program on Linux). You will typically need a "null modem" serial cable to do this. You can use a USB to serial adaptor if your computer does not have a serial port. The serial port defaults to 9600 bps with no hardware flow control. You can change the port speed using F7 (from the PS/2 keyboard). The setting is persistent.


You need to be running the latest (version 5.2) firmware on the Altair 8800 to support a serial console.

The serial port is the same one that is used between the Propeller and ATMEL AVR that emulates the 8080. If a PS/2 keyboard is not present, the Propeller chip "stays out of the way" and the external serial port can be used as a console.

On boot up you should see on the video display:

Keyboard offline    (this means the PS/2 keyboard is not present)
Serial port off     (this means the internal serial is off and will use an external console)

With a PS/2 keyboard attached you can also use F7 to turn the on board serial on or off. If a keyboard plugged in you will still see output to the serial port but the system will not use it for input. One implication of this is that you cannot use the TUTILS to transfer files between the SD card and RAM disk when using the serial console.

On powerup the ATMEL AVR chip tries to contact the Propeller chip. If a terminal is connected at that time it seems to confuse the system and cause it to flash an error code on the INP LED. The procedure that worked for me was the following steps:

  1. Unplug PS/2 keyboard.
  2. Power up the Altair.
  3. Connect serial port to the PC.

The main purpose of this is to run the system, such as CP/M, from an external terminal or computer. If the terminal emulates the same terminal type as your software is configured, you can run applications like WordStar or SuperCalc.


You can transfer files between your PC and computer if your terminal emulator program supports file sending and receiving. It might also be interesting to try running a file transfer program like KERMIT or XMODEM to transfer files as was done in the old days of CP/M and BBS systems.

Tuesday, March 18, 2014

WordStar 3.0 on the Briel Altair 8800

In the next instalment of this blog series, supplementing my YouTube video The Briel Altair 8800 Kit, Part 5: Advanced Topics, I'll cover getting WordStar installed, configured, and running on the Briel Altair 8800 under CP/M.

You can download WordStar 3.0 from here. You need to download and unzip the file WS30.ZIP on a desktop system. Then copy the files to the CP/M system, which should be the following:

INSTALL.COM MAILMRGE.OVR MERGPRIN.OVR WIMSGS.OVR WS.COM WSMSGS.OVR WSOVLY1.OVR WSU.COM

As mentioned in the video, you need to "patch" WordStar to support a non-standard terminal like the VT100/ANSI terminal that the Briel Altair 8800 emulates. The basic procedure is to run INSTALL.COM and enter the codes. It is a little tedious, but once done you have a version that works with the Briel Altair 8800. A complete transcript of the session is given at the end of this blog post. Thanks go to one of the Briel forum users for coming up with the patch codes.

Here is the list of patch values:

Symbol  Address Value(s)
HITE   0248     28
WID    0249     50
CLEAD1 024A     2,1B,5B
CLEAD2 0253     1,3B
CTRAIL 0258     1,48
LINOFF 025E     1
COLOFF 025F     1
ASCUR  0260     2
ERAEOL 026D     3,1B,5B,4B
LINDEL 0274     4,1B,5B,31,4D
LININS 027B     4,1B,5B,31,4C
IVON   0284     4,1B,5B,31,6D
IVOFF  028B     4,1B,5B,30,6D
TRMINI 0292     2,1B,63
IDTEX  018F     20,56,54,2D,31,30,30,20,20,20,20,20,20,20,20,20
                20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20

Once configured, run WS to launch WordStar.

A Google search will turn up copies of the complete WordStar 3 manuals.

You may also want a shorter command reference. A couple can be found here and here.

Don't forget to put the terminal in WordStar arrow key mode using F6.


Using the CP/M BDS C Compiler

I'll continue giving more details on the programs I demonstrated in the YouTube video The Briel Altair 8800 Kit, Part 5: Advanced Topics.

This time, the BDS C Compiler.

Go to Leo Zolman's BDS C web page and download the release file bdsc-all.zip.

BDS C comes with extensive documentation in the file bdsc-guide.pdf, but for the purposes of a simple demo, you can do the following. Unzip the file and copy these files to an SD card, and then transfer them to a CP/M drive:

BDSCIO.H C.CCC CC.COM CC2.COM
CLINK.COM DEFF.CRL DEFF2.CRL STDIO.H

The example program TAIL.C used in the demonstration was found here.

Here is an even shorter example C program that I  wrote. I entered it as the filename EX1.C:

/* BDS C example 1 */
#include

main(argc,argv)
char **argv;
{
    int i;

    printf("Example Program 1\n");
    for (i=1; i <=10; i++) {
        printf("%d\n", i);
    }
    return 0;
}

Here is a sample session showing EX1.C and TAIL.C being compiled, linked, and run (commands typed by the user are in bold).

B>dir

B: EX1      C   : NQUEENS  C   : BDSCIO   H   : C        CCC
B: CC       COM : CC2      COM : CLINK    COM : DEFF     CRL
B: DEFF2    CRL : STDIO    H   : TAIL     C

B>cc ex1

BD Software C Compiler v1.60  (part I)
  37K elbowroom
BD Software C Compiler v1.60 (part II)
  34K to spare

B>clink ex1

BD Software C Linker   v1.60

Last code address: 0E8D 
Externals start at 0E8E, occupy 0006 bytes, last byte at 0E93 
Top of memory: E805 
Stack space: D972 
Writing output...
  46K link space remaining

B>ex1

Example Program 1
1
2
3
4
5
6
7
8
9
10

B>cc tail

BD Software C Compiler v1.60  (part I)
  36K elbowroom
BD Software C Compiler v1.60 (part II)
  33K to spare

B>clink tail

BD Software C Linker   v1.60

Last code address: 1402 
Externals start at 1403, occupy 0006 bytes, last byte at 1408 
Top of memory: E805 
Stack space: D3FD 
Writing output...
  44K link space remaining

B>tail -10 tail.c

}
                                


int lastchar(c)
char c;
{
        return (!c) || (c == CPMEOF);
}

B>tail

Usage: tail [-#]

B>dir

B: TAIL     CRL : TAIL     COM : NQUEENS  CRL : NQUEENS  COM
B: EX1      C   : NQUEENS  C   : BDSCIO   H   : C        CCC
B: CC       COM : CC2      COM : CLINK    COM : DEFF     CRL
B: DEFF2    CRL : STDIO    H   : TAIL     C   : EX1      CRL
B: EX1      COM

Finally, here is the N Queens example program shown in the YouTube video. It will take a while to run to completion.   First the source code, followed by example output.

/* Solve the n queens problem */

#include

#define MAX_N 8

int  board[MAX_N*MAX_N];
int tries;
int  solutions;
int  n;
int  nsq;
int cache[MAX_N+1]; /* get some savings by caching last position */

/* display the board */
void print_board()
{
  int i;
  
  printf("+");
  for (i = 0; i < n ; i++)
    printf("---");
  printf("+\n");

  for (i = 0; i < nsq ; i++) {
    if ((i % n) == 0)
      printf("|");
    if (board[i])
      printf(" Q ");
    else
      printf(" . ");
    if (((i+1) % n) == 0)
      printf("|\n");
  }

  printf("+");
  for (i = 0; i < n ; i++)
    printf("---");
  printf("+\n");
}

/* find position of a piece */
int piece(n)
{
  int i;

  /* first try the cache */
  if (board[cache[n]] == n)
    return cache[n];
  
  for (i = 0 ; i < nsq ; i++)
    if (board[i] == n) {
      cache[n] = i; /* cache it for next time */
      return i;
    }
  return -1;
}

/* see if board is a solution */
void check_board()
{
  int i, p, r, c, j;

  /* loop over all pieces */
  for (i = 1 ; i <= n ; i++) {
    p = piece(i);

    /* not a solution if piece in same row */
    r = p / n;
    for (c = 0 ; c < n ; c++) {
      if (board[r*n+c] != 0 && board[r*n+c] != i)
return;
    }

    /* not a solution if piece in same column */
    c = p % n;
    for (r = 0 ; r < n ; r++) {
      if (board[r*n+c] != 0 && board[r*n+c] != i)
return;
    }
    
    /* not a solution if piece in same \ diagonal */
    for (j = -n ; j < n ; j++) {
      r = p / n + j;
      c = p % n + j;
      if ((r >= 0) && (r < n) && (c >= 0) && (c < n) &&
 (board[r*n+c] != 0) && (board[r*n+c] != i))
return;
    }
    /* not a solution if piece in same / diagonal */
    for (j = -n ; j < n ; j++) {
      r = p / n + j;
      c = p % n - j;
      if ((r >= 0) && (r < n) && (c >= 0) && (c < n) &&
 (board[r*n+c] != 0) && (board[r*n+c] != i))
return;
    }
  }
  solutions++;
  print_board();
}

/* move piece p to next position */
int next_pos(p)
{
  int i, t;

  if (p < 1)
    return 0;

  i = piece(p);

  if (i < nsq-n+p-1) {
    board[i] = 0;
    board[i+1] = p;
    return 1;
  } else {
    t = next_pos(p-1);
    board[i] = 0;
    board[piece(p-1)+1] = p;
    return t;
  }
}

/* generate the next possible solution */
int next_board()
{
  return next_pos(n);
}


int main()
{
  int i;

  solutions = 0;
  n = 5;
  nsq = n*n;           /* save n^2 to avoid calculating it again */

  printf("\n\n\n\nSOLVING N QUEENS PROBLEM FOR N = %d\n", n);

  /* clear the board */
  for (i = 0 ; i < nsq ; i++)
    board[i] = 0;

  /* initially place the queens */
  for (i = 0 ; i < n ; i++)
    board[i] = i+1;

  do {
    tries++;
    check_board();
  } while (next_board());
  
  printf("FOUND %d SOLUTIONS AFTER %ld TRIES.\n", solutions, tries);
        
  return 0;
}

B>nqueens

SOLVING N QUEENS PROBLEM FOR N = 5
+---------------+
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
+---------------+
FOUND 10 SOLUTIONS AFTER -12406 TRIES.

B>

Monday, March 17, 2014

Using the CP/M Assembler

I'll continue giving more details on the programs I demonstrated in the YouTube video The Briel Altair 8800 Kit, Part 5: Advanced Topics.

This time, the CP/M Assembler.

To follow the demos in the video, boot up a CP/M 2.2 image that has the assembler (ASM.COM), loader (LOAD.COM), and optionally the DDT debugger (DDT.COM). The Briel CPM22.DSK image on the CD will work.

If you use CP/M 3, there is a more sophisticated macro assembler called MAC.COM. I have not tried it with these examples.

Create a file HELLO.ASM with the following source code and copy it to your SD card. Use TREAD to copy it to the CP/M disk (or enter it locally on CP/M if you have a text editor such as ED or WordStar).

; This is an example of the "Hello World" program.
; Uses 8080 assembler mnemonics.
ORG 100h ; cpm programs start address.
JMP START ; go to program start.

; Variable storage space
MsgStr: DB 13,10,'Hello world.',13,10,0
Stack1: DW 0 ; place to save old stack.
Sbot: DS 32 ; temp stack for us to use.

; Constants
STOP: EQU $-1 ; top of our stack.
BDOS: EQU 5 ; address of BDOS entry.

; Start of code segment
START: LXI H, 0 ; HL = 0.
DAD SP ; HL = SP.
SHLD Stack1 ; save original stack.
LXI H, STOP ; HL = address of new stack.
SPHL ; stack pointer = our stack.
LXI H, MsgStr ; HL = address of string.
LOOP1: MOV A, M ; read string char.
ORA A ; set cpu flags.
JZ EXIT ; if char = 0 done.
MOV E, A ; E = char to send.
MVI C, 2 ; we want BDOS func 2.
PUSH H ; save HL register.
CALL BDOS ; call BDOS function.
POP H ; restore HL register
INX H ; point to next char.
JMP LOOP1 ; do next char.

; Exit and return code
EXIT: LHLD Stack1 ; HL = entry stack address.
SPHL ; SP = value on entry.
RET ; return control back to CPM.
END

Since I recorded the video, I found an even simpler hello world program which you can use instead if you like. The source code is below. I saved it as HELLO1.ASM and used it in the examples that follow.

        org 100h
bdos    equ    0005h    ; BDOS entry point
start:  mvi    c,9      ; BDOS function: output string
        lxi    d,msg$   ; address of msg
        call   bdos
        ret             ; return to CCP
msg$:   db    'Hello, world!$'
        end

Here is an example session assembling, linking, and running it, and disassembling it with DDT. Commands typed by the user are in bold. Note that in the video, when I demonstrated DDT, I did not correctly load the file, so the disassembly in the video was incorrect. The example below is correct. Note that this session was run on drive B so I needed to specify the path to the tools on drive A.

B>a:asm hello1

CP/M ASSEMBLER - VER 2.0
0117
000H USE FACTOR
END OF ASSEMBLY

B>a:load hello1

FIRST ADDRESS 0100
LAST  ADDRESS 0116
BYTES READ    0017
RECORDS WRITTEN 01

B>type hello1.hex
:100100000E09110901CD0500C948656C6C6F2C20E2
:07011000776F726C6421247B
:0000000000

B>type hello1.prn

 0100                   org 100h
 0005 =         bdos    equ    0005h    ; BDOS entry point
 0100 0E09      start:  mvi    c,9      ; BDOS function: output string
 0102 110901            lxi    d,msg$   ; address of msg
 0105 CD0500            call   bdos
 0108 C9                ret             ; return to CCP
 0109 48656C6C6Fmsg$:   db    'Hello, world!$'
 0117                   end

B>a:ddt hello1.com

DDT VERS 2.2
NEXT  PC
0180 0100
-l
  0100  MVI  C,09
  0102  LXI  D,0109
  0105  CALL 0005
  0108  RET  
  0109  MOV  C,B
  010A  MOV  H,L
  010B  MOV  L,H
  010C  MOV  L,H
  010D  MOV  L,A
  010E  INR  L
  010F  ??=  20
-^C
B>

Note that the assembler is for the Intel 8080. If you find CP/M programs for the Zilog Z80 and try to build them, they will not assemblem as it uses different mnemonics. They also won't run on the
Briel Altair 8800 as it only emulates Intel 8080 instructions.

The source for the "hello world" 8080 assembler program I listed above, as well as more information on ASM, can be found here.

Running Microsoft Basic 5 on CP/M

I recently posted a series of YouTube videos on the Briel Altair 800 kit, the most recent instalment being The Briel Altair 8800 Kit, Part 5: Advanced Topics  which I posted yesterday.

To supplement what I demonstrated there, I'm going to post more details and the files I used, to make it easier for others who want to try out the relevant software.

First, Microsoft BASIC.

Version 5.21 of Microsoft BASIC-80 dated 28-Jul-81 is included on the Briel Altair CD in the CP/M 3 disk image (CPM302GN.DSK) as the file MBASIC.COM. It will also run on CP/M version 2.2.

The Microsoft BASIC-80 ver 5.0 Reference Manual can be found on the Internet here.

Many of the programs from the David Ahl Creative Computing books on computer games can be found on the Briel Altair CD in the directory BASIC Software/creative computing.

Here is the source listing for the memory dump program I demonstrated. I wrote it quickly to demonstrate some of the BASIC-80 features like displaying numbers in hexadecimal.

100 REM Dump memory in hex and ASCII.
110 A = &H100 : REM Start address
120 A$ = "000" + HEX$(A)
130 A$ = RIGHT$(A$,4) 
140 PRINT A$;": ";
150 FOR I = 0 TO 15
160 S$ = "0" +HEX$(PEEK(A+I))
170 S$ = RIGHT$(S$,2)
180 PRINT S$;" ";
190 NEXT I
200 FOR I = 0 TO 15
210 IF PEEK(A+I) >= 32 AND PEEK(A+I) <= 126 THEN PRINT CHR$(PEEK(A+I)); ELSE PRINT".";
220 NEXT I
230 PRINT
240 A = A +16
250 GOTO 120