Restored support for JSSortix using very ugly hacks. :(

This commit is contained in:
Jonas 'Sortie' Termansen 2011-09-08 11:10:41 +02:00
parent 3859e1f566
commit cc61176e5b
13 changed files with 135 additions and 104 deletions

View File

@ -19,11 +19,11 @@ ISOFILE:=builds/$(DEBNAME).iso
INITRDDIR:=initrd
INITRD=sortix/sortix.initrd
all: $(INITRD)
suball:
(for D in $(MODULES); do $(MAKE) all $(MFLAGS) --directory $$D || exit 1; done)
all: $(INITRD)
clean:
rm -f $(INITRD)
(for D in $(MODULES); do $(MAKE) clean $(MFLAGS) --directory $$D || exit 1; done)

View File

@ -31,6 +31,11 @@ char direction[buffersize];
uint16_t animal = '%' | (COLOR8_RED<<8);
uint16_t snake = ' ' | (COLOR8_GREEN<<12);
const int defaultspeed = 75;
const int speedincrease = -5;
const int maxspeed = 40;
volatile int speed;
// HACK: Sortix has no random number generator yet!
int random_seed=1337;
int rand(int max)
@ -43,7 +48,7 @@ int rand(int max)
void Clear()
{
// Reset the game data.
for ( int i = 0; i < buffersize; i++ ) { frame->text[i] = 0; direction[i] = -1; }
for ( int i = 0; i < buffersize; i++ ) { frame->text[i] = ' '; direction[i] = -1; }
}
void Reset()
@ -66,6 +71,8 @@ void Reset()
tailmax = 3;
frame->text[animaly * width + animalx] = animal;
speed = defaultspeed;
}
int Init()
@ -125,7 +132,7 @@ void Update()
// Move the tail, if needed.
if ( taillen == tailmax )
{
frame->text[taily * width + tailx] = 0; taillen--;
frame->text[taily * width + tailx] = ' '; taillen--;
switch ( direction[taily * width + tailx] )
{
case 0: tailx--; break;
@ -144,6 +151,7 @@ void Update()
tailmax++;
animalx = 2 + rand(width-4);
animaly = 2 + rand(height-4);
if ( maxspeed < speed ) { speed += speedincrease; }
}
frame->text[animaly * width + animalx] = animal;
@ -167,11 +175,10 @@ int main(int argc, char* argv[])
int result = Init();
if ( result != 0 ) { return result; }
// Update the game every 300th milisecond.
// Update the game every once in a while.
while ( true )
{
const int sleepms = 75;
Thread::USleep(sleepms * 1000);
Thread::USleep(speed * 1000);
Update();
}

1
sortix/.gitignore vendored
View File

@ -5,3 +5,4 @@
*.so
*.a
*.initrd
*.out

View File

@ -3,7 +3,8 @@ ifndef CPU
endif
ifeq ($(CPU),x86)
X86FAMILY=1
BUILDID=x86
X86FAMILY=1
CPUDEFINES=-DPLATFORM_X86
CPUFLAGS=-m32
CPULDFLAGS=-melf_i386
@ -13,7 +14,8 @@ ifeq ($(CPU),x86)
endif
ifeq ($(CPU),x64)
X86FAMILY=1
BUILDID=x64
X86FAMILY=1
CPUDEFINES=-DPLATFORM_X64
CPUFLAGS=-m64 -ffreestanding -mcmodel=large -mno-red-zone
CPULDFLAGS=-melf64-little -z max-page-size=0x1000
@ -34,13 +36,10 @@ endif
DIRS=. x64 x86 x86-family
DEFINES:=-DSORTIX_KERNEL $(CPUDEFINES)
DEFINES:=$(DEFINES) -DPLATFORM_VIRTUAL_MEMORY
DEFINES:=$(DEFINES) -DPLATFORM_KERNEL_HEAP
#DEFINES:=$(DEFINES) -DPLATFORM_SERIAL
#DEFINES:=$(DEFINES) -DPLATFORM_HTP
#DEFINES:=$(DEFINES) -DCONWAY
#DEFINES:=$(DEFINES) -DPONG
DEFINES:=$(DEFINES) -DINITRD
ifeq ($(JSSORTIX),1)
DEFINES:=$(DEFINES) -DPLATFORM_SERIAL -DJSSORTIX
BUILDID:=$(BUILDID)-js
endif
CPPFLAGSRELEASE=-s -O3
CPPFLAGSDEBUG=
CPPFLAGS=-I.. -I. $(CPUDEFINES) $(CPUFLAGS) -std=gnu++0x -Wall -Wextra -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector $(DEFINES) $(CPPFLAGSRELEASE)
@ -76,9 +75,9 @@ all: sortix.bin
jssortix: jssortix.bin
jssortix.bin: $(JSOBJS)
ld -melf_i386 -Ttext 100000 -o jssortix.out $(JSOBJS)
objcopy -O binary jssortix.out jssortix.bin
sortix-x86-js.tmp: $(OBJS)
ld -melf_i386 -Ttext 100000 -o sortix-x86-js-internal.out $(OBJS)
objcopy -O binary sortix-x86-js-internal.out $@
# x64 compilation
x64/boot.o: x64/boot.s
@ -101,7 +100,7 @@ sortix-x86.tmp: $(OBJS)
# general rules
sortix.bin: sortix-$(CPU).tmp
sortix.bin: sortix-$(BUILDID).tmp
cp -vu $< $@
%.o: %.cpp
@ -113,15 +112,6 @@ sortix.bin: sortix-$(CPU).tmp
%.o: %.asm
nasm $(CPUNASMFLAGS) $< -o $@
%-js.o: %.cpp
g++ -c $< -o $@ $(CPPFLAGS) -DJSSORTIX
%-js.o: %.s
as $(CPUASFLAGS) $< -o $@
%-js.o: %.asm
nasm $(CPUNASMFLAGS) $< -o $@
clean:
for D in $(DIRS); do rm -fv $$D/*.o $$D/*.bin $$D/*.out $$D/*.tmp; done

View File

@ -60,7 +60,7 @@ namespace Sortix
? exceptions[regs->int_no] : "Unknown";
// Halt and catch fire if we are the kernel.
if ( (regs->cs & (0x4-1)) == 0 )
if ( (regs->cs & (0x4-1)) == 0 || regs->int_no == 13 )
{
PanicF("Unhandled CPU Exception id %zu '%s' at eip=0x%zx "
"(cr2=0x%p, err_code=0x%p)", regs->int_no, message,

View File

@ -115,6 +115,7 @@ namespace Sortix
Log::Print(" / \\ / \\ \n");
Log::Print(" /_____________\\ /____________\\ \n");
Log::Print(" \n");
Log::Print(" BOOTING OPERATING SYSTEM... ");
}
void DoWelcome()
@ -124,22 +125,6 @@ namespace Sortix
#endif
DoMaxsiLogo();
#ifdef PLATFORM_SERIAL
#ifdef PONG
Log::Print(" = THE SORTIX KERNEL - PONG EDITION = ");
#elif defined(CONWAY)
Log::Print(" = THE SORTIX KERNEL - CONWAY'S GAME OF LIFE EDITION = ");
#else
Log::Print(" ");
#endif
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
Log::Print(" ");
#endif
}
extern "C" void KernelInit(unsigned long Magic, multiboot_info_t* BootInfo)
@ -197,7 +182,7 @@ namespace Sortix
uint8_t* initrd = NULL;
size_t initrdsize = 0;
#ifdef INITRD
#ifndef JSSORTIX
uint8_t** modules = (uint8_t**) BootInfo->mods_addr;
for ( uint32_t I = 0; I < BootInfo->mods_count; I++ )
{
@ -205,9 +190,13 @@ namespace Sortix
initrd = modules[2*I+0];
break;
}
#else
// TODO: UGLY HACK because JSVM doesn't support multiboot yet!
initrd = (uint8_t*) 0x180000UL;
initrdsize = 0x80000; // 512 KiB
#endif
if ( initrd == NULL ) { PanicF("No initrd provided"); }
#endif
// Initialize the GDT and TSS structures.
GDT::Init();
@ -217,16 +206,12 @@ namespace Sortix
if ( BootInfo == NULL ) { Panic("kernel.cpp: The bootinfo structure was NULL. Are your bootloader multiboot compliant?"); }
#ifdef PLATFORM_VIRTUAL_MEMORY
// Initialize virtual memory. TODO: This is not fully working yet.
VirtualMemory::Init();
#ifdef PLATFORM_KERNEL_HEAP
// Initialize the kernel heap.
Maxsi::Memory::Init();
#endif
#endif
// Initialize the keyboard.
Keyboard::Init();

View File

@ -42,6 +42,7 @@ namespace Sortix
void SetLEDs(uint8_t Toggle);
void OnIRQ1(CPU::InterruptRegisters* Regs);
void SysReceieveKeystroke(CPU::InterruptRegisters* R);
bool QueueKeystroke(uint32_t keystroke);
}
}

View File

@ -223,11 +223,9 @@ namespace Sortix
addr_t KernelStackPage = Page::Get();
if ( KernelStackPage == 0 ) { Panic("scheduler.cpp: could not allocate kernel interrupt stack for tss!"); }
#ifdef PLATFORM_VIRTUAL_MEMORY
uintptr_t MapTo = 0x80000000;
VirtualMemory::MapKernel(MapTo, (uintptr_t) KernelStackPage);
#endif
GDT::SetKernelStack((size_t*) (MapTo+4096));
}
@ -236,7 +234,6 @@ namespace Sortix
// simply awaits an IRQ0 and then we shall be scheduling.
void MainLoop()
{
Log::PrintF("Waiting for IRQ0\n");
// Simply wait for the next IRQ0 and then the OS will run.
while ( true ) { }
}
@ -253,43 +250,25 @@ namespace Sortix
// TODO: We only support stacks of up to one page!
if ( 4096 < StackSize ) { StackSize = 4096; }
#ifndef PLATFORM_KERNEL_HEAP
// TODO: Use the proper memory management systems using new and delete instead of these hacks!
// TODO: These allocations might NOT be thread safe!
void* ThreadPage = Page::Get();
if ( ThreadPage == NULL ) { return NULL; }
#endif
// Allocate a stack for this thread.
size_t StackLength = StackSize / sizeof(size_t);
addr_t PhysStack = Page::Get();
if ( PhysStack == 0 )
{
#ifndef PLATFORM_KERNEL_HEAP
Page::Put(ThreadPage);
#endif
return NULL;
}
// Create a new thread data structure.
Thread* thread = new
#ifndef PLATFORM_KERNEL_HEAP
(ThreadPage)
#endif
Thread(Process, AllocatedThreadId++, PhysStack, StackLength);
Thread* thread = new Thread(Process, AllocatedThreadId++, PhysStack, StackLength);
#ifdef PLATFORM_X86
#ifdef PLATFORM_VIRTUAL_MEMORY
uintptr_t StackPos = 0x80000000UL;
uintptr_t MapTo = StackPos - 4096UL;
addr_t OldAddrSpace = VirtualMemory::SwitchAddressSpace(Process->GetAddressSpace());
VirtualMemory::MapUser(MapTo, PhysStack);
#else
uintptr_t StackPos = (uintptr_t) PhysStack + 4096;
#endif
size_t* Stack = (size_t*) StackPos;
#ifdef PLATFORM_X86
@ -311,10 +290,8 @@ namespace Sortix
// Mark the thread as running, which adds it to the scheduler's linked list.
thread->SetState(Thread::State::RUNNABLE);
#ifdef PLATFORM_VIRTUAL_MEMORY
// Avoid side effects by restoring the old address space.
VirtualMemory::SwitchAddressSpace(OldAddrSpace);
#endif
return thread;
}
@ -390,7 +367,8 @@ namespace Sortix
#ifdef PLATFORM_X86
if ( currentThread != NoopThread )
// TODO: HACK: Find a more accurate way to test for kernel code.
if ( R->eip >= 0x400000UL )
{
uint32_t RPL = 0x3;
@ -460,11 +438,7 @@ namespace Sortix
// TODO: What do we do with the result parameter?
Thread->~Thread();
//Log::PrintF("<ExitedThread debug=\"2\" thread=\"%p\"/>\n", Thread);
#ifndef PLATFORM_KERNEL_HEAP
Page::Put((addr_t) Thread);
#else
delete Thread;
#endif
//Log::PrintF("<ExitedThread debug=\"3\" thread=\"%p\"/>\n", Thread);
if ( Thread == currentThread ) { currentThread = NULL; }

View File

@ -25,8 +25,10 @@
#include "platform.h"
#include <libmaxsi/string.h>
#include "log.h"
#include "vga.h"
#include "uart.h"
#include "serialterminal.h"
#include "vgaterminal.h"
namespace Sortix
{
@ -46,7 +48,12 @@ namespace Sortix
size_t Print(void* /*user*/, const char* string, size_t stringlen)
{
#ifdef JSSORTIX
VGATerminal::Print(NULL, string, stringlen);
UART::RenderVGA((VGA::Frame*) 0xB8000);
#else
UART::Write(string, stringlen);
#endif
return stringlen;
}
}

View File

@ -29,6 +29,13 @@
#include "scheduler.h"
#include "log.h"
#ifdef PLATFORM_SERIAL
#include <libmaxsi/keyboard.h>
#include "keyboard.h"
#include "vga.h"
#include "uart.h"
#endif
#if !defined(PLATFORM_X86_FAMILY)
#error No time subsystem is available for this CPU
#endif
@ -72,6 +79,8 @@ namespace Sortix
}
bool didUglyIRQ0Hack;
bool isEsc;
bool isEscDepress;
void Init()
{
@ -86,10 +95,47 @@ namespace Sortix
didUglyIRQ0Hack = false;
RequestIQR0();
isEsc = isEscDepress = false;
}
void OnIRQ0(CPU::InterruptRegisters* Regs)
{
#ifdef PLATFORM_SERIAL
// TODO: Yeah, this is a bad hack.
int c;
while ( (c=UART::TryPopChar()) != -1 )
{
using namespace Maxsi::Keyboard;
if ( !isEsc && c == '\e' ) { isEsc = true; continue; }
if ( isEsc && c == '\e' ) { isEsc = false; }
if ( isEsc && c == '[' ) { continue; }
if ( isEsc && c == ']' ) { isEscDepress = true; continue; }
if ( isEsc && !isEscDepress && c == 'A' ) { Keyboard::QueueKeystroke(UP); }
if ( isEsc && !isEscDepress && c == 'B' ) { Keyboard::QueueKeystroke(DOWN); }
if ( isEsc && !isEscDepress && c == 'C' ) { Keyboard::QueueKeystroke(RIGHT); }
if ( isEsc && !isEscDepress && c == 'D' ) { Keyboard::QueueKeystroke(LEFT); }
if ( isEsc && isEscDepress && c == 'A' ) { Keyboard::QueueKeystroke(UP | DEPRESSED); }
if ( isEsc && isEscDepress && c == 'B' ) { Keyboard::QueueKeystroke(DOWN | DEPRESSED); }
if ( isEsc && isEscDepress && c == 'C' ) { Keyboard::QueueKeystroke(RIGHT | DEPRESSED); }
if ( isEsc && isEscDepress && c == 'D' ) { Keyboard::QueueKeystroke(LEFT | DEPRESSED); }
if ( isEsc ) { isEsc = false; isEscDepress = false; continue; }
if ( c == '\e' ) { c = ESC; }
if ( c == ('\e' | (1<<7)) ) { c = ESC | DEPRESSED; }
if ( c == 3 ) { SigInt(); continue; }
if ( c == 127 ) { c = '\b'; }
if ( c & (1<<7) )
{
c &= ~(1<<7); c |= DEPRESSED;
}
Keyboard::QueueKeystroke(c);
}
// TODO: But this hack may be worse.
UART::RenderVGA((VGA::Frame*) 0xB8000);
#endif
Ticks++;
// Let the scheduler switch to the next task.

View File

@ -24,6 +24,7 @@
#include "platform.h"
#include <libmaxsi/string.h>
#include <libmaxsi/memory.h>
#ifdef PLATFORM_SERIAL
#include "vga.h"
#endif
@ -216,15 +217,11 @@ namespace Sortix
void RenderVGA(const VGA::Frame* Frame)
{
#if 0
// Set the cursor to (0,0)
const char InitMessage[] = { String::ASCII_ESCAPE, '[', 'H' };
UART::Write(InitMessage, sizeof(InitMessage));
const uint16_t* Source = Frame->Data;
nat LastColor = 1337;
nat SkippedSince = 0;
bool posundefined = true;
for ( nat Y = 0; Y < Frame->Height; Y++)
{
@ -237,33 +234,42 @@ namespace Sortix
if ( Element == OldElement ) { continue; }
VGALastFrame.Data[Index] = Element;
// Update the position if we skipped some characters.
if ( Index - SkippedSince > 8 )
if ( Index - SkippedSince > 8 || posundefined )
{
const nat LineId = Y + 1;
const nat ColumnId = X + 1;
if ( ColumnId > 1 )
{
const char Message[] = { String::ASCII_ESCAPE, '[', '0' + LineId / 10, '0' + LineId % 10, ';', '0' + ColumnId / 10, '0' + ColumnId % 10, 'H' };
UART::Write(Message, sizeof(Message));
UART::WriteChar('\e');
UART::WriteChar('[');
UART::WriteChar('0' + LineId / 10);
UART::WriteChar('0' + LineId % 10);
UART::WriteChar(';');
UART::WriteChar('0' + ColumnId / 10);
UART::WriteChar('0' + ColumnId % 10);
UART::WriteChar('H');
}
else
{
const char Message[] = { String::ASCII_ESCAPE, '[', '0' + LineId / 10, '0' + LineId % 10, 'H' };
UART::Write(Message, sizeof(Message));
UART::WriteChar('\e');
UART::WriteChar('[');
UART::WriteChar('0' + LineId / 10);
UART::WriteChar('0' + LineId % 10);
UART::WriteChar('H');
}
SkippedSince = Index;
posundefined = false;
}
for ( nat Pos = SkippedSince; Pos <= Index; Pos++ )
{
Element = Source[Pos];
OldElement = VGALastFrame.Data[Pos];
nat NewColor = ConversionTable[ (Element >> 12) & 0xF ] << 3 | ConversionTable[ (Element >> 8) & 0xF ];
nat NewColor = (ConversionTable[ (Element >> 12) & 0xF ] << 3) | (ConversionTable[ (Element >> 8) & 0xF ]);
// Change the color if we need to.
if ( LastColor != NewColor )
@ -272,26 +278,41 @@ namespace Sortix
nat OldBGColor = LastColor / 8;
nat FGColor = NewColor % 8;
nat BGColor = NewColor / 8;
if ( LastColor == 1337 ) { OldFGColor = 9; OldBGColor = 9; }
if ( (OldFGColor != FGColor) && (OldBGColor != BGColor) )
{
const char Message[] = { String::ASCII_ESCAPE, '[', '3', '0' + FGColor, ';', '4', '0' + BGColor, 'm' };
UART::Write(Message, sizeof(Message));
UART::WriteChar('\e');
UART::WriteChar('[');
UART::WriteChar('3');
UART::WriteChar('0' + FGColor);
UART::WriteChar(';');
UART::WriteChar('4');
UART::WriteChar('0' + BGColor);
UART::WriteChar('m');
}
else if ( OldFGColor != FGColor )
{
const char Message[] = { String::ASCII_ESCAPE, '[', '3', '0' + FGColor, 'm' };
UART::Write(Message, sizeof(Message));
UART::WriteChar('\e');
UART::WriteChar('[');
UART::WriteChar('3');
UART::WriteChar('0' + FGColor);
UART::WriteChar('m');
}
else if ( OldBGColor != BGColor )
{
const char Message[] = { String::ASCII_ESCAPE, '[', '4', '0' + BGColor, 'm' };
UART::Write(Message, sizeof(Message));
UART::WriteChar('\e');
UART::WriteChar('[');
UART::WriteChar('4');
UART::WriteChar('0' + BGColor);
UART::WriteChar('m');
}
LastColor = NewColor;
}
VGALastFrame.Data[Pos] = Element;
Element &= 0x7F;
// Filter away any non-printable characters.
@ -303,7 +324,6 @@ namespace Sortix
SkippedSince = Index + 1;
}
}
#endif
}
#endif
}

View File

@ -119,7 +119,7 @@ isr_common_stub:
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
;sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
; In isr.c
@ -155,7 +155,7 @@ irq_common_stub:
popa ; Pops edi,esi,ebp...
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
sti
;sti
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP

View File

@ -4,7 +4,7 @@
int main(int argc, char* argv[])
{
// Reset the terminal's color and the rest of it.
printf("\e[m\e[J");
printf("\r\e[m\e[J");
const char* programname = "sh";
const char* newargv[] = { programname };