Skip to content

Commit

Permalink
enable pasopt.com to work for Pascal/Z with a hack. Also, minor cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidly committed Jul 19, 2024
1 parent 12a2303 commit 3108199
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 41 deletions.
22 changes: 14 additions & 8 deletions ntvcm.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ struct FCB
{
this->r0 = ( 0xff & o );
this->r1 = ( ( o & 0xff00 ) >> 8 );
this->r2 = 0;
// unused in cp/m 2.2 this->r2 = 0;
} //SetRandomIOOffset

void SetRecordCount( FILE * fp )
Expand Down Expand Up @@ -153,7 +153,7 @@ struct FCB

void Trace( bool justArg = false ) // justArg is the first 16 bytes at app startup
{
tracer.Trace( " FCB:\n" );
tracer.Trace( " FCB at address %04x:\n", (uint32_t) ( (uint8_t * ) this - memory ) );
tracer.Trace( " drive: %#x == %c\n", dr, ( 0 == dr ) ? 'A' : 'A' + dr - 1 );
tracer.Trace( " filename: '%c%c%c%c%c%c%c%c'\n", 0x7f & f[0], 0x7f & f[1], 0x7f & f[2], 0x7f & f[3],
0x7f & f[4], 0x7f & f[5], 0x7f & f[6], 0x7f & f[7] );
Expand Down Expand Up @@ -460,7 +460,7 @@ bool parse_FCB_Filename( FCB * pfcb, char * pcFilename )

*pcFilename = 0;

// CP/M assumes all filenames are upper case. Linux users generally use all lowercase filenames
// CP/M assumes all filenames are uppercase. Linux users generally use all lowercase filenames

if ( g_forceLowercase )
_strlwr( orig );
Expand Down Expand Up @@ -516,7 +516,7 @@ FILE * RemoveFileEntry( char * name )
if ( !strcmp( name, g_fileEntries[ i ].acName ) )
{
FILE * fp = g_fileEntries[ i ].fp;
tracer.Trace( "removing file entry '%s'\n", name );
tracer.Trace( " removing file entry '%s'\n", name );
g_fileEntries.erase( g_fileEntries.begin() + i );
return fp;
}
Expand Down Expand Up @@ -2342,6 +2342,7 @@ uint8_t x80_invoke_hook()
case 22:
{
// make file. return 255 if out of space or the file exists. 0..3 directory code otherwise.
// "the Make function has the side effect of activating the FCB and thus a subsequent open is not necessary."

FCB * pfcb = (FCB *) ( memory + reg.D() );
pfcb->Trace();
Expand Down Expand Up @@ -2574,7 +2575,7 @@ uint8_t x80_invoke_hook()
bool ok = parse_FCB_Filename( pfcb, acFilename );
if ( ok )
{
pfcb->r2 = 0; // only supported in cp/m post version 2.2
//pfcb->r2 = 0; // only supported in cp/m post version 2.2

FILE * fp = FindFileEntry( acFilename );
bool found = false;
Expand Down Expand Up @@ -2612,7 +2613,7 @@ uint8_t x80_invoke_hook()
bool ok = parse_FCB_Filename( pfcb, acFilename );
if ( ok )
{
pfcb->r2 = 0;
// unused in cp/m 2.2: pfcb->r2 = 0;

FILE * fp = FindFileEntry( acFilename );
if ( fp )
Expand Down Expand Up @@ -3054,6 +3055,12 @@ int main( int argc, char * argv[] )
}
}

// The Pascal/Z compiler's pasopt.com optimizer has a bug that depends on uninitialized RAM
// being set to non-zero values. If the BDOS moves, this must move too or the app will fail.

if ( ends_with( acCOM, "pasopt.com" ) )
memset( memory + 0xf400, 0x69, 0x800 );

// setup command-line arguments

FCB * arg1 = (FCB *) ( memory + FCB_ARG1_OFFSET );
Expand Down Expand Up @@ -3159,15 +3166,14 @@ int main( int argc, char * argv[] )
pdpb->cks = 64;
pdpb->off = 0;

memory[ 0x100 + file_size ] = OPCODE_HLT; // in case the app doesn't shutdown properly
reg.powerOn(); // set default values of registers
reg.pc = 0x100;
reg.sp = BDOS_ENTRY - 2; // the stack is written to below this address. 2 bytes here are zero for ret from app
reg.a = reg.b = reg.c = reg.d = reg.e = reg.h = reg.l = 0;
reg.fp = reg.ap = 0; // apparently this is expected by CPUTEST
reg.bp = reg.cp = reg.dp = reg.ep = reg.hp = reg.lp = 0;
reg.ix = reg.iy = 0;

if ( trace )
{
x80_trace_state();
Expand Down
71 changes: 38 additions & 33 deletions x80.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ void op_cmc()
if ( reg.fZ80Mode )
{
reg.fWasSubtract = false;
reg.fAuxCarry = !reg.fCarry;
reg.fAuxCarry = !reg.fCarry; // some docs say !reg.fAuxCarry
reg.z80_assignYX( reg.a );
}
} //op_cmc
Expand Down Expand Up @@ -674,7 +674,6 @@ void z80_op_sla( uint8_t * pval )
uint8_t val = *pval;
reg.fCarry = ( 0 != ( val & 0x80 ) );
val <<= 1;
val &= 0xfe;
set_sign_zero_parity( val );
reg.clearHN();
reg.z80_assignYX( val );
Expand All @@ -698,7 +697,6 @@ void z80_op_sra( uint8_t * pval )
uint8_t val = *pval;
reg.fCarry = ( 0 != ( val & 1 ) );
val >>= 1;
val &= 0x7f;
val |= ( ( *pval ) & 0x80 ); // leave high bit unchanged
set_sign_zero_parity( val );
reg.clearHN();
Expand Down Expand Up @@ -849,6 +847,8 @@ uint16_t z80_emulate( uint8_t op ) // this is just for instructions that aren
{
cycles = 8;
uint8_t rm = op2 & 0x7;
if ( 6 == rm )
cycles += 4;
uint8_t bit = ( op2 >> 3 ) & 0x7;
uint8_t val = src_value_rm( rm );
z80_op_bit( val, bit, ( 6 == rm ) ? vs_memory : vs_register );
Expand All @@ -857,6 +857,8 @@ uint16_t z80_emulate( uint8_t op ) // this is just for instructions that aren
{
cycles = 8;
uint8_t rm = op2 & 0x7;
if ( 6 == rm )
cycles += 7;
uint8_t bit = ( op2 >> 3 ) & 0x7;
uint8_t val = src_value_rm( rm );
uint8_t mask = ~ ( 1 << bit );
Expand All @@ -867,6 +869,8 @@ uint16_t z80_emulate( uint8_t op ) // this is just for instructions that aren
{
cycles = 8;
uint8_t rm = op2 & 0x7;
if ( 6 == rm )
cycles += 7;
uint8_t bit = ( op2 >> 3 ) & 0x7;
uint8_t val = src_value_rm( rm );
uint8_t mask = 1 << bit;
Expand Down Expand Up @@ -1143,12 +1147,12 @@ uint16_t z80_emulate( uint8_t op ) // this is just for instructions that aren
reg.z80_setIndex( op, val );
}
else if ( 0xe3 == op2 ) // ex (sp), ix/iy
{
{
cycles = 23;
uint16_t val = reg.z80_getIndex( op );
reg.z80_setIndex( op, mword( reg.sp ) );
setmword( reg.sp, val );
}
}
else if ( 0xe5 == op2 ) // push ix/iy
{
cycles = 15;
Expand Down Expand Up @@ -1440,16 +1444,16 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
{
uint8_t src = op2 & 0x7;
if ( 6 == src )
snprintf( ac, bufferSize, "ld (%s%s%d), %02x", i, op3int >= 0 ? "+" : "", op3int, op4 );
snprintf( ac, bufferSize, "ld (%s%s%d),%02x", i, op3int >= 0 ? "+" : "", op3int, op4 );
else
snprintf( ac, bufferSize, "ld (%s%s%d), %s", i, op3int >= 0 ? "+" : "", op3int, reg_strings[ src ] );
snprintf( ac, bufferSize, "ld (%s%s%d),%s", i, op3int >= 0 ? "+" : "", op3int, reg_strings[ src ] );
}
else if ( 0x09 == ( op2 & 0xcf ) )
snprintf( ac, bufferSize, "add %s, %s", i, rp_strings[ ( op2 >> 4 ) & 0x3 ] );
snprintf( ac, bufferSize, "add %s,%s", i, rp_strings[ ( op2 >> 4 ) & 0x3 ] );
else if ( 0x21 == op2 )
snprintf( ac, bufferSize, "ld %s, %04xh", i, op34 );
snprintf( ac, bufferSize, "ld %s,%04xh", i, op34 );
else if ( 0x22 == op2 )
snprintf( ac, bufferSize, "ld (%04xh), %s", op34, i );
snprintf( ac, bufferSize, "ld (%04xh),%s", op34, i );
else if ( 0x23 == op2 )
snprintf( ac, bufferSize, "inc %s", i );
else if ( 0x26 == op2 )
Expand All @@ -1465,7 +1469,7 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
else if ( 0x35 == op2 )
snprintf( ac, bufferSize, "dec (%s%s%d)", i, op3int >= 0 ? "+" : "", op3int );
else if ( 0x36 == op2 )
snprintf( ac, bufferSize, "ld (%s%s%d), %#xh", i, op3int >= 0 ? "+" : "", op3int, op4 );
snprintf( ac, bufferSize, "ld (%s%s%d),%02xh", i, op3int >= 0 ? "+" : "", op3int, op4 );
else if ( ( op2 >= 0x40 && op2 <= 0x6f ) || ( op2 >= 0x78 && op2 <= 0x7f ) )
{
char acto[ 4 ] = {0};
Expand All @@ -1490,12 +1494,12 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
else
acto[0] = 'a';

snprintf( ac, bufferSize, "ld %s, %s", acto, acfrom );
snprintf( ac, bufferSize, "ld %s,%s", acto, acfrom );
}
else if ( 0x2a == op2 )
snprintf( ac, bufferSize, "ld %s, (%04x)", i, op34 );
snprintf( ac, bufferSize, "ld %s,(%04x)", i, op34 );
else if ( 0x22 == op2 )
snprintf( ac, bufferSize, "ld (%04x), %s", op34, i );
snprintf( ac, bufferSize, "ld (%04x),%s", op34, i );
else if ( 0x80 == ( op2 & 0xc2 ) ) // math on il and ih with a. 84/85/8c/8d/94/95/a4/a5/b4/b5/bc/bd
{
uint8_t math = ( ( op2 >> 3 ) & 0x7 );
Expand All @@ -1504,13 +1508,13 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
else if ( 0x86 == ( op2 & 0xc7 ) ) // math on [ ix/iy + index ]. 86, 8e, 96, 9e, a6, ae, b6, be
{
uint8_t math = ( ( op2 >> 3 ) & 0x7 );
snprintf( ac, bufferSize, "%s a, (%s%s%d)", z80_math_strings[ math ], i, op3int >=0 ? "+" : "", op3int );
snprintf( ac, bufferSize, "%s a,(%s%s%d)", z80_math_strings[ math ], i, op3int >=0 ? "+" : "", op3int );
}
else if ( 0xcb == op2 && ( op4 <= 0x3f ) )
{
uint8_t rot = ( ( op4 >> 3 ) & 0x7 );
int offset = (int) (int8_t) op3;
snprintf( ac, bufferSize, "%s %s, (%s%s%d)", z80_rotate_strings[ rot ], reg_strings[ op4 & 0x7 ], i, offset >= 0 ? "+" : "", offset );
snprintf( ac, bufferSize, "%s %s,(%s%s%d)", z80_rotate_strings[ rot ], reg_strings[ op4 & 0x7 ], i, offset >= 0 ? "+" : "", offset );
}
else if ( 0xcb == op2 && ( ( ( op4 & 0xf ) == 0xe ) || ( ( op4 & 0xf ) == 0x6 ) ) ) // bit operations on indexed memory
{
Expand All @@ -1521,11 +1525,11 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
uint8_t top2bits = mod & 0xc0;

if ( 0x40 == top2bits ) // bit
snprintf( ac, bufferSize, "bit %u, ( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
snprintf( ac, bufferSize, "bit %u,( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
else if ( 0x80 == top2bits ) // reset
snprintf( ac, bufferSize, "res %u, ( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
snprintf( ac, bufferSize, "res %u,( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
else if ( 0xc0 == top2bits ) // set
snprintf( ac, bufferSize, "set %u, ( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
snprintf( ac, bufferSize, "set %u,( %s%s%d )", bit, i, index32 >= 0 ? "+" : "", index32 );
else if ( 0x26 == op4 ) // sla
snprintf( ac, bufferSize, "sla (%s%s%d)", i, index32 >= 0 ? "+" : "", index32 );
else if ( 0x2e == op4 ) // sra
Expand Down Expand Up @@ -1555,16 +1559,16 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
else if ( 0xe9 == op2 )
snprintf( ac, bufferSize, "jp (%s)", i ); // this official syntax is bad; it's not indirect
else if ( 0xf9 == op2 )
snprintf( ac, bufferSize, "ld sp, %s", i );
snprintf( ac, bufferSize, "ld sp,%s", i );
else
snprintf( ac, bufferSize, "unknown 0xdd / 0xfd instruction, op2 %2x", op2 );
}
else if ( 0xed == op ) // load and compare operations
{
if ( 0xb == ( op2 & 0xf ) )
snprintf( ac, bufferSize, "ld %s, (%04xh)", rp_strings[ ( ( op2 & 0xf0 ) >> 4 ) - 4 ], op34 );
snprintf( ac, bufferSize, "ld %s,(%04xh)", rp_strings[ ( ( op2 & 0xf0 ) >> 4 ) - 4 ], op34 );
else if ( 0x3 == ( op2 & 0xf ) )
snprintf( ac, bufferSize, "ld (%04xh), %s", op34, rp_strings[ ( ( op2 & 0xf0 ) >> 4 ) - 4 ] );
snprintf( ac, bufferSize, "ld (%04xh),%s", op34, rp_strings[ ( ( op2 & 0xf0 ) >> 4 ) - 4 ] );
else if ( 0x44 == op2 )
strcpy( ac, "neg" );
else if ( 0x47 == op2 )
Expand All @@ -1590,12 +1594,12 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
else if ( 0x02 == ( op2 & 0x8f ) )
{
uint8_t rp = ( ( ( op2 & 0x30 ) >> 4 ) & 3 );
snprintf( ac, bufferSize, "sbc hl, %s", rp_strings[ rp ] );
snprintf( ac, bufferSize, "sbc hl,%s", rp_strings[ rp ] );
}
else if ( 0x4a == ( op2 & 0xcf ) ) // adc hl, rp
{
uint8_t rp = ( ( op2 >> 4 ) & 3 );
snprintf( ac, bufferSize, "adc hl, %s", rp_strings[ rp ] );
snprintf( ac, bufferSize, "adc hl,%s", rp_strings[ rp ] );
}
else if ( 0xa1 == op2 )
strcpy( ac, "cpi" );
Expand Down Expand Up @@ -1648,37 +1652,39 @@ void z80_render( char * ac, size_t bufferSize, uint8_t op, uint16_t address )
{
uint8_t rm = op2 & 0x7;
uint8_t bit = ( op2 >> 3 ) & 0x7;
snprintf( ac, bufferSize, "bit %u, %s", bit, reg_strings[ rm ] );
snprintf( ac, bufferSize, "bit %u,%s", bit, reg_strings[ rm ] );
}
else if ( op2 >= 0x80 && op2 <= 0xbf ) // res bit #, rm
{
uint8_t rm = op2 & 0x7;
uint8_t bit = ( op2 >> 3 ) & 0x7;
snprintf( ac, bufferSize, "res %u, %s", bit, reg_strings[ rm ] );
snprintf( ac, bufferSize, "res %u,%s", bit, reg_strings[ rm ] );
}
else if ( op2 >= 0xc0 && op2 <= 0xff ) // set bit #, rm
{
uint8_t rm = op2 & 0x7;
uint8_t bit = ( op2 >> 3 ) & 0x7;
snprintf( ac, bufferSize, "set %u, %s", bit, reg_strings[ rm ] );
snprintf( ac, bufferSize, "set %u,%s", bit, reg_strings[ rm ] );
}
}
else if ( 0x08 == op )
strcpy( ac, "ex af, af'" );
strcpy( ac, "ex af,af'" );
else if ( 0x10 == op )
snprintf( ac, bufferSize, "djnz %d", op2int );
else if ( 0x18 == op )
snprintf( ac, bufferSize, "jr %d", op2int );
else if ( 0x20 == op )
snprintf( ac, bufferSize, "jr nz, %d", op2int );
snprintf( ac, bufferSize, "jr nz,%d", op2int );
else if ( 0x28 == op )
snprintf( ac, bufferSize, "jr z, %d", op2int );
snprintf( ac, bufferSize, "jr z,%d", op2int );
else if ( 0x30 == op )
snprintf( ac, bufferSize, "jr nc, %d", op2int );
snprintf( ac, bufferSize, "jr nc,%d", op2int );
else if ( 0x38 == op )
snprintf( ac, bufferSize, "jr c, %d", op2int );
snprintf( ac, bufferSize, "jr c,%d", op2int );
else if ( 0xd9 == op )
strcpy( ac, "exx" );
else
strcpy( ac, "unknown instruction" );
} //z80_render

void replace_with_num( char * pc, const char * psearch, uint16_t num, uint8_t width )
Expand Down Expand Up @@ -1728,7 +1734,6 @@ not_inlined void x80_trace_state()
uint8_t op3 = memory[ reg.pc + 2 ];
uint8_t op4 = memory[ reg.pc + 3 ];

// tracer.TraceBinaryData( memory + 0x1fe, 10, 4 );
if ( reg.fZ80Mode )
tracer.Trace( "pc %04x, op %02x, op2 %02x, op3 %02x, op4 %02x, a %02x, B %04x, D %04x, H %04x, ix %04x, iy %04x, sp %04x, %s, %s\n",
reg.pc, op, op2, op3, op4, reg.a, reg.B(), reg.D(), reg.H(), reg.ix, reg.iy, reg.sp,
Expand Down

0 comments on commit 3108199

Please sign in to comment.