Code:
#define WHITE_TXT 0x07 // white on black text
//---------------------------------------------------
//
// Color palette addresses
//
#define PAL_WRITE_ADDR (0x3c8) // palette write address
#define PAL_READ_ADDR (0x3c7) // palette write address
#define PAL_DATA (0x3c9) // palette data register
#define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
#define FP_OFF(fp) (*((unsigned *)&(fp)))
#define NULL 0
//---------------------------------------------------
//
// VBE modes.
//
// Note that ALL standard VGA video modes can be used
// with the vbe functions.
//
#define t40x25 0x003
#define g320x200c256 0x013
#define g640x400c256 0x100
#define g640x480c256 0x101
#define g800x600c16 0x102
#define g800x600c256 0x103
#define g1024x768c16 0x104
#define g1024x768c256 0x105
#define g1280x1024c16 0x106
#define g1280x1024c256 0x107
#define t80x60 0x108
#define t132x25 0x109
#define t132x43 0x10a
#define t132x50 0x10b
#define t132x60 0x10c
#define g320x200c32k 0x10d
#define g320x200c64k 0x10e
#define g320x200c16m 0x10f
#define g640x480c32k 0x110
#define g640x480c64k 0x111
#define g640x480c16m 0x112
#define g800x600c32k 0x113
#define g800x600c64k 0x114
#define g800x600c16m 0x115
#define g1024x768c32k 0x116
#define g1024x768c64k 0x117
#define g1024x768c16m 0x118
#define g1280x1024c32k 0x119
#define g1280x1024c64k 0x11a
#define g1280x1024c16m 0x11b
#define ptrszint signed long long
#define ptrszuint unsigned long long
#define ptrsz 8
//img_struct flags
#define IMG_FREEPAL 1 //free palette data before freeing image_struct
#define IMG_SCREEN 2 //img is linked to other screen pages
#define IMG_FREEMEM 4 //if set, memory must be freed
typedef enum __attribute__ ((packed)) {
FALSE = 0, TRUE = 1
} _bool;
typedef struct __attribute__ ((packed)) {
unsigned char video_memory_model;
unsigned char number_of_planes;
_bool packed_pixel;
_bool planer;
} _memory_model;
typedef struct __attribute__ ((packed)) {
_bool color_mode;
_bool graphics_mode;
_bool text_mode;
_bool bank_A_exists;
_bool bank_A_readable;
_bool bank_A_writable;
_bool bank_B_exists;
_bool bank_B_readable;
_bool bank_B_writable;
unsigned char bank_granularity;
unsigned char bank_size;
unsigned char *bank_A_start;
unsigned char *bank_B_start;
unsigned char *positioning_function;
unsigned short int bytes_per_scanline;
unsigned short int width;
unsigned short int height;
unsigned short int char_width;
unsigned short int char_height;
unsigned short int number_of_planes;
unsigned short int bits_per_pixel;
unsigned short int number_of_banks;
_memory_model memory_model;
unsigned short int images_pages;
unsigned short int red_mask_size;
unsigned short int green_mask_size;
unsigned short int blue_mask_size;
unsigned short int alpha_mask_size;
unsigned short int rsvd_mask;
unsigned short int red_field_pos;
unsigned short int green_field_pos;
unsigned short int blue_field_pos;
unsigned short int alpha_field_pos;
_bool color_map_is_programmable;
unsigned char rsvd[255];
} _mode_info;
_mode_info video;
typedef signed char _int8;
typedef signed short int _int16;
typedef signed long int _int32;
typedef signed long long _int64;
typedef unsigned char _uint8;
typedef unsigned short int _uint16;
typedef unsigned long int _uint32;
typedef unsigned long long _uint64;
typedef float _float32;
typedef double _float64;
//QBOS string descriptor table
typedef struct __attribute__ ((packed)) {
signed long int fileno;
signed long long fileid;
signed long long size;
signed long long offset;
} qbs_field;
typedef struct __attribute__ ((packed)) {
unsigned char *ch; //a 32-bit pointer to string data
unsigned long int len; //
unsigned char in_cmem; //set to 1 if in the conventional memory DBLOCK
unsigned short int *cmem_descriptor; //
unsigned short int cmem_descriptor_offset; //
unsigned long int listi; //the index int the list of strings that it references it
unsigned char tmp; //set to 1 if the string can be deleted immadiately after being processed
unsigned long int tmplisti; //the index in the list of strings that references it
unsigned char fixed; //fixed length string
unsigned char readonly; //set to 1 if string is read only
qbs_field *feild;
} qbs;
typedef struct __attribute__ ((packed)) {
unsigned char valid; //0, 1 0=invalid
unsigned char text; //if set, surface is a text surface
unsigned short int width, height; //
unsigned char bytes_per_pixel; //1,2,3,4
unsigned char bits_per_pixel; //1,2,4,8,12,15,16,24,32
unsigned long int mask; //1,3,0xF,0xFF,0xFFFF,0xFFFFFFFF
unsigned short int compatible_mode; //0,1,2,7,8,9,10,11,12,12-bit,13,15,16,24,32
unsigned long int color, background_color, draw_color; //
unsigned long int font; //8,14,16,?
signed short int top_row, bottom_row; //VIEW PRINT settings, unique (as in QB) to each "page"
signed short int cursor_x, cursor_y; //unique (as in QB) to each "page"
unsigned char cursor_show, cursor_firstvalue, cursor_lastvalue; //
union { //
unsigned char *offset; //
unsigned long int *offset32; //
}; //
unsigned long int flags; //
unsigned long int *pal; //
signed short int transparent_color; //-1 means no color is transperent
unsigned char alpha_disabled; //
unsigned char holding_cursor; //
unsigned char print_mode; //
//BEGIN apm ('active page migration')
//everything between apm points is migrated during active page changes
//note: apm data is only relevent to graphics modes
unsigned char apm_p1;
signed long int view_x1, view_y1, view_x2, view_y2;
signed long int view_offset_x, view_offset_y;
float x, y;
unsigned char clipping_or_scaling;
float caling_x, scaling_y, scaling_offset_x, scaling_offset_y;
float window_x1, window_y1, window_x2, window_y2;
double draw_ta;
double draw_scale;
unsigned amp_p2;
//END apm
} img_struct;
typedef struct __attribute__ ((packed)) {
unsigned short di, si, bp, sp, bx, dx, cx, ax;
unsigned short gs, fs, es, ds, eflags;
} regs16_t;
//format:[deadkey's symbol in UTF16], [ASCII code of letter], ,[resulting UTF16 character]...0
static unsigned short int deadchar_lookup[] = {
96,97,224,96,65,192,180,97,225,180,65,193,94,97,226,94,65,194,126,97,227,126,65,195,168,97,228,168,65,196,730,97,229,730,65,197,180,99,263,94,99,265,96,101,232,96,69,200,180,101,233,180,69,201,94,101,234,94,69,202,126,101,7869,168,101,235,168,69,203,180,103,501,94,103,285,94,104,293,168,104,7719,96,105,236,96,73,204,180,105,237,180,73,205,94,105,238,94,73,206,126,105,297,168,105,239,168,73,207,94,106,309,180,107,7729,180,108,314,180,109,7743,96,110,505,180,110,324,126,110,241,126,78,209,96,111,242,96,79,210,180,111,243,180,79,211,94,111,244,94,79,212,126,111,245,126,79,213,168,111,246,168,79,214,180,112,7765,180,114,341,180,115,347,94,115,349,168,116,7831,96,117,249,96,85,217,180,117,250,180,85,218,94,117,251,94,85,219,126,117,361,168,117,252,168,85,220,730,117,367,126,118,7805,96,119,7809,180,119,7811,94,119,373,168,119,7813,730,119,7832,168,120,7821,96,121,7923,180,121,253,180,89,221,94,121,375,126,121,7929,168,121,255,168,89,376,730,121,7833,180,122,378,94,122,7825
,0
};
static unsigned short int codepage437_to_unicode16[] = {
0x0020,0x263A,0x263B,0x2665,0x2666,0x2663,0x2660,0x2022,0x25D8,0x25CB,0x25D9,0x2642,0x2640,0x266A,0x266B,0x263C,
0x25BA,0x25C4,0x2195,0x203C,0x00B6,0x00A7,0x25AC,0x21A8,0x2191,0x2193,0x2192,0x2190,0x221F,0x2194,0x25B2,0x25BC,
0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,
0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,
0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,
0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,
0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x2302,
0x00C7,0x00FC,0x00E9,0x00E2,0x00E4,0x00E0,0x00E5,0x00E7,0x00EA,0x00EB,0x00E8,0x00EF,0x00EE,0x00EC,0x00C4,0x00C5,
0x00C9,0x00E6,0x00C6,0x00F4,0x00F6,0x00F2,0x00FB,0x00F9,0x00FF,0x00D6,0x00DC,0x00A2,0x00A3,0x00A5,0x20A7,0x0192,
0x00E1,0x00ED,0x00F3,0x00FA,0x00F1,0x00D1,0x00AA,0x00BA,0x00BF,0x2310,0x00AC,0x00BD,0x00BC,0x00A1,0x00AB,0x00BB,
0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556,0x2555,0x2563,0x2551,0x2557,0x255D,0x255C,0x255B,0x2510,
0x2514,0x2534,0x252C,0x251C,0x2500,0x253C,0x255E,0x255F,0x255A,0x2554,0x2569,0x2566,0x2560,0x2550,0x256C,0x2567,
0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256B,0x256A,0x2518,0x250C,0x2588,0x2584,0x258C,0x2590,0x2580,
0x03B1,0x00DF,0x0393,0x03C0,0x03A3,0x03C3,0x00B5,0x03C4,0x03A6,0x0398,0x03A9,0x03B4,0x221E,0x03C6,0x03B5,0x2229,
0x2261,0x00B1,0x2265,0x2264,0x2320,0x2321,0x00F7,0x2248,0x00B0,0x2219,0x00B7,0x221A,0x207F,0x00B2,0x25A0,0x0020
};
void kclear_screen();
unsigned int kprintf(char *message, unsigned int line);
extern void int32(unsigned char intnum, regs16_t *regs);
void update_cursor(int row, int col);
unsigned char inportb(unsigned int port);
unsigned char inportw(unsigned int port);
void outportb(unsigned int port,unsigned char value);
void outportw(unsigned int port,unsigned int value);
void int32_test();
int screen(unsigned short int mode);
void write_video_buffer(unsigned long int x, unsigned long int y, unsigned long int c);
int set_bank_b(unsigned short int addr);
int set_bank_b(unsigned short int addr);
void draw_line(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c);
void write_text(char *message, unsigned long int x, unsigned long int y, unsigned long int c);
void draw_box(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c, unsigned char filled);
void draw_window(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c, char *message);
void plot4points(signed long int cx, signed long int cy, signed long int x, signed long int y, signed long int c);
void plot8points(signed long int cx, signed long int cy, signed long int x, signed long int y, signed long int c);
void draw_circle(signed long int cx, signed long int cy, signed long int radius, signed long int c);
unsigned long int _lrotl(unsigned long int word, unsigned long int shift);
signed long long int qbr(long double f);
unsigned long long int qbr_longdouble_to_uint64(long double f);
signed long int qbr_float_to_long(float f);
signed long int qbr_double_to_long(double f);
unsigned long long getubits(unsigned long int bsize, unsigned char *base, ptrszint i);
unsigned long long getbits(unsigned long int bsize, unsigned char *base, ptrszint i);
void setbits(unsigned long int bsize, unsigned char *base, ptrszint i, signed long long val);
unsigned short int convert_unicode(unsigned short int src_fmt, void *src_buf, unsigned short int src_size, unsigned short int dest_fmt, void *dest_buf);
unsigned char *vbemem = (unsigned char *) 0xA0000, Bpp;
unsigned long int ScrWidth, ScrHeight, FontSeg, FontOffset;
unsigned long int NewBank, Bank, Power2[15];
unsigned short int Ww = 0xFFFF;
static signed long long bmask, bval64;
static unsigned long long *bptr64;
signed long int lock_mainloop = 0, lpos = 1, width_lprint = 80;
signed long int autodisplay = 1, key_display_state = 0, keydown_glyph=0;
signed long int key_display = 0, key_display_redraw = 0, qbOS_ime_reading=0;
//keyhit cyclic buffer
//keyhit specific internal flags: (stored in high 32-bits)
//&429467296->numpad was used
//note: if full, the oldest message is discarded to make way for the next message
signed long long keyhit[8192], keyhit_nextfree=0, keyhit_next = 0;
unsigned long int bindkey=0;
void kmain( void* mbd, unsigned int magic )
{
int y, x;
if ( magic != 0x2BADB002 )
{
/* Something went not according to specs. Print an error */
/* message and halt, but do *not* rely on the multiboot */
/* data structure. */
}
/* You could either use multiboot.h */
/* (http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh) */
/* or do your offsets yourself. The following is merely an example. */
char * boot_loader_name =(char*) ((long*)mbd)[16];
/* Print a letter to screen to see everything is working: */
unsigned char *videoram = (unsigned char *) 0xb8000;
//int32_test;
screen(0x101);
/*while(y < 200)
{
draw_line(0, y, 320, y, y);
y++;
}*/
draw_circle(50, 50, 50, 29);
//draw_window(110, 60, 220, 120, 29, "");
//draw_box(1, 1, 50, 50, 7, TRUE);
//write_text("Hello World", 10, 1, 7);
//kclear_screen();
// wait for key
regs16_t regs;
regs.ax = 0x0000;
int32(0x16, ®s);
screen(t40x25);
kprintf("Hi!\nHow's this for a starter OS?", 0);
/* Write your kernel here. */
}
void kclear_screen() // clear the entire text screen
{
char *vidmem = (char *) 0xb8000;
unsigned short i=0;
while(i < (80*24*2))
{
vidmem[i]=' ';
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
// the message, col, row, forground color, background color, blink flag
unsigned int kprintf(char *message, unsigned int line) // the message and then the line #
{
char *vidmem = (char *) 0xb8000;
unsigned short int i=0;
i=(line*80*2);
while(*message!=0)
{
if(*message=='\n') // check for a new line
{
line++;
i=(line*80*2);
*message++;
} else {
vidmem[i]=*message;
*message++;
i++;
vidmem[i]=WHITE_TXT;
i++;
};
};
return(1);
};
/* Input a byte from a port */
unsigned char inportb(unsigned int port)
{
unsigned char ret;
asm volatile ("inb %%dx,%%al":"=a" (ret):"d" (port));
return ret;
};
/* Output a byte to a port */
void outportb(unsigned int port,unsigned char value)
{
asm volatile ("outb %%al,%%dx": :"d" (port), "a" (value));
};
/* Input a word from a port */
unsigned char inportw(unsigned int port)
{
unsigned char ret;
asm volatile ("inw %%dx,%%ax":"=a" (ret):"d" (port));
return ret;
};
/* Output a word to a port */
void outportw(unsigned int port,unsigned int value)
{
asm volatile ("outw %%ax,%%dx": :"d" (port), "a" (value));
};
void update_cursor(int row, int col)
{
unsigned short position=(row*80) + col;
// cursor LOW port to vga INDEX register
outportb(0x3D4, 0x0F);
outportb(0x3D5, (unsigned char)(position&0xFF));
// cursor HIGH port to vga INDEX register
outportb(0x3D4, 0x0E);
outportb(0x3D5, (unsigned char)((position>>8)&0xFF));
};
// int32 test
void int32_test()
{
int y;
regs16_t regs;
// switch to 320x200x256 graphics mode
regs.ax = 0x0013;
int32(0x10, ®s);
for(y = 0; y < 200; y++)
vbemem[y] = y;
// wait for key
regs.ax = 0x0000;
int32(0x16, ®s);
// switch to 80x25x16 text mode
regs.ax = 0x0003;
int32(0x10, ®s);
};
int screen(unsigned short int mode)
{
unsigned short int k;
for(k=0; k<14; k++)
Power2[k] = 2 ^ k;
regs16_t regs;
regs.ax = 0x4F02;
regs.bx = mode;
int32(0x10, ®s);
regs.ax = 0x1130;
regs.bx = 6 * 256;
int32(0x10, ®s);
FontSeg = regs.es;
FontOffset = regs.bp;
switch(mode)
{
case 0x013:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 320;
video.width = 320;
video.height = 200;
video.char_width = 8;
video.char_height = 8;
video.bits_per_pixel = 8;
break;
case 0x100:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 640;
break;
case 0x101:
video.bank_A_start = (unsigned char *) 0xA0000; //liner framebuffer 0xd0000000;
video.bytes_per_scanline = 640;
break;
case 0x102:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 100;
break;
case 0x103:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 800;
break;
case 0x104:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 128;
break;
case 0x105:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1024;
break;
case 0x106:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 160;
break;
case 0x107:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1280;
break;
case 0x108:
video.bank_A_start = (unsigned char *) 0xB8000;
video.bytes_per_scanline = 160;
break;
case 0x109:
video.bank_A_start = (unsigned char *) 0xB8000;
video.bytes_per_scanline = 286;
break;
case 0x10A:
video.bank_A_start = (unsigned char *) 0xB8000;
video.bytes_per_scanline = 264;
break;
case 0x10C:
video.bank_A_start = (unsigned char *) 0xB8000;
video.bytes_per_scanline = 264;
break;
case 0x10D:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 640;
case 0x10E:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 640;
case 0x110:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1280;
case 0x111:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1280;
case 0x113:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1600;
case 0x114:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1600;
case 0x116:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 2048;
case 0x117:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 2048;
case 0x119:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 2560;
case 0x11A:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 2400;
case 0x120:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 1600;
case 0x140:
video.bank_A_start = (unsigned char *) 0xA0000;
video.bytes_per_scanline = 320;
};
return (regs.ax == 0x004F);
};
int set_bank_a(unsigned short int addr)
{
regs16_t regs;
regs.ax = 0x4F05;
regs.bx = 0x0000;
regs.dx = (addr / 65536);
int32(0x10, ®s);
Bank = NewBank;
return (regs.ax == 0x004F);
};
int set_bank_b(unsigned short int addr)
{
regs16_t regs;
regs.ax = 0x4F05;
regs.bx = 0x0001;
regs.dx = (addr / 65536);
int32(0x10, ®s);
return (regs.ax == 0x004F);
};
void write_video_buffer(unsigned long int x, unsigned long int y, unsigned long int c)
{
//if(NewBank!=Bank){set_bank_a(NewBank);}
video.bank_A_start[((y * video.bytes_per_scanline) + x)] = c;
};
void draw_line(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c)
{
unsigned long int r, a, x, y;
double s;
r = x2 - x1;
a = y2 - y1;
if(a==0){
for(x=x1; x<x2; x++)
write_video_buffer(x, y1, c);
}else if(r==0){
for(y=y1; y<y2; y++)
write_video_buffer(x1, y, c);
}else if(r>a){
s = a / r;
for(x=x1; x<x2; x++){
y= y1 + (s * (x - x1));
write_video_buffer(x, y, c);
};
}else{
s = r / a;
for(y=y1; y<y2; y++){
x = x1 + (s * (y - y1));
write_video_buffer(x, y, c);
};
};
};
void write_text(char *message, unsigned long int x, unsigned long int y, unsigned long int c)
{
unsigned long int j, k, i=1;
unsigned long int byte, letter=1;
char *bios_font = (unsigned char *) FontSeg;
while(*message!=0)
{
if(*message=='\n')
{
x = x + video.char_height; y = 0;
*message++;
}else{
letter = *message;
for(j=0; j<1; j++)
{
byte = bios_font[16 * letter + j + FontOffset];
for(k=0; k<7; k++)
if(byte & Power2[k]){write_video_buffer(x - k - 1 + 8 * i, y + j, c);}
};
*message++;
i++;
};
};
};
void draw_box(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c, unsigned char filled)
{
unsigned long int x, y;
if(filled)
{
for(x=x1; x<x2; x++)
{
for(y=y1; y<y2; y++)
write_video_buffer(x, y, c);
};
}else{
draw_line(x1, y1, x1, y2, c);
draw_line(x1, y1, x2, y1, c);
draw_line(x1, y2, x2, y2, c);
draw_line(x2, y1, x2, y2, c);
};
};
void draw_window(unsigned long int x1, unsigned long int y1, unsigned long int x2, unsigned long int y2, unsigned long int c, char *message)
{
//Draw Main Box
draw_box(x1, y1, x2, y2, c, TRUE);
draw_box(x1, y1, x2, y2, c - 4, FALSE);
draw_line(x1 + 1, y1 + 1, x1 + 1, y2 - 1, c - 14);
draw_line(x1 + 1, y1 + 1, x2 - 1, y1 + 1, c - 14);
draw_line(x2 + 1, y1, x2 + 1, y2 + 1, c - 21);
draw_line(x1, y2 + 1, x2 + 1, y2 + 1, c - 21);
//Title bar
draw_box(x1 + 4, y1 + 4, x2 - 4, y1 + 22, c - 21, TRUE);
draw_box(x1 + 4, y1 + 4, x2 - 4, y1 + 22, c - 4, FALSE);
draw_line(x2 - 3, y1 + 4, x2 - 3, y1 + 22, c - 14);
draw_line(x1 + 4, y1 + 23, x2 - 3, y1 + 23, c - 14);
//Displays char *message
//write_text(*message, x1 + 7, y1 + 10, c - 4);
//write_text(*message, x1 + 6, y1 + 9, c);
};
// The '(x != 0 && y != 0)' test in the last line of this function
// may be omitted for a performance benefit if the radius of the
// circle is known to be non-zero.
void plot4points(signed long int cx, signed long int cy, signed long int x, signed long int y, signed long int c)
{
write_video_buffer(cx + x, cy + y, c);
if(x!=0){write_video_buffer(cx - x, cy + y, c);};
if(y!=0){write_video_buffer(cx + x, cy - y, c);};
if(x!=0 && y!=0){write_video_buffer(cx-x, cy-y, c);};
};
void plot8points(signed long int cx, signed long int cy, signed long int x, signed long int y, signed long int c)
{
plot4points(cx, cy, x, y, c);
if(x!=y){plot4points(cx, cy, y, x, c);};
}
// 'cx' and 'cy' denote the offset of the circle center from the origin.
void draw_circle(signed long int cx, signed long int cy, signed long int radius, signed long int c)
{
signed long int error = -radius;
signed long int x = radius;
signed long int y = 0;
// The following while loop may altered to 'while(x>y)' for a
// proformance benefit, as long as a call to 'plot4points follows
// the body of the loop. This allows for the elimination of the
// '(x!=y) test in 'plot4points', providing a further benefit.
//
// For the sake of clarity, this is not shown here.
while(x>=y)
{
plot8points(cx, cy, x, y, c);
error += y;
y++;
error += y;
//The following test may be implemented in assembly language in
//most machines by testing the carry flag after adding 'y' to
//the value of 'error' in the previous step, since 'error;
// norminally has a negative value.
if(error>=0)
{
--x;
error -= x;
error -= x;
};
};
};
unsigned long int _lrotl(unsigned long int word, unsigned long int shift)
{
return (word << shift) | (word >> (32 - shift));
};
inline signed long long int qbr(long double f)
{
if(f<0){return(f-0.5f);}else{return(f+0.5f);};
};
unsigned long long int qbr_longdouble_to_uint64(long double f)
{
if(f<0){return(f-0.5f);}else{return(f+0.5f);};
};
signed long int qbr_float_to_long(float f)
{
if(f<0){return(f-0.5f);}else{return(f+0.5f);};
};
signed long int qbr_double_to_long(double f)
{
if(f<0){return(f-0.5f);}else{return(f+0.5f);};
};
//bit-array access functions
unsigned long long getubits(unsigned long int bsize, unsigned char *base, ptrszint i)
{
bmask=~(-(((signed long long)1)<<bsize));
i*=bsize;
return ((*(unsigned long long*)(base+(i>>3)))>>(i&7))&bmask;
}
unsigned long long getbits(unsigned long int bsize, unsigned char *base, ptrszint i)
{
bmask=~(-(((signed long long)1)<<bsize));
i*=bsize;
bval64=((*(unsigned long long*)(base+(i>>3)))>>(i&7))&bmask;
if(bval64&(((signed long long)1)<<(bsize-1))){return bval64|(~bmask);};
return bval64;
}
void setbits(unsigned long int bsize, unsigned char *base, ptrszint i, signed long long val)
{
bmask=-(((unsigned long long)1)<<bsize);
i*=bsize;
bptr64=(unsigned long long*)(base+(i>>3));
*bptr64=(*bptr64&(bmask<<(i&7)))|((val&(~bmask))<<(i&7));
};
unsigned short int convert_unicode(unsigned short int src_fmt, void *src_buf, unsigned short int src_size, unsigned short int dest_fmt, void *dest_buf)
{
/*
important: to ensure enough space is available for the conversion, dest_buf must be at least src_size*4+4 in length
returns: the number of bytes written to dest_buf
fmt values: 1=ASCII(CP437)
8=UTF8
16=UTF16
32=UTF32
*/
static unsigned short int dest_size;
dest_size=0;
//setup source
unsigned char *src_uint8p=NULL;
if(src_fmt==1){
src_uint8p=(unsigned char*)src_buf;
};
unsigned short int *src_uint16p=NULL;
if(src_fmt==16){
src_uint16p=(unsigned short int*)src_buf;
src_size=src_size-(src_size&1); //cull trailing bytes
};
unsigned long int *src_uint32p=NULL;
if(src_fmt==32){
src_uint32p=(unsigned long int*)src_buf;
src_size=src_size-(src_size&3); //cull trailing bytes
};
//setup dest
unsigned short int *dest_uint16p=NULL;
if(dest_fmt==16){
dest_uint16p=(unsigned short int*)dest_buf;
};
unsigned long int *dest_uint32p=NULL;
if(dest_fmt==32){
dest_uint32p=(unsigned long int*)dest_buf;
};
unsigned long int x; //scalar
while(src_size){
//convert src to scalar UNICODE value 'x'
if(src_fmt==1){ //CP437
x=*src_uint8p++;
src_size--;
x=codepage437_to_unicode16[x];
}
if(src_fmt==16){ //UTF16
src_size-=2;
x=*src_uint16p++;
//note: does not handle surrogate pairs yet
}
if(src_fmt==32){ //UTF32
src_size-=4;
x=*src_uint32p++;
}
//convert scalar UNICODE value 'x' to dest
if(dest_fmt==16){ //UTF16
*dest_uint16p++=x;
dest_size+=2;
//note: does not handle surrogate pairs yet
}
if(dest_fmt==32){ //UTF32
*dest_uint32p++=x;
dest_size+=4;
}
} //loop
//add NULL terminator (does not change the size in bytes returned)
if (dest_fmt==16) *dest_uint16p=0;
if (dest_fmt==32) *dest_uint32p=0;
return dest_size;
}