From 247070cc7e5ae117fd0d1b551fafdf5c13f0dd6b Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 20 Dec 2009 13:40:58 +0100 Subject: Keyboard warning gets logged --- .gitignore | 4 ++++ Source/Kernel/Core/kmain.wtf.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 7562cf6..254c5a7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ Source/Kernel/Map.txt Source/Kernel/Melon.ke Ports Ports/* +Cross +Cross/* +Unix +Unix/* diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index ad11eaf..5181cb7 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -214,13 +214,13 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //*************************************** LOAD SYSTEM STUFF - if (keymap != "builtin") { - if (!Kbd::loadKeymap(keymap)) *kvt << "WARNING : Could not load keymap " << keymap << ", using built-in keymap instead."; - } - Log::init(KL_STATUS); //Setup logging Log::log(KL_STATUS, "kmain : Melon booting."); + if (keymap != "builtin") { + if (!Kbd::loadKeymap(keymap)) Log::log(KL_WARNING, String("WARNING : Could not load keymap ") += keymap += ", using built-in keymap instead."); + } + Usr::load(); //Setup user managment Log::log(KL_STATUS, "kmain : User list loaded"); -- cgit v1.2.3 From 4333fd5847818d7c7509f1cd3651edf0bf58df86 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 20 Dec 2009 21:12:56 +0100 Subject: Text scrolling optimisation for VGATextOutput --- Source/Kernel/Devices/Display/VGATextOutput.class.cpp | 11 +++++++++++ Source/Kernel/Devices/Display/VGATextOutput.class.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp index 50a57b2..c597696 100644 --- a/Source/Kernel/Devices/Display/VGATextOutput.class.cpp +++ b/Source/Kernel/Devices/Display/VGATextOutput.class.cpp @@ -24,6 +24,7 @@ void VGATextOutput::getModes(Vector &to) { m.identifier = 1; m.graphWidth = 0; m.graphHeight = 0; + m.graphDepth = 0; m.device = this; to.push(m); m.textCols = 80; @@ -60,3 +61,13 @@ void VGATextOutput::clear() { u16int* where = (u16int*)RAM_ADDR; for (int i = 0; i < 25 * 80; i++) where[i] = 0; } + +bool VGATextOutput::textScroll(u16int line, u16int col, u16int height, u16int width, u8int color) { + u8int* where = (u8int*)RAM_ADDR; + for (u32int i = 1; i < height; i++) { + memcpy(where + ((line + i - 1) * (m_cols * 2)) + (col * 2), where + ((line + i) * (m_cols * 2)) + (col * 2), width * 2); + } + u16int* w = (u16int*)where; + memsetw(w + ((line + height - 1) * m_cols) + col, 0x20 | (color << 8), width); + return true; +} diff --git a/Source/Kernel/Devices/Display/VGATextOutput.class.h b/Source/Kernel/Devices/Display/VGATextOutput.class.h index 2c72d40..0b0ba94 100644 --- a/Source/Kernel/Devices/Display/VGATextOutput.class.h +++ b/Source/Kernel/Devices/Display/VGATextOutput.class.h @@ -18,6 +18,8 @@ class VGATextOutput : public Display { void putChar(u16int line, u16int col, WChar c, u8int color); void moveCursor(u16int line, u16int col); void clear(); + + bool textScroll(u16int line, u16int col, u16int height, u16int width, u8int color); }; #endif -- cgit v1.2.3 From 5c0d8c3ff6d02eec309463982df9e53f44f4359c Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 20 Dec 2009 21:25:05 +0100 Subject: Same optimisation for VESADisplay --- Source/Kernel/Devices/Display/GraphicDisplay.proto.h | 1 + Source/Kernel/Devices/Display/VESADisplay.class.cpp | 17 +++++++++++++++++ Source/Kernel/Devices/Display/VESADisplay.class.h | 1 + 3 files changed, 19 insertions(+) diff --git a/Source/Kernel/Devices/Display/GraphicDisplay.proto.h b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h index 9608ada..f58f5cf 100644 --- a/Source/Kernel/Devices/Display/GraphicDisplay.proto.h +++ b/Source/Kernel/Devices/Display/GraphicDisplay.proto.h @@ -10,6 +10,7 @@ extern u32int consoleColor[16]; #define C_FONT_HEIGHT 16 class GraphicDisplay : public Display { + protected: struct { int line, col; u32int buff[C_FONT_WIDTH][C_FONT_HEIGHT]; diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp index 7c4adca..2992910 100644 --- a/Source/Kernel/Devices/Display/VESADisplay.class.cpp +++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp @@ -300,3 +300,20 @@ void VESADisplay::drawChar(u16int line, u16int col, WChar c, u8int color) { y++; } } + +bool VESADisplay::textScroll(u16int line, u16int col, u16int height, u16int width, u8int color) { + u8int* start = memPos(col * C_FONT_WIDTH, line * C_FONT_HEIGHT); + u32int count = width * C_FONT_WIDTH * m_pixWidth; + u32int diff = C_FONT_HEIGHT * m_currMode.pitch; + putCsrBuff(); + for (int i = 0; i < (height - 1) * C_FONT_HEIGHT; i++) { + memcpy(start, start + diff, count); + start += m_currMode.pitch; + } + for (u32int i = 0; i < width; i++) { + drawChar(line + height - 1, col + i, " ", color); + } + m_csrBuff.line--; + drawCsr(); + return true; +} diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.h b/Source/Kernel/Devices/Display/VESADisplay.class.h index a6001e2..c3bae82 100644 --- a/Source/Kernel/Devices/Display/VESADisplay.class.h +++ b/Source/Kernel/Devices/Display/VESADisplay.class.h @@ -77,6 +77,7 @@ class VESADisplay : public GraphicDisplay { //Advanced graphical functions, recoded for being optimized virtual void drawChar(u16int line, u16int col, WChar c, u8int color); + bool textScroll(u16int line, u16int col, u16int height, u16int width, u8int color); }; #endif -- cgit v1.2.3 From 2a9defea402eec36e075e9e835b804dcc6926748 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 20 Dec 2009 23:09:17 +0100 Subject: Added a simple status bar for loading progress --- Source/Kernel/Config.h | 3 +++ Source/Kernel/Core/kmain.wtf.cpp | 44 ++++++++++++++++++++++++++++---- Source/Kernel/VTManager/SimpleVT.class.h | 2 ++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Source/Kernel/Config.h b/Source/Kernel/Config.h index 77573aa..40689e3 100644 --- a/Source/Kernel/Config.h +++ b/Source/Kernel/Config.h @@ -7,6 +7,9 @@ #define TXTLOGO_FGCOLOR 9 //Colors for the melon logo #define TXTLOGO_BGCOLOR 0 +#define STATUSBAR_BGCOLOR 7 +#define STATUSBAR_FGCOLOR 0 + #define KVT_FGCOLOR 7 //Colors for the vt for selecting a screen mode #define KVT_BGCOLOR 0 #define KVT_LIGHTCOLOR 9 diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index 5181cb7..2dc0377 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -116,9 +116,29 @@ void selectVideoMode(SimpleVT& v) { } } +#define STATUS(stat) { \ + progress++; \ + kvt->setColor(STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); \ + line = kvt->csrlin(); \ + kvt->moveCursor(0, 0); \ + *kvt << "Melon is loading : {"; \ + for (u32int i = 0; i < progress; i++) *kvt << ":"; \ + *kvt << ". "; \ + kvt->moveCursor(0, 42); \ + *kvt << "} "; \ + kvt->moveCursor(0, 51); \ + *kvt << "[" << stat; \ + kvt->moveCursor(0, 78); \ + *kvt << "] "; \ + kvt->setColor(KVT_FGCOLOR, KVT_BGCOLOR); \ + kvt->moveCursor(line, 0); \ +} + void kmain(multiboot_info_t* mbd, u32int magic) { DEBUG("Entering kmain."); + u16int progress = 0, line; //For logger + if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { Mem::placementAddress = (u32int)&end; //Setup basic stuff so that PANIC will work VGATextOutput *vgaout = new VGATextOutput(); @@ -146,27 +166,34 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //Create a VT for logging what kernel does kvt = new ScrollableVT(25, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR); kvt->map(0, 0); - *kvt << "Melon is loading...\n"; + *kvt << "Melon is loading :\n"; + STATUS("IDT"); IDT::init(); //Setup interrupts + STATUS("Paging"); u32int totalRam = ((mbd->mem_upper + mbd->mem_lower) * 1024); PhysMem::initPaging(totalRam); //Setup paging + STATUS("GDT"); GDT::init(); //Initialize real GDT, not fake one from loader.wtf.asm PhysMem::removeTemporaryPages(); //Remove useless page mapping + STATUS("Heap"); Mem::createHeap(); //Create kernel heap Dev::registerDevice(vgaout); + STATUS("Timer"); Dev::registerDevice(new Timer()); //Initialize timer String kcmdline((char*)mbd->cmdline); + STATUS("Multitasking"); Task::initialize(kcmdline, kvt); //Initialize multitasking asm volatile("sti"); //*************************************** PARSE COMMAND LINE + STATUS("Parse command line"); Vector opts = kcmdline.split(" "); String keymap = "builtin", init = "/System/Applications/PaperWork.app"; String root = "ramfs:0"; @@ -183,14 +210,15 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //*************************************** DEVICE SETUP - Dev::registerDevice(new PS2Keyboard()); //Initialize keyboard driver + STATUS("Keyboard"); Dev::registerDevice(new PS2Keyboard()); //Initialize keyboard driver Kbd::setFocus(kvt); //Set focus to virtual terminal - if (enableVESA) Dev::registerDevice(new VESADisplay()); - FloppyController::detect(); - ATAController::detect(); + STATUS("VESA"); if (enableVESA) Dev::registerDevice(new VESADisplay()); + STATUS("Floppy"); FloppyController::detect(); + STATUS("Hard disk drives"); ATAController::detect(); //*************************************** MOUNT FILESYSTEMS + STATUS("Root filesystem"); { // mount root filesystem if (!VFS::mount(String("/:") += root, kvt, mbd)) PANIC("Cannot mount root filesystem."); } @@ -198,6 +226,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) { cwd = VFS::getRootNode(); Task::currProcess()->setCwd(cwd); + STATUS("File systems"); // mount other filesystems for (u32int i = 0; i < mount.size(); i++) { VFS::mount(mount[i], kvt, mbd); @@ -214,17 +243,21 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //*************************************** LOAD SYSTEM STUFF + STATUS("Logging"); Log::init(KL_STATUS); //Setup logging Log::log(KL_STATUS, "kmain : Melon booting."); if (keymap != "builtin") { + STATUS("Keymap"); if (!Kbd::loadKeymap(keymap)) Log::log(KL_WARNING, String("WARNING : Could not load keymap ") += keymap += ", using built-in keymap instead."); } + STATUS("Users"); Usr::load(); //Setup user managment Log::log(KL_STATUS, "kmain : User list loaded"); if (init.empty()) { + STATUS("= LAUNCHING KERNEL SHELL ="); *kvt << "\n"; new KernelShell(cwd, kvt); while (KernelShell::getInstances() > 0) { @@ -232,6 +265,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) { } Sys::halt(); } else { + STATUS("= VIDEO MODE DETECTION ="); selectVideoMode(*kvt); //Create a VT for handling the Melon bootup logo SimpleVT *melonLogoVT = new SimpleVT(melonLogoLines, melonLogoCols, TXTLOGO_FGCOLOR, TXTLOGO_BGCOLOR); diff --git a/Source/Kernel/VTManager/SimpleVT.class.h b/Source/Kernel/VTManager/SimpleVT.class.h index 9eda6de..6125d10 100644 --- a/Source/Kernel/VTManager/SimpleVT.class.h +++ b/Source/Kernel/VTManager/SimpleVT.class.h @@ -24,6 +24,8 @@ class SimpleVT : public VirtualTerminal { bool isBoxed() { return true; } u8int height() { return m_rows; } u8int width() { return m_cols; } + u8int csrlin() { return m_csrlin; } + u8int csrcol() { return m_csrcol; } void map(s32int row = -1, s32int col = -1); void unmap(); -- cgit v1.2.3 From a975053605a0f041fd2003792d81c80391527e71 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Mon, 21 Dec 2009 00:11:00 +0100 Subject: Made status bar into a namespace, and added functionnalities --- .../2009-12-20-235850_728x426_scrot.png | Bin 0 -> 20314 bytes Source/Kernel/Core/SB.ns.cpp | 101 +++++++++++++++++++++ Source/Kernel/Core/SB.ns.h | 16 ++++ Source/Kernel/Core/Sys.ns.cpp | 7 ++ Source/Kernel/Core/kmain.wtf.cpp | 72 +++++++-------- .../Kernel/Devices/Display/VESADisplay.class.cpp | 2 +- Source/Kernel/Makefile | 1 + Source/Kernel/TaskManager/Process.class.cpp | 2 + Source/Kernel/TaskManager/Task.ns.h | 3 + Source/Kernel/VTManager/SimpleVT.class.cpp | 2 + Source/Kernel/VTManager/SimpleVT.class.h | 4 +- Source/Library/Common/SimpleList.class.h | 2 +- 12 files changed, 168 insertions(+), 44 deletions(-) create mode 100644 Media/Screenshots/2009-12-20-235850_728x426_scrot.png create mode 100644 Source/Kernel/Core/SB.ns.cpp create mode 100644 Source/Kernel/Core/SB.ns.h diff --git a/Media/Screenshots/2009-12-20-235850_728x426_scrot.png b/Media/Screenshots/2009-12-20-235850_728x426_scrot.png new file mode 100644 index 0000000..c9b057f Binary files /dev/null and b/Media/Screenshots/2009-12-20-235850_728x426_scrot.png differ diff --git a/Source/Kernel/Core/SB.ns.cpp b/Source/Kernel/Core/SB.ns.cpp new file mode 100644 index 0000000..62714a1 --- /dev/null +++ b/Source/Kernel/Core/SB.ns.cpp @@ -0,0 +1,101 @@ +#include "SB.ns.h" +#include +#include +#include +#include + +namespace SB { + +SimpleVT *sb = NULL; + +String msg; + +u16int boot_progress = 0; +bool gone_multi = false; + +Mutex lock(MUTEX_FALSE); + +void init() { + sb = new SimpleVT(1, 80, STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); + sb->map(0, 0); + sb->hideCursor(); +} + +void reinit() { + if (!gone_multi) return; + lock.waitLock(); + delete sb; + sb = new SimpleVT(1, Disp::mode.textCols, STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); + sb->map(0, 0); + sb->hideCursor(); + lock.unlock(); +} + +void drawprogress(const String& s) { + *sb << "\nMelon is loading : {"; + for (u32int i = 0; i < boot_progress; i++) *sb << ":"; + *sb << "."; + sb->moveCursor(0, 45); + *sb << "}"; + sb->moveCursor(0, 51); + *sb << "[" << s; + sb->moveCursor(0, 78); + *sb << "]"; +} + +void drawnormal() { + *sb << "\n [Up:" << (s64int)Time::uptime() << "s"; + sb->moveCursor(0, 10); + *sb << "] [Mem:" << (s64int)PhysMem::free() << "/" << (s64int)PhysMem::total(); + sb->moveCursor(0, 28); + *sb << "] [Proc.:" << (s64int)Task::processes->size(); + sb->moveCursor(0, 39); + *sb << "] [Threads:" << (s64int)Task::threads->size(); + sb->moveCursor(0, 52); + *sb << "] [" << msg; + sb->moveCursor(0, sb->width() - 2); + *sb << "]"; +} + +u32int thread(void*) { + while (!gone_multi); //Synchronize + while (1) { + lock.waitLock(); + if (boot_progress != 0) { + drawprogress(msg); + } else { + drawnormal(); + } + lock.unlock(); + Task::currThread()->sleep(100); + } + return 0; +} + +void gomulti() { + new Thread(thread, 0, true); + gone_multi = true; +} + +void progress(const String& s) { + if (gone_multi) { + lock.waitLock(); + boot_progress++; + msg = s; + lock.unlock(); + } else { + boot_progress++; + drawprogress(s); + } +} + +void message(const String& s) { + if (!gone_multi) return; + lock.waitLock(); + boot_progress = 0; + msg = s; + drawnormal(); + lock.unlock(); +} + +} //END NS diff --git a/Source/Kernel/Core/SB.ns.h b/Source/Kernel/Core/SB.ns.h new file mode 100644 index 0000000..687be02 --- /dev/null +++ b/Source/Kernel/Core/SB.ns.h @@ -0,0 +1,16 @@ +#ifndef DEF_SB_NS_H +#define DEF_SB_NS_H + +//StatusBar namespace :) +#include + +namespace SB { + void init(); //Setup status bar with default 80col configuration + void reinit(); //Setup status bar querying Disp:: for text screen width + void gomulti(); //Launch new thread for status bar + void progress(const String& s); //Update progress + void message(const String& s); //Set a message + +} + +#endif diff --git a/Source/Kernel/Core/Sys.ns.cpp b/Source/Kernel/Core/Sys.ns.cpp index 59da244..05e0d7d 100644 --- a/Source/Kernel/Core/Sys.ns.cpp +++ b/Source/Kernel/Core/Sys.ns.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #define DEBUGVT(x) SimpleVT *x = new SimpleVT(4, 56, PANIC_FGCOLOR, PANIC_BGCOLOR); x->map(); x->put('\n'); @@ -95,6 +96,7 @@ void stackTrace(u32int ebp, VirtualTerminal& vt, u32int maxframes, bool isUser) //Used by PANIC() macro (see common.wtf.h) void panic(char *message, char *file, u32int line) { + SB::message("PANIC"); asm volatile("cli"); DEBUGVT(vt); @@ -106,6 +108,7 @@ void panic(char *message, char *file, u32int line) { } void panic(char *message, registers_t *regs, char *file, u32int line) { + SB::message("PANIC"); asm volatile("cli"); SimpleVT vt(15, 70, BSOD_FGCOLOR, BSOD_BGCOLOR); @@ -129,6 +132,7 @@ void panic(char *message, registers_t *regs, char *file, u32int line) { //Used by ASSERT() macro (see common.wtf.h) void panic_assert(char *file, u32int line, char *desc) { + SB::message("ASSERTION FAILED"); asm volatile("cli"); DEBUGVT(vt); @@ -140,17 +144,20 @@ void panic_assert(char *file, u32int line, char *desc) { } void shutdown_cleanup() { + SB::message("Cleaning up system"); asm volatile("cli"); Log::close(); } void reboot() { shutdown_cleanup(); + SB::message("Rebooting..."); outb(0x64, 0xFE); } void halt() { shutdown_cleanup(); + SB::message("Halting"); String message("MELON SEZ : KTHXBYE, U CAN NAOW TURNZ OFF UR COMPUTER."); SimpleVT vt(3, message.size() + 16, HALT_FGCOLOR, HALT_BGCOLOR); vt.map(); diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index 2dc0377..83fca7b 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,7 @@ void selectVideoMode(SimpleVT& v) { u32int n = answer.toInt(); v.unmap(); if (n >= 0 and n < Disp::modes.size() and Disp::setMode(Disp::modes[n])) { + SB::reinit(); return; } else { Disp::setMode(Disp::modes[1]); @@ -116,29 +118,9 @@ void selectVideoMode(SimpleVT& v) { } } -#define STATUS(stat) { \ - progress++; \ - kvt->setColor(STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); \ - line = kvt->csrlin(); \ - kvt->moveCursor(0, 0); \ - *kvt << "Melon is loading : {"; \ - for (u32int i = 0; i < progress; i++) *kvt << ":"; \ - *kvt << ". "; \ - kvt->moveCursor(0, 42); \ - *kvt << "} "; \ - kvt->moveCursor(0, 51); \ - *kvt << "[" << stat; \ - kvt->moveCursor(0, 78); \ - *kvt << "] "; \ - kvt->setColor(KVT_FGCOLOR, KVT_BGCOLOR); \ - kvt->moveCursor(line, 0); \ -} - void kmain(multiboot_info_t* mbd, u32int magic) { DEBUG("Entering kmain."); - u16int progress = 0, line; //For logger - if (magic != MULTIBOOT_BOOTLOADER_MAGIC) { Mem::placementAddress = (u32int)&end; //Setup basic stuff so that PANIC will work VGATextOutput *vgaout = new VGATextOutput(); @@ -163,37 +145,41 @@ void kmain(multiboot_info_t* mbd, u32int magic) { VGATextOutput *vgaout = new VGATextOutput(); Disp::setText(vgaout); + SB::init(); + //Create a VT for logging what kernel does - kvt = new ScrollableVT(25, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR); - kvt->map(0, 0); - *kvt << "Melon is loading :\n"; + SB::progress("Create kernel VT"); + kvt = new ScrollableVT(24, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR); + kvt->map(1, 0); + kvt->moveCursor(0, 0); - STATUS("IDT"); + SB::progress("IDT"); IDT::init(); //Setup interrupts - STATUS("Paging"); + SB::progress("Paging"); u32int totalRam = ((mbd->mem_upper + mbd->mem_lower) * 1024); PhysMem::initPaging(totalRam); //Setup paging - STATUS("GDT"); + SB::progress("GDT"); GDT::init(); //Initialize real GDT, not fake one from loader.wtf.asm PhysMem::removeTemporaryPages(); //Remove useless page mapping - STATUS("Heap"); + SB::progress("Heap"); Mem::createHeap(); //Create kernel heap Dev::registerDevice(vgaout); - STATUS("Timer"); + SB::progress("Timer"); Dev::registerDevice(new Timer()); //Initialize timer String kcmdline((char*)mbd->cmdline); - STATUS("Multitasking"); + SB::progress("Multitasking"); Task::initialize(kcmdline, kvt); //Initialize multitasking + SB::gomulti(); asm volatile("sti"); //*************************************** PARSE COMMAND LINE - STATUS("Parse command line"); + SB::progress("Parse command line"); Vector opts = kcmdline.split(" "); String keymap = "builtin", init = "/System/Applications/PaperWork.app"; String root = "ramfs:0"; @@ -210,15 +196,15 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //*************************************** DEVICE SETUP - STATUS("Keyboard"); Dev::registerDevice(new PS2Keyboard()); //Initialize keyboard driver + SB::progress("Keyboard"); Dev::registerDevice(new PS2Keyboard()); //Initialize keyboard driver Kbd::setFocus(kvt); //Set focus to virtual terminal - STATUS("VESA"); if (enableVESA) Dev::registerDevice(new VESADisplay()); - STATUS("Floppy"); FloppyController::detect(); - STATUS("Hard disk drives"); ATAController::detect(); + SB::progress("VESA"); if (enableVESA) Dev::registerDevice(new VESADisplay()); + SB::progress("Floppy"); FloppyController::detect(); + SB::progress("Hard disk drives"); ATAController::detect(); //*************************************** MOUNT FILESYSTEMS - STATUS("Root filesystem"); + SB::progress("Root filesystem"); { // mount root filesystem if (!VFS::mount(String("/:") += root, kvt, mbd)) PANIC("Cannot mount root filesystem."); } @@ -226,7 +212,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) { cwd = VFS::getRootNode(); Task::currProcess()->setCwd(cwd); - STATUS("File systems"); + SB::progress("File systems"); // mount other filesystems for (u32int i = 0; i < mount.size(); i++) { VFS::mount(mount[i], kvt, mbd); @@ -243,35 +229,38 @@ void kmain(multiboot_info_t* mbd, u32int magic) { //*************************************** LOAD SYSTEM STUFF - STATUS("Logging"); + SB::progress("Logging"); Log::init(KL_STATUS); //Setup logging Log::log(KL_STATUS, "kmain : Melon booting."); if (keymap != "builtin") { - STATUS("Keymap"); + SB::progress("Keymap"); if (!Kbd::loadKeymap(keymap)) Log::log(KL_WARNING, String("WARNING : Could not load keymap ") += keymap += ", using built-in keymap instead."); } - STATUS("Users"); + SB::progress("Users"); Usr::load(); //Setup user managment Log::log(KL_STATUS, "kmain : User list loaded"); if (init.empty()) { - STATUS("= LAUNCHING KERNEL SHELL ="); + SB::progress("Start kernel shell"); *kvt << "\n"; new KernelShell(cwd, kvt); + SB::message("Melon is running \\o/"); while (KernelShell::getInstances() > 0) { Task::currThread()->sleep(100); } Sys::halt(); } else { - STATUS("= VIDEO MODE DETECTION ="); + SB::progress("Video mode selection"); selectVideoMode(*kvt); + SB::progress("Logo setup"); //Create a VT for handling the Melon bootup logo SimpleVT *melonLogoVT = new SimpleVT(melonLogoLines, melonLogoCols, TXTLOGO_FGCOLOR, TXTLOGO_BGCOLOR); melonLogoVT->map(1); new Thread(logoAnimation, (void*)melonLogoVT, true); + SB::progress("Launch INIT"); Process* p = Process::run(init, 0); if (p == 0) { PANIC((char*)(u8int*)ByteArray(String("Could not launch init : ") += init)); @@ -284,6 +273,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) { p->setInVT(vt); p->setOutVT(vt); p->start(); + SB::message("Init started"); while (p->getState() != P_FINISHED) Task::currThread()->sleep(100); PANIC("Init has terminated"); } diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp index 2992910..d06aaee 100644 --- a/Source/Kernel/Devices/Display/VESADisplay.class.cpp +++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp @@ -313,7 +313,7 @@ bool VESADisplay::textScroll(u16int line, u16int col, u16int height, u16int widt for (u32int i = 0; i < width; i++) { drawChar(line + height - 1, col + i, " ", color); } - m_csrBuff.line--; + if (m_csrBuff.line == line + height - 1) m_csrBuff.line--; drawCsr(); return true; } diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile index 0f244d5..6a44ecf 100644 --- a/Source/Kernel/Makefile +++ b/Source/Kernel/Makefile @@ -14,6 +14,7 @@ Objects = Core/loader.wtf.o \ Core/kmain.wtf.o \ Core/Sys.ns.o \ Core/Log.ns.o \ + Core/SB.ns.o \ MemoryManager/Mem.ns.o \ MemoryManager/PhysMem.ns.o \ MemoryManager/GDT.wtf.o \ diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp index bca5f1c..4c23df0 100644 --- a/Source/Kernel/TaskManager/Process.class.cpp +++ b/Source/Kernel/TaskManager/Process.class.cpp @@ -76,12 +76,14 @@ Process::Process(String binfile, u32int uid) : Ressource(PRIF_OBJTYPE, m_callTab m_userHeap = new Heap(); u32int heapIdxSize = PhysMem::total() * 16 + 0x10000; m_userHeap->create(USERHEAPSTART, USERHEAPINITSIZE + heapIdxSize, heapIdxSize, m_pagedir, true, true); + Task::registerProcess(this); } Process::~Process() { exit(); //Kill all threads delete m_pagedir; delete m_userHeap; + Task::unregisterProcess(this); } void Process::start() { diff --git a/Source/Kernel/TaskManager/Task.ns.h b/Source/Kernel/TaskManager/Task.ns.h index 056e4c0..4d2a48d 100644 --- a/Source/Kernel/TaskManager/Task.ns.h +++ b/Source/Kernel/TaskManager/Task.ns.h @@ -9,6 +9,9 @@ namespace Task { Thread* currThread(); Process* currProcess(); + extern SimpleList *processes; + extern SimpleList *threads; + void initialize(String cmdline, VirtualTerminal *vt); //cmdline should be the bootloader kernel command line, if anybody needs it void doSwitch(); void triggerSwitch(); diff --git a/Source/Kernel/VTManager/SimpleVT.class.cpp b/Source/Kernel/VTManager/SimpleVT.class.cpp index 4a16b54..28f9f98 100644 --- a/Source/Kernel/VTManager/SimpleVT.class.cpp +++ b/Source/Kernel/VTManager/SimpleVT.class.cpp @@ -9,6 +9,7 @@ SimpleVT::SimpleVT(u32int rows, u32int cols, u8int fgcolor, u8int bgcolor) : Vir m_rows = rows; m_cols = cols; m_mapped = false; + m_hideCursor = false; setColor(fgcolor, bgcolor); clear(); @@ -87,6 +88,7 @@ void SimpleVT::scroll() { void SimpleVT::updateCursor() { if (!m_mapped) return; + if (m_hideCursor) return; Disp::moveCursor(m_csrlin + m_maprow, m_csrcol + m_mapcol); } diff --git a/Source/Kernel/VTManager/SimpleVT.class.h b/Source/Kernel/VTManager/SimpleVT.class.h index 6125d10..8639a82 100644 --- a/Source/Kernel/VTManager/SimpleVT.class.h +++ b/Source/Kernel/VTManager/SimpleVT.class.h @@ -10,7 +10,7 @@ class SimpleVT : public VirtualTerminal { u8int m_color; u32int m_maprow, m_mapcol; - bool m_mapped; + bool m_mapped, m_hideCursor; u32int m_csrlin, m_csrcol; @@ -27,6 +27,8 @@ class SimpleVT : public VirtualTerminal { u8int csrlin() { return m_csrlin; } u8int csrcol() { return m_csrcol; } + void hideCursor(bool hide = true) { m_hideCursor = hide; } + void map(s32int row = -1, s32int col = -1); void unmap(); virtual void redraw(); diff --git a/Source/Library/Common/SimpleList.class.h b/Source/Library/Common/SimpleList.class.h index 2bbbace..5806155 100644 --- a/Source/Library/Common/SimpleList.class.h +++ b/Source/Library/Common/SimpleList.class.h @@ -78,7 +78,7 @@ class SimpleList { u32int size() { if (m_next == 0) - return 0; + return 1; return m_next->size() + 1; } }; -- cgit v1.2.3 From e7a0a24fa88e369eb3d345573200955e99324156 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Mon, 21 Dec 2009 18:56:08 +0100 Subject: More work on the status bar --- Melon.img | Bin 1474560 -> 1474560 bytes Source/Kernel/Core/SB.ns.cpp | 81 +++++++++++++++------ Source/Kernel/Core/SB.ns.h | 3 +- Source/Kernel/Core/kmain.wtf.cpp | 60 +++------------ Source/Kernel/DeviceManager/Disp.ns.cpp | 39 ++++++++++ Source/Kernel/DeviceManager/Disp.ns.h | 1 + .../Kernel/Devices/Display/VESADisplay.class.cpp | 2 +- Source/Kernel/Shell/KernelShell-sys.class.cpp | 22 ++++++ Source/Kernel/Shell/KernelShell.class.cpp | 26 ++----- Source/Kernel/Shell/KernelShell.class.h | 1 + 10 files changed, 141 insertions(+), 94 deletions(-) diff --git a/Melon.img b/Melon.img index 54e8877..9bc5826 100644 Binary files a/Melon.img and b/Melon.img differ diff --git a/Source/Kernel/Core/SB.ns.cpp b/Source/Kernel/Core/SB.ns.cpp index 62714a1..f5b21ec 100644 --- a/Source/Kernel/Core/SB.ns.cpp +++ b/Source/Kernel/Core/SB.ns.cpp @@ -4,6 +4,8 @@ #include #include +#define BOOT_ITEMS 17 + namespace SB { SimpleVT *sb = NULL; @@ -11,50 +13,83 @@ SimpleVT *sb = NULL; String msg; u16int boot_progress = 0; +u16int height; bool gone_multi = false; Mutex lock(MUTEX_FALSE); void init() { sb = new SimpleVT(1, 80, STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); + height = 1; sb->map(0, 0); sb->hideCursor(); } -void reinit() { - if (!gone_multi) return; - lock.waitLock(); - delete sb; - sb = new SimpleVT(1, Disp::mode.textCols, STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); - sb->map(0, 0); - sb->hideCursor(); - lock.unlock(); -} - void drawprogress(const String& s) { - *sb << "\nMelon is loading : {"; + sb->clear(); + int d = (sb->width() / 2) - ((BOOT_ITEMS + 4) / 2); + if (height == 1) d -= 4; + sb->moveCursor(0, d); + *sb << "{"; for (u32int i = 0; i < boot_progress; i++) *sb << ":"; *sb << "."; - sb->moveCursor(0, 45); + sb->moveCursor(0, BOOT_ITEMS + d + 3); *sb << "}"; - sb->moveCursor(0, 51); - *sb << "[" << s; - sb->moveCursor(0, 78); - *sb << "]"; + if (height > 1) { + *sb << "\n"; + *sb << "Loading : [" << s; + sb->moveCursor(1, sb->width() - 2); + *sb << "]"; + } else { + sb->moveCursor(0, 0); + *sb << "Melon is loading :"; + sb->moveCursor(0, d + BOOT_ITEMS + 6); + *sb << "[" << s; + sb->moveCursor(0, sb->width() - 2); + *sb << "]"; + } } void drawnormal() { - *sb << "\n [Up:" << (s64int)Time::uptime() << "s"; + sb->clear(); + sb->moveCursor(0, 0); + *sb << " [Up:" << (s64int)Time::uptime() << "s"; sb->moveCursor(0, 10); *sb << "] [Mem:" << (s64int)PhysMem::free() << "/" << (s64int)PhysMem::total(); sb->moveCursor(0, 28); *sb << "] [Proc.:" << (s64int)Task::processes->size(); - sb->moveCursor(0, 39); - *sb << "] [Threads:" << (s64int)Task::threads->size(); - sb->moveCursor(0, 52); - *sb << "] [" << msg; - sb->moveCursor(0, sb->width() - 2); - *sb << "]"; + sb->setCursorCol(39); + if (height > 1) { + *sb << "]"; + sb->moveCursor(1, 0); + *sb << " [Threads:" << (s64int)Task::threads->size(); + sb->setCursorCol(12); + *sb << "] [" << msg; + sb->setCursorCol(sb->width() - 2); + *sb << "]"; + } else { + *sb << "] [Threads:" << (s64int)Task::threads->size(); + sb->setCursorCol(52); + *sb << "] [" << msg; + sb->setCursorCol(sb->width() - 2); + *sb << "]"; + } +} + +void reinit() { + if (!gone_multi) return; + lock.waitLock(); + delete sb; + height = (Disp::mode.textCols < 80 ? 2 : 1); + sb = new SimpleVT(height, Disp::mode.textCols, STATUSBAR_FGCOLOR, STATUSBAR_BGCOLOR); + sb->map(0, 0); + sb->hideCursor(); + if (boot_progress != 0) { + drawprogress(msg); + } else { + drawnormal(); + } + lock.unlock(); } u32int thread(void*) { diff --git a/Source/Kernel/Core/SB.ns.h b/Source/Kernel/Core/SB.ns.h index 687be02..7b3b65c 100644 --- a/Source/Kernel/Core/SB.ns.h +++ b/Source/Kernel/Core/SB.ns.h @@ -5,12 +5,13 @@ #include namespace SB { + extern u16int height; + void init(); //Setup status bar with default 80col configuration void reinit(); //Setup status bar querying Disp:: for text screen width void gomulti(); //Launch new thread for status bar void progress(const String& s); //Update progress void message(const String& s); //Set a message - } #endif diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index 83fca7b..aa87d49 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -86,38 +86,6 @@ u32int logoAnimation(void* p) { return 0; } -void selectVideoMode(SimpleVT& v) { - Disp::getModes(); - v << "\nPlease select a graphic mode in the list below:\n"; - - for (u32int i = 0; i < Disp::modes.size(); i++) { - Disp::mode_t& m = Disp::modes[i]; - v << (s32int)i << ":\t" << "Text " << m.textRows << "x" << m.textCols << "\t"; - if (m.graphWidth != 0 and m.graphHeight != 0) { - v << "Graphics " << m.graphWidth << "x" << m.graphHeight << "x" << m.graphDepth << "\t"; - } else { - v << "No graphics"; - } - v.setCursorCol(50); - v << m.device->getName() << "\n"; - } - - while (1) { - v << "\nYour selection: "; - String answer = v.readLine(); - u32int n = answer.toInt(); - v.unmap(); - if (n >= 0 and n < Disp::modes.size() and Disp::setMode(Disp::modes[n])) { - SB::reinit(); - return; - } else { - Disp::setMode(Disp::modes[1]); - v.map(); - v << "Error while switching video mode, please select another one."; - } - } -} - void kmain(multiboot_info_t* mbd, u32int magic) { DEBUG("Entering kmain."); @@ -151,7 +119,12 @@ void kmain(multiboot_info_t* mbd, u32int magic) { SB::progress("Create kernel VT"); kvt = new ScrollableVT(24, 80, 20, KVT_FGCOLOR, KVT_BGCOLOR); kvt->map(1, 0); - kvt->moveCursor(0, 0); + kvt->setColor(TXTLOGO_FGCOLOR, TXTLOGO_BGCOLOR); + for (int i = 0; i < melonLogoLines; i++) { + kvt->setCursorCol(40 - (melonLogoCols / 2)); + *kvt << melonLogo[i] << "\n"; + } + kvt->setColor(KVT_FGCOLOR, KVT_BGCOLOR); SB::progress("IDT"); IDT::init(); //Setup interrupts @@ -225,7 +198,6 @@ void kmain(multiboot_info_t* mbd, u32int magic) { if (!m.empty() && m[0] != WChar("#")) VFS::mount(m, kvt, mbd); } } - //*************************************** LOAD SYSTEM STUFF @@ -242,36 +214,26 @@ void kmain(multiboot_info_t* mbd, u32int magic) { Usr::load(); //Setup user managment Log::log(KL_STATUS, "kmain : User list loaded"); + SB::progress("Video mode selection"); + Disp::selectMode(); if (init.empty()) { SB::progress("Start kernel shell"); *kvt << "\n"; new KernelShell(cwd, kvt); - SB::message("Melon is running \\o/"); + SB::message("Melon is running"); while (KernelShell::getInstances() > 0) { Task::currThread()->sleep(100); } Sys::halt(); } else { - SB::progress("Video mode selection"); - selectVideoMode(*kvt); - SB::progress("Logo setup"); - //Create a VT for handling the Melon bootup logo - SimpleVT *melonLogoVT = new SimpleVT(melonLogoLines, melonLogoCols, TXTLOGO_FGCOLOR, TXTLOGO_BGCOLOR); - melonLogoVT->map(1); - new Thread(logoAnimation, (void*)melonLogoVT, true); - SB::progress("Launch INIT"); Process* p = Process::run(init, 0); if (p == 0) { PANIC((char*)(u8int*)ByteArray(String("Could not launch init : ") += init)); } else { Log::log(KL_STATUS, String("kmain : Starting init : ") += init); - VirtualTerminal* vt = new ScrollableVT(Disp::textRows() - 10, Disp::textCols() - 4, - 200, SHELL_FGCOLOR, SHELL_BGCOLOR); - Kbd::setFocus(vt); - ((ScrollableVT*)vt)->map(9); - p->setInVT(vt); - p->setOutVT(vt); + p->setInVT(kvt); + p->setOutVT(kvt); p->start(); SB::message("Init started"); while (p->getState() != P_FINISHED) Task::currThread()->sleep(100); diff --git a/Source/Kernel/DeviceManager/Disp.ns.cpp b/Source/Kernel/DeviceManager/Disp.ns.cpp index 2827869..7ccf254 100644 --- a/Source/Kernel/DeviceManager/Disp.ns.cpp +++ b/Source/Kernel/DeviceManager/Disp.ns.cpp @@ -1,6 +1,8 @@ #include "Disp.ns.h" #include #include +#include +#include namespace Disp { @@ -52,6 +54,43 @@ bool setMode(mode_t& newmode) { return false; } +void selectMode() { + getModes(); + *kvt << "\nPlease select a graphic mode in the list below:\n"; + + for (u32int i = 0; i < Disp::modes.size(); i++) { + Disp::mode_t& m = Disp::modes[i]; + *kvt << (s32int)i << ":\t" << "Text " << m.textRows << "x" << m.textCols; + kvt->setCursorCol(21); + if (m.graphWidth != 0 and m.graphHeight != 0) { + *kvt << "Graphics " << m.graphWidth << "x" << m.graphHeight << "x" << m.graphDepth << "\t"; + } else { + *kvt << "No graphics"; + } + kvt->setCursorCol(45); + *kvt << m.device->getName() << "\n"; + } + + while (1) { + *kvt << "\nYour selection: "; + String answer = kvt->readLine(); + u32int n = answer.toInt(); + kvt->unmap(); + if (n >= 0 and n < Disp::modes.size() and Disp::setMode(Disp::modes[n])) { + delete kvt; + SB::reinit(); + kvt = new ScrollableVT(Disp::mode.textRows - SB::height, Disp::mode.textCols, 100, KVT_FGCOLOR, KVT_BGCOLOR); + kvt->map(SB::height); + Kbd::setFocus(kvt); + return; + } else { + Disp::setMode(Disp::modes[1]); + kvt->map(); + *kvt << "Error while switching video mode, please select another one."; + } + } +} + void setText(VGATextOutput* o) { mode.device = o; o->clear(); diff --git a/Source/Kernel/DeviceManager/Disp.ns.h b/Source/Kernel/DeviceManager/Disp.ns.h index 2a10358..d1fac57 100644 --- a/Source/Kernel/DeviceManager/Disp.ns.h +++ b/Source/Kernel/DeviceManager/Disp.ns.h @@ -25,6 +25,7 @@ namespace Disp { void getModes(); bool setMode(mode_t& mode); + void selectMode(); void setText(VGATextOutput* o); //To use only once : when display is initializing } diff --git a/Source/Kernel/Devices/Display/VESADisplay.class.cpp b/Source/Kernel/Devices/Display/VESADisplay.class.cpp index d06aaee..11b0882 100644 --- a/Source/Kernel/Devices/Display/VESADisplay.class.cpp +++ b/Source/Kernel/Devices/Display/VESADisplay.class.cpp @@ -109,7 +109,7 @@ bool VESADisplay::setMode(mode_t &mode) { regs.ax = 0x4F02; regs.bx = mode.identifier | 0x4000; V86::biosInt(0x10, regs); - if (regs.ax != 0x004F) return false; + if ((regs.ax & 0xFF00) != 0) return false; if (m_currMode.bpp == 8) { //Set palette to 8 bit diff --git a/Source/Kernel/Shell/KernelShell-sys.class.cpp b/Source/Kernel/Shell/KernelShell-sys.class.cpp index 85ba207..b1ab274 100644 --- a/Source/Kernel/Shell/KernelShell-sys.class.cpp +++ b/Source/Kernel/Shell/KernelShell-sys.class.cpp @@ -81,6 +81,28 @@ void KernelShell::mount(Vector& args) { } } +void KernelShell::unmount(Vector& args) { + if (args.size() == 2) { + FSNode* n = VFS::find(args[1], m_cwd); + bool ok = false; + if (n == 0) { + ok = false; + } else { + String p = VFS::path(n); + for (u32int i = 0; i < VFS::filesystems.size(); i++) { + if (VFS::path(VFS::filesystems[i]->getRootNode()) == p) { + ok = VFS::unmount(VFS::filesystems[i]); + break; + } + } + } + if (ok) *m_vt << "Ok, filesystem unmounted.\n"; + else *m_vt << "Error.\n"; + } else { + *m_vt << "Usage: unmount \n"; + } +} + void KernelShell::readblock(Vector& args) { if (args.size() == 3) { Vector devcs = Dev::findDevices("block"); diff --git a/Source/Kernel/Shell/KernelShell.class.cpp b/Source/Kernel/Shell/KernelShell.class.cpp index 71a717a..9fec9c7 100644 --- a/Source/Kernel/Shell/KernelShell.class.cpp +++ b/Source/Kernel/Shell/KernelShell.class.cpp @@ -5,6 +5,7 @@ #include #include #include +#include u32int KernelShell::m_instances = 0; @@ -62,6 +63,7 @@ u32int KernelShell::run() { {"part", &KernelShell::part}, {"readblock", &KernelShell::readblock}, {"mount", &KernelShell::mount}, + {"unmount", &KernelShell::unmount}, {"hexdump", &KernelShell::hexdump}, {0, 0} @@ -98,26 +100,10 @@ u32int KernelShell::run() { } else if (tokens[0] == "exit") { if (tokens.size() == 1) return 0; return tokens[1].toInt(); - } else if (tokens[0] == "unmount") { - if (tokens.size() == 2) { - FSNode* n = VFS::find(tokens[1], m_cwd); - bool ok = false; - if (n == 0) { - ok = false; - } else { - String p = VFS::path(n); - for (u32int i = 0; i < VFS::filesystems.size(); i++) { - if (VFS::path(VFS::filesystems[i]->getRootNode()) == p) { - ok = VFS::unmount(VFS::filesystems[i]); - break; - } - } - } - if (ok) *m_vt << "Ok, filesystem unmounted.\n"; - else *m_vt << "Error.\n"; - } else { - *m_vt << "Usage: unmount \n"; - } + } else if (tokens[0] == "mode") { + bool ch = (m_vt == kvt); + Disp::selectMode(); + if (ch) m_vt = kvt; } else if (tokens[0] != "" or tokens.size() != 1) { u32int i = 0; bool found = false; diff --git a/Source/Kernel/Shell/KernelShell.class.h b/Source/Kernel/Shell/KernelShell.class.h index 9655def..1552d28 100644 --- a/Source/Kernel/Shell/KernelShell.class.h +++ b/Source/Kernel/Shell/KernelShell.class.h @@ -37,6 +37,7 @@ class KernelShell { void part(Vector& args); void readblock(Vector& args); void mount(Vector& args); + void unmount(Vector& args); void setup(DirectoryNode* cwd, VirtualTerminal *vt); -- cgit v1.2.3 From 837290db7d39c8cd852541cb345dc5a57c9274ce Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Tue, 22 Dec 2009 15:16:22 +0100 Subject: Unknown reason change to Melon.im --- Melon.img | Bin 1474560 -> 1474560 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Melon.img b/Melon.img index 9bc5826..31bb8d6 100644 Binary files a/Melon.img and b/Melon.img differ -- cgit v1.2.3