如何以最简方式为自制小型操作系统实现720p/16位色图形模式?
问题描述
我正在开发一款小型操作系统,受够了VGA模式320x200分辨率、8位色的限制。不想重构全部代码,目标是以最简方式实现720p分辨率与16位色显示。以下是我的部分代码:
boot.asm
[org 0x7c00] KERNEL_LOCATION equ 0x1000 mov [BOOT_DISK], dl xor ax, ax mov es, ax mov ds, ax mov bp, 0x8000 mov sp, bp mov bx, KERNEL_LOCATION mov dh, 32 mov ah, 0x02 mov al, dh mov ch, 0x00 mov dh, 0x00 mov cl, 0x02 mov dl, [BOOT_DISK] int 0x13 mov ah, 0x00 mov al, 0x13 int 0x10 ; text mode CODE_SEG equ GDT_code - GDT_start DATA_SEG equ GDT_data - GDT_start cli lgdt [GDT_descriptor] mov eax, cr0 or eax, 1 mov cr0, eax jmp CODE_SEG:start_protected_mode jmp $ BOOT_DISK: db 0 GDT_start: GDT_null: dd 0x0 dd 0x0 GDT_code: dw 0xffff dw 0x0 db 0x0 db 0b10011010 db 0b11001111 db 0x0 GDT_data: dw 0xffff dw 0x0 db 0x0 db 0b10010010 db 0b11001111 db 0x0 GDT_end: GDT_descriptor: dw GDT_end - GDT_start - 1 dd GDT_start [bits 32] start_protected_mode: mov ax, DATA_SEG mov ds, ax mov ss, ax mov es, ax mov fs, ax mov gs, ax mov ebp, 0x90000 ; 32 bit stack base pointer mov esp, bp jmp KERNEL_LOCATION times 510-($-$$) db 0 dw 0xaa55
kernel.cpp
typedef unsigned char uint8_t; typedef unsigned char u8; typedef unsigned short uint16_t; typedef unsigned int u32; typedef u32 size_t; #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 200 #define SCREEN_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT) #define FPS 30 #define PIT_HERTZ 1193131.666 #define CLOCK_HIT (int)(PIT_HERTZ/FPS) #define KEY_LEFT 0x4B #define KEY_UP 0x48 #define KEY_RIGHT 0x4D #define KEY_DOWN 0x50 static uint8_t *BUFFER = (uint8_t *) 0xA0000; // double buffers uint8_t _sbuffers[2][SCREEN_SIZE]; uint8_t _sback = 0; #define CURRENT (_sbuffers[_sback]) #define SWAP() (_sback = 1 - _sback) #define screen_buffer() (_sbuffers[_sback]) #define screen_set(_p, _x, _y)\ (_sbuffers[_sback][((_y) * SCREEN_WIDTH + (_x))]=(_p)) static inline void outb(uint16_t port, uint8_t val) { asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); } static inline uint8_t inb(uint16_t port) { uint8_t ret; asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) ); return ret; } const unsigned char font[128-32][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+0020 (space) /*deleted to aid in shorter code...*/ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F }; static inline void *memcpy(void *dst, const void *src, size_t n) { u8 *d = (u8*)dst; const u8 *s = (const u8*)src; while (n-- > 0) { *d++ = *s++; } return d; } void screen_swap() { memcpy(BUFFER, CURRENT, SCREEN_SIZE); SWAP(); } unsigned read_pit(void) { unsigned count = 0; // al = channel in bits 6 and 7, remaining bits clear outb(0x43,0b0000000); count = inb(0x40); // Low byte count |= inb(0x40)<<8; // High byte return count; } void draw_char(char c, int x, int y, unsigned char color) { const unsigned char *glyph = font[(int)c-32]; for(int cy=0;cy<8;cy++){ for(int cx=0;cx<8;cx++){ if(((int)glyph[cy]&(1<<cx))==(1<<cx)){ screen_set(color,x+cx,y+cy); } } } } void draw_string(const char * s, int x, int y, unsigned char color) { int i = 0; while(s[i] != false) { draw_char(s[i],x+(i*8),y,color); i++; } } void draw_rect(int pos_x, int pos_y, int w, int h, unsigned char color) { for(int y = 0; y<h; y++) { for(int x = 0; x<w; x++) { screen_set(color,x+pos_x,y+pos_y); } } }
内容的提问来源于stack exchange,提问作者user17400329
相关产品推荐
相关产品推荐

