Permalink
Browse files

Fixed bugs in timer and LEM1802 hardware.

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...
James Rhodes
James Rhodes committed Jun 4, 2012
1 parent 61d6152 commit ce15102a64cc32809efac9ca2ddbb74c4af39616
View
@@ -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++)
View
@@ -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;
@@ -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);
}
}
@@ -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--;
@@ -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;
}
View
@@ -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;
}
View
@@ -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);
}
@@ -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]);
}
@@ -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)
@@ -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;
View
@@ -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"
@@ -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;
}
}
View
@@ -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.
///
@@ -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.
@@ -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.
///
@@ -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.
///
@@ -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.
///
@@ -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();
View
@@ -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;
+}
+
+
@@ -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
Oops, something went wrong.

0 comments on commit ce15102

Please sign in to comment.