2015-07-26 11:16:05 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "hp48.h"
|
2023-05-04 15:53:39 +02:00
|
|
|
#include "hp48emu.h"
|
2015-07-26 11:16:05 +02:00
|
|
|
#include "romio.h"
|
2022-03-24 13:41:22 +01:00
|
|
|
#include "timer.h"
|
2023-09-13 15:39:03 +02:00
|
|
|
#include "x48.h" /* get_ui_event() */
|
2023-05-18 23:11:40 +02:00
|
|
|
|
2022-03-24 13:41:22 +01:00
|
|
|
static int interrupt_called = 0;
|
2023-04-27 12:15:59 +02:00
|
|
|
extern long nibble_masks[ 16 ];
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2022-03-24 13:41:22 +01:00
|
|
|
int got_alarm;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
int first_press = 1; // PATCH
|
|
|
|
|
2022-03-24 13:41:22 +01:00
|
|
|
int conf_bank1 = 0x00000;
|
|
|
|
int conf_bank2 = 0x00000;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-04 15:53:39 +02:00
|
|
|
short conf_tab_sx[] = { 1, 2, 2, 2, 2, 0 };
|
|
|
|
short conf_tab_gx[] = { 1, 2, 2, 2, 2, 0 };
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_in( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
int i, in, out;
|
|
|
|
|
|
|
|
out = 0;
|
|
|
|
for ( i = 2; i >= 0; i-- ) {
|
|
|
|
out <<= 4;
|
|
|
|
out |= saturn.OUT[ i ];
|
|
|
|
}
|
|
|
|
in = 0;
|
|
|
|
for ( i = 0; i < 9; i++ )
|
|
|
|
if ( out & ( 1 << i ) )
|
|
|
|
in |= saturn.keybuf.rows[ i ];
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
// PATCH
|
|
|
|
// http://svn.berlios.de/wsvn/x48?op=comp&compare[]=/trunk@12&compare[]=/trunk@13
|
|
|
|
// PAS TERRIBLE VISIBLEMENT
|
|
|
|
|
|
|
|
if ( saturn.PC == 0x00E31 && !first_press &&
|
|
|
|
( ( out & 0x10 && in & 0x1 ) || // keys are Backspace
|
|
|
|
( out & 0x40 && in & 0x7 ) || // right, left & down
|
|
|
|
( out & 0x80 && in & 0x2 ) ) ) // up arrows
|
|
|
|
{
|
|
|
|
for ( i = 0; i < 9; i++ )
|
|
|
|
if ( out & ( 1 << i ) )
|
|
|
|
saturn.keybuf.rows[ i ] = 0;
|
|
|
|
first_press = 1;
|
|
|
|
} else
|
|
|
|
first_press = 0;
|
|
|
|
|
|
|
|
// FIN PATCH
|
|
|
|
|
|
|
|
for ( i = 0; i < 4; i++ ) {
|
|
|
|
saturn.IN[ i ] = in & 0xf;
|
|
|
|
in >>= 4;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void clear_program_stat( int n ) { saturn.PSTAT[ n ] = 0; }
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void set_program_stat( int n ) { saturn.PSTAT[ n ] = 1; }
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
int get_program_stat( int n ) { return saturn.PSTAT[ n ]; }
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void register_to_status( unsigned char* r ) {
|
|
|
|
int i;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 12; i++ ) {
|
|
|
|
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void status_to_register( unsigned char* r ) {
|
|
|
|
int i;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 12; i++ ) {
|
|
|
|
if ( saturn.PSTAT[ i ] ) {
|
|
|
|
r[ i / 4 ] |= 1 << ( i % 4 );
|
|
|
|
} else {
|
|
|
|
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void swap_register_status( unsigned char* r ) {
|
|
|
|
int i, tmp;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 12; i++ ) {
|
|
|
|
tmp = saturn.PSTAT[ i ];
|
|
|
|
saturn.PSTAT[ i ] = ( r[ i / 4 ] >> ( i % 4 ) ) & 1;
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( tmp )
|
2023-04-27 12:15:59 +02:00
|
|
|
r[ i / 4 ] |= 1 << ( i % 4 );
|
2023-05-17 10:27:19 +02:00
|
|
|
else
|
2023-04-27 12:15:59 +02:00
|
|
|
r[ i / 4 ] &= ~( 1 << ( i % 4 ) ) & 0xf;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void clear_status( void ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < 12; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.PSTAT[ i ] = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void set_register_nibble( unsigned char* reg, int n, unsigned char val ) {
|
|
|
|
reg[ n ] = val;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
unsigned char get_register_nibble( unsigned char* reg, int n ) {
|
|
|
|
return reg[ n ];
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void set_register_bit( unsigned char* reg, int n ) {
|
|
|
|
reg[ n / 4 ] |= ( 1 << ( n % 4 ) );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void clear_register_bit( unsigned char* reg, int n ) {
|
|
|
|
reg[ n / 4 ] &= ~( 1 << ( n % 4 ) );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
int get_register_bit( unsigned char* reg, int n ) {
|
|
|
|
return ( ( int )( reg[ n / 4 ] & ( 1 << ( n % 4 ) ) ) > 0 ) ? 1 : 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_reset( void ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < 6; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( opt_gx )
|
|
|
|
saturn.mem_cntl[ i ].unconfigured = conf_tab_gx[ i ];
|
|
|
|
else
|
|
|
|
saturn.mem_cntl[ i ].unconfigured = conf_tab_sx[ i ];
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
|
|
|
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_inton( void ) { saturn.kbd_ien = 1; }
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_intoff( void ) { saturn.kbd_ien = 0; }
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_return_interupt( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.int_pending ) {
|
|
|
|
saturn.int_pending = 0;
|
|
|
|
saturn.intenable = 0;
|
|
|
|
saturn.PC = 0xf;
|
|
|
|
} else {
|
|
|
|
saturn.PC = pop_return_addr();
|
|
|
|
saturn.intenable = 1;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( adj_time_pending ) {
|
|
|
|
schedule_event = 0;
|
|
|
|
sched_adjtime = 0;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_interupt( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
interrupt_called = 1;
|
|
|
|
if ( saturn.intenable ) {
|
|
|
|
push_return_addr( saturn.PC );
|
|
|
|
saturn.PC = 0xf;
|
|
|
|
saturn.intenable = 0;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_kbd_int( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
interrupt_called = 1;
|
|
|
|
if ( saturn.intenable ) {
|
|
|
|
push_return_addr( saturn.PC );
|
|
|
|
saturn.PC = 0xf;
|
|
|
|
saturn.intenable = 0;
|
2023-05-17 10:27:19 +02:00
|
|
|
} else
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.int_pending = 1;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_reset_interrupt_system( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.kbd_ien = 1;
|
2023-05-17 10:27:19 +02:00
|
|
|
int gen_intr = 0;
|
|
|
|
for ( int i = 0; i < 9; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.keybuf.rows[ i ] != 0 ) {
|
|
|
|
gen_intr = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( gen_intr )
|
2023-04-27 12:15:59 +02:00
|
|
|
do_kbd_int();
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_unconfigure( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
int i;
|
2023-05-17 10:27:19 +02:00
|
|
|
unsigned int conf = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 4; i >= 0; i-- ) {
|
|
|
|
conf <<= 4;
|
|
|
|
conf |= saturn.C[ i ];
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 6; i++ ) {
|
|
|
|
if ( saturn.mem_cntl[ i ].config[ 0 ] == conf ) {
|
|
|
|
if ( opt_gx )
|
|
|
|
saturn.mem_cntl[ i ].unconfigured = conf_tab_gx[ i ];
|
|
|
|
else
|
|
|
|
saturn.mem_cntl[ i ].unconfigured = conf_tab_sx[ i ];
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.mem_cntl[ i ].config[ 0 ] = 0x0;
|
|
|
|
saturn.mem_cntl[ i ].config[ 1 ] = 0x0;
|
|
|
|
break;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_configure( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
int i;
|
2023-05-17 10:27:19 +02:00
|
|
|
unsigned long conf = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 4; i >= 0; i-- ) {
|
|
|
|
conf <<= 4;
|
|
|
|
conf |= saturn.C[ i ];
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 6; i++ ) {
|
|
|
|
if ( saturn.mem_cntl[ i ].unconfigured ) {
|
|
|
|
saturn.mem_cntl[ i ].unconfigured--;
|
|
|
|
saturn.mem_cntl[ i ].config[ saturn.mem_cntl[ i ].unconfigured ] =
|
|
|
|
conf;
|
|
|
|
break;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
int get_identification( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
int i;
|
|
|
|
static int chip_id[] = { 0, 0, 0, 0, 0x05, 0xf6,
|
|
|
|
0x07, 0xf8, 0x01, 0xf2, 0, 0 };
|
|
|
|
int id;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( i = 0; i < 6; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.mem_cntl[ i ].unconfigured )
|
|
|
|
break;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( i < 6 )
|
|
|
|
id = chip_id[ 2 * i + ( 2 - saturn.mem_cntl[ i ].unconfigured ) ];
|
|
|
|
else
|
|
|
|
id = 0;
|
2022-03-24 11:19:16 +01:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
for ( i = 0; i < 3; i++ ) {
|
|
|
|
saturn.C[ i ] = id & 0x0f;
|
|
|
|
id >>= 4;
|
|
|
|
}
|
|
|
|
return 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
void do_shutdown( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
int wake, alarms;
|
|
|
|
t1_t2_ticks ticks;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( device.display_touched ) {
|
|
|
|
device.display_touched = 0;
|
|
|
|
update_display();
|
|
|
|
}
|
2022-03-24 11:19:16 +01:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
stop_timer( RUN_TIMER );
|
|
|
|
start_timer( IDLE_TIMER );
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( is_zero_register( saturn.OUT, OUT_FIELD ) ) {
|
|
|
|
saturn.intenable = 1;
|
|
|
|
saturn.int_pending = 0;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-09-07 12:39:01 +02:00
|
|
|
wake = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
alarms = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
do {
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
pause();
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( got_alarm ) {
|
|
|
|
got_alarm = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
ticks = get_t1_t2();
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( saturn.t2_ctrl & 0x01 )
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.timer2 = ticks.t2_ticks;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
saturn.timer1 = set_t1 - ticks.t1_ticks;
|
|
|
|
set_t1 = ticks.t1_ticks;
|
|
|
|
|
|
|
|
interrupt_called = 0;
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( get_ui_event() && interrupt_called )
|
|
|
|
wake = 1;
|
2023-04-27 12:15:59 +02:00
|
|
|
|
|
|
|
if ( saturn.timer2 <= 0 ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( saturn.t2_ctrl & 0x04 )
|
2023-04-27 12:15:59 +02:00
|
|
|
wake = 1;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.t2_ctrl & 0x02 ) {
|
|
|
|
wake = 1;
|
|
|
|
saturn.t2_ctrl |= 0x08;
|
|
|
|
do_interupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( saturn.timer1 <= 0 ) {
|
|
|
|
saturn.timer1 &= 0x0f;
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( saturn.t1_ctrl & 0x04 )
|
2023-04-27 12:15:59 +02:00
|
|
|
wake = 1;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.t1_ctrl & 0x03 ) {
|
|
|
|
wake = 1;
|
|
|
|
saturn.t1_ctrl |= 0x08;
|
|
|
|
do_interupt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wake == 0 ) {
|
|
|
|
interrupt_called = 0;
|
|
|
|
receive_char();
|
|
|
|
if ( interrupt_called )
|
|
|
|
wake = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
alarms++;
|
2022-03-24 13:41:22 +01:00
|
|
|
}
|
2023-04-27 12:15:59 +02:00
|
|
|
} while ( wake == 0 );
|
|
|
|
|
|
|
|
stop_timer( IDLE_TIMER );
|
|
|
|
start_timer( RUN_TIMER );
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_hardware_stat( int op ) {
|
|
|
|
if ( op & 1 )
|
|
|
|
saturn.XM = 1;
|
|
|
|
if ( op & 2 )
|
|
|
|
saturn.SB = 1;
|
|
|
|
if ( op & 4 )
|
|
|
|
saturn.SR = 1;
|
|
|
|
if ( op & 8 )
|
|
|
|
saturn.MP = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_hardware_stat( int op ) {
|
|
|
|
if ( op & 1 )
|
|
|
|
saturn.XM = 0;
|
|
|
|
if ( op & 2 )
|
|
|
|
saturn.SB = 0;
|
|
|
|
if ( op & 4 )
|
|
|
|
saturn.SR = 0;
|
|
|
|
if ( op & 8 )
|
|
|
|
saturn.MP = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int is_zero_hardware_stat( int op ) {
|
|
|
|
if ( op & 1 )
|
|
|
|
if ( saturn.XM != 0 )
|
|
|
|
return 0;
|
|
|
|
if ( op & 2 )
|
|
|
|
if ( saturn.SB != 0 )
|
|
|
|
return 0;
|
|
|
|
if ( op & 4 )
|
|
|
|
if ( saturn.SR != 0 )
|
|
|
|
return 0;
|
|
|
|
if ( op & 8 )
|
|
|
|
if ( saturn.MP != 0 )
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void push_return_addr( long addr ) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ( ++saturn.rstkp >= NR_RSTK ) {
|
|
|
|
for ( i = 1; i < NR_RSTK; i++ )
|
|
|
|
saturn.rstk[ i - 1 ] = saturn.rstk[ i ];
|
|
|
|
saturn.rstkp--;
|
|
|
|
}
|
|
|
|
saturn.rstk[ saturn.rstkp ] = addr;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-05-03 12:51:32 +02:00
|
|
|
long pop_return_addr( void ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( saturn.rstkp < 0 )
|
|
|
|
return 0;
|
|
|
|
return saturn.rstk[ saturn.rstkp-- ];
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
char* make_hexstr( long addr, int n ) {
|
|
|
|
static char str[ 44 ];
|
2023-05-17 10:27:19 +02:00
|
|
|
int t, trunc = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( n > 40 ) {
|
|
|
|
n = 40;
|
|
|
|
trunc = 1;
|
|
|
|
}
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
t = read_nibble( addr + i );
|
|
|
|
if ( t <= 9 )
|
|
|
|
str[ i ] = '0' + t;
|
|
|
|
else
|
|
|
|
str[ i ] = 'a' + ( t - 10 );
|
|
|
|
}
|
|
|
|
str[ n ] = '\0';
|
|
|
|
if ( trunc ) {
|
|
|
|
str[ n ] = '.';
|
|
|
|
str[ n + 1 ] = '.';
|
|
|
|
str[ n + 2 ] = '.';
|
|
|
|
str[ n + 3 ] = '\0';
|
|
|
|
}
|
|
|
|
return str;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void load_constant( unsigned char* reg, int n, long addr ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
int p = saturn.P;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
reg[ p ] = read_nibble( addr + i );
|
|
|
|
p = ( p + 1 ) & 0xf;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void load_addr( word_20* dat, long addr, int n ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
*dat &= ~nibble_masks[ i ];
|
|
|
|
*dat |= read_nibble( addr + i ) << ( i * 4 );
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void load_address( unsigned char* reg, long addr, int n ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
reg[ i ] = read_nibble( addr + i );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void register_to_address( unsigned char* reg, word_20* dat, int s ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
int n;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( s )
|
|
|
|
n = 4;
|
|
|
|
else
|
|
|
|
n = 5;
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
*dat &= ~nibble_masks[ i ];
|
|
|
|
*dat |= ( reg[ i ] & 0x0f ) << ( i * 4 );
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void address_to_register( word_20 dat, unsigned char* reg, int s ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
int n;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
if ( s )
|
|
|
|
n = 4;
|
|
|
|
else
|
|
|
|
n = 5;
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
reg[ i ] = dat & 0x0f;
|
|
|
|
dat >>= 4;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
2022-03-24 11:19:16 +01:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
long dat_to_addr( unsigned char* dat ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
long addr = 0;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 4; i >= 0; i-- ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
addr <<= 4;
|
|
|
|
addr |= ( dat[ i ] & 0xf );
|
|
|
|
}
|
|
|
|
return addr;
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
2022-03-24 11:19:16 +01:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void addr_to_dat( long addr, unsigned char* dat ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < 5; i++ ) {
|
2023-04-27 12:15:59 +02:00
|
|
|
dat[ i ] = ( addr & 0xf );
|
|
|
|
addr >>= 4;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void add_address( word_20* dat, int add ) {
|
|
|
|
*dat += add;
|
|
|
|
if ( *dat & ( word_20 )0xfff00000 ) {
|
|
|
|
saturn.CARRY = 1;
|
|
|
|
} else {
|
|
|
|
saturn.CARRY = 0;
|
|
|
|
}
|
|
|
|
*dat &= 0xfffff;
|
|
|
|
}
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
static int start_fields[] = { -1, 0, 2, 0, 15, 3, 0, 0, -1, 0,
|
|
|
|
2, 0, 15, 3, 0, 0, 0, 0, 0 };
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
static int end_fields[] = { -1, -1, 2, 2, 15, 14, 1, 15, -1, -1,
|
|
|
|
2, 2, 15, 14, 1, 4, 3, 2, 0 };
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
static inline int get_start( int code ) {
|
|
|
|
int s;
|
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( ( s = start_fields[ code ] ) == -1 )
|
2023-04-27 12:15:59 +02:00
|
|
|
s = saturn.P;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
|
|
|
return s; /* FIXME: potentially return uninitialized s ? */
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
static inline int get_end( int code ) {
|
|
|
|
int e;
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
if ( ( e = end_fields[ code ] ) == -1 )
|
2023-04-27 12:15:59 +02:00
|
|
|
e = saturn.P;
|
2023-05-17 10:27:19 +02:00
|
|
|
|
|
|
|
return e; /* FIXME: potentially return uninitialized e ? */
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void store( word_20 dat, unsigned char* reg, int code ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
int s = get_start( code );
|
|
|
|
int e = get_end( code );
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = s; i <= e; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
write_nibble( dat++, reg[ i ] );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void store_n( word_20 dat, unsigned char* reg, int n ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
write_nibble( dat++, reg[ i ] );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void recall( unsigned char* reg, word_20 dat, int code ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
int s = get_start( code );
|
|
|
|
int e = get_end( code );
|
2015-07-26 11:16:05 +02:00
|
|
|
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = s; i <= e; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
reg[ i ] = read_nibble_crc( dat++ );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 12:15:59 +02:00
|
|
|
void recall_n( unsigned char* reg, word_20 dat, int n ) {
|
2023-05-17 10:27:19 +02:00
|
|
|
for ( int i = 0; i < n; i++ )
|
2023-04-27 12:15:59 +02:00
|
|
|
reg[ i ] = read_nibble_crc( dat++ );
|
2015-07-26 11:16:05 +02:00
|
|
|
}
|