From 1aa6c47f8ef49ae5feb5f2e9c5caed0b99d1c54b Mon Sep 17 00:00:00 2001
From: folkert van heusden <mail@vanheusden.com>
Date: Thu, 18 Apr 2024 08:46:27 +0200
Subject: [PATCH] code clean-up

---
 rl02.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++--------------
 rl02.h   | 13 +++++++---
 2 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/rl02.cpp b/rl02.cpp
index e878a29..89aead2 100644
--- a/rl02.cpp
+++ b/rl02.cpp
@@ -1,4 +1,4 @@
-// (C) 2018-2023 by Folkert van Heusden
+// (C) 2018-2024 by Folkert van Heusden
 // Released under MIT license
 
 #include <errno.h>
@@ -13,9 +13,6 @@
 #include "utils.h"
 
 
-constexpr int sectors_per_track = 40;
-constexpr int bytes_per_sector  = 256;
-
 static const char * const regnames[] = { 
 	"control status",
 	"bus address   ",
@@ -43,6 +40,10 @@ void rl02::reset()
 {
 	memset(registers,   0x00, sizeof registers);
 	memset(xfer_buffer, 0x00, sizeof xfer_buffer);
+
+	track  = 0;
+	head   = 0;
+	sector = 0;
 }
 
 uint8_t rl02::readByte(const uint16_t addr)
@@ -102,13 +103,9 @@ void rl02::update_bus_address(const uint32_t a)
 	registers[(RL02_CSR - RL02_BASE) / 2] |= ((a >> 16) & 3) << 4;
 }
 
-uint32_t rl02::calcOffset(const uint16_t da) const
+uint32_t rl02::calcOffset() const
 {
-	int       sector = da & 63;
-	int       track  = (da >> 6) & 1023;
-	uint32_t  offset = (sectors_per_track * track + sector) * bytes_per_sector;
-
-	return offset;
+	return (rl02_sectors_per_track * track * 2 + head * rl02_sectors_per_track + sector) * rl02_bytes_per_sector;
 }
 
 void rl02::writeWord(const uint16_t addr, uint16_t v)
@@ -126,22 +123,49 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
 
 		DOLOG(debug, false, "RL02 set command %d, exec: %d", command, do_exec);
 
-		uint32_t disk_offset = calcOffset(registers[(RL02_DAR - RL02_BASE) / 2] & ~1);
-		int      device      = 0;  // TODO
+		int           device  = 0;  // TODO
+
+		bool          do_int  = false;
+
+		*disk_read_acitivity = true;
 
 		if (command == 2) {  // get status
 			registers[(RL02_MPR - RL02_BASE) / 2] = 0;
 		}
-		else if (command == 6 || command == 7) {  // read data / read data without header check
-			*disk_read_acitivity = true;
+		else if (command == 3) {  // seek
+			uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2];
 
-			uint32_t temp_disk_offset = disk_offset;
+			int cylinder_count = (((temp >> 7) & 255) + 1) * (temp & 4 ? 1 : -1);
+
+			int32_t new_track = 0;  // when bit 4 is set, a reset is performed
+
+			if ((temp & 8) == 0) {
+				new_track = track + cylinder_count;
+
+				if (new_track < 0)
+					new_track = 0;
+				else if (new_track >= rl02_track_count)
+					new_track = rl02_track_count;
+			}
+
+			DOLOG(debug, false, "RL02: seek from cylinder %d to %d (distance: %d, DAR: %06o)", track, new_track, cylinder_count, temp);
+			track  = new_track;
+
+			do_int = true;
+		}
+		else if (command == 6 || command == 7) {  // read data / read data without header check
+			uint16_t temp = registers[(RL02_DAR - RL02_BASE) / 2];
+			sector = temp & 63;
+			head   = !!(temp & 64);
+			track  = temp >> 7;
+
+			uint32_t temp_disk_offset = calcOffset();
 
 			uint32_t memory_address   = get_bus_address();
 
 			uint32_t count            = (65536l - registers[(RL02_MPR - RL02_BASE) / 2]) * 2;
 
-			DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct)", count, disk_offset, memory_address);
+			DOLOG(debug, false, "RL02 read %d bytes (dec) from %d (dec) to %06o (oct) [cylinder: %d, head: %d, sector: %d]", count, temp_disk_offset, memory_address, track, head, sector);
 
 			while(count > 0) {
 				uint32_t cur = std::min(uint32_t(sizeof xfer_buffer), count);
@@ -160,15 +184,31 @@ void rl02::writeWord(const uint16_t addr, uint16_t v)
 				temp_disk_offset += cur;
 
 				count -= cur;
+
+				sector++;
+				if (sector >= rl02_sectors_per_track) {
+					sector = 0;
+
+					head++;
+					if (head >= 2) {
+						head = 0;
+
+						track++;
+					}
+				}
 			}
 
+			do_int = true;
+		}
+
+		if (do_int) {
 			if (registers[(RL02_CSR - RL02_BASE) / 2] & 64) {  // interrupt enable?
 				DOLOG(debug, false, "RL02 triggering interrupt");
 
 				b->getCpu()->queue_interrupt(4, 0160);
 			}
-
-			*disk_read_acitivity = false;
 		}
+
+		*disk_read_acitivity = false;
 	}
 }
diff --git a/rl02.h b/rl02.h
index 06dc553..5bcd9bd 100644
--- a/rl02.h
+++ b/rl02.h
@@ -1,4 +1,4 @@
-// (C) 2018-2023 by Folkert van Heusden
+// (C) 2018-2024 by Folkert van Heusden
 // Released under MIT license
 
 #pragma once
@@ -19,6 +19,10 @@
 #define RL02_BASE  RL02_CSR
 #define RL02_END  (RL02_MPR + 2)
 
+constexpr const int rl02_sectors_per_track = 40;
+constexpr const int rl02_track_count       = 512;
+constexpr const int rl02_bytes_per_sector  = 256;
+
 class bus;
 
 class rl02
@@ -26,7 +30,10 @@ class rl02
 private:
 	bus      *const b;
 	uint16_t        registers[4];
-	uint8_t         xfer_buffer[512];
+	uint8_t         xfer_buffer[rl02_bytes_per_sector];
+	int16_t         track  { 0 };
+	uint8_t         head   { 0 };
+	uint8_t         sector { 0 };
 	std::vector<disk_backend *> fhs;
 
 	std::atomic_bool *const disk_read_acitivity  { nullptr };
@@ -34,7 +41,7 @@ private:
 
 	uint32_t get_bus_address() const;
 	void     update_bus_address(const uint32_t a);
-	uint32_t calcOffset(uint16_t) const;
+	uint32_t calcOffset() const;
 
 public:
 	rl02(const std::vector<disk_backend *> & files, bus *const b, std::atomic_bool *const disk_read_acitivity, std::atomic_bool *const disk_write_acitivity);