#include "chernobyl_stdlib.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "chernobyl.h"
#include "chernobyl_types.h"

#define HEAP_BASE 0x2400

void __trap_interrupt () {
   // Hardware will do something here
   return;
}

void set_w (u16* addr, u16 value) {
   *((u16 *) &addr) = value;
}

u16 get_w (u16 *addr) {
   return *((u16 *) addr);
}

void *_malloc (u16 size) {
   // if heap not initialized, initialize the heap
   // if (get_w (HEAP_BASE + 4)) {
   //    u16 heap_ptr = HEAP_BASE;
   //    set_w (heap_ptr, HEAP_BASE);
   //    set_w (heap_ptr + 2, HEAP_BASE);
   // }
   // create a new block on the heap

   // return the address of the new block
   return 0;
}

void _free (void *ptr) {
   return;
}

u16 _putchar (char c) {
   putchar (c);
   return c;
}

i16 _getchar () {
   return getchar ();
}

void _puts (const char *s) {
   u8 character = 0;
   while (character = *(u8 *) s++) {
      _putchar (character);
   }
   return;
}

void _getsn (char *__restrict buf, u16 length) {
   fgets (buf, length, stdin);
   buf[strnlen(buf, length) - 1] = '\0';
   return;
}

int _strcmp (const char *s1, const char *s2) {
   while (*s1 == *s2) {
      if (*(++s1) == 0) {
         break;
      }
      s2++;
   }
   return *s2 - *s1;
}

void INT (u16 interrupt) {
   swpb (&interrupt);
   interrupt |= 0x8000;
   //r.sr = interrupt;
   __trap_interrupt ();
   return;
}

void swpb (u16 *word) {
   ((u8 *) word)[0] = ((u8 *) word)[0] ^ ((u8 *) word)[1];
   ((u8 *) word)[1] = ((u8 *) word)[1] ^ ((u8 *) word)[0];
   ((u8 *) word)[0] = ((u8 *) word)[0] ^ ((u8 *) word)[1];
}
