@@ -46,14 +46,13 @@ Swim3Ctrl::Swim3Ctrl()
46
46
47
47
// Attach virtual Superdrive to the internal drive connector
48
48
// TODO: make SWIM3/drive wiring user selectable
49
- this ->drive_1 = std::unique_ptr<MacSuperdrive::MacSuperDrive>
49
+ this ->int_drive = std::unique_ptr<MacSuperdrive::MacSuperDrive>
50
50
(new MacSuperdrive::MacSuperDrive (" Superdrive1" ));
51
51
}
52
52
53
53
void Swim3Ctrl::reset ()
54
54
{
55
55
this ->setup_reg = 0 ;
56
- this ->selected_drive = nullptr ;
57
56
this ->mode_reg = 0 ;
58
57
this ->int_reg = 0 ;
59
58
this ->int_flags = 0 ;
@@ -95,7 +94,7 @@ int Swim3Ctrl::device_postinit()
95
94
std::string fd_image_path = GET_STR_PROP (" fdd_img" );
96
95
int fd_write_prot = GET_BIN_PROP (" fdd_wr_prot" );
97
96
if (!fd_image_path.empty ()) {
98
- this ->drive_1 ->insert_disk (fd_image_path, fd_write_prot);
97
+ this ->int_drive ->insert_disk (fd_image_path, fd_write_prot);
99
98
}
100
99
101
100
return 0 ;
@@ -117,17 +116,14 @@ uint8_t Swim3Ctrl::read(uint8_t reg_offset)
117
116
case Swim3Reg::Setup:
118
117
return this ->setup_reg ;
119
118
case Swim3Reg::Handshake_Mode1:
120
- if (this ->selected_drive ) {
119
+ if (this ->mode_reg & SWIM3_DRIVE_1 ) { // internal drive?
121
120
status_addr = ((this ->mode_reg & SWIM3_HEAD_SELECT) >> 2 ) | (this ->phase_lines & 7 );
122
- rddata_val = this ->selected_drive ->status (status_addr) & 1 ;
121
+ rddata_val = this ->int_drive ->status (status_addr) & 1 ;
123
122
124
123
// transfer rddata_val to both bit 2 (RDDATA) and bit 3 (SENSE)
125
124
// because those signals seem to be historically wired together
126
125
return (rddata_val << 2 ) | (rddata_val << 3 );
127
126
}
128
- else {
129
- LOG_F (ERROR, " SWIM3: read Handshake_Mode1; no drive selected yet" );
130
- }
131
127
return 0xC ; // report both RdData & Sense high
132
128
case Swim3Reg::Interrupt_Flags:
133
129
old_int_flags = this ->int_flags ;
@@ -168,31 +164,41 @@ void Swim3Ctrl::write(uint8_t reg_offset, uint8_t value)
168
164
case Swim3Reg::Phase:
169
165
this ->phase_lines = value & 0xF ;
170
166
if (this ->phase_lines & 8 ) { // CA3 aka LSTRB high -> sending a command to the drive
171
- uint8_t command_addr = ((this ->mode_reg & SWIM3_HEAD_SELECT) >> 3 ) | (this ->phase_lines & 3 );
172
- uint8_t val = (value >> 2 ) & 1 ;
173
- if (this ->selected_drive ) {
174
- this ->selected_drive ->command (command_addr, val);
175
- } else
176
- LOG_F (ERROR, " SWIM3: command %-17s addr=0x%X, value=%d; no drive selected yet" ,
177
- MacSuperdrive::get_command_name (command_addr).c_str (), command_addr, val);
178
- } else if (this ->phase_lines == 4 ) {
179
- // Select_Head_0 or Select_Head_1
167
+ if (this ->mode_reg & SWIM3_DRIVE_1) { // if internal drive is selected
168
+ this ->int_drive ->command (
169
+ ((this ->mode_reg & SWIM3_HEAD_SELECT) >> 3 ) | (this ->phase_lines & 3 ),
170
+ (value >> 2 ) & 1
171
+ );
172
+ }
173
+ } else if (this ->phase_lines == 4 && (this ->mode_reg & SWIM3_DRIVE_1)) {
180
174
status_addr = ((this ->mode_reg & SWIM3_HEAD_SELECT) >> 2 ) | (this ->phase_lines & 7 );
181
- if (this ->selected_drive )
182
- this ->rd_line = this ->selected_drive ->status (status_addr) & 1 ;
183
- else
184
- LOG_F (ERROR, " SWIM3: status %-13s 0x%X; no drive selected yet" ,
185
- MacSuperdrive::get_status_name (status_addr).c_str (), status_addr);
175
+ this ->rd_line = this ->int_drive ->status (status_addr) & 1 ;
186
176
}
187
177
break ;
188
178
case Swim3Reg::Setup:
189
179
this ->setup_reg = value;
190
180
break ;
191
181
case Swim3Reg::Status_Mode0:
192
- this ->mode_change (this ->mode_reg & ~value);
182
+ // ones in value clear the corresponding bits in the mode register
183
+ if ((this ->mode_reg & value) & (SWIM3_GO | SWIM3_GO_STEP)) {
184
+ if (value & SWIM3_GO_STEP) {
185
+ stop_stepping ();
186
+ } else {
187
+ stop_disk_access ();
188
+ }
189
+ }
190
+ this ->mode_reg &= ~value;
193
191
break ;
194
192
case Swim3Reg::Handshake_Mode1:
195
- this ->mode_change (this ->mode_reg | value);
193
+ // ones in value set the corresponding bits in the mode register
194
+ if ((this ->mode_reg ^ value) & (SWIM3_GO | SWIM3_GO_STEP)) {
195
+ if (value & SWIM3_GO_STEP) {
196
+ start_stepping ();
197
+ } else {
198
+ start_disk_access ();
199
+ }
200
+ }
201
+ this ->mode_reg |= value;
196
202
break ;
197
203
case Swim3Reg::Step:
198
204
this ->step_count = value;
@@ -229,10 +235,7 @@ void Swim3Ctrl::do_step()
229
235
{
230
236
if (this ->mode_reg & SWIM3_GO_STEP && this ->step_count ) { // are we still stepping?
231
237
// instruct the drive to perform single step in current direction
232
- if (this ->selected_drive )
233
- this ->selected_drive ->command (MacSuperdrive::CommandAddr::Do_Step, 0 );
234
- else
235
- LOG_F (ERROR, " SWIM3: do_step; no drive selected yet" );
238
+ this ->int_drive ->command (MacSuperdrive::CommandAddr::Do_Step, 0 );
236
239
if (--this ->step_count == 0 ) {
237
240
if (this ->step_timer_id ) {
238
241
this ->stop_stepping ();
@@ -314,13 +317,8 @@ void Swim3Ctrl::start_disk_access()
314
317
315
318
this ->target_sect = this ->first_sec ;
316
319
317
- if (!this ->selected_drive ) {
318
- LOG_F (ERROR, " SWIM3: start_disk_access; no drive selected yet" );
319
- return ;
320
- }
321
-
322
320
this ->access_timer_id = TimerManager::get_instance ()->add_oneshot_timer (
323
- this ->selected_drive ->sync_to_disk (),
321
+ this ->int_drive ->sync_to_disk (),
324
322
[this ]() {
325
323
this ->cur_state = SWIM3_ADDR_MARK_SEARCH;
326
324
this ->disk_access ();
@@ -333,14 +331,9 @@ void Swim3Ctrl::disk_access()
333
331
MacSuperdrive::SectorHdr hdr;
334
332
uint64_t delay;
335
333
336
- if (!this ->selected_drive ) {
337
- LOG_F (ERROR, " SWIM3: disk access; no drive selected yet" );
338
- return ;
339
- }
340
-
341
334
switch (this ->cur_state ) {
342
335
case SWIM3_ADDR_MARK_SEARCH:
343
- hdr = this ->selected_drive ->current_sector_header ();
336
+ hdr = this ->int_drive ->current_sector_header ();
344
337
// update the corresponding SWIM3 registers
345
338
this ->cur_track = ((hdr.side & 1 ) << 7 ) | (hdr.track & 0x7F );
346
339
this ->cur_sector = 0x80 /* CRC/checksum valid */ | (hdr.sector & 0x7F );
@@ -351,16 +344,16 @@ void Swim3Ctrl::disk_access()
351
344
if ((this ->cur_sector & 0x7F ) == this ->target_sect ) {
352
345
// sector matches -> transfer its data
353
346
this ->cur_state = SWIM3_DATA_XFER;
354
- delay = this ->selected_drive ->sector_data_delay ();
347
+ delay = this ->int_drive ->sector_data_delay ();
355
348
} else {
356
349
// move to next address mark
357
350
this ->cur_state = SWIM3_ADDR_MARK_SEARCH;
358
- delay = this ->selected_drive ->next_sector_delay ();
351
+ delay = this ->int_drive ->next_sector_delay ();
359
352
}
360
353
break ;
361
354
case SWIM3_DATA_XFER:
362
355
// transfer sector data over DMA
363
- this ->dma_ch ->push_data (this ->selected_drive ->get_sector_data_ptr (this ->cur_sector & 0x7F ), 512 );
356
+ this ->dma_ch ->push_data (this ->int_drive ->get_sector_data_ptr (this ->cur_sector & 0x7F ), 512 );
364
357
if (--this ->xfer_cnt == 0 ) {
365
358
this ->stop_disk_access ();
366
359
// generate sector_done interrupt
@@ -369,7 +362,7 @@ void Swim3Ctrl::disk_access()
369
362
return ;
370
363
}
371
364
this ->cur_state = SWIM3_ADDR_MARK_SEARCH;
372
- delay = this ->selected_drive ->next_addr_mark_delay (&this ->target_sect );
365
+ delay = this ->int_drive ->next_addr_mark_delay (&this ->target_sect );
373
366
break ;
374
367
default :
375
368
LOG_F (ERROR, " SWIM3: unknown disk access phase 0x%X" , this ->cur_state );
@@ -431,57 +424,6 @@ uint8_t Swim3Ctrl::calc_timer_val()
431
424
}
432
425
}
433
426
434
- void Swim3Ctrl::mode_change (uint8_t new_mode)
435
- {
436
- uint8_t changed_bits = this ->mode_reg ^ new_mode;
437
-
438
- if (changed_bits & (SWIM3_DRIVE_1 | SWIM3_DRIVE_2)) {
439
- this ->selected_drive = nullptr ;
440
- this ->cur_track = 0xFF ;
441
- this ->cur_sector = 0x7F ;
442
-
443
- switch (new_mode & (SWIM3_DRIVE_1 | SWIM3_DRIVE_2)) {
444
- case 0 :
445
- break ;
446
- case SWIM3_DRIVE_1:
447
- if (this ->drive_1 )
448
- this ->selected_drive = this ->drive_1 .get ();
449
- break ;
450
- case SWIM3_DRIVE_2:
451
- break ;
452
- case SWIM3_DRIVE_1 | SWIM3_DRIVE_2:
453
- LOG_F (ERROR, " SWIM3: both drives selected, selecting drive 1" );
454
- if (this ->drive_1 )
455
- this ->selected_drive = this ->drive_1 .get ();
456
- break ;
457
- }
458
- if (this ->xfer_cnt ) {
459
- LOG_F (ERROR, " SWIM3: selecting drive while xfer still in progress" );
460
- }
461
- }
462
-
463
- if (changed_bits & SWIM3_GO_STEP) {
464
- if (new_mode & SWIM3_GO_STEP)
465
- start_stepping ();
466
- else
467
- stop_stepping ();
468
- if (changed_bits & SWIM3_GO) {
469
- LOG_F (ERROR, " SWIM3: attempt to change GO and GO_STEP, ignoring GO" );
470
- }
471
- }
472
- else
473
- if (changed_bits & SWIM3_GO) {
474
- if (new_mode & SWIM3_GO)
475
- start_disk_access ();
476
- else {
477
- stop_disk_access ();
478
- this ->cur_sector &= ~0x80 ;
479
- }
480
- }
481
-
482
- this ->mode_reg = new_mode;
483
- }
484
-
485
427
// floppy disk formats properties for the cases
486
428
// where disk format needs to be specified manually
487
429
static const std::vector<std::string> FloppyFormats = {
0 commit comments