2015-11-05 20:23:46 +00:00
/*
2016-02-04 06:37:39 +00:00
GSPLUS - Advanced Apple IIGS Emulator Environment
2016-02-08 05:01:25 +00:00
Copyright ( C ) 2016 - Dagen Brock
2017-04-05 14:18:04 +00:00
2015-11-05 20:23:46 +00:00
Copyright ( C ) 2010 - 2012 by GSport contributors
2017-04-05 14:18:04 +00:00
2015-11-05 20:23:46 +00:00
Based on the KEGS emulator written by and Copyright ( C ) 2003 Kent Dickey
2017-04-05 14:18:04 +00:00
This program 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 2 of the License , or ( at your
2015-11-05 20:23:46 +00:00
option ) any later version .
2017-04-05 14:18:04 +00:00
This program 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
2015-11-05 20:23:46 +00:00
for more details .
2017-04-05 14:18:04 +00:00
You should have received a copy of the GNU General Public License along
with this program ; if not , write to the Free Software Foundation , Inc . ,
2015-11-05 20:23:46 +00:00
59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "defc.h"
2017-04-05 14:18:04 +00:00
# include "glog.h"
2015-11-05 20:23:46 +00:00
extern int Verbose ;
2016-02-08 05:01:25 +00:00
extern word32 g_vbl_count ; // OG change int to word32
2015-11-05 20:23:46 +00:00
extern int g_c036_val_speed ;
const byte phys_to_dos_sec [ ] = {
0x00 , 0x07 , 0x0e , 0x06 , 0x0d , 0x05 , 0x0c , 0x04 ,
0x0b , 0x03 , 0x0a , 0x02 , 0x09 , 0x01 , 0x08 , 0x0f
} ;
const byte phys_to_prodos_sec [ ] = {
0x00 , 0x08 , 0x01 , 0x09 , 0x02 , 0x0a , 0x03 , 0x0b ,
0x04 , 0x0c , 0x05 , 0x0d , 0x06 , 0x0e , 0x07 , 0x0f
} ;
const byte to_disk_byte [ ] = {
0x96 , 0x97 , 0x9a , 0x9b , 0x9d , 0x9e , 0x9f , 0xa6 ,
0xa7 , 0xab , 0xac , 0xad , 0xae , 0xaf , 0xb2 , 0xb3 ,
/* 0x10 */
0xb4 , 0xb5 , 0xb6 , 0xb7 , 0xb9 , 0xba , 0xbb , 0xbc ,
0xbd , 0xbe , 0xbf , 0xcb , 0xcd , 0xce , 0xcf , 0xd3 ,
/* 0x20 */
0xd6 , 0xd7 , 0xd9 , 0xda , 0xdb , 0xdc , 0xdd , 0xde ,
0xdf , 0xe5 , 0xe6 , 0xe7 , 0xe9 , 0xea , 0xeb , 0xec ,
/* 0x30 */
0xed , 0xee , 0xef , 0xf2 , 0xf3 , 0xf4 , 0xf5 , 0xf6 ,
0xf7 , 0xf9 , 0xfa , 0xfb , 0xfc , 0xfd , 0xfe , 0xff
} ;
int g_track_bytes_35 [ ] = {
0x200 * 12 ,
0x200 * 11 ,
0x200 * 10 ,
0x200 * 9 ,
0x200 * 8
} ;
int g_track_nibs_35 [ ] = {
816 * 12 ,
816 * 11 ,
816 * 10 ,
816 * 9 ,
816 * 8
} ;
int g_fast_disk_emul = 1 ;
int g_slow_525_emul_wr = 0 ;
double g_dcycs_end_emul_wr = 0.0 ;
int g_fast_disk_unnib = 0 ;
int g_iwm_fake_fast = 0 ;
int from_disk_byte [ 256 ] ;
int from_disk_byte_valid = 0 ;
Iwm iwm ;
extern int g_c031_disk35 ;
int g_iwm_motor_on = 0 ;
int g_check_nibblization = 0 ;
/* prototypes for IWM special routs */
int iwm_read_data_35 ( Disk * dsk , int fast_disk_emul , double dcycs ) ;
int iwm_read_data_525 ( Disk * dsk , int fast_disk_emul , double dcycs ) ;
void iwm_write_data_35 ( Disk * dsk , word32 val , int fast_disk_emul , double dcycs ) ;
void iwm_write_data_525 ( Disk * dsk , word32 val , int fast_disk_emul , double dcycs ) ;
void
iwm_init_drive ( Disk * dsk , int smartport , int drive , int disk_525 )
{
dsk - > dcycs_last_read = 0.0 ;
dsk - > name_ptr = 0 ;
dsk - > partition_name = 0 ;
dsk - > partition_num = - 1 ;
dsk - > file = 0 ;
dsk - > force_size = 0 ;
dsk - > image_start = 0 ;
dsk - > image_size = 0 ;
dsk - > smartport = smartport ;
dsk - > disk_525 = disk_525 ;
dsk - > drive = drive ;
dsk - > cur_qtr_track = 0 ;
dsk - > image_type = 0 ;
dsk - > vol_num = 254 ;
dsk - > write_prot = 1 ;
dsk - > write_through_to_unix = 0 ;
dsk - > disk_dirty = 0 ;
dsk - > just_ejected = 0 ;
dsk - > last_phase = 0 ;
dsk - > nib_pos = 0 ;
dsk - > num_tracks = 0 ;
dsk - > trks = 0 ;
}
void
disk_set_num_tracks ( Disk * dsk , int num_tracks )
{
int i ;
if ( dsk - > trks ! = 0 ) {
/* This should not be necessary! */
free ( dsk - > trks ) ;
halt_printf ( " Needed to free dsk->trks: %p \n " , dsk - > trks ) ;
}
dsk - > num_tracks = num_tracks ;
dsk - > trks = ( Trk * ) malloc ( num_tracks * sizeof ( Trk ) ) ;
for ( i = 0 ; i < num_tracks ; i + + ) {
dsk - > trks [ i ] . dsk = dsk ;
dsk - > trks [ i ] . nib_area = 0 ;
dsk - > trks [ i ] . track_dirty = 0 ;
dsk - > trks [ i ] . overflow_size = 0 ;
dsk - > trks [ i ] . track_len = 0 ;
dsk - > trks [ i ] . unix_pos = - 1 ;
dsk - > trks [ i ] . unix_len = - 1 ;
}
}
void
iwm_init ( )
{
int val ;
int i ;
for ( i = 0 ; i < 2 ; i + + ) {
iwm_init_drive ( & ( iwm . drive525 [ i ] ) , 0 , i , 1 ) ;
iwm_init_drive ( & ( iwm . drive35 [ i ] ) , 0 , i , 0 ) ;
}
for ( i = 0 ; i < MAX_C7_DISKS ; i + + ) {
iwm_init_drive ( & ( iwm . smartport [ i ] ) , 1 , i , 0 ) ;
}
if ( from_disk_byte_valid = = 0 ) {
for ( i = 0 ; i < 256 ; i + + ) {
from_disk_byte [ i ] = - 1 ;
}
for ( i = 0 ; i < 64 ; i + + ) {
val = to_disk_byte [ i ] ;
from_disk_byte [ val ] = i ;
}
from_disk_byte_valid = 1 ;
} else {
halt_printf ( " iwm_init called twice! \n " ) ;
}
iwm_reset ( ) ;
}
2016-02-08 05:01:25 +00:00
// OG Added shut function to IWM
// Free the memory, and more important free the open handle onto the disk
void
iwm_shut ( )
{
int i ;
for ( i = 0 ; i < 2 ; i + + ) {
eject_disk ( & iwm . drive525 [ i ] ) ;
eject_disk ( & iwm . drive35 [ i ] ) ;
}
for ( i = 0 ; i < MAX_C7_DISKS ; i + + ) {
eject_disk ( & iwm . smartport [ i ] ) ;
}
from_disk_byte_valid = 0 ;
}
2015-11-05 20:23:46 +00:00
void
iwm_reset ( )
{
iwm . q6 = 0 ;
iwm . q7 = 0 ;
iwm . motor_on = 0 ;
iwm . motor_on35 = 0 ;
iwm . motor_off = 0 ;
iwm . motor_off_vbl_count = 0 ;
iwm . step_direction35 = 0 ;
iwm . head35 = 0 ;
iwm . drive_select = 0 ;
iwm . iwm_mode = 0 ;
iwm . enable2 = 0 ;
iwm . reset = 0 ;
iwm . iwm_phase [ 0 ] = 0 ;
iwm . iwm_phase [ 1 ] = 0 ;
iwm . iwm_phase [ 2 ] = 0 ;
iwm . iwm_phase [ 3 ] = 0 ;
iwm . previous_write_val = 0 ;
iwm . previous_write_bits = 0 ;
g_iwm_motor_on = 0 ;
g_c031_disk35 = 0 ;
}
void
draw_iwm_status ( int line , char * buf )
{
char * flag [ 2 ] [ 2 ] ;
int apple35_sel ;
flag [ 0 ] [ 0 ] = " " ;
flag [ 0 ] [ 1 ] = " " ;
flag [ 1 ] [ 0 ] = " " ;
flag [ 1 ] [ 1 ] = " " ;
apple35_sel = ( g_c031_disk35 > > 6 ) & 1 ;
if ( g_iwm_motor_on ) {
flag [ apple35_sel ] [ iwm . drive_select ] = " * " ;
}
2017-04-05 14:18:04 +00:00
# ifdef ACTIVEGS // OG Pass monitoring info
2016-02-08 05:01:25 +00:00
{
extern void ki_loading ( int _motorOn , int _slot , int _drive , int _curtrack ) ;
int curtrack = 0 ;
if ( apple35_sel )
curtrack = iwm . drive35 [ iwm . drive_select ] . cur_qtr_track ;
else
curtrack = iwm . drive525 [ iwm . drive_select ] . cur_qtr_track > > 2 ;
2017-04-05 14:18:04 +00:00
2016-02-08 05:01:25 +00:00
ki_loading ( g_iwm_motor_on , apple35_sel ? 5 : 6 , iwm . drive_select + 1 , curtrack ) ;
}
# endif
2015-11-05 20:23:46 +00:00
sprintf ( buf , " s6d1:%2d%s s6d2:%2d%s s5d1:%2d/%d%s "
" s5d2:%2d/%d%s fast_disk_emul:%d,%d c036:%02x " ,
iwm . drive525 [ 0 ] . cur_qtr_track > > 2 , flag [ 0 ] [ 0 ] ,
iwm . drive525 [ 1 ] . cur_qtr_track > > 2 , flag [ 0 ] [ 1 ] ,
iwm . drive35 [ 0 ] . cur_qtr_track > > 1 ,
iwm . drive35 [ 0 ] . cur_qtr_track & 1 , flag [ 1 ] [ 0 ] ,
iwm . drive35 [ 1 ] . cur_qtr_track > > 1 ,
iwm . drive35 [ 1 ] . cur_qtr_track & 1 , flag [ 1 ] [ 1 ] ,
g_fast_disk_emul , g_slow_525_emul_wr , g_c036_val_speed ) ;
video_update_status_line ( line , buf ) ;
}
void
iwm_flush_disk_to_unix ( Disk * dsk )
{
byte buffer [ 0x4000 ] ;
int num_dirty ;
int j ;
int ret ;
int unix_pos ;
int unix_len ;
if ( dsk - > disk_dirty = = 0 | | dsk - > write_through_to_unix = = 0 ) {
return ;
}
printf ( " Writing disk %s to Unix \n " , dsk - > name_ptr ) ;
dsk - > disk_dirty = 0 ;
num_dirty = 0 ;
/* Dirty data! */
for ( j = 0 ; j < dsk - > num_tracks ; j + + ) {
ret = disk_track_to_unix ( dsk , j , & ( buffer [ 0 ] ) ) ;
if ( ret ! = 1 & & ret ! = 0 ) {
printf ( " iwm_flush_disk_to_unix ret: %d, cannot write "
" image to unix \n " , ret ) ;
halt_printf ( " Adjusting image not to write through! \n " ) ;
dsk - > write_through_to_unix = 0 ;
break ;
}
if ( ret ! = 1 ) {
/* not at an even track, or not dirty */
continue ;
}
if ( ( j & 3 ) ! = 0 & & dsk - > disk_525 ) {
halt_printf ( " Valid data on a non-whole trk: %03x \n " , j ) ;
continue ;
}
num_dirty + + ;
/* Write it out */
unix_pos = dsk - > trks [ j ] . unix_pos ;
unix_len = dsk - > trks [ j ] . unix_len ;
if ( unix_pos < 0 | | unix_len < 0x1000 ) {
halt_printf ( " Disk:%s trk:%d, unix_pos:%08x, len:%08x \n " ,
dsk - > name_ptr , j , unix_pos , unix_len ) ;
break ;
}
ret = fseek ( dsk - > file , unix_pos , SEEK_SET ) ;
if ( ret ! = 0 ) {
halt_printf ( " fseek 525: errno: %d \n " , errno ) ;
}
ret = fwrite ( & ( buffer [ 0 ] ) , 1 , unix_len , dsk - > file ) ;
if ( ret ! = unix_len ) {
printf ( " fwrite: %08x, errno:%d, qtrk: %02x, disk: %s \n " ,
ret , errno , j , dsk - > name_ptr ) ;
}
}
if ( num_dirty = = 0 ) {
halt_printf ( " Drive %s was dirty, but no track was dirty! \n " ,
dsk - > name_ptr ) ;
}
}
/* Check for dirty disk 3 times a second */
extern byte g_bram [ 2 ] [ 256 ] ;
extern byte * g_bram_ptr ;
extern byte g_temp_boot_slot ;
extern byte g_orig_boot_slot ;
2016-04-28 02:58:38 +00:00
extern int g_config_gsplus_update_needed ;
2015-11-05 20:23:46 +00:00
void
iwm_vbl_update ( int doit_3_persec )
{
Disk * dsk ;
int motor_on ;
int i ;
if ( iwm . motor_on & & iwm . motor_off ) {
2016-02-08 05:01:25 +00:00
if ( ( word32 ) iwm . motor_off_vbl_count < = g_vbl_count ) {
2017-04-05 14:18:04 +00:00
glogf ( " Disk timer expired, drive off: %08x \n " , g_vbl_count ) ;
2015-11-05 20:23:46 +00:00
iwm . motor_on = 0 ;
iwm . motor_off = 0 ;
if ( g_temp_boot_slot ! = 254 ) {
// Drive is off, now's a good time to turn off the temp boot slot if it was on.
g_temp_boot_slot = 254 ;
g_bram_ptr [ 40 ] = g_orig_boot_slot ;
clk_calculate_bram_checksum ( ) ;
2016-04-28 02:58:38 +00:00
g_config_gsplus_update_needed = 1 ;
2015-11-05 20:23:46 +00:00
}
}
}
if ( ! doit_3_persec ) {
return ;
}
motor_on = iwm . motor_on ;
if ( g_c031_disk35 & 0x40 ) {
motor_on = iwm . motor_on35 ;
if ( g_temp_boot_slot ! = 254 ) {
// Now's a good time to turn off the temp boot slot if it was on.
g_temp_boot_slot = 254 ;
g_bram_ptr [ 40 ] = g_orig_boot_slot ;
clk_calculate_bram_checksum ( ) ;
2016-04-28 02:58:38 +00:00
g_config_gsplus_update_needed = 1 ;
2015-11-05 20:23:46 +00:00
}
}
if ( motor_on = = 0 | | iwm . motor_off ) {
/* Disk not spinning, see if any dirty tracks to flush */
/* out to Unix */
for ( i = 0 ; i < 2 ; i + + ) {
dsk = & ( iwm . drive525 [ i ] ) ;
iwm_flush_disk_to_unix ( dsk ) ;
}
for ( i = 0 ; i < 2 ; i + + ) {
dsk = & ( iwm . drive35 [ i ] ) ;
iwm_flush_disk_to_unix ( dsk ) ;
}
}
}
void
iwm_show_stats ( )
{
printf ( " IWM stats: q7,q6: %d, %d, reset,enable2: %d,%d, mode: %02x \n " ,
iwm . q7 , iwm . q6 , iwm . reset , iwm . enable2 , iwm . iwm_mode ) ;
printf ( " motor: %d,%d, motor35:%d drive: %d, c031:%02x "
" phs: %d %d %d %d \n " ,
iwm . motor_on , iwm . motor_off , g_iwm_motor_on ,
iwm . drive_select , g_c031_disk35 ,
iwm . iwm_phase [ 0 ] , iwm . iwm_phase [ 1 ] , iwm . iwm_phase [ 2 ] ,
iwm . iwm_phase [ 3 ] ) ;
printf ( " iwm.drive525[0].file: %p, [1].file: %p \n " ,
iwm . drive525 [ 0 ] . file , iwm . drive525 [ 1 ] . file ) ;
printf ( " iwm.drive525[0].last_phase: %d, [1].last_phase: %d \n " ,
iwm . drive525 [ 0 ] . last_phase , iwm . drive525 [ 1 ] . last_phase ) ;
}
void
iwm_touch_switches ( int loc , double dcycs )
{
Disk * dsk ;
int phase ;
int on ;
int drive ;
if ( iwm . reset ) {
iwm_printf ( " IWM under reset: %d, enable2: %d \n " , iwm . reset ,
iwm . enable2 ) ;
}
on = loc & 1 ;
drive = iwm . drive_select ;
phase = loc > > 1 ;
if ( g_c031_disk35 & 0x40 ) {
dsk = & ( iwm . drive35 [ drive ] ) ;
} else {
dsk = & ( iwm . drive525 [ drive ] ) ;
}
if ( loc < 8 ) {
/* phase adjustments. See if motor is on */
iwm . iwm_phase [ phase ] = on ;
iwm_printf ( " Iwm phase %d=%d, all phases: %d %d %d %d (%f) \n " ,
phase , on , iwm . iwm_phase [ 0 ] , iwm . iwm_phase [ 1 ] ,
iwm . iwm_phase [ 2 ] , iwm . iwm_phase [ 3 ] , dcycs ) ;
if ( iwm . motor_on ) {
if ( g_c031_disk35 & 0x40 ) {
if ( phase = = 3 & & on ) {
iwm_do_action35 ( dcycs ) ;
}
} else if ( on ) {
/* Move apple525 head */
iwm525_phase_change ( drive , phase ) ;
}
}
/* See if enable or reset is asserted */
if ( iwm . iwm_phase [ 0 ] & & iwm . iwm_phase [ 2 ] ) {
iwm . reset = 1 ;
iwm_printf ( " IWM reset active \n " ) ;
} else {
iwm . reset = 0 ;
}
if ( iwm . iwm_phase [ 1 ] & & iwm . iwm_phase [ 3 ] ) {
iwm . enable2 = 1 ;
iwm_printf ( " IWM ENABLE2 active \n " ) ;
} else {
iwm . enable2 = 0 ;
}
} else {
/* loc >= 8 */
switch ( loc ) {
case 0x8 :
iwm_printf ( " Turning IWM motor off! \n " ) ;
if ( iwm . iwm_mode & 0x04 ) {
/* Turn off immediately */
iwm . motor_off = 0 ;
iwm . motor_on = 0 ;
} else {
/* 1 second delay */
if ( iwm . motor_on & & ! iwm . motor_off ) {
iwm . motor_off = 1 ;
iwm . motor_off_vbl_count = g_vbl_count
+ 60 ;
}
}
if ( g_iwm_motor_on | | g_slow_525_emul_wr ) {
/* recalc current speed */
set_halt ( HALT_EVENT ) ;
}
g_iwm_motor_on = 0 ;
g_slow_525_emul_wr = 0 ;
break ;
case 0x9 :
iwm_printf ( " Turning IWM motor on! \n " ) ;
iwm . motor_on = 1 ;
iwm . motor_off = 0 ;
if ( g_iwm_motor_on = = 0 ) {
/* recalc current speed */
set_halt ( HALT_EVENT ) ;
}
g_iwm_motor_on = 1 ;
break ;
case 0xa :
case 0xb :
iwm . drive_select = on ;
break ;
case 0xc :
case 0xd :
iwm . q6 = on ;
break ;
case 0xe :
case 0xf :
iwm . q7 = on ;
break ;
default :
printf ( " iwm_touch_switches: loc: %02x unknown! \n " , loc ) ;
exit ( 2 ) ;
}
}
if ( ! iwm . q7 ) {
iwm . previous_write_bits = 0 ;
}
if ( ( dcycs > g_dcycs_end_emul_wr ) & & g_slow_525_emul_wr ) {
set_halt ( HALT_EVENT ) ;
g_slow_525_emul_wr = 0 ;
}
}
void
iwm_move_to_track ( Disk * dsk , int new_track )
{
int disk_525 ;
int dr ;
disk_525 = dsk - > disk_525 ;
if ( new_track < 0 ) {
new_track = 0 ;
}
if ( new_track > = dsk - > num_tracks ) {
if ( disk_525 ) {
new_track = dsk - > num_tracks - 4 ;
} else {
new_track = dsk - > num_tracks - 2 + iwm . head35 ;
}
if ( new_track < = 0 ) {
new_track = 0 ;
}
}
if ( dsk - > cur_qtr_track ! = new_track ) {
dr = dsk - > drive + 1 ;
if ( disk_525 ) {
iwm_printf ( " s6d%d Track: %d.%02d \n " , dr ,
new_track > > 2 , 25 * ( new_track & 3 ) ) ;
} else {
iwm_printf ( " s5d%d Track: %d Side: %d \n " , dr ,
new_track > > 1 , new_track & 1 ) ;
}
dsk - > cur_qtr_track = new_track ;
}
}
void
iwm525_phase_change ( int drive , int phase )
{
Disk * dsk ;
int qtr_track ;
int delta ;
dsk = & ( iwm . drive525 [ drive ] ) ;
qtr_track = dsk - > cur_qtr_track ;
int half_track = qtr_track > > 1 ;
delta = 0 ;
2016-02-08 05:01:25 +00:00
if ( iwm . iwm_phase [ ( half_track + 1 ) & 3 ] )
2015-11-05 20:23:46 +00:00
delta + = 2 ;
2016-02-08 05:01:25 +00:00
if ( iwm . iwm_phase [ ( half_track + 3 ) & 3 ] )
2015-11-05 20:23:46 +00:00
delta - = 2 ;
qtr_track + = delta ;
if ( qtr_track < 0 ) {
printf ( " GRIND... " ) ;
qtr_track = 0 ;
}
if ( qtr_track > 4 * 34 ) {
printf ( " Disk arm moved past track 34, moving it back \n " ) ;
qtr_track = 4 * 34 ;
}
iwm_move_to_track ( dsk , qtr_track ) ;
iwm_printf ( " Moving drive to qtr track: %04x (trk:%d.%02d), %d, %d, "
" %d %d %d %d \n " , qtr_track , qtr_track > > 2 , 25 * ( qtr_track & 3 ) ,
phase , delta , iwm . iwm_phase [ 0 ] ,
iwm . iwm_phase [ 1 ] , iwm . iwm_phase [ 2 ] , iwm . iwm_phase [ 3 ] ) ;
}
int
iwm_read_status35 ( double dcycs )
{
Disk * dsk ;
int drive ;
int state ;
int tmp ;
drive = iwm . drive_select ;
dsk = & ( iwm . drive35 [ drive ] ) ;
if ( iwm . motor_on ) {
/* Read status */
state = ( iwm . iwm_phase [ 1 ] < < 3 ) + ( iwm . iwm_phase [ 0 ] < < 2 ) +
( ( g_c031_disk35 > > 6 ) & 2 ) + iwm . iwm_phase [ 2 ] ;
iwm_printf ( " Iwm status read state: %02x \n " , state ) ;
switch ( state ) {
case 0x00 : /* step direction */
return iwm . step_direction35 ;
break ;
case 0x01 : /* lower head activate */
/* also return instantaneous data from head */
iwm . head35 = 0 ;
iwm_move_to_track ( dsk , ( dsk - > cur_qtr_track & ( - 2 ) ) ) ;
return ( ( ( int ) dcycs ) & 1 ) ;
break ;
case 0x02 : /* disk in place */
/* 1 = no disk, 0 = disk */
iwm_printf ( " read disk in place, num_tracks: %d \n " ,
dsk - > num_tracks ) ;
tmp = ( dsk - > num_tracks < = 0 ) ;
return tmp ;
break ;
case 0x03 : /* upper head activate */
/* also return instantaneous data from head */
iwm . head35 = 1 ;
iwm_move_to_track ( dsk , ( dsk - > cur_qtr_track | 1 ) ) ;
return ( ( ( int ) dcycs ) & 1 ) ;
break ;
case 0x04 : /* disk is stepping? */
/* 1 = not stepping, 0 = stepping */
return 1 ;
break ;
case 0x05 : /* Unknown function of ROM 03? */
/* 1 = or $20 into 0xe1/f24+drive, 0 = don't */
return 1 ;
break ;
case 0x06 : /* disk is locked */
/* 0 = locked, 1 = unlocked */
return ( ! dsk - > write_prot ) ;
break ;
case 0x08 : /* motor on */
/* 0 = on, 1 = off */
return ! iwm . motor_on35 ;
break ;
case 0x09 : /* number of sides */
/* 1 = 2 sides, 0 = 1 side */
return 1 ;
break ;
case 0x0a : /* at track 0 */
/* 1 = not at track 0, 0 = there */
tmp = ( dsk - > cur_qtr_track ! = 0 ) ;
iwm_printf ( " Read at track0_35: %d \n " , tmp ) ;
return tmp ;
break ;
case 0x0b : /* disk ready??? */
/* 0 = ready, 1 = not ready? */
tmp = ! iwm . motor_on35 ;
iwm_printf ( " Read disk ready, ret: %d \n " , tmp ) ;
return tmp ;
break ;
case 0x0c : /* disk switched?? */
/* 0 = not switched, 1 = switched? */
tmp = ( dsk - > just_ejected ! = 0 ) ;
iwm_printf ( " Read disk switched: %d \n " , tmp ) ;
return tmp ;
break ;
case 0x0d : /* false read when ejecting disk */
return 1 ;
case 0x0e : /* tachometer */
halt_printf ( " Reading tachometer! \n " ) ;
return ( ( ( int ) dcycs ) & 1 ) ;
break ;
case 0x0f : /* drive installed? */
/* 0 = drive exists, 1 = no drive */
if ( drive ) {
/* pretend no drive 1 */
return 1 ;
}
return 0 ;
break ;
default :
halt_printf ( " Read 3.5 status, state: %02x \n " , state ) ;
return 1 ;
}
} else {
iwm_printf ( " Read 3.5 status with drive off! \n " ) ;
return 1 ;
}
}
void
iwm_do_action35 ( double dcycs )
{
Disk * dsk ;
int drive ;
int state ;
drive = iwm . drive_select ;
dsk = & ( iwm . drive35 [ drive ] ) ;
if ( iwm . motor_on ) {
/* Perform action */
state = ( iwm . iwm_phase [ 1 ] < < 3 ) + ( iwm . iwm_phase [ 0 ] < < 2 ) +
( ( g_c031_disk35 > > 6 ) & 2 ) + iwm . iwm_phase [ 2 ] ;
switch ( state ) {
case 0x00 : /* Set step direction inward */
/* towards higher tracks */
iwm . step_direction35 = 0 ;
iwm_printf ( " Iwm set step dir35 = 0 \n " ) ;
break ;
case 0x01 : /* Set step direction outward */
/* towards lower tracks */
iwm . step_direction35 = 1 ;
iwm_printf ( " Iwm set step dir35 = 1 \n " ) ;
break ;
case 0x03 : /* reset disk-switched flag? */
iwm_printf ( " Iwm reset disk switch \n " ) ;
dsk - > just_ejected = 0 ;
/* set_halt(1); */
break ;
case 0x04 : /* step disk */
if ( iwm . step_direction35 ) {
iwm_move_to_track ( dsk , dsk - > cur_qtr_track - 2 ) ;
} else {
iwm_move_to_track ( dsk , dsk - > cur_qtr_track + 2 ) ;
}
break ;
case 0x08 : /* turn motor on */
iwm_printf ( " Iwm set motor_on35 = 1 \n " ) ;
iwm . motor_on35 = 1 ;
break ;
case 0x09 : /* turn motor off */
iwm_printf ( " Iwm set motor_on35 = 0 \n " ) ;
iwm . motor_on35 = 0 ;
break ;
case 0x0d : /* eject disk */
eject_disk ( dsk ) ;
2016-02-08 05:01:25 +00:00
# ifdef ACTIVEGS // OG : pass eject info to the Control (ActiveX specific)
{
extern void ejectDisk ( int slot , int disk ) ;
ejectDisk ( dsk - > disk_525 ? 6 : 5 , dsk - > drive + 1 ) ;
}
# endif
2015-11-05 20:23:46 +00:00
break ;
case 0x02 :
case 0x07 :
case 0x0b : /* hacks to allow AE 1.6MB driver to not crash me */
break ;
default :
halt_printf ( " Do 3.5 action, state: %02x \n " , state ) ;
return ;
}
} else {
halt_printf ( " Set 3.5 status with drive off! \n " ) ;
return ;
}
}
int
iwm_read_c0ec ( double dcycs )
{
Disk * dsk ;
int drive ;
iwm . q6 = 0 ;
if ( iwm . q7 = = 0 & & iwm . enable2 = = 0 & & iwm . motor_on ) {
drive = iwm . drive_select ;
if ( g_c031_disk35 & 0x40 ) {
dsk = & ( iwm . drive35 [ drive ] ) ;
return iwm_read_data_35 ( dsk , g_fast_disk_emul , dcycs ) ;
} else {
dsk = & ( iwm . drive525 [ drive ] ) ;
return iwm_read_data_525 ( dsk , g_fast_disk_emul , dcycs ) ;
}
}
return read_iwm ( 0xc , dcycs ) ;
}
int
read_iwm ( int loc , double dcycs )
{
Disk * dsk ;
word32 status ;
double diff_dcycs ;
double dcmp ;
int on ;
int state ;
int drive ;
int val ;
loc = loc & 0xf ;
on = loc & 1 ;
if ( loc = = 0xc ) {
iwm . q6 = 0 ;
} else {
iwm_touch_switches ( loc , dcycs ) ;
}
state = ( iwm . q7 < < 1 ) + iwm . q6 ;
drive = iwm . drive_select ;
if ( g_c031_disk35 & 0x40 ) {
dsk = & ( iwm . drive35 [ drive ] ) ;
} else {
dsk = & ( iwm . drive525 [ drive ] ) ;
}
if ( on ) {
/* odd address, return 0 */
return 0 ;
} else {
/* even address */
switch ( state ) {
case 0x00 : /* q7 = 0, q6 = 0 */
if ( iwm . enable2 ) {
return iwm_read_enable2 ( dcycs ) ;
} else {
if ( iwm . motor_on ) {
return iwm_read_data ( dsk ,
g_fast_disk_emul , dcycs ) ;
} else {
iwm_printf ( " read iwm st 0, m off! \n " ) ;
/* HACK!!!! */
return 0xff ;
//return (((int)dcycs) & 0x7f) + 0x80;
}
}
break ;
case 0x01 : /* q7 = 0, q6 = 1 */
/* read IWM status reg */
if ( iwm . enable2 ) {
iwm_printf ( " Read status under enable2: 1 \n " ) ;
status = 1 ;
} else {
if ( g_c031_disk35 & 0x40 ) {
status = iwm_read_status35 ( dcycs ) ;
} else {
status = dsk - > write_prot ;
}
}
val = ( status < < 7 ) + ( iwm . motor_on < < 5 ) +
iwm . iwm_mode ;
iwm_printf ( " Read status: %02x \n " , val ) ;
return val ;
break ;
case 0x02 : /* q7 = 1, q6 = 0 */
/* read handshake register */
if ( iwm . enable2 ) {
return iwm_read_enable2_handshake ( dcycs ) ;
} else {
status = 0xc0 ;
diff_dcycs = dcycs - dsk - > dcycs_last_read ;
dcmp = 16.0 ;
if ( dsk - > disk_525 = = 0 ) {
dcmp = 32.0 ;
}
if ( diff_dcycs > dcmp ) {
iwm_printf ( " Write underrun! \n " ) ;
iwm_printf ( " cur: %f, dc_last: %f \n " ,
dcycs , dsk - > dcycs_last_read ) ;
status = status & 0xbf ;
}
return status ;
}
break ;
case 0x03 : /* q7 = 1, q6 = 1 */
halt_printf ( " read iwm state 3! \n " ) ;
return 0 ;
break ;
}
2017-04-05 14:18:04 +00:00
2015-11-05 20:23:46 +00:00
}
halt_printf ( " Got to end of read_iwm, loc: %02x! \n " , loc ) ;
return 0 ;
}
void
write_iwm ( int loc , int val , double dcycs )
{
Disk * dsk ;
int on ;
int state ;
int drive ;
int fast_writes ;
loc = loc & 0xf ;
on = loc & 1 ;
iwm_touch_switches ( loc , dcycs ) ;
state = ( iwm . q7 < < 1 ) + iwm . q6 ;
drive = iwm . drive_select ;
fast_writes = g_fast_disk_emul ;
if ( g_c031_disk35 & 0x40 ) {
dsk = & ( iwm . drive35 [ drive ] ) ;
} else {
dsk = & ( iwm . drive525 [ drive ] ) ;
fast_writes = ! g_slow_525_emul_wr & & fast_writes ;
}
if ( on ) {
/* odd address, write something */
if ( state = = 0x03 ) {
/* q7, q6 = 1,1 */
if ( iwm . motor_on ) {
if ( iwm . enable2 ) {
iwm_write_enable2 ( val , dcycs ) ;
} else {
iwm_write_data ( dsk , val ,
fast_writes , dcycs ) ;
}
} else {
/* write mode register */
val = val & 0x1f ;
iwm . iwm_mode = val ;
if ( val ! = 0 & & val ! = 0x0f & & val ! = 0x07 & &
val ! = 0x04 & & val ! = 0x0b ) {
halt_printf ( " set iwm_mode:%02x! \n " , val ) ;
}
}
} else {
if ( iwm . enable2 ) {
iwm_write_enable2 ( val , dcycs ) ;
} else {
#if 0
// Flobynoid writes to 0xc0e9 causing these messages...
printf ( " Write iwm1, st: %02x, loc: %x: %02x \n " ,
state , loc , val ) ;
# endif
}
}
return ;
} else {
/* even address */
if ( iwm . enable2 ) {
iwm_write_enable2 ( val , dcycs ) ;
} else {
iwm_printf ( " Write iwm2, st: %02x, loc: %x: %02x \n " ,
state , loc , val ) ;
}
return ;
}
return ;
}
int
iwm_read_enable2 ( double dcycs )
{
iwm_printf ( " Read under enable2! \n " ) ;
return 0xff ;
}
int g_cnt_enable2_handshake = 0 ;
int
iwm_read_enable2_handshake ( double dcycs )
{
int val ;
iwm_printf ( " Read handshake under enable2! \n " ) ;
val = 0xc0 ;
g_cnt_enable2_handshake + + ;
if ( g_cnt_enable2_handshake > 3 ) {
g_cnt_enable2_handshake = 0 ;
val = 0x80 ;
}
return val ;
}
void
iwm_write_enable2 ( int val , double dcycs )
{
iwm_printf ( " Write under enable2: %02x! \n " , val ) ;
return ;
}
int
iwm_read_data ( Disk * dsk , int fast_disk_emul , double dcycs )
{
if ( dsk - > disk_525 ) {
return iwm_read_data_525 ( dsk , fast_disk_emul , dcycs ) ;
} else {
return iwm_read_data_35 ( dsk , fast_disk_emul , dcycs ) ;
}
}
void
iwm_write_data ( Disk * dsk , word32 val , int fast_disk_emul , double dcycs )
{
if ( dsk - > disk_525 ) {
iwm_write_data_525 ( dsk , val , fast_disk_emul , dcycs ) ;
} else {
iwm_write_data_35 ( dsk , val , fast_disk_emul , dcycs ) ;
}
}
# undef IWM_READ_ROUT
# undef IWM_WRITE_ROUT
# undef IWM_CYC_MULT
# undef IWM_DISK_525
# define IWM_READ_ROUT iwm_read_data_35
# define IWM_WRITE_ROUT iwm_write_data_35
# define IWM_CYC_MULT 1
# define IWM_DISK_525 0
# include "iwm_35_525.h"
# undef IWM_READ_ROUT
# undef IWM_WRITE_ROUT
# undef IWM_CYC_MULT
# undef IWM_DISK_525
# define IWM_READ_ROUT iwm_read_data_525
# define IWM_WRITE_ROUT iwm_write_data_525
# define IWM_CYC_MULT 2
# define IWM_DISK_525 1
# include "iwm_35_525.h"
# undef IWM_READ_ROUT
# undef IWM_WRITE_ROUT
# undef IWM_CYC_MULT
# undef IWM_DISK_525
/* c600 */
void
sector_to_partial_nib ( byte * in , byte * nib_ptr )
{
byte * aux_buf ;
byte * nib_out ;
int val ;
int val2 ;
int x ;
int i ;
/* Convert 256(+1) data bytes to 342+1 disk nibbles */
aux_buf = nib_ptr ;
nib_out = nib_ptr + 0x56 ;
for ( i = 0 ; i < 0x56 ; i + + ) {
aux_buf [ i ] = 0 ;
}
x = 0x55 ;
for ( i = 0x101 ; i > = 0 ; i - - ) {
val = in [ i ] ;
if ( i > = 0x100 ) {
val = 0 ;
}
val2 = ( aux_buf [ x ] < < 1 ) + ( val & 1 ) ;
val = val > > 1 ;
val2 = ( val2 < < 1 ) + ( val & 1 ) ;
val = val > > 1 ;
nib_out [ i ] = val ;
aux_buf [ x ] = val2 ;
x - - ;
if ( x < 0 ) {
x = 0x55 ;
}
}
}
int
disk_unnib_4x4 ( Disk * dsk )
{
int val1 ;
int val2 ;
val1 = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = iwm_read_data ( dsk , 1 , 0 ) ;
return ( ( val1 < < 1 ) + 1 ) & val2 ;
}
int
iwm_denib_track525 ( Disk * dsk , Trk * trk , int qtr_track , byte * outbuf )
{
byte aux_buf [ 0x80 ] ;
byte * buf ;
int sector_done [ 16 ] ;
int num_sectors_done ;
int track_len ;
int vol , track , phys_sec , log_sec , cksum ;
int val ;
int val2 ;
int prev_val ;
int x ;
int my_nib_cnt ;
int save_qtr_track ;
int save_nib_pos ;
int tmp_nib_pos ;
int status ;
int i ;
save_qtr_track = dsk - > cur_qtr_track ;
save_nib_pos = dsk - > nib_pos ;
iwm_move_to_track ( dsk , qtr_track ) ;
dsk - > nib_pos = 0 ;
g_fast_disk_unnib = 1 ;
track_len = trk - > track_len ;
for ( i = 0 ; i < 16 ; i + + ) {
sector_done [ i ] = 0 ;
}
num_sectors_done = 0 ;
val = 0 ;
status = - 1 ;
my_nib_cnt = 0 ;
while ( my_nib_cnt + + < 2 * track_len ) {
/* look for start of a sector */
if ( val ! = 0xd5 ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xaa ) {
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0x96 ) {
continue ;
}
/* It's a sector start */
vol = disk_unnib_4x4 ( dsk ) ;
track = disk_unnib_4x4 ( dsk ) ;
phys_sec = disk_unnib_4x4 ( dsk ) ;
if ( phys_sec < 0 | | phys_sec > 15 ) {
printf ( " Track %02x, read sec as %02x \n " , qtr_track > > 2 ,
phys_sec ) ;
break ;
}
if ( dsk - > image_type = = DSK_TYPE_DOS33 ) {
log_sec = phys_to_dos_sec [ phys_sec ] ;
} else {
log_sec = phys_to_prodos_sec [ phys_sec ] ;
}
cksum = disk_unnib_4x4 ( dsk ) ;
if ( ( vol ^ track ^ phys_sec ^ cksum ) ! = 0 ) {
/* not correct format */
printf ( " Track %02x not DOS 3.3 since hdr cksum, %02x "
" %02x %02x %02x \n " ,
qtr_track > > 2 , vol , track , phys_sec , cksum ) ;
break ;
}
/* see what sector it is */
if ( track ! = ( qtr_track > > 2 ) | | ( phys_sec < 0 ) | | ( phys_sec > 15 ) ) {
printf ( " Track %02x bad since track: %02x, sec: %02x \n " ,
qtr_track > > 2 , track , phys_sec ) ;
break ;
}
if ( sector_done [ phys_sec ] ) {
printf ( " Already done sector %02x on track %02x! \n " ,
phys_sec , qtr_track > > 2 ) ;
break ;
}
/* So far so good, let's do it! */
val = 0 ;
i = 0 ;
while ( i < NIBS_FROM_ADDR_TO_DATA ) {
i + + ;
if ( val ! = 0xd5 ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xaa ) {
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xad ) {
continue ;
}
/* got it, just break */
break ;
}
if ( i > = NIBS_FROM_ADDR_TO_DATA ) {
printf ( " No data header, track %02x, sec %02x \n " ,
qtr_track > > 2 , phys_sec ) ;
printf ( " nib_pos: %08x \n " , dsk - > nib_pos ) ;
break ;
}
buf = outbuf + 0x100 * log_sec ;
/* Data start! */
prev_val = 0 ;
for ( i = 0x55 ; i > = 0 ; i - - ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
if ( val2 < 0 ) {
printf ( " Bad data area1, val:%02x,val2:%02x \n " ,
val , val2 ) ;
printf ( " i:%03x,n_pos:%04x \n " , i , dsk - > nib_pos ) ;
break ;
}
prev_val = val2 ^ prev_val ;
aux_buf [ i ] = prev_val ;
}
/* rest of data area */
for ( i = 0 ; i < 0x100 ; i + + ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
if ( val2 < 0 ) {
printf ( " Bad data area2, read: %02x \n " , val ) ;
printf ( " nib_pos: %04x \n " , dsk - > nib_pos ) ;
break ;
}
prev_val = val2 ^ prev_val ;
buf [ i ] = prev_val ;
}
/* checksum */
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
if ( val2 < 0 ) {
printf ( " Bad data area3, read: %02x \n " , val ) ;
printf ( " nib_pos: %04x \n " , dsk - > nib_pos ) ;
break ;
}
if ( val2 ! = prev_val ) {
printf ( " Bad data cksum, got %02x, wanted: %02x \n " ,
val2 , prev_val ) ;
printf ( " nib_pos: %04x \n " , dsk - > nib_pos ) ;
break ;
}
/* Got this far, data is good, merge aux_buf into buf */
x = 0x55 ;
for ( i = 0 ; i < 0x100 ; i + + ) {
val = aux_buf [ x ] ;
val2 = ( buf [ i ] < < 1 ) + ( val & 1 ) ;
val = val > > 1 ;
val2 = ( val2 < < 1 ) + ( val & 1 ) ;
buf [ i ] = val2 ;
val = val > > 1 ;
aux_buf [ x ] = val ;
x - - ;
if ( x < 0 ) {
x = 0x55 ;
}
}
sector_done [ phys_sec ] = 1 ;
num_sectors_done + + ;
if ( num_sectors_done > = 16 ) {
status = 0 ;
break ;
}
}
tmp_nib_pos = dsk - > nib_pos ;
iwm_move_to_track ( dsk , save_qtr_track ) ;
dsk - > nib_pos = save_nib_pos ;
g_fast_disk_unnib = 0 ;
if ( status = = 0 ) {
return 1 ;
}
printf ( " Nibblization not done, %02x sectors found on track %02x \n " ,
num_sectors_done , qtr_track > > 2 ) ;
printf ( " my_nib_cnt: %04x, nib_pos: %04x, trk_len: %04x \n " , my_nib_cnt ,
tmp_nib_pos , track_len ) ;
for ( i = 0 ; i < 16 ; i + + ) {
printf ( " sector_done[%d] = %d \n " , i , sector_done [ i ] ) ;
}
return - 1 ;
}
int
iwm_denib_track35 ( Disk * dsk , Trk * trk , int qtr_track , byte * outbuf )
{
word32 buf_c00 [ 0x100 ] ;
word32 buf_d00 [ 0x100 ] ;
word32 buf_e00 [ 0x100 ] ;
byte * buf ;
word32 tmp_5c , tmp_5d , tmp_5e ;
word32 tmp_66 , tmp_67 ;
int sector_done [ 16 ] ;
int num_sectors_done ;
int track_len ;
int phys_track , phys_sec , phys_side , phys_capacity , cksum ;
int tmp ;
int track , side ;
int num_sectors ;
int val ;
int val2 ;
int x , y ;
int carry ;
int my_nib_cnt ;
int save_qtr_track ;
int save_nib_pos ;
int status ;
int i ;
save_qtr_track = dsk - > cur_qtr_track ;
save_nib_pos = dsk - > nib_pos ;
iwm_move_to_track ( dsk , qtr_track ) ;
dsk - > nib_pos = 0 ;
g_fast_disk_unnib = 1 ;
track_len = trk - > track_len ;
num_sectors = g_track_bytes_35 [ qtr_track > > 5 ] > > 9 ;
for ( i = 0 ; i < num_sectors ; i + + ) {
sector_done [ i ] = 0 ;
}
num_sectors_done = 0 ;
val = 0 ;
status = - 1 ;
my_nib_cnt = 0 ;
track = qtr_track > > 1 ;
side = qtr_track & 1 ;
while ( my_nib_cnt + + < 2 * track_len ) {
/* look for start of a sector */
if ( val ! = 0xd5 ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xaa ) {
continue ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0x96 ) {
continue ;
}
/* It's a sector start */
val = iwm_read_data ( dsk , 1 , 0 ) ;
phys_track = from_disk_byte [ val ] ;
if ( phys_track ! = ( track & 0x3f ) ) {
printf ( " Track %02x.%d, read track %02x, %02x \n " ,
track , side , phys_track , val ) ;
break ;
}
phys_sec = from_disk_byte [ iwm_read_data ( dsk , 1 , 0 ) ] ;
if ( phys_sec < 0 | | phys_sec > = num_sectors ) {
printf ( " Track %02x.%d, read sector %02x?? \n " ,
track , side , phys_sec ) ;
break ;
}
phys_side = from_disk_byte [ iwm_read_data ( dsk , 1 , 0 ) ] ;
if ( phys_side ! = ( ( side < < 5 ) + ( track > > 6 ) ) ) {
printf ( " Track %02x.%d, read side %02x?? \n " ,
track , side , phys_side ) ;
break ;
}
phys_capacity = from_disk_byte [ iwm_read_data ( dsk , 1 , 0 ) ] ;
if ( phys_capacity ! = 0x24 & & phys_capacity ! = 0x22 ) {
printf ( " Track %02x.%x capacity: %02x != 0x24/22 \n " ,
track , side , phys_capacity ) ;
}
cksum = from_disk_byte [ iwm_read_data ( dsk , 1 , 0 ) ] ;
tmp = phys_track ^ phys_sec ^ phys_side ^ phys_capacity ;
if ( cksum ! = tmp ) {
printf ( " Track %02x.%d, sector %02x, cksum: %02x.%02x \n " ,
track , side , phys_sec , cksum , tmp ) ;
break ;
}
if ( sector_done [ phys_sec ] ) {
printf ( " Already done sector %02x on track %02x.%x! \n " ,
phys_sec , track , side ) ;
break ;
}
/* So far so good, let's do it! */
val = 0 ;
for ( i = 0 ; i < 38 ; i + + ) {
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val = = 0xd5 ) {
break ;
}
}
if ( val ! = 0xd5 ) {
printf ( " No data header, track %02x.%x, sec %02x \n " ,
track , side , phys_sec ) ;
break ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xaa ) {
printf ( " Bad data hdr1,val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
printf ( " nib_pos: %08x \n " , dsk - > nib_pos ) ;
break ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xad ) {
printf ( " Bad data hdr2,val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
buf = outbuf + ( phys_sec < < 9 ) ;
/* check sector again */
val = from_disk_byte [ iwm_read_data ( dsk , 1 , 0 ) ] ;
if ( val ! = phys_sec ) {
printf ( " Bad data hdr3,val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
/* Data start! */
tmp_5c = 0 ;
tmp_5d = 0 ;
tmp_5e = 0 ;
y = 0xaf ;
carry = 0 ;
while ( y > 0 ) {
/* 626f */
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
if ( val2 < 0 ) {
printf ( " Bad data area1b, read: %02x \n " , val ) ;
printf ( " i:%03x,n_pos:%04x \n " , i , dsk - > nib_pos ) ;
break ;
}
tmp_66 = val2 ;
tmp_5c = tmp_5c < < 1 ;
carry = ( tmp_5c > > 8 ) ;
tmp_5c = ( tmp_5c + carry ) & 0xff ;
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
if ( val2 < 0 ) {
printf ( " Bad data area2, read: %02x \n " , val ) ;
break ;
}
val2 = val2 + ( ( tmp_66 < < 2 ) & 0xc0 ) ;
val2 = val2 ^ tmp_5c ;
buf_c00 [ y ] = val2 ;
tmp_5e = val2 + tmp_5e + carry ;
carry = ( tmp_5e > > 8 ) ;
tmp_5e = tmp_5e & 0xff ;
/* 62b8 */
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
val2 = val2 + ( ( tmp_66 < < 4 ) & 0xc0 ) ;
val2 = val2 ^ tmp_5e ;
buf_d00 [ y ] = val2 ;
tmp_5d = val2 + tmp_5d + carry ;
carry = ( tmp_5d > > 8 ) ;
tmp_5d = tmp_5d & 0xff ;
y - - ;
if ( y < = 0 ) {
break ;
}
/* 6274 */
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
val2 = val2 + ( ( tmp_66 < < 6 ) & 0xc0 ) ;
val2 = val2 ^ tmp_5d ;
buf_e00 [ y + 1 ] = val2 ;
tmp_5c = val2 + tmp_5c + carry ;
carry = ( tmp_5c > > 8 ) ;
tmp_5c = tmp_5c & 0xff ;
}
/* 62d0 */
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] ;
tmp_66 = ( val2 < < 6 ) & 0xc0 ;
tmp_67 = ( val2 < < 4 ) & 0xc0 ;
val2 = ( val2 < < 2 ) & 0xc0 ;
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] + val2 ;
if ( tmp_5e ! = ( word32 ) val2 ) {
printf ( " Checksum 5e bad: %02x vs %02x \n " , tmp_5e , val2 ) ;
printf ( " val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] + tmp_67 ;
if ( tmp_5d ! = ( word32 ) val2 ) {
printf ( " Checksum 5d bad: %02x vs %02x \n " , tmp_5e , val2 ) ;
printf ( " val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
val2 = from_disk_byte [ val ] + tmp_66 ;
if ( tmp_5c ! = ( word32 ) val2 ) {
printf ( " Checksum 5c bad: %02x vs %02x \n " , tmp_5e , val2 ) ;
printf ( " val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
/* Whew, got it!...check for DE AA */
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xde ) {
printf ( " Bad data epi1,val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
printf ( " nib_pos: %08x \n " , dsk - > nib_pos ) ;
break ;
}
val = iwm_read_data ( dsk , 1 , 0 ) ;
if ( val ! = 0xaa ) {
printf ( " Bad data epi2,val:%02x trk %02x.%x, sec %02x \n " ,
val , track , side , phys_sec ) ;
break ;
}
/* Now, convert buf_c/d/e to output */
/* 6459 */
y = 0 ;
for ( x = 0xab ; x > = 0 ; x - - ) {
* buf + + = buf_c00 [ x ] ;
y + + ;
if ( y > = 0x200 ) {
break ;
}
* buf + + = buf_d00 [ x ] ;
y + + ;
if ( y > = 0x200 ) {
break ;
}
* buf + + = buf_e00 [ x ] ;
y + + ;
if ( y > = 0x200 ) {
break ;
}
}
sector_done [ phys_sec ] = 1 ;
num_sectors_done + + ;
if ( num_sectors_done > = num_sectors ) {
status = 0 ;
break ;
}
val = 0 ;
}
if ( status < 0 ) {
printf ( " dsk->nib_pos: %04x, status: %d \n " , dsk - > nib_pos ,
status ) ;
for ( i = 0 ; i < num_sectors ; i + + ) {
printf ( " sector done[%d] = %d \n " , i , sector_done [ i ] ) ;
}
}
iwm_move_to_track ( dsk , save_qtr_track ) ;
dsk - > nib_pos = save_nib_pos ;
g_fast_disk_unnib = 0 ;
if ( status = = 0 ) {
return 1 ;
}
printf ( " Nibblization not done, %02x sectors found on track %02x \n " ,
num_sectors_done , qtr_track > > 2 ) ;
return - 1 ;
}
/* ret = 1 -> dirty data written out */
/* ret = 0 -> not dirty, no error */
/* ret < 0 -> error */
int
disk_track_to_unix ( Disk * dsk , int qtr_track , byte * outbuf )
{
int i ;
Trk * trk ;
int disk_525 ;
disk_525 = dsk - > disk_525 ;
trk = & ( dsk - > trks [ qtr_track ] ) ;
if ( trk - > track_len = = 0 | | trk - > track_dirty = = 0 ) {
return 0 ;
}
trk - > track_dirty = 0 ;
if ( ( qtr_track & 3 ) & & disk_525 ) {
halt_printf ( " You wrote to phase %02x! Can't wr bk to unix! \n " ,
qtr_track ) ;
dsk - > write_through_to_unix = 0 ;
return - 1 ;
}
2017-04-05 14:18:04 +00:00
if ( disk_525 )
2016-02-08 05:01:25 +00:00
{
// OG
// Add support for .nib file
if ( dsk - > image_type ! = DSK_TYPE_NIB )
2015-11-05 20:23:46 +00:00
return iwm_denib_track525 ( dsk , trk , qtr_track , outbuf ) ;
2016-02-08 05:01:25 +00:00
else
{
int len = trk - > track_len ;
byte * trk_ptr = trk - > nib_area + 1 ;
byte * nib_ptr = outbuf ;
2017-04-05 14:18:04 +00:00
for ( i = 0 ; i < len ; i + = 2 )
2016-02-08 05:01:25 +00:00
{
* nib_ptr + + = * trk_ptr ;
trk_ptr + = 2 ;
}
return 1 ;
}
2015-11-05 20:23:46 +00:00
} else {
return iwm_denib_track35 ( dsk , trk , qtr_track , outbuf ) ;
}
}
void
show_hex_data ( byte * buf , int count )
{
int i ;
for ( i = 0 ; i < count ; i + = 16 ) {
printf ( " %04x: %02x %02x %02x %02x %02x %02x %02x %02x "
" %02x %02x %02x %02x %02x %02x %02x %02x \n " , i ,
2017-04-05 14:18:04 +00:00
buf [ i + 0 ] , buf [ i + 1 ] , buf [ i + 2 ] , buf [ i + 3 ] ,
buf [ i + 4 ] , buf [ i + 5 ] , buf [ i + 6 ] , buf [ i + 7 ] ,
buf [ i + 8 ] , buf [ i + 9 ] , buf [ i + 10 ] , buf [ i + 11 ] ,
2015-11-05 20:23:46 +00:00
buf [ i + 12 ] , buf [ i + 13 ] , buf [ i + 14 ] , buf [ i + 15 ] ) ;
}
}
void
disk_check_nibblization ( Disk * dsk , int qtr_track , byte * buf , int size )
{
byte buffer [ 0x3000 ] ;
Trk * trk ;
int ret , ret2 ;
int i ;
if ( size > 0x3000 ) {
printf ( " size %08x is > 0x3000, disk_check_nibblization \n " , size ) ;
exit ( 3 ) ;
}
for ( i = 0 ; i < size ; i + + ) {
buffer [ i ] = 0 ;
}
trk = & ( dsk - > trks [ qtr_track ] ) ;
if ( dsk - > disk_525 ) {
ret = iwm_denib_track525 ( dsk , trk , qtr_track , & ( buffer [ 0 ] ) ) ;
} else {
ret = iwm_denib_track35 ( dsk , trk , qtr_track , & ( buffer [ 0 ] ) ) ;
}
ret2 = - 1 ;
for ( i = 0 ; i < size ; i + + ) {
if ( buffer [ i ] ! = buf [ i ] ) {
printf ( " buffer[%04x]: %02x != %02x \n " , i , buffer [ i ] ,
buf [ i ] ) ;
ret2 = i ;
break ;
}
}
if ( ret ! = 1 | | ret2 > = 0 ) {
printf ( " disk_check_nib ret:%d, ret2:%d for q_track %03x \n " ,
ret , ret2 , qtr_track ) ;
show_hex_data ( buf , 0x1000 ) ;
show_hex_data ( buffer , 0x1000 ) ;
iwm_show_a_track ( & ( dsk - > trks [ qtr_track ] ) ) ;
exit ( 2 ) ;
}
}
# define TRACK_BUF_LEN 0x2000
void
disk_unix_to_nib ( Disk * dsk , int qtr_track , int unix_pos , int unix_len ,
int nib_len )
{
byte track_buf [ TRACK_BUF_LEN ] ;
Trk * trk ;
int must_clear_track ;
int ret ;
int len ;
int i ;
2017-04-05 14:18:04 +00:00
2015-11-05 20:23:46 +00:00
/* Read track from dsk int track_buf */
must_clear_track = 0 ;
if ( unix_len > TRACK_BUF_LEN ) {
printf ( " diks_unix_to_nib: requested len of image %s = %05x \n " ,
dsk - > name_ptr , unix_len ) ;
}
if ( unix_pos > = 0 ) {
ret = fseek ( dsk - > file , unix_pos , SEEK_SET ) ;
if ( ret ! = 0 ) {
printf ( " fseek of disk %s len 0x%x errno: %d \n " ,
dsk - > name_ptr , unix_pos , errno ) ;
must_clear_track = 1 ;
}
len = fread ( track_buf , 1 , unix_len , dsk - > file ) ;
if ( len ! = unix_len ) {
printf ( " read of disk %s q_trk %d ret: %d, errno: %d \n " ,
dsk - > name_ptr , qtr_track , ret , errno ) ;
must_clear_track = 1 ;
}
}
if ( must_clear_track ) {
for ( i = 0 ; i < TRACK_BUF_LEN ; i + + ) {
track_buf [ i ] = 0 ;
}
}
#if 0
printf ( " Q_track %02x dumped out \n " , qtr_track ) ;
for ( i = 0 ; i < 4096 ; i + = 32 ) {
printf ( " %04x: %02x%02x%02x%02x%02x%02x%02x%02x "
" %02x%02x%02x%02x%02x%02x%02x%02x "
" %02x%02x%02x%02x%02x%02x%02x%02x "
" %02x%02x%02x%02x%02x%02x%02x%02x \n " , i ,
track_buf [ i + 0 ] , track_buf [ i + 1 ] , track_buf [ i + 2 ] ,
track_buf [ i + 3 ] , track_buf [ i + 4 ] , track_buf [ i + 5 ] ,
track_buf [ i + 6 ] , track_buf [ i + 7 ] , track_buf [ i + 8 ] ,
track_buf [ i + 9 ] , track_buf [ i + 10 ] , track_buf [ i + 11 ] ,
track_buf [ i + 12 ] , track_buf [ i + 13 ] , track_buf [ i + 14 ] ,
track_buf [ i + 15 ] , track_buf [ i + 16 ] , track_buf [ i + 17 ] ,
track_buf [ i + 18 ] , track_buf [ i + 19 ] , track_buf [ i + 20 ] ,
track_buf [ i + 21 ] , track_buf [ i + 22 ] , track_buf [ i + 23 ] ,
track_buf [ i + 24 ] , track_buf [ i + 25 ] , track_buf [ i + 26 ] ,
track_buf [ i + 27 ] , track_buf [ i + 28 ] , track_buf [ i + 29 ] ,
track_buf [ i + 30 ] , track_buf [ i + 31 ] ) ;
}
# endif
dsk - > nib_pos = 0 ; /* for consistency */
trk = & ( dsk - > trks [ qtr_track ] ) ;
trk - > track_dirty = 0 ;
trk - > overflow_size = 0 ;
trk - > track_len = 2 * nib_len ;
trk - > unix_pos = unix_pos ;
trk - > unix_len = unix_len ;
trk - > dsk = dsk ;
trk - > nib_area = ( byte * ) malloc ( trk - > track_len ) ;
/* create nibblized image */
if ( dsk - > disk_525 & & dsk - > image_type = = DSK_TYPE_NIB ) {
iwm_nibblize_track_nib525 ( dsk , trk , track_buf , qtr_track ) ;
} else if ( dsk - > disk_525 ) {
iwm_nibblize_track_525 ( dsk , trk , track_buf , qtr_track ) ;
} else {
iwm_nibblize_track_35 ( dsk , trk , track_buf , qtr_track ) ;
}
}
void
iwm_nibblize_track_nib525 ( Disk * dsk , Trk * trk , byte * track_buf , int qtr_track )
{
byte * nib_ptr ;
byte * trk_ptr ;
int len ;
int i ;
len = trk - > track_len ;
trk_ptr = track_buf ;
nib_ptr = & ( trk - > nib_area [ 0 ] ) ;
for ( i = 0 ; i < len ; i + = 2 ) {
nib_ptr [ i ] = 8 ;
nib_ptr [ i + 1 ] = * trk_ptr + + ; ;
}
iwm_printf ( " Nibblized q_track %02x \n " , qtr_track ) ;
}
void
iwm_nibblize_track_525 ( Disk * dsk , Trk * trk , byte * track_buf , int qtr_track )
{
byte partial_nib_buf [ 0x300 ] ;
word32 * word_ptr ;
word32 val ;
word32 last_val ;
int phys_sec ;
int log_sec ;
int num_sync ;
int i ;
word_ptr = ( word32 * ) & ( trk - > nib_area [ 0 ] ) ;
2016-04-28 02:58:38 +00:00
# if defined(GSPLUS_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__) // OSX needs to calculate endianness mid-compilation, can't be passed on compile command
2015-11-05 20:23:46 +00:00
val = 0xff08ff08 ;
# else
val = 0x08ff08ff ;
# endif
for ( i = 0 ; i < trk - > track_len ; i + = 4 ) {
* word_ptr + + = val ;
}
for ( phys_sec = 0 ; phys_sec < 16 ; phys_sec + + ) {
if ( dsk - > image_type = = DSK_TYPE_DOS33 ) {
log_sec = phys_to_dos_sec [ phys_sec ] ;
} else {
log_sec = phys_to_prodos_sec [ phys_sec ] ;
}
/* Create sync headers */
if ( phys_sec = = 0 ) {
num_sync = 70 ;
} else {
num_sync = 14 ;
}
for ( i = 0 ; i < num_sync ; i + + ) {
disk_nib_out ( dsk , 0xff , 10 ) ;
}
disk_nib_out ( dsk , 0xd5 , 10 ) ; /* prolog */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* prolog */
disk_nib_out ( dsk , 0x96 , 8 ) ; /* prolog */
disk_4x4_nib_out ( dsk , dsk - > vol_num ) ;
disk_4x4_nib_out ( dsk , qtr_track > > 2 ) ;
disk_4x4_nib_out ( dsk , phys_sec ) ;
disk_4x4_nib_out ( dsk , dsk - > vol_num ^ ( qtr_track > > 2 ) ^ phys_sec ) ;
disk_nib_out ( dsk , 0xde , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xeb , 8 ) ; /* epi */
/* Inter sync */
disk_nib_out ( dsk , 0xff , 8 ) ;
for ( i = 0 ; i < 5 ; i + + ) {
disk_nib_out ( dsk , 0xff , 10 ) ;
}
disk_nib_out ( dsk , 0xd5 , 10 ) ; /* data prolog */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* data prolog */
disk_nib_out ( dsk , 0xad , 8 ) ; /* data prolog */
sector_to_partial_nib ( & ( track_buf [ log_sec * 256 ] ) ,
& ( partial_nib_buf [ 0 ] ) ) ;
last_val = 0 ;
for ( i = 0 ; i < 0x156 ; i + + ) {
val = partial_nib_buf [ i ] ;
disk_nib_out ( dsk , to_disk_byte [ last_val ^ val ] , 8 ) ;
last_val = val ;
}
disk_nib_out ( dsk , to_disk_byte [ last_val ] , 8 ) ;
/* data epilog */
disk_nib_out ( dsk , 0xde , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xeb , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xff , 8 ) ;
for ( i = 0 ; i < 6 ; i + + ) {
disk_nib_out ( dsk , 0xff , 10 ) ;
}
}
/* finish nibblization */
disk_nib_end_track ( dsk ) ;
iwm_printf ( " Nibblized q_track %02x \n " , qtr_track ) ;
if ( g_check_nibblization ) {
disk_check_nibblization ( dsk , qtr_track , & ( track_buf [ 0 ] ) , 0x1000 ) ;
}
}
void
iwm_nibblize_track_35 ( Disk * dsk , Trk * trk , byte * track_buf , int qtr_track )
{
int phys_to_log_sec [ 16 ] ;
word32 buf_c00 [ 0x100 ] ;
word32 buf_d00 [ 0x100 ] ;
word32 buf_e00 [ 0x100 ] ;
byte * buf ;
word32 * word_ptr ;
word32 val ;
int num_sectors ;
int unix_len ;
int log_sec ;
int phys_sec ;
int track ;
int side ;
int interleave ;
int num_sync ;
word32 phys_track , phys_side , capacity , cksum ;
word32 tmp_5c , tmp_5d , tmp_5e , tmp_5f ;
word32 tmp_63 , tmp_64 , tmp_65 ;
word32 acc_hi ;
int carry ;
int x , y ;
int i ;
word_ptr = ( word32 * ) & ( trk - > nib_area [ 0 ] ) ;
2016-04-28 02:58:38 +00:00
# if defined(GSPLUS_LITTLE_ENDIAN) || defined (__LITTLE_ENDIAN__)
2015-11-05 20:23:46 +00:00
val = 0xff08ff08 ;
# else
val = 0x08ff08ff ;
# endif
if ( trk - > track_len & 3 ) {
halt_printf ( " track_len: %08x is not a multiple of 4 \n " ,
trk - > track_len ) ;
}
for ( i = 0 ; i < trk - > track_len ; i + = 4 ) {
* word_ptr + + = val ;
}
unix_len = trk - > unix_len ;
num_sectors = ( unix_len > > 9 ) ;
for ( i = 0 ; i < num_sectors ; i + + ) {
phys_to_log_sec [ i ] = - 1 ;
}
phys_sec = 0 ;
interleave = 2 ;
for ( log_sec = 0 ; log_sec < num_sectors ; log_sec + + ) {
while ( phys_to_log_sec [ phys_sec ] > = 0 ) {
phys_sec + + ;
if ( phys_sec > = num_sectors ) {
phys_sec = 0 ;
}
}
phys_to_log_sec [ phys_sec ] = log_sec ;
phys_sec + = interleave ;
if ( phys_sec > = num_sectors ) {
phys_sec - = num_sectors ;
}
}
track = qtr_track > > 1 ;
side = qtr_track & 1 ;
for ( phys_sec = 0 ; phys_sec < num_sectors ; phys_sec + + ) {
log_sec = phys_to_log_sec [ phys_sec ] ;
if ( log_sec < 0 ) {
printf ( " Track: %02x.%x phys_sec: %02x = %d! \n " ,
track , side , phys_sec , log_sec ) ;
exit ( 2 ) ;
}
/* Create sync headers */
if ( phys_sec = = 0 ) {
num_sync = 400 ;
} else {
num_sync = 54 ;
}
for ( i = 0 ; i < num_sync ; i + + ) {
disk_nib_out ( dsk , 0xff , 10 ) ;
}
disk_nib_out ( dsk , 0xd5 , 10 ) ; /* prolog */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* prolog */
disk_nib_out ( dsk , 0x96 , 8 ) ; /* prolog */
phys_track = track & 0x3f ;
phys_side = ( side < < 5 ) + ( track > > 6 ) ;
capacity = 0x22 ;
disk_nib_out ( dsk , to_disk_byte [ phys_track ] , 8 ) ; /* trk */
disk_nib_out ( dsk , to_disk_byte [ log_sec ] , 8 ) ; /* sec */
disk_nib_out ( dsk , to_disk_byte [ phys_side ] , 8 ) ; /* sides+trk */
disk_nib_out ( dsk , to_disk_byte [ capacity ] , 8 ) ; /* capacity*/
cksum = ( phys_track ^ log_sec ^ phys_side ^ capacity ) & 0x3f ;
disk_nib_out ( dsk , to_disk_byte [ cksum ] , 8 ) ; /* cksum*/
disk_nib_out ( dsk , 0xde , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* epi */
/* Inter sync */
for ( i = 0 ; i < 5 ; i + + ) {
disk_nib_out ( dsk , 0xff , 10 ) ;
}
disk_nib_out ( dsk , 0xd5 , 10 ) ; /* data prolog */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* data prolog */
disk_nib_out ( dsk , 0xad , 8 ) ; /* data prolog */
disk_nib_out ( dsk , to_disk_byte [ log_sec ] , 8 ) ; /* sec again */
/* do nibblizing! */
buf = track_buf + ( log_sec < < 9 ) ;
/* 6320 */
tmp_5e = 0 ;
tmp_5d = 0 ;
tmp_5c = 0 ;
y = 0 ;
x = 0xaf ;
buf_c00 [ 0 ] = 0 ;
buf_d00 [ 0 ] = 0 ;
buf_e00 [ 0 ] = 0 ;
buf_e00 [ 1 ] = 0 ;
for ( y = 0x4 ; y > 0 ; y - - ) {
buf_c00 [ x ] = 0 ;
buf_d00 [ x ] = 0 ;
buf_e00 [ x ] = 0 ;
x - - ;
}
while ( x > = 0 ) {
/* 6338 */
tmp_5c = tmp_5c < < 1 ;
carry = ( tmp_5c > > 8 ) ;
tmp_5c = ( tmp_5c + carry ) & 0xff ;
val = buf [ y ] ;
tmp_5e = val + tmp_5e + carry ;
carry = ( tmp_5e > > 8 ) ;
tmp_5e = tmp_5e & 0xff ;
val = val ^ tmp_5c ;
buf_c00 [ x ] = val ;
y + + ;
/* 634c */
val = buf [ y ] ;
tmp_5d = tmp_5d + val + carry ;
carry = ( tmp_5d > > 8 ) ;
tmp_5d = tmp_5d & 0xff ;
val = val ^ tmp_5e ;
buf_d00 [ x ] = val ;
y + + ;
x - - ;
if ( x < = 0 ) {
break ;
}
/* 632a */
val = buf [ y ] ;
tmp_5c = tmp_5c + val + carry ;
carry = ( tmp_5c > > 8 ) ;
tmp_5c = tmp_5c & 0xff ;
val = val ^ tmp_5d ;
buf_e00 [ x + 1 ] = val ;
y + + ;
}
/* 635f */
val = ( ( tmp_5c > > 2 ) ^ tmp_5d ) & 0x3f ;
/* 6367 */
val = ( val ^ tmp_5d ) > > 2 ;
/* 636b */
val = ( val ^ tmp_5e ) & 0x3f ;
/* 636f */
val = ( val ^ tmp_5e ) > > 2 ;
/* 6373 */
tmp_5f = val ;
/* 6375 */
tmp_63 = 0 ;
tmp_64 = 0 ;
tmp_65 = 0 ;
acc_hi = 0 ;
y = 0xae ;
while ( y > = 0 ) {
/* 63e4 */
/* write out acc_hi */
val = to_disk_byte [ acc_hi & 0x3f ] ;
disk_nib_out ( dsk , val , 8 ) ;
/* 63f2 */
val = to_disk_byte [ tmp_63 & 0x3f ] ;
tmp_63 = buf_c00 [ y ] ;
acc_hi = tmp_63 > > 6 ;
disk_nib_out ( dsk , val , 8 ) ;
/* 640b */
val = to_disk_byte [ tmp_64 & 0x3f ] ;
tmp_64 = buf_d00 [ y ] ;
acc_hi = ( acc_hi < < 2 ) + ( tmp_64 > > 6 ) ;
disk_nib_out ( dsk , val , 8 ) ;
y - - ;
if ( y < 0 ) {
break ;
}
/* 63cb */
val = to_disk_byte [ tmp_65 & 0x3f ] ;
tmp_65 = buf_e00 [ y + 1 ] ;
acc_hi = ( acc_hi < < 2 ) + ( tmp_65 > > 6 ) ;
disk_nib_out ( dsk , val , 8 ) ;
}
/* 6429 */
val = to_disk_byte [ tmp_5f & 0x3f ] ;
disk_nib_out ( dsk , val , 8 ) ;
val = to_disk_byte [ tmp_5e & 0x3f ] ;
disk_nib_out ( dsk , val , 8 ) ;
val = to_disk_byte [ tmp_5d & 0x3f ] ;
disk_nib_out ( dsk , val , 8 ) ;
val = to_disk_byte [ tmp_5c & 0x3f ] ;
disk_nib_out ( dsk , val , 8 ) ;
/* 6440 */
/* data epilog */
disk_nib_out ( dsk , 0xde , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xaa , 8 ) ; /* epi */
disk_nib_out ( dsk , 0xff , 8 ) ;
}
disk_nib_end_track ( dsk ) ;
if ( g_check_nibblization ) {
disk_check_nibblization ( dsk , qtr_track , & ( track_buf [ 0 ] ) ,
unix_len ) ;
}
}
void
disk_4x4_nib_out ( Disk * dsk , word32 val )
{
disk_nib_out ( dsk , 0xaa | ( val > > 1 ) , 8 ) ;
disk_nib_out ( dsk , 0xaa | val , 8 ) ;
}
void
disk_nib_out ( Disk * dsk , byte val , int size )
{
Trk * trk ;
int pos ;
int old_size ;
int track_len ;
int overflow_size ;
int qtr_track ;
qtr_track = dsk - > cur_qtr_track ;
track_len = 0 ;
trk = 0 ;
if ( dsk - > trks ! = 0 ) {
trk = & ( dsk - > trks [ qtr_track ] ) ;
track_len = trk - > track_len ;
}
if ( track_len < = 10 ) {
printf ( " Writing to an invalid qtr track: %02x! \n " , qtr_track ) ;
printf ( " name: %s, track_len: %08x, val: %08x, size: %d \n " ,
dsk - > name_ptr , track_len , val , size ) ;
exit ( 1 ) ;
return ;
}
trk - > track_dirty = 1 ;
dsk - > disk_dirty = 1 ;
pos = trk - > dsk - > nib_pos ;
overflow_size = trk - > overflow_size ;
if ( pos > = track_len ) {
pos = 0 ;
}
old_size = trk - > nib_area [ pos ] ;
while ( size > = ( 10 + old_size ) ) {
size = size - old_size ;
pos + = 2 ;
if ( pos > = track_len ) {
pos = 0 ;
}
old_size = trk - > nib_area [ pos ] ;
}
if ( size > 10 ) {
size = 10 ;
}
if ( ( val & 0x80 ) = = 0 ) {
val | = 0x80 ;
}
trk - > nib_area [ pos + + ] = size ;
trk - > nib_area [ pos + + ] = val ;
if ( pos > = track_len ) {
pos = 0 ;
}
overflow_size + = ( size - old_size ) ;
if ( ( overflow_size > 8 ) & & ( size > 8 ) ) {
overflow_size - = trk - > nib_area [ pos ] ;
trk - > nib_area [ pos + + ] = 0 ;
trk - > nib_area [ pos + + ] = 0 ;
if ( pos > = track_len ) {
pos = 0 ;
}
} else if ( overflow_size < - 64 ) {
halt_printf ( " overflow_sz:%03x, pos:%02x \n " , overflow_size , pos ) ;
}
trk - > dsk - > nib_pos = pos ;
trk - > overflow_size = overflow_size ;
if ( ( val & 0x80 ) = = 0 | | size < 8 ) {
halt_printf ( " disk_nib_out, wrote %02x, size: %d \n " , val , size ) ;
}
}
void
disk_nib_end_track ( Disk * dsk )
{
int qtr_track ;
dsk - > nib_pos = 0 ;
qtr_track = dsk - > cur_qtr_track ;
dsk - > trks [ qtr_track ] . track_dirty = 0 ;
dsk - > disk_dirty = 0 ;
}
void
iwm_show_track ( int slot_drive , int track )
{
Disk * dsk ;
Trk * trk ;
int drive ;
int sel35 ;
int qtr_track ;
if ( slot_drive < 0 ) {
drive = iwm . drive_select ;
sel35 = ( g_c031_disk35 > > 6 ) & 1 ;
} else {
drive = slot_drive & 1 ;
sel35 = ! ( ( slot_drive > > 1 ) & 1 ) ;
}
2017-04-05 14:18:04 +00:00
2015-11-05 20:23:46 +00:00
if ( sel35 ) {
dsk = & ( iwm . drive35 [ drive ] ) ;
} else {
dsk = & ( iwm . drive525 [ drive ] ) ;
}
if ( track < 0 ) {
qtr_track = dsk - > cur_qtr_track ;
} else {
qtr_track = track ;
}
if ( dsk - > trks = = 0 ) {
return ;
}
trk = & ( dsk - > trks [ qtr_track ] ) ;
if ( trk - > track_len < = 0 ) {
printf ( " Track_len: %d \n " , trk - > track_len ) ;
printf ( " No track for type: %d, drive: %d, qtrk: 0x%02x \n " ,
sel35 , drive , qtr_track ) ;
return ;
}
printf ( " Current drive: %d, q_track: 0x%02x \n " , drive , qtr_track ) ;
iwm_show_a_track ( trk ) ;
}
void
iwm_show_a_track ( Trk * trk )
{
int sum ;
int len ;
int pos ;
int i ;
printf ( " Showtrack:dirty: %d, pos: %04x, ovfl: %04x, len: %04x \n " ,
trk - > track_dirty , trk - > dsk - > nib_pos ,
trk - > overflow_size , trk - > track_len ) ;
len = trk - > track_len ;
printf ( " Track len in bytes: %04x \n " , len ) ;
if ( len > = 2 * 15000 ) {
len = 2 * 15000 ;
printf ( " len too big, using %04x \n " , len ) ;
}
pos = 0 ;
for ( i = 0 ; i < len ; i + = 16 ) {
printf ( " %04x: %2d,%02x %2d,%02x %2d,%02x %2d,%02x "
" %2d,%02x %2d,%02x %2d,%02x %2d,%02x \n " , pos ,
trk - > nib_area [ pos ] , trk - > nib_area [ pos + 1 ] ,
trk - > nib_area [ pos + 2 ] , trk - > nib_area [ pos + 3 ] ,
trk - > nib_area [ pos + 4 ] , trk - > nib_area [ pos + 5 ] ,
trk - > nib_area [ pos + 6 ] , trk - > nib_area [ pos + 7 ] ,
trk - > nib_area [ pos + 8 ] , trk - > nib_area [ pos + 9 ] ,
trk - > nib_area [ pos + 10 ] , trk - > nib_area [ pos + 11 ] ,
trk - > nib_area [ pos + 12 ] , trk - > nib_area [ pos + 13 ] ,
trk - > nib_area [ pos + 14 ] , trk - > nib_area [ pos + 15 ] ) ;
pos + = 16 ;
if ( pos > = len ) {
pos - = len ;
}
}
sum = 0 ;
for ( i = 0 ; i < len ; i + = 2 ) {
sum + = trk - > nib_area [ i ] ;
}
printf ( " bit_sum: %d, expected: %d, overflow_size: %d \n " ,
sum , len * 8 / 2 , trk - > overflow_size ) ;
}