~vdupras/collapseos

ref: 421ca5112f091f8ba3322a13e128e083e6bd1615 collapseos/emul/8086/pcat.c -rw-r--r-- 3.1 KiB
421ca511Virgil Dupras Remove one level of C< override 1 year, 11 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
127
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <curses.h>
#include "cpu.h"

#define WCOLS 80
#define WLINES 25
#define SEC_PER_TRK 0x24
#define HEADCNT 2

extern uint8_t byteregtable[8];
extern union _bytewordregs_ regs;
extern uint16_t segregs[4];
extern INTHOOK INTHOOKS[0x100];

static FILE *fp;
WINDOW *bw, *dw, *w;

static void int10() {
    uint8_t cmd = regs.byteregs[regah];
    uint8_t al = regs.byteregs[regal];
    uint16_t dx = regs.wordregs[regdx];
    switch (cmd) {
        case 0x02: // at-xy
            wmove(w, dx>>8, dx&0xff);
            break;
        case 0x0e: // emit
        if (al >= 0x20 || al == '\n') {
            wechochar(w, al);
        } else if (al == 0x08) {
            int y, x; getyx(w, y, x);
            wmove(w, y, x-1);
        }
        break;
    }
}

static void int13() {
    uint8_t cmd = regs.byteregs[regah];
    uint8_t al = regs.byteregs[regal];
    uint8_t cl = regs.byteregs[regcl];
    uint8_t ch = regs.byteregs[regch];
    uint8_t dh = regs.byteregs[regdh];
    uint16_t bx = regs.wordregs[regbx];
    switch (cmd) {
        case 0x02: // read disk sector(s)
        case 0x03: // write disk sector(s)
        // CL = sector number (1-based), AL = sector count
        // DH = head number, CH = track number
        // ES:BX = dest addr
        fseek(fp, (((ch*HEADCNT*SEC_PER_TRK)+(dh*SEC_PER_TRK))+cl-1)*512, SEEK_SET);
        for (int i=0; i<(al*512); i++) {
            if (cmd == 0x03) { // write
                fputc(getmem8(segregs[reges], bx+i), fp);
            } else { // read
                putmem8(segregs[reges], bx+i, fgetc(fp));
            }
        }
        break;

        case 0x08: // poll sectors per track / per head
        // we just report a lot of them
        regs.wordregs[regcx] = SEC_PER_TRK;
        regs.byteregs[regdh] = HEADCNT-1;
        break;
    }
}

static void int16() {
    int c;
    // debug_panel();
    c = wgetch(w);
    regs.byteregs[regal] = c;
}

static void usage()
{
    fprintf(stderr, "Usage: ./pcat /path/to/fd\n");
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        usage();
        return 1;
    }
    INTHOOKS[0x10] = int10;
    INTHOOKS[0x13] = int13;
    INTHOOKS[0x16] = int16;
    reset86(0x7c00);
    // initialize memory
    fp = fopen(argv[1], "r");
    if (!fp) {
        fprintf(stderr, "Can't open %s\n", argv[1]);
        return 1;
    }
    // read MBR into RAM
    for (int i=0; i<512; i++) {
        int c = getc(fp);
        if (c != EOF) {
            write86(0x7c00+i, c);
        }
    }
    uint16_t magic = readw86(0x7dfe);
    if (magic != 0xaa55) {
        fprintf(stderr, "Invalid MBR magic %x\n", magic);
        return 1;
    }
    initscr(); cbreak(); noecho(); nl(); clear();
    // border window
    bw = newwin(WLINES+2, WCOLS+2, 0, 0);
    wborder(bw, 0, 0, 0, 0, 0, 0, 0, 0);
    wrefresh(bw);
    // debug panel
    dw = newwin(1, 30, LINES-1, COLS-30);
    w = newwin(WLINES, WCOLS, 1, 1);
    scrollok(w, 1);
    while (exec86(100)) {
        //debug_panel();
    }
    nocbreak(); echo(); delwin(w); delwin(bw); delwin(dw); endwin();
    printf("\nDone!\n");
    //emul_printdebug();
    fclose(fp);
    return 0;
}