Compare commits

...

10 Commits

Author SHA1 Message Date
d7df8501d6 Last fixes tonight 2025-10-04 00:27:06 +02:00
f419f72649 Small improvements 2025-10-04 00:00:41 +02:00
775295804e Add ftpget 2025-10-03 23:48:11 +02:00
d1bea93d07 hello: now with args 2025-10-03 23:47:31 +02:00
2f507a2f71 clang-format -i 2025-10-03 23:47:12 +02:00
da77e08b80 polmon: al int80, run args, ret code 2025-10-03 23:34:27 +02:00
cad4f5081a Exit wozmon 2025-10-03 23:31:43 +02:00
5bb49da246 polio: fix comms 2025-10-03 23:27:27 +02:00
a55c7c47e0 kbd: use macros 2025-10-03 23:22:21 +02:00
cbe304cabf Move stuff around 2025-10-03 23:21:54 +02:00
13 changed files with 259 additions and 230 deletions

View File

@@ -14,7 +14,6 @@ binaries: ## Build all small binaries
docker build --build-arg TARGET=readfloppy.bin -o . --target=export . docker build --build-arg TARGET=readfloppy.bin -o . --target=export .
docker build --build-arg TARGET=writefloppy.bin -o . --target=export . docker build --build-arg TARGET=writefloppy.bin -o . --target=export .
docker build --build-arg TARGET=crc16.bin -o . --target=export . docker build --build-arg TARGET=crc16.bin -o . --target=export .
docker build --build-arg TARGET=wozmon.bin -o . --target=export .
docker build --build-arg TARGET=hello.bin -o . --target=export . docker build --build-arg TARGET=hello.bin -o . --target=export .
docker build --build-arg TARGET=copy.bin -o . --target=export . docker build --build-arg TARGET=copy.bin -o . --target=export .
docker build --build-arg TARGET=call.bin -o . --target=export . docker build --build-arg TARGET=call.bin -o . --target=export .
@@ -22,6 +21,15 @@ binaries: ## Build all small binaries
docker build --build-arg TARGET=readio.bin -o . --target=export . docker build --build-arg TARGET=readio.bin -o . --target=export .
docker build --build-arg TARGET=writeio.bin -o . --target=export . docker build --build-arg TARGET=writeio.bin -o . --target=export .
.PHONY: polos
polos: ## Build polOS components
docker build --build-arg TARGET=fat12boot.bin -o . --target=export .
docker build --build-arg TARGET=polio.com -o . --target=export .
docker build --build-arg TARGET=polmon.com -o . --target=export .
docker build --build-arg TARGET=mushroom.com -o . --target=export .
docker build --build-arg TARGET=hello.com -o . --target=export .
docker build --build-arg TARGET=ftpget.com -o . --target=export .
.PHONY: floppy .PHONY: floppy
floppy: ## Make a bootable floppy image floppy: ## Make a bootable floppy image
docker build --build-arg TARGET=polos.img -o . --target=export . docker build --build-arg TARGET=polos.img -o . --target=export .

View File

@@ -2,6 +2,10 @@
#include "paracomm.h" #include "paracomm.h"
#include "parallel.h" #include "parallel.h"
#ifndef NOKBD
#define NOKBD 1
#endif // NOKBD
ParaComms pc; ParaComms pc;
void setup() { void setup() {
@@ -37,7 +41,10 @@ void loop() {
} }
led_counter += 1; led_counter += 1;
// checkKbdReset(); #if NOKBD
#else // NOKBD
checkKbdReset();
#endif // NOKBD
uint8_t mosib; uint8_t mosib;
if (strobeOccurred(mosib)) { if (strobeOccurred(mosib)) {
@@ -48,9 +55,9 @@ void loop() {
if (Serial.available() > 0) { if (Serial.available() > 0) {
int c = Serial.read(); int c = Serial.read();
#if 1 #if NOKBD
pc.SendByte(c); pc.SendByte(c);
#else #else // NOKBD
if (c == 2) { if (c == 2) {
mode = 0; mode = 0;
} else if (c == 3) { } else if (c == 3) {
@@ -62,6 +69,6 @@ void loop() {
pc.SendByte(c); pc.SendByte(c);
} }
} }
#endif #endif // NOKBD
} }
} }

View File

@@ -23,7 +23,7 @@ def device_thread(device, ws):
def slowwrite(device, data): def slowwrite(device, data):
for b in data: for b in data:
device.write([b]) device.write([b])
time.sleep(0.01) time.sleep(0.005)
def ws_thread(device, ws): def ws_thread(device, ws):

View File

@@ -20,8 +20,7 @@ LDFLAGS = -mregparmcall -Wl,--gc-sections -Os -nostdlib -flto
%.com: %.elf %.com: %.elf
ia16-elf-objcopy -O binary $< $@ ia16-elf-objcopy -O binary $< $@
bootsectors = fat12boot.bin wozmon.bin fat12boot.bin:
$(bootsectors):
ia16-elf-objcopy -O binary $< $@ ia16-elf-objcopy -O binary $< $@
fat12boot.elf: fat12boot.o fat12.o bootsect.S fat12boot.elf: fat12boot.o fat12.o bootsect.S
@@ -37,33 +36,22 @@ polmon.elf: polmon.o stdlib.o
polio.elf: LDFLAGS += -T flat0600.ld polio.elf: LDFLAGS += -T flat0600.ld
polio.elf: polio-main.o polio.s fat12.o paracomm.o stdlib.o polio.elf: polio-main.o polio.s fat12.o paracomm.o stdlib.o
wozmon.o: polmon.cc
wozmon.o: CPPFLAGS = -DWOZMON=1
wozmon.o:
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
wozmon.elf: wozmon.o bootsect.S
wozmon.elf: LDFLAGS += -T bootsect.ld
wozmon.elf: CPPFLAGS += -DNOBPB
wozmon.bin: wozmon.elf
paracli.elf: LDFLAGS += -T doscom.ld paracli.elf: LDFLAGS += -T doscom.ld
paracli.elf: paracli.s paracomm.o paracli.elf: paracli.s paracomm.o
dos-programs = mushroom.elf hello.elf dos-programs = mushroom.com hello.com ftpget.com
$(dos-programs): LDFLAGS += -T doscom.ld $(dos-programs:.com=.elf): LDFLAGS += -T doscom.ld
mushroom.elf: mushroom.s mushroom.elf: mushroom.s
hello.elf: hello.o stdlib.o crt0.s hello.elf: hello.o stdlib.o crt0.s
ftpget.elf: ftpget.o stdlib.o crt0.s
polos.img: fat12boot.bin polmon.com polio.com mushroom.com hello.com polos.img: fat12boot.bin polmon.com polio.com $(dos-programs)
dd if=/dev/zero of=$@ bs=512 count=720 dd if=/dev/zero of=$@ bs=512 count=720
mformat -i $@ -t 40 -h 2 -s 9 mformat -i $@ -t 40 -h 2 -s 9
mcopy -i $@ polio.com ::/ mcopy -i $@ polio.com ::/
mcopy -i $@ polmon.com ::/ mcopy -i $@ polmon.com ::/
mcopy -i $@ mushroom.com ::/ mcopy -i $@ $(dos-programs) ::/
mcopy -i $@ hello.com ::/
dd if=fat12boot.bin of=$@ conv=notrunc dd if=fat12boot.bin of=$@ conv=notrunc
.PHONY: clean .PHONY: clean

33
src/ftpget.c Normal file
View File

@@ -0,0 +1,33 @@
#include <stdint.h>
#include <unistd.h>
#include "polos.h"
#define kDefaultChunkSize 0x20
int main(int argc, uint16_t argv[]) {
if (argc < 2) {
return -1;
}
uint8_t* dest = (uint8_t*)argv[0];
uint16_t size = argv[1];
uint8_t chunksize = kDefaultChunkSize;
if (argc > 2) {
chunksize = argv[2];
}
uint8_t ok = 0x42;
for (int i = 0; i < size; ) {
runcomms(kUntilIdle);
// delay?
int len = read(kLpt1, dest + i, chunksize);
if (len <= 0) {
break;
}
write(kLpt1, &ok, 1);
i += len;
}
}

View File

@@ -1,5 +1,12 @@
#include <stdio.h> #include <stdio.h>
int main() { int main(int argc, int argv[]) {
puts("Hello, world!\r\n"); puts("Hello, world!\r\n");
if (argc > 1) {
return argv[0] + argv[1];
} else if (argc > 0) {
return argv[0];
}
return 0x42;
} }

View File

@@ -22,6 +22,7 @@ static uint8_t miso_recvbuf[256];
static uint8_t miso_size; static uint8_t miso_size;
static uint8_t miso_received_nibbles; static uint8_t miso_received_nibbles;
static uint8_t miso_state; static uint8_t miso_state;
recv_cb miso_recv_cb;
static void swapbuffers() { static void swapbuffers() {
mosi_sendbuf = mosi_workbuf[mosi_workbuf_idx]; mosi_sendbuf = mosi_workbuf[mosi_workbuf_idx];
@@ -92,19 +93,21 @@ void paracomm_feed(uint8_t n) {
miso_received_nibbles += 1; miso_received_nibbles += 1;
if (miso_received_nibbles == 2 * miso_size) { if (miso_received_nibbles == 2 * miso_size) {
miso_recv_cb(miso_recvbuf, miso_size);
miso_state = 0; miso_state = 0;
} }
} break; } break;
} }
} }
void paracomm_init() { void paracomm_init(recv_cb miso_cb) {
mosi_size = 0; mosi_size = 0;
mosi_workbuf_idx = 0; mosi_workbuf_idx = 0;
mosi_workbuf_size = 0; mosi_workbuf_size = 0;
mosi_state = 0; mosi_state = 0;
miso_state = 0; miso_state = 0;
miso_recv_cb = miso_cb;
} }
int paracomm_send(uint8_t b) { int paracomm_send(uint8_t b) {
@@ -119,20 +122,4 @@ int paracomm_send(uint8_t b) {
return 0; return 0;
} }
uint8_t paracomm_recv(uint8_t* buf, uint8_t size) { uint8_t paracomm_busy() { return mosi_state != 0 || miso_state != 0; }
if (miso_state != 0) {
return 0;
}
if (size > miso_size) {
size = miso_size;
}
memcpy(buf, miso_recvbuf, size);
memcpy(miso_recvbuf, miso_recvbuf+size, miso_size - size);
miso_size -= size;
return size;
}
uint8_t paracomm_busy() {
return mosi_state != 0 || miso_state != 0;
}

View File

@@ -2,19 +2,16 @@
#include <stdint.h> #include <stdint.h>
typedef void (*recv_cb)(const uint8_t* buf, uint8_t size);
/** Must call first **/ /** Must call first **/
void paracomm_init(); void paracomm_init(recv_cb cb);
/** Sends a single byte. /** Sends a single byte.
* Returns: 0 if no error, non-0 otherwise. * Returns: 0 if no error, non-0 otherwise.
*/ */
int paracomm_send(uint8_t b); int paracomm_send(uint8_t b);
/** Receive some bytes.
* Returns: number of bytes copied
*/
uint8_t paracomm_recv(uint8_t* buf, uint8_t size);
/** Call after reading a nibble from the port */ /** Call after reading a nibble from the port */
void paracomm_feed(uint8_t n); void paracomm_feed(uint8_t n);

View File

@@ -12,7 +12,7 @@
#define kParallelDataPort 0x3bc #define kParallelDataPort 0x3bc
#define kParallelStatusPort 0x3bd #define kParallelStatusPort 0x3bd
#define kParallelControlPort 0x3be #define kParallelControlPort 0x3be
#define kParaDelay 400 #define kParaDelay 100
#define kRecvBufferSize 256 #define kRecvBufferSize 256
void dosdbt(); void dosdbt();
@@ -51,15 +51,16 @@ static void __delay__(int n) {
} }
} }
uint8_t xferpara() { uint8_t xferpara(uint8_t until_idle) {
uint8_t mosib = paracomm_nextbyte(); do {
__outb__(kParallelDataPort, mosib); uint8_t mosib = paracomm_nextbyte();
__outb__(kParallelControlPort, 1); __outb__(kParallelDataPort, mosib);
__delay__(kParaDelay); __outb__(kParallelControlPort, 1);
__outb__(kParallelControlPort, 0); __delay__(kParaDelay);
__delay__(kParaDelay); __outb__(kParallelControlPort, 0);
uint8_t mison = __inb__(kParallelStatusPort) >> 4; uint8_t mison = __inb__(kParallelStatusPort) >> 4;
paracomm_feed(mison); paracomm_feed(mison);
} while (until_idle && paracomm_busy());
return paracomm_busy(); return paracomm_busy();
} }
@@ -74,6 +75,22 @@ uint8_t parasend(uint8_t* addr, uint8_t size) {
return i; return i;
} }
uint8_t pararecv(uint8_t* buf, uint8_t size) {
if (parasize == 0) {
return 0;
}
if (size > parasize) {
size = parasize;
}
memcpy(buf, parabuf, size);
if (size < parasize) {
memcpy(parabuf, parabuf + size, parasize - size);
}
parasize -= size;
return size;
}
int main() { int main() {
dosdbt(); dosdbt();
parasize = 0; parasize = 0;

View File

@@ -6,7 +6,7 @@
.global _start .global _start
_start: _start:
cli cli
mov ax, 0x2000 # stack address mov ax, 0x2000 # stack address, shared with polmon
mov sp, ax # ss should already be 0 mov sp, ax # ss should already be 0
sti sti
jmp main jmp main
@@ -143,7 +143,7 @@ recvpara:
mov ax, [bp+0] mov ax, [bp+0]
add ax, si add ax, si
mov dx, [bp+2] mov dx, [bp+2]
call paracomm_recv call pararecv
ret ret
.section .text.int80h .section .text.int80h
@@ -157,14 +157,13 @@ int80h:
xor cx, cx xor cx, cx
mov es, cx mov es, cx
mov ds, cx mov ds, cx
shl ah xchg ah, cl
cmp ah, offset int80h_entries shl cl
cmp cl, offset int80h_entries
jge 0f jge 0f
mov al, ah mov si, cx
xor ah, ah
mov si, ax
mov bp, sp mov bp, sp
lea bp, [bp + 16] # 10 for us, 6 for the interrupt add bp, 16 # 10 for us, 6 for the interrupt
call cs:[int80h_table+si] call cs:[int80h_table+si]
jmp 1f jmp 1f
0: 0:

View File

@@ -2,94 +2,24 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#ifndef WOZMON
#define WOZMON 0
#endif
#if WOZMON
#define BACKSPACE 0
#define ASCIIDUMP 0
#define CLEARSCREENCMD 0
#define INT80H 0
#define SHOWTITLE 0
#define BOOTSTRAP 0
#define LAUNCH 0
#define CTRLBREAK 0
#endif // WOZMON
#ifndef BACKSPACE
#define BACKSPACE 1
#endif
#ifndef ASCIIDUMP
#define ASCIIDUMP 1
#endif
#ifndef CLEARSCREENCMD
#define CLEARSCREENCMD 1
#endif
#ifndef INT80H
#define INT80H 1
#endif
#ifndef SHOWTITLE
#define SHOWTITLE 1
#endif
#ifndef BOOTSTRAP
#define BOOTSTRAP 1
#endif
#ifndef LAUNCH
#define LAUNCH 1
#endif
#ifndef CTRLBREAK
#define CTRLBREAK 1
#endif
namespace { namespace {
#if WOZMON
int getchar() {
register char c asm("al");
asm volatile("movb $0x00, %%ah\n\t"
"int $0x16"
: "=r"(c)::"ah", "cc");
return c;
}
void putchar(int c) {
asm volatile("push %%bp \n\t"
"mov %0, %%ax \n\t"
"movb $0x0e, %%ah \n\t"
"movb $0, %%bh \n\t"
"int $0x10 \n\t"
"pop %%bp \n\t" ::"r"(c)
: "ax", "bh", "cc");
}
#endif // WOZMON
constexpr int kDumpSize = 16; constexpr int kDumpSize = 16;
// arguments on the stack in reverse order extern "C" uint16_t Int80h(uint16_t fun, uint16_t nargs, uint16_t args[]);
extern "C" uint16_t Int80h(uint8_t fun, int nargs);
asm(".section .text.Int80h \n" asm(".section .text.Int80h \n"
"Int80h: \n" "Int80h: \n"
" push %si \n" " push %si \n"
" push %bp \n" " push %bp \n"
" mov %al, %ah \n"
" mov %sp, %bp \n" " mov %sp, %bp \n"
" lea 6(%bp), %si \n" // 4 for pushed stuff, 2 for return addr " mov %cx, %si \n"
" shl $1, %dx \n"
" add %dx, %si \n"
"0: \n" "0: \n"
" test %dx, %dx \n" " cmp %cx, %si \n"
" jz 1f \n" " je 1f \n"
" push (%si) \n" " push -2(%si) \n"
" dec %dx \n" " sub $2, %si \n"
" add $2, %si \n"
" jmp 0b \n" " jmp 0b \n"
"1: \n" "1: \n"
" int $0x80 \n" " int $0x80 \n"
@@ -111,21 +41,22 @@ uint8_t ReadHexNibble(uint8_t c) {
return 10 + (c - 'a'); return 10 + (c - 'a');
} }
uint16_t ReadUintN(int n, const char* buf) { uint16_t ReadUintN(int n, const char*& buf) {
uint16_t out = 0; uint16_t out = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (buf[i] == 0) { if (*buf < '0') {
break; break;
} }
out <<= 4; out <<= 4;
out += ReadHexNibble(buf[i]); out += ReadHexNibble(*buf);
buf += 1;
} }
return out; return out;
} }
uint8_t ReadUint8(const char* buf) { return ReadUintN(2, buf); } uint8_t ReadUint8(const char*& buf) { return ReadUintN(2, buf); }
uint16_t ReadUint16(const char* buf) { return ReadUintN(4, buf); } uint16_t ReadUint16(const char*& buf) { return ReadUintN(4, buf); }
void WriteHexNibble(uint8_t c) { void WriteHexNibble(uint8_t c) {
if (c > 9) { if (c > 9) {
@@ -145,6 +76,11 @@ void WriteUint16(uint16_t a) {
WriteUint8(a & 0xff); WriteUint8(a & 0xff);
} }
void WriteUint16ln(uint16_t a) {
WriteUint16(a);
puts("\r\n");
}
uint8_t __get_far_u8__(uint16_t addr, uint16_t seg) { uint8_t __get_far_u8__(uint16_t addr, uint16_t seg) {
register uint16_t ad asm("si") = addr; register uint16_t ad asm("si") = addr;
register uint16_t sg asm("ds") = seg; register uint16_t sg asm("ds") = seg;
@@ -173,7 +109,6 @@ void Dump(uint16_t addr, uint16_t seg, int count) {
uint8_t d = __get_far_u8__(addr + i, seg); uint8_t d = __get_far_u8__(addr + i, seg);
WriteUint8(d); WriteUint8(d);
} }
#if ASCIIDUMP
putchar(' '); putchar(' ');
putchar(' '); putchar(' ');
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@@ -184,7 +119,6 @@ void Dump(uint16_t addr, uint16_t seg, int count) {
putchar('.'); putchar('.');
} }
} }
#endif
} }
void DumpHex(uint16_t addr, uint16_t seg) { void DumpHex(uint16_t addr, uint16_t seg) {
@@ -197,8 +131,7 @@ void DumpHex(uint16_t addr, uint16_t seg) {
putchar(']'); putchar(']');
putchar(':'); putchar(':');
Dump(addr, seg, kDumpSize); Dump(addr, seg, kDumpSize);
putchar('\r'); puts("\r\n");
putchar('\n');
} }
void ClearScreen() { void ClearScreen() {
@@ -244,49 +177,71 @@ void tofatname(const char* name, char* fatname) {
} }
} }
void LaunchFile(const char* name) { uint16_t __readfile__(const char* name, uint16_t addr) {
register uint16_t ret asm("ax");
asm volatile("push %2 \n\t"
"push %1 \n\t"
"mov $04, %%ah \n\t"
"int $0x80 \n\t"
"pop %%cx \n\t"
"pop %%cx \n\t"
: "=r"(ret)
: "r"(name), "r"(addr)
: "bx", "cx", "dx", "memory", "cc");
return ret;
}
uint16_t LaunchFile(const char* name, uint8_t argc, uint16_t* argv) {
constexpr uint16_t kSegment = 0x200; constexpr uint16_t kSegment = 0x200;
constexpr uint16_t kAddress = 0x100; constexpr uint16_t kAddress = 0x100;
constexpr uint16_t kHeaderAddress = (kSegment << 4); constexpr uint16_t kHeaderAddress = (kSegment << 4);
constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress; constexpr uint16_t kFlatAddress = (kSegment << 4) + kAddress;
constexpr uint8_t kTrampoline[] = { 0xe8, 0xfd, 0x00, 0xcb }; constexpr uint16_t kArgvAddress = 0x0004;
// trampoline:
// call 0x100
// retf
// XXX: if you change kAddress, the trampoline needs to be updated
constexpr uint8_t kTrampoline[] = {0xe8, 0xfd, 0x00, 0xcb};
char fatname[11]; char fatname[11];
tofatname(name, fatname); tofatname(name, fatname);
uint16_t r = __readfile__(fatname, kFlatAddress);
if (r) {
return r;
}
auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress); auto* ptr = reinterpret_cast<uint8_t*>(kHeaderAddress);
memcpy(ptr, kTrampoline, sizeof(kTrampoline)); memcpy(ptr, kTrampoline, sizeof(kTrampoline));
auto* argp = reinterpret_cast<uint16_t*>(kHeaderAddress + kArgvAddress);
memcpy(argp, argv, argc * 2);
asm volatile("mov %1, %%ax \n\t" register uint16_t ac asm("ax") = argc;
"push %%ax \n\t" register uint16_t av asm("dx") = kArgvAddress;
"mov %0, %%ax \n\t" asm volatile("mov %2, %%cx \n\t"
"push %%ax \n\t" "mov %%cx, %%ds \n\t"
"mov $04, %%ah \n\t" "mov %%cx, %%es \n\t"
"int $0x80 \n\t"
"add $4, %%sp \n\t"
"mov %2, %%ax \n\t"
"mov %%ax, %%ds \n\t"
"mov %%ax, %%es \n\t"
"cli \n\t" "cli \n\t"
"mov %%ax, %%ss \n\t" "mov %%cx, %%ss \n\t"
"mov %3, %%ax \n\t" "mov %3, %%cx \n\t"
"xchg %%ax, %%sp \n\t" "xchg %%cx, %%sp \n\t"
"sti \n\t" "sti \n\t"
"push %%ax \n\t" "push %%cx \n\t"
"lcall %2,$0 \n\t" "lcall %2,$0 \n\t"
"xor %%ax, %%ax \n\t" "xor %%cx, %%cx \n\t"
"mov %%ax, %%ds \n\t" "mov %%cx, %%ds \n\t"
"mov %%ax, %%es \n\t" "mov %%cx, %%es \n\t"
"cli \n\t" "cli \n\t"
"pop %%sp \n\t" "pop %%sp \n\t"
"mov %%ax, %%ss \n\t" "mov %%cx, %%ss \n\t"
"sti" "sti"
:: "rmi"(fatname), : "+r"(ac), "+r"(av)
"rmi"(kFlatAddress), "i"(kSegment), "i"(kHeaderAddress) : "i"(kSegment), "i"(kAddress)
: "ax", "bx", "cx", "dx", "memory"); : "bx", "cx", "memory", "cc");
}
#if CTRLBREAK return ac;
}
constexpr uint16_t kCtrlBreakVector = (0x1b * 4); constexpr uint16_t kCtrlBreakVector = (0x1b * 4);
@@ -294,9 +249,9 @@ extern "C" void cbreak();
asm(" .section .text.cbreak \n" asm(" .section .text.cbreak \n"
"cbreak: \n" "cbreak: \n"
" xor %ax, %ax \n" " xor %ax, %ax \n"
" mov %ds, %ax \n" " mov %ax, %ds \n"
" cli \n" " cli \n"
" mov %ss, %ax \n" " mov %ax, %ds \n"
" mov $0x2000, %sp \n" " mov $0x2000, %sp \n"
" sti \n" " sti \n"
" pushf \n" " pushf \n"
@@ -313,15 +268,13 @@ void InstallCtrlBreak() {
vec[1] = 0; vec[1] = 0;
} }
#endif // CTRLBREAK
bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) { bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
bool dump = true; bool dump = true;
for (const char* ptr = buf; *ptr;) { for (const char* ptr = buf; *ptr;) {
if (*ptr == 's') { if (*ptr == 's') {
cur_addr = 0; cur_addr = 0;
cur_seg = ReadUint16(ptr + 1); ptr += 1;
ptr += 5; cur_seg = ReadUint16(ptr);
} else if (*ptr == '$') { } else if (*ptr == '$') {
__basic__(); __basic__();
} else if (*ptr == 'j') { } else if (*ptr == 'j') {
@@ -329,52 +282,47 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
ptr++; ptr++;
auto jump = reinterpret_cast<uint16_t (*)()>(cur_addr); auto jump = reinterpret_cast<uint16_t (*)()>(cur_addr);
uint16_t ret = jump(); uint16_t ret = jump();
WriteUint16(ret); WriteUint16ln(ret);
putchar('\r');
putchar('\n');
#if INT80H
} else if (*ptr == 'i') { } else if (*ptr == 'i') {
dump = false; dump = false;
int nargs = 0; uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0;
ptr++; ptr++;
int fun = ReadUint8(ptr); int fun = ReadUint8(ptr) << 8;
ptr += 2; fun += ReadUint8(ptr);
for (; *ptr;) { for (; *ptr && nargs < 8;) {
if (*ptr == ' ') { if (*ptr == ' ') {
ptr++; ptr++;
continue; continue;
} }
uint16_t d = ReadUint16(ptr); args[nargs++] = ReadUint16(ptr);
asm volatile("push %0" ::"r"(d));
nargs++;
ptr += 4;
} }
uint16_t ret = Int80h(fun, nargs); uint16_t ret = Int80h(fun, nargs, args);
asm volatile("shl %0 \n\t" WriteUint16ln(ret);
"add %0, %%sp" ::"r"(nargs));
WriteUint16(ret);
putchar('\r');
putchar('\n');
#endif // INT80H
#if CLEARSCREENCMD
} else if (*ptr == 'l') { } else if (*ptr == 'l') {
dump = false; dump = false;
ClearScreen(); ClearScreen();
ptr++; ptr++;
#endif // CLEARSCREENCMD
#if LAUNCH
} else if (*ptr == 'r') { } else if (*ptr == 'r') {
dump = false; dump = false;
uint16_t args[8]; // ought to be enough for everybody
uint8_t nargs = 0;
ptr++; ptr++;
while (*ptr == ' ') { while (*ptr == ' ') {
ptr++; ptr++;
} }
int l = 0; const char* fname = ptr;
for (; ptr[l]; l++) { for (; *ptr && *ptr != ' '; ptr++) {
} }
LaunchFile(ptr); for (; *ptr && nargs < 8;) {
ptr += l; if (*ptr == ' ') {
#endif // LAUNCH ptr++;
continue;
}
args[nargs++] = ReadUint16(ptr);
}
uint16_t ret = LaunchFile(fname, nargs, args);
WriteUint16ln(ret);
} else if (*ptr == 'w') { } else if (*ptr == 'w') {
dump = false; dump = false;
uint16_t addr = cur_addr; uint16_t addr = cur_addr;
@@ -387,21 +335,17 @@ bool ParseCommand(const char* buf, uint16_t& cur_addr, uint16_t& cur_seg) {
uint8_t d = ReadUint8(ptr); uint8_t d = ReadUint8(ptr);
__set_far_u8__(addr, cur_seg, d); __set_far_u8__(addr, cur_seg, d);
addr++; addr++;
ptr += 2;
} }
} else { } else {
cur_addr = ReadUint16(ptr); cur_addr = ReadUint16(ptr);
ptr += 4;
} }
} }
return dump; return dump;
} }
void DisplayPrompt() { void DisplayPrompt() { puts("> "); }
putchar('>');
putchar(' ');
}
[[noreturn]]
void polmon() { void polmon() {
uint16_t cur_addr = 0; uint16_t cur_addr = 0;
uint16_t cur_seg = 0; uint16_t cur_seg = 0;
@@ -410,9 +354,7 @@ void polmon() {
char* inptr = inbuf; char* inptr = inbuf;
ClearScreen(); ClearScreen();
#if SHOWTITLE
puts("PolMon for Workgroups 3.1\r\n"); puts("PolMon for Workgroups 3.1\r\n");
#endif // SHOWTITLE
DisplayPrompt(); DisplayPrompt();
while (1) { while (1) {
@@ -434,7 +376,6 @@ void polmon() {
first = false; first = false;
inptr = inbuf; inptr = inbuf;
DisplayPrompt(); DisplayPrompt();
#if BACKSPACE
} else if (c == kBackspace || c == kOtherBackspace) { } else if (c == kBackspace || c == kOtherBackspace) {
inptr--; inptr--;
if (inptr < inbuf) { if (inptr < inbuf) {
@@ -444,26 +385,19 @@ void polmon() {
} }
putchar(' '); putchar(' ');
putchar(kOtherBackspace); putchar(kOtherBackspace);
#endif
} else { } else {
*inptr = c; *inptr = c;
inptr++; inptr++;
} }
} }
__builtin_unreachable();
} }
} // namespace } // namespace
int main() { int main() {
#if CTRLBREAK
InstallCtrlBreak(); InstallCtrlBreak();
#endif // CTRLBREAK
polmon(); polmon();
} }
#if BOOTSTRAP __attribute__((section(".init"), used)) void _start() { main(); }
__attribute__((section(".init"), noreturn, used)) void _start() {
main();
__builtin_unreachable();
}
#endif // BOOTSTRAP

7
src/polos.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#define kLpt1 0x10
#define kUntilIdle 1
#define kOnce 0
int runcomms(char until_idle);

View File

@@ -1,6 +1,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "polos.h"
int getchar() { int getchar() {
register char c asm("al"); register char c asm("al");
asm volatile("movb $0x00, %%ah\n\t" asm volatile("movb $0x00, %%ah\n\t"
@@ -43,3 +45,46 @@ void* memset(void* ptr, int val, size_t len) {
} }
return ptr; return ptr;
} }
int _int80h_2(uint8_t fun, uint16_t arg1, uint16_t arg2) {
register uint16_t a1 asm("dx") = arg1;
register uint16_t a2 asm("cx") = arg2;
register uint8_t ah asm("ah") = fun;
register uint16_t ret asm("ax");
asm volatile("push %3 \n\t"
"push %2 \n\t"
"int $0x80 \n\t"
"pop %%cx \n\t"
"pop %%cx \n\t"
: "=r"(ret)
: "r"(ah), "r"(a1), "r"(a2)
: "bx", "cc", "memory");
return ret;
}
int runcomms(char until_idle) {
register int ret asm("ax");
register char ui asm("al") = until_idle;
asm volatile("mov $0x07, %%ah \n\t"
"int $0x80 \n\t"
: "=r"(ret)
: "r"(until_idle)
: "bx", "cx", "dx", "cc", "memory");
return ret;
}
int read(int fd, void* buf, size_t size) {
if (fd != kLpt1) {
return -1;
}
return _int80h_2(0x05, (uint16_t)buf, size);
}
int write(int fd, void* buf, size_t size) {
if (fd != kLpt1) {
return -1;
}
return _int80h_2(0x06, (uint16_t)buf, size);
}