Changes in / [7b50125:40b2112] in buchla-emu
- Files:
-
- 5 deleted
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r7b50125 r40b2112 1 1 bios.abs 2 bios.elf3 2 midas.abs 4 midas.elf5 3 6 build /*4 build 7 5 buchla 8 buchla.exe9 6 mkdisk 10 mkdisk.exe11 7 12 8 buchla.disk -
Makefile
r7b50125 r40b2112 4 4 GCC := gcc 5 5 SDL2 := /opt/sdl2 6 EXT :=7 6 else 8 7 GCC := x86_64-w64-mingw32-gcc 9 8 SDL2 := /opt/sdl2-win 10 EXT := .exe11 9 endif 12 10 … … 34 32 FLAGS_LNK := $(FLAGS) -pthread -Wall -Wextra 35 33 LIBS := $(SDL2_LIB)/libSDL2.a \ 36 $(SDL2_LIB)/libSDL2_net.a \37 34 $(SDL2_LIB)/libSDL2_ttf.a \ 38 35 $(SDL2_LIB)/libfreetype.a \ … … 44 41 FLAGS_LNK := $(FLAGS) -Wall -Wextra 45 42 LIBS := $(SDL2_LIB)/libSDL2.a \ 46 $(SDL2_LIB)/libSDL2_net.a \47 43 $(SDL2_LIB)/libSDL2_ttf.a \ 48 44 $(SDL2_LIB)/libfreetype.a \ … … 64 60 $(SDL2_LIB)/libSDL2.a \ 65 61 $(SDL2_LIB)/libSDL2main.a \ 66 $(SDL2_LIB)/libSDL2_net.a \67 62 $(SDL2_LIB)/libSDL2_ttf.a \ 68 63 $(SDL2_LIB)/libfreetype.a \ 69 64 -l gdi32 \ 70 65 -l imm32 \ 71 -l iphlpapi \72 66 -l ole32 \ 73 67 -l oleaut32 \ 74 68 -l version \ 75 -l winmm \ 76 -l ws2_32 69 -l winmm 77 70 endif 78 71 79 72 HEADERS := $(wildcard cpu/*.h) $(wildcard emu/*.h) 80 73 81 all: buchla $(EXT)buchla.disk74 all: buchla buchla.disk 82 75 83 build/gen: 76 build: 77 mkdir build 78 79 build/gen: | build 84 80 gcc $(FLAGS) -o build/gen cpu/m68kmake.c 85 81 … … 94 90 95 91 $(GEN_CP) $(GEN_HP): \ 96 build/gen 92 build/gen | build 97 93 cd cpu; ../build/gen ../build 98 94 … … 104 100 CPU_OP := $(CPU_O:%=build/%) 105 101 106 build/%.o: cpu/%.c $(HEADERS) $(GEN_HP) 102 build/%.o: cpu/%.c $(HEADERS) $(GEN_HP) | build 107 103 $(GCC) $(FLAGS_CPU) -c -o $@ $< 108 104 109 105 EMU_C := main.c cpu.c vid.c fpu.c tim.c lcd.c ser.c mid.c fdd.c snd.c \ 110 led.c kbd.c sdl.c gdb.c106 led.c kbd.c sdl.c 111 107 EMU_O := $(EMU_C:.c=.o) 112 108 EMU_OP := $(EMU_O:%=build/%) 113 109 114 build/%.o: emu/%.c $(HEADERS) 110 build/%.o: emu/%.c $(HEADERS) | build 115 111 $(GCC) $(FLAGS_EMU) -c -o $@ $< 116 112 117 buchla $(EXT):$(CPU_OP) $(GEN_OP) $(EMU_OP)118 $(GCC) $(FLAGS_LNK) -o buchla $(EXT)\113 buchla: $(CPU_OP) $(GEN_OP) $(EMU_OP) 114 $(GCC) $(FLAGS_LNK) -o buchla \ 119 115 $(CPU_OP) $(GEN_OP) $(EMU_OP) \ 120 116 $(LIBS) 121 117 122 mkdisk $(EXT):emu/mkdisk.c123 $(GCC) $(FLAGS_AUX) -o mkdisk $(EXT)emu/mkdisk.c118 mkdisk: emu/mkdisk.c 119 $(GCC) $(FLAGS_AUX) -o mkdisk emu/mkdisk.c 124 120 125 buchla.disk: mkdisk $(EXT)midas.abs126 ./mkdisk $(EXT)121 buchla.disk: mkdisk midas.abs 122 ./mkdisk 127 123 128 run: buchla $(EXT)buchla.disk129 ./buchla $(EXT) ${EMU_OPTS}124 run: buchla buchla.disk 125 ./buchla 130 126 131 val: buchla $(EXT)buchla.disk127 val: buchla buchla.disk 132 128 valgrind --leak-resolution=high --track-fds=yes --leak-check=full \ 133 --show-reachable=yes --suppressions=misc/buchla.supp \ 134 ./buchla$(EXT) ${EMU_OPTS} 129 --show-reachable=yes --suppressions=misc/buchla.supp ./buchla 135 130 136 131 clean: 137 rm - f build/gen build/*.c build/*.h build/*.o138 rm -f buchla $(EXT)139 rm -f mkdisk $(EXT)132 rm -rf build 133 rm -f buchla 134 rm -f mkdisk 140 135 rm -f buchla.disk -
emu/all.h
r7b50125 r40b2112 28 28 29 29 #include <SDL2/SDL.h> 30 #include <SDL2/SDL_net.h>31 30 #include <SDL2/SDL_ttf.h> 32 31 … … 48 47 49 48 extern int32_t sdl_verbose; 50 extern int32_t gdb_verbose;51 49 extern int32_t cpu_verbose; 52 50 extern int32_t fpu_verbose; … … 63 61 extern const char *bios; 64 62 extern const char *disk; 65 extern const char *font;66 67 extern SDL_atomic_t run;68 63 69 64 extern void sdl_init(void); 70 65 extern void sdl_quit(void); 71 extern void sdl_loop(void);72 66 73 extern void gdb_init(void);74 extern void gdb_quit(void);75 extern void gdb_loop(void);76 extern void gdb_inst(bool bp);77 78 extern SDL_mutex *cpu_mutex;79 80 extern void cpu_init(void);81 extern void cpu_quit(void);82 67 extern void cpu_loop(void); 83 84 extern uint8_t cpu_peek(int32_t addr);85 extern void cpu_poke(int32_t addr, uint8_t val);86 68 87 69 extern void fpu_init(void); … … 115 97 extern void ser_write(uint32_t off, int32_t sz, uint32_t val); 116 98 117 extern void ser_sdl(void);118 99 extern void ser_text(SDL_TextInputEvent *ev); 119 100 extern void ser_key(SDL_KeyboardEvent *ev); -
emu/cpu.c
r7b50125 r40b2112 52 52 } hw_t; 53 53 54 static uint64_t freq;55 static uint64_t quan;56 57 SDL_mutex *cpu_mutex;58 59 54 static bool reset = true; 60 55 … … 74 69 static hw_t hw_map[] = { 75 70 { 0x180000, 0x200000, 0, fpu_init, fpu_quit, fpu_exec, fpu_read, fpu_write }, 76 { 0x200000, 0x28000 2, 0, vid_init, vid_quit, vid_exec, vid_read, vid_write },71 { 0x200000, 0x280000, 0, vid_init, vid_quit, vid_exec, vid_read, vid_write }, 77 72 { 0x3a0001, 0x3a4001, 4, tim_init, tim_quit, tim_exec, tim_read, tim_write }, 78 73 { 0x3a4001, 0x3a8001, 0, lcd_init, lcd_quit, lcd_exec, lcd_read, lcd_write }, … … 384 379 } 385 380 386 // once midas.abs gets loaded, activate RAM381 // handle loading midas.abs 387 382 388 383 if (addr == APP_START) { 389 ram_data[addr] = (uint8_t)val;390 384 ram_rw_beg = APP_START; 391 385 ram_rw_end = RAM_START + RAM_SIZE; … … 468 462 } 469 463 470 uint8_t cpu_peek(int32_t addr)471 {472 if (addr >= RAM_START && addr <= RAM_START + RAM_SIZE - 1) {473 return ram_data[addr - RAM_START];474 }475 476 if (addr >= ROM_START && addr <= ROM_START + ROM_SIZE - 1) {477 return rom_data[addr - ROM_START];478 }479 480 return 0;481 }482 483 void cpu_poke(int32_t addr, uint8_t val)484 {485 if (addr >= RAM_START && addr <= RAM_START + RAM_SIZE - 1) {486 ram_data[addr - RAM_START] = val;487 }488 489 if (addr >= ROM_START && addr <= ROM_START + ROM_SIZE - 1) {490 rom_data[addr - ROM_START] = val;491 }492 }493 494 464 static void inst_cb(void) 495 465 { 496 466 uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC); 497 467 uint32_t op = m68k_read_memory_16(pc); 498 499 gdb_inst(op == 0x4e4f);500 468 501 469 if (op == 0x4e4d) { … … 651 619 } 652 620 653 void cpu_init(void) 654 { 655 cpu_mutex = SDL_CreateMutex(); 656 657 if (cpu_mutex == NULL) { 658 fail("SDL_CreateMutex() failed: %s", SDL_GetError()); 659 } 660 661 freq = SDL_GetPerformanceFrequency(); 662 quan = freq / PER_SEC; 663 664 inf("freq %" PRIu64 " quan %" PRIu64, freq, quan); 665 621 void cpu_loop(void) 622 { 666 623 hw_init(); 667 624 bios_init(); 668 625 626 inf("entering CPU loop"); 669 627 m68k_init(); 670 628 m68k_set_cpu_type(M68K_CPU_TYPE_68000); 671 629 m68k_set_instr_hook_callback(inst_cb); 672 630 m68k_pulse_reset(); 673 } 674 675 void cpu_quit(void) 676 { 677 hw_quit(); 678 SDL_DestroyMutex(cpu_mutex); 679 } 680 681 void cpu_loop(void) 682 { 683 inf("entering CPU loop"); 684 int32_t count = 0; 685 686 while (SDL_AtomicGet(&run) != 0) { 631 632 uint64_t freq = SDL_GetPerformanceFrequency(); 633 uint64_t quan = freq / PER_SEC; 634 inf("freq %" PRIu64 " quan %" PRIu64, freq, quan); 635 636 bool run = true; 637 638 #if defined EMU_LINUX 639 SDL_Scancode down = SDL_SCANCODE_UNKNOWN; 640 #endif 641 642 while (run) { 687 643 uint64_t until = SDL_GetPerformanceCounter() + quan; 688 689 if (SDL_LockMutex(cpu_mutex) < 0) {690 fail("SDL_LockMutex() failed: %s", SDL_GetError());691 }692 644 693 645 m68k_execute(CPU_FREQ / PER_SEC); … … 700 652 m68k_set_irq(irq); 701 653 702 if (SDL_UnlockMutex(cpu_mutex) < 0) { 703 fail("SDL_UnlockMutex() failed: %s", SDL_GetError()); 704 } 705 706 if ((++count & 0x1ff) == 0) { 707 SDL_Delay(0); 654 SDL_Event ev; 655 656 while (SDL_PollEvent(&ev) > 0) { 657 #if defined EMU_LINUX 658 // Work around duplicate key-down events on Linux. 659 660 if (ev.type == SDL_KEYDOWN) { 661 if (down == ev.key.keysym.scancode) { 662 continue; 663 } 664 665 down = ev.key.keysym.scancode; 666 } 667 else if (ev.type == SDL_KEYUP) { 668 down = SDL_SCANCODE_UNKNOWN; 669 } 670 #endif 671 672 if (ev.type == SDL_QUIT || 673 (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE)) { 674 run = false; 675 continue; 676 } 677 678 if (ev.type == SDL_TEXTINPUT) { 679 ser_text(&ev.text); 680 continue; 681 } 682 683 if (ev.type == SDL_KEYDOWN) { 684 ser_key(&ev.key); 685 continue; 686 } 708 687 } 709 688 710 689 while (SDL_GetPerformanceCounter() < until) { 711 for (int32_t i = 0; i < 100; ++i) { 712 _mm_pause(); 713 } 690 _mm_pause(); 714 691 } 715 692 } 716 693 717 694 inf("leaving CPU loop"); 718 } 695 hw_quit(); 696 } -
emu/main.c
r7b50125 r40b2112 25 25 static verb_flag_t verb_flags[] = { 26 26 { "sdl", &sdl_verbose }, 27 { "gdb", &gdb_verbose },28 27 { "cpu", &cpu_verbose }, 29 28 { "fpu", &fpu_verbose }, … … 41 40 const char *bios = "bios.abs"; 42 41 const char *disk = "buchla.disk"; 43 const char *font = "ttf/vera-sans-mono.ttf";44 45 SDL_atomic_t run;46 42 47 43 static void usage(FILE *fh) 48 44 { 49 fprintf(fh, "usage: buchla [-h] [-v comp [-v comp [...]]] [-b bios] [-d disk] [-f font]\n");45 fprintf(fh, "usage: buchla [-h] [-v comp [-v comp [...]]] [-b bios] [-d disk]\n"); 50 46 fprintf(fh, "where comp is one of: "); 51 47 … … 87 83 } 88 84 89 if (strcmp(argv[i], "-f") == 0) {90 if (++i == argc) {91 usage(stderr);92 fprintf(stderr, "missing argument to -f\n");93 exit(1);94 }95 96 font = argv[i];97 continue;98 }99 100 85 if (strcmp(argv[i], "-v") == 0) { 101 86 if (++i == argc) { … … 133 118 } 134 119 135 static int32_t cpu_thread(void *data)136 {137 (void)data;138 139 cpu_loop();140 return 0;141 }142 143 static int32_t gdb_thread(void *data)144 {145 (void)data;146 147 gdb_loop();148 return 0;149 }150 151 120 int32_t main(int32_t argc, char *argv[]) 152 121 { 153 122 parse_args(argc, argv); 154 123 sdl_init(); 155 gdb_init();156 cpu_init();157 124 158 SDL_AtomicSet(&run, 1); 159 SDL_Thread *thr_cpu = SDL_CreateThread(cpu_thread, "cpu", NULL); 125 cpu_loop(); 160 126 161 if (thr_cpu == NULL) {162 fail("SDL_CreateThread() failed: %s", SDL_GetError());163 }164 165 SDL_Thread *thr_gdb = SDL_CreateThread(gdb_thread, "gdb", NULL);166 167 if (thr_gdb == NULL) {168 fail("SDL_CreateThread() failed: %s", SDL_GetError());169 }170 171 sdl_loop();172 173 SDL_WaitThread(thr_cpu, NULL);174 SDL_WaitThread(thr_gdb, NULL);175 176 cpu_quit();177 gdb_quit();178 127 sdl_quit(); 179 128 return 0; -
emu/sdl.c
r7b50125 r40b2112 18 18 #include <all.h> 19 19 20 int32_t sdl_verbose = 0;20 int32_t sdl_verbose = false; 21 21 22 22 #define ver(...) _ver(sdl_verbose, 0, __VA_ARGS__) 23 23 #define ver2(...) _ver(sdl_verbose, 1, __VA_ARGS__) 24 24 #define ver3(...) _ver(sdl_verbose, 2, __VA_ARGS__) 25 26 typedef void (*sdl_func_t)(void);27 28 static sdl_func_t sdl_funcs[] = {29 ser_sdl30 };31 25 32 26 void sdl_init(void) … … 38 32 39 33 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE); 40 41 if (SDLNet_Init() < 0) {42 fail("SDLNet_Init() failed: %s", SDLNet_GetError());43 }44 34 45 35 if (TTF_Init() < 0) { … … 54 44 { 55 45 TTF_Quit(); 56 SDLNet_Quit();57 46 SDL_Quit(); 58 47 } 59 60 void sdl_loop(void)61 {62 inf("entering SDL loop");63 64 #if defined EMU_LINUX65 SDL_Scancode down = SDL_SCANCODE_UNKNOWN;66 #endif67 68 while (SDL_AtomicGet(&run) != 0) {69 for (int32_t i = 0; i < ARRAY_COUNT(sdl_funcs); ++i) {70 sdl_funcs[i]();71 }72 73 SDL_Event ev;74 75 while (SDL_PollEvent(&ev) > 0) {76 #if defined EMU_LINUX77 // Work around duplicate key-down events on Linux.78 79 if (ev.type == SDL_KEYDOWN) {80 if (down == ev.key.keysym.scancode) {81 continue;82 }83 84 down = ev.key.keysym.scancode;85 }86 else if (ev.type == SDL_KEYUP) {87 down = SDL_SCANCODE_UNKNOWN;88 }89 #endif90 91 if (ev.type == SDL_QUIT ||92 (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE)) {93 ver("quit");94 SDL_AtomicSet(&run, 0);95 continue;96 }97 98 if (ev.type == SDL_TEXTINPUT) {99 ser_text(&ev.text);100 continue;101 }102 103 if (ev.type == SDL_KEYDOWN) {104 ser_key(&ev.key);105 continue;106 }107 108 SDL_Delay(50);109 }110 }111 112 inf("leaving SDL loop");113 } -
emu/ser.c
r7b50125 r40b2112 37 37 #define CON_FGR ((SDL_Color){ .r = 255, .b = 255, .g = 255, .a = 255 }) 38 38 39 #define CON_FONT "ttf/vera-sans-mono.ttf" 40 39 41 #define REG_IER_ISR 0 40 42 #define REG_CFR_SR 1 … … 58 60 static SDL_Window *win; 59 61 static SDL_Renderer *ren; 60 static SDL_atomic_t frame;61 62 62 63 static TTF_Font *fon; … … 69 70 static int32_t bel = 0; 70 71 71 static void scroll(void) 72 { 73 memmove(mem, mem + 1, (CON_H - 1) * (CON_W + 1)); 74 memset(mem + (CON_H - 1), ' ', CON_W); 75 } 76 77 static void forw(void) 78 { 79 if (cur_x < CON_W - 1) { 80 ++cur_x; 81 return; 82 } 83 84 if (cur_y == CON_H - 1) { 85 cur_x = 0; 86 scroll(); 87 return; 88 } 89 90 cur_x = 0; 91 ++cur_y; 92 } 93 94 static void back(void) 95 { 96 if (cur_x > 0) { 97 --cur_x; 98 return; 99 } 100 101 if (cur_y == 0) { 102 return; 103 } 104 105 cur_x = CON_W - 1; 106 --cur_y; 107 } 108 109 static void down(void) 110 { 111 if (cur_y < CON_H - 1) { 112 ++cur_y; 113 return; 114 } 115 116 scroll(); 117 } 118 119 static void echo(uint8_t c) 120 { 121 if (c < 32) { 122 switch (c) { 123 case '\r': 124 cur_x = 0; 125 break; 126 127 case '\n': 128 down(); 129 break; 130 131 case '\b': 132 back(); 133 break; 134 135 case '\a': 136 bel = BEL_CYC; 137 break; 138 139 default: 140 echo('^'); 141 echo((uint8_t)(c + '@')); 142 return; 143 } 144 } 145 else { 146 mem[cur_y][cur_x] = c; 147 forw(); 148 } 149 150 SDL_AtomicAdd(&frame, 1); 151 } 152 153 static void out(int32_t un, uint8_t c) 154 { 155 if (SDL_LockMutex(cpu_mutex) < 0) { 156 fail("SDL_LockMutex() failed: %s", SDL_GetError()); 157 } 158 159 state[un].rdr = c; 160 state[un].rdr_ok = true; 161 state[un].irq_r = true; 162 163 if (SDL_UnlockMutex(cpu_mutex) < 0) { 164 fail("SDL_UnlockMutex() failed: %s", SDL_GetError()); 165 } 166 } 167 168 void ser_sdl(void) 169 { 170 ver3("ser_sdl()"); 171 172 static int32_t last = 0; 173 int32_t now = SDL_AtomicGet(&frame); 174 175 if (last == now) { 176 ver3("no update"); 177 return; 178 } 179 180 last = now; 181 72 static void update(void) 73 { 182 74 if (SDL_FillRect(sur, NULL, bel == 0 ? CON_BGR : CON_BEL) < 0) { 183 75 fail("SDL_FillRect() failed: %s", SDL_GetError()); … … 194 86 195 87 for (int32_t y = 0; y < CON_H; ++y) { 196 char line[CON_W + 1]; 197 198 if (SDL_LockMutex(cpu_mutex) < 0) { 199 fail("SDL_LockMutex() failed: %s", SDL_GetError()); 200 } 201 202 memcpy(line, mem[y], CON_W + 1); 203 204 if (SDL_UnlockMutex(cpu_mutex) < 0) { 205 fail("SDL_UnlockMutex() failed: %s", SDL_GetError()); 206 } 207 208 SDL_Surface *lin = TTF_RenderText_Blended(fon, line, CON_FGR); 88 SDL_Surface *lin = TTF_RenderText_Blended(fon, (char *)mem[y], CON_FGR); 209 89 210 90 if (lin == NULL) { … … 238 118 } 239 119 120 static void scroll(void) 121 { 122 memmove(mem, mem + 1, (CON_H - 1) * (CON_W + 1)); 123 memset(mem + (CON_H - 1), ' ', CON_W); 124 } 125 126 static void forw(void) 127 { 128 if (cur_x < CON_W - 1) { 129 ++cur_x; 130 return; 131 } 132 133 if (cur_y == CON_H - 1) { 134 cur_x = 0; 135 scroll(); 136 return; 137 } 138 139 cur_x = 0; 140 ++cur_y; 141 } 142 143 static void back(void) 144 { 145 if (cur_x > 0) { 146 --cur_x; 147 return; 148 } 149 150 if (cur_y == 0) { 151 return; 152 } 153 154 cur_x = CON_W - 1; 155 --cur_y; 156 } 157 158 static void down(void) 159 { 160 if (cur_y < CON_H - 1) { 161 ++cur_y; 162 return; 163 } 164 165 scroll(); 166 } 167 168 static void echo(uint8_t c) 169 { 170 if (c < 32) { 171 switch (c) { 172 case '\r': 173 cur_x = 0; 174 break; 175 176 case '\n': 177 down(); 178 break; 179 180 case '\b': 181 back(); 182 break; 183 184 case '\a': 185 bel = BEL_CYC; 186 break; 187 188 default: 189 echo('^'); 190 echo((uint8_t)(c + '@')); 191 return; 192 } 193 } 194 else { 195 mem[cur_y][cur_x] = c; 196 forw(); 197 } 198 199 update(); 200 } 201 202 static void out(int32_t un, uint8_t c) 203 { 204 state[un].rdr = c; 205 state[un].rdr_ok = true; 206 state[un].irq_r = true; 207 } 208 240 209 void ser_key(SDL_KeyboardEvent *ev) 241 210 { … … 283 252 } 284 253 285 SDL_AtomicSet(&frame, 1); 286 287 SDL_RWops *ops = SDL_RWFromFile(font, "rb"); 254 SDL_RWops *ops = SDL_RWFromFile(CON_FONT, "rb"); 288 255 289 256 if (ops == NULL) { 290 fail("error while opening font file %s: %s", font, SDL_GetError());257 fail("error while opening font file " CON_FONT ": %s", SDL_GetError()); 291 258 } 292 259 … … 294 261 295 262 if (fon == NULL) { 296 fail("error while loading font file %s: %s", font, TTF_GetError());263 fail("error while loading font file " CON_FONT ": %s", TTF_GetError()); 297 264 } 298 265 … … 319 286 mem[y][CON_W] = 0; 320 287 } 288 289 update(); 321 290 } 322 291 … … 340 309 341 310 if (bel == BEL_CYC - 1 || bel == 0) { 342 SDL_AtomicAdd(&frame, 1);311 update(); 343 312 } 344 313 } -
readme.txt
r7b50125 r40b2112 26 26 https://libsdl.org/ 27 27 28 The SDL2 website also hosts the SDL2_net and SDL2_ttf projects, which 29 add support for networking and TrueType fonts to SDL2 30 31 SDL2_ttf, in turn, requires the FreeType library, which is available 32 from the FreeType website: 28 The SDL2 website also hosts the SDL2_ttf project, which adds support 29 for TrueType fonts to SDL2. SDL2_ttf, in turn, requires the FreeType 30 library, which is available from the FreeType website: 33 31 34 32 https://www.freetype.org/ … … 69 67 make install 70 68 71 # Build and install SDL2_ttf , now that we have FreeType and SDL269 # Build and install SDL2_ttf last 72 70 73 71 tar zxvf SDL2_ttf-2.0.14.tar.gz … … 78 76 ../configure --prefix=/opt/sdl2 \ 79 77 --with-sdl-prefix=/opt/sdl2 --with-freetype-prefix=/opt/sdl2 80 81 make82 make install83 84 # Build and install SDL2_net last85 86 tar zxvf SDL2_net-2.0.1.tar.gz87 cd SDL2_net-2.0.188 mkdir build89 cd build90 91 ../configure --prefix=/opt/sdl2 --with-sdl-prefix=/opt/sdl292 78 93 79 make … … 113 99 Then, to cross-build the emulator, invoke 114 100 115 make buchla .exeWIN=1101 make buchla WIN=1 116 102 117 103 from the top-level directory of this repository. Defining the "WIN" 118 104 variable selects the cross-toolchain and "/opt/sdl2-win" as the 119 105 library directory. 120 121 In addition to the emulator, we need to build the mkdisk utility,122 which we'll use to create a 720-KiB floppy disk image that can be read123 by the Buchla firmware.124 125 Building mkdisk works pretty much like building the emulator. On Linux126 and OS X, invoke127 128 make mkdisk129 130 from the top-level directory of this repository. To cross-build the131 Windows version, invoke132 133 make mkdisk.exe WIN=1134 135 instead.136 137 138 Running the emulator139 --------------------140 141 This is where this repository, buchla-emu, meets its companion142 repository, buchla-68k. We assume that you built the following files143 according to the instructions in the buchla-68k repository:144 145 bios.abs146 midas.abs147 148 Please copy (or symlink) them into the top-level directory of this149 repository, buchla-emu.150 151 bios.abs contains the Buchla 700's BIOS code. The file is loaded by152 the emulator directly to emulate the BIOS PROM.153 154 midas.abs is the MIDAS VII software. Unlike the BIOS, which resides in155 a PROM, it is loaded from a floppy disk. To create this floppy disk,156 we need the mkdisk utility.157 158 mkdisk expects to be run from inside the directory that contains159 midas.abs and produces a disk image file, buchla.disk in the same160 directory. For example, on Linux:161 162 ~/buchla-emu$ ls -l midas.abs163 lrwxrwxrwx 1 emu emu 23 Jul 30 18:07 midas.abs -> ../buchla-68k/midas.abs164 ~/buchla-emu$ ./mkdisk165 ~/buchla-emu$ ls -l buchla.disk166 -rw-r--r-- 1 emu emu 737280 Aug 6 09:44 buchla.disk167 168 Now we have everything in place to run the emulator. On Linux and OS X169 you can invoke it directly from the top-level directory of this170 repository:171 172 ~/buchla-emu$ ./buchla173 174 If you prefer to install the emulator elsewhere, be sure to copy the175 following files:176 177 buchla | buchla.exe emulator executable (.exe for Windows)178 ttf/vera-sans-mono.ttf emulator font179 bios.abs BIOS code180 buchla.disk disk image181 182 This also applies to copying the cross-compiled Windows emulator to a183 Windows machine.184 185 If you would like to keep the BIOS code, disk image, and font separate186 from the emulator executable, check out the emulator's -b, -d, and -f187 command line options. Use -h for an overview of all available options.188 189 190 Cross-debugging the firmware191 ----------------------------192 193 While the emulator is running, it listens on TCP port 12053 for194 incoming connections from a GDB cross-debugger. This allows for195 comfortable source-level debugging of the cross-compiled BIOS and196 MIDAS VII code, while it runs in the emulator.197 198 We assume that you have a GCC cross-toolchain in /opt/cross-m68k, as199 described in the buchla-68k repository. Based on that, we build a200 GDB cross-debugger:201 202 # If you haven't yet done so, add the cross-toolchain to your203 # PATH, so that the GDB build can find it.204 205 export PATH="/opt/cross-m68k/bin:${PATH}"206 207 tar zxvf gdb-7.12.tar.gz208 cd gdb-7.12209 210 mkdir build211 cd build212 213 ../configure --prefix=/opt/cross-m68k --target=m68k-none-elf214 215 make -j2216 make install217 218 The Buchla firmware uses its own (Atari-like) object and executable219 file format. However, the cross-toolchain and the cross-debugger220 support the ELF standard.221 222 When you built the BIOS and MIDAS VII software, you ended up with two223 files in the Buchla's executable file format, bios.abs and midas.abs.224 However, the cross-build process also produces matching ELF files,225 bios.elf and midas.elf, suitable for the cross-debugger.226 227 Depending on whether you would like to cross-debug the BIOS or MIDAS228 VII, you'd specify either bios.elf or midas.elf when invoking the229 cross-debugger.230 231 To follow along the following example, copy (or symlink) bios.elf and232 midas.elf from the buchla-68k repository into the top-level directory233 of this repository.234 235 In order to open a debug session for the BIOS, run the cross-debugger236 with bios.abs and connect it to the running emulator using GDB's237 238 target remote :12053239 240 command. 12053 is the port on which the emulator listens for incoming241 GDB connections.242 243 host:~/buchla-emu$ m68k-none-elf-gdb ./bios.elf244 GNU gdb (GDB) 7.12245 Copyright (C) 2016 Free Software Foundation, Inc.246 [...]247 (gdb) target remote :12053248 Remote debugging using :12053249 trwzsup () at rom/bios.s:832250 832 move.l 0(a0,d0),d0 | Get routine address251 (gdb)252 253 From here on, everything is pretty much standard GDB, for example:254 255 (gdb) break pscan256 Breakpoint 1 at 0x105a64: file rom/romp.c, line 3403.257 (gdb) cont258 [...]259 (gdb) bt260 #0 pscan () at rom/romp.c:3403261 #1 0x00105e96 in main () at rom/romp.c:3587262 #2 0x00105fd6 in Croot (cp=0x0) at prolog/croot.c:141263 #3 0x00105f52 in start1 () at prolog/fsmain.s:59264 (gdb)265 266 In order to debug MIDAS VII, run the cross-debugger with midas.elf,267 instead:268 269 host:~/buchla-emu$ m68k-none-elf-gdb ./midas.elf270 GNU gdb (GDB) 7.12271 Copyright (C) 2016 Free Software Foundation, Inc.272 [...]273 106 274 107 … … 285 118 * Motorola MC6840: Timers. 286 119 287 * Rockwell R65C52: Serial console and MIDI ports.120 * Motorola MC6850: Serial console and MIDI ports. 288 121 289 122 * Epson SED1335: LCD controller. … … 333 166 334 167 2. A second chip for the actual sound generation. This is likely 335 a DSP. 168 a DSP, possibly a Hitachi HD61810, which supports a 16-bit 169 floating-point format that's also found in the firmware 170 source code (12-bit mantissa, 4-bit exponent). 336 171 337 XXX - Details to be filled in. 172 This chip takes in the current levels of a voice's envelopes 173 and, based on them, performs the FM synthesis for this voice 174 by modulating the user-drawn carrier waves A and B according 175 to the selected FM configuration (algorithm). 338 176 339 177 We don't know how many of the envelopes not related to FM … … 352 190 would be great to be able to compare the emulation to real hardware. 353 191 354 If your Buchla is non-functional, this is also fine. We might be able355 to gain some insights from reading outthe FPU microcode PROMs.192 If it's non-functional, this is also fine. We might be able to gain 193 some insights from reading the FPU microcode PROMs.
Note:
See TracChangeset
for help on using the changeset viewer.