// yes it compiles. It'll segfault instantly, of course.
//#include <stdlib.h>
//#include <string.h>
//#include <stdio.h>

//#include <io.c>
//#include <lib.c>

#include <stddef.h>

int verify_ed25519 (char * ed25519_pubkey, void * buf, int size, char * signature);

void getsn (char* buf, int length);
int  puts(const char *);

void INT (int arg, ...);

int main (void) {
   int (*loadaddr)();    // >=> sp       0080
   char signature[0x41]; // >=> sp+2     8605e027f42368ea6bba9de66409f6a8ddedcd49614a4648281c47a7b4ad252f5639069b17ba8ff104d371e2d8a625b038f0750667364087e7987e40ea81510f
   char payload[0x101];  // >=> sp+0x43  3540088000450545054505450545054505450f433041

   puts ("Welcome to the secure program loader.");
   while (1) {

      puts ("Please enter second stage load address.");
      getsn ((char *) &loadaddr, 2);

      puts ("Please enter the second stage program.");
      memset (&payload /*sp+0x43*/, 0, 0x101);
      getsn ((char *) &payload /*sp+0x43*/, 0x100); // get 100 bytes into sp+0x43

      puts ("Please enter program signature.");
      memset((char *) &signature /* sp+2 */, 0, 0x41);
      getsn ((char *) &signature /* sp+2 */, 0x40);

      if ((int)loadaddr & 0x8000 && (int)loadaddr < 0xf001) {
         // Here, it copies the payload
         memcpy ((void *)loadaddr, &payload, 0x100);
         // Then, it verifies the signature
         if (verify_ed25519 ((char *)0x2400, loadaddr, 0x100, signature) == 1) {
            puts ("Signature valid, executing payload");
            if (loadaddr()) {
               puts ("ACCESS GRANTED");
               INT (0x7f, 0, 0);
               exit (0);
            } else {
               puts ("ACCESS DENIED");
            }
         } else {
            // ??? memory not cleared? For shame.S
            puts ("Incorrect signature, continuing");
         }
      }
      else {
         puts ("Load address outside allowed range of 0x8000-0xF000");
      }
   }
}

int sample_payload (void) {
   short a = 0x8008;
   //goto a;
   a = a;
   a = a;
   a = a;
   a = a;
   a = a;
   a = 0;
   return a;
}

void INT (int arg, ...) {

}

int verify_ed25519 (char * ed25519_pubkey, void * buf, int size, char * signature) {
   int result = 0; // >=> sp+4
   INT (0x33, ed25519_pubkey, buf, size, signature, &result);
   return result;
}

void getsn (char* buf, int length) {
   INT (2, buf, length);
}

int putchar (int c) {
   INT (0, c);
}

int puts (const char * str) {
   char c;
   while (c = *str) {
      str++;
      putchar(c);
   }
   putchar('\n');
   return 0;
}
