+++ /dev/null
- /*
- * UAE - The Un*x Amiga Emulator
- *
- * CD32 Akiko emulation
- *
- * - C2P
- * - NVRAM
- * - CDROM
- *
- * Copyright 2001, 2002 Toni Wilen
- *
- */
-
-#include "sysconfig.h"
-#include "sysdeps.h"
-
-#include "config.h"
-#include "options.h"
-#include "memory.h"
-#include "events.h"
-#include "savestate.h"
-#include "blkdev.h"
-#include "zfile.h"
-#include "threaddep/thread.h"
-#include "akiko.h"
-
-#define AKIKO_DEBUG_NVRAM 0
-#define AKIKO_DEBUG_IO 1
-#define AKIKO_DEBUG_IO_CMD 1
-
-int cd32_enabled;
-
-static int m68k_getpc (void) { return 0; }
-
-/*
- * CD32 1Kb NVRAM (EEPROM) emulation
- *
- * NVRAM chip is 24C08 CMOS EEPROM (1024x8 bits = 1Kb)
- * Chip interface is I2C (2 wire serial)
- * Akiko addresses used:
- * 0xb80030: bit 7 = SCL (clock), 6 = SDA (data)
- * 0xb80032: 0xb80030 data direction register (0 = input, 1 = output)
- *
- * Because I don't have any experience on I2C, following code may be
- * unnecessarily complex and not 100% correct..
- */
-
-enum i2c { I2C_WAIT, I2C_START, I2C_DEVICEADDR, I2C_WORDADDR, I2C_DATA };
-
-/* size of EEPROM, don't try to change,
- * (hardcoded in Kickstart)
- */
-#define NVRAM_SIZE 1024
-/* max size of one write request */
-#define NVRAM_PAGE_SIZE 16
-
-static uae_u8 cd32_nvram[NVRAM_SIZE], nvram_writetmp[NVRAM_PAGE_SIZE];
-static int nvram_address, nvram_writeaddr;
-static int nvram_rw;
-static int bitcounter = -1, direction = -1;
-static uae_u8 nvram_byte;
-static int scl_out, scl_in, scl_dir, oscl, sda_out, sda_in, sda_dir, osda;
-static int sda_dir_nvram;
-static int state = I2C_WAIT;
-
-static void nvram_write (int offset, int len)
-{
- struct zfile *f = zfile_fopen (currprefs.flashfile, "rb+");
- if (!f) {
- f = zfile_fopen (currprefs.flashfile, "wb");
- if (!f) return;
- zfile_fwrite (cd32_nvram, NVRAM_SIZE, 1, f);
- zfile_fclose (f);
- }
- zfile_fseek (f, offset, SEEK_SET);
- zfile_fwrite (cd32_nvram + offset, len, 1, f);
- zfile_fclose (f);
-}
-
-static void nvram_read (void)
-{
- struct zfile *f;
-
- f = zfile_fopen (currprefs.flashfile, "rb");
- memset (cd32_nvram, 0, NVRAM_SIZE);
- if (!f) return;
- zfile_fread (cd32_nvram, NVRAM_SIZE, 1, f);
- zfile_fclose (f);
-}
-
-static void i2c_do (void)
-{
-#if AKIKO_DEBUG_NVRAM
- int i;
-#endif
- sda_in = 1;
- if (!sda_dir_nvram && scl_out && oscl) {
- if (!sda_out && osda) { /* START-condition? */
- state = I2C_DEVICEADDR;
- bitcounter = 0;
- direction = -1;
-#if AKIKO_DEBUG_NVRAM
- write_log ("START\n");
-#endif
- return;
- } else if(sda_out && !osda) { /* STOP-condition? */
- state = I2C_WAIT;
- bitcounter = -1;
-#if AKIKO_DEBUG_NVRAM
- write_log ("STOP\n");
-#endif
- if (direction > 0) {
- memcpy (cd32_nvram + (nvram_address & ~(NVRAM_PAGE_SIZE - 1)), nvram_writetmp, NVRAM_PAGE_SIZE);
- nvram_write (nvram_address & ~(NVRAM_PAGE_SIZE - 1), NVRAM_PAGE_SIZE);
- direction = -1;
-#if AKIKO_DEBUG_NVRAM
- write_log ("NVRAM write address %04X:", nvram_address & ~(NVRAM_PAGE_SIZE - 1));
- for (i = 0; i < NVRAM_PAGE_SIZE; i++)
- write_log ("%02X", nvram_writetmp[i]);
- write_log ("\n");
-
-#endif
- }
- return;
- }
- }
- if (bitcounter >= 0) {
- if (direction) {
- /* Amiga -> NVRAM */
- if (scl_out && !oscl) {
- if (bitcounter == 8) {
-#if AKIKO_DEBUG_NVRAM
- write_log ("RB %02X ", nvram_byte, m68k_getpc ());
-#endif
- sda_in = 0; /* ACK */
- if (direction > 0) {
- nvram_writetmp[nvram_writeaddr++] = nvram_byte;
- nvram_writeaddr &= 15;
- bitcounter = 0;
- } else {
- bitcounter = -1;
- }
- } else {
- //write_log ("NVRAM received bit %d, offset %d\n", sda_out, bitcounter);
- nvram_byte <<= 1;
- nvram_byte |= sda_out;
- bitcounter++;
- }
- }
- } else {
- /* NVRAM -> Amiga */
- if (scl_out && !oscl && bitcounter < 8) {
- if (bitcounter == 0)
- nvram_byte = cd32_nvram[nvram_address];
- sda_dir_nvram = 1;
- sda_in = (nvram_byte & 0x80) ? 1 : 0;
- //write_log ("NVRAM sent bit %d, offset %d\n", sda_in, bitcounter);
- nvram_byte <<= 1;
- bitcounter++;
- if (bitcounter == 8) {
-#if AKIKO_DEBUG_NVRAM
- write_log ("NVRAM sent byte %02X address %04X PC=%08X\n", cd32_nvram[nvram_address], nvram_address, m68k_getpc ());
-#endif
- nvram_address++;
- nvram_address &= NVRAM_SIZE - 1;
- sda_dir_nvram = 0;
- }
- }
- if(!sda_out && sda_dir && !scl_out) /* ACK from Amiga */
- bitcounter = 0;
- }
- if (bitcounter >= 0) return;
- }
- switch (state)
- {
- case I2C_DEVICEADDR:
- if ((nvram_byte & 0xf0) != 0xa0) {
- write_log ("WARNING: I2C_DEVICEADDR: device address != 0xA0\n");
- state = I2C_WAIT;
- return;
- }
- nvram_rw = (nvram_byte & 1) ? 0 : 1;
- if (nvram_rw) {
- /* 2 high address bits, only fetched if WRITE = 1 */
- nvram_address &= 0xff;
- nvram_address |= ((nvram_byte >> 1) & 3) << 8;
- state = I2C_WORDADDR;
- direction = -1;
- } else {
- state = I2C_DATA;
- direction = 0;
- sda_dir_nvram = 1;
- }
- bitcounter = 0;
-#if AKIKO_DEBUG_NVRAM
- write_log ("I2C_DEVICEADDR: rw %d, address %02Xxx PC=%08X\n", nvram_rw, nvram_address >> 8, m68k_getpc ());
-#endif
- break;
- case I2C_WORDADDR:
- nvram_address &= 0x300;
- nvram_address |= nvram_byte;
-#if AKIKO_DEBUG_NVRAM
- write_log ("I2C_WORDADDR: address %04X PC=%08X\n", nvram_address, m68k_getpc ());
-#endif
- if (direction < 0) {
- memcpy (nvram_writetmp, cd32_nvram + (nvram_address & ~(NVRAM_PAGE_SIZE - 1)), NVRAM_PAGE_SIZE);
- nvram_writeaddr = nvram_address & (NVRAM_PAGE_SIZE - 1);
- }
- state = I2C_DATA;
- bitcounter = 0;
- direction = 1;
- break;
- }
-}
-
-static void akiko_nvram_write (int offset, uae_u32 v)
-{
- int sda;
- switch (offset)
- {
- case 0:
- oscl = scl_out;
- scl_out = (v & 0x80) ? 1 : 0;
- osda = sda_out;
- sda_out = (v & 0x40) ? 1 : 0;
- break;
- case 2:
- scl_dir = (v & 0x80) ? 1 : 0;
- sda_dir = (v & 0x40) ? 1 : 0;
- break;
- default:
- return;
- }
- sda = sda_out;
- if (oscl != scl_out || osda != sda) {
- i2c_do ();
- oscl = scl_out;
- osda = sda;
- }
-}
-
-static uae_u32 akiko_nvram_read (int offset)
-{
- uae_u32 v = 0;
- switch (offset)
- {
- case 0:
- if (!scl_dir)
- v |= scl_in ? 0x80 : 0x00;
- else
- v |= scl_out ? 0x80 : 0x00;
- if (!sda_dir)
- v |= sda_in ? 0x40 : 0x00;
- else
- v |= sda_out ? 0x40 : 0x00;
- break;
- case 2:
- v |= scl_dir ? 0x80 : 0x00;
- v |= sda_dir ? 0x40 : 0x00;
- break;
- }
- return v;
-}
-
-/* CD32 Chunky to Planar hardware emulation
- * Akiko addresses used:
- * 0xb80038-0xb8003b
- */
-
-static uae_u32 akiko_buffer[8];
-static int akiko_read_offset, akiko_write_offset;
-static uae_u32 akiko_result[8];
-
-static void akiko_c2p_do (void)
-{
- int i;
-
- for (i = 0; i < 8; i++) akiko_result[i] = 0;
- /* FIXME: better c2p algoritm than this piece of crap.... */
- for (i = 0; i < 8 * 32; i++) {
- if (akiko_buffer[7 - (i >> 5)] & (1 << (i & 31)))
- akiko_result[i & 7] |= 1 << (i >> 3);
- }
-}
-
-static void akiko_c2p_write (int offset, uae_u32 v)
-{
- if (offset == 3) akiko_buffer[akiko_write_offset] = 0;
- akiko_buffer[akiko_write_offset] |= v << ( 8 * (3 - offset));
- if (offset == 0) {
- akiko_write_offset++;
- akiko_write_offset &= 7;
- }
- akiko_read_offset = 0;
-}
-
-static uae_u32 akiko_c2p_read (int offset)
-{
- uae_u32 v;
-
- if (akiko_read_offset == 0 && offset == 3)
- akiko_c2p_do ();
- akiko_write_offset = 0;
- v = akiko_result[akiko_read_offset];
- if (offset == 0) {
- akiko_read_offset++;
- akiko_read_offset &= 7;
- }
- return v >> (8 * (3 - offset));
-}
-
-/* CD32 CDROM hardware emulation
- * Akiko addresses used:
- * 0xb80004-0xb80028
- *
- * I can't believe cd.device and custom loaders are fooled to think
- * this piece of crap emulates real CD32 CDROM controller and drive :)
- */
-
-#define CDSTATUS_FRAME 0x80000000
-#define CDSTATUS_DATA_AVAILABLE 0x10000000
-#define CDSTATUS_DATASECTOR_ERROR 0x08000000 /* ?? */
-#define CDSTATUS_DATASECTOR 0x04000000
-
-#define CDS_ERROR 0x80
-#define CDS_PLAYING 0x08
-
-static uae_u32 cdrom_status1, cdrom_status2;
-static uae_u8 cdrom_status3;
-static uae_u32 cdrom_address1, cdrom_address2;
-static uae_u32 cdrom_longmask;
-static uae_u32 cdrom_readmask_r, cdrom_readmask_w;
-static uae_u8 cdrom_command_offset_complete; /* 0x19 */
-static uae_u8 cdrom_command_offset_todo; /* 0x1d */
-static uae_u8 cdrom_result_complete; /* 0x1a */
-static uae_u8 cdrom_result_last_pos; /* 0x1f */
-static uae_u8 cdrom_result_buffer[32];
-static uae_u8 cdrom_command_buffer[32];
-static uae_u8 cdrom_command;
-
-#define MAX_TOC_ENTRIES 103 /* tracks 1-99, A0,A1 and A2 */
-static int cdrom_toc_entries;
-static int cdrom_toc_counter;
-static uae_u8 cdrom_toc_buffer[MAX_TOC_ENTRIES*13];
-
-static int cdrom_disk, cdrom_paused, cdrom_playing;
-static int cdrom_command_active;
-static int cdrom_command_length;
-static int cdrom_checksum_error;
-static int cdrom_data_offset, cdrom_speed, cdrom_sector_counter;
-static int cdrom_current_sector;
-static int cdrom_data_end, cdrom_leadout;
-static int cdrom_dosomething;
-
-static uae_u8 *sector_buffer_1, *sector_buffer_2;
-static int sector_buffer_sector_1, sector_buffer_sector_2;
-#define SECTOR_BUFFER_SIZE 64
-static uae_u8 *sector_buffer_info_1, *sector_buffer_info_2;
-
-static int unitnum = -1;
-
-static uae_u8 frombcd (uae_u8 v)
-{
- return (v >> 4) * 10 + (v & 15);
-}
-
-static uae_u8 tobcd (uae_u8 v)
-{
- return ((v / 10) << 4) | (v % 10);
-}
-
-static int fromlongbcd (uae_u8 *p)
-{
- return (frombcd (p[0]) << 16) | (frombcd (p[1]) << 8) | (frombcd (p[2]) << 0);
-}
-
-/* convert minutes, seconds and frames -> logical sector number */
-static int msf2lsn (int msf)
-{
- int sector = (((msf >> 16) & 0xff) * 60 * 75 + ((msf >> 8) & 0xff) * 75 + ((msf >> 0) & 0xff)) - 150;
- if (sector < 0)
- sector = 0;
- return sector;
-}
-
-/* convert logical sector number -> minutes, seconds and frames */
-static int lsn2msf (int sectors)
-{
- int msf;
- sectors += 150;
- msf = (sectors / (75 * 60)) << 16;
- msf |= ((sectors / 75) % 60) << 8;
- msf |= (sectors % 75) << 0;
- return msf;
-}
-
-static uae_u32 last_play_end;
-static int cd_play_audio (uae_u32 startmsf, uae_u32 endmsf, int scan)
-{
- if (endmsf == 0xffffffff)
- endmsf = last_play_end;
- else
- last_play_end = endmsf;
- return sys_command_play (DF_IOCTL, unitnum,startmsf, endmsf, scan);
-}
-
-
-/* read qcode */
-static uae_u32 last_play_pos;
-static int cd_qcode (uae_u8 *d)
-{
- uae_u8 *buf, *s, as;
-
- if (d)
- memset (d, 0, 11);
- last_play_pos = 0;
- buf = sys_command_qcode (DF_IOCTL, unitnum);
- if (!buf)
- return 0;
- as = buf[1];
- if (as != 0x11 && as != 0x12 && as != 0x13 && as != 0x15) /* audio status ok? */
- return 0;
- s = buf + 4;
- last_play_pos = (s[9] << 16) | (s[10] << 8) | (s[11] << 0);
- if (!d)
- return 0;
- /* ??? */
- d[0] = 0;
- /* CtlAdr */
- d[1] = (s[1] >> 4) | (s[1] << 4);
- /* Track */
- d[2] = tobcd (s[2]);
- /* Index */
- d[3] = tobcd (s[3]);
- /* TrackPos */
- d[4] = tobcd (s[9]);
- d[5] = tobcd (s[10]);
- d[6] = tobcd (s[11]);
- /* DiskPos */
- d[7] = 0;
- d[8] = tobcd (s[5]);
- d[9] = tobcd (s[6]);
- d[10] = tobcd (s[7]);
- if (as == 0x15) {
- /* Make sure end of disc position is passed.
- */
- int lsn = msf2lsn ((s[5] << 16) | (s[6] << 8) | (s[7] << 0));
- int msf = lsn2msf (cdrom_leadout);
- if (lsn >= cdrom_leadout || cdrom_leadout - lsn < 10) {
- d[8] = tobcd ((uae_u8)(msf >> 16));
- d[9] = tobcd ((uae_u8)(msf >> 8));
- d[10] = tobcd ((uae_u8)(msf >> 0));
- }
- }
-
- return 0;
-}
-
-/* read toc */
-static int cdrom_toc (void)
-{
- int i, j;
- int datatrack = 0, secondtrack = 0;
- uae_u8 *s, *d, *buf;
-
- cdrom_toc_counter = -1;
- cdrom_toc_entries = 0;
- buf = sys_command_toc (DF_IOCTL, unitnum);
- if (!buf)
- return 1;
- i = (buf[0] << 8) | (buf[1] << 0);
- i -= 2;
- i /= 11;
- if (i > MAX_TOC_ENTRIES)
- return -1;
- memset (cdrom_toc_buffer, 0, MAX_TOC_ENTRIES * 13);
- cdrom_data_end = -1;
- for (j = 0; j < i; j++) {
- s = buf + 4 + j * 11;
- d = &cdrom_toc_buffer[j * 13];
- d[1] = (s[1] >> 4) | (s[1] << 4);
- d[3] = s[3] < 100 ? tobcd(s[3]) : s[3];
- d[8] = tobcd (s[8]);
- d[9] = tobcd (s[9]);
- d[10] = tobcd (s[10]);
- if (s[3] == 1 && (s[1] & 0x0f) == 0x04)
- datatrack = 1;
- if (s[3] == 2)
- secondtrack = msf2lsn ((s[8] << 16) | (s[9] << 8) | (s[10] << 0));
- if (s[3] == 0xa2)
- cdrom_leadout = msf2lsn ((s[8] << 16) | (s[9] << 8) | (s[10] << 0));
- }
- if (datatrack) {
- if (secondtrack)
- cdrom_data_end = secondtrack;
- else
- cdrom_data_end = cdrom_leadout;
- }
- cdrom_toc_entries = i;
- return 0;
-}
-
-/* open device */
-static int sys_cddev_open (void)
-{
- int first = -1;
- int found = 0;
- struct device_info di1, *di2;
-
- for (unitnum = 0; unitnum < MAX_TOTAL_DEVICES; unitnum++) {
- di2 = sys_command_info (DF_IOCTL, unitnum, &di1);
- if (di2 && di2->type == INQ_ROMD) {
- if (sys_command_open (DF_IOCTL, unitnum)) {
- if (first < 0)
- first = unitnum;
- if (!cdrom_toc ()) {
- found = 1;
- break;
- }
- sys_command_close (DF_IOCTL, unitnum);
- }
- }
- }
- if (!found) {
- if (first >= 0) {
- unitnum = first;
- sys_command_open (DF_IOCTL, unitnum);
- } else {
- unitnum = -1;
- return 1;
- }
- }
- /* make sure CD audio is not playing */
- sys_command_pause (DF_IOCTL, unitnum, 0);
- sys_command_stop (DF_IOCTL, unitnum);
- sys_command_pause (DF_IOCTL, unitnum, 1);
- return 0;
-}
-
-/* close device */
-static void sys_cddev_close (void)
-{
- sys_command_pause (DF_IOCTL, unitnum, 0);
- sys_command_stop (DF_IOCTL, unitnum);
- sys_command_pause (DF_IOCTL, unitnum, 1);
- sys_command_close (DF_IOCTL, unitnum);
-}
-
-static int command_lengths[] = { 1,2,1,1,12,2,1,1,4,1,-1,-1,-1,-1,-1 };
-
-static void cdrom_return_data (int len)
-{
- uae_u32 cmd_buf = cdrom_address2;
- int i;
- uae_u8 checksum;
-
- if (len <= 0) return;
-#if AKIKO_DEBUG_IO_CMD
- write_log ("OUT:");
-#endif
- checksum = 0xff;
- for (i = 0; i < len; i++) {
- checksum -= cdrom_result_buffer[i];
- put_byte (cmd_buf + ((cdrom_result_complete + i) & 0xff), cdrom_result_buffer[i]);
-#if AKIKO_DEBUG_IO_CMD
- write_log ("%02X ", cdrom_result_buffer[i]);
-#endif
- }
- put_byte (cmd_buf + ((cdrom_result_complete + len) & 0xff), checksum);
-#if AKIKO_DEBUG_IO_CMD
- write_log ("%02X\n", checksum);
-#endif
- cdrom_result_complete += len + 1;
- cdrom_status1 |= CDSTATUS_DATA_AVAILABLE;
-}
-
-static int cdrom_command_something (void)
-{
- return 0;
-}
-
-static int cdrom_command_media_status (void)
-{
- struct device_info di;
-
- cdrom_result_buffer[0] = cdrom_command;
- cdrom_result_buffer[1] = sys_command_info (DF_IOCTL, unitnum, &di)->media_inserted ? 1 : 0;
- return 2;
-}
-
-/* check if cd drive door is open or closed */
-static int cdrom_command_door_status (void)
-{
- struct device_info di;
- if (!sys_command_info (DF_IOCTL, unitnum, &di)->media_inserted) {
- cdrom_result_buffer[1] = 0x80;
- cdrom_disk = 0;
- } else {
- cdrom_result_buffer[1] = 1;
- cdrom_disk = 1;
- }
- cdrom_toc ();
- cdrom_result_buffer[0] = cdrom_command;
- return 20;
-}
-
-/* return one TOC entry */
-static int cdrom_return_toc_entry (void)
-{
- cdrom_result_buffer[0] = 6;
- if (cdrom_toc_entries == 0) {
- cdrom_result_buffer[1] = CDS_ERROR;
- return 15;
- }
- cdrom_result_buffer[1] = 0;
- memcpy (cdrom_result_buffer + 2, cdrom_toc_buffer + cdrom_toc_counter * 13, 13);
- cdrom_toc_counter++;
- if (cdrom_toc_counter >= cdrom_toc_entries)
- cdrom_toc_counter = 0;
- return 15;
-}
-
-/* pause CD audio */
-static int cdrom_command_pause (void)
-{
- cdrom_toc_counter = -1;
- cdrom_result_buffer[0] = cdrom_command;
- cdrom_result_buffer[1] = cdrom_playing ? CDS_PLAYING : 0;
- if (!cdrom_playing)
- return 2;
- if (cdrom_paused)
- return 2;
- sys_command_pause (DF_IOCTL, unitnum, 1);
- cdrom_paused = 1;
- return 2;
-}
-
-/* unpause CD audio */
-static int cdrom_command_unpause (void)
-{
- cdrom_result_buffer[0] = cdrom_command;
- cdrom_result_buffer[1] = cdrom_playing ? CDS_PLAYING : 0;
- if (!cdrom_paused)
- return 2;
- if (!cdrom_playing)
- return 2;
- cdrom_paused = 0;
- sys_command_pause (DF_IOCTL, unitnum, 0);
- return 2;
-}
-
-/* seek head/play CD audio/read data sectors */
-static int cdrom_command_multi (void)
-{
- int seekpos = fromlongbcd (cdrom_command_buffer + 1);
- int endpos = fromlongbcd (cdrom_command_buffer + 4);
-
- cdrom_playing = 0;
- cdrom_speed = (cdrom_command_buffer[8] & 0x40) ? 2 : 1;
- cdrom_result_buffer[0] = cdrom_command;
- cdrom_result_buffer[1] = 0;
- if (!cdrom_disk) {
- cdrom_result_buffer[1] |= CDS_ERROR;
- return 2;
- }
-
- if (cdrom_command_buffer[7] == 0x80) { /* data read */
- int cdrom_data_offset_end = msf2lsn (endpos);
- cdrom_data_offset = msf2lsn (seekpos);
-#if AKIKO_DEBUG_IO_CMD
- write_log ("READ DATA FROM %06X (%d) TO %06X (%d) SPEED=%dx\n", seekpos, cdrom_data_offset, endpos, cdrom_data_offset_end, cdrom_speed);
-#endif
- cdrom_result_buffer[1] |= 0x02;
- } else if (cdrom_command_buffer[10] & 4) { /* play audio */
- int scan = 0;
- if (cdrom_command_buffer[7] & 0x04)
- scan = 1;
- else if (cdrom_command_buffer[7] & 0x08)
- scan = -1;
-#if AKIKO_DEBUG_IO_CMD
- write_log ("PLAY FROM %06X to %06X SCAN=%d\n", seekpos, endpos, scan);
-#endif
- if (!cd_play_audio (seekpos, endpos, 0)) {
- cdrom_result_buffer[1] = CDS_ERROR;
- } else {
- cdrom_playing = 1;
- cdrom_result_buffer[1] |= CDS_PLAYING;
- }
- } else {
-#if AKIKO_DEBUG_IO_CMD
- write_log ("SEEKTO %06X\n",seekpos);
-#endif
- if (seekpos < 150)
- cdrom_toc_counter = 0;
- else
- cdrom_toc_counter = -1;
- }
- return 2;
-}
-
-/* return subq entry */
-static int cdrom_command_subq (void)
-{
- cdrom_result_buffer[0] = cdrom_command;
- cdrom_result_buffer[1] = 0;
- if (cd_qcode (cdrom_result_buffer + 2))
- cdrom_result_buffer[1] = CDS_ERROR;
- return 15;
-}
-
-static void cdrom_run_command (void)
-{
- uae_u32 cmd_buf = cdrom_address2 + 0x200;
- int i, cmd_len;
- uae_u8 checksum;
-
- for (;;) {
- if (cdrom_command_active)
- return;
- if (cdrom_command_offset_complete == cdrom_command_offset_todo)
- return;
- cdrom_command = get_byte (cmd_buf + cdrom_command_offset_complete);
- if ((cdrom_command & 0xf0) == 0)
- return;
- cdrom_checksum_error = 0;
- cmd_len = command_lengths[cdrom_command & 0x0f];
- if (cmd_len < 0) {
-#if AKIKO_DEBUG_IO_CMD
- write_log ("unknown command\n");
-#endif
- cmd_len = 1;
- }
-#if AKIKO_DEBUG_IO_CMD
- write_log ("IN:");
-#endif
- checksum = 0;
- for (i = 0; i < cmd_len + 1; i++) {
- cdrom_command_buffer[i] = get_byte (cmd_buf + ((cdrom_command_offset_complete + i) & 0xff));
- checksum += cdrom_command_buffer[i];
-#if AKIKO_DEBUG_IO_CMD
- write_log ("%02X ", cdrom_command_buffer[i]);
-#endif
- }
- if (checksum!=0xff) {
-#if AKIKO_DEBUG_IO_CMD
- write_log (" checksum error");
-#endif
- cdrom_checksum_error = 1;
- }
-#if AKIKO_DEBUG_IO_CMD
- write_log ("\n");
-#endif
- cdrom_command_active = 1;
- cdrom_command_length = cmd_len;
- return;
- }
-}
-
-static void cdrom_run_command_run (void)
-{
- int len;
-
- cdrom_command_offset_complete = (cdrom_command_offset_complete + cdrom_command_length + 1) & 0xff;
- memset (cdrom_result_buffer, 0, sizeof(cdrom_result_buffer));
- switch (cdrom_command & 0x0f)
- {
- case 2:
- len = cdrom_command_pause ();
- break;
- case 3:
- len = cdrom_command_unpause ();
- break;
- case 4:
- len = cdrom_command_multi ();
- break;
- case 5:
- cdrom_dosomething = 1;
- len = cdrom_command_something ();
- break;
- case 6:
- len = cdrom_command_subq ();
- break;
- case 7:
- len = cdrom_command_door_status ();
- break;
- default:
- len = 0;
- break;
- }
- if (len == 0)
- return;
- if (cdrom_checksum_error)
- cdrom_result_buffer[1] |= 0x80;
- cdrom_return_data (len);
-}
-
-extern void encode_l2 (uae_u8 *p, int address);
-
-/* DMA transfer one CD sector */
-static void cdrom_run_read (void)
-{
- int i, j, sector;
- int read = 0;
- uae_u8 buf[2352];
- int sec;
-
- if (!(cdrom_longmask & 0x04000000))
- return;
- if (!cdrom_readmask_w)
- return;
- if (cdrom_data_offset < 0)
- return;
- if (unitnum >= 0) {
- for (j = 0; j < 16; j++) {
- if (cdrom_readmask_w & (1 << j)) break;
- }
- sector = cdrom_current_sector = cdrom_data_offset + cdrom_sector_counter;
- sec = sector - sector_buffer_sector_1;
- if (sector_buffer_sector_1 >= 0 && sec >= 0 && sec < SECTOR_BUFFER_SIZE) {
- if (sector_buffer_info_1[sec] != 0xff && sector_buffer_info_1[sec] != 0) {
- memcpy (buf + 16, sector_buffer_1 + sec * 2048, 2048);
- encode_l2 (buf, sector + 150);
- buf[0] = 0;
- buf[1] = 0;
- buf[2] = 0;
- buf[3] = cdrom_sector_counter;
- for (i = 0; i < 2352; i++)
- put_byte (cdrom_address1 + j * 4096 + i, buf[i]);
- cdrom_readmask_r |= 1 << j;
- }
- if (sector_buffer_info_1[sec] != 0xff)
- sector_buffer_info_1[sec]--;
- } else
- return;
-#if AKIKO_DEBUG_IO_CMD
- write_log ("read sector=%d, scnt=%d -> %d\n", cdrom_data_offset, cdrom_sector_counter, sector);
-#endif
- cdrom_readmask_w &= ~(1 << j);
- cdrom_status1 |= CDSTATUS_DATASECTOR;
- }
- cdrom_sector_counter++;
-}
-
-static uae_sem_t akiko_sem;
-
-static void akiko_handler (void)
-{
- static int mediacheckcnt;
- struct device_info di;
-
- if (cdrom_result_complete > cdrom_result_last_pos && cdrom_result_complete - cdrom_result_last_pos < 100) {
- cdrom_status1 |= CDSTATUS_DATA_AVAILABLE;
- return;
- }
- if (cdrom_result_last_pos < cdrom_result_complete)
- return;
- if (mediacheckcnt > 0)
- mediacheckcnt--;
- if (mediacheckcnt == 0) {
- int media = sys_command_info (DF_IOCTL, unitnum, &di)->media_inserted;
- if (media != cdrom_disk) {
- write_log ("media changed = %d\n", media);
- cdrom_disk = media;
- cdrom_return_data (cdrom_command_media_status ());
- cdrom_toc ();
- return;
- }
- mediacheckcnt = 312 * 50 * 2;
- }
- if (cdrom_toc_counter >= 0 && !cdrom_command_active && cdrom_dosomething) {
- cdrom_return_data (cdrom_return_toc_entry ());
- cdrom_dosomething--;
- return;
- }
-}
-
-static void akiko_internal (void)
-{
- cdrom_run_command ();
- if (cdrom_command_active > 0) {
- cdrom_command_active--;
- if (!cdrom_command_active)
- cdrom_run_command_run ();
- }
-}
-
-extern int cd32_enabled;
-
-void AKIKO_hsync_handler (void)
-{
- static int framecounter;
-
- if (!cd32_enabled)
- return;
- framecounter--;
- if (framecounter <= 0) {
- cdrom_run_read ();
- framecounter = 1000000 / (74 * 75 * cdrom_speed);
- cdrom_status1 |= CDSTATUS_FRAME;
- }
- akiko_internal ();
- akiko_handler ();
-}
-
-
-static volatile int akiko_thread_running;
-
-/* cdrom data buffering thread */
-static void *akiko_thread (void *null)
-{
- int i;
- uae_u8 *tmp1;
- uae_u8 *tmp2;
- int tmp3;
- uae_u8 *p;
- int offset;
- int sector;
-
- while(akiko_thread_running) {
- uae_sem_wait (&akiko_sem);
- sector = cdrom_current_sector;
- for (i = 0; i < SECTOR_BUFFER_SIZE; i++) {
- if (sector_buffer_info_1[i] == 0xff) break;
- }
- if (cdrom_data_end > 0 && sector >= 0 && (sector_buffer_sector_1 < 0 || sector < sector_buffer_sector_1 || sector >= sector_buffer_sector_1 + SECTOR_BUFFER_SIZE * 2 / 3 || i != SECTOR_BUFFER_SIZE)) {
- memset (sector_buffer_info_2, 0, SECTOR_BUFFER_SIZE);
-#if AKIKO_DEBUG_IO_CMD
- write_log ("filling buffer sector=%d (max=%d)\n", sector, cdrom_data_end);
-#endif
- sector_buffer_sector_2 = sector;
- offset = 0;
- while (offset < SECTOR_BUFFER_SIZE) {
- p = 0;
- if (sector < cdrom_data_end)
- p = sys_command_read (DF_IOCTL, unitnum, sector);
- if (p)
- memcpy (sector_buffer_2 + offset * 2048, p, 2048);
- sector_buffer_info_2[offset] = p ? 3 : 0;
- offset++;
- sector++;
- }
- tmp1 = sector_buffer_info_1;
- sector_buffer_info_1 = sector_buffer_info_2;
- sector_buffer_info_2 = tmp1;
- tmp2 = sector_buffer_1;
- sector_buffer_1 = sector_buffer_2;
- sector_buffer_2 = tmp2;
- tmp3 = sector_buffer_sector_1;
- sector_buffer_sector_1 = sector_buffer_sector_2;
- sector_buffer_sector_2 = tmp3;
- }
- uae_sem_post (&akiko_sem);
- Sleep (10);
- }
- akiko_thread_running = -1;
- return 0;
-}
-
-static uae_u8 akiko_get_long (uae_u32 v, int offset)
-{
- return v >> ((3 - offset) * 8);
-}
-static void akiko_put_long (uae_u32 *p, int offset, int v)
-{
- *p &= ~(0xff << ((3 - offset) * 8));
- *p |= v << ((3 - offset) * 8);
-}
-
-uae_u32 akiko_bget2 (uaecptr addr, int msg)
-{
- uae_u8 v;
-
- addr &= 0xffff;
- uae_sem_wait (&akiko_sem);
- switch (addr)
- {
- /* "CAFE" = Akiko identification.
- * Kickstart ignores Akiko C2P if this ID isn't correct */
- case 0x02:
- v = 0xCA;
- break;
- case 0x03:
- v = 0xFE;
- break;
-
- /* CDROM control */
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- v = akiko_get_long (cdrom_status1, addr - 0x04);
- break;
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- v = akiko_get_long (cdrom_status2, addr - 0x08);
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- v = akiko_get_long (cdrom_address1, addr - 0x10);
- break;
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- v = akiko_get_long (cdrom_address2, addr - 0x14);
- break;
- case 0x18:
- v = cdrom_status3;
- break;
- case 0x19:
- v = cdrom_command_offset_complete;
- break;
- case 0x1a:
- v = cdrom_result_complete;
- break;
- case 0x1f:
- v = cdrom_result_last_pos;
- break;
- case 0x20:
- case 0x21:
- v = akiko_get_long (cdrom_readmask_w, addr - 0x20 + 2);
- break;
- case 0x24:
- case 0x25:
- case 0x26:
- case 0x27:
- v = akiko_get_long (cdrom_longmask, addr - 0x24);
- break;
-
- /* NVRAM */
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- v = akiko_nvram_read (addr - 0x30);
- break;
-
- /* C2P */
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- v = akiko_c2p_read (addr - 0x38);
- break;
-
- default:
- write_log ("akiko_bget: unknown address %08X\n", addr);
- v = 0;
- break;
- }
- akiko_internal ();
- uae_sem_post (&akiko_sem);
- if (msg && addr < 0x30 && AKIKO_DEBUG_IO)
- write_log ("akiko_bget %08X: %08X %02X\n", m68k_getpc (), addr, v & 0xff);
- return v;
-}
-
-uae_u32 akiko_bget (uaecptr addr)
-{
- return akiko_bget2 (addr,1);
-}
-
-uae_u32 akiko_wget (uaecptr addr)
-{
- uae_u16 v;
- addr &= 0xffff;
- v = akiko_bget2 (addr + 1, 0);
- v |= akiko_bget2 (addr + 0, 0) << 8;
- if (addr < 0x30 && AKIKO_DEBUG_IO)
- write_log ("akiko_wget %08X: %08X %04X\n", m68k_getpc (), addr, v & 0xffff);
- return v;
-}
-
-uae_u32 akiko_lget (uaecptr addr)
-{
- uae_u32 v;
-
- addr &= 0xffff;
- v = akiko_bget2 (addr + 3, 0);
- v |= akiko_bget2 (addr + 2, 0) << 8;
- v |= akiko_bget2 (addr + 1, 0) << 16;
- v |= akiko_bget2 (addr + 0, 0) << 24;
- if (addr < 0x30 && (addr != 4 && addr != 8) && AKIKO_DEBUG_IO)
- write_log ("akiko_lget %08X: %08X %08X\n", m68k_getpc (), addr, v);
- return v;
-}
-
-void akiko_bput2 (uaecptr addr, uae_u32 v, int msg)
-{
- uae_u32 tmp;
-
- addr &= 0xffff;
- v &= 0xff;
- if(msg && addr < 0x30 && AKIKO_DEBUG_IO)
- write_log ("akiko_bput %08X: %08X=%02X\n", m68k_getpc (), addr, v & 0xff);
- uae_sem_wait (&akiko_sem);
- switch (addr)
- {
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
- akiko_put_long (&cdrom_status1, addr - 0x04, v);
- break;
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- akiko_put_long (&cdrom_status2, addr - 0x08, v);
- if (addr == 8)
- cdrom_status1 &= cdrom_status2;
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- akiko_put_long (&cdrom_address1, addr - 0x10, v);
- break;
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- akiko_put_long (&cdrom_address2, addr - 0x14, v);
- break;
- case 0x18:
- cdrom_status3 = v;
- break;
- case 0x19:
- cdrom_command_offset_complete = v;
- break;
- case 0x1a:
- cdrom_result_complete = v;
- break;
- case 0x1d:
- cdrom_command_offset_todo = v;
- break;
- case 0x1f:
- cdrom_result_last_pos = v;
- break;
- case 0x20:
- cdrom_readmask_w |= (v << 8);
- cdrom_readmask_r &= 0x00ff;
- break;
- case 0x21:
- cdrom_readmask_w |= (v << 0);
- cdrom_readmask_r &= 0xff00;
- break;
- case 0x24:
- case 0x25:
- case 0x26:
- case 0x27:
- tmp = cdrom_longmask;
- akiko_put_long (&cdrom_longmask, addr - 0x24, v);
- if ((cdrom_longmask & 0x04000000) && !(tmp & 0x04000000))
- cdrom_sector_counter = 0;
- break;
-
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- akiko_nvram_write (addr - 0x30, v);
- break;
-
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- akiko_c2p_write (addr - 0x38, v);
- break;
-
- default:
- write_log ("akiko_bput: unknown address %08X\n", addr);
- break;
- }
- akiko_internal ();
- uae_sem_post (&akiko_sem);
-}
-
-void akiko_bput (uaecptr addr, uae_u32 v)
-{
- akiko_bput2 (addr, v, 1);
-}
-
-void akiko_wput (uaecptr addr, uae_u32 v)
-{
- addr &= 0xfff;
- if((addr < 0x30 && AKIKO_DEBUG_IO))
- write_log ("akiko_wput %08X: %08X=%04X\n", m68k_getpc (), addr, v & 0xffff);
- akiko_bput2 (addr + 1, v & 0xff, 0);
- akiko_bput2 (addr + 0, v >> 8, 0);
-}
-
-void akiko_lput (uaecptr addr, uae_u32 v)
-{
- addr &= 0xffff;
- if(addr < 0x30 && AKIKO_DEBUG_IO)
- write_log ("akiko_lput %08X: %08X=%08X\n", m68k_getpc (), addr, v);
- akiko_bput2 (addr + 3, (v >> 0) & 0xff, 0);
- akiko_bput2 (addr + 2, (v >> 8) & 0xff, 0);
- akiko_bput2 (addr + 1, (v >> 16) & 0xff, 0);
- akiko_bput2 (addr + 0, (v >> 24) & 0xff, 0);
-}
-
-static uae_thread_id akiko_tid;
-
-void akiko_reset (void)
-{
- nvram_read ();
- state = I2C_WAIT;
- bitcounter = -1;
- direction = -1;
-
- cdrom_speed = 1;
- cdrom_current_sector = -1;
-
- if (akiko_thread_running > 0) {
- akiko_thread_running = 0;
- while(akiko_thread_running == 0)
- Sleep (10);
- akiko_thread_running = 0;
- }
-}
-
-extern uae_u32 extendedkickmemory;
-
-static uae_u8 patchdata[]={0x0c,0x82,0x00,0x00,0x03,0xe8,0x64,0x00,0x00,0x46};
-
-static void patchrom (void)
-{
- int i;
- uae_u8 *p = (uae_u8*)extendedkickmemory;
- for (i = 0; i < 524288 - sizeof (patchdata); i++) {
- if (!memcmp (p + i, patchdata, sizeof(patchdata))) {
- p[i + 6] = 0x4e;
- p[i + 7] = 0x71;
- p[i + 8] = 0x4e;
- p[i + 9] = 0x71;
- write_log ("extended rom delay loop patched at 0x%p\n", i + 6 + 0xe00000);
- return;
- }
- }
- write_log ("couldn't patch extended rom\n");
-}
-
-void akiko_free (void)
-{
- akiko_reset ();
- if (unitnum >= 0)
- sys_cddev_close ();
- unitnum = -1;
- free (sector_buffer_1);
- free (sector_buffer_2);
- free (sector_buffer_info_1);
- free (sector_buffer_info_2);
- sector_buffer_1 = 0;
- sector_buffer_2 = 0;
- sector_buffer_info_1 = 0;
- sector_buffer_info_2 = 0;
-}
-
-void akiko_init (void)
-{
- static int cdromok = 0;
-
- if (cdromok == 0) {
- unitnum = -1;
- device_func_init(DEVICE_TYPE_ANY);
- if (!sys_cddev_open ()) {
- cdromok = 1;
- sector_buffer_1 = malloc (SECTOR_BUFFER_SIZE * 2048);
- sector_buffer_2 = malloc (SECTOR_BUFFER_SIZE * 2048);
- sector_buffer_info_1 = malloc (SECTOR_BUFFER_SIZE);
- sector_buffer_info_2 = malloc (SECTOR_BUFFER_SIZE);
- sector_buffer_sector_1 = -1;
- sector_buffer_sector_2 = -1;
- patchrom ();
- }
- }
- if (!savestate_state) {
- cdrom_playing = cdrom_paused = 0;
- cdrom_data_offset = -1;
- uae_sem_init (&akiko_sem, 0, 1);
- }
- if (cdromok && !akiko_thread_running) {
- akiko_thread_running = 1;
- uae_start_thread (akiko_thread, 0, &akiko_tid);
- }
-}
-
-uae_u8 *save_akiko(int *len)
-{
- uae_u8 *dstbak, *dst;
- int i;
-
- dstbak = dst = malloc (1000);
- save_u16 (0);
- save_u16 (0xCAFE);
- save_u32 (cdrom_status1);
- save_u32 (cdrom_status2);
- save_u32 (0);
- save_u32 (cdrom_address1);
- save_u32 (cdrom_address2);
- save_u8 (cdrom_status3);
- save_u8 (cdrom_command_offset_complete);
- save_u8 (cdrom_result_complete);
- save_u8 (0);
- save_u8 (0);
- save_u8 (cdrom_command_offset_todo);
- save_u8 (0);
- save_u8 (cdrom_result_last_pos);
- save_u16 ((uae_u16)cdrom_readmask_w);
- save_u16 (0);
- save_u32 (cdrom_longmask);
- save_u32 (0);
- save_u32 (0);
- save_u32 ((scl_dir ? 0x8000 : 0) | (sda_dir ? 0x4000 : 0));
- save_u32 (0);
- save_u32 (0);
-
- for (i = 0; i < 8; i++)
- save_u32 (akiko_buffer[i]);
- save_u8 ((uae_u8)akiko_read_offset);
- save_u8 ((uae_u8)akiko_write_offset);
-
- save_u32 ((cdrom_playing ? 1 : 0) | (cdrom_paused ? 2 : 0));
- if (cdrom_playing)
- cd_qcode (0);
- save_u32 (last_play_pos);
- save_u32 (last_play_end);
- save_u8 ((uae_u8)cdrom_toc_counter);
-
- *len = dst - dstbak;
- return dstbak;
-}
-
-uae_u8 *restore_akiko(uae_u8 *src)
-{
- uae_u32 v;
- int i;
-
- restore_u16 ();
- restore_u16 ();
- cdrom_status1 = restore_u32 ();
- cdrom_status2 = restore_u32 ();
- restore_u32();
- cdrom_address1 = restore_u32 ();
- cdrom_address2 = restore_u32 ();
- cdrom_status3 = restore_u8 ();
- cdrom_command_offset_complete = restore_u8 ();
- cdrom_result_complete = restore_u8 ();
- restore_u8 ();
- restore_u8 ();
- cdrom_command_offset_todo = restore_u8 ();
- restore_u8 ();
- cdrom_result_last_pos = restore_u8 ();
- cdrom_readmask_w = restore_u16 ();
- restore_u16 ();
- cdrom_longmask = restore_u32 ();
- restore_u32();
- restore_u32();
- v = restore_u32();
- scl_dir = (v & 0x8000) ? 1 : 0;
- sda_dir = (v & 0x4000) ? 1 : 0;
- restore_u32();
- restore_u32();
-
- for (i = 0; i < 8; i++)
- akiko_buffer[i] = restore_u32 ();
- akiko_read_offset = restore_u8 ();
- akiko_write_offset = restore_u8 ();
- akiko_c2p_do ();
-
- cdrom_playing = cdrom_paused = 0;
- v = restore_u32 ();
- if (v & 1)
- cdrom_playing = 1;
- if (v & 2)
- cdrom_paused = 1;
- last_play_pos = restore_u32 ();
- last_play_end = restore_u32 ();
- cdrom_toc_counter = restore_u8 ();
- if (cdrom_toc_counter == 255)
- cdrom_toc_counter = -1;
- if (cdrom_playing)
- sys_command_play (DF_IOCTL, unitnum, last_play_pos, last_play_end, 0);
-
- return src;
-}
+++ /dev/null
-/*
-* UAE - The Un*x Amiga Emulator
-*
-* CIA chip support
-*
-* Copyright 1995 Bernd Schmidt, Alessandro Bissacco
-* Copyright 1996, 1997 Stefan Reinauer, Christian Schmitt
-*/
-
-
-#include "sysconfig.h"
-#include "sysdeps.h"
-#include <assert.h>
-
-#include "options.h"
-#include "events.h"
-#include "memory.h"
-#include "custom.h"
-#include "newcpu.h"
-#include "cia.h"
-#include "serial.h"
-#include "disk.h"
-#include "xwin.h"
-#include "keybuf.h"
-#include "gui.h"
-#include "savestate.h"
-#include "inputdevice.h"
-#include "zfile.h"
-#include "ar.h"
-#include "parallel.h"
-#include "akiko.h"
-#include "cdtv.h"
-#include "debug.h"
-#include "arcadia.h"
-#include "audio.h"
-#include "keyboard.h"
-#include "uae.h"
-#include "amax.h"
-#include "sampler.h"
-#include "dongle.h"
-#include "inputrecord.h"
-#include "autoconf.h"
-
-#define CIAA_DEBUG_R 0
-#define CIAA_DEBUG_W 0
-#define CIAA_DEBUG_IRQ 0
-
-#define CIAB_DEBUG_R 0
-#define CIAB_DEBUG_W 0
-#define CIAB_DEBUG_IRQ 0
-
-#define DONGLE_DEBUG 0
-#define KB_DEBUG 0
-#define CLOCK_DEBUG 0
-
-#define TOD_HACK
-
-/* e-clock is 10 CPU cycles, 4 cycles high, 6 low
-* data transfer happens during 4 high cycles
-*/
-#define ECLOCK_DATA_CYCLE 4
-#define ECLOCK_WAIT_CYCLE 6
-
-#define DIV10 ((ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) * CYCLE_UNIT / 2) /* Yes, a bad identifier. */
-#define CIASTARTCYCLESHI 3
-#define CIASTARTCYCLESCRA 2
-
-static unsigned int ciaaicr, ciaaimask, ciabicr, ciabimask;
-static unsigned int ciaacra, ciaacrb, ciabcra, ciabcrb;
-static unsigned int ciaastarta, ciaastartb, ciabstarta, ciabstartb;
-static unsigned int ciaaicr_reg, ciabicr_reg;
-
-/* Values of the CIA timers. */
-static unsigned long ciaata, ciaatb, ciabta, ciabtb;
-/* Computed by compute_passed_time. */
-static unsigned long ciaata_passed, ciaatb_passed, ciabta_passed, ciabtb_passed;
-
-static unsigned long ciaatod, ciabtod, ciaatol, ciabtol, ciaaalarm, ciabalarm;
-static int ciaatlatch, ciabtlatch;
-static bool oldled, oldovl, oldcd32mute;
-static bool led;
-static int led_old_brightness;
-static unsigned long led_cycles_on, led_cycles_off, led_cycle;
-
-unsigned int ciabpra;
-
-static unsigned long ciaala, ciaalb, ciabla, ciablb;
-static int ciaatodon, ciabtodon;
-static unsigned int ciaapra, ciaaprb, ciaadra, ciaadrb, ciaasdr, ciaasdr_cnt;
-static unsigned int ciabprb, ciabdra, ciabdrb, ciabsdr, ciabsdr_cnt;
-static int div10;
-static int kbstate, kblostsynccnt;
-static uae_u8 kbcode;
-
-static uae_u8 serbits;
-static int warned = 10;
-static int rtc_delayed_write;
-
-
-static void setclr (unsigned int *p, unsigned int val)
-{
- if (val & 0x80) {
- *p |= val & 0x7F;
- } else {
- *p &= ~val;
- }
-}
-
-static void ICRA(uae_u32 data)
-{
- if (ciaaimask & ciaaicr) {
- ciaaicr |= 0x80;
- INTREQ_0 (0x8000 | data);
- }
- ciaaicr_reg |= ciaaicr;
-}
-static void ICRB(uae_u32 data)
-{
- if (ciabimask & ciabicr) {
- ciabicr |= 0x80;
- INTREQ_0 (0x8000 | data);
- }
- ciabicr_reg |= ciabicr;
-}
-
-static void RethinkICRA (void)
-{
- if (ciaaicr) {
-#if CIAA_DEBUG_IRQ
- write_log (_T("CIAA IRQ %02X\n"), ciaaicr);
-#endif
- if (currprefs.cpu_cycle_exact)
- event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x0008, ICRA);
- else
- ICRA (0x0008);
- }
-}
-
-static void RethinkICRB (void)
-{
- if (ciabicr) {
-#if CIAB_DEBUG_IRQ
- write_log (_T("CIAB IRQ %02X\n"), ciabicr);
-#endif
- if (currprefs.cpu_cycle_exact)
- event2_newevent_xx (-1, 2 * CYCLE_UNIT + CYCLE_UNIT / 2, 0x2000, ICRB);
- else
- ICRB (0x2000);
- }
-}
-
-void rethink_cias (void)
-{
- RethinkICRA ();
- RethinkICRB ();
-}
-
-/* Figure out how many CIA timer cycles have passed for each timer since the
-last call of CIA_calctimers. */
-
-static void compute_passed_time (void)
-{
- unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
- unsigned long int ciaclocks = ccount / DIV10;
-
- ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
-
- /* CIA A timers */
- if ((ciaacra & 0x21) == 0x01) {
- unsigned long int cc = ciaclocks;
- if (cc > ciaastarta)
- cc -= ciaastarta;
- else
- cc = 0;
- assert ((ciaata + 1) >= cc);
- ciaata_passed = cc;
- }
- if ((ciaacrb & 0x61) == 0x01) {
- unsigned long int cc = ciaclocks;
- if (cc > ciaastartb)
- cc -= ciaastartb;
- else
- cc = 0;
- assert ((ciaatb + 1) >= cc);
- ciaatb_passed = cc;
- }
-
- /* CIA B timers */
- if ((ciabcra & 0x21) == 0x01) {
- unsigned long int cc = ciaclocks;
- if (cc > ciabstarta)
- cc -= ciabstarta;
- else
- cc = 0;
- assert ((ciabta + 1) >= cc);
- ciabta_passed = cc;
- }
- if ((ciabcrb & 0x61) == 0x01) {
- unsigned long int cc = ciaclocks;
- if (cc > ciabstartb)
- cc -= ciabstartb;
- else
- cc = 0;
- assert ((ciabtb + 1) >= cc);
- ciabtb_passed = cc;
- }
-}
-
-/* Called to advance all CIA timers to the current time. This expects that
-one of the timer values will be modified, and CIA_calctimers will be called
-in the same cycle. */
-
-static int CIA_update_check (void)
-{
- unsigned long int ccount = (get_cycles () - eventtab[ev_cia].oldcycles + div10);
- unsigned long int ciaclocks = ccount / DIV10;
-
- int aovfla = 0, aovflb = 0, asp = 0, bovfla = 0, bovflb = 0, bsp = 0;
- int icr = 0;
-
- div10 = ccount % DIV10;
-
- /* CIA A timers */
- if ((ciaacra & 0x21) == 0x01) {
- bool check = true;
- unsigned long int cc = ciaclocks;
- if (ciaastarta > 0) {
- if (cc > ciaastarta) {
- cc -= ciaastarta;
- ciaastarta = 0;
- } else {
- ciaastarta -= cc;
- check = false;
- }
- }
- if (check) {
- assert ((ciaata + 1) >= cc);
- if ((ciaata + 1) == cc) {
- if ((ciaacra & 0x48) == 0x40 && ciaasdr_cnt > 0 && --ciaasdr_cnt == 0)
- asp = 1;
- aovfla = 1;
- if ((ciaacrb & 0x61) == 0x41 || (ciaacrb & 0x61) == 0x61) {
- if (ciaatb-- == 0)
- aovflb = 1;
- }
- }
- ciaata -= cc;
- }
- }
- if ((ciaacrb & 0x61) == 0x01) {
- bool check = true;
- unsigned long int cc = ciaclocks;
- if (ciaastartb > 0) {
- if (cc > ciaastartb) {
- cc -= ciaastartb;
- ciaastartb = 0;
- } else {
- ciaastartb -= cc;
- check = false;
- }
- }
- if (check) {
- assert ((ciaatb + 1) >= cc);
- if ((ciaatb + 1) == cc)
- aovflb = 1;
- ciaatb -= cc;
- }
- }
-
- /* CIA B timers */
- if ((ciabcra & 0x21) == 0x01) {
- bool check = true;
- unsigned long int cc = ciaclocks;
- if (ciabstarta > 0) {
- if (cc > ciabstarta) {
- cc -= ciabstarta;
- ciabstarta = 0;
- } else {
- ciabstarta -= cc;
- check = false;
- }
- }
- if (check) {
- assert ((ciabta + 1) >= cc);
- if ((ciabta + 1) == cc) {
- if ((ciabcra & 0x48) == 0x40 && ciabsdr_cnt > 0 && --ciabsdr_cnt == 0)
- bsp = 1;
- bovfla = 1;
- if ((ciabcrb & 0x61) == 0x41 || (ciabcrb & 0x61) == 0x61) {
- if (ciabtb-- == 0)
- bovflb = 1;
- }
- }
- ciabta -= cc;
- }
- }
- if ((ciabcrb & 0x61) == 0x01) {
- bool check = true;
- unsigned long int cc = ciaclocks;
- if (ciabstartb > 0) {
- if (cc > ciabstartb) {
- cc -= ciabstartb;
- ciabstartb = 0;
- } else {
- ciabstartb -= cc;
- check = false;
- }
- }
- if (check) {
- assert ((ciabtb + 1) >= cc);
- if ((ciabtb + 1) == cc)
- bovflb = 1;
- ciabtb -= cc;
- }
- }
-
- if (aovfla) {
- ciaaicr |= 1; icr = 1;
- ciaata = ciaala;
- if (ciaacra & 0x8) {
- ciaacra &= ~1;
- }
- }
- if (aovflb) {
- ciaaicr |= 2; icr = 1;
- ciaatb = ciaalb;
- if (ciaacrb & 0x8) {
- ciaacrb &= ~1;
- }
- }
- if (asp) {
- ciaaicr |= 8; icr = 1;
- }
- if (bovfla) {
- ciabicr |= 1; icr |= 2;
- ciabta = ciabla;
- if (ciabcra & 0x8) {
- ciabcra &= ~1;
- }
- }
- if (bovflb) {
- ciabicr |= 2; icr |= 2;
- ciabtb = ciablb;
- if (ciabcrb & 0x8) {
- ciabcrb &= ~1;
- }
- }
- if (bsp) {
- ciabicr |= 8; icr |= 2;
- }
- return icr;
-}
-static void CIA_update (void)
-{
- int icr = CIA_update_check ();
- if (icr & 1)
- RethinkICRA ();
- if (icr & 2)
- RethinkICRB ();
-}
-
-
-/* Call this only after CIA_update has been called in the same cycle. */
-
-static void CIA_calctimers (void)
-{
- long int ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1;
- int div10diff = DIV10 - div10;
-
- eventtab[ev_cia].oldcycles = get_cycles ();
-
- if ((ciaacra & 0x21) == 0x01) {
- ciaatimea = div10diff + DIV10 * (ciaata + ciaastarta);
- }
-#if 0
- if ((ciaacrb & 0x61) == 0x41) {
- /* Timer B will not get any pulses if Timer A is off. */
- if (ciaatimea >= 0) {
- /* If Timer A is in one-shot mode, and Timer B needs more than
- * one pulse, it will not underflow. */
- if (ciaatb == 0 || (ciaacra & 0x8) == 0) {
- /* Otherwise, we can determine the time of the underflow. */
- /* This may overflow, however. So just ignore this timer and
- use the fact that we'll call CIA_handler for the A timer. */
- /* ciaatimeb = ciaatimea + ciaala * DIV10 * ciaatb; */
- }
- }
- }
-#endif
- if ((ciaacrb & 0x61) == 0x01) {
- ciaatimeb = div10diff + DIV10 * (ciaatb + ciaastartb);
- }
-
- if ((ciabcra & 0x21) == 0x01) {
- ciabtimea = div10diff + DIV10 * (ciabta + ciabstarta);
- }
-#if 0
- if ((ciabcrb & 0x61) == 0x41) {
- /* Timer B will not get any pulses if Timer A is off. */
- if (ciabtimea >= 0) {
- /* If Timer A is in one-shot mode, and Timer B needs more than
- * one pulse, it will not underflow. */
- if (ciabtb == 0 || (ciabcra & 0x8) == 0) {
- /* Otherwise, we can determine the time of the underflow. */
- /* ciabtimeb = ciabtimea + ciabla * DIV10 * ciabtb; */
- }
- }
- }
-#endif
- if ((ciabcrb & 0x61) == 0x01) {
- ciabtimeb = div10diff + DIV10 * (ciabtb + ciabstartb);
- }
-
- eventtab[ev_cia].active = (ciaatimea != -1 || ciaatimeb != -1
- || ciabtimea != -1 || ciabtimeb != -1);
- if (eventtab[ev_cia].active) {
- unsigned long int ciatime = ~0L;
- if (ciaatimea != -1)
- ciatime = ciaatimea;
- if (ciaatimeb != -1 && ciaatimeb < ciatime)
- ciatime = ciaatimeb;
- if (ciabtimea != -1 && ciabtimea < ciatime)
- ciatime = ciabtimea;
- if (ciabtimeb != -1 && ciabtimeb < ciatime)
- ciatime = ciabtimeb;
- eventtab[ev_cia].evtime = ciatime + get_cycles ();
- }
- events_schedule();
-}
-
-void CIA_handler (void)
-{
- CIA_update ();
- CIA_calctimers ();
-}
-
-void cia_diskindex (void)
-{
- ciabicr |= 0x10;
- RethinkICRB ();
-}
-void cia_parallelack (void)
-{
- ciaaicr |= 0x10;
- RethinkICRA ();
-}
-
-static int checkalarm (unsigned long tod, unsigned long alarm, bool inc)
-{
- if (tod == alarm)
- return 1;
- if (!inc)
- return 0;
- /* Amix workaround */
- if (currprefs.mmu_model)
- return 0;
- /* emulate buggy TODMED counter.
- * it counts: .. 29 2A 2B 2C 2D 2E 2F 20 30 31 32 ..
- * (2F->20->30 only takes couple of cycles but it will trigger alarm..
- */
- if (tod & 0x000fff)
- return 0;
- if (((tod - 1) & 0xfff000) == alarm)
- return 1;
- return 0;
-}
-
-STATIC_INLINE bool ciab_checkalarm (bool inc, bool irq)
-{
- // hack: do not trigger alarm interrupt if KS code and both
- // tod and alarm == 0. This incorrectly triggers on non-cycle exact
- // modes. Real hardware value written to ciabtod by KS is always
- // at least 1 or larger due to bus cycle delays when reading
- // old value.
- if ((munge24 (m68k_getpc ()) & 0xFFF80000) == 0xF80000) {
- if (ciabtod == 0 && ciabalarm == 0)
- return false;
- }
- if (checkalarm (ciabtod, ciabalarm, inc)) {
-#if CIAB_DEBUG_IRQ
- write_log (_T("CIAB tod %08x %08x\n"), ciabtod, ciabalarm);
-#endif
- if (irq) {
- ciabicr |= 4;
- RethinkICRB ();
- }
- return true;
- }
- return false;
-}
-
-STATIC_INLINE void ciaa_checkalarm (bool inc)
-{
- if (checkalarm (ciaatod, ciaaalarm, inc)) {
-#if CIAA_DEBUG_IRQ
- write_log (_T("CIAA tod %08x %08x\n"), ciaatod, ciaaalarm);
-#endif
- ciaaicr |= 4;
- RethinkICRA ();
- }
-}
-
-#ifdef TOD_HACK
-static uae_u64 tod_hack_tv, tod_hack_tod, tod_hack_tod_last;
-static int tod_hack_enabled;
-#define TOD_HACK_TIME 312 * 50 * 10
-static void tod_hack_reset (void)
-{
- struct timeval tv;
- gettimeofday (&tv, NULL);
- tod_hack_tv = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
- tod_hack_tod = ciaatod;
- tod_hack_tod_last = tod_hack_tod;
-}
-#endif
-
-static int heartbeat_cnt;
-void cia_heartbeat (void)
-{
- heartbeat_cnt = 10;
-}
-
-static void do_tod_hack (int dotod)
-{
- struct timeval tv;
- static int oldrate;
- uae_u64 t;
- int rate;
- int docount = 0;
-
- if (tod_hack_enabled == 0)
- return;
- if (!heartbeat_cnt) {
- if (tod_hack_enabled > 0)
- tod_hack_enabled = -1;
- return;
- }
- if (tod_hack_enabled < 0) {
- tod_hack_enabled = TOD_HACK_TIME;
- return;
- }
- if (tod_hack_enabled > 1) {
- tod_hack_enabled--;
- if (tod_hack_enabled == 1) {
- //write_log (_T("TOD HACK enabled\n"));
- tod_hack_reset ();
- }
- return;
- }
-
- if (currprefs.cs_ciaatod == 0)
- rate = (int)(vblank_hz + 0.5);
- else if (currprefs.cs_ciaatod == 1)
- rate = 50;
- else
- rate = 60;
- if (rate <= 0)
- return;
- if (rate != oldrate || ciaatod != tod_hack_tod_last) {
- //if (ciaatod != 0)
- // write_log (_T("TOD HACK reset %d,%d %d,%d\n"), rate, oldrate, ciaatod, tod_hack_tod_last);
- tod_hack_reset ();
- oldrate = rate;
- docount = 1;
- }
- if (!dotod && currprefs.cs_ciaatod == 0)
- return;
- gettimeofday (&tv, NULL);
- t = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec;
- if (t - tod_hack_tv >= 1000000 / rate) {
- tod_hack_tv += 1000000 / rate;
- docount = 1;
- }
- if (docount) {
- ciaatod++;
- ciaatod &= 0x00ffffff;
- tod_hack_tod_last = ciaatod;
- ciaa_checkalarm (false);
- }
-}
-
-static int resetwarning_phase, resetwarning_timer;
-
-static void setcode (uae_u8 keycode)
-{
- kbcode = ~((keycode << 1) | (keycode >> 7));
-}
-
-static void sendrw (void)
-{
- setcode (AK_RESETWARNING);
- ciaasdr = kbcode;
- kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
- ciaaicr |= 8;
- RethinkICRA ();
- write_log (_T("KB: sent reset warning code (phase=%d)\n"), resetwarning_phase);
-}
-
-int resetwarning_do (int canreset)
-{
- if (resetwarning_phase) {
- /* just force reset if second reset happens during resetwarning */
- if (canreset) {
- resetwarning_phase = 0;
- resetwarning_timer = 0;
- }
- return 0;
- }
- resetwarning_phase = 1;
- resetwarning_timer = maxvpos_nom * 5;
- write_log (_T("KB: reset warning triggered\n"));
- sendrw ();
- return 1;
-}
-
-static void resetwarning_check (void)
-{
- if (resetwarning_timer > 0) {
- resetwarning_timer--;
- if (resetwarning_timer <= 0) {
- write_log (_T("KB: reset warning forced reset. Phase=%d\n"), resetwarning_phase);
- resetwarning_phase = -1;
- kblostsynccnt = 0;
- send_internalevent (INTERNALEVENT_KBRESET);
- uae_reset (0, 1);
- }
- }
- if (resetwarning_phase == 1) {
- if (!kblostsynccnt) { /* first AK_RESETWARNING handshake received */
- write_log (_T("KB: reset warning second phase..\n"));
- resetwarning_phase = 2;
- resetwarning_timer = maxvpos_nom * 5;
- sendrw ();
- }
- } else if (resetwarning_phase == 2) {
- if (ciaacra & 0x40) { /* second AK_RESETWARNING handshake active */
- resetwarning_phase = 3;
- write_log (_T("KB: reset warning SP = output\n"));
- /* System won't reset until handshake signal becomes inactive or 10s has passed */
- resetwarning_timer = 10 * maxvpos_nom * vblank_hz;
- }
- } else if (resetwarning_phase == 3) {
- if (!(ciaacra & 0x40)) { /* second AK_RESETWARNING handshake disabled */
- write_log (_T("KB: reset warning end by software. reset.\n"));
- resetwarning_phase = -1;
- kblostsynccnt = 0;
- send_internalevent (INTERNALEVENT_KBRESET);
- uae_reset (0, 1);
- }
- }
-}
-
-void CIA_hsync_prehandler (void)
-{
-}
-
-static void keyreq (void)
-{
-#if KB_DEBUG
- write_log (_T("code=%x\n"), kbcode);
-#endif
- ciaasdr = kbcode;
- kblostsynccnt = 8 * maxvpos * 8; // 8 frames * 8 bits.
- ciaaicr |= 8;
- RethinkICRA ();
-}
-
-/* All this complexity to lazy evaluate TOD increase.
- * Only increase it cycle-exactly if it is visible to running program:
- * causes interrupt or program is reading or writing TOD registers
- */
-
-static int ciab_tod_hoffset;
-static int ciab_tod_event_state;
-// TOD increase has extra 14-16 E-clock delay
-// Possibly TICK input pin has built-in debounce circuit
-#define TOD_INC_DELAY (14 * (ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) / 2)
-
-static void CIAB_tod_inc (uae_u32 v)
-{
- ciab_tod_event_state = 3; // done
- ciabtod++;
- ciabtod &= 0xFFFFFF;
- ciab_checkalarm (true, true);
-}
-
-// Someone reads or writes TOD registers, sync TOD increase
-static void CIAB_tod_check (void)
-{
- if (ciab_tod_event_state != 1 || !ciabtodon)
- return;
- int hpos = current_hpos ();
- hpos -= ciab_tod_hoffset;
- if (hpos >= 0 || currprefs.m68k_speed < 0) {
- // Program should see the changed TOD
- CIAB_tod_inc (0);
- return;
- }
- // Not yet, add event to guarantee exact TOD inc position
- ciab_tod_event_state = 2; // event active
- event2_newevent_xx (-1, -hpos, 0, CIAB_tod_inc);
-}
-
-void CIAB_tod_handler (int hoffset)
-{
- uae_u32 v;
-
- ciab_tod_hoffset = hoffset + TOD_INC_DELAY;
- if (!ciabtodon)
- return;
- ciab_tod_event_state = 1; // TOD inc needed
- v = ciabtod;
- ciabtod++;
- ciabtod &= 0xFFFFFF;
- bool irq = ciab_checkalarm (false, false);
- ciabtod = v;
- if (irq) {
- // causes interrupt on this line, add event
- ciab_tod_event_state = 2; // event active
- event2_newevent_xx (-1, ciab_tod_hoffset, 0, CIAB_tod_inc);
- }
-}
-
-void CIA_hsync_posthandler (bool dotod)
-{
- // Previous line was supposed to increase TOD but
- // no one cared. Do it now at the start of next line.
- if (ciab_tod_event_state == 1)
- CIAB_tod_inc (0);
- ciab_tod_event_state = 0;
-
- if (currprefs.tod_hack && ciaatodon)
- do_tod_hack (dotod);
-
- if (resetwarning_phase) {
- resetwarning_check ();
- while (keys_available ())
- get_next_key ();
- } else if ((keys_available () || kbstate < 3) && !kblostsynccnt && (hsync_counter & 15) == 0) {
- switch (kbstate)
- {
- case 0:
- kbcode = 0; /* powerup resync */
- kbstate++;
- break;
- case 1:
- setcode (AK_INIT_POWERUP);
- kbstate++;
- break;
- case 2:
- setcode (AK_TERM_POWERUP);
- kbstate++;
- break;
- case 3:
- kbcode = ~get_next_key ();
- break;
- }
- keyreq ();
- }
-}
-
-static void calc_led (int old_led)
-{
- unsigned long c = get_cycles ();
- unsigned long t = (c - led_cycle) / CYCLE_UNIT;
- if (old_led)
- led_cycles_on += t;
- else
- led_cycles_off += t;
- led_cycle = c;
-}
-
-static void led_vsync (void)
-{
- int v;
-
- calc_led (led);
- if (led_cycles_on && !led_cycles_off)
- v = 255;
- else if (led_cycles_off && !led_cycles_on)
- v = 0;
- else if (led_cycles_off)
- v = led_cycles_on * 255 / (led_cycles_on + led_cycles_off);
- else
- v = 255;
- if (v < 0)
- v = 0;
- if (v > 255)
- v = 255;
- gui_data.powerled_brightness = v;
- led_cycles_on = 0;
- led_cycles_off = 0;
- if (led_old_brightness != gui_data.powerled_brightness) {
- gui_data.powerled = gui_data.powerled_brightness > 127;
- gui_led (LED_POWER, gui_data.powerled);
- led_filter_audio ();
- }
- led_old_brightness = gui_data.powerled_brightness;
- led_cycle = get_cycles ();
-}
-
-static void write_battclock (void);
-void CIA_vsync_prehandler (void)
-{
- if (heartbeat_cnt > 0)
- heartbeat_cnt--;
- if (rtc_delayed_write < 0) {
- rtc_delayed_write = 50;
- } else if (rtc_delayed_write > 0) {
- rtc_delayed_write--;
- if (rtc_delayed_write == 0)
- write_battclock ();
- }
- led_vsync ();
- CIA_handler ();
- if (kblostsynccnt > 0) {
- kblostsynccnt -= maxvpos;
- if (kblostsynccnt <= 0) {
- kblostsynccnt = 0;
- keyreq ();
-#if KB_DEBUG
- write_log (_T("lostsync\n"));
-#endif
- }
- }
-}
-
-static void CIAA_tod_handler (uae_u32 v)
-{
- ciaatod++;
- ciaatod &= 0xFFFFFF;
- ciaa_checkalarm (true);
-}
-
-void CIAA_tod_inc (int cycles)
-{
-#ifdef TOD_HACK
- if (currprefs.tod_hack && tod_hack_enabled == 1)
- return;
-#endif
- if (!ciaatodon)
- return;
- event2_newevent_xx (-1, cycles + TOD_INC_DELAY, 0, CIAA_tod_handler);
-}
-
-static void bfe001_change (void)
-{
- uae_u8 v = ciaapra;
- bool led2;
-
- v |= ~ciaadra; /* output is high when pin's direction is input */
- led2 = (v & 2) ? 0 : 1;
- if (led2 != led) {
- calc_led (led);
- led = led2;
- led_old_brightness = -1;
- }
- if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) {
- oldovl = v & 1;
- if (!oldovl) {
- map_overlay (1);
- } else {
- //activate_debugger ();
- map_overlay (0);
- }
- }
- if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) {
- oldcd32mute = v & 1;
- akiko_mute (oldcd32mute ? 0 : 1);
- }
-}
-
-static uae_u8 ReadCIAA (unsigned int addr)
-{
- unsigned int tmp;
- int reg = addr & 15;
-
- compute_passed_time ();
-
-#if CIAA_DEBUG_R > 0
- write_log (_T("R_CIAA: bfe%x01 %08X\n"), reg, M68K_GETPC);
-#endif
-
- switch (reg) {
- case 0:
-#ifdef ACTION_REPLAY
- action_replay_ciaread ();
-#endif
- tmp = DISK_status() & 0x3c;
- tmp |= handle_joystick_buttons (ciaapra, ciaadra);
- tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03;
- tmp = dongle_cia_read (0, reg, tmp);
-#if DONGLE_DEBUG > 0
- if (notinrom())
- write_log (_T("BFE001 R %02X %s\n"), tmp, debuginfo(0));
-#endif
-
- if (inputrecord_debug & 2) {
- if (input_record > 0)
- inprec_recorddebug_cia (tmp, div10, m68k_getpc ());
- else if (input_play > 0)
- inprec_playdebug_cia (tmp, div10, m68k_getpc ());
- }
-
- return tmp;
- case 1:
-#ifdef PARALLEL_PORT
- if (isprinter () > 0) {
- tmp = ciaaprb;
- } else if (isprinter () < 0) {
- uae_u8 v;
- parallel_direct_read_data (&v);
- tmp = v;
-#ifdef ARCADIA
- } else if (arcadia_bios) {
- tmp = arcadia_parport (0, ciaaprb, ciaadrb);
-#endif
- } else if (currprefs.win32_samplersoundcard >= 0) {
-
- tmp = sampler_getsample ((ciabpra & 4) ? 1 : 0);
-
- } else
-#endif
-
- {
- tmp = handle_parport_joystick (0, ciaaprb, ciaadrb);
- tmp = dongle_cia_read (1, reg, tmp);
-#if DONGLE_DEBUG > 0
- if (notinrom())
- write_log (_T("BFE101 R %02X %s\n"), tmp, debuginfo(0));
-#endif
- }
- if (ciaacrb & 2) {
- int pb7 = 0;
- if (ciaacrb & 4)
- pb7 = ciaacrb & 1;
- tmp &= ~0x80;
- tmp |= pb7 ? 0x80 : 00;
- }
- if (ciaacra & 2) {
- int pb6 = 0;
- if (ciaacra & 4)
- pb6 = ciaacra & 1;
- tmp &= ~0x40;
- tmp |= pb6 ? 0x40 : 00;
- }
- return tmp;
- case 2:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE201 R %02X %s\n"), ciaadra, debuginfo(0));
-#endif
- return ciaadra;
- case 3:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE301 R %02X %s\n"), ciaadrb, debuginfo(0));
-#endif
- return ciaadrb;
- case 4:
- return (uae_u8)((ciaata - ciaata_passed) & 0xff);
- case 5:
- return (uae_u8)((ciaata - ciaata_passed) >> 8);
- case 6:
- return (uae_u8)((ciaatb - ciaatb_passed) & 0xff);
- case 7:
- return (uae_u8)((ciaatb - ciaatb_passed) >> 8);
- case 8:
- if (ciaatlatch) {
- ciaatlatch = 0;
- return (uae_u8)ciaatol;
- } else
- return (uae_u8)ciaatod;
- case 9:
- if (ciaatlatch)
- return (uae_u8)(ciaatol >> 8);
- else
- return (uae_u8)(ciaatod >> 8);
- case 10:
- if (!ciaatlatch) { /* only if not already latched. A1200 confirmed. (TW) */
- /* no latching if ALARM is set */
- if (!(ciaacrb & 0x80))
- ciaatlatch = 1;
- ciaatol = ciaatod;
- }
- return (uae_u8)(ciaatol >> 16);
- case 12:
-#if KB_DEBUG
- write_log (_T("CIAA serial port: %02x %08x\n"), ciaasdr, M68K_GETPC);
-#endif
- return ciaasdr;
- case 13:
- tmp = ciaaicr_reg;
- ciaaicr &= ~ciaaicr_reg;
- ciaaicr_reg = 0;
- RethinkICRA ();
- return tmp;
- case 14:
- return ciaacra;
- case 15:
- return ciaacrb;
- }
- return 0;
-}
-
-static uae_u8 ReadCIAB (unsigned int addr)
-{
- unsigned int tmp;
- int reg = addr & 15;
-
-#if CIAB_DEBUG_R > 0
- if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_R > 1)
- write_log (_T("R_CIAB: bfd%x00 %08X\n"), reg, M68K_GETPC);
-#endif
-
- compute_passed_time ();
-
- switch (reg) {
- case 0:
- tmp = 0;
-#ifdef SERIAL_PORT
- if (currprefs.use_serial)
- tmp = serial_readstatus(ciabdra);
-#endif
-#ifdef PARALLEL_PORT
- if (isprinter () > 0) {
- //tmp |= ciabpra & (0x04 | 0x02 | 0x01);
- tmp &= ~3; // clear BUSY and PAPEROUT
- tmp |= 4; // set SELECT
- } else if (isprinter () < 0) {
- uae_u8 v;
- parallel_direct_read_status (&v);
- tmp |= v & 7;
- } else {
- tmp |= handle_parport_joystick (1, ciabpra, ciabdra);
- }
-#endif
- tmp = dongle_cia_read (1, reg, tmp);
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD000 R %02X %s\n"), tmp, debuginfo(0));
-#endif
- return tmp;
- case 1:
-#ifdef ACTION_REPLAY
- action_replay_ciaread ();
-#endif
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD100 R %02X %s\n"), ciabprb, debuginfo(0));
-#endif
- tmp = ciabprb;
- tmp = dongle_cia_read (1, reg, tmp);
- if (ciabcrb & 2) {
- int pb7 = 0;
- if (ciabcrb & 4)
- pb7 = ciabcrb & 1;
- tmp &= ~0x80;
- tmp |= pb7 ? 0x80 : 00;
- }
- if (ciabcra & 2) {
- int pb6 = 0;
- if (ciabcra & 4)
- pb6 = ciabcra & 1;
- tmp &= ~0x40;
- tmp |= pb6 ? 0x40 : 00;
- }
- return tmp;
- case 2:
- return ciabdra;
- case 3:
- return ciabdrb;
- case 4:
- return (uae_u8)((ciabta - ciabta_passed) & 0xff);
- case 5:
- return (uae_u8)((ciabta - ciabta_passed) >> 8);
- case 6:
- return (uae_u8)((ciabtb - ciabtb_passed) & 0xff);
- case 7:
- return (uae_u8)((ciabtb - ciabtb_passed) >> 8);
- case 8:
- CIAB_tod_check ();
- if (ciabtlatch) {
- ciabtlatch = 0;
- return (uae_u8)ciabtol;
- } else
- return (uae_u8)ciabtod;
- case 9:
- CIAB_tod_check ();
- if (ciabtlatch)
- return (uae_u8)(ciabtol >> 8);
- else
- return (uae_u8)(ciabtod >> 8);
- case 10:
- CIAB_tod_check ();
- if (!ciabtlatch) {
- /* no latching if ALARM is set */
- if (!(ciabcrb & 0x80))
- ciabtlatch = 1;
- ciabtol = ciabtod;
- }
- return (uae_u8)(ciabtol >> 16);
- case 12:
- return ciabsdr;
- case 13:
- tmp = ciabicr_reg;
- ciabicr &= ~ciabicr_reg;
- ciabicr_reg = 0;
- RethinkICRB ();
- return tmp;
- case 14:
- //write_log (_T("CIABCRA READ %d %x\n"), ciabcra, M68K_GETPC);
- return ciabcra;
- case 15:
- return ciabcrb;
- }
- return 0;
-}
-
-static void WriteCIAA (uae_u16 addr, uae_u8 val)
-{
- int reg = addr & 15;
-
-#if CIAA_DEBUG_W > 0
- write_log (_T("W_CIAA: bfe%x01 %02X %08X\n"), reg, val, M68K_GETPC);
-#endif
-#ifdef ACTION_REPLAY
- ar_ciaa[reg] = val;
-#endif
- if (!currprefs.cs_ciaoverlay && oldovl) {
- map_overlay (1);
- oldovl = 0;
- }
- switch (reg) {
- case 0:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE001 W %02X %s\n"), val, debuginfo(0));
-#endif
- ciaapra = (ciaapra & ~0xc3) | (val & 0xc3);
- bfe001_change ();
- handle_cd32_joystick_cia (ciaapra, ciaadra);
- dongle_cia_write (0, reg, val);
-#ifdef AMAX
- if (currprefs.amaxromfile[0])
- amax_bfe001_write (val, ciaadra);
-#endif
- break;
- case 1:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE101 W %02X %s\n"), val, debuginfo(0));
-#endif
- ciaaprb = val;
- dongle_cia_write (0, reg, val);
-#ifdef PARALLEL_PORT
- if (isprinter() > 0) {
- doprinter (val);
- cia_parallelack ();
- } else if (isprinter() < 0) {
- parallel_direct_write_data (val, ciaadrb);
- cia_parallelack ();
-#ifdef ARCADIA
- } else if (arcadia_bios) {
- arcadia_parport (1, ciaaprb, ciaadrb);
-#endif
- }
-#endif
- break;
- case 2:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE201 W %02X %s\n"), val, debuginfo(0));
-#endif
- ciaadra = val;
- dongle_cia_write (0, reg, val);
- bfe001_change ();
- break;
- case 3:
- ciaadrb = val;
- dongle_cia_write (0, reg, val);
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFE301 W %02X %s\n"), val, debuginfo(0));
-#endif
-#ifdef ARCADIA
- if (arcadia_bios)
- arcadia_parport (1, ciaaprb, ciaadrb);
-#endif
- break;
- case 4:
- CIA_update ();
- ciaala = (ciaala & 0xff00) | val;
- CIA_calctimers ();
- break;
- case 5:
- CIA_update ();
- ciaala = (ciaala & 0xff) | (val << 8);
- if ((ciaacra & 1) == 0)
- ciaata = ciaala;
- if (ciaacra & 8) {
- ciaata = ciaala;
- ciaacra |= 1;
- ciaastarta = CIASTARTCYCLESHI;
- }
- CIA_calctimers ();
- break;
- case 6:
- CIA_update ();
- ciaalb = (ciaalb & 0xff00) | val;
- CIA_calctimers ();
- break;
- case 7:
- CIA_update ();
- ciaalb = (ciaalb & 0xff) | (val << 8);
- if ((ciaacrb & 1) == 0)
- ciaatb = ciaalb;
- if (ciaacrb & 8) {
- ciaatb = ciaalb;
- ciaacrb |= 1;
- ciaastartb = CIASTARTCYCLESHI;
- }
- CIA_calctimers ();
- break;
- case 8:
- if (ciaacrb & 0x80) {
- ciaaalarm = (ciaaalarm & ~0xff) | val;
- } else {
- ciaatod = (ciaatod & ~0xff) | val;
- ciaatodon = 1;
- ciaa_checkalarm (false);
- }
- break;
- case 9:
- if (ciaacrb & 0x80) {
- ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8);
- } else {
- ciaatod = (ciaatod & ~0xff00) | (val << 8);
- }
- break;
- case 10:
- if (ciaacrb & 0x80) {
- ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16);
- } else {
- ciaatod = (ciaatod & ~0xff0000) | (val << 16);
- ciaatodon = 0;
- }
- break;
- case 12:
- CIA_update ();
- ciaasdr = val;
- if ((ciaacra & 0x41) == 0x41 && ciaasdr_cnt == 0)
- ciaasdr_cnt = 8 * 2;
-#if KB_DEBUG
- write_log (_T("CIAA serial port write: %02x cnt=%d PC=%08x\n"), ciaasdr, ciaasdr_cnt, M68K_GETPC);
-#endif
- CIA_calctimers ();
- break;
- case 13:
- setclr (&ciaaimask,val);
- break;
- case 14:
- CIA_update ();
- val &= 0x7f; /* bit 7 is unused */
- if ((val & 1) && !(ciaacra & 1))
- ciaastarta = CIASTARTCYCLESCRA;
- if ((val & 0x40) == 0 && (ciaacra & 0x40) != 0) {
- /* todo: check if low to high or high to low only */
- kblostsynccnt = 0;
-#if KB_DEBUG
- write_log (_T("KB_ACK %02x->%02x\n"), ciaacra, val);
-#endif
- }
- ciaacra = val;
- if (ciaacra & 0x10) {
- ciaacra &= ~0x10;
- ciaata = ciaala;
- }
- CIA_calctimers ();
- break;
- case 15:
- CIA_update ();
- if ((val & 1) && !(ciaacrb & 1))
- ciaastartb = CIASTARTCYCLESCRA;
- ciaacrb = val;
- if (ciaacrb & 0x10) {
- ciaacrb &= ~0x10;
- ciaatb = ciaalb;
- }
- CIA_calctimers ();
- break;
- }
-}
-
-static void WriteCIAB (uae_u16 addr, uae_u8 val)
-{
- int reg = addr & 15;
-
-#if CIAB_DEBUG_W > 0
- if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_W > 1)
- write_log (_T("W_CIAB: bfd%x00 %02X %08X\n"), reg, val, M68K_GETPC);
-#endif
-#ifdef ACTION_REPLAY
- ar_ciab[reg] = val;
-#endif
- switch (reg) {
- case 0:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD000 W %02X %s\n"), val, debuginfo(0));
-#endif
- dongle_cia_write (1, reg, val);
- ciabpra = val;
-#ifdef SERIAL_PORT
- if (currprefs.use_serial)
- serial_writestatus(ciabpra, ciabdra);
-#endif
-#ifdef PARALLEL_PORT
- if (isprinter () < 0)
- parallel_direct_write_status (val, ciabdra);
-#endif
- break;
- case 1:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD100 W %02X %s\n"), val, debuginfo(0));
-#endif
- dongle_cia_write (1, reg, val);
- ciabprb = val;
- DISK_select (val);
- break;
- case 2:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD200 W %02X %s\n"), val, debuginfo(0));
-#endif
- dongle_cia_write (1, reg, val);
- ciabdra = val;
-#ifdef SERIAL_PORT
- if (currprefs.use_serial)
- serial_writestatus (ciabpra, ciabdra);
-#endif
- break;
- case 3:
-#if DONGLE_DEBUG > 0
- if (notinrom ())
- write_log (_T("BFD300 W %02X %s\n"), val, debuginfo(0));
-#endif
- dongle_cia_write (1, reg, val);
- ciabdrb = val;
- break;
- case 4:
- CIA_update ();
- ciabla = (ciabla & 0xff00) | val;
- CIA_calctimers ();
- break;
- case 5:
- CIA_update ();
- ciabla = (ciabla & 0xff) | (val << 8);
- if ((ciabcra & 1) == 0)
- ciabta = ciabla;
- if (ciabcra & 8) {
- ciabta = ciabla;
- ciabcra |= 1;
- ciabstarta = CIASTARTCYCLESHI;
- }
- CIA_calctimers ();
- break;
- case 6:
- CIA_update ();
- ciablb = (ciablb & 0xff00) | val;
- CIA_calctimers ();
- break;
- case 7:
- CIA_update ();
- ciablb = (ciablb & 0xff) | (val << 8);
- if ((ciabcrb & 1) == 0)
- ciabtb = ciablb;
- if (ciabcrb & 8) {
- ciabtb = ciablb;
- ciabcrb |= 1;
- ciabstartb = CIASTARTCYCLESHI;
- }
- CIA_calctimers ();
- break;
- case 8:
- CIAB_tod_check ();
- if (ciabcrb & 0x80) {
- ciabalarm = (ciabalarm & ~0xff) | val;
- } else {
- ciabtod = (ciabtod & ~0xff) | val;
- ciabtodon = 1;
- ciab_checkalarm (false, true);
- }
- break;
- case 9:
- CIAB_tod_check ();
- if (ciabcrb & 0x80) {
- ciabalarm = (ciabalarm & ~0xff00) | (val << 8);
- } else {
- ciabtod = (ciabtod & ~0xff00) | (val << 8);
- }
- break;
- case 10:
- CIAB_tod_check ();
- if (ciabcrb & 0x80) {
- ciabalarm = (ciabalarm & ~0xff0000) | (val << 16);
- } else {
- ciabtod = (ciabtod & ~0xff0000) | (val << 16);
- ciabtodon = 0;
- }
- break;
- case 12:
- CIA_update ();
- ciabsdr = val;
- if ((ciabcra & 0x40) == 0)
- ciabsdr_cnt = 0;
- if ((ciabcra & 0x41) == 0x41 && ciabsdr_cnt == 0)
- ciabsdr_cnt = 8 * 2;
- CIA_calctimers ();
- break;
- case 13:
- setclr (&ciabimask, val);
- break;
- case 14:
- CIA_update ();
- val &= 0x7f; /* bit 7 is unused */
- if ((val & 1) && !(ciabcra & 1))
- ciabstarta = CIASTARTCYCLESCRA;
- ciabcra = val;
- if (ciabcra & 0x10) {
- ciabcra &= ~0x10;
- ciabta = ciabla;
- }
- CIA_calctimers ();
- break;
- case 15:
- CIA_update ();
- if ((val & 1) && !(ciabcrb & 1))
- ciabstartb = CIASTARTCYCLESCRA;
- ciabcrb = val;
- if (ciabcrb & 0x10) {
- ciabcrb &= ~0x10;
- ciabtb = ciablb;
- }
- CIA_calctimers ();
- break;
- }
-}
-
-void cia_set_overlay (bool overlay)
-{
- oldovl = overlay;
-}
-
-void CIA_reset (void)
-{
-#ifdef TOD_HACK
- tod_hack_tv = 0;
- tod_hack_tod = 0;
- tod_hack_enabled = 0;
- if (currprefs.tod_hack)
- tod_hack_enabled = TOD_HACK_TIME;
-#endif
-
- kblostsynccnt = 0;
- serbits = 0;
- oldcd32mute = 1;
- oldled = true;
- resetwarning_phase = resetwarning_timer = 0;
- heartbeat_cnt = 0;
- ciab_tod_event_state = 0;
-
- if (!savestate_state) {
- oldovl = true;
- kbstate = 0;
- ciaatlatch = ciabtlatch = 0;
- ciaapra = 0; ciaadra = 0;
- ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0;
- ciaaicr = ciabicr = ciaaimask = ciabimask = 0;
- ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */
- ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF;
- ciaaalarm = ciabalarm = 0;
- ciabpra = 0x8C; ciabdra = 0;
- div10 = 0;
- ciaasdr_cnt = 0; ciaasdr = 0;
- ciabsdr_cnt = 0; ciabsdr = 0;
- ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0;
- CIA_calctimers ();
- DISK_select_set (ciabprb);
- }
- map_overlay (0);
-#ifdef SERIAL_PORT
- if (currprefs.use_serial && !savestate_state)
- serial_dtr_off (); /* Drop DTR at reset */
-#endif
- if (savestate_state) {
- if (currprefs.cs_ciaoverlay) {
- oldovl = true;
- }
- bfe001_change ();
- if (!currprefs.cs_ciaoverlay) {
- map_overlay (oldovl ? 0 : 1);
- }
- }
-#ifdef CD32
- if (!isrestore ()) {
- akiko_reset ();
- if (!akiko_init ())
- currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = 0;
- }
-#endif
-}
-
-void dumpcia (void)
-{
- console_out_f (_T("A: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
- ciaacra, ciaacrb, ciaaicr, ciaaimask, ciaata, ciaala, ciaatb, ciaalb);
- console_out_f (_T("TOD %06x (%06x) ALARM %06x %c%c CYC=%08X\n"),
- ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S', get_cycles ());
- console_out_f (_T("B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)\n"),
- ciabcra, ciabcrb, ciabicr, ciabimask, ciabta, ciabla, ciabtb, ciablb);
- console_out_f (_T("TOD %06x (%06x) ALARM %06x %c%c CLK=%d\n"),
- ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S', div10 / CYCLE_UNIT);
-}
-
-/* CIA memory access */
-
-static uae_u32 REGPARAM3 cia_lget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 cia_wget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 cia_bget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 cia_lgeti (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 cia_wgeti (uaecptr) REGPARAM;
-static void REGPARAM3 cia_lput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 cia_wput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 cia_bput (uaecptr, uae_u32) REGPARAM;
-
-addrbank cia_bank = {
- cia_lget, cia_wget, cia_bget,
- cia_lput, cia_wput, cia_bput,
- default_xlate, default_check, NULL, _T("CIA"),
- cia_lgeti, cia_wgeti, ABFLAG_IO, 0x3f00, 0xbfc000
-};
-
-// Gayle or Fat Gary does not enable CIA /CS lines if both CIAs are selected
-// Old Gary based Amigas enable both CIAs in this situation
-
-STATIC_INLINE bool issinglecia (void)
-{
- return currprefs.cs_ide || currprefs.cs_pcmcia || currprefs.cs_mbdmac;
-}
-STATIC_INLINE bool isgayle (void)
-{
- return currprefs.cs_ide || currprefs.cs_pcmcia;
-}
-
-static void cia_wait_pre (void)
-{
- if (currprefs.cachesize)
- return;
-
-#ifndef CUSTOM_SIMPLE
- int div = (get_cycles () - eventtab[ev_cia].oldcycles) % DIV10;
- int cycles;
-
- if (div >= DIV10 * ECLOCK_DATA_CYCLE / 10) {
- cycles = DIV10 - div;
- cycles += DIV10 * ECLOCK_DATA_CYCLE / 10;
- } else if (div) {
- cycles = DIV10 + DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
- } else {
- cycles = DIV10 * ECLOCK_DATA_CYCLE / 10 - div;
- }
-
- if (cycles) {
- if (currprefs.cpu_cycle_exact)
- x_do_cycles_pre (cycles);
- else
- do_cycles (cycles);
- }
-#endif
-}
-
-static void cia_wait_post (uae_u32 value)
-{
- if (currprefs.cachesize) {
- do_cycles (8 * CYCLE_UNIT /2);
- } else {
- int c = 6 * CYCLE_UNIT / 2;
- if (currprefs.cpu_cycle_exact)
- x_do_cycles_post (c, value);
- else
- do_cycles (c);
- }
-}
-
-static bool isgaylenocia (uaecptr addr)
-{
- // gayle CIA region is only 4096 bytes at 0xbfd000 and 0xbfe000
- if (!isgayle ())
- return true;
- uaecptr mask = addr & 0xf000;
- bool cia = mask == 0xe000 || mask == 0xd000;
- return cia;
-}
-
-static uae_u32 REGPARAM2 cia_bget (uaecptr addr)
-{
- int r = (addr & 0xf00) >> 8;
- uae_u8 v = 0xff;
-
-#ifdef JIT
- special_mem |= S_READ;
-#endif
-
- if (!isgaylenocia (addr))
- return v;
-
- cia_wait_pre ();
- switch ((addr >> 12) & 3) {
- case 0:
- if (!issinglecia ())
- v = (addr & 1) ? ReadCIAA (r) : ReadCIAB (r);
- break;
- case 1:
- v = (addr & 1) ? 0xff : ReadCIAB (r);
- break;
- case 2:
- v = (addr & 1) ? ReadCIAA (r) : 0xff;
- break;
- case 3:
- if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
- v = (addr & 1) ? regs.irc : regs.irc >> 8;
- if (warned > 0 || currprefs.illegal_mem) {
- write_log (_T("cia_bget: unknown CIA address %08X=%02X PC=%08X\n"), addr, v & 0xff, M68K_GETPC);
- warned--;
- }
- break;
- }
- cia_wait_post (v);
-
- return v;
-}
-
-static uae_u32 REGPARAM2 cia_wget (uaecptr addr)
-{
- int r = (addr & 0xf00) >> 8;
- uae_u16 v = 0xffff;
-
-#ifdef JIT
- special_mem |= S_READ;
-#endif
-
- if (!isgaylenocia (addr))
- return v;
-
- cia_wait_pre ();
- switch ((addr >> 12) & 3)
- {
- case 0:
- if (!issinglecia ())
- v = (ReadCIAB (r) << 8) | ReadCIAA (r);
- break;
- case 1:
- v = (ReadCIAB (r) << 8) | 0xff;
- break;
- case 2:
- v = (0xff << 8) | ReadCIAA (r);
- break;
- case 3:
- if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
- v = regs.irc;
- if (warned > 0 || currprefs.illegal_mem) {
- write_log (_T("cia_wget: unknown CIA address %08X=%04X PC=%08X\n"), addr, v & 0xffff, M68K_GETPC);
- warned--;
- }
- break;
- }
- cia_wait_post (v);
- return v;
-}
-
-static uae_u32 REGPARAM2 cia_lget (uaecptr addr)
-{
- uae_u32 v;
- v = cia_wget (addr) << 16;
- v |= cia_wget (addr + 2);
- return v;
-}
-
-static uae_u32 REGPARAM2 cia_wgeti (uaecptr addr)
-{
- if (currprefs.cpu_model >= 68020)
- return dummy_wgeti (addr);
- return cia_wget (addr);
-}
-static uae_u32 REGPARAM2 cia_lgeti (uaecptr addr)
-{
- if (currprefs.cpu_model >= 68020)
- return dummy_lgeti (addr);
- return cia_lget (addr);
-}
-
-static void REGPARAM2 cia_bput (uaecptr addr, uae_u32 value)
-{
- int r = (addr & 0xf00) >> 8;
-
-#ifdef JIT
- special_mem |= S_WRITE;
-#endif
-
- if (!isgaylenocia (addr))
- return;
-
- cia_wait_pre ();
- if (!issinglecia () || (addr & 0x3000) != 0) {
- if ((addr & 0x2000) == 0)
- WriteCIAB (r, value);
- if ((addr & 0x1000) == 0)
- WriteCIAA (r, value);
- if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
- write_log (_T("cia_bput: unknown CIA address %08X=%082X PC=%08X\n"), addr, value & 0xff, M68K_GETPC);
- warned--;
- }
- }
- cia_wait_post (value);
-}
-
-static void REGPARAM2 cia_wput (uaecptr addr, uae_u32 value)
-{
- int r = (addr & 0xf00) >> 8;
-
-#ifdef JIT
- special_mem |= S_WRITE;
-#endif
-
- if (!isgaylenocia (addr))
- return;
-
- cia_wait_pre ();
- if (!issinglecia () || (addr & 0x3000) != 0) {
- if ((addr & 0x2000) == 0)
- WriteCIAB (r, value >> 8);
- if ((addr & 0x1000) == 0)
- WriteCIAA (r, value & 0xff);
- if (((addr & 0x3000) == 0x3000) && (warned > 0 || currprefs.illegal_mem)) {
- write_log (_T("cia_wput: unknown CIA address %08X=%04X %08X\n"), addr, value & 0xffff, M68K_GETPC);
- warned--;
- }
- }
- cia_wait_post (value);
-}
-
-static void REGPARAM2 cia_lput (uaecptr addr, uae_u32 value)
-{
- cia_wput (addr, value >> 16);
- cia_wput (addr + 2, value & 0xffff);
-}
-
-/* battclock memory access */
-
-static uae_u32 REGPARAM3 clock_lget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 clock_wget (uaecptr) REGPARAM;
-static uae_u32 REGPARAM3 clock_bget (uaecptr) REGPARAM;
-static void REGPARAM3 clock_lput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 clock_wput (uaecptr, uae_u32) REGPARAM;
-static void REGPARAM3 clock_bput (uaecptr, uae_u32) REGPARAM;
-
-addrbank clock_bank = {
- clock_lget, clock_wget, clock_bget,
- clock_lput, clock_wput, clock_bput,
- default_xlate, default_check, NULL, _T("Battery backed up clock (none)"),
- dummy_lgeti, dummy_wgeti, ABFLAG_IO, 0x3f, 0xd80000
-};
-
-static unsigned int clock_control_d;
-static unsigned int clock_control_e;
-static unsigned int clock_control_f;
-
-#define RF5C01A_RAM_SIZE 16
-static uae_u8 rtc_memory[RF5C01A_RAM_SIZE], rtc_alarm[RF5C01A_RAM_SIZE];
-
-static uae_u8 getclockreg (int addr, struct tm *ct)
-{
- uae_u8 v = 0;
-
- if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
- switch (addr) {
- case 0x0: v = ct->tm_sec % 10; break;
- case 0x1: v = ct->tm_sec / 10; break;
- case 0x2: v = ct->tm_min % 10; break;
- case 0x3: v = ct->tm_min / 10; break;
- case 0x4: v = ct->tm_hour % 10; break;
- case 0x5:
- if (clock_control_f & 4) {
- v = ct->tm_hour / 10; // 24h
- } else {
- v = (ct->tm_hour % 12) / 10; // 12h
- v |= ct->tm_hour >= 12 ? 4 : 0; // AM/PM bit
- }
- break;
- case 0x6: v = ct->tm_mday % 10; break;
- case 0x7: v = ct->tm_mday / 10; break;
- case 0x8: v = (ct->tm_mon + 1) % 10; break;
- case 0x9: v = (ct->tm_mon + 1) / 10; break;
- case 0xA: v = ct->tm_year % 10; break;
- case 0xB: v = (ct->tm_year / 10) & 0x0f; break;
- case 0xC: v = ct->tm_wday; break;
- case 0xD: v = clock_control_d; break;
- case 0xE: v = clock_control_e; break;
- case 0xF: v = clock_control_f; break;
- }
- } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
- int bank = clock_control_d & 3;
- /* memory access */
- if (bank >= 2 && addr < 0x0d)
- return (rtc_memory[addr] >> ((bank == 2) ? 0 : 4)) & 0x0f;
- /* alarm */
- if (bank == 1 && addr < 0x0d) {
- v = rtc_alarm[addr];
-#if CLOCK_DEBUG
- write_log (_T("CLOCK ALARM R %X: %X\n"), addr, v);
-#endif
- return v;
- }
- switch (addr) {
- case 0x0: v = ct->tm_sec % 10; break;
- case 0x1: v = ct->tm_sec / 10; break;
- case 0x2: v = ct->tm_min % 10; break;
- case 0x3: v = ct->tm_min / 10; break;
- case 0x4: v = ct->tm_hour % 10; break;
- case 0x5:
- if (rtc_alarm[10] & 1)
- v = ct->tm_hour / 10; // 24h
- else
- v = ((ct->tm_hour % 12) / 10) | (ct->tm_hour >= 12 ? 2 : 0); // 12h
- break;
- case 0x6: v = ct->tm_wday; break;
- case 0x7: v = ct->tm_mday % 10; break;
- case 0x8: v = ct->tm_mday / 10; break;
- case 0x9: v = (ct->tm_mon + 1) % 10; break;
- case 0xA: v = (ct->tm_mon + 1) / 10; break;
- case 0xB: v = (ct->tm_year % 100) % 10; break;
- case 0xC: v = (ct->tm_year % 100) / 10; break;
- case 0xD: v = clock_control_d; break;
- /* E and F = write-only, reads as zero */
- case 0xE: v = 0; break;
- case 0xF: v = 0; break;
- }
- }
-#if CLOCK_DEBUG
- write_log(_T("CLOCK R: %X = %X, PC=%08x\n"), addr, v, M68K_GETPC);
-#endif
- return v;
-}
-
-static void write_battclock (void)
-{
- if (!currprefs.rtcfile[0] || currprefs.cs_rtc == 0)
- return;
- struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("wb"));
- if (f) {
- uae_u8 zero[13] = { 0 };
- struct tm *ct;
- time_t t = time (0);
- t += currprefs.cs_rtc_adjust;
- ct = localtime (&t);
- uae_u8 od = clock_control_d;
- if (currprefs.cs_rtc == 2)
- clock_control_d &= ~3;
- for (int i = 0; i < 13; i++) {
- uae_u8 v = getclockreg (i, ct);
- zfile_fwrite (&v, 1, 1, f);
- }
- clock_control_d = od;
- zfile_fwrite (&clock_control_d, 1, 1, f);
- zfile_fwrite (&clock_control_e, 1, 1, f);
- zfile_fwrite (&clock_control_f, 1, 1, f);
- if (currprefs.cs_rtc == 2) {
- zfile_fwrite (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
- zfile_fwrite (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
- }
- zfile_fclose (f);
- }
-}
-
-void rtc_hardreset (void)
-{
- rtc_delayed_write = 0;
- if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
- clock_bank.name = currprefs.cs_rtc == 1 ? _T("Battery backed up clock (MSM6242B)") : _T("Battery backed up clock A2000 (MSM6242B)");
- clock_control_d = 0x1;
- clock_control_e = 0;
- clock_control_f = 0x4; /* 24/12 */
- } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
- clock_bank.name = _T("Battery backed up clock (RF5C01A)");
- clock_control_d = 0x8; /* Timer EN */
- clock_control_e = 0;
- clock_control_f = 0;
- memset (rtc_memory, 0, RF5C01A_RAM_SIZE);
- memset (rtc_alarm, 0, RF5C01A_RAM_SIZE);
- rtc_alarm[10] = 1; /* 24H mode */
- }
- if (currprefs.rtcfile[0]) {
- struct zfile *f = zfile_fopen (currprefs.rtcfile, _T("rb"));
- if (f) {
- uae_u8 empty[13];
- zfile_fread (empty, 13, 1, f);
- zfile_fread (&clock_control_d, 1, 1, f);
- zfile_fread (&clock_control_e, 1, 1, f);
- zfile_fread (&clock_control_f, 1, 1, f);
- zfile_fread (rtc_alarm, RF5C01A_RAM_SIZE, 1, f);
- zfile_fread (rtc_memory, RF5C01A_RAM_SIZE, 1, f);
- zfile_fclose (f);
- }
- }
-}
-
-static uae_u32 REGPARAM2 clock_lget (uaecptr addr)
-{
- return (clock_wget (addr) << 16) | clock_wget (addr + 2);
-}
-
-static uae_u32 REGPARAM2 clock_wget (uaecptr addr)
-{
- return (clock_bget (addr) << 8) | clock_bget (addr + 1);
-}
-
-static uae_u32 REGPARAM2 clock_bget (uaecptr addr)
-{
- time_t t;
- struct tm *ct;
- uae_u8 v = 0;
-
-#ifdef JIT
- special_mem |= S_READ;
-#endif
-#ifdef CDTV
- if (currprefs.cs_cdtvram && addr >= 0xdc8000)
- return cdtv_battram_read (addr);
-#endif
- addr &= 0x3f;
- if ((addr & 3) == 2 || (addr & 3) == 0 || currprefs.cs_rtc == 0) {
- if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible)
- v = regs.irc >> 8;
- return v;
- }
- t = time (0);
- t += currprefs.cs_rtc_adjust;
- ct = localtime (&t);
- addr >>= 2;
- return getclockreg (addr, ct);
-}
-
-static void REGPARAM2 clock_lput (uaecptr addr, uae_u32 value)
-{
- clock_wput (addr, value >> 16);
- clock_wput (addr + 2, value);
-}
-
-static void REGPARAM2 clock_wput (uaecptr addr, uae_u32 value)
-{
- clock_bput (addr, value >> 8);
- clock_bput (addr + 1, value);
-}
-
-static void REGPARAM2 clock_bput (uaecptr addr, uae_u32 value)
-{
-#ifdef JIT
- special_mem |= S_WRITE;
-#endif
-// write_log(_T("W: %x (%x): %x, PC=%08x\n"), addr, (addr & 0xff) >> 2, value & 0xff, M68K_GETPC);
-#ifdef CDTV
- if (currprefs.cs_cdtvram && addr >= 0xdc8000) {
- cdtv_battram_write (addr, value);
- return;
- }
-#endif
- addr &= 0x3f;
- if ((addr & 1) != 1 || currprefs.cs_rtc == 0)
- return;
- addr >>= 2;
- value &= 0x0f;
- if (currprefs.cs_rtc == 1 || currprefs.cs_rtc == 3) { /* MSM6242B */
-#if CLOCK_DEBUG
- write_log (_T("CLOCK W %X: %X\n"), addr, value);
-#endif
- switch (addr)
- {
- case 0xD: clock_control_d = value & (1|8); break;
- case 0xE: clock_control_e = value; break;
- case 0xF: clock_control_f = value; break;
- }
- } else if (currprefs.cs_rtc == 2) { /* RF5C01A */
- int bank = clock_control_d & 3;
- /* memory access */
- if (bank >= 2 && addr < 0x0d) {
- uae_u8 ov = rtc_memory[addr];
- rtc_memory[addr] &= ((bank == 2) ? 0xf0 : 0x0f);
- rtc_memory[addr] |= value << ((bank == 2) ? 0 : 4);
- if (rtc_memory[addr] != ov)
- rtc_delayed_write = -1;
- return;
- }
- /* alarm */
- if (bank == 1 && addr < 0x0d) {
-#if CLOCK_DEBUG
- write_log (_T("CLOCK ALARM W %X: %X\n"), addr, value);
-#endif
- uae_u8 ov = rtc_alarm[addr];
- rtc_alarm[addr] = value;
- rtc_alarm[0] = rtc_alarm[1] = rtc_alarm[9] = rtc_alarm[12] = 0;
- rtc_alarm[3] &= ~0x8;
- rtc_alarm[5] &= ~0xc;
- rtc_alarm[6] &= ~0x8;
- rtc_alarm[8] &= ~0xc;
- rtc_alarm[10] &= ~0xe;
- rtc_alarm[11] &= ~0xc;
- if (rtc_alarm[addr] != ov)
- rtc_delayed_write = -1;
- return;
- }
-#if CLOCK_DEBUG
- write_log (_T("CLOCK W %X: %X\n"), addr, value);
-#endif
- switch (addr)
- {
- case 0xD: clock_control_d = value; break;
- case 0xE: clock_control_e = value; break;
- case 0xF: clock_control_f = value; break;
- }
- }
- rtc_delayed_write = -1;
-}
-
-#ifdef SAVESTATE
-
-/* CIA-A and CIA-B save/restore code */
-
-static void save_cia_prepare (void)
-{
- CIA_update_check ();
- CIA_calctimers ();
- compute_passed_time ();
-}
-
-void restore_cia_start (void)
-{
- /* Fixes very old statefiles without keyboard state */
- kbstate = 3;
- setcapslockstate (0);
- kblostsynccnt = 0;
-}
-
-void restore_cia_finish (void)
-{
- eventtab[ev_cia].oldcycles = get_cycles ();
- CIA_update ();
- CIA_calctimers ();
- compute_passed_time ();
- eventtab[ev_cia].oldcycles -= div10;
- //dumpcia ();
- DISK_select_set (ciabprb);
-}
-
-uae_u8 *restore_cia (int num, uae_u8 *src)
-{
- uae_u8 b;
- uae_u16 w;
- uae_u32 l;
-
- /* CIA registers */
- b = restore_u8 (); /* 0 PRA */
- if (num) ciabpra = b; else ciaapra = b;
- b = restore_u8 (); /* 1 PRB */
- if (num) ciabprb = b; else ciaaprb = b;
- b = restore_u8 (); /* 2 DDRA */
- if (num) ciabdra = b; else ciaadra = b;
- b = restore_u8 (); /* 3 DDRB */
- if (num) ciabdrb = b; else ciaadrb = b;
- w = restore_u16 (); /* 4 TA */
- if (num) ciabta = w; else ciaata = w;
- w = restore_u16 (); /* 6 TB */
- if (num) ciabtb = w; else ciaatb = w;
- l = restore_u8 (); /* 8/9/A TOD */
- l |= restore_u8 () << 8;
- l |= restore_u8 () << 16;
- if (num) ciabtod = l; else ciaatod = l;
- restore_u8 (); /* B unused */
- b = restore_u8 (); /* C SDR */
- if (num) ciabsdr = b; else ciaasdr = b;
- b = restore_u8 (); /* D ICR INFORMATION (not mask!) */
- if (num) ciabicr = b; else ciaaicr = b;
- b = restore_u8 (); /* E CRA */
- if (num) ciabcra = b; else ciaacra = b;
- b = restore_u8 (); /* F CRB */
- if (num) ciabcrb = b; else ciaacrb = b;
-
- /* CIA internal data */
-
- b = restore_u8 (); /* ICR MASK */
- if (num) ciabimask = b; else ciaaimask = b;
- w = restore_u8 (); /* timer A latch */
- w |= restore_u8 () << 8;
- if (num) ciabla = w; else ciaala = w;
- w = restore_u8 (); /* timer B latch */
- w |= restore_u8 () << 8;
- if (num) ciablb = w; else ciaalb = w;
- w = restore_u8 (); /* TOD latched value */
- w |= restore_u8 () << 8;
- w |= restore_u8 () << 16;
- if (num) ciabtol = w; else ciaatol = w;
- l = restore_u8 (); /* alarm */
- l |= restore_u8 () << 8;
- l |= restore_u8 () << 16;
- if (num) ciabalarm = l; else ciaaalarm = l;
- b = restore_u8 ();
- if (num) ciabtlatch = b & 1; else ciaatlatch = b & 1; /* is TOD latched? */
- if (num) ciabtodon = b & 2; else ciaatodon = b & 2; /* is TOD stopped? */
- b = restore_u8 ();
- if (num)
- div10 = CYCLE_UNIT * b;
- b = restore_u8 ();
- if (num) ciabsdr_cnt = b; else ciaasdr_cnt = b;
- return src;
-}
-
-uae_u8 *save_cia (int num, int *len, uae_u8 *dstptr)
-{
- uae_u8 *dstbak,*dst, b;
- uae_u16 t;
-
- if (dstptr)
- dstbak = dst = dstptr;
- else
- dstbak = dst = xmalloc (uae_u8, 1000);
-
- save_cia_prepare ();
-
- /* CIA registers */
-
- b = num ? ciabpra : ciaapra; /* 0 PRA */
- save_u8 (b);
- b = num ? ciabprb : ciaaprb; /* 1 PRB */
- save_u8 (b);
- b = num ? ciabdra : ciaadra; /* 2 DDRA */
- save_u8 (b);
- b = num ? ciabdrb : ciaadrb; /* 3 DDRB */
- save_u8 (b);
- t = (num ? ciabta - ciabta_passed : ciaata - ciaata_passed);/* 4 TA */
- save_u16 (t);
- t = (num ? ciabtb - ciabtb_passed : ciaatb - ciaatb_passed);/* 6 TB */
- save_u16 (t);
- b = (num ? ciabtod : ciaatod); /* 8 TODL */
- save_u8 (b);
- b = (num ? ciabtod >> 8 : ciaatod >> 8); /* 9 TODM */
- save_u8 (b);
- b = (num ? ciabtod >> 16 : ciaatod >> 16); /* A TODH */
- save_u8 (b);
- save_u8 (0); /* B unused */
- b = num ? ciabsdr : ciaasdr; /* C SDR */
- save_u8 (b);
- b = num ? ciabicr : ciaaicr; /* D ICR INFORMATION (not mask!) */
- save_u8 (b);
- b = num ? ciabcra : ciaacra; /* E CRA */
- save_u8 (b);
- b = num ? ciabcrb : ciaacrb; /* F CRB */
- save_u8 (b);
-
- /* CIA internal data */
-
- save_u8 (num ? ciabimask : ciaaimask); /* ICR */
- b = (num ? ciabla : ciaala); /* timer A latch LO */
- save_u8 (b);
- b = (num ? ciabla >> 8 : ciaala >> 8); /* timer A latch HI */
- save_u8 (b);
- b = (num ? ciablb : ciaalb); /* timer B latch LO */
- save_u8 (b);
- b = (num ? ciablb >> 8 : ciaalb >> 8); /* timer B latch HI */
- save_u8 (b);
- b = (num ? ciabtol : ciaatol); /* latched TOD LO */
- save_u8 (b);
- b = (num ? ciabtol >> 8 : ciaatol >> 8); /* latched TOD MED */
- save_u8 (b);
- b = (num ? ciabtol >> 16 : ciaatol >> 16); /* latched TOD HI */
- save_u8 (b);
- b = (num ? ciabalarm : ciaaalarm); /* alarm LO */
- save_u8 (b);
- b = (num ? ciabalarm >> 8 : ciaaalarm >> 8);/* alarm MED */
- save_u8 (b);
- b = (num ? ciabalarm >> 16 : ciaaalarm >> 16); /* alarm HI */
- save_u8 (b);
- b = 0;
- if (num)
- b |= ciabtlatch ? 1 : 0;
- else
- b |= ciaatlatch ? 1 : 0; /* is TOD latched? */
- if (num)
- b |= ciabtodon ? 2 : 0;
- else
- b |= ciaatodon ? 2 : 0; /* TOD stopped? */
- save_u8 (b);
- save_u8 (num ? div10 / CYCLE_UNIT : 0);
- save_u8 (num ? ciabsdr_cnt : ciaasdr_cnt);
- *len = dst - dstbak;
- return dstbak;
-}
-
-uae_u8 *save_keyboard (int *len, uae_u8 *dstptr)
-{
- uae_u8 *dst, *dstbak;
- if (dstptr)
- dstbak = dst = dstptr;
- else
- dstbak = dst = xmalloc (uae_u8, 4 + 4 + 1 + 1 + 1 + 1 + 1 + 2);
- save_u32 (getcapslockstate () ? 1 : 0);
- save_u32 (1);
- save_u8 (kbstate);
- save_u8 (0);
- save_u8 (0);
- save_u8 (0);
- save_u8 (kbcode);
- save_u16 (kblostsynccnt);
- *len = dst - dstbak;
- return dstbak;
-}
-
-uae_u8 *restore_keyboard (uae_u8 *src)
-{
- setcapslockstate (restore_u32 () & 1);
- uae_u32 v = restore_u32 ();
- kbstate = restore_u8 ();
- restore_u8 ();
- restore_u8 ();
- restore_u8 ();
- kbcode = restore_u8 ();
- kblostsynccnt = restore_u16 ();
- if (!(v & 1)) {
- kbstate = 3;
- kblostsynccnt = 0;
- }
- return src;
-}
-
-#endif /* SAVESTATE */