- [NEW] [zx_disk] RECALIBRATE command (0x07)

- [NEW] [zx_disk] SENSE INTERRUPT STATUS command (0x08)
- [ONGOING] [zx_disk] SEEK command (0x0f)
This commit is contained in:
2025-08-05 17:05:32 +02:00
parent 40c825cdb9
commit 90b34749d1

View File

@@ -7,9 +7,15 @@
#define ZX_FDC_MODE_EXECUTION 2
#define ZX_FDC_MODE_RESULT 3
#define ZX_FDC_DATA_DIRECTION_INPUT 0x00
#define ZX_FDC_DATA_DIRECTION_OUTPUT 0x40
#define ZX_FDC_COMMAND_MASK 0x1F
#define ZX_FDC_COMMAND_SPECIFY 0x03
#define ZX_FDC_COMMAND_SENSE_DRIVE_STATUS 0x04
#define ZX_FDC_COMMAND_RECALIBRATE 0x07
#define ZX_FDC_COMMAND_SENSE_INTERRUPT_STATUS 0x08
#define ZX_FDC_COMMAND_SEEK 0x0F
#define ZX_FDC_MAIN_DRIVE0_BUSY 1
#define ZX_FDC_MAIN_DRIVE1_BUSY 2
@@ -25,17 +31,14 @@ namespace zx_disk
{
uint8_t mode = ZX_FDC_MODE_IDLE;
uint8_t call_count = 0;
uint8_t main_status_register = 0x80;
uint8_t st0 = 0x00;
uint8_t st1 = 0x00;
uint8_t st2 = 0x00;
uint8_t st3 = 0x00;
//uint8_t data_direction = 0x00; // 0x40
uint8_t fdd0busy = 0;
uint8_t srt, hlt, hut, nd;
bool seeking = false;
uint8_t current_head = 0;
uint8_t current_drive = 0;
uint8_t current_track = 0;
int zx_fdc_main_status_port_in(int port);
int zx_fdc_data_port_in(int port);
@@ -52,21 +55,50 @@ namespace zx_disk
}
uint8_t main_status_register()
{
const uint8_t val = (fdd0busy) |
((mode==ZX_FDC_MODE_IDLE) ? 0x00 : 0x10) |
((mode==ZX_FDC_MODE_EXECUTION) ? 0x20 : 0x00) |
((mode==ZX_FDC_MODE_RESULT) ? 0x40 : 0x00) |
(0x80);
return val;
}
int zx_fdc_main_status_port_in(int port)
{
printf("FDC port 0x2ffd IN\n");
return main_status_register;
return main_status_register();
}
uint8_t ST0()
{
return current_drive | (current_head<<2) | (seeking ? 0x20 : 0x00) | (fdd0busy ? 0x00 : 0x40);
}
uint8_t ST3()
{
return current_drive | (current_head<<2) | 0x38; // ST3
}
void start_command(uint8_t command);
uint8_t (*process_current_command)(uint8_t) = nullptr;
uint8_t process_command_unknown(uint8_t command);
uint8_t process_command_specify(uint8_t command);
uint8_t process_command_sense_drive_status(uint8_t command);
uint8_t process_command_recalibrate(uint8_t command);
uint8_t process_command_sense_interrupt_status(uint8_t command);
uint8_t process_command_seek(uint8_t command);
int zx_fdc_data_port_in(int port)
{
printf("FDC port 0x3ffd IN\n");
if (mode == ZX_FDC_MODE_COMMAND) {
printf("IGNORED!\n");
return 0;
}
if (process_current_command) return process_current_command(0);
return 0;
}
@@ -74,6 +106,10 @@ namespace zx_disk
void zx_fdc_data_port_out(int port, int val)
{
printf("FDC port 0x3ffd OUT: 0x%02x\n", val);
if (mode == ZX_FDC_MODE_RESULT) {
printf("IGNORED!\n");
return;
}
if (process_current_command)
process_current_command(val);
else
@@ -82,7 +118,8 @@ namespace zx_disk
void start_command(uint8_t command)
{
main_status_register |= ZX_FDC_MAIN_BUSY;
if ((fdd0busy) && (command != ZX_FDC_COMMAND_SENSE_INTERRUPT_STATUS)) return;
mode = ZX_FDC_MODE_COMMAND;
call_count = 1;
switch(command)
@@ -93,14 +130,42 @@ namespace zx_disk
case ZX_FDC_COMMAND_SENSE_DRIVE_STATUS:
process_current_command = process_command_sense_drive_status;
break;
case ZX_FDC_COMMAND_RECALIBRATE:
process_current_command = process_command_recalibrate;
fdd0busy = 1;
break;
case ZX_FDC_COMMAND_SENSE_INTERRUPT_STATUS:
process_current_command = process_command_sense_interrupt_status;
mode = ZX_FDC_MODE_RESULT;
call_count = 0;
break;
case ZX_FDC_COMMAND_SEEK:
process_current_command = process_command_seek;
fdd0busy = 1;
seeking = true;
break;
default:
{
process_current_command = process_command_unknown;
mode = ZX_FDC_MODE_RESULT;
call_count = 0;
}
}
}
// ===================================================================
// FDC COMMAND: UNKNOWN
// ===================================================================
uint8_t process_command_unknown(uint8_t command)
{
process_current_command = nullptr;
mode = ZX_FDC_MODE_IDLE;
const uint8_t val = ST0();
printf("--> (returning 0x%02x)\n", val);
return val;
}
// ===================================================================
// FDC COMMAND: SPECIFY (0x03)
// ===================================================================
@@ -118,7 +183,6 @@ namespace zx_disk
call_count=0;
process_current_command = nullptr;
mode = ZX_FDC_MODE_IDLE;
main_status_register &= ~ZX_FDC_MAIN_BUSY;
break;
}
return 0;
@@ -138,12 +202,82 @@ namespace zx_disk
mode = ZX_FDC_MODE_RESULT;
break;
case ZX_FDC_MODE_RESULT:
{
process_current_command = nullptr;
mode = ZX_FDC_MODE_IDLE;
main_status_register &= ~ZX_FDC_MAIN_BUSY;
return current_drive | (current_head<<2) | 0x38; // ST3
const uint8_t val = ST3();
printf("--> (returning 0x%02x)\n", val);
return val;
}
}
return 0;
}
// ===================================================================
// FDC COMMAND: RECALIBRATE (0x07)
// ===================================================================
uint8_t process_command_recalibrate(uint8_t command)
{
switch (mode)
{
case ZX_FDC_MODE_COMMAND:
current_drive = command & 0x3;
call_count = 0;
current_track = 0;
process_current_command = nullptr;
mode = ZX_FDC_MODE_IDLE;
break;
}
return 0;
}
// ===================================================================
// FDC COMMAND: SENSE INTERRUPT STATUS (0x08)
// ===================================================================
uint8_t process_command_sense_interrupt_status(uint8_t command)
{
switch (call_count)
{
case 0:
{
call_count++;
const uint8_t val = ST0();
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 1:
process_current_command = nullptr;
fdd0busy = 0;
seeking = false;
call_count = 0;
mode = ZX_FDC_MODE_IDLE;
printf("--> (returning 0x%02x)\n", current_track);
return current_track;
}
return 0;
}
// ===================================================================
// FDC COMMAND: SEEK (0x0F)
// ===================================================================
uint8_t process_command_seek(uint8_t command)
{
switch (call_count)
{
case 1:
{
current_head = (command & 0x4)>>2;
current_drive = command & 0x3;
call_count++;
break;
}
case 2:
current_track = command;
process_current_command = nullptr;
call_count = 0;
mode = ZX_FDC_MODE_IDLE;
break;
}
return 0;
}
}