Compare commits
10 Commits
1b2237f2f7
...
d7df8501d6
| Author | SHA1 | Date | |
|---|---|---|---|
| d7df8501d6 | |||
| f419f72649 | |||
| 775295804e | |||
| d1bea93d07 | |||
| 2f507a2f71 | |||
| da77e08b80 | |||
| cad4f5081a | |||
| 5bb49da246 | |||
| a55c7c47e0 | |||
| cbe304cabf |
10
Makefile
10
Makefile
@@ -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 .
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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):
|
||||||
24
src/Makefile
24
src/Makefile
@@ -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
33
src/ftpget.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
15
src/polio.s
15
src/polio.s
@@ -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:
|
||||||
|
|||||||
260
src/polmon.cc
260
src/polmon.cc
@@ -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
7
src/polos.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define kLpt1 0x10
|
||||||
|
#define kUntilIdle 1
|
||||||
|
#define kOnce 0
|
||||||
|
|
||||||
|
int runcomms(char until_idle);
|
||||||
45
src/stdlib.c
45
src/stdlib.c
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user