Skip to content

Instantly share code, notes, and snippets.

@kanzwataru
Created April 29, 2019 02:27
Show Gist options
  • Select an option

  • Save kanzwataru/1b1202a1792802d731675d782836e1fd to your computer and use it in GitHub Desktop.

Select an option

Save kanzwataru/1b1202a1792802d731675d782836e1fd to your computer and use it in GitHub Desktop.
MS-DOS Protected Mode (DOS/4GW) Test
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#define STAR_MAX 128
#define STAR_DARK 16
#define STAR_BRIGHT 31
#define STAR_SHIFT 4
#define STAR_SPEED 5
struct Vector {
int x, y, z;
};
unsigned char *vga_mem = (unsigned char *)0xA0000;
unsigned short *txt_mem = (unsigned short *)0xB8000;
int lin = 0;
int col = 0;
struct Vector stars[STAR_MAX];
void modeswitch(unsigned char mode) {
_asm {
mov al, mode
int 0x10
}
}
void vsync(void) {
while(inp(0x03da) & 8) {}
while(!(inp(0x03da) & 8)) {}
}
unsigned short *output_text(unsigned short *t, char *text, char properties) {
size_t i;
size_t length = strlen(text);
for(i = 0; i < length; ++i) {
if(text[i] == 0x0A) {
++col;
lin = 0;
}
else if(text[i] == 0x20) {
++lin;
if(t)
++t;
}
else {
++lin;
if(t)
*t++ = properties << 8 | text[i];
else
txt_mem[col * 80 + lin] = properties << 8 | text[i];
}
}
return txt_mem + (col * 80 + lin);
}
float remap(float value, float oldmin, float oldmax, float newmin, float newmax)
{
float real_range = oldmax - oldmin;
float new_range = newmax - newmin;
return (((value - oldmin) * new_range) / real_range) + newmin;
}
void draw_star(struct Vector star) {
float k, x, y;
unsigned char col;
star.x >>= STAR_SHIFT; star.y >>= STAR_SHIFT; star.z >>= STAR_SHIFT;
k = 32.0f / star.z;
x = star.x * k + (320 / 2);
y = star.y * k + (200 / 2);
col = (int)remap(star.z, 25, 0, STAR_DARK, STAR_BRIGHT);
if(!(x >= 320 || x <= 0 || y >= 200 || y <= 0))
vga_mem[(int)y * 320 + (int)x] = col;
}
int main(void) {
int i;
unsigned short *t = txt_mem;
char buf[512];
size_t size = 64000;
void *mem = NULL;
srand(0);
memset(t, 0, 4000);
sprintf(buf, "\n\n size of int is: %d\n", sizeof(int));
output_text(NULL, buf, 0x07);
if(sizeof(int) == 4) {
output_text(NULL, "Now we're cooking with gas!!\n\n", 0x82);
t = output_text(NULL, " Allocating size: ", 0x07);
while((mem = malloc(size)) != NULL) {
sprintf(buf, "%zu KB (%zu MB)", size / 1000, size / 1000000);
memset(t, 0, 256);
output_text(t, buf, 0x0F);
size += 64000;
free(mem);
}
}
else {
output_text(NULL, "16-bit real mode it is then...\n", 0x04);
}
output_text(NULL, "\n\nTime for more stuff?: ", 0x07);
getch();
output_text(NULL, "\nGoing into mode 13h!!\n", 0x85);
modeswitch(0x13);
//replace_pit_interrupt();
do {
memset(vga_mem + 320 * (rand() % 200), rand(), 320);
vsync();
} while(!kbhit());
getch();
for(i = 0; i < STAR_MAX; ++i) {
stars[i].x = ((rand() % 50) - 25) << STAR_SHIFT;
stars[i].y = ((rand() % 50) - 25) << STAR_SHIFT;
stars[i].z = ((rand() % 50) - 25) << STAR_SHIFT;
}
do {
memset(vga_mem, 0, 320 * 200);
for(i = 0; i < STAR_MAX; ++i) {
stars[i].z -= STAR_SPEED;
if(stars[i].z < 0) {
stars[i].z = 25 << STAR_SHIFT;
stars[i].x = ((rand() % 50) - 25) << STAR_SHIFT;
stars[i].y = ((rand() % 50) - 25) << STAR_SHIFT;
}
draw_star(stars[i]);
}
vsync();
} while(!kbhit());
modeswitch(0x03);
//restore_pit_interrupt();
return 0;
}
/*
* タイマーなどの割り込みを置き換えるのは拡張メモリーではめっちゃくちゃ難しくなっちゃうからとりえあず放置
typedef void interrupt (*handler_t)(void);
handler_t old_pit_handler;
long freq_div = 1000;
long prev_slow_tick = 0;
long time_counter = 0;
void interrupt pit_handler(void) {
long slow_tick;
_asm cli
slow_tick = time_counter * 1193182 / (freq_div * 65536);
time_counter++;
if(slow_tick != prev_slow_tick){
prev_slow_tick = slow_tick;
old_pit_handler();
}
else {
outp(0x20, 0x20);
}
_asm sti
printf("yos\n");
}
void *selector_to_addr(unsigned short selector, unsigned short offset) {
union REGS r;
union SREGS s;
r.x.eax = 0x0006;
r.x.bx = selector;
int386(0x31, &r, &r);
return (void *)((r.x.cx << 4 | r.x.dx) + offset);
}
void pm_setvect(handler_t vector) {
}
handler_t pm_getvect(void) {
union REGS r;
union SREGS s;
r.x.eax = 0x0204;
r.h.bl = 0x08;
int386(0x31, &r, &r);
return selector_to_addr((unsigned short)r.x.ecx, (unsigned short)r.x.edx);
}
void replace_pit_interrupt(void) {
long speed = 1193182 / freq_div;
old_pit_handler = _dos_getvect(0x08);
outp(0x43, 0x36);
outp(0x40, speed % 0x100);
outp(0x40, speed / 0x100);
_dos_setvect(0x08, pit_handler);
}
void restore_pit_interrupt(void) {
outp(0x43, 0x36);
outp(0x40, 0xFF);
outp(0x40, 0xFF);
_dos_setvect(0x08, old_pit_handler);
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment