Skip to content
This repository has been archived by the owner on Jun 27, 2018. It is now read-only.

Commit

Permalink
Fixed bugs in timer and LEM1802 hardware.
Browse files Browse the repository at this point in the history
Fixed hardware accessing registers incorrectly.
Implemented DUMP_PALETTE and DUMP_FONT functionality into LEM1802 hardware.
Updated verbosity of interrupt debugging messages to be correct.
Fixed vm_halt() function and messages; added vprintd() function.
Fixed timer to use host time() function for determining when to fire.
  • Loading branch information
hach-que committed Jun 4, 2012
1 parent 61d6152 commit ce15102
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 39 deletions.
1 change: 1 addition & 0 deletions libdcpu-vm/dcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void vm_init(vm_t* vm, bool init_memory)
vm->dummy = 0x0;
vm->halted = false;
vm->skip = false;
printd(LEVEL_DEBUG, "turning off interrupt queue\n");
vm->queue_interrupts = false;
vm->irq_count = 0;
for (i = 0; i < 256; i++)
Expand Down
15 changes: 8 additions & 7 deletions libdcpu-vm/dcpubase.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void vm_halt(vm_t* vm, const char* message, ...)
{
va_list argptr;
va_start(argptr, message);
vfprintf(stderr, message, argptr);
vprintd(LEVEL_DEFAULT, message, argptr);
va_end(argptr);
vm->halted = true;
return;
Expand All @@ -47,23 +47,24 @@ void vm_interrupt(vm_t* vm, uint16_t msgid)
else
{
vm->irq[vm->irq_count++] = msgid;
printd(LEVEL_DEFAULT, "appending interrupt %u to interrupt queue\n", msgid);
printd(LEVEL_DEBUG, "appending interrupt %u to interrupt queue\n", msgid);
}
}
else
{
if (vm->ia == 0)
{
printd(LEVEL_DEFAULT, "ignoring request to fire interrupt %u\n", msgid);
printd(LEVEL_DEBUG, "ignoring request to fire interrupt %u\n", msgid);
return;
}

vm->ram[--vm->sp] = vm->pc;
vm->ram[--vm->sp] = vm->registers[REG_A];
vm->pc = vm->ia;
vm->registers[REG_A] = msgid;
printd(LEVEL_DEBUG, "turning on interrupt queue\n");
vm->queue_interrupts = true;
printd(LEVEL_DEFAULT, "executing interrupt %u right now\n", msgid);
printd(LEVEL_DEBUG, "executing interrupt %u right now\n", msgid);
}
}

Expand Down Expand Up @@ -228,7 +229,7 @@ void vm_cycle(vm_t* vm)
if (!vm->queue_interrupts && vm->irq_count > 0)
{
a = vm->irq[0];
printd(LEVEL_ERROR, "sending interrupt handler with msgid %u\n");
printd(LEVEL_DEBUG, "sending interrupt handler with msgid %u\n");
memcpy(&vm->irq, &vm->irq[1], INTERRUPT_MAX * sizeof(uint16_t));
vm->irq[INTERRUPT_MAX] = 0;
vm->irq_count--;
Expand Down Expand Up @@ -429,14 +430,14 @@ void vm_cycle(vm_t* vm)
break;

default:
vm_halt(vm, "Invalid non-basic opcode %u. (0x%04X at 0x%04X)", b, instruction, vm->pc);
vm_halt(vm, "Invalid non-basic opcode %u. (0x%04X at 0x%04X)\n", b, instruction, vm->pc);
break;
}

break;

default:
vm_halt(vm, "Invalid opcode %u. (0x%04X at 0x%04X)", op, instruction, vm->pc);
vm_halt(vm, "Invalid opcode %u. (0x%04X at 0x%04X)\n", op, instruction, vm->pc);
break;
}

Expand Down
2 changes: 1 addition & 1 deletion libdcpu-vm/dcpuhook.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ uint16_t vm_hook_register(vm_t* vm, vm_hook hook, uint16_t mode, void* ud)

if (id >= HOOK_MAX)
{
vm_halt(vm, "unable to register hook, maximum reached!");
vm_halt(vm, "unable to register hook, maximum reached!\n");
return 0;
}

Expand Down
17 changes: 11 additions & 6 deletions libdcpu-vm/dcpuops.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,9 @@ void vm_op_int(vm_t* vm, uint16_t a)
uint16_t val_a = vm_resolve_value(vm, a, POS_A);
OP_NUM_CYCLES(4);

printd(LEVEL_DEFAULT, "sending interrupt %u\n", val_a);
printd(LEVEL_DEBUG, "turning off interrupt queue\n");
vm->queue_interrupts = false;
printd(LEVEL_DEBUG, "sending interrupt %u\n", val_a);
vm_interrupt(vm, val_a);
}

Expand All @@ -599,7 +600,9 @@ void vm_op_rfi(vm_t* vm, uint16_t a)
VM_SKIP_RESET;
vm->registers[REG_A] = vm->ram[vm->sp++];
vm->pc = vm->ram[vm->sp++];
printd(LEVEL_DEBUG, "turning off interrupt queue\n");
vm->queue_interrupts = false;
printd(LEVEL_DEBUG, "returning from interrupt.\n");
VM_HOOK_FIRE(&vm->registers[REG_A]);
}

Expand All @@ -611,16 +614,18 @@ void vm_op_iaq(vm_t* vm, uint16_t a)

VM_SKIP_RESET;

printd(LEVEL_DEBUG, "IAQ CALLED WITH %u\n", val_a);

if (val_a == 0)
{
// Should we even be doing this???
//for (i = 0; i < vm->irq_count; i++)
// vm_interrupt(vm, vm->irq[i]);
//vm->irq_count = 0;
printd(LEVEL_DEBUG, "turning off interrupt queue\n");
vm->queue_interrupts = false;
}
else
{
printd(LEVEL_DEBUG, "turning on interrupt queue\n");
vm->queue_interrupts = true;
}
}

void vm_op_hwn(vm_t* vm, uint16_t a)
Expand Down Expand Up @@ -655,7 +660,7 @@ void vm_op_hwq(vm_t* vm, uint16_t a)
{
queried_device = vm_hw_get_device(vm, val_a);

if (vm->debug) printf("\nhwq: index %d %08X", val_a, queried_device.id);
printd(LEVEL_DEBUG, "hwq: index %d %08X\n", val_a, queried_device.id);

*store_a = (queried_device.id & 0x0000FFFF) >> 0;
*store_b = (queried_device.id & 0xFFFF0000) >> 16;
Expand Down
27 changes: 22 additions & 5 deletions libdcpu-vm/hwlem1802.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
#include <stdio.h>
#include <string.h>
#include <bstring.h>

#include <debug.h>
#include "hw.h"
#include "hwlem1802.h"
#include "hwlem1802mem.h"
#include "hwlem1802util.h"
#include "hwioascii.h"
#include "dcpuhook.h"
#include "dcpubase.h"
Expand Down Expand Up @@ -203,33 +204,49 @@ void vm_hw_lem1802_break(vm_t* vm, uint16_t pos, void* ud)

void vm_hw_lem1802_interrupt(vm_t* vm, void* ud)
{
uint16_t requested_action = vm_resolve_value(vm, REG_A, 0);
uint16_t val_b = vm_resolve_value(vm, REG_B, 0);
uint16_t requested_action = vm->registers[REG_A];
uint16_t val_b = vm->registers[REG_B];
uint16_t idx = 0;
uint32_t store;

switch (requested_action)
{
case LEM1802_MEM_MAP_SCREEN:
printd(LEVEL_DEBUG, "LEM1802 SCREEN MAPPED.\n");
vm_hw_lem1802_mem_set_screen(vm, val_b);
break;

case LEM1802_MEM_MAP_FONT:
printd(LEVEL_DEBUG, "LEM1802 FONT MAPPED.\n");
vm_hw_lem1802_mem_set_font(vm, val_b);
break;

case LEM1802_MEM_MAP_PALETTE:
printd(LEVEL_DEBUG, "LEM1802 PALETTE MAPPED.\n");
vm_hw_lem1802_mem_set_palette(vm, val_b);
break;

case LEM1802_SET_BORDER_COLOR:
printd(LEVEL_DEBUG, "LEM1802 BORDER SET.\n");
vm_hw_lem1802_set_border(vm, val_b);
break;

case LEM1802_MEM_DUMP_FONT:
// TODO
printd(LEVEL_DEBUG, "LEM1802 DUMP FONT.\n");
vm->sleep_cycles += 256;
for (idx = 0; idx < 128; idx++)
{
store = vm_hw_lem1802_mem_get_font_default_representation(idx);
vm->ram[val_b + idx * 2] = (uint16_t)(store >> 16);
vm->ram[val_b + idx * 2 + 1] = (uint16_t)((store << 16) >> 16);
}
break;

case LEM1802_MEM_DUMP_PALETTE:
// TODO
printd(LEVEL_DEBUG, "LEM1802 DUMP PALETTE.\n");
vm->sleep_cycles += 16;
for (idx = 0; idx < 16; idx++)
vm->ram[val_b + idx] = vm_hw_lem1802_util_get_raw(vm_hw_lem1802_mem_get_default_palette_color(idx));
break;
}
}
Expand Down
101 changes: 101 additions & 0 deletions libdcpu-vm/hwlem1802mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ uint16_t font_location = 0;
///
TCOD_image_t font_image = NULL;

///
/// Another cloned LibTCOD image, used to dump the
/// default into RAM when required.
///
TCOD_image_t font_default = NULL;

///
/// The width of a single character in the font image.
///
Expand Down Expand Up @@ -105,6 +111,7 @@ void vm_hw_lem1802_mem_init(vm_t* vm)
TCOD_console_set_keyboard_repeat(200, 10);
TCOD_sys_set_fps(10000);
font_image = TCOD_image_load(font_path->data);
font_default = TCOD_image_load(font_path->data);
TCOD_sys_get_char_size(&font_char_width, &font_char_height);

// Free memory.
Expand Down Expand Up @@ -157,6 +164,17 @@ TCOD_color_t vm_hw_lem1802_mem_get_palette_color(vm_t* vm, uint16_t idx)
}
}

///
/// Returns the default color based on the required index.
///
/// @param idx The color index.
/// @return The LibTCOD color to use in rendering.
///
TCOD_color_t vm_hw_lem1802_mem_get_default_palette_color(uint16_t idx)
{
return vm_hw_lem1802_util_get_color(palette_internal[idx]);
}

///
/// Sets the font location used for resolving font characters.
///
Expand Down Expand Up @@ -217,6 +235,77 @@ uint16_t vm_hw_lem1802_mem_get_font_char_height()
return font_char_height;
}

///
/// Returns a representation of a default character as it would
/// appear in the DCPU-16 RAM.
///
/// @param idx The index in the font to retrieve.
/// @return The 32-bit integer (which is stored as two 16-bit words) representation.
///
uint32_t vm_hw_lem1802_mem_get_font_default_representation(uint16_t idx)
{
unsigned int i = 0, x = 0, y = 0, fx = 0, fy = 0;
TCOD_color_t color_white = { 255, 255, 255 };
TCOD_image_t char_image = NULL;
uint16_t char_width, char_height;
uint16_t ax = 0, ay = 0;
uint16_t first = 0;
uint16_t second = 0;
uint16_t result = 0;
TCOD_color_t color;

// Get the font character width / height.
char_width = vm_hw_lem1802_mem_get_font_char_width();
char_height = vm_hw_lem1802_mem_get_font_char_height();
char_image = vm_hw_lem1802_mem_get_default_font_image();

// Work out the position of the character in the font.
fx = idx / 16 * char_width;
fy = idx % 16 * char_height;

// For each pixel in the image, grab it's on / off value
// from the memory location.
for (x = 0; x < 4; x++)
{
// Loop through each row.
for (y = 0; y < 8; y++)
{
// TEMPORARY: Some loaded fonts may have characters wider
// or higher than the addressable font size and thus
// we must skip over intermediate pixels.
for (ax = 0; ax < char_width; ax += char_width / HW_LEM1802_FONT_CHAR_ADDRESSABLE_WIDTH)
{
for (ay = 0; ay < char_height; ay += char_height / HW_LEM1802_FONT_CHAR_ADDRESSABLE_HEIGHT)
{
// Determine whether the pixel is on or off.
color = TCOD_image_get_pixel(char_image, (fx + x) * char_width / HW_LEM1802_FONT_CHAR_ADDRESSABLE_WIDTH + ax, ay - (fy + y + 1) * char_height / HW_LEM1802_FONT_CHAR_ADDRESSABLE_HEIGHT);
if (color.r == color_white.r && color.g == color_white.g && color.b == color_white.b)
result = 1;
else
result = 0;

// Shift across 8-bits if needed.
if (x == 0 || x == 2)
result = result << 8;

// Shift back based on the row.
result = result >> y;

// Set in the correct upper or lower field.
if (x == 0 || x == 1)
first += result;
else
second += result;
}
}
}
}

// Combine first and second values into
// a single uint32_t and return.
return ((uint32_t)first << 16) + (uint32_t)second;
}

///
/// Returns the LibTCOD image.
///
Expand All @@ -231,6 +320,18 @@ TCOD_image_t vm_hw_lem1802_mem_get_font_image()
return font_image;
}

///
/// Returns the default LibTCOD image.
///
/// Returns the defaultLibTCOD image.
///
/// @return The font image.
///
TCOD_image_t vm_hw_lem1802_mem_get_default_font_image()
{
return font_default;
}

///
/// Sets the screen location used for memory mapping values.
///
Expand Down
3 changes: 3 additions & 0 deletions libdcpu-vm/hwlem1802mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@ void vm_hw_lem1802_mem_init(vm_t* vm);
void vm_hw_lem1802_mem_free(vm_t* vm);
void vm_hw_lem1802_mem_set_palette(vm_t* vm, uint16_t pos);
TCOD_color_t vm_hw_lem1802_mem_get_palette_color(vm_t* vm, uint16_t idx);
TCOD_color_t vm_hw_lem1802_mem_get_default_palette_color(uint16_t idx);
void vm_hw_lem1802_mem_set_font(vm_t* vm, uint16_t pos);
uint16_t vm_hw_lem1802_mem_get_font();
uint16_t vm_hw_lem1802_mem_get_font_char_width();
uint16_t vm_hw_lem1802_mem_get_font_char_height();
uint32_t vm_hw_lem1802_mem_get_font_default_representation(uint16_t idx);
TCOD_image_t vm_hw_lem1802_mem_get_font_image();
TCOD_image_t vm_hw_lem1802_mem_get_default_font_image();
void vm_hw_lem1802_mem_set_screen(vm_t* vm, uint16_t pos);
uint16_t vm_hw_lem1802_mem_get_screen();

Expand Down
19 changes: 19 additions & 0 deletions libdcpu-vm/hwlem1802util.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,22 @@ TCOD_color_t vm_hw_lem1802_util_get_color(uint16_t raw)
return result;
}

///
/// Converts a LibTCOD color into a raw 16-bit color.
///
/// @param color The LibTCOD color.
/// @return The raw value.
///
uint16_t vm_hw_lem1802_util_get_raw(TCOD_color_t color)
{
uint16_t result = 0;

// Mathematical!
result += ((color.r / 16) << 8) & 0xF00;
result += ((color.g / 16) << 4) & 0x0F0;
result += ((color.b / 16) << 0) & 0x00F;

return result;
}


1 change: 1 addition & 0 deletions libdcpu-vm/hwlem1802util.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <libtcod.h>

TCOD_color_t vm_hw_lem1802_util_get_color(uint16_t raw);
uint16_t vm_hw_lem1802_util_get_raw(TCOD_color_t color);

#endif

Expand Down
Loading

0 comments on commit ce15102

Please sign in to comment.