forked from daitangio/x16-emulator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
via.c
145 lines (128 loc) · 2.69 KB
/
via.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Commander X16 Emulator
// Copyright (c) 2019 Michael Steil
// All rights reserved. License: 2-clause BSD
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include <stdlib.h>
#include "via.h"
#include "ps2.h"
#include "memory.h"
//XXX
#include "glue.h"
#include "joystick.h"
//
// VIA#1
//
// PA0-7 RAM bank
// PB0-2 ROM bank
// PB3 IECATT0
// PB4 IECCLK0
// PB5 IECDAT0
// PB6 IECCLK
// PB7 IECDAT
// CB1 IECSRQ
static uint8_t via1registers[16];
void
via1_init()
{
srand(time(NULL));
// default banks are 0
memory_set_ram_bank(0);
memory_set_rom_bank(0);
via1registers[0] = memory_get_rom_bank(); // PB: ROM bank, IEC
via1registers[1] = memory_get_ram_bank(); // PA: RAM bank
}
uint8_t
via1_read(uint8_t reg)
{
if (reg == 4 || reg == 5 || reg == 8 || reg == 9) {
// timer A and B: return random numbers for RND(0)
// XXX TODO: these should be real timers :)
return rand() & 0xff;
} else {
return via1registers[reg];
}
}
void
via1_write(uint8_t reg, uint8_t value)
{
via1registers[reg] = value;
if (reg == 0) { // PB: ROM bank, IEC
memory_set_rom_bank(value & 7);
// TODO: IEC
} else if (reg == 1) { // PA: RAM bank
memory_set_ram_bank(value);
} else {
// TODO
}
}
//
// VIA#2
//
// PA0 PS/2 DAT
// PA1 PS/2 CLK
// PA2 LCD backlight
// PA3 NESJOY latch (for both joysticks)
// PA4 NESJOY joy1 data
// PA5 NESJOY joy1 CLK
// PA6 NESJOY joy2 data
// PA7 NESJOY joy2 CLK
static uint8_t via2registers[16];
static uint8_t via2pb_in;
void
via2_init()
{
}
uint8_t
via2_read(uint8_t reg)
{
if (reg == 0) {
// PB
// 0 input -> take input bit
// 1 output -> take output bit
return (via2pb_in & (via2registers[2] ^ 0xff)) |
(via2registers[0] & via2registers[2]);
} else if (reg == 1) {
// PA
uint8_t value =
(via2registers[3] & PS2_CLK_MASK ? 0 : ps2_clk_out << 1) |
(via2registers[3] & PS2_DATA_MASK ? 0 : ps2_data_out);
value = value | (joystick1_data ? JOY_DATA1_MASK : 0) |
(joystick2_data ? JOY_DATA2_MASK : 0);
return value;
} else {
return via2registers[reg];
}
}
void
via2_write(uint8_t reg, uint8_t value)
{
via2registers[reg] = value;
if (reg == 0) {
// PB
} else if (reg == 2) {
// PB DDRB
} else if (reg == 1 || reg == 3) {
// PA
ps2_clk_in = via2registers[3] & PS2_CLK_MASK ? via2registers[1] & PS2_CLK_MASK : 1;
ps2_data_in = via2registers[3] & PS2_DATA_MASK ? via2registers[1] & PS2_DATA_MASK : 1;
joystick_latch = via2registers[1] & JOY_LATCH_MASK;
joystick_clock = via2registers[1] & JOY_CLK_MASK;
}
}
uint8_t
via2_pb_get_out()
{
return via2registers[2] /* DDR */ & via2registers[0]; /* PB */
}
void
via2_pb_set_in(uint8_t value)
{
via2pb_in = value;
}
void
via2_sr_set(uint8_t value)
{
via2registers[10] = value;
}