// // disk.c // Steve ][ // // Created by Tamas Rudnai on 2/15/20. // Copyright © 2019, 2020 Tamas Rudnai. All rights reserved. // // This file is part of Steve ][ -- The Apple ][ Emulator. // // Steve ][ is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Steve ][ is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Steve ][. If not, see . // #include #include "disk.h" #include "6502.h" #include "common.h" #include "woz.h" #include "speaker.h" disk_t disk = { { 0, 0, 0 }, // phase 0, // clk_last_access 0, // clk_since_last_read 0, // drive number }; const int diskAccelerator_frames = 2; int diskAccelerator_count = 0; int diskAccelerator_speed = 25; // if less than actual CPU speed means no acceleration int diskAccelerator_enabled = 0; int disk_sfx_enabled = 1; // motor position from the magnet state // -1 means invalid, not supported const int magnet_to_Poistion[16] = { // 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 -1, 0, 2, 1, 4, -1, 3, -1, 6, 7, -1, -1, 5, -1, -1, -1 }; const int position_to_direction[8][8] = { // N NE E SE S SW W NW // 0 1 2 3 4 5 6 7 { 0, 1, 2, 3, 0, -3, -2, -1 }, // 0 N { -1, 0, 1, 2, 3, 0, -3, -2 }, // 1 NE { -2, -1, 0, 1, 2, 3, 0, -3 }, // 2 E { -3, -2, -1, 0, 1, 2, 3, 0 }, // 3 SE { 0, -3, -2, -1, 0, 1, 2, 3 }, // 4 S { 3, 0, -3, -2, -1, 0, 1, 2 }, // 5 SW { 2, 3, 0, -3, -2, -1, 0, 1 }, // 6 W { 1, 2, 3, 0, -3, -2, -1, 0 }, // 7 NW }; const uint8_t phy2log_dos33[16] = { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 }; const uint8_t log2phy_dos33[16] = { 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15 }; const uint8_t phy2log_pascal[16] = { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; const uint8_t log2phy_pascal[16] = { 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 }; const uint8_t phy2log_cpm[16] = { 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5 }; const uint8_t log2phy_cpm[16] = { 0, 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13 }; void disk_accelerator_speedup() { if ( ( diskAccelerator_enabled ) && ( FRAME(diskAccelerator_speed) >= clk_6502_per_frm ) ) { clk_6502_per_frm = clk_6502_per_frm_max = FRAME(diskAccelerator_speed); // clk_6502_per_frm_diskAccelerator; diskAccelerator_count = diskAccelerator_frames; } } void disk_phase() { int position = magnet_to_Poistion[disk.phase.magnet]; if ( position >= 0 ) { int lastPosition = disk.phase.count & 7; int direction = position_to_direction[lastPosition][position]; disk.phase.count += direction; if( disk.phase.count < minDiskPhaseNum ) { disk.phase.count = minDiskPhaseNum; spkr_play_disk_ioerr(); } else if( disk.phase.count > maxDiskPhaseNum ) { disk.phase.count = maxDiskPhaseNum; spkr_play_disk_ioerr(); } else { spkr_play_disk_arm(); } // TODO: Add track positioning sfx // spkr_toggle(); // printf("Head Position: p:%d d:%d l:%d: ph:%u)\n", position, direction, lastPosition, disk.phase.count); disk.clk_last_access = m6502.clktime; disk_accelerator_speedup(); } else { // invalid magnet config } // printf("\n"); } void disk_phase_on( uint8_t currentMagnet ) { disk.phase.magnet |= 1 << currentMagnet; disk_phase(); } void disk_phase_off( uint8_t currentMagnet ) { disk.phase.magnet &= ~(1 << currentMagnet); disk_phase(); } void disk_motor_on() { spkr_play_disk_motor(); spkr_stop_disk_motor( -1 ); } void disk_motor_off() { spkr_stop_disk_motor( 3 * fps ); // 3 second delay } uint8_t disk_read() { dbgPrintf("io_DISK_READ (S%u)\n", 6); disk.clk_last_access = m6502.clktime; disk_accelerator_speedup(); // Debug disk read // spkr_toggle(); if ( disk.drive ) { return rand(); } return woz_read(); }