summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/Kernel/Core/kmain.wtf.cpp8
-rw-r--r--Source/Kernel/DeviceManager/Disp.ns.cpp4
-rw-r--r--Source/Kernel/DeviceManager/Disp.ns.h1
-rw-r--r--Source/Kernel/Devices/Display/Display.proto.h1
-rw-r--r--Source/Kernel/Devices/Display/VESADisplay.class.cpp37
-rw-r--r--Source/Kernel/Devices/Display/VGATextOutput.class.cpp8
-rw-r--r--Source/Kernel/Devices/Display/vga-vesa.wtf.asm22
-rw-r--r--Source/Kernel/Makefile2
-rw-r--r--Source/Kernel/TaskManager/V86/V86.ns.cpp23
-rw-r--r--Source/Kernel/TaskManager/V86/V86.ns.h7
-rw-r--r--Source/Kernel/TaskManager/V86/V86Thread.class.cpp127
-rw-r--r--Source/Kernel/TaskManager/V86/V86Thread.class.h25
-rw-r--r--Source/Kernel/TaskManager/V86/v86.wtf.asm48
-rw-r--r--Source/Kernel/VTManager/SimpleVT.class.cpp6
14 files changed, 176 insertions, 143 deletions
diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp
index a59149b..28c65d1 100644
--- a/Source/Kernel/Core/kmain.wtf.cpp
+++ b/Source/Kernel/Core/kmain.wtf.cpp
@@ -173,9 +173,15 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
asm volatile("sti");
- selectVideoMode(*kvt);
+ selectVideoMode(*kvt); //////////////////////// SETUP VIDEO MODE
kvt->unmap();
+ for (int x = 0; x < 256; x++) {
+ for (int y = 0; y < 256; y++) {
+ Disp::mode.device->putPix(x, y, (x << 8) | y);
+ }
+ }
+
//Create a VT for handling the Melon bootup logo
SimpleVT *melonLogoVT = new SimpleVT(melonLogoLines, melonLogoCols, TXTLOGO_FGCOLOR, TXTLOGO_BGCOLOR);
melonLogoVT->map(1);
diff --git a/Source/Kernel/DeviceManager/Disp.ns.cpp b/Source/Kernel/DeviceManager/Disp.ns.cpp
index 246e959..2f1ebcd 100644
--- a/Source/Kernel/DeviceManager/Disp.ns.cpp
+++ b/Source/Kernel/DeviceManager/Disp.ns.cpp
@@ -24,6 +24,10 @@ void moveCursor(u16int line, u16int col) {
mode.device->moveCursor(line, col);
}
+bool textScroll(u16int line, u16int col, u16int height, u16int width, u8int color) {
+ return mode.device->textScroll(line, col, height, width, color);
+}
+
void clear() {
mode.device->clear();
}
diff --git a/Source/Kernel/DeviceManager/Disp.ns.h b/Source/Kernel/DeviceManager/Disp.ns.h
index 0d56cf0..2a10358 100644
--- a/Source/Kernel/DeviceManager/Disp.ns.h
+++ b/Source/Kernel/DeviceManager/Disp.ns.h
@@ -20,6 +20,7 @@ namespace Disp {
u16int textRows();
void putChar(u16int line, u16int col, WChar c, u8int color);
void moveCursor(u16int line, u16int col);
+ bool textScroll(u16int line, u16int col, u16int height, u16int width, u8int color);
void clear();
void getModes();
diff --git a/Source/Kernel/Devices/Display/Display.proto.h b/Source/Kernel/Devices/Display/Display.proto.h
index 8401e0b..26c3696 100644
--- a/Source/Kernel/Devices/Display/Display.proto.h
+++ b/Source/Kernel/Devices/Display/Display.proto.h
@@ -18,6 +18,7 @@ class Display : public Device {
//Text functions
virtual void putChar(u16int line, u16int col, WChar c, u8int color) = 0; //Color : <bg 4bits><fg 4bits>
virtual void moveCursor(u16int line, u16int col) = 0;
+ virtual bool textScroll(u16int line, u16int col, u16int height, u16int width, u8int color) { return false; }
//Graphic functions, can stay unimplemented for textual displays
virtual void putPix(u16int x, u16int y, u32int color) {}
diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp
index 4c3041a..ae64403 100644
--- a/Source/Kernel/Devices/Display/VESADisplay.class.cpp
+++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp
@@ -3,8 +3,6 @@
#include <MemoryManager/PhysMem.ns.h>
-extern v86_function_t vesa_int; //in vga-vesa.wtf.asm
-
using namespace Disp;
String VESADisplay::getClass() {
@@ -16,15 +14,16 @@ String VESADisplay::getName() {
}
vbe_controller_info_t VESADisplay::getCtrlrInfo() {
+ V86::map();
vbe_controller_info_t *info = (vbe_controller_info_t*)V86::alloc(sizeof(vbe_controller_info_t));
info->signature[0] = 'V'; info->signature[1] = 'B'; info->signature[2] = 'E'; info->signature[3] = '2';
info->videomodes = 0;
- registers_t regs;
- regs.eax = 0x00004F00;
- regs.esi = LIN_SEG(info);
- regs.edi = LIN_OFF(info);
- V86::run(vesa_int, regs, 0);
- if (regs.eax != 0x004F) PANIC("Something went wrong in detecting VBE modes.");
+ v86_regs_t regs;
+ regs.ax = 0x4F00;
+ regs.es = LIN_SEG(info);
+ regs.di = LIN_OFF(info);
+ V86::biosInt(0x10, regs);
+ if (regs.ax != 0x004F) PANIC("Something went wrong in detecting VBE modes.");
if (info->signature[3] != 'A') PANIC("No vesa sinature");
return *info;
}
@@ -33,12 +32,12 @@ vbe_mode_info_t VESADisplay::getModeInfo(u16int id) {
V86::map();
vbe_mode_info_t *mode = (vbe_mode_info_t*)V86::alloc(sizeof(vbe_mode_info_t));
CMem::memset((u8int*)mode, 0, sizeof(vbe_mode_info_t));
- registers_t regs;
- regs.eax = 0x00004F01;
- regs.ecx = id;
- regs.esi = LIN_SEG(mode);
- regs.edi = LIN_OFF(mode);
- V86::run(vesa_int, regs, 0);
+ v86_regs_t regs;
+ regs.ax = 0x00004F01;
+ regs.cx = id;
+ regs.es = LIN_SEG(mode);
+ regs.di = LIN_OFF(mode);
+ V86::biosInt(0x10, regs);
return *mode;
}
@@ -52,7 +51,7 @@ void VESADisplay::getModes(Vector<mode_t> &to) {
if ((mode.attributes & 0x90) != 0x90) continue;
if (mode.memory_model != 4 and mode.memory_model != 6) continue;
- if (mode.bpp != 24) continue;
+ //if (mode.bpp != 24) continue;
mode_t m; m.device = this;
m.textCols = mode.Xres / C_FONT_WIDTH; m.textRows = mode.Yres / C_FONT_HEIGHT;
m.identifier = modes[i];
@@ -64,10 +63,10 @@ void VESADisplay::getModes(Vector<mode_t> &to) {
bool VESADisplay::setMode(mode_t &mode) {
if (mode.device != this) return false;
m_currMode = getModeInfo(mode.identifier);
- registers_t regs;
- regs.eax = 0x00004F02;
- regs.ebx = mode.identifier | 0x4000;
- V86::run(vesa_int, regs, 0);
+ v86_regs_t regs;
+ regs.ax = 0x00004F02;
+ regs.bx = mode.identifier | 0x4000;
+ V86::biosInt(0x10, regs);
m_fb = (u8int*)0xF0000000;
for (u32int i = 0; i < (u32int)(m_currMode.Yres * m_currMode.pitch); i += 0x1000) {
diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
index d307f60..8c687ba 100644
--- a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
+++ b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp
@@ -3,8 +3,6 @@
#include <TaskManager/V86/V86.ns.h>
-extern v86_function_t setvgamode;
-
//Virtual address in higher half
#define RAM_ADDR 0xC00B8000
@@ -35,10 +33,10 @@ void VGATextOutput::getModes(Vector<mode_t> &to) {
bool VGATextOutput::setMode(mode_t& mode) {
if (mode.device == this && (mode.identifier == 3 or mode.identifier == 1)) {
- registers_t r;
- r.eax = mode.identifier;
+ v86_regs_t r;
+ r.ax = mode.identifier;
m_cols = mode.textCols;
- V86::run(setvgamode, r, 0);
+ V86::biosInt(0x10, r);
clear();
return true;
}
diff --git a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm b/Source/Kernel/Devices/Display/vga-vesa.wtf.asm
deleted file mode 100644
index 4a6a1d6..0000000
--- a/Source/Kernel/Devices/Display/vga-vesa.wtf.asm
+++ /dev/null
@@ -1,22 +0,0 @@
-[BITS 16]
-
-[GLOBAL setvgamode]
-setvgamode:
- dw setvgamode_end - setvgamode_start
-setvgamode_start:
- int 60
- int 10h
- int 3
-setvgamode_end:
- db 0
-
-[GLOBAL vesa_int]
-vesa_int:
- dw vesa_int_end - vesa_int_start
-vesa_int_start:
- int 60
- mov es, si
- int 10h
- int 3
-vesa_int_end:
- db 0
diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile
index 0126c43..82498b2 100644
--- a/Source/Kernel/Makefile
+++ b/Source/Kernel/Makefile
@@ -30,6 +30,7 @@ Objects = Core/loader.wtf.o \
TaskManager/Thread.class.o \
TaskManager/V86/V86Thread.class.o \
TaskManager/V86/V86.ns.o \
+ TaskManager/V86/v86.wtf.o \
TaskManager/Task.ns.o \
TaskManager/Task.wtf.o \
VTManager/VirtualTerminal.proto.o \
@@ -72,7 +73,6 @@ Objects = Core/loader.wtf.o \
Devices/Display/VGATextOutput.class.o \
Devices/Display/GraphicDisplay.proto.o \
Devices/Display/VESADisplay.class.o \
- Devices/Display/vga-vesa.wtf.o \
Devices/Keyboard/PS2Keyboard.class.o \
Devices/Floppy/FloppyController.class.o \
Devices/Floppy/FloppyDrive.class.o \
diff --git a/Source/Kernel/TaskManager/V86/V86.ns.cpp b/Source/Kernel/TaskManager/V86/V86.ns.cpp
index 93d51f2..f70728c 100644
--- a/Source/Kernel/TaskManager/V86/V86.ns.cpp
+++ b/Source/Kernel/TaskManager/V86/V86.ns.cpp
@@ -5,10 +5,17 @@ namespace V86 {
u16int seg = V86_ALLOC_START;
-void run(v86_function_t& entry, registers_t &regs, u32int data) {
+void run(v86_function_t& entry, v86_regs_t &regs) {
v86_retval_t ret;
ret.regs = &regs;
- new V86Thread(&entry, &ret, data);
+ new V86Thread(&entry, &ret);
+ while (!ret.finished) Task::currThread()->sleep(10);
+}
+
+void biosInt(u8int int_no, v86_regs_t &regs) {
+ v86_retval_t ret;
+ ret.regs = &regs;
+ new V86Thread(int_no, &ret);
while (!ret.finished) Task::currThread()->sleep(10);
}
@@ -19,8 +26,7 @@ void map(Process* p) {
}
}
-u16int allocSeg(u16int length, Process* p) {
- if (p == 0) p = Task::currProcess();
+u16int allocSeg(u16int length) {
if (length & 0xF) length = (length & 0xFFFF0) + 0x10;
u16int segments = length / 16;
if (seg < V86_ALLOC_START) seg = V86_ALLOC_START;
@@ -28,16 +34,11 @@ u16int allocSeg(u16int length, Process* p) {
u16int ret = seg;
seg += segments;
- void* ptr = FP_TO_LINEAR(ret, 0);
- for (u32int i = (u32int)ptr & 0xFFFFF000; i < (u32int)ptr + length; i += 0x1000) {
- p->getPagedir()->allocFrame(i, true, true);
- }
-
return ret;
}
-void* alloc(u16int length, Process* p) {
- return FP_TO_LINEAR(allocSeg(length, p), 0);
+void* alloc(u16int length) {
+ return FP_TO_LINEAR(allocSeg(length), 0);
}
}
diff --git a/Source/Kernel/TaskManager/V86/V86.ns.h b/Source/Kernel/TaskManager/V86/V86.ns.h
index 9fa132b..ec8e928 100644
--- a/Source/Kernel/TaskManager/V86/V86.ns.h
+++ b/Source/Kernel/TaskManager/V86/V86.ns.h
@@ -23,11 +23,12 @@ inline FARPTR LINEAR_TO_FP(void* ptr) {
#define V86_ALLOC_END 0x9000
namespace V86 {
- void run(v86_function_t& entry, registers_t &regs, u32int data);
+ void run(v86_function_t& entry, v86_regs_t &regs);
+ void biosInt(u8int int_no, v86_regs_t &regs);
void map(Process* p = 0); //Maps lower 1MB of virtual memory to physical memory (lower 1MB as well)
- u16int allocSeg(u16int size, Process* p = 0);
- void* alloc(u16int size, Process* p = 0);
+ u16int allocSeg(u16int size);
+ void* alloc(u16int size);
}
#endif
diff --git a/Source/Kernel/TaskManager/V86/V86Thread.class.cpp b/Source/Kernel/TaskManager/V86/V86Thread.class.cpp
index 26fca63..5002225 100644
--- a/Source/Kernel/TaskManager/V86/V86Thread.class.cpp
+++ b/Source/Kernel/TaskManager/V86/V86Thread.class.cpp
@@ -3,85 +3,75 @@
#include <TaskManager/V86/V86.ns.h>
-void V86Thread::runV86(V86Thread* thread, u32int data, u32int ss, u32int cs) {
- thread->m_process->getPagedir()->switchTo();
- //Setup values on user stack
- u32int *stack = (u32int*)(FP_TO_LINEAR(ss, V86_STACKSIZE));
- stack--; *stack = data;
-
- u32int sp = V86_STACKSIZE - 4;
-
- //Setup a false iret structure on the kernel stack, containing (first pushed first) :
- // - gs = cs
- // - fs = cs
- // - ds = cs
- // - es = cs
- // - stack segment = ss (temporarily in ecx)
- // - stack pointer = sp (temp in ebx)
- // - flags (OR'ed with EFLAGS.VM)
- // - code segment = cs (temp in eax)
- // - instruction pointer = ip (is 0)
- asm volatile(" \
- pushl %%eax; \
- pushl %%eax; \
- pushl %%eax; \
- pushl %%eax; \
- pushl %%ecx; \
- pushl %%ebx; \
- pushf; \
- pop %%ebx; \
- or $0x200, %%ebx; \
- or $0x20000, %%ebx; \
- push %%ebx; \
- pushl %%eax; \
- pushl $0; \
- iret; \
- " : : "a"(cs), "c"(ss), "b"(sp));
-}
+//in v86.wtf.asm
+extern "C" void v86_run(u32int pd_phys, //A page directory's physical address
+ v86_regs_t* regs);
/*
* Set up a V86 task :
* Allocate space for the kernel stack
- * Map frames in lower 1MB : IVT (first page), BDA (0xA0000 to 0xFFFFF)
+ * Map frames in lower 1MB
* Find somewhere to put the stack and the code, still in lower 1MB
- * Map that space, and copy the 16bit code to that place
+ * Copy the 16bit code to that place
* Setup values on the kernel stack for starting the thread (V86Thread::runV86),
* giving it entry point and stack location
*/
-V86Thread::V86Thread(v86_function_t* entry, v86_retval_t* ret, u32int data) : Thread() {
- m_ret = ret; m_ret->finished = false;
- m_xchgspace = 0;
- m_isKernel = true;
- m_if = true;
+V86Thread::V86Thread(v86_function_t* entry, v86_retval_t* ret) : Thread() {
+ m_ret = ret;
+ setup();
+ m_continueOnIret = true;
+
+ m_ret->regs->cs = V86::allocSeg(entry->size); //Alocate segments for the code to run in
+ u8int* codeptr = (u8int*)(FP_TO_LINEAR(m_ret->regs->cs, 0));
+ memcpy(codeptr, entry->data, entry->size); //Copy the code there
+
+ m_ret->regs->ip = 0;
+
+ m_state = T_RUNNING;
+ m_process->registerThread(this);
+ Task::registerThread(this);
+}
+
+V86Thread::V86Thread(u8int int_no, v86_retval_t* ret) : Thread() {
+ m_ret = ret;
+ setup();
+ m_continueOnIret = false;
+
+ //setup CS:IP for running interrupt
+ u16int* ivt = 0;
+
+ m_ret->regs->cs = ivt[int_no * 2 + 1];
+ m_ret->regs->ip = ivt[int_no * 2];
+
+ m_state = T_RUNNING;
+ m_process->registerThread(this);
+ Task::registerThread(this);
+}
+
+void V86Thread::setup() {
+ m_ret->finished = false; m_xchgspace = 0; m_isKernel = true;
m_process = Task::currProcess();
- m_kernelStack.addr = Mem::alloc(STACKSIZE);
- m_kernelStack.size = STACKSIZE;
+ m_if = true; //Set virtual interrupt flag
+ m_kernelStack.addr = Mem::alloc(STACKSIZE); m_kernelStack.size = STACKSIZE; //Setup kernel stack
m_process->getPagedir()->switchTo();
//Map all lower memory
V86::map();
- u16int cs = V86::allocSeg(entry->size); //Alocate segments for the code to run in
- u8int* codeptr = (u8int*)(FP_TO_LINEAR(cs, 0));
- memcpy(codeptr, entry->data, entry->size); //Copy the code there
-
- u16int ss = V86::allocSeg(V86_STACKSIZE);
+ //Allocate space for v86 stack
+ m_ret->regs->ss = V86::allocSeg(V86_STACKSIZE);
+ m_ret->regs->sp = V86_STACKSIZE - 4;
+ //Setup kernel stack for running v86_run (entry procedure)
u32int* stack = (u32int*)((u32int)m_kernelStack.addr + m_kernelStack.size);
- stack--; *stack = cs; //Pass code segment (ip = 0)
- stack--; *stack = ss; //Pass stack segment (sp = V86_STACKSIZE)
- stack--; *stack = data; //Pass data for thread
- stack--; *stack = (u32int)this; //Pass thread pointer
+ stack--; *stack = (u32int)m_ret->regs;
+ stack--; *stack = m_process->getPagedir()->physicalAddr;
stack--; *stack = 0;
m_esp = (u32int)stack;
- m_ebp = m_esp + 8;
- m_eip = (u32int)runV86;
-
- m_state = T_RUNNING;
- m_process->registerThread(this);
- Task::registerThread(this);
+ m_ebp = m_esp + 4;
+ m_eip = (u32int)v86_run;
}
bool V86Thread::handleV86GPF(registers_t *regs) {
@@ -135,16 +125,6 @@ bool V86Thread::handleV86GPF(registers_t *regs) {
return true;
case 0xCD: // INT N
if (ip[1] == 3) return false; //Breakpoint exception, here used for telling that thread has ended
- if (ip[1] == 60) { //INT 60 is used so that the real mode code can retrieve some regs from caller
- regs->eax = m_ret->regs->eax;
- regs->ebx = m_ret->regs->ebx;
- regs->ecx = m_ret->regs->ecx;
- regs->edx = m_ret->regs->edx;
- regs->edi = m_ret->regs->edi;
- regs->esi = m_ret->regs->esi;
- regs->eip = (u16int)(regs->eip + 2);
- return true;
- }
stack -= 3;
regs->useresp = ((regs->useresp & 0xFFFF) - 6) & 0xFFFF;
@@ -162,7 +142,7 @@ bool V86Thread::handleV86GPF(registers_t *regs) {
regs->eflags = EFLAGS_IF | EFLAGS_VM | stack[2];
m_if = (stack[2] & EFLAGS_IF) != 0;
regs->useresp = ((regs->useresp & 0xFFFF) + 6) & 0xFFFF;
- return false;
+ return m_continueOnIret;
case 0xFA: // CLI
m_if = false;
regs->eip = (u16int)(regs->eip + 1);
@@ -181,7 +161,12 @@ void V86Thread::handleException(registers_t *regs, int no) {
if (no == 13) { //General protection fault
if (!handleV86GPF(regs)) {
m_ret->finished = true;
- *(m_ret->regs) = *regs;
+ m_ret->regs->ax = (u16int)regs->eax;
+ m_ret->regs->bx = (u16int)regs->ebx;
+ m_ret->regs->cx = (u16int)regs->ecx;
+ m_ret->regs->dx = (u16int)regs->edx;
+ m_ret->regs->di = (u16int)regs->edi;
+ m_ret->regs->si = (u16int)regs->esi;
Task::currentThreadExits(0);
return;
}
diff --git a/Source/Kernel/TaskManager/V86/V86Thread.class.h b/Source/Kernel/TaskManager/V86/V86Thread.class.h
index 591bea6..7ca55b1 100644
--- a/Source/Kernel/TaskManager/V86/V86Thread.class.h
+++ b/Source/Kernel/TaskManager/V86/V86Thread.class.h
@@ -3,16 +3,22 @@
#include <TaskManager/Thread.class.h>
-struct v86_retval_t {
- registers_t *regs;
- bool finished;
-};
-
struct v86_function_t {
u16int size;
u8int data[];
};
+struct v86_regs_t {
+ u16int ax, bx, cx, dx, di, si;
+ u16int cs, ds, es, fs, gs, ss;
+ u16int ip, sp;
+} __attribute__((packed));
+
+struct v86_retval_t {
+ v86_regs_t *regs;
+ bool finished;
+};
+
#define V86_STACKSIZE 1024
#define EFLAGS_IF 0x200
@@ -26,12 +32,13 @@ class V86Thread : public Thread {
v86_retval_t* m_ret;
- bool m_if; //V86 IF flag
+ bool m_if, m_continueOnIret; //V86 IF flag
+
+ void setup();
- static void runV86(V86Thread* t, u32int data, u32int ss, u32int cs);
-
public:
- V86Thread(v86_function_t* entry, v86_retval_t* ret, u32int data);
+ V86Thread(v86_function_t* entry, v86_retval_t* ret);
+ V86Thread(u8int int_no, v86_retval_t* ret);
bool handleV86GPF(registers_t *regs);
void handleException(registers_t *regs, int no);
diff --git a/Source/Kernel/TaskManager/V86/v86.wtf.asm b/Source/Kernel/TaskManager/V86/v86.wtf.asm
new file mode 100644
index 0000000..09b08a2
--- /dev/null
+++ b/Source/Kernel/TaskManager/V86/v86.wtf.asm
@@ -0,0 +1,48 @@
+; This is the procedure that is first run when starting a V86 thread
+; Parameters : esp+4 = page directory to switch to, esp+8 = v86_regs_t pointer
+; Algorithm :
+; - Switch page directory
+; - Create a false IRET structure, with : (first pushed first)
+; GS, FS, DS, ES, SS, SP, EFLAGS (with eflags.if and eflags.vm), CS, IP
+; - Set general purpose regisers : ax bx cx dx di si
+; - Call iret, switch to V86 mode.
+
+[BITS 32]
+
+[GLOBAL v86_run]
+v86_run:
+ mov eax, [esp + 4]
+ mov cr3, eax
+ mov eax, [esp + 8]
+
+ xor ebx, ebx
+ mov bx, [eax + 20] ; get GS
+ push ebx
+ mov bx, [eax + 18] ; get FS
+ push ebx
+ mov bx, [eax + 14] ; get DS
+ push ebx
+ mov bx, [eax + 16] ; get ES
+ push ebx
+ mov bx, [eax + 22] ; get SS
+ push ebx
+ mov bx, [eax + 26] ; get SP
+ push ebx
+ pushf
+ pop ebx
+ or ebx, 20200h
+ push ebx
+ xor ebx, ebx
+ mov bx, [eax + 12] ; get CS
+ push ebx
+ mov bx, [eax + 24] ; get IP
+ push ebx
+
+ mov bx, [eax + 2]
+ mov cx, [eax + 4]
+ mov dx, [eax + 6]
+ mov di, [eax + 8]
+ mov si, [eax + 10]
+ mov ax, [eax]
+
+ iret
diff --git a/Source/Kernel/VTManager/SimpleVT.class.cpp b/Source/Kernel/VTManager/SimpleVT.class.cpp
index d304a5f..4a16b54 100644
--- a/Source/Kernel/VTManager/SimpleVT.class.cpp
+++ b/Source/Kernel/VTManager/SimpleVT.class.cpp
@@ -78,7 +78,11 @@ void SimpleVT::scroll() {
BUFCHR(m_rows - 1, c).c = ' ';
BUFCHR(m_rows - 1, c).color = m_color;
}
- if (m_mapped) redraw();
+ if (m_mapped) {
+ if (!Disp::textScroll(m_maprow, m_mapcol, m_rows, m_cols, m_color)) {
+ redraw();
+ }
+ }
}
void SimpleVT::updateCursor() {