-
Notifications
You must be signed in to change notification settings - Fork 0
/
cx16api.c
143 lines (108 loc) · 2.83 KB
/
cx16api.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
#include <cx16.h>
#include "cx16api.h"
/*
Get the next character in the keyboard queue without removing it,
and place the length of the queue in the variable queue_length.
*/
uint8_t kbdbuf_peek(uint8_t* queue_length)
{
static uint8_t byte;
// JSR to $FEBD (kbd_get_char)
__asm__("jsr $febd");
// Store the X register (queue length) in the length variable
__asm__("stx %v", byte);
*queue_length = byte;
// if length is 0, return 0
if (byte == 0) {
return 0;
}
// Copy the A register (next char) to 'next_char' variable
__asm__("lda %v", byte);
return byte; // return the next char
}
/*
Initialize the state of the PSG. Silence all voices.
Reset the attenuation levels to 0.
Set "playstring" defaults including O4, T120, S1, and L4.
Set all PSG voices to the pulse waveform at 50% duty with panning set to both L+R
*/
void psg_init(void)
{
uint8_t OLD_BANK = ROM_BANK;
ROM_BANK = 0x0A;
__asm__("jsr $C04B");
ROM_BANK = OLD_BANK;
}
/*
Set the frequency of a PSG voice without changing any other attributes of the voice
*/
void psg_setfreq(uint16_t freq, uint8_t voice)
{
/*
.A = voice (register is already set)
.X .Y = 16 bit frequency in VERA PSG format
*/
static uint8_t A, X, Y, OLD_BANK;
uint32_t frequency_word;
A = voice;
frequency_word = (freq * 131072U) / 48828U;
X = frequency_word & 0xFF;
Y = frequency_word >> 8;
OLD_BANK = ROM_BANK;
ROM_BANK = 0x0A;
asm("lda %v", A);
asm("ldx %v", X);
asm("ldy %v", Y);;
__asm__("jsr $C057");
ROM_BANK = OLD_BANK;
}
/*
Set the volume for the voice.
The volume that's written to the VERA has attenuation applied.
Valid volumes range from $00 to $3F inclusive
*/
void psg_setvol(uint8_t vol, uint8_t voice)
{
static uint8_t A,X, OLD_BANK;
A = voice;
X = vol;
OLD_BANK = ROM_BANK;
ROM_BANK = 0x0A;
__asm__("lda %v", A);
__asm__("ldx %v", X);
__asm__("jsr $C05D");
ROM_BANK = OLD_BANK;
}
/*
Turn on a PSG voice at full volume (factoring in attenuation) and set its frequency
*/
void psg_playfreq(uint16_t freq, uint8_t voice) {
static uint8_t A, X, Y, OLD_BANK;
uint32_t new_freq;
A = voice;
new_freq = (freq * 131072U) / 48828U;
X = new_freq & 0xFF;
Y = new_freq >> 8;
OLD_BANK = ROM_BANK;
ROM_BANK = 0x0A;
__asm__("lda %v", A);
__asm__("ldx %v", X);
__asm__("ldy %v", Y);
__asm__("jsr $C04E");
ROM_BANK = OLD_BANK;
}
/*
Write a value to one of the VERA PSG registers
*/
void psg_write(uint8_t reg_offset, uint8_t val)
{
static uint8_t A, X, OLD_BANK;
A = val;
X = reg_offset;
OLD_BANK = ROM_BANK;
ROM_BANK = 0x0A;
__asm__("lda %v", A);
__asm__("ldx %v", X);
__asm__("jsr $C060");
ROM_BANK = OLD_BANK;
}