Created
April 29, 2019 02:27
-
-
Save kanzwataru/1b1202a1792802d731675d782836e1fd to your computer and use it in GitHub Desktop.
MS-DOS Protected Mode (DOS/4GW) Test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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