Removed deprecated VGA API and moved it to /dev/vga.
This commit is contained in:
parent
c0fa3a6aae
commit
b6a0fd0374
|
@ -6,6 +6,11 @@
|
|||
#include <libmaxsi/sortix-vga.h>
|
||||
#include <libmaxsi/sortix-keyboard.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace Maxsi;
|
||||
using namespace Maxsi::Keyboard;
|
||||
|
@ -16,7 +21,8 @@ const int height = 25;
|
|||
const int rowstride = width + 2;
|
||||
const int buffersize = (height+2) * (width+2);
|
||||
|
||||
System::VGA::Frame* frame;
|
||||
int vgafd;
|
||||
uint16_t frame[width*height];
|
||||
|
||||
bool running;
|
||||
int posx;
|
||||
|
@ -33,17 +39,15 @@ void Clear()
|
|||
for ( int i = 0; i < buffersize; i++ ) { framea[i] = 0; frameb[i] = 0; }
|
||||
}
|
||||
|
||||
bool FlushVGA()
|
||||
{
|
||||
return writeall(vgafd, frame, sizeof(frame)) == 0;
|
||||
}
|
||||
|
||||
int Init()
|
||||
{
|
||||
// Create a VGA frame we can render onto.
|
||||
frame = System::VGA::CreateFrame();
|
||||
if ( frame == NULL )
|
||||
{
|
||||
Print("Could not create VGA frame\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
System::VGA::ChangeFrame(frame->fd);
|
||||
vgafd = open("/dev/vga", O_RDWR);
|
||||
if ( vgafd < 0 ) { printf("Unable to open vga device: %s", strerror(errno)); return 1; }
|
||||
|
||||
Clear();
|
||||
|
||||
|
@ -87,7 +91,7 @@ void Cycle()
|
|||
|
||||
void Render()
|
||||
{
|
||||
uint16_t* dest = frame->text;
|
||||
uint16_t* dest = frame;
|
||||
|
||||
uint16_t set = 'O' | (COLOR8_LIGHT_GREY << 8);
|
||||
uint16_t unset = ' ' | (COLOR8_LIGHT_GREY << 8);
|
||||
|
@ -106,6 +110,8 @@ void Render()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlushVGA();
|
||||
}
|
||||
|
||||
void Update()
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include <libmaxsi/sortix-sound.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace Maxsi;
|
||||
using namespace Maxsi::Keyboard;
|
||||
|
@ -29,7 +33,8 @@ const int padsize = 5;
|
|||
const unsigned goalfreq = 800;
|
||||
const unsigned collisionfreq = 1200;
|
||||
|
||||
System::VGA::Frame* frame;
|
||||
int vgafd;
|
||||
uint16_t frame[width*height];
|
||||
|
||||
int ballx;
|
||||
int bally;
|
||||
|
@ -48,16 +53,15 @@ unsigned p2score;
|
|||
unsigned time;
|
||||
unsigned soundleft;
|
||||
|
||||
bool FlushVGA()
|
||||
{
|
||||
return writeall(vgafd, frame, sizeof(frame)) == 0;
|
||||
}
|
||||
|
||||
int Init()
|
||||
{
|
||||
frame = System::VGA::CreateFrame();
|
||||
if ( frame == NULL )
|
||||
{
|
||||
Print("Could not create VGA frame\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
System::VGA::ChangeFrame(frame->fd);
|
||||
vgafd = open("/dev/vga", O_RDWR);
|
||||
if ( vgafd < 0 ) { printf("Unable to open vga device: %s", strerror(errno)); return 1; }
|
||||
|
||||
Reset();
|
||||
|
||||
|
@ -94,9 +98,11 @@ void ClearScreen()
|
|||
|
||||
for ( int x = 0; x < width; x++ )
|
||||
{
|
||||
frame->text[x + y*width] = ' ' | color;
|
||||
frame[x + y*width] = ' ' | color;
|
||||
}
|
||||
}
|
||||
|
||||
FlushVGA();
|
||||
}
|
||||
|
||||
void Collision()
|
||||
|
@ -107,7 +113,7 @@ void Collision()
|
|||
|
||||
void Goal(nat player)
|
||||
{
|
||||
frame->text[ballx + bally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
frame[ballx + bally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
|
||||
int offset = (rand() % 4) - 2;
|
||||
ballx = width/2;
|
||||
|
@ -137,16 +143,16 @@ void Goal(nat player)
|
|||
|
||||
void UpdateUI()
|
||||
{
|
||||
for ( int x = 0; x < width; x++ ) { frame->text[x] = ' ' | (COLOR8_LIGHT_GREY << 12) | (COLOR8_RED << 8); }
|
||||
for ( int x = 0; x < width; x++ ) { frame[x] = ' ' | (COLOR8_LIGHT_GREY << 12) | (COLOR8_RED << 8); }
|
||||
|
||||
char num[12];
|
||||
int len;
|
||||
|
||||
len = String::ConvertUInt32(p1score, num);
|
||||
for ( int i = 0; i < len; i++ ) { frame->text[i] = ( frame->text[i] & 0xFF00 ) | num[i]; }
|
||||
for ( int i = 0; i < len; i++ ) { frame[i] = ( frame[i] & 0xFF00 ) | num[i]; }
|
||||
|
||||
len = String::ConvertUInt32(p2score, num);
|
||||
for ( int i = 0; i < len; i++ ) { frame->text[width - len + i] = ( frame->text[width - len + i] & 0xFF00 ) | num[i]; }
|
||||
for ( int i = 0; i < len; i++ ) { frame[width - len + i] = ( frame[width - len + i] & 0xFF00 ) | num[i]; }
|
||||
}
|
||||
|
||||
void Update()
|
||||
|
@ -163,12 +169,12 @@ void Update()
|
|||
|
||||
for ( int y = 1; y < height; y++ )
|
||||
{
|
||||
uint16_t color = ( y < p1y || y >= p1y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_RED << 12; frame->text[y*width] = ' ' | color;
|
||||
uint16_t color = ( y < p1y || y >= p1y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_RED << 12; frame[y*width] = ' ' | color;
|
||||
}
|
||||
|
||||
for ( int y = 1; y < height; y++ )
|
||||
{
|
||||
uint16_t color = ( y < p2y || y >= p2y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_BLUE << 12; frame->text[width-1 + y*width] = ' ' | color;
|
||||
uint16_t color = ( y < p2y || y >= p2y + padsize ) ? COLOR8_BLACK << 12 : COLOR8_BLUE << 12; frame[width-1 + y*width] = ' ' | color;
|
||||
}
|
||||
|
||||
if ( bally + ballvely <= 1 ) { ballvely = 0 - ballvely; Collision(); }
|
||||
|
@ -177,14 +183,14 @@ void Update()
|
|||
if ( ballx + ballvelx < 1 ) { if ( bally + ballvely < p1y - 1 || bally + ballvely > p1y + padsize + 1 ) { Goal(2); } else { ballvelx = 0 - ballvelx; Collision(); } }
|
||||
if ( ballx + ballvelx >= width-1 ) { if ( bally + ballvely < p2y - 1 || bally + ballvely > p2y + padsize + 1 ) { Goal(1); } else { ballvelx = 0 - ballvelx; Collision(); } }
|
||||
|
||||
frame->text[oldballx + oldbally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
frame->text[ballx + bally*width] = '.' | (COLOR8_WHITE << 8);
|
||||
frame[oldballx + oldbally*width] = ' ' | (COLOR8_WHITE << 8);
|
||||
frame[ballx + bally*width] = '.' | (COLOR8_WHITE << 8);
|
||||
oldballx = ballx; oldbally = bally;
|
||||
|
||||
ballx += ballvelx;
|
||||
bally += ballvely;
|
||||
|
||||
frame->text[ballx + bally*width] = 'o' | (COLOR8_WHITE << 8);
|
||||
frame[ballx + bally*width] = 'o' | (COLOR8_WHITE << 8);
|
||||
}
|
||||
|
||||
void ReadInput()
|
||||
|
@ -236,6 +242,7 @@ int main(int argc, char* argv[])
|
|||
ReadInput();
|
||||
Update();
|
||||
UpdateUI();
|
||||
FlushVGA();
|
||||
Thread::USleep(sleepms * 1000);
|
||||
if ( soundleft < 0 ) { continue; }
|
||||
if ( soundleft <= 50 )
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
#include <libmaxsi/keyboard.h>
|
||||
#include <libmaxsi/sortix-vga.h>
|
||||
#include <libmaxsi/sortix-keyboard.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace Maxsi;
|
||||
using namespace Maxsi::Keyboard;
|
||||
|
@ -14,7 +19,8 @@ const int height = 25;
|
|||
|
||||
const int buffersize = height * width;
|
||||
|
||||
System::VGA::Frame* frame;
|
||||
int vgafd;
|
||||
uint16_t frame[width*height];
|
||||
|
||||
int posx;
|
||||
int posy;
|
||||
|
@ -40,7 +46,7 @@ volatile int speed;
|
|||
void Clear()
|
||||
{
|
||||
// Reset the game data.
|
||||
for ( int i = 0; i < buffersize; i++ ) { frame->text[i] = ' '; direction[i] = -1; }
|
||||
for ( int i = 0; i < buffersize; i++ ) { frame[i] = ' '; direction[i] = -1; }
|
||||
}
|
||||
|
||||
void Reset()
|
||||
|
@ -62,22 +68,20 @@ void Reset()
|
|||
taillen = 0;
|
||||
tailmax = 3;
|
||||
|
||||
frame->text[animaly * width + animalx] = animal;
|
||||
frame[animaly * width + animalx] = animal;
|
||||
|
||||
speed = defaultspeed;
|
||||
}
|
||||
|
||||
bool FlushVGA()
|
||||
{
|
||||
return writeall(vgafd, frame, sizeof(frame)) == 0;
|
||||
}
|
||||
|
||||
int Init()
|
||||
{
|
||||
// Create a VGA frame we can render onto.
|
||||
frame = System::VGA::CreateFrame();
|
||||
if ( frame == NULL )
|
||||
{
|
||||
Print("Could not create VGA frame\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
System::VGA::ChangeFrame(frame->fd);
|
||||
vgafd = open("/dev/vga", O_RDWR);
|
||||
if ( vgafd < 0 ) { printf("Unable to open vga device: %s", strerror(errno)); return 1; }
|
||||
|
||||
Reset();
|
||||
|
||||
|
@ -124,7 +128,7 @@ void Update()
|
|||
// Move the tail, if needed.
|
||||
if ( taillen == tailmax )
|
||||
{
|
||||
frame->text[taily * width + tailx] = ' '; taillen--;
|
||||
frame[taily * width + tailx] = ' '; taillen--;
|
||||
switch ( direction[taily * width + tailx] )
|
||||
{
|
||||
case 0: tailx--; break;
|
||||
|
@ -135,7 +139,7 @@ void Update()
|
|||
}
|
||||
|
||||
// Check for collision.
|
||||
if ( frame->text[newy * width + newx] == snake ) { Reset(); return; }
|
||||
if ( frame[newy * width + newx] == snake ) { Reset(); return; }
|
||||
|
||||
// Check for food.
|
||||
if ( newx == animalx && newy == animaly )
|
||||
|
@ -148,7 +152,7 @@ void Update()
|
|||
if ( maxspeed < speed ) { speed += speedincrease; }
|
||||
}
|
||||
|
||||
frame->text[animaly * width + animalx] = animal;
|
||||
frame[animaly * width + animalx] = animal;
|
||||
|
||||
// Remember where we are going.
|
||||
int dir = 0;
|
||||
|
@ -161,7 +165,7 @@ void Update()
|
|||
// Move the head.
|
||||
posx = newx;
|
||||
posy = newy;
|
||||
frame->text[posy * width + posx] = snake; taillen++;
|
||||
frame[posy * width + posx] = snake; taillen++;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
@ -174,6 +178,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
Thread::USleep(speed * 1000);
|
||||
Update();
|
||||
FlushVGA();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -50,7 +50,6 @@ c/h/signal.h \
|
|||
COMMONOBJS=c++.o memory.o string.o error.o format.o
|
||||
SORTIXOBJS:=$(addprefix sortix/,$(COMMONOBJS))
|
||||
LIBMAXSIOBJS:=$(COMMONOBJS) \
|
||||
sortix-vga.o \
|
||||
sortix-keyboard.o \
|
||||
sortix-sound.o \
|
||||
process.o \
|
||||
|
|
|
@ -47,47 +47,6 @@ namespace System
|
|||
#define COLOR8_LIGHT_MAGENTA 13
|
||||
#define COLOR8_LIGHT_BROWN 14
|
||||
#define COLOR8_WHITE 15
|
||||
|
||||
// This is the contents of a VGA framebuffer used in text mode. The
|
||||
// lower 8 lower bits correspond to an ASCII character, the next 4 bits
|
||||
// is the text color, and the upper 4 bits are the background color.
|
||||
struct Frame
|
||||
{
|
||||
public:
|
||||
// The width of each line in characters.
|
||||
const static size_t width = 80;
|
||||
|
||||
// The number of lines.
|
||||
const static size_t height = 25;
|
||||
|
||||
// The data containing the frame.
|
||||
uint16_t text[width * height];
|
||||
|
||||
// An opaque file descriptor that defines this frame. Used to change
|
||||
// the current frame or deleting frames.
|
||||
int fd;
|
||||
|
||||
// Beware: The kernel may or may keep more hidden data here. You may
|
||||
// not depend on the usage of this area.
|
||||
|
||||
private:
|
||||
// Only the kernel may create an instance of this structure.
|
||||
Frame() { }
|
||||
|
||||
};
|
||||
|
||||
// Allocates a framebuffer able to store VGA data. This buffer is not
|
||||
// relocatable and must remain at this position.
|
||||
Frame* CreateFrame();
|
||||
|
||||
// Sets the process' current VGA frame. If the process currently have
|
||||
// focus, then this is the frame shown on the screen. Any edits done
|
||||
// on this frame while it is active will be shown instantly on the
|
||||
// screen if the process have focus.
|
||||
int ChangeFrame(int fd);
|
||||
|
||||
// Deletes a frame. This is equivalent to IO::Close(fd).
|
||||
int DeleteFrame(int fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/******************************************************************************
|
||||
|
||||
COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
|
||||
|
||||
This file is part of LibMaxsi.
|
||||
|
||||
LibMaxsi is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
LibMaxsi is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with LibMaxsi. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix-vga.cpp
|
||||
Provides access to the VGA framebuffer under Sortix. This is highly
|
||||
unportable and is very likely to be removed or changed radically.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "platform.h"
|
||||
#include "syscall.h"
|
||||
#include "sortix-vga.h"
|
||||
|
||||
namespace System
|
||||
{
|
||||
namespace VGA
|
||||
{
|
||||
|
||||
DEFN_SYSCALL0(Frame*, SysCreateFrame, 5);
|
||||
DEFN_SYSCALL1(int, SysChangeFrame, 6, int);
|
||||
DEFN_SYSCALL1(int, SysDeleteFrame, 7, int);
|
||||
|
||||
Frame* CreateFrame()
|
||||
{
|
||||
return SysCreateFrame();
|
||||
}
|
||||
|
||||
int ChangeFrame(int fd)
|
||||
{
|
||||
return SysChangeFrame(fd);
|
||||
}
|
||||
|
||||
int DeleteFrame(int fd)
|
||||
{
|
||||
return SysDeleteFrame(fd);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
#include "../filesystem.h"
|
||||
#include "../directory.h"
|
||||
#include "../stream.h"
|
||||
#include "../vga.h"
|
||||
#include "devfs.h"
|
||||
|
||||
using namespace Maxsi;
|
||||
|
@ -170,8 +171,8 @@ namespace Sortix
|
|||
|
||||
int DevDevFSDir::Read(sortix_dirent* dirent, size_t available)
|
||||
{
|
||||
const char* names[] = { "null", "tty" };
|
||||
const size_t nameslength = 2;
|
||||
const char* names[] = { "null", "tty", "vga" };
|
||||
const size_t nameslength = 3;
|
||||
|
||||
if ( available <= sizeof(sortix_dirent) ) { return -1; }
|
||||
if ( nameslength <= position )
|
||||
|
@ -217,6 +218,7 @@ namespace Sortix
|
|||
|
||||
if ( String::Compare(path, "/null") == 0 ) { return new DevNull; }
|
||||
if ( String::Compare(path, "/tty") == 0 ) { return new DevLogTTY; }
|
||||
if ( String::Compare(path, "/vga") == 0 ) { return new DevVGA; }
|
||||
|
||||
Error::Set(flags & O_CREAT ? EPERM : ENOENT);
|
||||
return NULL;
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace Sortix
|
|||
// TODO: But this hack may be worse.
|
||||
if ( numvgaframes )
|
||||
{
|
||||
UART::RenderVGA((VGA::Frame*) 0xB8000);
|
||||
UART::RenderVGA((const uint16_t*) 0xB8000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ namespace Sortix
|
|||
{
|
||||
VGATerminal::Print(NULL, string, stringlen);
|
||||
#ifdef PLATFORM_SERIAL
|
||||
UART::RenderVGA((VGA::Frame*) 0xB8000);
|
||||
UART::RenderVGA((const uint16_t*) 0xB8000);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
|
@ -69,7 +69,9 @@ namespace Sortix
|
|||
const nat BOTH_EMPTY = LSR_TEMT | LSR_THRE;
|
||||
|
||||
#ifdef SORTIX_VGA_H
|
||||
VGA::Frame VGALastFrame;
|
||||
const unsigned FrameWidth = 80;
|
||||
const unsigned FrameHeight = 25;
|
||||
uint16_t VGALastFrame[FrameWidth * FrameHeight];
|
||||
#endif
|
||||
|
||||
nat ProbeBaud(nat Port)
|
||||
|
@ -212,25 +214,25 @@ namespace Sortix
|
|||
|
||||
void InvalidateVGA()
|
||||
{
|
||||
for ( nat I = 0; I < VGALastFrame.Width * VGALastFrame.Height; I++ ) { VGALastFrame.Data[I] = 0; }
|
||||
for ( nat I = 0; I < FrameWidth * FrameHeight; I++ ) { VGALastFrame[I] = 0; }
|
||||
}
|
||||
|
||||
void RenderVGA(const VGA::Frame* Frame)
|
||||
void RenderVGA(const uint16_t* Frame)
|
||||
{
|
||||
const uint16_t* Source = Frame->Data;
|
||||
const uint16_t* Source = Frame;
|
||||
|
||||
nat LastColor = 1337;
|
||||
nat SkippedSince = 0;
|
||||
bool posundefined = true;
|
||||
|
||||
for ( nat Y = 0; Y < Frame->Height; Y++)
|
||||
for ( nat Y = 0; Y < FrameHeight; Y++)
|
||||
{
|
||||
for ( nat X = 0; X < Frame->Width; X++ )
|
||||
for ( nat X = 0; X < FrameWidth; X++ )
|
||||
{
|
||||
nat Index = Y * Frame->Width + X;
|
||||
nat Index = Y * FrameWidth + X;
|
||||
|
||||
nat Element = Source[Index];
|
||||
nat OldElement = VGALastFrame.Data[Index];
|
||||
nat OldElement = VGALastFrame[Index];
|
||||
|
||||
if ( Element == OldElement ) { continue; }
|
||||
|
||||
|
@ -267,7 +269,7 @@ namespace Sortix
|
|||
for ( nat Pos = SkippedSince; Pos <= Index; Pos++ )
|
||||
{
|
||||
Element = Source[Pos];
|
||||
OldElement = VGALastFrame.Data[Pos];
|
||||
OldElement = VGALastFrame[Pos];
|
||||
|
||||
nat NewColor = (ConversionTable[ (Element >> 12) & 0xF ] << 3) | (ConversionTable[ (Element >> 8) & 0xF ]);
|
||||
|
||||
|
@ -311,7 +313,7 @@ namespace Sortix
|
|||
LastColor = NewColor;
|
||||
}
|
||||
|
||||
VGALastFrame.Data[Pos] = Element;
|
||||
VGALastFrame[Pos] = Element;
|
||||
|
||||
Element &= 0x7F;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Sortix
|
|||
int TryPopChar();
|
||||
#ifdef SORTIX_VGA_H
|
||||
void InvalidateVGA();
|
||||
void RenderVGA(const VGA::Frame* Frame = (const VGA::Frame*) 0xB8000);
|
||||
void RenderVGA(const uint16_t* frame = (const uint16_t*) 0xB8000UL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
213
sortix/vga.cpp
213
sortix/vga.cpp
|
@ -23,6 +23,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include "platform.h"
|
||||
#include <libmaxsi/error.h>
|
||||
#include <libmaxsi/memory.h>
|
||||
#include "vga.h"
|
||||
#include "memorymanagement.h"
|
||||
|
@ -37,29 +38,19 @@ namespace Sortix
|
|||
{
|
||||
namespace VGA
|
||||
{
|
||||
addr_t SysCreateFrame();
|
||||
int SysChangeFrame(int fd);
|
||||
int SysDeleteFrame(int fd);
|
||||
|
||||
uint16_t* const vga = (uint16_t* const) 0xB8000;
|
||||
const int width = 80;
|
||||
const int height = 80;
|
||||
|
||||
DevVGAFrame* currentframe;
|
||||
byte* const VGA = (byte* const) 0xB8000;
|
||||
const unsigned WIDTH = 80;
|
||||
const unsigned HEIGHT = 25;
|
||||
const size_t VGA_SIZE = sizeof(uint16_t) * WIDTH * HEIGHT;
|
||||
|
||||
void Init()
|
||||
{
|
||||
currentframe = NULL;
|
||||
|
||||
Syscall::Register(SYSCALL_CREATE_FRAME, (void*) SysCreateFrame);
|
||||
Syscall::Register(SYSCALL_CHANGE_FRAME, (void*) SysChangeFrame);
|
||||
Syscall::Register(SYSCALL_DELETE_FRAME, (void*) SysDeleteFrame);
|
||||
}
|
||||
|
||||
// Changes the position of the hardware cursor.
|
||||
void SetCursor(nat x, nat y)
|
||||
{
|
||||
nat value = x + y * width;
|
||||
nat value = x + y * WIDTH;
|
||||
|
||||
// This sends a command to indicies 14 and 15 in the
|
||||
// CRT Control Register of the VGA controller. These
|
||||
|
@ -69,149 +60,71 @@ namespace Sortix
|
|||
CPU::OutPortB(0x3D5, (value >> 8) & 0xFF);
|
||||
CPU::OutPortB(0x3D4, 15);
|
||||
CPU::OutPortB(0x3D5, (value >> 0) & 0xFF);
|
||||
}
|
||||
|
||||
addr_t SysCreateFrame()
|
||||
{
|
||||
addr_t page = Page::Get();
|
||||
if ( !page ) { return 0; }
|
||||
|
||||
Process* process = CurrentProcess();
|
||||
addr_t mapto = process->AllocVirtualAddr(0x1000UL);
|
||||
UserFrame* userframe = (UserFrame*) mapto;
|
||||
|
||||
// TODO: Check if mapto collides with any other memory section!
|
||||
|
||||
if ( !Memory::MapUser(page, mapto) )
|
||||
{
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
Maxsi::Memory::Set(userframe, 0, sizeof(UserFrame));
|
||||
|
||||
DevVGAFrame* frame = new DevVGAFrame();
|
||||
if ( frame == NULL )
|
||||
{
|
||||
Memory::UnmapUser(mapto);
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
int fd = process->descriptors.Allocate(frame);
|
||||
if ( fd < 0 )
|
||||
{
|
||||
delete frame;
|
||||
Memory::UnmapUser(mapto);
|
||||
Page::Put(page); return 0;
|
||||
}
|
||||
|
||||
userframe->fd = fd;
|
||||
|
||||
frame->process = process;
|
||||
frame->physical = page;
|
||||
frame->userframe = userframe;
|
||||
|
||||
return mapto;
|
||||
}
|
||||
|
||||
int SysChangeFrame(int fd)
|
||||
{
|
||||
Process* process = CurrentProcess();
|
||||
Device* device = process->descriptors.Get(fd);
|
||||
if ( !device ) { return -1; }
|
||||
|
||||
if ( !device->IsType(Device::VGABUFFER) ) { return -2; }
|
||||
|
||||
DevVGAFrame* frame = (DevVGAFrame*) device;
|
||||
|
||||
ASSERT(frame->process == process);
|
||||
ASSERT(frame->physical != 0);
|
||||
ASSERT(frame->userframe != NULL);
|
||||
ASSERT(frame->onscreen == (frame == currentframe));
|
||||
|
||||
// TODO: Check if userframe is actually user-space writable!
|
||||
|
||||
// Check if we need to do anything.
|
||||
if ( frame == currentframe ) { return 0; }
|
||||
|
||||
// If there is already a currently used frame? If so, swap it from
|
||||
// the VGA memory and back to the RAM. This should be done
|
||||
// transparently such that the program doesn't feel the difference.
|
||||
if ( currentframe != NULL )
|
||||
{
|
||||
ASSERT(currentframe->physical != frame->physical);
|
||||
ASSERT(currentframe->userframe != frame->userframe);
|
||||
ASSERT(currentframe->onscreen == true);
|
||||
|
||||
if ( currentframe->process != process )
|
||||
{
|
||||
Memory::SwitchAddressSpace(currentframe->process->addrspace);
|
||||
}
|
||||
|
||||
// Remap the pages in the owning process.
|
||||
// TODO: Check if userframe is actually user-space writable!
|
||||
Memory::UnmapUser((addr_t) currentframe->userframe);
|
||||
Memory::MapUser(currentframe->physical, (addr_t) currentframe->userframe);
|
||||
Memory::InvalidatePage((addr_t) frame->userframe);
|
||||
|
||||
// Restore the contents of this frame to the VGA framebuffer.
|
||||
Maxsi::Memory::Copy(currentframe->userframe, vga, sizeof(UserFrame));
|
||||
|
||||
if ( currentframe->process != process )
|
||||
{
|
||||
Memory::SwitchAddressSpace(process->addrspace);
|
||||
}
|
||||
|
||||
currentframe->onscreen = false;
|
||||
}
|
||||
|
||||
// Now move the contents of this frame to the VGA framebuffer.
|
||||
Maxsi::Memory::Copy(vga, frame->userframe, sizeof(UserFrame));
|
||||
|
||||
// Remap the pages such that the current process now uses the vga.
|
||||
Memory::UnmapUser((addr_t) frame->userframe);
|
||||
Memory::MapUser((addr_t) vga, (addr_t) frame->userframe);
|
||||
Memory::InvalidatePage((addr_t) frame->userframe);
|
||||
|
||||
frame->onscreen = true;
|
||||
currentframe = frame;
|
||||
SetCursor(width, height-1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SysDeleteFrame(int fd)
|
||||
{
|
||||
Process* process = CurrentProcess();
|
||||
Device* device = process->descriptors.Get(fd);
|
||||
process->descriptors.Free(fd);
|
||||
|
||||
if ( device == NULL ) { return -1; }
|
||||
device->Unref();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DevVGAFrame::DevVGAFrame()
|
||||
DevVGA::DevVGA()
|
||||
{
|
||||
process = NULL;
|
||||
userframe = NULL;
|
||||
physical = 0;
|
||||
onscreen = false;
|
||||
SerialTerminal::OnVGAFrameCreated();
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
DevVGAFrame::~DevVGAFrame()
|
||||
DevVGA::~DevVGA()
|
||||
{
|
||||
SerialTerminal::OnVGAFrameDeleted();
|
||||
if ( process != NULL ) { ASSERT(CurrentProcess() == process); }
|
||||
if ( userframe != NULL ) { Memory::UnmapUser((addr_t) userframe); Memory::InvalidatePage((addr_t) userframe); }
|
||||
if ( physical != 0 ) { Page::Put(physical); }
|
||||
if ( VGA::currentframe == this ) { VGA::currentframe = NULL; }
|
||||
}
|
||||
|
||||
bool DevVGAFrame::IsType(unsigned type)
|
||||
ssize_t DevVGA::Read(byte* dest, size_t count)
|
||||
{
|
||||
return type == Device::VGABUFFER;
|
||||
if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; }
|
||||
Maxsi::Memory::Copy(dest, VGA::VGA + offset, count);
|
||||
offset += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t DevVGA::Write(const byte* src, size_t count)
|
||||
{
|
||||
if ( offset == VGA::VGA_SIZE && count ) { Error::Set(ENOSPC); return -1; }
|
||||
if ( VGA::VGA_SIZE - offset < count ) { count = VGA::VGA_SIZE - offset; }
|
||||
Maxsi::Memory::Copy(VGA::VGA + offset, src, count);
|
||||
offset = (offset + count) % VGA::VGA_SIZE;
|
||||
return count;
|
||||
}
|
||||
|
||||
bool DevVGA::IsReadable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DevVGA::IsWritable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t DevVGA::BlockSize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uintmax_t DevVGA::Size()
|
||||
{
|
||||
return VGA::VGA_SIZE;
|
||||
}
|
||||
|
||||
uintmax_t DevVGA::Position()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool DevVGA::Seek(uintmax_t position)
|
||||
{
|
||||
if ( VGA::VGA_SIZE < position ) { Error::Set(EINVAL); return false; }
|
||||
offset = position;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DevVGA::Resize(uintmax_t size)
|
||||
{
|
||||
if ( size == VGA::VGA_SIZE ) { return false; }
|
||||
Error::Set(ENOSPC);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
41
sortix/vga.h
41
sortix/vga.h
|
@ -26,11 +26,10 @@
|
|||
#define SORTIX_VGA_H
|
||||
|
||||
#include "device.h"
|
||||
#include "stream.h"
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
class Process;
|
||||
|
||||
namespace VGA
|
||||
{
|
||||
// TODO: Move these to a better place
|
||||
|
@ -51,38 +50,32 @@ namespace Sortix
|
|||
#define COLOR8_LIGHT_BROWN 14
|
||||
#define COLOR8_WHITE 15
|
||||
|
||||
struct Frame
|
||||
{
|
||||
static const nat Mode = 0x3;
|
||||
static const size_t Width = 80;
|
||||
static const size_t Height = 25;
|
||||
|
||||
uint16_t Data[80*25];
|
||||
};
|
||||
|
||||
struct UserFrame : public Frame
|
||||
{
|
||||
int fd;
|
||||
};
|
||||
|
||||
void Init();
|
||||
void SetCursor(nat x, nat y);
|
||||
}
|
||||
|
||||
class DevVGAFrame : public Device
|
||||
class DevVGA : public DevBuffer
|
||||
{
|
||||
public:
|
||||
DevVGAFrame();
|
||||
~DevVGAFrame();
|
||||
typedef DevBuffer BaseClass;
|
||||
|
||||
public:
|
||||
virtual bool IsType(unsigned type);
|
||||
DevVGA();
|
||||
virtual ~DevVGA();
|
||||
|
||||
private:
|
||||
size_t offset;
|
||||
|
||||
public:
|
||||
Process* process;
|
||||
addr_t physical;
|
||||
VGA::UserFrame* userframe;
|
||||
bool onscreen;
|
||||
virtual ssize_t Read(byte* dest, size_t count);
|
||||
virtual ssize_t Write(const byte* src, size_t count);
|
||||
virtual bool IsReadable();
|
||||
virtual bool IsWritable();
|
||||
virtual size_t BlockSize();
|
||||
virtual uintmax_t Size();
|
||||
virtual uintmax_t Position();
|
||||
virtual bool Seek(uintmax_t position);
|
||||
virtual bool Resize(uintmax_t size);
|
||||
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue