fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 360 lines 8.7 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/vic20/setup.c * 7 * Created: 2020-04-19 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2020-2022 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include "main.h" 24#include "keybd.h" 25#include "msg.h" 26#include "vic20.h" 27#include "video.h" 28 29#include <stdlib.h> 30#include <string.h> 31 32#include <chipset/e6522.h> 33 34#include <cpu/e6502/e6502.h> 35 36#include <devices/cassette.h> 37#include <devices/memory.h> 38 39#include <drivers/pti/pti-io.h> 40#include <drivers/sound/sound.h> 41#include <drivers/video/terminal.h> 42 43#include <lib/brkpt.h> 44#include <lib/iniram.h> 45#include <lib/initerm.h> 46#include <lib/load.h> 47#include <lib/log.h> 48 49#include <libini/libini.h> 50 51 52#define V20_CLOCK_PAL ((443361875 + 200) / 400) 53#define V20_CLOCK_NTSC (14318181 / 14) 54 55 56static 57void v20_setup_vic20 (vic20_t *sim, ini_sct_t *ini) 58{ 59 unsigned speed; 60 int pal, aspeed; 61 ini_sct_t *sct; 62 63 sct = ini_next_sct (ini, NULL, "system"); 64 65 ini_get_uint16 (sct, "speed", &speed, 1); 66 ini_get_bool (sct, "pal", &pal, 0); 67 ini_get_bool (sct, "auto_speed", &aspeed, 1); 68 69 sim->pal = (pal != 0); 70 sim->clock = sim->pal ? V20_CLOCK_PAL : V20_CLOCK_NTSC; 71 72 sim->speed = speed; 73 sim->speed_base = speed; 74 sim->speed_auto = (aspeed != 0); 75 sim->speed_tape = 0; 76 77 sim->framedrop_base = 0; 78 sim->framedrop_tape = 0; 79 80 pce_log_tag (MSG_INF, "VIC20:", 81 "cpu=6502 clock=%lu speed=%u autospeed=%d pal=%d\n", 82 sim->clock, sim->speed, sim->speed_auto, sim->pal 83 ); 84 85 if ((sim->cpu = e6502_new()) == NULL) { 86 pce_log (MSG_ERR, "*** creating the cpu failed\n"); 87 return; 88 } 89 90 e6502_set_flags (sim->cpu, E6502_FLAG_UNDEF); 91 92 if ((sim->mem = mem_new()) == NULL) { 93 pce_log (MSG_ERR, "*** creating memory failed\n"); 94 return; 95 } 96 97 e6502_set_mem_f (sim->cpu, sim->mem, mem_get_uint8, mem_set_uint8); 98} 99 100static 101void v20_setup_mem (vic20_t *sim, ini_sct_t *ini) 102{ 103 mem_set_fct (sim->mem, sim, 104 v20_get_uint8, NULL, NULL, 105 v20_set_uint8, NULL, NULL 106 ); 107 108 ini_get_ram (sim->mem, ini, NULL); 109 ini_get_rom (sim->mem, ini); 110} 111 112static 113void v20_setup_via (vic20_t *sim, ini_sct_t *ini) 114{ 115 pce_log_tag (MSG_INF, "VIA:", "initialized\n"); 116 117 sim->ira1 = 0xfe; 118 sim->irb2 = 0xff; 119 120 e6522_init (&sim->via1, 0); 121 e6522_set_irq_fct (&sim->via1, sim, v20_set_via1_irq); 122 e6522_set_ora_fct (&sim->via1, sim, v20_set_via1_ora); 123 e6522_set_orb_fct (&sim->via1, sim, v20_set_via1_orb); 124 e6522_set_ca2_fct (&sim->via1, sim, v20_set_via1_ca2); 125 126 e6522_init (&sim->via2, 0); 127 e6522_set_irq_fct (&sim->via2, sim, v20_set_via2_irq); 128 e6522_set_ora_fct (&sim->via2, sim, v20_set_via2_ora); 129 e6522_set_orb_fct (&sim->via2, sim, v20_set_via2_orb); 130 131 e6522_set_ca1_inp (&sim->via1, 1); 132 e6522_set_ira_inp (&sim->via1, sim->ira1); 133 e6522_set_irb_inp (&sim->via2, sim->irb2); 134} 135 136static 137void v20_setup_video (vic20_t *sim, ini_sct_t *ini) 138{ 139 int pal, border; 140 int hue; 141 unsigned sat, brt, drop; 142 unsigned long srate; 143 const char *snd; 144 ini_sct_t *sct; 145 146 sct = ini_next_sct (ini, NULL, "video"); 147 148 ini_get_bool (sct, "pal", &pal, sim->pal); 149 ini_get_bool (sct, "border", &border, 0); 150 ini_get_sint16 (sct, "hue", &hue, 0); 151 ini_get_uint16 (sct, "saturation", &sat, 50); 152 ini_get_uint16 (sct, "brightness", &brt, 100); 153 ini_get_uint16 (sct, "framedrop", &drop, 0); 154 ini_get_string (sct, "sound", &snd, NULL); 155 ini_get_uint32 (sct, "sample_rate", &srate, 44100); 156 157 pce_log_tag (MSG_INF, "VIC:", 158 "pal=%d drop=%u hue=%d sat=%u brt=%u srate=%lu\n", 159 pal, drop, hue, sat, brt, srate 160 ); 161 162 if (snd != NULL) { 163 pce_log_tag (MSG_INF, "VIC:", "sound=%s\n", snd); 164 } 165 166 sim->framedrop_base = drop; 167 168 v20_video_init (&sim->video); 169 170 v20_video_set_clock (&sim->video, sim->clock); 171 v20_video_set_srate (&sim->video, srate); 172 173 v20_video_set_pal (&sim->video, pal, border); 174 v20_video_set_memmap (&sim->video, sim->mem); 175 176 v20_video_set_framedrop (&sim->video, drop); 177 178 v20_video_set_hue (&sim->video, hue); 179 v20_video_set_saturation (&sim->video, sat / 100.0); 180 v20_video_set_brightness (&sim->video, brt / 100.0); 181 182 if (v20_video_set_sound_driver (&sim->video, snd)) { 183 pce_log (MSG_ERR, "*** sound driver failed\n"); 184 } 185} 186 187static 188void v20_setup_terminal (vic20_t *sim, ini_sct_t *ini) 189{ 190 sim->trm = ini_get_terminal (ini, par_terminal); 191 192 if (sim->trm == NULL) { 193 return; 194 } 195 196 trm_set_msg_fct (sim->trm, sim, v20_set_msg); 197 trm_set_key_fct (sim->trm, sim, v20_keybd_set_key); 198 199 v20_video_set_term (&sim->video, sim->trm); 200} 201 202static 203void v20_setup_keybd (vic20_t *sim, ini_sct_t *ini) 204{ 205 unsigned i; 206 int joy; 207 ini_sct_t *sct; 208 209 sct = ini_next_sct (ini, NULL, "keyboard"); 210 211 ini_get_bool (sct, "keypad_joystick", &joy, 0); 212 213 sim->keypad_joystick = (joy != 0); 214 215 pce_log_tag (MSG_INF, "KEYBOARD:", "joystick=%d\n", 216 sim->keypad_joystick 217 ); 218 219 sim->joymat = 0; 220 221 for (i = 0; i < 8; i++) { 222 sim->keymat[i] = 0; 223 } 224} 225 226static 227void v20_setup_datasette (vic20_t *sim, ini_sct_t *ini) 228{ 229 const char *read_name, *write_name; 230 unsigned long delay; 231 ini_sct_t *sct; 232 233 cas_init (&sim->cas); 234 235 if ((sct = ini_next_sct (ini, NULL, "datasette")) == NULL) { 236 return; 237 } 238 239 ini_get_string (sct, "file", &write_name, NULL); 240 ini_get_string (sct, "write", &write_name, write_name); 241 ini_get_string (sct, "read", &read_name, write_name); 242 ini_get_uint32 (sct, "motor_delay", &delay, 50); 243 244 pce_log_tag (MSG_INF, "CASSETTE:", "read=%s write=%s motor_delay=%lu\n", 245 (read_name != NULL) ? read_name : "<none>", 246 (write_name != NULL) ? write_name : "<none>", 247 delay 248 ); 249 250 delay = (unsigned long) (((double) delay * sim->clock) / 1000.0); 251 252 cas_set_inp_fct (&sim->cas, sim, v20_cas_set_inp); 253 cas_set_play_fct (&sim->cas, sim, v20_cas_set_play); 254 cas_set_run_fct (&sim->cas, sim, v20_set_speed_tape); 255 256 cas_set_clock (&sim->cas, sim->clock); 257 cas_set_motor_delay (&sim->cas, delay); 258 259 pti_set_default_clock (sim->clock); 260 261 if (cas_set_read_name (&sim->cas, read_name)) { 262 pce_log (MSG_ERR, "*** opening read file failed (%s)\n", 263 read_name 264 ); 265 } 266 267 if (cas_set_write_name (&sim->cas, write_name, 1)) { 268 pce_log (MSG_ERR, "*** opening write file failed (%s)\n", 269 write_name 270 ); 271 } 272} 273 274static 275void v20_set_memmap (vic20_t *sim) 276{ 277 unsigned i; 278 mem_blk_t *blk; 279 280 e6502_set_mem_map_rd (sim->cpu, 0x0000, 0xffff, NULL); 281 e6502_set_mem_map_wr (sim->cpu, 0x0000, 0xffff, NULL); 282 283 for (i = 0; i < sim->mem->cnt; i++) { 284 blk = sim->mem->lst[i].blk; 285 286 if (blk->data == NULL) { 287 continue; 288 } 289 290 e6502_set_mem_map_rd (sim->cpu, blk->addr1, blk->addr2, blk->data); 291 292 if (blk->readonly) { 293 continue; 294 } 295 296 e6502_set_mem_map_wr (sim->cpu, blk->addr1, blk->addr2, blk->data); 297 } 298} 299 300vic20_t *v20_new (ini_sct_t *ini) 301{ 302 vic20_t *sim; 303 304 if ((sim = malloc (sizeof (vic20_t))) == NULL) { 305 return (NULL); 306 } 307 308 memset (sim, 0, sizeof (vic20_t)); 309 310 sim->cfg = ini; 311 312 sim->brk = 0; 313 sim->irq_via1 = 0; 314 sim->irq_via2 = 0; 315 sim->clk_div = 0; 316 317 bps_init (&sim->bps); 318 319 v20_setup_vic20 (sim, ini); 320 v20_setup_mem (sim, ini); 321 v20_setup_via (sim, ini); 322 v20_setup_video (sim, ini); 323 v20_setup_keybd (sim, ini); 324 v20_setup_datasette (sim, ini); 325 v20_setup_terminal (sim, ini); 326 327 pce_load_mem_ini (sim->mem, ini); 328 329 v20_set_memmap (sim); 330 331 v20_set_msg (sim, "term.title", "VIC-20"); 332 333 /* v20_debug_mem (sim); */ 334 335 return (sim); 336} 337 338void v20_del (vic20_t *sim) 339{ 340 if (sim == NULL) { 341 return; 342 } 343 344 cas_free (&sim->cas); 345 346 v20_video_free (&sim->video); 347 348 trm_del (sim->trm); 349 350 e6522_free (&sim->via2); 351 e6522_free (&sim->via1); 352 353 e6502_del (sim->cpu); 354 355 mem_del (sim->mem); 356 357 bps_free (&sim->bps); 358 359 free (sim); 360}