// zeal - A portable Glk-based Z-code interpreter
// Copyright (C) 2000 Jeremy Condit <jcondit@eecs.harvard.edu>
// 
// 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.

// =======================================================================
//  alpha.cc:
//
//  the alphabet class represents an alphabet table in the z-machine
//  memory or the default table if a custom one is not specified.
// =======================================================================
 
#include "zeal.h"
#include "error.h"
#include "alpha.h"
#include "machine.h"

extern machine* m;

// =======================================================================
//  alphabet
// =======================================================================

// static data
//
// the alphabet tables used for versions 1 and 2+, respectively.

const char* alphabet::table1[] =
{
    "abcdefghijklmnopqrstuvwxyz",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    " 0123456789.,!?_#'\"/\\<-:()"
};

const char* alphabet::table2[] =
{
    "abcdefghijklmnopqrstuvwxyz",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
    " \r0123456789.,!?_#'\"/\\-:()"
};

// constructor/destructor
//
// maintains addresses used to locate either one of the standard
// translation tables (in zeal's memory) or a custom table (in the game's
// memory).

alphabet::alphabet()
  : custom(0), standard(0)
{
    ubyte ver = m->version();

    standard = (ver == 1) ? table1 : table2;
    custom = (ver >= 5) ? m->read_word(HEADER_ALPHA_BASE) : 0;
}

alphabet::~alphabet()
{
}

// zchar_to_zscii
//
// converts a z-char to zscii by looking it up in either the custom or
// standard tables.

ubyte
alphabet::zchar_to_zscii(int a, ubyte zchar)
{
    ASSERT(a >= 0 && a <= 2);
    ASSERT(zchar >= 6 && zchar <= 31);

    if (custom != 0) {
        return m->read_byte(custom + (a * 26) + zchar - 6);
    } else {
        return standard[a][zchar - 6];
    }
}

// zscii_to_zchar
//
// converts a zscii char to a z-char by attempting to find a mapping in
// the alphabet table.  return value indicates whether such a value was
// found.

bool
alphabet::zscii_to_zchar(ubyte zscii, int* a, ubyte* zchar)
{
    ASSERT(a != NULL);
    ASSERT(zchar != NULL);

    // take a guess
    if (zscii >= 'a' && zscii <= 'z' &&
        zscii == zchar_to_zscii(0, zscii - 'a' + 6)) {
        *a = 0;
        *zchar = zscii - 'a' + 6;
        return true;
    }

    // that didn't work--do an exhaustive search
    for (int i = 0; i < 3; i++) {
        for (int j = (i == 2) ? 7 : 6; j < 32; j++) {
            if (zchar_to_zscii(i, j) == zscii) {
                *a = i;
                *zchar = j;
                return true;
            }
        }
    }

    return false;
}
