/* * libcaca Colour ASCII-Art library * Copyright (c) 2006 Sam Hocevar * 2009 Jean-Yves Lamoureux * All Rights Reserved * * This library is free software. It comes without any warranty, to * the extent permitted by applicable law. You can redistribute it * and/or modify it under the terms of the Do What the Fuck You Want * to Public License, Version 2, as published by Sam Hocevar. See * http://www.wtfpl.net/ for more details. */ #include "config.h" #include "caca_types.h" #include "klibc.h" #include "drivers/timer.h" #include "kernel.h" void htoa(unsigned int value, char s[]); #define IS_DIGIT(x) (x>='0' && x<='9') #define IS_ALPHA(x) (x>='A' && x<='z') #define IS_UPPER(x) (x>='A' && x<='Z') #define IS_LOWER(x) (x>='a' && x<='z') #define UPPER(x) (IS_LOWER(x)?(x+('A'-'a')):x) #define LOWER(x) (IS_UPPER(x)?(x-('a'-'A')):x) /* Our default seed for random number generator */ static int seed = 0x68743284; /* Our memory mapping */ static uint32_t *freemem = (uint32_t *) 0x00200000; int kX = 0; int kY = 0; void scroll(void) { unsigned char *video, *tmp; for (video = (unsigned char *)0xB8000; video < (unsigned char *)0xB8FA0; video++) { tmp = (unsigned char *)(video + 1 * 160); if (tmp < (unsigned char *)0xB8FA0) *video = *tmp; else *video = 0; } kY -= 1; if (kY < 0) kY = 0; } void putcar(unsigned char c) { unsigned char *video; if (c == 10) { kX = 0; kY++; } else { video = (unsigned char *)(0xB8000 + 2 * kX + 160 * kY); *video = c; *(video + 1) = 0x07; kX++; if (kX > 79) { kX = 0; kY++; } if (kY >= 24) { scroll(); } } } void print(char *str) { char const *ptr = str; while (*ptr) { putcar(*ptr++); } } void clearscreen(void) { int x, y; kX = 0; kY = 0; for (y = 0; y < 25; y++) for (x = 0; x < 80; x++) { putcar(' '); } kX = 0; kY = 0; } /* stdlib.h functions */ void *malloc(size_t size) { uint32_t *p = freemem; if (!size) return NULL; size = (size + 0x7) / 4; *p = size; freemem += size + 1; return p + 1; } void free(void *ptr) { return; } void *realloc(void *ptr, size_t size) { uint32_t oldsize; void *p; if (!size) return NULL; if (!ptr) oldsize = 0; else { oldsize = ((uint32_t *) ptr)[-1]; if (oldsize >= size) return ptr; } p = malloc(size); memcpy(p, ptr, oldsize); return p; } char *getenv(const char *name) { return NULL; } int getpid(void) { return 0x1337; } void srand(unsigned int s) { seed = rand(); } int time(void *dummy) { return rand(); } int rand(void) { seed = (seed * 0x7f32ba17) ^ 0xf893a735; return seed % RAND_MAX; } int abs(int j) { if (j < 0) return -j; return j; } void exit(int status) { /* FIXME: reboot? */ while (1); } int atexit(void (*function) (void)) { /* FIXME: register function */ return 0; } /* string.h functions */ void *memset(void *s, int c, size_t n) { uint8_t *ptr = s; while (n--) *ptr++ = c; return s; } void *memcpy(void *dest, const void *src, size_t n) { uint8_t *destptr = dest; uint8_t const *srcptr = src; while (n--) *destptr++ = *srcptr++; return dest; } void *memmove(void *dest, const void *src, size_t n) { memcpy(freemem, src, n); memcpy(dest, freemem, n); return dest; } size_t strlen(const char *s) { int len = 0; while (*s++) len++; return len; } int strcmp(const char *s1, const char *s2) { while (*s1 && *s1 == *s2) { s1++; s2++; } return (int)*s1 - (int)*s2; } int strcasecmp(const char *s1, const char *s2) { while (*s1 && *s2 && UPPER(*s1) == UPPER(*s2)) { s1++; s2++; } return (int)UPPER(*s1) - (int)UPPER(*s2); } int memcmp(const void *_s1, const void *_s2, size_t n) { uint8_t const *s1 = _s1, *s2 = _s2; while (n--) { if (*s1 != *s2) return (int)*s1 - (int)*s2; s1++; s2++; } return 0; } char *strdup(const char *s) { char *new; unsigned int len = strlen(s); new = malloc(len + 1); memcpy(new, s, len + 1); return new; } char *strchr(const char *s, int c) { do if (*s == c) return (char *)(intptr_t) s; while (*s++); return NULL; } /* stdarg.h functions */ int vsnprintf(char *str, size_t size, const char *format, va_list ap) { /* FIXME */ return 0; } /* stdio.h functions */ FILE *fopen(const char *path, const char *mode) { /* FIXME */ return NULL; } int feof(FILE * stream) { /* FIXME */ return 0; } char *fgets(char *s, int size, FILE * stream) { /* FIXME */ return NULL; } size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream) { return 0; } int fclose(FILE * fp) { /* FIXME */ return 0; } int printf(const char *fmt, ...) { char str[200]; char tmp[100]; args_list args; args_start(args, fmt); char *s; int ptr = 0; int i = 0; for (; fmt[i]; ++i) { if ((fmt[i] != '%') && (fmt[i] != '\\')) { str[ptr++] = fmt[i]; continue; } else if (fmt[i] == '\\') { switch (fmt[++i]) { case 'a': str[ptr++] = '\a'; break; case 'b': str[ptr++] = '\b'; break; case 't': str[ptr++] = '\t'; break; case 'n': str[ptr++] = '\n'; break; case 'r': str[ptr++] = '\r'; break; case '\\': str[ptr++] = '\\'; break; } continue; } switch (fmt[++i]) { case 's': s = (char *)args_next(args, char *); while (*s) str[ptr++] = *s++; break; case 'c': str[ptr++] = (char)args_next(args, int); break; case 'p': case 'x': htoa((unsigned long)args_next(args, unsigned long), tmp); memcpy(&str[ptr], tmp, strlen(tmp)); ptr += strlen(tmp); break; case 'd': itoa((unsigned long)args_next(args, unsigned long), tmp); memcpy(&str[ptr], tmp, strlen(tmp)); ptr += strlen(tmp); break; case '%': str[ptr++] = '%'; break; default: str[ptr++] = fmt[i]; break; } } str[ptr] = '\0'; args_end(args); print(str); return 0; } int fprintf(FILE * stream, const char *format, ...) { /* FIXME */ return 0; } int fflush(FILE * stream) { /* FIXME */ return 0; } int sprintf(char *str, const char *fmt, ...) { char tmp[100]; args_list args; args_start(args, fmt); char *s; int ptr = 0; int i = 0; for (; fmt[i]; ++i) { if ((fmt[i] != '%') && (fmt[i] != '\\')) { str[ptr++] = fmt[i]; continue; } else if (fmt[i] == '\\') { switch (fmt[++i]) { case 'a': str[ptr++] = '\a'; break; case 'b': str[ptr++] = '\b'; break; case 't': str[ptr++] = '\t'; break; case 'n': str[ptr++] = '\n'; break; case 'r': str[ptr++] = '\r'; break; case '\\': str[ptr++] = '\\'; break; } continue; } switch (fmt[++i]) { case 's': s = (char *)args_next(args, char *); while (*s) str[ptr++] = *s++; break; case 'c': str[ptr++] = (char)args_next(args, int); break; case 'p': case 'x': htoa((unsigned long)args_next(args, unsigned long), tmp); memcpy(&str[ptr], tmp, strlen(tmp)); ptr += strlen(tmp); break; case 'd': itoa((unsigned long)args_next(args, unsigned long), tmp); memcpy(&str[ptr], tmp, strlen(tmp)); ptr += strlen(tmp); break; case '%': str[ptr++] = '%'; break; default: str[ptr++] = fmt[i]; break; } } str[ptr] = '\0'; args_end(args); return 0; } int sscanf(const char *str, const char *format, ...) { /* FIXME */ return 0; } /* unistd.h functions */ void usleep(unsigned long usec) { u32 start = ticks; signed int diff = 0; while (1) { diff = (signed int)(ticks - start); if (diff >= (signed int)(usec / 20)) break; } } void sleep(unsigned long sec) { usleep(sec * 1000); } int gettimeofday(struct timeval *tv, struct timezone *tz) { static int usec = 0; static int sec = 0; /* FIXME */ usec += 10000; if (usec > 1000000) { sec++; usec -= 1000000; } tv->tv_sec = sec; tv->tv_usec = usec; return 0; } /* math.h functions */ double cos(double x) { double ret = 0.0; #ifdef HAVE_FSIN_FCOS asm volatile ("fcos":"=t" (ret):"0"(x)); #else double x2; double num = 1.0; double fact = 1.0; int i; x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); x2 = x * x; /* cos(x) = 1/0! - x^2/2! + x^4/4! - x^6/6! ... */ for (i = 0; i < 10; i++) { ret += num / fact; num *= -x2; fact *= (2 * i + 1) * (2 * i + 2); } #endif return ret; } double sin(double x) { double ret = 0.0; #ifdef HAVE_FSIN_FCOS asm volatile ("fsin":"=t" (ret):"0"(x)); #else double x2; double num; double fact = 1.0; int i; x = x - ((double)(int)(x / (2 * M_PI))) * (2 * M_PI); x2 = x * x; num = x; /* sin(x) = x/1! - x^3/3! + x^5/5! - x^7/7! ... */ for (i = 0; i < 10; i++) { ret += num / fact; num *= -x2; fact *= (2 * i + 2) * (2 * i + 3); } #endif return ret; } double sqrt(double x) { double ret = x; int i; /* This is Newton's method */ for (i = 0; i < 10; i++) ret = (ret * ret + x) / (ret * 2.0); return ret; } /* reverse: reverse string s in place */ void reverse(char s[]) { int i, j; char c; for (i = 0, j = strlen(s) - 1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; } } /* itoa implementation, by Kernighan and Ritchie's The C Programming Language */ void itoa(int n, char s[]) { int i, sign; if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ i = 0; do { /* generate digits in reverse order */ s[i++] = n % 10 + '0'; /* get next digit */ } while ((n /= 10) > 0); /* delete it */ if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } void htoa(unsigned int value, char s[]) { int i = 8; int ptr = 0; while (i-- > 0) { s[ptr++] = "0123456789abcdef"[(value >> (i * 4)) & 0xf]; } s[ptr] = 0; } /* errno.h stuff */ int errno = 0;