/* poke - read a value directly from memory
 *
 * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  This software is provided "as is" without express or
 * implied warranty.
 *
 * V1.0: 27/Nov/94 first version
 */
#define THIS_PROGRAM    "peek"
#define THIS_VERSION    "1.0"

#include <exec/types.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <stdlib.h>
#include <string.h>

#define SysBase_DECLARED
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>

extern struct Library *SysBase;

static const char amiga_version[] = "\0$VER: " THIS_PROGRAM " " THIS_VERSION " (" __COMMODORE_DATE__ ")";

const char Template[] = "ADDR/A,B=BYTE/S,S=SHORT=W=WORD/S,L=LONG/S,H=X=HEX/S";
__aligned struct {
    STRPTR  addr;
    LONG    isbyte, isword, islong;
    LONG    hex;
} Args;


void
_main()
{
    struct RDArgs *rdargs;
    APTR addr;
    ULONG val;
    LONG rc = RETURN_OK;

    /* RawDoFmt() 'put' function
     * MC68000 machine code:
     *      move.b d0,(a3)+
     *      rts
     * Idea by Doug Walker, walker@unx.sas.com
     */
    __aligned const unsigned char rawdocode[] = { 0x16, 0xC0, 0x4E, 0x75 };


    if( SysBase->lib_Version < 37 ) {
        #define MESSAGE "requires AmigaOS 2.04 or higher\n"
        Write(Output(), MESSAGE, sizeof(MESSAGE)-1);
        _exit(RETURN_FAIL);
        #undef MESSAGE
    }

    if( rdargs = ReadArgs(Template, (LONG *)&Args, NULL) ) {
        int used = 0;
        if( Args.isbyte )   used++;
        if( Args.isword )   used++;
        if( Args.islong )   used++;
        if( used > 1 ) {
            PutStr("only one type specifier allowed\n");
            rc = RETURN_ERROR;
        }
        else {
            char buf[16] = {0};
            char *endp1;

            addr = (APTR)strtoul(Args.addr, &endp1, 0);
            if( *endp1 != '\0' ) {
                PutStr("invalid address\n");
                rc = RETURN_ERROR;
            }
            else {
                if( Args.islong )
                    val = *(ULONG *)addr;
                else
                if( Args.isword )
                    val = (ULONG)(*(USHORT *)addr);
                else
                    val = (ULONG)(*(UBYTE *)addr);

                if( Args.hex )
                    endp1 = "0x%lx\n";
                else
                    endp1 = "%ld\n";
                RawDoFmt(endp1, (APTR)&val, (void (*)())rawdocode, buf);
                PutStr(buf);
            }
        }
        FreeArgs(rdargs);
    }
    else {
        PutStr("required argument missing\n");
        rc = RETURN_ERROR;
    }
    _exit((int)rc);
}

