mirror of
https://github.com/pevans/erc-c.git
synced 2024-08-21 00:29:00 +00:00
Add functions for pressing/releasing keys
This commit is contained in:
parent
0e02fb8a1a
commit
98f70e0a9a
@ -8,8 +8,19 @@ typedef struct {
|
|||||||
* The apple 2 hardware used an MOS-6502 processor.
|
* The apple 2 hardware used an MOS-6502 processor.
|
||||||
*/
|
*/
|
||||||
mos6502 *cpu;
|
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;
|
} apple2;
|
||||||
|
|
||||||
extern apple2 *apple2_create();
|
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
|
#endif
|
||||||
|
75
src/apple2.c
75
src/apple2.c
@ -3,7 +3,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "apple2.h"
|
#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 *
|
||||||
apple2_create()
|
apple2_create()
|
||||||
{
|
{
|
||||||
@ -15,6 +31,65 @@ apple2_create()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mach->cpu = mos6502_create();
|
mach->cpu = mos6502_create();
|
||||||
|
mach->memory = mach->cpu->memory;
|
||||||
|
|
||||||
return mach;
|
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);
|
||||||
|
}
|
||||||
|
@ -2,11 +2,47 @@
|
|||||||
|
|
||||||
#include "apple2.h"
|
#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)
|
Test(apple2, create)
|
||||||
{
|
{
|
||||||
apple2 *mach;
|
|
||||||
|
|
||||||
mach = apple2_create();
|
|
||||||
cr_assert_neq(mach, NULL);
|
cr_assert_neq(mach, NULL);
|
||||||
cr_assert_neq(mach->cpu, 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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user