1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00
2015-11-03 19:54:12 +07:00

151 lines
2.9 KiB
C
Executable File

/*
* Implementation of vimlac memory.
*
* Memory size is a compile-time constant.
* The code here handles indirect memory references as will
* as the 8 auto-index registers at 010-017 in every 2K block.
*/
#include <stdio.h>
#include "memory.h"
/*****
* constants for the memory
******/
/* size of memory is 16K words */
#define ADDR_MASK 0x3fff
/* mask and limits to check if address is auto-index register */
#define INDEX_MASK 03777
#define LOWER_INDEX 010
#define HIGHER_INDEX 017
/*****
* State variables for the memory emulation
******/
#define ROM_START 040
#define ROM_END 077
#define ROM_SIZE (ROM_END - ROM_START + 1)
static bool rom_readonly = false;
/* the physical memory */
static WORD memory[MEM_SIZE];
/******
* Macro to decide if we are using an auto-index register
******/
#define AUTO_INDEX(a) (((a & INDEX_MASK) >= LOWER_INDEX) && ((a & INDEX_MASK) <= HIGHER_INDEX))
WORD
mem_get(WORD address, bool indirect)
{
WORD a = address & ADDR_MASK; /* wrap address to physical memory */
WORD result;
if (indirect && AUTO_INDEX(a)) /* if auto-index and indirect, increment */
memory[a] = (memory[a] + 1) & WORD_MASK;
result = memory[a & ADDR_MASK];
if (indirect)
result = memory[result & ADDR_MASK];
return result;
}
void
mem_put(WORD address, bool indirect, WORD value)
{
WORD a = address & ADDR_MASK; /* wrap address to physical memory */
if (indirect && AUTO_INDEX(a)) /* if auto-index and indirect, increment */
memory[a] = (memory[a] + 1) & WORD_MASK;
if (indirect)
a = memory[a & ADDR_MASK];
memory[a & ADDR_MASK] = value;
}
void
mem_clear(WORD value)
{
if (rom_readonly)
{ /* save the ROM contents */
WORD rom[ROM_SIZE];
memcpy(rom, &memory[ROM_START], sizeof(WORD)*ROM_SIZE);
memset(memory, value, sizeof(WORD)*MEM_SIZE);
memcpy(&memory[ROM_START], rom, sizeof(WORD)*ROM_SIZE);
}
else
memset(memory, value, sizeof(WORD)*MEM_SIZE);
}
void
mem_set_rom(WORD *rom)
{
rom_readonly = true;
memcpy(&memory[ROM_START], rom, sizeof(WORD)*ROM_SIZE);
}
void
mem_set_rom_readonly(bool readonly)
{
rom_readonly = readonly;
}
void
mem_load_core(char *filename)
{
FILE *fd = fopen(filename, "rb");
WORD addr;
for (addr = 0; addr < MEM_SIZE; ++addr)
{
unsigned char byte1;
unsigned char byte2;
WORD value;
fread(&byte1, 1, 1, fd);
fread(&byte2, 1, 1, fd);
value = (byte1 << 8) + byte2;
memory[addr] = value;
}
fclose(fd);
}
void
mem_save_core(char *filename)
{
FILE *fd = fopen(filename, "wb");
WORD addr;
/* write memory in bytes, get around endian problems */
for (addr = 0; addr < MEM_SIZE; ++addr)
{
unsigned char byte;
WORD value;
value = memory[addr];
byte = (value >> 8) & 0xff;
fwrite(&byte, 1, 1, fd);
byte = value & 0xff;
fwrite(&byte, 1, 1, fd);
}
fclose(fd);
}
void
mem_set_PTR_rom(void)
{
}