/*
    exDOS - Experimental 32 Bit protected mode scripted operating system
    (C) 2005 Jason Hunt
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    Contact: nulluser@gmail.com

    File: cmd.c
*/

#include "types.h"
#include "stdio.h"
#include "system.h"
#include "video.h"
#include "fat12.h"
#include "mem.h"
#include "process.h"


/* Get value form buffer, wrap around */
inline byte get_area(byte * buffer, byte x, byte y)
{
    if (x > 79) x = 0;
    if (x == 255) x = 79;
        
    return(buffer[x + y * 80]);        
}
/* End of get_area */


/* Buffer test */
void fire( void )
{
    word *video = (word*) 0xb8000;
    byte *buffer = (byte*) kmallocn(80*25, "fire buffer");

    byte x, y, v;
    word i; 

    while (kbhit());    // Wait for key up
     
    for (i = 80; i < 80*25; i++)
        buffer[i] = 0;

    while(!kbhit())
    {
        // Setup hot spots
        for (x = 0; x < 80; x++)
            buffer[x + 80 * 24] = (rand() % 2) *215 + 26;
        
        // Permutate buffer
        for (x = 0; x < 80; x++)
            for (y = 23; y > 1; y--)
            {
                v =  ((word)get_area(buffer, x, y) + 
                      (word)get_area(buffer, x+1, y+1) +
                      (word)get_area(buffer, x-1, y+1) +
                      (word)get_area(buffer, x, y+1)) >> 2;
   
                 if (v > 4) v -= 4; else v = 0;

                 buffer[x+y*80] = v;
            }       

         // Caclulate color and dump to display
         for (i = 80; i < 80*25; i++)
         {
             v = buffer[i] >> 4;
                  
             video[i] = (v << 8) + (v << 12) + 0x20;
         }                    
    }

    getchar();

    vga_set_cursor(2, 24);
    vga_update_cursor();

    putchar('\n');     

    kfree(buffer);
}
/* End of buffer test */


/* Explore memory */
void mem_dump( void )
{
    byte *addr = (byte *) 0x10000;
    byte i, j;
    byte c;
    byte done = 0;

    vga_disable_cursor_move();

    byte old_x, old_y;
    
    vga_get_cursor(&old_x, &old_y);

    vga_set_cursor(0, 24);
    vga_update_cursor();
    
    vga_set_attr(0x1f); 
    puts("  Memory explorer.  q/a - Move 0x1000   w/s - Move 0x200   Escape to quit       ");
    vga_set_attr(0x0f);

    while(!done)
    {
        vga_set_cursor(0, 1);

        for (j = 0; j < 23; j++)

        {
            vga_put_hex_32((dword)addr);

            putchar(' ');    
                        
            for (i = 0; i < 16; i++)
            {
                vga_put_hex(*addr++); 
                putchar(' ');    
            }    
            putchar(' '); 
            
            addr -= 16;
            
            // Display the memory as text
            for (i = 0; i < 16; i++)
            {
                c = *addr++;
                if (c > 0x20)
                    putchar(c); 
                else
                    putchar('.');
            }    
            puts("      ");
        }        
                                                                                                                 
        c = getchar();                                  /* Get some user input */

        if (c == 0x1b) done = 1; else                   /* Escape exits */
        if (c == 'q') addr -= 0x1000 + 16*23; else      /* Page up fast */
        if (c == 'a') addr += 0x1000 - 16*23; else      /* Page down fast */
        if (c == 'w') addr -= 16*23 * 2;                /* Page up slow */
    }    


    vga_enable_cursor_move();
    
    vga_set_cursor(2, 24);
    vga_update_cursor();

    putchar('\n');
}
/* End of mem_dump */


/* Display help information */
void do_help( void )
{
    puts("Commands:\n");
    puts("  help     - Show help\n");
    puts("  mem      - Kmalloc fragmentation test\n");
    puts("  fire     - Display test\n");
    puts("  dump     - Memory explorer\n");
    puts("  blocks   - Show memory allocations\n");
    puts("  reboot   - Reboot machine\n");
    puts("  mount    - Mount floppy\n");
    puts("  unmount  - Unmount floppy\n");
    puts("  cd       - Change directory\n");
    puts("  ls       - Display directory listing -l for long\n");
    puts("  cat      - Display file from disk\n");
    puts("  ps       - Show process listing\n");
    puts("  task     - Multitasking test, increment screen bytes\n");
}
/* End of do_help */



/* Splits a line into the command and the parameter */
void split_command(byte *line, byte *c, byte *p)
{
    while (*line != ' ' && *line)    // Make command string
        *c++ = *line++;              // Space or null ends the string

    *c = NULL;                        // Null terminate

    if (*line == ' ') line++;

    while (*line) *p++ = *line++;    // Make parameter string

    *p = NULL;                        // Null terminate            
}
/* End of split_command */


/* Kernel command line */
void kernel_cmd( void )
{
    byte line[128];
    byte command[128];
    byte param[128];

    do_help();

    while(1)
    {
        puts("> ");

        getline(line, 128);

        split_command(line, command, param);

        if (!line[0]) continue;// Check for blank line

        if (!strcmp(command, "help")) do_help(); else
        if (!strcmp(command, "reboot")) reboot(); else
        if (!strcmp(command, "dump")) mem_dump(); else
        if (!strcmp(command, "fire")) fire(); else
        if (!strcmp(command, "cat")) fat12_cat(param); else
        if (!strcmp(command, "ls")) fat12_ls(param); else
        if (!strcmp(command, "mem")) mem_test(); else
        if (!strcmp(command, "blocks")) show_blocks(); else
        if (!strcmp(command, "mount")) fat12_mount(); else
        if (!strcmp(command, "unmount")) fat12_unmount(); else
        if (!strcmp(command, "cd")) fat12_cd(param); else
        if (!strcmp(command, "task")) process_test(); else
        if (!strcmp(command, "ps"))  process_show_all(); else
        {
            prints("Unknown Command: ", command);
        }
    }  
}
/* End of kernel_cmd */

        


