time
This commit is contained in:
parent
fbf131b5c0
commit
8ad6ef551e
18 changed files with 362 additions and 50 deletions
2
.env
2
.env
|
@ -3,7 +3,7 @@ LD=i386-elf-ld
|
||||||
AS=nasm
|
AS=nasm
|
||||||
AR=ar
|
AR=ar
|
||||||
|
|
||||||
CFLAGS=-ffreestanding -m32 -O2 -Wall -Wextra -pedantic -DKERNEL_LOG
|
CFLAGS=-ffreestanding -m32 -O2 -Wall -Wextra -pedantic # -DKERNEL_LOG
|
||||||
LDFLAGS=-nostdlib
|
LDFLAGS=-nostdlib
|
||||||
|
|
||||||
QEMU=qemu-system-i386
|
QEMU=qemu-system-i386
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
/boot
|
/iso
|
||||||
/os.iso
|
/os.iso
|
||||||
/kernel/bin
|
/kernel/bin
|
||||||
/libk/bin
|
/libk/bin
|
||||||
|
|
14
Makefile
14
Makefile
|
@ -1,6 +1,6 @@
|
||||||
include .env
|
include .env
|
||||||
|
|
||||||
.PHONY: all libk kernel
|
.PHONY: all libk kernel clean run
|
||||||
|
|
||||||
all: os.iso
|
all: os.iso
|
||||||
|
|
||||||
|
@ -11,16 +11,16 @@ kernel:
|
||||||
make --directory=kernel
|
make --directory=kernel
|
||||||
|
|
||||||
os.iso: libk kernel
|
os.iso: libk kernel
|
||||||
rm -fr os.iso
|
@rm -fr os.iso
|
||||||
mkdir -p boot/grub
|
@mkdir -p iso/boot/grub
|
||||||
cp grub.cfg boot/grub
|
cp grub.cfg iso/boot/grub
|
||||||
cp kernel/bin/kernel.bin boot
|
cp kernel/bin/kernel.bin iso/boot
|
||||||
grub-mkrescue -o os.iso .
|
grub-mkrescue -o os.iso iso
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
make --directory=libk clean
|
make --directory=libk clean
|
||||||
make --directory=kernel clean
|
make --directory=kernel clean
|
||||||
rm -fr boot
|
rm -fr iso
|
||||||
rm -fr os.iso
|
rm -fr os.iso
|
||||||
|
|
||||||
run:
|
run:
|
||||||
|
|
|
@ -4,7 +4,7 @@ C_SRC = $(shell find src -type f -name "*.c")
|
||||||
C_OBJ = $(patsubst %.c,bin/%.o, $(C_SRC))
|
C_OBJ = $(patsubst %.c,bin/%.o, $(C_SRC))
|
||||||
|
|
||||||
ASM_SRC = $(shell find src -type f -name "*.asm")
|
ASM_SRC = $(shell find src -type f -name "*.asm")
|
||||||
ASM_OBJ = $(patsubst %.asm,bin/%.o, $(ASM_SRC))
|
ASM_OBJ = $(patsubst %.asm,bin/%.asm.o, $(ASM_SRC))
|
||||||
|
|
||||||
CFLAGS += -Iinclude -Isrc -I../libk/include -std=gnu17
|
CFLAGS += -Iinclude -Isrc -I../libk/include -std=gnu17
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ $(C_OBJ): bin/%.o : %.c
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CC) -c $(CFLAGS) -o $@ $<
|
$(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
$(ASM_OBJ): bin/%.o : %.asm
|
$(ASM_OBJ): bin/%.asm.o : %.asm
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(AS) $< -f elf -o $@
|
$(AS) $< -f elf -o $@
|
||||||
|
|
||||||
|
|
30
kernel/include/time.h
Normal file
30
kernel/include/time.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct Time {
|
||||||
|
int sec; /// Seconds [0,59]
|
||||||
|
int min; /// Minutes [0,59]
|
||||||
|
int hour; /// Hour [0,23]
|
||||||
|
int mday; /// Day of month [1,31]
|
||||||
|
int mon; /// Month of year [0,11]
|
||||||
|
int year; /// Years since 1900
|
||||||
|
int wday; /// Day of week [0,6] (Sunday = 0)
|
||||||
|
int yday; /// Day of year [0,365]
|
||||||
|
int yn; /// Year number [0,99]
|
||||||
|
int cen; /// Century [19,20]
|
||||||
|
int leap; /// If year is a leap year (True == 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void rtc_update(void);
|
||||||
|
extern void rtc_set_timezone(int offset);
|
||||||
|
extern struct Time *rtc_utctime(void);
|
||||||
|
extern struct Time *rtc_localtime(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the time into a string format
|
||||||
|
* @param time the current time
|
||||||
|
* @param format see manpage for date
|
||||||
|
* @param buf the buffer to store it in
|
||||||
|
*/
|
||||||
|
extern void timetostr(struct Time *time, char *format, char *buf, size_t n);
|
|
@ -4,7 +4,6 @@
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "acpi/acpi.h"
|
#include "acpi/acpi.h"
|
||||||
#include "graphics/framebuffer.h"
|
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
|
|
||||||
static struct BootInfo info;
|
static struct BootInfo info;
|
||||||
|
@ -18,12 +17,6 @@ static void read_cmdline(struct BootTag *tag, char *data, uint8_t len) {
|
||||||
info.tags[ID_CMDLINE] = *tag;
|
info.tags[ID_CMDLINE] = *tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_framebuffer(struct BootTag *tag, uint32_t *data) {
|
|
||||||
debugk("Found framebuffer");
|
|
||||||
tag->data.framebuffer = (struct Framebuffer *) data;
|
|
||||||
info.tags[ID_FRAMEBUFFER] = *tag;;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void read_memorymap(struct BootTag *tag, uint32_t *data) {
|
static void read_memorymap(struct BootTag *tag, uint32_t *data) {
|
||||||
debugk("Found memorymap");
|
debugk("Found memorymap");
|
||||||
tag->data.memory_map = (struct MemoryMap *) data;
|
tag->data.memory_map = (struct MemoryMap *) data;
|
||||||
|
@ -48,9 +41,6 @@ static uint32_t *read_tag(uint32_t *data) {
|
||||||
case ID_CMDLINE:
|
case ID_CMDLINE:
|
||||||
read_cmdline(&tag, (char *)(data + 2), data_len);
|
read_cmdline(&tag, (char *)(data + 2), data_len);
|
||||||
break;
|
break;
|
||||||
case ID_FRAMEBUFFER:
|
|
||||||
read_framebuffer(&tag, data + 2);
|
|
||||||
break;
|
|
||||||
case iD_MEMORYMAP:
|
case iD_MEMORYMAP:
|
||||||
read_memorymap(&tag, data + 2);
|
read_memorymap(&tag, data + 2);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "acpi/acpi.h"
|
#include "acpi/acpi.h"
|
||||||
#include "graphics/framebuffer.h"
|
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
|
|
||||||
#define CMDLINE_MAX 32
|
#define CMDLINE_MAX 32
|
||||||
|
@ -15,7 +14,6 @@ struct BootTag {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
union {
|
union {
|
||||||
char cmdline[CMDLINE_MAX];
|
char cmdline[CMDLINE_MAX];
|
||||||
struct Framebuffer *framebuffer;
|
|
||||||
struct MemoryMap *memory_map;
|
struct MemoryMap *memory_map;
|
||||||
struct RootSystemDescriptionPointer *rsdp;
|
struct RootSystemDescriptionPointer *rsdp;
|
||||||
} data;
|
} data;
|
||||||
|
@ -30,7 +28,6 @@ struct BootInfo {
|
||||||
enum BootTagID {
|
enum BootTagID {
|
||||||
ID_CMDLINE = 0,
|
ID_CMDLINE = 0,
|
||||||
iD_MEMORYMAP = 6,
|
iD_MEMORYMAP = 6,
|
||||||
ID_FRAMEBUFFER = 8,
|
|
||||||
ID_RSDP = 14
|
ID_RSDP = 14
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ fpu_init:
|
||||||
cmp word [test], 0
|
cmp word [test], 0
|
||||||
jne no_fpu
|
jne no_fpu
|
||||||
|
|
||||||
xor eax, 0
|
mov eax, 0
|
||||||
ret
|
ret
|
||||||
|
|
||||||
no_fpu:
|
no_fpu:
|
||||||
|
|
138
kernel/src/drivers/cmos.c
Normal file
138
kernel/src/drivers/cmos.c
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
#include "print.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define CMOS_WRITE_PORT 0x70
|
||||||
|
#define CMOS_READ_PORT 0x71
|
||||||
|
|
||||||
|
#define CMOS_REG_SEC 0x00
|
||||||
|
#define CMOS_REG_MIN 0x02
|
||||||
|
#define CMOS_REG_HOUR 0x04
|
||||||
|
#define CMOS_REG_WDAY 0x06
|
||||||
|
#define CMOS_REG_MDAY 0x07
|
||||||
|
#define CMOS_REG_MON 0x08
|
||||||
|
#define CMOS_REG_YEAR 0x09
|
||||||
|
#define CMOS_REG_CEN 0x32
|
||||||
|
|
||||||
|
static struct Time time;
|
||||||
|
static struct Time localtime;
|
||||||
|
static int cur_offset = 0;
|
||||||
|
|
||||||
|
static uint8_t cmos_read(uint8_t reg) {
|
||||||
|
uint8_t hex, ret;
|
||||||
|
|
||||||
|
outb(CMOS_WRITE_PORT, reg);
|
||||||
|
hex = inb(CMOS_READ_PORT);
|
||||||
|
|
||||||
|
ret = hex & 0x0F;
|
||||||
|
ret += (hex & 0xF0) / 16 * 10;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mday_offset[12] = {
|
||||||
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||||
|
};
|
||||||
|
|
||||||
|
static int month_days[12] = {
|
||||||
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||||
|
};
|
||||||
|
|
||||||
|
static void update_localtime(void) {
|
||||||
|
|
||||||
|
int change, max;
|
||||||
|
|
||||||
|
// set localtime
|
||||||
|
localtime = time;
|
||||||
|
|
||||||
|
// do we acutally need to do anything
|
||||||
|
if (cur_offset == 0) return;
|
||||||
|
localtime.hour += cur_offset;
|
||||||
|
|
||||||
|
// check if day rolled over
|
||||||
|
change = localtime.hour < 0 ? -1 : localtime.hour >= 24 ? 1 : 0;
|
||||||
|
if (!change) return;
|
||||||
|
|
||||||
|
// roll over day
|
||||||
|
localtime.hour = (localtime.hour + 24) % 24;
|
||||||
|
localtime.wday = (localtime.wday + change + 7) % 7;
|
||||||
|
localtime.mday += change;
|
||||||
|
localtime.yday += change;
|
||||||
|
|
||||||
|
// check if month rolled over
|
||||||
|
max = month_days[localtime.mon];
|
||||||
|
if (localtime.leap && localtime.mon == 1) max++;
|
||||||
|
change = localtime.mday < 0 ? -1 : localtime.mday >= max ? 1 : 0;
|
||||||
|
if (!change) return;
|
||||||
|
|
||||||
|
// roll over month
|
||||||
|
localtime.mon = (localtime.mon + change + 12) % 12;
|
||||||
|
|
||||||
|
// check if year rolled over
|
||||||
|
max = localtime.leap ? 366 : 365;
|
||||||
|
change = localtime.yday < 0 ? -1 : localtime.yday >= max ? 1 : 0;
|
||||||
|
if (!change) return;
|
||||||
|
|
||||||
|
// roll over year
|
||||||
|
localtime.yn += change;
|
||||||
|
|
||||||
|
// check if cen rolled over
|
||||||
|
change = localtime.yn < 0 ? -1 : localtime.yn >= 100 ? 1 : 0;
|
||||||
|
if (!change) goto year;
|
||||||
|
|
||||||
|
// roll over cen
|
||||||
|
localtime.cen += change;
|
||||||
|
|
||||||
|
|
||||||
|
year:
|
||||||
|
|
||||||
|
localtime.year = localtime.yn + localtime.cen * 100;
|
||||||
|
localtime.leap = localtime.year % 4 == 0 && localtime.year % 100 != 0;
|
||||||
|
|
||||||
|
if (localtime.leap && localtime.yday == -1)
|
||||||
|
localtime.yday = 365;
|
||||||
|
else if (localtime.yday == -1)
|
||||||
|
localtime.yday = 364;
|
||||||
|
else
|
||||||
|
localtime.yday = 0;
|
||||||
|
|
||||||
|
localtime.year -= 1900;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_set_timezone(int offset) {
|
||||||
|
cur_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_update(void) {
|
||||||
|
time.sec = cmos_read(CMOS_REG_SEC);
|
||||||
|
time.min = cmos_read(CMOS_REG_MIN);
|
||||||
|
time.hour = cmos_read(CMOS_REG_HOUR);
|
||||||
|
time.wday = cmos_read(CMOS_REG_WDAY) - 1;
|
||||||
|
time.mday = cmos_read(CMOS_REG_MDAY);
|
||||||
|
time.mon = cmos_read(CMOS_REG_MON) - 1;
|
||||||
|
time.yn = cmos_read(CMOS_REG_YEAR);
|
||||||
|
time.cen = 20;
|
||||||
|
|
||||||
|
time.year = time.yn + time.cen * 100;
|
||||||
|
|
||||||
|
time.leap = time.year % 4 == 0 && time.year % 100 != 0;
|
||||||
|
|
||||||
|
time.yday = mday_offset[time.mon] + time.mday;
|
||||||
|
|
||||||
|
if (time.leap && time.mon > 2)
|
||||||
|
time.yday++;
|
||||||
|
|
||||||
|
time.year -= 1900;
|
||||||
|
|
||||||
|
update_localtime();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Time *rtc_utctime(void) {
|
||||||
|
return &time;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Time *rtc_localtime(void) {
|
||||||
|
return &localtime;
|
||||||
|
}
|
0
kernel/src/drivers/vga.c
Normal file
0
kernel/src/drivers/vga.c
Normal file
0
kernel/src/drivers/vga.h
Normal file
0
kernel/src/drivers/vga.h
Normal file
|
@ -1,15 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
struct Framebuffer {
|
|
||||||
uint64_t addr;
|
|
||||||
uint32_t pitch;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
uint8_t depth;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t reserved;
|
|
||||||
// struct FramebufferPallete palettes[];
|
|
||||||
|
|
||||||
} __attribute__ ((packed));
|
|
|
@ -9,25 +9,35 @@
|
||||||
#include "acpi/acpi.h"
|
#include "acpi/acpi.h"
|
||||||
#include "drivers/ps2kb.h"
|
#include "drivers/ps2kb.h"
|
||||||
#include "drivers/ps2mouse.h"
|
#include "drivers/ps2mouse.h"
|
||||||
|
#include "time.h"
|
||||||
#include "tty/color.h"
|
#include "tty/color.h"
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "tty/term.h"
|
#include "tty/term.h"
|
||||||
|
|
||||||
static int timer = 0;
|
#define WIDTH 30
|
||||||
|
static char buf[WIDTH];
|
||||||
|
static int timer = -1;
|
||||||
|
|
||||||
void idt_pic_eoi(uint8_t exception) {
|
void idt_pic_eoi(uint8_t exception) {
|
||||||
pic_eoi(exception - PIC_REMAP_OFFSET);
|
pic_eoi(exception - PIC_REMAP_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_pic_timer(void) {
|
void idt_pic_timer(void) {
|
||||||
uint32_t state = term_save();
|
|
||||||
term_setfg(VGA_LIGHT_GREEN);
|
|
||||||
term_setpos(60, 0);
|
|
||||||
puts(" ");
|
|
||||||
term_setpos(60, 0);
|
|
||||||
printk("%d", timer);
|
|
||||||
timer += 1;
|
timer += 1;
|
||||||
|
if (timer % 20 != 0) return;
|
||||||
|
|
||||||
|
uint32_t state = term_save();
|
||||||
|
|
||||||
|
term_setfg(VGA_LIGHT_GREEN);
|
||||||
|
term_setpos(TERM_W - WIDTH - 1, 0);
|
||||||
|
for (size_t i = 0; i < WIDTH; i++) putchar(' ');
|
||||||
|
term_setpos(TERM_W - WIDTH - 1, 0);
|
||||||
|
|
||||||
|
timetostr(rtc_localtime(), "%a %b %d %Y %H:%M:%S", buf, WIDTH);
|
||||||
|
printk("%s", buf);
|
||||||
|
|
||||||
term_load(state);
|
term_load(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "drivers/ps2mouse.h"
|
#include "drivers/ps2mouse.h"
|
||||||
#include "interrupt/idt.h"
|
#include "interrupt/idt.h"
|
||||||
#include "interrupt/pic.h"
|
#include "interrupt/pic.h"
|
||||||
|
#include "time.h"
|
||||||
#include "tty/cursor.h"
|
#include "tty/cursor.h"
|
||||||
#include "tty/term.h"
|
#include "tty/term.h"
|
||||||
|
|
||||||
|
@ -21,6 +22,9 @@ void kernel_main(void* boot_info) {
|
||||||
term_init();
|
term_init();
|
||||||
cursor_enable();
|
cursor_enable();
|
||||||
|
|
||||||
|
rtc_set_timezone(-4);
|
||||||
|
rtc_update();
|
||||||
|
|
||||||
idt_init();
|
idt_init();
|
||||||
pic_remap(PIC_REMAP_OFFSET);
|
pic_remap(PIC_REMAP_OFFSET);
|
||||||
|
|
||||||
|
@ -64,5 +68,8 @@ void kernel_main(void* boot_info) {
|
||||||
y = fclamp(y, 0, TERM_H);
|
y = fclamp(y, 0, TERM_H);
|
||||||
printk(" x%d y%d\n", (int)x, (int)y);
|
printk(" x%d y%d\n", (int)x, (int)y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term_flush();
|
||||||
|
rtc_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
146
kernel/src/print/time.c
Normal file
146
kernel/src/print/time.c
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static char* ABB_WEEKDAY[7] = {
|
||||||
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* FULL_WEEKDAY[7] = {
|
||||||
|
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturady"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* ABB_MONTH[12] = {
|
||||||
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* FULL_MONTH[12] = {
|
||||||
|
"January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) {
|
||||||
|
size_t digits = 1;
|
||||||
|
unsigned int x = num;
|
||||||
|
|
||||||
|
while (x /= 10, x > 0) digits++;
|
||||||
|
if (pad == 0) pad = digits;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pad; i++) {
|
||||||
|
|
||||||
|
size_t digit;
|
||||||
|
if (i >= digits) {
|
||||||
|
digit = 0;
|
||||||
|
} else {
|
||||||
|
digit = num % 10;
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pad - i - 1 >= n) continue;
|
||||||
|
buf[pad - i - 1] = '0' + digit;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pad > n) pad = n;
|
||||||
|
|
||||||
|
return buf + pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timetostr(struct Time *time, char *format, char *buf, size_t n) {
|
||||||
|
char *index = buf;
|
||||||
|
char c;
|
||||||
|
int space;
|
||||||
|
|
||||||
|
while (
|
||||||
|
c = *format++,
|
||||||
|
space = (buf + n) - index,
|
||||||
|
c != '\0' && space > 0
|
||||||
|
) {
|
||||||
|
if (c != '%') {
|
||||||
|
*index++ = c;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
c = *format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '%':
|
||||||
|
*index++ = '%';
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
index = strncpy(index, ABB_WEEKDAY[time->wday], space);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
index = strncpy(index, FULL_WEEKDAY[time->wday], space);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case 'h':
|
||||||
|
index = strncpy(index, ABB_MONTH[time->mon], space);
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
index = strncpy(index, FULL_MONTH[time->mon], space);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
index = write_num(time->cen, 0, index, space);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
index = write_num(time->mday, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
index = write_num(time->hour, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
index = write_num((time->hour + 12) % 12 + 1, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
index = write_num(time->yday, 3, index, space);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
index = write_num(time->mon + 1, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
index = write_num(time->min, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
*index++ = '\n';
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
index = strncpy(index, time->hour > 11 ? "PM" : "AM", space);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
index = strncpy(index, time->hour > 11 ? "pm" : "am", space);
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
index = write_num((time->mon + 3) / 3, 0, index, space);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
index = write_num(time->sec, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
*index++ = '\t';
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
index = write_num(((time->wday + 1 )% 7) + 1, 0, index, space);
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
index = write_num(time->wday, 0, index, space);
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
index = write_num(time->yn, 2, index, space);
|
||||||
|
break;
|
||||||
|
case 'Y':
|
||||||
|
index = write_num(time->year + 1900, 0, index, space);
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
char b[3] = {'%', c, '\0'};
|
||||||
|
index = strncpy(index, b, space);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space < 1)
|
||||||
|
buf[n - 1] = '\0';
|
||||||
|
else
|
||||||
|
*index = '\0';
|
||||||
|
}
|
|
@ -9,7 +9,8 @@
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
|
|
||||||
uint16_t *buffer;
|
uint16_t buffer[TERM_W * TERM_H * sizeof(uint16_t)];
|
||||||
|
uint16_t *front;
|
||||||
uint8_t x, y;
|
uint8_t x, y;
|
||||||
uint8_t color;
|
uint8_t color;
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ static void term_clear_line(int y) {
|
||||||
void term_init (void) {
|
void term_init (void) {
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
buffer = (uint16_t*) 0xb8000;
|
front = (uint16_t*) 0xb8000;
|
||||||
term_setfg(VGA_WHITE);
|
term_setfg(VGA_WHITE);
|
||||||
term_setbg(VGA_BLACK);
|
term_setbg(VGA_BLACK);
|
||||||
term_clear();
|
term_clear();
|
||||||
|
@ -129,3 +130,9 @@ void putchar(int c) {
|
||||||
bool term_newline(void) {
|
bool term_newline(void) {
|
||||||
return x == 0;
|
return x == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void term_flush(void) {
|
||||||
|
int_disable();
|
||||||
|
memcpy(front, buffer, TERM_W * TERM_H * sizeof(uint16_t));
|
||||||
|
int_enable();
|
||||||
|
}
|
||||||
|
|
|
@ -25,3 +25,5 @@ uint16_t term_save_col(void);
|
||||||
void term_load_col(uint16_t color);
|
void term_load_col(uint16_t color);
|
||||||
|
|
||||||
bool term_newline(void);
|
bool term_newline(void);
|
||||||
|
|
||||||
|
void term_flush(void);
|
||||||
|
|
Loading…
Reference in a new issue