So I read the whole book except some of the video and keyboard stuff that I may not need
(or at least don't need yet).
Here's my rough draft of dos support functions. The vv array is the payload of the ESC
bytes from the ESC instruction. My interrupt handlers fill it in with the interrupt number.
U is a uintptr_t.
It need to do more error checking and reporting, but this should be enough to access
files from my Forth CODEs. Maybe exiting a dos program ought not to exit() the whole
emulator.
static int keyboard_input_with_echo(){
bput(al, fgetc(stdin));
}
static int display_output(){
fputs( cp437tounicode( bget(dl) ), stdout );
bput(al,bget(dl)); if(bget(al)=='\t')bput(al,' ');
}
static int display_string(){
f=wget(dx);
while(mem[f]!='$')fputs( cp437tounicode( mem[f++] ), stdout );
bput(al,'$');
}
static int get_date(){
time_t t=time(NULL);struct tm*tm=localtime(&t);
wput(cx,tm->tm_year);
wput(dh,tm->tm_mon);
wput(dl,tm->tm_mday);
wput(al,tm->tm_wday);
}
static int get_time(){
struct timeval tv;gettimeofday(&tv,0);
time_t t=time(NULL);struct tm*tm=localtime(&t);
bput(ch,tm->tm_hour);
bput(cl,tm->tm_min);
bput(dh,tm->tm_sec);
bput(dl,tv.tv_usec/10);
}
static int open_file(){
U mode = bget(al);
FILE *f = fopen(mem + ds_(dx), (mode & 7) == 0? "r":
(mode & 7) == 1? "w": "rw");
if( f ){
U handle = next_handle ++;
handles[ handle ] = f;
wput(ax, handle);
clc();
return 0;
}
wput(ax, 0);
stc();
}
static int close_file_handle(){
U handle = wget(bx);
fclose( handles[ handle ] );
handles[ handle ] = 0;
-- next_handle;
}
static int read_file(){
U handle = wget(bx);
U count = fread(mem + ds_(dx), 1, wget(cx), handles[ handle ]);
if( count ){
wput(ax, count);
clc();
return 0;
}
wput(ax, 5); //access denied
stc();
}
static int write_file(){
U handle = wget(bx);
U count = fwrite(mem + ds_(dx), 1, wget(cx), handles[ handle ]);
if( count == wget(cx) ){
clc();
return 0;
}
wput(ax, 5); //access denied
stc();
}
static int move_file_pointer(){
U handle = wget(bx);
U whence = bget(al);
fseek( handles[ handle ], qget(cx,dx), whence == 0? SEEK_SET:
whence == 1? SEEK_CUR:
whence == 2? SEEK_END: 0);
U pos = ftell( handles[ handle ] );
qput(dx, ax, pos);
}
static int dos( UC vv[7] ){
switch(bget(ah)){
CASE 0x01: return keyboard_input_with_echo();
CASE 0x02: return display_output();
CASE 0x09: return display_string();
CASE 0x2A: return get_date();
CASE 0x2C: return get_time();
CASE 0x3C: // create file
CASE 0x3D: return open_file();
CASE 0x3E: return close_file_handle();
CASE 0x3F: return read_file();
CASE 0x40: return write_file();
CASE 0x42: return move_file_pointer();
CASE 0x44: // ioctl
CASE 0x4B: // load/execute program
CASE 0x4C: exit(bget(al));
CASE 0x5B: // create new file
;
}
}
static int keyboard_input_with_echo(){
bput(al, fgetc(stdin));
}
static int display_output(){
fputs( cp437tounicode( bget(dl) ), stdout );
bput(al,bget(dl)); if(bget(al)=='\t')bput(al,' ');
}
static int display_string(){
f=wget(dx);
while(mem[f]!='$')fputs( cp437tounicode( mem[f++] ), stdout );
bput(al,'$');
}
static int get_date(){
time_t t=time(NULL);struct tm*tm=localtime(&t);
wput(cx,tm->tm_year);
wput(dh,tm->tm_mon);
wput(dl,tm->tm_mday);
wput(al,tm->tm_wday);
}
static int get_time(){
struct timeval tv;gettimeofday(&tv,0);
time_t t=time(NULL);struct tm*tm=localtime(&t);
bput(ch,tm->tm_hour);
bput(cl,tm->tm_min);
bput(dh,tm->tm_sec);
bput(dl,tv.tv_usec/10);
}
static int open_file(){
U mode = bget(al);
FILE *f = fopen(mem + ds_(dx), (mode & 7) == 0? "r":
(mode & 7) == 1? "w": "rw");
if( f ){
U handle = next_handle ++;
handles[ handle ] = f;
wput(ax, handle);
clc();
return 0;
}
wput(ax, 0);
stc();
}
static int close_file_handle(){
U handle = wget(bx);
fclose( handles[ handle ] );
handles[ handle ] = 0;
-- next_handle;
}
static int read_file(){
U handle = wget(bx);
U count = fread(mem + ds_(dx), 1, wget(cx), handles[ handle ]);
if( count ){
wput(ax, count);
clc();
return 0;
}
wput(ax, 5); //access denied
stc();
}
static int write_file(){
U handle = wget(bx);
U count = fwrite(mem + ds_(dx), 1, wget(cx), handles[ handle ]);
if( count == wget(cx) ){
clc();
return 0;
}
wput(ax, 5); //access denied
stc();
}
static int move_file_pointer(){
U handle = wget(bx);
U whence = bget(al);
fseek( handles[ handle ], qget(cx,dx), whence == 0? SEEK_SET:
whence == 1? SEEK_CUR:
whence == 2? SEEK_END: 0);
U pos = ftell( handles[ handle ] );
qput(dx, ax, pos);
}
static int dos( UC vv[7] ){
switch(bget(ah)){
CASE 0x01: return keyboard_input_with_echo();
CASE 0x02: return display_output();
CASE 0x09: return display_string();
CASE 0x2A: return get_date();
CASE 0x2C: return get_time();
CASE 0x3C: // create file
CASE 0x3D: return open_file();
CASE 0x3E: return close_file_handle();
CASE 0x3F: return read_file();
CASE 0x40: return write_file();
CASE 0x42: return move_file_pointer();
CASE 0x44: // ioctl
CASE 0x4B: // load/execute program
CASE 0x4C: exit(bget(al));
CASE 0x5B: // create new file
;
}
}
And this bit is silly but fun:
unsigned cp437table[256] = {
' ', 0x263A,0x263B,0x2665,0x2666,0x2663,0x2660,0x2022,
0x25D8,0x25CB,0x2509,0x2642,0x2640,0x266A,0x266B,0x263C,
0x25BA,0x25C4,0x2195,0x203C,0x00B6,0x00A7,0x25AC,0x21A8,
0x2191,0x2193,0x2192,0x2190,0x221F,0x2194,0x25B2,0x25BC,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,0x2302,
0xC7,0xFC,0xE9,0xE2,0xE4,0xE0,0xE5,0xE7,0xEA,0xEB,0xE8,0xEF,0xEE,0xEC,0xC4,0xC5,
0xC9,0xE6,0xC6,0xF4,0xF6,0xF2,0xFB,0xF9,0xFF,0xD6,0xDC,0xA2,0xA3,0xA5,0x20A7,0x192,
0xE1,0xED,0xF3,0xFA,0xF1,0xD1,0xAA,0xBA,0xBF,0x2310,0xAC,0xBD,0xBC,0xA1,0xAB,0xBB,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,
0x2555,0x2563,0x2551,0x2557,0x255D,0x255C,0x255B,0x2510,
0x2514,0x2534,0x252C,0x251C,0x2500,0x253C,0x255E,0x255F,
0x255A,0x2554,0x2569,0x2566,0x2560,0x2550,0x256C,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256B,
0x256A,0x251B,0x250C,0x2588,0x2584,0x258C,0x2590,0x2580,
0x3B1,0xDF,0x393,0x3C0,0x3A3,0x3C3,0x3BC,0x3C4,
0x3A6,0x398,0x3A9,0x3B4,0x221E,0x3C6,0x3B5,0x2229,
0x2261,0xB1,0x2265,0x2264,0x2320,0x2321,0xF7,0x2248,
0xB0,0x2219,0xB7,0x221A,0x207F,0xB2,0x25A0,0xA0
};
static
char *cp437tounicode( unsigned int c ){
static char buf[4] = "";
unsigned ucs4 = cp437table[ c ];
if( ucs4 < 0x80 ){ // 0... ....
buf[0] = ucs4;
buf[1] = 0;
} else
if( ucs4 < 0x800 ){ // 110. .... 10.. ....
buf[0] = 0xC0 | ucs4 >> 6;
buf[1] = 0x80 | ucs4 & 0x3F;
buf[2] = 0;
} else
if( ucs4 < 0x10000 ){ // 1110 .... 10.. .... 10.. ....
buf[0] = 0xE0 | (ucs4 >> 12) & 0xF;
buf[1] = 0x80 | (ucs4 >> 6) & 0x3F;
buf[2] = 0x80 | ucs4 & 0x3F;
buf[3] = 0;
}
return buf;
}