diff --git a/.gitignore b/.gitignore index 56f681c..58fe60e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,6 @@ Player/player Player/player.wasm Player/Cosmo Master/master -Tools/assets +Tools/Assets Player/Out/Cosmo/player* diff --git a/Common/Std/any.c b/Common/Std/any.c index 0849891..a6065f4 100644 --- a/Common/Std/any.c +++ b/Common/Std/any.c @@ -126,7 +126,7 @@ void com_std_print_(int32_t start, ...) { } while (type != '.'); - com_std_write(COM_STD_OUTFD, "\n", 1); + com_std_write(COM_STD_OUTFD, "\n\r", 2); va_end(args); } diff --git a/Common/Std/dos.c b/Common/Std/dos.c new file mode 100644 index 0000000..cb51eee --- /dev/null +++ b/Common/Std/dos.c @@ -0,0 +1,80 @@ +#include "../std.h" +#include +#include +#include + +#include "any.c" +#include "nolibc.c" + +// void *com_std_alloc(void *ptr, size_t size) { +// return size != 0 ? realloc(ptr, size) : (free(ptr), NULL); +// } + +// double com_std_sqrt(double v) { return sqrt(v); } +// double com_std_fabs(double v) { return fabs(v); } +// double com_std_sin(double v) { return sin(v); } +// double com_std_cos(double v) { return cos(v); } + +// com_std_fd com_std_open(char const *path, uint32_t flags) { +// com_std_assert(flags != 0); +// char *mode = flags & COM_STD_OPEN_READ && flags & COM_STD_OPEN_WRITE ? "r+" +// : flags & COM_STD_OPEN_READ ? "r" +// : "w"; +// return fopen(path, mode); +// } + +bool com_std_write(com_std_fd fd, void const *data, uint32_t bytes) { + uint32_t written; + bool carry_clear; + __asm__ volatile("int $0x21" + : "=a"(written), "=@ccnc"(carry_clear) + : "a"(0x4000), "b"(fd), "c"(bytes), "d"(data) + : "memory", "cc"); + return !carry_clear && written == bytes; +} + +// int32_t com_std_read(com_std_fd fd, void *data, uint32_t upto) { +// com_std_assert(data != NULL && upto != 0); +// return fread(data, 1, upto, fd); +// } + +// bool com_std_has_data(com_std_fd fd) { +// struct pollfd pfd = {.fd = (intptr_t)fd, .events = POLLIN}; +// int ret = poll(&pfd, 1, 0); +// if (ret > 0) { +// return pfd.revents & POLLIN; +// } else +// return false; +// } + +// bool com_std_sfwd(com_std_fd fd, uint32_t bytes) { +// com_std_assert(fd != NULL && bytes != 0); +// return fseek(fd, bytes, SEEK_CUR) == 0; +// } + +// com_std_fd com_std_socket(bool isnetwork) { +// if (!isnetwork) { +// int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); +// return fdopen(sockfd, "w+b"); +// } else +// return NULL; +// } + +// bool com_std_connect(com_std_fd fd, bool isnetwork, char const *address) { +// com_std_assert(address != NULL); +// if (!isnetwork) { +// struct sockaddr_un addr = {.sun_family = AF_UNIX}; +// __builtin_memcpy(&addr.sun_path, address, com_str_ext_len(address)); +// return connect(fileno(fd), (struct sockaddr *)&addr, sizeof(addr)) == 0; +// } else +// return NULL; +// } + +void com_std_exit(int32_t status) { + (void)status; + __asm__ volatile("int $0x21" ::"a"(0x4c00 | (status & 0xff)) + : "memory", "cc"); + __builtin_unreachable(); +} + +// void com_std_close(com_std_fd fd) { fclose(fd); } diff --git a/Common/Std/nolibc.c b/Common/Std/nolibc.c index d1b93a1..263fe2a 100644 --- a/Common/Std/nolibc.c +++ b/Common/Std/nolibc.c @@ -48,7 +48,7 @@ void sincos(double v, double *s, double *c) { double sqrt(double v) { double r; - __asm__ volatile("sqrtss %1, %0" : "=x"(r) : "x"(v)); + __asm__ volatile("rsqrtss %1, %0" : "=x"(r) : "x"(v)); return r; } diff --git a/Common/def.h b/Common/def.h index e896dbf..82dc436 100644 --- a/Common/def.h +++ b/Common/def.h @@ -21,19 +21,25 @@ #define COM_DEF_TARGET_LINUX 1 #define COM_DEF_TARGET_WASM 2 #define COM_DEF_TARGET_COSMO 3 +#define COM_DEF_TARGET_DOS 4 +#ifndef COM_DEF_TARGET #if defined(__wasm__) #define COM_DEF_TARGET COM_DEF_TARGET_WASM -#define com_def_export_sym(m_s) __attribute__((export_name(m_s))) #elif defined(__linux__) #define COM_DEF_TARGET COM_DEF_TARGET_LINUX -#define com_def_export_sym(m_s) __attribute__((visibility("default"))) #elif defined(__COSMOPOLITAN__) #define COM_DEF_TARGET COM_DEF_TARGET_COSMO -#define com_def_export_sym(m_s) __attribute__((visibility("default"))) #else #error Unknown target. #endif +#endif + +#if COM_DEF_TARGET == COM_DEF_TARGET_WASM +#define com_def_export_sym(m_s) __attribute__((export_name(m_s))) +#else +#define com_def_export_sym(m_s) __attribute__((visibility("default"))) +#endif #define COM_DEF_CPU_AMD64 1 #define COM_DEF_CPU_X86 2 diff --git a/Common/std.h b/Common/std.h index d4c79c3..00d7458 100644 --- a/Common/std.h +++ b/Common/std.h @@ -3,6 +3,8 @@ even memory mnagement. */ +/* TODO: Split into io.h and math.h */ + #ifndef COM_STD_H #define COM_STD_H @@ -69,6 +71,9 @@ void com_std_print_(int32_t start, ...); #define com_std_print(...) com_std_print_(__VA_ARGS__, '.') void com_std_print_str(char const *str, uint32_t len, bool newline); +/* Note: Functions listed below are only available for dev builds. */ +/* Trigonometry functions are for reference testing of our own fixed point + * implementations. Do not use otherwise. */ #define COM_STD_PIF ((float)3.14159265358979323846) double com_std_sqrt(double v); @@ -76,9 +81,7 @@ double com_std_fabs(double v); double com_std_sin(double v); double com_std_cos(double v); -/* Note: Functions listed below are only available for dev builds. */ -/* Trigonometry functions are for reference testing of our own fixed point - * implementations. Do not use otherwise. */ +/* TODO: Move to def.h? or just asrt.h? */ #define com_std_assert(p_h) \ do { \ if (!(p_h)) { \ diff --git a/Common/str.h b/Common/str.h index fbb2adc..88f40c9 100644 --- a/Common/str.h +++ b/Common/str.h @@ -24,12 +24,19 @@ typedef struct com_str { uint32_t len; uint32_t flags; char data[] __attribute__((aligned(COM_DEF_ALIGNMENT))); - } com_str; /* NOTE: Have to be moved to static or global memory. */ #define com_str_lit(p_l) {NULL, sizeof(p_l) - 1, COM_STR_NULL_TERMINATED, (p_l)} +static inline void com_str_copy_to_mem(struct com_str *s, char *to, + bool withnull) { + for (int i = 0; i < s->len; ++i) + to[i] = s->data[i]; + if (withnull) + to[s->len] = '\0'; +} + static inline uint32_t com_str_ext_len(char const *s) { char const *p = s; for (; *p != 0; ++p) { diff --git a/Player/Display/dos.c b/Player/Display/dos.c index 846084a..aa84c4e 100644 --- a/Player/Display/dos.c +++ b/Player/Display/dos.c @@ -1,12 +1,13 @@ -#include "../../Common/def.h" +#include "../../Common/std.h" +#include "../../Common/str.h" #include "display.h" #include #include #include #include -#define WIDTH 320 -#define HEIGHT 200 +#define WIDTH 640 +#define HEIGHT 480 #define MODE_VGA_320_200_8 0x13 #define MODE_VESA_640_480_8 0x101 @@ -18,63 +19,94 @@ #define COLOR_NUM 8 #define COLOR_STEP (HEIGHT / COLOR_NUM) -// /* https://wiki.osdev.org/VESA_Video_Modes */ -// _Packed struct VbeInfoBlock { -// char VbeSignature[4]; // == "VESA" -// uint16_t VbeVersion; // == 0x0300 for VBE 3.0 -// uint16_t OemStringPtr[2]; // isa vbeFarPtr -// uint8_t Capabilities[4]; -// uint16_t VideoModePtr[2]; // isa vbeFarPtr -// uint16_t TotalMemory; // as # of 64KB blocks -// uint8_t Reserved[492]; -// }; +intptr_t baseaddr; -// _Packed struct ModeInfoBlock { -// uint16_t -// attributes; // deprecated, only bit 7 should be of interest to you, and -// it -// // indicates the mode supports a linear frame buffer. -// uint8_t window_a; // deprecated -// uint8_t window_b; // deprecated -// uint16_t granularity; // deprecated; used while calculating bank numbers -// uint16_t window_size; -// uint16_t segment_a; -// uint16_t segment_b; -// uint32_t win_func_ptr; // deprecated; used to switch banks from protected -// mode -// // without returning to real mode -// uint16_t pitch; // number of bytes per horizontal line -// uint16_t width; // width in pixels -// uint16_t height; // height in pixels -// uint8_t w_char; // unused... -// uint8_t y_char; // ... -// uint8_t planes; -// uint8_t bpp; // bits per pixel in this mode -// uint8_t banks; // deprecated; total number of banks in this mode -// uint8_t memory_model; -// uint8_t bank_size; // deprecated; size of a bank, almost always 64 KB but -// may -// // be 16 KB... -// uint8_t image_pages; -// uint8_t reserved0; +/* http://www.techhelpmanual.com/649-dpmiregrec.html */ +struct DpmiRegRec { + uint32_t edi; + uint32_t esi; + uint32_t ebi; + uint32_t _reserved; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint16_t flags; + uint16_t es; + uint16_t ds; + uint16_t fs; + uint16_t gs; + uint16_t ip; + uint16_t cs; + uint16_t sp; + uint16_t ss; +} __attribute__((packed)) dpmi_regs; -// uint8_t red_mask; -// uint8_t red_position; -// uint8_t green_mask; -// uint8_t green_position; -// uint8_t blue_mask; -// uint8_t blue_position; -// uint8_t reserved_mask; -// uint8_t reserved_position; -// uint8_t direct_color_attributes; +/* http://www.techhelpmanual.com/602-int_31h_0300h__simulate_real_mode_interrupt.html + */ +static inline struct DpmiRegRec *real_mode_interrupt(uint8_t interrupt) { + intptr_t result; + bool carry_clear; + __asm__ volatile("int $0x31" + : "=@ccs"(carry_clear), "=D"(result) + : "a"(0x0300), "b"(interrupt), "c"(0), "D"(&dpmi_regs) + : "memory", "cc"); + return !carry_clear ? (struct DpmiRegRec *)(result) : NULL; +} -// uint32_t framebuffer; // physical address of the linear frame buffer; write -// // here to draw to the screen -// uint32_t off_screen_mem_off; -// uint16_t off_screen_mem_size; // size of memory in the framebuffer but not -// // being displayed on the screen -// uint8_t reserved1[206]; -// }; +/* https://wiki.osdev.org/VESA_Video_Modes */ +struct __attribute__((packed)) VbeInfoBlock { + char VbeSignature[4]; // == "VESA" + uint16_t VbeVersion; // == 0x0300 for VBE 3.0 + uint16_t OemStringPtr[2]; // isa vbeFarPtr + uint8_t Capabilities[4]; + uint16_t VideoModePtr[2]; // isa vbeFarPtr + uint16_t TotalMemory; // as # of 64KB blocks + uint8_t Reserved[492]; +}; + +struct __attribute__((packed)) ModeInfoBlock { + uint16_t attributes; // deprecated, only bit 7 should be of interest to you, + // and indicates the mode supports a linear frame buffer. + uint8_t window_a; // deprecated + uint8_t window_b; // deprecated + uint16_t granularity; // deprecated; used while calculating bank numbers + uint16_t window_size; + uint16_t segment_a; + uint16_t segment_b; + uint32_t win_func_ptr; // deprecated; used to switch banks from protected mode + // without returning to real mode + uint16_t pitch; // number of bytes per horizontal line + uint16_t width; // width in pixels + uint16_t height; // height in pixels + uint8_t w_char; // unused... + uint8_t y_char; // ... + uint8_t planes; + uint8_t bpp; // bits per pixel in this mode + uint8_t banks; // deprecated; total number of banks in this mode + uint8_t memory_model; + uint8_t bank_size; // deprecated; size of a bank, almost always 64 KB but may + // be 16 KB... + uint8_t image_pages; + uint8_t reserved0; + + uint8_t red_mask; + uint8_t red_position; + uint8_t green_mask; + uint8_t green_position; + uint8_t blue_mask; + uint8_t blue_position; + uint8_t reserved_mask; + uint8_t reserved_position; + uint8_t direct_color_attributes; + + uint32_t framebuffer; // physical address of the linear frame buffer; write + // here to draw to the screen + uint32_t off_screen_mem_off; + uint16_t off_screen_mem_size; // size of memory in the framebuffer but not + // being displayed on the screen + uint8_t reserved1[206]; +}; // static char get_video_mode(); // #pragma aux get_video_mode = "mov ah, 0x0f" \ @@ -84,14 +116,63 @@ // #pragma aux set_video_mode = "mov ah, 0x00" \ // "int 0x10" parm[al] modify[ah]; -// static void set_vesa_video_mode(unsigned short); -// #pragma aux set_vesa_video_mode = "mov ax, 0x4f02" \ -// "int 0x10" parm[bx] modify[ah]; +static inline void set_vesa_video_mode(uint16_t mode) { + __asm__ volatile("int $0x10" ::"a"(0x4f02), "b"(mode) : "memory", "cc"); +} // static void wait_for_key(); // #pragma aux wait_for_key = "mov ah, 0x00" \ // "int 0x16" modify[ah]; +static inline uint16_t get_vesa_controller_info(struct VbeInfoBlock *block) { + // dpmi_regs.eax = 0x4f00; + // dpmi_regs.es = (intptr_t)block >> 4; + // dpmi_regs.edi = (intptr_t)block & 0xF; + + // struct DpmiRegRec *r = real_mode_interrupt(0x10); + // if (!r) { + // com_std_print('c', "Error calling real mode interrupt 0x10"); + // return 0; + // } + + /* Hope and play we don't need to set ES here. */ + uint16_t result; + __asm__ volatile(/*"push %%es\n" + "movw %0, %%es\n"*/ + "int $0x10\n" + // "pop %%es" + : "=a"(result) + : "a"(0x4f00), /*"r"((intptr_t)block >> 16), */ + "di"((intptr_t)block) + : "memory", "cc"); + + // com_std_print('u', r->eax, 'u', r->es, 'u', r->edi); + + // return r->eax; + return result; +} + +static inline uint16_t get_vesa_mode_info(uint16_t mode, + struct ModeInfoBlock *block) { + /* Hope and play we don't need to set ES here. */ + uint16_t result; + __asm__ volatile(/*"push %%es\n" + "movw %0, %%es\n" */ + "int $0x10\n" + // "pop %%es" + : "=a"(result) + : "a"(0x4f01), "c"(mode), /*"r"((intptr_t)block >> 16),*/ + "di"((intptr_t)block) + : "memory", "cc"); + return result; +} + +/* https://tippach.hier-im-netz.de/wdosx/int21api.html#f09 */ +static inline void print_to_console(char *const str) { + __asm__ volatile("int $0x21" ::"a"(0x0900), "d"(str) + : "memory", "cc", "esi", "edi", "esp"); +} + // static short get_vesa_controller_info(struct VbeInfoBlock *); // #pragma aux get_vesa_controller_info = "mov ax, 0x4f00" \ // "int 0x10" parm[es di] value[ax]; @@ -100,51 +181,10 @@ // #pragma aux get_vesa_mode_info = "mov ax, 0x4F01" \ // "int 0x10" parm[cx][es di] value[ax]; -// /* https://wiki.osdev.org/User:Omarrx024/VESA_Tutorial*/ -// static char *find_display_memory(void) { -// struct VbeInfoBlock *ctrl = (struct VbeInfoBlock *)0x2000; -// struct ModeInfoBlock *inf = (struct ModeInfoBlock *)0x3000; -// uint16_t *modes; -// int i; - -// strncpy(ctrl->VbeSignature, "VBE2", 4); -// if (get_vesa_controller_info(ctrl) != 0x004F) -// return NULL; - -// modes = (uint16_t *)(ctrl->VideoModePtr); -// for (i = 0; modes[i] != 0xFFFF; ++i) { -// if (get_vesa_mode_info(modes[i], inf) != 0x004F) -// continue; - -// // Check if this is a graphics mode with linear frame buffer support -// if ((inf->attributes & 0x80) != 0x80) -// continue; - -// // Check if this is a packed pixel or direct color mode -// if (inf->memory_model != 4 && inf->memory_model != 6) -// continue; - -// // Check if this is exactly the mode we're looking for -// if (WIDTH == inf->width && HEIGHT == inf->height && 256 == inf->pitch) -// return (char *)inf->framebuffer; -// } - -// return NULL; -// } - -/* Not really needed i guess? */ -// static inline bool real_mode_interrupt(uint8_t interrupt) { -// bool carry_clear; -// __asm__ volatile("int $0x31" -// : "=@ccnc"(carry_clear) -// : "a"(0x0300), "b"(interrupt), "c"(0), "D"(&dpmi_regs) -// : "memory", "cc"); -// return !carry_clear; -// } - typedef struct { - uint16_t rm_segment; - uint16_t pm_selector; + uint16_t segment; + uint16_t selector; + intptr_t linear; } LowMemBlock; // Allocates low memory under 1MB @@ -156,53 +196,88 @@ static inline LowMemBlock allocate_low_mem(uint32_t size_in_bytes) { uint16_t seg, sel; uint8_t failed = 0; - __asm__ __volatile__( - "movw $0x0100, %%ax \n\t" // DPMI allocate DOS memory block - "int $0x31 \n\t" - "setc %2 \n\t" // Check Carry Flag for error - : "=a"(seg), "=d"(sel), "=r"(failed) - : "b"(paragraphs) - : "cc"); + __asm__ __volatile__("int $0x31\n" + "setc %2\n" // Check Carry Flag for error + : "=a"(seg), "=d"(sel), "=r"(failed) + : "a"(0x0100), "b"(paragraphs) + : "cc"); if (!failed) { - block.rm_segment = seg; - block.pm_selector = sel; + block.segment = seg; + block.selector = sel; + block.linear = (sel << 4) + seg - baseaddr; } - return block; -} -static inline void copy_to_low_mem(LowMemBlock block, char *data, - uint32_t size) { - __asm__ volatile("movw %0, %%es\n" - "movw %1, %%di\n" - "movw %2, %%si\n" - "movw .data, %%ax\n" - "movw %3, %%cx\n" - "cld\n" - "rep movsb" ::"r"(block.rm_segment), - "r"(block.pm_selector), "r"(data), "r"(size) - : "memory", "cc", "ax", "bx", "cx", "esi", "di"); + return block; } // Frees the allocated low memory (DPMI Ax=0101h) static inline void free_low_mem(uint16_t selector) { - __asm__ __volatile__("movw $0x0101, %%ax \n\t" // DPMI free DOS memory block - "int $0x31" - : - : "d"(selector) - : "ax", "cc"); + __asm__ __volatile__("int $0x31" : : "a"(0x0101), "d"(selector) : "cc"); } +/* https://wiki.osdev.org/User:Omarrx024/VESA_Tutorial */ +static char *init_vesa_mode(void) { + set_vesa_video_mode(MODE_VESA_640_480_8 | 0x4000); + + LowMemBlock const mem = allocate_low_mem(sizeof(struct VbeInfoBlock) + + sizeof(struct ModeInfoBlock)); + + struct VbeInfoBlock *ctrl = (struct VbeInfoBlock *)((intptr_t)mem.linear); + struct ModeInfoBlock *inf = + (struct ModeInfoBlock *)((intptr_t)mem.linear + + sizeof(struct VbeInfoBlock)); + uint16_t *modes; + int i; + + static struct com_str vbe2str = com_str_lit("VBE2"); + com_str_copy_to_mem(&vbe2str, ctrl->VbeSignature, false); + if (get_vesa_controller_info(ctrl + baseaddr) != 0x004F) + return NULL; + + modes = (uint16_t *)(((intptr_t)ctrl->VideoModePtr[0] << 4) + + ctrl->VideoModePtr[1] - baseaddr); + + for (i = 0; modes[i] != 0xFFFF; ++i) { + if (get_vesa_mode_info(modes[i], inf + baseaddr) != 0x004F) + continue; + + com_std_print('c', "Mode:", 'u', modes[i] & 0xFFFFBFFF, 'u', inf->width, + 'u', inf->height, 'u', inf->bpp); + + // Check if this is a graphics mode with linear frame buffer support + if ((inf->attributes & 0x80) != 0x80) + continue; + + // Check if this is a packed pixel or direct color mode + if (inf->memory_model != 4 && inf->memory_model != 6) + continue; + + // Check if this is exactly the mode we're looking for + if (WIDTH == inf->width && HEIGHT == inf->height && 8 == inf->bpp) + return (char *)(intptr_t)inf->framebuffer - baseaddr; + } + + return NULL; +} + +// static inline void copy_to_low_mem(LowMemBlock block, char *data, +// uint32_t size) { +// __asm__ volatile("movw %0, %%es\n" +// "movw %1, %%di\n" +// "movw %2, %%si\n" +// "movw .data, %%ax\n" +// "movw %3, %%cx\n" +// "cld\n" +// "rep movsb" ::"r"(block.rm_segment), +// "r"(block.pm_selector), "r"(data), "r"(size) +// : "memory", "cc", "ax", "bx", "cx", "esi", "di"); +// } + static inline void set_video_mode(uint16_t mode) { __asm__ volatile("int $0x10" : : "a"(mode) : "memory", "cc"); } -/* http://www.techhelpmanual.com/439-dos_fn_40h__write_to_file_via_handle.html - */ -static inline void writetest(void) { - __asm__ volatile("int $0x21" : : "a"(0x0200), "d"('Y') : "memory", "cc"); -} - /* http://www.techhelpmanual.com/630-int_31h_0800h__physical_address_mapping.html */ static inline void *map_physical_address(uint32_t physical_addr, @@ -210,7 +285,7 @@ static inline void *map_physical_address(uint32_t physical_addr, uint16_t high, low; bool carry_clear; __asm__ volatile("int $0x31" - : "=b"(high), "=c"(low), "=@ccnc"(carry_clear) + : "=b"(high), "=c"(low), "=@ccs"(carry_clear) : "a"(0x0800), "b"(physical_addr >> 16), "c"(physical_addr & 0xFFFF), "S"(size >> 16), "D"(size & 0xFFFF) @@ -222,7 +297,7 @@ static inline uint16_t alloc_ldt_descriptor(void) { bool carry_clear; uint16_t selector; __asm__ volatile("int $0x31" - : "=a"(selector), "=@ccnc"(carry_clear) + : "=a"(selector), "=@ccs"(carry_clear) : "a"(0x0000), "c"(1) : "memory", "cc"); return !carry_clear ? selector : 0; @@ -232,7 +307,7 @@ static inline bool set_segment_base_address(uint16_t selector, uint32_t baseaddr) { bool carry_clear; __asm__ volatile("int $0x31" - : "=a"(selector), "=@ccnc"(carry_clear) + : "=a"(selector), "=@ccs"(carry_clear) : "a"(0x0007), "c"(baseaddr >> 16), "d"(baseaddr & 0xFFFF) : "memory", "cc"); return !carry_clear; @@ -241,7 +316,7 @@ static inline bool set_segment_base_address(uint16_t selector, static inline bool set_segment_limit(uint16_t selector, uint32_t size) { bool carry_clear; __asm__ volatile("int $0x31" - : "=@ccnc"(carry_clear) + : "=@ccs"(carry_clear) : "a"(0x0008), "b"(selector), "c"(size >> 16), "d"(size & 0xFFFF) : "memory", "cc"); @@ -254,7 +329,7 @@ static inline bool set_segment_rights(uint16_t selector, bool read, uint16_t flags = 1 | (write << 1) | (1 << 4) | (1 << 7) | (1 << 14) | (1 << 15); __asm__ volatile("int $0x31" - : "=@ccnc"(carry_clear) + : "=@ccs"(carry_clear) : "a"(0x0009), "b"(selector), "c"(flags) : "memory", "cc"); return !carry_clear; @@ -264,7 +339,7 @@ static inline intptr_t get_segment_base_address(uint16_t selector) { bool carry_clear; uint16_t high, low; __asm__ volatile("int $0x31" - : "=@ccnc"(carry_clear), "=c"(high), "=d"(low) + : "=@ccs"(carry_clear), "=c"(high), "=d"(low) : "a"(0x0006), "b"(selector) : "memory", "cc"); // return carry_clear ? 0 : (((intptr_t)high << 16) | (intptr_t)low); @@ -275,32 +350,28 @@ static inline void use_segment(uint16_t selector) { __asm__ volatile("" : "=S"(selector)::); } -/* https://tippach.hier-im-netz.de/wdosx/int21api.html#f09 */ -static inline void print_to_console(char *const str) { - __asm__ volatile("int $0x21" ::"a"(0x0900), "d"(str) - : "memory", "cc", "esi", "edi", "esp"); -} - static uint32_t test = 0x1420124; extern int plr_display_dos_main(void) { /* Fat DS trick, see __djgpp_nearptr_enable() */ - unsigned short ds_selector; + uint16_t ds_selector; asm("movw %%ds, %0" : "=r"(ds_selector)); set_segment_limit(ds_selector, 0xFFFFFFFF); - intptr_t baseaddr = get_segment_base_address(ds_selector); + baseaddr = get_segment_base_address(ds_selector); if (baseaddr == 0) return -1; - unsigned char *volatile buf = - (unsigned char *)((intptr_t)0xA0000 - baseaddr); // VGA memory address + char *volatile buf = + (char *)((intptr_t)0xA0000 - baseaddr); // VGA memory address /* TODO: Make VESA work for sweet sweet 640x480. */ // unsigned char saved_mode = get_video_mode(); // Save original mode // set_vesa_video_mode(MODE_VESA_640_480_8); // Set our VGA mode - set_video_mode(MODE_VGA_320_200_8); // Set our VGA mode + // set_video_mode(MODE_VGA_320_200_8); // Set our VGA mode - // buf = find_display_memory(); + buf = init_vesa_mode(); + if (!buf) + return -1; /* TODO: Fetch info about the mode, to know the availability */ /* as well as base address in memory */ @@ -323,14 +394,8 @@ extern int plr_display_dos_main(void) { for (y = 0; y < HEIGHT; y++) { for (x = 0; x < WIDTH; x++) { buf[y * WIDTH + x] = COLOR_OFFSET + y / COLOR_STEP; - // __asm__ volatile("int $0x10" - // : - // : "a"(0x0C << 8 | COLOR_OFFSET + y / COLOR_STEP), - // "b"(0), "c"(x), "d"(y) - // : "memory", "cc"); } } - // writetest(); } // dpmi_regs = (struct dpmi_regs){.eax = 0x00004C00}; diff --git a/Player/Makefile b/Player/Makefile index 7520583..4909f7e 100644 --- a/Player/Makefile +++ b/Player/Makefile @@ -92,11 +92,11 @@ endif endif # https://tippach.hier-im-netz.de/wdosx -dos: CFLAGS += -ffreestanding -m32 -fno-PIC -fno-PIE -nostdlib -nodefaultlibs +dos: CFLAGS += -ffreestanding -m32 -msse2 -fno-PIC -fno-PIE -nostdlib -nodefaultlibs dos: $(CC) -c ./Main/dos.s -o ./Main/dos.o -m32 - $(CC) -c ./Display/dos.c -o ./Display/dos.o $(CFLAGS) - ld.lld -m elf_i386 -T dos.ld ./Main/dos.o ./Display/dos.o -o dos.elf + $(CC) -c ./amalgam.c -o ./amalgam-dos.o -DCOM_DEF_TARGET=COM_DEF_TARGET_DOS $(CFLAGS) + ld.lld -m elf_i386 -T dos.ld ./Main/dos.o ./amalgam-dos.o -o dos.elf objcopy -O binary --strip-all dos.elf dos.bin cat WDosX/WDOSX.DX dos.bin > DOS.EXE ifeq ($(RUN), 1) diff --git a/Player/amalgam.c b/Player/amalgam.c index 6d78ba7..0a4bfab 100644 --- a/Player/amalgam.c +++ b/Player/amalgam.c @@ -29,4 +29,7 @@ #include "../Common/Timer/posix.c" #include "./Display/x11.c" #include "./Main/cosmo.c" +#elif COM_DEF_TARGET == COM_DEF_TARGET_DOS +#include "../Common/Std/dos.c" +#include "./Display/dos.c" #endif diff --git a/Player/dos.ld b/Player/dos.ld index 369d55b..1a2fc7f 100644 --- a/Player/dos.ld +++ b/Player/dos.ld @@ -9,18 +9,16 @@ SECTIONS } textend = .; - /* We will need to manually map this. */ - /* At runtime we can figure this out from mapped code segment. */ datastart = .; - .rodata : { - *(.rodata*) - } - .data : { *(.data*) } dataend = .; + .rodata : { + *(.rodata*) + } + /* TODO: We need to manually map this, as loader is incapable of doing so with flat binary. */ bssstart = .; .bss : {