//========================================================================
//
// server68k.cc
//
// Copyright 1999 Emmanuel Lesueur
//
//========================================================================

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define Object ZZObject
#include <exec/nodes.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <proto/exec.h>
#include <proto/dos.h>
#undef Object
#undef Allocate
#include "apdf/AComm.h"

#define DB(x) //x

#ifndef NO_CUSTOM_MEM
void* myAllocMem(size_t sz) {
    return AllocMem(sz,MEMF_ANY);
}

void myFreeMem(void* p,size_t sz) {
    FreeMem(p,sz);
}
#endif

struct MyMessage {
    struct Message msg;
    void *data;
    size_t len;
    int id;
};


static MsgPort *port;
static MsgPort *reply_port;
void* decryptBase;
void* unlzwBase;
static BPTR modulesdir;

static comm_info* m68k_create_comm_info(size_t sz) {
    comm_info* ci=(comm_info*)malloc(sizeof(comm_info));
    if(ci) {
	ci->msg=AllocVec(sizeof(MyMessage)+sz,MEMF_PUBLIC|MEMF_CLEAR);
	if(!ci->msg) {
	    free(ci);
	    ci=NULL;
	} else {
	    ci->cmddata=(MyMessage*)ci->msg+1;
	    ((MyMessage*)ci->msg)->msg.mn_ReplyPort=reply_port;
	    ((MyMessage*)ci->msg)->msg.mn_Length=sz;
	}
    }
    return ci;
}

static void m68k_delete_comm_info(comm_info* ci) {
    FreeVec(ci->msg);
    free(ci);
}

static int m68k_exchange_msg(struct comm_info *ci,struct msg_base *msg,size_t len,int id) {
    DB(printf("SV: exchange_msg(%lx,%lx,%ld,%ld)\n",ci,msg,len,id);)
    MyMessage* m=(MyMessage*)ci->msg;
    m->data=msg;
    m->len=len;
    m->id=id;
    PutMsg(port,&m->msg);
    WaitPort(reply_port);
    GetMsg(reply_port);
    DB(printf("success=%d\n",msg?msg->success:1);)
    return msg?msg->success:1;
}

static void m68k_send_msg(struct comm_info *ci,void *msg,size_t len,int id) {
    MyMessage* m=(MyMessage*)ci->msg;
    DB(printf("SV: send_msg(%lx,%lx,%ld,%ld)\n",ci,msg,len,id);)
    m->data=msg;
    m->len=len;
    m->id=id;
    PutMsg(port,&m->msg);
}

static void *m68k_get_msg(struct comm_info *ci,void **data,size_t *len,int *id) {
    MyMessage* msg;
    WaitPort(reply_port);
    msg=(MyMessage*)GetMsg(reply_port);
    *data=msg->data;
    *len=msg->len;
    *id=msg->id;
    DB(printf("SV: get_msg(%lx)=(%lx,%lx,%ld,%ld)\n",ci,msg,*data,*len,*id);)
    return msg;
}

static void m68k_reply_msg(struct comm_info *ci,void *msg) {
    DB(printf("SV: reply_msg(%lx,%lx)\n",ci,msg);)
    ReplyMsg((Message*)msg);
}

void cleanup() {
    DeleteMsgPort(reply_port);
}

bool decryptionEnabled() {
    if(!decryptBase) {
	BPTR olddir=CurrentDir(modulesdir);
	decryptBase=OpenLibrary((UBYTE*)"ApdfDecrypt_68k.module",1);
	CurrentDir(olddir);
    }
    return decryptBase!=NULL;
}

int main() {
    create_comm_info=m68k_create_comm_info;
    delete_comm_info=m68k_delete_comm_info;
    exchange_msg=m68k_exchange_msg;
    //send_msg=m68k_send_msg;
    get_msg=m68k_get_msg;
    reply_msg=m68k_reply_msg;

    Task* task=FindTask(NULL);
    MyMessage* startupmsg=(MyMessage*)task->tc_UserData;

    modulesdir=CurrentDir(0);
    CurrentDir(modulesdir);
    port=startupmsg->msg.mn_ReplyPort;
    reply_port=CreateMsgPort();
    DB(printf("server %lx: client_port=%lx reply_port=%lx\n",task,port,reply_port);)

    unlzwBase=OpenLibrary((UBYTE*)"ApdfUnLZW_68k.module",1);

    if(!reply_port)
	return 0;

    atexit(cleanup);

    startupmsg->data=reply_port;
    ReplyMsg(&startupmsg->msg);
    WaitPort(reply_port);
    GetMsg(reply_port);
    DB(printf("server: got startupmsg\n");)

    comm_info ci;
    ci.msg=NULL;
    ci.cmddata=NULL;

    server(&ci);

    CloseLibrary((Library*)decryptBase);
    CloseLibrary((Library*)unlzwBase);

    return 0;
}

#ifndef NO_CUSTOM_MEM

#ifdef DEBUGMEM
extern "C" void printunfreed();
extern "C" void call_printunfreed() {
    printunfreed();
}
__asm__(".stabs \"___EXIT_LIST__\",22,0,0,_call_printunfreed");
__asm__(".stabs \"___EXIT_LIST__\",20,0,0,108");
#endif

extern "C" void meminit();
extern "C" void memcleanup();
extern "C" void call_meminit() {
    meminit();
}
extern "C" void call_memcleanup() {
    memcleanup();
}

__asm__(".stabs \"___INIT_LIST__\",22,0,0,_call_meminit");
__asm__(".stabs \"___INIT_LIST__\",20,0,0,78");

__asm__(".stabs \"___EXIT_LIST__\",22,0,0,_call_memcleanup");
__asm__(".stabs \"___EXIT_LIST__\",20,0,0,78");
#endif

