Esempio n. 1
0
void storew (zword addr, zword value)
{

    storeb ((zword) (addr + 0), hi (value));
    storeb ((zword) (addr + 1), lo (value));

}/* storew */
Esempio n. 2
0
File: table.c Progetto: BAM-X/frotz
/*
 * z_copy_table, copy a table or fill it with zeroes.
 *
 *	zargs[0] = address of table
 * 	zargs[1] = destination address or 0 for fill
 *	zargs[2] = size of table
 *
 * Note: Copying is safe even when source and destination overlap; but
 *       if zargs[1] is negative the table _must_ be copied forwards.
 *
 */
void z_copy_table (void)
{
    zword addr;
    zword size = zargs[2];
    zbyte value;
    int i;

    if (zargs[1] == 0)      				/* zero table */

	for (i = 0; i < size; i++)
	    storeb ((zword) (zargs[0] + i), 0);

    else if ((short) size < 0 || zargs[0] > zargs[1])	/* copy forwards */

	for (i = 0; i < (((short) size < 0) ? - (short) size : size); i++) {
	    addr = zargs[0] + i;
	    LOW_BYTE (addr, value)
	    storeb ((zword) (zargs[1] + i), value);
	}

    else						/* copy backwards */

	for (i = size - 1; i >= 0; i--) {
	    addr = zargs[0] + i;
	    LOW_BYTE (addr, value)
	    storeb ((zword) (zargs[1] + i), value);
	}

}/* z_copy_table */
Esempio n. 3
0
void Mem::restart_header(void) {
	zword screen_x_size;
	zword screen_y_size;
	zbyte font_x_size;
	zbyte font_y_size;

	int i;

	SET_BYTE(H_CONFIG, h_config);
	SET_WORD(H_FLAGS, h_flags);

	if (h_version >= V4) {
		SET_BYTE(H_INTERPRETER_NUMBER, h_interpreter_number);
		SET_BYTE(H_INTERPRETER_VERSION, h_interpreter_version);
		SET_BYTE(H_SCREEN_ROWS, h_screen_rows);
		SET_BYTE(H_SCREEN_COLS, h_screen_cols);
	}

	// It's less trouble to use font size 1x1 for V5 games, especially because of
	// a bug in the unreleased German version of "Zork 1"

	if (h_version != V6) {
		screen_x_size = (zword)h_screen_cols;
		screen_y_size = (zword)h_screen_rows;
		font_x_size = 1;
		font_y_size = 1;
	} else {
		screen_x_size = h_screen_width;
		screen_y_size = h_screen_height;
		font_x_size = h_font_width;
		font_y_size = h_font_height;
	}

	if (h_version >= V5) {
		SET_WORD(H_SCREEN_WIDTH, screen_x_size);
		SET_WORD(H_SCREEN_HEIGHT, screen_y_size);
		SET_BYTE(H_FONT_HEIGHT, font_y_size);
		SET_BYTE(H_FONT_WIDTH, font_x_size);
		SET_BYTE(H_DEFAULT_BACKGROUND, h_default_background);
		SET_BYTE(H_DEFAULT_FOREGROUND, h_default_foreground);
	}

	if (h_version == V6)
		for (i = 0; i < 8; i++)
			storeb((zword)(H_USER_NAME + i), h_user_name[i]);

	SET_BYTE(H_STANDARD_HIGH, h_standard_high);
	SET_BYTE(H_STANDARD_LOW, h_standard_low);

	set_header_extension(HX_FLAGS, hx_flags);
	set_header_extension(HX_FORE_COLOUR, hx_fore_colour);
	set_header_extension(HX_BACK_COLOUR, hx_back_colour);
}
Esempio n. 4
0
void memory_new_line (void)
{
    zword size;
    zword addr;

    redirect[depth].total += redirect[depth].width;
    redirect[depth].width = 0;

    addr = redirect[depth].table;

    LOW_WORD (addr, size)
    addr += 2;

    if (redirect[depth].xsize != 0xffff) {

	redirect[depth].table = addr + size;
	size = 0;

    } else storeb ((zword) (addr + (size++)), 13);

    storew (redirect[depth].table, size);

}/* memory_new_line */
Esempio n. 5
0
void memory_word (const zword *s)
{
    zword size;
    zword addr;
    zword c;

    if (h_version == V6) {

	int width = os_string_width (s);

	if (redirect[depth].xsize != 0xffff)

	    if (redirect[depth].width + width > redirect[depth].xsize) {

		if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
		    width = os_string_width (++s);

		memory_new_line ();

	    }

	redirect[depth].width += width;

    }

    addr = redirect[depth].table;

    LOW_WORD (addr, size)
    addr += 2;

    while ((c = *s++) != 0)
	storeb ((zword) (addr + (size++)), translate_to_zscii (c));

    storew (redirect[depth].table, size);

}/* memory_word */
Esempio n. 6
0
void Mem::storew(zword addr, zword value) {
	storeb((zword)(addr + 0), hi(value));
	storeb((zword)(addr + 1), lo(value));
}
Esempio n. 7
0
void Processor::z_read() {
	zchar buffer[INPUT_BUFFER_SIZE];
	zword addr;
	zchar key;
	zbyte max, size;
	zbyte c;
	int i;

	// Supply default arguments
	if (zargc < 3)
		zargs[2] = 0;

	// Get maximum input size
	addr = zargs[0];

	LOW_BYTE(addr, max);

	if (h_version <= V4)
		max--;

	if (max >= INPUT_BUFFER_SIZE)
		max = INPUT_BUFFER_SIZE - 1;

	// Get initial input size
	if (h_version >= V5) {
		addr++;
		LOW_BYTE(addr, size);
	} else {
		size = 0;
	}

	// Copy initial input to local buffer
	for (i = 0; i < size; i++) {
		addr++;
		LOW_BYTE(addr, c);
		buffer[i] = translate_from_zscii(c);
	}
	buffer[i] = 0;

	// Draw status line for V1 to V3 games
	if (h_version <= V3)
		z_show_status();

	// Read input from current input stream
	key = stream_read_input(
		max, buffer,		// buffer and size
		zargs[2],			// timeout value
		zargs[3],			// timeout routine
		false,				// enable hot keys
		h_version == V6		// no script in V6
	);

	if (key == ZC_BAD)
		return;

	// Perform save_undo for V1 to V4 games
	if (h_version <= V4)
		save_undo();

	// Copy local buffer back to dynamic memory
	for (i = 0; buffer[i] != 0; i++) {
		if (key == ZC_RETURN) {
			buffer[i] = unicode_tolower (buffer[i]);
		}

		storeb((zword)(zargs[0] + ((h_version <= V4) ? 1 : 2) + i), translate_to_zscii(buffer[i]));
	}

	// Add null character (V1-V4) or write input length into 2nd byte
	if (h_version <= V4)
		storeb((zword)(zargs[0] + 1 + i), 0);
	else
		storeb((zword)(zargs[0] + 1), i);

	// Tokenise line if a token buffer is present
	if (key == ZC_RETURN && zargs[1] != 0)
		tokenise_line (zargs[0], zargs[1], 0, false);

	// Store key
	if (h_version >= V5)
		store(translate_to_zscii(key));
}
Esempio n. 8
0
void NewCpu::Step()
{
    if (_stealCycles > 0)
    {
        _stealCycles--;
    }
    else if (_dmaCycles > 0)
    {
        if (_dmaCycles % 2 == 0)
        {
            _value = loadb(_dmaAddr++);
        }
        else
        {
            storeb(0x2004, _value);
        }
        _dmaCycles--;
        if (_dmaCycles == 0)
        {
            _dmaAddr = 0;
            EndInstr();
        }
    }
    else if (_cycle == 0)
    {
        if (_wantNmi)
        {
            _type = InstrType::NMI;
            _wantNmi = false;
            _cycle = 1;
        }
        else if (_wantIrq && !_regs.GetFlag(Flag::IRQ))
        {
            _type = InstrType::IRQ;
            _wantIrq = false;
            _cycle = 1;
        }
        else
        {
#if defined(TRACE)
            Trace();
#endif
            _op = LoadBBumpPC();
            Decode();
            _cycle = 1;
        }
    }
    else
    {
        switch (_type)
        {
        case InstrType::BRK:
            switch (_cycle)
            {
            case 1: LoadBBumpPC(); _cycle++; break;
            case 2: PushB(_regs.PC.B.H); _cycle++; break;
            case 3: PushB(_regs.PC.B.L); _cycle++; break;
            case 4: PushB(_regs.P | (u8)Flag::Break | (u8)Flag::Unused); _cycle++; break;
            case 5: _regs.PC.B.L = loadb(IRQ_VECTOR); _cycle++; break;
            case 6: _regs.PC.B.H = loadb(IRQ_VECTOR + 1); _regs.SetFlag(Flag::IRQ, true); EndInstr(); break;
            }
            break;
        case InstrType::NMI:
            switch (_cycle)
            {
            case 1: _cycle++; break;
            case 2: PushB(_regs.PC.B.H); _cycle++; break;
            case 3: PushB(_regs.PC.B.L); _cycle++; break;
            case 4: PushB(_regs.P); _cycle++; break;
            case 5: _regs.PC.B.L = loadb(NMI_VECTOR); _cycle++; break;
            case 6: _regs.PC.B.H = loadb(NMI_VECTOR + 1); EndInstr(); break;
            }
            break;
        case InstrType::IRQ:
            switch (_cycle)
            {
            case 1: _cycle++; break;
            case 2: PushB(_regs.PC.B.H); _cycle++; break;
            case 3: PushB(_regs.PC.B.L); _cycle++; break;
            case 4: PushB(_regs.P); _cycle++; break;
            case 5: _regs.PC.B.L = loadb(IRQ_VECTOR); _cycle++; break;
            case 6: _regs.PC.B.H = loadb(IRQ_VECTOR + 1); _regs.SetFlag(Flag::IRQ, true); EndInstr(); break;
            }
            break;
        case InstrType::RTI:
            switch (_cycle)
            {
            case 1: loadb(_regs.PC.W); _cycle++; break;
            case 2: _regs.SP++; _cycle++; break;
            case 3: _regs.P = loadb(0x100 | _regs.SP++); _cycle++; break;
            case 4: _regs.PC.B.L = loadb(0x100 | _regs.SP++); _cycle++; break;
            case 5: _regs.PC.B.H = loadb(0x100 | _regs.SP); EndInstr(); break;
            }
            break;
        case InstrType::RTS:
            switch (_cycle)
            {
            case 1: loadb(_regs.PC.W); _cycle++; break;
            case 2: _regs.SP++; _cycle++; break;
            case 3: _regs.PC.B.L = loadb(0x100 | _regs.SP++); _cycle++; break;
            case 4: _regs.PC.B.H = loadb(0x100 | _regs.SP); _cycle++; break;
            case 5: _regs.PC.W++; EndInstr(); break;
            }
            break;
        case InstrType::PHAorPHP:
            switch (_cycle)
            {
            case 1: loadb(_regs.PC.W); _cycle++; break;
            case 2: 
                if (_pIdxReg == &_regs.P)
                {
                    PushB(*_pIdxReg | (u8)Flag::Break | (u8)Flag::Unused);
                }
                else
                {
                    PushB(*_pIdxReg);
                }
                EndInstr();
                break;
            }
            break;
        case InstrType::PLAorPLP:
            switch (_cycle)
            {
            case 1: loadb(_regs.PC.W); _cycle++; break;
            case 2: _regs.SP++; _cycle++; break;
            case 3:
                *_pIdxReg = loadb(0x100 | _regs.SP);
                if (_pIdxReg == &_regs.A)
                {
                    _regs.SetZN(_regs.A);
                }
                EndInstr();
                break;
            }
            break;
        case InstrType::JSR:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: _cycle++; break;
            case 3: PushB(_regs.PC.B.H); _cycle++; break;
            case 4: PushB(_regs.PC.B.L); _cycle++; break;
            case 5: _regs.PC.B.H = loadb(_regs.PC.W); _regs.PC.B.L = _value; EndInstr(); break;
            }
            break;
        case InstrType::Implied:
            loadb(_regs.PC.W); // throwaway read
            (*this.*_action)();
            EndInstr();
            break;
        case InstrType::Accumulator:
            loadb(_regs.PC.W);
            _value = _regs.A;
            (*this.*_action)();
            _regs.A = _value;
            EndInstr();
            break;
        case InstrType::Immediate:
            _value = LoadBBumpPC();
            (*this.*_action)();
            EndInstr();
            break;
        case InstrType::AbsoluteJmp:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: _regs.PC.B.H = LoadBBumpPC(); _regs.PC.B.L = _value; EndInstr(); break;
            }
            break;
        case InstrType::AbsoluteRead:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.H = LoadBBumpPC(); _cycle++; break;
            case 3:
                _value = loadb(_addr.W);
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::AbsoluteRMW:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.H = LoadBBumpPC(); _cycle++; break;
            case 3: _value = loadb(_addr.W); _cycle++; break;
            case 4: storeb(_addr.W, _value); (*this.*_action)(); _cycle++; break;
            case 5: storeb(_addr.W, _value); EndInstr(); break;
            }
            break;
        case InstrType::AbsoluteWrite:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.H = LoadBBumpPC(); _cycle++; break;
            case 3: 
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::ZPRead:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: _value = loadb(_addr.W); (*this.*_action)(); EndInstr(); break;
            }
            break;
        case InstrType::ZPRMW:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: _value = loadb(_addr.W); _cycle++; break;
            case 3: storeb(_addr.W, _value); (*this.*_action)(); _cycle++; break;
            case 4: storeb(_addr.W, _value); EndInstr(); break;
            }
            break;
        case InstrType::ZPWRite:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: (*this.*_action)(); EndInstr(); break;
            }
            break;
        case InstrType::ZPIndexedRead:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_addr.W); _addr.B.L = (u8)(_addr.B.L + *_pIdxReg); _cycle++; break;
            case 3: _value = loadb(_addr.W); (*this.*_action)(); EndInstr(); break;
            }
            break;
        case InstrType::ZPIndexedRMW:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_addr.W); _addr.B.L = (u8)(_addr.B.L + _regs.X); _cycle++; break;
            case 3: _value = loadb(_addr.W); _cycle++; break;
            case 4: storeb(_addr.W, _value); (*this.*_action)(); _cycle++; break;
            case 5: storeb(_addr.W, _value); EndInstr(); break;
            }
            break;
        case InstrType::ZPIndexedWrite:
            switch (_cycle)
            {
            case 1: _addr.W = (u16)LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_addr.W); _addr.B.L = (u8)(_addr.B.L + *_pIdxReg); _cycle++; break;
            case 3: (*this.*_action)(); EndInstr(); break;
            }
            break;
        case InstrType::AbsoluteIndexedRead:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2:
                _addr.B.H = LoadBBumpPC();
                Pair newAddr;
                newAddr.W = (u16)_addr.B.L + (u16)*_pIdxReg;
                _addr.B.L = newAddr.B.L;
                _pageCross = newAddr.B.H != 0;
                _cycle++;
                break;
            case 3:
                _value = loadb(_addr.W);
                if (_pageCross)
                {
                    _addr.B.H++;
                    _cycle++;
                }
                else
                {
                    (*this.*_action)();
                    EndInstr();
                }
                break;
            case 4:
                _value = loadb(_addr.W);
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::AbsoluteIndexedRMW:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2:
                _addr.B.H = LoadBBumpPC();
                Pair newAddr;
                newAddr.W = (u16)_addr.B.L + (u16)_regs.X;
                _addr.B.L = newAddr.B.L;
                _pageCross = newAddr.B.H != 0;
                _cycle++;
                break;
            case 3:
                loadb(_addr.W);
                if (_pageCross)
                {
                    _addr.B.H++;
                }
                _cycle++;
                break;
            case 4: _value = loadb(_addr.W); _cycle++; break;
            case 5: storeb(_addr.W, _value); (*this.*_action)(); _cycle++; break;
            case 6: storeb(_addr.W, _value); EndInstr(); break;
            }
            break;
        case InstrType::AbsoluteIndexedWrite:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2: 
                _addr.B.H = LoadBBumpPC();
                Pair newAddr;
                newAddr.W = (u16)_addr.B.L + (u16)*_pIdxReg;
                _addr.B.L = newAddr.B.L;
                _pageCross = newAddr.B.H != 0;
                _cycle++;
                break;
            case 3:
                loadb(_addr.W);
                if (_pageCross)
                {
                    _addr.B.H++;
                }
                _cycle++;
                break;
            case 4:
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::Relative:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: 
                {
                    u8 op = loadb(_regs.PC.W);
                    (*this.*_action)();
                    if (_doBranch)
                    {
                        Pair newPC;
                        newPC.W = (u16)((i32)(i16)_regs.PC.W + (i32)(i8)_value);
                        _regs.PC.B.L = newPC.B.L;
                        _pageCross = newPC.B.H != _regs.PC.B.H;
                        _value = newPC.B.H;
                        _cycle++;
                    }
                    else
                    {
                        EndInstr();
#if defined(TRACE)
                        Trace();
#endif
                        _op = op;
                        _regs.PC.W++;
                        Decode();
                        _cycle = 1;
                    }
                }
                break;
            case 3:
                {
                    u8 op = loadb(_regs.PC.W);
                    if (_pageCross)
                    {
                        _regs.PC.B.H = _value;
                        _cycle++;
                    }
                    else
                    {
                        EndInstr();
#if defined(TRACE)
                        Trace();
#endif
                        _op = op;
                        _regs.PC.W++;
                        Decode();
                        _cycle = 1;
                    }
                }
                break;
            case 4:
                {
#if defined(TRACE)
                    Trace();
#endif
                    _op = LoadBBumpPC();
                    Decode();
                    _cycle = 1;
                }
                break;
            }
            break;
        case InstrType::IndexedIndirectRead:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_value); _value += _regs.X; _cycle++; break;
            case 3: _addr.B.L = loadb(_value); _cycle++; break;
            case 4: _addr.B.H = loadb((u8)(_value + 1)); _cycle++; break;
            case 5: _value = loadb(_addr.W); (*this.*_action)();  EndInstr(); break;
            }
            break;
        case InstrType::IndexedIndirectRMW:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_value); _value += _regs.X; _cycle++; break;
            case 3: _addr.B.L = loadb(_value); _cycle++; break;
            case 4: _addr.B.H = loadb((u8)(_value + 1)); _cycle++; break;
            case 5: _value = loadb(_addr.W); _cycle++; break;
            case 6: storeb(_addr.W, _value); (*this.*_action)(); _cycle++; break;
            case 7: storeb(_addr.W, _value); EndInstr(); break;
            }
            break;
        case InstrType::IndexedIndirectWrite:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: loadb(_value); _value += _regs.X; _cycle++; break;
            case 3: _addr.B.L = loadb(_value); _cycle++; break;
            case 4: _addr.B.H = loadb((u8)(_value + 1)); _cycle++; break;
            case 5: (*this.*_action)(); EndInstr(); break;
            }
            break;
        case InstrType::IndirectIndexedRead:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.L = loadb(_value); _cycle++; break;
            case 3: 
                _addr.B.H = loadb((u8)(_value + 1));
                Pair newAddr;
                newAddr.W = (u16)_addr.B.L + (u16)_regs.Y;
                _addr.B.L = newAddr.B.L;
                _pageCross = newAddr.B.H != 0;
                _cycle++;
                break;
            case 4:
                _value = loadb(_addr.W);
                if (_pageCross)
                {
                    _addr.B.H++;
                    _cycle++;
                }
                else
                {
                    (*this.*_action)();
                    EndInstr();
                }
                break;
            case 5:
                _value = loadb(_addr.W);
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::IndirectIndexedRMW:
            __debugbreak();
            break;
        case InstrType::IndirectIndexedWrite:
            switch (_cycle)
            {
            case 1: _value = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.L = loadb(_value); _cycle++; break;
            case 3:
                _addr.B.H = loadb((u8)(_value + 1));
                Pair newAddr;
                newAddr.W = (u16)_addr.B.L + (u16)_regs.Y;
                _addr.B.L = newAddr.B.L;
                _pageCross = newAddr.B.H != 0;
                _cycle++;
                break;
            case 4:
                loadb(_addr.W);
                if (_pageCross)
                {
                    _addr.B.H++;
                }
                _cycle++;
                break;
            case 5:
                (*this.*_action)();
                EndInstr();
                break;
            }
            break;
        case InstrType::AbsoluteIndirectJmp:
            switch (_cycle)
            {
            case 1: _addr.B.L = LoadBBumpPC(); _cycle++; break;
            case 2: _addr.B.H = LoadBBumpPC(); _cycle++; break;
            case 3: _value = loadb(_addr.W); _cycle++; break;
            case 4: _addr.B.L = u8(_addr.B.L + 1); _regs.PC.B.L = _value; _regs.PC.B.H = loadb(_addr.W); EndInstr(); break;
            }
            break;
        default:
            __debugbreak();
        }
    }
}