-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcbm1basic.c
More file actions
169 lines (134 loc) · 3.06 KB
/
cbm1basic.c
File metadata and controls
169 lines (134 loc) · 3.06 KB
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* bad6502 A Raspberry Pi-based backend to a 65C02 CPU
Copyright (C) 2025 D.Herrendoerfer
MIT License
*/
/* MSBASIC
* using cbm1 msbasic from microsoft
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <termios.h>
#include "../badX16/cpu/fake6502.h"
#include "msbasic/cbm1_msbasic.h"
#include "bios/cbm2_bios.h"
#define RAM_START 0xC000
#define COLD_START 0xE0D2
// the ram
uint8_t mem[0x10000];
// terminal settings
struct termios previous_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &previous_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &previous_termios);
memcpy(&new_termios, &previous_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv) > 0;
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
if (c == 0x18) {
printf("\r\nCNTL+X pressed, exiting\r\n");
exit(1);
}
return c;
}
}
uint8_t read6502(uint16_t address, uint8_t bank)
{
// Manual reset vector
if (address == 0xFFFC)
return COLD_START & 0xff;
if (address == 0xFFFD)
return COLD_START >> 8;
//2348: NMI ?
//if (address >= 0xFFC0) {
// printf("\r\n < 0x%04X",address);
//}
// Virtual hardware (reads a char from stdin)
if (address == 0xFF01) {
if (!kbhit())
return 0;
return getch();
}
// mem read
return mem[address];
}
void write6502(uint16_t address, uint8_t bank, uint8_t data)
{
// mem write
// if (address >= 0xFF00) {
// printf("\r\n > 0x%04X, 0x%02X",address,data);
// }
// Virtual hardware (writes char to stdout)
if (address == 0xFF00) {
printf("%c",(char)data);
// if (data == 13)
// printf("\n");
fsync(1);
}
if (address >= 0x8000) //simulated ROM above F000
return;
mem[address] = data;
}
// Main prog
int main(int argc, char **argv)
{
// setup terminal
set_conio_terminal_mode();
setbuf(stdout, NULL);
for (uint16_t i=0; i != 0xFFFF; i++) {
mem[i] = 0xFF;
}
//load msbasic @RAM_START
printf("Loading CBM MSBASIC 1 to :0x%04X\r\n",RAM_START);
for (uint16_t i=0; i < msbasic_bin_len; i++) {
mem[RAM_START+i] = msbasic_bin[i];
}
//load bios
printf("Loading BIOS to 0xFF10\r\n");
for (uint16_t i=0; i < bios_len; i++) {
mem[0xFF10+i] = bios[i];
}
//reset the cpu
reset6502(0);
// step past the reset code
for (int i=0 ; i<32 ; i++) {
step6502();
usleep(1000);
}
loop:
step6502();
#ifndef FAST
usleep(100000);
#endif
goto loop;
printf("\n\nExecution stopped. (but we never get here)");
return 0;
}