[英]What is the simplest way to get a higher resolution Graphics Mode?
我正在开发一个小型操作系统,我已经决定我已经厌倦了 VGA 的 320x200 8 位颜色限制。 我真的不想重构我所有的代码,所以我的目标是实现获得 720p 和 16 位颜色的最简单方法。 这是我的一些代码(以及我的 GitHub 的链接):
启动.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, ebp
jmp KERNEL_LOCATION
times 510-($-$$) db 0
dw 0xaa55
内核.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);
}
}
}
由于您的目标是 16 位颜色,因此建议使用更高的 VGA 640x480 分辨率不会为您解决问题!
您需要切换到 VESA 视频模式。 来自https://vesa.org/的“VESA BIOS EXTENSION (VBE) Core Function Standard v3”是您应该阅读的文档。
与您的图形问题无关,但重要的是引导加载程序代码中的错误。 而且因为我看到你不断重新发布这些错误,我发现你解决这些问题很紧迫......
mov [BOOT_DISK], dl
指令已经依赖于正确的 DS 段寄存器。 您必须在设置段寄存器后存储 DL。xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax ; \
mov sp, 0x8000 ; /
mov [BOOT_DISK], dl
和
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax ; \
mov esp, 0x00090000 ; / 32 bit stack base pointer
mov ebp, esp ; Only if you need this!
在 BIOS.LoadSectors 函数 02h 之后,您不能省略检查错误状态! 如果发生错误,请重试操作几次,然后失败并显示合适的消息。
评论你的代码,写出真实的评论! with mov ah, 0x00
mov al, 0x13
int 0x10 ; text mode
int 0x10 ; text mode
,您正在设置图形模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.