diff options
Diffstat (limited to 'libc/bios')
-rw-r--r-- | libc/bios/Config | 1 | ||||
-rw-r--r-- | libc/bios/Makefile | 35 | ||||
-rw-r--r-- | libc/bios/README | 10 | ||||
-rw-r--r-- | libc/bios/bios.c | 230 | ||||
-rw-r--r-- | libc/bios/bios_vid.c | 489 |
5 files changed, 765 insertions, 0 deletions
diff --git a/libc/bios/Config b/libc/bios/Config new file mode 100644 index 0000000..e7f1971 --- /dev/null +++ b/libc/bios/Config @@ -0,0 +1 @@ +bios: Minimal syscalls for BIOS level diff --git a/libc/bios/Makefile b/libc/bios/Makefile new file mode 100644 index 0000000..5fcc964 --- /dev/null +++ b/libc/bios/Makefile @@ -0,0 +1,35 @@ +# Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> +# This file is part of the Linux-8086 C library and is distributed +# under the GNU Library General Public License. + +ifeq ($(LIB_OS),BIOS) +ASRC=bios.c +AOBJ=bios_start.o bios_isatty.o \ + bios_open.o bios_read.o bios_write.o bios_lseek.o bios_close.o + +BSRC=bios_vid.c +BOBJ=bios_putc.o bios_getc.o bios_khit.o bios_rdline.o + +OBJ=$(AOBJ) $(BOBJ) + +CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) + +all: $(LIBC)($(OBJ)) + @: + +$(LIBC)($(AOBJ)): $(ASRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + $(RM) $*.o + +$(LIBC)($(BOBJ)): $(BSRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + $(RM) $*.o +else +all: + @: +endif + +clean: + rm -f *.o libc.a diff --git a/libc/bios/README b/libc/bios/README new file mode 100644 index 0000000..cc883e1 --- /dev/null +++ b/libc/bios/README @@ -0,0 +1,10 @@ +Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> +This file is part of the Linux-8086 C library and is distributed +under the GNU Library General Public License. + +This is a very simple set of functions for standalone executables. + +There is a choice as to which console type you want to use, I think +the VT52 clone is best. + +-Robert diff --git a/libc/bios/bios.c b/libc/bios/bios.c new file mode 100644 index 0000000..a8d2079 --- /dev/null +++ b/libc/bios/bios.c @@ -0,0 +1,230 @@ +/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +#if !__FIRST_ARG_IN_AX__ +#ifdef __AS386_16__ +#ifdef __STANDALONE__ + +#include <dos.h> +#include <fcntl.h> +#include <errno.h> +int errno; + +#ifdef L_bios_start +char ** environ = { 0 }; + +void (*__cleanup)() = 0; + +#asm + .data +export ___argr +___argr: + .word 0,0,0,0,0,0,0 ! A struct REGS +defarg: + .word boot_str, 0 +boot_str: + .asciz "boot" +loop_save: + .word 0 + + .text +export ___cstartup ! Crt0 startup +___cstartup: + mov ___argr+0,ax + mov ___argr+2,bx + mov ___argr+4,cx + mov ___argr+6,dx + mov ___argr+8,si + mov ___argr+10,di + +zap_bss: ! Clear the BSS + mov ax,ds + mov es,ax ! ES now data seg + mov di,#__edata + mov cx,#__end + sub cx,di + xor ax,ax + cld + rep + stosb + + push [_environ] + mov ax,#defarg ! Don`t define __mkargv, standalone programs don`t + push ax ! get any arguments. + mov ax,#1 + push ax + + mov bx,#auto_start ! Pointer to first autostart function +auto_run: + mov [loop_save],bx + mov bx,[bx] + test bx,bx + jz no_entry + call bx ! Call the function +no_entry: + mov bx,[loop_save] + inc bx ! next + inc bx + jmp auto_run ! And round for the next. + +call_exit: ! Last item called by above. + pop bx ! Be tidy. + push ax ! At the end the last called was main() push it`s + call _exit ! return val and call exit(); +bad_exit: + jmp bad_exit ! Exit returned !! + + loc 2 + .word _main ! Segment 2 is the trailing pointers, main and the + .word call_exit ! routine to call exit. +data_start: + + .text +export _exit +_exit: ! exit(rv) function + mov bx,sp + push [bx+2] ! Copy the `rv` for the exit fuctions. + mov bx,[___cleanup] ! Call exit, normally this is `__do_exit` + test bx,bx + je no_clean ! But it`s default is null + call bx +no_clean: + inc sp + inc sp + +export __exit +__exit: + xor ax,ax + mov es,ax + mov ax,cs + seg es + mov [$E6*4+2],ax + mov ax,#reti_ins + seg es + mov [$E6*4],ax + mov ax,#$FFFF + int $E6 ! Try to exit DOSEMU + ! If we get here we`re not in dosemu. + seg es + mov [$472],#$1234 ! Warm reboot. + jmpi $0000,$FFFF +reti_ins: + reti + +#endasm + +#endif + +/****************************************************************************/ + +#ifdef L___file_3 + +/* If the block function does track buffering this should be ok ... */ +struct { + int (*block_rw)(); /* Args (rwoc, &buffer, blockno) 1k blocks */ + /* 0 = read, 1 = write */ + /* 2 = open, buffer is fname ptr */ + /* 3 = close, other args ignored */ + long offset; + + int flags; + long block_num; + char buffer[1024]; +} __file_3_data; + +#define FILE3_OPEN 1 /* File is open */ +#define FILE3_DATA 2 /* buffer has valid contents */ +#define FILE3_DIRTY 4 /* buffer has been modified */ + +#endif + +#ifdef L_bios_write +write(fd,buf,len) +int fd,len; +char * buf; +{ + register int v, c; + if(fd == 1 || fd == 2) + { + for(v=len; v>0; v--) + { + c= *buf++; + if( c == '\n') bios_putc('\r'); + bios_putc(c); + } + return len; + } + errno = EBADF; + return -1; +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_read +read(fd,buf,len) +int fd,len; +char * buf; +{ + if(fd == 0) return bios_rdline(buf, len); + errno = EBADF; + return -1; +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_lseek +long +lseek(fd, offt, whence) +int fd, whence; +long offt; +{ + if( fd >= 0 && fd <= 2 ) errno = ESPIPE; + else errno = EBADF; + return -1L; +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_open +open(name, flags, mode) +char * name; +int flags, mode; +{ + errno = ENOENT; + return -1; +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_close +close(fd) +int fd; +{ + if( fd >= 0 && fd <= 2 ) errno = ENOSYS; + else errno = EBADF; + return -1; +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_isatty +isatty(fd) +int fd; +{ + if( fd >= 0 && fd <= 2 ) return 1; + return 0; +} +#endif + +/****************************************************************************/ + +#endif +#endif +#endif diff --git a/libc/bios/bios_vid.c b/libc/bios/bios_vid.c new file mode 100644 index 0000000..db2e91d --- /dev/null +++ b/libc/bios/bios_vid.c @@ -0,0 +1,489 @@ +/* Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk> + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* Various possible console types */ +#define VT52_CON /* IMO the best, no clear to EOS/EOL yet */ +#define XANSI_CON /* Largest but still not complete */ +#define XDUMB_CON /* Can't do much */ +#define XSPEC_CON /* Incomplete, best for slow links */ + +#if !__FIRST_ARG_IN_AX__ +#ifdef __AS386_16__ +#ifdef __STANDALONE__ + +#include <dos.h> +#include <errno.h> +int errno; + +#ifdef L_bios_putc +#define CTRL(x) ((x)&0x1F) +static int last_attr = 0x07; +static int con_mode; +static unsigned char con_height = 24, con_width = 79; + +static int con_colour = 0; +static unsigned char con_row, con_col; + +#ifdef VT52_CON +bios_putc(c) +int c; +{ +static int ctrl = 0; + int new_attr; + if( con_mode==0 ) asm_coninit(); + + switch( ctrl ) + { + case 1: + ctrl=0; + switch(c) + { + case 'A': if( con_row ) con_row--; asm_cpos(con_row, con_col); break; + case 'B': if( con_row != con_height ) con_row++; + asm_cpos(con_row, con_col); break; + case 'C': if( con_col != con_height ) con_col++; + asm_cpos(con_row, con_col); break; + case 'D': if( con_col ) con_col--; asm_cpos(con_row, con_col); break; + case 'E': last_attr = 0x07; asm_cls(); + case 'H': asm_cpos(0,0); break; + case 'J': asm_cls(); break; + case 'K': break; + case 'R': ctrl = 2; break; /* Foreground */ + case 'S': ctrl = 3; break; /* Background */ + case 'Y': ctrl = 4; break; /* ttypos */ + } + break; + case 2: ctrl=0; new_attr = (last_attr & 0xF0) + (c&0xF); + if(0) { + case 3: ctrl=0; new_attr = (last_attr & 0x0F) + (c<<4); + } + switch(c) + { + case '_': if( !con_colour ) last_attr = (last_attr&0x88) + 1; + break; + case '!': last_attr = (last_attr&0x88) + 0x70; break; + case ' ': last_attr = 0x07; break; + case '+': last_attr |= 0x08; break; + case '*': last_attr |= 0x80; break; + + default: if( con_colour ) + last_attr = new_attr; + } + break; + case 4: ctrl=5; con_col = c-' '; break; + case 5: ctrl=0; con_row = c-' '; asm_cpos(con_row, con_col); break; + break; + + default: + if( c & 0xE0 ) + { asm_colour(last_attr) ; asm_putc(c); } + else switch(c) + { + default: + asm_putc(c); + break; + case CTRL('I'): + asm_putc(' '); /* Only some BIOS's have this, so play safe */ + break; + case CTRL('L'): + asm_cpos(0,0); + asm_cls(); + break; + case CTRL('['): + ctrl = 1; + asm_gpos(); + break; + } + break; + } +} +#endif + +#ifdef ANSI_CON +#define MAX_ARGS 8 +static int colconv[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; +static int vidcnt = 0; +static int ansi_2 = 0; +static int ansi_argc = 0; +static int ansi_argv[MAX_ARGS]; + +bios_putc(c) +int c; +{ + if( con_mode==0 ) asm_coninit(); + + if( vidcnt == 0 || c < ' ' || c > '~' ) + { + switch(c & 0xFF) + { + default: + asm_colour(last_attr); + asm_putc(c); + break; + case CTRL('L'): + asm_cpos(0,0); + asm_cls(); + break; + case CTRL('['): + vidcnt=1; + break; + } + return; + } + + /* ... ansi/vt100 interpretation, this collects _all_ ansi control strings */ + switch(vidcnt) + { + case 1: for(ansi_argc=0; ansi_argc<MAX_ARGS; ansi_argc++) + ansi_argv[ansi_argc] = 0; + ansi_2 = 0; + ansi_argc = 0; + vidcnt++; + + if( c != '[' ) + { + do_ansi(c + 0x1B00, ansi_argc, ansi_argv); + vidcnt = 0; + } + break; + + case 2: if( c == ';' ) + { + if( ansi_argc < MAX_ARGS ) + ansi_argc++; + } + else if( c >= '0' && c <= '9' ) + ansi_argv[ansi_argc] = ansi_argv[ansi_argc] * 10 + c - '0'; + else if( c >= '@' ) + { + do_ansi(c+ansi_2, ++ansi_argc, ansi_argv); + vidcnt = 0; + } + else + ansi_2 = (c<<8); + break; + + default: vidcnt = 0; /* This definitly won't happen ... definitly ... */ + } +} + +do_ansi(ctrl, argc, argv) +int ctrl, argc, *argv; +{ + switch(ctrl) + { + case 'A': + case 'B': + case 'C': + case 'D': + asm_gpos(); + if( argv[0] < 1 ) argv[0] = 1; + switch(ctrl) + { + case 'A': if( argv[0]>con_row ) con_row=0; else con_row-=argv[0]; break; + case 'B': if( argv[0]+con_row>con_height ) + con_row = con_height; + else + con_row += argv[0]; + break; + case 'C': if( argv[0]+con_col>con_width ) + con_col = con_width; + else + con_col += argv[0]; + break; + case 'D': if( argv[0]>con_col ) con_col=0; else con_col-=argv[0]; break; + } + asm_cpos(con_row, con_col); + break; + + case 'H': + if( --argv[0] < 0 ) argv[0] = 0; + if( --argv[1] < 0 ) argv[1] = 0; + asm_cpos(argv[0],argv[1]); + break; + case 'J': if( argv[0] == 2 ) asm_cls(); + break; + case 'm': + { + int ar; + for(ar=0; ar<argc; ar++) switch(argv[ar]) + { + case 0: last_attr = 0x07; break; + case 1: last_attr |= 0x08; break; + case 5: last_attr |= 0x80; break; + case 7: last_attr = 0x70; break; + case 30: case 31: case 32: case 33: + case 34: case 35: case 36: case 37: + if( con_colour ) + last_attr = ((last_attr&0xF8)|(colconv[argv[ar]-30])); + break; + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + if( con_colour ) + last_attr = ((last_attr&0x8F)|((colconv[argv[ar]-40])<<4)); + break; + default: break; + } + } + } +} +#endif + +#ifdef SPEC_CON +static char vidbuf[3]; +static int vidcnt=0; + +bios_putc(c) +int c; +{ + if( con_mode==0 ) asm_coninit(); + if( vidcnt == 0 ) + { + if( c & 0xE0 ) + { asm_colour(last_attr) ; asm_putc(c); } + else switch(c) + { + default: + asm_putc(c); + break; + case CTRL('L'): + asm_cpos(0,0); + asm_cls(); + break; + case CTRL('P'): + case CTRL(']'): + vidbuf[vidcnt++] = c; + break; + } + } + else + { + vidbuf[vidcnt++] = c; + if( vidcnt < 3 && + (vidbuf[0] != CTRL(']') || vidbuf[1] < '`' || vidbuf[1] > 'p')) + return; + + if( vidbuf[0] == CTRL('P') ) + { + if( vidbuf[1] >= 32 && vidbuf[1] <= 56 + && vidbuf[2] >= 32 && vidbuf[2] <= 111 ) + asm_cpos((vidbuf[1]-32), (vidbuf[2]-32)); + } + else + { + if( vidbuf[1] >= '`' ) + last_attr = ( (vidbuf[1]&0xF) | (last_attr&0xF0)); + else + last_attr = ( (vidbuf[2]&0xF) | ((vidbuf[1]&0xF)<<4)); + + if( !con_colour ) + last_attr = (last_attr&0x88) + ((last_attr&7)?0x07:0x70); + } + vidcnt=0; + } +} +#endif + +#ifdef DUMB_CON +bios_putc(c) +int c; +{ + if( con_mode==0 ) asm_coninit(); + if( c & 0xE0 ) asm_putc(c); + else switch(c) + { + default: + asm_putc(c); + break; + case CTRL('L'): + asm_cls(); + case CTRL('^'): + asm_cpos(0,0); + break; + } +} +#endif + +static asm_coninit() +{ +#asm + mov ax,#$0F00 + int $10 + mov _con_mode,ax +#endasm + if( (con_mode &0xFF) > 39 ) con_width = (con_mode>>8); + if( (con_mode&0xFF) != 0x7) + con_colour = 1; +} + +static asm_putc(c) +{ +#asm +#if !__FIRST_ARG_IN_AX__ + mov bx,sp + mov ax,[bx+2] +#endif + mov ah,#$0E + mov bx,#7 + int $10 +#endasm +} + +static asm_cls() +{ +#asm + push bp ! Bug in some old BIOS`s + !mov ax,#$0500 + !int $10 + mov ax,#$0600 + mov bh,_last_attr + mov cx,#$0000 + mov dl,_con_width + mov dh,_con_height + int $10 + pop bp +#endasm +} + +static asm_cpos(r,c) +{ +#asm +#if __FIRST_ARG_IN_AX__ + mov bx,sp + mov dh,al + mov ax,[bx+2] + mov dl,al +#else + mov bx,sp + mov ax,[bx+2] + mov dh,al + mov ax,[bx+4] + mov dl,al +#endif + mov ah,#$02 + mov bx,#7 + int $10 +#endasm +} + +#ifndef DUMB_CON +static asm_colour(c) +{ +#asm +#if __FIRST_ARG_IN_AX__ + mov bx,ax +#else + mov bx,sp + mov bx,[bx+2] +#endif + mov ah,#$08 + int $10 + mov ah,#$09 + mov cx,#1 + int $10 +#endasm +} + +static asm_gpos() +{ +#asm + mov ah,#$03 + mov bx,#7 + int $10 + mov [_con_row],dh + mov [_con_col],dl + mov ax,cx +#endasm +} +#endif +#endif + +/****************************************************************************/ + +#ifdef L_bios_rdline +bios_rdline(buf, len) +char * buf; +int len; +{ + int ch; + int pos=0; + + if( len == 1 ) + { + buf[0]=((ch=bios_getc())&0xFF?ch&0xFF:((ch>>8)&0xFF|0x80)); + return 1; + } + + for(ch=0;;) + { + if(ch != '\003') + { + ch = bios_getc(); + if( pos == 0 && (ch&0xFF) == 0 ) + { + buf[0] = ((ch>>8)|0x80); + return 1; + } + ch &= 0x7F; + if( ch == '\033' ) ch=3; /* ESC= Interrupt too */ + } + if( ch == '\r' ) + { + bios_putc('\r'); bios_putc('\n'); + buf[pos++] = '\n'; + return pos; + } + if( ch >= ' ' && ch != 0x7F && pos < len-1) + bios_putc(buf[pos++] = ch); + else if( (ch == '\003' || ch == '\b') && pos > 0 ) + { + bios_putc('\b'); bios_putc(' '); bios_putc('\b'); + pos--; + } + else if( ch == '\003' ) + return 0; + else + bios_putc('\007'); + } +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_getc +bios_getc() +{ +#asm + xor ax,ax + int $16 +#endasm +} +#endif + +/****************************************************************************/ + +#ifdef L_bios_khit +bios_khit() +{ +#asm + mov ah,#1 + int $16 + jz nokey + cmp ax,#0 + jnz dort + mov ax,#3 +dort: + ret +nokey: + xor ax,ax +#endasm +} +#endif + +/****************************************************************************/ + +#endif +#endif +#endif |