#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) {
   /*
4678:  0b12           push	r11
467a:  c293 0424      tst.b	&0x2404
467e:  0f24           jz	$+0x20 <malloc+0x26>
4680:  1e42 0024      mov	&0x2400, r14
4684:  8e4e 0000      mov	r14, 0x0(r14)
4688:  8e4e 0200      mov	r14, 0x2(r14)
468c:  1d42 0224      mov	&0x2402, r13
4690:  3d50 faff      add	#0xfffa, r13
4694:  0d5d           add	r13, r13
4696:  8e4d 0400      mov	r13, 0x4(r14)
469a:  c243 0424      mov.b	#0x0, &0x2404
; malloc+0x26:
469e:  1b42 0024      mov	&0x2400, r11
46a2:  0e4b           mov	r11, r14
46a4:  1d4e 0400      mov	0x4(r14), r13
46a8:  1db3           bit	#0x1, r13
46aa:  2820           jnz	$+0x52 <46fc>

46fc:  0d4e           mov	r14, r13
46fe:  1e4e 0200      mov	0x2(r14), r14
4702:  0e9d           cmp	r13, r14
4704:  0228           jnc	$+0x6 <malloc+0x92>
4706:  0e9b           cmp	r11, r14
4708:  cd23           jnz	$-0x64 <malloc+0x2c>
; puts("Heap exhausted. Aborting")
470a:  3f40 5e46      mov	#0x465e, r15
470e:  b012 504d      call	#0x4d50 <puts>
4712:  3040 3e44      br	#0x443e <__stop_progExec__>
4716:  0f43           clr	r15
4718:  3b41           pop	r11
471a:  3041           ret
*/

   // 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];
}
