Skip to content

Commit 200913b

Browse files
committed
add -f flag to take keystrokes from a text file for Z80 CamelForth v1.01, which can't read files
1 parent 7992e64 commit 200913b

File tree

1 file changed

+74
-10
lines changed

1 file changed

+74
-10
lines changed

ntvcm.cxx

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ static bool g_forceConsole = false;
218218
static bool g_forceLowercase = false;
219219
static bool g_backspaceToDel = false;
220220
static bool g_kayproToCP437 = false;
221+
static size_t g_fileInputOffset = 0;
222+
static vector<char> g_fileInputText;
221223

222224
enum terminal_escape { termVT100, termVT52, termKayproII };
223225
static terminal_escape g_termEscape = termVT100;
@@ -1523,13 +1525,26 @@ uint8_t map_input( uint8_t input )
15231525
return output;
15241526
} //map_input
15251527

1528+
char get_next_kbd_char()
1529+
{
1530+
if ( g_fileInputOffset < g_fileInputText.size() )
1531+
return g_fileInputText[ g_fileInputOffset++ ];
1532+
1533+
return (char) ConsoleConfiguration::portable_getch();
1534+
} //get_next_kbd_char
1535+
1536+
bool is_kbd_char_available()
1537+
{
1538+
return ( ( g_fileInputOffset < g_fileInputText.size() ) || g_consoleConfig.throttled_kbhit() );
1539+
} //is_kbd_char_available
1540+
15261541
bool cpm_read_console( char * buf, size_t bufsize, uint8_t & out_len )
15271542
{
15281543
char ch = 0;
15291544
out_len = 0;
15301545
while ( out_len < (uint8_t) bufsize )
15311546
{
1532-
ch = (char) ConsoleConfiguration::portable_getch();
1547+
ch = get_next_kbd_char();
15331548
tracer.Trace( " cpm_read_console read character %02x -- '%c'\n", ch, printable( ch ) );
15341549

15351550
// CP/M read console buffer treats these control characters as special: c, e, h, j, m, r, u, x
@@ -1669,15 +1684,15 @@ uint8_t x80_invoke_hook()
16691684
}
16701685
case 2: // const console status. A=0 if nothing available, A=0xff if a keystroke is available
16711686
{
1672-
if ( g_consoleConfig.throttled_kbhit() )
1687+
if ( is_kbd_char_available() )
16731688
reg.a = 0xff;
16741689
else
16751690
reg.a = 0;
16761691
break;
16771692
}
16781693
case 3: // conin. wait until the keyboard has a character and return it in a.
16791694
{
1680-
uint8_t input = (uint8_t) g_consoleConfig.portable_getch();
1695+
uint8_t input = (uint8_t) get_next_kbd_char();
16811696
tracer.Trace( " conin got %02xh from getch()\n", input );
16821697
reg.a = map_input( input );
16831698
tracer.Trace( " conin is returning %02xh = '%c'\n", reg.a, printable( reg.a ) );
@@ -1741,7 +1756,7 @@ uint8_t x80_invoke_hook()
17411756
{
17421757
// console input. echo input to console
17431758

1744-
uint8_t ch = (uint8_t) g_consoleConfig.portable_getch();
1759+
uint8_t ch = (uint8_t) get_next_kbd_char();
17451760
reg.a = map_input( ch );
17461761
set_bdos_status();
17471762
tracer.Trace( " bdos console in: %02x == '%c'\n", ch, printable( ch ) );
@@ -1769,7 +1784,7 @@ uint8_t x80_invoke_hook()
17691784
{
17701785
// reader input. aka raw console input. I haven't found an app that uses this yet.
17711786

1772-
uint8_t ch = (uint8_t) g_consoleConfig.portable_getch();
1787+
uint8_t ch = (uint8_t) get_next_kbd_char();
17731788
reg.a = map_input( ch );
17741789
set_bdos_status();
17751790
tracer.Trace( " bdos reader input / raw console in: %02x == '%c'\n", ch, printable( ch ) );
@@ -1793,10 +1808,10 @@ uint8_t x80_invoke_hook()
17931808

17941809
if ( 0xff == reg.e )
17951810
{
1796-
if ( g_consoleConfig.throttled_kbhit() )
1811+
if ( is_kbd_char_available() )
17971812
{
17981813
kbd_poll_busyloops = 0;
1799-
uint8_t input = (uint8_t) g_consoleConfig.portable_getch();
1814+
uint8_t input = (uint8_t) get_next_kbd_char();
18001815
tracer.Trace( " read character %u == %02x == '%c'\n", input, input, printable( input ) );
18011816
reg.a = map_input( input );
18021817
}
@@ -1890,7 +1905,7 @@ uint8_t x80_invoke_hook()
18901905
{
18911906
// get console status. return A=0 if no characters are waiting or non-zero if a character is waiting
18921907

1893-
if ( g_consoleConfig.throttled_kbhit() )
1908+
if ( is_kbd_char_available() )
18941909
reg.a = 0xff;
18951910
else
18961911
reg.a = 0;
@@ -2762,8 +2777,9 @@ void usage( char const * perr = 0 )
27622777
printf( " -c never auto-detect ESC characters and change to to 80x24 mode\n" );
27632778
printf( " -C always switch to 80x24 mode (Windows only)\n" );
27642779
printf( " -d don't clear the display on app exit when in 80x24 mode\n" );
2780+
printf( " -f:<file> plain text file of characters fed to the app as keystrokes.\n" );
27652781
printf( " -i trace 8080/Z80 instructions when tracing with -t\n" );
2766-
printf( " -k translate Kaypro II extended characters to Windows code page 437 or Linux ascii art\n" );
2782+
printf( " -k translate Kaypro II extended characters to approximate native characters\n" );
27672783
printf( " -l force CP/M filenames to be lowercase (can be useful on Linux)\n" );
27682784
printf( " -p show performance information at app exit\n" );
27692785
printf( " -s:X speed in Hz. Default is 0, which is as fast as possible.\n" );
@@ -2787,6 +2803,40 @@ void usage( char const * perr = 0 )
27872803
exit( -1 );
27882804
} //usage
27892805

2806+
static void load_input_file_text( const char * file_path )
2807+
{
2808+
FILE * fp = fopen( file_path, "rb" );
2809+
if ( !fp )
2810+
usage( "-f file not found" );
2811+
CFile thefile( fp );
2812+
2813+
size_t file_size = portable_filelen( fp );
2814+
vector<char> original;
2815+
original.resize( file_size );
2816+
bool ok = ( 1 == fread( original.data(), file_size, 1, fp ) );
2817+
if ( !ok )
2818+
{
2819+
printf( "can't read from text input file '%s', error %d = %s\n", file_path, errno, strerror( errno ) );
2820+
usage( "can't read from -f file" );
2821+
}
2822+
2823+
// remove any line feeds. stop at ^z. pass through CR and TAB. fail on other non-alpha characters.
2824+
2825+
for ( size_t cur = 0; cur < file_size; cur++ )
2826+
{
2827+
char c = original[ cur ];
2828+
if ( ( c >= 0x20 && c <= 0x7e ) || ( 13 == c || 9 == c ) ) // normal, CR, TAB
2829+
g_fileInputText.push_back( c );
2830+
else if ( 0x1a == c ) // ^z
2831+
break;
2832+
else if ( 10 != c ) // line feed
2833+
{
2834+
tracer.Trace( "input file has byte %02x at offset %zd\n", c, cur );
2835+
usage( "-f input file can't contain binary data" );
2836+
}
2837+
}
2838+
} //load_input_file_text
2839+
27902840
bool write_fcb_arg( FCB * arg, char * pc )
27912841
{
27922842
if ( ':' == pc[ 1 ] )
@@ -2846,6 +2896,7 @@ int main( int argc, char * argv[] )
28462896
char * pcCOM = 0;
28472897
char * pcArg1 = 0;
28482898
char * pcArg2 = 0;
2899+
char * pfileInputText = 0;
28492900
bool trace = false;
28502901
bool traceInstructions = false;
28512902
uint64_t clockrate = 0;
@@ -2898,6 +2949,13 @@ int main( int argc, char * argv[] )
28982949
clearDisplayOnExit = false;
28992950
else if ( '8' == ca )
29002951
reg.fZ80Mode = false;
2952+
else if ( 'f' == ca )
2953+
{
2954+
if ( ( ':' != parg[2] ) || !strlen( parg + 3 ) )
2955+
usage( ":<filename> expected with -f" );
2956+
2957+
pfileInputText = parg + 3;
2958+
}
29012959
else if ( 'i' == ca )
29022960
traceInstructions = true;
29032961
else if ( 'l' == ca )
@@ -2951,7 +3009,13 @@ int main( int argc, char * argv[] )
29513009
tracer.SetQuiet( true );
29523010
tracer.SetFlushEachTrace( true );
29533011
x80_trace_instructions( traceInstructions );
2954-
3012+
3013+
if ( pfileInputText )
3014+
{
3015+
load_input_file_text( pfileInputText );
3016+
tracer.Trace( "-f input file has %ld characters\n", g_fileInputText.size() );
3017+
}
3018+
29553019
if ( 0 != processAffinityMask )
29563020
set_process_affinity( processAffinityMask );
29573021

0 commit comments

Comments
 (0)