Lots of little things, Changed test output, Usermode test build
This commit is contained in:
		
							
								
								
									
										15
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o\
 | 
			
		||||
		  usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o disk.o hexedit.o
 | 
			
		||||
		  paging.o fault.o tests.o kbd.o helper.o progs.o disk.o hexedit.o textedit.o
 | 
			
		||||
CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding\
 | 
			
		||||
		 -march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c
 | 
			
		||||
LFLAGS = -Wl,--gc-sections -Wl,--print-gc-sections -m32 -nostartfiles -nostdlib
 | 
			
		||||
@@ -18,11 +18,14 @@ $(OUTFILE): boot.bin kernel.bin
 | 
			
		||||
	# Write kernel beyond boot sector, maximum 128K (256 sectors)
 | 
			
		||||
	dd bs=512 count=256 seek=1 conv=notrunc if=kernel.bin of=$@
 | 
			
		||||
 | 
			
		||||
boot.bin: boot.nasm
 | 
			
		||||
	nasm -o $@ $<
 | 
			
		||||
kernel.bin: out.o link.ld usermode.o
 | 
			
		||||
	clang $(LFLAGS) -Wl,-M -Tlink.ld -ffreestanding -o $@ out.o usermode.o
 | 
			
		||||
 | 
			
		||||
kernel.bin: out.o link.ld
 | 
			
		||||
	clang $(LFLAGS) -Wl,-M -Tlink.ld -ffreestanding -o $@ $<
 | 
			
		||||
usermode.o: usermode.bin
 | 
			
		||||
	objcopy -I binary -O elf32-i386 -B i386 $< $@
 | 
			
		||||
 | 
			
		||||
%.bin: %.nasm
 | 
			
		||||
	nasm -o $@ $<
 | 
			
		||||
 | 
			
		||||
out.o: $(objects)
 | 
			
		||||
	clang $(LFLAGS) -e entry -r -o $@ $^
 | 
			
		||||
@@ -38,4 +41,4 @@ virtdisk:
 | 
			
		||||
	echo -n -e '\x55\xaa' | dd bs=1 seek=510 conv=notrunc of=virtdisk.bin
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f $(objects) out.o kernel.bin boot.bin
 | 
			
		||||
	rm -f $(objects) out.o kernel.bin boot.bin usermode.bin
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								disk.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								disk.c
									
									
									
									
									
								
							@@ -1,3 +1,4 @@
 | 
			
		||||
#include "disk.h"
 | 
			
		||||
#include "v86defs.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "dosfs/dosfs.h"
 | 
			
		||||
@@ -9,14 +10,15 @@ extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n);
 | 
			
		||||
#define DISKCACHESECTORMASK 7
 | 
			
		||||
#define DISKCACHESECTORSIZE 8
 | 
			
		||||
#define DISKCACHEBLOCKCOUNT 128
 | 
			
		||||
uint8_t (*DiskCache)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE] = (uint8_t (*)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE])0x280000;
 | 
			
		||||
uint8_t (*const DiskCache)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE] = (uint8_t (* const)[DISKCACHEBLOCKCOUNT][DISKCACHEBLOCKSIZE])0x280000;
 | 
			
		||||
uint32_t DiskCacheLastRead[DISKCACHEBLOCKCOUNT];
 | 
			
		||||
uint32_t DiskCacheSector[DISKCACHEBLOCKCOUNT];
 | 
			
		||||
 | 
			
		||||
extern uint32_t _gpf_eax_save;
 | 
			
		||||
extern uint32_t _gpf_eflags_save;
 | 
			
		||||
extern uint16_t error_screen[80*50]; // defined in kernel.c
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
extern void error_environment(); // defined in kernel.c
 | 
			
		||||
uint32_t numHead;
 | 
			
		||||
uint32_t secPerTrack;
 | 
			
		||||
@@ -48,12 +50,6 @@ void Disk_SetupCHS() {
 | 
			
		||||
		maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2);
 | 
			
		||||
		useCHS = 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// Init Cache
 | 
			
		||||
	for (int i = 0; i < DISKCACHEBLOCKCOUNT; i++) {
 | 
			
		||||
		DiskCacheLastRead[i] = 0;
 | 
			
		||||
		DiskCacheSector[i] = -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern uint32_t TIMERVAL;
 | 
			
		||||
@@ -95,25 +91,32 @@ void UpdateCache(uint32_t sector, uint8_t *buffer) {
 | 
			
		||||
		((uint32_t*)cache)[i] = ((uint32_t*)buffer)[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	// NOTE If the buffer provided is outside the 0x20000-0x2FE00 range,
 | 
			
		||||
	// the function will use that buffer for the Virtual 8086 process
 | 
			
		||||
	// and copy to the other buffer after
 | 
			
		||||
	uint8_t *v86buf = buffer;
 | 
			
		||||
	if ((uintptr_t)v86buf >= 0x20000 && (uintptr_t)v86buf < 0x28000)
 | 
			
		||||
		v86buf = (uint8_t *)0x28000;
 | 
			
		||||
	else v86buf = (uint8_t *)0x20000;
 | 
			
		||||
 | 
			
		||||
	// TODO This check should probably happen at the kernel level
 | 
			
		||||
	if (useCHS == -1) {
 | 
			
		||||
		Disk_SetupCHS();
 | 
			
		||||
void InitCache() {
 | 
			
		||||
	for (int i = 0; i < DISKCACHEBLOCKCOUNT; i++) {
 | 
			
		||||
		DiskCacheLastRead[i] = 0;
 | 
			
		||||
		DiskCacheSector[i] = -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NOTE Must be run before reading from disk
 | 
			
		||||
void InitDisk() {
 | 
			
		||||
	InitCache();
 | 
			
		||||
	Disk_SetupCHS();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) {
 | 
			
		||||
	uint8_t *cache = FindInCache(sector);
 | 
			
		||||
	if (cache) {
 | 
			
		||||
		memcpy(buffer, cache, count * SECTOR_SIZE);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// NOTE If the buffer provided is outside the 0x20000-0x2F000 range,
 | 
			
		||||
	// the function will use 0x20000 for the Virtual 8086 process
 | 
			
		||||
	// and copy to the other buffer after
 | 
			
		||||
	uint8_t *v86buf = (uintptr_t)buffer >= 0x20000 && (uintptr_t)buffer <= 0x2F000 ?
 | 
			
		||||
			buffer :
 | 
			
		||||
			(uint8_t*)0x20000;
 | 
			
		||||
 | 
			
		||||
	// TODO Do error handling
 | 
			
		||||
	if (!useCHS) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								helper.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								helper.c
									
									
									
									
									
								
							@@ -53,6 +53,7 @@ uint32_t OpenVol(VOLINFO *vi) {
 | 
			
		||||
    uint8_t pactive, ptype;
 | 
			
		||||
    uint32_t pstart, psize;
 | 
			
		||||
    pstart = DFS_GetPtnStart(0, diskReadBuf, 0, &pactive, &ptype, &psize);
 | 
			
		||||
    if (pstart == -1) return -1;
 | 
			
		||||
    return DFS_GetVolInfo(0, diskReadBuf, pstart, vi);
 | 
			
		||||
}
 | 
			
		||||
uint32_t OpenDir(uint8_t *path, VOLINFO *vi, DIRINFO *di) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,12 +5,12 @@
 | 
			
		||||
#define BLOCKSHIFT 16 // blockSize = 1 << blockShift
 | 
			
		||||
#define MAXFILESIZE 0x80000000 // 2GB
 | 
			
		||||
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
 | 
			
		||||
uint16_t writtenMap[TOTALBLOCKS] __attribute__((section(".progbss")));;
 | 
			
		||||
uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".progbss")));;
 | 
			
		||||
uint16_t writtenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));;
 | 
			
		||||
uint32_t blockLenMap[TOTALBLOCKS] __attribute__((section(".hexbss")));;
 | 
			
		||||
// NOTE This is linked at the end of program BSS section,
 | 
			
		||||
// so that it can be expanded without telling C how much
 | 
			
		||||
// it actually needs
 | 
			
		||||
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".proglatebss")));
 | 
			
		||||
uint8_t writeStoreBase[BLOCKSIZE] __attribute__((section(".hexlatebss")));
 | 
			
		||||
void HexEditor(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint32_t err;
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								interrupt.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								interrupt.c
									
									
									
									
									
								
							@@ -95,9 +95,11 @@ extern uint16_t error_screen[80*50]; // defined in kernel.c
 | 
			
		||||
extern uint16_t *ivt;
 | 
			
		||||
extern void real_test();
 | 
			
		||||
extern void jmp_usermode_test();
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
extern void return_prev_task();
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
extern void error_environment(); // defined in kernel.c
 | 
			
		||||
extern uint32_t _gpf_eax_save;
 | 
			
		||||
#define VALID_FLAGS 0xDFF
 | 
			
		||||
@@ -333,3 +335,11 @@ void setup_interrupts() {
 | 
			
		||||
    asm volatile("sti");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
void triple_fault() {
 | 
			
		||||
    IDTR.size = 0;
 | 
			
		||||
    asm volatile("lidt %0": : "m"(IDTR));
 | 
			
		||||
    asm volatile("sti");
 | 
			
		||||
    asm volatile("int $1");
 | 
			
		||||
    for(;;);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								kbd.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								kbd.c
									
									
									
									
									
								
							@@ -71,6 +71,13 @@ void keyboardHandler(struct interrupt_frame *frame) {
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
void kbd_clear() {
 | 
			
		||||
    _KBDWAIT = 0;
 | 
			
		||||
    _LSTKEY_ASCII = 0;
 | 
			
		||||
    _LSTKEY_SCAN = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
void kbd_wait() {
 | 
			
		||||
    _KBDWAIT = 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								kbd.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								kbd.h
									
									
									
									
									
								
							@@ -5,6 +5,9 @@
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
void kbd_wait();
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
void kbd_clear();
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
uint8_t get_key();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								kernel.c
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								kernel.c
									
									
									
									
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
#include "tests.h"
 | 
			
		||||
#include "progs.h"
 | 
			
		||||
#include "helper.h"
 | 
			
		||||
#include "disk.h"
 | 
			
		||||
 | 
			
		||||
typedef unsigned short word;
 | 
			
		||||
 | 
			
		||||
@@ -63,15 +64,6 @@ uint32_t get_cr4() {
 | 
			
		||||
    return reg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern char _loadusercode, _usercode, _eusercode;
 | 
			
		||||
void LoadUser() {
 | 
			
		||||
    // Put Usermode code in proper place based on linker
 | 
			
		||||
    char *s = &_loadusercode;
 | 
			
		||||
    char *d = &_usercode;
 | 
			
		||||
    while (d < &_eusercode)
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern char _edata, _v86code, _ev86code, _bstart, _bend;
 | 
			
		||||
void setup_binary() {
 | 
			
		||||
    // Put V86 code in proper place based on linker
 | 
			
		||||
@@ -80,26 +72,11 @@ void setup_binary() {
 | 
			
		||||
    while (d < &_ev86code)
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
 | 
			
		||||
    LoadUser();
 | 
			
		||||
 | 
			
		||||
    // Clear BSS area
 | 
			
		||||
    for (d = &_bstart; d < &_bend; d++)
 | 
			
		||||
        *d = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern char _bprogstart, _bprogend;
 | 
			
		||||
// NOTE This is linked at the same place
 | 
			
		||||
// as the load address of usermode code,
 | 
			
		||||
// so things linked with bss here *must not*
 | 
			
		||||
// call usermode code at the same place
 | 
			
		||||
void ClearProgBss() {
 | 
			
		||||
    // TODO Make sure there's no weird alignment stuff,
 | 
			
		||||
    // although more BSS should always come after this
 | 
			
		||||
    // ideally.
 | 
			
		||||
    for (uint32_t *d = (uint32_t*)&_bprogstart; d < (uint32_t*)&_bprogend; d++)
 | 
			
		||||
        *d = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t error_screen[80*50]; // 50-line VGA screen of error content
 | 
			
		||||
 | 
			
		||||
extern uint16_t *ivt;
 | 
			
		||||
@@ -124,9 +101,11 @@ void ensure_v86env() {
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
extern void return_prev_task();
 | 
			
		||||
__attribute((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__no_caller_saved_registers__))
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32_t stack3, uint32_t stack4, uint32_t stack5) {
 | 
			
		||||
    ensure_v86env();
 | 
			
		||||
    setup_interrupts(); // just in case
 | 
			
		||||
@@ -172,7 +151,7 @@ void error_environment(uint32_t stack0, uint32_t stack1, uint32_t stack2, uint32
 | 
			
		||||
uint32_t GetFreeStack() {
 | 
			
		||||
    uint32_t stack;
 | 
			
		||||
    asm volatile("mov %%esp,%%eax":"=a"(stack));
 | 
			
		||||
    stack = ((stack - 0x4000) / 0x1000) * 0x1000;
 | 
			
		||||
    stack = ((stack - 0x2000) / 0x1000) * 0x1000;
 | 
			
		||||
    return stack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -254,12 +233,18 @@ void RestoreVGA() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t fileCount, fileOffset;
 | 
			
		||||
DIRENT *entries = (DIRENT*)0x400000;
 | 
			
		||||
// We store dir entries in usermode space,
 | 
			
		||||
// which is nice because there's nothing after,
 | 
			
		||||
// but it does mean we need to reload the dir
 | 
			
		||||
// after every task called. This might be fine,
 | 
			
		||||
// since the task might have modified the directory.
 | 
			
		||||
extern char _USERMODE;
 | 
			
		||||
DIRENT *const DirEntries = (DIRENT*)&_USERMODE;
 | 
			
		||||
#define MAXDISPFILES 16
 | 
			
		||||
void PrintFileList(uint16_t *vga) {
 | 
			
		||||
    uint16_t *vga_text = &((uint16_t *)vga)[80*6+3];
 | 
			
		||||
    for (int i = 0; (i + fileOffset) < fileCount && i < MAXDISPFILES; i++) {
 | 
			
		||||
        DIRENT *de = &entries[i + fileOffset];
 | 
			
		||||
        DIRENT *de = &DirEntries[i + fileOffset];
 | 
			
		||||
        for (int i = 0; i < 11 && de->name[i]; i++) {
 | 
			
		||||
            if (i == 8) { *(uint8_t*)vga_text = ' '; vga_text++; } // space for 8.3
 | 
			
		||||
            *(uint8_t *)vga_text = de->name[i];
 | 
			
		||||
@@ -323,7 +308,7 @@ void FileSelect() {
 | 
			
		||||
            OpenVol(&vi);
 | 
			
		||||
            current_path[current_path_end] = 0;
 | 
			
		||||
            OpenDir(current_path, &vi, &di);
 | 
			
		||||
            GetFileList(entries, &fileCount, INT32_MAX, &vi, &di);
 | 
			
		||||
            GetFileList(DirEntries, &fileCount, INT32_MAX, &vi, &di);
 | 
			
		||||
            reload = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (fileHovered >= fileCount) {
 | 
			
		||||
@@ -365,23 +350,22 @@ void FileSelect() {
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_P:
 | 
			
		||||
                if (IsDir(&entries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                if (IsDir(&DirEntries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                create_child(GetFreeStack(), (uintptr_t)ProgramLoadTest, 2, current_path, &vi);
 | 
			
		||||
                RestoreVGA();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_X:
 | 
			
		||||
                if (IsDir(&entries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                ClearProgBss();
 | 
			
		||||
                if (IsDir(&DirEntries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                create_child(GetFreeStack(), (uintptr_t)HexEditor, 2, current_path, &vi);
 | 
			
		||||
                RestoreVGA();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_T:
 | 
			
		||||
                if (IsDir(&entries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                if (IsDir(&DirEntries[fileHovered])) break;
 | 
			
		||||
                File83ToPath((char*)DirEntries[fileHovered].name, (char*)¤t_path[current_path_end]);
 | 
			
		||||
                //TextViewTest(path, &vi);
 | 
			
		||||
                create_child(GetFreeStack(), (uintptr_t)TextViewTest, 2, current_path, &vi);
 | 
			
		||||
                RestoreVGA();
 | 
			
		||||
@@ -389,9 +373,9 @@ void FileSelect() {
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_O:
 | 
			
		||||
            case 0x9C: // enter release
 | 
			
		||||
                if (IsDir(&entries[fileHovered])) {
 | 
			
		||||
                if (IsDir(&DirEntries[fileHovered])) {
 | 
			
		||||
                    uint8_t tmp_path[80];
 | 
			
		||||
                    File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path);
 | 
			
		||||
                    File83ToPath((char*)DirEntries[fileHovered].name, (char*)tmp_path);
 | 
			
		||||
                    if ((*(uint32_t*)tmp_path & 0xffff) == ('.' | 0x0000)) {
 | 
			
		||||
                        // Current dir, do nothing
 | 
			
		||||
                        break;
 | 
			
		||||
@@ -425,6 +409,45 @@ void FileSelect() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemRun() {
 | 
			
		||||
    uint16_t *vga_text = (word *)0xb8000;
 | 
			
		||||
    RestoreVGA();
 | 
			
		||||
    DrawScreen((uint16_t*)0xb8000);
 | 
			
		||||
 | 
			
		||||
    // Check for FAT partition
 | 
			
		||||
    {
 | 
			
		||||
        VOLINFO vi;
 | 
			
		||||
        // TODO Check partitions beyond 0
 | 
			
		||||
        while (OpenVol(&vi)) {
 | 
			
		||||
            vga_text = &((word*)0xb8000)[80*4 + 2];
 | 
			
		||||
            vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
 | 
			
		||||
            vga_text = &((word*)0xb8000)[80*5 + 2];
 | 
			
		||||
            vga_text += printStr("Press R to retry.", vga_text);
 | 
			
		||||
            for (;(get_scancode() & 0xff) != KEY_R;);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        create_child(GetFreeStack(), (uintptr_t)FileSelect, 0);
 | 
			
		||||
        // should never return, so if it does,
 | 
			
		||||
        // we have an error
 | 
			
		||||
        {
 | 
			
		||||
            union V86Regs_t regs;
 | 
			
		||||
            FARPTR v86_entry = i386LinearToFp(v86TextMode);
 | 
			
		||||
            enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
        }
 | 
			
		||||
        RestoreVGA();
 | 
			
		||||
        DrawScreen((uint16_t*)0xb8000);
 | 
			
		||||
        vga_text = &((word*)0xb8000)[80*4 + 2];
 | 
			
		||||
        vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
 | 
			
		||||
        vga_text = &((word*)0xb8000)[80*5 + 2];
 | 
			
		||||
        vga_text += printStr("Press R to retry.", vga_text);
 | 
			
		||||
        for (;(get_scancode() & 0xff) != KEY_R;);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((__noreturn__))
 | 
			
		||||
extern void triple_fault();
 | 
			
		||||
uint32_t kernel_check = 0x12345678;
 | 
			
		||||
void start() {
 | 
			
		||||
    word *vga_text = (word *)0xb8000;
 | 
			
		||||
@@ -471,46 +494,26 @@ void start() {
 | 
			
		||||
    //vga_text += printStr("Y ", vga_text);
 | 
			
		||||
    //enable_sse();
 | 
			
		||||
 | 
			
		||||
    setup_binary();
 | 
			
		||||
 | 
			
		||||
    // edit
 | 
			
		||||
    setup_interrupts();
 | 
			
		||||
    setup_tss();
 | 
			
		||||
    init_paging();
 | 
			
		||||
    //print_flags();
 | 
			
		||||
    vga_text += printStr("CR0:", vga_text);
 | 
			
		||||
    vga_text += printDword(get_cr0(), vga_text);
 | 
			
		||||
    vga_text++;
 | 
			
		||||
    //print_cr3();
 | 
			
		||||
    //print_cr4();
 | 
			
		||||
    backup_ivtbios();
 | 
			
		||||
 | 
			
		||||
    //vga_text = &((word *)0xb8000)[160];
 | 
			
		||||
    //vga_text += printStr("Press T for tests, or any key to continue... ", vga_text);
 | 
			
		||||
    //uint8_t key = get_key();
 | 
			
		||||
    //if (key == 't' || key == 'T')
 | 
			
		||||
    //    create_child(GetFreeStack(), (uintptr_t)RunTests, 0);
 | 
			
		||||
    RestoreVGA();
 | 
			
		||||
    DrawScreen((uint16_t*)0xb8000);
 | 
			
		||||
    uint32_t stack;
 | 
			
		||||
    asm volatile("mov %%esp,%%eax":"=a"(stack));
 | 
			
		||||
    stack = ((stack - 0x4000) / 0x1000) * 0x1000;
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        create_child(stack, (uintptr_t)FileSelect, 0);
 | 
			
		||||
        // should never return, so if it does,
 | 
			
		||||
        // we have an error
 | 
			
		||||
        {
 | 
			
		||||
            union V86Regs_t regs;
 | 
			
		||||
            FARPTR v86_entry = i386LinearToFp(v86TextMode);
 | 
			
		||||
            enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
        }
 | 
			
		||||
        RestoreVGA();
 | 
			
		||||
        DrawScreen((uint16_t*)0xb8000);
 | 
			
		||||
        vga_text = &((word*)0xb8000)[80*4 + 2];
 | 
			
		||||
        vga_text += printStr("Error loading file select. Ensure the disk has a valid MBR and FAT partition.", vga_text);
 | 
			
		||||
        vga_text = &((word*)0xb8000)[80*5 + 2];
 | 
			
		||||
        vga_text += printStr("Press R to retry.", vga_text);
 | 
			
		||||
        for (;(get_scancode() & 0xff) != KEY_R;);
 | 
			
		||||
    }
 | 
			
		||||
    // Setup system
 | 
			
		||||
    setup_binary();
 | 
			
		||||
    setup_interrupts();
 | 
			
		||||
    setup_tss();
 | 
			
		||||
    init_paging();
 | 
			
		||||
    backup_ivtbios();
 | 
			
		||||
    InitDisk();
 | 
			
		||||
 | 
			
		||||
    create_child(GetFreeStack(), (uintptr_t)SystemRun, 0);
 | 
			
		||||
    // If this returns, something is *very* wrong, reboot the system
 | 
			
		||||
    // TODO Maybe try to recover?
 | 
			
		||||
 | 
			
		||||
    // Triple fault
 | 
			
		||||
    triple_fault();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								link.ld
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								link.ld
									
									
									
									
									
								
							@@ -3,14 +3,15 @@ ENTRY(entry)
 | 
			
		||||
 | 
			
		||||
SECTIONS {
 | 
			
		||||
    . = 0x100000;
 | 
			
		||||
    _USERMODE = 0x400000;
 | 
			
		||||
 | 
			
		||||
    .text : {
 | 
			
		||||
        *(.text);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .data : {
 | 
			
		||||
        *(.data);
 | 
			
		||||
        *(.data*);
 | 
			
		||||
        *(.data);
 | 
			
		||||
        *(.rodata);
 | 
			
		||||
        *(.rodata*);
 | 
			
		||||
        _edata = .;
 | 
			
		||||
@@ -19,29 +20,30 @@ SECTIONS {
 | 
			
		||||
    .realmode 0x4000 :
 | 
			
		||||
        AT ( _edata )
 | 
			
		||||
        { _v86code = .; *(.v86); _ev86code = .; }
 | 
			
		||||
 | 
			
		||||
    . = _edata + SIZEOF(.realmode);
 | 
			
		||||
    .thing : { _loadusercode = .; }
 | 
			
		||||
 | 
			
		||||
    .usermode 0x400000 : AT(_loadusercode) {
 | 
			
		||||
        _usercode = .; *(.user); _eusercode = .;
 | 
			
		||||
    }
 | 
			
		||||
    .bss 0x400000 (NOLOAD) : AT(_loadusercode + SIZEOF(.usermode)) {
 | 
			
		||||
        _bprogstart = .;
 | 
			
		||||
        *(.progbss);
 | 
			
		||||
        *(.progbss*);
 | 
			
		||||
        _bprogend = .;
 | 
			
		||||
        *(.proglatebss);
 | 
			
		||||
        *(.proglatebss*);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    . = ADDR(.data) + SIZEOF(.data) + SIZEOF(.realmode) + SIZEOF(.usermode);
 | 
			
		||||
 | 
			
		||||
    .bss : ALIGN(0x1000)
 | 
			
		||||
    {
 | 
			
		||||
        _bstart = .; *(.bss); *(.bss*) _bend = .;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .bss _USERMODE (NOLOAD) : AT(_bend) {
 | 
			
		||||
        _bhexstart = .;
 | 
			
		||||
        *(.hexbss);
 | 
			
		||||
        *(.hexbss*);
 | 
			
		||||
        _bhexend = .;
 | 
			
		||||
        *(.hexlatebss);
 | 
			
		||||
        *(.hexlatebss*);
 | 
			
		||||
    }
 | 
			
		||||
    .bss _USERMODE (NOLOAD) : AT(_bend) {
 | 
			
		||||
        _btextstart = .;
 | 
			
		||||
        *(.textbss);
 | 
			
		||||
        *(.textbss*);
 | 
			
		||||
        _btextend = .;
 | 
			
		||||
        *(.textlatebss);
 | 
			
		||||
        *(.textlatebss*);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /DISCARD/ : {
 | 
			
		||||
        *(.note*)
 | 
			
		||||
        *(.comment*)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										184
									
								
								progs.c
									
									
									
									
									
								
							
							
						
						
									
										184
									
								
								progs.c
									
									
									
									
									
								
							@@ -1,193 +1,15 @@
 | 
			
		||||
#include "progs.h"
 | 
			
		||||
 | 
			
		||||
void TextViewTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    uint32_t fileLen;
 | 
			
		||||
    uint8_t *diskReadBuf = (uint8_t *)0x500000;
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err;
 | 
			
		||||
        uint8_t *scratch = (uint8_t *)0x20000;
 | 
			
		||||
        FILEINFO fi;
 | 
			
		||||
        err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            vga_text += printStr("Open Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // file too large
 | 
			
		||||
        if (fi.filelen > 0x300000) {
 | 
			
		||||
            vga_text += printStr("File too large.", vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        DFS_Seek(&fi, 0, scratch);
 | 
			
		||||
        if (fi.pointer != 0) {
 | 
			
		||||
            vga_text += printStr("Seek Error", vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        err = DFS_ReadFile(&fi, scratch, diskReadBuf, &fileLen, fi.filelen);
 | 
			
		||||
        if (err && err != DFS_EOF) {
 | 
			
		||||
            vga_text += printStr("Read Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t *lineOffsets = (uint32_t *)0x400000;
 | 
			
		||||
    uint32_t lastLine;
 | 
			
		||||
    {
 | 
			
		||||
        char nl;
 | 
			
		||||
        uint8_t c = 0x0A; // start with a pretend newline
 | 
			
		||||
        uint32_t line = -1; // start a pretend line behind
 | 
			
		||||
        for (int32_t o = -1; o < (int32_t)fileLen; c = diskReadBuf[++o]) {
 | 
			
		||||
            // newline
 | 
			
		||||
            if (c == 0x0A) {
 | 
			
		||||
                lineOffsets[++line] = o;
 | 
			
		||||
            }
 | 
			
		||||
            // file too large
 | 
			
		||||
            if ((uintptr_t)&lineOffsets[line] >= 0x4FFFFC) {
 | 
			
		||||
                vga_text += printStr("File too large.", vga_text);
 | 
			
		||||
                kbd_wait();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        lastLine = line;
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t currLine = 0;
 | 
			
		||||
    char cont = 1;
 | 
			
		||||
    uint32_t screenSize = 80*25;
 | 
			
		||||
    char redraw = 1;
 | 
			
		||||
    uint32_t linesOnScreen = 0;
 | 
			
		||||
    for (;cont;) {
 | 
			
		||||
        if (redraw) {
 | 
			
		||||
            vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
            for (int i = 0; i < screenSize; i++)
 | 
			
		||||
                vga_text[i] = 0x0f00;
 | 
			
		||||
            char pathBuff[22];
 | 
			
		||||
            trimPath((char*)path, pathBuff, sizeof(pathBuff));
 | 
			
		||||
            vga_text += printStr(pathBuff, vga_text);
 | 
			
		||||
            vga_text += 2;
 | 
			
		||||
            vga_text += printDec(currLine, vga_text);
 | 
			
		||||
            vga_text += printChar('/', vga_text);
 | 
			
		||||
            vga_text += printDec(lastLine, vga_text);
 | 
			
		||||
            vga_text += printStr(" Scroll: Up/Down PgUp/PgDown Home/End", vga_text);
 | 
			
		||||
            {
 | 
			
		||||
                const char prnt[] = "Exit: E";
 | 
			
		||||
                vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)+1];
 | 
			
		||||
                vga_text += printStr((char*)prnt, vga_text);
 | 
			
		||||
            }
 | 
			
		||||
            for (vga_text = &((uint16_t*)0xb8000)[84]; vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text += 80)
 | 
			
		||||
                *(uint8_t*)vga_text = '|';
 | 
			
		||||
            vga_text = &((uint16_t*)0xb8000)[0];
 | 
			
		||||
            uint32_t lineOff = 6;
 | 
			
		||||
            uint8_t c = 0x0A; // start with a pretend newline
 | 
			
		||||
            uint32_t line = currLine - 1; // start a pretend line behind
 | 
			
		||||
            int32_t o = lineOffsets[currLine]; // the real or fake newline on previous line
 | 
			
		||||
            linesOnScreen = screenSize/80;
 | 
			
		||||
            for (; o < (int32_t)fileLen && vga_text < &((uint16_t*)0xb8000)[screenSize]; c = diskReadBuf[++o]) {
 | 
			
		||||
                // newline
 | 
			
		||||
                if (c == 0x0A) {
 | 
			
		||||
                    vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
 | 
			
		||||
                    line++;
 | 
			
		||||
                    {
 | 
			
		||||
                        uint16_t *vga_tmp = vga_text;
 | 
			
		||||
                        uint16_t decTmp[11];
 | 
			
		||||
                        char cnt = printDec(line, decTmp);
 | 
			
		||||
                        char off = cnt <= 4 ? 0 : cnt - 4;
 | 
			
		||||
                        vga_tmp += 4 - (cnt - off);
 | 
			
		||||
                        for (int i = off; i < cnt; i++, vga_tmp++)
 | 
			
		||||
                            *(uint8_t*)vga_tmp = (uint8_t)decTmp[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    vga_text += 6;
 | 
			
		||||
                    lineOff = 6;
 | 
			
		||||
                    continue;
 | 
			
		||||
                } 
 | 
			
		||||
                *(uint8_t*)vga_text = c;
 | 
			
		||||
                vga_text++;
 | 
			
		||||
                lineOff++;
 | 
			
		||||
                if (lineOff == 80) { // last char
 | 
			
		||||
                    vga_text += 6;
 | 
			
		||||
                    lineOff = 6;
 | 
			
		||||
                    linesOnScreen--;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            redraw = 0;
 | 
			
		||||
        }
 | 
			
		||||
        uint16_t key = get_scancode();
 | 
			
		||||
        union V86Regs_t regs;
 | 
			
		||||
        FARPTR v86_entry;
 | 
			
		||||
        switch (key & 0xff) {
 | 
			
		||||
            case KEY_DOWN: // down
 | 
			
		||||
                if (currLine < lastLine && lineOffsets[currLine+1] < fileLen) {
 | 
			
		||||
                    currLine++;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_UP: // up
 | 
			
		||||
                if ((currLine > 0 && lineOffsets[currLine-1] < fileLen) || currLine == 1) {
 | 
			
		||||
                    currLine--;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_PGDOWN:
 | 
			
		||||
                if (currLine+(linesOnScreen/2) <= lastLine && lineOffsets[currLine+(linesOnScreen/2)] < fileLen) {
 | 
			
		||||
                    currLine += (linesOnScreen/2);
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                } else goto end;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_PGUP:
 | 
			
		||||
                if (currLine > (linesOnScreen/2) && lineOffsets[currLine-(linesOnScreen/2)] < fileLen) {
 | 
			
		||||
                    currLine -= (linesOnScreen/2);
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                } else if (currLine <= (linesOnScreen/2)) {
 | 
			
		||||
                    currLine = 0;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_HOME: home:
 | 
			
		||||
                if (currLine != 0) {
 | 
			
		||||
                    currLine = 0;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_END: end:
 | 
			
		||||
                if (currLine != lastLine) {
 | 
			
		||||
                    currLine = lastLine;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_E: // e
 | 
			
		||||
                cont = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F2:
 | 
			
		||||
                if (screenSize != 80*25) {
 | 
			
		||||
                    SetVideo25Lines();
 | 
			
		||||
                    SetCursorDisabled();
 | 
			
		||||
                    screenSize = 80*25;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F5:
 | 
			
		||||
                if (screenSize != 80*50) {
 | 
			
		||||
                    SetVideo50Lines();
 | 
			
		||||
                    SetCursorDisabled();
 | 
			
		||||
                    screenSize = 80*50;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// 400000 - 700000 Usermode Code (3mB)
 | 
			
		||||
// 700000 - 800000 Usermode Stack (1mB)
 | 
			
		||||
extern char _USERMODE;
 | 
			
		||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x0f00;
 | 
			
		||||
    uint32_t successcount;
 | 
			
		||||
    uint8_t *diskReadBuf = (uint8_t *)0x400000;
 | 
			
		||||
    uint8_t *diskReadBuf = (uint8_t *)&_USERMODE;
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err;
 | 
			
		||||
        uint8_t *scratch = (uint8_t *)0x20000;
 | 
			
		||||
@@ -227,7 +49,7 @@ void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
 | 
			
		||||
    vga_text += printStr("Press any key to run.", vga_text);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    uint32_t res = create_user_child(0x800000, 0x400000, 0);
 | 
			
		||||
    uint32_t res = create_user_child(0x800000, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
    regs.w.ax = 3; // text mode
 | 
			
		||||
    V8086Int(0x10, ®s); 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										167
									
								
								tests.c
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								tests.c
									
									
									
									
									
								
							@@ -13,18 +13,21 @@ void TestV86() {
 | 
			
		||||
    regs.d.eax = 0x66666666;
 | 
			
		||||
    FARPTR v86_entry = i386LinearToFp(v86Test);
 | 
			
		||||
    enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000 + (80*2);
 | 
			
		||||
    vga_text += printStr("Done.", vga_text);
 | 
			
		||||
}
 | 
			
		||||
extern char _loadusercode, _usercode, _eusercode;
 | 
			
		||||
extern char _USERMODE;
 | 
			
		||||
extern char _binary_usermode_bin_start, _binary_usermode_bin_end;
 | 
			
		||||
void ReloadUser() {
 | 
			
		||||
    // Put Usermode code in proper place based on linker
 | 
			
		||||
    char *s = &_loadusercode;
 | 
			
		||||
    char *d = &_usercode;
 | 
			
		||||
    while (d < &_eusercode)
 | 
			
		||||
    char *s = &_binary_usermode_bin_start;
 | 
			
		||||
    char *d = (char *)&_USERMODE;
 | 
			
		||||
    while (s < &_binary_usermode_bin_end)
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
}
 | 
			
		||||
char TestUser() {
 | 
			
		||||
    ReloadUser();
 | 
			
		||||
    char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)user_test, 0);
 | 
			
		||||
    char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)&_USERMODE, 0);
 | 
			
		||||
    if ((uintptr_t)vga != 0xA0000) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
@@ -34,24 +37,40 @@ char TestUser() {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
void TestDiskRead() {
 | 
			
		||||
    //vga_text += printStr("Starting Disk Read... ", vga_text);
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
    char *diskReadBuf = (char *)0x20000;
 | 
			
		||||
	v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
		(uintptr_t)diskReadBuf & 0x000F |
 | 
			
		||||
		(((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
 | 
			
		||||
    regs.h.ah = 0x42;
 | 
			
		||||
    FARPTR v86_entry = i386LinearToFp(v86DiskOp);
 | 
			
		||||
    enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < (80*25)/2; i++) {
 | 
			
		||||
        printByte(diskReadBuf[i], &vga_text[i*2]);
 | 
			
		||||
    v86disk_addr_packet.transfer_buffer =
 | 
			
		||||
        (uintptr_t)diskReadBuf & 0x000F |
 | 
			
		||||
        (((uintptr_t)diskReadBuf & 0xFFFF0) << 12);
 | 
			
		||||
    v86disk_addr_packet.start_block = 0;
 | 
			
		||||
    v86disk_addr_packet.blocks = 2;
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
    kbd_clear();
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        regs.h.ah = 0x42;
 | 
			
		||||
        FARPTR v86_entry = i386LinearToFp(v86DiskOp);
 | 
			
		||||
        enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s);
 | 
			
		||||
        uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
        for (int i = 0; i < 25; i++) {
 | 
			
		||||
            uint16_t *vga_line = &vga_text[i*80];
 | 
			
		||||
            for (int j = 0; j < 26; j++) {
 | 
			
		||||
                printByte(diskReadBuf[i*26 + j], &vga_line[j*2]);
 | 
			
		||||
                *(uint8_t*)&vga_line[j + (26*2)+1] = diskReadBuf[i*26 + j];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        uint16_t scan = get_scancode();
 | 
			
		||||
        if ((scan & 0xff) == KEY_PGUP) {
 | 
			
		||||
            if(v86disk_addr_packet.start_block > 0) v86disk_addr_packet.start_block--;
 | 
			
		||||
        } else if ((scan & 0xff) == KEY_PGDOWN)
 | 
			
		||||
            v86disk_addr_packet.start_block++;
 | 
			
		||||
        else if (scan & 0xff00) break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
extern uint32_t _gpf_eax_save;
 | 
			
		||||
extern uint32_t _gpf_eflags_save;
 | 
			
		||||
void TestCHS() {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t*)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x0f00;
 | 
			
		||||
    printStr("CHS Test ", vga_text);
 | 
			
		||||
    // CHS Read
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
@@ -175,55 +194,77 @@ void TestFAT() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunTests() {
 | 
			
		||||
    char doTests = 1;
 | 
			
		||||
    uint16_t *vga_text = (uint16_t*)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x1f00;
 | 
			
		||||
    uint8_t key;
 | 
			
		||||
    vga_text += printStr("V86 Test... ", vga_text);
 | 
			
		||||
    //asm ("xchgw %bx, %bx");
 | 
			
		||||
    TestV86(); // has int 3 wait in v86
 | 
			
		||||
    vga_text = (uint16_t *)0xb8000 + (80*3);
 | 
			
		||||
    vga_text += printStr("Done. Press 'N' for next test.", vga_text);
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        key = get_key();
 | 
			
		||||
        if (key == 'N' || key == 'n') break;
 | 
			
		||||
        *vga_text = (*vga_text & 0xFF00) | key;
 | 
			
		||||
        vga_text++;
 | 
			
		||||
    }
 | 
			
		||||
    char userResult = TestUser();
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
    regs.w.ax = 3; // text mode
 | 
			
		||||
    V8086Int(0x10, ®s); 
 | 
			
		||||
    vga_text = (uint16_t *)0xb8000 + (80*5);
 | 
			
		||||
    printStr("Press any key to continue.", vga_text);
 | 
			
		||||
    if (userResult) {
 | 
			
		||||
        // Usermode returned wrong value
 | 
			
		||||
        printStr("Usermode test failed! Press any key to continue.", vga_text);
 | 
			
		||||
    }
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    TestCHS();
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    TestDiskRead();
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    TestFAT();
 | 
			
		||||
    for (char l = 1;l;) {
 | 
			
		||||
        if (doTests) {
 | 
			
		||||
            vga_text = (uint16_t*)0xb8000;
 | 
			
		||||
            for (int i = 0; i < 80*25; i++)
 | 
			
		||||
                vga_text[i] = 0x1f00;
 | 
			
		||||
            vga_text += printStr("V86 Test... ", vga_text);
 | 
			
		||||
            //asm ("xchgw %bx, %bx");
 | 
			
		||||
            TestV86(); // has int 3 wait in v86
 | 
			
		||||
            vga_text = (uint16_t *)0xb8000 + (80*3);
 | 
			
		||||
            vga_text += printStr("Press 'N' for next test.", vga_text);
 | 
			
		||||
            for(;;) {
 | 
			
		||||
                key = get_key();
 | 
			
		||||
                if (key == 'N' || key == 'n') break;
 | 
			
		||||
                *vga_text = (*vga_text & 0xFF00) | key;
 | 
			
		||||
                vga_text++;
 | 
			
		||||
            }
 | 
			
		||||
            if (TestUser()) {
 | 
			
		||||
                union V86Regs_t regs;
 | 
			
		||||
                regs.w.ax = 3; // text mode
 | 
			
		||||
                V8086Int(0x10, ®s); 
 | 
			
		||||
                vga_text = (uint16_t *)0xb8000 + (80*5);
 | 
			
		||||
                printStr("Usermode test failed! Press any key to continue.", vga_text);
 | 
			
		||||
                kbd_wait();
 | 
			
		||||
            } else {
 | 
			
		||||
                kbd_wait();
 | 
			
		||||
                union V86Regs_t regs;
 | 
			
		||||
                regs.w.ax = 3; // text mode
 | 
			
		||||
                V8086Int(0x10, ®s); 
 | 
			
		||||
            }
 | 
			
		||||
            doTests = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    vga_text = &((uint16_t*)0xB8000)[80*16];
 | 
			
		||||
    vga_text += printStr("Press E for a flagrant system error. Press C to continue... ", vga_text);
 | 
			
		||||
    for (char l = 1;l;) { switch (key = get_key()) {
 | 
			
		||||
        case 'e':
 | 
			
		||||
        case 'E':
 | 
			
		||||
            // flagrant system error
 | 
			
		||||
            *((uint8_t*)0x1000000) = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'c':
 | 
			
		||||
        case 'C':
 | 
			
		||||
            // continue
 | 
			
		||||
            l = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            *vga_text = (*vga_text & 0xFF00) | key;
 | 
			
		||||
            vga_text++;
 | 
			
		||||
            break;
 | 
			
		||||
    }}
 | 
			
		||||
        vga_text = &((uint16_t*)0xB8000)[80*14];
 | 
			
		||||
        vga_text += printStr("Press E for a flagrant system error.  ", vga_text);
 | 
			
		||||
        vga_text = &((uint16_t*)0xB8000)[80*15];
 | 
			
		||||
        vga_text += printStr("Press D for disk tests.               ", vga_text);
 | 
			
		||||
        vga_text = &((uint16_t*)0xB8000)[80*16];
 | 
			
		||||
        vga_text += printStr("Press R to repeat tests.              ", vga_text);
 | 
			
		||||
        vga_text = &((uint16_t*)0xB8000)[80*17];
 | 
			
		||||
        vga_text += printStr("Press C to continue...                ", vga_text);
 | 
			
		||||
        switch (key = get_key()) {
 | 
			
		||||
            case 'e':
 | 
			
		||||
            case 'E':
 | 
			
		||||
                // flagrant system error
 | 
			
		||||
                *((uint8_t*)0x1000000) = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'c':
 | 
			
		||||
            case 'C':
 | 
			
		||||
                // continue
 | 
			
		||||
                l = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case 'd':
 | 
			
		||||
            case 'D':
 | 
			
		||||
                // disk tests
 | 
			
		||||
                TestCHS();
 | 
			
		||||
                kbd_wait();
 | 
			
		||||
                TestDiskRead();
 | 
			
		||||
                TestFAT();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'r':
 | 
			
		||||
            case 'R':
 | 
			
		||||
                doTests = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                *vga_text = (*vga_text & 0xFF00) | key;
 | 
			
		||||
                vga_text++;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										238
									
								
								textedit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								textedit.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,238 @@
 | 
			
		||||
#include "progs.h"
 | 
			
		||||
 | 
			
		||||
#define MAXFILESIZE 0x300000 // 3MB
 | 
			
		||||
#define MAXLINES 100000
 | 
			
		||||
#define BLOCKSIZE 0x1000
 | 
			
		||||
#define BLOCKMASK 0xfff
 | 
			
		||||
#define BLOCKSHIFT 12
 | 
			
		||||
#define TOTALBLOCKS (MAXFILESIZE/BLOCKSIZE)
 | 
			
		||||
uintptr_t lineOffsets[MAXLINES] __attribute__((section(".textbss")));;
 | 
			
		||||
uintptr_t lineLengths[MAXLINES] __attribute__((section(".textbss")));;
 | 
			
		||||
uint8_t editedBlocks[TOTALBLOCKS] __attribute__((section(".textbss")));;
 | 
			
		||||
uint8_t fileBuffer[MAXFILESIZE]
 | 
			
		||||
    __attribute__((aligned(0x1000)))
 | 
			
		||||
    __attribute__((section(".textlatebss")));
 | 
			
		||||
void TextViewTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    uint32_t fileLen;
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err;
 | 
			
		||||
        uint8_t *scratch = (uint8_t *)0x20000;
 | 
			
		||||
        FILEINFO fi;
 | 
			
		||||
        err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            vga_text += printStr("Open Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // file too large
 | 
			
		||||
        if (fi.filelen > MAXFILESIZE) {
 | 
			
		||||
            vga_text += printStr("File too large.", vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        DFS_Seek(&fi, 0, scratch);
 | 
			
		||||
        if (fi.pointer != 0) {
 | 
			
		||||
            vga_text += printStr("Seek Error", vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        err = DFS_ReadFile(&fi, scratch, fileBuffer, &fileLen, fi.filelen);
 | 
			
		||||
        if (err && err != DFS_EOF) {
 | 
			
		||||
            vga_text += printStr("Read Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t lastLine;
 | 
			
		||||
    {
 | 
			
		||||
        char nl;
 | 
			
		||||
        uint8_t c = 0x0A; // start with a pretend newline
 | 
			
		||||
        uint32_t line = -1; // start a pretend line behind
 | 
			
		||||
        uint32_t lineLen = 0;
 | 
			
		||||
        for (int32_t o = -1; o < (int32_t)fileLen; lineLen++, c = fileBuffer[++o]) {
 | 
			
		||||
            // newline
 | 
			
		||||
            if (c == 0x0A) {
 | 
			
		||||
                lineOffsets[++line] = o;
 | 
			
		||||
                lineLengths[line] = lineLen > 0 ? lineLen : 1;
 | 
			
		||||
                lineLen = 0;
 | 
			
		||||
            }
 | 
			
		||||
            // file too large
 | 
			
		||||
            if (line >= MAXLINES) {
 | 
			
		||||
                vga_text += printStr("File too large.", vga_text);
 | 
			
		||||
                kbd_wait();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        lineLengths[line] = lineLen;
 | 
			
		||||
        lastLine = line;
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t currLine = 0;
 | 
			
		||||
    char cont = 1;
 | 
			
		||||
    uint32_t screenSize = 80*25;
 | 
			
		||||
    char redraw = 1;
 | 
			
		||||
    uint32_t linesOnScreen = 0;
 | 
			
		||||
    uint32_t cursorLine = 0;
 | 
			
		||||
    uint32_t cursorLineOffset = 0;
 | 
			
		||||
    char cursorChange = 0;
 | 
			
		||||
    for (;cont;) {
 | 
			
		||||
        if (cursorLine > lastLine) {
 | 
			
		||||
            cursorLine = lastLine;
 | 
			
		||||
            cursorLineOffset = lineLengths[lastLine] - 2;
 | 
			
		||||
            cursorChange = 1;
 | 
			
		||||
        }
 | 
			
		||||
        if (lineLengths[cursorLine+1] == 1 && cursorLineOffset == 0){}
 | 
			
		||||
        else if (cursorLineOffset >= lineLengths[cursorLine+1] - 1) {
 | 
			
		||||
            cursorLineOffset = 0;
 | 
			
		||||
            cursorLine++;
 | 
			
		||||
            cursorChange = 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (redraw || cursorChange) {
 | 
			
		||||
            vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
            for (int i = 0; i < screenSize; i++)
 | 
			
		||||
                vga_text[i] = 0x0f00;
 | 
			
		||||
            char pathBuff[22];
 | 
			
		||||
            trimPath((char*)path, pathBuff, sizeof(pathBuff));
 | 
			
		||||
            vga_text += printStr(pathBuff, vga_text);
 | 
			
		||||
            vga_text += 2;
 | 
			
		||||
            vga_text += printDec(currLine, vga_text);
 | 
			
		||||
            vga_text += printChar('/', vga_text);
 | 
			
		||||
            vga_text += printDec(lastLine, vga_text);
 | 
			
		||||
            vga_text += printStr(" Scroll: Up/Down PgUp/PgDown Home/End", vga_text);
 | 
			
		||||
            {
 | 
			
		||||
                const char prnt[] = "Exit: F1";
 | 
			
		||||
                vga_text = &((uint16_t*)0xb8000)[80-sizeof(prnt)+1];
 | 
			
		||||
                vga_text += printStr((char*)prnt, vga_text);
 | 
			
		||||
            }
 | 
			
		||||
            for (vga_text = &((uint16_t*)0xb8000)[84]; vga_text < &((uint16_t*)0xb8000)[screenSize]; vga_text += 80)
 | 
			
		||||
                *(uint8_t*)vga_text = '|';
 | 
			
		||||
            vga_text = &((uint16_t*)0xb8000)[0];
 | 
			
		||||
            uint32_t screenLineOff = 6;
 | 
			
		||||
            uint32_t lineOffset = 0;
 | 
			
		||||
            uint8_t c = 0x0A; // start with a pretend newline
 | 
			
		||||
            uint32_t line = currLine - 1; // start a pretend line behind
 | 
			
		||||
            int32_t o = lineOffsets[currLine]; // the real or fake newline on previous line
 | 
			
		||||
            linesOnScreen = screenSize/80;
 | 
			
		||||
            for (; o < (int32_t)fileLen && vga_text < &((uint16_t*)0xb8000)[screenSize]; c = fileBuffer[++o]) {
 | 
			
		||||
                // newline
 | 
			
		||||
                if (c == 0x0A) {
 | 
			
		||||
                    vga_text = nextLine(vga_text,(uint16_t*)0xb8000);
 | 
			
		||||
                    line++;
 | 
			
		||||
                    lineOffset = 0;
 | 
			
		||||
                    {
 | 
			
		||||
                        uint16_t *vga_tmp = vga_text;
 | 
			
		||||
                        uint16_t decTmp[11];
 | 
			
		||||
                        char cnt = printDec(line, decTmp);
 | 
			
		||||
                        char off = cnt <= 4 ? 0 : cnt - 4;
 | 
			
		||||
                        vga_tmp += 4 - (cnt - off);
 | 
			
		||||
                        for (int i = off; i < cnt; i++, vga_tmp++)
 | 
			
		||||
                            *(uint8_t*)vga_tmp = (uint8_t)decTmp[i];
 | 
			
		||||
                    }
 | 
			
		||||
                    vga_text += 6;
 | 
			
		||||
                    screenLineOff = 6;
 | 
			
		||||
                    if (cursorLine == line && cursorLineOffset == lineOffset) {
 | 
			
		||||
                        ((uint8_t*)vga_text)[1] = 0xf0;
 | 
			
		||||
                    }
 | 
			
		||||
                    continue;
 | 
			
		||||
                } 
 | 
			
		||||
                *(uint8_t*)vga_text = c;
 | 
			
		||||
                if (cursorLine == line && cursorLineOffset == lineOffset) {
 | 
			
		||||
                    ((uint8_t*)vga_text)[1] = 0xf0;
 | 
			
		||||
                }
 | 
			
		||||
                lineOffset++;
 | 
			
		||||
                vga_text++;
 | 
			
		||||
                screenLineOff++;
 | 
			
		||||
                if (screenLineOff == 80) { // last char
 | 
			
		||||
                    vga_text += 6;
 | 
			
		||||
                    screenLineOff = 6;
 | 
			
		||||
                    linesOnScreen--;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            redraw = 0;
 | 
			
		||||
        }
 | 
			
		||||
        uint16_t key = get_scancode();
 | 
			
		||||
        union V86Regs_t regs;
 | 
			
		||||
        FARPTR v86_entry;
 | 
			
		||||
        switch (key & 0xff) {
 | 
			
		||||
            /*case KEY_DOWN: // down
 | 
			
		||||
                if (currLine < lastLine && lineOffsets[currLine+1] < fileLen) {
 | 
			
		||||
                    currLine++;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_UP: // up
 | 
			
		||||
                if ((currLine > 0 && lineOffsets[currLine-1] < fileLen) || currLine == 1) {
 | 
			
		||||
                    currLine--;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;*/
 | 
			
		||||
            case KEY_DOWN:
 | 
			
		||||
                cursorLine++;
 | 
			
		||||
                cursorChange = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_UP:
 | 
			
		||||
                if (cursorLine > 0) cursorLine--;
 | 
			
		||||
                cursorChange = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_LEFT:
 | 
			
		||||
                if (cursorLineOffset > 0) cursorLineOffset--;
 | 
			
		||||
                cursorChange = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_RIGHT:
 | 
			
		||||
                cursorLineOffset++;
 | 
			
		||||
                cursorChange = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_PGDOWN:
 | 
			
		||||
                if (currLine+(linesOnScreen/2) <= lastLine && lineOffsets[currLine+(linesOnScreen/2)] < fileLen) {
 | 
			
		||||
                    currLine += (linesOnScreen/2);
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                } else goto end;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_PGUP:
 | 
			
		||||
                if (currLine > (linesOnScreen/2) && lineOffsets[currLine-(linesOnScreen/2)] < fileLen) {
 | 
			
		||||
                    currLine -= (linesOnScreen/2);
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                } else if (currLine <= (linesOnScreen/2)) {
 | 
			
		||||
                    currLine = 0;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_HOME: home:
 | 
			
		||||
                if (currLine != 0) {
 | 
			
		||||
                    currLine = 0;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_END: end:
 | 
			
		||||
                if (currLine != lastLine) {
 | 
			
		||||
                    currLine = lastLine;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F1:
 | 
			
		||||
                cont = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F2:
 | 
			
		||||
                if (screenSize != 80*25) {
 | 
			
		||||
                    SetVideo25Lines();
 | 
			
		||||
                    SetCursorDisabled();
 | 
			
		||||
                    screenSize = 80*25;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_F5:
 | 
			
		||||
                if (screenSize != 80*50) {
 | 
			
		||||
                    SetVideo50Lines();
 | 
			
		||||
                    SetCursorDisabled();
 | 
			
		||||
                    screenSize = 80*50;
 | 
			
		||||
                    redraw = 1;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
[SECTION .user]
 | 
			
		||||
[BITS 32]
 | 
			
		||||
[ORG 0x400000]
 | 
			
		||||
global user_test
 | 
			
		||||
user_test:
 | 
			
		||||
mov dword [0xb8000], 0x0f000f00 | 'U' | 's' << 16
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										192
									
								
								v86.nasm
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								v86.nasm
									
									
									
									
									
								
							@@ -4,7 +4,83 @@ global v86Interrupt
 | 
			
		||||
v86Interrupt:
 | 
			
		||||
int 0x00
 | 
			
		||||
int 0x30
 | 
			
		||||
jmp $
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
global v86TransFlag
 | 
			
		||||
v86TransFlag:
 | 
			
		||||
push cs
 | 
			
		||||
pop es
 | 
			
		||||
mov ax, 0x13
 | 
			
		||||
int 0x10
 | 
			
		||||
mov ax,0x1012
 | 
			
		||||
xor bx,bx
 | 
			
		||||
mov cx,5
 | 
			
		||||
mov dx,.c
 | 
			
		||||
int 0x10
 | 
			
		||||
push 0xa000
 | 
			
		||||
pop es
 | 
			
		||||
xor di,di
 | 
			
		||||
xor ax,ax
 | 
			
		||||
.loop:
 | 
			
		||||
mov cx, 12800
 | 
			
		||||
rep stosb
 | 
			
		||||
inc ax
 | 
			
		||||
cmp ax,5
 | 
			
		||||
jl .loop
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
.c: db `\0263>=*.\?\?\?=*.\0263>`
 | 
			
		||||
 | 
			
		||||
global v86VideoInt
 | 
			
		||||
v86VideoInt:
 | 
			
		||||
int 0x10
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
global v86DiskOp
 | 
			
		||||
v86DiskOp:
 | 
			
		||||
xor bx, bx ; TODO fix assuming we're in first 64k
 | 
			
		||||
mov ds, bx
 | 
			
		||||
mov dl, 0x80 ; TODO get this from BIOS or something
 | 
			
		||||
mov si, v86disk_addr_packet ; ds:si
 | 
			
		||||
int 0x13
 | 
			
		||||
jc .err
 | 
			
		||||
int 0x30
 | 
			
		||||
.err:
 | 
			
		||||
ud2
 | 
			
		||||
global v86disk_addr_packet
 | 
			
		||||
v86disk_addr_packet:
 | 
			
		||||
db 0x10, 0x00 ; size, reserved
 | 
			
		||||
dw 0x1 ; blocks
 | 
			
		||||
dd 0x23000000 ; transfer buffer 0x23000
 | 
			
		||||
dq 0x1 ; start block
 | 
			
		||||
 | 
			
		||||
global v86DiskGetGeometry
 | 
			
		||||
v86DiskGetGeometry:
 | 
			
		||||
mov ah, 8
 | 
			
		||||
mov dl, 0x80
 | 
			
		||||
int 0x13
 | 
			
		||||
movzx eax, ch
 | 
			
		||||
shl eax, 16
 | 
			
		||||
mov al, cl
 | 
			
		||||
mov ah, dh
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
global v86DiskReadCHS
 | 
			
		||||
v86DiskReadCHS:
 | 
			
		||||
push 0x2000
 | 
			
		||||
pop es
 | 
			
		||||
int 0x13
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
global v86TextMode
 | 
			
		||||
v86TextMode:
 | 
			
		||||
mov ax, 0x3
 | 
			
		||||
int 0x10
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
real_hexprint:
 | 
			
		||||
xor cx, cx
 | 
			
		||||
@@ -36,94 +112,48 @@ ret
 | 
			
		||||
 | 
			
		||||
global v86Test
 | 
			
		||||
v86Test:
 | 
			
		||||
mov ax, 0xb814
 | 
			
		||||
mov ax, (0xB8000 + (80*2)) >> 4
 | 
			
		||||
mov es, ax
 | 
			
		||||
mov di, 20
 | 
			
		||||
mov di, 0
 | 
			
		||||
mov word es:[di+0], 0x1f00 | 'S'
 | 
			
		||||
mov word es:[di+2], 0x1f00 | 'S'
 | 
			
		||||
mov word es:[di+4], 0x1f00 | ':'
 | 
			
		||||
add di, 6
 | 
			
		||||
mov ax, ss
 | 
			
		||||
call real_printword
 | 
			
		||||
add di, 2
 | 
			
		||||
mov word es:[di+0], 0x1f00 | 'S'
 | 
			
		||||
mov word es:[di+2], 0x1f00 | 'P'
 | 
			
		||||
mov word es:[di+4], 0x1f00 | ':'
 | 
			
		||||
add di, 6
 | 
			
		||||
mov ax, sp
 | 
			
		||||
call real_printword
 | 
			
		||||
add di, 2
 | 
			
		||||
mov word es:[di+0], 0x1f00 | 'D'
 | 
			
		||||
mov word es:[di+2], 0x1f00 | 'S'
 | 
			
		||||
mov word es:[di+4], 0x1f00 | ':'
 | 
			
		||||
add di, 6
 | 
			
		||||
mov ax, ds
 | 
			
		||||
call real_printword
 | 
			
		||||
add di, 2
 | 
			
		||||
mov word es:[di+0], 0x1f00 | 'C'
 | 
			
		||||
mov word es:[di+2], 0x1f00 | 'S'
 | 
			
		||||
mov word es:[di+4], 0x1f00 | ':'
 | 
			
		||||
add di, 6
 | 
			
		||||
mov ax, cs
 | 
			
		||||
call real_printword
 | 
			
		||||
int 3
 | 
			
		||||
add di, 2
 | 
			
		||||
mov ax, cs
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov si, .testStr
 | 
			
		||||
mov ah, 0x1f
 | 
			
		||||
mov cx, .testStr_end - .testStr
 | 
			
		||||
.print:
 | 
			
		||||
lodsb
 | 
			
		||||
stosw
 | 
			
		||||
loop .print
 | 
			
		||||
int 3 ; wait for key
 | 
			
		||||
int 0x30 ; exit
 | 
			
		||||
jmp $
 | 
			
		||||
 | 
			
		||||
global v86TransFlag
 | 
			
		||||
v86TransFlag:
 | 
			
		||||
push cs
 | 
			
		||||
pop es
 | 
			
		||||
mov ax, 0x13
 | 
			
		||||
int 0x10
 | 
			
		||||
mov ax,0x1012
 | 
			
		||||
xor bx,bx
 | 
			
		||||
mov cx,5
 | 
			
		||||
mov dx,.c
 | 
			
		||||
int 0x10
 | 
			
		||||
push 0xa000
 | 
			
		||||
pop es
 | 
			
		||||
xor di,di
 | 
			
		||||
xor ax,ax
 | 
			
		||||
.loop:
 | 
			
		||||
mov cx, 12800
 | 
			
		||||
rep stosb
 | 
			
		||||
inc ax
 | 
			
		||||
cmp ax,5
 | 
			
		||||
jl .loop
 | 
			
		||||
int 0x30
 | 
			
		||||
jmp $
 | 
			
		||||
.c: db `\0263>=*.\?\?\?=*.\0263>`
 | 
			
		||||
 | 
			
		||||
global v86TextMode
 | 
			
		||||
v86TextMode:
 | 
			
		||||
mov ax, 0x3
 | 
			
		||||
int 0x10
 | 
			
		||||
int 0x30
 | 
			
		||||
jmp $
 | 
			
		||||
 | 
			
		||||
global v86VideoInt
 | 
			
		||||
v86VideoInt:
 | 
			
		||||
int 0x10
 | 
			
		||||
int 0x30
 | 
			
		||||
jmp $
 | 
			
		||||
 | 
			
		||||
global v86DiskOp
 | 
			
		||||
v86DiskOp:
 | 
			
		||||
xor bx, bx ; TODO fix assuming we're in first 64k
 | 
			
		||||
mov ds, bx
 | 
			
		||||
mov dl, 0x80 ; TODO get this from BIOS or something
 | 
			
		||||
mov si, v86disk_addr_packet ; ds:si
 | 
			
		||||
int 0x13
 | 
			
		||||
jc .err
 | 
			
		||||
int 0x30
 | 
			
		||||
.err:
 | 
			
		||||
ud2
 | 
			
		||||
jmp $
 | 
			
		||||
global v86disk_addr_packet
 | 
			
		||||
v86disk_addr_packet:
 | 
			
		||||
db 0x10, 0x00 ; size, reserved
 | 
			
		||||
dw 0x1 ; blocks
 | 
			
		||||
dd 0x23000000 ; transfer buffer 0x23000
 | 
			
		||||
dq 0x1 ; start block
 | 
			
		||||
 | 
			
		||||
global v86DiskGetGeometry
 | 
			
		||||
v86DiskGetGeometry:
 | 
			
		||||
mov ah, 8
 | 
			
		||||
mov dl, 0x80
 | 
			
		||||
int 0x13
 | 
			
		||||
movzx eax, ch
 | 
			
		||||
shl eax, 16
 | 
			
		||||
mov al, cl
 | 
			
		||||
mov ah, dh
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
 | 
			
		||||
global v86DiskReadCHS
 | 
			
		||||
v86DiskReadCHS:
 | 
			
		||||
push 0x2000
 | 
			
		||||
pop es
 | 
			
		||||
int 0x13
 | 
			
		||||
int 0x30
 | 
			
		||||
ud2
 | 
			
		||||
.testStr: db "PRESS ANY KEY"
 | 
			
		||||
.testStr_end:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user