/*  Pcsx - Pc Psx Emulator
 *  Copyright (C) 1999-2003  Pcsx Team
 *
 *  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, see <http://www.gnu.org/licenses>.
 */

#include "psxcommon.h"
#include "r3000a.h"
#include "debug.h"

/*
PCSX Debug console protocol description, version 1.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Commands number are formatted using %03X (yes)
Registers number are formatted using %02X.
Breakpoints numbers are formatted using %X
All other values are formatted using %08X, unless specified.


Client inputs:
~~~~~~~~~~~~~
Basic commands (1xx):
--------------------
100 <message>
    Sends a dumb message. Will be replied with a 200 reply, followed by the message.
101
    Gets PCSX version.
102
    Gets protocol version.
103
    Gets status
110
    Gets PC.
111 [reg]
    Gets GP register, or all, if no argument.
112
    Gets LO/HI registers.
113 [reg]
    Gets COP0 register, or all, if no argument.
114 [reg]
    Gets COP2 control register, or all, if no argument.
115 [reg]
    Gets COP2 data register, or all, if no argument.
119 [pc]
    Disassemble current PC, or given PC.
121 <reg>=<value>
    Sets a GP register. Will return a 221 message.
122 <LO|HI>=<value>
    Sets LO or HI register. Will return a 222 message.
123 <reg>=<value>
    Sets a COP0 register. Will return a 223 message.
124 <reg>=<value>
    Sets a COP2 control register. Will return a 224 message.
125 <reg>=<value>
    Sets a COP2 data register. Will return a 225 message.
130 <size>@<addr>
    Dumps a range of memory, of size bytes starting at addr.
140 <size>@<addr>
    Sets a range of memory, of size bytes starting at addr.
    Will have to send immediately exactly size bytes afterward.
150 [number]
    Starts/reset mapping execution flow, or stop it if number = 0
151 [number]
    Starts/reset mapping read8 flow, or stop it if number = 0
152 [number]
    Starts/reset mapping read16 flow, or stop it if number = 0
153 [number]
    Starts/reset mapping read32 flow, or stop it if number = 0
154 [number]
    Starts/reset mapping write8 flow, or stop it if number = 0
155 [number]
    Starts/reset mapping write16 flow, or stop it if number = 0
156 [number]
    Starts/reset mapping write32 flow, or stop it if number = 0
160 [number]
    Breaks on map exec flow, or stop it if number = 0
161 [number]
    Breaks on map read8 flow, or stop it if number = 0
162 [number]
    Breaks on map read16 flow, or stop it if number = 0
163 [number]
    Breaks on map read32 flow, or stop it if number = 0
164 [number]
    Breaks on map write8 flow, or stop it if number = 0
165 [number]
    Breaks on map write16 flow, or stop it if number = 0
166 [number]
    Breaks on map write32 flow, or stop it if number = 0
170
    Dumps the execution flow map in an IDC file

Execution flow control commands (3xx):
-------------------------------------
300 [number]
    Get a list of the actual breakpoints. Will get '400' answers.
301 [number]
    Deletes a breakpoint, or all, if no arguments.
310 <address>
    Sets an exec breakpoint.
320 <address>
    Sets a read breakpoint, 1 byte / 8 bits.
321 <address>
    Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address.
322 <address>
    Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
330 <address>
    Sets a write breakpoint, 1 byte / 8 bits.
331 <address>
    Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address.
332 <address>
    Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
390
    Pauses execution. Equivalents to a breakpoint.
391
    Restarts execution.
395 [number]
    Traces execution, 1 instruction by default. Formatted using %i
398
    Soft (quick) resets.
399
    Resets.
    

Server outputs:
~~~~~~~~~~~~~~
Spontaneous messages (0xx):
--------------------------
000 <message>
    Greeting banner.
010 / 011 / 012 / 013 / 014 / 015 / 016
    Execution hit mapping flow automatic breakpoint.
030 <number>@<PC>
    Execution hit breakpoint, PCSX is paused. Displays PC's value.

Basic commands acknowledge (2xx):
--------------------------------
200 <message>
    Sends a dumb message.
201 <message>
    Returns PCSX version.
202 <message>
    Returns protocol version.
203 <status>
    status = 0: running; = 1: paused; = 2: trace
210 PC=<value>
    Displays current PC value.
211 <reg>=<value>
    Displays one GP register value.
212 LO=<value> HI=<value>
    Displays LO/HI registers.
213 <reg>=<value>
    Displays one COP0 register value.
214 <reg>=<value>
    Displays one COP2 control register value.
215 <reg>=<value>
    Displays one COP2 data register value.
219 <message>
    Displays one line of disassembled code.
221 <reg>=<value>
    Displays one GP register value, ack for modification.
222 LO=<value> HI=<value>
    Displays LO/HI registers, ack for modification.
223 <reg>=<value>
    Displays one COP0 register value, ack for modification.
224 <reg>=<value>
    Displays one COP2 control register value, ack for modification.
225 <reg>=<value>
    Displays one COP2 data register value, ack for modification.
230 <size>@<addr>
    Dumping memory. Will then raw outputs size bytes.
240 <size>@<addr>
    Memory set acknowledge.
250 / 251 / 252 / 253 / 254 / 255 / 256
    Acknolwedge of 15x commands.
260 / 261 / 262 / 263 / 264 / 265 / 266
    Acknolwedge of 16x commands.
270
    Acknolwedge of 170 command.

Execution flow control commands acknowledge (4xx):
-------------------------------------------------
400 <number>@<address>-<type>
    Displays a breakpoint, where 'type' can be of E, R1, R2, R4, W1, W2 or W4.
401 <message>
    Breakpoint deleting acknowledge.
410, 420, 421, 422, 430, 431, 432 <number>
    Breakpoint adding acknowledge. Returns the number of the added breakpoint.
490 <message>
    Pausing.
491 <message>
    Resuming.
495 <message>
    Tracing.
498 <message>
    Soft resetting.
499 <message>
    Resetting.

Error messages (5xx):
--------------------
500 <message>
    Command not understood.
511 <message>
    Invalid GPR register.
512 <message>
    Invalid LO/HI register.
513, 514 <message>
    Invalid range or address.
530 <message>
    Non existant breakpoint.
531, 532, 533 <message>
    Invalid breakpoint address.
*/

static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 0;
static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0;
static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0;

static void ProcessCommands();

static u8 *MemoryMap = NULL;

enum {
    MAP_EXEC = 1,
    MAP_R8 = 2,
    MAP_R16 = 4,
    MAP_R32 = 8,
    MAP_W8 = 16,
    MAP_W16 = 32,
    MAP_W32 = 64,
    MAP_EXEC_JAL = 128,
};

char *breakpoint_type_names[] = {
    "E", "R1", "R2", "R4", "W1", "W2", "W4"
};

typedef struct breakpoint_s {
    struct breakpoint_s *next, *prev;
    int number, type;
    u32 address;
} breakpoint_t;

static breakpoint_t *first = NULL;

int add_breakpoint(int type, u32 address) {
    breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t));

    bp->type = type;
    bp->address = address;

    if (first) {
        bp->number = first->prev->number + 1;
        bp->next = first;
        bp->prev = first->prev;
        first->prev = bp;
        bp->prev->next = bp;
    } else {
        first = bp;
        bp->number = 1;
        bp->next = bp;
        bp->prev = bp;
    }

    return bp->number;
}

void delete_breakpoint(breakpoint_t * bp) {
    if (bp == first) {
        if (bp->next == bp) {
            first = NULL;
        } else {
            first = bp->next;
        }
    }

    bp->next->prev = bp->prev;
    bp->prev->next = bp->next;

    free(bp);
}

breakpoint_t *next_breakpoint(breakpoint_t *bp) {
    return bp->next != first ? bp->next : 0;
}

breakpoint_t *find_breakpoint(int number) {
    breakpoint_t *p;

    for (p = first; p; p = next_breakpoint(p)) {
        if (p->number == number)
            return p;
    }

    return 0;
}

void StartDebugger() {
}

void StopDebugger() {
}

void PauseDebugger() {
    trace = 0;
    paused = 1;
}

void ResumeDebugger() {
    trace = 0;
    paused = 0;
}

void DebugVSync() {
 
}

void MarkMap(u32 address, int mask) {
}

int IsMapMarked(u32 address, int mask) {
    return (MemoryMap[address & 0x001fffff] & mask) != 0;
}

void ProcessDebug() {
}

static void ProcessCommands() {
  
}

void DebugCheckBP(u32 address, enum breakpoint_types type) {
   
 }
