- [NEW] [zx_disk] Càrrega d'arxius .DSK (nomes extended, hardcoded)

- [NEW] [zx_disk] READ ID command (0x0A)
This commit is contained in:
2025-08-06 20:02:54 +02:00
parent 6791916f75
commit 8b36807e3b
2 changed files with 172 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
#include "zx_disk.h"
#include "z80.h"
#include <stdio.h>
#include <stdlib.h>
#define ZX_FDC_MODE_IDLE 0
#define ZX_FDC_MODE_COMMAND 1
@@ -16,6 +17,7 @@
#define ZX_FDC_COMMAND_RECALIBRATE 0x07
#define ZX_FDC_COMMAND_SENSE_INTERRUPT_STATUS 0x08
#define ZX_FDC_COMMAND_SEEK 0x0F
#define ZX_FDC_COMMAND_READ_ID 0x0A
#define ZX_FDC_MAIN_DRIVE0_BUSY 1
#define ZX_FDC_MAIN_DRIVE1_BUSY 2
@@ -29,16 +31,46 @@
namespace zx_disk
{
struct sector_t
{
uint8_t id { 0 };
uint8_t size { 0 };
uint8_t st1 { 0 };
uint8_t st2 { 0 };
uint16_t data_length{ 0 };
uint8_t *data { nullptr };
};
struct track_t
{
uint8_t size { 0 };
uint8_t sector_size { 0 };
uint8_t num_sectors { 0 };
uint8_t filler_byte { 0x35 };
sector_t *sectors { nullptr };
};
struct disk_t
{
uint8_t num_tracks { 0 };
uint8_t num_sides { 0 };
track_t *tracks { nullptr };
};
disk_t disk;
uint8_t mode = ZX_FDC_MODE_IDLE;
uint8_t call_count = 0;
//uint8_t data_direction = 0x00; // 0x40
uint8_t fdd0busy = 0;
bool command_success = false;
uint8_t srt, hlt, hut, nd;
bool seeking = false;
uint8_t current_head = 0;
uint8_t current_drive = 0;
uint8_t current_track = 0;
uint8_t current_sector = 0;
int zx_fdc_main_status_port_in(int port);
int zx_fdc_data_port_in(int port);
@@ -48,6 +80,7 @@ namespace zx_disk
{
z80::connect_port(0x2ffd, 0xf002, zx_fdc_main_status_port_in, nullptr);
z80::connect_port(0x3ffd, 0xf002, zx_fdc_data_port_in, zx_fdc_data_port_out);
load("goldenaxe1.dsk");
}
void reset()
@@ -55,6 +88,63 @@ namespace zx_disk
}
void load(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (!f) return;
fseek(f, 0, SEEK_END);
const int file_size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *buffer = (uint8_t*)malloc(file_size);
fread(buffer, file_size, 1, f);
fclose(f);
if (disk.tracks) {
for (int i=0; i<disk.num_tracks; ++i) {
for (int j=0; j<disk.tracks[i].num_sectors; ++j) {
free(disk.tracks[i].sectors[i].data);
}
free(disk.tracks[i].sectors);
}
free(disk.tracks);
}
// Hardcoded to read extended disks. Also, no security checks at all. Fuck the police.
disk.num_tracks = buffer[0x30];
disk.num_sides = buffer[0x31];
disk.tracks = (track_t*)malloc(disk.num_tracks*sizeof(track_t));
for (int i=0; i<disk.num_tracks; ++i) disk.tracks[i].size = buffer[0x34+i];
uint32_t pos = 0x100;
for (int i=0; i<disk.num_tracks; ++i)
{
track_t &track = disk.tracks[i];
track.sector_size = buffer[pos+0x14];
track.num_sectors = buffer[pos+0x15];
track.filler_byte = buffer[pos+0x17];
track.sectors = (sector_t*)malloc(track.num_sectors*sizeof(sector_t));
pos += 0x18;
for (int j=0; j<track.num_sectors; ++j)
{
sector_t &sector = track.sectors[j];
sector.id = buffer[pos+0x02];
sector.size = buffer[pos+0x03];
sector.st1 = buffer[pos+0x04];
sector.st2 = buffer[pos+0x05];
sector.data_length = buffer[pos+0x06] + (buffer[pos+0x07]<<8);
if (sector.data_length==0) sector.data_length = sector.size<<8;
pos += 8;
}
if (pos&0xff) pos = (pos & 0xffffff00) + 0x100;
for (int j=0; j<track.num_sectors; ++j)
{
sector_t &sector = track.sectors[j];
const int size = sector.size<<8;
sector.data = (uint8_t*)malloc(size);
for (int k=0; k<size; ++k) sector.data[k] = buffer[pos++];
}
}
}
uint8_t main_status_register()
{
const uint8_t val = (fdd0busy) |
@@ -93,6 +183,7 @@ namespace zx_disk
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);
uint8_t process_command_read_id(uint8_t command);
int zx_fdc_data_port_in(int port)
{
@@ -146,6 +237,9 @@ namespace zx_disk
fdd0busy = 1;
seeking = true;
break;
case ZX_FDC_COMMAND_READ_ID:
process_current_command = process_command_read_id;
break;
default:
{
process_current_command = process_command_unknown;
@@ -283,4 +377,81 @@ namespace zx_disk
}
return 0;
}
// ===================================================================
// FDC COMMAND: READ ID (0x0A)
// ===================================================================
uint8_t process_command_read_id(uint8_t command)
{
switch (mode)
{
case ZX_FDC_MODE_COMMAND:
current_head = (command & 0x4)>>2;
current_drive = command & 0x3;
call_count = 0;
current_sector = 0;
mode = ZX_FDC_MODE_RESULT;
break;
case ZX_FDC_MODE_RESULT:
{
switch (call_count)
{
case 0:
{
call_count++;
fdd0busy = 1;
const uint8_t val = ST0();
fdd0busy = 0;
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 1:
{
call_count++;
const uint8_t val = 0x00; // ST1
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 2:
{
call_count++;
const uint8_t val = 0x00; // ST2
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 3:
{
call_count++;
const uint8_t val = current_track+1;
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 4:
{
call_count++;
const uint8_t val = current_head;
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 5:
{
call_count++;
const uint8_t val = current_sector+1;
printf("--> (returning 0x%02x)\n", val);
return val;
}
case 6:
{
call_count = 0;
process_current_command = nullptr;
mode = ZX_FDC_MODE_IDLE;
const uint8_t val = disk.tracks[current_track].sectors[current_sector].size;
printf("--> (returning 0x%02x)\n", val);
return val;
}
}
}
}
return 0;
}
}