Skip to content

Instantly share code, notes, and snippets.

@davidgiven
Created May 31, 2023 21:43
Show Gist options
  • Save davidgiven/66ddef283e2965bd35f052e8ed93443c to your computer and use it in GitHub Desktop.
Save davidgiven/66ddef283e2965bd35f052e8ed93443c to your computer and use it in GitHub Desktop.
This is a very barebones CP/M port for the Agon Light, using the BBC BASIC assembler to do all the work.
10 bbase=&FD00
20 fbase=bbase-3584
30 cbase=fbase-2048
40 iobyte=&0003
50 cdisk=&0004
60 bdoscall=&0005
70 bioscall=&0000
80 DIM code 4096
90 FOR pass=4 TO 7 STEP 3
100 P%=0
110 O%=code
120 [OPT pass
130 :
140 ; mos binary header and startup code
150 :
160 jp main
170 .loop
180 DEFM "12345"
190 :
200 ]
210 FOR r=&08 TO &30 STEP 8
220 [OPT pass
230 DEFB &49
240 rst r
250 ret
260 DEFM "12345"
270 ]
280 NEXT
290 [OPT pass
300 :
310 ei
320 reti
330 DEFM "12345"
340 :
350 DEFM "MOS"
360 DEFB 0
370 DEFB 0
380 :
390 .startup_banner
400 DEFB 12
410 DEFM "Hacked up CP/M for the Agon Light"
420 DEFB 13
430 DEFB 10
440 .startup_banner_end
450 .main
460 ld sp, &8000
470 ld hl, startup_banner
480 ld bc, startup_banner_end - startup_banner
490 DEFB &49
500 rst &18 ; print string
510 :
520 ld hl, bios_load_address
530 ld de, bbase
540 ld bc, &10000-bbase
550 ldir
560 :
570 ld hl, diskimage_filename
580 ld c, 3
590 ld a, &A ; mos_fopen
600 DEFB &49
610 rst 8
620 ld (filehandle), a
630 :
640 jp bbase
650 :
660 .diskimage_filename
670 DEFM "cpmdisk.img"
680 DEFB 0
690 ]
700 :
710 bios_load_address=P%
720 P%=bbase
730 [opt pass
740 jp boote
750 jp wboote
760 jp conste
770 jp conine
780 jp conoute
790 jp liste
800 jp punche
810 jp readere
820 jp homee
830 jp seldske
840 jp settrke
850 jp setsece
860 jp setdmae
870 jp reade
880 jp writee
890 jp listste
900 jp sectrane
910 :
920 .boote
930 xor a
940 ld (iobyte), a
950 ld (cdisk), a
960 ; fall through
970 :
980 .wboote
990 ld sp, &0100
1000 ld a, &C3
1010 ld (bdoscall), a
1020 ld hl, fbase+6
1030 ld (bdoscall+1), hl
1040 ld (bioscall), a
1050 ld hl, bbase+3
1060 ld (bioscall+1), hl
1070 ld hl, bdosccp_filename
1080 ld de, cbase
1090 ld bc, bbase-cbase
1100 ld a, 1 ; mos_load
1110 DEFB &49
1120 rst 8
1130 ld a, (cdisk)
1140 ld c, a
1150 jp cbase
1160 .bdosccp_filename
1170 DEFM "bdosccp.img"
1180 DEFB 0
1190 :
1200 .conste
1210 xor a
1220 ret
1230 :
1240 .conine
1250 ld a, 0 ; mos_getkey
1260 DEFB &49
1270 rst 8
1280 or a
1290 jr z, conine
1300 ret
1310 :
1320 .conoute
1330 ld a, c
1340 DEFB &49
1350 rst &10
1360 ret
1370 :
1380 .liste
1390 .punche
1400 .readere
1410 ret
1420 :
1430 .homee
1440 ld hl, 0
1450 ld (current_track), hl
1460 ld (current_sector), hl
1470 ret
1480 :
1490 .seldske
1500 ld a, c
1510 ld (current_drive), a
1520 ld hl, dph
1530 or a
1540 ret z
1550 ld hl, 0
1560 ret
1570 .current_drive
1580 DEFB 0
1590 :
1600 .settrke
1610 ld (current_track), bc
1620 ret
1630 .current_track
1640 DEFW 0
1650 :
1660 .setsece
1670 ld (current_sector), bc
1680 ret
1690 .current_sector
1700 DEFW 0
1710 :
1720 .setdmae
1730 ld (current_dma), bc
1740 ret
1750 .current_dma
1760 DEFW 0
1770 :
1780 .prepare_read_write
1790 call seek_to_sector
1800 ld hl, (current_dma)
1810 ld a, &04
1820 call set_hlu
1830 DEFB &5B: ld de, 128: DEFB 0
1840 ret
1850 :
1860 .reade
1870 call prepare_read_write
1880 ld a, &1A ; mos_fread
1890 DEFB &49
1900 rst 8
1910 .check_read_write_result
1920 ld hl, -128
1930 add hl, de
1940 ld a, h
1950 or l
1960 ret z
1970 ld a, 1
1980 ret
1990 :
2000 .writee
2010 call prepare_read_write
2020 ld a, &1B ; mos_fwrite
2030 DEFB &49
2040 rst 8
2050 jr check_read_write_result
2060 :
2070 .listste
2080 xor a
2090 ret
2100 :
2110 .sectrane
2120 ld h, b
2130 ld l, c
2140 ret
2150 :
2160 .seek_to_sector
2170 ld a, (current_track)
2180 ld h, a
2190 ld a, (dpb+0)
2200 ld l, a
2210 mlt hl
2220 ld de, (current_sector)
2230 add hl, de
2240 xor a
2250 srl h
2260 rr l
2270 rra
2280 ld c, a
2290 ld a, h
2300 ld h, l
2310 ld l, c
2320 call set_hlu
2330 ld e, 0
2340 ld a, (filehandle)
2350 ld c, a
2360 ld a, &1C ; mos_flseek
2370 DEFB &49
2380 rst 8
2390 ret
2400 :
2410 .set_hlu
2420 ld (hlu_insn+2), hl
2430 ld (hlu_insn+4), a
2440 .hlu_insn
2450 DEFB &5B: ld hl, 0: DEFB 0
2460 ret
2470 :
2480 .phex8
2490 ld a, c
2500 rra
2510 rra
2520 rra
2530 rra
2540 call phexconv
2550 ld a, c
2560 .phexconv
2570 and &0F
2580 add a, &90
2590 daa
2600 adc a, &40
2610 daa
2620 DEFB &49
2630 rst &10
2640 ret
2650 .dph
2660 DEFW 0 ; sector translation vector
2670 DEFW 0 ; BIOS scratchpad 1
2680 DEFW 0 ; BIOS scratchpad 2
2690 DEFW 0 ; BIOS scratchpad 3
2700 DEFW dirbuf ; directory buffer
2710 DEFW dpb ; DPB for this drive
2720 DEFW drive_a_check_vector
2730 DEFW drive_a_bitmap
2740 .dpb
2750 DEFW 18*4 ; CP/M sectors per track
2760 DEFB 4 ; BSH
2770 DEFB 15 ; BLM
2780 DEFB 0 ; EXM
2790 DEFW 350 ; DSM, number of blocks -1
2800 DEFW 127 ; DRM, number of dirents -1
2810 DEFW &00C0 ; initial allocation vector
2820 DEFW 32 ; size of disk check vector
2830 DEFW 2 ; number of reserved tracks
2840 .drive_a_bitmap
2850 OPT FNadvance(44)
2860 .drive_a_check_vector
2870 OPT FNadvance(32)
2880 .dirbuf
2890 OPT FNadvance(128)
2900 .filehandle
2910 DEFB 0
2920 ]
2930 :
2940 NEXT
2950 len=O%-code
2960 PRINT "Code length: ";len
2970 DIM savecode 40
2980 P%=savecode
2990 [
3000 .filename
3010 DEFM "CPM.BIN"
3020 DEFB 0
3030 .saver
3040 : ld hl, filename
3050 : ld a, 5 ; mos_del
3060 DEFB &49
3070 : rst 8
3080 : ld hl, filename
3090 : ld de, code
3100 : ld bc, len
3110 : ld a, 2 ; mos_save
3120 DEFB &49
3130 : rst 8
3140 : ld l, a
3150 : ld h, 0
3160 : ret
3170 ]
3180 L% = (USR saver) / &10000
3190 IF L% THEN PRINT "Save failed! ";~L%:STOP
3200 PRINT "cbase=";~cbase
3210 PRINT "fbase=";~fbase
3220 PRINT "bbase=";~bbase
3230 SAVE "cpm.bas"
3240 END
3250 :
3260 DEF FNadvance(amount)
3270 P%=P%+amount
3280 O%=O%+amount
3290 =pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment