|
|
@@ -0,0 +1,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 0x3f |
|
|
|
#define TRK_PER_HEAD 0xff |
|
|
|
|
|
|
|
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&0xff, dx>>8); |
|
|
|
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, ((((dh*TRK_PER_HEAD)+ch)*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] = TRK_PER_HEAD-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; |
|
|
|
} |