-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmicrotanbasic.c
More file actions
160 lines (127 loc) · 2.96 KB
/
Copy pathmicrotanbasic.c
File metadata and controls
160 lines (127 loc) · 2.96 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
/* bad6502 A Raspberry Pi-based backend to a 65C02 CPU
Copyright (C) 2025 D.Herrendoerfer
MIT License
*/
/* MSBASIC
* using microtan msbasic from microsoft
* added unbuffered terminal
*/
#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/microtan_msbasic.h"
#include "bios/microtan_bios.h"
#define RAM_START 0xC000
#define COLD_START 0xE076
// 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;
// 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
// Virtual hardware (writes char to stdout)
if (address == 0xFF00) {
printf("%c",(char)data);
fsync(1);
}
if ((address >= 0x1E00) & (address < 2000)) //simulated ROM above E000
return;
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] = 0x60;
}
//load msbasic @RAM_START
printf("Loading MICROTAN MSBASIC 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 0xEF00\r\n");
for (uint16_t i=0; i < bios_len; i++) {
mem[0xEF00+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;
}