; sys/s 07-Apr-1988 A.J.Travis ; ; Operating system interface for tcc under Acorn/BBC MOS ; ; 20-Jun-1991 v0.71 - J.G.Harston ; system/exit pass return value via osbyte 1 ; 30-Jun-2005 v0.73 ; is*(), to*(), etc. moved to ctype/s ; ; NB: _* symbols *must* be no more than 8 chars as tccom truncates! ; low level stdio program execution routines ; ========================================== ; On entry, y=>top of stacked parameters at (sp), left-to-right ; x=top parameter ; On exit, xy=return value ; ; exit() ; ------ ; exit from user program ; _exit lda #1 ; return value is in xy jsr osbyte ; set return value ldx rsp ; get stored SP txs ; restore stack rts ; and return ; system(string) ; -------------- ; execute MOS command and return result ; _system ; jsr ~gsconv ; convert to BBC format ; ldx #gsbuf ; jsr oscli jsr _os_cli ; execute command line lda #1 ; recover return value ldx #0 ; clear it once read jsr osbyte ; read return value into x ldy #0 ; clear y rts ; return return value in xy ; _cmdline() ; ---------- ; export address of MOS command line to C environment ; __cmdlin lda #1 ;get address of MOS command line ldx #param ;4 byte parameter block ldy #0 ;no file descriptor involved jsr osargs ldx param ;return address of '\r' terminated line ldy param+1 rts ; Escape event - should use os_escape() ; ===================================== ; ; escape trap ; escape cmp #6 ;escape event? bne ~escape1 lda #13 ;disable escape event ldx #6 ;event no. jsr osbyte lda #$7e ;acknowledge escape condition jsr osbyte lda #0 ;close all open files ldy #0 jsr osfind lda #$b2 ;write keyboard semaphore ldy #$00 ;and y ldx #$ff ;eor x (enable keyboard interrupts) jsr osbyte brk .byte $11 ;escape 'error' code .byte $0a,$0d ;lf/cr .text "escape" .byte 0 ~escape1 rts ; ; low level stdio file i/o routines ; ================================= ; creat(name, pmode) ; ------------------ ; pmode ignored in this version ... ; _creat lda #$80 ; open in write mode bne ~open2 ; jump to open file ; ldx #gsbuf ; jsr osfind ; tax ;return fd in xy ; beq ~reterr ;unless zero file handle ; ; ldy #0 ; rts ;~createrr ; ldx #$ff ;return -1 on error ; ldy #$ff ; rts ; open(name, rwmode) ; ------------------ ; exit with error status if file does not exist ; new files are opened with creat() ; BBC modes: read=$40, write=$80, r/w=$c0 ; _open ; jsr ~gsconv ;convert filename ; lda #gsbuf ; sta param+1 ; lda #5 ;read catalogue information ; ldx #param ; jsr osfile ; cmp #0 ; beq ~reterr ;if zero, file does not exist ; ldy #2 lda (sp),y ;rwmode lo clc adc #1 ;convert to BBC format ror a ror a ror a ~open2 pha jsr ~gsconv pla jsr osfind ldy #0 tax ; return fd in xy beq ~reterr ; return -1 if not opened rts ; ~reterr ;~openerr ldx #$ff ; return -1 on error ldy #$ff rts ; ~retok ldx #0 ; return 0 for ok ldy #0 rts ; close(fd) ; --------- ; _close ldy #0 lda (sp),y ;fd lo tay ;BBC fd parameter lda #0 ;close file operation jmp osfind ; jsr osfind ; rts ; stat(name, fcb) ; --------------- ; _stat lda #5 ; read catalogue information ldy #0 ; point to name jmp ~osfile ; remove(name), unlink(name) ; -------------------------- ; _remove _unlink jsr ~gsconv ; lda #gsbuf ; sta param+1 stx param sty param+1 lda #6 ;delete file ldx #param jmp osfile ; jsr osfile ; rts ; rename(oldname, newname) ; ------------------------ ; _rename rts ; unimplemented ; read(fd, buf, count) ; -------------------- ; checks eof on fd before attempting to read ; _read ldy #0 lda (sp),y ;fd tax ;BBC fd in x lda #127 ;check eof operation jsr osbyte txa ;exit status in x bne ~retok ; beq ~doread ;x=$ff is eof ; ldx #0 ;return 0 ; ldy #0 ; rts ~doread lda #4 pha jmp ~access ; write(fd, buf, count) ; --------------------- ; _write ldy #0 lda (sp),y ;fd cmp #1 ;fd 1 is stdout beq ~sput cmp #2 ;fd 2 is stderr beq ~sput lda #2 pha jmp ~access ; string output on stdout or stderr ; ~sput ldy #2 lda (sp),y ;buf lo sta pr iny lda (sp),y ;buf hi sta pr+1 iny lda (sp),y ;count lo sta tr iny lda (sp),y ;count hi tax ldy #0 ~sput1 lda tr bne ~sput2 cpx #0 beq ~sput3 dex ~sput2 dec tr lda (pr),y jsr ~aput iny bne ~sput1 inc pr+1 jmp ~sput1 ~sput3 rts ; 'C' file access interface to OSGBPB ; ----------------------------------- ; on entry: ; a=2: write, ignoring new file ptr ; a=4: read, ignoring new file ptr ; ; high order buffer address is zero, so the 6502 second processor ; accesses the 'correct' buffer in second processor memory. ; ~access ldy #0 lda (sp),y ;fd lo sta param ldy #2 lda (sp),y ;buf addr lo sta param+1 iny lda (sp),y ;buf addr hi sta param+2 lda #0 ;hi order buf addr bytes sta param+3 sta param+4 iny lda (sp),y ;count lo sta param+5 iny lda (sp),y ;count hi sta param+6 lda #0 sta param+7 ;zero high order count sta param+8 pla ;get access mode ldx #param jsr osgbpb sec ;calc no. transfers ldy #4 lda (sp),y ;count lo sbc param+5 ;resid lo tax ;ntransfers lo iny lda (sp),y ;count hi sbc param+6 ;resid hi tay ;ntransfers hi rts ; getc(fd) ; -------- ; _getc ldy #0 lda (sp),y ;fd lo beq ~getchar ;fd 0 is stdin tay ;BBC fd in y jsr osbget bcc *+5 jmp ~reterr ; bcs ~reterr ; bcs ~geof ;c indicates eof on fd tax jmp ext ;sign extend char ;~geof ; ldx #$ff ;return -1 on eof ; ldy #$ff ; rts ; input char from keyboard/rs423 ; ~getchar jsr osrdch cmp #$0d ;\r bne ~echo jsr oswrch ;echo \r on input lda #$0a ;map \r to \n on input ~echo jsr oswrch ;echo chars on input tax jmp ext ;sign extend char ; putc(c, fd) ; ----------- ; _putc ldy #0 lda (sp),y ;char to put tax ;save in x for now ldy #2 lda (sp),y ;fd cmp #1 ;fd 1 is stdout beq ~xput cmp #2 ;fd 2 is stderr beq ~xput tay ;BBC fd in y txa ;BBC char in a jmp osbput ; jsr osbput ; rts ; output x to screen/rs423 ; ~xput txa ; ; output a to screen/rs423 ; ~aput cmp #$0a ;\n beq ~mapn jmp oswrch ; jsr oswrch ; rts ; ; map \n to \r\n on output ; ~mapn lda #$0d ;\r jsr oswrch lda #$0a ;\n jmp oswrch ; jsr oswrch ; rts ; BBC MOS functions ; ================= ; os_cli(s) ; --------- ; pass string to MOS to execute ; _os_cli jsr ~gsconv ; convert to BBC format ; ldx #gsbuf jmp oscli ; os_byte(type, parameters) ; ------------------------ ; MOS "osbyte" interface ; a is type of call ; x and y are parameters ; _os_byte ;_osbyte stx asave ;; ldy #2 lda (sp),y ;x parameter tax iny lda (sp),y ;y parameter tay ;; ; sta asave ;save it ; ldy #0 ; lda (sp),y ;type of call ; ldy asave lda asave ;; jmp osbyte ; jsr osbyte ; rts ;return val in xy ; os_host() ; --------- _os_host lda #0 ldx #1 bne ~osfx ; os_fx(type, x, y) ; ----------------- _os_fx stx asave ; A parameter ldy #2 lda (sp),y ; X parameter tax iny iny lda (sp),y ; Y parameter tay lda asave ~osfx jsr osbyte ldy #0 rts ; os_word(type, address) ; --------------------- ; MOS "osword" interface ; a is type of call ; (x + y << 8) is address of parameter block ; _os_word ;_osword stx asave ;; ldy #2 lda (sp),y ;address lo tax iny lda (sp),y ;address hi tay ;; ; sta asave ;save it ; ldy #0 ; lda (sp),y ;type of call ; ldy asave lda asave ;; jsr osword tya ~carry tax ;return y in low byte php pla and #$01 tay ;return carry in high byte rts ;return val in xy ; os_bget(handle) ; --------------- _os_bget txa beq os_rdch tay jsr osbget jmp ~carry ; os_rdch() ; --------- _os_rdch jsr osrdch jmp ~carry ; os_bput(handle, byte) ; --------------------- _os_bput stx asave ldy #2 lda (sp),y ; byte to write ldy asave beq ~oswrch jmp osbput ; os_wrch(c) ; ---------- ; output char to output stream without any transformation ; _os_wrch ;_vdu ; ldy #0 ; lda (sp),y txa ; get char from xy ~oswrch jmp oswrch ; jsr oswrch ; rts ; os_newl() ; --------- _os_newl jmp osnewl ; os_asci(c) ; ---------- _os_asci txa jmp osasci ; osfile(name, fcb, type) ; ----------------------- ; MOS osfile interface ; _osfile jmp ~reterr ; ldy #4 ; lda (sp),y ;osfile type ;~osfile ; pha ;save type ; jsr ~gsconv ;convert name to MOS format ; ldy #2 ; lda (sp),y ;fcb address lo ; sta tr ; iny ; lda (sp),y ;fcb address hi ; sta tr+1 ; ldy #0 ; lda #gsbuf ; sta (tr),y ;fcb address hi ; pla ;osfile type ; ldx tr ;addr of fcb ; ldy tr+1 ; jsr osfile ; cmp #0 ;check MOS exit status, 0 = no file ; bne ~osfile1 ; ldx #$ff ;return -1 if no file found ; ldy #$ff ; rts ;~osfile1 ; ldx #0 ;return 0 otherwise ; ldy #0 ; sta (tr),y ;leave MOS file type in fcb ; rts ;; ;; os_file(type, name, fcb) ; 0/1 2/3 4/5 ;; ----------------------- ;; MOS osfile interface ;; _os_file ldy #0 lda (sp),y ; osfile type ldy #2 ; point to name ~osfile pha ; save type tya pha ; save pointer to name jsr ~conv1 ; convert name to MOS format pla tya ; retrieve pointer to name iny iny ; point to fcb lda (sp),y ;fcb address lo sta tr iny lda (sp),y ;fcb address hi sta tr+1 ldy #0 lda #gsbuf sta (tr),y ;fcb address hi pla ;osfile type ldx tr ;addr of fcb ldy tr+1 jsr osfile tax ldy #0 ; return file type sta (tr),y ; also leave file type in fcb rts ; os_args(action, handle, data) ; ----------------------------- _os_args rts ; os_gbpb(action, handle, block) ; ------------------------------ _os_gbpb rts ; os_find(action, name) ; ----------------------- _os_find stx asave ; action ldy #2 jsr ~conv1 ; convert filename string lda asave jsr osfind ; os_close(handle) ; --------------- _os_clos txa tay lda #0 jmp osfind ; os_report() ; ----------- _os_repo ldx $fd ldy $fe ; return pointer to error block rts ; os_error(e, s) ; -------------- _os_erro stx $101 ; store error number ldy #2 lda (sp),y sta pr iny lda (sp),y sta pr+1 ; pr=>string ldy #$ff ~oserrlp iny lda (pr),y sta $102,y ; copy to error buffer bne ~oserrlp sta $100 ; store BRK jmp $100 ; jump to execute error ; os_escape() ; ----------- _os_esca bit $ff bmi ~escset jmp ~retok ~escset jmp ~reterr ; os_onerror(f) ; ------------- _os_oner iny txa ora (sp),y beq ~onerroff lda (sp),y ; sta ... dey lda (sp),y ; sta ... rts ~onerroff lda #break ; sta ... rts ; os_call(r) ; ---------- ; r => A,X,Y,P,PClo,PChi _os_call jsr ~oscall1 pha php pla sta asave ; save P txa pha tya pha lda asave ; get P back pha ; assumes called code doesn't corrupt pr ldy #3 ~oscall3 pla sta (pr),y ; copy returned registers to r dey bpl ~oscall3 iny ; y=0 tax ; returns value in A rts ~oscall1 lda (sp),y sta pr iny lda (sp),y sta pr+1 ldy #5 ~oscall2 lda (pr),y pha dey bmi ~oscall2 sta asave pla pla tax pla tay lda asave rti ; pop P and stacked address ; convert string from C to BBC format ; =================================== ; string is null terminated in c, $0d terminated in BBC ; use pr to copy filename from addr pointed to by ; top stack item into MOS general string input buffer ; ~gsconv ldy #0 ~conv1 lda (sp),y ;name lo sta pr iny lda (sp),y ;name hi sta pr+1 ldy #0 ~conv lda (pr),y sta gsbuf,y ;parameter block for call beq ~term iny bne ~conv ;max length = 255 chars ~term lda #13 ;replaces C '\0' sta gsbuf,y ldx #converted string ldy #>gsbuf rts