/**
 * TrueReality - dispatch.c
 * Copyright (C) 1998, 1999 Niki W. Waibel
 *
 * This program is free software; you can redistribute it and/
 * or modify it under the terms of the GNU General Public Li-
 * cence as published by the Free Software Foundation; either
 * version 2 of the Licence, or any later version.
 *
 * This program is distributed in the hope that it will be use-
 * ful, but WITHOUT ANY WARRANTY; without even the implied war-
 * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public Licence for more details.
 *
 * You should have received a copy of the GNU General Public
 * Licence along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 * USA.
 *
 * Information about me (the author):
 *   Niki W. Waibel, Reichenau 20, 6890 Lustenau, Austria - EUROPE
 *   niki.waibel@gmx.net
**/



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

#include <config.h>
#include <parser_extern.h>
#include <file_loader_extern.h>
#include <type_sizes.h>

#include "N64/memory.h"
#include "N64/cpu.h"
#include "N64/registers.h"
#include "N64/controller.h"

#include "os/os.h"
#include "input/keyboard/keyboard.h"
#include "output/audio/audio.h"

#include "file_loader.h"
#include "endian.h"
#include "dispatch.h"



#ifdef DEBUG
        #include <debug.h>
#endif

#if DISPLAY_SUPPORT
        #include "output/display/display.h"
#endif

#ifdef JOYSTICK
        #include "input/joystick/joystick.h"
#endif





#if DISPLAY_SUPPORT
static void display_close();
static void display_open();
static void display_refresh();
#endif
static WORD controller_get_status(WORD);









/*
 * the next 3 (display) routines are just compiled
 * if a display is specified in the Makefile
 *
 */

#if DISPLAY_SUPPORT





void display_open()
{
        char name[80];
        int  n = 80;
        int  i;



        switch(prefs.display)
        {
            case NO_DISPLAY:
                puts("Display:                                                             no display");
                break;


            case LOCAL_DISPLAY:
            case LOCAL_DISPLAY_PROCESS:
                if(OpenVisual() != -1)
                {
                        GetVisualName(name, &n);
            
                        printf("Connected to display:");
             
                        for(i = 21; i < (79-strlen(name)); i++)
                                putchar(' ');
                        puts(name); fflush(stdout);
                }
                else
                {
                        puts("Display connection failed, using display:                             no display");

                        prefs.display = NO_DISPLAY;
                }
                break;


            case REMOTE_DISPLAY:   /* far from complete */
                puts("REMOTE_DISPLAY is not implemented yet, using display:                 no display");
                prefs.display = NO_DISPLAY;
                break;
   
        } /* switch(prefs.display) */
   
} /* void display_open() */





void display_close()
{
        switch(prefs.display)
        {
            case NO_DISPLAY:
                break;

            case LOCAL_DISPLAY:
                CloseVisual();
                prefs.display = NO_DISPLAY;
                break;

            case LOCAL_DISPLAY_PROCESS:   /* far from complete */
            case REMOTE_DISPLAY:          /* far from complete */
                prefs.display = NO_DISPLAY;
                break;

        } /* switch(prefs.display) */
   
} /* void display_close() */





static void display_refresh()
{
        switch(prefs.display)
        {
            case NO_DISPLAY:
            case LOCAL_DISPLAY_PROCESS:   /* far from complete */
            case REMOTE_DISPLAY:          /* far from complete */
                break;

            case LOCAL_DISPLAY:
                RefreshVisual();
                break;

        } /* switch(prefs.display) */
   
} /* static void display_refresh() */





#endif /* #if DISPLAY_SUPPORT */





static WORD controller_get_status(WORD controller)
{
        WORD state;



        switch(prefs.display)
        {
            case NO_DISPLAY:
#if DISPLAY_SUPPORT & SUPPORT_LOCAL_DISPLAY_PROCESS
            case LOCAL_DISPLAY_PROCESS:
#endif
#if DISPLAY_SUPPORT & SUPPORT_REMOTE_DISPLAY
            case REMOTE_DISPLAY:
#endif
                fprintf(stdout,
                        "controller_get_status:\n"
                        "   input value of controller #%d\n"
                        "   (BBBBXXYY) ",
                        (int)controller);
                if(scanf("%lx", &state) == 1)
                        return(state);
                else
                        return(0);
                        
#if DISPLAY_SUPPORT & SUPPORT_LOCAL_DISPLAY
            case LOCAL_DISPLAY:
                return(CheckVisual());
#endif

        } /* switch(prefs.display) */
   

   
        return(0);   /* to make compiler happy */
   
} /* static unsigned long controller_get_status() */





int dispatch(int command, void *value)
{
        switch(command)
        {
            case EMU_RESET:
                clear_n64_mem();
                cpu_reset();
                copy_code();
                display_refresh();
                break;

            case CHECK_MACHINE_ENDIAN:
                return(check_machine_endian());

            case SHUTDOWN:
#if DISPLAY_SUPPORT
                display_close();
#endif
#ifdef JOYSTICK
                CloseJoystick();
#endif
#ifdef AUDIO
                CloseAudio();
#endif
                free_n64_mem();
                free(rom.image);
                exit(0);
                
            case MEMORY_ALLOC:
                return(alloc_n64_mem());
                
            case MEMORY_CLEAR:
                clear_n64_mem();
                return(0);
                
            case MEMORY_FREE:
                free_n64_mem();
                return(0);

#if DISPLAY_SUPPORT
            case DISPLAY_OPEN:
                display_open();
                return(0);

            case DISPLAY_REFRESH:
                display_refresh();
                return(0);
                
            case DISPLAY_CLOSE:
                display_close();
                return(0);
#endif

            case CONTROLLER_GET_STATUS:
                *((WORD *)value) = controller_get_status(*((WORD *)value));
                return(0);
                
            case CONTROLLER_INIT:
                InitController(*((WORD *)value));
                return(0);
        
            case CATCH_SIGNALS:
                CatchSignals();
                return(0);
        
            case CPU_RESET:
                cpu_reset();
                return(0);
        
            case CPU_STOP:
                reg.halt = 1;
                return(0);
        
#ifdef JOYSTICK
            case JOYSTICK_OPEN:
                return(OpenJoystick());
        
            case JOYSTICK_CLOSE:
                return(CloseJoystick());
#else
            case JOYSTICK_OPEN:
            case JOYSTICK_CLOSE:
                return(0);
#endif

#ifdef AUDIO
            case AUDIO_OPEN:
                return(OpenAudio());

            case AUDIO_CLOSE:
                return(CloseAudio());
 
            case AUDIO_UPDATE:
                UpdateAudio();
                return(0);

            case AUDIO_READY:
                return(ReadyAudio());
#else
            case AUDIO_OPEN:
            case AUDIO_CLOSE:
            case AUDIO_UPDATE:
                return(0);
            case AUDIO_READY:
                return(AUDIO_DMA_READY);
#endif
        
        } /* switch(command) */



        return(0);   /* to make compiler happy */

} /* int dispatch(int command, void *value) */

