1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-12-21 08:30:55 +00:00

Add functions for pressing/releasing keys

This commit is contained in:
Peter Evans 2017-12-06 15:21:39 -06:00
parent 0e02fb8a1a
commit 98f70e0a9a
3 changed files with 125 additions and 3 deletions

View File

@ -8,8 +8,19 @@ typedef struct {
* The apple 2 hardware used an MOS-6502 processor.
*/
mos6502 *cpu;
/*
* This is the literal memory that the CPU above will create. You
* should _not_ attempt to free this memory; allow the CPU's own
* delete function to do that.
*/
vm_segment *memory;
} apple2;
extern apple2 *apple2_create();
extern void apple2_free(apple2 *);
extern void apple2_press_key(apple2 *, vm_8bit);
extern void apple2_clear_strobe(apple2 *);
extern void apple2_release_key(apple2 *);
#endif

View File

@ -3,7 +3,23 @@
*/
#include "apple2.h"
#include "vm_segment.h"
/*
* This is the memory address where an apple program can find the value
* of the key that was last pressed.
*/
#define LAST_KEY 0xC000
/*
* This is the address in memory where you can find whether a key is
* currently pressed or not.
*/
#define ANY_KEY_DOWN 0xC010
/*
* Create the basic apple2 structure.
*/
apple2 *
apple2_create()
{
@ -15,6 +31,65 @@ apple2_create()
}
mach->cpu = mos6502_create();
mach->memory = mach->cpu->memory;
return mach;
}
/*
* Free the memory reserved for an apple2 struct.
*/
void
apple2_free(apple2 *mach)
{
mos6502_free(mach->cpu);
// NOTE: we do _NOT_ want to clear the memory field of mach, as it's
// co-owned with the cpu struct that we just freed above.
free(mach);
}
void
apple2_press_key(apple2 *mach, vm_8bit ch)
{
// The apple2 can only handle ASCII values of 0 through 127.
// However, the eigth bit is called the "strobe" bit, and is treated
// specially. In particular, the strobe bit is 1 if a key was
// pressed down, and remains 1 until you reset it by reading from
// the clear-strobe location.
ch = ch | 0x80;
// This is the location in memory where a program will expect to
// find the value of the last key that was pressed.
vm_segment_set(mach->memory, LAST_KEY, ch);
// This area is a combination of flags; the eighth bit here is the
// "any-key-down" flag, which is a bit of a mouthful. It's 1 if a
// key is pressed, and 0 if not. The effect of reading this bit will
// also _clear_ the strobe bit in the $C000 address (above).
vm_segment_set(mach->memory, ANY_KEY_DOWN, 0x80);
}
/*
* This function will clear the 8th bit, which is the "strobe" bit, from
* the position in memory where the value of the last key that was
* pressed is held.
*/
void
apple2_clear_strobe(apple2 *mach)
{
vm_8bit ch;
ch = vm_segment_get(mach->memory, LAST_KEY);
vm_segment_set(mach->memory, LAST_KEY, ch & 0x7F);
}
/*
* This function will clear the value of the any-key-down switch/flag.
*/
void
apple2_release_key(apple2 *mach)
{
vm_segment_set(mach->memory, ANY_KEY_DOWN, 0);
}

View File

@ -2,11 +2,47 @@
#include "apple2.h"
static apple2 *mach;
void
setup()
{
mach = apple2_create();
}
void
teardown()
{
apple2_free(mach);
}
TestSuite(apple2, .init = setup, .fini = teardown);
Test(apple2, create)
{
apple2 *mach;
mach = apple2_create();
cr_assert_neq(mach, NULL);
cr_assert_neq(mach->cpu, NULL);
}
Test(apple2, press_key)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123 | 0x80);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0x80);
}
Test(apple2, clear_strobe)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123 | 0x80);
apple2_clear_strobe(mach);
cr_assert_eq(vm_segment_get(mach->memory, 0xC000), 123);
}
Test(apple2, release_key)
{
apple2_press_key(mach, 123);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0x80);
apple2_release_key(mach);
cr_assert_eq(vm_segment_get(mach->memory, 0xC010), 0);
}