Block device support in IO bus.
No docs on this yet because it's barely tested at all.
Will Haldean Brown
8 years ago
0 | 0 | #ifndef __6502_FUNCTIONS__ |
1 | 1 | #define __6502_FUNCTIONS__ |
2 | ||
3 | #include <stdlib.h> | |
2 | 4 | |
3 | 5 | #include "cpu.h" |
4 | 6 | |
5 | 7 | #define ZP(x) ((uint8_t) (x)) |
6 | 8 | #define STACK_PUSH(m) (m)->mem[(m)->sp-- + STACK_START] |
7 | 9 | #define STACK_POP(m) (m)->mem[++(m)->sp + STACK_START] |
10 | ||
11 | #ifdef DEBUG | |
12 | #define debugf(...) fprintf(stderr, __VA_ARGS__) | |
13 | #else | |
14 | #define debugf(...) do {} while (0) | |
15 | #endif | |
8 | 16 | |
9 | 17 | static inline size_t mem_abs(uint8_t low, uint8_t high, uint8_t off) { |
10 | 18 | return (uint16_t) off + (uint16_t) low + ((uint16_t) high << 8); |
1 | 1 | |
2 | 2 | #include <ncurses.h> |
3 | 3 | #include <stdio.h> |
4 | #include <stdlib.h> | |
4 | 5 | #include <sys/select.h> |
5 | 6 | #include <sys/time.h> |
6 | 7 | |
12 | 13 | uint8_t io_modeflags = 0x00; |
13 | 14 | uint8_t io_supports_paint; |
14 | 15 | |
16 | FILE *blck0 = NULL; | |
17 | ||
15 | 18 | WINDOW *window = NULL; |
16 | 19 | |
17 | 20 | void init_vterm(); |
18 | 21 | void update_vterm(cpu *, uint16_t); |
19 | 22 | void finish_vterm(); |
23 | ||
24 | void set_block_source(FILE *source) { | |
25 | blck0 = source; | |
26 | } | |
20 | 27 | |
21 | 28 | void init_io() { |
22 | 29 | initscr(); |
42 | 49 | getch(); |
43 | 50 | } |
44 | 51 | |
45 | if (io_modeflags & IO_MODEFLAG_VTERM) { | |
46 | finish_vterm(); | |
47 | } | |
52 | endwin(); | |
48 | 53 | } |
49 | 54 | |
50 | 55 | void init_vterm() { |
100 | 105 | |
101 | 106 | if (get_emu_flag(m, EMU_FLAG_DIRTY)) { |
102 | 107 | uint16_t addr = m->dirty_mem_addr; |
103 | ||
104 | #ifdef DEBUG | |
105 | fprintf(stderr, "dirty address %04X has value %02x\n", | |
106 | addr, m->mem[addr]); | |
107 | #endif | |
108 | debugf("dirty address %04X has value %02x\n", addr, m->mem[addr]); | |
108 | 109 | |
109 | 110 | if (addr == IO_PUTCHAR) { |
110 | 111 | if (io_modeflags & IO_MODEFLAG_VTERM) { |
119 | 120 | update_paint(m->mem[addr]); |
120 | 121 | } else if (IO_VTERM_START <= addr && addr < IO_VTERM_END) { |
121 | 122 | update_vterm(m, addr); |
123 | } else if (addr == IO_BLCK0_ADDRL | |
124 | || addr == IO_BLCK0_ADDRH | |
125 | || addr == IO_BLCK0_READ) { | |
126 | if (blck0 == NULL) { | |
127 | finish_vterm(); | |
128 | fprintf(stderr, "tried to read from unattached block device\n"); | |
129 | exit(-1); | |
130 | return; | |
131 | } | |
132 | ||
133 | uint16_t read_addr = | |
134 | m->mem[IO_BLCK0_ADDRH] << 8 | m->mem[IO_BLCK0_ADDRL]; | |
135 | int res = fseek(blck0, read_addr, SEEK_SET); | |
136 | if (res) { | |
137 | debugf("ERROR: fseek returned %d\n", res); | |
138 | m->mem[IO_BLCK0_ERR] = IO_BLCK_ERR_SEEK; | |
139 | return; | |
140 | } | |
141 | ||
142 | res = fgetc(blck0); | |
143 | if (res == EOF) { | |
144 | debugf("ERROR: fgetc returned EOF\n"); | |
145 | m->mem[IO_BLCK0_ERR] = IO_BLCK_ERR_EOF; | |
146 | return; | |
147 | } | |
148 | m->mem[IO_BLCK0_READ] = 0xFF & res; | |
149 | m->mem[IO_BLCK0_ERR] = 0x00; | |
122 | 150 | } |
123 | 151 | } |
124 | 152 | } |
0 | 0 | #ifndef __6502_IO__ |
1 | ||
2 | #include <stdio.h> | |
1 | 3 | |
2 | 4 | #include "cpu.h" |
3 | 5 | |
6 | #define IO_PAINT 0xFEE8 | |
4 | 7 | #define IO_PUTCHAR 0xFF00 |
5 | 8 | #define IO_GETCHAR 0xFF01 |
6 | 9 | #define IO_MODEFLAGS 0xFF02 |
7 | #define IO_PAINT 0xFEE8 | |
10 | ||
11 | // writing to ADDRL, ADDRH or READ will trigger an interrupt that will read from | |
12 | // the disk address specified by ADDRL and ADDRH and write the result into READ. | |
13 | // if errors are encountered, ERR will be nonzero. | |
14 | #define IO_BLCK0_ADDRL 0xFF03 | |
15 | #define IO_BLCK0_ADDRH 0xFF04 | |
16 | #define IO_BLCK0_READ 0xFF05 | |
17 | #define IO_BLCK0_WRITE 0xFF06 | |
18 | #define IO_BLCK0_ERR 0xFF07 | |
19 | ||
20 | #define IO_BLCK_ERR_EOF 0x01 | |
21 | #define IO_BLCK_ERR_SEEK 0x02 | |
8 | 22 | |
9 | 23 | #define IO_VTERM_START 0xFB00 |
10 | 24 | #define IO_VTERM_END 0xFF00 |
26 | 40 | #define IO_PAINT_UNDERLINE 0x40 |
27 | 41 | #define IO_PAINT_BOLD 0x80 |
28 | 42 | |
43 | void set_block_source(FILE *source); | |
29 | 44 | void init_io(); |
30 | 45 | void finish_io(); |
31 | 46 | void handle_io(cpu *m); |
0 | 0 | #include "cpu.h" |
1 | 1 | #include "emu.h" |
2 | #include "functions.h" | |
3 | #include "io.h" | |
2 | 4 | #include "opcodes.h" |
3 | 5 | |
4 | 6 | #include <ctype.h> |
11 | 13 | printf("usage: x6502 [OPTION]... [FILE] \n"); |
12 | 14 | printf("options:\n"); |
13 | 15 | printf("\t-b addr\t\tthe base address at which code will be loaded\n"); |
16 | printf("\t-d file\t\ta binary file to back the block device\n"); | |
14 | 17 | printf("\t\t\t(optional, defaults to zero)\n"); |
15 | 18 | } |
16 | 19 | |
17 | 20 | int main(int argc, char *argv[]) { |
18 | 21 | int base_addr = 0x1000; |
22 | char *blck0_file = NULL; | |
19 | 23 | |
20 | 24 | int c; |
21 | while ((c = getopt(argc, argv, "hb:")) != -1) { | |
25 | while ((c = getopt(argc, argv, "hb:d:")) != -1) { | |
22 | 26 | switch (c) { |
23 | 27 | case 'b': |
24 | 28 | base_addr = atoi(optarg); |
29 | break; | |
30 | ||
31 | case 'd': | |
32 | blck0_file = optarg; | |
25 | 33 | break; |
26 | 34 | |
27 | 35 | case 'h': |
29 | 37 | return 0; |
30 | 38 | |
31 | 39 | case '?': |
32 | if (optopt == 'b') { | |
40 | if (optopt == 'b' || optopt == 'd') { | |
33 | 41 | fprintf(stderr, "Option -%c requires an argument.\n", optopt); |
34 | 42 | } |
35 | 43 | usage(); |
43 | 51 | return -1; |
44 | 52 | } |
45 | 53 | |
46 | FILE *in_f = fopen(argv[optind], "rb"); | |
54 | debugf("using %s as a backing file for block device 0\n", blck0_file); | |
55 | if (blck0_file != NULL) { | |
56 | FILE *blck0 = fopen(blck0_file, "r+"); | |
57 | if (blck0 == NULL) { | |
58 | fprintf(stderr, "block file %s does not exist.\n", blck0_file); | |
59 | return -1; | |
60 | } | |
61 | set_block_source(blck0); | |
62 | } | |
63 | ||
64 | FILE *in_f = fopen(argv[optind], "r"); | |
47 | 65 | int b; |
48 | 66 | int i = base_addr; |
49 | 67 | cpu *m = new_cpu(base_addr); |
0 | cli | |
1 | lda #$02 ; set WAIT_TERMINATE flag | |
2 | sta $FF02 | |
3 | lda #$03 | |
4 | sta $FF03 | |
5 | lda #$00 | |
6 | sta $FF04 | |
7 | lda #$00 | |
8 | cmp $FF07 | |
9 | beq printchar | |
10 | lda #'e' | |
11 | sta $FF00 | |
12 | lda #'r' | |
13 | sta $FF00 | |
14 | sta $FF00 | |
15 | jmp done | |
16 | printchar: | |
17 | lda $FF05 | |
18 | sta $FF00 | |
19 | done: |
0 | #include <errno.h> | |
1 | #include <stdio.h> | |
2 | #include <string.h> | |
3 | ||
4 | int main() { | |
5 | FILE *f = fopen("testdisk.bin", "w"); | |
6 | if (f == NULL) { | |
7 | printf("could not open file, err: %s", strerror(errno)); | |
8 | return 1; | |
9 | } | |
10 | fprintf(f, "hello, world!"); | |
11 | fclose(f); | |
12 | return 0; | |
13 | } |
0 | hello, world!⏎ |